Skip to content

fix(linux): route X11 capture through real sources#613

Merged
meiiie merged 2 commits into
mainfrom
fix/linux-portal-screen-fallback
May 28, 2026
Merged

fix(linux): route X11 capture through real sources#613
meiiie merged 2 commits into
mainfrom
fix/linux-portal-screen-fallback

Conversation

@meiiie
Copy link
Copy Markdown
Collaborator

@meiiie meiiie commented May 28, 2026

Summary

  • route Linux/Wayland portal capture through the existing synthetic sentinel only when the session looks like Wayland
  • let Linux/X11 capture use Electron's documented desktopCapturer.getSources() source IDs instead of the synthetic screen:0:0 id
  • keep stale screen:fallback:* selections from failing immediately by resolving them back to the Linux portal path when needed

Why

A Fedora/X11 user reported that video source capture could not start. The previous Linux handler always used a synthetic portal id for screen:linux-portal, which is useful for Wayland portal behavior but risky on X11 where Electron can provide real desktop capturer source IDs.

Validation

  • npm run test -- electron/ipc/register/sourceMapping.test.ts src/hooks/useScreenRecorder.test.ts
  • npx biome check --formatter-enabled=false electron/main.ts electron/ipc/register/sourceMapping.ts electron/ipc/register/sourceMapping.test.ts electron/ipc/register/sources.ts src/hooks/useScreenRecorder.ts src/hooks/useScreenRecorder.test.ts
  • npx tsc --noEmit
  • npm run smoke:electron-main-cjs

Notes

  • Needs real Fedora/X11 confirmation because this machine is Windows.
  • Scoped to Linux source selection only; timeline/cache/preset requests stay separate.

Summary by CodeRabbit

  • Improvements

    • Refined screen-source selection on Linux (better Wayland vs X11 handling) with clearer fallbacks so correct screen or portal capture is chosen.
    • Streamlined decision for when to use a synthetic Linux portal source to reduce extra portal prompts.
  • Tests

    • Added unit tests covering platform-specific screen mapping and portal vs native capture scenarios.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

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: fea8d56b-438f-4988-aedf-aa20aeb4d2cb

📥 Commits

Reviewing files that changed from the base of the PR and between 067070d and 532d194.

📒 Files selected for processing (5)
  • electron/ipc/register/sourceMapping.test.ts
  • electron/ipc/register/sourceMapping.ts
  • electron/ipc/register/sources.ts
  • src/hooks/useScreenRecorder.test.ts
  • src/hooks/useScreenRecorder.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • electron/ipc/register/sources.ts
  • src/hooks/useScreenRecorder.test.ts
  • src/hooks/useScreenRecorder.ts
  • electron/ipc/register/sourceMapping.test.ts

📝 Walkthrough

Walkthrough

Extracts Linux/Wayland portal source logic into a new sourceMapping module (constant + heuristics) and integrates it into Electron IPC sources, main display handler, and the browser-capture hook, with tests validating platform-specific screen ID routing and portal-sentinel synthesis.

Changes

Linux Portal Source Mapping

Layer / File(s) Summary
Linux portal source mapping helpers and tests
electron/ipc/register/sourceMapping.ts, electron/ipc/register/sourceMapping.test.ts
Adds LINUX_PORTAL_SCREEN_SOURCE_ID, Wayland-session heuristic, getScreenSourceIdForDisplay(), shouldUseSyntheticLinuxPortalSource(), and tests covering matched/unmatched and Wayland/X11/non-Linux behaviors.
Electron sources enumeration integration
electron/ipc/register/sources.ts
Reordered imports and replaced inline matchedSource?.id ?? screen:fallback:${displayId} logic with getScreenSourceIdForDisplay({ displayId, env: process.env, matchedSourceId: matchedSource?.id, platform: process.platform }).
Electron main display handler integration
electron/main.ts
Replaced inline platform/sourceId checks in setDisplayMediaRequestHandler with shouldUseSyntheticLinuxPortalSource(env, platform, sourceId).
Browser capture hook refactor and tests
src/hooks/useScreenRecorder.ts, src/hooks/useScreenRecorder.test.ts
Added shouldUseLinuxPortalCapture() helper, replaced hardcoded "screen:linux-portal" checks with constant-driven comparisons, updated routing to consider both browserCaptureSourceId and selectedSourceId, and added tests validating portal routing and precedence.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

Checked

Poem

🐰 I hop through Wayland nights,
mapping screens with lantern lights.
Sentinels and fallbacks sing,
constants keep the routing spring.
Tests cheer softly, code feels right.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix: routing X11 capture through real Electron sources instead of synthetic ones, which is the core objective of this PR.
Description check ✅ Passed The PR description includes a clear summary, motivation explaining the reported bug, validation steps, and implementation notes. All critical sections are present and well-documented.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/linux-portal-screen-fallback

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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 and usage tips.

@meiiie
Copy link
Copy Markdown
Collaborator Author

meiiie commented May 28, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/hooks/useScreenRecorder.test.ts (1)

211-238: ⚡ Quick win

Add X11/Wayland-aware coverage for portal decision logic.

These tests validate ID combinations only. Please add a case that protects Linux/X11 from portal routing when source resolution should stay on Electron IDs.

🤖 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 `@src/hooks/useScreenRecorder.test.ts` around lines 211 - 238, Add a unit test
for shouldUseLinuxPortalCapture that ensures a live Electron/X11/Wayland source
stays on Electron capture even when selectedSourceId points at the Linux portal:
call shouldUseLinuxPortalCapture with browserCaptureSourceId: "screen:42:0" and
selectedSourceId: "screen:linux-portal" and assert it returns false so portal
routing is not applied to live Electron IDs.
electron/ipc/register/sourceMapping.test.ts (1)

41-91: ⚡ Quick win

Add regression cases for X11-unmatched mapping and stale fallback IDs.

The suite currently doesn’t lock in two key behaviors from this PR scope:

  1. unmatched Linux/X11 should avoid sentinel routing, and
  2. stale screen:fallback:* should recover correctly on Wayland.
🤖 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/ipc/register/sourceMapping.test.ts` around lines 41 - 91, Add two
regression tests for shouldUseSyntheticLinuxPortalSource: one asserting that
when platform is "linux", env indicates X11 (e.g. XDG_SESSION_TYPE: "x11") and
sourceId is a sentinel/mapping-unmatched value (e.g.
LINUX_PORTAL_SCREEN_SOURCE_ID or any non-concrete id), the function returns
false (avoid sentinel routing for X11); and another asserting that when platform
is "linux", env indicates Wayland (WAYLAND_DISPLAY present) and sourceId is a
stale fallback like "screen:fallback:0", the function returns true (recover to
synthetic path on Wayland). Use the existing test helper/constant names
shouldUseSyntheticLinuxPortalSource and LINUX_PORTAL_SCREEN_SOURCE_ID to locate
where to add these cases and match the style of surrounding tests.
🤖 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.

Inline comments:
In `@electron/ipc/register/sourceMapping.ts`:
- Around line 48-50: The current check rejects any non-sentinel sourceId,
blocking persisted "screen:fallback:*" IDs; update the condition in the source
validation (the if using sourceId and LINUX_PORTAL_SCREEN_SOURCE_ID) to allow
IDs that start with the "screen:fallback:" prefix (i.e., treat them as eligible
for Wayland synthetic recovery) while still rejecting other non-sentinel values;
refer to the sourceId variable and LINUX_PORTAL_SCREEN_SOURCE_ID constant and
add a prefix check for "screen:fallback:" to permit those stale IDs.
- Around line 28-30: getScreenSourceIdForDisplay() currently returns the
sentinel LINUX_PORTAL_SCREEN_SOURCE_ID for any unmatched Linux display
regardless of session type; change it to only return
LINUX_PORTAL_SCREEN_SOURCE_ID when running on Linux AND the session is Wayland
(e.g., XDG_SESSION_TYPE === 'wayland' or an existing isWaylandSession() helper),
otherwise fall back to the previous non-portal behavior (return a real
desktopCapturer source id or null/undefined) so X11 paths do not receive the
portal sentinel. Ensure you update the logic around
getScreenSourceIdForDisplay(), reference LINUX_PORTAL_SCREEN_SOURCE_ID, and add
or reuse a small session-type check function to gate the portal sentinel.

---

Nitpick comments:
In `@electron/ipc/register/sourceMapping.test.ts`:
- Around line 41-91: Add two regression tests for
shouldUseSyntheticLinuxPortalSource: one asserting that when platform is
"linux", env indicates X11 (e.g. XDG_SESSION_TYPE: "x11") and sourceId is a
sentinel/mapping-unmatched value (e.g. LINUX_PORTAL_SCREEN_SOURCE_ID or any
non-concrete id), the function returns false (avoid sentinel routing for X11);
and another asserting that when platform is "linux", env indicates Wayland
(WAYLAND_DISPLAY present) and sourceId is a stale fallback like
"screen:fallback:0", the function returns true (recover to synthetic path on
Wayland). Use the existing test helper/constant names
shouldUseSyntheticLinuxPortalSource and LINUX_PORTAL_SCREEN_SOURCE_ID to locate
where to add these cases and match the style of surrounding tests.

In `@src/hooks/useScreenRecorder.test.ts`:
- Around line 211-238: Add a unit test for shouldUseLinuxPortalCapture that
ensures a live Electron/X11/Wayland source stays on Electron capture even when
selectedSourceId points at the Linux portal: call shouldUseLinuxPortalCapture
with browserCaptureSourceId: "screen:42:0" and selectedSourceId:
"screen:linux-portal" and assert it returns false so portal routing is not
applied to live Electron IDs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 76e59c7c-30be-4f64-9218-79594fdebdc2

📥 Commits

Reviewing files that changed from the base of the PR and between 4cd02b5 and 067070d.

📒 Files selected for processing (6)
  • electron/ipc/register/sourceMapping.test.ts
  • electron/ipc/register/sourceMapping.ts
  • electron/ipc/register/sources.ts
  • electron/main.ts
  • src/hooks/useScreenRecorder.test.ts
  • src/hooks/useScreenRecorder.ts

Comment thread electron/ipc/register/sourceMapping.ts Outdated
Comment thread electron/ipc/register/sourceMapping.ts Outdated
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

@meiiie meiiie merged commit 9add65b into main May 28, 2026
3 checks passed
@meiiie meiiie deleted the fix/linux-portal-screen-fallback branch May 28, 2026 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant