Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit 9b87037

Browse files
gruljaCommit Bot
authored andcommitted
Improve screen sharing with PipeWire on Wayland
Currently, sharing a screen or a window on Wayland opens unnecessary preview dialog on Chromium side, which is then followed by a similar dialog on xdg-desktop-portal side. The Chromium dialog is useless on Wayland, as it doesn't show anything. This is because Chromium doesn't have access to screen content as in case of X11 session. To fix this, we want to avoid showing the preview dialog in case we find that we run on Wayland and only pick a screen or a window from the dialog that comes from xdg-desktop-portal. This patch splits BaseCapturerPipeWire class, moving portal related code into XdgPortalBase, which does all the DBus communication and which is supposed to be reused by BaseCapturerPipeWire when the user confirms the dialog from xdg-desktop-portal. The XdgPortalBase is extended to support multiple calls at once, where each call is identified by Id. Relevant change on Chromium side will be in a different review. Bug: chromium:682122 Change-Id: If8afd36da66231eb154cdc00114908ac897ee4cf Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/160649 Commit-Queue: Tommi <[email protected]> Reviewed-by: Tommi <[email protected]> Reviewed-by: Erik Språng <[email protected]> Cr-Commit-Position: refs/heads/master@{#32342}
1 parent ff9f646 commit 9b87037

16 files changed

+1818
-1075
lines changed

modules/desktop_capture/BUILD.gn

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ if (rtc_include_tests) {
7676
"window_finder_unittest.cc",
7777
]
7878
public_configs = [ ":x11_config" ]
79+
if (is_linux) {
80+
public_configs += [ ":pipewire_config" ]
81+
if (rtc_use_pipewire) {
82+
configs += [
83+
":pipewire_config",
84+
":gio",
85+
]
86+
87+
if (rtc_link_pipewire) {
88+
configs += [ ":pipewire" ]
89+
} else {
90+
deps += [ ":pipewire_stubs" ]
91+
}
92+
}
93+
}
7994
if (is_win) {
8095
deps += [ "../../rtc_base:win32" ]
8196
}
@@ -132,6 +147,21 @@ if (rtc_include_tests) {
132147
}
133148
deps += [ ":desktop_capture_mock" ]
134149
public_configs = [ ":x11_config" ]
150+
if (is_linux) {
151+
public_configs += [ ":pipewire_config" ]
152+
if (rtc_use_pipewire) {
153+
configs += [
154+
":pipewire_config",
155+
":gio",
156+
]
157+
158+
if (rtc_link_pipewire) {
159+
configs += [ ":pipewire" ]
160+
} else {
161+
deps += [ ":pipewire_stubs" ]
162+
}
163+
}
164+
}
135165
}
136166
}
137167

@@ -496,6 +526,7 @@ rtc_library("desktop_capture_generic") {
496526
absl_deps = [
497527
"//third_party/abseil-cpp/absl/memory",
498528
"//third_party/abseil-cpp/absl/strings",
529+
"//third_party/abseil-cpp/absl/types:optional",
499530
]
500531

501532
if (rtc_use_x11_extensions) {
@@ -516,10 +547,10 @@ rtc_library("desktop_capture_generic") {
516547
sources += [
517548
"linux/base_capturer_pipewire.cc",
518549
"linux/base_capturer_pipewire.h",
519-
"linux/screen_capturer_pipewire.cc",
520-
"linux/screen_capturer_pipewire.h",
521-
"linux/window_capturer_pipewire.cc",
522-
"linux/window_capturer_pipewire.h",
550+
"linux/pipewire_base.cc",
551+
"linux/pipewire_base.h",
552+
"linux/xdg_desktop_portal_base.cc",
553+
"linux/xdg_desktop_portal_base.h",
523554
]
524555

525556
configs += [

modules/desktop_capture/desktop_capture_options.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ DesktopCaptureOptions DesktopCaptureOptions::CreateDefault() {
3535
#if defined(WEBRTC_USE_X11)
3636
result.set_x_display(SharedXDisplay::CreateDefault());
3737
#endif
38+
#if defined(WEBRTC_USE_PIPEWIRE)
39+
result.set_xdp_base(XdgDesktopPortalBase::CreateDefault());
40+
#endif
3841
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
3942
result.set_configuration_monitor(new DesktopConfigurationMonitor());
4043
result.set_full_screen_window_detector(

modules/desktop_capture/desktop_capture_options.h

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_
1111
#define MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_
1212

13+
#include "absl/types/optional.h"
1314
#include "api/scoped_refptr.h"
1415
#include "rtc_base/system/rtc_export.h"
1516

@@ -23,6 +24,10 @@
2324

2425
#include "modules/desktop_capture/full_screen_window_detector.h"
2526

27+
#if defined(WEBRTC_USE_PIPEWIRE)
28+
#include "modules/desktop_capture/linux/xdg_desktop_portal_base.h"
29+
#endif
30+
2631
namespace webrtc {
2732

2833
// An object that stores initialization parameters for screen and window
@@ -131,13 +136,68 @@ class RTC_EXPORT DesktopCaptureOptions {
131136
#if defined(WEBRTC_USE_PIPEWIRE)
132137
bool allow_pipewire() const { return allow_pipewire_; }
133138
void set_allow_pipewire(bool allow) { allow_pipewire_ = allow; }
139+
140+
// Provides a way how to identify portal call for a sharing request
141+
// made by the client. This allows to go through the preview dialog
142+
// and to the web page itself with just one xdg-desktop-portal call.
143+
// Client is supposed to:
144+
// 1) Call start_request(id) to tell us an identificator for the current
145+
// request
146+
// 2) Call close_request(id) in case the preview dialog was cancelled
147+
// or user picked a web page to be shared
148+
// Note: In case the current request is not finalized, we will close it for
149+
// safety reasons and client will need to ask the portal again
150+
// This was done primarily for chromium support as there was no way how to
151+
// identify a portal call made for the preview and later on continue with the
152+
// same content on the web page itself.
153+
154+
void start_request(int32_t request_id) {
155+
// In case we get a duplicit start_request call, which might happen when a
156+
// browser requests both screen and window sharing, we don't want to do
157+
// anything.
158+
if (request_id == xdp_base_->CurrentConnectionId()) {
159+
return;
160+
}
161+
162+
// In case we are about to start a new request and the previous one is not
163+
// finalized and not stream to the web page itself we will just close it.
164+
if (!xdp_base_->IsConnectionStreamingOnWeb(absl::nullopt) &&
165+
xdp_base_->IsConnectionInitialized(absl::nullopt)) {
166+
xdp_base_->CloseConnection(absl::nullopt);
167+
}
168+
169+
xdp_base_->SetCurrentConnectionId(request_id);
170+
}
171+
172+
void close_request(int32_t request_id) {
173+
xdp_base_->CloseConnection(request_id);
174+
xdp_base_->SetCurrentConnectionId(absl::nullopt);
175+
}
176+
177+
absl::optional<int32_t> request_id() {
178+
// Reset request_id in case the connection is in final state, which means it
179+
// is streaming content to the web page itself and nobody should be asking
180+
// again for this ID.
181+
if (xdp_base_->IsConnectionStreamingOnWeb(absl::nullopt)) {
182+
xdp_base_->SetCurrentConnectionId(absl::nullopt);
183+
}
184+
185+
return xdp_base_->CurrentConnectionId();
186+
}
187+
188+
XdgDesktopPortalBase* xdp_base() const { return xdp_base_; }
189+
void set_xdp_base(rtc::scoped_refptr<XdgDesktopPortalBase> xdp_base) {
190+
xdp_base_ = std::move(xdp_base);
191+
}
134192
#endif
135193

136194
private:
137195
#if defined(WEBRTC_USE_X11)
138196
rtc::scoped_refptr<SharedXDisplay> x_display_;
139197
#endif
140-
198+
#if defined(WEBRTC_USE_PIPEWIRE)
199+
rtc::scoped_refptr<XdgDesktopPortalBase> xdp_base_;
200+
#endif
141201
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
142202
rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;
143203
bool allow_iosurface_ = false;

0 commit comments

Comments
 (0)