mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-26 02:50:06 +01:00
Reference count event target struct when applicable
If the target of an event is a reference counted object, such as libinput_seat and libinput_device, make events own its own reference to the object, releasing it when destroyed. In order to do this, a new API requirement and function are introduced; libinput_event_destroy(). The user is required to use libinput_event_destroy() instead of free() after having retrieved an event using libinput_get_event(). This fixes a race that would be triggered if a device or seat would be added and removed before the user calling libinput_get_event(). Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
This commit is contained in:
parent
5836054306
commit
758e553645
2 changed files with 75 additions and 1 deletions
|
|
@ -35,6 +35,12 @@
|
|||
#include "evdev.h"
|
||||
#include "udev-seat.h"
|
||||
|
||||
enum libinput_event_class {
|
||||
LIBINPUT_EVENT_CLASS_BASE,
|
||||
LIBINPUT_EVENT_CLASS_SEAT,
|
||||
LIBINPUT_EVENT_CLASS_DEVICE,
|
||||
};
|
||||
|
||||
struct libinput_source {
|
||||
libinput_source_dispatch_t dispatch;
|
||||
void *user_data;
|
||||
|
|
@ -116,6 +122,48 @@ libinput_destroy(struct libinput *libinput)
|
|||
free(libinput);
|
||||
}
|
||||
|
||||
static enum libinput_event_class
|
||||
libinput_event_get_class(struct libinput_event *event)
|
||||
{
|
||||
switch (event->type) {
|
||||
case LIBINPUT_EVENT_ADDED_SEAT:
|
||||
case LIBINPUT_EVENT_REMOVED_SEAT:
|
||||
case LIBINPUT_EVENT_ADDED_DEVICE:
|
||||
case LIBINPUT_EVENT_REMOVED_DEVICE:
|
||||
return LIBINPUT_EVENT_CLASS_BASE;
|
||||
|
||||
case LIBINPUT_EVENT_DEVICE_REGISTER_CAPABILITY:
|
||||
case LIBINPUT_EVENT_DEVICE_UNREGISTER_CAPABILITY:
|
||||
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION:
|
||||
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
|
||||
case LIBINPUT_EVENT_POINTER_BUTTON:
|
||||
case LIBINPUT_EVENT_POINTER_AXIS:
|
||||
case LIBINPUT_EVENT_TOUCH_TOUCH:
|
||||
return LIBINPUT_EVENT_CLASS_DEVICE;
|
||||
}
|
||||
|
||||
/* We should never end up here. */
|
||||
abort();
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT void
|
||||
libinput_event_destroy(struct libinput_event *event)
|
||||
{
|
||||
switch (libinput_event_get_class(event)) {
|
||||
case LIBINPUT_EVENT_CLASS_BASE:
|
||||
break;
|
||||
case LIBINPUT_EVENT_CLASS_SEAT:
|
||||
libinput_seat_unref(event->target.seat);
|
||||
break;
|
||||
case LIBINPUT_EVENT_CLASS_DEVICE:
|
||||
libinput_device_unref(event->target.device);
|
||||
break;
|
||||
}
|
||||
|
||||
free(event);
|
||||
}
|
||||
|
||||
int
|
||||
open_restricted(struct libinput *libinput,
|
||||
const char *path, int flags)
|
||||
|
|
@ -546,6 +594,17 @@ libinput_post_event(struct libinput *libinput,
|
|||
libinput->events_len = events_len;
|
||||
}
|
||||
|
||||
switch (libinput_event_get_class(event)) {
|
||||
case LIBINPUT_EVENT_CLASS_BASE:
|
||||
break;
|
||||
case LIBINPUT_EVENT_CLASS_SEAT:
|
||||
libinput_seat_ref(event->target.seat);
|
||||
break;
|
||||
case LIBINPUT_EVENT_CLASS_DEVICE:
|
||||
libinput_device_ref(event->target.device);
|
||||
break;
|
||||
}
|
||||
|
||||
libinput->events_count = events_count;
|
||||
events[libinput->events_in] = event;
|
||||
libinput->events_in = (libinput->events_in + 1) % libinput->events_len;
|
||||
|
|
|
|||
|
|
@ -296,7 +296,8 @@ libinput_dispatch(struct libinput *libinput);
|
|||
*
|
||||
* Retrieve the next event from libinput's internal event queue.
|
||||
*
|
||||
* After handling the retrieved event, the caller must free it using free().
|
||||
* After handling the retrieved event, the caller must destroy it using
|
||||
* libinput_event_destroy().
|
||||
*
|
||||
* @param libinput A previously initialized libinput context
|
||||
* @return The next available event, or NULL if no event is available.
|
||||
|
|
@ -350,6 +351,20 @@ libinput_suspend(struct libinput *libinput);
|
|||
void
|
||||
libinput_destroy(struct libinput *libinput);
|
||||
|
||||
/**
|
||||
* @defgroup event Acessing and destruction of events
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup event
|
||||
*
|
||||
* Destroy the event.
|
||||
*
|
||||
* @param event An event retrieved by libinput_get_event().
|
||||
*/
|
||||
void
|
||||
libinput_event_destroy(struct libinput_event *event);
|
||||
|
||||
/**
|
||||
* @defgroup seat Initialization and manipulation of seats
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue