From 7db22756b760c672eaa8996a314865bd093f7122 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 26 Aug 2015 16:00:26 +1000 Subject: [PATCH] Revamp button action handling One giant commit, but I didn't know how to split this up easier. The problem is a misunderstanding in what the button type is and the code that built on that misunderstanding, requiring a lot of interdependent parts to be updated at once. The button _type_ is the physical description of the button. The button _action type_ is what will happen when you hit the buttons. The type is read-only, since we're not dealing with mr potato head here. The action is adjustible and we now support buttons, keys and special in-hardware actions (e.g. dpi changes). A few FIXMEs still in place, e.g. we don't handle modifiers with keys. For buttons we just take numerical button numbers. i.e. we can map a button to button 4, which will result in BTN_SIDE, and eventually logical button 8 in X. For keys we take KEY_FOO, since eventually we want this to come out as that (could do this for button as well I guess). Modifiers are currently ignored. For special actions we have a enum of actions we support. The button type enum is thus reduced a lot, and everything needs to be switched. This breaks ratbag-command change-button, will be fixed later since it's misdesigned as it is anyway. Signed-off-by: Peter Hutterer --- src/driver-etekcity.c | 121 ++++++++++++++++--------------------- src/driver-hidpp10.c | 5 +- src/driver-hidpp20.c | 5 +- src/hidpp20.c | 56 ++++++++++-------- src/hidpp20.h | 2 +- src/libratbag-private.h | 30 +++++++++- src/libratbag.c | 98 +++++++++++++++++++++++++++--- src/libratbag.h | 128 +++++++++++++++++++++++++--------------- src/libratbag.sym | 7 ++- tools/ratbag-command.c | 49 ++++----------- 10 files changed, 305 insertions(+), 196 deletions(-) diff --git a/src/driver-etekcity.c b/src/driver-etekcity.c index fa52dde7..9a0f4fad 100644 --- a/src/driver-etekcity.c +++ b/src/driver-etekcity.c @@ -100,92 +100,70 @@ print_key(uint8_t key) return "UNKNOWN"; } -static enum ratbag_button_action_type -etekcity_raw_to_action(uint8_t data, enum ratbag_button_type button_type) -{ - if (button_type == RATBAG_BUTTON_TYPE_UNKNOWN) - return RATBAG_BUTTON_ACTION_TYPE_NONE; - - return RATBAG_BUTTON_ACTION_TYPE_BUTTON; -} - struct etekcity_button_mapping { uint8_t raw; - enum ratbag_button_type type; + struct ratbag_button_action action; }; static struct etekcity_button_mapping etekcity_button_mapping[] = { - { 1, RATBAG_BUTTON_TYPE_LEFT }, - { 2, RATBAG_BUTTON_TYPE_RIGHT }, - { 3, RATBAG_BUTTON_TYPE_MIDDLE }, -// { 4, "2 x BTN_LEFT" }, - { 6, RATBAG_BUTTON_TYPE_NONE }, - { 0, RATBAG_BUTTON_TYPE_NONE }, - { 7, RATBAG_BUTTON_TYPE_EXTRA }, - { 8, RATBAG_BUTTON_TYPE_SIDE }, - { 9, RATBAG_BUTTON_TYPE_WHEEL_UP }, - { 10, RATBAG_BUTTON_TYPE_WHEEL_DOWN }, - { 11, RATBAG_BUTTON_TYPE_WHEEL_LEFT }, - { 12, RATBAG_BUTTON_TYPE_WHEEL_RIGHT }, - - /* DPI switch */ - { 13, RATBAG_BUTTON_TYPE_RESOLUTION_CYCLE_UP }, - { 14, RATBAG_BUTTON_TYPE_RESOLUTION_UP }, - { 15, RATBAG_BUTTON_TYPE_RESOLUTION_DOWN }, - - /* Macro */ - { 16, RATBAG_BUTTON_TYPE_MACRO }, - - /* Profile */ - { 18, RATBAG_BUTTON_TYPE_PROFILE_CYCLE_UP }, - { 19, RATBAG_BUTTON_TYPE_PROFILE_UP }, - { 20, RATBAG_BUTTON_TYPE_PROFILE_DOWN }, - -// { 21, "HOLD BTN_LEFT ON/OFF" }, - - /* multimedia */ - { 25, RATBAG_BUTTON_TYPE_KEY_CONFIG }, - { 26, RATBAG_BUTTON_TYPE_KEY_PREVIOUSSONG }, - { 27, RATBAG_BUTTON_TYPE_KEY_NEXTSONG }, - { 28, RATBAG_BUTTON_TYPE_KEY_PLAYPAUSE }, - { 29, RATBAG_BUTTON_TYPE_KEY_STOPCD }, - { 30, RATBAG_BUTTON_TYPE_KEY_MUTE }, - { 31, RATBAG_BUTTON_TYPE_KEY_VOLUMEUP }, - { 32, RATBAG_BUTTON_TYPE_KEY_VOLUMEDOWN }, - - /* windows */ - { 33, RATBAG_BUTTON_TYPE_KEY_CALC }, - { 34, RATBAG_BUTTON_TYPE_KEY_MAIL }, - { 35, RATBAG_BUTTON_TYPE_KEY_BOOKMARKS }, - { 36, RATBAG_BUTTON_TYPE_KEY_FORWARD }, - { 37, RATBAG_BUTTON_TYPE_KEY_BACK }, - { 38, RATBAG_BUTTON_TYPE_KEY_STOP }, - { 39, RATBAG_BUTTON_TYPE_KEY_FILE }, - { 40, RATBAG_BUTTON_TYPE_KEY_REFRESH }, - { 41, RATBAG_BUTTON_TYPE_KEY_HOMEPAGE }, - { 42, RATBAG_BUTTON_TYPE_KEY_SEARCH }, + { 1, BUTTON_ACTION_BUTTON(1) }, + { 2, BUTTON_ACTION_BUTTON(2) }, + { 3, BUTTON_ACTION_BUTTON(3) }, + { 4, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_DOUBLECLICK) }, + { 6, BUTTON_ACTION_NONE }, + { 7, BUTTON_ACTION_BUTTON(4) }, + { 8, BUTTON_ACTION_BUTTON(5) }, + { 9, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_UP) }, + { 10, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_DOWN) }, + { 11, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_LEFT) }, + { 12, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_RIGHT) }, + { 13, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_CYCLE_UP) }, + { 14, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_UP) }, + { 15, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DOWN) }, + { 16, BUTTON_ACTION_NONE }, + { 17, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP) }, + { 18, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_UP) }, + { 19, BUTTON_ACTION_SPECIAL(RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_DOWN) }, + { 25, BUTTON_ACTION_KEY(KEY_CONFIG) }, + { 26, BUTTON_ACTION_KEY(KEY_PREVIOUSSONG) }, + { 27, BUTTON_ACTION_KEY(KEY_NEXTSONG) }, + { 28, BUTTON_ACTION_KEY(KEY_PLAYPAUSE) }, + { 29, BUTTON_ACTION_KEY(KEY_STOPCD) }, + { 30, BUTTON_ACTION_KEY(KEY_MUTE) }, + { 31, BUTTON_ACTION_KEY(KEY_VOLUMEUP) }, + { 32, BUTTON_ACTION_KEY(KEY_VOLUMEDOWN) }, + { 33, BUTTON_ACTION_KEY(KEY_CALC) }, + { 34, BUTTON_ACTION_KEY(KEY_MAIL) }, + { 35, BUTTON_ACTION_KEY(KEY_BOOKMARKS) }, + { 36, BUTTON_ACTION_KEY(KEY_FORWARD) }, + { 37, BUTTON_ACTION_KEY(KEY_BACK) }, + { 38, BUTTON_ACTION_KEY(KEY_STOP) }, + { 39, BUTTON_ACTION_KEY(KEY_FILE) }, + { 40, BUTTON_ACTION_KEY(KEY_REFRESH) }, + { 41, BUTTON_ACTION_KEY(KEY_HOMEPAGE) }, + { 42, BUTTON_ACTION_KEY(KEY_SEARCH) }, }; -static enum ratbag_button_type -etekcity_raw_to_button_type(uint8_t data) +static const struct ratbag_button_action* +etekcity_raw_to_button_action(uint8_t data) { struct etekcity_button_mapping *mapping; ARRAY_FOR_EACH(etekcity_button_mapping, mapping) { if (mapping->raw == data) - return mapping->type; + return &mapping->action; } - return RATBAG_BUTTON_TYPE_UNKNOWN; + return NULL; } static uint8_t -etekcity_button_type_to_raw(enum ratbag_button_type type) +etekcity_button_action_to_raw(const struct ratbag_button_action *action) { struct etekcity_button_mapping *mapping; ARRAY_FOR_EACH(etekcity_button_mapping, mapping) { - if (mapping->type == type) + if (mapping->action.type == action->type) return mapping->raw; } @@ -330,17 +308,20 @@ etekcity_read_button(struct ratbag_button *button) struct etekcity_data *drv_data = ratbag_get_drv_data(device); uint8_t data; unsigned index = etekcity_button_to_index(button->index); + const struct ratbag_button_action *action; data = drv_data->profiles[profile->index][3 + index * 3]; log_debug(device->ratbag, " - button%d: %s (%02x) %s:%d\n", button->index, print_key(data), data, __FILE__, __LINE__); - button->type = etekcity_raw_to_button_type(data); - button->action_type = etekcity_raw_to_action(data, button->type); + action = etekcity_raw_to_button_action(data); + button->action = *action; + /* FIXME: button->type needs a separate lookup table */ } static int -etekcity_write_button(struct ratbag_button *button) +etekcity_write_button(struct ratbag_button *button, + const struct ratbag_button_action *action) { struct ratbag_profile *profile = button->profile; struct ratbag_device *device = profile->device; @@ -350,9 +331,7 @@ etekcity_write_button(struct ratbag_button *button) data = &drv_data->profiles[profile->index][3 + index * 3]; - if (button->action_type == RATBAG_BUTTON_ACTION_TYPE_BUTTON) { - *data = etekcity_button_type_to_raw(button->type); - } + *data = etekcity_button_action_to_raw(action); return 0; } diff --git a/src/driver-hidpp10.c b/src/driver-hidpp10.c index 91dbfc6c..ba68e82c 100644 --- a/src/driver-hidpp10.c +++ b/src/driver-hidpp10.c @@ -73,7 +73,7 @@ hidpp10drv_read_button(struct ratbag_button *button) case 10: case 11: case 12: /* these don't actually exist on the device */ - type = RATBAG_BUTTON_TYPE_NONE; break; + type = RATBAG_BUTTON_TYPE_UNKNOWN; break; default: break; } @@ -82,7 +82,8 @@ hidpp10drv_read_button(struct ratbag_button *button) } static int -hidpp10drv_write_button(struct ratbag_button *button) +hidpp10drv_write_button(struct ratbag_button *button, + const struct ratbag_button_action *action) { return -1; } diff --git a/src/driver-hidpp20.c b/src/driver-hidpp20.c index 33c4df9d..6c1a87e3 100644 --- a/src/driver-hidpp20.c +++ b/src/driver-hidpp20.c @@ -94,11 +94,12 @@ hidpp20drv_read_button(struct ratbag_button *button) control->reporting.divert || control->reporting.persist ? "(redirected) " : "", __FILE__, __LINE__); button->type = hidpp20_1b04_get_logical_mapping(mapping); - button->action_type = hidpp20drv_raw_to_action(button->type); + button->action.type = hidpp20drv_raw_to_action(button->type); } static int -hidpp20drv_write_button(struct ratbag_button *button) +hidpp20drv_write_button(struct ratbag_button *button, + const struct ratbag_button_action *action) { struct ratbag_device *device = button->profile->device; struct hidpp20drv_data *drv_data = ratbag_get_drv_data(device); diff --git a/src/hidpp20.c b/src/hidpp20.c index 7f5ce5c5..e300a53e 100644 --- a/src/hidpp20.c +++ b/src/hidpp20.c @@ -512,7 +512,7 @@ struct hidpp20_1b04_mapping { static const struct hidpp20_1b04_mapping hidpp20_1b04_logical_mapping[] = { - { 0, "None" , RATBAG_BUTTON_TYPE_NONE}, + { 0, "None" , RATBAG_BUTTON_TYPE_UNKNOWN}, { 1, "Volume Up" , RATBAG_BUTTON_TYPE_UNKNOWN}, { 2, "Volume Down" , RATBAG_BUTTON_TYPE_UNKNOWN}, { 3, "Mute" , RATBAG_BUTTON_TYPE_UNKNOWN}, @@ -530,26 +530,32 @@ static const struct hidpp20_1b04_mapping hidpp20_1b04_logical_mapping[] = { 315, "LedToggle" , RATBAG_BUTTON_TYPE_UNKNOWN}, }; -static const struct hidpp20_1b04_mapping hidpp20_1b04_physical_mapping[] = +struct hidpp20_1b04_action_mapping { + uint16_t value; + const char *name; + struct ratbag_button_action action; +}; + +static const struct hidpp20_1b04_action_mapping hidpp20_1b04_physical_mapping[] = { - { 0, "None" , RATBAG_BUTTON_TYPE_NONE}, - { 1, "Volume Up" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 2, "Volume Down" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 3, "Mute" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 4, "Play/Pause" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 5, "Next" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 6, "Previous" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 7, "Stop" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 56, "Left Click" , RATBAG_BUTTON_TYPE_LEFT}, - { 57, "Right Click" , RATBAG_BUTTON_TYPE_RIGHT}, - { 58, "Middle Click" , RATBAG_BUTTON_TYPE_MIDDLE}, - { 59, "Wheel Side Click Left" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 60, "Back Click" , RATBAG_BUTTON_TYPE_SIDE}, - { 61, "Wheel Side Click Right" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 62, "Forward Click" , RATBAG_BUTTON_TYPE_EXTRA}, - { 156, "Gesture Button" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 157, "SmartShift" , RATBAG_BUTTON_TYPE_UNKNOWN}, - { 221, "LedToggle" , RATBAG_BUTTON_TYPE_UNKNOWN}, + { 0, "None" , BUTTON_ACTION_NONE }, + { 1, "Volume Up" , BUTTON_ACTION_KEY(KEY_VOLUMEUP) }, + { 2, "Volume Down" , BUTTON_ACTION_KEY(KEY_VOLUMEDOWN) }, + { 3, "Mute" , BUTTON_ACTION_KEY(KEY_MUTE) }, + { 4, "Play/Pause" , BUTTON_ACTION_KEY(KEY_PLAYPAUSE) }, + { 5, "Next" , BUTTON_ACTION_KEY(KEY_NEXTSONG) }, + { 6, "Previous" , BUTTON_ACTION_KEY(KEY_PREVIOUSSONG) }, + { 7, "Stop" , BUTTON_ACTION_KEY(KEY_STOPCD) }, + { 56, "Left Click" , BUTTON_ACTION_BUTTON(1) }, + { 57, "Right Click" , BUTTON_ACTION_BUTTON(2) }, + { 58, "Middle Click" , BUTTON_ACTION_BUTTON(3) }, + { 59, "Wheel Side Click Left" , BUTTON_ACTION_BUTTON(10) }, /* FIXME */ + { 60, "Back Click" , BUTTON_ACTION_BUTTON(4) }, + { 61, "Wheel Side Click Right" , BUTTON_ACTION_BUTTON(11)}, /* FIXME */ + { 62, "Forward Click" , BUTTON_ACTION_BUTTON(5) }, + { 156, "Gesture Button" , BUTTON_ACTION_NONE }, + { 157, "SmartShift" , BUTTON_ACTION_NONE }, + { 221, "LedToggle" , BUTTON_ACTION_NONE }, }; enum ratbag_button_type @@ -591,23 +597,23 @@ hidpp20_1b04_get_logical_mapping_name(uint16_t value) return "UNKNOWN"; } -enum ratbag_button_type +const struct ratbag_button_action* hidpp20_1b04_get_physical_mapping(uint16_t value) { - const struct hidpp20_1b04_mapping *map; + const struct hidpp20_1b04_action_mapping *map; ARRAY_FOR_EACH(hidpp20_1b04_physical_mapping, map) { if (map->value == value) - return map->type; + return &map->action; } - return RATBAG_BUTTON_TYPE_UNKNOWN; + return NULL; } const char * hidpp20_1b04_get_physical_mapping_name(uint16_t value) { - const struct hidpp20_1b04_mapping *map; + const struct hidpp20_1b04_action_mapping *map; ARRAY_FOR_EACH(hidpp20_1b04_physical_mapping, map) { if (map->value == value) diff --git a/src/hidpp20.h b/src/hidpp20.h index 73d52ef8..fa666f42 100644 --- a/src/hidpp20.h +++ b/src/hidpp20.h @@ -174,7 +174,7 @@ int hidpp20_special_key_mouse_set_control(struct ratbag_device *device, enum ratbag_button_type hidpp20_1b04_get_logical_mapping(uint16_t value); uint16_t hidpp20_1b04_get_logical_control_id(enum ratbag_button_type type); const char *hidpp20_1b04_get_logical_mapping_name(uint16_t value); -enum ratbag_button_type hidpp20_1b04_get_physical_mapping(uint16_t value); +const struct ratbag_button_action *hidpp20_1b04_get_physical_mapping(uint16_t value); const char *hidpp20_1b04_get_physical_mapping_name(uint16_t value); /* -------------------------------------------------------------------------- */ diff --git a/src/libratbag-private.h b/src/libratbag-private.h index c52f864e..743b7192 100644 --- a/src/libratbag-private.h +++ b/src/libratbag-private.h @@ -36,6 +36,7 @@ #define VERSION_ANY 0xffff struct ratbag_driver; +struct ratbag_button_action; struct ratbag { const struct ratbag_interface *interface; @@ -161,7 +162,8 @@ struct ratbag_driver { * should later on write the profile in one call to * .write_profile(). */ - int (*write_button)(struct ratbag_button *button); + int (*write_button)(struct ratbag_button *button, + const struct ratbag_button_action *action); /** For the given profile, overwrite the current resolution * of the sensor expressed in DPI, and commit it to the hardware. @@ -186,13 +188,37 @@ struct ratbag_profile { int report_rate; }; +#define BUTTON_ACTION_NONE \ + { .type = RATBAG_BUTTON_ACTION_TYPE_NONE } +#define BUTTON_ACTION_BUTTON(num_) \ + { .type = RATBAG_BUTTON_ACTION_TYPE_BUTTON, \ + .action.button = num_ } +#define BUTTON_ACTION_SPECIAL(sp_) \ + { .type = RATBAG_BUTTON_ACTION_TYPE_SPECIAL, \ + .action.special = sp_ } +#define BUTTON_ACTION_KEY(k_) \ + { .type = RATBAG_BUTTON_ACTION_TYPE_KEY, \ + .action.key.key = k_ } + +struct ratbag_button_action { + enum ratbag_button_action_type type; + union ratbag_btn_action { + unsigned int button; /* action_type == button */ + enum ratbag_button_action_special special; /* action_type == special */ + struct { + unsigned int key; /* action_type == key */ + /* FIXME: modifiers */ + } key; + } action; +}; + struct ratbag_button { int refcount; struct list link; struct ratbag_profile *profile; unsigned index; enum ratbag_button_type type; - enum ratbag_button_action_type action_type; + struct ratbag_button_action action; }; static inline int diff --git a/src/libratbag.c b/src/libratbag.c index 631a2c4f..c95dc8aa 100644 --- a/src/libratbag.c +++ b/src/libratbag.c @@ -741,19 +741,103 @@ ratbag_button_get_type(struct ratbag_button *button) return button->type; } -LIBRATBAG_EXPORT int -ratbag_button_set_type(struct ratbag_button *button, enum ratbag_button_type type) +LIBRATBAG_EXPORT unsigned int +ratbag_button_get_button(struct ratbag_button *button) { - enum ratbag_button_type orig_type = button->type; + if (!button->profile->device->driver->read_button) + return 0; /* FIXME */ + + if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_BUTTON) + return 0; + + return button->action.action.button; +} + +LIBRATBAG_EXPORT int +ratbag_button_set_button(struct ratbag_button *button, unsigned int btn) +{ + struct ratbag_button_action action; int rc; if (!button->profile->device->driver->write_button) return -ENOTSUP; - button->type = type; - rc = button->profile->device->driver->write_button(button); - if (rc) - button->type = orig_type; + action.type = RATBAG_BUTTON_ACTION_TYPE_BUTTON; + action.action.button = btn; + + rc = button->profile->device->driver->write_button(button, &action); + + return rc; +} + +LIBRATBAG_EXPORT enum ratbag_button_action_special +ratbag_button_get_special(struct ratbag_button *button) +{ + if (!button->profile->device->driver->read_button) + return -ENOTSUP; + + if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_BUTTON) + return 0; + + return button->action.action.button; +} + +LIBRATBAG_EXPORT int +ratbag_button_set_special(struct ratbag_button *button, + enum ratbag_button_action_special act) +{ + struct ratbag_button_action action; + int rc; + + /* FIXME: range checks */ + + if (!button->profile->device->driver->write_button) + return -1; + + action.type = RATBAG_BUTTON_ACTION_TYPE_SPECIAL; + action.action.special = act; + + rc = button->profile->device->driver->write_button(button, &action); + + return rc; +} + +LIBRATBAG_EXPORT unsigned int +ratbag_button_get_key(struct ratbag_button *button, + unsigned int *modifiers, + size_t *sz) +{ + if (!button->profile->device->driver->read_button) + return 0; + + if (button->action.type != RATBAG_BUTTON_ACTION_TYPE_KEY) + return 0; + + /* FIXME: modifiers */ + *sz = 0; + return button->action.action.key.key; +} + +LIBRATBAG_EXPORT int +ratbag_button_set_key(struct ratbag_button *button, + unsigned int key, + unsigned int *modifiers, + size_t sz) +{ + struct ratbag_button_action action; + int rc; + + /* FIXME: range checks */ + + if (!button->profile->device->driver->write_button) + return -1; + + /* FIXME: modifiers */ + + action.type = RATBAG_BUTTON_ACTION_TYPE_KEY; + action.action.key.key = key; + rc = button->profile->device->driver->write_button(button, &action); + return rc; } diff --git a/src/libratbag.h b/src/libratbag.h index dff2a34e..5e9dc40a 100644 --- a/src/libratbag.h +++ b/src/libratbag.h @@ -445,34 +445,6 @@ enum ratbag_button_type { RATBAG_BUTTON_TYPE_PROFILE_CYCLE_UP, RATBAG_BUTTON_TYPE_PROFILE_UP, RATBAG_BUTTON_TYPE_PROFILE_DOWN, - - /* Macro */ - RATBAG_BUTTON_TYPE_MACRO, - - /* multimedia */ - RATBAG_BUTTON_TYPE_KEY_CONFIG, - RATBAG_BUTTON_TYPE_KEY_PREVIOUSSONG, - RATBAG_BUTTON_TYPE_KEY_NEXTSONG, - RATBAG_BUTTON_TYPE_KEY_PLAYPAUSE, - RATBAG_BUTTON_TYPE_KEY_STOPCD, - RATBAG_BUTTON_TYPE_KEY_MUTE, - RATBAG_BUTTON_TYPE_KEY_VOLUMEUP, - RATBAG_BUTTON_TYPE_KEY_VOLUMEDOWN, - - /* desktop */ - RATBAG_BUTTON_TYPE_KEY_CALC, - RATBAG_BUTTON_TYPE_KEY_MAIL, - RATBAG_BUTTON_TYPE_KEY_BOOKMARKS, - RATBAG_BUTTON_TYPE_KEY_FORWARD, - RATBAG_BUTTON_TYPE_KEY_BACK, - RATBAG_BUTTON_TYPE_KEY_STOP, - RATBAG_BUTTON_TYPE_KEY_FILE, - RATBAG_BUTTON_TYPE_KEY_REFRESH, - RATBAG_BUTTON_TYPE_KEY_HOMEPAGE, - RATBAG_BUTTON_TYPE_KEY_SEARCH, - - /* disabled button */ - RATBAG_BUTTON_TYPE_NONE, }; /** @@ -491,21 +463,6 @@ enum ratbag_button_type { enum ratbag_button_type ratbag_button_get_type(struct ratbag_button *button); -/** - * @ingroup device - * - * Change the type of the physical button. This function is intended to be - * used by configuration tools to configure devices. - * - * FIXME: if we do this with linux/input.h instead, we need to add things like - * BTN_RESOLUTION_UP/DOWN there. But this is supposed to describe the - * physical location of the button, so input.h is not a good match. - * - * @return The error code or 0 on success. - */ -int -ratbag_button_set_type(struct ratbag_button *button, enum ratbag_button_type type); - /** * @ingroup device * @@ -524,6 +481,11 @@ enum ratbag_button_action_type { * Button sends numeric button events */ RATBAG_BUTTON_ACTION_TYPE_BUTTON, + /** + * Button triggers a mouse-specific special function. This includes + * resolution changes and profile changes. + */ + RATBAG_BUTTON_ACTION_TYPE_SPECIAL, /** * Button sends a key or key + modifier combination */ @@ -542,16 +504,50 @@ enum ratbag_button_action_type { enum ratbag_button_action_type ratbag_button_get_action_type(struct ratbag_button *button); +enum ratbag_button_action_special { + /** + * This button is not set up for a special action + */ + RATBAG_BUTTON_ACTION_SPECIAL_INVALID = -1, + RATBAG_BUTTON_ACTION_SPECIAL_UNKNOWN = (1 << 30), + + RATBAG_BUTTON_ACTION_SPECIAL_DOUBLECLICK, + + /* Wheel mappings */ + RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_LEFT, + RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_RIGHT, + RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_UP, + RATBAG_BUTTON_ACTION_SPECIAL_WHEEL_DOWN, + + /* DPI switch */ + RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_CYCLE_UP, + RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_UP, + RATBAG_BUTTON_ACTION_SPECIAL_RESOLUTION_DOWN, + + /* Profile */ + RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_CYCLE_UP, + RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_UP, + RATBAG_BUTTON_ACTION_SPECIAL_PROFILE_DOWN, + +}; + /** * @ingroup device * + * This function returns the logical button number this button is mapped to, + * starting at 1. The button numbers are in sequence and do not correspond + * to any meaning other than its numeric value. It is up to the input stack + * how to map that logical button number, but usually buttons 1, 2 and 3 are + * mapped into left, middle, right. + * * If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_BUTTON, * this function returns 0. * - * @return The button number this button sends, in one of BTN_*, as defined - * in linux/input.h. + * @return The logical button number this button sends. * @retval 0 This button is disabled or its action type is not @ref * RATBAG_BUTTON_ACTION_TYPE_BUTTON. + * + * @see ratbag_button_set_button */ unsigned int ratbag_button_get_button(struct ratbag_button *button); @@ -559,16 +555,50 @@ ratbag_button_get_button(struct ratbag_button *button); /** * @ingroup device * + * See ratbag_button_get_button() for a description of the button number. + * * @param button A previously initialized ratbag button - * @param btn The button number to assign to this button, one of BTN_* as - * defined in linux/input.h + * @param btn The logical button number to assign to this button. * @return 0 on success or nonzero otherwise. On success, the button's * action is set to @ref RATBAG_BUTTON_ACTION_TYPE_BUTTON. + * + * @see ratbag_button_get_button */ int ratbag_button_set_button(struct ratbag_button *button, unsigned int btn); +/** + * @ingroup device + * + * This function returns the special function assigned to this button. + * + * If the button's action type is not @ref RATBAG_BUTTON_ACTION_TYPE_SPECIAL, + * this function returns @ref RATBAG_BUTTON_ACTION_SPECIAL_INVALID. + * + * @return The special function assigned to this button + * + * @see ratbag_button_set_button + */ +enum ratbag_button_action_special +ratbag_button_get_special(struct ratbag_button *button); + +/** + * @ingroup device + * + * This function sets the special function assigned to this button. + * + * @param button A previously initialized ratbag button + * @param action The special action to assign to this button. + * @return 0 on success or nonzero otherwise. On success, the button's + * action is set to @ref RATBAG_BUTTON_ACTION_TYPE_SPECIAL. + * + * @see ratbag_button_get_button + */ +int +ratbag_button_set_special(struct ratbag_button *button, + enum ratbag_button_action_special action); + /** * @ingroup device * @@ -597,7 +627,7 @@ ratbag_button_get_key(struct ratbag_button *button, * @ingroup device * * @param button A previously initialized ratbag button - * @param btn The button number to assign to this button, one of BTN_* as + * @param key The button number to assign to this button, one of BTN_* as * defined in linux/input.h * @param modifiers The modifiers required for this action. The * modifiers are as defined in linux/input.h, in the order they should be @@ -610,7 +640,7 @@ ratbag_button_get_key(struct ratbag_button *button, */ int ratbag_button_set_key(struct ratbag_button *button, - unsigned int btn, + unsigned int key, unsigned int *modifiers, size_t sz); diff --git a/src/libratbag.sym b/src/libratbag.sym index 88d08261..6be55d84 100644 --- a/src/libratbag.sym +++ b/src/libratbag.sym @@ -5,7 +5,12 @@ global: ratbag_create_context; ratbag_button_ref; ratbag_button_get_type; - ratbag_button_set_type; + ratbag_button_get_button; + ratbag_button_get_key; + ratbag_button_get_special; + ratbag_button_set_button; + ratbag_button_set_key; + ratbag_button_set_special; ratbag_button_unref; ratbag_device_unref; ratbag_device_get_active_profile; diff --git a/tools/ratbag-command.c b/tools/ratbag-command.c index be79cfeb..e6f5df88 100644 --- a/tools/ratbag-command.c +++ b/tools/ratbag-command.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -155,34 +156,6 @@ button_type_to_str(enum ratbag_button_type type) case RATBAG_BUTTON_TYPE_PROFILE_CYCLE_UP: str = "profile cycle up"; break; case RATBAG_BUTTON_TYPE_PROFILE_UP: str = "profile up"; break; case RATBAG_BUTTON_TYPE_PROFILE_DOWN: str = "profile down"; break; - - /* Macro */ - case RATBAG_BUTTON_TYPE_MACRO: str = "macro"; break; - - /* multimedia */ - case RATBAG_BUTTON_TYPE_KEY_CONFIG: str = "key config"; break; - case RATBAG_BUTTON_TYPE_KEY_PREVIOUSSONG: str = "key previous song"; break; - case RATBAG_BUTTON_TYPE_KEY_NEXTSONG: str = "key next song"; break; - case RATBAG_BUTTON_TYPE_KEY_PLAYPAUSE: str = "key play/pause"; break; - case RATBAG_BUTTON_TYPE_KEY_STOPCD: str = "key stop"; break; - case RATBAG_BUTTON_TYPE_KEY_MUTE: str = "key mute"; break; - case RATBAG_BUTTON_TYPE_KEY_VOLUMEUP: str = "key volume up"; break; - case RATBAG_BUTTON_TYPE_KEY_VOLUMEDOWN: str = "key volume down"; break; - - /* desktop */ - case RATBAG_BUTTON_TYPE_KEY_CALC: str = "key calc"; break; - case RATBAG_BUTTON_TYPE_KEY_MAIL: str = "key mail"; break; - case RATBAG_BUTTON_TYPE_KEY_BOOKMARKS: str = "key bookmarks"; break; - case RATBAG_BUTTON_TYPE_KEY_FORWARD: str = "key forward"; break; - case RATBAG_BUTTON_TYPE_KEY_BACK: str = "key back"; break; - case RATBAG_BUTTON_TYPE_KEY_STOP: str = "key stop"; break; - case RATBAG_BUTTON_TYPE_KEY_FILE: str = "key file"; break; - case RATBAG_BUTTON_TYPE_KEY_REFRESH: str = "key refresh"; break; - case RATBAG_BUTTON_TYPE_KEY_HOMEPAGE: str = "key homepage"; break; - case RATBAG_BUTTON_TYPE_KEY_SEARCH: str = "key search"; break; - - /* disabled button */ - case RATBAG_BUTTON_TYPE_NONE: str = "none"; break; } return str; @@ -373,6 +346,8 @@ ratbag_cmd_switch_etekcity(struct ratbag *ratbag, uint32_t flags, int argc, char struct ratbag_button *button_6, *button_7; struct ratbag_profile *profile = NULL; int rc = 1, commit = 0; + unsigned int modifiers[10]; + size_t modifiers_sz = 10; if (argc != 1) { usage(); @@ -402,15 +377,15 @@ ratbag_cmd_switch_etekcity(struct ratbag *ratbag, uint32_t flags, int argc, char button_6 = ratbag_profile_get_button_by_index(profile, 6); button_7 = ratbag_profile_get_button_by_index(profile, 7); - if (ratbag_button_get_type(button_6) == RATBAG_BUTTON_TYPE_KEY_VOLUMEUP && - ratbag_button_get_type(button_7) == RATBAG_BUTTON_TYPE_KEY_VOLUMEDOWN) { - ratbag_button_set_type(button_6, RATBAG_BUTTON_TYPE_NONE); - ratbag_button_set_type(button_7, RATBAG_BUTTON_TYPE_NONE); + if (ratbag_button_get_key(button_6, modifiers, &modifiers_sz) == KEY_VOLUMEUP && + ratbag_button_get_key(button_7, modifiers, &modifiers_sz) == KEY_VOLUMEDOWN) { + ratbag_button_set_button(button_6, 0); + ratbag_button_set_button(button_7, 0); commit = 1; - } else if (ratbag_button_get_type(button_6) == RATBAG_BUTTON_TYPE_NONE && - ratbag_button_get_type(button_7) == RATBAG_BUTTON_TYPE_NONE) { - ratbag_button_set_type(button_6, RATBAG_BUTTON_TYPE_KEY_VOLUMEUP); - ratbag_button_set_type(button_7, RATBAG_BUTTON_TYPE_KEY_VOLUMEDOWN); + } else if (ratbag_button_get_button(button_6) == 0 && + ratbag_button_get_button(button_7) == 0) { + ratbag_button_set_key(button_6, KEY_VOLUMEUP, modifiers, 0); + ratbag_button_set_key(button_7, KEY_VOLUMEDOWN, modifiers, 0); commit = 2; } @@ -459,6 +434,7 @@ ratbag_cmd_change_button(struct ratbag *ratbag, uint32_t flags, int argc, char * type_index = atoi(argv[1]); path = argv[2]; +#if 0 /* FIXME */ device = ratbag_cmd_open_device(ratbag, path); if (!device) { error("Looks like '%s' is not supported\n", path); @@ -514,6 +490,7 @@ out: profile = ratbag_profile_unref(profile); device = ratbag_device_unref(device); +#endif return rc; }