diff --git a/meson.build b/meson.build index f9ddadd8b..e54bb0514 100644 --- a/meson.build +++ b/meson.build @@ -215,7 +215,7 @@ src_libinput_util = [ ] libinput_util = static_library('libinput-util', src_libinput_util, - dependencies : [dep_udev, dep_libevdev], + dependencies : [dep_udev, dep_libevdev, dep_libwacom], include_directories : includes_include) dep_libinput_util = declare_dependency(link_with : libinput_util) @@ -233,7 +233,7 @@ src_libfilter = [ 'src/filter-private.h' ] libfilter = static_library('filter', src_libfilter, - dependencies : dep_udev, + dependencies : [dep_udev, dep_libwacom], include_directories : includes_include) dep_libfilter = declare_dependency(link_with : libfilter) @@ -290,7 +290,7 @@ src_libquirks = [ 'src/builddir.h', ] -deps_libquirks = [dep_udev, dep_libinput_util] +deps_libquirks = [dep_udev, dep_libwacom, dep_libinput_util] libquirks = static_library('quirks', src_libquirks, dependencies : deps_libquirks, include_directories : includes_include) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index edac4fbde..e293fe877 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -3851,6 +3851,7 @@ tp_requires_rotation(struct tp_dispatch *tp, struct evdev_device *device) { bool rotate = false; #if HAVE_LIBWACOM + struct libinput *li = tp_libinput_context(tp); WacomDeviceDatabase *db = NULL; WacomDevice **devices = NULL, **d; @@ -3861,12 +3862,9 @@ tp_requires_rotation(struct tp_dispatch *tp, struct evdev_device *device) if ((device->tags & EVDEV_TAG_TABLET_TOUCHPAD) == 0) goto out; - db = libwacom_database_new(); - if (!db) { - evdev_log_info(device, - "Failed to initialize libwacom context.\n"); + db = libinput_libwacom_ref(li); + if (!db) goto out; - } /* Check if we have a device with the same vid/pid. If not, we need to loop through all devices and check their paired @@ -3896,9 +3894,12 @@ tp_requires_rotation(struct tp_dispatch *tp, struct evdev_device *device) } free(devices); + out: + /* We don't need to keep it around for the touchpad, we're done with + * it until the device dies. */ if (db) - libwacom_database_destroy(db); + libinput_libwacom_unref(li); #endif return rotate; diff --git a/src/evdev-tablet-pad-leds.c b/src/evdev-tablet-pad-leds.c index ec01e0e29..b741d0c24 100644 --- a/src/evdev-tablet-pad-leds.c +++ b/src/evdev-tablet-pad-leds.c @@ -490,16 +490,14 @@ static int pad_init_leds_from_libwacom(struct pad_dispatch *pad, struct evdev_device *device) { + struct libinput *li = pad_libinput_context(pad); WacomDeviceDatabase *db = NULL; WacomDevice *wacom = NULL; int rc = 1; - db = libwacom_database_new(); - if (!db) { - evdev_log_info(device, - "Failed to initialize libwacom context.\n"); + db = libinput_libwacom_ref(li); + if (!db) goto out; - } wacom = libwacom_new_from_path(db, udev_device_get_devnode(device->udev_device), @@ -522,7 +520,7 @@ pad_init_leds_from_libwacom(struct pad_dispatch *pad, if (wacom) libwacom_destroy(wacom); if (db) - libwacom_database_destroy(db); + libinput_libwacom_unref(li); if (rc != 0) pad_destroy_leds(pad); diff --git a/src/evdev-tablet-pad.c b/src/evdev-tablet-pad.c index f1cbc4a40..cb02726a7 100644 --- a/src/evdev-tablet-pad.c +++ b/src/evdev-tablet-pad.c @@ -529,17 +529,15 @@ pad_init_buttons_from_libwacom(struct pad_dispatch *pad, { bool rc = false; #if HAVE_LIBWACOM_GET_BUTTON_EVDEV_CODE + struct libinput *li = pad_libinput_context(pad); WacomDeviceDatabase *db = NULL; WacomDevice *tablet = NULL; int num_buttons; int map = 0; - db = libwacom_database_new(); - if (!db) { - evdev_log_info(device, - "Failed to initialize libwacom context.\n"); + db = libinput_libwacom_ref(li); + if (!db) goto out; - } tablet = libwacom_new_from_usbid(db, evdev_device_get_id_vendor(device), @@ -566,7 +564,7 @@ pad_init_buttons_from_libwacom(struct pad_dispatch *pad, if (tablet) libwacom_destroy(tablet); if (db) - libwacom_database_destroy(db); + libinput_libwacom_unref(li); #endif return rc; } diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 4012b1549..fc4982d53 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -913,15 +913,13 @@ tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet, WacomStylusType type; WacomAxisTypeFlags axes; - db = libwacom_database_new(); - if (!db) { - evdev_log_info(tablet->device, - "Failed to initialize libwacom context.\n"); - goto out; - } + db = tablet_libinput_context(tablet)->libwacom.db; + if (!db) + return rc; + s = libwacom_stylus_get_for_id(db, tool->tool_id); if (!s) - goto out; + return rc; type = libwacom_stylus_get_type(s); if (type == WSTYLUS_PUCK) { @@ -965,9 +963,6 @@ tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet, copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE); rc = 0; -out: - if (db) - libwacom_database_destroy(db); #endif return rc; } @@ -1990,6 +1985,7 @@ tablet_destroy(struct evdev_dispatch *dispatch) { struct tablet_dispatch *tablet = tablet_dispatch(dispatch); struct libinput_tablet_tool *tool, *tmp; + struct libinput *li = tablet_libinput_context(tablet); libinput_timer_cancel(&tablet->quirks.prox_out_timer); libinput_timer_destroy(&tablet->quirks.prox_out_timer); @@ -1998,6 +1994,8 @@ tablet_destroy(struct evdev_dispatch *dispatch) libinput_tablet_tool_unref(tool); } + libinput_libwacom_unref(li); + free(tablet); } @@ -2317,6 +2315,9 @@ struct evdev_dispatch * evdev_tablet_create(struct evdev_device *device) { struct tablet_dispatch *tablet; + struct libinput *li = evdev_libinput_context(device); + + libinput_libwacom_ref(li); /* Stop false positives caused by the forced proximity code */ if (getenv("LIBINPUT_RUNNING_TEST_SUITE")) diff --git a/src/evdev.c b/src/evdev.c index a077a87d5..3b0cfaeb1 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -2700,17 +2700,15 @@ evdev_tablet_has_left_handed(struct evdev_device *device) { bool has_left_handed = false; #if HAVE_LIBWACOM - WacomDeviceDatabase *db; + struct libinput *li = evdev_libinput_context(device); + WacomDeviceDatabase *db = NULL; WacomDevice *d = NULL; WacomError *error; const char *devnode; - db = libwacom_database_new(); - if (!db) { - evdev_log_info(device, - "failed to initialize libwacom context.\n"); + db = libinput_libwacom_ref(li); + if (!db) goto out; - } error = libwacom_error_new(); devnode = udev_device_get_devnode(device->udev_device); @@ -2737,7 +2735,8 @@ evdev_tablet_has_left_handed(struct evdev_device *device) libwacom_error_free(&error); if (d) libwacom_destroy(d); - libwacom_database_destroy(db); + if (db) + libinput_libwacom_unref(li); out: #endif diff --git a/src/libinput-private.h b/src/libinput-private.h index 9a0acc54d..13a36b493 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -31,6 +31,10 @@ #include #include +#if HAVE_LIBWACOM +#include +#endif + #include "linux/input.h" #include "libinput.h" @@ -155,6 +159,13 @@ struct libinput { bool quirks_initialized; struct quirks_context *quirks; + +#if HAVE_LIBWACOM + struct { + WacomDeviceDatabase *db; + size_t refcount; + } libwacom; +#endif }; typedef void (*libinput_seat_destroy_func) (struct libinput_seat *seat); @@ -837,4 +848,15 @@ point_in_rect(const struct device_coords *point, point->y < rect->y + rect->h); } +#if HAVE_LIBWACOM +WacomDeviceDatabase * +libinput_libwacom_ref(struct libinput *li); +void +libinput_libwacom_unref(struct libinput *li); +#else +static inline void *libinput_libwacom_ref(struct libinput *li) { return NULL; } +static inline void libinput_libwacom_unref(struct libinput *li) {} +#endif + + #endif /* LIBINPUT_PRIVATE_H */ diff --git a/src/libinput.c b/src/libinput.c index 60286a641..4891736d6 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -4164,3 +4164,37 @@ libinput_device_config_rotation_get_default_angle(struct libinput_device *device return device->config.rotation->get_default_angle(device); } + +#if HAVE_LIBWACOM +WacomDeviceDatabase * +libinput_libwacom_ref(struct libinput *li) +{ + WacomDeviceDatabase *db = NULL; + if (!li->libwacom.db) { + db = libwacom_database_new(); + if (!db) { + log_error(li, + "Failed to initialize libwacom context\n"); + return NULL; + } + + li->libwacom.db = db; + li->libwacom.refcount = 0; + } + + li->libwacom.refcount++; + db = li->libwacom.db; + return db; +} + +void +libinput_libwacom_unref(struct libinput *li) +{ + assert(li->libwacom.refcount >= 1); + + if (--li->libwacom.refcount == 0) { + libwacom_database_destroy(li->libwacom.db); + li->libwacom.db = NULL; + } +} +#endif