Skip to content

Commit 7c4cd93

Browse files
committed
Bugfix: Build issue with fix teams screen share
1 parent 7c4c957 commit 7c4cd93

File tree

7 files changed

+72
-2
lines changed

7 files changed

+72
-2
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-04-03
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
## Context
2+
3+
The Electron 41 `Streams` interface:
4+
```
5+
video?: Video | WebFrameMain // 'loopback' NOT valid
6+
audio?: 'loopback' | 'loopbackWithMute' | WebFrameMain // 'loopback' valid
7+
```
8+
9+
`'loopback'` for audio means "provide system audio via PipeWire loopback". There is no `'loopback'` equivalent for video — video must be a `DesktopCapturerSource`-shaped object (`Video`) or a `WebFrameMain`.
10+
11+
On Wayland we cannot use `desktopCapturer.getSources()` (it does not work under Ozone), so we cannot manually supply a `Video` object. Instead, `useSystemPicker: true` tells Electron to show the OS-native picker; on Linux with xdg-desktop-portal this is the portal picker. Electron then supplies the selected stream to the webview without requiring the handler to manually specify a `Video` source.
12+
13+
The `setDisplayMediaRequestHandler` must still be called (without any handler Electron 20+ rejects all `getDisplayMedia` calls). Setting `useSystemPicker: true` handles video via portal; passing `audio: 'loopback'` in the callback provides system audio via PipeWire.
14+
15+
## Goals / Non-Goals
16+
17+
**Goals:**
18+
- Fix the TypeScript build error
19+
- Correctly route video to portal picker and audio to PipeWire loopback on Wayland
20+
21+
**Non-Goals:**
22+
- Changing X11 screen sharing (not affected — handler is gated on `isWayland()`)
23+
24+
## Decisions
25+
26+
**Decision: `{ audio: 'loopback' }` + `{ useSystemPicker: true }`**
27+
28+
Rationale: `'loopback'` is only type-valid for audio. `useSystemPicker: true` is the documented mechanism for delegating video source selection to the OS (portal on Linux). This is the only TypeScript-valid approach that correctly handles both video and audio on Wayland.
29+
30+
Alternative: `callback({})` with no video — `getDisplayMedia` would resolve with no video track, which breaks screen sharing.
31+
32+
Alternative: Remove the handler entirely — Electron 20+ rejects `getDisplayMedia` when no handler is set.
33+
34+
## Risks / Trade-offs
35+
36+
- [`useSystemPicker` is documented as "macOS Experimental"] → The option is present in the type definition and Electron's picker logic is cross-platform; on Linux it delegates to xdg-desktop-portal when available. Worth verifying manually after the fix.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## Why
2+
3+
The previous implementation of `setDisplayMediaRequestHandler` passes `video: 'loopback'`, but the Electron 41 TypeScript types only accept `Video | WebFrameMain` for `video``'loopback'` is only valid for `audio`. The build fails with a `TS2322` type error. Additionally, the approach was conceptually wrong: to get portal-sourced video on Wayland, the handler needs `useSystemPicker: true`, which tells Electron to show the system's native picker (xdg-desktop-portal on Linux) for video source selection.
4+
5+
## What Changes
6+
7+
- Replace `callback({ video: 'loopback', audio: 'loopback' })` with `callback({ audio: 'loopback' })` and add `{ useSystemPicker: true }` as the second argument to `setDisplayMediaRequestHandler`
8+
- `useSystemPicker: true` triggers the xdg-desktop-portal video picker on Linux; `audio: 'loopback'` provides system audio via PipeWire
9+
10+
## Capabilities
11+
12+
### New Capabilities
13+
14+
_(none)_
15+
16+
### Modified Capabilities
17+
18+
_(none — this is a build fix; the intended runtime behavior is unchanged)_
19+
20+
## Impact
21+
22+
- `src/main/window.ts` (`applySessionPermissions`): one-line fix to the `setDisplayMediaRequestHandler` callback

openspec/changes/fix-screen-share-handler-types/specs/.keep

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<!-- No spec-level changes. This change is a build fix only. -->
2+
<!-- The intended behavior is already covered by the screen-sharing spec. -->
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## 1. Fix
2+
3+
- [x] 1.1 In `src/main/window.ts`, change `callback({ video: 'loopback', audio: 'loopback' })` to `callback({ audio: 'loopback' })` and add `{ useSystemPicker: true }` as the second argument to `setDisplayMediaRequestHandler`
4+
5+
## 2. Verify
6+
7+
- [x] 2.1 Run `npm run build` — confirm no TypeScript errors
8+
- [ ] 2.2 Test screen sharing in Teams on Wayland — confirm portal picker appears and sharing works

src/main/window.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export function applySessionPermissions(
8484
// WebRTCPipeWireCapturer feature can route them to xdg-desktop-portal.
8585
if (isWayland()) {
8686
sess.setDisplayMediaRequestHandler((_request, callback) => {
87-
callback({ video: 'loopback', audio: 'loopback' });
88-
});
87+
callback({ audio: 'loopback' });
88+
}, { useSystemPicker: true });
8989
}
9090
}

0 commit comments

Comments
 (0)