sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit 6a26f248d47459aee153025e93c5de908550ed70
parent e9adab1822735457f42e8bb681f051c9269116e9
Author: Elizabeth Hunt <elizabeth@simponic.xyz>
Date:   Sun,  1 Sep 2024 14:47:58 -0700

add a patch which wraps the cursor around monitors

Diffstat:
Adwm.suckless.org/patches/torus/demo.gif | 0
Adwm.suckless.org/patches/torus/dwm-torus-20240901-5687f46.diff | 232+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adwm.suckless.org/patches/torus/index.md | 16++++++++++++++++
3 files changed, 248 insertions(+), 0 deletions(-)

diff --git a/dwm.suckless.org/patches/torus/demo.gif b/dwm.suckless.org/patches/torus/demo.gif Binary files differ. diff --git a/dwm.suckless.org/patches/torus/dwm-torus-20240901-5687f46.diff b/dwm.suckless.org/patches/torus/dwm-torus-20240901-5687f46.diff @@ -0,0 +1,232 @@ +From bdd2dcfc0d33b894c4bddb00008f33abcd3478a5 Mon Sep 17 00:00:00 2001 +From: Elizabeth Hunt <elizabeth@simponic.xyz> +Date: Sun, 1 Sep 2024 14:37:36 -0700 +Subject: [PATCH] wrap the cursor around the monitor(s) like a torus! + +--- + config.def.h | 3 ++ + config.mk | 8 +++- + dwm.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 128 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..8251624 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -114,3 +114,6 @@ static const Button buttons[] = { + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; + ++/* torus config */ ++static int torusenabled = 1; ++static int wormholedelta = 1; // how close to the edge do we get before we take a wormhole to the other side. +diff --git a/config.mk b/config.mk +index 8efca9a..5f7634f 100644 +--- a/config.mk ++++ b/config.mk +@@ -14,6 +14,10 @@ X11LIB = /usr/X11R6/lib + XINERAMALIBS = -lXinerama + XINERAMAFLAGS = -DXINERAMA + ++# Xinput extensions, comment if you don't want it ++XINPUTLIBS = -lXi ++XINPUTFLAGS = -DXINPUT ++ + # freetype + FREETYPELIBS = -lfontconfig -lXft + FREETYPEINC = /usr/include/freetype2 +@@ -23,10 +27,10 @@ FREETYPEINC = /usr/include/freetype2 + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XINPUTLIBS} + + # flags +-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} ++CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} ${XINPUTFLAGS} + #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} + CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} + LDFLAGS = ${LIBS} +diff --git a/dwm.c b/dwm.c +index 67c6b2b..392496e 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -39,6 +39,9 @@ + #ifdef XINERAMA + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ ++#ifdef XINPUT ++#include <X11/extensions/XInput2.h> ++#endif /* XINPUT */ + #include <X11/Xft/Xft.h> + + #include "drw.h" +@@ -183,12 +186,16 @@ static void mappingnotify(XEvent *e); + static void maprequest(XEvent *e); + static void monocle(Monitor *m); + static void motionnotify(XEvent *e); ++static void rawmotionnotify(XEvent *e); ++static void genericeventnotify(XEvent *e); + static void movemouse(const Arg *arg); + static Client *nexttiled(Client *c); + static void pop(Client *c); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); + static Monitor *recttomon(int x, int y, int w, int h); ++static Monitor *raycastx(Monitor *src, int y, int dx); ++static Monitor *raycasty(Monitor *src, int x, int dy); + static void resize(Client *c, int x, int y, int w, int h, int interact); + static void resizeclient(Client *c, int x, int y, int w, int h); + static void resizemouse(const Arg *arg); +@@ -242,6 +249,9 @@ static int sw, sh; /* X display screen geometry width, height */ + static int bh; /* bar height */ + static int lrpad; /* sum of left and right padding for text */ + static int (*xerrorxlib)(Display *, XErrorEvent *); ++#ifdef XINPUT ++static int xinputextensionop; ++#endif /* XINPUT */ + static unsigned int numlockmask = 0; + static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, +@@ -257,7 +267,8 @@ static void (*handler[LASTEvent]) (XEvent *) = { + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, +- [UnmapNotify] = unmapnotify ++ [UnmapNotify] = unmapnotify, ++ [GenericEvent] = genericeventnotify, + }; + static Atom wmatom[WMLast], netatom[NetLast]; + static int running = 1; +@@ -1142,6 +1153,58 @@ motionnotify(XEvent *e) + mon = m; + } + ++void ++genericeventnotify(XEvent *e) ++{ ++ if (e->xcookie.extension == xinputextensionop && ++ e->xcookie.evtype == XI_RawMotion) { ++ rawmotionnotify(e); ++ } ++} ++ ++void ++rawmotionnotify(XEvent *e) ++{ ++ if (torusenabled == 0) return; ++ ++ int x, y; ++ if (!getrootptr(&x, &y)) return; ++ ++ int warpx = x; ++ int warpy = y; ++ if (BETWEEN(x, selmon->mx, selmon->mx + wormholedelta)) { ++ /* ensure there's no monitor to the left */ ++ if (recttomon(selmon->mx - 1, y, 1, 1) != selmon) ++ return; ++ /* take the wormhole */ ++ Monitor *farright = raycastx(selmon, y, 1); ++ warpx = farright->mx + farright->mw - wormholedelta - 1; ++ } else if (BETWEEN(x, selmon->mx + selmon->mw - wormholedelta, ++ selmon->mx + selmon->mw)) { ++ /* ensure there's no monitor to the right */ ++ if (recttomon(selmon->mx + selmon->mw + 1, y, 1, 1) != selmon) ++ return; ++ Monitor *farleft = raycastx(selmon, y, -1); ++ warpx = farleft->mx + wormholedelta + 1; ++ } else if (BETWEEN(y, selmon->my, selmon->my + wormholedelta)) { ++ /* ensure there's no monitor under us */ ++ if (recttomon(x, y, selmon->my - 1, 1) != selmon) ++ return; ++ Monitor *farup = raycasty(selmon, x, 1); ++ warpy = farup->my + farup->mh - wormholedelta - 1; ++ } else if (BETWEEN(y, selmon->my + selmon->mh - wormholedelta, ++ selmon->my + selmon->mh)) { ++ /* ensure there's no monitor above us */ ++ if (recttomon(x, y, selmon->my + selmon->mh + 1, 1) != selmon) ++ return; ++ Monitor *fardown = raycasty(selmon, x, -1); ++ warpy = fardown->my + wormholedelta + 1; ++ } ++ ++ if (warpx != x || warpy != y) ++ XWarpPointer(dpy, None, root, 0, 0, 0, 0, warpx, warpy); ++} ++ + void + movemouse(const Arg *arg) + { +@@ -1275,6 +1338,44 @@ recttomon(int x, int y, int w, int h) + return r; + } + ++Monitor * ++raycastx(Monitor *src, int y, int dx) ++{ ++ Monitor *farthest = src; ++ for (Monitor *m = mons; m; m = m->next) { ++ int scansy = BETWEEN(y, m->my, m->my + m->mh); ++ if (!scansy) { ++ continue; ++ } ++ if (dx == 1 && (m->mx + m->mw > farthest->mx + farthest->mw)) { ++ farthest = m; ++ } ++ if (dx == -1 && (m->mx < farthest->mx)) { ++ farthest = m; ++ } ++ } ++ return farthest; ++} ++ ++Monitor * ++raycasty(Monitor *src, int x, int dy) ++{ ++ Monitor *farthest = src; ++ for (Monitor *m = mons; m; m = m->next) { ++ int scansx = BETWEEN(x, m->mx, m->mx + m->mw); ++ if (!scansx) { ++ continue; ++ } ++ if (dy == 1 && (m->my + m->mh > farthest->my + farthest->mh)) { ++ farthest = m; ++ } ++ if (dy == -1 && (m->my < farthest->my)) { ++ farthest = m; ++ } ++ } ++ return farthest; ++} ++ + void + resize(Client *c, int x, int y, int w, int h, int interact) + { +@@ -1609,6 +1710,23 @@ setup(void) + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); + XSelectInput(dpy, root, wa.event_mask); ++#ifdef XINPUT ++ /* select XInput raw motion events; we can't hook into PointerMotionMask since some windows block it. */ ++ size_t maskbyteslen = XIMaskLen(XI_RawMotion); ++ unsigned char *maskbytes = calloc(maskbyteslen, sizeof(unsigned char)); ++ XISetMask(maskbytes, XI_RawMotion); ++ XIEventMask mask; ++ int _unused; ++ if (!XQueryExtension(dpy, "XInputExtension", &xinputextensionop, ++ &_unused, &_unused)) { ++ fprintf(stderr, "XInputExtension not found"); ++ exit(1); ++ } ++ mask.deviceid = XIAllMasterDevices; ++ mask.mask_len = maskbyteslen * sizeof(unsigned char); ++ mask.mask = maskbytes; ++ XISelectEvents(dpy, root, &mask, 1); ++#endif /* XINPUT */ + grabkeys(); + focus(NULL); + } +-- +2.46.0 + diff --git a/dwm.suckless.org/patches/torus/index.md b/dwm.suckless.org/patches/torus/index.md @@ -0,0 +1,16 @@ +torus +================ + +Description +----------- +This patch wraps your mouse cursor around the screen as if it were a torus, inspired by [taralli](https://github.com/kmcallister/taralli). + +![a short repeating demo of the torus patch on two oddly stacked monitors to show edge cases](demo.gif) + +Download +-------- +* [dwm-torus-20240901-5687f46.diff](dwm-torus-20240901-5687f46.diff) + +Authors +------- +* Elizabeth Hunt - <elizabeth@simponic.xyz>