diff --git a/modules/desktop_capture/linux/wayland/screencast_portal.cc b/modules/desktop_capture/linux/wayland/screencast_portal.cc index 0b9db6ffb0..bbf933966b 100644 --- a/modules/desktop_capture/linux/wayland/screencast_portal.cc +++ b/modules/desktop_capture/linux/wayland/screencast_portal.cc @@ -39,7 +39,24 @@ using xdg_portal::TearDownSession; ScreenCastPortal::ScreenCastPortal( ScreenCastPortal::CaptureSourceType source_type, PortalNotifier* notifier) - : notifier_(notifier), capture_source_type_(source_type) {} + : ScreenCastPortal(source_type, + notifier, + OnProxyRequested, + OnSourcesRequestResponseSignal, + this) {} + +ScreenCastPortal::ScreenCastPortal( + CaptureSourceType source_type, + PortalNotifier* notifier, + ProxyRequestResponseHandler proxy_request_response_handler, + SourcesRequestResponseSignalHandler sources_request_response_signal_handler, + gpointer user_data) + : notifier_(notifier), + capture_source_type_(source_type), + proxy_request_response_handler_(proxy_request_response_handler), + sources_request_response_signal_handler_( + sources_request_response_signal_handler), + user_data_(user_data) {} ScreenCastPortal::~ScreenCastPortal() { UnsubscribeSignalHandlers(); @@ -72,10 +89,27 @@ void ScreenCastPortal::UnsubscribeSignalHandlers() { } } +void ScreenCastPortal::SetSessionDetails( + const xdg_portal::SessionDetails& session_details) { + if (session_details.proxy) { + proxy_ = session_details.proxy; + connection_ = g_dbus_proxy_get_connection(proxy_); + } + if (session_details.cancellable) { + cancellable_ = session_details.cancellable; + } + if (!session_details.session_handle.empty()) { + session_handle_ = session_details.session_handle; + } + if (session_details.pipewire_stream_node_id) { + pw_stream_node_id_ = session_details.pipewire_stream_node_id; + } +} + void ScreenCastPortal::Start() { cancellable_ = g_cancellable_new(); - RequestSessionProxy(kScreenCastInterfaceName, OnProxyRequested, cancellable_, - this); + RequestSessionProxy(kScreenCastInterfaceName, proxy_request_response_handler_, + cancellable_, this); } void ScreenCastPortal::PortalFailed(RequestResponse result) { @@ -177,8 +211,8 @@ void ScreenCastPortal::SourcesRequest() { sources_handle_ = PrepareSignalHandle(variant_string.get(), connection_); sources_request_signal_id_ = SetupRequestResponseSignal( - sources_handle_.c_str(), OnSourcesRequestResponseSignal, this, - connection_); + sources_handle_.c_str(), sources_request_response_signal_handler_, + user_data_, connection_); RTC_LOG(LS_INFO) << "Requesting sources from the screen cast session."; g_dbus_proxy_call( @@ -316,6 +350,10 @@ void ScreenCastPortal::OnStartRequestResponseSignal(GDBusConnection* connection, that->OpenPipeWireRemote(); } +uint32_t ScreenCastPortal::pipewire_stream_node_id() { + return pw_stream_node_id_; +} + void ScreenCastPortal::OpenPipeWireRemote() { GVariantBuilder builder; g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); diff --git a/modules/desktop_capture/linux/wayland/screencast_portal.h b/modules/desktop_capture/linux/wayland/screencast_portal.h index 75884450db..d29f773cb2 100644 --- a/modules/desktop_capture/linux/wayland/screencast_portal.h +++ b/modules/desktop_capture/linux/wayland/screencast_portal.h @@ -21,6 +21,19 @@ namespace webrtc { class ScreenCastPortal { public: + using ProxyRequestResponseHandler = void (*)(GObject* object, + GAsyncResult* result, + gpointer user_data); + + using SourcesRequestResponseSignalHandler = + void (*)(GDBusConnection* connection, + const char* sender_name, + const char* object_path, + const char* interface_name, + const char* signal_name, + GVariant* parameters, + gpointer user_data); + // Values are set based on source type property in // xdg-desktop-portal/screencast // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml @@ -57,6 +70,13 @@ class ScreenCastPortal { explicit ScreenCastPortal(ScreenCastPortal::CaptureSourceType source_type, PortalNotifier* notifier); + explicit ScreenCastPortal( + CaptureSourceType source_type, + PortalNotifier* notifier, + ProxyRequestResponseHandler proxy_request_response_handler, + SourcesRequestResponseSignalHandler + sources_request_response_signal_handler, + gpointer user_data); ~ScreenCastPortal(); // Initialize ScreenCastPortal with series of DBus calls where we try to @@ -76,6 +96,13 @@ class ScreenCastPortal { void UnsubscribeSignalHandlers(); + // Set of methods leveraged by remote desktop portal to setup a common session + // with screen cast portal. + void SetSessionDetails(const xdg_portal::SessionDetails& session_details); + uint32_t pipewire_stream_node_id(); + void SourcesRequest(); + void OpenPipeWireRemote(); + private: PortalNotifier* notifier_; @@ -89,6 +116,10 @@ class ScreenCastPortal { CursorMode cursor_mode_ = ScreenCastPortal::CursorMode::kMetadata; + ProxyRequestResponseHandler proxy_request_response_handler_; + SourcesRequestResponseSignalHandler sources_request_response_signal_handler_; + gpointer user_data_; + GDBusConnection* connection_ = nullptr; GDBusProxy* proxy_ = nullptr; GCancellable* cancellable_ = nullptr; @@ -121,7 +152,6 @@ class ScreenCastPortal { const char* signal_name, GVariant* parameters, gpointer user_data); - void SourcesRequest(); static void OnSourcesRequested(GDBusProxy* proxy, GAsyncResult* result, gpointer user_data); @@ -145,7 +175,6 @@ class ScreenCastPortal { GVariant* parameters, gpointer user_data); - void OpenPipeWireRemote(); static void OnOpenPipeWireRemoteRequested(GDBusProxy* proxy, GAsyncResult* result, gpointer user_data); diff --git a/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h b/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h index 9b7953424d..4fb058c427 100644 --- a/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h +++ b/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h @@ -32,6 +32,13 @@ constexpr char kSessionInterfaceName[] = "org.freedesktop.portal.Session"; constexpr char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; constexpr char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; +struct SessionDetails { + GDBusProxy* proxy; + GCancellable* cancellable; + std::string session_handle; + uint32_t pipewire_stream_node_id; +}; + using ProxyRequestCallback = void (*)(GObject*, GAsyncResult*, gpointer); using SessionRequestCallback = void (*)(GDBusProxy*, GAsyncResult*, gpointer); using SessionRequestResponseSignalHandler = void (*)(GDBusConnection*,