2017-06-21 06:23:44 +00:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2015-2017 Red Hat Inc.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "backends/meta-remote-desktop-session.h"
|
|
|
|
|
|
|
|
#include <linux/input.h>
|
|
|
|
#include <xkbcommon/xkbcommon.h>
|
2018-01-29 06:28:07 +00:00
|
|
|
#include <stdlib.h>
|
2017-06-21 06:23:44 +00:00
|
|
|
|
|
|
|
#include "backends/meta-dbus-session-watcher.h"
|
|
|
|
#include "backends/meta-screen-cast-session.h"
|
2018-07-20 14:37:37 +00:00
|
|
|
#include "backends/meta-remote-access-controller-private.h"
|
2017-06-21 06:23:44 +00:00
|
|
|
#include "backends/x11/meta-backend-x11.h"
|
|
|
|
#include "cogl/cogl.h"
|
2020-11-04 09:27:40 +00:00
|
|
|
#include "core/display-private.h"
|
2017-06-21 06:23:44 +00:00
|
|
|
#include "meta/meta-backend.h"
|
2018-07-10 08:36:24 +00:00
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
#include "meta-dbus-remote-desktop.h"
|
|
|
|
|
|
|
|
#define META_REMOTE_DESKTOP_SESSION_DBUS_PATH "/org/gnome/Mutter/RemoteDesktop/Session"
|
|
|
|
|
2020-12-15 09:34:43 +00:00
|
|
|
typedef enum _MetaRemoteDesktopNotifyAxisFlags
|
2018-01-29 06:40:28 +00:00
|
|
|
{
|
2020-12-15 09:34:43 +00:00
|
|
|
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_NONE = 0,
|
2018-01-29 06:40:28 +00:00
|
|
|
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH = 1 << 0,
|
2020-12-15 09:34:43 +00:00
|
|
|
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_WHEEL = 1 << 1,
|
|
|
|
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_FINGER = 1 << 2,
|
|
|
|
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_CONTINUOUS = 1 << 3,
|
2018-01-29 06:40:28 +00:00
|
|
|
} MetaRemoteDesktopNotifyAxisFlags;
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
struct _MetaRemoteDesktopSession
|
|
|
|
{
|
|
|
|
MetaDBusRemoteDesktopSessionSkeleton parent;
|
|
|
|
|
2020-11-04 09:27:40 +00:00
|
|
|
GDBusConnection *connection;
|
2017-08-25 07:19:53 +00:00
|
|
|
char *peer_name;
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
char *session_id;
|
|
|
|
char *object_path;
|
|
|
|
|
|
|
|
MetaScreenCastSession *screen_cast_session;
|
|
|
|
gulong screen_cast_session_closed_handler_id;
|
2020-05-16 08:44:04 +00:00
|
|
|
guint started : 1;
|
2017-06-21 06:23:44 +00:00
|
|
|
|
|
|
|
ClutterVirtualInputDevice *virtual_pointer;
|
|
|
|
ClutterVirtualInputDevice *virtual_keyboard;
|
2018-01-29 06:44:03 +00:00
|
|
|
ClutterVirtualInputDevice *virtual_touchscreen;
|
2018-07-20 14:37:37 +00:00
|
|
|
|
|
|
|
MetaRemoteDesktopSessionHandle *handle;
|
2020-10-13 15:38:42 +00:00
|
|
|
|
|
|
|
gboolean is_clipboard_enabled;
|
2020-11-04 09:27:40 +00:00
|
|
|
gulong owner_changed_handler_id;
|
|
|
|
unsigned int transfer_serial;
|
2017-06-21 06:23:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_remote_desktop_session_init_iface (MetaDBusRemoteDesktopSessionIface *iface);
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_dbus_session_init_iface (MetaDbusSessionInterface *iface);
|
|
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (MetaRemoteDesktopSession,
|
|
|
|
meta_remote_desktop_session,
|
|
|
|
META_DBUS_TYPE_REMOTE_DESKTOP_SESSION_SKELETON,
|
|
|
|
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_REMOTE_DESKTOP_SESSION,
|
|
|
|
meta_remote_desktop_session_init_iface)
|
|
|
|
G_IMPLEMENT_INTERFACE (META_TYPE_DBUS_SESSION,
|
|
|
|
meta_dbus_session_init_iface))
|
|
|
|
|
2018-07-20 14:37:37 +00:00
|
|
|
struct _MetaRemoteDesktopSessionHandle
|
|
|
|
{
|
|
|
|
MetaRemoteAccessHandle parent;
|
|
|
|
|
|
|
|
MetaRemoteDesktopSession *session;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaRemoteDesktopSessionHandle,
|
|
|
|
meta_remote_desktop_session_handle,
|
|
|
|
META_TYPE_REMOTE_ACCESS_HANDLE)
|
|
|
|
|
|
|
|
static MetaRemoteDesktopSessionHandle *
|
|
|
|
meta_remote_desktop_session_handle_new (MetaRemoteDesktopSession *session);
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
static gboolean
|
|
|
|
meta_remote_desktop_session_is_running (MetaRemoteDesktopSession *session)
|
|
|
|
{
|
|
|
|
return !!session->virtual_pointer;
|
|
|
|
}
|
|
|
|
|
2018-07-20 14:37:37 +00:00
|
|
|
static void
|
|
|
|
init_remote_access_handle (MetaRemoteDesktopSession *session)
|
|
|
|
{
|
|
|
|
MetaBackend *backend = meta_get_backend ();
|
|
|
|
MetaRemoteAccessController *remote_access_controller;
|
|
|
|
MetaRemoteAccessHandle *remote_access_handle;
|
|
|
|
|
|
|
|
session->handle = meta_remote_desktop_session_handle_new (session);
|
|
|
|
|
|
|
|
remote_access_controller = meta_backend_get_remote_access_controller (backend);
|
|
|
|
remote_access_handle = META_REMOTE_ACCESS_HANDLE (session->handle);
|
|
|
|
meta_remote_access_controller_notify_new_handle (remote_access_controller,
|
|
|
|
remote_access_handle);
|
|
|
|
}
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
static gboolean
|
|
|
|
meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
|
|
|
|
GError **error)
|
|
|
|
{
|
2019-10-02 12:40:40 +00:00
|
|
|
ClutterBackend *backend = clutter_get_default_backend ();
|
|
|
|
ClutterSeat *seat = clutter_backend_get_default_seat (backend);
|
2017-06-21 06:23:44 +00:00
|
|
|
|
2020-05-16 08:44:04 +00:00
|
|
|
g_assert (!session->started);
|
2017-06-21 06:23:44 +00:00
|
|
|
|
|
|
|
if (session->screen_cast_session)
|
|
|
|
{
|
|
|
|
if (!meta_screen_cast_session_start (session->screen_cast_session, error))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
session->virtual_pointer =
|
2019-10-02 12:40:40 +00:00
|
|
|
clutter_seat_create_virtual_device (seat, CLUTTER_POINTER_DEVICE);
|
2017-06-21 06:23:44 +00:00
|
|
|
session->virtual_keyboard =
|
2019-10-02 12:40:40 +00:00
|
|
|
clutter_seat_create_virtual_device (seat, CLUTTER_KEYBOARD_DEVICE);
|
2018-01-29 06:44:03 +00:00
|
|
|
session->virtual_touchscreen =
|
2019-10-02 12:40:40 +00:00
|
|
|
clutter_seat_create_virtual_device (seat, CLUTTER_TOUCHSCREEN_DEVICE);
|
2018-01-29 06:44:03 +00:00
|
|
|
|
2018-07-20 14:37:37 +00:00
|
|
|
init_remote_access_handle (session);
|
2020-05-16 08:44:04 +00:00
|
|
|
session->started = TRUE;
|
2018-07-20 14:37:37 +00:00
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_remote_desktop_session_close (MetaRemoteDesktopSession *session)
|
|
|
|
{
|
|
|
|
MetaDBusRemoteDesktopSession *skeleton =
|
|
|
|
META_DBUS_REMOTE_DESKTOP_SESSION (session);
|
|
|
|
|
2020-05-16 08:44:04 +00:00
|
|
|
session->started = FALSE;
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
if (session->screen_cast_session)
|
|
|
|
{
|
2019-11-16 00:25:52 +00:00
|
|
|
g_clear_signal_handler (&session->screen_cast_session_closed_handler_id,
|
|
|
|
session->screen_cast_session);
|
2017-06-21 06:23:44 +00:00
|
|
|
meta_screen_cast_session_close (session->screen_cast_session);
|
|
|
|
session->screen_cast_session = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_clear_object (&session->virtual_pointer);
|
|
|
|
g_clear_object (&session->virtual_keyboard);
|
2018-11-19 10:49:41 +00:00
|
|
|
g_clear_object (&session->virtual_touchscreen);
|
2017-06-21 06:23:44 +00:00
|
|
|
|
|
|
|
meta_dbus_session_notify_closed (META_DBUS_SESSION (session));
|
|
|
|
meta_dbus_remote_desktop_session_emit_closed (skeleton);
|
|
|
|
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (session));
|
|
|
|
|
2018-07-20 14:37:37 +00:00
|
|
|
if (session->handle)
|
|
|
|
{
|
|
|
|
MetaRemoteAccessHandle *remote_access_handle =
|
|
|
|
META_REMOTE_ACCESS_HANDLE (session->handle);
|
|
|
|
|
|
|
|
meta_remote_access_handle_notify_stopped (remote_access_handle);
|
|
|
|
}
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
g_object_unref (session);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
meta_remote_desktop_session_get_object_path (MetaRemoteDesktopSession *session)
|
|
|
|
{
|
|
|
|
return session->object_path;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
meta_remote_desktop_session_get_session_id (MetaRemoteDesktopSession *session)
|
|
|
|
{
|
|
|
|
return session->session_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_screen_cast_session_closed (MetaScreenCastSession *screen_cast_session,
|
|
|
|
MetaRemoteDesktopSession *session)
|
|
|
|
{
|
|
|
|
session->screen_cast_session = NULL;
|
|
|
|
meta_remote_desktop_session_close (session);
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_remote_desktop_session_register_screen_cast (MetaRemoteDesktopSession *session,
|
|
|
|
MetaScreenCastSession *screen_cast_session,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
if (session->screen_cast_session)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
"Remote desktop session already have an associated "
|
|
|
|
"screen cast session");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
session->screen_cast_session = screen_cast_session;
|
|
|
|
session->screen_cast_session_closed_handler_id =
|
|
|
|
g_signal_connect (screen_cast_session, "session-closed",
|
|
|
|
G_CALLBACK (on_screen_cast_session_closed),
|
|
|
|
session);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
MetaRemoteDesktopSession *
|
|
|
|
meta_remote_desktop_session_new (MetaRemoteDesktop *remote_desktop,
|
2017-08-25 07:19:53 +00:00
|
|
|
const char *peer_name,
|
2017-06-21 06:23:44 +00:00
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
GDBusInterfaceSkeleton *interface_skeleton;
|
|
|
|
MetaRemoteDesktopSession *session;
|
|
|
|
|
|
|
|
session = g_object_new (META_TYPE_REMOTE_DESKTOP_SESSION, NULL);
|
|
|
|
|
2017-08-25 07:19:53 +00:00
|
|
|
session->peer_name = g_strdup (peer_name);
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
interface_skeleton = G_DBUS_INTERFACE_SKELETON (session);
|
2020-11-04 09:27:40 +00:00
|
|
|
session->connection = meta_remote_desktop_get_connection (remote_desktop);
|
2017-06-21 06:23:44 +00:00
|
|
|
if (!g_dbus_interface_skeleton_export (interface_skeleton,
|
2020-11-04 09:27:40 +00:00
|
|
|
session->connection,
|
2017-06-21 06:23:44 +00:00
|
|
|
session->object_path,
|
|
|
|
error))
|
|
|
|
{
|
|
|
|
g_object_unref (session);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
2017-08-25 07:19:53 +00:00
|
|
|
static gboolean
|
|
|
|
check_permission (MetaRemoteDesktopSession *session,
|
|
|
|
GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
return g_strcmp0 (session->peer_name,
|
|
|
|
g_dbus_method_invocation_get_sender (invocation)) == 0;
|
|
|
|
}
|
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
static gboolean
|
|
|
|
meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session,
|
|
|
|
GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
if (!session->started)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Session not started");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!check_permission (session, invocation))
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_ACCESS_DENIED,
|
|
|
|
"Permission denied");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
static gboolean
|
|
|
|
handle_start (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
GError *error = NULL;
|
|
|
|
|
2020-05-16 08:44:04 +00:00
|
|
|
if (session->started)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Already started");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-08-25 07:19:53 +00:00
|
|
|
if (!check_permission (session, invocation))
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_ACCESS_DENIED,
|
|
|
|
"Permission denied");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
if (!meta_remote_desktop_session_start (session, &error))
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Failed to start remote desktop: %s",
|
|
|
|
error->message);
|
|
|
|
g_error_free (error);
|
|
|
|
|
|
|
|
meta_remote_desktop_session_close (session);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_start (skeleton, invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_stop (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
|
2020-05-16 08:44:04 +00:00
|
|
|
if (!session->started)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Session not started");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-08-25 07:19:53 +00:00
|
|
|
if (!check_permission (session, invocation))
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_ACCESS_DENIED,
|
|
|
|
"Permission denied");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
meta_remote_desktop_session_close (session);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_stop (skeleton, invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-01-29 06:38:13 +00:00
|
|
|
static gboolean
|
|
|
|
handle_notify_keyboard_keycode (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
unsigned int keycode,
|
|
|
|
gboolean pressed)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
ClutterKeyState state;
|
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2018-01-29 06:38:13 +00:00
|
|
|
|
|
|
|
if (pressed)
|
|
|
|
state = CLUTTER_KEY_STATE_PRESSED;
|
|
|
|
else
|
|
|
|
state = CLUTTER_KEY_STATE_RELEASED;
|
|
|
|
|
|
|
|
clutter_virtual_input_device_notify_key (session->virtual_keyboard,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
|
|
|
keycode,
|
|
|
|
state);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_keyboard_keycode (skeleton,
|
|
|
|
invocation);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
static gboolean
|
|
|
|
handle_notify_keyboard_keysym (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
unsigned int keysym,
|
|
|
|
gboolean pressed)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
ClutterKeyState state;
|
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2017-08-25 07:19:53 +00:00
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
if (pressed)
|
|
|
|
state = CLUTTER_KEY_STATE_PRESSED;
|
|
|
|
else
|
|
|
|
state = CLUTTER_KEY_STATE_RELEASED;
|
|
|
|
|
|
|
|
clutter_virtual_input_device_notify_keyval (session->virtual_keyboard,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
|
|
|
keysym,
|
|
|
|
state);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_keyboard_keysym (skeleton,
|
|
|
|
invocation);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Translation taken from the clutter evdev backend. */
|
|
|
|
static int
|
|
|
|
translate_to_clutter_button (int button)
|
|
|
|
{
|
|
|
|
switch (button)
|
|
|
|
{
|
|
|
|
case BTN_LEFT:
|
|
|
|
return CLUTTER_BUTTON_PRIMARY;
|
|
|
|
case BTN_RIGHT:
|
|
|
|
return CLUTTER_BUTTON_SECONDARY;
|
|
|
|
case BTN_MIDDLE:
|
|
|
|
return CLUTTER_BUTTON_MIDDLE;
|
|
|
|
default:
|
|
|
|
/*
|
|
|
|
* For compatibility reasons, all additional buttons go after the old
|
|
|
|
* 4-7 scroll ones.
|
|
|
|
*/
|
|
|
|
return button - (BTN_LEFT - 1) + 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_notify_pointer_button (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
int button_code,
|
|
|
|
gboolean pressed)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
uint32_t button;
|
|
|
|
ClutterButtonState state;
|
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2017-08-25 07:19:53 +00:00
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
button = translate_to_clutter_button (button_code);
|
|
|
|
|
|
|
|
if (pressed)
|
|
|
|
state = CLUTTER_BUTTON_STATE_PRESSED;
|
|
|
|
else
|
|
|
|
state = CLUTTER_BUTTON_STATE_RELEASED;
|
|
|
|
|
|
|
|
clutter_virtual_input_device_notify_button (session->virtual_pointer,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
|
|
|
button,
|
|
|
|
state);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_pointer_button (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-12-15 09:34:43 +00:00
|
|
|
static gboolean
|
|
|
|
clutter_scroll_source_from_axis_flags (MetaRemoteDesktopNotifyAxisFlags axis_flags,
|
|
|
|
ClutterScrollSource *scroll_source)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopNotifyAxisFlags scroll_mask;
|
|
|
|
|
|
|
|
scroll_mask = META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_WHEEL |
|
|
|
|
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_FINGER |
|
|
|
|
META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_CONTINUOUS;
|
|
|
|
|
|
|
|
switch (axis_flags & scroll_mask)
|
|
|
|
{
|
|
|
|
case META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_WHEEL:
|
|
|
|
*scroll_source = CLUTTER_SCROLL_SOURCE_WHEEL;
|
|
|
|
return TRUE;
|
|
|
|
case META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_NONE:
|
|
|
|
case META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_FINGER:
|
|
|
|
*scroll_source = CLUTTER_SCROLL_SOURCE_FINGER;
|
|
|
|
return TRUE;
|
|
|
|
case META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_CONTINUOUS:
|
|
|
|
*scroll_source = CLUTTER_SCROLL_SOURCE_CONTINUOUS;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2018-01-29 06:40:28 +00:00
|
|
|
static gboolean
|
|
|
|
handle_notify_pointer_axis (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
double dx,
|
|
|
|
double dy,
|
|
|
|
uint32_t flags)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE;
|
2020-12-15 09:34:43 +00:00
|
|
|
ClutterScrollSource scroll_source;
|
2018-01-29 06:40:28 +00:00
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2018-01-29 06:40:28 +00:00
|
|
|
|
2020-12-15 09:34:43 +00:00
|
|
|
if (!clutter_scroll_source_from_axis_flags (flags, &scroll_source))
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Invalid scroll source");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-01-29 06:40:28 +00:00
|
|
|
if (flags & META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH)
|
|
|
|
{
|
|
|
|
finish_flags |= (CLUTTER_SCROLL_FINISHED_HORIZONTAL |
|
|
|
|
CLUTTER_SCROLL_FINISHED_VERTICAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
clutter_virtual_input_device_notify_scroll_continuous (session->virtual_pointer,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
|
|
|
dx, dy,
|
2020-12-15 09:34:43 +00:00
|
|
|
scroll_source,
|
2018-01-29 06:40:28 +00:00
|
|
|
finish_flags);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_pointer_axis (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
static ClutterScrollDirection
|
|
|
|
discrete_steps_to_scroll_direction (unsigned int axis,
|
|
|
|
int steps)
|
|
|
|
{
|
|
|
|
if (axis == 0 && steps < 0)
|
|
|
|
return CLUTTER_SCROLL_UP;
|
|
|
|
if (axis == 0 && steps > 0)
|
|
|
|
return CLUTTER_SCROLL_DOWN;
|
|
|
|
if (axis == 1 && steps < 0)
|
|
|
|
return CLUTTER_SCROLL_LEFT;
|
|
|
|
if (axis == 1 && steps > 0)
|
|
|
|
return CLUTTER_SCROLL_RIGHT;
|
|
|
|
|
|
|
|
g_assert_not_reached ();
|
2019-01-24 23:47:44 +00:00
|
|
|
return 0;
|
2017-06-21 06:23:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_notify_pointer_axis_discrete (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
unsigned int axis,
|
|
|
|
int steps)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
ClutterScrollDirection direction;
|
2018-01-29 06:28:07 +00:00
|
|
|
int step_count;
|
2017-06-21 06:23:44 +00:00
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2017-08-25 07:19:53 +00:00
|
|
|
|
2018-01-29 06:26:47 +00:00
|
|
|
if (axis > 1)
|
2017-06-21 06:23:44 +00:00
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Invalid axis value");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (steps == 0)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Invalid axis steps value");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't have the actual scroll source, but only know they should be
|
|
|
|
* considered as discrete steps. The device that produces such scroll events
|
|
|
|
* is the scroll wheel, so pretend that is the scroll source.
|
|
|
|
*/
|
|
|
|
direction = discrete_steps_to_scroll_direction (axis, steps);
|
2018-01-29 06:28:07 +00:00
|
|
|
|
|
|
|
for (step_count = 0; step_count < abs (steps); step_count++)
|
|
|
|
clutter_virtual_input_device_notify_discrete_scroll (session->virtual_pointer,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
|
|
|
direction,
|
|
|
|
CLUTTER_SCROLL_SOURCE_WHEEL);
|
2017-06-21 06:23:44 +00:00
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_pointer_axis_discrete (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-01-29 06:40:57 +00:00
|
|
|
static gboolean
|
|
|
|
handle_notify_pointer_motion_relative (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
double dx,
|
|
|
|
double dy)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2018-01-29 06:40:57 +00:00
|
|
|
|
|
|
|
clutter_virtual_input_device_notify_relative_motion (session->virtual_pointer,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
|
|
|
dx, dy);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_pointer_motion_relative (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
static gboolean
|
|
|
|
handle_notify_pointer_motion_absolute (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
const char *stream_path,
|
|
|
|
double x,
|
|
|
|
double y)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
2018-01-29 06:42:48 +00:00
|
|
|
MetaScreenCastStream *stream;
|
|
|
|
double abs_x, abs_y;
|
2017-06-21 06:23:44 +00:00
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2018-01-29 06:42:48 +00:00
|
|
|
|
2020-06-29 13:01:55 +00:00
|
|
|
|
|
|
|
if (!session->screen_cast_session)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"No screen cast active");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-01-29 06:42:48 +00:00
|
|
|
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
|
|
|
stream_path);
|
|
|
|
if (!stream)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Unknown stream");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_screen_cast_stream_transform_position (stream, x, y, &abs_x, &abs_y);
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
clutter_virtual_input_device_notify_absolute_motion (session->virtual_pointer,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
2018-01-29 06:42:48 +00:00
|
|
|
abs_x, abs_y);
|
2017-06-21 06:23:44 +00:00
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_pointer_motion_absolute (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-01-29 06:44:03 +00:00
|
|
|
static gboolean
|
|
|
|
handle_notify_touch_down (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
const char *stream_path,
|
|
|
|
unsigned int slot,
|
|
|
|
double x,
|
|
|
|
double y)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
MetaScreenCastStream *stream;
|
|
|
|
double abs_x, abs_y;
|
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2018-01-29 06:44:03 +00:00
|
|
|
|
2020-10-22 09:18:34 +00:00
|
|
|
if (slot > CLUTTER_VIRTUAL_INPUT_DEVICE_MAX_TOUCH_SLOTS)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Touch slot out of range");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-06-29 13:01:55 +00:00
|
|
|
if (!session->screen_cast_session)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"No screen cast active");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-01-29 06:44:03 +00:00
|
|
|
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
|
|
|
stream_path);
|
|
|
|
if (!stream)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Unknown stream");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_screen_cast_stream_transform_position (stream, x, y, &abs_x, &abs_y);
|
|
|
|
|
|
|
|
clutter_virtual_input_device_notify_touch_down (session->virtual_touchscreen,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
|
|
|
slot,
|
|
|
|
abs_x, abs_y);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_touch_down (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_notify_touch_motion (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
const char *stream_path,
|
|
|
|
unsigned int slot,
|
|
|
|
double x,
|
|
|
|
double y)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
MetaScreenCastStream *stream;
|
|
|
|
double abs_x, abs_y;
|
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2018-01-29 06:44:03 +00:00
|
|
|
|
2020-06-29 13:01:55 +00:00
|
|
|
|
2020-10-22 09:18:34 +00:00
|
|
|
if (slot > CLUTTER_VIRTUAL_INPUT_DEVICE_MAX_TOUCH_SLOTS)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Touch slot out of range");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-06-29 13:01:55 +00:00
|
|
|
if (!session->screen_cast_session)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"No screen cast active");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-01-29 06:44:03 +00:00
|
|
|
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
|
|
|
stream_path);
|
|
|
|
if (!stream)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Unknown stream");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_screen_cast_stream_transform_position (stream, x, y, &abs_x, &abs_y);
|
|
|
|
|
|
|
|
clutter_virtual_input_device_notify_touch_motion (session->virtual_touchscreen,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
|
|
|
slot,
|
|
|
|
abs_x, abs_y);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_touch_motion (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_notify_touch_up (MetaDBusRemoteDesktopSession *skeleton,
|
2020-10-22 09:18:34 +00:00
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
unsigned int slot)
|
2018-01-29 06:44:03 +00:00
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
|
2020-05-16 08:46:57 +00:00
|
|
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
|
|
|
return TRUE;
|
2018-01-29 06:44:03 +00:00
|
|
|
|
2020-10-22 09:18:34 +00:00
|
|
|
if (slot > CLUTTER_VIRTUAL_INPUT_DEVICE_MAX_TOUCH_SLOTS)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Touch slot out of range");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2018-01-29 06:44:03 +00:00
|
|
|
clutter_virtual_input_device_notify_touch_up (session->virtual_touchscreen,
|
|
|
|
CLUTTER_CURRENT_TIME,
|
|
|
|
slot);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_notify_touch_up (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:27:40 +00:00
|
|
|
static const char *
|
|
|
|
mime_types_to_string (char **formats,
|
|
|
|
char *buf,
|
|
|
|
int buf_len)
|
|
|
|
{
|
|
|
|
g_autofree char *mime_types_string = NULL;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!formats)
|
|
|
|
return "N\\A";
|
|
|
|
|
|
|
|
mime_types_string = g_strjoinv (",", formats);
|
|
|
|
len = strlen (mime_types_string);
|
|
|
|
strncpy (buf, mime_types_string, buf_len - 1);
|
|
|
|
if (len >= buf_len - 1)
|
|
|
|
buf[buf_len - 2] = '*';
|
|
|
|
buf[buf_len - 1] = '\0';
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GVariant *
|
|
|
|
generate_owner_changed_variant (char **mime_types_array)
|
|
|
|
{
|
|
|
|
GVariantBuilder builder;
|
|
|
|
|
|
|
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
|
|
|
if (mime_types_array)
|
|
|
|
{
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "mime-types",
|
|
|
|
g_variant_new ("(^as)", mime_types_array));
|
|
|
|
}
|
|
|
|
|
|
|
|
return g_variant_builder_end (&builder);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_selection_owner_changed (MetaSelection *selection,
|
|
|
|
MetaSelectionType selection_type,
|
|
|
|
MetaSelectionSource *owner,
|
|
|
|
MetaRemoteDesktopSession *session)
|
|
|
|
{
|
|
|
|
char log_buf[255];
|
|
|
|
g_autofree char **mime_types_array = NULL;
|
|
|
|
GList *l;
|
|
|
|
int i;
|
|
|
|
GVariant *options_variant;
|
|
|
|
const char *object_path;
|
|
|
|
|
|
|
|
if (selection_type != META_SELECTION_CLIPBOARD)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (owner)
|
|
|
|
{
|
|
|
|
GList *mime_types;
|
|
|
|
mime_types = meta_selection_source_get_mimetypes (owner);
|
|
|
|
|
|
|
|
mime_types_array = g_new0 (char *, g_list_length (mime_types) + 1);
|
|
|
|
for (l = meta_selection_source_get_mimetypes (owner), i = 0;
|
|
|
|
l;
|
|
|
|
l = l->next, i++)
|
|
|
|
mime_types_array[i] = l->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
|
|
|
"Clipboard owner changed, owner: %p (%s), mime types: [%s], "
|
|
|
|
"notifying %s",
|
|
|
|
owner,
|
|
|
|
owner ? g_type_name_from_instance ((GTypeInstance *) owner)
|
|
|
|
: "NULL",
|
|
|
|
mime_types_to_string (mime_types_array, log_buf,
|
|
|
|
G_N_ELEMENTS (log_buf)),
|
|
|
|
session->peer_name);
|
|
|
|
|
|
|
|
options_variant = generate_owner_changed_variant (mime_types_array);
|
|
|
|
|
|
|
|
object_path = g_dbus_interface_skeleton_get_object_path (
|
|
|
|
G_DBUS_INTERFACE_SKELETON (session));
|
|
|
|
g_dbus_connection_emit_signal (session->connection,
|
|
|
|
NULL,
|
|
|
|
object_path,
|
|
|
|
"org.gnome.Mutter.RemoteDesktop.Session",
|
|
|
|
"SelectionOwnerChanged",
|
|
|
|
g_variant_new ("(@a{sv})", options_variant),
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
session->transfer_serial++;
|
|
|
|
}
|
|
|
|
|
2020-10-13 15:38:42 +00:00
|
|
|
static gboolean
|
|
|
|
handle_enable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
GVariant *arg_options)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
2020-11-04 09:27:40 +00:00
|
|
|
MetaDisplay *display = meta_get_display ();
|
|
|
|
MetaSelection *selection = meta_display_get_selection (display);
|
2020-10-13 15:38:42 +00:00
|
|
|
|
|
|
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
|
|
|
"Enable clipboard for %s",
|
|
|
|
g_dbus_method_invocation_get_sender (invocation));
|
|
|
|
|
|
|
|
if (session->is_clipboard_enabled)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Already enabled");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
session->is_clipboard_enabled = TRUE;
|
2020-11-04 09:27:40 +00:00
|
|
|
session->owner_changed_handler_id =
|
|
|
|
g_signal_connect (selection, "owner-changed",
|
|
|
|
G_CALLBACK (on_selection_owner_changed),
|
|
|
|
session);
|
2020-10-13 15:38:42 +00:00
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_enable_clipboard (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_disable_clipboard (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
2020-11-04 09:27:40 +00:00
|
|
|
MetaDisplay *display = meta_get_display ();
|
|
|
|
MetaSelection *selection = meta_display_get_selection (display);
|
2020-10-13 15:38:42 +00:00
|
|
|
|
|
|
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
|
|
|
"Disable clipboard for %s",
|
|
|
|
g_dbus_method_invocation_get_sender (invocation));
|
|
|
|
|
|
|
|
if (!session->is_clipboard_enabled)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Was not enabled");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:27:40 +00:00
|
|
|
g_clear_signal_handler (&session->owner_changed_handler_id, selection);
|
|
|
|
|
2020-10-13 15:38:42 +00:00
|
|
|
meta_dbus_remote_desktop_session_complete_disable_clipboard (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_set_selection (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
GVariant *arg_options)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
|
|
|
"Set selection for %s",
|
|
|
|
g_dbus_method_invocation_get_sender (invocation));
|
|
|
|
|
|
|
|
if (!session->is_clipboard_enabled)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Clipboard not enabled");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_set_selection (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_selection_write (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
GUnixFDList *fd_list,
|
|
|
|
unsigned int serial)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
|
|
|
"Write selection for %s",
|
|
|
|
g_dbus_method_invocation_get_sender (invocation));
|
|
|
|
|
|
|
|
if (!session->is_clipboard_enabled)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Clipboard not enabled");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-11-04 09:27:40 +00:00
|
|
|
if (session->transfer_serial != serial)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Provided transfer serial %u "
|
|
|
|
"doesn't match current current "
|
|
|
|
"transfer serial %u",
|
|
|
|
serial,
|
|
|
|
session->transfer_serial);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-10-13 15:38:42 +00:00
|
|
|
meta_dbus_remote_desktop_session_complete_selection_write (skeleton,
|
|
|
|
invocation,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_selection_write_done (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
unsigned int arg_serial,
|
|
|
|
gboolean arg_success)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
|
|
|
"Write selection done for %s",
|
|
|
|
g_dbus_method_invocation_get_sender (invocation));
|
|
|
|
|
|
|
|
if (!session->is_clipboard_enabled)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Clipboard not enabled");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_selection_write_done (skeleton,
|
|
|
|
invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_selection_read (MetaDBusRemoteDesktopSession *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation,
|
|
|
|
GUnixFDList *fd_list,
|
|
|
|
const char *mime_type)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
|
|
|
|
|
|
|
meta_topic (META_DEBUG_REMOTE_DESKTOP,
|
|
|
|
"Read selection for %s",
|
|
|
|
g_dbus_method_invocation_get_sender (invocation));
|
|
|
|
|
|
|
|
if (!session->is_clipboard_enabled)
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Clipboard not enabled");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_complete_selection_read (skeleton,
|
|
|
|
invocation,
|
|
|
|
NULL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-06-21 06:23:44 +00:00
|
|
|
static void
|
|
|
|
meta_remote_desktop_session_init_iface (MetaDBusRemoteDesktopSessionIface *iface)
|
|
|
|
{
|
|
|
|
iface->handle_start = handle_start;
|
|
|
|
iface->handle_stop = handle_stop;
|
2018-01-29 06:38:13 +00:00
|
|
|
iface->handle_notify_keyboard_keycode = handle_notify_keyboard_keycode;
|
2017-06-21 06:23:44 +00:00
|
|
|
iface->handle_notify_keyboard_keysym = handle_notify_keyboard_keysym;
|
|
|
|
iface->handle_notify_pointer_button = handle_notify_pointer_button;
|
2018-01-29 06:40:28 +00:00
|
|
|
iface->handle_notify_pointer_axis = handle_notify_pointer_axis;
|
2017-06-21 06:23:44 +00:00
|
|
|
iface->handle_notify_pointer_axis_discrete = handle_notify_pointer_axis_discrete;
|
2018-01-29 06:40:57 +00:00
|
|
|
iface->handle_notify_pointer_motion_relative = handle_notify_pointer_motion_relative;
|
2017-06-21 06:23:44 +00:00
|
|
|
iface->handle_notify_pointer_motion_absolute = handle_notify_pointer_motion_absolute;
|
2018-01-29 06:44:03 +00:00
|
|
|
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;
|
2020-10-13 15:38:42 +00:00
|
|
|
iface->handle_enable_clipboard = handle_enable_clipboard;
|
|
|
|
iface->handle_disable_clipboard = handle_disable_clipboard;
|
|
|
|
iface->handle_set_selection = handle_set_selection;
|
|
|
|
iface->handle_selection_write = handle_selection_write;
|
|
|
|
iface->handle_selection_write_done = handle_selection_write_done;
|
|
|
|
iface->handle_selection_read = handle_selection_read;
|
2017-06-21 06:23:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_remote_desktop_session_client_vanished (MetaDbusSession *dbus_session)
|
|
|
|
{
|
|
|
|
meta_remote_desktop_session_close (META_REMOTE_DESKTOP_SESSION (dbus_session));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_dbus_session_init_iface (MetaDbusSessionInterface *iface)
|
|
|
|
{
|
|
|
|
iface->client_vanished = meta_remote_desktop_session_client_vanished;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_remote_desktop_session_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (object);
|
2020-11-04 09:27:40 +00:00
|
|
|
MetaDisplay *display = meta_get_display ();
|
|
|
|
MetaSelection *selection = meta_display_get_selection (display);
|
2017-06-21 06:23:44 +00:00
|
|
|
|
|
|
|
g_assert (!meta_remote_desktop_session_is_running (session));
|
|
|
|
|
2020-11-04 09:27:40 +00:00
|
|
|
g_clear_signal_handler (&session->owner_changed_handler_id, selection);
|
|
|
|
|
2018-07-20 14:37:37 +00:00
|
|
|
g_clear_object (&session->handle);
|
2017-08-25 07:19:53 +00:00
|
|
|
g_free (session->peer_name);
|
2017-06-21 06:23:44 +00:00
|
|
|
g_free (session->session_id);
|
|
|
|
g_free (session->object_path);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_remote_desktop_session_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_remote_desktop_session_init (MetaRemoteDesktopSession *session)
|
|
|
|
{
|
|
|
|
MetaDBusRemoteDesktopSession *skeleton =
|
|
|
|
META_DBUS_REMOTE_DESKTOP_SESSION (session);
|
|
|
|
GRand *rand;
|
|
|
|
static unsigned int global_session_number = 0;
|
|
|
|
|
|
|
|
rand = g_rand_new ();
|
|
|
|
session->session_id = meta_generate_random_id (rand, 32);
|
|
|
|
g_rand_free (rand);
|
|
|
|
|
|
|
|
meta_dbus_remote_desktop_session_set_session_id (skeleton, session->session_id);
|
|
|
|
|
|
|
|
session->object_path =
|
|
|
|
g_strdup_printf (META_REMOTE_DESKTOP_SESSION_DBUS_PATH "/u%u",
|
|
|
|
++global_session_number);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_remote_desktop_session_class_init (MetaRemoteDesktopSessionClass *klass)
|
|
|
|
{
|
|
|
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->finalize = meta_remote_desktop_session_finalize;
|
|
|
|
}
|
2018-07-20 14:37:37 +00:00
|
|
|
|
|
|
|
static MetaRemoteDesktopSessionHandle *
|
|
|
|
meta_remote_desktop_session_handle_new (MetaRemoteDesktopSession *session)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSessionHandle *handle;
|
|
|
|
|
|
|
|
handle = g_object_new (META_TYPE_REMOTE_DESKTOP_SESSION_HANDLE, NULL);
|
|
|
|
handle->session = session;
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_remote_desktop_session_handle_stop (MetaRemoteAccessHandle *handle)
|
|
|
|
{
|
|
|
|
MetaRemoteDesktopSession *session;
|
|
|
|
|
|
|
|
session = META_REMOTE_DESKTOP_SESSION_HANDLE (handle)->session;
|
|
|
|
if (!session)
|
|
|
|
return;
|
|
|
|
|
|
|
|
meta_remote_desktop_session_close (session);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_remote_desktop_session_handle_init (MetaRemoteDesktopSessionHandle *handle)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_remote_desktop_session_handle_class_init (MetaRemoteDesktopSessionHandleClass *klass)
|
|
|
|
{
|
|
|
|
MetaRemoteAccessHandleClass *remote_access_handle_class =
|
|
|
|
META_REMOTE_ACCESS_HANDLE_CLASS (klass);
|
|
|
|
|
|
|
|
remote_access_handle_class->stop = meta_remote_desktop_session_handle_stop;
|
|
|
|
}
|