Skip to content

Commit

Permalink
remote-desktop: add the ability to communicate via an EIS socket
Browse files Browse the repository at this point in the history
This is intended as replacement for the NotifyFoo methods. libei
provides a more flexible and powerful method of sending input events to
the compositor.

A new method ConnectToEIS requests a file descriptor from the compositor
which can then be plugged into libei.

Once established, the communication between compositor and application
is direct, without the need to go through the portal process(es).

To avoid ambiguities between NotifyFoo and input events sent via libei,
any application that uses an EIS connection may not use the NotifyFoo
methods.
  • Loading branch information
whot committed Apr 1, 2022
1 parent 9e00c2f commit a6f208b
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 1 deletion.
19 changes: 19 additions & 0 deletions data/org.freedesktop.impl.portal.RemoteDesktop.xml
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,25 @@
<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 passive libei context
Request a connection to an EIS implementation.
This method is available in version 2 of this interface.
-->
<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
33 changes: 32 additions & 1 deletion data/org.freedesktop.portal.RemoteDesktop.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
The Remote desktop portal allows to create remote desktop sessions.
This documentation describes version 1 of this interface.
This documentation describes version 2 of this interface.
-->
<interface name="org.freedesktop.portal.RemoteDesktop">
<!--
Expand Down Expand Up @@ -382,6 +382,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 an active libei context
Request a connection to an EIS implementation. The returned handle can
be passed to ei_setup_backend_socket() 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 before #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 be silently discarded.
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
112 changes: 112 additions & 0 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 @@ -85,6 +86,7 @@ typedef struct _RemoteDesktopSession
DeviceType shared_devices;

GList *streams;
gboolean uses_eis;
} RemoteDesktopSession;

typedef struct _RemoteDesktopSessionClass
Expand Down Expand Up @@ -686,6 +688,9 @@ check_notify (Session *session,
{
RemoteDesktopSession *remote_desktop_session = (RemoteDesktopSession *)session;

if (remote_desktop_session->uses_eis)
return FALSE;

switch (remote_desktop_session->state)
{
case REMOTE_DESKTOP_SESSION_STATE_STARTED:
Expand Down Expand Up @@ -1350,6 +1355,111 @@ 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_INIT:
case REMOTE_DESKTOP_SESSION_STATE_DEVICES_SELECTED:
case REMOTE_DESKTOP_SESSION_STATE_SELECTING_DEVICES:
case REMOTE_DESKTOP_SESSION_STATE_SOURCES_SELECTED:
case REMOTE_DESKTOP_SESSION_STATE_SELECTING_SOURCES:
break;
case REMOTE_DESKTOP_SESSION_STATE_STARTED:
case REMOTE_DESKTOP_SESSION_STATE_STARTING:
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session is already started");
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);
out_fd_list = g_unix_fd_list_new ();
}

/* FIXME: libreis_set_name() and friends */

remote_desktop_session->uses_eis = TRUE;

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 @@ -1367,6 +1477,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;

iface->handle_connect_to_eis = handle_connect_to_eis;
}

static void
Expand Down

0 comments on commit a6f208b

Please sign in to comment.