diff --git a/src/libinput.c b/src/libinput.c index 7cd15b64..65c5b4e8 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -583,21 +583,25 @@ libinput_tool_get_serial(struct libinput_tool *tool) return tool->serial; } -LIBINPUT_EXPORT void +LIBINPUT_EXPORT struct libinput_tool * libinput_tool_ref(struct libinput_tool *tool) { tool->refcount++; + return tool; } -LIBINPUT_EXPORT void +LIBINPUT_EXPORT struct libinput_tool * libinput_tool_unref(struct libinput_tool *tool) { assert(tool->refcount > 0); - if (--tool->refcount == 0) { - list_remove(&tool->link); - free(tool); - } + tool->refcount--; + if (tool->refcount > 0) + return tool; + + list_remove(&tool->link); + free(tool); + return NULL; } struct libinput_source * diff --git a/src/libinput.h b/src/libinput.h index 38b6610f..8909e6f9 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -1010,8 +1010,9 @@ libinput_tool_get_type(struct libinput_tool *tool); * Increment the ref count of tool by one * * @param tool The tool to increment the ref count of + * @return The passed tool */ -void +struct libinput_tool * libinput_tool_ref(struct libinput_tool *tool); /** @@ -1021,8 +1022,9 @@ libinput_tool_ref(struct libinput_tool *tool); * the memory allocated for tool will be freed. * * @param tool The tool to decrement the ref count of + * @return NULL if the tool was destroyed otherwise the passed tool */ -void +struct libinput_tool * libinput_tool_unref(struct libinput_tool *tool); /** diff --git a/test/tablet.c b/test/tablet.c index adecdaba..1786375f 100644 --- a/test/tablet.c +++ b/test/tablet.c @@ -537,6 +537,42 @@ START_TEST(invalid_serials) } END_TEST +START_TEST(tool_ref) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event_tablet *tablet_event; + struct libinput_event *event; + struct libinput_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); + while ((event = libinput_get_event(li))) { + if (libinput_event_get_type(event) == + LIBINPUT_EVENT_TABLET_TOOL_UPDATE) { + break; + } + libinput_event_destroy(event); + } + + tablet_event = libinput_event_get_tablet_event(event); + tool = libinput_event_tablet_get_tool(tablet_event); + + ck_assert_notnull(tool); + ck_assert(tool == libinput_tool_ref(tool)); + ck_assert(tool == libinput_tool_unref(tool)); + ck_assert(libinput_tool_unref(tool) == NULL); + + libinput_event_destroy(event); +} +END_TEST + + START_TEST(pad_buttons_ignored) { struct litest_device *dev = litest_current_device(); @@ -589,6 +625,7 @@ END_TEST int main(int argc, char **argv) { + litest_add("tablet:tool", tool_ref, 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);