sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | 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