diff --git a/data/cintiq-pro-13.tablet b/data/cintiq-pro-13.tablet index 4b0b773ea..a98180718 100644 --- a/data/cintiq-pro-13.tablet +++ b/data/cintiq-pro-13.tablet @@ -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 diff --git a/data/wacom.example b/data/wacom.example index d4366c3c1..7c16f01f4 100644 --- a/data/wacom.example +++ b/data/wacom.example @@ -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 diff --git a/libwacom/libwacom-database.c b/libwacom/libwacom-database.c index bc5271274..16fd04b34 100644 --- a/libwacom/libwacom-database.c +++ b/libwacom/libwacom-database.c @@ -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) @@ -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) { @@ -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) { @@ -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; diff --git a/libwacom/libwacom.c b/libwacom/libwacom.c index 27e6eadd4..92155994c 100644 --- a/libwacom/libwacom.c +++ b/libwacom/libwacom.c @@ -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; } @@ -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) { diff --git a/libwacom/libwacom.h b/libwacom/libwacom.h index cafed6402..389681d2b 100644 --- a/libwacom/libwacom.h +++ b/libwacom/libwacom.h @@ -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 diff --git a/libwacom/libwacom.sym b/libwacom/libwacom.sym index e517f2de7..76ed06921 100644 --- a/libwacom/libwacom.sym +++ b/libwacom/libwacom.sym @@ -68,3 +68,7 @@ global: local: *; }; + +LIBWACOM_2.9 { + libwacom_get_num_keys; +} LIBWACOM_2.0; diff --git a/libwacom/libwacomint.h b/libwacom/libwacomint.h index e1af83845..537afdb48 100644 --- a/libwacom/libwacomint.h +++ b/libwacom/libwacomint.h @@ -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() ! */ @@ -92,6 +97,8 @@ struct _WacomDevice { GArray *styli; GHashTable *buttons; /* 'A' : WacomButton */ + WacomKeycode keycodes[32]; + size_t num_keycodes; GArray *status_leds; diff --git a/test/test-load.c b/test/test-load.c index 10938b022..abb80117a 100644 --- a/test/test-load.c +++ b/test/test-load.c @@ -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) { @@ -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); diff --git a/tools/libwacom-update-db.py b/tools/libwacom-update-db.py index e30c88c99..c503c3381 100755 --- a/tools/libwacom-update-db.py +++ b/tools/libwacom-update-db.py @@ -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