Skip to content

Commit

Permalink
remote: Add API to allow for persistence on RemoteDesktop sessions
Browse files Browse the repository at this point in the history
Same as the ScreenCast API

Fixes #127
  • Loading branch information
whot committed Oct 18, 2023
1 parent f375bfa commit 8210d54
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 13 deletions.
54 changes: 51 additions & 3 deletions libportal/remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,12 @@ select_devices (CreateCall *call)
g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&options, "{sv}", "handle_token", g_variant_new_string (token));
g_variant_builder_add (&options, "{sv}", "types", g_variant_new_uint32 (call->devices));
if (call->portal->remote_desktop_interface_version >= 2)
{
g_variant_builder_add (&options, "{sv}", "persist_mode", g_variant_new_uint32 (call->persist_mode));
if (call->restore_token)
g_variant_builder_add (&options, "{sv}", "restore_token", g_variant_new_string (call->restore_token));
}
g_dbus_connection_call (call->portal->bus,
PORTAL_BUS_NAME,
PORTAL_OBJECT_PATH,
Expand Down Expand Up @@ -551,6 +557,48 @@ xdp_portal_create_remote_desktop_session (XdpPortal *portal,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
xdp_portal_create_remote_desktop_session_full (portal,
devices,
outputs,
flags,
cursor_mode,
XDP_PERSIST_MODE_NONE,
NULL,
cancellable,
callback,
data);
}

/**
* xdp_portal_create_remote_desktop_session_full:
* @portal: a [class@Portal]
* @devices: which kinds of input devices to ofer in the new dialog
* @outputs: which kinds of source to offer in the dialog
* @flags: options for this call
* @cursor_mode: the cursor mode of the session
* @persist_mode: the persist mode of the session
* @restore_token: (nullable): the token of a previous screencast session to restore
* @cancellable: (nullable): optional [[email protected]]
* @callback: (scope async): a callback to call when the request is done
* @data: (closure): data to pass to @callback
*
* Creates a session for remote desktop.
*
* When the request is done, @callback will be called. You can then
* call [[email protected]_remote_desktop_session_finish] to get the results.
*/
void
xdp_portal_create_remote_desktop_session_full (XdpPortal *portal,
XdpDeviceType devices,
XdpOutputType outputs,
XdpRemoteDesktopFlags flags,
XdpCursorMode cursor_mode,
XdpPersistMode persist_mode,
const char *restore_token,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data)
{
CreateCall *call;

Expand All @@ -563,8 +611,8 @@ xdp_portal_create_remote_desktop_session (XdpPortal *portal,
call->devices = devices;
call->outputs = outputs;
call->cursor_mode = cursor_mode;
call->persist_mode = XDP_PERSIST_MODE_NONE;
call->restore_token = NULL;
call->persist_mode = persist_mode;
call->restore_token = g_strdup (restore_token);
call->multiple = (flags & XDP_REMOTE_DESKTOP_FLAG_MULTIPLE) != 0;
call->task = g_task_new (portal, cancellable, callback, data);

Expand Down Expand Up @@ -1021,7 +1069,7 @@ xdp_session_pointer_motion (XdpSession *session,
*
* Moves the pointer to a new position in the given streams logical
* coordinate space.
*
*
* May only be called on a remote desktop session
* with `XDP_DEVICE_POINTER` access.
*/
Expand Down
13 changes: 13 additions & 0 deletions libportal/remote.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,19 @@ void xdp_portal_create_remote_desktop_session (XdpPortal
GAsyncReadyCallback callback,
gpointer data);

XDP_PUBLIC
void xdp_portal_create_remote_desktop_session_full (XdpPortal *portal,
XdpDeviceType devices,
XdpOutputType outputs,
XdpRemoteDesktopFlags flags,
XdpCursorMode cursor_mode,
XdpPersistMode persist_mode,
const char *restore_token,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer data);


XDP_PUBLIC
XdpSession *xdp_portal_create_remote_desktop_session_finish (XdpPortal *portal,
GAsyncResult *result,
Expand Down
105 changes: 95 additions & 10 deletions tests/pyportaltest/test_remotedesktop.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ def create_session(
flags=Xdp.RemoteDesktopFlags.NONE,
cursor_mode=Xdp.CursorMode.HIDDEN,
start_session=True,
persist_mode=None,
restore_token=None,
) -> SessionSetup:
params = params or {}
# To make the tests easier, load ScreenCast automatically if we have
Expand All @@ -79,16 +81,28 @@ def create_session_done(portal, task, data):
session_error = e
self.mainloop.quit()

xdp.create_remote_desktop_session(
devices=devices,
outputs=outputs,
flags=flags,
cursor_mode=cursor_mode,
cancellable=cancellable,
callback=create_session_done,
data=None,
)

if restore_token is not None and persist_mode is not None:
xdp.create_remote_desktop_session_full(
devices=devices,
outputs=outputs,
flags=flags,
cursor_mode=cursor_mode,
persist_mode=persist_mode,
restore_token=restore_token,
cancellable=cancellable,
callback=create_session_done,
data=None,
)
else:
xdp.create_remote_desktop_session(
devices=devices,
outputs=outputs,
flags=flags,
cursor_mode=cursor_mode,
cancellable=cancellable,
callback=create_session_done,
data=None,
)
self.mainloop.run()
assert create_session_done_invoked
if session_error is not None:
Expand Down Expand Up @@ -166,8 +180,76 @@ def test_create_session(self):
assert list(options.keys()) == [
"handle_token",
"types",
"persist_mode",
]
assert options["types"] == devices
assert options["persist_mode"] == Xdp.PersistMode.NONE

method_calls = self.mock_interface.GetMethodCalls("SelectSources")
assert len(method_calls) == 1
_, args = method_calls.pop(0)
session_handle, options = args

assert list(options.keys()) == [
"handle_token",
"types",
"multiple",
"cursor_mode",
"persist_mode",
]

assert options["types"] == outputs
assert options["multiple"] == flags
assert options["cursor_mode"] == cursor_mode
assert options["persist_mode"] == Xdp.PersistMode.NONE

def test_create_session_restore(self):
"""
Create a session with some "random" values and ensure that they're
passed through to the portal.
"""
devices = Xdp.DeviceType.POINTER | Xdp.DeviceType.KEYBOARD
outputs = Xdp.OutputType.MONITOR | Xdp.OutputType.WINDOW
cursor_mode = Xdp.CursorMode.METADATA
flags = Xdp.RemoteDesktopFlags.MULTIPLE
persist_mode = Xdp.PersistMode.PERSISTENT
restore_token = "12345"

self.create_session(
devices=devices,
outputs=outputs,
flags=flags,
cursor_mode=cursor_mode,
persist_mode=persist_mode,
restore_token=restore_token,
start_session=False,
)

# Now verify our DBus calls were correct
method_calls = self.mock_interface.GetMethodCalls("CreateSession")
assert len(method_calls) == 1
_, args = method_calls.pop(0)
(options,) = args

assert list(options.keys()) == [
"handle_token",
"session_handle_token",
]

method_calls = self.mock_interface.GetMethodCalls("SelectDevices")
assert len(method_calls) == 1
_, args = method_calls.pop(0)
session_handle, options = args

assert list(options.keys()) == [
"handle_token",
"types",
"persist_mode",
"restore_token",
]
assert options["types"] == devices
assert options["persist_mode"] == persist_mode
assert options["restore_token"] == restore_token

method_calls = self.mock_interface.GetMethodCalls("SelectSources")
assert len(method_calls) == 1
Expand All @@ -180,6 +262,7 @@ def test_create_session(self):
"multiple",
"cursor_mode",
"persist_mode",
"restore_token",
]

assert options["types"] == outputs
Expand Down Expand Up @@ -223,8 +306,10 @@ def test_create_session_no_outputs(self):
assert list(options.keys()) == [
"handle_token",
"types",
"persist_mode",
]
assert options["types"] == devices
assert options["persist_mode"] == Xdp.PersistMode.NONE

# No outputs means this should never get called
method_calls = self.mock_interface.GetMethodCalls("SelectSources")
Expand Down

0 comments on commit 8210d54

Please sign in to comment.