mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-05-24 01:40:08 +08:00
🐛 fix(window): 修复 Windows 恢复窗口后字体缩放异常
- 记录最小化和隐藏状态以识别任务栏恢复场景 - 恢复窗口时使用 restore 缩放修复路径校正 viewport drift - 增加任务栏恢复窗口缩放逻辑测试
This commit is contained in:
@@ -73,7 +73,7 @@ import {
|
||||
splitConflictsByContext,
|
||||
type ConflictInfo,
|
||||
} from './utils/shortcuts';
|
||||
import { resolveTitleBarToggleIconKey, resolveWindowsScaleCheckDelayMs, shouldApplyWindowsScaleFix, shouldToggleMaximisedWindowForScaleFix, type WindowsScaleCheckTrigger } from './utils/windowStateUi';
|
||||
import { resolveTitleBarToggleIconKey, resolveWindowsScaleCheckDelayMs, shouldApplyWindowsScaleFix, shouldToggleMaximisedWindowForScaleFix, type WindowScaleFixReason, type WindowsScaleCheckTrigger } from './utils/windowStateUi';
|
||||
import { resolveVisibleStartupWindowBounds } from './utils/windowRestoreBounds';
|
||||
import {
|
||||
SIDEBAR_UTILITY_ITEM_KEYS,
|
||||
@@ -635,10 +635,12 @@ function App() {
|
||||
let lastFixAt = 0;
|
||||
let activationTimer: number | null = null;
|
||||
let resizeTimer: number | null = null;
|
||||
let minimisedSeen = false;
|
||||
let hiddenSeen = document.visibilityState === 'hidden';
|
||||
|
||||
const wait = (ms: number) => new Promise<void>((resolve) => window.setTimeout(resolve, ms));
|
||||
|
||||
const fixWindowScaleIfNeeded = async (reason: 'activation' | 'ratio-change') => {
|
||||
const fixWindowScaleIfNeeded = async (reason: WindowScaleFixReason) => {
|
||||
if (cancelled || inFlight) return;
|
||||
const now = Date.now();
|
||||
if (now - lastFixAt < 700) return;
|
||||
@@ -713,6 +715,22 @@ function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const rememberMinimisedState = async (): Promise<boolean> => {
|
||||
if (cancelled) return false;
|
||||
const isMinimised = await WindowIsMinimised().catch(() => false);
|
||||
if (isMinimised) {
|
||||
minimisedSeen = true;
|
||||
}
|
||||
return isMinimised;
|
||||
};
|
||||
|
||||
const rememberMinimisedStateSoon = () => {
|
||||
window.setTimeout(() => {
|
||||
if (cancelled) return;
|
||||
void rememberMinimisedState();
|
||||
}, 120);
|
||||
};
|
||||
|
||||
const checkDevicePixelRatio = () => {
|
||||
if (cancelled) return;
|
||||
const currentRatio = Number(window.devicePixelRatio) || 1;
|
||||
@@ -746,10 +764,16 @@ function App() {
|
||||
if (activationTimer !== null) {
|
||||
window.clearTimeout(activationTimer);
|
||||
}
|
||||
activationTimer = window.setTimeout(() => {
|
||||
activationTimer = window.setTimeout(async () => {
|
||||
activationTimer = null;
|
||||
if (cancelled) return;
|
||||
void fixWindowScaleIfNeeded('activation');
|
||||
if (await rememberMinimisedState()) {
|
||||
return;
|
||||
}
|
||||
const reason: WindowScaleFixReason = (minimisedSeen || hiddenSeen) ? 'restore' : 'activation';
|
||||
minimisedSeen = false;
|
||||
hiddenSeen = false;
|
||||
void fixWindowScaleIfNeeded(reason);
|
||||
}, 80);
|
||||
};
|
||||
|
||||
@@ -759,9 +783,19 @@ function App() {
|
||||
scheduleActivationFix();
|
||||
};
|
||||
|
||||
const handleWindowBlur = () => {
|
||||
if (cancelled) return;
|
||||
if (document.visibilityState === 'hidden') {
|
||||
hiddenSeen = true;
|
||||
}
|
||||
rememberMinimisedStateSoon();
|
||||
};
|
||||
|
||||
const handleVisibilityChange = () => {
|
||||
if (cancelled) return;
|
||||
if (document.visibilityState !== 'visible') {
|
||||
hiddenSeen = true;
|
||||
rememberMinimisedStateSoon();
|
||||
return;
|
||||
}
|
||||
scheduleDevicePixelRatioCheck('visibilitychange');
|
||||
@@ -775,12 +809,17 @@ function App() {
|
||||
};
|
||||
|
||||
const handleWindowResize = () => {
|
||||
rememberMinimisedStateSoon();
|
||||
scheduleDevicePixelRatioCheck('resize');
|
||||
};
|
||||
|
||||
const pollTimer = window.setInterval(checkDevicePixelRatio, 900);
|
||||
const pollTimer = window.setInterval(() => {
|
||||
void rememberMinimisedState();
|
||||
checkDevicePixelRatio();
|
||||
}, 900);
|
||||
window.addEventListener('resize', handleWindowResize);
|
||||
window.addEventListener('focus', handleWindowFocus);
|
||||
window.addEventListener('blur', handleWindowBlur);
|
||||
window.addEventListener('pageshow', handlePageShow);
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
|
||||
@@ -795,6 +834,7 @@ function App() {
|
||||
window.clearInterval(pollTimer);
|
||||
window.removeEventListener('resize', handleWindowResize);
|
||||
window.removeEventListener('focus', handleWindowFocus);
|
||||
window.removeEventListener('blur', handleWindowBlur);
|
||||
window.removeEventListener('pageshow', handlePageShow);
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
};
|
||||
|
||||
@@ -17,6 +17,12 @@ describe('windowStateUi', () => {
|
||||
expect(shouldApplyWindowsScaleFix('ratio-change', true)).toBe(true);
|
||||
});
|
||||
|
||||
it('applies the Windows scale fix when a minimized taskbar window is restored with viewport drift', () => {
|
||||
expect(shouldApplyWindowsScaleFix('restore', true)).toBe(true);
|
||||
expect(shouldApplyWindowsScaleFix('restore', false)).toBe(false);
|
||||
expect(shouldToggleMaximisedWindowForScaleFix('restore', true)).toBe(true);
|
||||
});
|
||||
|
||||
it('debounces resize-triggered Windows scale checks until window transitions settle', () => {
|
||||
expect(resolveWindowsScaleCheckDelayMs('resize')).toBeGreaterThan(0);
|
||||
expect(resolveWindowsScaleCheckDelayMs('focus')).toBe(0);
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
export type WindowVisualState = 'normal' | 'maximized' | 'fullscreen';
|
||||
export type WindowScaleFixReason = 'activation' | 'ratio-change';
|
||||
export type WindowScaleFixReason = 'activation' | 'ratio-change' | 'restore';
|
||||
export type WindowsScaleCheckTrigger = 'focus' | 'pageshow' | 'poll' | 'resize' | 'visibilitychange';
|
||||
export type TitleBarToggleIconKey = 'maximize' | 'restore';
|
||||
|
||||
export const shouldApplyWindowsScaleFix = (
|
||||
reason: WindowScaleFixReason,
|
||||
hasViewportScaleDrift: boolean,
|
||||
): boolean => reason === 'ratio-change' && hasViewportScaleDrift;
|
||||
): boolean => (reason === 'ratio-change' || reason === 'restore') && hasViewportScaleDrift;
|
||||
|
||||
export const shouldToggleMaximisedWindowForScaleFix = shouldApplyWindowsScaleFix;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user