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 <michael.weiser@gmx.de>
This commit is contained in:
Michael Weiser 2020-01-25 20:59:18 +01:00
parent 44a2a60dcd
commit abb82c153e
3 changed files with 74 additions and 21 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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,