diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2021-03-25 12:37:19 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2021-03-29 12:42:37 +1000 |
commit | 031ff565c8d7059f895ba6e6ff3048214dc5024a (patch) | |
tree | e96b86d47a7d1a0f8dbabc7a469c348962bb491f | |
parent | 2289d35e0428d1cf6e566102b1b86088ad3d26cb (diff) | |
download | libwacom-031ff565c8d7059f895ba6e6ff3048214dc5024a.tar.gz |
Switch the buttons to a GHashTable
Slightly simpler to manage, we keep a hashtable around with the alphabetic
button as key and a new struct with flags + code as value. This removes the
need for all the seperate array + length tracking.
Minor regression: a caller passing invalid button codes will simply return the
zero values now, without a glib error message.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | libwacom/libwacom-database.c | 146 | ||||
-rw-r--r-- | libwacom/libwacom.c | 75 | ||||
-rw-r--r-- | libwacom/libwacomint.h | 11 |
3 files changed, 137 insertions, 95 deletions
diff --git a/libwacom/libwacom-database.c b/libwacom/libwacom-database.c index d3c2366..569b0d5 100644 --- a/libwacom/libwacom-database.c +++ b/libwacom/libwacom-database.c @@ -422,6 +422,7 @@ libwacom_parse_buttons_key(WacomDevice *device, return; for (i = 0; vals[i] != NULL; i++) { char val; + WacomButton *button; val = *vals[i]; if (strlen (vals[i]) > 1 || @@ -430,85 +431,118 @@ libwacom_parse_buttons_key(WacomDevice *device, g_warning ("Ignoring value '%s' in key '%s'", vals[i], key); continue; } - val -= 'A'; - device->buttons[(int) val] |= flag; + + button = g_hash_table_lookup(device->buttons, GINT_TO_POINTER(val)); + if (!button) { + button = g_new0(WacomButton, 1); + g_hash_table_insert(device->buttons, GINT_TO_POINTER(val), button); + } + + button->flags |= flag; } g_strfreev (vals); } +static void +reset_code(gpointer key, gpointer value, gpointer user_data) +{ + WacomButton *button = value; + button->code = 0; +} + static inline bool set_button_codes_from_string(WacomDevice *device, char **strvals) { - gint i; + bool success = false; assert(strvals); - for (i = 0; i < device->num_buttons; i++) { - gint val; + for (guint i = 0; i < g_hash_table_size(device->buttons); i++) { + char key = 'A' + i; + int code; + WacomButton *button = g_hash_table_lookup(device->buttons, GINT_TO_POINTER(key)); + + if (!button) { + g_error("%s: Button %c is not defined, ignoring all codes\n", + device->name, key); + goto out; + } if (!strvals[i]) { g_error ("%s: Missing EvdevCode for button %d, ignoring all codes\n", device->name, i); - return false; + goto out; } - if (!safe_atoi_base (strvals[i], &val, 16) || val < BTN_MISC || val >= BTN_DIGI) { - g_warning ("%s: Invalid EvdevCode %s for button %d, ignoring all codes\n", - device->name, strvals[i], i); - return false; + if (!safe_atoi_base (strvals[i], &code, 16) || code < BTN_MISC || code >= BTN_DIGI) { + g_warning ("%s: Invalid EvdevCode %s for button %c, ignoring all codes\n", + device->name, strvals[i], key); + goto out; } - device->button_codes[i] = val; + button->code = code; } + success = true; - return true; +out: + if (!success) + g_hash_table_foreach(device->buttons, reset_code, NULL); + + return success; } static inline void set_button_codes_from_heuristics(WacomDevice *device) { - gint i; - for (i = 0; i < device->num_buttons; i++) { + for (char key = 'A'; key <= 'Z'; key++) { + int code = 0; + WacomButton *button; + + button = g_hash_table_lookup(device->buttons, GINT_TO_POINTER(key)); + if (!button) + continue; + if (device->cls == WCLASS_BAMBOO || device->cls == WCLASS_GRAPHIRE) { - switch (i) { - case 0: - device->button_codes[i] = BTN_LEFT; - break; - case 1: - device->button_codes[i] = BTN_RIGHT; - break; - case 2: - device->button_codes[i] = BTN_FORWARD; - break; - case 3: - device->button_codes[i] = BTN_BACK; - break; + switch (key) { + case 'A': code = BTN_LEFT; break; + case 'B': code = BTN_RIGHT; break; + case 'C': code = BTN_FORWARD; break; + case 'D': code = BTN_BACK; break; default: - device->button_codes[i] = 0; break; } } else { /* Assume traditional ExpressKey ordering */ - switch (i) { - case 0 ... 9: - device->button_codes[i] = BTN_0 + i; - break; - case 10 ... 15: - device->button_codes[i] = BTN_A + (i-10); - break; - case 16: - case 17: - device->button_codes[i] = BTN_BASE + (i-16); - break; + switch (key) { + case 'A': code = BTN_0; break; + case 'B': code = BTN_1; break; + case 'C': code = BTN_2; break; + case 'D': code = BTN_3; break; + case 'E': code = BTN_4; break; + case 'F': code = BTN_5; break; + case 'G': code = BTN_6; break; + case 'H': code = BTN_7; break; + case 'I': code = BTN_8; break; + case 'J': code = BTN_9; break; + case 'K': code = BTN_A; break; + case 'L': code = BTN_B; break; + case 'M': code = BTN_C; break; + case 'N': code = BTN_X; break; + case 'O': code = BTN_Y; break; + case 'P': code = BTN_Z; break; + case 'Q': code = BTN_BASE; break; + case 'R': code = BTN_BASE2; break; default: - device->button_codes[i] = 0; break; } } - if (device->button_codes[i] == 0) - g_warning ("Unable to determine evdev code for button %d (%s)", i, device->name); + if (code == 0) + g_warning ("Unable to determine evdev code for button %c (%s)", + key, device->name); + + button->code = code; } } @@ -519,8 +553,7 @@ libwacom_parse_button_codes(WacomDevice *device, char **vals; vals = g_key_file_get_string_list(keyfile, BUTTONS_GROUP, "EvdevCodes", NULL, NULL); - if (!vals || - !set_button_codes_from_string(device, vals)) + if (!vals || !set_button_codes_from_string(device, vals)) set_button_codes_from_heuristics(device); g_strfreev (vals); @@ -532,16 +565,21 @@ libwacom_parse_num_modes (WacomDevice *device, const char *key, WacomButtonFlags flag) { + GHashTableIter iter; int num; - int i; + gpointer k, v; num = g_key_file_get_integer (keyfile, BUTTONS_GROUP, key, NULL); if (num > 0) return num; - for (i = 0; i < device->num_buttons; i++) { - if (device->buttons[i] & flag) + + g_hash_table_iter_init(&iter, device->buttons); + while (g_hash_table_iter_next(&iter, &k, &v)) { + WacomButton *button = v; + if (button->flags & flag) num++; } + return num; } @@ -621,6 +659,7 @@ libwacom_parse_tablet_keyfile(WacomDeviceDatabase *db, char *paired; char **string_list; bool success = FALSE; + int num_buttons; keyfile = g_key_file_new(); @@ -760,17 +799,18 @@ libwacom_parse_tablet_keyfile(WacomDeviceDatabase *db, g_warning ("Tablet '%s' has touch switch but no touch tool. This is impossible", libwacom_get_match(device)); device->num_strips = g_key_file_get_integer(keyfile, FEATURES_GROUP, "NumStrips", NULL); - device->num_buttons = g_key_file_get_integer(keyfile, FEATURES_GROUP, "Buttons", &error); - if (device->num_buttons == 0 && + + num_buttons = g_key_file_get_integer(keyfile, FEATURES_GROUP, "Buttons", &error); + if (num_buttons == 0 && g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { g_warning ("Tablet '%s' has no buttons defined, do something!", libwacom_get_match(device)); g_clear_error (&error); } - if (device->num_buttons > 0) { - device->buttons = g_new0 (WacomButtonFlags, device->num_buttons); - device->button_codes = g_new0 (gint, device->num_buttons); + + device->buttons = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, g_free); + if (num_buttons > 0) libwacom_parse_buttons(device, keyfile); - } string_list = g_key_file_get_string_list(keyfile, FEATURES_GROUP, "StatusLEDs", NULL, NULL); if (string_list) { diff --git a/libwacom/libwacom.c b/libwacom/libwacom.c index b151fb3..9f6aa0d 100644 --- a/libwacom/libwacom.c +++ b/libwacom/libwacom.c @@ -311,6 +311,8 @@ static WacomDevice * libwacom_copy(const WacomDevice *device) { WacomDevice *d; + GHashTableIter iter; + gpointer k, v; d = g_new0 (WacomDevice, 1); g_atomic_int_inc(&d->refcnt); @@ -343,10 +345,16 @@ libwacom_copy(const WacomDevice *device) g_array_append_val(d->styli, id); } d->num_leds = device->num_leds; - d->status_leds = g_memdup2 (device->status_leds, sizeof(WacomStatusLEDs) * device->num_leds); - d->num_buttons = device->num_buttons; - d->buttons = g_memdup2 (device->buttons, sizeof(WacomButtonFlags) * device->num_buttons); - d->button_codes = g_memdup2 (device->button_codes, sizeof(int) * device->num_buttons); + d->status_leds = g_memdup2(device->status_leds, sizeof(WacomStatusLEDs) * device->num_leds); + + d->buttons = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, g_free); + g_hash_table_iter_init(&iter, device->buttons); + while (g_hash_table_iter_next(&iter, &k, &v)) { + WacomButton *a = v; + WacomButton *b = g_memdup2(a, sizeof(WacomButton)); + g_hash_table_insert(d->buttons, k, b); + } return d; } @@ -401,6 +409,9 @@ libwacom_same_layouts (const WacomDevice *a, const WacomDevice *b) LIBWACOM_EXPORT int libwacom_compare(const WacomDevice *a, const WacomDevice *b, WacomCompareFlags flags) { + GHashTableIter iter; + gpointer k, v; + g_return_val_if_fail(a || b, 0); if (!a || !b) @@ -439,7 +450,7 @@ libwacom_compare(const WacomDevice *a, const WacomDevice *b, WacomCompareFlags f if (a->ring2_num_modes != b->ring2_num_modes) return 1; - if (a->num_buttons != b->num_buttons) + if (g_hash_table_size(a->buttons) != g_hash_table_size(b->buttons)) return 1; if (a->styli->len != b->styli->len) @@ -454,11 +465,14 @@ libwacom_compare(const WacomDevice *a, const WacomDevice *b, WacomCompareFlags f if (memcmp(a->status_leds, b->status_leds, sizeof(WacomStatusLEDs) * a->num_leds) != 0) return 1; - if (memcmp(a->buttons, b->buttons, sizeof(WacomButtonFlags) * a->num_buttons) != 0) - return 1; + g_hash_table_iter_init(&iter, a->buttons); + while (g_hash_table_iter_next(&iter, &k, &v)) { + WacomButton *ba = v; + WacomButton *bb = g_hash_table_lookup(b->buttons, k); - if (memcmp(a->button_codes, b->button_codes, sizeof(int) * a->num_buttons) != 0) - return 1; + if (!bb || ba->flags != bb->flags || ba->code != bb->code) + return 1; + } if ((a->paired == NULL && b->paired != NULL) || (a->paired != NULL && b->paired == NULL) || @@ -880,8 +894,8 @@ libwacom_unref(WacomDevice *device) g_array_free (device->matches, TRUE); g_array_free (device->styli, TRUE); g_free (device->status_leds); - g_free (device->buttons); - g_free (device->button_codes); + if (device->buttons) + g_hash_table_destroy (device->buttons); g_free (device); return NULL; @@ -1048,7 +1062,7 @@ libwacom_has_touch(const WacomDevice *device) LIBWACOM_EXPORT int libwacom_get_num_buttons(const WacomDevice *device) { - return device->num_buttons; + return g_hash_table_size(device->buttons); } LIBWACOM_EXPORT const int * @@ -1114,24 +1128,18 @@ struct { LIBWACOM_EXPORT int libwacom_get_button_led_group (const WacomDevice *device, char button) { - int button_index, led_index; - WacomButtonFlags button_flags; - - g_return_val_if_fail (device->num_buttons > 0, -1); - g_return_val_if_fail (button >= 'A', -1); - g_return_val_if_fail (button < 'A' + device->num_buttons, -1); - - button_index = button - 'A'; - button_flags = device->buttons[button_index]; + int led_index; + WacomButton *b = g_hash_table_lookup(device->buttons, + GINT_TO_POINTER(button)); - if (!(button_flags & WACOM_BUTTON_MODESWITCH)) + if (!(b->flags & WACOM_BUTTON_MODESWITCH)) return -1; for (led_index = 0; led_index < device->num_leds; led_index++) { guint n; for (n = 0; n < G_N_ELEMENTS (button_status_leds); n++) { - if ((button_flags & button_status_leds[n].button_flags) && + if ((b->flags & button_status_leds[n].button_flags) && (device->status_leds[led_index] == button_status_leds[n].status_leds)) { return led_index; } @@ -1179,29 +1187,20 @@ libwacom_get_bustype(const WacomDevice *device) LIBWACOM_EXPORT WacomButtonFlags libwacom_get_button_flag(const WacomDevice *device, char button) { - int index; + WacomButton *b = g_hash_table_lookup(device->buttons, + GINT_TO_POINTER(button)); - g_return_val_if_fail (device->num_buttons > 0, WACOM_BUTTON_NONE); - g_return_val_if_fail (button >= 'A', WACOM_BUTTON_NONE); - g_return_val_if_fail (button < 'A' + device->num_buttons, WACOM_BUTTON_NONE); - index = button - 'A'; - - return device->buttons[index]; + return b ? b->flags : WACOM_BUTTON_NONE; } LIBWACOM_EXPORT int libwacom_get_button_evdev_code(const WacomDevice *device, char button) { - int index; - - g_return_val_if_fail (device->num_buttons > 0, 0); - g_return_val_if_fail (button >= 'A', 0); - g_return_val_if_fail (button < 'A' + device->num_buttons, 0); - - index = button - 'A'; + WacomButton *b = g_hash_table_lookup(device->buttons, + GINT_TO_POINTER(button)); - return device->button_codes[index]; + return b ? b->code : 0; } LIBWACOM_EXPORT const diff --git a/libwacom/libwacomint.h b/libwacom/libwacomint.h index f5041a2..47574b0 100644 --- a/libwacom/libwacomint.h +++ b/libwacom/libwacomint.h @@ -61,6 +61,12 @@ struct _WacomMatch { uint32_t product_id; }; +/* Used in the device->buttons hashtable */ +typedef struct _WacomButton { + WacomButtonFlags flags; + int code; +} WacomButton; + /* WARNING: When adding new members to this struct * make sure to update libwacom_copy() and * libwacom_print_device_description() ! */ @@ -85,10 +91,7 @@ struct _WacomDevice { int ring2_num_modes; GArray *styli; - - int num_buttons; - WacomButtonFlags *buttons; - int *button_codes; + GHashTable *buttons; /* 'A' : WacomButton */ int num_leds; WacomStatusLEDs *status_leds; |