Files
MyGoNavi/frontend/src/utils/windowStateUi.ts
Syngnat 77a306beb2 🐛 fix(window): 修复外接显示器恢复后字体模糊
- 恢复策略:Windows 最小化恢复时不再依赖 viewport drift 才触发修复
- 渲染刷新:普通窗口执行 1px 尺寸 nudge,强制 WebView2/DWM 重建渲染 surface
- 体验保护:最大化窗口继续保留 zoom reset + resize,避免可见重复最大化动画
- 测试覆盖:补充 restore 无 drift 场景与自动修复路径断言
Refs #495
2026-06-12 15:58:30 +08:00

33 lines
1.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export type WindowVisualState = 'normal' | 'maximized' | 'fullscreen';
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 === 'restore' || (reason === 'ratio-change' && hasViewportScaleDrift);
// 关于 restore 场景为何刻意不走 toggle见 9848b8b2
// maximised 窗口在 Windows 上无法通过 SetSize nudge 修复 viewport driftOS 拒绝 resize
// 唯一能让 WebView2 重新计算缩放的办法是 Unmaximise → Maximise但在任务栏图标点击恢复的
// 真实场景下,用户会肉眼看到窗口"被弹两次"的重复最大化动画——比偶发字体变大更糟。
// 取舍restore 时普通窗口走 1px SetSize nudge 迫使 WebView2/DWM 重新分配 backing surface
// maximised 窗口只做 WebView2 zoom reset + resize避免可见的重复最大化抖动。
// ratio-changeDPR 变化,例如把窗口拖到另一块显示器)则允许 toggle因为那种场景下用户预期会有视觉过渡。
export const shouldToggleMaximisedWindowForScaleFix = (
reason: WindowScaleFixReason,
hasViewportScaleDrift: boolean,
): boolean => reason === 'ratio-change' && hasViewportScaleDrift;
export const shouldResetWebViewZoomForScaleFix = (
reason: WindowScaleFixReason,
_hasViewportScaleDrift: boolean,
): boolean => reason === 'restore';
export const resolveWindowsScaleCheckDelayMs = (trigger: WindowsScaleCheckTrigger): number =>
trigger === 'resize' ? 240 : 0;
export const resolveTitleBarToggleIconKey = (windowState: WindowVisualState): TitleBarToggleIconKey =>
windowState === 'maximized' ? 'restore' : 'maximize';