eis/client: Add touch support
Touch devices are handled very similarly to how absolute pointer devices, by creating either shared or standalone devices depending on what kind of monitor it's associated with. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4064>
This commit is contained in:
parent
6a1e1d74e5
commit
c46db0a020
@ -29,6 +29,7 @@
|
||||
|
||||
#define MAX_BUTTON 128
|
||||
#define MAX_KEY 0x2ff /* KEY_MAX as of 5.13 */
|
||||
#define MAX_SLOTS 64
|
||||
|
||||
typedef struct _MetaEisDevice MetaEisDevice;
|
||||
|
||||
@ -41,6 +42,12 @@ struct _MetaEisDevice
|
||||
|
||||
guchar button_state[(MAX_BUTTON + 7) / 8];
|
||||
guchar key_state[(MAX_KEY + 7) / 8];
|
||||
|
||||
struct {
|
||||
gboolean is_acquired;
|
||||
uint32_t eis_touch_id;
|
||||
} slots[MAX_SLOTS];
|
||||
GHashTable *slot_map;
|
||||
};
|
||||
|
||||
struct _MetaEisClient
|
||||
@ -56,6 +63,7 @@ struct _MetaEisClient
|
||||
MetaEisDevice *keyboard_device;
|
||||
gulong keymap_changed_handler_id;
|
||||
gboolean have_abs_pointer_devices;
|
||||
gboolean have_touch_devices;
|
||||
|
||||
gulong viewports_changed_handler_id;
|
||||
};
|
||||
@ -178,10 +186,38 @@ drop_abs_devices (gpointer key,
|
||||
return drop_device (key, value, data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drop_touch_devices (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
struct eis_device *eis_device = key;
|
||||
|
||||
if (!eis_device_has_capability (eis_device, EIS_DEVICE_CAP_TOUCH))
|
||||
return FALSE;
|
||||
|
||||
return drop_device (key, value, data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drop_viewport_devices (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
struct eis_device *eis_device = key;
|
||||
|
||||
if (!eis_device_has_capability (eis_device, EIS_DEVICE_CAP_TOUCH) &&
|
||||
!eis_device_has_capability (eis_device, EIS_DEVICE_CAP_POINTER_ABSOLUTE))
|
||||
return FALSE;
|
||||
|
||||
return drop_device (key, value, data);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_eis_device_free (MetaEisDevice *device)
|
||||
{
|
||||
eis_device_unref (device->eis_device);
|
||||
g_hash_table_unref (device->slot_map);
|
||||
free (device);
|
||||
}
|
||||
|
||||
@ -310,6 +346,18 @@ configure_abs (MetaEisClient *client,
|
||||
add_viewport_region (eis_device, viewport);
|
||||
}
|
||||
|
||||
static void
|
||||
configure_touch (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_TOUCH);
|
||||
|
||||
add_viewport_region (eis_device, viewport);
|
||||
}
|
||||
|
||||
static MetaEisDevice *
|
||||
create_device (MetaEisClient *client,
|
||||
struct eis_seat *eis_seat,
|
||||
@ -340,6 +388,7 @@ create_device (MetaEisClient *client,
|
||||
device = g_new0 (MetaEisDevice, 1);
|
||||
device->eis_device = eis_device_ref (eis_device);
|
||||
device->device = virtual_device;
|
||||
device->slot_map = g_hash_table_new (NULL, NULL);
|
||||
eis_device_set_user_data (eis_device, device);
|
||||
|
||||
g_hash_table_insert (client->eis_devices,
|
||||
@ -395,19 +444,16 @@ handle_motion_relative (MetaEisClient *client,
|
||||
}
|
||||
|
||||
static MetaEisViewport *
|
||||
find_viewport (struct eis_event *event)
|
||||
find_viewport (MetaEisDevice *device,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
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);
|
||||
region = eis_device_get_region_at (device->eis_device, x, y);
|
||||
if (!region)
|
||||
return NULL;
|
||||
|
||||
@ -423,12 +469,13 @@ handle_motion_absolute (MetaEisClient *client,
|
||||
MetaEisViewport *viewport;
|
||||
double x, y;
|
||||
|
||||
viewport = find_viewport (event);
|
||||
x = eis_event_pointer_get_absolute_x (event);
|
||||
y = eis_event_pointer_get_absolute_y (event);
|
||||
|
||||
viewport = find_viewport (device, x, y);
|
||||
if (!viewport)
|
||||
return;
|
||||
|
||||
x = eis_event_pointer_get_absolute_x (event);
|
||||
y = eis_event_pointer_get_absolute_y (event);
|
||||
if (!meta_eis_viewport_transform_coordinate (viewport, x, y, &x, &y))
|
||||
return;
|
||||
|
||||
@ -603,6 +650,119 @@ handle_key (MetaEisClient *client,
|
||||
notify_key (device, key, is_press);
|
||||
}
|
||||
|
||||
static int
|
||||
acquire_slot (MetaEisDevice *device,
|
||||
uint32_t eis_touch_id)
|
||||
{
|
||||
int slot;
|
||||
|
||||
for (slot = 0; slot < MAX_SLOTS; slot++)
|
||||
{
|
||||
if (device->slots[slot].is_acquired)
|
||||
continue;
|
||||
|
||||
device->slots[slot].is_acquired = TRUE;
|
||||
device->slots[slot].eis_touch_id = eis_touch_id;
|
||||
g_hash_table_insert (device->slot_map,
|
||||
GUINT_TO_POINTER (eis_touch_id),
|
||||
GINT_TO_POINTER (slot));
|
||||
return slot;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
get_slot (MetaEisDevice *device,
|
||||
uint32_t touch_id)
|
||||
{
|
||||
return GPOINTER_TO_INT (g_hash_table_lookup (device->slot_map,
|
||||
GUINT_TO_POINTER (touch_id)));
|
||||
}
|
||||
|
||||
static void
|
||||
release_slot (MetaEisDevice *device,
|
||||
int slot)
|
||||
{
|
||||
g_assert (device->slots[slot].is_acquired);
|
||||
|
||||
device->slots[slot].is_acquired = FALSE;
|
||||
g_hash_table_remove (device->slot_map,
|
||||
GUINT_TO_POINTER (device->slots[slot].eis_touch_id));
|
||||
device->slots[slot].eis_touch_id = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_touch_down (MetaEisClient *client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
||||
MetaEisViewport *viewport;
|
||||
double x, y;
|
||||
int slot;
|
||||
|
||||
x = eis_event_touch_get_x (event);
|
||||
y = eis_event_touch_get_y (event);
|
||||
|
||||
viewport = find_viewport (device, x, y);
|
||||
if (!viewport)
|
||||
return;
|
||||
|
||||
if (!meta_eis_viewport_transform_coordinate (viewport, x, y, &x, &y))
|
||||
return;
|
||||
|
||||
slot = acquire_slot (device, eis_event_touch_get_id (event));
|
||||
clutter_virtual_input_device_notify_touch_down (device->device,
|
||||
g_get_monotonic_time (),
|
||||
slot,
|
||||
x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_touch_motion (MetaEisClient *client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
||||
MetaEisViewport *viewport;
|
||||
double x, y;
|
||||
int slot;
|
||||
|
||||
x = eis_event_touch_get_x (event);
|
||||
y = eis_event_touch_get_y (event);
|
||||
|
||||
viewport = find_viewport (device, x, y);
|
||||
if (!viewport)
|
||||
return;
|
||||
|
||||
if (!meta_eis_viewport_transform_coordinate (viewport, x, y, &x, &y))
|
||||
return;
|
||||
|
||||
slot = get_slot (device, eis_event_touch_get_id (event));
|
||||
|
||||
clutter_virtual_input_device_notify_touch_motion (device->device,
|
||||
g_get_monotonic_time (),
|
||||
slot,
|
||||
x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_touch_up (MetaEisClient *client,
|
||||
struct eis_event *event)
|
||||
{
|
||||
struct eis_device *eis_device = eis_event_get_device (event);
|
||||
MetaEisDevice *device = eis_device_get_user_data (eis_device);
|
||||
int slot;
|
||||
|
||||
slot = get_slot (device, eis_event_touch_get_id (event));
|
||||
release_slot (device, slot);
|
||||
|
||||
clutter_virtual_input_device_notify_touch_up (device->device,
|
||||
g_get_monotonic_time (),
|
||||
slot);
|
||||
}
|
||||
|
||||
static void
|
||||
on_keymap_changed (MetaBackend *backend,
|
||||
gpointer data)
|
||||
@ -697,6 +857,15 @@ add_abs_pointer_devices (MetaEisClient *client)
|
||||
configure_abs);
|
||||
}
|
||||
|
||||
static void
|
||||
add_touch_devices (MetaEisClient *client)
|
||||
{
|
||||
add_viewport_devices (client,
|
||||
CLUTTER_TOUCHSCREEN_DEVICE,
|
||||
"virtual touch screen",
|
||||
configure_touch);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_eis_client_process_event (MetaEisClient *client,
|
||||
struct eis_event *event)
|
||||
@ -711,6 +880,7 @@ meta_eis_client_process_event (MetaEisClient *client,
|
||||
gboolean wants_pointer_device;
|
||||
gboolean wants_keyboard_device;
|
||||
gboolean wants_abs_pointer_devices;
|
||||
gboolean wants_touch_devices;
|
||||
|
||||
eis_seat = eis_event_get_seat (event);
|
||||
|
||||
@ -720,6 +890,8 @@ meta_eis_client_process_event (MetaEisClient *client,
|
||||
eis_event_seat_has_capability (event, EIS_DEVICE_CAP_KEYBOARD);
|
||||
wants_abs_pointer_devices =
|
||||
eis_event_seat_has_capability (event, EIS_DEVICE_CAP_POINTER_ABSOLUTE);
|
||||
wants_touch_devices =
|
||||
eis_event_seat_has_capability (event, EIS_DEVICE_CAP_TOUCH);
|
||||
|
||||
if (wants_pointer_device && !client->pointer_device)
|
||||
{
|
||||
@ -795,6 +967,25 @@ meta_eis_client_process_event (MetaEisClient *client,
|
||||
client);
|
||||
client->have_abs_pointer_devices = FALSE;
|
||||
}
|
||||
|
||||
if (wants_touch_devices && !client->have_touch_devices)
|
||||
{
|
||||
meta_topic (META_DEBUG_EIS,
|
||||
"Seat %s bindings updated, enabling touch devices",
|
||||
eis_seat_get_name (eis_seat));
|
||||
add_touch_devices (client);
|
||||
client->have_touch_devices = TRUE;
|
||||
}
|
||||
else if (!wants_touch_devices && client->have_touch_devices)
|
||||
{
|
||||
meta_topic (META_DEBUG_EIS,
|
||||
"Seat %s bindings updated, destroying touch devices",
|
||||
eis_seat_get_name (eis_seat));
|
||||
g_hash_table_foreach_remove (client->eis_devices,
|
||||
drop_touch_devices,
|
||||
client);
|
||||
client->have_touch_devices = FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EIS_EVENT_DEVICE_CLOSED:
|
||||
@ -834,6 +1025,15 @@ meta_eis_client_process_event (MetaEisClient *client,
|
||||
case EIS_EVENT_KEYBOARD_KEY:
|
||||
handle_key (client, event);
|
||||
break;
|
||||
case EIS_EVENT_TOUCH_DOWN:
|
||||
handle_touch_down (client, event);
|
||||
break;
|
||||
case EIS_EVENT_TOUCH_MOTION:
|
||||
handle_touch_motion (client, event);
|
||||
break;
|
||||
case EIS_EVENT_TOUCH_UP:
|
||||
handle_touch_up (client, event);
|
||||
break;
|
||||
case EIS_EVENT_FRAME:
|
||||
/* FIXME: we should be accumulating the above events */
|
||||
break;
|
||||
@ -855,11 +1055,14 @@ update_viewports (MetaEisClient *client)
|
||||
meta_topic (META_DEBUG_EIS, "Updating viewports");
|
||||
|
||||
g_hash_table_foreach_remove (client->eis_devices,
|
||||
drop_abs_devices,
|
||||
drop_viewport_devices,
|
||||
client);
|
||||
|
||||
if (client->have_abs_pointer_devices)
|
||||
add_abs_pointer_devices (client);
|
||||
|
||||
if (client->have_touch_devices)
|
||||
add_touch_devices (client);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -916,6 +1119,11 @@ meta_eis_client_new (MetaEis *eis,
|
||||
eis_seat_configure_capability (eis_seat, EIS_DEVICE_CAP_SCROLL);
|
||||
}
|
||||
|
||||
if (meta_eis_get_device_types (eis) & META_EIS_DEVICE_TYPE_TOUCHSCREEN)
|
||||
{
|
||||
eis_seat_configure_capability (eis_seat, EIS_DEVICE_CAP_TOUCH);
|
||||
}
|
||||
|
||||
eis_seat_add (eis_seat);
|
||||
eis_seat_unref (eis_seat);
|
||||
client->eis_seat = eis_seat_ref (eis_seat);
|
||||
|
Loading…
x
Reference in New Issue
Block a user