fix(linux): GPU crash-loop, X11 screen-capture failure, and clipped HUD popovers#705
fix(linux): GPU crash-loop, X11 screen-capture failure, and clipped HUD popovers#705panjiangyi wants to merge 3 commits into
Conversation
getGpuSwitches() appended `--use-gl=egl` on Linux X11. Native EGL (gl=egl-gles2) is not among the allowed GL implementations in Electron's Linux build (only egl-angle is), so the GPU process failed to initialize and crash-looped on every launch: ERROR:ui/gl/init/gl_factory.cc:102] Requested GL implementation (gl=egl-gles2,angle=none) not found in allowed implementations: [(gl=egl-angle,angle=default)] ERROR:components/viz/service/main/viz_main_impl.cc:189] Exiting GPU process due to errors during initialization This forced the app into software compositing (the viz compositor thread pinned near a full core even when idle) and broke features that require the GPU process. Let Chromium use its default ANGLE backend instead of forcing native EGL. Co-Authored-By: Claude <noreply@anthropic.com>
…yMedia
setDisplayMediaRequestHandler returned a synthetic source id
"screen:0:0" on all Linux. That is a Wayland trick to make Chromium
open the xdg-desktop-portal picker exactly once. On X11 there is no
portal path for getDisplayMedia: Chromium must receive a *real*
desktopCapturer source id, otherwise it cannot resolve the capture and
getDisplayMedia rejects with "Could not start video source" (no picker
is ever shown).
Gate the synthetic sentinel to Wayland only (detected via
shouldForceLinuxEgl, which is false on Wayland). On X11, enumerate
desktopCapturer sources and return a real `screen:` source.
Verified on X11/GNOME with a minimal Electron harness: both
getDisplayMedia and the legacy getUserMedia({chromeMediaSource:
'desktop'}) succeed once a real desktopCapturer source id is returned,
while the synthetic id reliably fails.
Co-Authored-By: Claude <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughLinux GPU switch generation no longer forces EGL on Linux. The display-media request handler now gates the portal sentinel on Linux Wayland and adjusts source selection. HUD fallback overlay expansion now applies on Linux too. ChangesLinux GPU, capture, and HUD behavior
Sequence Diagram(s)sequenceDiagram
participant sessionDefaultSession as "session.defaultSession"
participant shouldForceLinuxEgl
participant desktopCapturer
sessionDefaultSession->>shouldForceLinuxEgl: compute Linux Wayland session
shouldForceLinuxEgl-->>sessionDefaultSession: boolean
alt portal sentinel active
sessionDefaultSession-->>sessionDefaultSession: return synthetic screen:0:0 source
else enumerate sources
sessionDefaultSession->>desktopCapturer: getSources({ types: ["screen","window"] })
desktopCapturer-->>sessionDefaultSession: sources
sessionDefaultSession-->>sessionDefaultSession: return exact sourceId or first screen: source
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
electron/main.ts (1)
20-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winSplit portal/session detection from the old EGL-forcing helper.
shouldForceLinuxEgl()still returns true for X11 even though this PR intentionally stops forcing EGL. Using it as!shouldForceLinuxEgl(...)works today, but keeps stale semantics in the display-media path; a predicate likeisLinuxWaylandSessionorusesLinuxPortalDisplayMediawould make the contract harder to regress.Also applies to: 1015-1018
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@electron/main.ts` at line 20, The display-media path is still using the stale shouldForceLinuxEgl predicate to infer portal/session behavior, which couples it to old EGL semantics. Replace that usage in electron/main.ts and the display-media decision logic with a dedicated session predicate such as isLinuxWaylandSession or usesLinuxPortalDisplayMedia, and update the call sites that currently negate shouldForceLinuxEgl so the intent is explicit and does not regress when EGL forcing changes.electron/gpuSwitches.test.ts (1)
55-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winKeep the Linux switch shape consistent across tests.
The X11 test now codifies that Linux omits
useGl, but the Wayland case still expectsuseGl: undefined. Removing it makes the intended contract explicit for all Linux sessions.Proposed test cleanup
).toEqual({ - useGl: undefined, disableFeatures: ["VaapiVideoDecoder", "VaapiVideoEncoder"], });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@electron/gpuSwitches.test.ts` around lines 55 - 64, The Linux GPU switch tests are inconsistent about the returned object shape from getGpuSwitches, with the X11 case omitting useGl while the Wayland case still asserts useGl: undefined. Update the Linux Wayland expectation in gpuSwitches.test.ts to match the same contract as the X11 test by removing the explicit useGl field, keeping only the relevant disableFeatures assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@electron/gpuSwitches.test.ts`:
- Around line 55-64: The Linux GPU switch tests are inconsistent about the
returned object shape from getGpuSwitches, with the X11 case omitting useGl
while the Wayland case still asserts useGl: undefined. Update the Linux Wayland
expectation in gpuSwitches.test.ts to match the same contract as the X11 test by
removing the explicit useGl field, keeping only the relevant disableFeatures
assertion.
In `@electron/main.ts`:
- Line 20: The display-media path is still using the stale shouldForceLinuxEgl
predicate to infer portal/session behavior, which couples it to old EGL
semantics. Replace that usage in electron/main.ts and the display-media decision
logic with a dedicated session predicate such as isLinuxWaylandSession or
usesLinuxPortalDisplayMedia, and update the call sites that currently negate
shouldForceLinuxEgl so the intent is explicit and does not regress when EGL
forcing changes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: edf35d7c-746e-4db4-8b9b-8fd8c9cbf92d
📒 Files selected for processing (3)
electron/gpuSwitches.test.tselectron/gpuSwitches.tselectron/main.ts
On Linux, isHudOverlayMousePassthroughSupported() returns false, so the
HUD overlay uses the compact 860x160 fallback window. That fallback is
meant to expand to 860x540 while the HUD is interactive (so menus and
popovers have room to render), but the expansion was explicitly skipped
on Linux:
if (!isHudOverlayMousePassthroughSupported()) {
if (process.platform !== "linux") { // expansion skipped on Linux
setHudOverlayFallbackExpanded(!ignore);
}
...
}
With the window stuck at 860x160, upward popovers (e.g. the countdown
delay menu) are clipped by the window edge — only the last couple of
items are visible — and the toolbar has almost no room to drag within
the window.
Call setHudOverlayFallbackExpanded(!ignore) regardless of platform. The
window still shrinks back to the compact size when the HUD is not
interactive, so the on-screen footprint stays small when not in use.
(The Win32-only transparent-overlay corruption referenced elsewhere in
main.ts is on a different code path and unrelated to this change.)
Co-Authored-By: Claude <noreply@anthropic.com>
Summary
Three independent fixes that make Recordly usable on Linux X11 (tested on a hybrid-GPU laptop: AMD iGPU + NVIDIA, GNOME, X11 session, Electron 39.2.7). Each is a separate commit.
1. GPU process crash-loops because of
--use-gl=egl→ app stuck in software compositingelectron/gpuSwitches.tsappended--use-gl=eglon Linux X11. Native EGL (gl=egl-gles2) is not an allowed GL implementation in Electron's Linux build (onlyegl-angleis), so the GPU process failed to initialize and crash-looped on every launch:This forced the app into software compositing (the
VizCompositorThthread pinned near a full core even when idle) and broke features that require the GPU process. Fix: stop forcing native EGL; let Chromium use its default ANGLE backend.2.
getDisplayMediafails with "Could not start video source" on X11setDisplayMediaRequestHandlerreturned a synthetic source idscreen:0:0on all Linux — a Wayland trick to make Chromium open thexdg-desktop-portalpicker exactly once. On X11 there is no portal path forgetDisplayMedia: Chromium must receive a realdesktopCapturersource id, otherwise it cannot resolve the capture andgetDisplayMediarejects withCould not start video source(no picker shown).Fix: gate the synthetic sentinel to Wayland only (detected via
shouldForceLinuxEgl, which is false on Wayland). On X11, enumeratedesktopCapturer.getSources()and return a realscreen:source.3. HUD popovers clipped / toolbar barely draggable on Linux
On Linux,
isHudOverlayMousePassthroughSupported()returns false, so the HUD overlay uses the compact 860×160 fallback window. That fallback is meant to expand to 860×540 while the HUD is interactive (so menus/popovers render and the toolbar has room to move), but the expansion was explicitly skipped on Linux (if (process.platform !== "linux")). With the window stuck at 860×160, upward popovers (e.g. the countdown-delay menu) are clipped by the window edge — only the last couple of items are visible — and the toolbar has almost no room to drag.Fix: call
setHudOverlayFallbackExpanded(!ignore)regardless of platform. The window still shrinks back to compact when the HUD is not interactive, so the on-screen footprint stays small when idle. (The Win32 transparent-overlay corruption referenced inmain.tsis on a different code path and unrelated.)Verification
Built from source and ran on the affected machine:
getDisplayMediaand the legacygetUserMedia({ chromeMediaSource: 'desktop' })succeed once a realdesktopCapturersource id is returned, while the synthetic id reliably fails. After the fix, recording starts correctly on X11.Wayland behavior is unchanged (synthetic source id still used; passthrough path unaffected).
Environment
XDG_SESSION_TYPE=x11🤖 Generated with Claude Code
Summary by CodeRabbit