element-hq / element-hq/element-web
Screen-share picker polls desktopCapturer.getSources every 500 ms with window thumbnails; on Windows each call takes ~3 s, so calls pile up and stall the main process
- Dominant language
- TypeScript
- Stars
- 13.5k
- Forks
- 2.8k
- PR merge metrics
- PR metrics pending
Description
### Steps to reproduce
1. Element Desktop on Windows, in a call (legacy 1:1 or Element Call).
2. Click "Share screen" to open the screen-share source picker.
3. Leave it open for a few seconds, optionally switch to the "Application window" tab.
### Outcome
#### What did you expect?
The picker opens, shows live thumbnails and stays responsive.
#### What happened instead?
The main process stalls: the picker takes several seconds to populate, then the whole app becomes sluggish or stops repainting while the dialog is open. On Electron 42 builds (Element 1.12.18 and around) this went further and hard-crashed the app (`Exception code: 0x80000003` in the Windows event log, `%LocalAppData%\CrashDumps\Element.exe.*.dmp`) - that is electron/electron#51910, which no longer crashes on Electron 43/44 but still fails slowly.
Root cause is in `DesktopCapturerSourcePicker.tsx`, not in Electron:
- `getDesktopCapturerSources()` always asks for **both** `screen` and `window` sources **with 312x176 thumbnails**, regardless of which tab is visible.
- `componentDidMount` starts a `setInterval(..., 500)` whose callback is `async` and awaits the IPC round-trip. `setInterval` does not wait for the previous callback, so as soon as one `getSources` call takes longer than 500 ms the calls pile up.
- On Windows, window thumbnails go through Chromium's WGC fallback, which fails per window for anything not capturable (`wgc_capture_source.cc: CreateForWindow failed with hr: -2147024809`, `wgc_capturer_win.cc: Source is not capturable`). Each rejected window adds latency.
Measured today with a bare Electron 44.0.0 main process calling `desktopCapturer.getSources({ types: ["window"], thumbnailSize: { width: 312, height: 176 } })` in a loop, 12 windows open, Windows 11 Pro 26200:
```
iter 14: 12 windows, 3289ms, empty thumbs=1
iter 15: 12 windows, 3310ms, empty thumbs=1
iter 16: 12 windows, 3320ms, empty thumbs=1
iter 17: 12 windows, 3248ms, empty thumbs=1
[2088:...:ERROR:...\wgc_capture_source.cc:156] CreateForWindow failed with hr: -2147024809: [0x00000000]
[2088:...:ERROR:...\wgc_capturer_win.cc:348] Source is not capturable.
```
So every poll takes about 3.3 s while the picker schedules a new one every 0.5 s. That is roughly six overlapping `getSources` calls in flight on the main process at any time for as long as the dialog is open. Screen-only sources return in well under 500 ms; it is the window thumbnails that are slow.
#### Suggested fix
Small and contained to the picker:
1. Only request the source type of the **visible tab** (`types: ["screen"]` or `types: ["window"]`), not both.
2. Do not use a fixed `setInterval` with an async callback. Either chain the next fetch after the previous one resolves, or guard with an "in flight" flag so calls never overlap.
3. Use a longer interval (1000 ms works fine visually) - a screen thumbnail refresh is already ~0.5 s on machines where DXGI duplication falls back.
I have this running in a fork (https://github.com/oss96/element-web/blob/feat/screenshare-audio-by-application/apps/web/src/components/views/elements/DesktopCapturerSourcePicker.tsx) and can open a PR with just the polling change if wanted.
### Operating system
Windows 11 Pro (10.0.26200)
### Application version
Reproduced against `develop` at 9a536a3419 (1.12.27, Electron 44.0.0). Crash variant seen on 1.12.18 (Electron 42).
### How did you install the app?
Built from source (electron-builder, Squirrel) and the official installer.
### Homeserver
n/a
### Will you send logs?
Included above.
Contributor guide
Research direction
Start in apps/web/src/components/views/elements/DesktopCapturerSourcePicker.tsx, reading componentDidMount and getDesktopCapturerSources while reproducing the picker on Windows. Verify that only the visible tab's sources are requested, polling calls do not overlap, and the picker remains responsive with refreshed thumbnails.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron, typescript
- Domain
- desktop, performance
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100