2021-08-17 09:09:59 +10:00
|
|
|
/* -*- 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
|
2023-08-07 11:50:23 +02:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2021-08-17 09:09:59 +10:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "backends/meta-eis-client.h"
|
2023-08-28 22:18:48 +02:00
|
|
|
|
|
|
|
#include "backends/meta-backend-private.h"
|
2021-08-17 09:09:59 +10:00
|
|
|
#include "backends/meta-monitor-manager-private.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;
|
|
|
|
|
2023-08-28 23:13:16 +02:00
|
|
|
MetaEisViewport *viewport;
|
|
|
|
|
2021-08-17 09:09:59 +10:00
|
|
|
guchar button_state[(MAX_BUTTON + 7) / 8];
|
|
|
|
guchar key_state[(MAX_KEY + 7) / 8];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct _MetaEisClient
|
|
|
|
{
|
|
|
|
GObject parent_instance;
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEis *eis;
|
2021-08-17 09:09:59 +10:00
|
|
|
|
|
|
|
struct eis_client *eis_client;
|
|
|
|
struct eis_seat *eis_seat;
|
|
|
|
|
|
|
|
GHashTable *eis_devices; /* eis_device => MetaEisDevice*/
|
2023-08-28 23:13:16 +02:00
|
|
|
|
|
|
|
gulong viewports_changed_handler_id;
|
2021-08-17 09:09:59 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaEisClient, meta_eis_client, G_TYPE_OBJECT)
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
typedef void (* MetaEisDeviceConfigFunc) (MetaEisClient *client,
|
2023-08-28 22:14:53 +02:00
|
|
|
struct eis_device *device,
|
|
|
|
gpointer user_data);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
|
|
|
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
|
2023-08-15 12:49:16 +02:00
|
|
|
notify_key (MetaEisDevice *device,
|
2021-08-17 09:09:59 +10:00
|
|
|
uint32_t key,
|
|
|
|
gboolean is_press)
|
|
|
|
{
|
|
|
|
ClutterKeyState state;
|
|
|
|
|
|
|
|
state = is_press ? CLUTTER_KEY_STATE_PRESSED : CLUTTER_KEY_STATE_RELEASED;
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_key (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
key,
|
|
|
|
state);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
notify_button (MetaEisDevice *device,
|
2021-08-17 09:09:59 +10:00
|
|
|
uint32_t button,
|
|
|
|
gboolean is_press)
|
|
|
|
{
|
|
|
|
ClutterButtonState state;
|
|
|
|
|
|
|
|
state = is_press ? CLUTTER_BUTTON_STATE_PRESSED : CLUTTER_BUTTON_STATE_RELEASED;
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_button (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
button,
|
|
|
|
state);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
remove_device (MetaEisClient *client,
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_device *eis_device,
|
|
|
|
gboolean remove_from_hashtable)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
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);
|
2023-08-15 12:49:16 +02:00
|
|
|
g_clear_pointer (&device->eis_device, eis_device_unref);
|
|
|
|
g_clear_object (&device->device);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
|
|
|
if (remove_from_hashtable)
|
2023-08-15 12:49:16 +02:00
|
|
|
g_hash_table_remove (client->eis_devices, eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
drop_device (gpointer htkey,
|
|
|
|
gpointer value,
|
|
|
|
gpointer data)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisClient *client = data;
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_device *eis_device = htkey;
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
uint32_t key, button;
|
|
|
|
|
|
|
|
for (key = 0; key < MAX_KEY; key++)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
if (bit_is_set (device->key_state, key))
|
|
|
|
notify_key (device, key, FALSE);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
for (button = 0; button < MAX_BUTTON; button++)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
if (bit_is_set (device->button_state, key))
|
|
|
|
notify_button (device, button, FALSE);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
remove_device (client, eis_device, FALSE);
|
2021-08-17 09:09:59 +10:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_eis_device_free (MetaEisDevice *device)
|
|
|
|
{
|
|
|
|
eis_device_unref (device->eis_device);
|
|
|
|
free (device);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
configure_rel (MetaEisClient *client,
|
2023-08-28 22:14:53 +02:00
|
|
|
struct eis_device *eis_device,
|
|
|
|
gpointer user_data)
|
2021-08-17 09:09:59 +10:00
|
|
|
{
|
|
|
|
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
|
2023-08-15 12:49:16 +02:00
|
|
|
configure_keyboard (MetaEisClient *client,
|
2023-08-28 22:14:53 +02:00
|
|
|
struct eis_device *eis_device,
|
|
|
|
gpointer user_data)
|
2021-08-17 09:09:59 +10:00
|
|
|
{
|
|
|
|
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 =
|
2023-08-15 12:49:16 +02:00
|
|
|
meta_backend_get_keymap (meta_eis_get_backend (client->eis));
|
2021-08-17 09:09:59 +10:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-28 23:13:16 +02:00
|
|
|
static gboolean
|
|
|
|
has_region (struct eis_device *eis_device,
|
|
|
|
int x,
|
|
|
|
int y,
|
|
|
|
int width,
|
|
|
|
int height)
|
2021-08-17 09:09:59 +10:00
|
|
|
{
|
2023-09-12 13:23:50 +02:00
|
|
|
size_t i = 0;
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-28 23:13:16 +02:00
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
struct eis_region *region;
|
|
|
|
|
|
|
|
region = eis_device_get_region (eis_device, i++);
|
|
|
|
if (!region)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (eis_region_get_x (region) == x &&
|
|
|
|
eis_region_get_y (region) == y &&
|
|
|
|
eis_region_get_width (region) == width &&
|
|
|
|
eis_region_get_height (region) == height)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
add_viewport_region (struct eis_device *eis_device,
|
|
|
|
MetaEisViewport *viewport)
|
|
|
|
{
|
|
|
|
gboolean has_position;
|
|
|
|
int x, y;
|
|
|
|
int width, height;
|
|
|
|
double scale;
|
|
|
|
const char *mapping_id;
|
|
|
|
struct eis_region *eis_region;
|
|
|
|
|
2023-09-02 09:57:56 -03:00
|
|
|
has_position = meta_eis_viewport_get_position (viewport, &x, &y);
|
2023-08-28 23:13:16 +02:00
|
|
|
meta_eis_viewport_get_size (viewport, &width, &height);
|
|
|
|
scale = meta_eis_viewport_get_physical_scale (viewport);
|
|
|
|
|
|
|
|
if (has_region (eis_device, x, y, width, height))
|
|
|
|
return;
|
|
|
|
|
|
|
|
eis_region = eis_device_new_region (eis_device);
|
|
|
|
if (has_position)
|
|
|
|
eis_region_set_offset (eis_region, x, y);
|
|
|
|
eis_region_set_size (eis_region, width, height);
|
|
|
|
eis_region_set_physical_scale (eis_region, scale);
|
|
|
|
|
|
|
|
mapping_id = meta_eis_viewport_get_mapping_id (viewport);
|
2023-08-30 21:37:44 +02:00
|
|
|
if (mapping_id)
|
|
|
|
eis_region_set_mapping_id (eis_region, mapping_id);
|
2023-08-28 23:13:16 +02:00
|
|
|
|
|
|
|
eis_region_set_user_data (eis_region, viewport);
|
|
|
|
eis_region_add (eis_region);
|
|
|
|
eis_region_unref (eis_region);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
configure_abs_shared (MetaEisClient *client,
|
|
|
|
struct eis_device *eis_device,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
MetaEisViewport *viewport = META_EIS_VIEWPORT (user_data);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2023-08-28 23:13:16 +02:00
|
|
|
add_viewport_region (eis_device, viewport);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-28 23:13:16 +02:00
|
|
|
configure_abs_standalone (MetaEisClient *client,
|
|
|
|
struct eis_device *eis_device,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
MetaEisViewport *viewport = META_EIS_VIEWPORT (user_data);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
add_viewport_region (eis_device, viewport);
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaEisDevice *
|
backends/eis-client: Do not add device before adding EIS regions
When a device is added, libei does not allow adding additional regions
for that particular device, as it is already advertised to the EI
client.
As a result, mutter currently effectively only adds the first region to
a device, but not the others.
This makes input in multi monitor sessions only possible on one monitor,
as the EI client cannot look up the other regions, since they were not
advertised to it.
Fix this situation by not adding and resuming the device, when a shared
device is used.
Instead, for shared devices, always add all regions first, and then
after that, add and resume the device.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3273>
2023-09-12 19:03:25 +02:00
|
|
|
create_device (MetaEisClient *client,
|
|
|
|
struct eis_seat *eis_seat,
|
|
|
|
ClutterInputDeviceType type,
|
|
|
|
const char *name_suffix,
|
|
|
|
MetaEisDeviceConfigFunc extra_config_func,
|
|
|
|
gpointer extra_config_user_data)
|
2021-08-17 09:09:59 +10:00
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaBackend *backend = meta_eis_get_backend (client->eis);
|
|
|
|
MetaEisDevice *device;
|
2021-08-17 09:09:59 +10:00
|
|
|
ClutterSeat *seat = meta_backend_get_default_seat (backend);
|
2023-08-15 12:49:16 +02:00
|
|
|
ClutterVirtualInputDevice *virtual_device;
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_device *eis_device;
|
|
|
|
gchar *name;
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
virtual_device = clutter_seat_create_virtual_device (seat, type);
|
2021-08-17 09:09:59 +10:00
|
|
|
eis_device = eis_seat_new_device (eis_seat);
|
2023-08-15 12:49:16 +02:00
|
|
|
name = g_strdup_printf ("%s %s", eis_client_get_name (client->eis_client),
|
2021-08-17 09:09:59 +10:00
|
|
|
name_suffix);
|
|
|
|
eis_device_configure_name (eis_device, name);
|
|
|
|
if (extra_config_func)
|
2023-08-28 22:14:53 +02:00
|
|
|
extra_config_func (client, eis_device, extra_config_user_data);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
device = g_new0 (MetaEisDevice, 1);
|
|
|
|
device->eis_device = eis_device_ref (eis_device);
|
|
|
|
device->device = virtual_device;
|
|
|
|
eis_device_set_user_data (eis_device, device);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
g_hash_table_insert (client->eis_devices,
|
2021-08-17 09:09:59 +10:00
|
|
|
eis_device, /* owns the initial ref now */
|
2023-08-15 12:49:16 +02:00
|
|
|
device);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
|
|
|
g_free (name);
|
2023-08-28 23:13:16 +02:00
|
|
|
|
|
|
|
return device;
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
backends/eis-client: Do not add device before adding EIS regions
When a device is added, libei does not allow adding additional regions
for that particular device, as it is already advertised to the EI
client.
As a result, mutter currently effectively only adds the first region to
a device, but not the others.
This makes input in multi monitor sessions only possible on one monitor,
as the EI client cannot look up the other regions, since they were not
advertised to it.
Fix this situation by not adding and resuming the device, when a shared
device is used.
Instead, for shared devices, always add all regions first, and then
after that, add and resume the device.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3273>
2023-09-12 19:03:25 +02:00
|
|
|
static void
|
|
|
|
propagate_device (MetaEisDevice *device)
|
|
|
|
{
|
|
|
|
eis_device_add (device->eis_device);
|
|
|
|
eis_device_resume (device->eis_device);
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaEisDevice *
|
|
|
|
add_device (MetaEisClient *client,
|
|
|
|
struct eis_seat *eis_seat,
|
|
|
|
ClutterInputDeviceType type,
|
|
|
|
const char *name_suffix,
|
|
|
|
MetaEisDeviceConfigFunc extra_config_func,
|
|
|
|
gpointer extra_config_user_data)
|
|
|
|
{
|
|
|
|
MetaEisDevice *device;
|
|
|
|
|
|
|
|
device = create_device (client,
|
|
|
|
eis_seat,
|
|
|
|
type,
|
|
|
|
name_suffix,
|
|
|
|
extra_config_func, extra_config_user_data);
|
|
|
|
propagate_device (device);
|
|
|
|
|
|
|
|
return device;
|
|
|
|
}
|
|
|
|
|
2021-08-17 09:09:59 +10:00
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_motion_relative (MetaEisClient *client,
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_event *event)
|
|
|
|
{
|
|
|
|
struct eis_device *eis_device = eis_event_get_device (event);
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
double dx, dy;
|
|
|
|
|
|
|
|
dx = eis_event_pointer_get_dx (event);
|
|
|
|
dy = eis_event_pointer_get_dy (event);
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_relative_motion (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
dx, dy);
|
|
|
|
}
|
|
|
|
|
2023-08-28 23:13:16 +02:00
|
|
|
static MetaEisViewport *
|
|
|
|
find_viewport (struct eis_event *event)
|
|
|
|
{
|
|
|
|
struct eis_device *eis_device = eis_event_get_device (event);
|
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
|
|
|
double x, y;
|
|
|
|
struct eis_region *region;
|
|
|
|
|
|
|
|
if (device->viewport)
|
|
|
|
return device->viewport;
|
|
|
|
|
|
|
|
x = eis_event_pointer_get_absolute_x (event);
|
|
|
|
y = eis_event_pointer_get_absolute_y (event);
|
|
|
|
region = eis_device_get_region_at (eis_device, x, y);
|
|
|
|
if (!region)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return META_EIS_VIEWPORT (eis_region_get_user_data (region));
|
|
|
|
}
|
|
|
|
|
2021-08-17 09:09:59 +10:00
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_motion_absolute (MetaEisClient *client,
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_event *event)
|
|
|
|
{
|
|
|
|
struct eis_device *eis_device = eis_event_get_device (event);
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2023-08-28 23:13:16 +02:00
|
|
|
MetaEisViewport *viewport;
|
2021-08-17 09:09:59 +10:00
|
|
|
double x, y;
|
|
|
|
|
2023-08-28 23:13:16 +02:00
|
|
|
viewport = find_viewport (event);
|
|
|
|
if (!viewport)
|
|
|
|
return;
|
|
|
|
|
2021-08-17 09:09:59 +10:00
|
|
|
x = eis_event_pointer_get_absolute_x (event);
|
|
|
|
y = eis_event_pointer_get_absolute_y (event);
|
2023-08-28 23:13:16 +02:00
|
|
|
if (!meta_eis_viewport_transform_coordinate (viewport, x, y, &x, &y))
|
|
|
|
return;
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_absolute_motion (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_scroll (MetaEisClient *client,
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_event *event)
|
|
|
|
{
|
|
|
|
struct eis_device *eis_device = eis_event_get_device (event);
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
double dx, dy;
|
|
|
|
|
|
|
|
dx = eis_event_scroll_get_dx (event);
|
|
|
|
dy = eis_event_scroll_get_dy (event);
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_scroll_continuous (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
dx, dy,
|
2023-09-02 10:57:53 +02:00
|
|
|
CLUTTER_SCROLL_SOURCE_WHEEL,
|
2021-08-17 09:09:59 +10:00
|
|
|
CLUTTER_SCROLL_FINISHED_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_scroll_stop (MetaEisClient *client,
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_event *event)
|
|
|
|
{
|
|
|
|
struct eis_device *eis_device = eis_event_get_device (event);
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
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)
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_scroll_continuous (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
0.0, 0.0,
|
2023-09-02 10:57:53 +02:00
|
|
|
CLUTTER_SCROLL_SOURCE_WHEEL,
|
2021-08-17 09:09:59 +10:00
|
|
|
finish_flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_scroll_cancel (MetaEisClient *client,
|
|
|
|
struct eis_event *event)
|
2021-08-17 09:09:59 +10:00
|
|
|
{
|
|
|
|
struct eis_device *eis_device = eis_event_get_device (event);
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
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)
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_scroll_continuous (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
dx, dy,
|
2023-09-02 10:57:53 +02:00
|
|
|
CLUTTER_SCROLL_SOURCE_WHEEL,
|
2021-08-17 09:09:59 +10:00
|
|
|
CLUTTER_SCROLL_FINISHED_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_scroll_discrete (MetaEisClient *client,
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_event *event)
|
|
|
|
{
|
|
|
|
struct eis_device *eis_device = eis_event_get_device (event);
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
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)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_discrete_scroll (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
CLUTTER_SCROLL_RIGHT,
|
2023-09-02 10:57:53 +02:00
|
|
|
CLUTTER_SCROLL_SOURCE_WHEEL);
|
2021-08-17 09:09:59 +10:00
|
|
|
dx--;
|
|
|
|
}
|
|
|
|
else if (dx < 0)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_discrete_scroll (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
CLUTTER_SCROLL_LEFT,
|
2023-09-02 10:57:53 +02:00
|
|
|
CLUTTER_SCROLL_SOURCE_WHEEL);
|
2021-08-17 09:09:59 +10:00
|
|
|
dx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dy > 0)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_discrete_scroll (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
CLUTTER_SCROLL_DOWN,
|
2023-09-02 10:57:53 +02:00
|
|
|
CLUTTER_SCROLL_SOURCE_WHEEL);
|
2021-08-17 09:09:59 +10:00
|
|
|
dy--;
|
|
|
|
}
|
|
|
|
else if (dy < 0)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
clutter_virtual_input_device_notify_discrete_scroll (device->device,
|
2021-08-17 09:09:59 +10:00
|
|
|
g_get_monotonic_time (),
|
|
|
|
CLUTTER_SCROLL_UP,
|
2023-09-02 10:57:53 +02:00
|
|
|
CLUTTER_SCROLL_SOURCE_WHEEL);
|
2021-08-17 09:09:59 +10:00
|
|
|
dy++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_button (MetaEisClient *client,
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_event *event)
|
|
|
|
{
|
|
|
|
struct eis_device *eis_device = eis_event_get_device (event);
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
uint32_t button;
|
|
|
|
gboolean is_press = eis_event_button_get_is_press (event);
|
|
|
|
|
|
|
|
button = eis_event_button_get_button (event);
|
2023-10-11 21:30:35 +08:00
|
|
|
button = meta_evdev_button_to_clutter (button);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
|
|
|
if (button > MAX_BUTTON)
|
|
|
|
return;
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
if (is_press && !bit_is_set (device->button_state, button))
|
|
|
|
bit_set (device->button_state, button);
|
|
|
|
else if (!is_press && bit_is_set (device->button_state, button))
|
|
|
|
bit_clear (device->button_state, button);
|
2021-08-17 09:09:59 +10:00
|
|
|
else
|
|
|
|
return; /* Duplicate press/release, should've been filtered by libeis */
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
notify_button (device,
|
2021-08-17 09:09:59 +10:00
|
|
|
button,
|
|
|
|
eis_event_button_get_is_press (event));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_key (MetaEisClient *client,
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_event *event)
|
|
|
|
{
|
|
|
|
struct eis_device *eis_device = eis_event_get_device (event);
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
2021-08-17 09:09:59 +10:00
|
|
|
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;
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
if (is_press && !bit_is_set (device->key_state, key))
|
|
|
|
bit_set (device->key_state, key);
|
|
|
|
else if (!is_press && bit_is_set (device->key_state, key))
|
|
|
|
bit_clear (device->key_state, key);
|
2021-08-17 09:09:59 +10:00
|
|
|
else
|
|
|
|
return; /* Duplicate press/release, should've been filtered by libeis */
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
notify_key (device, key, is_press);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisClient *client = data;
|
2021-08-17 09:09:59 +10:00
|
|
|
|
|
|
|
/* Changing the keymap means we have to remove our device and recreate it
|
|
|
|
* with the new keymap.
|
|
|
|
*/
|
2023-08-15 12:49:16 +02:00
|
|
|
g_hash_table_foreach_remove (client->eis_devices,
|
2021-08-17 09:09:59 +10:00
|
|
|
drop_kbd_devices,
|
2023-08-15 12:49:16 +02:00
|
|
|
client);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
add_device (client,
|
|
|
|
client->eis_seat,
|
2021-08-17 09:09:59 +10:00
|
|
|
CLUTTER_KEYBOARD_DEVICE,
|
|
|
|
"virtual keyboard",
|
2023-08-28 22:14:53 +02:00
|
|
|
configure_keyboard, NULL);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
2023-08-28 23:13:16 +02:00
|
|
|
static void
|
|
|
|
add_abs_pointer_devices (MetaEisClient *client)
|
|
|
|
{
|
|
|
|
MetaEisDevice *shared_device = NULL;
|
|
|
|
GList *viewports;
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
viewports = meta_eis_peek_viewports (client->eis);
|
|
|
|
if (!viewports)
|
|
|
|
return; /* FIXME: should be an error */
|
|
|
|
|
|
|
|
for (l = viewports; l; l = l->next)
|
|
|
|
{
|
|
|
|
MetaEisViewport *viewport = l->data;
|
|
|
|
|
|
|
|
if (meta_eis_viewport_is_standalone (viewport))
|
|
|
|
{
|
|
|
|
MetaEisDevice *device;
|
|
|
|
|
|
|
|
device = add_device (client,
|
|
|
|
client->eis_seat,
|
|
|
|
CLUTTER_POINTER_DEVICE,
|
|
|
|
"standalone virtual absolute pointer",
|
|
|
|
configure_abs_standalone,
|
|
|
|
viewport);
|
|
|
|
device->viewport = viewport;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!shared_device)
|
|
|
|
{
|
backends/eis-client: Do not add device before adding EIS regions
When a device is added, libei does not allow adding additional regions
for that particular device, as it is already advertised to the EI
client.
As a result, mutter currently effectively only adds the first region to
a device, but not the others.
This makes input in multi monitor sessions only possible on one monitor,
as the EI client cannot look up the other regions, since they were not
advertised to it.
Fix this situation by not adding and resuming the device, when a shared
device is used.
Instead, for shared devices, always add all regions first, and then
after that, add and resume the device.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3273>
2023-09-12 19:03:25 +02:00
|
|
|
shared_device = create_device (client,
|
|
|
|
client->eis_seat,
|
|
|
|
CLUTTER_POINTER_DEVICE,
|
|
|
|
"shared virtual absolute pointer",
|
|
|
|
configure_abs_shared,
|
|
|
|
viewport);
|
2023-08-28 23:13:16 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
add_viewport_region (shared_device->eis_device, viewport);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
backends/eis-client: Do not add device before adding EIS regions
When a device is added, libei does not allow adding additional regions
for that particular device, as it is already advertised to the EI
client.
As a result, mutter currently effectively only adds the first region to
a device, but not the others.
This makes input in multi monitor sessions only possible on one monitor,
as the EI client cannot look up the other regions, since they were not
advertised to it.
Fix this situation by not adding and resuming the device, when a shared
device is used.
Instead, for shared devices, always add all regions first, and then
after that, add and resume the device.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3273>
2023-09-12 19:03:25 +02:00
|
|
|
|
|
|
|
if (shared_device)
|
|
|
|
propagate_device (shared_device);
|
2023-08-28 23:13:16 +02:00
|
|
|
}
|
|
|
|
|
2021-08-17 09:09:59 +10:00
|
|
|
gboolean
|
2023-08-15 12:49:16 +02:00
|
|
|
meta_eis_client_process_event (MetaEisClient *client,
|
2021-08-17 09:09:59 +10:00
|
|
|
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))
|
2023-08-28 17:18:31 +02:00
|
|
|
{
|
|
|
|
add_device (client,
|
|
|
|
eis_seat,
|
|
|
|
CLUTTER_POINTER_DEVICE,
|
|
|
|
"virtual pointer",
|
2023-08-28 22:14:53 +02:00
|
|
|
configure_rel, NULL);
|
2023-08-28 17:18:31 +02:00
|
|
|
}
|
2021-08-17 09:09:59 +10:00
|
|
|
if (eis_event_seat_has_capability (event, EIS_DEVICE_CAP_KEYBOARD))
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
add_device (client,
|
2021-08-17 09:09:59 +10:00
|
|
|
eis_seat,
|
|
|
|
CLUTTER_KEYBOARD_DEVICE,
|
|
|
|
"virtual keyboard",
|
2023-08-28 22:14:53 +02:00
|
|
|
configure_keyboard, NULL);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-28 17:16:58 +02:00
|
|
|
g_signal_connect (meta_eis_get_backend (client->eis),
|
|
|
|
"keymap-changed",
|
|
|
|
G_CALLBACK (on_keymap_changed),
|
|
|
|
client);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
2023-08-28 23:13:16 +02:00
|
|
|
|
|
|
|
add_abs_pointer_devices (client);
|
2021-08-17 09:09:59 +10:00
|
|
|
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:
|
2023-08-15 12:49:16 +02:00
|
|
|
remove_device (client, eis_event_get_device (event), TRUE);
|
2021-08-17 09:09:59 +10:00
|
|
|
break;
|
|
|
|
case EIS_EVENT_POINTER_MOTION:
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_motion_relative (client, event);
|
2021-08-17 09:09:59 +10:00
|
|
|
break;
|
|
|
|
case EIS_EVENT_POINTER_MOTION_ABSOLUTE:
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_motion_absolute (client, event);
|
2021-08-17 09:09:59 +10:00
|
|
|
break;
|
|
|
|
case EIS_EVENT_BUTTON_BUTTON:
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_button (client, event);
|
2021-08-17 09:09:59 +10:00
|
|
|
break;
|
|
|
|
case EIS_EVENT_SCROLL_DELTA:
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_scroll (client, event);
|
2021-08-17 09:09:59 +10:00
|
|
|
break;
|
|
|
|
case EIS_EVENT_SCROLL_STOP:
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_scroll_stop (client, event);
|
2021-08-17 09:09:59 +10:00
|
|
|
break;
|
|
|
|
case EIS_EVENT_SCROLL_CANCEL:
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_scroll_cancel (client, event);
|
2021-08-17 09:09:59 +10:00
|
|
|
break;
|
|
|
|
case EIS_EVENT_SCROLL_DISCRETE:
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_scroll_discrete (client, event);
|
2021-08-17 09:09:59 +10:00
|
|
|
break;
|
|
|
|
case EIS_EVENT_KEYBOARD_KEY:
|
2023-08-15 12:49:16 +02:00
|
|
|
handle_key (client, event);
|
2021-08-17 09:09:59 +10:00
|
|
|
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
|
2023-08-28 23:13:16 +02:00
|
|
|
update_viewports (MetaEisClient *client)
|
2021-08-17 09:09:59 +10:00
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
g_hash_table_foreach_remove (client->eis_devices,
|
2021-08-17 09:09:59 +10:00
|
|
|
drop_abs_devices,
|
2023-08-15 12:49:16 +02:00
|
|
|
client);
|
2023-08-28 23:13:16 +02:00
|
|
|
add_abs_pointer_devices (client);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-28 23:13:16 +02:00
|
|
|
on_viewports_changed (MetaEis *eis,
|
|
|
|
MetaEisClient *client)
|
2021-08-17 09:09:59 +10:00
|
|
|
{
|
2023-08-28 23:13:16 +02:00
|
|
|
update_viewports (client);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
meta_eis_client_disconnect (MetaEisClient *client)
|
2021-08-17 09:09:59 +10:00
|
|
|
{
|
2023-08-28 23:13:16 +02:00
|
|
|
g_clear_signal_handler (&client->viewports_changed_handler_id, client->eis);
|
2023-08-15 12:49:16 +02:00
|
|
|
g_hash_table_foreach_remove (client->eis_devices, drop_device, client);
|
|
|
|
g_clear_pointer (&client->eis_seat, eis_seat_unref);
|
|
|
|
if (client->eis_client)
|
|
|
|
eis_client_disconnect (client->eis_client);
|
|
|
|
g_clear_pointer (&client->eis_client, eis_client_unref);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
MetaEisClient *
|
2023-08-15 12:49:16 +02:00
|
|
|
meta_eis_client_new (MetaEis *eis,
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_client *eis_client)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisClient *client;
|
2021-08-17 09:09:59 +10:00
|
|
|
struct eis_seat *eis_seat;
|
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
client = g_object_new (META_TYPE_EIS_CLIENT, NULL);
|
|
|
|
client->eis = eis;
|
|
|
|
client->eis_client = eis_client_ref (eis_client);
|
|
|
|
eis_client_set_user_data (client->eis_client, client);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
|
|
|
/* 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");
|
2023-08-28 17:21:35 +02:00
|
|
|
|
|
|
|
if (meta_eis_get_device_types (eis) & META_EIS_DEVICE_TYPE_KEYBOARD)
|
|
|
|
{
|
|
|
|
eis_seat_configure_capability (eis_seat, EIS_DEVICE_CAP_KEYBOARD);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (meta_eis_get_device_types (eis) & META_EIS_DEVICE_TYPE_POINTER)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2021-08-17 09:09:59 +10:00
|
|
|
|
|
|
|
eis_seat_add (eis_seat);
|
|
|
|
eis_seat_unref (eis_seat);
|
2023-08-15 12:49:16 +02:00
|
|
|
client->eis_seat = eis_seat_ref (eis_seat);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
client->eis_devices = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
|
|
|
(GDestroyNotify) eis_device_unref,
|
|
|
|
(GDestroyNotify) meta_eis_device_free);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-28 23:13:16 +02:00
|
|
|
client->viewports_changed_handler_id =
|
|
|
|
g_signal_connect (eis, "viewports-changed",
|
|
|
|
G_CALLBACK (on_viewports_changed),
|
|
|
|
client);
|
|
|
|
update_viewports (client);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
return client;
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-08-15 12:49:16 +02:00
|
|
|
meta_eis_client_init (MetaEisClient *client)
|
2021-08-17 09:09:59 +10:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_eis_client_finalize (GObject *object)
|
|
|
|
{
|
2023-08-15 12:49:16 +02:00
|
|
|
MetaEisClient *client = META_EIS_CLIENT (object);
|
2021-08-17 09:09:59 +10:00
|
|
|
|
2023-08-15 12:49:16 +02:00
|
|
|
g_signal_handlers_disconnect_by_func (meta_eis_get_backend (client->eis),
|
2021-08-17 09:09:59 +10:00
|
|
|
on_keymap_changed,
|
2023-08-15 12:49:16 +02:00
|
|
|
client);
|
|
|
|
meta_eis_client_disconnect (client);
|
2023-08-22 21:57:07 +02:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_eis_client_parent_class)->finalize (object);
|
2021-08-17 09:09:59 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_eis_client_class_init (MetaEisClientClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->finalize = meta_eis_client_finalize;
|
|
|
|
}
|