diff --git a/electron/main.ts b/electron/main.ts index f00f264d..636c29ff 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -900,8 +900,13 @@ app.whenReady().then(async () => { // is set we skip getSources entirely and hand back a synthetic // source id; Chromium then opens the portal once to actually // resolve the capture. + // Default to the sentinel on Linux when no source has been + // pre-selected (e.g. fresh session where the renderer skipped the + // source picker entirely). This avoids calling getSources() which + // would itself trigger an extra portal dialog. const isLinuxPortalSentinel = - process.platform === "linux" && sourceId === "screen:linux-portal"; + process.platform === "linux" && + (sourceId === "screen:linux-portal" || !sourceId); if (isLinuxPortalSentinel) { callback({ video: { id: "screen:0:0", name: "Entire screen" } }); return; diff --git a/src/components/launch/LaunchWindow.tsx b/src/components/launch/LaunchWindow.tsx index 9bbcd2f0..2c4e6146 100644 --- a/src/components/launch/LaunchWindow.tsx +++ b/src/components/launch/LaunchWindow.tsx @@ -1093,23 +1093,27 @@ export function LaunchWindow() { const idleControls = ( <> - + {platform !== "linux" && ( + <> + - + + + )} + mediaDevices.getDisplayMedia({ + audio: withAudio, + video: { + displaySurface: "monitor", + width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH }, + height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT }, + frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE }, + cursor: "never", + }, + selfBrowserSurface: "exclude", + surfaceSwitching: "exclude", + }); if (systemAudioEnabled) { try { screenMediaStream = useLinuxPortal - ? await mediaDevices.getDisplayMedia({ - audio: true, - video: { - displaySurface: "monitor", - width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH }, - height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT }, - frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE }, - cursor: "never", - }, - selfBrowserSurface: "exclude", - surfaceSwitching: "exclude", - }) + ? await acquireLinuxPortalStream(true) : await mediaDevices.getUserMedia({ audio: { mandatory: { @@ -1065,18 +1077,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn { "System audio is not available for this source. Recording will continue without system audio.", ); screenMediaStream = useLinuxPortal - ? await mediaDevices.getDisplayMedia({ - audio: false, - video: { - displaySurface: "monitor", - width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH }, - height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT }, - frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE }, - cursor: "never", - }, - selfBrowserSurface: "exclude", - surfaceSwitching: "exclude", - }) + ? await acquireLinuxPortalStream(false) : await mediaDevices.getUserMedia({ audio: false, video: browserScreenVideoConstraints, @@ -1084,18 +1085,7 @@ export function useScreenRecorder(): UseScreenRecorderReturn { } } else { screenMediaStream = useLinuxPortal - ? await mediaDevices.getDisplayMedia({ - audio: false, - video: { - displaySurface: "monitor", - width: { ideal: TARGET_WIDTH, max: TARGET_WIDTH }, - height: { ideal: TARGET_HEIGHT, max: TARGET_HEIGHT }, - frameRate: { ideal: TARGET_FRAME_RATE, max: TARGET_FRAME_RATE }, - cursor: "never", - }, - selfBrowserSurface: "exclude", - surfaceSwitching: "exclude", - }) + ? await acquireLinuxPortalStream(false) : await mediaDevices.getUserMedia({ audio: false, video: browserScreenVideoConstraints,