diff --git a/libs/scrap/src/wayland/pipewire.rs b/libs/scrap/src/wayland/pipewire.rs index 8859d0d3b..f0852e564 100644 --- a/libs/scrap/src/wayland/pipewire.rs +++ b/libs/scrap/src/wayland/pipewire.rs @@ -507,6 +507,22 @@ where }) } +// The request object path a portal method call will use, derived from our unique +// bus name and the `handle_token` we pass in the call arguments. Knowing it up +// front lets us subscribe to the `Response` signal *before* making the call. +// https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Request.html +fn get_request_path( + conn: &SyncConnection, + handle_token: &str, +) -> Result, dbus::Error> { + let sender = conn.unique_name().trim_start_matches(':').replace('.', "_"); + dbus::Path::new(format!( + "/org/freedesktop/portal/desktop/request/{}/{}", + sender, handle_token + )) + .map_err(|_| dbus::Error::new_failed("Failed to construct portal request path")) +} + pub fn get_portal(conn: &SyncConnection) -> Proxy<&SyncConnection> { conn.with_proxy( "org.freedesktop.portal.Desktop", @@ -632,13 +648,14 @@ pub fn request_remote_desktop( let failure_res = failure.clone(); let session: Arc>> = Arc::new(Mutex::new(None)); let session_res = session.clone(); + let create_session_handle_token = "u1"; args.insert( "session_handle_token".to_string(), - Variant(Box::new("u1".to_string())), + Variant(Box::new(create_session_handle_token.to_string())), ); args.insert( "handle_token".to_string(), - Variant(Box::new("u1".to_string())), + Variant(Box::new(create_session_handle_token.to_string())), ); let mut is_support_restore_token = false; @@ -654,15 +671,9 @@ pub fn request_remote_desktop( // between the caller subscribing to the signal after receiving the reply for the method call and the signal getting emitted, // a convention for Request object paths has been established that allows // the caller to subscribe to the signal before making the method call. - let path; - if is_server_running() { - path = screencast_portal::create_session(&portal, args)?; - } else { - path = remote_desktop_portal::create_session(&portal, args)?; - } handle_response( &conn, - path, + get_request_path(&conn, create_session_handle_token)?, on_create_session_response( fd.clone(), streams.clone(), @@ -673,6 +684,11 @@ pub fn request_remote_desktop( ), failure_res.clone(), )?; + if is_server_running() { + let _ = screencast_portal::create_session(&portal, args)?; + } else { + let _ = remote_desktop_portal::create_session(&portal, args)?; + } // wait 3 minutes for user interaction for _ in 0..1800 { @@ -751,9 +767,10 @@ fn on_create_session_response( // persist_mode may be configured by the user. args.insert("persist_mode".to_string(), Variant(Box::new(2u32))); } + let select_sources_handle_token = "u3"; args.insert( "handle_token".to_string(), - Variant(Box::new("u3".to_string())), + Variant(Box::new(select_sources_handle_token.to_string())), ); // https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.ScreenCast.html if is_server_running() { @@ -769,42 +786,43 @@ fn on_create_session_response( }); } - let path = portal.select_sources(ses.clone(), args)?; handle_response( c, - path, + get_request_path(c, select_sources_handle_token)?, on_select_sources_response( fd.clone(), streams.clone(), failure.clone(), - ses, + ses.clone(), is_support_restore_token, ), failure.clone(), )?; + let _ = portal.select_sources(ses.clone(), args)?; } else { // TODO: support persist_mode for remote_desktop_portal // https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html + let select_devices_handle_token = "u2"; args.insert( "handle_token".to_string(), - Variant(Box::new("u2".to_string())), + Variant(Box::new(select_devices_handle_token.to_string())), ); args.insert("types".to_string(), Variant(Box::new(7u32))); - let path = portal.select_devices(ses.clone(), args)?; handle_response( c, - path, + get_request_path(c, select_devices_handle_token)?, on_select_devices_response( fd.clone(), streams.clone(), failure.clone(), - ses, + ses.clone(), is_support_restore_token, ), failure.clone(), )?; + let _ = portal.select_devices(ses.clone(), args)?; } Ok(()) @@ -825,9 +843,10 @@ fn on_select_devices_response( move |_: OrgFreedesktopPortalRequestResponse, c, _| { let portal = get_portal(c); let mut args: PropMap = HashMap::new(); + let select_sources_handle_token = "u3"; args.insert( "handle_token".to_string(), - Variant(Box::new("u3".to_string())), + Variant(Box::new(select_sources_handle_token.to_string())), ); // https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.ScreenCast.html if is_server_running() { @@ -836,19 +855,19 @@ fn on_select_devices_response( args.insert("types".into(), Variant(Box::new(1u32))); //| 2u32))); let session = session.clone(); - let path = portal.select_sources(session.clone(), args)?; handle_response( c, - path, + get_request_path(c, select_sources_handle_token)?, on_select_sources_response( fd.clone(), streams.clone(), failure.clone(), - session, + session.clone(), is_support_restore_token, ), failure.clone(), )?; + let _ = portal.select_sources(session.clone(), args)?; Ok(()) } @@ -868,19 +887,14 @@ fn on_select_sources_response( move |_: OrgFreedesktopPortalRequestResponse, c, _| { let portal = get_portal(c); let mut args: PropMap = HashMap::new(); + let start_handle_token = "u4"; args.insert( "handle_token".to_string(), - Variant(Box::new("u4".to_string())), + Variant(Box::new(start_handle_token.to_string())), ); - let path; - if is_server_running() { - path = screencast_portal::start(&portal, session.clone(), "", args)?; - } else { - path = remote_desktop_portal::start(&portal, session.clone(), "", args)?; - } handle_response( c, - path, + get_request_path(c, start_handle_token)?, on_start_response( fd.clone(), streams.clone(), @@ -889,6 +903,11 @@ fn on_select_sources_response( ), failure.clone(), )?; + if is_server_running() { + let _ = screencast_portal::start(&portal, session.clone(), "", args)?; + } else { + let _ = remote_desktop_portal::start(&portal, session.clone(), "", args)?; + } Ok(()) }