Add libinput_tablet_tool_get_name() for the tool's specific name

If the tool has a name let's provide that to the caller. We have it
easily accessible so let's export it to make everyone's life easier. The
name is provided by libwacom, there is no need for us
to even copy that value since we don't need it ourselves.

Note that at this point effectively only (some) Wacom devices have
meaningful names. Virtually all non-wacom devices will use a generic
tool and even the built-in Wacoms will largely just say "AES Pen".

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1399>
This commit is contained in:
Peter Hutterer 2026-01-08 16:57:59 +10:00
parent 7d19cb5f40
commit dee2d38476
6 changed files with 144 additions and 2 deletions

View file

@ -1643,6 +1643,31 @@ libinput_tablet_tool_get_tool_id(struct libinput_tablet_tool *tool)
return tool->tool_id;
}
LIBINPUT_EXPORT const char *
libinput_tablet_tool_get_name(struct libinput_tablet_tool *tool)
{
#ifdef HAVE_LIBWACOM
if (!tool->last_device)
return NULL;
auto libinput = libinput_device_get_context(tool->last_device);
auto wacom_db = libinput->libwacom.db;
if (!wacom_db)
return NULL;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
const WacomStylus *stylus = libwacom_stylus_get_for_id(wacom_db, tool->tool_id);
#pragma GCC diagnostic pop
if (!stylus)
return NULL;
return libwacom_stylus_get_name(stylus);
#else
return NULL;
#endif
}
LIBINPUT_EXPORT int
libinput_tablet_tool_is_unique(struct libinput_tablet_tool *tool)
{

View file

@ -2886,6 +2886,7 @@ libinput_event_tablet_tool_get_time_usec(struct libinput_event_tablet_tool *even
* @return The tool type for this tool object
*
* @see libinput_tablet_tool_get_tool_id
* @see libinput_tablet_tool_get_name
*
* @since 1.2
*/
@ -2908,12 +2909,39 @@ libinput_tablet_tool_get_type(struct libinput_tablet_tool *tool);
* @return The tool ID for this tool object or 0 if none is provided
*
* @see libinput_tablet_tool_get_type
* @see libinput_tablet_tool_get_name
*
* @since 1.2
*/
uint64_t
libinput_tablet_tool_get_tool_id(struct libinput_tablet_tool *tool);
/**
* @ingroup event_tablet
*
* Return the tool name for a tool object, if any.
*
* The tool name is a human-readable string that identifies the specific tool,
* for example "Pro Pen 2" or "Airbrush" and may be presented to the user.
*
* The lifetime of the returned string is tied to the lifetime of the
* libinput_tablet_tool. The string may be NULL.
*
* @note This function requires libwacom support. If libwacom is not available
* at compile time or the tool is not known to libwacom, this function returns
* NULL.
*
* @param tool The libinput tool
* @return The tool name for this tool object or NULL if no name is available
*
* @see libinput_tablet_tool_get_tool_id
* @see libinput_tablet_tool_get_type
*
* @since 1.31
*/
const char *
libinput_tablet_tool_get_name(struct libinput_tablet_tool *tool);
/**
* @ingroup event_tablet
*

View file

@ -386,4 +386,5 @@ LIBINPUT_1.31 {
libinput_device_config_dwt_set_timeout;
libinput_device_config_dwtp_get_timeout;
libinput_device_config_dwtp_set_timeout;
libinput_tablet_tool_get_name;
} LIBINPUT_1.30;

View file

@ -663,6 +663,10 @@ print_proximity_event(struct libinput_event *ev,
_autofree_ char *axes = NULL;
_autofree_ char *proxin = NULL;
const char *tool_name = libinput_tablet_tool_get_name(tool);
if (!tool_name)
tool_name = "<unnamed>";
switch (libinput_tablet_tool_get_type(tool)) {
case LIBINPUT_TABLET_TOOL_TYPE_PEN:
tool_str = "pen";
@ -729,10 +733,11 @@ print_proximity_event(struct libinput_event *ev,
libinput_tablet_tool_has_button(tool, BTN_0) ? "0" : "");
}
return strdup_printf("%s\t%s\t%-8s (%#" PRIx64 ", id %#" PRIx64 ") %s%s",
return strdup_printf("%s\t%s\t%-8s ('%s', %#" PRIx64 ", id %#" PRIx64 ") %s%s",
time,
axes ? axes : "",
tool_str,
tool_name,
libinput_tablet_tool_get_serial(tool),
libinput_tablet_tool_get_tool_id(tool),
state_str,

View file

@ -2422,6 +2422,77 @@ START_TEST(tool_id)
}
END_TEST
START_TEST(tool_name)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
int tool_id = litest_test_param_get_i32(test_env->params, "tool_id");
struct axis_replacement axes[] = {
{ ABS_DISTANCE, 10 },
{ ABS_PRESSURE, 0 },
{ ABS_MISC, tool_id },
{ -1, -1 },
};
litest_drain_events(li);
litest_tablet_proximity_in(dev, 10, 10, axes);
litest_dispatch(li);
_destroy_(libinput_event) *event = libinput_get_event(li);
auto tablet_event =
litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
auto tool = libinput_event_tablet_tool_get_tool(tablet_event);
const char *name = libinput_tablet_tool_get_name(tool);
#ifdef HAVE_LIBWACOM
switch (tool_id) {
case 0x823:
litest_assert_str_eq(name, "Grip Pen");
break;
case 0x4802:
litest_assert_str_eq(name, "Classic Pen");
break;
case 0x100902:
litest_assert_str_eq(name, "Airbrush Pen");
break;
default:
litest_assert_not_reached();
}
#else
litest_assert_ptr_null(name);
#endif
}
END_TEST
START_TEST(tool_no_name)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct axis_replacement axes[] = {
{ ABS_DISTANCE, 10 },
{ ABS_PRESSURE, 0 },
{ -1, -1 },
};
litest_drain_events(li);
litest_tablet_proximity_in(dev, 10, 10, axes);
litest_dispatch(li);
_destroy_(libinput_event) *event = libinput_get_event(li);
auto tablet_event =
litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
auto tool = libinput_event_tablet_tool_get_tool(tablet_event);
const char *name = libinput_tablet_tool_get_name(tool);
litest_assert_ptr_null(name);
}
END_TEST
START_TEST(serial_changes_tool)
{
struct litest_device *dev = litest_current_device();
@ -7875,6 +7946,13 @@ TEST_COLLECTION(tablet)
litest_add(tool_unique, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
litest_add(tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
litest_add(tool_id, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
litest_with_parameters(params, "tool_id", 'I', 3,
litest_named_i32(0x823, "GripPen"),
litest_named_i32(0x4802, "ClassicPen"),
litest_named_i32(0x100902, "AirbrushPen")) {
litest_add_parametrized_for_device(tool_name, LITEST_WACOM_CINTIQ_PRO16_PEN, params);
}
litest_add_for_device(tool_no_name, LITEST_HUION_TABLET);
litest_add(serial_changes_tool, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
litest_add(invalid_serials, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
litest_add_no_device(tools_with_serials);

View file

@ -204,7 +204,12 @@ print_state(struct context *ctx)
abort();
}
printf("\rTool: %s serial %#" PRIx64 ", id %#" PRIx64 "\n",
const char *tool_name = libinput_tablet_tool_get_name(ctx->tool);
if (!tool_name)
tool_name = "<unnamed>";
printf("\rTool: '%s' %s serial %#" PRIx64 ", id %#" PRIx64 "\n",
tool_name,
tool_str,
libinput_tablet_tool_get_serial(ctx->tool),
libinput_tablet_tool_get_tool_id(ctx->tool));