From 89f97663eacf53f6925614b02957ab4655283621 Mon Sep 17 00:00:00 2001 From: Wooseong Kim Date: Thu, 1 Oct 2026 17:01:31 +0900 Subject: [PATCH 1/2] fix(web): drop the macOS traffic-light inset from the paired web client A browser tab has no native window buttons, but a Mac user agent still reserved that left gap. Desktop macOS keeps the inset. Co-authored-by: Cursor --- .../src/app-shell/TitlebarLeftControls.tsx | 7 +++- .../src/app-shell/app-window-chrome.ts | 7 +++- .../src/lib/desktop-window-chrome.test.ts | 35 ++++++++++++++++++- src/renderer/src/lib/desktop-window-chrome.ts | 17 +++++++++ 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/renderer/src/app-shell/TitlebarLeftControls.tsx b/src/renderer/src/app-shell/TitlebarLeftControls.tsx index 352e3d121fba..22c6d5fff91e 100644 --- a/src/renderer/src/app-shell/TitlebarLeftControls.tsx +++ b/src/renderer/src/app-shell/TitlebarLeftControls.tsx @@ -15,6 +15,7 @@ import { } from '@/store/slices/worktree-nav-history' import { useShortcutLabel } from '../hooks/useShortcutLabel' import { useAppStore } from '../store' +import { isPairedWebClientWindow, shouldShowMacTrafficLightPad } from '@/lib/desktop-window-chrome' import { hasCustomTitleBar, isMac } from './app-window-chrome' import type { AppChromeLayout } from './use-app-chrome-layout' @@ -42,7 +43,11 @@ export function TitlebarLeftControls({ layout }: { layout: AppChromeLayout }): R }`} >
- {isMac && !layout.isFullScreen ? ( + {shouldShowMacTrafficLightPad({ + isMac, + isWebClient: isPairedWebClientWindow(), + isFullScreen: layout.isFullScreen + }) ? (
) : hasCustomTitleBar ? ( /* Why: Windows/Linux remove the native title bar, so render the logo plus a ··· button that pops the application menu (as Alt does). */ diff --git a/src/renderer/src/app-shell/app-window-chrome.ts b/src/renderer/src/app-shell/app-window-chrome.ts index 8305650c4d03..8e02f2f44b2d 100644 --- a/src/renderer/src/app-shell/app-window-chrome.ts +++ b/src/renderer/src/app-shell/app-window-chrome.ts @@ -1,5 +1,6 @@ import { isPairedWebClientWindow, + macTrafficLightsWidth, shouldRenderDesktopWindowChrome } from '@/lib/desktop-window-chrome' @@ -19,4 +20,8 @@ export const WINDOW_CONTROLS_HEIGHT = hasCustomTitleBar ? '36px' : '0px' // Why: macOS paints traffic lights on the window's top-left edge. Windows and Linux paint their // controls on the right, so only macOS needs a surface to keep the left edge uncovered. -export const MAC_TRAFFIC_LIGHTS_WIDTH = isMac ? '80px' : '0px' +// A paired web client on a Mac has no traffic lights (#19299). +export const MAC_TRAFFIC_LIGHTS_WIDTH = macTrafficLightsWidth({ + isMac, + isWebClient: isPairedWebClientWindow() +}) diff --git a/src/renderer/src/lib/desktop-window-chrome.test.ts b/src/renderer/src/lib/desktop-window-chrome.test.ts index a4bde1495ddd..ff3bd5cc2513 100644 --- a/src/renderer/src/lib/desktop-window-chrome.test.ts +++ b/src/renderer/src/lib/desktop-window-chrome.test.ts @@ -1,5 +1,9 @@ import { describe, expect, it } from 'vitest' -import { shouldRenderDesktopWindowChrome } from './desktop-window-chrome' +import { + macTrafficLightsWidth, + shouldRenderDesktopWindowChrome, + shouldShowMacTrafficLightPad +} from './desktop-window-chrome' describe('shouldRenderDesktopWindowChrome', () => { it('renders custom chrome for frameless desktop Linux and Windows windows', () => { @@ -16,3 +20,32 @@ describe('shouldRenderDesktopWindowChrome', () => { expect(shouldRenderDesktopWindowChrome({ platform: 'win32', isWebClient: true })).toBe(false) }) }) + +describe('mac traffic-light inset', () => { + it('reserves the inset on desktop macOS, including while fullscreen hides the pad', () => { + expect(macTrafficLightsWidth({ isMac: true, isWebClient: false })).toBe('80px') + expect( + shouldShowMacTrafficLightPad({ isMac: true, isWebClient: false, isFullScreen: false }) + ).toBe(true) + expect( + shouldShowMacTrafficLightPad({ isMac: true, isWebClient: false, isFullScreen: true }) + ).toBe(false) + }) + + it('does not reserve a traffic-light inset in the paired web client on a Mac', () => { + expect(macTrafficLightsWidth({ isMac: true, isWebClient: true })).toBe('0px') + expect( + shouldShowMacTrafficLightPad({ isMac: true, isWebClient: true, isFullScreen: false }) + ).toBe(false) + expect( + shouldShowMacTrafficLightPad({ isMac: true, isWebClient: true, isFullScreen: true }) + ).toBe(false) + }) + + it('does not reserve a traffic-light inset on Windows or Linux', () => { + expect(macTrafficLightsWidth({ isMac: false, isWebClient: false })).toBe('0px') + expect( + shouldShowMacTrafficLightPad({ isMac: false, isWebClient: false, isFullScreen: false }) + ).toBe(false) + }) +}) diff --git a/src/renderer/src/lib/desktop-window-chrome.ts b/src/renderer/src/lib/desktop-window-chrome.ts index 59683f155185..345f8d0ba447 100644 --- a/src/renderer/src/lib/desktop-window-chrome.ts +++ b/src/renderer/src/lib/desktop-window-chrome.ts @@ -21,3 +21,20 @@ export function shouldRenderDesktopWindowChrome({ }: DesktopWindowChromeInput): boolean { return !isWebClient && (platform === 'win32' || platform === 'linux') } + +/** Desktop macOS keeps the left inset for native traffic lights. A paired browser has none. */ +export function macTrafficLightsWidth(input: { + isMac: boolean + isWebClient: boolean +}): '80px' | '0px' { + return input.isMac && !input.isWebClient ? '80px' : '0px' +} + +/** The pad element is hidden in fullscreen; the width token above stays, matching desktop today. */ +export function shouldShowMacTrafficLightPad(input: { + isMac: boolean + isWebClient: boolean + isFullScreen: boolean +}): boolean { + return input.isMac && !input.isWebClient && !input.isFullScreen +} From d34dabbcc9eb924ba2b5c946976c90ca861aaf25 Mon Sep 17 00:00:00 2001 From: Wooseong Kim Date: Thu, 1 Oct 2026 19:05:34 +0900 Subject: [PATCH 2/2] fix(web): drive the traffic-light width and pad from one paired-web read The inset token and the pad were each passed isWebClient by their own call site, so a test of the helpers could stay green while one site stopped reading the flag. Co-authored-by: Cursor --- .../src/app-shell/TitlebarLeftControls.tsx | 7 +++---- .../src/app-shell/app-window-chrome.ts | 8 +++---- .../src/lib/desktop-window-chrome.test.ts | 21 ++++++++++++++++++- src/renderer/src/lib/desktop-window-chrome.ts | 19 +++++++++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/renderer/src/app-shell/TitlebarLeftControls.tsx b/src/renderer/src/app-shell/TitlebarLeftControls.tsx index 22c6d5fff91e..1ef2affdaae8 100644 --- a/src/renderer/src/app-shell/TitlebarLeftControls.tsx +++ b/src/renderer/src/app-shell/TitlebarLeftControls.tsx @@ -15,7 +15,7 @@ import { } from '@/store/slices/worktree-nav-history' import { useShortcutLabel } from '../hooks/useShortcutLabel' import { useAppStore } from '../store' -import { isPairedWebClientWindow, shouldShowMacTrafficLightPad } from '@/lib/desktop-window-chrome' +import { macTrafficLightChromeForWindow } from '@/lib/desktop-window-chrome' import { hasCustomTitleBar, isMac } from './app-window-chrome' import type { AppChromeLayout } from './use-app-chrome-layout' @@ -43,11 +43,10 @@ export function TitlebarLeftControls({ layout }: { layout: AppChromeLayout }): R }`} >
- {shouldShowMacTrafficLightPad({ + {macTrafficLightChromeForWindow({ isMac, - isWebClient: isPairedWebClientWindow(), isFullScreen: layout.isFullScreen - }) ? ( + }).showPad ? (
) : hasCustomTitleBar ? ( /* Why: Windows/Linux remove the native title bar, so render the logo plus a ··· button that pops the application menu (as Alt does). */ diff --git a/src/renderer/src/app-shell/app-window-chrome.ts b/src/renderer/src/app-shell/app-window-chrome.ts index 8e02f2f44b2d..23c4faa3e97c 100644 --- a/src/renderer/src/app-shell/app-window-chrome.ts +++ b/src/renderer/src/app-shell/app-window-chrome.ts @@ -1,6 +1,6 @@ import { isPairedWebClientWindow, - macTrafficLightsWidth, + macTrafficLightChromeForWindow, shouldRenderDesktopWindowChrome } from '@/lib/desktop-window-chrome' @@ -21,7 +21,7 @@ export const WINDOW_CONTROLS_HEIGHT = hasCustomTitleBar ? '36px' : '0px' // Why: macOS paints traffic lights on the window's top-left edge. Windows and Linux paint their // controls on the right, so only macOS needs a surface to keep the left edge uncovered. // A paired web client on a Mac has no traffic lights (#19299). -export const MAC_TRAFFIC_LIGHTS_WIDTH = macTrafficLightsWidth({ +export const MAC_TRAFFIC_LIGHTS_WIDTH = macTrafficLightChromeForWindow({ isMac, - isWebClient: isPairedWebClientWindow() -}) + isFullScreen: false +}).width diff --git a/src/renderer/src/lib/desktop-window-chrome.test.ts b/src/renderer/src/lib/desktop-window-chrome.test.ts index ff3bd5cc2513..afe25ade04ab 100644 --- a/src/renderer/src/lib/desktop-window-chrome.test.ts +++ b/src/renderer/src/lib/desktop-window-chrome.test.ts @@ -1,10 +1,15 @@ -import { describe, expect, it } from 'vitest' +import { afterEach, describe, expect, it, vi } from 'vitest' import { + macTrafficLightChromeForWindow, macTrafficLightsWidth, shouldRenderDesktopWindowChrome, shouldShowMacTrafficLightPad } from './desktop-window-chrome' +afterEach(() => { + vi.unstubAllGlobals() +}) + describe('shouldRenderDesktopWindowChrome', () => { it('renders custom chrome for frameless desktop Linux and Windows windows', () => { expect(shouldRenderDesktopWindowChrome({ platform: 'linux', isWebClient: false })).toBe(true) @@ -42,6 +47,20 @@ describe('mac traffic-light inset', () => { ).toBe(false) }) + it('reads the paired web flag for both the inset width and the pad', () => { + vi.stubGlobal('__ORCA_WEB_CLIENT__', true) + expect(macTrafficLightChromeForWindow({ isMac: true, isFullScreen: false })).toEqual({ + width: '0px', + showPad: false + }) + + vi.stubGlobal('__ORCA_WEB_CLIENT__', false) + expect(macTrafficLightChromeForWindow({ isMac: true, isFullScreen: false })).toEqual({ + width: '80px', + showPad: true + }) + }) + it('does not reserve a traffic-light inset on Windows or Linux', () => { expect(macTrafficLightsWidth({ isMac: false, isWebClient: false })).toBe('0px') expect( diff --git a/src/renderer/src/lib/desktop-window-chrome.ts b/src/renderer/src/lib/desktop-window-chrome.ts index 345f8d0ba447..affa660c1378 100644 --- a/src/renderer/src/lib/desktop-window-chrome.ts +++ b/src/renderer/src/lib/desktop-window-chrome.ts @@ -38,3 +38,22 @@ export function shouldShowMacTrafficLightPad(input: { }): boolean { return input.isMac && !input.isWebClient && !input.isFullScreen } + +/** + * One read of the paired-web flag feeds both the width token and the pad. + * Call sites that pass `isWebClient` themselves can drift apart. + */ +export function macTrafficLightChromeForWindow(input: { isMac: boolean; isFullScreen: boolean }): { + width: '80px' | '0px' + showPad: boolean +} { + const isWebClient = isPairedWebClientWindow() + return { + width: macTrafficLightsWidth({ isMac: input.isMac, isWebClient }), + showPad: shouldShowMacTrafficLightPad({ + isMac: input.isMac, + isWebClient, + isFullScreen: input.isFullScreen + }) + } +}