Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remote-desktop: add the ability to communicate via an EIS socket #762

Merged
merged 3 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions data/org.freedesktop.impl.portal.RemoteDesktop.xml
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,26 @@
<arg type="a{sv}" name="options" direction="in"/>
<arg type="u" name="slot" direction="in"/>
</method>
<!--
ConnectToEIS:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@app_id: App id of the application
@options: Vardict with optional further information
@fd: A file descriptor to an EIS implementation that can be passed to a
sender libei context

Request a connection to an EIS implementation.

This method is available in version 2 of this interface.
GeorgesStavracas marked this conversation as resolved.
Show resolved Hide resolved
-->
<method name="ConnectToEIS">
<annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
<arg type="o" name="session_handle" direction="in"/>
<arg type="s" name="app_id" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
<arg type="a{sv}" name="options" direction="in"/>
<arg type="h" name="fd" direction="out"/>
</method>
<!--
AvailableDeviceTypes:

Expand Down
31 changes: 31 additions & 0 deletions data/org.freedesktop.portal.RemoteDesktop.xml
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,37 @@
<arg type="a{sv}" name="options" direction="in"/>
<arg type="u" name="slot" direction="in"/>
</method>

<!--
ConnectToEIS:
@session_handle: Object path for the #org.freedesktop.portal.Session object
@options: Vardict with optional further information
@fd: A file descriptor to an EIS implementation that can be passed to a libei sender context

Request a connection to an EIS implementation. The returned handle can
be passed to ei_setup_backend_fd() for a libei sender context to
complete the connection. All information about available devices and the
event flow is subject to libei. Please see the libei documentation for details.

This method may only be called once per session, where the EIS
implementation disconnects the session should be closed.

This method must be called after #org.freedesktop.portal.RemoteDesktop.Start()

Once an EIS connection is established, input events must be sent exclusively via
the EIS connection. Any events submitted via NotifyPointerMotion,
NotifyKeyboardKeycode and other Notify* methods will return an error.

This method was added in version 2 of this interface.
-->
<method name="ConnectToEIS">
<annotation name="org.gtk.GDBus.C.Name" value="connect_to_eis"/>
<annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
<arg type="o" name="session_handle" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<arg type="h" name="fd" direction="out"/>
</method>

<!--
AvailableDeviceTypes:

Expand Down
126 changes: 115 additions & 11 deletions src/remote-desktop.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "xdp-impl-dbus.h"
#include "xdp-utils.h"

#include <gio/gunixfdlist.h>
#include <stdint.h>

typedef struct _RemoteDesktop RemoteDesktop;
Expand Down Expand Up @@ -88,6 +89,8 @@ typedef struct _RemoteDesktopSession
gboolean sources_selected;

gboolean clipboard_enabled;

gboolean uses_eis;
} RemoteDesktopSession;

typedef struct _RemoteDesktopSessionClass
Expand Down Expand Up @@ -695,7 +698,7 @@ check_notify (Session *session,
{
RemoteDesktopSession *remote_desktop_session = (RemoteDesktopSession *)session;

if (!remote_desktop_session->devices_selected)
if (!remote_desktop_session->devices_selected || remote_desktop_session->uses_eis)
return FALSE;

switch (remote_desktop_session->state)
Expand Down Expand Up @@ -771,7 +774,7 @@ handle_notify_pointer_motion (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: pointer");
"Session is not allowed to call NotifyPointer methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand Down Expand Up @@ -829,7 +832,7 @@ handle_notify_pointer_motion_absolute (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: pointer");
"Session is not allowed to call NotifyPointer methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand Down Expand Up @@ -897,7 +900,7 @@ handle_notify_pointer_button (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: pointer");
"Session is not allowed to call NotifyPointer methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand Down Expand Up @@ -960,7 +963,7 @@ handle_notify_pointer_axis (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: pointer");
"Session is not allowed to call NotifyPointer methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand Down Expand Up @@ -1018,7 +1021,7 @@ handle_notify_pointer_axis_discrete (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: pointer");
"Session is not allowed to call NotifyPointer methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand Down Expand Up @@ -1076,7 +1079,7 @@ handle_notify_keyboard_keycode (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: keyboard");
"Session is not allowed to call NotifyPointer methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand Down Expand Up @@ -1134,7 +1137,7 @@ handle_notify_keyboard_keysym (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: keyboard");
"Session is not allowed to call NotifyKeyboard methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand Down Expand Up @@ -1194,7 +1197,7 @@ handle_notify_touch_down (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: touchscreen");
"Session is not allowed to call NotifyTouch methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand Down Expand Up @@ -1264,7 +1267,7 @@ handle_notify_touch_motion (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: touchscreen");
"Session is not allowed to call NotifyTouch methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand Down Expand Up @@ -1331,7 +1334,7 @@ handle_notify_touch_up (XdpDbusRemoteDesktop *object,
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session doesn't have access to a device of type: touchscreen");
"Session is not allowed to call NotifyTouch methods");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

Expand All @@ -1357,6 +1360,105 @@ handle_notify_touch_up (XdpDbusRemoteDesktop *object,
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

static XdpOptionKey remote_desktop_connect_to_eis_options[] = {
};

static gboolean
handle_connect_to_eis (XdpDbusRemoteDesktop *object,
GDBusMethodInvocation *invocation,
GUnixFDList *in_fd_list,
const char *arg_session_handle,
GVariant *arg_options)
{
Call *call = call_from_invocation (invocation);
Session *session;
RemoteDesktopSession *remote_desktop_session;
g_autoptr(GUnixFDList) out_fd_list = NULL;
g_autoptr(GError) error = NULL;
GVariantBuilder options_builder;
GVariant *fd;

session = acquire_session_from_call (arg_session_handle, call);
if (!session)
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Invalid session");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

SESSION_AUTOLOCK_UNREF (session);

if (!is_remote_desktop_session (session))
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Invalid session");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

remote_desktop_session = (RemoteDesktopSession *)session;

if (remote_desktop_session->uses_eis)
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session is already connected");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

switch (remote_desktop_session->state)
{
case REMOTE_DESKTOP_SESSION_STATE_STARTED:
break;
case REMOTE_DESKTOP_SESSION_STATE_INIT:
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session is not ready");
return G_DBUS_METHOD_INVOCATION_HANDLED;
case REMOTE_DESKTOP_SESSION_STATE_CLOSED:
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session is already closed");
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
if (!xdp_filter_options (arg_options, &options_builder,
remote_desktop_connect_to_eis_options,
G_N_ELEMENTS (remote_desktop_connect_to_eis_options),
&error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

if (!xdp_dbus_impl_remote_desktop_call_connect_to_eis_sync (impl,
arg_session_handle,
xdp_app_info_get_id (call->app_info),
g_variant_builder_end (&options_builder),
in_fd_list,
&fd,
&out_fd_list,
NULL,
&error))
{
g_warning ("Failed to ConnectToEIS: %s", error->message);
g_dbus_method_invocation_return_gerror (invocation, error);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

remote_desktop_session->uses_eis = TRUE;
whot marked this conversation as resolved.
Show resolved Hide resolved

xdp_dbus_remote_desktop_complete_connect_to_eis (object, invocation, out_fd_list, fd);
return G_DBUS_METHOD_INVOCATION_HANDLED;
}

static void
remote_desktop_iface_init (XdpDbusRemoteDesktopIface *iface)
{
Expand All @@ -1374,6 +1476,8 @@ remote_desktop_iface_init (XdpDbusRemoteDesktopIface *iface)
iface->handle_notify_touch_down = handle_notify_touch_down;
iface->handle_notify_touch_motion = handle_notify_touch_motion;
iface->handle_notify_touch_up = handle_notify_touch_up;

GeorgesStavracas marked this conversation as resolved.
Show resolved Hide resolved
iface->handle_connect_to_eis = handle_connect_to_eis;
}

static void
Expand Down
2 changes: 1 addition & 1 deletion src/xdg-desktop-portal.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ method_needs_request (GDBusMethodInvocation *invocation)
}
else if (strcmp (interface, "org.freedesktop.portal.RemoteDesktop") == 0)
{
if (strstr (method, "Notify") == method)
if (strstr (method, "Notify") == method || strcmp (method, "ConnectToEIS") == 0)
return FALSE;
else
return TRUE;
Expand Down
1 change: 1 addition & 0 deletions tests/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ if enable_pytest
pytest,
args: ['--verbose', '--log-level=DEBUG'],
suite: ['pytest'],
timeout: 60,
)
endif

Expand Down
Loading
Loading