Skip to content

fix(desktop): use native frame when X11 client insets are unsupported - #10157

Open
chivopic wants to merge 11 commits into
pingdotgg:mainfrom
chivopic:fix/linux-x11-native-frame-fallback
Open

fix(desktop): use native frame when X11 client insets are unsupported#10157
chivopic wants to merge 11 commits into
pingdotgg:mainfrom
chivopic:fix/linux-x11-native-frame-fallback

Conversation

@chivopic

@chivopic chivopic commented Sep 5, 2026

Copy link
Copy Markdown

Fixes #10142.

What changed

  • Detect the actual Linux display backend, including explicit --ozone-platform=x11|wayland overrides.
  • For hidden-title-bar X11 windows, inspect the window manager's _NET_SUPPORTED hints at window creation time via xprop.
  • If _GTK_FRAME_EXTENTS is definitively unsupported, remove Electron's hidden title-bar overlay and create the window with frame: true so the window manager supplies native decorations.
  • Fail open when the X11 capability cannot be inspected or the probe times out, preserving the existing window chrome rather than changing behavior in an unknown environment.
  • Leave Wayland, macOS, Windows, already-native windows, and X11 WMs that advertise _GTK_FRAME_EXTENTS unchanged.

Why

Electron 43 introduced Linux client-side decoration behavior that can leave an opaque resize/shadow inset on non-compositing X11 WMs such as i3. Chromium's X11 path uses WM support for _GTK_FRAME_EXTENTS as part of deciding whether client frame insets are supported, so this patch uses the same capability boundary for T3 Code's automatic fallback.

This is intentionally narrower than the closed native-frame preference PR #5398: there is no new setting, IPC state, restart preference, or UI. The fallback only activates when the current Electron backend is X11 and the WM is positively known not to support the client inset protocol implicated in the regression.

Tests

Added focused regression coverage for:

  • X11 vs Wayland session detection, including Wayland sessions that also expose DISPLAY
  • explicit Electron Ozone backend overrides taking precedence over desktop session variables
  • native-frame fallback when _GTK_FRAME_EXTENTS is absent
  • preserving the current hidden overlay when the hint is present
  • conservative behavior when capability inspection fails
  • no probing or mutation for Wayland or already-native windows

Validation status

The branch is rebased onto current upstream main and is mergeable. Upstream GitHub Actions currently require approval for this fork PR: CI/preview workflows end in action_required before creating any jobs, so there is not yet a runner result to report.

Note

Use native frame when Linux X11 window manager lacks GTK frame-extents support

  • Adds X11 session detection (isLinuxX11Session) and an xprop-backed hint reader with a 250 ms timeout to inspect whether the window manager advertises the exact GTK_FRAME_EXTENTS atom.
  • When the atom is absent, resolveLinuxX11WindowFrameOptions converts hidden-title-bar overlay requests to native-frame options before BrowserWindow construction; Wayland, non-X11, and inspection-failure cases keep the original options.
  • ElectronWindow.create is now async and records each created window's title-bar-overlay capability in a weak map; syncWindowAppearance gates setTitleBarOverlay calls on that recorded capability.
  • Adds a one-permit semaphore to serialize main-window creation across createMain, ensureMain, and createMainIfBackendReady, preventing concurrent publication of multiple main windows.
  • Behavioral Change: ElectronWindow.create now returns a Promise; callers awaiting it will see a possible 250 ms delay on Linux X11 while xprop runs. Windows whose WM lacks GTK_FRAME_EXTENTS will appear with native decorations instead of a hidden title bar.

Macroscope summarized c029bb0.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 5, 2026
@chivopic
chivopic force-pushed the fix/linux-x11-native-frame-fallback branch from b4d3db0 to 4931886 Compare September 5, 2026 16:27
Comment thread apps/desktop/src/electron/LinuxWindowFrame.ts
@chivopic
chivopic force-pushed the fix/linux-x11-native-frame-fallback branch from 898fee4 to 7cae4eb Compare September 5, 2026 16:30
Comment thread apps/desktop/src/electron/LinuxWindowFrame.ts Outdated
@chivopic
chivopic marked this pull request as ready for review September 5, 2026 16:31
Copilot AI lite review requested due to automatic review settings September 5, 2026 16:31
@cursor

cursor Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread apps/desktop/src/electron/LinuxWindowFrame.ts
Comment thread apps/desktop/src/electron/LinuxWindowFrame.ts
@macroscopeapp

macroscopeapp Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR changes production desktop window creation and default title-bar behavior on some Linux/X11 environments, adding an xprop integration, native-frame fallback, per-window appearance tracking, and creation serialization. The cross-cutting runtime impact and unresolved concurrency risk merit human review.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@juliusmarminge

Copy link
Copy Markdown
Member

Fix needed before merge: the native-frame fallback is incompatible with the existing appearance-update path.

I reproduced this using Electron 43.4.1 on Linux, the exact resolver at e0328495, and the extracted production appearance helpers from current main aea9ecbc. The DesktopWindow and DesktopLifecycle files are identical between those revisions.

Native window configuration Existing appearance update
Current hidden title bar with overlay Success
PR fallback, frame: true, no overlay TypeError: Titlebar overlay is not enabled
PR supported-hint control, overlay retained Success

syncWindowAppearance reconstructs an overlay from the platform and calls setTitleBarOverlay even when this PR deliberately removed it at construction. The background color changes first, then the Effect fails with a defect. syncAllAppearance stops at that failure, so later windows are skipped. The normal theme-update hook invokes this path. I did not demonstrate a process crash.

Please preserve each window's resolved overlay capability through appearance updates. Native-framed windows should still receive the background update; overlay-enabled windows must keep their light/dark overlay update. Cover both in a mixed-window pass instead of swallowing the exception or disabling all Linux overlay updates.

Scope of the proof: real BrowserWindow and real native setters, exact source helpers, synthetic _NET_SUPPORTED input, and a private Xvfb display without a window manager. No live database, provider call, or Mac use. This independently confirms the introduced appearance regression, not the original Ubuntu/i3 border or its visual fix. The original-platform check and the native-frame/default-behavior human review remain open.

Reviewed by GPT 6 Astra via Codex in T3 Code.

@chivopic
chivopic force-pushed the fix/linux-x11-native-frame-fallback branch from 3bd26d3 to f9ecc5a Compare September 6, 2026 07:50
@cursor

cursor Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

},
} satisfies typeof ElectronWindowCreateOptions.Type;
create: (options) =>
Effect.promise(() =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Medium electron/ElectronWindow.ts:181

Concurrent activations can create duplicate main windows on X11: create awaits resolveLinuxX11WindowFrameOptions before constructing BrowserWindow, while mainWindowRef remains empty, so ensureMain/createMainIfBackendReady both pass their checks and later overwrite the ref with different windows. Add an in-flight creation guard or serialize main-window creation so only one activation can proceed.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/desktop/src/electron/ElectronWindow.ts around line 181:

Concurrent activations can create duplicate main windows on X11: `create` awaits `resolveLinuxX11WindowFrameOptions` before constructing `BrowserWindow`, while `mainWindowRef` remains empty, so `ensureMain`/`createMainIfBackendReady` both pass their checks and later overwrite the ref with different windows. Add an in-flight creation guard or serialize main-window creation so only one activation can proceed.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 7b64f4b. Main-window check/create/publish paths are now serialized in DesktopWindow with a single Semaphore(1). createMain, ensureMain, and createMainIfBackendReady share that mutex and use an internal unlocked creation helper while holding it, so concurrent activation/readiness paths cannot both observe an empty main and create separate windows. Generic ElectronWindow.create (including the WSL splash path) remains unlocked.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Sorry, I'm unable to act on this request because you do not have permissions within this repository.

@cursor

cursor Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@chivopic
chivopic force-pushed the fix/linux-x11-native-frame-fallback branch from f97c7a9 to cc0132c Compare September 6, 2026 07:57

chivopic commented Sep 6, 2026

Copy link
Copy Markdown
Author

Fixed the appearance-update regression in cc0132c.

The resolved window chrome capability is now recorded when BrowserWindow is constructed. syncWindowAppearance always updates the background, but only calls setTitleBarOverlay for windows that were actually created with the overlay enabled, so the X11 native-frame fallback no longer hits TypeError: Titlebar overlay is not enabled or aborts later window updates.

I also added a mixed-window regression test covering a native-framed window and an overlay-enabled window in the same appearance pass: both receive the background update, while only the overlay-enabled window receives the title-bar overlay update.

The branch is mergeable. The new upstream workflows are currently action_required pending approval for the fork PR, so there is not yet a runner result for this head.

@cursor

cursor Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@chivopic
chivopic force-pushed the fix/linux-x11-native-frame-fallback branch from 54ebc69 to 7b64f4b Compare September 6, 2026 08:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 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.

0.0.38: light gray 7px border on left/right/bottom on i3/X11 without compositor

3 participants