Skip to content

fix(desktop): theme changes no longer stop at windows without a title bar overlay - #28081

Open
swsammy wants to merge 2 commits into
pingdotgg:mainfrom
swsammy:fix/overlay-guard
Open

swsammy wants to merge 2 commits into
pingdotgg:mainfrom
swsammy:fix/overlay-guard

Conversation

@swsammy

@swsammy swsammy commented Oct 31, 2026 •

Copy link
Copy Markdown

Problem

On Linux and Windows, switching between light and dark calls setTitleBarOverlay on every open window: syncAppearance runs syncWindowAppearance (window/DesktopWindow.ts) through ElectronWindow.syncAllAppearance. Only the main window is created with a title bar overlay. On the picture-in-picture preview, the preview's sign-in popups, the startup-recovery window and the connecting splash, Electron throws TypeError: Titlebar overlay is not enabled. The appearance pass dies with a defect at that window, so windows after it in getAllWindows() don't get updated either. Julius traced this path in #10157 (#10157 (comment)).

To reproduce on Linux: open a browser preview, choose "Open separate preview window" from its menu, then switch between Light and Dark. Each switch prints an UnhandledPromiseRejectionWarning: TypeError: Titlebar overlay is not enabled on stderr. The sync runs as void runEffect(...) in DesktopLifecycle.ts, so this isn't an app log line. The desktop.lifecycle.themeUpdated span fails.

What a user notices depends on window order. Windows visited before the throw update normally, and so does the throwing window's background, because setBackgroundColor runs before setTitleBarOverlay. Windows later in the pass keep the old background (and, if the main window is among them, its old title bar button colours), and every switch leaves an unhandled rejection and a failed span.

Change

ElectronWindow.create records which windows were created with a titleBarOverlay, and syncAllAppearance passes that to its callback. syncWindowAppearance calls setTitleBarOverlay only on those windows. Windows created outside ElectronWindow.create, such as the preview window and its popups, are never recorded, so they count as having no overlay. Background colour updates still go to every window, as before.

This adapts the guard from #10157 (see Prior work). That PR closed for missing X11 evidence on its main change, not because of the guard. The state lives in the ElectronWindow service instance (next to the existing auxiliaryWindows set) rather than in a module-level map.

Scope and approval

This is a very small, focused fix for an obvious bug: a call that Electron rejects on windows without an overlay, and that cuts the theme update short for the remaining windows. It changes only which windows receive setTitleBarOverlay; the main window's overlay and every window's background update behave as before.

Verification

Tests (written first, failing on main):

  • window/DesktopWindow.test.ts: "updates title bar overlays only on overlay windows on linux / win32" runs the real syncAppearance over two windows: a default-framed one whose setTitleBarOverlay throws like Electron's, then an overlay window. Both get the background, only the overlay window gets setTitleBarOverlay, and the pass completes. On main both cases die with TypeError: Titlebar overlay is not enabled.
  • electron/ElectronWindow.test.ts: "reports which windows were created with a title bar overlay" creates a default window and an overlay window through the real create, plus one window not created through it, and checks that syncAllAppearance reports [false, true, false].

vp test run apps/desktop/src/electron/ElectronWindow.test.ts apps/desktop/src/window/DesktopWindow.test.ts: 3 failed / 25 passed with the fix's source files reverted to main (a24ec905c8), 28 passed with the fix. vp run check:changed passes format, lint, knip, affected typechecks and adjacent tests.

Real app (desktop dev build, KDE Plasma 6 Wayland, Electron 44.9.3 from nixpkgs since the pinned 44.10.0 binary doesn't run on NixOS): open a preview, choose "Open separate preview window", switch Light → Dark.

Before, on main, stderr at each switch:

(node:3218975) UnhandledPromiseRejectionWarning: TypeError: Titlebar overlay is not enabled
    at PrimitiveImpl.~effect/Effect/args (apps/desktop/dist-electron/main.cjs:123666:51)
    ...
    at NativeTheme.emit (node:events:514:28)

and desktop.trace.ndjson records desktop.lifecycle.themeUpdated as Failure with that cause, once per switch (2 of 2).

After, on this branch, in two runs: the separate preview window was open, and no switch produced a Titlebar overlay is not enabled rejection on stderr. All five desktop.lifecycle.themeUpdated spans those switches recorded are Success. The page targets DevTools listed during the second run:

page  T3 Code (Dev)                     t3code-dev://app/#/draft/214b784c-…
page  data:text/html;charset=utf-8,…    (separate preview window: previewPictureInPicture.onFrame)
page  DevTools                          devtools://devtools/bundled/devtools_app.html

Reviewed in alternating rounds by GPT-6.1 Sol and Claude Fable 5.1. The code passed two rounds from each with no open findings, and later rounds checked this description.

Not checked: X11, a packaged build, and Windows beyond the win32 unit test.

Prior work

The guard follows @chivopic's commit cc0132c in #10157, and Julius's trace of the appearance path in the same PR. Thanks to both.

Fix, tests, real-app reproduction and this description by Claude Opus 5.5 in T3 Code (Claude Code harness). Reviewed by GPT-6.1 Sol in the Codex CLI and by Claude Fable 5.1 as a Claude Code subagent.

🤖 Generated with Claude Code

… bar overlay

On Linux and Windows, syncAppearance called setTitleBarOverlay on every
open window. Only the main window has an overlay, so Electron threw
"Titlebar overlay is not enabled" on the picture-in-picture preview,
preview popups, startup recovery and splash windows, and windows later
in the pass skipped the update.

ElectronWindow.create now records windows created with a title bar
overlay, and the appearance pass updates the overlay only on those.

Fix, tests and real-app reproduction by Claude Opus 5.5 in T3 Code
(Claude Code harness). Reviewed by GPT-6.1 Sol in the Codex CLI and by
Claude Fable 5.1 as a Claude Code subagent.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: GPT-6.1 Sol <noreply@openai.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Oct 31, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 04072d2

Macroscope's review found this PR approvable — Theme synchronization now updates title bar overlays only on windows that support them, allowing other windows to continue receiving appearance updates. The change is limited to desktop presentation and preserves existing product defaults.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

Run configuration
Commits

Reviewing files that changed from the base of the PR and between 04072d2 and db88be7.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 2359643 and 04072d2.

Files selected for processing: 4
  • apps/desktop/src/electron/ElectronWindow.test.ts
  • apps/desktop/src/electron/ElectronWindow.ts
  • apps/desktop/src/window/DesktopWindow.test.ts
  • apps/desktop/src/window/DesktopWindow.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Walkthrough

ElectronWindow tracks whether each window was created with a title-bar overlay and passes that state to appearance synchronization. DesktopWindow updates title-bar overlays only for overlay-enabled windows. Tests cover background updates on framed and overlay windows on Linux and Windows.

Changes: Per-window appearance synchronization

Layer / File(s) Summary
Track and pass overlay state
apps/desktop/src/electron/ElectronWindow.ts, apps/desktop/src/electron/ElectronWindow.test.ts
ElectronWindow records windows created with a title-bar overlay and passes each window’s overlay state to the appearance sync callback. A Windows test checks the reported state for framed, overlay, and unmarked windows.
Gate title-bar overlay updates
apps/desktop/src/window/DesktopWindow.ts, apps/desktop/src/window/DesktopWindow.test.ts
DesktopWindow uses the passed overlay state to gate title-bar overlay updates. Tests check that framed and overlay windows both receive background updates, while only the overlay window receives a title-bar overlay update.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Possibly related PRs

  • pingdotgg/t3code#24193: This PR also involves DesktopWindow.syncAppearance during native-theme updates and behavior across windows with different title-bar overlay states.

Suggested reviewers: juliusmarminge

Merge Risk: Minimal · previous review 04072

Appearance updates should continue across windows without overlays. No merge-blocking risk was identified.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly and concisely describes the primary fix: theme updates now continue when windows do not have a title bar overlay.
Description check Passed The description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the failure, implementation, test results, real-app verification, and untested environment…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the failure, implementation, test results, real-app verification, and untested environments.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant