Skip to content

Commit

Permalink
data: add a new Keys/KeyCodes entry to the tablet files
Browse files Browse the repository at this point in the history
This is parsed but not exported by libwacom itself beyond the number of
available keys. We can add other bits once we know what potential
callers want.

It is used however to determine if a device has a pad and thus used to
set the ID_INPUT_TABLET_PAD property through the hwdb. This fixes the
issue with some devices without buttons (but with keys) to not get
labelled as pads, e.g. the Cintiq Pro 13.

Fixes #585
  • Loading branch information
whot committed Sep 28, 2023
1 parent 1103aa2 commit fd5666d
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 1 deletion.
4 changes: 4 additions & 0 deletions data/cintiq-pro-13.tablet
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ Stylus=true
Reversible=false
Touch=true
Ring=false

[Keys]
# first key is in-kernel display toggle
KeyCodes=0;KEY_CONTROLPANEL;KEY_ONSCREEN_KEYBOARD;KEY_BUTTONCONFIG;SW_MUTE_DEVICE
7 changes: 7 additions & 0 deletions data/wacom.example
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,10 @@ Touchstrip2=J
# We assume the same number of modes for each of the touchstrips
# if there is more than one
StripsNumModes=4


# Metadata about the keys on the tablet
[Keys]
# The evdev codes for the keys (if any) in order from left to right.
# Keys that have a code of zero do not produce any events.
KeyCodes=0;KEY_CONTROLPANEL;KEY_ONSCREEN_KEYBOARD;KEY_BUTTONCONFIG;SW_MUTE_DEVICE
70 changes: 70 additions & 0 deletions libwacom/libwacom-database.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#define FEATURES_GROUP "Features"
#define DEVICE_GROUP "Device"
#define BUTTONS_GROUP "Buttons"
#define KEYS_GROUP "Keys"

static WacomClass
libwacom_class_string_to_enum(const char *class)
Expand Down Expand Up @@ -493,6 +494,50 @@ set_button_codes_from_string(WacomDevice *device, char **strvals)
return success;
}

static inline bool
set_key_codes_from_string(WacomDevice *device, char **strvals)
{
bool success = false;
assert(strvals);

for (unsigned int idx = 0; strvals[idx]; idx++) {
const char *str = strvals[idx];
int code = -1;
int type = -1;

if (!str) {
g_error("%s: Missing KeyCode for key %d, ignoring all codes\n",
device->name, idx);
goto out;
} else if (g_str_has_prefix(str, "KEY")) {
type = EV_KEY;
code = libevdev_event_code_from_code_name(str);
} else if (g_str_has_prefix(str, "SW")) {
type = EV_SW;
code = libevdev_event_code_from_code_name(str);
} else {
if (safe_atoi_base (strvals[idx], &code, 16))
type = EV_KEY;
}

if (code == -1 || type == -1) {
g_warning ("%s: Invalid KeyCode %s, ignoring all codes\n", device->name, str);
goto out;
}

device->keycodes[idx].type = type;
device->keycodes[idx].code = code;
device->num_keycodes = idx + 1;
}

success = true;
out:
if (!success) {
memset(device->keycodes, 0, sizeof(device->keycodes));
}
return success;
}

static inline void
set_button_codes_from_heuristics(WacomDevice *device)
{
Expand Down Expand Up @@ -604,6 +649,30 @@ libwacom_parse_buttons(WacomDevice *device,
device->strips_num_modes = libwacom_parse_num_modes(device, keyfile, "StripsNumModes", WACOM_BUTTON_TOUCHSTRIP_MODESWITCH);
}

static void
libwacom_parse_key_codes(WacomDevice *device,
GKeyFile *keyfile)
{
char **vals;

vals = g_key_file_get_string_list(keyfile, KEYS_GROUP, "KeyCodes", NULL, NULL);
if (vals)
set_key_codes_from_string(device, vals);

g_strfreev (vals);
}

static void
libwacom_parse_keys(WacomDevice *device,
GKeyFile *keyfile)
{
if (!g_key_file_has_group(keyfile, KEYS_GROUP))
return;

libwacom_parse_key_codes(device, keyfile);
}


static int
styli_id_sort(gconstpointer pa, gconstpointer pb)
{
Expand Down Expand Up @@ -831,6 +900,7 @@ libwacom_parse_tablet_keyfile(WacomDeviceDatabase *db,

libwacom_parse_features(device, keyfile);
libwacom_parse_buttons(device, keyfile);
libwacom_parse_keys(device, keyfile);

success = TRUE;

Expand Down
10 changes: 10 additions & 0 deletions libwacom/libwacom.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,10 @@ libwacom_copy(const WacomDevice *device)
WacomButton *b = g_memdup2(a, sizeof(WacomButton));
g_hash_table_insert(d->buttons, k, b);
}

d->num_keycodes = device->num_keycodes;
memcpy(d->keycodes, device->keycodes, sizeof(device->keycodes));

return d;
}

Expand Down Expand Up @@ -1120,6 +1124,12 @@ libwacom_get_num_buttons(const WacomDevice *device)
return g_hash_table_size(device->buttons);
}

LIBWACOM_EXPORT int
libwacom_get_num_keys(const WacomDevice *device)
{
return device->num_keycodes;
}

LIBWACOM_EXPORT const int *
libwacom_get_supported_styli(const WacomDevice *device, int *num_styli)
{
Expand Down
10 changes: 10 additions & 0 deletions libwacom/libwacom.h
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,16 @@ int libwacom_has_touch(const WacomDevice *device);
*/
int libwacom_get_num_buttons(const WacomDevice *device);

/**
* Tablet keys indices are numbered from zero
*
* @param device The tablet to query
* @return The number of keys on the tablet
*
* @ingroup devices
*/
int libwacom_get_num_keys(const WacomDevice *device);

/**
* @param device The tablet to query
* @param num_styli Return location for the number of listed styli
Expand Down
4 changes: 4 additions & 0 deletions libwacom/libwacom.sym
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,7 @@ global:
local:
*;
};

LIBWACOM_2.9 {
libwacom_get_num_keys;
} LIBWACOM_2.0;
7 changes: 7 additions & 0 deletions libwacom/libwacomint.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ typedef struct _WacomButton {
int code;
} WacomButton;

typedef struct _WacomKeycode {
unsigned int type;
unsigned int code;
} WacomKeycode;

/* WARNING: When adding new members to this struct
* make sure to update libwacom_copy() and
* libwacom_print_device_description() ! */
Expand All @@ -92,6 +97,8 @@ struct _WacomDevice {

GArray *styli;
GHashTable *buttons; /* 'A' : WacomButton */
WacomKeycode keycodes[32];
size_t num_keycodes;

GArray *status_leds;

Expand Down
13 changes: 13 additions & 0 deletions test/test-load.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,16 @@ test_cintiq13hd(struct fixture *f, gconstpointer user_data)
libwacom_destroy(device);
}

static void
test_cintiqpro13(struct fixture *f, gconstpointer user_data)
{
WacomDevice *device = libwacom_new_from_name(f->db, "Wacom Cintiq Pro 13", NULL);
g_assert_nonnull(device);
g_assert_cmpint(libwacom_get_num_keys(device), ==, 5);

libwacom_destroy(device);
}

static void
test_bamboopen(struct fixture *f, gconstpointer user_data)
{
Expand Down Expand Up @@ -294,6 +304,9 @@ int main(int argc, char **argv)
g_test_add("/load/056a:0304", struct fixture, NULL,
fixture_setup, test_cintiq13hd,
fixture_teardown);
g_test_add("/load/056a:034f", struct fixture, NULL,
fixture_setup, test_cintiqpro13,
fixture_teardown);
g_test_add("/load/056a:0065", struct fixture, NULL,
fixture_setup, test_bamboopen,
fixture_teardown);
Expand Down
2 changes: 1 addition & 1 deletion tools/libwacom-update-db.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def _load(self, path):
)
except KeyError:
pass
t.has_pad = config.has_section("Buttons")
t.has_pad = any(config.has_section(s) for s in ["Buttons", "Keys"])
yield t


Expand Down

0 comments on commit fd5666d

Please sign in to comment.