const struct libinput_interface *interface;
const struct libinput_interface_backend *interface_backend;
void *user_data;
+ int refcount;
};
typedef void (*libinput_seat_destroy_func) (struct libinput_seat *seat);
libinput->interface = interface;
libinput->interface_backend = interface_backend;
libinput->user_data = user_data;
+ libinput->refcount = 1;
list_init(&libinput->source_destroy_list);
list_init(&libinput->seat_list);
list_init(&libinput->source_destroy_list);
}
-LIBINPUT_EXPORT void
-libinput_destroy(struct libinput *libinput)
+LIBINPUT_EXPORT struct libinput *
+libinput_ref(struct libinput *libinput)
+{
+ libinput->refcount++;
+ return libinput;
+}
+
+LIBINPUT_EXPORT struct libinput *
+libinput_unref(struct libinput *libinput)
{
struct libinput_event *event;
struct libinput_device *device, *next_device;
struct libinput_seat *seat, *next_seat;
if (libinput == NULL)
- return;
+ return NULL;
+
+ assert(libinput->refcount > 0);
+ libinput->refcount--;
+ if (libinput->refcount > 0)
+ return libinput;
libinput_suspend(libinput);
libinput_drop_destroyed_sources(libinput);
close(libinput->epoll_fd);
free(libinput);
+
+ return NULL;
}
LIBINPUT_EXPORT void
* device are ignored. Such devices and those that failed to open
* ignored until the next call to libinput_resume().
*
+ * The reference count of the context is initialized to 1. See @ref
+ * libinput_unref.
+ *
* @param interface The callback interface
* @param user_data Caller-specific data passed to the various callback
* interfaces.
* The context is fully initialized but will not generate events until at
* least one device has been added.
*
+ * The reference count of the context is initialized to 1. See @ref
+ * libinput_unref.
+ *
* @param interface The callback interface
* @param user_data Caller-specific data passed to the various callback
* interfaces.
/**
* @ingroup base
*
- * Destroy the libinput context. After this, object references associated with
- * the destroyed context are invalid and may not be interacted with.
+ * Add a reference to the context. A context is destroyed whenever the
+ * reference count reaches 0. See @ref libinput_unref.
+ *
+ * @param libinput A previously initialized valid libinput context
+ * @return The passed libinput context
+ */
+struct libinput *
+libinput_ref(struct libinput *libinput);
+
+/**
+ * @ingroup base
+ *
+ * Dereference the libinput context. After this, the context may have been
+ * destroyed, if the last reference was dereferenced. If so, the context is
+ * invalid and may not be interacted with.
*
* @param libinput A previously initialized libinput context
+ * @return NULL if context was destroyed otherwise the passed context
*/
-void
-libinput_destroy(struct libinput *libinput);
+struct libinput *
+libinput_unref(struct libinput *libinput);
/**
* @ingroup base
if (udev_input_enable(&input->base) < 0) {
udev_unref(udev);
- libinput_destroy(&input->base);
+ libinput_unref(&input->base);
free(input);
return NULL;
}
for (i = 0; i < num_devices; ++i)
litest_delete_device(devices[i]);
- libinput_destroy(libinput);
+ libinput_unref(libinput);
}
END_TEST
libinput_device_unref(d->libinput_device);
if (d->owns_context)
- libinput_destroy(d->libinput);
+ libinput_unref(d->libinput);
libevdev_free(d->evdev);
libevdev_uinput_destroy(d->uinput);
memset(d,0, sizeof(*d));
ck_assert_int_gt(log_handler_called, 0);
log_handler_called = 0;
- libinput_destroy(li);
+ libinput_unref(li);
libinput_log_set_priority(pri);
}
END_TEST
ck_assert_int_gt(log_handler_called, 0);
log_handler_called = 0;
- libinput_destroy(li);
+ libinput_unref(li);
libinput_log_set_priority(pri);
}
ck_assert_int_gt(log_handler_called, 0);
log_handler_called = 0;
- libinput_destroy(li);
+ libinput_unref(li);
libinput_log_set_priority(pri);
}
END_TEST
log_handler_called = 0;
libinput_log_set_handler(simple_log_handler, NULL);
- libinput_destroy(li);
+ libinput_unref(li);
libinput_log_set_priority(pri);
}
END_TEST
log_handler_called = 0;
- libinput_destroy(li);
+ libinput_unref(li);
libinput_log_set_priority(pri);
}
END_TEST
libinput_event_destroy(event);
}
- libinput_destroy(li);
+ libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(device_added, 0);
libinput_event_destroy(event);
}
- libinput_destroy(li);
+ libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(motion, 0);
libinput_event_destroy(event);
}
- libinput_destroy(li);
+ libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(motion, 0);
libinput_event_destroy(event);
}
- libinput_destroy(li);
+ libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(key, 0);
libinput_event_destroy(event);
}
- libinput_destroy(li);
+ libinput_unref(li);
libevdev_uinput_destroy(uinput);
ck_assert_int_gt(touch, 0);
ck_assert(li == NULL);
li = libinput_path_create_context(&simple_interface, NULL);
ck_assert(li != NULL);
- libinput_destroy(li);
+ libinput_unref(li);
ck_assert_int_eq(open_func_count, 0);
ck_assert_int_eq(close_func_count, 0);
ck_assert_int_eq(open_func_count, 0);
ck_assert_int_eq(close_func_count, 0);
- libinput_destroy(li);
+ libinput_unref(li);
ck_assert_int_eq(close_func_count, 0);
open_func_count = 0;
ck_assert_int_eq(open_func_count, 1);
libevdev_uinput_destroy(uinput);
- libinput_destroy(li);
+ libinput_unref(li);
ck_assert_int_eq(close_func_count, 1);
open_func_count = 0;
libinput_resume(li);
libevdev_uinput_destroy(uinput);
- libinput_destroy(li);
+ libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
libinput_resume(li);
libevdev_uinput_destroy(uinput);
- libinput_destroy(li);
+ libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
libinput_resume(li);
libevdev_uinput_destroy(uinput);
- libinput_destroy(li);
+ libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
libevdev_uinput_destroy(uinput1);
libevdev_uinput_destroy(uinput2);
- libinput_destroy(li);
+ libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
ck_assert_int_eq(nevents, 2);
libevdev_uinput_destroy(uinput2);
- libinput_destroy(li);
+ libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
ck_assert_int_eq(nevents, 1);
libevdev_uinput_destroy(uinput1);
- libinput_destroy(li);
+ libinput_unref(li);
open_func_count = 0;
close_func_count = 0;
ck_assert(found == 1);
- libinput_destroy(li);
+ libinput_unref(li);
libevdev_uinput_destroy(uinput);
}
for (i = 0; i < num_devices; ++i)
litest_delete_device(devices[i]);
- libinput_destroy(libinput);
+ libinput_unref(libinput);
}
END_TEST
ck_assert(event != NULL);
libinput_event_destroy(event);
- libinput_destroy(li);
+ libinput_unref(li);
udev_unref(udev);
}
END_TEST
ck_assert(event == NULL);
libinput_event_destroy(event);
- libinput_destroy(li);
+ libinput_unref(li);
udev_unref(udev);
}
END_TEST
ck_assert(default_seat_found);
- libinput_destroy(li);
+ libinput_unref(li);
udev_unref(udev);
}
END_TEST
libinput_resume(li);
libinput_event_destroy(event);
- libinput_destroy(li);
+ libinput_unref(li);
udev_unref(udev);
}
END_TEST
libinput_resume(li);
libinput_event_destroy(event);
- libinput_destroy(li);
+ libinput_unref(li);
udev_unref(udev);
}
END_TEST
process_events_count_devices(li, &num_devices);
ck_assert_int_gt(num_devices, 0);
- libinput_destroy(li);
+ libinput_unref(li);
udev_unref(udev);
}
END_TEST
libinput_event_destroy(ev);
}
- libinput_destroy(li);
+ libinput_unref(li);
udev_unref(udev);
}
END_TEST
ck_assert(found == 1);
- libinput_destroy(li);
+ libinput_unref(li);
udev_unref(udev);
}
END_TEST
device = libinput_path_add_device(*li, path);
if (!device) {
fprintf(stderr, "Failed to initialized device %s\n", path);
- libinput_destroy(*li);
+ libinput_unref(*li);
return 1;
}
mainloop(li);
- libinput_destroy(li);
+ libinput_unref(li);
if (udev)
udev_unref(udev);
gtk_main();
- libinput_destroy(li);
+ libinput_unref(li);
udev_unref(udev);
return 0;