diff options
author | Tarcísio Eduardo Moreira Crocomo <tarcisioe@pm.me> | 2024-04-09 18:46:42 -0300 |
---|---|---|
committer | Tarcísio Eduardo Moreira Crocomo <tarcisioe@pm.me> | 2024-04-09 19:08:17 -0300 |
commit | 46d1fff0b0cbefc52fd388ec2f8439655d1b4a5e (patch) | |
tree | dfbcdf59c2f0e7c250f99fdbdf4152e3411ab1e9 | |
parent | 1d5d45a251dd6f384067248db4ea69680995028e (diff) |
touchpad: add clickfinger button map
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/988>
-rw-r--r-- | completion/zsh/_libinput | 4 | ||||
-rw-r--r-- | doc/user/clickpad-softbuttons.rst | 11 | ||||
-rw-r--r-- | doc/user/tapping.rst | 13 | ||||
-rw-r--r-- | src/evdev-mt-touchpad-buttons.c | 68 | ||||
-rw-r--r-- | src/evdev-mt-touchpad.c | 1 | ||||
-rw-r--r-- | src/evdev-mt-touchpad.h | 6 | ||||
-rw-r--r-- | src/libinput-private.h | 4 | ||||
-rw-r--r-- | src/libinput.c | 40 | ||||
-rw-r--r-- | src/libinput.h | 73 | ||||
-rw-r--r-- | src/libinput.sym | 3 | ||||
-rw-r--r-- | test/litest.h | 12 | ||||
-rw-r--r-- | test/test-touchpad-buttons.c | 161 | ||||
-rw-r--r-- | tools/libinput-debug-events.man | 3 | ||||
-rw-r--r-- | tools/shared.c | 16 | ||||
-rw-r--r-- | tools/shared.h | 3 | ||||
-rwxr-xr-x | tools/test_tool_option_parsing.py | 1 |
16 files changed, 385 insertions, 34 deletions
diff --git a/completion/zsh/_libinput b/completion/zsh/_libinput index 36689d08..58428b36 100644 --- a/completion/zsh/_libinput +++ b/completion/zsh/_libinput @@ -50,6 +50,10 @@ __all_seats() '--apply-to=[Apply configuration options where the device name matches the pattern]:pattern' \ '--disable-sendevents=[Disable send-events option for the devices matching the pattern]:pattern' \ '--set-click-method=[Set the desired click method]:click-method:(none clickfinger buttonareas)' \ + '--set-clickfinger-map=[Set button mapping for clickfinger]:tap-map:(( \ + lrm\:2-fingers\ right-click\ /\ 3-fingers\ middle-click \ + lmr\:2-fingers\ middle-click\ /\ 3-fingers\ right-click \ + ))' \ '--set-scroll-method=[Set the desired scroll method]:scroll-method:(none twofinger edge button)' \ '--set-scroll-button=[Set the button to the given button code]' \ '--set-profile=[Set pointer acceleration profile]:accel-profile:(adaptive flat)' \ diff --git a/doc/user/clickpad-softbuttons.rst b/doc/user/clickpad-softbuttons.rst index 781aad94..06b653f6 100644 --- a/doc/user/clickpad-softbuttons.rst +++ b/doc/user/clickpad-softbuttons.rst @@ -102,11 +102,12 @@ ignores such button clicks, this behavior is intentional. Clickfinger behavior ------------------------------------------------------------------------------ -This is the default behavior on Apple touchpads. -Here, a left, right, middle button event is generated when one, two, or -three fingers are held down on the touchpad when a physical click is -generated. The location of the fingers does not matter and there are no -software-defined button areas. +This is the default behavior on Apple touchpads. Here, a left, right, middle +button event is generated when one, two, or three fingers are held down on the +touchpad when a physical click is generated, given the default mapping. The +location of the fingers does not matter and there are no software-defined +button areas. It is possible to swap right and middle buttons, the same way as +with :ref:`tapping <tapping>`. .. figure:: clickfinger.svg :align: center diff --git a/doc/user/tapping.rst b/doc/user/tapping.rst index 95b2d49d..85b55f1f 100644 --- a/doc/user/tapping.rst +++ b/doc/user/tapping.rst @@ -8,12 +8,13 @@ Tap-to-click behaviour finger touch down/up sequence maps into a button click. This is most commonly used on touchpads, but may be available on other devices. -libinput implements tapping for one, two, and three fingers, where supported -by the hardware, and maps those taps into a left, right, and middle button -click, respectively. Not all devices support three fingers, libinput will -support tapping up to whatever is supported by the hardware. libinput does -not support four-finger taps or any tapping with more than four fingers, -even though some hardware can distinguish between that many fingers. +libinput implements tapping for one, two, and three fingers, where supported by +the hardware, and maps those taps into a left, right, and middle button click, +respectively. This mapping can be switched to left, middle and right through +configuration. Not all devices support three fingers, libinput will support +tapping up to whatever is supported by the hardware. libinput does not support +four-finger taps or any tapping with more than four fingers, even though some +hardware can distinguish between that many fingers. .. _tapping_default: diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 08f0a907..0f0a640e 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -958,6 +958,51 @@ tp_guess_clickpad(const struct tp_dispatch *tp, struct evdev_device *device) return is_clickpad; } +static inline void +tp_button_update_clickfinger_map(struct tp_dispatch *tp) +{ + if (tp->buttons.state != BUTTON_STATE_NONE) + return; + + if (tp->buttons.map != tp->buttons.want_map) + tp->buttons.map = tp->buttons.want_map; +} + +void +tp_button_post_process_state(struct tp_dispatch *tp) +{ + tp_button_update_clickfinger_map(tp); +} + +static enum libinput_config_status +tp_button_config_set_clickfinger_map(struct libinput_device *device, + enum libinput_config_clickfinger_button_map map) +{ + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); + + tp->buttons.want_map = map; + + tp_button_update_clickfinger_map(tp); + + return LIBINPUT_CONFIG_STATUS_SUCCESS; +} + +static enum libinput_config_clickfinger_button_map +tp_button_config_get_clickfinger_map(struct libinput_device *device) +{ + struct evdev_dispatch *dispatch = evdev_device(device)->dispatch; + struct tp_dispatch *tp = tp_dispatch(dispatch); + + return tp->buttons.want_map; +} + +static enum libinput_config_clickfinger_button_map +tp_button_config_get_default_clickfinger_map(struct libinput_device *device) +{ + return LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM; +} + void tp_init_buttons(struct tp_dispatch *tp, struct evdev_device *device) @@ -982,8 +1027,15 @@ tp_init_buttons(struct tp_dispatch *tp, tp->buttons.config_method.set_method = tp_button_config_click_set_method; tp->buttons.config_method.get_method = tp_button_config_click_get_method; tp->buttons.config_method.get_default_method = tp_button_config_click_get_default_method; + tp->buttons.config_method.set_clickfinger_map = tp_button_config_set_clickfinger_map; + tp->buttons.config_method.get_clickfinger_map = tp_button_config_get_clickfinger_map; + tp->buttons.config_method.get_default_clickfinger_map = tp_button_config_get_default_clickfinger_map; + tp->device->base.config.click_method = &tp->buttons.config_method; + tp->buttons.map = LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM; + tp->buttons.want_map = tp->buttons.map; + tp->buttons.click_method = tp_click_get_default_method(tp); tp_switch_click_method(tp); @@ -1118,6 +1170,10 @@ tp_clickfinger_set_button(struct tp_dispatch *tp) struct tp_touch *t; struct tp_touch *first = NULL, *second = NULL; + int32_t button_map[2][3] = { + { BTN_LEFT, BTN_RIGHT, BTN_MIDDLE }, + { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT }, + }; tp_for_each_touch(tp, t) { if (t->state != TOUCH_BEGIN && t->state != TOUCH_UPDATE) @@ -1148,11 +1204,12 @@ tp_clickfinger_set_button(struct tp_dispatch *tp) nfingers = 1; out: + nfingers = max(1, nfingers); + switch (nfingers) { - case 0: - case 1: button = BTN_LEFT; break; - case 2: button = BTN_RIGHT; break; - case 3: button = BTN_MIDDLE; break; + case 1: + case 2: + case 3: button = button_map[tp->buttons.map][nfingers-1]; break; default: button = 0; break; @@ -1326,8 +1383,9 @@ int tp_post_button_events(struct tp_dispatch *tp, uint64_t time) { if (tp->buttons.is_clickpad || - tp->device->model_flags & EVDEV_MODEL_APPLE_TOUCHPAD_ONEBUTTON) + tp->device->model_flags & EVDEV_MODEL_APPLE_TOUCHPAD_ONEBUTTON) { return tp_post_clickpadbutton_buttons(tp, time); + } return tp_post_physical_buttons(tp, time); } diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index d9b7ca5f..845e408d 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1846,6 +1846,7 @@ tp_post_process_state(struct tp_dispatch *tp, uint64_t time) tp_thumb_reset(tp); tp_tap_post_process_state(tp); + tp_button_post_process_state(tp); } static void diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index bd5eab5f..26588dbb 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -399,6 +399,9 @@ struct tp_dispatch { enum libinput_config_click_method click_method; struct libinput_device_config_click_method config_method; + + enum libinput_config_clickfinger_button_map map; + enum libinput_config_clickfinger_button_map want_map; } buttons; struct { @@ -626,6 +629,9 @@ void tp_tap_post_process_state(struct tp_dispatch *tp); void +tp_button_post_process_state(struct tp_dispatch *tp); + +void tp_init_tap(struct tp_dispatch *tp); void diff --git a/src/libinput-private.h b/src/libinput-private.h index de1d7d64..dff0aaae 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -333,6 +333,10 @@ struct libinput_device_config_click_method { enum libinput_config_click_method method); enum libinput_config_click_method (*get_method)(struct libinput_device *device); enum libinput_config_click_method (*get_default_method)(struct libinput_device *device); + enum libinput_config_status (*set_clickfinger_map)(struct libinput_device *device, + enum libinput_config_clickfinger_button_map map); + enum libinput_config_clickfinger_button_map (*get_clickfinger_map)(struct libinput_device *device); + enum libinput_config_clickfinger_button_map (*get_default_clickfinger_map)(struct libinput_device *device); }; struct libinput_device_config_middle_emulation { diff --git a/src/libinput.c b/src/libinput.c index 5bebe56b..db16fe3f 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -72,6 +72,7 @@ ASSERT_INT_SIZE(enum libinput_config_drag_lock_state); ASSERT_INT_SIZE(enum libinput_config_send_events_mode); ASSERT_INT_SIZE(enum libinput_config_accel_profile); ASSERT_INT_SIZE(enum libinput_config_click_method); +ASSERT_INT_SIZE(enum libinput_config_clickfinger_button_map); ASSERT_INT_SIZE(enum libinput_config_middle_emulation_state); ASSERT_INT_SIZE(enum libinput_config_scroll_method); ASSERT_INT_SIZE(enum libinput_config_dwt_state); @@ -4509,6 +4510,45 @@ libinput_device_config_click_get_default_method(struct libinput_device *device) return LIBINPUT_CONFIG_CLICK_METHOD_NONE; } +LIBINPUT_EXPORT enum libinput_config_status +libinput_device_config_click_set_clickfinger_button_map(struct libinput_device *device, + enum libinput_config_clickfinger_button_map map) +{ + switch (map) { + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM: + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR: + break; + default: + return LIBINPUT_CONFIG_STATUS_INVALID; + } + + if ((libinput_device_config_click_get_methods(device) & + LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) != LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) + return LIBINPUT_CONFIG_STATUS_UNSUPPORTED; + + return device->config.click_method->set_clickfinger_map(device, map); +} + +LIBINPUT_EXPORT enum libinput_config_clickfinger_button_map +libinput_device_config_click_get_clickfinger_button_map(struct libinput_device *device) +{ + if ((libinput_device_config_click_get_methods(device) & + LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) != LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) + return LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM; + + return device->config.click_method->get_clickfinger_map(device); +} + +LIBINPUT_EXPORT enum libinput_config_clickfinger_button_map +libinput_device_config_click_get_default_clickfinger_button_map(struct libinput_device *device) +{ + if ((libinput_device_config_click_get_methods(device) & + LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) != LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) + return LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM; + + return device->config.click_method->get_default_clickfinger_map(device); +} + LIBINPUT_EXPORT int libinput_device_config_middle_emulation_is_available( struct libinput_device *device) diff --git a/src/libinput.h b/src/libinput.h index 85403be5..954ec617 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -4608,6 +4608,7 @@ libinput_device_group_get_user_data(struct libinput_device_group *group); * - libinput_device_config_tap_set_drag_enabled() * - libinput_device_config_tap_set_drag_lock_enabled() * - libinput_device_config_click_set_method() + * - libinput_device_config_click_set_clickfinger_button_map() * - libinput_device_config_scroll_set_method() * - libinput_device_config_dwt_set_enabled() * - Touchscreens: @@ -4749,6 +4750,16 @@ enum libinput_config_tap_button_map { /** * @ingroup config + */ +enum libinput_config_clickfinger_button_map { + /** 1/2/3 finger click maps to left/right/middle */ + LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM, + /** 1/2/3 finger click maps to left/middle/right*/ + LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR, +}; + +/** + * @ingroup config * * Set the finger number to button number mapping for tap-to-click. The * default mapping on most devices is to have a 1, 2 and 3 finger tap to map @@ -5818,6 +5829,68 @@ libinput_device_config_click_get_default_method(struct libinput_device *device); /** * @ingroup config + * + * Set the finger number to button number mapping for clickfinger. The + * default mapping on most devices is to have a 1, 2 and 3 finger tap to map + * to the left, right and middle button, respectively. + * A device may permit changing the button mapping but disallow specific + * maps. In this case @ref LIBINPUT_CONFIG_STATUS_UNSUPPORTED is returned, + * the caller is expected to handle this case correctly. + * + * Changing the button mapping may not take effect immediately, + * the device may wait until it is in a neutral state before applying any + * changes. + * + * @param device The device to configure + * @param map The new finger-to-button number mapping + * + * @return A config status code. Changing the order on a device that does not + * support the clickfinger method always fails with @ref + * LIBINPUT_CONFIG_STATUS_UNSUPPORTED. + * + * @see libinput_device_config_click_get_clickfinger_button_map + * @see libinput_device_config_click_get_default_clickfinger_button_map + */ +enum libinput_config_status +libinput_device_config_click_set_clickfinger_button_map(struct libinput_device *device, + enum libinput_config_clickfinger_button_map map); + +/** + * @ingroup config + * + * Get the finger number to button number mapping for clickfinger. + * + * The return value for a device that does not support tapping is always + * @ref LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM. + * + * @param device The device to configure + * @return The current finger-to-button number mapping + * + * @see libinput_device_config_click_set_clickfinger_button_map + * @see libinput_device_config_click_get_default_clickfinger_button_map + */ +enum libinput_config_clickfinger_button_map +libinput_device_config_click_get_clickfinger_button_map(struct libinput_device *device); + +/** + * @ingroup config + * + * Get the default finger number to button number mapping for clickfinger. + * + * The return value for a device that does not support clickfinger is always + * @ref LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM. + * + * @param device The device to configure + * @return The default finger-to-button number mapping + * + * @see libinput_device_config_click_set_clickfinger_button_map + * @see libinput_device_config_click_get_clickfinger_button_map + */ +enum libinput_config_clickfinger_button_map +libinput_device_config_click_get_default_clickfinger_button_map(struct libinput_device *device); + +/** + * @ingroup config */ enum libinput_config_middle_emulation_state { /** diff --git a/src/libinput.sym b/src/libinput.sym index 3624401c..a598f77a 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -335,6 +335,9 @@ LIBINPUT_1.23 { } LIBINPUT_1.21; LIBINPUT_1.26 { + libinput_device_config_click_set_clickfinger_button_map; + libinput_device_config_click_get_default_clickfinger_button_map; + libinput_device_config_click_get_clickfinger_button_map; libinput_device_get_id_bustype; libinput_device_tablet_pad_get_num_dials; libinput_event_tablet_pad_get_dial_delta_v120; diff --git a/test/litest.h b/test/litest.h index 73a4ef9a..6108be50 100644 --- a/test/litest.h +++ b/test/litest.h @@ -1156,6 +1156,18 @@ litest_enable_clickfinger(struct litest_device *dev) } static inline void +litest_set_clickfinger_map(struct litest_device *dev, + enum libinput_config_clickfinger_button_map map) +{ + enum libinput_config_status status, expected; + struct libinput_device *device = dev->libinput_device; + + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + status = libinput_device_config_click_set_clickfinger_button_map(device, map); + litest_assert_int_eq(status, expected); +} + +static inline void litest_enable_buttonareas(struct litest_device *dev) { enum libinput_config_status status, expected; diff --git a/test/test-touchpad-buttons.c b/test/test-touchpad-buttons.c index 8af48c64..3bc9fff4 100644 --- a/test/test-touchpad-buttons.c +++ b/test/test-touchpad-buttons.c @@ -82,6 +82,48 @@ START_TEST(touchpad_click_defaults_clickfinger) } END_TEST +START_TEST(touchpad_click_default_clickfinger_map) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + enum libinput_config_clickfinger_button_map map; + + map = libinput_device_config_click_get_clickfinger_button_map(device); + ck_assert_int_eq(map, LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM); + map = libinput_device_config_click_get_default_clickfinger_button_map(device); + ck_assert_int_eq(map, LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM); +} +END_TEST + +START_TEST(touchpad_click_set_clickfinger_map) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + enum libinput_config_clickfinger_button_map map; + enum libinput_config_status status; + + map = LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM; + status = libinput_device_config_click_set_clickfinger_button_map(device, map); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + map = libinput_device_config_click_get_clickfinger_button_map(dev->libinput_device); + ck_assert_int_eq(map, LIBINPUT_CONFIG_TAP_MAP_LRM); + + map = LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR; + status = libinput_device_config_click_set_clickfinger_button_map(device, map); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + map = libinput_device_config_click_get_clickfinger_button_map(dev->libinput_device); + ck_assert_int_eq(map, LIBINPUT_CONFIG_TAP_MAP_LMR); + + map = LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM - 1; + status = libinput_device_config_click_set_clickfinger_button_map(device, map); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID); + + map = LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR + 1; + status = libinput_device_config_click_set_clickfinger_button_map(device, map); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID); +} +END_TEST + START_TEST(touchpad_click_defaults_btnarea) { struct litest_device *dev = litest_current_device(); @@ -217,8 +259,22 @@ START_TEST(touchpad_2fg_clickfinger) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + enum libinput_config_clickfinger_button_map map = _i; /* ranged test */ + unsigned int button = 0; litest_enable_clickfinger(dev); + litest_set_clickfinger_map(dev, map); + + switch (map) { + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM: + button = BTN_RIGHT; + break; + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR: + button = BTN_MIDDLE; + break; + default: + litest_abort_msg("Invalid map range %d", map); + } litest_drain_events(li); @@ -233,9 +289,9 @@ START_TEST(touchpad_2fg_clickfinger) libinput_dispatch(li); - litest_assert_button_event(li, BTN_RIGHT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_PRESSED); - litest_assert_button_event(li, BTN_RIGHT, + litest_assert_button_event(li, button, LIBINPUT_BUTTON_STATE_RELEASED); } END_TEST @@ -244,11 +300,25 @@ START_TEST(touchpad_3fg_clickfinger) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + enum libinput_config_clickfinger_button_map map = _i; /* ranged test */ + unsigned int button = 0; if (litest_slot_count(dev) < 3) return; litest_enable_clickfinger(dev); + litest_set_clickfinger_map(dev, map); + + switch (map) { + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM: + button = BTN_MIDDLE; + break; + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR: + button = BTN_RIGHT; + break; + default: + litest_abort_msg("Invalid map range %d", map); + } litest_drain_events(li); @@ -266,10 +336,10 @@ START_TEST(touchpad_3fg_clickfinger) libinput_dispatch(li); litest_assert_button_event(li, - BTN_MIDDLE, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_MIDDLE, + button, LIBINPUT_BUTTON_STATE_RELEASED); } END_TEST @@ -278,12 +348,26 @@ START_TEST(touchpad_3fg_clickfinger_btntool) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + enum libinput_config_clickfinger_button_map map = _i; /* ranged test */ + unsigned int button = 0; if (litest_slot_count(dev) >= 3 || !libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_TRIPLETAP)) return; litest_enable_clickfinger(dev); + litest_set_clickfinger_map(dev, map); + + switch (map) { + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM: + button = BTN_MIDDLE; + break; + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR: + button = BTN_RIGHT; + break; + default: + litest_abort_msg("Invalid map range %d", map); + } litest_drain_events(li); @@ -305,10 +389,10 @@ START_TEST(touchpad_3fg_clickfinger_btntool) libinput_dispatch(li); litest_assert_button_event(li, - BTN_MIDDLE, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_MIDDLE, + button, LIBINPUT_BUTTON_STATE_RELEASED); } END_TEST @@ -418,13 +502,15 @@ START_TEST(touchpad_2fg_clickfinger_distance) struct libinput *li = dev->libinput; double w, h; bool small_touchpad = false; - unsigned int expected_button; + unsigned int expected_button = 0; + enum libinput_config_clickfinger_button_map map = _i; /* ranged test */ if (libinput_device_get_size(dev->libinput_device, &w, &h) == 0 && h < 50.0) small_touchpad = true; litest_enable_clickfinger(dev); + litest_set_clickfinger_map(dev, map); litest_drain_events(li); @@ -458,7 +544,14 @@ START_TEST(touchpad_2fg_clickfinger_distance) /* if the touchpad is small enough, we expect all fingers to count * for clickfinger */ if (small_touchpad) - expected_button = BTN_RIGHT; + switch (map) { + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM: + expected_button = BTN_RIGHT; + break; + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR: + expected_button = BTN_MIDDLE; + break; + } else expected_button = BTN_LEFT; @@ -475,11 +568,25 @@ START_TEST(touchpad_3fg_clickfinger_distance) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + enum libinput_config_clickfinger_button_map map = _i; /* ranged test */ + unsigned int button = 0; if (litest_slot_count(dev) < 3) return; litest_enable_clickfinger(dev); + litest_set_clickfinger_map(dev, map); + + switch (map) { + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM: + button = BTN_MIDDLE; + break; + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR: + button = BTN_RIGHT; + break; + default: + litest_abort_msg("Invalid map range %d", map); + } litest_drain_events(li); @@ -496,10 +603,10 @@ START_TEST(touchpad_3fg_clickfinger_distance) litest_touch_up(dev, 2); litest_assert_button_event(li, - BTN_MIDDLE, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_MIDDLE, + button, LIBINPUT_BUTTON_STATE_RELEASED); } END_TEST @@ -508,11 +615,25 @@ START_TEST(touchpad_3fg_clickfinger_distance_btntool) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + enum libinput_config_clickfinger_button_map map = _i; /* ranged test */ + unsigned int button = 0; if (litest_slot_count(dev) > 2) return; litest_enable_clickfinger(dev); + litest_set_clickfinger_map(dev, map); + + switch (map) { + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM: + button = BTN_MIDDLE; + break; + case LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR: + button = BTN_RIGHT; + break; + default: + litest_abort_msg("Invalid map range %d", map); + } litest_drain_events(li); @@ -534,10 +655,10 @@ START_TEST(touchpad_3fg_clickfinger_distance_btntool) litest_touch_up(dev, 1); litest_assert_button_event(li, - BTN_MIDDLE, + button, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, - BTN_MIDDLE, + button, LIBINPUT_BUTTON_STATE_RELEASED); } END_TEST @@ -2127,20 +2248,22 @@ END_TEST TEST_COLLECTION(touchpad_buttons) { struct range finger_count = {1, 4}; + struct range clickfinger_map_range = { LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM, + LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR + 1 }; litest_add(touchpad_button, LITEST_TOUCHPAD, LITEST_CLICKPAD); litest_add(touchpad_1fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); litest_add(touchpad_1fg_clickfinger_no_touch, LITEST_CLICKPAD, LITEST_ANY); - litest_add(touchpad_2fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); - litest_add(touchpad_3fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); - litest_add(touchpad_3fg_clickfinger_btntool, LITEST_CLICKPAD, LITEST_ANY); + litest_add_ranged(touchpad_2fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY, &clickfinger_map_range); + litest_add_ranged(touchpad_3fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY, &clickfinger_map_range); + litest_add_ranged(touchpad_3fg_clickfinger_btntool, LITEST_CLICKPAD, LITEST_ANY, &clickfinger_map_range); litest_add(touchpad_4fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); litest_add(touchpad_4fg_clickfinger_btntool_2slots, LITEST_CLICKPAD, LITEST_ANY); litest_add(touchpad_4fg_clickfinger_btntool_3slots, LITEST_CLICKPAD, LITEST_ANY); - litest_add(touchpad_2fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY); - litest_add(touchpad_3fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY); - litest_add(touchpad_3fg_clickfinger_distance_btntool, LITEST_CLICKPAD, LITEST_ANY); + litest_add_ranged(touchpad_2fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY, &clickfinger_map_range); + litest_add_ranged(touchpad_3fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY, &clickfinger_map_range); + litest_add_ranged(touchpad_3fg_clickfinger_distance_btntool, LITEST_CLICKPAD, LITEST_ANY, &clickfinger_map_range); litest_add_for_device(touchpad_2fg_clickfinger_bottom, LITEST_SYNAPTICS_TOPBUTTONPAD); litest_add(touchpad_clickfinger_to_area_method, LITEST_CLICKPAD, LITEST_ANY); litest_add(touchpad_clickfinger_to_area_method_while_down, LITEST_CLICKPAD, LITEST_ANY); @@ -2161,6 +2284,8 @@ TEST_COLLECTION(touchpad_buttons) litest_add_ranged(touchpad_clickfinger_click_drag, LITEST_CLICKPAD, LITEST_ANY, &finger_count); litest_add(touchpad_click_defaults_clickfinger, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_click_default_clickfinger_map, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add(touchpad_click_set_clickfinger_map, LITEST_APPLE_CLICKPAD, LITEST_ANY); litest_add(touchpad_click_defaults_btnarea, LITEST_CLICKPAD, LITEST_APPLE_CLICKPAD); litest_add(touchpad_click_defaults_none, LITEST_TOUCHPAD, LITEST_CLICKPAD); litest_add(touchpad_click_defaults_none, LITEST_ANY, LITEST_TOUCHPAD); diff --git a/tools/libinput-debug-events.man b/tools/libinput-debug-events.man index 2eeefd4b..380312dd 100644 --- a/tools/libinput-debug-events.man +++ b/tools/libinput-debug-events.man @@ -88,6 +88,9 @@ Enable or disable the scroll button lock .B \-\-set\-click\-method=[none|clickfinger|buttonareas] Set the desired click method .TP 8 +.B \-\-set\-clickfinger\-map=[lrm|lmr] +Set button mapping for clickfinger +.TP 8 .B \-\-set\-scroll\-method=[none|twofinger|edge|button] Set the desired scroll method .TP 8 diff --git a/tools/shared.c b/tools/shared.c index cc8396a7..d8acadcf 100644 --- a/tools/shared.c +++ b/tools/shared.c @@ -205,6 +205,18 @@ tools_parse_option(int option, return 1; } break; + case OPT_CLICKFINGER_MAP: + if (!optarg) + return 1; + + if (streq(optarg, "lrm")) { + options->clickfinger_map = LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM; + } else if (streq(optarg, "lmr")) { + options->clickfinger_map = LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR; + } else { + return 1; + } + break; case OPT_SCROLL_METHOD: if (!optarg) return 1; @@ -499,6 +511,10 @@ tools_device_apply_config(struct libinput_device *device, if (options->click_method != (enum libinput_config_click_method)-1) libinput_device_config_click_set_method(device, options->click_method); + if (options->clickfinger_map != (enum libinput_config_clickfinger_button_map)-1) + libinput_device_config_click_set_clickfinger_button_map(device, + options->clickfinger_map); + if (options->scroll_method != (enum libinput_config_scroll_method)-1) libinput_device_config_scroll_set_method(device, options->scroll_method); diff --git a/tools/shared.h b/tools/shared.h index 45230741..a34e67bb 100644 --- a/tools/shared.h +++ b/tools/shared.h @@ -51,6 +51,7 @@ enum configuration_options { OPT_DWTP_ENABLE, OPT_DWTP_DISABLE, OPT_CLICK_METHOD, + OPT_CLICKFINGER_MAP, OPT_SCROLL_METHOD, OPT_SCROLL_BUTTON, OPT_SCROLL_BUTTON_LOCK_ENABLE, @@ -86,6 +87,7 @@ enum configuration_options { { "enable-scroll-button-lock", no_argument, 0, OPT_SCROLL_BUTTON_LOCK_ENABLE }, \ { "disable-scroll-button-lock",no_argument, 0, OPT_SCROLL_BUTTON_LOCK_DISABLE }, \ { "set-click-method", required_argument, 0, OPT_CLICK_METHOD }, \ + { "set-clickfinger-map", required_argument, 0, OPT_CLICKFINGER_MAP }, \ { "set-scroll-method", required_argument, 0, OPT_SCROLL_METHOD }, \ { "set-scroll-button", required_argument, 0, OPT_SCROLL_BUTTON }, \ { "set-profile", required_argument, 0, OPT_PROFILE }, \ @@ -113,6 +115,7 @@ struct tools_options { int left_handed; int middlebutton; enum libinput_config_click_method click_method; + enum libinput_config_clickfinger_button_map clickfinger_map; enum libinput_config_scroll_method scroll_method; enum libinput_config_tap_button_map tap_map; int scroll_button; diff --git a/tools/test_tool_option_parsing.py b/tools/test_tool_option_parsing.py index 303e3840..9c0f6287 100755 --- a/tools/test_tool_option_parsing.py +++ b/tools/test_tool_option_parsing.py @@ -218,6 +218,7 @@ options = { "set-scroll-method": ["none", "twofinger", "edge", "button"], "set-profile": ["adaptive", "flat"], "set-tap-map": ["lrm", "lmr"], + "set-clickfinger-map": ["lrm", "lmr"], }, # options with a range (and increment) "ranges": { |