Skip to content

fix(linux): GPU crash-loop, X11 screen-capture failure, and clipped HUD popovers#705

Open
panjiangyi wants to merge 3 commits into
webadderallorg:mainfrom
panjiangyi:fix/linux-gpu-and-screen-capture
Open

fix(linux): GPU crash-loop, X11 screen-capture failure, and clipped HUD popovers#705
panjiangyi wants to merge 3 commits into
webadderallorg:mainfrom
panjiangyi:fix/linux-gpu-and-screen-capture

Conversation

@panjiangyi

@panjiangyi panjiangyi commented Jun 25, 2026

Copy link
Copy Markdown

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 compositing

electron/gpuSwitches.ts appended --use-gl=egl on Linux X11. Native EGL (gl=egl-gles2) is not an allowed GL implementation 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 VizCompositorTh thread 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. getDisplayMedia fails with "Could not start video source" on X11

setDisplayMediaRequestHandler returned a synthetic source id screen:0:0 on all Linux — 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 shown).

Fix: gate the synthetic sentinel to Wayland only (detected via shouldForceLinuxEgl, which is false on Wayland). On X11, enumerate desktopCapturer.getSources() and return a real screen: 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 in main.ts is on a different code path and unrelated.)

Verification

Built from source and ran on the affected machine:

Wayland behavior is unchanged (synthetic source id still used; passthrough path unaffected).

Environment

  • Ubuntu, GNOME, XDG_SESSION_TYPE=x11
  • Hybrid AMD iGPU + NVIDIA (NVIDIA in on-demand mode)
  • Electron 39.2.7

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved Linux GPU handling by using the default graphics backend (avoids forcing EGL on Electron Linux).
    • Fixed screen-sharing source selection on Linux/Wayland, improving detection of the “Entire screen” option and fallback behavior when a specific source isn’t available.
    • Resolved HUD overlay mouse passthrough fallback sizing on non-passthrough cases, including Linux.
  • Tests
    • Updated GPU switch expectations for Linux X11 coverage to match the new default behavior.

panjiangyi and others added 2 commits June 25, 2026 12:14
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>
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: be3cee11-0893-4270-bfaf-5b0fdf2526d7

📥 Commits

Reviewing files that changed from the base of the PR and between 807d869 and afdd9f6.

📒 Files selected for processing (1)
  • electron/windows.ts

📝 Walkthrough

Walkthrough

Linux 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.

Changes

Linux GPU, capture, and HUD behavior

Layer / File(s) Summary
Linux GPU switches stop forcing EGL
electron/gpuSwitches.ts, electron/gpuSwitches.test.ts
Linux getGpuSwitches now returns only the VAAPI feature disables, and the Linux X11 test expects no EGL forcing.
Display-media sentinel and source fallback
electron/main.ts
The display-media handler gates the portal sentinel on Linux Wayland and resolves capture sources by exact sourceId, then screen: entries, then the first source.
HUD fallback expands on Linux
electron/windows.ts
When HUD mouse passthrough is not supported, the fallback overlay is expanded on all non-passthrough paths, including Linux.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • webadderallorg/Recordly#302: Changes the same Linux EGL-forcing path in electron/gpuSwitches.ts and related Linux GPU switch behavior.
  • webadderallorg/Recordly#613: Touches the same setDisplayMediaRequestHandler Linux/Wayland sentinel and sourceId resolution flow in electron/main.ts.
  • webadderallorg/Recordly#612: Modifies the same setHudOverlayMousePassthrough Linux fallback expansion behavior in electron/windows.ts.

Poem

A bunny hops through Linux glow,
No EGL tugging to and fro.
I spot the screen, then choose the view,
And stretch the HUD when passthrough’s through. 🐇

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is detailed, but it omits several required template sections like Motivation, Type of Change, Related Issues, Testing Guide, and Checklist. Add the missing template sections and fill in the required fields for motivation, change type, related issues, testing steps, and checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main Linux fixes: GPU crash-loop, X11 capture, and HUD clipping.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (2)
electron/main.ts (1)

20-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Split 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 like isLinuxWaylandSession or usesLinuxPortalDisplayMedia would 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 win

Keep the Linux switch shape consistent across tests.

The X11 test now codifies that Linux omits useGl, but the Wayland case still expects useGl: 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

📥 Commits

Reviewing files that changed from the base of the PR and between d8e34a1 and 807d869.

📒 Files selected for processing (3)
  • electron/gpuSwitches.test.ts
  • electron/gpuSwitches.ts
  • electron/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>
@panjiangyi panjiangyi changed the title fix(linux): GPU process crash-loop and X11 screen-capture failure fix(linux): GPU crash-loop, X11 screen-capture failure, and clipped HUD popovers Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant