From 1a1ce4791796a0b188f1d1e1059a73c15ba895d6 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 27 Jun 2023 14:59:48 +0200 Subject: [PATCH 01/19] layoutmenu: fixing warning from original patch --- patch/bar_layoutmenu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch/bar_layoutmenu.c b/patch/bar_layoutmenu.c index 1b95069..bab4e47 100644 --- a/patch/bar_layoutmenu.c +++ b/patch/bar_layoutmenu.c @@ -9,7 +9,7 @@ layoutmenu(const Arg *arg) { s = fgets(c, sizeof(c), p); pclose(p); - if (!s || *s == '\0' || c == '\0') + if (!s || *s == '\0' || c[0] == '\0') return; i = atoi(c); From 99f6f1b52cdd70f02d0ad902d7bfac6e2e889464 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 27 Jun 2023 16:07:13 +0200 Subject: [PATCH 02/19] Adding focusfollowmouse patch ref. #364 --- README.md | 6 ++++++ dwm.c | 23 ++++++++++++++--------- patch/combo.c | 2 +- patch/distributetags.c | 4 ++-- patch/focusadjacenttag.c | 4 ++-- patch/focusfollowmouse.c | 9 +++++++++ patch/focusfollowmouse.h | 1 + patch/include.c | 3 +++ patch/include.h | 3 +++ patch/scratchpad.c | 2 +- patch/scratchpad_alt_1.c | 4 ++-- patch/swallow.c | 2 +- patch/tagallmon.c | 2 +- patch/tagothermonitor.c | 2 +- patch/tagswapmon.c | 2 +- patch/xrdb.c | 3 +-- patches.def.h | 6 ++++++ 17 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 patch/focusfollowmouse.c create mode 100644 patch/focusfollowmouse.h diff --git a/README.md b/README.md index 4d47e3c..9d063bc 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 ### Changelog: +2023-06-27 - Added the focusfollowmouse patch + 2023-06-25 - Added the toggletopbar patch 2023-01-18 - Added the view history patch @@ -433,6 +435,10 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 - allows focusing on clients based on direction (up, down, left, right) instead of client order + - [focusfollowmouse](https://github.com/bakkeby/patches/wiki/focusfollowmouse) + - the window under the mouse cursor will receive focus when changing tags, closing windows or + moving client out of view (as opposed to the most recently focused client) + - [focusmaster](https://dwm.suckless.org/patches/focusmaster/) - a simple patch that just puts focus back to the master client diff --git a/dwm.c b/dwm.c index 03ceb92..269f965 100644 --- a/dwm.c +++ b/dwm.c @@ -1489,8 +1489,8 @@ configurenotify(XEvent *e) createpreview(m); #endif // BAR_TAGPREVIEW_PATCH } - focus(NULL); arrange(NULL); + focus(NULL); } } } @@ -2037,6 +2037,10 @@ expose(XEvent *e) void focus(Client *c) { + #if FOCUSFOLLOWMOUSE_PATCH + if (!c || !ISVISIBLE(c)) + c = getpointerclient(); + #endif // FOCUSFOLLOWMOUSE_PATCH if (!c || !ISVISIBLE(c)) for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); if (selmon->sel && selmon->sel != c) @@ -3347,11 +3351,12 @@ sendmon(Client *c, Monitor *m) if (hadfocus) { focus(c); restack(m); - } else + } else { focus(NULL); + } #else - focus(NULL); arrange(NULL); + focus(NULL); #endif // EXRESIZE_PATCH / SENDMON_KEEPFOCUS_PATCH #if SWITCHTAG_PATCH if (c->switchtag) @@ -4074,6 +4079,7 @@ tag(const Arg *arg) if (selmon->sel->switchtag) selmon->sel->switchtag = 0; #endif // SWITCHTAG_PATCH + arrange(selmon); focus(NULL); #if SWAPFOCUS_PATCH && PERTAG_PATCH selmon->pertag->prevclient[selmon->pertag->curtag] = NULL; @@ -4081,7 +4087,6 @@ tag(const Arg *arg) if (tagmask & 1) selmon->pertag->prevclient[tagindex] = NULL; #endif // SWAPFOCUS_PATCH - arrange(selmon); #if VIEWONTAG_PATCH if ((arg->ui & TAGMASK) != selmon->tagset[selmon->seltags]) view(arg); @@ -4213,13 +4218,13 @@ toggletag(const Arg *arg) newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if (newtags) { selmon->sel->tags = newtags; + arrange(selmon); focus(NULL); #if SWAPFOCUS_PATCH && PERTAG_PATCH for (tagmask = arg->ui & TAGMASK, tagindex = 1; tagmask!=0; tagmask >>= 1, tagindex++) if (tagmask & 1) selmon->pertag->prevclient[tagindex] = NULL; #endif // SWAPFOCUS_PATCH - arrange(selmon); } #if BAR_EWMHTAGS_PATCH updatecurrentdesktop(); @@ -4306,8 +4311,8 @@ toggleview(const Arg *arg) #endif // PERTAGBAR_PATCH #endif // PERTAG_PATCH #if !TAGSYNC_PATCH - focus(NULL); arrange(selmon); + focus(NULL); #endif // TAGSYNC_PATCH #if !EMPTYVIEW_PATCH } @@ -4318,8 +4323,8 @@ toggleview(const Arg *arg) #if !EMPTYVIEW_PATCH if (newtagset) { #endif // EMPTYVIEW_PATCH - focus(NULL); arrange(NULL); + focus(NULL); #if !EMPTYVIEW_PATCH } #endif // EMPTYVIEW_PATCH @@ -4456,9 +4461,9 @@ unmanage(Client *c, int destroyed) if (s) return; #endif // SWALLOW_PATCH + arrange(m); focus(NULL); updateclientlist(); - arrange(m); #if SWITCHTAG_PATCH if (switchtag && ((switchtag & TAGMASK) != selmon->tagset[selmon->seltags])) view(&((Arg) { .ui = switchtag })); @@ -4953,12 +4958,12 @@ view(const Arg *arg) } selmon = origselmon; #endif // TAGSYNC_PATCH - focus(NULL); #if TAGSYNC_PATCH arrange(NULL); #else arrange(selmon); #endif // TAGSYNC_PATCH + focus(NULL); #if BAR_EWMHTAGS_PATCH updatecurrentdesktop(); #endif // BAR_EWMHTAGS_PATCH diff --git a/patch/combo.c b/patch/combo.c index 58b31f1..0b0bc5a 100644 --- a/patch/combo.c +++ b/patch/combo.c @@ -22,8 +22,8 @@ combotag(const Arg *arg) combo = 1; selmon->sel->tags = arg->ui & TAGMASK; } - focus(NULL); arrange(selmon); + focus(NULL); } } diff --git a/patch/distributetags.c b/patch/distributetags.c index f20f53f..d786774 100644 --- a/patch/distributetags.c +++ b/patch/distributetags.c @@ -22,10 +22,10 @@ distributetags(const Arg *arg) #if TAGSYNC_PATCH } selmon = origselmon; - focus(NULL); arrange(NULL); - #else focus(NULL); + #else arrange(selmon); + focus(NULL); #endif // TAGSYNC_PATCH } diff --git a/patch/focusadjacenttag.c b/patch/focusadjacenttag.c index 67dd768..f0244a2 100644 --- a/patch/focusadjacenttag.c +++ b/patch/focusadjacenttag.c @@ -6,8 +6,8 @@ tagtoleft(const Arg *arg) && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 && selmon->tagset[selmon->seltags] > 1) { selmon->sel->tags >>= 1; - focus(NULL); arrange(selmon); + focus(NULL); } } @@ -19,8 +19,8 @@ tagtoright(const Arg *arg) && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 && selmon->tagset[selmon->seltags] & (MASK >> 1)) { selmon->sel->tags <<= 1; - focus(NULL); arrange(selmon); + focus(NULL); } } diff --git a/patch/focusfollowmouse.c b/patch/focusfollowmouse.c new file mode 100644 index 0000000..d75a9da --- /dev/null +++ b/patch/focusfollowmouse.c @@ -0,0 +1,9 @@ +Client * +getpointerclient(void) +{ + Window dummy, win; + int di; + unsigned int dui; + XQueryPointer(dpy, root, &dummy, &win, &di, &di, &di, &di, &dui); + return wintoclient(win); +} diff --git a/patch/focusfollowmouse.h b/patch/focusfollowmouse.h new file mode 100644 index 0000000..6b24d5f --- /dev/null +++ b/patch/focusfollowmouse.h @@ -0,0 +1 @@ +static Client *getpointerclient(void); diff --git a/patch/include.c b/patch/include.c index 12de942..440633a 100644 --- a/patch/include.c +++ b/patch/include.c @@ -151,6 +151,9 @@ #if FOCUSDIR_PATCH #include "focusdir.c" #endif +#if FOCUSFOLLOWMOUSE_PATCH +#include "focusfollowmouse.c" +#endif #if FOCUSMASTER_PATCH #include "focusmaster.c" #endif diff --git a/patch/include.h b/patch/include.h index 41031f6..2879103 100644 --- a/patch/include.h +++ b/patch/include.h @@ -154,6 +154,9 @@ #if FOCUSADJACENTTAG_PATCH #include "focusadjacenttag.h" #endif +#if FOCUSFOLLOWMOUSE_PATCH +#include "focusfollowmouse.h" +#endif #if FOCUSMASTER_PATCH #include "focusmaster.h" #endif diff --git a/patch/scratchpad.c b/patch/scratchpad.c index 9e24ff6..013e35f 100644 --- a/patch/scratchpad.c +++ b/patch/scratchpad.c @@ -62,8 +62,8 @@ togglescratch(const Arg *arg) if (found) { if (newtagset) { selmon->tagset[selmon->seltags] = newtagset; - focus(NULL); arrange(selmon); + focus(NULL); } if (ISVISIBLE(found)) { focus(found); diff --git a/patch/scratchpad_alt_1.c b/patch/scratchpad_alt_1.c index 6724d5c..8704582 100644 --- a/patch/scratchpad_alt_1.c +++ b/patch/scratchpad_alt_1.c @@ -6,8 +6,8 @@ scratchpad_hide() if (selmon->sel) { selmon->sel->tags = SCRATCHPAD_MASK; selmon->sel->isfloating = 1; - focus(NULL); arrange(selmon); + focus(NULL); } } @@ -36,8 +36,8 @@ scratchpad_show() if (scratchpad_last_showed->tags != SCRATCHPAD_MASK) { scratchpad_last_showed->tags = SCRATCHPAD_MASK; - focus(NULL); arrange(selmon); + focus(NULL); return; } diff --git a/patch/swallow.c b/patch/swallow.c index 8a63cc0..df8f927 100644 --- a/patch/swallow.c +++ b/patch/swallow.c @@ -91,8 +91,8 @@ unswallow(Client *c) setfloatinghint(c); #endif // BAR_EWMHTAGS_PATCH setclientstate(c, NormalState); - focus(NULL); arrange(c->mon); + focus(NULL); } pid_t diff --git a/patch/tagallmon.c b/patch/tagallmon.c index d6b879a..3dee569 100644 --- a/patch/tagallmon.c +++ b/patch/tagallmon.c @@ -43,7 +43,7 @@ tagallmon(const Arg *arg) } } - focus(NULL); arrange(NULL); + focus(NULL); } diff --git a/patch/tagothermonitor.c b/patch/tagothermonitor.c index d12f6ff..90739dc 100644 --- a/patch/tagothermonitor.c +++ b/patch/tagothermonitor.c @@ -37,8 +37,8 @@ tagothermon(const Arg *arg, int dir) sendmon(sel, newmon); if (arg->ui & TAGMASK) { sel->tags = arg->ui & TAGMASK; - focus(NULL); arrange(newmon); + focus(NULL); } } diff --git a/patch/tagswapmon.c b/patch/tagswapmon.c index 4719b8c..915512e 100644 --- a/patch/tagswapmon.c +++ b/patch/tagswapmon.c @@ -69,7 +69,7 @@ tagswapmon(const Arg *arg) } } - focus(NULL); arrange(NULL); + focus(NULL); } diff --git a/patch/xrdb.c b/patch/xrdb.c index aa32854..aa14969 100644 --- a/patch/xrdb.c +++ b/patch/xrdb.c @@ -132,7 +132,6 @@ xrdb(const Arg *arg) #endif // BAR_ALPHA_PATCH ColCount ); - focus(NULL); arrange(NULL); + focus(NULL); } - diff --git a/patches.def.h b/patches.def.h index b7f9f8a..1875853 100644 --- a/patches.def.h +++ b/patches.def.h @@ -646,6 +646,12 @@ */ #define FOCUSDIR_PATCH 0 +/* When changing tags, closing windows or moving clients out of view then focus will revert to the + * client window that remains under the mouse cursor rather than the most recently focused window. + * https://github.com/bakkeby/patches/wiki/focusfollowmouse + */ +#define FOCUSFOLLOWMOUSE_PATCH 0 + /* A simple patch that just puts focus back to the master client. * https://dwm.suckless.org/patches/focusmaster/ */ From ab7d28ff0f747eff6abc0dc460523c2d5c8f067a Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 27 Jun 2023 16:31:02 +0200 Subject: [PATCH 03/19] bar border - allow for the border size to be explicitly set ref. #364 --- config.def.h | 6 ++++++ dwm.c | 4 ++-- patch/setborderpx.c | 14 ++++++++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/config.def.h b/config.def.h index e75a22e..af32234 100644 --- a/config.def.h +++ b/config.def.h @@ -7,6 +7,12 @@ static const int corner_radius = 10; #else static const unsigned int borderpx = 1; /* border pixel of windows */ #endif // ROUNDED_CORNERS_PATCH +#if BAR_BORDER_PATCH +/* This allows the bar border size to be explicitly set separately from borderpx. + * If left as 0 then it will default to the borderpx value of the monitor and will + * automatically update with setborderpx. */ +static const unsigned int barborderpx = 0; /* border pixel of bar */ +#endif // BAR_BORDER_PATCH static const unsigned int snap = 32; /* snap pixel */ #if SWALLOW_PATCH static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ diff --git a/dwm.c b/dwm.c index 269f965..2beb2a6 100644 --- a/dwm.c +++ b/dwm.c @@ -484,7 +484,7 @@ struct Monitor { int gappov; /* vertical outer gaps */ #endif // VANITYGAPS_PATCH #if SETBORDERPX_PATCH - unsigned int borderpx; + int borderpx; #endif // SETBORDERPX_PATCH unsigned int seltags; unsigned int sellt; @@ -1676,7 +1676,7 @@ createmon(void) bar->showbar = 1; bar->external = 0; #if BAR_BORDER_PATCH - bar->borderpx = borderpx; + bar->borderpx = (barborderpx ? barborderpx : borderpx); #else bar->borderpx = 0; #endif // BAR_BORDER_PATCH diff --git a/patch/setborderpx.c b/patch/setborderpx.c index 6cc0b34..250a939 100644 --- a/patch/setborderpx.c +++ b/patch/setborderpx.c @@ -15,13 +15,15 @@ setborderpx(const Arg *arg) int delta = 2 * (m->borderpx - prev_borderpx); #if BAR_BORDER_PATCH - for (bar = m->bar; bar; bar = bar->next) { - bar->bh = bar->bh - 2 * bar->borderpx + 2 * m->borderpx; - bar->borderpx = m->borderpx; + if (!barborderpx) { + for (bar = m->bar; bar; bar = bar->next) { + bar->bh = bar->bh - 2 * bar->borderpx + 2 * m->borderpx; + bar->borderpx = m->borderpx; + } + updatebarpos(m); + for (bar = m->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); } - updatebarpos(m); - for (bar = m->bar; bar; bar = bar->next) - XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); #endif // BAR_BORDER_PATCH for (c = m->clients; c; c = c->next) { From 74abea7c706420e644f71e4f99aab78b1057e133 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 27 Jun 2023 17:24:36 +0200 Subject: [PATCH 04/19] Adding unmanaged patch ref. #365 --- README.md | 6 +++++- dwm.c | 28 ++++++++++++++++++++++++++++ patches.def.h | 7 +++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d063bc..f5b0607 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 ### Changelog: -2023-06-27 - Added the focusfollowmouse patch +2023-06-27 - Added the focusfollowmouse and unmanaged patches 2023-06-25 - Added the toggletopbar patch @@ -808,6 +808,10 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 - resets isfloating on any visible windows that have it set and optionally also applies a layout + - [unmanaged](https://github.com/bakkeby/patches/wiki/unmanaged) + - adds a client rule that allows for windows to not be managed by the window manager + - this can be useful for external bars, widgets, launchers, docks, desktop icons and more + - [~urgentborder~](https://dwm.suckless.org/patches/urgentborder/) - ~this patch makes "urgent" windows have different colors~ diff --git a/dwm.c b/dwm.c index 2beb2a6..74f3ee2 100644 --- a/dwm.c +++ b/dwm.c @@ -568,6 +568,9 @@ typedef struct { #if RENAMED_SCRATCHPADS_PATCH const char scratchkey; #endif // RENAMED_SCRATCHPADS_PATCH + #if UNMANAGED_PATCH + int unmanaged; + #endif // UNMANAGED_PATCH #if XKB_PATCH int xkb_layout; #endif // XKB_PATCH @@ -775,6 +778,9 @@ static int xkbEventType = 0; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh; /* bar geometry */ +#if UNMANAGED_PATCH +static int unmanaged = 0; /* whether the window manager should manage the new window or not */ +#endif // UNMANAGED_PATCH static int lrpad; /* sum of left and right padding for text */ /* Some clients (e.g. alacritty) helpfully send configure requests with a new size or position * when they detect that they have been moved to another monitor. This can cause visual glitches @@ -932,6 +938,9 @@ applyrules(Client *c) c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); } #endif // SCRATCHPADS_PATCH + #if UNMANAGED_PATCH + unmanaged = r->unmanaged; + #endif // UNMANAGED_PATCH for (m = mons; m && m->num != r->monitor; m = m->next); if (m) c->mon = m; @@ -2502,6 +2511,25 @@ manage(Window w, XWindowAttributes *wa) #endif // SWALLOW_PATCH } + #if UNMANAGED_PATCH + if (unmanaged) { + XMapWindow(dpy, c->win); + if (unmanaged == 1) + XRaiseWindow(dpy, c->win); + else if (unmanaged == 2) + XLowerWindow(dpy, c->win); + + updatewmhints(c); + if (!c->neverfocus) + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + sendevent(c, wmatom[WMTakeFocus]); + + free(c); + unmanaged = 0; + return; + } + #endif // UNMANAGED_PATCH + if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) c->x = c->mon->wx + c->mon->ww - WIDTH(c); if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) diff --git a/patches.def.h b/patches.def.h index 1875853..e82af9a 100644 --- a/patches.def.h +++ b/patches.def.h @@ -1309,6 +1309,13 @@ */ #define UNFLOATVISIBLE_PATCH 0 +/* This patch adds a client rule that allows for windows that do not specify the override-redirect + * to not be managed by the window manager. This can be useful for external bars, widgets, + * launchers, docks, desktop icons and more. + * https://github.com/bakkeby/patches/wiki/unmanaged + */ +#define UNMANAGED_PATCH 0 + /* This patch adds configurable gaps between windows differentiating between outer, inner, * horizontal and vertical gaps. * https://github.com/bakkeby/patches/blob/master/dwm/dwm-vanitygaps-6.2.diff From 7849eaa08b71d359c939b946598716539b4ba1d7 Mon Sep 17 00:00:00 2001 From: Mahdi Nayef Date: Thu, 24 Aug 2023 16:18:03 +0000 Subject: [PATCH 05/19] Use pkg-config to locate fribidi library's files (#369) --- config.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.mk b/config.mk index 7c09ded..69b8092 100644 --- a/config.mk +++ b/config.mk @@ -52,8 +52,8 @@ XRENDER = -lXrender #IMLIB2LIBS = -lImlib2 # Uncomment for the bidi patch -#BDINC = -I/usr/include/fribidi -#BDLIBS = -lfribidi +#BDINC = `pkg-config --cflags fribidi` +#BDLIBS = `pkg-config --libs fribidi` # includes and libs INCS = -I${X11INC} -I${FREETYPEINC} ${YAJLINC} ${PANGOINC} ${BDINC} From 5865c68c0e71208f4d55522e208509d85b1291cd Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 22 Sep 2023 18:05:25 +0200 Subject: [PATCH 06/19] systray + unmanaged: fixed compatibility issue --- dwm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dwm.c b/dwm.c index 74f3ee2..b5383eb 100644 --- a/dwm.c +++ b/dwm.c @@ -2522,7 +2522,11 @@ manage(Window w, XWindowAttributes *wa) updatewmhints(c); if (!c->neverfocus) XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + #if BAR_SYSTRAY_PATCH + sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); + #else sendevent(c, wmatom[WMTakeFocus]); + #endif // BAR_SYSTRAY_PATCH free(c); unmanaged = 0; From 3e97a1d25cb985150aa2667822cbda066f5b3cba Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 22 Sep 2023 18:08:42 +0200 Subject: [PATCH 07/19] Makefile: remove the options target The Makefile used to suppress output (by using @), so this target made sense at the time. But the Makefile should be simple and make debugging with less abstractions or fancy printing. The Makefile was made verbose and doesn't hide the build output, so remove this target. Prompted by a question on the mailing list about the options target. ref. https://git.suckless.org/dwm/commit/9f8855343c881bdc01b9fff5b956537ba1106b76.html --- Makefile | 12 +++--------- README.md | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 23e899f..bc984d7 100644 --- a/Makefile +++ b/Makefile @@ -9,17 +9,11 @@ OBJ = ${SRC:.c=.o} # FreeBSD users, prefix all ifdef, else and endif statements with a . for this to work (e.g. .ifdef) ifdef YAJLLIBS -all: options dwm dwm-msg +all: dwm dwm-msg else -all: options dwm +all: dwm endif -options: - @echo dwm build options: - @echo "CFLAGS = ${CFLAGS}" - @echo "LDFLAGS = ${LDFLAGS}" - @echo "CC = ${CC}" - .c.o: ${CC} -c ${CFLAGS} $< @@ -74,4 +68,4 @@ uninstall: ${DESTDIR}${MANPREFIX}/man1/dwm.1\ ${DESTDIR}${PREFIX}/share/xsessions/dwm.desktop -.PHONY: all options clean dist install uninstall +.PHONY: all clean dist install uninstall diff --git a/README.md b/README.md index f5b0607..14e76bd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This dwm 6.4 (e81f17d, 2023-04-09) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0). +This dwm 6.4 (9f88553, 2023-09-22) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0). For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/dwm-flexipatch/blob/master/patches.def.h): ```c From 8191c0739ac863f85c29d9f21be0f06f0d038652 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 1 Oct 2023 20:51:16 +0200 Subject: [PATCH 08/19] focusonclick: not skipping motionnotify events as to avoid interferring with tagpreview and other on hover patches --- dwm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/dwm.c b/dwm.c index b5383eb..66a380b 100644 --- a/dwm.c +++ b/dwm.c @@ -679,9 +679,7 @@ static void killclient(const Arg *arg); static void manage(Window w, XWindowAttributes *wa); static void mappingnotify(XEvent *e); static void maprequest(XEvent *e); -#if !FOCUSONCLICK_PATCH static void motionnotify(XEvent *e); -#endif // FOCUSONCLICK_PATCH static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); #if !ZOOMSWAP_PATCH || TAGINTOSTACK_ALLMASTER_PATCH || TAGINTOSTACK_ONEMASTER_PATCH @@ -817,9 +815,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { #endif // COMBO_PATCH / BAR_HOLDBAR_PATCH [MappingNotify] = mappingnotify, [MapRequest] = maprequest, - #if !FOCUSONCLICK_PATCH [MotionNotify] = motionnotify, - #endif // FOCUSONCLICK_PATCH [PropertyNotify] = propertynotify, #if BAR_SYSTRAY_PATCH [ResizeRequest] = resizerequest, @@ -2702,12 +2698,13 @@ maprequest(XEvent *e) manage(ev->window, &wa); } -#if !FOCUSONCLICK_PATCH void motionnotify(XEvent *e) { + #if !FOCUSONCLICK_PATCH static Monitor *mon = NULL; Monitor *m; + #endif // FOCUSONCLICK_PATCH Bar *bar; #if LOSEFULLSCREEN_PATCH Client *sel; @@ -2724,6 +2721,7 @@ motionnotify(XEvent *e) hidetagpreview(selmon); #endif // BAR_TAGPREVIEW_PATCH + #if !FOCUSONCLICK_PATCH if (ev->window != root) return; if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { @@ -2738,8 +2736,8 @@ motionnotify(XEvent *e) focus(NULL); } mon = m; + #endif // FOCUSONCLICK_PATCH } -#endif // FOCUSONCLICK_PATCH void movemouse(const Arg *arg) From ddb2e833a47b5c82eb87cbaf8db2f356a1a6723a Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 1 Oct 2023 21:07:58 +0200 Subject: [PATCH 09/19] tagpreview: adding compatibility with powerline tags and taglabels --- config.def.h | 4 +-- patch/bar_powerline_tags.c | 54 ++++++++++++++++++++++++++++++++++++++ patch/bar_powerline_tags.h | 2 +- patch/bar_taglabels.c | 45 +++++++++++++++++++++++++++++++ patch/bar_taglabels.h | 3 ++- 5 files changed, 104 insertions(+), 4 deletions(-) diff --git a/config.def.h b/config.def.h index af32234..201c1fb 100644 --- a/config.def.h +++ b/config.def.h @@ -549,13 +549,13 @@ static const BarRule barrules[] = { { -1, 0, BAR_ALIGN_LEFT, width_stbutton, draw_stbutton, click_stbutton, NULL, "statusbutton" }, #endif // BAR_STATUSBUTTON_PATCH #if BAR_POWERLINE_TAGS_PATCH - { 0, 0, BAR_ALIGN_LEFT, width_pwrl_tags, draw_pwrl_tags, click_pwrl_tags, NULL, "powerline_tags" }, + { 0, 0, BAR_ALIGN_LEFT, width_pwrl_tags, draw_pwrl_tags, click_pwrl_tags, hover_pwrl_tags, "powerline_tags" }, #endif // BAR_POWERLINE_TAGS_PATCH #if BAR_TAGS_PATCH { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, hover_tags, "tags" }, #endif // BAR_TAGS_PATCH #if BAR_TAGLABELS_PATCH - { -1, 0, BAR_ALIGN_LEFT, width_taglabels, draw_taglabels, click_taglabels, NULL, "taglabels" }, + { -1, 0, BAR_ALIGN_LEFT, width_taglabels, draw_taglabels, click_taglabels, hover_taglabels, "taglabels" }, #endif // BAR_TAGLABELS_PATCH #if BAR_TAGGRID_PATCH { -1, 0, BAR_ALIGN_LEFT, width_taggrid, draw_taggrid, click_taggrid, NULL, "taggrid" }, diff --git a/patch/bar_powerline_tags.c b/patch/bar_powerline_tags.c index d5ad787..0987c9b 100644 --- a/patch/bar_powerline_tags.c +++ b/patch/bar_powerline_tags.c @@ -105,3 +105,57 @@ click_pwrl_tags(Bar *bar, Arg *arg, BarArg *a) return ClkTagBar; } +int +hover_pwrl_tags(Bar *bar, BarArg *a, XMotionEvent *ev) +{ + #if BAR_TAGPREVIEW_PATCH + int i = 0, x = lrpad / 2; + int px, py; + int plw = drw->fonts->h / 2 + 1; + Monitor *m = bar->mon; + #if VANITYGAPS_PATCH + int ov = gappov; + int oh = gappoh; + #else + int ov = 0; + int oh = 0; + #endif // VANITYGAPS_PATCH + + #if BAR_HIDEVACANTTAGS_PATCH + Client *c; + unsigned int occ = 0; + for (c = bar->mon->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + #endif // BAR_HIDEVACANTTAGS_PATCH + + do { + #if BAR_HIDEVACANTTAGS_PATCH + if (!(occ & 1 << i || bar->mon->tagset[bar->mon->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + x += TEXTW(tagicon(bar->mon, i)) + plw; + } while (a->x >= x && ++i < NUMTAGS); + + if (i < NUMTAGS) { + if ((i + 1) != selmon->previewshow && !(selmon->tagset[selmon->seltags] & 1 << i)) { + if (bar->by > m->my + m->mh / 2) // bottom bar + py = bar->by - m->mh / scalepreview - oh; + else // top bar + py = bar->by + bar->bh + oh; + px = bar->bx + ev->x - m->mw / scalepreview / 2; + if (px + m->mw / scalepreview > m->mx + m->mw) + px = m->wx + m->ww - m->mw / scalepreview - ov; + else if (px < bar->bx) + px = m->wx + ov; + selmon->previewshow = i + 1; + showtagpreview(i, px, py); + } else if (selmon->tagset[selmon->seltags] & 1 << i) { + hidetagpreview(selmon); + } + } else if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH + + return 1; +} diff --git a/patch/bar_powerline_tags.h b/patch/bar_powerline_tags.h index a51dcc7..b0838a6 100644 --- a/patch/bar_powerline_tags.h +++ b/patch/bar_powerline_tags.h @@ -1,4 +1,4 @@ static int width_pwrl_tags(Bar *bar, BarArg *a); static int draw_pwrl_tags(Bar *bar, BarArg *a); static int click_pwrl_tags(Bar *bar, Arg *arg, BarArg *a); - +static int hover_pwrl_tags(Bar *bar, BarArg *a, XMotionEvent *ev); diff --git a/patch/bar_taglabels.c b/patch/bar_taglabels.c index 9e6d441..cf1b762 100644 --- a/patch/bar_taglabels.c +++ b/patch/bar_taglabels.c @@ -89,3 +89,48 @@ click_taglabels(Bar *bar, Arg *arg, BarArg *a) } return ClkTagBar; } + +int +hover_taglabels(Bar *bar, BarArg *a, XMotionEvent *ev) +{ + #if BAR_TAGPREVIEW_PATCH + int i = 0, x = lrpad / 2; + int px, py; + Monitor *m = bar->mon; + #if VANITYGAPS_PATCH + int ov = gappov; + int oh = gappoh; + #else + int ov = 0; + int oh = 0; + #endif // VANITYGAPS_PATCH + + do { + if (!m->taglabel[i][0]) + continue; + x += TEXTW(m->taglabel[i]); + } while (a->x >= x && ++i < NUMTAGS); + + if (i < NUMTAGS) { + if ((i + 1) != selmon->previewshow && !(selmon->tagset[selmon->seltags] & 1 << i)) { + if (bar->by > m->my + m->mh / 2) // bottom bar + py = bar->by - m->mh / scalepreview - oh; + else // top bar + py = bar->by + bar->bh + oh; + px = bar->bx + ev->x - m->mw / scalepreview / 2; + if (px + m->mw / scalepreview > m->mx + m->mw) + px = m->wx + m->ww - m->mw / scalepreview - ov; + else if (px < bar->bx) + px = m->wx + ov; + selmon->previewshow = i + 1; + showtagpreview(i, px, py); + } else if (selmon->tagset[selmon->seltags] & 1 << i) { + hidetagpreview(selmon); + } + } else if (selmon->previewshow != 0) { + hidetagpreview(selmon); + } + #endif // BAR_TAGPREVIEW_PATCH + + return 1; +} diff --git a/patch/bar_taglabels.h b/patch/bar_taglabels.h index 57250f9..61b5aa0 100644 --- a/patch/bar_taglabels.h +++ b/patch/bar_taglabels.h @@ -2,4 +2,5 @@ static int width_taglabels(Bar *bar, BarArg *a); static int draw_taglabels(Bar *bar, BarArg *a); -static int click_taglabels(Bar *bar, Arg *arg, BarArg *a); \ No newline at end of file +static int click_taglabels(Bar *bar, Arg *arg, BarArg *a); +static int hover_taglabels(Bar *bar, BarArg *a, XMotionEvent *ev); From dd1660b1ed3b60b46cc20ad38b082d07f0f2cc96 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 2 Oct 2023 09:51:34 +0200 Subject: [PATCH 10/19] renamed scratchpads: auto-unhide a minimised (icon state) scratchpad when toggled --- patch/renamed_scratchpads.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/patch/renamed_scratchpads.c b/patch/renamed_scratchpads.c index db99723..3bc9bb0 100644 --- a/patch/renamed_scratchpads.c +++ b/patch/renamed_scratchpads.c @@ -66,12 +66,13 @@ togglescratch(const Arg *arg) if (c->scratchkey != ((char**)arg->v)[0][0]) continue; - /* awesomebar / wintitleactions compatibility, unhide scratchpad if hidden + #if BAR_WINTITLEACTIONS_PATCH + /* unhide scratchpad if hidden */ if (HIDDEN(c)) { XMapWindow(dpy, c->win); setclientstate(c, NormalState); } - */ + #endif // BAR_WINTITLEACTIONS_PATCH /* Record the first found scratchpad client for focus purposes, but prioritise the scratchpad on the current monitor if one exists */ From d807d3da3e1bfed2e79fee5938a10e934be9b4b2 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 3 Oct 2023 21:25:10 +0200 Subject: [PATCH 11/19] renamed scratchpads: allow a fullscreen scratchpad auto-hide when focus is lost if combined with both the losefullscreen patch and the auto-hide patch for renamed scratchpads --- dwm.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 66a380b..7497c65 100644 --- a/dwm.c +++ b/dwm.c @@ -2704,11 +2704,11 @@ motionnotify(XEvent *e) #if !FOCUSONCLICK_PATCH static Monitor *mon = NULL; Monitor *m; - #endif // FOCUSONCLICK_PATCH - Bar *bar; #if LOSEFULLSCREEN_PATCH Client *sel; #endif // LOSEFULLSCREEN_PATCH + #endif // FOCUSONCLICK_PATCH + Bar *bar; XMotionEvent *ev = &e->xmotion; if ((bar = wintobar(ev->window))) { @@ -4373,13 +4373,24 @@ unfocus(Client *c, int setfocus, Client *nextfocus) selmon->pertag->prevclient[selmon->pertag->curtag] = c; #endif // SWAPFOCUS_PATCH #if LOSEFULLSCREEN_PATCH - if (c->isfullscreen && ISVISIBLE(c) && c->mon == selmon && nextfocus && !nextfocus->isfloating) + if (c->isfullscreen && ISVISIBLE(c) && c->mon == selmon && nextfocus && !nextfocus->isfloating) { + #if RENAMED_SCRATCHPADS_PATCH && RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->scratchkey != 0 && c->fakefullscreen != 1) + togglescratch(&((Arg) {.v = (const char*[]){ &c->scratchkey, NULL } })); + #else + if (c->scratchkey != 0) + togglescratch(&((Arg) {.v = (const char*[]){ &c->scratchkey, NULL } })); + #endif // FAKEFULLSCREEN_CLIENT_PATCH + else + #endif // RENAMED_SCRATCHPADS_AUTO_HIDE_PATCH #if FAKEFULLSCREEN_CLIENT_PATCH if (c->fakefullscreen != 1) setfullscreen(c, 0); #else setfullscreen(c, 0); #endif // #if FAKEFULLSCREEN_CLIENT_PATCH + } #endif // LOSEFULLSCREEN_PATCH grabbuttons(c, 0); #if !BAR_FLEXWINTITLE_PATCH From 1b5a58f23115b37bc0a3ed56b614edce604edb5c Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 20 Oct 2023 10:53:10 +0200 Subject: [PATCH 12/19] Fix space before tab in indent --- patch/layout_flextile-deluxe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch/layout_flextile-deluxe.c b/patch/layout_flextile-deluxe.c index c7429f4..ec7cd7d 100644 --- a/patch/layout_flextile-deluxe.c +++ b/patch/layout_flextile-deluxe.c @@ -643,7 +643,7 @@ arrange_tatami(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, in if (j < ai + cats) { /* Arrange cats (all excess clients that can't be tiled as mats). Cats sleep on mats. */ - switch (cats) { + switch (cats) { case 1: // fill break; case 2: // up and down From 83a047aca7bf1759250bdb8e8380ce261c9c2037 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sat, 4 Nov 2023 21:38:38 +0100 Subject: [PATCH 13/19] shift: filter out scratchpad tags ref. #382 --- patch/shift.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch/shift.c b/patch/shift.c index 355e645..1babd42 100644 --- a/patch/shift.c +++ b/patch/shift.c @@ -6,7 +6,7 @@ shift(const Arg *arg, int clients) unsigned int tagmask = 0; #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH - shifted.ui = selmon->tagset[selmon->seltags]; + shifted.ui = selmon->tagset[selmon->seltags] & ~SPTAGMASK; #else shifted.ui = selmon->tagset[selmon->seltags]; #endif // SCRATCHPADS_PATCH From 4a22fd046cdeb53899eb23f81607287244dcdfdb Mon Sep 17 00:00:00 2001 From: Songli Yu <1097985743@qq.com> Date: Mon, 6 Nov 2023 05:07:43 +0800 Subject: [PATCH 14/19] Fix when only one client in a tag and click it to hide it, then click it one more time, the client will not show as expected. (#385) --- patch/bar_wintitleactions.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch/bar_wintitleactions.c b/patch/bar_wintitleactions.c index 61a5d21..36a06fb 100644 --- a/patch/bar_wintitleactions.c +++ b/patch/bar_wintitleactions.c @@ -51,7 +51,7 @@ togglewin(const Arg *arg) Client *c = (Client*)arg->v; if (!c) return; - if (c == selmon->sel) + if (!HIDDEN(c) && c == selmon->sel) hide(c); else { if (HIDDEN(c)) From 63bab1aa8a5a2925fbccd1022f173ea68ba6663e Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 7 Nov 2023 17:58:45 +0100 Subject: [PATCH 15/19] sticky: prioritise non-sticky windows on focus(NULL) ref. #387 --- dwm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dwm.c b/dwm.c index 7497c65..0ffc759 100644 --- a/dwm.c +++ b/dwm.c @@ -2046,6 +2046,10 @@ focus(Client *c) if (!c || !ISVISIBLE(c)) c = getpointerclient(); #endif // FOCUSFOLLOWMOUSE_PATCH + #if STICKY_PATCH + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c) && !c->issticky; c = c->snext); + #endif // STICKY_PATCH if (!c || !ISVISIBLE(c)) for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); if (selmon->sel && selmon->sel != c) From 332c90049d5fd08a35b4e2e73312d9d5536e3e62 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 7 Nov 2023 21:44:39 +0100 Subject: [PATCH 16/19] sticky: prioritise non-sticky windows on focus(NULL) correction ref. #387 --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 0ffc759..a64dfec 100644 --- a/dwm.c +++ b/dwm.c @@ -2048,7 +2048,7 @@ focus(Client *c) #endif // FOCUSFOLLOWMOUSE_PATCH #if STICKY_PATCH if (!c || !ISVISIBLE(c)) - for (c = selmon->stack; c && !ISVISIBLE(c) && !c->issticky; c = c->snext); + for (c = selmon->stack; c && (!ISVISIBLE(c) || c->issticky); c = c->snext); #endif // STICKY_PATCH if (!c || !ISVISIBLE(c)) for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); From ad9664fa01037fa41d9183100baef30d0cad7be8 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Wed, 8 Nov 2023 21:09:27 +0100 Subject: [PATCH 17/19] shift: skip sticky clients when working out which tags are occupied ref. #387 --- patch/shift.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/patch/shift.c b/patch/shift.c index 1babd42..66b4dce 100644 --- a/patch/shift.c +++ b/patch/shift.c @@ -18,6 +18,10 @@ shift(const Arg *arg, int clients) for (c = selmon->clients; c && clients; c = c->next) { if (c == selmon->sel) continue; + #if STICKY_PATCH + if (c->issticky) + continue; + #endif // STICKY_PATCH #if SCRATCHPADS_PATCH && !RENAMED_SCRATCHPADS_PATCH if (!(c->tags & SPTAGMASK)) tagmask |= c->tags; From d86ea2de25d7ba54b57f208feb6f05071077820b Mon Sep 17 00:00:00 2001 From: Songli Yu Date: Thu, 9 Nov 2023 04:34:43 +0800 Subject: [PATCH 18/19] Fix patch compatibility issue in the resizemousescroll function of TAPRESIZE_PATCH. (#393) --- patch/tapresize.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/patch/tapresize.c b/patch/tapresize.c index c236b5d..7b918cb 100644 --- a/patch/tapresize.c +++ b/patch/tapresize.c @@ -10,8 +10,15 @@ resizemousescroll(const Arg *arg) if (!(c = selmon->sel)) return; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && c->fakefullscreen != 1) /* no support resizing fullscreen windows by mouse */ + return; + #else if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // !FAKEFULLSCREEN_PATCH restack(selmon); if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) From 817db8c3caa115fb6a56e3f64bdf7b2b02a3a58f Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 12 Nov 2023 09:41:31 +0100 Subject: [PATCH 19/19] Adding focusmaster-return patch variant ref. #398 --- README.md | 6 ++++++ config.def.h | 4 ++-- dwm.c | 24 ++++++++++++++++++++++++ patch/focusmaster.c | 39 +++++++++++++++++++++++++++++++++------ patch/include.c | 2 +- patch/include.h | 2 +- patches.def.h | 6 ++++++ 7 files changed, 73 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 14e76bd..6ee0bdf 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 ### Changelog: +2023-11-12 - Added the focusmaster-return patch variant + 2023-06-27 - Added the focusfollowmouse and unmanaged patches 2023-06-25 - Added the toggletopbar patch @@ -442,6 +444,10 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 - [focusmaster](https://dwm.suckless.org/patches/focusmaster/) - a simple patch that just puts focus back to the master client + - [focusmaster-return](https://dwm.suckless.org/patches/focusmaster/) + - a simple patch that just puts focus back to the master client + - additionally allows focus to be switched back to the previous client + - [focusonclick](https://dwm.suckless.org/patches/focusonclick/) - this patch makes you switch focus only by mouse click and not sloppy (focus follows mouse pointer) diff --git a/config.def.h b/config.def.h index 201c1fb..18a553f 100644 --- a/config.def.h +++ b/config.def.h @@ -914,9 +914,9 @@ static const Key keys[] = { #if TAB_PATCH { MODKEY|ControlMask, XK_b, tabmode, {-1} }, #endif // TAB_PATCH - #if FOCUSMASTER_PATCH + #if FOCUSMASTER_PATCH || FOCUSMASTER_RETURN_PATCH { MODKEY|ControlMask, XK_space, focusmaster, {0} }, - #endif // FOCUSMASTER_PATCH + #endif // FOCUSMASTER_PATCH / FOCUSMASTER_RETURN_PATCH #if STACKER_PATCH STACKKEYS(MODKEY, focus) STACKKEYS(MODKEY|ShiftMask, push) diff --git a/dwm.c b/dwm.c index a64dfec..c3c6292 100644 --- a/dwm.c +++ b/dwm.c @@ -504,6 +504,9 @@ struct Monitor { Client *clients; Client *sel; Client *stack; + #if FOCUSMASTER_RETURN_PATCH + Client *tagmarked[32]; + #endif // FOCUSMASTER_RETURN_PATCH Monitor *next; Bar *bar; const Layout *lt[2]; @@ -1818,6 +1821,11 @@ detach(Client *c) #if SEAMLESS_RESTART_PATCH c->idx = 0; #endif // SEAMLESS_RESTART_PATCH + #if FOCUSMASTER_RETURN_PATCH + for (int i = 1; i < NUMTAGS; i++) + if (c == c->mon->tagmarked[i]) + c->mon->tagmarked[i] = NULL; + #endif // FOCUSMASTER_RETURN_PATCH for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); *tc = c->next; @@ -2846,6 +2854,13 @@ nexttiled(Client *c) void pop(Client *c) { + #if FOCUSMASTER_RETURN_PATCH + int i; + for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); + i++; + + c->mon->tagmarked[i] = nexttiled(c->mon->clients); + #endif // FOCUSMASTER_RETURN_PATCH detach(c); attach(c); focus(c); @@ -5086,6 +5101,9 @@ void zoom(const Arg *arg) { Client *c = selmon->sel; + #if FOCUSMASTER_RETURN_PATCH && ZOOMSWAP_PATCH + int i; + #endif // FOCUSMASTER_RETURN_PATCH if (arg && arg->v) c = (Client*)arg->v; if (!c) @@ -5139,6 +5157,12 @@ zoom(const Arg *arg) cold = nexttiled(c->mon->clients); if (c != cold && !at) at = findbefore(c); + #if FOCUSMASTER_RETURN_PATCH + for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); + i++; + + c->mon->tagmarked[i] = cold; + #endif // FOCUSMASTER_RETURN_PATCH detach(c); attach(c); /* swap windows instead of pushing the previous one down */ diff --git a/patch/focusmaster.c b/patch/focusmaster.c index 13a47e5..371525f 100644 --- a/patch/focusmaster.c +++ b/patch/focusmaster.c @@ -1,14 +1,41 @@ void focusmaster(const Arg *arg) { - Client *c; + Client *master; + Monitor *m = selmon; + #if FOCUSMASTER_RETURN_PATCH + int i; + #endif // FOCUSMASTER_RETURN_PATCH - if (selmon->nmaster < 1) + if (m->nmaster < 1) + return; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (!m->sel || (m->sel->isfullscreen && m->sel->fakefullscreen != 1 && lockfullscreen)) + return; + #else + if (!m->sel || (m->sel->isfullscreen && lockfullscreen)) + return; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // FAKEFULLSCREEN_PATCH + + master = nexttiled(m->clients); + + if (!master) return; - c = nexttiled(selmon->clients); + #if FOCUSMASTER_RETURN_PATCH + for (i = 0; !(m->tagset[m->seltags] & 1 << i); i++); + i++; - if (c) - focus(c); + if (m->sel == master) { + if (m->tagmarked[i] && ISVISIBLE(m->tagmarked[i])) + focus(m->tagmarked[i]); + } else { + m->tagmarked[i] = m->sel; + focus(master); + } + #else + focus(master); + #endif // FOCUSMASTER_RETURN_PATCH } - diff --git a/patch/include.c b/patch/include.c index 440633a..8b58e6a 100644 --- a/patch/include.c +++ b/patch/include.c @@ -154,7 +154,7 @@ #if FOCUSFOLLOWMOUSE_PATCH #include "focusfollowmouse.c" #endif -#if FOCUSMASTER_PATCH +#if FOCUSMASTER_PATCH || FOCUSMASTER_RETURN_PATCH #include "focusmaster.c" #endif #if FOCUSURGENT_PATCH diff --git a/patch/include.h b/patch/include.h index 2879103..726dfc0 100644 --- a/patch/include.h +++ b/patch/include.h @@ -157,7 +157,7 @@ #if FOCUSFOLLOWMOUSE_PATCH #include "focusfollowmouse.h" #endif -#if FOCUSMASTER_PATCH +#if FOCUSMASTER_PATCH || FOCUSMASTER_RETURN_PATCH #include "focusmaster.h" #endif #if FOCUSURGENT_PATCH diff --git a/patches.def.h b/patches.def.h index e82af9a..7b43fda 100644 --- a/patches.def.h +++ b/patches.def.h @@ -657,6 +657,12 @@ */ #define FOCUSMASTER_PATCH 0 +/* A variant of the focusmaster patch that additionally allows the focus to be returned to the + * previously focused client + * https://dwm.suckless.org/patches/focusmaster/ + */ +#define FOCUSMASTER_RETURN_PATCH 0 + /* Switch focus only by mouse click and not sloppy (focus follows mouse pointer). * https://dwm.suckless.org/patches/focusonclick/ */