mirror of https://github.com/bakkeby/patches
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
412 lines
11 KiB
Diff
412 lines
11 KiB
Diff
From 15f09e0e690328cb7bfd35b577435cba7b2e4859 Mon Sep 17 00:00:00 2001
|
|
From: Bakkeby <bakkeby@gmail.com>
|
|
Date: Mon, 12 Jun 2023 15:17:51 +0200
|
|
Subject: [PATCH 1/2] 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 <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
+#include <time.h>
|
|
#include <X11/cursorfont.h>
|
|
#include <X11/keysym.h>
|
|
#include <X11/Xatom.h>
|
|
@@ -39,6 +40,8 @@
|
|
#ifdef XINERAMA
|
|
#include <X11/extensions/Xinerama.h>
|
|
#endif /* XINERAMA */
|
|
+#include <X11/extensions/Xfixes.h>
|
|
+#include <X11/extensions/XInput2.h>
|
|
#include <X11/Xft/Xft.h>
|
|
|
|
#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
|
|
|
|
|
|
From f1c11a763cb6943839c4e66c419bd84bd1b32459 Mon Sep 17 00:00:00 2001
|
|
From: Bakkeby <bakkeby@gmail.com>
|
|
Date: Thu, 21 Sep 2023 11:01:56 +0200
|
|
Subject: [PATCH 2/2] Adding cursorwarp patch on top of banish
|
|
|
|
---
|
|
dwm.c | 20 ++++++++++++++++++++
|
|
1 file changed, 20 insertions(+)
|
|
|
|
diff --git a/dwm.c b/dwm.c
|
|
index bb7760b..1a8e311 100644
|
|
--- a/dwm.c
|
|
+++ b/dwm.c
|
|
@@ -238,6 +238,7 @@ static void updatetitle(Client *c);
|
|
static void updatewindowtype(Client *c);
|
|
static void updatewmhints(Client *c);
|
|
static void view(const Arg *arg);
|
|
+static void warp(Client *c);
|
|
static Client *wintoclient(Window w);
|
|
static Monitor *wintomon(Window w);
|
|
static int xerror(Display *dpy, XErrorEvent *ee);
|
|
@@ -867,6 +868,8 @@ focusmon(const Arg *arg)
|
|
unfocus(selmon->sel, 0);
|
|
selmon = m;
|
|
focus(NULL);
|
|
+ if (m->sel)
|
|
+ warp(m->sel)
|
|
}
|
|
|
|
void
|
|
@@ -892,6 +895,7 @@ focusstack(const Arg *arg)
|
|
if (c) {
|
|
focus(c);
|
|
restack(selmon);
|
|
+ warp(c)
|
|
}
|
|
}
|
|
|
|
@@ -1159,6 +1163,8 @@ manage(Window w, XWindowAttributes *wa)
|
|
c->mon->sel = c;
|
|
arrange(c->mon);
|
|
XMapWindow(dpy, c->win);
|
|
+ if (c && c->mon == selmon && ISVISIBLE(c))
|
|
+ warp(c);
|
|
focus(NULL);
|
|
}
|
|
|
|
@@ -1919,6 +1925,8 @@ unmanage(Client *c, int destroyed)
|
|
focus(NULL);
|
|
updateclientlist();
|
|
arrange(m);
|
|
+ if (m->sel && m == selmon)
|
|
+ warp(m->sel);
|
|
}
|
|
|
|
void
|
|
@@ -2182,6 +2190,18 @@ view(const Arg *arg)
|
|
arrange(selmon);
|
|
}
|
|
|
|
+void
|
|
+warp(Client *c)
|
|
+{
|
|
+ if (cursor_hidden) {
|
|
+ mouse_x = c->x + c->w/2;
|
|
+ mouse_y = c->y + c->h/2;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2);
|
|
+}
|
|
+
|
|
Client *
|
|
wintoclient(Window w)
|
|
{
|
|
--
|
|
2.19.1
|
|
|