mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
fix: use generic capturer to list both screens and windows when possible (#39189)
* fix: use generic capturer to list both screens and windows when possible Screensharing with PipeWire via XDG Desktop Portal requires explicit user permission via permission dialogs. Chromium has separate tabs for screens and windows and thus its portal implementation requests permissions separately for each. However, the screencast portal has no such limitation and supports both screens and windows in a single request. WebRTC now supports this type of capture in a new method called called `CreateGenericCapturer`. The `desktopCapturer` implementation has been modified to use it. Additionally, Chromium has been patched to use same generic capturer to ensure that the source IDs remain valid for `getUserMedia`. Co-authored-by: Athul Iddya <athul@iddya.com> * build: clean up incorrectly backported patches * chore: cherry-pick 0e9556a90cec from webrtc --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Athul Iddya <athul@iddya.com> Co-authored-by: Keeley Hammond <vertedinde@electronjs.org> Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
This commit is contained in:
@@ -131,3 +131,4 @@ fix_crash_on_nativetheme_change_during_context_menu_close.patch
|
||||
potential_fix_for_flaky_desktopcaptureapitest_delegation_unittest.patch
|
||||
fix_select_the_first_menu_item_when_opened_via_keyboard.patch
|
||||
chore_add_buildflag_guard_around_new_include.patch
|
||||
fix_use_delegated_generic_capturer_when_available.patch
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Athul Iddya <athul@iddya.com>
|
||||
Date: Fri, 14 Jul 2023 08:03:37 -0700
|
||||
Subject: fix: use delegated generic capturer when available
|
||||
|
||||
When the generic capturer is used to fetch capture sources, the returned
|
||||
ID will be arbitrarily prefixed with "screen" or "window" regardless of
|
||||
the source type. If the window capturer is used to stream video when the
|
||||
source was a screen or vice-versa, the stream fails to restart in
|
||||
delegated capturers like PipeWire.
|
||||
|
||||
To fix this, use the generic capturer to fetch the media stream if it's
|
||||
delegated and available. This does not cause any issues if the original
|
||||
capturer was window or screen-specific, as the IDs remain valid for
|
||||
generic capturer as well.
|
||||
|
||||
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc
|
||||
index 27687ee9f362c708af3e45d61effb20cebb413ae..ac97925378aa3872c7dc55e6184866be855f7a6b 100644
|
||||
--- a/content/browser/media/capture/desktop_capture_device.cc
|
||||
+++ b/content/browser/media/capture/desktop_capture_device.cc
|
||||
@@ -789,8 +789,14 @@ std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
|
||||
DesktopCapturerLacros::CaptureType::kScreen,
|
||||
webrtc::DesktopCaptureOptions());
|
||||
#else
|
||||
- std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
|
||||
- webrtc::DesktopCapturer::CreateScreenCapturer(options));
|
||||
+ std::unique_ptr<webrtc::DesktopCapturer> screen_capturer;
|
||||
+ if (auto generic_capturer =
|
||||
+ webrtc::DesktopCapturer::CreateGenericCapturer(options);
|
||||
+ generic_capturer && generic_capturer->GetDelegatedSourceListController()) {
|
||||
+ screen_capturer = std::move(generic_capturer);
|
||||
+ } else {
|
||||
+ screen_capturer = webrtc::DesktopCapturer::CreateScreenCapturer(options);
|
||||
+ }
|
||||
#endif
|
||||
if (screen_capturer && screen_capturer->SelectSource(source.id)) {
|
||||
capturer = std::make_unique<webrtc::DesktopAndCursorComposer>(
|
||||
@@ -809,8 +815,14 @@ std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
|
||||
new DesktopCapturerLacros(DesktopCapturerLacros::CaptureType::kWindow,
|
||||
webrtc::DesktopCaptureOptions()));
|
||||
#else
|
||||
- std::unique_ptr<webrtc::DesktopCapturer> window_capturer =
|
||||
- webrtc::DesktopCapturer::CreateWindowCapturer(options);
|
||||
+ std::unique_ptr<webrtc::DesktopCapturer> window_capturer;
|
||||
+ if (auto generic_capturer =
|
||||
+ webrtc::DesktopCapturer::CreateGenericCapturer(options);
|
||||
+ generic_capturer && generic_capturer->GetDelegatedSourceListController()) {
|
||||
+ window_capturer = std::move(generic_capturer);
|
||||
+ } else {
|
||||
+ window_capturer = webrtc::DesktopCapturer::CreateWindowCapturer(options);
|
||||
+ }
|
||||
#endif
|
||||
if (window_capturer && window_capturer->SelectSource(source.id)) {
|
||||
capturer = std::make_unique<webrtc::DesktopAndCursorComposer>(
|
||||
@@ -1,2 +1,3 @@
|
||||
fix_fallback_to_x11_capturer_on_wayland.patch
|
||||
cherry-pick-0e9556a90cec.patch
|
||||
fix_mark_pipewire_capturer_as_failed_after_session_is_closed.patch
|
||||
|
||||
102
patches/webrtc/cherry-pick-0e9556a90cec.patch
Normal file
102
patches/webrtc/cherry-pick-0e9556a90cec.patch
Normal file
@@ -0,0 +1,102 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Grulich <grulja@gmail.com>
|
||||
Date: Wed, 12 Jul 2023 13:15:40 +0200
|
||||
Subject: Desktop capture: introduce capturer requesting both screen and
|
||||
windows
|
||||
|
||||
When PipeWire and xdg-desktop-portals are used, we can actually combine
|
||||
both source types into one request. Make this part of the API for those
|
||||
who want to use it this way, e.g. Firefox or Electron, otherwise they
|
||||
will end up making two simultaneous requests, resulting into two dialogs
|
||||
at the same time asking, while they can be combined into just one.
|
||||
|
||||
Bug: webrtc:15363
|
||||
Change-Id: Ib6e1e47f66cb01d5c65096aec378b44c3af5f387
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/311549
|
||||
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
|
||||
Commit-Queue: Jan Grulich <grulja@gmail.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#40425}
|
||||
|
||||
diff --git a/modules/desktop_capture/desktop_capture_types.h b/modules/desktop_capture/desktop_capture_types.h
|
||||
index 9627076eea3d1272f87b773ada86be6051f1e224..a4e3e897fde1d3c7bb470449448f30ff6e50caea 100644
|
||||
--- a/modules/desktop_capture/desktop_capture_types.h
|
||||
+++ b/modules/desktop_capture/desktop_capture_types.h
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
-enum class CaptureType { kWindow, kScreen };
|
||||
+enum class CaptureType { kWindow, kScreen, kAnyScreenContent };
|
||||
|
||||
// Type used to identify windows on the desktop. Values are platform-specific:
|
||||
// - On Windows: HWND cast to intptr_t.
|
||||
diff --git a/modules/desktop_capture/desktop_capturer.cc b/modules/desktop_capture/desktop_capturer.cc
|
||||
index 5211f1acecaba963e1436c1d04aa953853c79eb7..b99f5ecb803ac0ac0e26fbdb3411c77605f33011 100644
|
||||
--- a/modules/desktop_capture/desktop_capturer.cc
|
||||
+++ b/modules/desktop_capture/desktop_capturer.cc
|
||||
@@ -26,6 +26,10 @@
|
||||
#include "rtc_base/win/windows_version.h"
|
||||
#endif // defined(RTC_ENABLE_WIN_WGC)
|
||||
|
||||
+#if defined(WEBRTC_USE_PIPEWIRE)
|
||||
+#include "modules/desktop_capture/linux/wayland/base_capturer_pipewire.h"
|
||||
+#endif
|
||||
+
|
||||
namespace webrtc {
|
||||
|
||||
void LogDesktopCapturerFullscreenDetectorUsage() {
|
||||
@@ -101,6 +105,25 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateScreenCapturer(
|
||||
return capturer;
|
||||
}
|
||||
|
||||
+// static
|
||||
+std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateGenericCapturer(
|
||||
+ const DesktopCaptureOptions& options) {
|
||||
+ std::unique_ptr<DesktopCapturer> capturer;
|
||||
+
|
||||
+#if defined(WEBRTC_USE_PIPEWIRE)
|
||||
+ if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) {
|
||||
+ capturer = std::make_unique<BaseCapturerPipeWire>(
|
||||
+ options, CaptureType::kAnyScreenContent);
|
||||
+ }
|
||||
+
|
||||
+ if (capturer && options.detect_updated_region()) {
|
||||
+ capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer)));
|
||||
+ }
|
||||
+#endif // defined(WEBRTC_USE_PIPEWIRE)
|
||||
+
|
||||
+ return capturer;
|
||||
+}
|
||||
+
|
||||
#if defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11)
|
||||
bool DesktopCapturer::IsRunningUnderWayland() {
|
||||
const char* xdg_session_type = getenv("XDG_SESSION_TYPE");
|
||||
diff --git a/modules/desktop_capture/desktop_capturer.h b/modules/desktop_capture/desktop_capturer.h
|
||||
index fd884f13ff771de2d5ea8b79ba530e9d3b03e913..9c7ecc78f46ea2e2c173416132318f0526714265 100644
|
||||
--- a/modules/desktop_capture/desktop_capturer.h
|
||||
+++ b/modules/desktop_capture/desktop_capturer.h
|
||||
@@ -186,6 +186,11 @@ class RTC_EXPORT DesktopCapturer {
|
||||
static std::unique_ptr<DesktopCapturer> CreateScreenCapturer(
|
||||
const DesktopCaptureOptions& options);
|
||||
|
||||
+ // Creates a DesktopCapturer instance which targets to capture windows and
|
||||
+ // screens.
|
||||
+ static std::unique_ptr<DesktopCapturer> CreateGenericCapturer(
|
||||
+ const DesktopCaptureOptions& options);
|
||||
+
|
||||
#if defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11)
|
||||
static bool IsRunningUnderWayland();
|
||||
|
||||
diff --git a/modules/desktop_capture/linux/wayland/screencast_portal.cc b/modules/desktop_capture/linux/wayland/screencast_portal.cc
|
||||
index a473802176a649a62f6d6a377f97daaa9d1e893c..61ed84ebb532521ce9a4af69355807b04f228859 100644
|
||||
--- a/modules/desktop_capture/linux/wayland/screencast_portal.cc
|
||||
+++ b/modules/desktop_capture/linux/wayland/screencast_portal.cc
|
||||
@@ -41,6 +41,8 @@ ScreenCastPortal::CaptureSourceType ScreenCastPortal::ToCaptureSourceType(
|
||||
return ScreenCastPortal::CaptureSourceType::kScreen;
|
||||
case CaptureType::kWindow:
|
||||
return ScreenCastPortal::CaptureSourceType::kWindow;
|
||||
+ case CaptureType::kAnyScreenContent:
|
||||
+ return ScreenCastPortal::CaptureSourceType::kAnyScreenContent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,6 +234,33 @@ void DesktopCapturer::StartHandling(bool capture_window,
|
||||
// clear any existing captured sources.
|
||||
captured_sources_.clear();
|
||||
|
||||
if (capture_window && capture_screen) {
|
||||
// Some capturers like PipeWire suppport a single capturer for both screens
|
||||
// and windows. Use it if possible, treating both as window capture
|
||||
if (auto capturer = webrtc::DesktopCapturer::CreateGenericCapturer(
|
||||
content::desktop_capture::CreateDesktopCaptureOptions());
|
||||
capturer && capturer->GetDelegatedSourceListController()) {
|
||||
capture_screen_ = false;
|
||||
capture_window_ = capture_window;
|
||||
window_capturer_ = std::make_unique<NativeDesktopMediaList>(
|
||||
DesktopMediaList::Type::kWindow, std::move(capturer));
|
||||
window_capturer_->SetThumbnailSize(thumbnail_size);
|
||||
|
||||
OnceCallback update_callback = base::BindOnce(
|
||||
&DesktopCapturer::UpdateSourcesList, weak_ptr_factory_.GetWeakPtr(),
|
||||
window_capturer_.get());
|
||||
OnceCallback failure_callback = base::BindOnce(
|
||||
&DesktopCapturer::HandleFailure, weak_ptr_factory_.GetWeakPtr());
|
||||
|
||||
window_listener_ = std::make_unique<DesktopListListener>(
|
||||
std::move(update_callback), std::move(failure_callback),
|
||||
thumbnail_size.IsEmpty());
|
||||
window_capturer_->StartUpdating(window_listener_.get());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Start listening for captured sources.
|
||||
capture_window_ = capture_window;
|
||||
capture_screen_ = capture_screen;
|
||||
|
||||
Reference in New Issue
Block a user