backends/eis: Add EIS client support
This adds support for EIS clients in the form of MetaEis and MetaEisClient. The purpose is to allow clients to connect and send emulated input events using EIS. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2628>
This commit is contained in:
parent
2059273f57
commit
a20aa28af0
@ -147,6 +147,8 @@ MetaDbusSessionWatcher * meta_backend_get_dbus_session_watcher (MetaBackend *bac
|
||||
MetaRemoteDesktop * meta_backend_get_remote_desktop (MetaBackend *backend);
|
||||
|
||||
MetaScreenCast * meta_backend_get_screen_cast (MetaBackend *backend);
|
||||
|
||||
MetaEis * meta_backend_get_eis (MetaBackend *backend);
|
||||
#endif
|
||||
|
||||
MetaInputCapture * meta_backend_get_input_capture (MetaBackend *backend);
|
||||
|
@ -95,4 +95,7 @@ typedef struct _MetaGammaLut
|
||||
typedef struct _MetaInputCapture MetaInputCapture;
|
||||
typedef struct _MetaInputCaptureSession MetaInputCaptureSession;
|
||||
|
||||
typedef struct _MetaEis MetaEis;
|
||||
typedef struct _MetaEisClient MetaEisClient;
|
||||
|
||||
#endif /* META_BACKEND_TYPE_H */
|
||||
|
@ -79,6 +79,9 @@
|
||||
#include "meta/util.h"
|
||||
|
||||
#ifdef HAVE_REMOTE_DESKTOP
|
||||
#include "backends/meta-dbus-session-watcher.h"
|
||||
#include "backends/meta-eis.h"
|
||||
#include "backends/meta-remote-access-controller-private.h"
|
||||
#include "backends/meta-remote-desktop.h"
|
||||
#include "backends/meta-screen-cast.h"
|
||||
#endif
|
||||
@ -139,6 +142,7 @@ struct _MetaBackendPrivate
|
||||
#ifdef HAVE_REMOTE_DESKTOP
|
||||
MetaScreenCast *screen_cast;
|
||||
MetaRemoteDesktop *remote_desktop;
|
||||
MetaEis *eis;
|
||||
#endif
|
||||
MetaInputCapture *input_capture;
|
||||
|
||||
@ -208,6 +212,7 @@ meta_backend_dispose (GObject *object)
|
||||
#ifdef HAVE_REMOTE_DESKTOP
|
||||
g_clear_object (&priv->remote_desktop);
|
||||
g_clear_object (&priv->screen_cast);
|
||||
g_clear_object (&priv->eis);
|
||||
#endif
|
||||
g_clear_object (&priv->input_capture);
|
||||
g_clear_object (&priv->dbus_session_watcher);
|
||||
@ -581,6 +586,7 @@ meta_backend_real_post_init (MetaBackend *backend)
|
||||
meta_remote_access_controller_add (
|
||||
priv->remote_access_controller,
|
||||
META_DBUS_SESSION_MANAGER (priv->remote_desktop));
|
||||
priv->eis = meta_eis_new (backend);
|
||||
#endif /* HAVE_REMOTE_DESKTOP */
|
||||
|
||||
priv->input_capture = meta_input_capture_new (backend);
|
||||
@ -1440,6 +1446,16 @@ meta_backend_get_screen_cast (MetaBackend *backend)
|
||||
|
||||
return priv->screen_cast;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_eis: (skip)
|
||||
*/
|
||||
MetaEis *
|
||||
meta_backend_get_eis (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
return priv->eis;
|
||||
}
|
||||
#endif /* HAVE_REMOTE_DESKTOP */
|
||||
|
||||
MetaInputCapture *
|
||||
|
752
src/backends/meta-eis-client.c
Normal file
752
src/backends/meta-eis-client.c
Normal file
@ -0,0 +1,752 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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-backend-private.h"
|
||||
#include "backends/meta-eis-client.h"
|
||||
#include "backends/meta-monitor-manager-private.h"
|
||||
#include "backends/meta-viewport-info.h"
|
||||
|
||||
#include "clutter/clutter-mutter.h"
|
||||
#include "core/meta-anonymous-file.h"
|
||||
|
||||
#define MAX_BUTTON 128
|
||||
#define MAX_KEY 0x2ff /* KEY_MAX as of 5.13 */
|
||||
|
||||
typedef struct _MetaEisDevice MetaEisDevice;
|
||||
|
||||
struct _MetaEisDevice
|
||||
{
|
||||
struct eis_device *eis_device;
|
||||
ClutterVirtualInputDevice *device;
|
||||
|
||||
guchar button_state[(MAX_BUTTON + 7) / 8];
|
||||
guchar key_state[(MAX_KEY + 7) / 8];
|
||||
};
|
||||
|
||||
struct _MetaEisClient
|
||||
{
|
||||
GObject parent_instance;
|
||||
MetaEis *meta_eis;
|
||||
|
||||
MetaViewportInfo *viewports;
|
||||
struct eis_client *eis_client;
|
||||
struct eis_seat *eis_seat;
|
||||
|
||||
GHashTable *eis_devices; /* eis_device => MetaEisDevice*/
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaEisClient, meta_eis_client, G_TYPE_OBJECT)
|
||||
|
||||
typedef void (* MetaEisDeviceConfigFunc) (MetaEisClient *meta_eis_client,
|
||||
struct eis_device *device);
|
||||
|
||||
static bool
|
||||
bit_is_set (const guchar *array,
|
||||
int bit)
|
||||
{
|
||||
return !!(array[bit / 8] & (1 << (bit % 8)));
|
||||
}
|
||||
|
||||
static void
|
||||
bit_set (guchar *array,
|
||||
int bit)
|
||||
{
|
||||
array[bit / 8] |= (1 << (bit % 8));
|
||||
}
|
||||
|
||||
static void
|
||||
bit_clear (guchar *array,
|
||||
int bit)
|
||||
{
|
||||
array[bit / 8] &= ~(1 << (bit % 8));
|
||||
}
|
||||
|
||||
static void
|
||||
notify_key (MetaEisDevice *meta_eis_device,
|
||||
uint32_t key,
|
||||
gboolean is_press)
|
||||
{
|
||||
ClutterKeyState state;
|
||||
|
||||
state = is_press ? CLUTTER_KEY_STATE_PRESSED : CLUTTER_KEY_STATE_RELEASED;
|
||||
clutter_virtual_input_device_notify_key (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
key,
|
||||
state);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_button (MetaEisDevice *meta_eis_device,
|
||||
uint32_t button,
|
||||
gboolean is_press)
|
||||
{
|
||||
ClutterButtonState state;
|
||||
|
||||
state = is_press ? CLUTTER_BUTTON_STATE_PRESSED : CLUTTER_BUTTON_STATE_RELEASED;
|
||||
clutter_virtual_input_device_notify_button (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
button,
|
||||
state);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_device (MetaEisClient *meta_eis_client,
|
||||
struct eis_device *eis_device,
|
||||
gboolean remove_from_hashtable)
|
||||
{
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
struct eis_keymap *eis_keymap = eis_device_keyboard_get_keymap (eis_device);
|
||||
|
||||
if (eis_keymap)
|
||||
{
|
||||
MetaAnonymousFile *f = eis_keymap_get_user_data (eis_keymap);
|
||||
if (f)
|
||||
meta_anonymous_file_free (f);
|
||||
}
|
||||
|
||||
eis_device_pause (eis_device);
|
||||
eis_device_remove (eis_device);
|
||||
g_clear_pointer (&meta_eis_device->eis_device, eis_device_unref);
|
||||
g_clear_object (&meta_eis_device->device);
|
||||
|
||||
if (remove_from_hashtable)
|
||||
g_hash_table_remove (meta_eis_client->eis_devices, eis_device);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drop_device (gpointer htkey,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
MetaEisClient *meta_eis_client = data;
|
||||
struct eis_device *eis_device = htkey;
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
uint32_t key, button;
|
||||
|
||||
for (key = 0; key < MAX_KEY; key++)
|
||||
{
|
||||
if (bit_is_set (meta_eis_device->key_state, key))
|
||||
notify_key (meta_eis_device, key, FALSE);
|
||||
}
|
||||
|
||||
for (button = 0; button < MAX_BUTTON; button++)
|
||||
{
|
||||
if (bit_is_set (meta_eis_device->button_state, key))
|
||||
notify_button (meta_eis_device, button, FALSE);
|
||||
}
|
||||
|
||||
remove_device (meta_eis_client, eis_device, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_device_free (MetaEisDevice *device)
|
||||
{
|
||||
eis_device_unref (device->eis_device);
|
||||
free (device);
|
||||
}
|
||||
|
||||
static void
|
||||
configure_rel (MetaEisClient *meta_eis_client,
|
||||
struct eis_device *eis_device)
|
||||
{
|
||||
eis_device_configure_capability (eis_device, EIS_DEVICE_CAP_POINTER);
|
||||
eis_device_configure_capability (eis_device, EIS_DEVICE_CAP_BUTTON);
|
||||
eis_device_configure_capability (eis_device, EIS_DEVICE_CAP_SCROLL);
|
||||
}
|
||||
|
||||
static void
|
||||
configure_keyboard (MetaEisClient *meta_eis_client,
|
||||
struct eis_device *eis_device)
|
||||
{
|
||||
size_t len;
|
||||
MetaAnonymousFile *f;
|
||||
int fd = -1;
|
||||
char *data;
|
||||
struct xkb_keymap *xkb_keymap;
|
||||
|
||||
eis_device_configure_capability (eis_device, EIS_DEVICE_CAP_KEYBOARD);
|
||||
|
||||
xkb_keymap =
|
||||
meta_backend_get_keymap (meta_eis_get_backend (meta_eis_client->meta_eis));
|
||||
if (!xkb_keymap)
|
||||
return;
|
||||
|
||||
data = xkb_keymap_get_as_string (xkb_keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
len = strlen (data);
|
||||
f = meta_anonymous_file_new (len, (uint8_t*)data);
|
||||
if (f)
|
||||
fd = meta_anonymous_file_open_fd (f, META_ANONYMOUS_FILE_MAPMODE_SHARED);
|
||||
|
||||
g_free (data);
|
||||
if (fd != -1)
|
||||
{
|
||||
struct eis_keymap *eis_keymap;
|
||||
|
||||
eis_keymap = eis_device_new_keymap (eis_device, EIS_KEYMAP_TYPE_XKB,
|
||||
fd, len);
|
||||
/* libeis dup()s the fd */
|
||||
meta_anonymous_file_close_fd (fd);
|
||||
/* The memfile must be kept alive while the device is alive */
|
||||
eis_keymap_set_user_data (eis_keymap, f);
|
||||
eis_keymap_add (eis_keymap);
|
||||
eis_keymap_unref (eis_keymap);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
configure_abs (MetaEisClient *meta_eis_client,
|
||||
struct eis_device *eis_device)
|
||||
{
|
||||
int idx = 0;
|
||||
cairo_rectangle_int_t rect;
|
||||
float scale;
|
||||
|
||||
if (!meta_eis_client->viewports)
|
||||
return; /* FIXME: should be an error */
|
||||
|
||||
eis_device_configure_capability (eis_device, EIS_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
eis_device_configure_capability (eis_device, EIS_DEVICE_CAP_BUTTON);
|
||||
eis_device_configure_capability (eis_device, EIS_DEVICE_CAP_SCROLL);
|
||||
|
||||
while (meta_viewport_info_get_view_info (meta_eis_client->viewports, idx++, &rect, &scale))
|
||||
{
|
||||
struct eis_region *r = eis_device_new_region (eis_device);
|
||||
eis_region_set_offset (r, rect.x, rect.y);
|
||||
eis_region_set_size (r, rect.width, rect.height);
|
||||
eis_region_set_physical_scale (r, scale);
|
||||
eis_region_add (r);
|
||||
eis_region_unref (r);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_device (MetaEisClient *meta_eis_client,
|
||||
struct eis_seat *eis_seat,
|
||||
ClutterInputDeviceType type,
|
||||
const char *name_suffix,
|
||||
MetaEisDeviceConfigFunc extra_config_func)
|
||||
{
|
||||
MetaBackend *backend = meta_eis_get_backend (meta_eis_client->meta_eis);
|
||||
MetaEisDevice *meta_eis_device;
|
||||
ClutterSeat *seat = meta_backend_get_default_seat (backend);
|
||||
ClutterVirtualInputDevice *device;
|
||||
struct eis_device *eis_device;
|
||||
gchar *name;
|
||||
|
||||
device = clutter_seat_create_virtual_device (seat, type);
|
||||
eis_device = eis_seat_new_device (eis_seat);
|
||||
name = g_strdup_printf ("%s %s", eis_client_get_name (meta_eis_client->eis_client),
|
||||
name_suffix);
|
||||
eis_device_configure_name (eis_device, name);
|
||||
if (extra_config_func)
|
||||
extra_config_func (meta_eis_client, eis_device);
|
||||
|
||||
meta_eis_device = g_new0 (MetaEisDevice, 1);
|
||||
meta_eis_device->eis_device = eis_device_ref (eis_device);
|
||||
meta_eis_device->device = device;
|
||||
eis_device_set_user_data (eis_device, meta_eis_device);
|
||||
|
||||
g_hash_table_insert (meta_eis_client->eis_devices,
|
||||
eis_device, /* owns the initial ref now */
|
||||
meta_eis_device);
|
||||
|
||||
eis_device_add (eis_device);
|
||||
eis_device_resume (eis_device);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_motion_relative (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
double dx, dy;
|
||||
|
||||
dx = eis_event_pointer_get_dx (event);
|
||||
dy = eis_event_pointer_get_dy (event);
|
||||
|
||||
clutter_virtual_input_device_notify_relative_motion (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
dx, dy);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_motion_absolute (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
double x, y;
|
||||
|
||||
x = eis_event_pointer_get_absolute_x (event);
|
||||
y = eis_event_pointer_get_absolute_y (event);
|
||||
|
||||
clutter_virtual_input_device_notify_absolute_motion (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_scroll (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
double dx, dy;
|
||||
|
||||
dx = eis_event_scroll_get_dx (event);
|
||||
dy = eis_event_scroll_get_dy (event);
|
||||
|
||||
clutter_virtual_input_device_notify_scroll_continuous (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
dx, dy,
|
||||
CLUTTER_SCROLL_SOURCE_UNKNOWN,
|
||||
CLUTTER_SCROLL_FINISHED_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_scroll_stop (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE;
|
||||
|
||||
if (eis_event_scroll_get_stop_x (event))
|
||||
finish_flags |= CLUTTER_SCROLL_FINISHED_HORIZONTAL;
|
||||
if (eis_event_scroll_get_stop_y (event))
|
||||
finish_flags |= CLUTTER_SCROLL_FINISHED_VERTICAL;
|
||||
|
||||
if (finish_flags != CLUTTER_SCROLL_FINISHED_NONE)
|
||||
clutter_virtual_input_device_notify_scroll_continuous (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
0.0, 0.0,
|
||||
CLUTTER_SCROLL_SOURCE_UNKNOWN,
|
||||
finish_flags);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_scroll_cancel (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
double dx = 0.0, dy = 0.0;
|
||||
|
||||
/* There's no real match for the EIS scroll cancel event, so let's just send a
|
||||
* really small scroll event that hopefully resets the scroll speed to
|
||||
* something where kinetic scrolling is not viable.
|
||||
*/
|
||||
if (eis_event_scroll_get_stop_x (event))
|
||||
dx = 0.01;
|
||||
if (eis_event_scroll_get_stop_y (event))
|
||||
dy = 0.01;
|
||||
|
||||
if (dx != 0.0 || dy != 0.0)
|
||||
clutter_virtual_input_device_notify_scroll_continuous (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
dx, dy,
|
||||
CLUTTER_SCROLL_SOURCE_UNKNOWN,
|
||||
CLUTTER_SCROLL_FINISHED_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_scroll_discrete (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
int dx, dy;
|
||||
|
||||
/* FIXME: need to handle the remainders here for high-resolution scrolling */
|
||||
dx = eis_event_scroll_get_discrete_dx (event) / 120;
|
||||
dy = eis_event_scroll_get_discrete_dy (event) / 120;
|
||||
|
||||
/* Intentionally interleaved */
|
||||
while (dx || dy)
|
||||
{
|
||||
if (dx > 0)
|
||||
{
|
||||
clutter_virtual_input_device_notify_discrete_scroll (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
CLUTTER_SCROLL_RIGHT,
|
||||
CLUTTER_SCROLL_SOURCE_UNKNOWN);
|
||||
dx--;
|
||||
}
|
||||
else if (dx < 0)
|
||||
{
|
||||
clutter_virtual_input_device_notify_discrete_scroll (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
CLUTTER_SCROLL_LEFT,
|
||||
CLUTTER_SCROLL_SOURCE_UNKNOWN);
|
||||
dx++;
|
||||
}
|
||||
|
||||
if (dy > 0)
|
||||
{
|
||||
clutter_virtual_input_device_notify_discrete_scroll (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
CLUTTER_SCROLL_DOWN,
|
||||
CLUTTER_SCROLL_SOURCE_UNKNOWN);
|
||||
dy--;
|
||||
}
|
||||
else if (dy < 0)
|
||||
{
|
||||
clutter_virtual_input_device_notify_discrete_scroll (meta_eis_device->device,
|
||||
g_get_monotonic_time (),
|
||||
CLUTTER_SCROLL_UP,
|
||||
CLUTTER_SCROLL_SOURCE_UNKNOWN);
|
||||
dy++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_button (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
uint32_t button;
|
||||
gboolean is_press = eis_event_button_get_is_press (event);
|
||||
|
||||
button = eis_event_button_get_button (event);
|
||||
switch (button)
|
||||
{
|
||||
case 0x110: /* BTN_LEFT */
|
||||
button = CLUTTER_BUTTON_PRIMARY;
|
||||
break;
|
||||
case 0x111: /* BTN_RIGHT */
|
||||
button = CLUTTER_BUTTON_SECONDARY;
|
||||
break;
|
||||
case 0x112: /* BTN_MIDDLE */
|
||||
button = CLUTTER_BUTTON_MIDDLE;
|
||||
break;
|
||||
default:
|
||||
if (button > 0x110)
|
||||
button -= 0x110;
|
||||
break;
|
||||
}
|
||||
|
||||
if (button > MAX_BUTTON)
|
||||
return;
|
||||
|
||||
if (is_press && !bit_is_set (meta_eis_device->button_state, button))
|
||||
bit_set (meta_eis_device->button_state, button);
|
||||
else if (!is_press && bit_is_set (meta_eis_device->button_state, button))
|
||||
bit_clear (meta_eis_device->button_state, button);
|
||||
else
|
||||
return; /* Duplicate press/release, should've been filtered by libeis */
|
||||
|
||||
notify_button (meta_eis_device,
|
||||
button,
|
||||
eis_event_button_get_is_press (event));
|
||||
}
|
||||
|
||||
static void
|
||||
handle_key (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *meta_eis_device = eis_device_get_user_data (eis_device);
|
||||
uint32_t key;
|
||||
gboolean is_press = eis_event_keyboard_get_key_is_press (event);
|
||||
|
||||
key = eis_event_keyboard_get_key (event);
|
||||
|
||||
if (key > MAX_KEY)
|
||||
return;
|
||||
|
||||
if (is_press && !bit_is_set (meta_eis_device->key_state, key))
|
||||
bit_set (meta_eis_device->key_state, key);
|
||||
else if (!is_press && bit_is_set (meta_eis_device->key_state, key))
|
||||
bit_clear (meta_eis_device->key_state, key);
|
||||
else
|
||||
return; /* Duplicate press/release, should've been filtered by libeis */
|
||||
|
||||
notify_key (meta_eis_device, key, is_press);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drop_kbd_devices (gpointer htkey,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
struct eis_device *eis_device = htkey;
|
||||
|
||||
if (!eis_device_has_capability (eis_device, EIS_DEVICE_CAP_KEYBOARD))
|
||||
return FALSE;
|
||||
|
||||
return drop_device (htkey, value, data);
|
||||
}
|
||||
|
||||
static void
|
||||
on_keymap_changed (MetaBackend *backend,
|
||||
gpointer data)
|
||||
{
|
||||
MetaEisClient *meta_eis_client = data;
|
||||
|
||||
/* Changing the keymap means we have to remove our device and recreate it
|
||||
* with the new keymap.
|
||||
*/
|
||||
g_hash_table_foreach_remove (meta_eis_client->eis_devices,
|
||||
drop_kbd_devices,
|
||||
meta_eis_client);
|
||||
|
||||
add_device (meta_eis_client,
|
||||
meta_eis_client->eis_seat,
|
||||
CLUTTER_KEYBOARD_DEVICE,
|
||||
"virtual keyboard",
|
||||
configure_keyboard);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_eis_client_process_event (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
enum eis_event_type type = eis_event_get_type (event);
|
||||
struct eis_seat *eis_seat;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case EIS_EVENT_SEAT_BIND:
|
||||
eis_seat = eis_event_get_seat (event);
|
||||
if (eis_event_seat_has_capability (event, EIS_DEVICE_CAP_POINTER))
|
||||
add_device (meta_eis_client,
|
||||
eis_seat,
|
||||
CLUTTER_POINTER_DEVICE,
|
||||
"virtual pointer",
|
||||
configure_rel);
|
||||
if (eis_event_seat_has_capability (event, EIS_DEVICE_CAP_KEYBOARD))
|
||||
{
|
||||
add_device (meta_eis_client,
|
||||
eis_seat,
|
||||
CLUTTER_KEYBOARD_DEVICE,
|
||||
"virtual keyboard",
|
||||
configure_keyboard);
|
||||
|
||||
g_signal_connect (meta_eis_get_backend (meta_eis_client->meta_eis),
|
||||
"keymap-changed",
|
||||
G_CALLBACK (on_keymap_changed),
|
||||
meta_eis_client);
|
||||
}
|
||||
if (eis_event_seat_has_capability (event, EIS_DEVICE_CAP_POINTER_ABSOLUTE))
|
||||
add_device (meta_eis_client,
|
||||
eis_seat,
|
||||
CLUTTER_POINTER_DEVICE,
|
||||
"virtual absolute pointer",
|
||||
configure_abs);
|
||||
break;
|
||||
|
||||
/* We only have one seat, so if the client unbinds from that
|
||||
* just disconnect it, no point keeping it alive */
|
||||
case EIS_EVENT_DEVICE_CLOSED:
|
||||
remove_device (meta_eis_client, eis_event_get_device (event), TRUE);
|
||||
break;
|
||||
case EIS_EVENT_POINTER_MOTION:
|
||||
handle_motion_relative (meta_eis_client, event);
|
||||
break;
|
||||
case EIS_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
handle_motion_absolute (meta_eis_client, event);
|
||||
break;
|
||||
case EIS_EVENT_BUTTON_BUTTON:
|
||||
handle_button (meta_eis_client, event);
|
||||
break;
|
||||
case EIS_EVENT_SCROLL_DELTA:
|
||||
handle_scroll (meta_eis_client, event);
|
||||
break;
|
||||
case EIS_EVENT_SCROLL_STOP:
|
||||
handle_scroll_stop (meta_eis_client, event);
|
||||
break;
|
||||
case EIS_EVENT_SCROLL_CANCEL:
|
||||
handle_scroll_cancel (meta_eis_client, event);
|
||||
break;
|
||||
case EIS_EVENT_SCROLL_DISCRETE:
|
||||
handle_scroll_discrete (meta_eis_client, event);
|
||||
break;
|
||||
case EIS_EVENT_KEYBOARD_KEY:
|
||||
handle_key (meta_eis_client, event);
|
||||
break;
|
||||
case EIS_EVENT_FRAME:
|
||||
/* FIXME: we should be accumulating the above events */
|
||||
break;
|
||||
case EIS_EVENT_DEVICE_START_EMULATING:
|
||||
break;
|
||||
case EIS_EVENT_DEVICE_STOP_EMULATING:
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unhandled EIS event type %d", type);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drop_abs_devices (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
struct eis_device *eis_device = key;
|
||||
|
||||
if (!eis_device_has_capability (eis_device, EIS_DEVICE_CAP_POINTER_ABSOLUTE))
|
||||
return FALSE;
|
||||
|
||||
return drop_device (key, value, data);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_client_set_viewports (MetaEisClient *meta_eis_client,
|
||||
MetaViewportInfo *viewports)
|
||||
{
|
||||
/* Updating viewports means we have to recreate our absolute pointer
|
||||
* devices. */
|
||||
|
||||
g_hash_table_foreach_remove (meta_eis_client->eis_devices,
|
||||
drop_abs_devices,
|
||||
meta_eis_client);
|
||||
|
||||
g_clear_object (&meta_eis_client->viewports);
|
||||
meta_eis_client->viewports = g_object_ref (viewports);
|
||||
|
||||
add_device (meta_eis_client,
|
||||
meta_eis_client->eis_seat,
|
||||
CLUTTER_POINTER_DEVICE,
|
||||
"virtual absolute pointer",
|
||||
configure_abs);
|
||||
}
|
||||
|
||||
static void
|
||||
on_monitors_changed (MetaMonitorManager *monitor_manager,
|
||||
MetaEisClient *meta_eis_client)
|
||||
{
|
||||
MetaViewportInfo *viewports;
|
||||
|
||||
viewports = meta_monitor_manager_get_viewports (monitor_manager);
|
||||
meta_eis_client_set_viewports (meta_eis_client, viewports);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_client_disconnect (MetaEisClient *meta_eis_client)
|
||||
{
|
||||
MetaBackend *backend = meta_eis_get_backend (meta_eis_client->meta_eis);
|
||||
MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (monitor_manager,
|
||||
on_monitors_changed,
|
||||
meta_eis_client);
|
||||
g_hash_table_foreach_remove (meta_eis_client->eis_devices, drop_device, meta_eis_client);
|
||||
g_clear_pointer (&meta_eis_client->eis_seat, eis_seat_unref);
|
||||
if (meta_eis_client->eis_client)
|
||||
eis_client_disconnect (meta_eis_client->eis_client);
|
||||
g_clear_pointer (&meta_eis_client->eis_client, eis_client_unref);
|
||||
g_clear_object (&meta_eis_client->viewports);
|
||||
}
|
||||
|
||||
MetaEisClient *
|
||||
meta_eis_client_new (MetaEis *meta_eis,
|
||||
struct eis_client *eis_client)
|
||||
{
|
||||
MetaEisClient *meta_eis_client;
|
||||
MetaBackend *backend;
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaViewportInfo *viewports;
|
||||
struct eis_seat *eis_seat;
|
||||
|
||||
meta_eis_client = g_object_new (META_TYPE_EIS_CLIENT, NULL);
|
||||
meta_eis_client->meta_eis = meta_eis;
|
||||
meta_eis_client->eis_client = eis_client_ref (eis_client);
|
||||
eis_client_set_user_data (meta_eis_client->eis_client, meta_eis_client);
|
||||
|
||||
/* We're relying on some third party to filter clients for us */
|
||||
eis_client_connect (eis_client);
|
||||
|
||||
/* We only support one seat for now. libeis keeps the ref for the
|
||||
* seat and we don't need to care about it.
|
||||
* The capabilities we define are the maximum capabilities, the client
|
||||
* may only bind to a subset of those, reducing the capabilities
|
||||
* of the seat in the process.
|
||||
*/
|
||||
eis_seat = eis_client_new_seat (eis_client, "mutter default seat");
|
||||
eis_seat_configure_capability (eis_seat, EIS_DEVICE_CAP_KEYBOARD);
|
||||
eis_seat_configure_capability (eis_seat, EIS_DEVICE_CAP_POINTER);
|
||||
eis_seat_configure_capability (eis_seat, EIS_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
eis_seat_configure_capability (eis_seat, EIS_DEVICE_CAP_BUTTON);
|
||||
eis_seat_configure_capability (eis_seat, EIS_DEVICE_CAP_SCROLL);
|
||||
|
||||
eis_seat_add (eis_seat);
|
||||
eis_seat_unref (eis_seat);
|
||||
meta_eis_client->eis_seat = eis_seat_ref (eis_seat);
|
||||
|
||||
meta_eis_client->eis_devices = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
(GDestroyNotify) eis_device_unref,
|
||||
(GDestroyNotify) meta_eis_device_free);
|
||||
|
||||
backend = meta_eis_get_backend (meta_eis);
|
||||
monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||
viewports = meta_monitor_manager_get_viewports (monitor_manager);
|
||||
meta_eis_client_set_viewports (meta_eis_client, viewports);
|
||||
g_signal_connect (monitor_manager, "monitors-changed",
|
||||
G_CALLBACK (on_monitors_changed),
|
||||
meta_eis_client);
|
||||
|
||||
return meta_eis_client;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_client_init (MetaEisClient *meta_eis_client)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_client_constructed (GObject *object)
|
||||
{
|
||||
if (G_OBJECT_CLASS (meta_eis_client_parent_class)->constructed)
|
||||
G_OBJECT_CLASS (meta_eis_client_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_client_finalize (GObject *object)
|
||||
{
|
||||
MetaEisClient *meta_eis_client = META_EIS_CLIENT (object);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (meta_eis_get_backend (meta_eis_client->meta_eis),
|
||||
on_keymap_changed,
|
||||
meta_eis_client);
|
||||
meta_eis_client_disconnect (meta_eis_client);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_client_class_init (MetaEisClientClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_eis_client_constructed;
|
||||
object_class->finalize = meta_eis_client_finalize;
|
||||
}
|
43
src/backends/meta-eis-client.h
Normal file
43
src/backends/meta-eis-client.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef META_EIS_CLIENT_H
|
||||
#define META_EIS_CLIENT_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <libeis.h>
|
||||
|
||||
#include "backends/meta-backend-types.h"
|
||||
#include "backends/meta-eis.h"
|
||||
|
||||
#define META_TYPE_EIS_CLIENT (meta_eis_client_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaEisClient, meta_eis_client,
|
||||
META, EIS_CLIENT, GObject)
|
||||
|
||||
MetaEisClient *meta_eis_client_new (MetaEis *meta_eis,
|
||||
struct eis_client *eis_client);
|
||||
|
||||
gboolean meta_eis_client_process_event (MetaEisClient *meta_eis_client,
|
||||
struct eis_event *eis_event);
|
||||
|
||||
#endif /* META_EIS_H */
|
298
src/backends/meta-eis.c
Normal file
298
src/backends/meta-eis.c
Normal file
@ -0,0 +1,298 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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 <libeis.h>
|
||||
|
||||
#include "backends/meta-eis.h"
|
||||
#include "backends/meta-eis-client.h"
|
||||
#include "clutter/clutter-mutter.h"
|
||||
|
||||
typedef struct _MetaEventSource MetaEventSource;
|
||||
|
||||
struct _MetaEventSource
|
||||
{
|
||||
GSource source;
|
||||
|
||||
MetaEis *meta_eis;
|
||||
GPollFD event_poll_fd;
|
||||
};
|
||||
|
||||
struct _MetaEis
|
||||
{
|
||||
GObject parent_instance;
|
||||
MetaBackend *backend;
|
||||
|
||||
struct eis *eis;
|
||||
MetaEventSource *event_source;
|
||||
|
||||
GHashTable *eis_clients; /* eis_client => MetaEisClient */
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaEis, meta_eis, G_TYPE_OBJECT)
|
||||
|
||||
MetaBackend *
|
||||
meta_eis_get_backend (MetaEis *meta_eis)
|
||||
{
|
||||
return meta_eis->backend;
|
||||
}
|
||||
|
||||
void
|
||||
meta_eis_remove_all_clients (MetaEis *meta_eis)
|
||||
{
|
||||
g_hash_table_remove_all (meta_eis->eis_clients);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_remove_client (MetaEis *meta_eis,
|
||||
struct eis_client *eis_client)
|
||||
{
|
||||
g_hash_table_remove (meta_eis->eis_clients, eis_client);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_add_client (MetaEis *meta_eis,
|
||||
struct eis_client *eis_client)
|
||||
{
|
||||
MetaEisClient *meta_eis_client;
|
||||
|
||||
meta_eis_client = meta_eis_client_new (meta_eis, eis_client);
|
||||
|
||||
g_hash_table_insert (meta_eis->eis_clients,
|
||||
eis_client_ref (eis_client),
|
||||
meta_eis_client);
|
||||
}
|
||||
|
||||
static void
|
||||
process_event (MetaEis *meta_eis,
|
||||
struct eis_event *event)
|
||||
{
|
||||
enum eis_event_type type = eis_event_get_type (event);
|
||||
struct eis_client *eis_client = eis_event_get_client (event);
|
||||
MetaEisClient *meta_eis_client;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case EIS_EVENT_CLIENT_CONNECT:
|
||||
meta_eis_add_client (meta_eis, eis_client);
|
||||
break;
|
||||
case EIS_EVENT_CLIENT_DISCONNECT:
|
||||
meta_eis_remove_client (meta_eis, eis_client);
|
||||
break;
|
||||
default:
|
||||
meta_eis_client = g_hash_table_lookup (meta_eis->eis_clients, eis_client);
|
||||
if (!meta_eis_client)
|
||||
{
|
||||
g_warning ("Event for unknown EIS client: %s",
|
||||
eis_client_get_name (eis_client));
|
||||
return;
|
||||
}
|
||||
meta_eis_client_process_event (meta_eis_client, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_events (MetaEis *meta_eis)
|
||||
{
|
||||
struct eis_event *e;
|
||||
|
||||
while ((e = eis_get_event (meta_eis->eis)))
|
||||
{
|
||||
process_event (meta_eis, e);
|
||||
eis_event_unref (e);
|
||||
}
|
||||
}
|
||||
|
||||
static MetaEventSource *
|
||||
meta_event_source_new (MetaEis *meta_eis,
|
||||
int fd,
|
||||
GSourceFuncs *event_funcs)
|
||||
{
|
||||
GSource *source;
|
||||
MetaEventSource *event_source;
|
||||
|
||||
source = g_source_new (event_funcs, sizeof (MetaEventSource));
|
||||
event_source = (MetaEventSource *) source;
|
||||
|
||||
/* setup the source */
|
||||
event_source->meta_eis = meta_eis;
|
||||
|
||||
event_source->event_poll_fd.fd = fd;
|
||||
event_source->event_poll_fd.events = G_IO_IN;
|
||||
|
||||
/* and finally configure and attach the GSource */
|
||||
g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
|
||||
g_source_add_poll (source, &event_source->event_poll_fd);
|
||||
g_source_set_can_recurse (source, TRUE);
|
||||
g_source_attach (source, NULL);
|
||||
|
||||
return event_source;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_event_source_free (MetaEventSource *source)
|
||||
{
|
||||
GSource *g_source = (GSource *) source;
|
||||
|
||||
/* ignore the return value of close, it's not like we can do something
|
||||
* about it */
|
||||
close (source->event_poll_fd.fd);
|
||||
|
||||
g_source_destroy (g_source);
|
||||
g_source_unref (g_source);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_event_prepare (GSource *g_source,
|
||||
int *timeout_ms)
|
||||
{
|
||||
MetaEventSource *source = (MetaEventSource *) g_source;
|
||||
MetaEis *meta_eis = source->meta_eis;
|
||||
struct eis_event *e;
|
||||
|
||||
*timeout_ms = -1;
|
||||
|
||||
e = eis_peek_event (meta_eis->eis);
|
||||
if (e)
|
||||
{
|
||||
eis_event_unref (e);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_event_check (GSource *source)
|
||||
{
|
||||
MetaEventSource *event_source = (MetaEventSource *) source;
|
||||
gboolean retval;
|
||||
|
||||
retval = !!(event_source->event_poll_fd.revents & G_IO_IN);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_event_dispatch (GSource *g_source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaEventSource *source = (MetaEventSource *) g_source;
|
||||
MetaEis *meta_eis = source->meta_eis;
|
||||
|
||||
eis_dispatch (meta_eis->eis);
|
||||
process_events (meta_eis);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GSourceFuncs eis_event_funcs = {
|
||||
meta_event_prepare,
|
||||
meta_event_check,
|
||||
meta_event_dispatch,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
try_and_find_free_eis_socket (MetaEis *meta_eis)
|
||||
{
|
||||
int rc;
|
||||
int n;
|
||||
char socketname[16];
|
||||
|
||||
for (n = 0; n < 100; n++)
|
||||
{
|
||||
g_snprintf (socketname, sizeof (socketname), "eis-%d", n);
|
||||
rc = eis_setup_backend_socket (meta_eis->eis, socketname);
|
||||
if (rc == 0)
|
||||
{
|
||||
g_info ("Using EIS socket: %s", socketname);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
MetaEis *
|
||||
meta_eis_new (MetaBackend *backend)
|
||||
{
|
||||
MetaEis *meta_eis;
|
||||
int fd;
|
||||
int rc;
|
||||
|
||||
meta_eis = g_object_new (META_TYPE_EIS, NULL);
|
||||
meta_eis->backend = backend;
|
||||
|
||||
meta_eis->eis = eis_new (meta_eis);
|
||||
rc = try_and_find_free_eis_socket (meta_eis);
|
||||
if (rc != 0)
|
||||
{
|
||||
g_warning ("Failed to initialize the EIS socket: %s", g_strerror (-rc));
|
||||
g_clear_pointer (&meta_eis->eis, eis_unref);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = eis_get_fd (meta_eis->eis);
|
||||
meta_eis->event_source = meta_event_source_new (meta_eis, fd, &eis_event_funcs);
|
||||
|
||||
return meta_eis;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_init (MetaEis *meta_eis)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_constructed (GObject *object)
|
||||
{
|
||||
MetaEis *meta_eis = META_EIS (object);
|
||||
|
||||
meta_eis->eis_clients = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
(GDestroyNotify) eis_client_unref,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
|
||||
if (G_OBJECT_CLASS (meta_eis_parent_class)->constructed)
|
||||
G_OBJECT_CLASS (meta_eis_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_finalize (GObject *object)
|
||||
{
|
||||
MetaEis *meta_eis = META_EIS (object);
|
||||
|
||||
g_clear_pointer (&meta_eis->event_source, meta_event_source_free);
|
||||
g_clear_pointer (&meta_eis->eis, eis_unref);
|
||||
g_clear_pointer (&meta_eis->eis_clients, g_hash_table_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_class_init (MetaEisClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_eis_constructed;
|
||||
object_class->finalize = meta_eis_finalize;
|
||||
}
|
39
src/backends/meta-eis.h
Normal file
39
src/backends/meta-eis.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef META_EIS_H
|
||||
#define META_EIS_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "backends/meta-backend-types.h"
|
||||
#include "backends/meta-viewport-info.h"
|
||||
|
||||
#define META_TYPE_EIS (meta_eis_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaEis, meta_eis,
|
||||
META, EIS, GObject)
|
||||
|
||||
MetaEis * meta_eis_new (MetaBackend *backend);
|
||||
MetaBackend * meta_eis_get_backend (MetaEis *meta_eis);
|
||||
void meta_eis_remove_all_clients (MetaEis *meta_eis);
|
||||
|
||||
#endif /* META_EIS_H */
|
@ -35,6 +35,7 @@
|
||||
|
||||
#include "backends/meta-dbus-session-watcher.h"
|
||||
#include "backends/meta-dbus-session-manager.h"
|
||||
#include "backends/meta-eis.h"
|
||||
#include "backends/meta-screen-cast-session.h"
|
||||
#include "backends/meta-remote-access-controller-private.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
@ -224,6 +225,8 @@ meta_remote_desktop_session_close (MetaDbusSession *dbus_session)
|
||||
{
|
||||
MetaRemoteDesktopSession *session =
|
||||
META_REMOTE_DESKTOP_SESSION (dbus_session);
|
||||
MetaBackend *backend =
|
||||
meta_dbus_session_manager_get_backend (session->session_manager);
|
||||
MetaDBusRemoteDesktopSession *skeleton =
|
||||
META_DBUS_REMOTE_DESKTOP_SESSION (session);
|
||||
|
||||
@ -256,6 +259,8 @@ meta_remote_desktop_session_close (MetaDbusSession *dbus_session)
|
||||
meta_remote_access_handle_notify_stopped (remote_access_handle);
|
||||
}
|
||||
|
||||
meta_eis_remove_all_clients (meta_backend_get_eis (backend));
|
||||
|
||||
g_object_unref (session);
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ endif
|
||||
if have_remote_desktop
|
||||
mutter_pkg_private_deps += [
|
||||
libpipewire_dep,
|
||||
libeis_dep,
|
||||
]
|
||||
endif
|
||||
|
||||
@ -531,6 +532,10 @@ endif
|
||||
|
||||
if have_remote_desktop
|
||||
mutter_sources += [
|
||||
'backends/meta-eis.c',
|
||||
'backends/meta-eis.h',
|
||||
'backends/meta-eis-client.c',
|
||||
'backends/meta-eis-client.h',
|
||||
'backends/meta-remote-desktop.c',
|
||||
'backends/meta-remote-desktop.h',
|
||||
'backends/meta-remote-desktop-session.c',
|
||||
|
Loading…
Reference in New Issue
Block a user