dwm-torus-20240901-5687f46.diff - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
dwm-torus-20240901-5687f46.diff (7358B)
---
1 From bdd2dcfc0d33b894c4bddb00008f33abcd3478a5 Mon Sep 17 00:00:00 2001
2 From: Elizabeth Hunt <elizabeth@simponic.xyz>
3 Date: Sun, 1 Sep 2024 14:37:36 -0700
4 Subject: [PATCH] wrap the cursor around the monitor(s) like a torus!
5
6 ---
7 config.def.h | 3 ++
8 config.mk | 8 +++-
9 dwm.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++-
10 3 files changed, 128 insertions(+), 3 deletions(-)
11
12 diff --git a/config.def.h b/config.def.h
13 index 9efa774..8251624 100644
14 --- a/config.def.h
15 +++ b/config.def.h
16 @@ -114,3 +114,6 @@ static const Button buttons[] = {
17 { ClkTagBar, MODKEY, Button3, toggletag, {0} },
18 };
19
20 +/* torus config */
21 +static int torusenabled = 1;
22 +static int wormholedelta = 1; // how close to the edge do we get before we take a wormhole to the other side.
23 diff --git a/config.mk b/config.mk
24 index 8efca9a..5f7634f 100644
25 --- a/config.mk
26 +++ b/config.mk
27 @@ -14,6 +14,10 @@ X11LIB = /usr/X11R6/lib
28 XINERAMALIBS = -lXinerama
29 XINERAMAFLAGS = -DXINERAMA
30
31 +# Xinput extensions, comment if you don't want it
32 +XINPUTLIBS = -lXi
33 +XINPUTFLAGS = -DXINPUT
34 +
35 # freetype
36 FREETYPELIBS = -lfontconfig -lXft
37 FREETYPEINC = /usr/include/freetype2
38 @@ -23,10 +27,10 @@ FREETYPEINC = /usr/include/freetype2
39
40 # includes and libs
41 INCS = -I${X11INC} -I${FREETYPEINC}
42 -LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
43 +LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XINPUTLIBS}
44
45 # flags
46 -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
47 +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} ${XINPUTFLAGS}
48 #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS}
49 CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS}
50 LDFLAGS = ${LIBS}
51 diff --git a/dwm.c b/dwm.c
52 index 67c6b2b..392496e 100644
53 --- a/dwm.c
54 +++ b/dwm.c
55 @@ -39,6 +39,9 @@
56 #ifdef XINERAMA
57 #include <X11/extensions/Xinerama.h>
58 #endif /* XINERAMA */
59 +#ifdef XINPUT
60 +#include <X11/extensions/XInput2.h>
61 +#endif /* XINPUT */
62 #include <X11/Xft/Xft.h>
63
64 #include "drw.h"
65 @@ -183,12 +186,16 @@ static void mappingnotify(XEvent *e);
66 static void maprequest(XEvent *e);
67 static void monocle(Monitor *m);
68 static void motionnotify(XEvent *e);
69 +static void rawmotionnotify(XEvent *e);
70 +static void genericeventnotify(XEvent *e);
71 static void movemouse(const Arg *arg);
72 static Client *nexttiled(Client *c);
73 static void pop(Client *c);
74 static void propertynotify(XEvent *e);
75 static void quit(const Arg *arg);
76 static Monitor *recttomon(int x, int y, int w, int h);
77 +static Monitor *raycastx(Monitor *src, int y, int dx);
78 +static Monitor *raycasty(Monitor *src, int x, int dy);
79 static void resize(Client *c, int x, int y, int w, int h, int interact);
80 static void resizeclient(Client *c, int x, int y, int w, int h);
81 static void resizemouse(const Arg *arg);
82 @@ -242,6 +249,9 @@ static int sw, sh; /* X display screen geometry width, height */
83 static int bh; /* bar height */
84 static int lrpad; /* sum of left and right padding for text */
85 static int (*xerrorxlib)(Display *, XErrorEvent *);
86 +#ifdef XINPUT
87 +static int xinputextensionop;
88 +#endif /* XINPUT */
89 static unsigned int numlockmask = 0;
90 static void (*handler[LASTEvent]) (XEvent *) = {
91 [ButtonPress] = buttonpress,
92 @@ -257,7 +267,8 @@ static void (*handler[LASTEvent]) (XEvent *) = {
93 [MapRequest] = maprequest,
94 [MotionNotify] = motionnotify,
95 [PropertyNotify] = propertynotify,
96 - [UnmapNotify] = unmapnotify
97 + [UnmapNotify] = unmapnotify,
98 + [GenericEvent] = genericeventnotify,
99 };
100 static Atom wmatom[WMLast], netatom[NetLast];
101 static int running = 1;
102 @@ -1142,6 +1153,58 @@ motionnotify(XEvent *e)
103 mon = m;
104 }
105
106 +void
107 +genericeventnotify(XEvent *e)
108 +{
109 + if (e->xcookie.extension == xinputextensionop &&
110 + e->xcookie.evtype == XI_RawMotion) {
111 + rawmotionnotify(e);
112 + }
113 +}
114 +
115 +void
116 +rawmotionnotify(XEvent *e)
117 +{
118 + if (torusenabled == 0) return;
119 +
120 + int x, y;
121 + if (!getrootptr(&x, &y)) return;
122 +
123 + int warpx = x;
124 + int warpy = y;
125 + if (BETWEEN(x, selmon->mx, selmon->mx + wormholedelta)) {
126 + /* ensure there's no monitor to the left */
127 + if (recttomon(selmon->mx - 1, y, 1, 1) != selmon)
128 + return;
129 + /* take the wormhole */
130 + Monitor *farright = raycastx(selmon, y, 1);
131 + warpx = farright->mx + farright->mw - wormholedelta - 1;
132 + } else if (BETWEEN(x, selmon->mx + selmon->mw - wormholedelta,
133 + selmon->mx + selmon->mw)) {
134 + /* ensure there's no monitor to the right */
135 + if (recttomon(selmon->mx + selmon->mw + 1, y, 1, 1) != selmon)
136 + return;
137 + Monitor *farleft = raycastx(selmon, y, -1);
138 + warpx = farleft->mx + wormholedelta + 1;
139 + } else if (BETWEEN(y, selmon->my, selmon->my + wormholedelta)) {
140 + /* ensure there's no monitor under us */
141 + if (recttomon(x, y, selmon->my - 1, 1) != selmon)
142 + return;
143 + Monitor *farup = raycasty(selmon, x, 1);
144 + warpy = farup->my + farup->mh - wormholedelta - 1;
145 + } else if (BETWEEN(y, selmon->my + selmon->mh - wormholedelta,
146 + selmon->my + selmon->mh)) {
147 + /* ensure there's no monitor above us */
148 + if (recttomon(x, y, selmon->my + selmon->mh + 1, 1) != selmon)
149 + return;
150 + Monitor *fardown = raycasty(selmon, x, -1);
151 + warpy = fardown->my + wormholedelta + 1;
152 + }
153 +
154 + if (warpx != x || warpy != y)
155 + XWarpPointer(dpy, None, root, 0, 0, 0, 0, warpx, warpy);
156 +}
157 +
158 void
159 movemouse(const Arg *arg)
160 {
161 @@ -1275,6 +1338,44 @@ recttomon(int x, int y, int w, int h)
162 return r;
163 }
164
165 +Monitor *
166 +raycastx(Monitor *src, int y, int dx)
167 +{
168 + Monitor *farthest = src;
169 + for (Monitor *m = mons; m; m = m->next) {
170 + int scansy = BETWEEN(y, m->my, m->my + m->mh);
171 + if (!scansy) {
172 + continue;
173 + }
174 + if (dx == 1 && (m->mx + m->mw > farthest->mx + farthest->mw)) {
175 + farthest = m;
176 + }
177 + if (dx == -1 && (m->mx < farthest->mx)) {
178 + farthest = m;
179 + }
180 + }
181 + return farthest;
182 +}
183 +
184 +Monitor *
185 +raycasty(Monitor *src, int x, int dy)
186 +{
187 + Monitor *farthest = src;
188 + for (Monitor *m = mons; m; m = m->next) {
189 + int scansx = BETWEEN(x, m->mx, m->mx + m->mw);
190 + if (!scansx) {
191 + continue;
192 + }
193 + if (dy == 1 && (m->my + m->mh > farthest->my + farthest->mh)) {
194 + farthest = m;
195 + }
196 + if (dy == -1 && (m->my < farthest->my)) {
197 + farthest = m;
198 + }
199 + }
200 + return farthest;
201 +}
202 +
203 void
204 resize(Client *c, int x, int y, int w, int h, int interact)
205 {
206 @@ -1609,6 +1710,23 @@ setup(void)
207 |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
208 XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
209 XSelectInput(dpy, root, wa.event_mask);
210 +#ifdef XINPUT
211 + /* select XInput raw motion events; we can't hook into PointerMotionMask since some windows block it. */
212 + size_t maskbyteslen = XIMaskLen(XI_RawMotion);
213 + unsigned char *maskbytes = calloc(maskbyteslen, sizeof(unsigned char));
214 + XISetMask(maskbytes, XI_RawMotion);
215 + XIEventMask mask;
216 + int _unused;
217 + if (!XQueryExtension(dpy, "XInputExtension", &xinputextensionop,
218 + &_unused, &_unused)) {
219 + fprintf(stderr, "XInputExtension not found");
220 + exit(1);
221 + }
222 + mask.deviceid = XIAllMasterDevices;
223 + mask.mask_len = maskbyteslen * sizeof(unsigned char);
224 + mask.mask = maskbytes;
225 + XISelectEvents(dpy, root, &mask, 1);
226 +#endif /* XINPUT */
227 grabkeys();
228 focus(NULL);
229 }
230 --
231 2.46.0
232