diff --git a/dwm/dwm-focusedontop-6.4.diff b/dwm/dwm-focusedontop-6.4.diff new file mode 100644 index 0000000..f5d18cf --- /dev/null +++ b/dwm/dwm-focusedontop-6.4.diff @@ -0,0 +1,217 @@ +From ba1a3b540431e5df71f038c6ce845b2815b69178 Mon Sep 17 00:00:00 2001 +From: Bakkeby +Date: Sat, 22 Jul 2023 22:14:04 +0200 +Subject: [PATCH] focusedontop: allow the currently focused client to display + on top of floating windows, but not on top of transient windows + +--- + config.def.h | 7 +++--- + dwm.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 64 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 061ad66..c7ce58d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -5,6 +5,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const int focusedontoptiled = 1; /* 1 means focused tile client is shown on top of floating windows */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +@@ -26,9 +27,9 @@ static const Rule rules[] = { + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ /* class instance title tags mask isfloating alwaysontop monitor */ ++ { "Gimp", NULL, NULL, 0, 1, 0, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1 }, + }; + + /* layout(s) */ +diff --git a/dwm.c b/dwm.c +index e5efb6a..6cc9265 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -93,6 +93,7 @@ struct Client { + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int alwaysontop; + Client *next; + Client *snext; + Monitor *mon; +@@ -138,6 +139,7 @@ typedef struct { + const char *title; + unsigned int tags; + int isfloating; ++ int alwaysontop; + int monitor; + } Rule; + +@@ -188,6 +190,7 @@ static Client *nexttiled(Client *c); + static void pop(Client *c); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); ++static void raiseclient(Client *c); + 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); +@@ -300,6 +303,7 @@ applyrules(Client *c) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; ++ c->alwaysontop = r->alwaysontop; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; +@@ -763,6 +767,7 @@ enternotify(XEvent *e) + { + Client *c; + Monitor *m; ++ XEvent xev; + XCrossingEvent *ev = &e->xcrossing; + + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) +@@ -775,6 +780,7 @@ enternotify(XEvent *e) + } else if (!c || c == selmon->sel) + return; + focus(c); ++ while (XCheckMaskEvent(dpy, EnterWindowMask, &xev)); + } + + void +@@ -809,7 +815,7 @@ focus(Client *c) + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; +- drawbars(); ++ restack(selmon); + } + + /* there are some broken focus acquiring clients needing extra handling */ +@@ -840,6 +846,7 @@ void + focusstack(const Arg *arg) + { + Client *c = NULL, *i; ++ XEvent xev; + + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) + return; +@@ -860,6 +867,7 @@ focusstack(const Arg *arg) + focus(c); + restack(selmon); + } ++ while (XCheckMaskEvent(dpy, EnterWindowMask, &xev)); + } + + Atom +@@ -1025,6 +1033,7 @@ manage(Window w, XWindowAttributes *wa) + Client *c, *t = NULL; + Window trans = None; + XWindowChanges wc; ++ XEvent xev; + + c = ecalloc(1, sizeof(Client)); + c->win = w; +@@ -1039,6 +1048,7 @@ manage(Window w, XWindowAttributes *wa) + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; + c->tags = t->tags; ++ c->alwaysontop = 1; + } else { + c->mon = selmon; + applyrules(c); +@@ -1077,6 +1087,7 @@ manage(Window w, XWindowAttributes *wa) + arrange(c->mon); + XMapWindow(dpy, c->win); + focus(NULL); ++ while (XCheckMaskEvent(dpy, EnterWindowMask, &xev)); + } + + void +@@ -1252,6 +1263,46 @@ quit(const Arg *arg) + running = 0; + } + ++void ++raiseclient(Client *c) ++{ ++ Client *s, *top = NULL; ++ Monitor *m; ++ XWindowChanges wc; ++ ++ /* If the raised client is on the sticky workspace, then refer to the previously ++ * selected workspace when for searching other clients. */ ++ m = c->mon; ++ wc.stack_mode = Above; ++ wc.sibling = m->barwin ? m->barwin : wmcheckwin; ++ ++ /* Check if there are floating always on top clients that need to be on top. */ ++ for (s = m->stack; s; s = s->snext) { ++ if (!s->isfloating || !s->alwaysontop) ++ continue; ++ ++ if (!top) { ++ top = s; ++ XRaiseWindow(dpy, s->win); ++ wc.stack_mode = Below; ++ wc.sibling = s->win; ++ continue; ++ } ++ ++ XConfigureWindow(dpy, s->win, CWSibling|CWStackMode, &wc); ++ wc.sibling = s->win; ++ } ++ ++ /* If the given client c is not handled by the above for loop */ ++ if (c && (!c->isfloating || !c->alwaysontop)) { ++ if (!top) { ++ XRaiseWindow(dpy, c->win); ++ } else { ++ XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); ++ } ++ } ++} ++ + Monitor * + recttomon(int x, int y, int w, int h) + { +@@ -1349,14 +1400,16 @@ void + restack(Monitor *m) + { + Client *c; ++ Client *raised; + XEvent ev; + XWindowChanges wc; + + drawbar(m); + if (!m->sel) + return; +- if (m->sel->isfloating || !m->lt[m->sellt]->arrange) +- XRaiseWindow(dpy, m->sel->win); ++ ++ raised = (focusedontoptiled || m->sel->isfloating ? m->sel : NULL); ++ + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + wc.sibling = m->barwin; +@@ -1366,6 +1419,10 @@ restack(Monitor *m) + wc.sibling = c->win; + } + } ++ ++ if (raised) ++ raiseclient(raised); ++ + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + } +-- +2.19.1 +