From 06a05b2e5696746641a1fe77705e28b427c1cf39 Mon Sep 17 00:00:00 2001 From: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Date: Tue, 13 Oct 2026 13:01:58 -0700 Subject: [PATCH] Auto-hide the menu bar in web popups and re-layout when it appears (#28388) On Windows and Linux, Orca's app menu is attached to every window, including web popups, so it permanently takes up vertical space above the popup content. Popups now hide that menu by default, so they match a normal browser window. Alt still reveals it, but revealing it shrinks the content area without resizing the window. The origin bar and content view kept their old heights, which left a gap or clipped content. The popup now listens for `bounds-changed` on its content view and re-runs its layout, so the content fills the space under the revealed menu bar. --- .../browser/popup-origin-bar-window.test.ts | 45 +++++++++++++++---- src/main/browser/popup-origin-bar-window.ts | 6 ++- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/main/browser/popup-origin-bar-window.test.ts b/src/main/browser/popup-origin-bar-window.test.ts index fedcd4dfdd0..48d2e962eae 100644 --- a/src/main/browser/popup-origin-bar-window.test.ts +++ b/src/main/browser/popup-origin-bar-window.test.ts @@ -64,16 +64,31 @@ const { fakeElectron } = vi.hoisted(() => { } } + class FakeContentView { + private handlers = new Map() + addChildView = vi.fn() + on(event: string, handler: Handler): void { + this.handlers.set(event, [...(this.handlers.get(event) ?? []), handler]) + } + emit(event: string): void { + for (const handler of this.handlers.get(event) ?? []) { + handler() + } + } + } + class FakeBaseWindow { static instances: FakeBaseWindow[] = [] options: Record private handlers = new Map() - contentView = { addChildView: vi.fn() } + contentView = new FakeContentView() + contentSize: { width: number; height: number } setTitle = vi.fn() isDestroyed = vi.fn(() => false) close = vi.fn(() => this.emit('closed')) constructor(options: Record) { this.options = options + this.contentSize = { width: Number(options.width), height: Number(options.height) } FakeBaseWindow.instances.push(this) } on(event: string, handler: Handler): void { @@ -83,12 +98,7 @@ const { fakeElectron } = vi.hoisted(() => { this.on(event, handler) } getContentBounds(): { x: number; y: number; width: number; height: number } { - return { - x: 0, - y: 0, - width: this.options.width as number, - height: this.options.height as number - } + return { x: 0, y: 0, ...this.contentSize } } emit(event: string, ...args: unknown[]): void { for (const handler of this.handlers.get(event) ?? []) { @@ -203,7 +213,8 @@ describe('openPopupWithOriginBar', () => { expect(lastWindow().options).toMatchObject({ width: 500, - height: 400 + POPUP_ORIGIN_BAR_HEIGHT + height: 400 + POPUP_ORIGIN_BAR_HEIGHT, + autoHideMenuBar: true }) const { bar, content } = lastViews() expect(bar.setBounds).toHaveBeenCalledWith({ @@ -220,6 +231,24 @@ describe('openPopupWithOriginBar', () => { }) }) + it('re-lays out when the revealed menu bar shrinks the content area', () => { + openPopupWithOriginBar( + { webContents: createFakeWebContents() as never, width: 500, height: 400 }, + 'https://example.com/' + ) + const window = lastWindow() + const menuBarHeight = 25 + window.contentSize = { width: 500, height: 400 + POPUP_ORIGIN_BAR_HEIGHT - menuBarHeight } + window.contentView.emit('bounds-changed') + + expect(lastViews().content.setBounds).toHaveBeenLastCalledWith({ + x: 0, + y: POPUP_ORIGIN_BAR_HEIGHT, + width: 500, + height: 400 - menuBarHeight + }) + }) + it('keeps the origin bar isolated with locked-down webPreferences', () => { openPopupWithOriginBar( { webContents: createFakeWebContents() as never }, diff --git a/src/main/browser/popup-origin-bar-window.ts b/src/main/browser/popup-origin-bar-window.ts index cfbe3ef3d3b..0786f136c5b 100644 --- a/src/main/browser/popup-origin-bar-window.ts +++ b/src/main/browser/popup-origin-bar-window.ts @@ -155,7 +155,9 @@ export function openPopupWithOriginBar( : {}), minWidth: MIN_POPUP_CONTENT_WIDTH, minHeight: MIN_POPUP_CONTENT_HEIGHT + POPUP_ORIGIN_BAR_HEIGHT, - title: initialOrigin.label + title: initialOrigin.label, + // Why: Windows/Linux attach Orca's app menu to every window, including web popups. + autoHideMenuBar: true }) // Why: the origin bar renders only Orca's own data: URL and must stay @@ -184,6 +186,8 @@ export function openPopupWithOriginBar( }) } window.on('resize', layoutViews) + // Why: Alt-revealing the auto-hidden menu bar shrinks the content area without resizing the window. + window.contentView.on('bounds-changed', layoutViews) // Why: HTML5 fullscreen makes the whole window fullscreen. resize covers // this on macOS, but re-pin on the explicit events too so the origin bar // provably stays above fullscreen content on every platform.