Skip to content

fix(screensharing): prevent the "hall of mirrors" when sharing a screen - #1826

Open
vladopol wants to merge 1 commit into
nextcloud:mainfrom
vladopol:feat/screenshare-content-protection
Open

fix(screensharing): prevent the "hall of mirrors" when sharing a screen#1826
vladopol wants to merge 1 commit into
nextcloud:mainfrom
vladopol:feat/screenshare-content-protection

Conversation

@vladopol

Copy link
Copy Markdown

When a user shares their whole screen on the desktop client, the Talk window is itself on the shared screen and renders the live screen-share, so the capture recurses into an infinite "hall of mirrors" (#7792) — especially when sharing the entire desktop.

Unlike the browser, the desktop client knows what is being shared (getDesktopMediaSource returns the source id), so it can solve this natively: while a whole screen is being shared, the Talk window is excluded from OS screen capture via BrowserWindow.setContentProtection. The window then doesn't appear in the shared stream at all — no recursion, and remote participants see a clean desktop instead of the call window.

How

  • Detection wraps getUserMedia: when a screen (not a single window) capture starts, the window is protected; when the capture track ends or is stopped, protection is released. On page (re)load the state is reset to a known baseline. Talk (spreed) is not modified and the media stream is not touched.
  • Only screen / entire‑desktop captures are protected — sharing a single window is unaffected.
  • Windows: WDA_EXCLUDEFROMCAPTURE (the window is excluded; the desktop behind it shows through). macOS: NSWindowSharingNone. Linux: setContentProtection is a no‑op there, so the window stays in the stream — the spreed‑side overlay (#18690) covers that case.

Performance

Measured on low‑end hardware — enabling content protection adds no measurable CPU/GPU cost; the capture path is unchanged.

Testing

Verified on Windows and macOS with a second participant — sharing a whole screen no longer mirrors, the Talk window is absent from the shared stream, and sharing a single window is unchanged.


Refs #7792. Complements the cross‑platform overlay in #18690 (which remains the fallback on Linux and in browsers).

When a user shares their whole screen on the desktop client, the Talk window is
itself on the shared screen and renders the live screen-share, so the capture
recurses into an infinite "hall of mirrors" (#7792) - especially when sharing
the entire desktop.

Unlike the browser, the desktop client knows what is being shared
(getDesktopMediaSource returns the source id), so it can solve this natively:
while a whole screen is being shared, the Talk window is excluded from OS screen
capture via BrowserWindow.setContentProtection. The window then does not appear
in the shared stream at all - no recursion, and remote participants see a clean
desktop instead of the call window.

Detection wraps getUserMedia: when a screen (not a single window) capture starts,
the window is protected; when the capture track ends or is stopped, protection is
released. Talk (spreed) is not modified and the media stream is not touched. Only
screen / entire-desktop captures are protected - sharing a single window is
unaffected.

setContentProtection maps to WDA_EXCLUDEFROMCAPTURE on Windows and
NSWindowSharingNone on macOS; it is a no-op on Linux, where the spreed overlay
(#18690) covers the case.

Refs #7792

Signed-off-by: Vladimir Poluliashenko <vladopol@gmail.com>
@ShGKme

ShGKme commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Hi @vladopol

Thank you for your contribution here.
The issue has been already fixed on the web-client side in:

We'll discuss with the team if it still makes sense to block entire windows and not only the screensharing preview.

But if we do want to block the entire window from the screensharing, overriding mediaDevices.getUserMedia is too risky and indirect way to archive that. The patch isn't trivial, it is easy to miss something during the patching while the implemented feature isn't critical. Instead, we need an explicit API from the Talk side to get that screensharing state and react on its change. We can add API from the Talk side for that. It would be useful in the future to have more control during the screensharing.

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants