|
|
79df40 |
From dfd79cf19dcebf283bd884dded8efc83e449016d Mon Sep 17 00:00:00 2001
|
|
|
79df40 |
From: Olivier Fourdan <ofourdan@redhat.com>
|
|
|
79df40 |
Date: Mon, 19 Nov 2018 11:25:57 +0100
|
|
|
79df40 |
Subject: [PATCH 07/28] clutter: Keep a device reference with events
|
|
|
79df40 |
|
|
|
79df40 |
If a device (virtual or real) is removed while there are remaining
|
|
|
79df40 |
events queued for that device, the event loop may try to access the
|
|
|
79df40 |
event freed memory.
|
|
|
79df40 |
|
|
|
79df40 |
To avoid the issue, add a reference to the device when the event is
|
|
|
79df40 |
created or copied, and remove the reference once the device is freed.
|
|
|
79df40 |
|
|
|
79df40 |
Closes: https://gitlab.gnome.org/GNOME/mutter/issues/393
|
|
|
79df40 |
---
|
|
|
79df40 |
clutter/clutter/clutter-event.c | 16 ++++++++++++----
|
|
|
79df40 |
1 file changed, 12 insertions(+), 4 deletions(-)
|
|
|
79df40 |
|
|
|
79df40 |
diff --git a/clutter/clutter/clutter-event.c b/clutter/clutter/clutter-event.c
|
|
|
79df40 |
index 10b6c0082..1b21b6a97 100644
|
|
|
79df40 |
--- a/clutter/clutter/clutter-event.c
|
|
|
79df40 |
+++ b/clutter/clutter/clutter-event.c
|
|
|
79df40 |
@@ -1068,61 +1068,61 @@ clutter_event_get_device_type (const ClutterEvent *event)
|
|
|
79df40 |
|
|
|
79df40 |
g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE);
|
|
|
79df40 |
|
|
|
79df40 |
device = clutter_event_get_device (event);
|
|
|
79df40 |
if (device != NULL)
|
|
|
79df40 |
return clutter_input_device_get_device_type (device);
|
|
|
79df40 |
|
|
|
79df40 |
return CLUTTER_POINTER_DEVICE;
|
|
|
79df40 |
}
|
|
|
79df40 |
|
|
|
79df40 |
/**
|
|
|
79df40 |
* clutter_event_set_device:
|
|
|
79df40 |
* @event: a #ClutterEvent
|
|
|
79df40 |
* @device: (allow-none): a #ClutterInputDevice, or %NULL
|
|
|
79df40 |
*
|
|
|
79df40 |
* Sets the device for @event.
|
|
|
79df40 |
*
|
|
|
79df40 |
* Since: 1.6
|
|
|
79df40 |
*/
|
|
|
79df40 |
void
|
|
|
79df40 |
clutter_event_set_device (ClutterEvent *event,
|
|
|
79df40 |
ClutterInputDevice *device)
|
|
|
79df40 |
{
|
|
|
79df40 |
g_return_if_fail (event != NULL);
|
|
|
79df40 |
g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
|
|
|
79df40 |
|
|
|
79df40 |
if (is_event_allocated (event))
|
|
|
79df40 |
{
|
|
|
79df40 |
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
|
|
79df40 |
|
|
|
79df40 |
- real_event->device = device;
|
|
|
79df40 |
+ g_set_object (&real_event->device, device);
|
|
|
79df40 |
}
|
|
|
79df40 |
|
|
|
79df40 |
switch (event->type)
|
|
|
79df40 |
{
|
|
|
79df40 |
case CLUTTER_NOTHING:
|
|
|
79df40 |
case CLUTTER_STAGE_STATE:
|
|
|
79df40 |
case CLUTTER_DESTROY_NOTIFY:
|
|
|
79df40 |
case CLUTTER_CLIENT_MESSAGE:
|
|
|
79df40 |
case CLUTTER_DELETE:
|
|
|
79df40 |
case CLUTTER_EVENT_LAST:
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
case CLUTTER_ENTER:
|
|
|
79df40 |
case CLUTTER_LEAVE:
|
|
|
79df40 |
event->crossing.device = device;
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
case CLUTTER_BUTTON_PRESS:
|
|
|
79df40 |
case CLUTTER_BUTTON_RELEASE:
|
|
|
79df40 |
event->button.device = device;
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
case CLUTTER_MOTION:
|
|
|
79df40 |
event->motion.device = device;
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
case CLUTTER_SCROLL:
|
|
|
79df40 |
event->scroll.device = device;
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
@@ -1337,62 +1337,62 @@ clutter_event_new (ClutterEventType type)
|
|
|
79df40 |
return new_event;
|
|
|
79df40 |
}
|
|
|
79df40 |
|
|
|
79df40 |
/**
|
|
|
79df40 |
* clutter_event_copy:
|
|
|
79df40 |
* @event: A #ClutterEvent.
|
|
|
79df40 |
*
|
|
|
79df40 |
* Copies @event.
|
|
|
79df40 |
*
|
|
|
79df40 |
* Return value: (transfer full): A newly allocated #ClutterEvent
|
|
|
79df40 |
*/
|
|
|
79df40 |
ClutterEvent *
|
|
|
79df40 |
clutter_event_copy (const ClutterEvent *event)
|
|
|
79df40 |
{
|
|
|
79df40 |
ClutterEvent *new_event;
|
|
|
79df40 |
ClutterEventPrivate *new_real_event;
|
|
|
79df40 |
ClutterInputDevice *device;
|
|
|
79df40 |
gint n_axes = 0;
|
|
|
79df40 |
|
|
|
79df40 |
g_return_val_if_fail (event != NULL, NULL);
|
|
|
79df40 |
|
|
|
79df40 |
new_event = clutter_event_new (CLUTTER_NOTHING);
|
|
|
79df40 |
new_real_event = (ClutterEventPrivate *) new_event;
|
|
|
79df40 |
|
|
|
79df40 |
*new_event = *event;
|
|
|
79df40 |
|
|
|
79df40 |
if (is_event_allocated (event))
|
|
|
79df40 |
{
|
|
|
79df40 |
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
|
|
79df40 |
|
|
|
79df40 |
- new_real_event->device = real_event->device;
|
|
|
79df40 |
- new_real_event->source_device = real_event->source_device;
|
|
|
79df40 |
+ g_set_object (&new_real_event->device, real_event->device);
|
|
|
79df40 |
+ g_set_object (&new_real_event->source_device, real_event->source_device);
|
|
|
79df40 |
new_real_event->delta_x = real_event->delta_x;
|
|
|
79df40 |
new_real_event->delta_y = real_event->delta_y;
|
|
|
79df40 |
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
|
|
|
79df40 |
new_real_event->base_state = real_event->base_state;
|
|
|
79df40 |
new_real_event->button_state = real_event->button_state;
|
|
|
79df40 |
new_real_event->latched_state = real_event->latched_state;
|
|
|
79df40 |
new_real_event->locked_state = real_event->locked_state;
|
|
|
79df40 |
new_real_event->tool = real_event->tool;
|
|
|
79df40 |
}
|
|
|
79df40 |
|
|
|
79df40 |
device = clutter_event_get_device (event);
|
|
|
79df40 |
if (device != NULL)
|
|
|
79df40 |
n_axes = clutter_input_device_get_n_axes (device);
|
|
|
79df40 |
|
|
|
79df40 |
switch (event->type)
|
|
|
79df40 |
{
|
|
|
79df40 |
case CLUTTER_BUTTON_PRESS:
|
|
|
79df40 |
case CLUTTER_BUTTON_RELEASE:
|
|
|
79df40 |
if (event->button.axes != NULL)
|
|
|
79df40 |
new_event->button.axes = g_memdup (event->button.axes,
|
|
|
79df40 |
sizeof (gdouble) * n_axes);
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
case CLUTTER_SCROLL:
|
|
|
79df40 |
if (event->scroll.axes != NULL)
|
|
|
79df40 |
new_event->scroll.axes = g_memdup (event->scroll.axes,
|
|
|
79df40 |
sizeof (gdouble) * n_axes);
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
case CLUTTER_MOTION:
|
|
|
79df40 |
@@ -1408,60 +1408,68 @@ clutter_event_copy (const ClutterEvent *event)
|
|
|
79df40 |
if (event->touch.axes != NULL)
|
|
|
79df40 |
new_event->touch.axes = g_memdup (event->touch.axes,
|
|
|
79df40 |
sizeof (gdouble) * n_axes);
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
default:
|
|
|
79df40 |
break;
|
|
|
79df40 |
}
|
|
|
79df40 |
|
|
|
79df40 |
if (is_event_allocated (event))
|
|
|
79df40 |
_clutter_backend_copy_event_data (clutter_get_default_backend (),
|
|
|
79df40 |
event,
|
|
|
79df40 |
new_event);
|
|
|
79df40 |
|
|
|
79df40 |
return new_event;
|
|
|
79df40 |
}
|
|
|
79df40 |
|
|
|
79df40 |
/**
|
|
|
79df40 |
* clutter_event_free:
|
|
|
79df40 |
* @event: A #ClutterEvent.
|
|
|
79df40 |
*
|
|
|
79df40 |
* Frees all resources used by @event.
|
|
|
79df40 |
*/
|
|
|
79df40 |
void
|
|
|
79df40 |
clutter_event_free (ClutterEvent *event)
|
|
|
79df40 |
{
|
|
|
79df40 |
if (G_LIKELY (event != NULL))
|
|
|
79df40 |
{
|
|
|
79df40 |
_clutter_backend_free_event_data (clutter_get_default_backend (), event);
|
|
|
79df40 |
|
|
|
79df40 |
+ if (is_event_allocated (event))
|
|
|
79df40 |
+ {
|
|
|
79df40 |
+ ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
|
|
79df40 |
+
|
|
|
79df40 |
+ g_clear_object (&real_event->device);
|
|
|
79df40 |
+ g_clear_object (&real_event->source_device);
|
|
|
79df40 |
+ }
|
|
|
79df40 |
+
|
|
|
79df40 |
switch (event->type)
|
|
|
79df40 |
{
|
|
|
79df40 |
case CLUTTER_BUTTON_PRESS:
|
|
|
79df40 |
case CLUTTER_BUTTON_RELEASE:
|
|
|
79df40 |
g_free (event->button.axes);
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
case CLUTTER_MOTION:
|
|
|
79df40 |
g_free (event->motion.axes);
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
case CLUTTER_SCROLL:
|
|
|
79df40 |
g_free (event->scroll.axes);
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
case CLUTTER_TOUCH_BEGIN:
|
|
|
79df40 |
case CLUTTER_TOUCH_UPDATE:
|
|
|
79df40 |
case CLUTTER_TOUCH_END:
|
|
|
79df40 |
case CLUTTER_TOUCH_CANCEL:
|
|
|
79df40 |
g_free (event->touch.axes);
|
|
|
79df40 |
break;
|
|
|
79df40 |
|
|
|
79df40 |
default:
|
|
|
79df40 |
break;
|
|
|
79df40 |
}
|
|
|
79df40 |
|
|
|
79df40 |
g_hash_table_remove (all_events, event);
|
|
|
79df40 |
g_slice_free (ClutterEventPrivate, (ClutterEventPrivate *) event);
|
|
|
79df40 |
}
|
|
|
79df40 |
}
|
|
|
79df40 |
@@ -1662,61 +1670,61 @@ clutter_event_get_source_device (const ClutterEvent *event)
|
|
|
79df40 |
if (real_event->source_device != NULL)
|
|
|
79df40 |
return real_event->source_device;
|
|
|
79df40 |
|
|
|
79df40 |
return clutter_event_get_device (event);
|
|
|
79df40 |
}
|
|
|
79df40 |
|
|
|
79df40 |
/**
|
|
|
79df40 |
* clutter_event_set_source_device:
|
|
|
79df40 |
* @event: a #ClutterEvent
|
|
|
79df40 |
* @device: (allow-none): a #ClutterInputDevice
|
|
|
79df40 |
*
|
|
|
79df40 |
* Sets the source #ClutterInputDevice for @event.
|
|
|
79df40 |
*
|
|
|
79df40 |
* The #ClutterEvent must have been created using clutter_event_new().
|
|
|
79df40 |
*
|
|
|
79df40 |
* Since: 1.8
|
|
|
79df40 |
*/
|
|
|
79df40 |
void
|
|
|
79df40 |
clutter_event_set_source_device (ClutterEvent *event,
|
|
|
79df40 |
ClutterInputDevice *device)
|
|
|
79df40 |
{
|
|
|
79df40 |
ClutterEventPrivate *real_event;
|
|
|
79df40 |
|
|
|
79df40 |
g_return_if_fail (event != NULL);
|
|
|
79df40 |
g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
|
|
|
79df40 |
|
|
|
79df40 |
if (!is_event_allocated (event))
|
|
|
79df40 |
return;
|
|
|
79df40 |
|
|
|
79df40 |
real_event = (ClutterEventPrivate *) event;
|
|
|
79df40 |
- real_event->source_device = device;
|
|
|
79df40 |
+ g_set_object (&real_event->source_device, device);
|
|
|
79df40 |
}
|
|
|
79df40 |
|
|
|
79df40 |
/**
|
|
|
79df40 |
* clutter_event_get_axes:
|
|
|
79df40 |
* @event: a #ClutterEvent
|
|
|
79df40 |
* @n_axes: (out): return location for the number of axes returned
|
|
|
79df40 |
*
|
|
|
79df40 |
* Retrieves the array of axes values attached to the event.
|
|
|
79df40 |
*
|
|
|
79df40 |
* Return value: (transfer none): an array of axis values
|
|
|
79df40 |
*
|
|
|
79df40 |
* Since: 1.6
|
|
|
79df40 |
*/
|
|
|
79df40 |
gdouble *
|
|
|
79df40 |
clutter_event_get_axes (const ClutterEvent *event,
|
|
|
79df40 |
guint *n_axes)
|
|
|
79df40 |
{
|
|
|
79df40 |
gdouble *retval = NULL;
|
|
|
79df40 |
guint len = 0;
|
|
|
79df40 |
|
|
|
79df40 |
switch (event->type)
|
|
|
79df40 |
{
|
|
|
79df40 |
case CLUTTER_NOTHING:
|
|
|
79df40 |
case CLUTTER_STAGE_STATE:
|
|
|
79df40 |
case CLUTTER_DESTROY_NOTIFY:
|
|
|
79df40 |
case CLUTTER_CLIENT_MESSAGE:
|
|
|
79df40 |
case CLUTTER_DELETE:
|
|
|
79df40 |
case CLUTTER_ENTER:
|
|
|
79df40 |
case CLUTTER_LEAVE:
|
|
|
79df40 |
case CLUTTER_KEY_PRESS:
|
|
|
79df40 |
--
|
|
|
79df40 |
2.26.2
|
|
|
79df40 |
|