From 97f5f9381208532bcee33c62b8de59b786e91ce4 Mon Sep 17 00:00:00 2001
From: Consolatis <35009135+Consolatis@users.noreply.github.com>
Date: Sun, 18 May 2025 04:41:57 +0200
Subject: [PATCH] [proof-of-concept] add swipe mousebinds
Use like
```xml
```
---
include/config/mousebind.h | 4 +++
src/config/mousebind.c | 5 +++-
src/config/rcxml.c | 3 +++
src/input/gestures.c | 53 ++++++++++++++++++++++++++++++++++++++
4 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/include/config/mousebind.h b/include/config/mousebind.h
index b86ed4e7..47ebfd86 100644
--- a/include/config/mousebind.h
+++ b/include/config/mousebind.h
@@ -14,6 +14,7 @@ enum mouse_event {
MOUSE_ACTION_RELEASE,
MOUSE_ACTION_DRAG,
MOUSE_ACTION_SCROLL,
+ MOUSE_ACTION_SWIPE,
};
enum direction {
@@ -30,6 +31,9 @@ struct mousebind {
/* ex: BTN_LEFT, BTN_RIGHT from linux/input_event_codes.h */
uint32_t button;
+ /* used for MOUSE_ACTION_SWIPE */
+ uint32_t fingers;
+
/* scroll direction; considered instead of button for scroll events */
enum direction direction;
diff --git a/src/config/mousebind.c b/src/config/mousebind.c
index 6b5254f3..0e5db5de 100644
--- a/src/config/mousebind.c
+++ b/src/config/mousebind.c
@@ -98,6 +98,8 @@ mousebind_event_from_str(const char *str)
return MOUSE_ACTION_DRAG;
} else if (!strcasecmp(str, "scroll")) {
return MOUSE_ACTION_SCROLL;
+ } else if (!strcasecmp(str, "swipe")) {
+ return MOUSE_ACTION_SWIPE;
}
wlr_log(WLR_ERROR, "unknown mouse action (%s)", str);
return MOUSE_ACTION_NONE;
@@ -111,7 +113,8 @@ mousebind_the_same(struct mousebind *a, struct mousebind *b)
&& a->button == b->button
&& a->direction == b->direction
&& a->mouse_event == b->mouse_event
- && a->modifiers == b->modifiers;
+ && a->modifiers == b->modifiers
+ && a->fingers == b->fingers;
}
struct mousebind *
diff --git a/src/config/rcxml.c b/src/config/rcxml.c
index dc11b1c8..a407b41b 100644
--- a/src/config/rcxml.c
+++ b/src/config/rcxml.c
@@ -591,6 +591,9 @@ fill_mousebind(xmlNode *node, const char *context)
mousebind->direction = mousebind_direction_from_str(
buf, &mousebind->modifiers);
}
+ if (lab_xml_get_string(node, "fingers", buf, sizeof(buf))) {
+ mousebind->fingers = atoi(buf);
+ }
if (lab_xml_get_string(node, "action", buf, sizeof(buf))) {
/* */
mousebind->mouse_event = mousebind_event_from_str(buf);
diff --git a/src/input/gestures.c b/src/input/gestures.c
index b40da82c..6d513fc5 100644
--- a/src/input/gestures.c
+++ b/src/input/gestures.c
@@ -2,10 +2,20 @@
#include "input/gestures.h"
#include
#include
+#include "action.h"
#include "common/macros.h"
+#include "config/mousebind.h"
+#include "config/rcxml.h"
+#include "input/gestures.h"
#include "labwc.h"
#include "idle.h"
+static struct {
+ double dx;
+ double dy;
+ uint32_t fingers;
+} swipe_state;
+
static void
handle_pinch_begin(struct wl_listener *listener, void *data)
{
@@ -57,6 +67,10 @@ handle_swipe_begin(struct wl_listener *listener, void *data)
wlr_pointer_gestures_v1_send_swipe_begin(seat->pointer_gestures,
seat->seat, event->time_msec, event->fingers);
+
+ swipe_state.dx = 0;
+ swipe_state.dy = 0;
+ swipe_state.fingers = event->fingers;
}
static void
@@ -70,6 +84,14 @@ handle_swipe_update(struct wl_listener *listener, void *data)
wlr_pointer_gestures_v1_send_swipe_update(seat->pointer_gestures,
seat->seat, event->time_msec, event->dx, event->dy);
+
+ if (swipe_state.fingers == event->fingers) {
+ swipe_state.dx += event->dx;
+ swipe_state.dy += event->dy;
+ } else {
+ swipe_state.dx = 0;
+ swipe_state.dy = 0;
+ }
}
static void
@@ -83,6 +105,37 @@ handle_swipe_end(struct wl_listener *listener, void *data)
wlr_pointer_gestures_v1_send_swipe_end(seat->pointer_gestures,
seat->seat, event->time_msec, event->cancelled);
+
+ // TODO: check for !event->cancelled ?
+ if (swipe_state.dx || swipe_state.dy) {
+ enum direction direction;
+ if (swipe_state.dx * swipe_state.dx > swipe_state.dy * swipe_state.dy) {
+ direction = swipe_state.dx > 0
+ ? LAB_DIRECTION_RIGHT
+ : LAB_DIRECTION_LEFT;
+ } else {
+ direction = swipe_state.dy > 0
+ ? LAB_DIRECTION_DOWN
+ : LAB_DIRECTION_UP;
+ }
+ struct mousebind *mousebind;
+ wl_list_for_each(mousebind, &rc.mousebinds, link) {
+ if (mousebind->mouse_event != MOUSE_ACTION_SWIPE) {
+ continue;
+ }
+ if (mousebind->fingers != swipe_state.fingers) {
+ continue;
+ }
+ if (mousebind->direction != direction) {
+ continue;
+ }
+ actions_run(/*view*/ NULL, seat->server,
+ &mousebind->actions, /*cursor_ctx*/ NULL);
+ }
+ }
+ swipe_state.dx = 0;
+ swipe_state.dy = 0;
+ swipe_state.fingers = 0;
}
static void