From bcf0d745727cca275e7ac33fd97be5a5fe1c4d9b Mon Sep 17 00:00:00 2001 From: UnathiCodex Date: Thu, 16 Jul 2026 21:21:43 +0200 Subject: [PATCH] fix(desktop): preserve zoom across display moves (#65874) Reassert the persisted webContents zoom after BrowserWindow moved, covering Windows monitor transitions where Chromium recalculates display scaling and drops the user-selected zoom. --- apps/desktop/electron/main.ts | 5 +++-- apps/desktop/electron/zoom.test.ts | 5 +++-- apps/desktop/electron/zoom.ts | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/desktop/electron/main.ts b/apps/desktop/electron/main.ts index 1aec6d7e8e18..d9c14e066019 100644 --- a/apps/desktop/electron/main.ts +++ b/apps/desktop/electron/main.ts @@ -6981,8 +6981,9 @@ function wireCommonWindowHandlers(win, { zoom = true }: { zoom?: boolean } = {}) if (zoom) { installZoomShortcuts(win) - // Re-apply persisted zoom on show/restore (Windows drops webContents zoom on - // minimize/restore) and on first load (reloads / crash recovery). + // Re-apply persisted zoom on show/restore/cross-display move (Windows can + // drop webContents zoom after minimize or a monitor-scale change) and on + // first load (reloads / crash recovery). installZoomReassertOnWindowEvents(win, () => restorePersistedZoomLevel(win)) win.webContents.once('did-finish-load', () => restorePersistedZoomLevel(win)) } diff --git a/apps/desktop/electron/zoom.test.ts b/apps/desktop/electron/zoom.test.ts index d0a1517d38e5..7fb81299494e 100644 --- a/apps/desktop/electron/zoom.test.ts +++ b/apps/desktop/electron/zoom.test.ts @@ -64,7 +64,7 @@ test('extreme percentages clamp to the level bounds', () => { assert.equal(percentToZoomLevel(1_000_000), 9) }) -test('installZoomReassertOnWindowEvents wires show and restore', () => { +test('installZoomReassertOnWindowEvents wires show, restore, and cross-display moves', () => { const handlers = new Map() const win = { @@ -82,7 +82,8 @@ test('installZoomReassertOnWindowEvents wires show and restore', () => { assert.deepEqual([...handlers.keys()], [...ZOOM_REASSERT_WINDOW_EVENTS]) handlers.get('show')() handlers.get('restore')() - assert.equal(calls, 2) + handlers.get('moved')() + assert.equal(calls, 3) }) test('installZoomReassertOnWindowEvents skips destroyed windows', () => { diff --git a/apps/desktop/electron/zoom.ts b/apps/desktop/electron/zoom.ts index baf8ff48b70e..aa7f31bc240b 100644 --- a/apps/desktop/electron/zoom.ts +++ b/apps/desktop/electron/zoom.ts @@ -49,8 +49,9 @@ export function applyZoomLevel(webContents, level) { } // Chromium on Windows can drop webContents zoom when a BrowserWindow is minimized -// and restored. Re-apply the persisted level on these lifecycle transitions. -export const ZOOM_REASSERT_WINDOW_EVENTS = ['show', 'restore'] +// and restored or crosses onto a monitor with different display scaling. Re-apply +// the persisted level after each completed lifecycle transition. +export const ZOOM_REASSERT_WINDOW_EVENTS = ['show', 'restore', 'moved'] export function installZoomReassertOnWindowEvents(win, reassert) { if (!win?.on) {