From abb82c153ed8ad2ce2335739826b4ef46ef83bd3 Mon Sep 17 00:00:00 2001 From: Michael Weiser Date: Sat, 25 Jan 2020 20:59:18 +0100 Subject: [PATCH] input: Extend swipe gesture support to finger count Swipe pointer gesture bindings added in an earlier commit would catch swipes indiscriminately, ignoring the number of fingers used. Add the necessary logic to distinguish three- from four-finger swipes. Other finger counts cannot be bound to and are passed through to clients. Continue to trivially map each dimension of a gesture to discrete pseudo button codes considering that we're unlikely to take this much further and would otherwise need to extend struct sway_binding to carry some kind of button-specific internal data. Test plan: - add workspace switching to config like so: bindsym --whole-window SWIPE_3_LEFT workspace prev_on_output bindsym --whole-window SWIPE_4_RIGHT workspace next_on_output - start sway and open two workspaces - switch back and forth using horizontal three- and four-finger swipes, observing that different finger counts are necessary per direction Signed-off-by: Michael Weiser --- include/sway/input/cursor.h | 13 +++++++---- sway/input/cursor.c | 37 +++++++++++++++++++----------- sway/input/seatop_default.c | 45 +++++++++++++++++++++++++++++++++---- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 0727ccfc6..31d47ac81 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -14,10 +14,15 @@ #define SWAY_SCROLL_DOWN KEY_MAX + 2 #define SWAY_SCROLL_LEFT KEY_MAX + 3 #define SWAY_SCROLL_RIGHT KEY_MAX + 4 -#define SWAY_SWIPE_UP KEY_MAX + 5 -#define SWAY_SWIPE_DOWN KEY_MAX + 6 -#define SWAY_SWIPE_LEFT KEY_MAX + 7 -#define SWAY_SWIPE_RIGHT KEY_MAX + 8 + +#define SWAY_SWIPE_DIR_UP 0 +#define SWAY_SWIPE_DIR_DOWN 1 +#define SWAY_SWIPE_DIR_LEFT 2 +#define SWAY_SWIPE_DIR_RIGHT 3 +#define SWAY_SWIPE_DIR_COUNT 4 + +#define SWAY_SWIPE_3 SWAY_SCROLL_RIGHT + 1 +#define SWAY_SWIPE_4 SWAY_SWIPE_3 + SWAY_SWIPE_DIR_COUNT struct sway_cursor { struct sway_seat *seat; diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 83ab5c6f4..69b7a825d 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -1222,11 +1222,14 @@ uint32_t get_mouse_bindsym(const char *name, char **error) { uint32_t button; const char *dir; } swipes[] = { - SWAY_SWIPE_UP, "UP", - SWAY_SWIPE_DOWN, "DOWN", - SWAY_SWIPE_LEFT, "LEFT", - SWAY_SWIPE_RIGHT, "RIGHT", - 0, NULL, + SWAY_SWIPE_3 + SWAY_SWIPE_DIR_UP, "3_UP", + SWAY_SWIPE_3 + SWAY_SWIPE_DIR_DOWN, "3_DOWN", + SWAY_SWIPE_3 + SWAY_SWIPE_DIR_LEFT, "3_LEFT", + SWAY_SWIPE_3 + SWAY_SWIPE_DIR_RIGHT, "3_RIGHT", + SWAY_SWIPE_4 + SWAY_SWIPE_DIR_UP, "4_UP", + SWAY_SWIPE_4 + SWAY_SWIPE_DIR_DOWN, "4_DOWN", + SWAY_SWIPE_4 + SWAY_SWIPE_DIR_LEFT, "4_LEFT", + SWAY_SWIPE_4 + SWAY_SWIPE_DIR_RIGHT, "4_RIGHT", 0, NULL, }, *sp; const char *dir = &name[strlen("SWIPE_")]; @@ -1303,14 +1306,22 @@ const char *get_mouse_button_name(uint32_t button) { name = "SWAY_SCROLL_LEFT"; } else if (button == SWAY_SCROLL_RIGHT) { name = "SWAY_SCROLL_RIGHT"; - } else if (button == SWAY_SWIPE_UP) { - name = "SWAY_SWIPE_UP"; - } else if (button == SWAY_SWIPE_DOWN) { - name = "SWAY_SWIPE_DOWN"; - } else if (button == SWAY_SWIPE_LEFT) { - name = "SWAY_SWIPE_LEFT"; - } else if (button == SWAY_SWIPE_RIGHT) { - name = "SWAY_SWIPE_RIGHT"; + } else if (button == SWAY_SWIPE_3 + SWAY_SWIPE_DIR_UP) { + name = "SWAY_SWIPE_3_UP"; + } else if (button == SWAY_SWIPE_3 + SWAY_SWIPE_DIR_DOWN) { + name = "SWAY_SWIPE_3_DOWN"; + } else if (button == SWAY_SWIPE_3 + SWAY_SWIPE_DIR_LEFT) { + name = "SWAY_SWIPE_3_LEFT"; + } else if (button == SWAY_SWIPE_3 + SWAY_SWIPE_DIR_RIGHT) { + name = "SWAY_SWIPE_3_RIGHT"; + } else if (button == SWAY_SWIPE_4 + SWAY_SWIPE_DIR_UP) { + name = "SWAY_SWIPE_4_UP"; + } else if (button == SWAY_SWIPE_4 + SWAY_SWIPE_DIR_DOWN) { + name = "SWAY_SWIPE_4_DOWN"; + } else if (button == SWAY_SWIPE_4 + SWAY_SWIPE_DIR_LEFT) { + name = "SWAY_SWIPE_4_LEFT"; + } else if (button == SWAY_SWIPE_4 + SWAY_SWIPE_DIR_RIGHT) { + name = "SWAY_SWIPE_4_RIGHT"; } } return name; diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c index 963726e6d..bf8ff9189 100644 --- a/sway/input/seatop_default.c +++ b/sway/input/seatop_default.c @@ -21,6 +21,7 @@ struct seatop_default_event { uint32_t pressed_buttons[SWAY_CURSOR_PRESSED_BUTTONS_CAP]; size_t pressed_button_count; bool swiping; + uint8_t swipe_fingers; double swipe_travel_x, swipe_travel_y; }; @@ -749,6 +750,16 @@ static void handle_pointer_axis(struct sway_seat *seat, } } +static uint32_t swipe_button_base(uint8_t fingers) { + if (fingers == 3) { + return SWAY_SWIPE_3; + } else if (fingers == 4) { + return SWAY_SWIPE_4; + } + + return 0; +} + static void handle_swipe_begin(struct sway_seat *seat, struct wlr_event_pointer_swipe_begin *event) { struct sway_input_device *input_device = @@ -778,6 +789,13 @@ static void handle_swipe_begin(struct sway_seat *seat, input_device ? input_device->wlr_device : NULL; char *dev_id = device ? input_device_get_identifier(device) : strdup("*"); + // zero for both turns below loop into a no-op + uint32_t button_base = swipe_button_base(event->fingers); + uint32_t button_end = 0; + if (button_base != 0) { + button_end = button_base + SWAY_SWIPE_DIR_COUNT; + } + /** * Handle mouse bindings - if there's any swipe bindings for this * context. Here we must swallow all swipes if there's even one @@ -789,8 +807,7 @@ static void handle_swipe_begin(struct sway_seat *seat, * is at least one binding. */ struct sway_binding *binding = NULL; - for (uint32_t button = SWAY_SWIPE_UP; button <= SWAY_SWIPE_RIGHT; - button++) { + for (uint32_t button = button_base; button < button_end; button++) { state_add_button(e, button); // check for an on-press binding binding = get_active_mouse_binding(e, @@ -816,6 +833,7 @@ static void handle_swipe_begin(struct sway_seat *seat, if (handled) { // mark this as ours and start tracking e->swiping = true; + e->swipe_fingers = event->fingers; e->swipe_travel_x = 0; e->swipe_travel_y = 0; } @@ -834,6 +852,13 @@ static void handle_swipe_update(struct sway_seat *seat, // is this ours? if (e->swiping) { + // libinput does not do this. Instead the current swipe is + // cancelled and a new one started. But better be safe. + if (e->swipe_fingers != event->fingers) { + sway_log(SWAY_DEBUG, "Ignoring changed finger count mid-swipe"); + return; + } + e->swipe_travel_x += event->dx; e->swipe_travel_y += event->dy; return; @@ -847,11 +872,23 @@ static void handle_swipe_update(struct sway_seat *seat, } static uint32_t swipe_to_button(struct seatop_default_event *event) { + uint8_t direction; if (fabs(event->swipe_travel_x) > fabs(event->swipe_travel_y)) { - return event->swipe_travel_x > 0 ? SWAY_SWIPE_RIGHT : SWAY_SWIPE_LEFT; + if (event->swipe_travel_x > 0) { + direction = SWAY_SWIPE_DIR_RIGHT; + } else { + direction = SWAY_SWIPE_DIR_LEFT; + } + } else { + if (event->swipe_travel_y > 0) { + direction = SWAY_SWIPE_DIR_DOWN; + } else { + direction = SWAY_SWIPE_DIR_UP; + } } - return event->swipe_travel_y > 0 ? SWAY_SWIPE_DOWN : SWAY_SWIPE_UP; + uint32_t button_base = swipe_button_base(event->swipe_fingers); + return button_base + direction; } static void handle_swipe_end(struct sway_seat *seat,