mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-12 16:02:48 +08:00
🐛 fix(window): 修复 mac 窗口恢复越界
This commit is contained in:
@@ -420,7 +420,8 @@ describe('tool center menu entries', () => {
|
||||
});
|
||||
|
||||
it('clamps normal runtime window bounds back into the visible screen after display changes', () => {
|
||||
expect(appSource).toContain('const readCurrentVisibleViewport = () => ({');
|
||||
expect(appSource).toContain('const readCurrentVisibleViewport = () => resolveWailsWindowVisibleViewport(');
|
||||
expect(appSource).toContain('{ useMonitorLocalOrigin: isMacLikePlatform() }');
|
||||
expect(appSource).toContain('const repairRuntimeWindowBounds = async () => {');
|
||||
expect(appSource).toContain('const nextBounds = resolveVisibleStartupWindowBounds(currentBounds, readCurrentVisibleViewport());');
|
||||
expect(appSource).toContain("void emitWindowDiagnostic('adjust:runtime-window-bounds'");
|
||||
|
||||
@@ -36,7 +36,7 @@ import {
|
||||
useStore,
|
||||
} from './store';
|
||||
import { GlobalProxyConfig, SavedConnection, SecurityUpdateIssue, SecurityUpdateStatus } from './types';
|
||||
import { blurToFilter, normalizeBlurForPlatform, normalizeOpacityForPlatform, isWindowsPlatform, resolveAppearanceValues } from './utils/appearance';
|
||||
import { blurToFilter, normalizeBlurForPlatform, normalizeOpacityForPlatform, isMacLikePlatform, isWindowsPlatform, resolveAppearanceValues } from './utils/appearance';
|
||||
import { buildFontFamilyOptions, DEFAULT_MONO_FONT_FAMILY, DEFAULT_UI_FONT_FAMILY, getLinuxCJKFontInstallHint, matchFontFamilyOption, resolveMonoFontFamily, resolveUIFontFamily, sanitizeFontFamilyInput, type FontFamilyOption, type InstalledFontFamily } from './utils/fontFamilies';
|
||||
import {
|
||||
DENSITY_OPTIONS,
|
||||
@@ -129,6 +129,7 @@ import {
|
||||
} from './utils/shortcuts';
|
||||
import { resolveTitleBarToggleIconKey, resolveWindowsScaleCheckDelayMs, shouldApplyWindowsScaleFix, shouldResetWebViewZoomForScaleFix, shouldToggleMaximisedWindowForScaleFix, type WindowScaleFixReason, type WindowsScaleCheckTrigger } from './utils/windowStateUi';
|
||||
import { resolveVisibleStartupWindowBounds } from './utils/windowRestoreBounds';
|
||||
import { resolveWailsWindowVisibleViewport } from './utils/wailsWindowViewport';
|
||||
import {
|
||||
SIDEBAR_UTILITY_ITEM_KEYS,
|
||||
resolveAIEntryPlacement,
|
||||
@@ -378,12 +379,11 @@ const detectNavigatorPlatform = (): string => {
|
||||
return navigator.userAgent || '';
|
||||
};
|
||||
|
||||
const readCurrentVisibleViewport = () => ({
|
||||
availWidth: window.screen?.availWidth || window.innerWidth || 0,
|
||||
availHeight: window.screen?.availHeight || window.innerHeight || 0,
|
||||
availLeft: (window.screen as Screen & { availLeft?: number })?.availLeft || 0,
|
||||
availTop: (window.screen as Screen & { availTop?: number })?.availTop || 0,
|
||||
});
|
||||
const readCurrentVisibleViewport = () => resolveWailsWindowVisibleViewport(
|
||||
window.screen as Screen & { availLeft?: number; availTop?: number },
|
||||
{ innerWidth: window.innerWidth, innerHeight: window.innerHeight },
|
||||
{ useMonitorLocalOrigin: isMacLikePlatform() },
|
||||
);
|
||||
|
||||
const getSystemThemeMode = (): 'light' | 'dark' => {
|
||||
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
|
||||
|
||||
43
frontend/src/utils/wailsWindowViewport.test.ts
Normal file
43
frontend/src/utils/wailsWindowViewport.test.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { resolveWailsWindowVisibleViewport } from './wailsWindowViewport';
|
||||
|
||||
describe('wailsWindowViewport', () => {
|
||||
it('keeps browser work-area offsets for platforms that use absolute screen coordinates', () => {
|
||||
expect(resolveWailsWindowVisibleViewport(
|
||||
{ availWidth: 1728, availHeight: 1040, availLeft: -1728, availTop: 40 },
|
||||
{ innerWidth: 1440, innerHeight: 900 },
|
||||
)).toEqual({
|
||||
availWidth: 1728,
|
||||
availHeight: 1040,
|
||||
availLeft: -1728,
|
||||
availTop: 40,
|
||||
});
|
||||
});
|
||||
|
||||
it('uses current-monitor local origin for macOS Wails window positioning', () => {
|
||||
expect(resolveWailsWindowVisibleViewport(
|
||||
{ availWidth: 1728, availHeight: 1040, availLeft: -1728, availTop: 40 },
|
||||
{ innerWidth: 1440, innerHeight: 900 },
|
||||
{ useMonitorLocalOrigin: true },
|
||||
)).toEqual({
|
||||
availWidth: 1728,
|
||||
availHeight: 1040,
|
||||
availLeft: 0,
|
||||
availTop: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it('falls back to window inner size when screen size is unavailable', () => {
|
||||
expect(resolveWailsWindowVisibleViewport(
|
||||
null,
|
||||
{ innerWidth: 1280, innerHeight: 720 },
|
||||
{ useMonitorLocalOrigin: true },
|
||||
)).toEqual({
|
||||
availWidth: 1280,
|
||||
availHeight: 720,
|
||||
availLeft: 0,
|
||||
availTop: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
52
frontend/src/utils/wailsWindowViewport.ts
Normal file
52
frontend/src/utils/wailsWindowViewport.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
export type WailsWindowVisibleViewport = {
|
||||
availWidth: number;
|
||||
availHeight: number;
|
||||
availLeft?: number;
|
||||
availTop?: number;
|
||||
};
|
||||
|
||||
type ScreenLike = {
|
||||
availWidth?: number;
|
||||
availHeight?: number;
|
||||
availLeft?: number;
|
||||
availTop?: number;
|
||||
} | null | undefined;
|
||||
|
||||
type ViewportFallback = {
|
||||
innerWidth?: number;
|
||||
innerHeight?: number;
|
||||
};
|
||||
|
||||
const toFiniteInteger = (value: unknown, fallback = 0): number => {
|
||||
const next = Math.trunc(Number(value));
|
||||
return Number.isFinite(next) ? next : fallback;
|
||||
};
|
||||
|
||||
/**
|
||||
* 解析 Wails 主窗口恢复使用的可见区域。
|
||||
* Wails 的 WindowSetPosition 在 macOS 上接收当前 monitor 可见区域内的局部坐标,
|
||||
* 因此 macOS 不能把浏览器 screen.availLeft/availTop 的全局屏幕偏移继续传下去。
|
||||
*/
|
||||
export const resolveWailsWindowVisibleViewport = (
|
||||
screenLike: ScreenLike,
|
||||
fallback: ViewportFallback,
|
||||
options?: { useMonitorLocalOrigin?: boolean },
|
||||
): WailsWindowVisibleViewport => {
|
||||
const availWidth = toFiniteInteger(
|
||||
screenLike?.availWidth,
|
||||
toFiniteInteger(fallback.innerWidth),
|
||||
);
|
||||
const availHeight = toFiniteInteger(
|
||||
screenLike?.availHeight,
|
||||
toFiniteInteger(fallback.innerHeight),
|
||||
);
|
||||
const useMonitorLocalOrigin = options?.useMonitorLocalOrigin === true;
|
||||
|
||||
return {
|
||||
availWidth,
|
||||
availHeight,
|
||||
// macOS 修复点:Wails 会自己把局部坐标映射到当前 NSScreen.visibleFrame。
|
||||
availLeft: useMonitorLocalOrigin ? 0 : toFiniteInteger(screenLike?.availLeft),
|
||||
availTop: useMonitorLocalOrigin ? 0 : toFiniteInteger(screenLike?.availTop),
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user