Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions emain/emain-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { focusedBuilderWindow, getBuilderWindowById } from "./emain-builder";
import { openBuilderWindow } from "./emain-ipc";
import { isDev, unamePlatform } from "./emain-platform";
import { clearTabCache } from "./emain-tabview";
import { decreaseZoomLevel, increaseZoomLevel } from "./emain-util";
import { decreaseZoomLevel, increaseZoomLevel, resetZoomLevel } from "./emain-util";
import {
createNewWaveWindow,
createWorkspace,
Expand Down Expand Up @@ -238,8 +238,7 @@ function makeViewMenu(
click: (_, window) => {
const wc = getWindowWebContents(window) ?? webContents;
if (wc) {
wc.setZoomFactor(1);
wc.send("zoom-factor-change", 1);
resetZoomLevel(wc);
}
},
},
Expand Down
10 changes: 2 additions & 8 deletions emain/emain-tabview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
handleCtrlShiftFocus,
handleCtrlShiftState,
increaseZoomLevel,
resetZoomLevel,
shFrameNavHandler,
shNavHandler,
} from "./emain-util";
Expand Down Expand Up @@ -48,8 +49,7 @@ function handleWindowsMenuAccelerators(
}

if (checkKeyPressed(waveEvent, "Ctrl:0")) {
tabView.webContents.setZoomFactor(1);
tabView.webContents.send("zoom-factor-change", 1);
resetZoomLevel(tabView.webContents);
return true;
}

Expand Down Expand Up @@ -165,9 +165,6 @@ export class WaveTabView extends WebContentsView {
removeWaveTabView(this.waveTabId);
this.isDestroyed = true;
});
this.webContents.on("zoom-changed", (_event, zoomDirection) => {
this.webContents.send("zoom-factor-change", this.webContents.getZoomFactor());
});
this.setBackgroundColor(computeBgColor(fullConfig));
}

Expand Down Expand Up @@ -339,9 +336,6 @@ export async function getOrCreateWebViewForTab(waveWindowId: string, tabId: stri
}
}
});
tabView.webContents.on("zoom-changed", (e) => {
tabView.webContents.send("zoom-changed");
});
tabView.webContents.setWindowOpenHandler(({ url, frameName }) => {
if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("file://")) {
console.log("openExternal fallback", url);
Expand Down
24 changes: 22 additions & 2 deletions emain/emain-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,36 @@ const MinZoomLevel = 0.4;
const MaxZoomLevel = 2.6;
const ZoomDelta = 0.2;

// Note: Chromium automatically syncs zoom factor across all WebContents
// sharing the same origin/session, so we only need to notify renderers
// to update their CSS/state — not call setZoomFactor on each one.
// We broadcast to all WebContents (including devtools, webviews, etc.) but
// that is safe because "zoom-factor-change" is a custom app-defined event
// that only our renderers listen to; unrecognized IPC messages are ignored.
function broadcastZoomFactorChanged(newZoomFactor: number): void {
for (const wc of electron.webContents.getAllWebContents()) {
if (wc.isDestroyed()) {
continue;
}
wc.send("zoom-factor-change", newZoomFactor);
}
Comment on lines +21 to +27
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Broadcasting only the IPC leaves other WebContents on a stale zoom factor.

Right now only the initiating webContents gets setZoomFactor(...); every other renderer just receives "zoom-factor-change". That makes the CSS update propagate, but getZoomFactor() in those other windows/tabs still returns the old value, so newly initialized views and the next +/- step start from the wrong baseline. This helper needs to synchronize the actual Electron zoom state for each app-owned WebContents, or the app needs a single shared zoom source that new tabs hydrate from.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@emain/emain-util.ts` around lines 15 - 21, broadcastZoomFactorChanged
currently only sends an IPC message ("zoom-factor-change") which leaves other
WebContents' internal zoom state stale; update the function
(broadcastZoomFactorChanged) to also call wc.setZoomFactor(newZoomFactor) for
each non-destroyed, app-owned electron.webContents (in addition to wc.send) so
getZoomFactor() reflects the new value, or alternatively implement/consume a
single shared zoom source that new WebContents hydrate from; ensure you only
call setZoomFactor on appropriate WebContents (skip destroyed or external/guest
contents).

}

export function increaseZoomLevel(webContents: electron.WebContents): void {
const newZoom = Math.min(MaxZoomLevel, webContents.getZoomFactor() + ZoomDelta);
webContents.setZoomFactor(newZoom);
webContents.send("zoom-factor-change", newZoom);
broadcastZoomFactorChanged(newZoom);
}

export function decreaseZoomLevel(webContents: electron.WebContents): void {
const newZoom = Math.max(MinZoomLevel, webContents.getZoomFactor() - ZoomDelta);
webContents.setZoomFactor(newZoom);
webContents.send("zoom-factor-change", newZoom);
broadcastZoomFactorChanged(newZoom);
}

export function resetZoomLevel(webContents: electron.WebContents): void {
webContents.setZoomFactor(1);
broadcastZoomFactorChanged(1);
}

export function getElectronExecPath(): string {
Expand Down
Loading