diff --git a/dwm/dwm-banish-6.4.diff b/dwm/dwm-banish-6.4.diff new file mode 100644 index 0000000..6924fb4 --- /dev/null +++ b/dwm/dwm-banish-6.4.diff @@ -0,0 +1,331 @@ +From 15f09e0e690328cb7bfd35b577435cba7b2e4859 Mon Sep 17 00:00:00 2001 +From: Bakkeby +Date: Mon, 12 Jun 2023 15:17:51 +0200 +Subject: [PATCH] Banish patch - behaviour similiar to xbanish and unclutter + +--- + config.mk | 6 ++- + dwm.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 149 insertions(+), 7 deletions(-) + +diff --git a/config.mk b/config.mk +index ef8acf7..ae0a7f3 100644 +--- a/config.mk ++++ b/config.mk +@@ -14,6 +14,10 @@ X11LIB = /usr/X11R6/lib + XINERAMALIBS = -lXinerama + XINERAMAFLAGS = -DXINERAMA + ++# Banish: dependency on libxi and libxfixes for mouse related features ++XINPUTLIBS = -lXi ++XFIXESLIBS = -lXfixes ++ + # freetype + FREETYPELIBS = -lfontconfig -lXft + FREETYPEINC = /usr/include/freetype2 +@@ -23,7 +27,7 @@ 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} ${XFIXESLIBS} + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index e5efb6a..bb7760b 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -39,6 +40,8 @@ + #ifdef XINERAMA + #include + #endif /* XINERAMA */ ++#include ++#include + #include + + #include "drw.h" +@@ -49,6 +52,8 @@ + #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) + #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) ++#define INTERSECTC(X,Y,W,H,Z) (MAX(0, MIN((X)+(W),(Z)->x+(Z)->w) - MAX((X),(Z)->x)) \ ++ * MAX(0, MIN((Y)+(H),(Z)->y+(Z)->h) - MAX((Y),(Z)->y))) + #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) +@@ -169,12 +174,14 @@ static void focus(Client *c); + static void focusin(XEvent *e); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); ++static void genericevent(XEvent *e); + static Atom getatomprop(Client *c, Atom prop); + static int getrootptr(int *x, int *y); + static long getstate(Window w); + static int gettextprop(Window w, Atom atom, char *text, unsigned int size); + static void grabbuttons(Client *c, int focused); + static void grabkeys(void); ++static void hidecursor(const Arg *arg); + static void incnmaster(const Arg *arg); + static void keypress(XEvent *e); + static void killclient(const Arg *arg); +@@ -185,9 +192,11 @@ static void monocle(Monitor *m); + static void motionnotify(XEvent *e); + static void movemouse(const Arg *arg); + static Client *nexttiled(Client *c); ++static unsigned long long now(void); + static void pop(Client *c); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); ++static Client *recttoclient(int x, int y, int w, int h, int include_floating); + static Monitor *recttomon(int x, int y, int w, int h); + 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); +@@ -204,6 +213,7 @@ static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); + static void seturgent(Client *c, int urg); ++static void showcursor(const Arg *arg); + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); +@@ -244,6 +254,14 @@ static int bh; /* bar height */ + static int lrpad; /* sum of left and right padding for text */ + static int (*xerrorxlib)(Display *, XErrorEvent *); + static unsigned int numlockmask = 0; ++static int cursor_hidden = 0; ++/* mouse_x and mouse_y are used to store the actual co-ordinates of the mouse cursor when ++ * hidden. These can be manipulated freely, e.g. when using the warp patch, to set a new ++ * cursor position for when the cursor is to be revealed again. */ ++static int mouse_x = 0; ++static int mouse_y = 0; ++static int xi_opcode; ++static unsigned long long last_button_press = 0; + static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, +@@ -252,6 +270,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [Expose] = expose, ++ [GenericEvent] = genericevent, + [FocusIn] = focusin, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, +@@ -432,7 +451,20 @@ buttonpress(XEvent *e) + selmon = m; + focus(NULL); + } +- if (ev->window == selmon->barwin) { ++ ++ c = wintoclient(ev->window); ++ ++ if (!c && cursor_hidden) { ++ c = recttoclient(mouse_x, mouse_y, 1, 1, 1); ++ showcursor(NULL); ++ } ++ ++ if (c) { ++ focus(c); ++ restack(selmon); ++ XAllowEvents(dpy, ReplayPointer, CurrentTime); ++ click = ClkClientWin; ++ } else if (ev->window == selmon->barwin) { + i = x = 0; + do + x += TEXTW(tags[i]); +@@ -446,16 +478,14 @@ buttonpress(XEvent *e) + click = ClkStatusText; + else + click = ClkWinTitle; +- } else if ((c = wintoclient(ev->window))) { +- focus(c); +- restack(selmon); +- XAllowEvents(dpy, ReplayPointer, CurrentTime); +- click = ClkClientWin; + } ++ + for (i = 0; i < LENGTH(buttons); i++) + if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) + buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); ++ ++ last_button_press = now(); + } + + void +@@ -765,6 +795,9 @@ enternotify(XEvent *e) + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + ++ if (cursor_hidden) ++ return; ++ + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + c = wintoclient(ev->window); +@@ -862,6 +895,36 @@ focusstack(const Arg *arg) + } + } + ++void ++genericevent(XEvent *e) ++{ ++ if (e->xcookie.extension != xi_opcode) ++ return; ++ ++ if (!XGetEventData(dpy, &e->xcookie)) ++ return; ++ ++ switch (e->xcookie.evtype) { ++ case XI_RawMotion: ++ if (cursor_hidden) ++ showcursor(NULL); ++ break; ++ case XI_RawTouchBegin: ++ case XI_RawTouchEnd: ++ case XI_RawTouchUpdate: ++ if (!cursor_hidden) ++ hidecursor(NULL); ++ break; ++ case XI_RawKeyRelease: ++ if (now() - last_button_press > 2000 && !cursor_hidden) { ++ hidecursor(NULL); ++ } ++ break; ++ } ++ ++ XFreeEventData(dpy, &e->xcookie); ++} ++ + Atom + getatomprop(Client *c, Atom prop) + { +@@ -885,6 +948,12 @@ getrootptr(int *x, int *y) + unsigned int dui; + Window dummy; + ++ if (cursor_hidden) { ++ *x = mouse_x; ++ *y = mouse_y; ++ return 1; ++ } ++ + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); + } + +@@ -968,6 +1037,20 @@ grabkeys(void) + } + } + ++void ++hidecursor(const Arg *arg) ++{ ++ if (cursor_hidden) ++ return; ++ ++ XFixesHideCursor(dpy, root); ++ if (getrootptr(&mouse_x, &mouse_y)) { ++ XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->mx + selmon->mw, selmon->my); ++ } ++ ++ cursor_hidden = 1; ++} ++ + void + incnmaster(const Arg *arg) + { +@@ -1200,6 +1283,13 @@ nexttiled(Client *c) + return c; + } + ++unsigned long long ++now(void) { ++ struct timespec currentTime; ++ clock_gettime(CLOCK_REALTIME, ¤tTime); ++ return currentTime.tv_sec * 1000LL + currentTime.tv_nsec / 1000000LL; ++} ++ + void + pop(Client *c) + { +@@ -1252,6 +1342,23 @@ quit(const Arg *arg) + running = 0; + } + ++Client * ++recttoclient(int x, int y, int w, int h, int include_floating) ++{ ++ Client *c, *r = NULL; ++ int a, area = 1; ++ ++ for (c = selmon->stack; c; c = c->snext) { ++ if (!ISVISIBLE(c) || (c->isfloating && !include_floating)) ++ continue; ++ if ((a = INTERSECTC(x, y, w, h, c)) >= area) { ++ area = a; ++ r = c; ++ } ++ } ++ return r; ++} ++ + Monitor * + recttomon(int x, int y, int w, int h) + { +@@ -1593,6 +1700,25 @@ setup(void) + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); + XSelectInput(dpy, root, wa.event_mask); ++ ++ if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &i, &i)) { ++ fprintf(stderr, "Warning: XInput is not available."); ++ } ++ /* Tell XInput to send us all RawMotion events. */ ++ unsigned char mask_bytes[XIMaskLen(XI_LASTEVENT)]; ++ memset(mask_bytes, 0, sizeof(mask_bytes)); ++ XISetMask(mask_bytes, XI_RawMotion); ++ XISetMask(mask_bytes, XI_RawKeyRelease); ++ XISetMask(mask_bytes, XI_RawTouchBegin); ++ XISetMask(mask_bytes, XI_RawTouchEnd); ++ XISetMask(mask_bytes, XI_RawTouchUpdate); ++ ++ XIEventMask mask; ++ mask.deviceid = XIAllMasterDevices; ++ mask.mask_len = sizeof(mask_bytes); ++ mask.mask = mask_bytes; ++ XISelectEvents(dpy, root, &mask, 1); ++ + grabkeys(); + focus(NULL); + } +@@ -1610,6 +1736,18 @@ seturgent(Client *c, int urg) + XFree(wmh); + } + ++void ++showcursor(const Arg *arg) ++{ ++ if (!cursor_hidden) ++ return; ++ ++ XWarpPointer(dpy, None, root, 0, 0, 0, 0, mouse_x, mouse_y); ++ XFixesShowCursor(dpy, root); ++ ++ cursor_hidden = 0; ++} ++ + void + showhide(Client *c) + { +-- +2.19.1 +