diff --git a/doc/tablet-support.dox b/doc/tablet-support.dox index ac56e47a..fbe778da 100644 --- a/doc/tablet-support.dox +++ b/doc/tablet-support.dox @@ -126,7 +126,9 @@ and @ref LIBINPUT_TABLET_TOOL_TYPE_LENS tools. Some tools provide hardware information that enables libinput to uniquely identify the physical device. For example, tools compatible with the Wacom Intuos 4, Intuos 5, Intuos Pro and Cintiq series are uniquely identifiable -through a serial number. +through a serial number. libinput does not specify how a tool can be +identified uniquely, a caller should use libinput_tablet_tool_is_unique() to +check if the tool is unique. libinput creates a struct libinput_tablet_tool on the first proximity in of this tool. By default, this struct is destroyed on proximity out and diff --git a/src/libinput.c b/src/libinput.c index 093f3186..082c1b05 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1318,6 +1318,12 @@ libinput_tablet_tool_get_tool_id(struct libinput_tablet_tool *tool) return tool->tool_id; } +LIBINPUT_EXPORT int +libinput_tablet_tool_is_unique(struct libinput_tablet_tool *tool) +{ + return tool->serial != 0; +} + LIBINPUT_EXPORT uint64_t libinput_tablet_tool_get_serial(struct libinput_tablet_tool *tool) { diff --git a/src/libinput.h b/src/libinput.h index 73266a06..71d28203 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -144,7 +144,7 @@ enum libinput_pointer_axis_source { * Tablet events generated by such a device are bound to a specific tool * rather than coming from the device directly. Depending on the hardware it * is possible to track the same physical tool across multiple - * struct libinput_device devices. + * struct libinput_device devices, see @ref tablet-serial-numbers. */ struct libinput_tablet_tool; @@ -1931,14 +1931,26 @@ libinput_tablet_tool_has_button(struct libinput_tablet_tool *tool, /** * @ingroup event_tablet * - * Return the serial number of a tool + * Return nonzero if the physical tool can be uniquely identified by + * libinput, or nonzero otherwise. If a tool can be uniquely identified, + * keeping a reference to the tool allows tracking the tool across + * proximity out sequences and across compatible tablets. + * See @ref tablet-serial-numbers for more details. * - * @note Not all tablets report a serial number along with the type of tool - * being used. If the hardware does not provide a unique serial number, the - * serial number is always 0. + * @param tool A tablet tool + * @return 1 if the tool can be uniquely identified, 0 otherwise. + */ +int +libinput_tablet_tool_is_unique(struct libinput_tablet_tool *tool); + +/** + * @ingroup event_tablet + * + * Return the serial number of a tool. If the tool does not report a serial + * number, this function returns zero. * * @param tool The libinput tool - * @return The new tool serial triggering this event + * @return The tool serial number */ uint64_t libinput_tablet_tool_get_serial(struct libinput_tablet_tool *tool); diff --git a/src/libinput.sym b/src/libinput.sym index ddfe81dd..22a8dd82 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -226,6 +226,7 @@ LIBINPUT_TABLET_SUPPORT { libinput_tablet_tool_has_wheel; libinput_tablet_tool_has_slider; libinput_tablet_tool_has_button; + libinput_tablet_tool_is_unique; libinput_tablet_tool_ref; libinput_tablet_tool_set_user_data; libinput_tablet_tool_unref; diff --git a/test/tablet.c b/test/tablet.c index 456b0473..a2d0b36d 100644 --- a/test/tablet.c +++ b/test/tablet.c @@ -1257,6 +1257,30 @@ START_TEST(normalization) } END_TEST +START_TEST(tool_unique) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event_tablet_tool *tablet_event; + struct libinput_event *event; + struct libinput_tablet_tool *tool; + + litest_drain_events(li); + + litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1); + litest_event(dev, EV_MSC, MSC_SERIAL, 1000); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + + libinput_dispatch(li); + event = libinput_get_event(li); + tablet_event = litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY); + tool = libinput_event_tablet_tool_get_tool(tablet_event); + ck_assert(libinput_tablet_tool_is_unique(tool)); + libinput_event_destroy(event); +} +END_TEST + START_TEST(tool_serial) { struct litest_device *dev = litest_current_device(); @@ -2801,6 +2825,7 @@ litest_setup_tests(void) litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); litest_add_no_device("tablet:tool", tool_capabilities); litest_add("tablet:tool", tool_in_prox_before_start, LITEST_TABLET, LITEST_ANY); + litest_add("tablet:tool_serial", tool_unique, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); litest_add("tablet:tool_serial", tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); litest_add("tablet:tool_serial", serial_changes_tool, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY); litest_add("tablet:tool_serial", invalid_serials, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);