From: Jan Grulich Date: Mon, 20 Feb 2023 21:25:00 +0000 Subject: Bug 1817263 - fix OS picker behavior under Wayland r=ng,jib,stransky Recent WebRTC backports and changes that are about to be backported from upstream to Firefox breaks and will break how we work with PipWire based desktop capturer. Currently when constructing device list, a fallback to ScreenCapturerX11 is used, as we don't call set_allow_pipewire(), which wouldn't make a difference anyway. In such case the only thing we need is a placeholder for a screen that will request OS level prompt. We also need a way to request both screens and windows in one xdg-desktop-portal call as recent WebRTC made each type be called separately, therefore the introduction of GenericCapturer. Lastly we need to make sure when there is a MediaDevice requesting the OS prompt, that it will be checked as first. In order to use unmodified libwebrtc, Firefox would need to rework the OS picker to request each type (screens and windows) separately so we can just use regular ScreenCapturer and WindowCapturer. This should be done ideally the way Chromium does it, where users can actually see even the preview of what they picked over xdg-desktop-portal before it is actually shared with requesting web page and they also have option to make the request again in case they picked a wrong window or screen. Differential Revision: https://phabricator.services.mozilla.com/D169627 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/acd6266642951aacf8915a56777c780cae9e9af3 --- .../desktop_capture/desktop_capture_types.h | 2 +- modules/desktop_capture/desktop_capturer.cc | 28 +++++++++++++++++++ modules/desktop_capture/desktop_capturer.h | 13 +++++++++ .../linux/wayland/base_capturer_pipewire.cc | 11 +------- .../linux/wayland/screencast_portal.cc | 2 ++ 5 files changed, 45 insertions(+), 11 deletions(-) diff --git a/modules/desktop_capture/desktop_capture_types.h b/modules/desktop_capture/desktop_capture_types.h index 381d1021c4..e777a45f92 100644 --- a/modules/desktop_capture/desktop_capture_types.h +++ b/modules/desktop_capture/desktop_capture_types.h @@ -19,7 +19,7 @@ typedef int pid_t; // matching what used to be in 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 4baa93cab9..7df6becb4e 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) || defined(WEBRTC_USE_X11) +#include "modules/desktop_capture/linux/wayland/base_capturer_pipewire.h" +#endif + namespace webrtc { void LogDesktopCapturerFullscreenDetectorUsage() { @@ -84,6 +88,30 @@ std::unique_ptr DesktopCapturer::CreateWindowCapturer( return capturer; } +#if defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11) +// static +std::unique_ptr DesktopCapturer::CreateGenericCapturer( + const DesktopCaptureOptions& options) { + std::unique_ptr capturer = CreateRawGenericCapturer(options); + if (capturer && options.detect_updated_region()) { + capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer))); + } + + return capturer; +} + +// static +std::unique_ptr DesktopCapturer::CreateRawGenericCapturer( + const DesktopCaptureOptions& options) { + if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { + return std::make_unique(options, + CaptureType::kAnyScreenContent); + } + + return nullptr; +} +#endif // defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11) + // static std::unique_ptr DesktopCapturer::CreateScreenCapturer( const DesktopCaptureOptions& options) { diff --git a/modules/desktop_capture/desktop_capturer.h b/modules/desktop_capture/desktop_capturer.h index cf75004af5..951c4a9b10 100644 --- a/modules/desktop_capture/desktop_capturer.h +++ b/modules/desktop_capture/desktop_capturer.h @@ -170,6 +170,12 @@ class RTC_EXPORT DesktopCapturer { // The return value if `pos` is out of the scope of the source is undefined. virtual bool IsOccluded(const DesktopVector& pos); +#if defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11) + // Creates a DesktopCapturer instance which targets to capture windows and screens. + static std::unique_ptr CreateGenericCapturer( + const DesktopCaptureOptions& options); +#endif + // Creates a DesktopCapturer instance which targets to capture windows. static std::unique_ptr CreateWindowCapturer( const DesktopCaptureOptions& options); @@ -198,6 +204,13 @@ class RTC_EXPORT DesktopCapturer { // CroppingWindowCapturer needs to create raw capturers without wrappers, so // the following two functions are protected. +#if defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11) + // Creates a platform specific DesktopCapturer instance which targets to + // capture windows and screens. + static std::unique_ptr CreateRawGenericCapturer( + const DesktopCaptureOptions& options); +#endif + // Creates a platform specific DesktopCapturer instance which targets to // capture windows. static std::unique_ptr CreateRawWindowCapturer( diff --git a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc index dae2b70510..cf4f7dc9aa 100644 --- a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc +++ b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc @@ -165,15 +165,6 @@ void BaseCapturerPipeWire::CaptureFrame() { callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); } -// Keep in sync with defines at browser/actors/WebRTCParent.jsm -// With PipeWire we can't select which system resource is shared so -// we don't create a window/screen list. Instead we place these constants -// as window name/id so frontend code can identify PipeWire backend -// and does not try to create screen/window preview. - -#define PIPEWIRE_ID 0xaffffff -#define PIPEWIRE_NAME "####_PIPEWIRE_PORTAL_####" - bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) { RTC_DCHECK(sources->size() == 0); // List of available screens is already presented by the xdg-desktop-portal, @@ -190,7 +181,7 @@ bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) { bool BaseCapturerPipeWire::SelectSource(SourceId id) { // Screen selection is handled by the xdg-desktop-portal. selected_source_id_ = id; - return id == PIPEWIRE_ID; + return true; } DelegatedSourceListController* diff --git a/modules/desktop_capture/linux/wayland/screencast_portal.cc b/modules/desktop_capture/linux/wayland/screencast_portal.cc index abfade56e7..e7aaee001b 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; } } -- 2.34.1