mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
seat-x11: Translate device enabled/disabled into clutter events
When a device is removed from the seat the events that this device may have emitted just before being removed might still be in the stage events queue, this may lead a to a crash because: Once the device is removed, we dispose it and the staling event is kept in queue and sent for processing at next loop. During event processing we ask the backend to update the last device with the disposed device The device is disposed once the events referencing it, are free'd The actual last device emission happens in an idle, but at this point the device may have been free'd, and in any case will be still disposed and so not providing useful informations. To avoid this, once a device has been added/removed from the seat, we queue ClutterDeviceEvent events to inform the stack that the device state has changed, preserving the order with the other actual generated device events. In this way it can't happen that we emit another event before that the device has been added or after that it has been removed. Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1345
This commit is contained in:
parent
cf67c54f87
commit
9db289b4ae
@ -654,8 +654,6 @@ add_device (MetaSeatX11 *seat_x11,
|
|||||||
info->attachment == seat_x11->keyboard_id))
|
info->attachment == seat_x11->keyboard_id))
|
||||||
{
|
{
|
||||||
seat_x11->devices = g_list_prepend (seat_x11->devices, device);
|
seat_x11->devices = g_list_prepend (seat_x11->devices, device);
|
||||||
seat_x11->has_touchscreens |=
|
|
||||||
clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -679,13 +677,9 @@ add_device (MetaSeatX11 *seat_x11,
|
|||||||
GINT_TO_POINTER (info->attachment));
|
GINT_TO_POINTER (info->attachment));
|
||||||
_clutter_input_device_set_associated_device (device, master);
|
_clutter_input_device_set_associated_device (device, master);
|
||||||
_clutter_input_device_add_slave (master, device);
|
_clutter_input_device_add_slave (master, device);
|
||||||
|
|
||||||
g_signal_emit_by_name (seat_x11, "device-added", device);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_touch_mode (seat_x11);
|
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,44 +698,51 @@ has_touchscreens (MetaSeatX11 *seat_x11)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_device (MetaSeatX11 *seat_x11,
|
remove_device (MetaSeatX11 *seat_x11,
|
||||||
int device_id)
|
ClutterInputDevice *device)
|
||||||
{
|
{
|
||||||
ClutterInputDevice *device;
|
if (seat_x11->core_pointer == device)
|
||||||
gboolean check_touchscreens = FALSE;
|
|
||||||
|
|
||||||
device = g_hash_table_lookup (seat_x11->devices_by_id,
|
|
||||||
GINT_TO_POINTER (device_id));
|
|
||||||
|
|
||||||
if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE)
|
|
||||||
check_touchscreens = TRUE;
|
|
||||||
|
|
||||||
if (device != NULL)
|
|
||||||
{
|
{
|
||||||
if (seat_x11->core_pointer == device)
|
seat_x11->core_pointer = NULL;
|
||||||
{
|
}
|
||||||
seat_x11->core_pointer = NULL;
|
else if (seat_x11->core_keyboard == device)
|
||||||
}
|
{
|
||||||
else if (seat_x11->core_keyboard == device)
|
seat_x11->core_keyboard = NULL;
|
||||||
{
|
}
|
||||||
seat_x11->core_keyboard = NULL;
|
else
|
||||||
}
|
{
|
||||||
else
|
seat_x11->devices = g_list_remove (seat_x11->devices, device);
|
||||||
{
|
}
|
||||||
seat_x11->devices = g_list_remove (seat_x11->devices, device);
|
}
|
||||||
g_signal_emit_by_name (seat_x11, "device-removed", device);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_run_dispose (G_OBJECT (device));
|
static gboolean
|
||||||
g_hash_table_remove (seat_x11->devices_by_id,
|
meta_seat_x11_handle_device_event (ClutterSeat *seat,
|
||||||
GINT_TO_POINTER (device_id));
|
ClutterEvent *event)
|
||||||
|
{
|
||||||
|
MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
|
||||||
|
ClutterInputDevice *device = event->device.device;
|
||||||
|
gboolean is_touch;
|
||||||
|
|
||||||
|
is_touch =
|
||||||
|
clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE;
|
||||||
|
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
case CLUTTER_DEVICE_ADDED:
|
||||||
|
seat_x11->has_touchscreens |= is_touch;
|
||||||
|
break;
|
||||||
|
case CLUTTER_DEVICE_REMOVED:
|
||||||
|
if (is_touch)
|
||||||
|
seat_x11->has_touchscreens = has_touchscreens (seat_x11);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_touchscreens)
|
if (is_touch)
|
||||||
{
|
update_touch_mode (seat_x11);
|
||||||
seat_x11->has_touchscreens = has_touchscreens (seat_x11);
|
|
||||||
update_touch_mode (seat_x11);
|
return TRUE;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -803,12 +804,14 @@ device_get_tool_serial (ClutterInputDevice *device)
|
|||||||
return serial_id;
|
return serial_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
translate_hierarchy_event (ClutterBackend *backend,
|
translate_hierarchy_event (ClutterBackend *backend,
|
||||||
MetaSeatX11 *seat_x11,
|
MetaSeatX11 *seat_x11,
|
||||||
XIHierarchyEvent *ev)
|
XIHierarchyEvent *ev,
|
||||||
|
ClutterEvent *event)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
gboolean retval = FALSE;
|
||||||
|
|
||||||
for (i = 0; i < ev->num_info; i++)
|
for (i = 0; i < ev->num_info; i++)
|
||||||
{
|
{
|
||||||
@ -828,15 +831,38 @@ translate_hierarchy_event (ClutterBackend *backend,
|
|||||||
clutter_x11_untrap_x_errors ();
|
clutter_x11_untrap_x_errors ();
|
||||||
if (info != NULL)
|
if (info != NULL)
|
||||||
{
|
{
|
||||||
add_device (seat_x11, backend, &info[0], FALSE);
|
ClutterInputDevice *device;
|
||||||
|
|
||||||
|
device = add_device (seat_x11, backend, &info[0], FALSE);
|
||||||
|
|
||||||
|
event->any.type = CLUTTER_DEVICE_ADDED;
|
||||||
|
event->any.time = ev->time;
|
||||||
|
clutter_event_set_device (event, device);
|
||||||
|
|
||||||
|
retval = TRUE;
|
||||||
XIFreeDeviceInfo (info);
|
XIFreeDeviceInfo (info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ev->info[i].flags & XIDeviceDisabled)
|
else if (ev->info[i].flags & XIDeviceDisabled)
|
||||||
{
|
{
|
||||||
|
g_autoptr (ClutterInputDevice) device = NULL;
|
||||||
g_debug ("Hierarchy event: device disabled");
|
g_debug ("Hierarchy event: device disabled");
|
||||||
|
|
||||||
remove_device (seat_x11, ev->info[i].deviceid);
|
g_hash_table_steal_extended (seat_x11->devices_by_id,
|
||||||
|
GINT_TO_POINTER (ev->info[i].deviceid),
|
||||||
|
NULL,
|
||||||
|
(gpointer) &device);
|
||||||
|
|
||||||
|
if (device != NULL)
|
||||||
|
{
|
||||||
|
remove_device (seat_x11, device);
|
||||||
|
|
||||||
|
event->any.type = CLUTTER_DEVICE_REMOVED;
|
||||||
|
event->any.time = ev->time;
|
||||||
|
clutter_event_set_device (event, device);
|
||||||
|
|
||||||
|
retval = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ((ev->info[i].flags & XISlaveAttached) ||
|
else if ((ev->info[i].flags & XISlaveAttached) ||
|
||||||
(ev->info[i].flags & XISlaveDetached))
|
(ev->info[i].flags & XISlaveDetached))
|
||||||
@ -883,6 +909,8 @@ translate_hierarchy_event (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1115,6 +1143,9 @@ get_event_stage (MetaSeatX11 *seat_x11,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case XI_HierarchyChanged:
|
||||||
|
return CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ()));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1570,6 +1601,7 @@ meta_seat_x11_class_init (MetaSeatX11Class *klass)
|
|||||||
seat_class->create_virtual_device = meta_seat_x11_create_virtual_device;
|
seat_class->create_virtual_device = meta_seat_x11_create_virtual_device;
|
||||||
seat_class->get_supported_virtual_device_types = meta_seat_x11_get_supported_virtual_device_types;
|
seat_class->get_supported_virtual_device_types = meta_seat_x11_get_supported_virtual_device_types;
|
||||||
seat_class->warp_pointer = meta_seat_x11_warp_pointer;
|
seat_class->warp_pointer = meta_seat_x11_warp_pointer;
|
||||||
|
seat_class->handle_device_event = meta_seat_x11_handle_device_event;
|
||||||
|
|
||||||
props[PROP_OPCODE] =
|
props[PROP_OPCODE] =
|
||||||
g_param_spec_int ("opcode",
|
g_param_spec_int ("opcode",
|
||||||
@ -1672,8 +1704,7 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(xi_event->evtype == XI_HierarchyChanged ||
|
if (!(xi_event->evtype == XI_DeviceChanged ||
|
||||||
xi_event->evtype == XI_DeviceChanged ||
|
|
||||||
xi_event->evtype == XI_PropertyEvent))
|
xi_event->evtype == XI_PropertyEvent))
|
||||||
{
|
{
|
||||||
stage = get_event_stage (seat, xi_event);
|
stage = get_event_stage (seat, xi_event);
|
||||||
@ -1691,9 +1722,8 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
|||||||
{
|
{
|
||||||
XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event;
|
XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event;
|
||||||
|
|
||||||
translate_hierarchy_event (backend, seat, xev);
|
retval = translate_hierarchy_event (backend, seat, xev, event);
|
||||||
}
|
}
|
||||||
retval = FALSE;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XI_DeviceChanged:
|
case XI_DeviceChanged:
|
||||||
|
Loading…
Reference in New Issue
Block a user