summaryrefslogtreecommitdiffstats
path: root/patches/gestures.patch
blob: 4f743252595533026b4392db344724e600a8f13a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
From 42f97e88bd901d81b81da61c44a790b583706308 Mon Sep 17 00:00:00 2001
From: wochap <gean.marroquin@gmail.com>
Date: Fri, 5 Jul 2024 11:18:49 -0500
Subject: [PATCH] implement gestures

---
 config.def.h |  9 +++++++
 dwl.c        | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 77 insertions(+)

diff --git a/config.def.h b/config.def.h
index 22d2171..8b75564 100644
--- a/config.def.h
+++ b/config.def.h
@@ -14,6 +14,8 @@ static const float urgentcolor[]           = COLOR(0xff0000ff);
 /* This conforms to the xdg-protocol. Set the alpha to zero to restore the old behavior */
 static const float fullscreen_bg[]         = {0.1f, 0.1f, 0.1f, 1.0f}; /* You can also use glsl colors */
 
+static const unsigned int swipe_min_threshold = 0;
+
 /* tagging - TAGCOUNT must be no greater than 31 */
 #define TAGCOUNT (9)
 
@@ -174,3 +176,10 @@ static const Button buttons[] = {
 	{ MODKEY, BTN_MIDDLE, togglefloating, {0} },
 	{ MODKEY, BTN_RIGHT,  moveresize,     {.ui = CurResize} },
 };
+
+static const Gesture gestures[] = {
+	// { MODKEY, SWIPE_LEFT, 4, shiftview, { .i = 1 } },
+	// { MODKEY, SWIPE_RIGHT, 4, shiftview, { .i = -1 } },
+	{ MODKEY, SWIPE_UP, 3, focusstack, {.i = 1} },
+	{ MODKEY, SWIPE_DOWN, 3, focusstack, {.i = -1} },
+};
diff --git a/dwl.c b/dwl.c
index ded83e2..5d861e8 100644
--- a/dwl.c
+++ b/dwl.c
@@ -88,6 +88,7 @@ enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrBlock,
 enum { NetWMWindowTypeDialog, NetWMWindowTypeSplash, NetWMWindowTypeToolbar,
 	NetWMWindowTypeUtility, NetLast }; /* EWMH atoms */
 #endif
+enum { SWIPE_LEFT, SWIPE_RIGHT, SWIPE_DOWN, SWIPE_UP };
 
 typedef union {
 	int i;
@@ -103,6 +104,14 @@ typedef struct {
 	const Arg arg;
 } Button;
 
+typedef struct {
+	unsigned int mod;
+	unsigned int motion;
+	unsigned int fingers_count;
+	void (*func)(const Arg *);
+	const Arg arg;
+} Gesture;
+
 typedef struct Monitor Monitor;
 typedef struct {
 	/* Must keep these three elements in this order */
@@ -251,6 +260,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
 static void arrangelayers(Monitor *m);
 static void axisnotify(struct wl_listener *listener, void *data);
 static void buttonpress(struct wl_listener *listener, void *data);
+static int ongesture(struct wlr_pointer_swipe_end_event *event);
 static void swipe_begin(struct wl_listener *listener, void *data);
 static void swipe_update(struct wl_listener *listener, void *data);
 static void swipe_end(struct wl_listener *listener, void *data);
@@ -416,6 +426,10 @@ static struct wlr_box sgeom;
 static struct wl_list mons;
 static Monitor *selmon;
 
+static uint32_t swipe_fingers = 0;
+static double swipe_dx = 0;
+static double swipe_dy = 0;
+
 #ifdef XWAYLAND
 static void activatex11(struct wl_listener *listener, void *data);
 static void associatex11(struct wl_listener *listener, void *data);
@@ -435,6 +449,8 @@ static xcb_atom_t netatom[NetLast];
 /* attempt to encapsulate suck into one file */
 #include "client.h"
 
+static const unsigned int abzsquare = swipe_min_threshold * swipe_min_threshold;
+
 /* function implementations */
 void
 applybounds(Client *c, struct wlr_box *bbox)
@@ -657,6 +673,11 @@ swipe_begin(struct wl_listener *listener, void *data)
 {
 	struct wlr_pointer_swipe_begin_event *event = data;
 
+	swipe_fingers = event->fingers;
+	// Reset swipe distance at the beginning of a swipe
+	swipe_dx = 0;
+	swipe_dy = 0;
+
 	// Forward swipe begin event to client
 	wlr_pointer_gestures_v1_send_swipe_begin(
 		pointer_gestures, 
@@ -671,6 +692,11 @@ swipe_update(struct wl_listener *listener, void *data)
 {
 	struct wlr_pointer_swipe_update_event *event = data;
 
+	swipe_fingers = event->fingers;
+	// Accumulate swipe distance
+	swipe_dx += event->dx;
+	swipe_dy += event->dy;
+
 	// Forward swipe update event to client
 	wlr_pointer_gestures_v1_send_swipe_update(
 		pointer_gestures, 
@@ -681,11 +707,53 @@ swipe_update(struct wl_listener *listener, void *data)
 	);
 }
 
+int
+ongesture(struct wlr_pointer_swipe_end_event *event)
+{
+	struct wlr_keyboard *keyboard;
+	uint32_t mods;
+	const Gesture *g;
+	unsigned int motion;
+	unsigned int adx = (int)round(fabs(swipe_dx));
+	unsigned int ady = (int)round(fabs(swipe_dy));
+	int handled = 0;
+
+	if (event->cancelled) {
+		return handled;
+	}
+
+	// Require absolute distance movement beyond a small thresh-hold
+	if (adx * adx + ady * ady < abzsquare) {
+		return handled;
+	}
+
+	if (adx > ady) {
+		motion = swipe_dx < 0 ? SWIPE_LEFT : SWIPE_RIGHT;
+	} else {
+		motion = swipe_dy < 0 ? SWIPE_UP : SWIPE_DOWN;
+	}
+
+	keyboard = wlr_seat_get_keyboard(seat);
+	mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
+	for (g = gestures; g < END(gestures); g++) {
+		if (CLEANMASK(mods) == CLEANMASK(g->mod) &&
+			 swipe_fingers == g->fingers_count &&
+			 motion == g->motion && g->func) {
+			g->func(&g->arg);
+			handled = 1;
+		}
+	}
+	return handled;
+}
+
 void
 swipe_end(struct wl_listener *listener, void *data)
 {
 	struct wlr_pointer_swipe_end_event *event = data;
 
+	// TODO: should we stop here if the event has been handled?
+	ongesture(event);
+
 	// Forward swipe end event to client
 	wlr_pointer_gestures_v1_send_swipe_end(
 		pointer_gestures, 
-- 
2.45.1