From 67fc80803d09529d0edff02c5079a71387853a10 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 31 Oct 2021 13:45:18 +0100 Subject: [PATCH 01/49] onlyquitonempty: refactoring patch to only take client windows into consideration when deciding whether or not to allow dwm to quit As per the original patch https://dwm.suckless.org/patches/onlyquitonempty/ it used XQueryTree to get a count of the number of windows open to determine whether to allow the window manager to exit. This meant that the empty quit count variable would have to take into account background windows such as the bar, which has side effects like plugging in another monitor could mean that you would not longer be allowed to quit dwm until the monitor is removed. Likewise a systray and each systray icon would give a +1 to the number of windows in the system. This is unintuitive to understand and convoluted to explain, hence the refactoring here to use the more sane approach of only counting the number of client windows that the window manager manages. This is an old idea which was intentionally not added to dwm-flexipatch due to the aim of staying true to the original patch (as in if you were to patch that manually you would get the same experience as you had when trying the patch out in dwm-flexipatch). This is ref. discussion in #194. --- config.def.h | 2 +- dwm.c | 32 ++++++++++++++------------------ 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/config.def.h b/config.def.h index 8e68937..aa79412 100644 --- a/config.def.h +++ b/config.def.h @@ -100,7 +100,7 @@ static int fakefsindicatortype = INDICATOR_PLUS; static int floatfakefsindicatortype = INDICATOR_PLUS_AND_LARGER_SQUARE; #endif // FAKEFULLSCREEN_CLIENT_PATCH #if ONLYQUITONEMPTY_PATCH -static const int quit_empty_window_count = 2; /* only allow dwm to quit if no windows are open, value here represents number of deamons */ +static const int quit_empty_window_count = 0; /* only allow dwm to quit if no (<= count) windows are open */ #endif // ONLYQUITONEMPTY_PATCH #if BAR_EXTRASTATUS_PATCH static const char statussep = ';'; /* separator between status bars */ diff --git a/dwm.c b/dwm.c index 2bd28e6..5d53587 100644 --- a/dwm.c +++ b/dwm.c @@ -2744,27 +2744,23 @@ quit(const Arg *arg) #if COOL_AUTOSTART_PATCH size_t i; #endif // COOL_AUTOSTART_PATCH - #if ONLYQUITONEMPTY_PATCH - unsigned int n; - Window *junk = malloc(1); - - XQueryTree(dpy, root, junk, junk, &junk, &n); - - if (n <= quit_empty_window_count) - { - #if RESTARTSIG_PATCH - restart = arg->i; - #endif // RESTARTSIG_PATCH - running = 0; - } - else - printf("[dwm] not exiting (n=%d)\n", n); - - free(junk); - #else // !ONLYQUITONEMPTY_PATCH #if RESTARTSIG_PATCH restart = arg->i; #endif // RESTARTSIG_PATCH + #if ONLYQUITONEMPTY_PATCH + Monitor *m; + Client *c; + unsigned int n = 0; + + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next, n++); + + if (restart || n <= quit_empty_window_count) + running = 0; + else + fprintf(stderr, "[dwm] not exiting (n=%d)\n", n); + + #else // !ONLYQUITONEMPTY_PATCH running = 0; #endif // ONLYQUITONEMPTY_PATCH From efb9cc721e77128d28142893fe419e044e1ca1c7 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 11 Nov 2021 09:21:58 +0100 Subject: [PATCH 02/49] onlyquitonempty: fix for compilation error when not using the restart sig patch ref. #196 --- dwm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dwm.c b/dwm.c index 5d53587..fb9ced1 100644 --- a/dwm.c +++ b/dwm.c @@ -2755,7 +2755,11 @@ quit(const Arg *arg) for (m = mons; m; m = m->next) for (c = m->clients; c; c = c->next, n++); + #if RESTARTSIG_PATCH if (restart || n <= quit_empty_window_count) + #else + if (n <= quit_empty_window_count) + #endif // RESTARTSIG_PATCH running = 0; else fprintf(stderr, "[dwm] not exiting (n=%d)\n", n); From c7af5c6b67cf2f09439050f635684a42a879c446 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sat, 20 Nov 2021 22:48:46 +0100 Subject: [PATCH 03/49] winicon: Fix potential integer overflow --- patch/bar_winicon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/patch/bar_winicon.c b/patch/bar_winicon.c index 5ae7fe7..a50766c 100644 --- a/patch/bar_winicon.c +++ b/patch/bar_winicon.c @@ -73,13 +73,13 @@ geticonprop(Window win) unsigned long *i; uint32_t bstd = UINT32_MAX, d, m; for (i = p; i < end - 1; i += sz) { - if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return NULL; } + if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return NULL; } if ((sz = w * h) > end - i) break; if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } } if (!bstp) { for (i = p; i < end - 1; i += sz) { - if ((w = *i++) > UINT16_MAX || (h = *i++) > UINT16_MAX) { XFree(p); return NULL; } + if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return NULL; } if ((sz = w * h) > end - i) break; if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; } } From 63fed59d19ee51f8f8d2876425817e099cb57b04 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 23 Nov 2021 22:36:53 +0100 Subject: [PATCH 04/49] Adding taglabels patch ref. #199 --- README.md | 5 +++ config.def.h | 9 +++++ dwm.c | 3 ++ patch/bar_taglabels.c | 87 +++++++++++++++++++++++++++++++++++++++++++ patch/bar_taglabels.h | 5 +++ patch/include.c | 3 ++ patch/include.h | 3 ++ patches.def.h | 7 +++- 8 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 patch/bar_taglabels.c create mode 100644 patch/bar_taglabels.h diff --git a/README.md b/README.md index 18e8b1a..d165871 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ If you are experiencing issues then you may want to check out the [Known Issues] ### Changelog: +2021-11-23 - Added the taglabels patch + 2021-09-08 - Added the alwayscenter patch 2021-07-27 - Added the winicon patch @@ -703,6 +705,9 @@ If you are experiencing issues then you may want to check out the [Known Issues] - [taggrid](https://dwm.suckless.org/patches/taggrid/) - adds an option to place tags in rows like in many other window managers + - [taglabels](https://dwm.suckless.org/patches/taglabels/) + - shows tag + class of master client in the tags section of the bar + - [tagmonfixfs](https://github.com/bakkeby/patches/wiki/tagmonfixfs/) - allows moving a fullscreen window to another monitor while remaining in fullscreen diff --git a/config.def.h b/config.def.h index aa79412..2ed1a25 100644 --- a/config.def.h +++ b/config.def.h @@ -91,6 +91,12 @@ static const char buttonbar[] = ""; static const unsigned int systrayspacing = 2; /* systray spacing */ static const int showsystray = 1; /* 0 means no systray */ #endif // BAR_SYSTRAY_PATCH +#if BAR_TAGLABELS_PATCH +static const char ptagf[] = "[%s %s]"; /* format of a tag label */ +static const char etagf[] = "[%s]"; /* format of an empty tag */ +static const int lcaselbl = 0; /* 1 means make tag label lowercase */ +#endif // BAR_TAGLABELS_PATCH + /* Indicators: see patch/bar_indicators.h for options */ static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE; static int tiledindicatortype = INDICATOR_NONE; @@ -480,6 +486,9 @@ static const BarRule barrules[] = { #if BAR_TAGS_PATCH { -1, 0, BAR_ALIGN_LEFT, width_tags, draw_tags, click_tags, "tags" }, #endif // BAR_TAGS_PATCH + #if BAR_TAGLABELS_PATCH + { -1, 0, BAR_ALIGN_LEFT, width_taglabels, draw_taglabels, click_taglabels, "taglabels" }, + #endif // BAR_TAGLABELS_PATCH #if BAR_TAGGRID_PATCH { -1, 0, BAR_ALIGN_LEFT, width_taggrid, draw_taggrid, click_taggrid, "taggrid" }, #endif // BAR_TAGGRID_PATCH diff --git a/dwm.c b/dwm.c index fb9ced1..d1e1dbe 100644 --- a/dwm.c +++ b/dwm.c @@ -485,6 +485,9 @@ struct Monitor { #if INSETS_PATCH Inset inset; #endif // INSETS_PATCH + #if BAR_TAGLABELS_PATCH + char taglabel[NUMTAGS][64]; + #endif // BAR_TAGLABELS_PATCH #if IPC_PATCH char lastltsymbol[16]; TagState tagstate; diff --git a/patch/bar_taglabels.c b/patch/bar_taglabels.c new file mode 100644 index 0000000..f9c3cf8 --- /dev/null +++ b/patch/bar_taglabels.c @@ -0,0 +1,87 @@ +int +width_taglabels(Bar *bar, BarArg *a) +{ + int w, i; + Client *c; + Monitor *m = bar->mon; + char *icon; + unsigned int occ = 0; + + for (c = m->clients; c; c = c->next) + occ |= c->tags == 255 ? 0 : c->tags; + + for (w = 0, i = 0; i < NUMTAGS; i++) { + m->taglabel[i][0] = '\0'; + #if BAR_HIDEVACANTTAGS_PATCH + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) + continue; + #endif // BAR_HIDEVACANTTAGS_PATCH + icon = tagicon(m, i); + XClassHint ch = { NULL, NULL }; + for (c = m->clients; c; c = c->next) { + if (c->tags & (1 << i)) { + XGetClassHint(dpy, c->win, &ch); + break; + } + } + if (ch.res_class) { + if (lcaselbl) + ch.res_class[0] = tolower(ch.res_class[0]); + snprintf(m->taglabel[i], 64, ptagf, icon, ch.res_class); + } else + snprintf(m->taglabel[i], 64, etagf, icon); + + w += TEXTW(m->taglabel[i]); + } + return w; +} + +int +draw_taglabels(Bar *bar, BarArg *a) +{ + int invert = 0; + int w, x = a->x; + unsigned int i, occ = 0, urg = 0; + Client *c; + Monitor *m = bar->mon; + + for (c = m->clients; c; c = c->next) + if (c->isurgent) + urg |= c->tags; + + for (i = 0; i < NUMTAGS; i++) { + /* do not draw vacant tags */ + if (!m->taglabel[i][0]) + continue; + drw_setscheme(drw, scheme[ + m->tagset[m->seltags] & 1 << i + ? SchemeTagsSel + : urg & 1 << i + ? SchemeUrg + : SchemeTagsNorm + ]); + w = TEXTW(m->taglabel[i]); + drw_text(drw, x, a->y, w, a->h, lrpad / 2, m->taglabel[i], invert, False); + drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype); + x += w; + } + + return 1; +} + +int +click_taglabels(Bar *bar, Arg *arg, BarArg *a) +{ + int i = 0, x = lrpad / 2; + Monitor *m = bar->mon; + + do { + if (!m->taglabel[i][0]) + continue; + x += TEXTW(m->taglabel[i]); + } while (a->x >= x && ++i < NUMTAGS); + if (i < NUMTAGS) { + arg->ui = 1 << i; + } + return ClkTagBar; +} diff --git a/patch/bar_taglabels.h b/patch/bar_taglabels.h new file mode 100644 index 0000000..57250f9 --- /dev/null +++ b/patch/bar_taglabels.h @@ -0,0 +1,5 @@ +#include /* for making tab label lowercase, very tiny standard library */ + +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 diff --git a/patch/include.c b/patch/include.c index 29dac83..d47c6fd 100644 --- a/patch/include.c +++ b/patch/include.c @@ -56,6 +56,9 @@ #if BAR_TAGS_PATCH #include "bar_tags.c" #endif +#if BAR_TAGLABELS_PATCH +#include "bar_taglabels.c" +#endif #if BAR_TAGGRID_PATCH #include "bar_taggrid.c" #endif diff --git a/patch/include.h b/patch/include.h index eea37a8..f26f36e 100644 --- a/patch/include.h +++ b/patch/include.h @@ -56,6 +56,9 @@ #if BAR_TAGS_PATCH #include "bar_tags.h" #endif +#if BAR_TAGLABELS_PATCH +#include "bar_taglabels.h" +#endif #if BAR_TAGGRID_PATCH #include "bar_taggrid.h" #endif diff --git a/patches.def.h b/patches.def.h index bcd15e2..7451dc4 100644 --- a/patches.def.h +++ b/patches.def.h @@ -152,9 +152,14 @@ */ #define BAR_SYSTRAY_PATCH 0 -/* Show tag symbols in bar */ +/* Show tag symbols in the bar. */ #define BAR_TAGS_PATCH 1 +/* Show tag symbols + class of master window in the bar. + * https://dwm.suckless.org/patches/taglabels/ + */ +#define BAR_TAGLABELS_PATCH 0 + /* This patch adds the window icon next to the window title in the bar. * * The patch depends on Imlib2 for icon scaling. From a9078fdb4d2105cd2e58a00c3f4a6ae31b353f2c Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 23 Nov 2021 22:49:27 +0100 Subject: [PATCH 05/49] Adding underlinetags patch ref. #199 --- README.md | 11 +++++++---- config.def.h | 6 ++++++ patch/bar_taglabels.c | 4 ++++ patch/bar_tags.c | 4 ++++ patches.def.h | 5 +++++ 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d165871..dcc4f9c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you are experiencing issues then you may want to check out the [Known Issues] ### Changelog: -2021-11-23 - Added the taglabels patch +2021-11-23 - Added the taglabels and underlinetags patches 2021-09-08 - Added the alwayscenter patch @@ -469,6 +469,9 @@ If you are experiencing issues then you may want to check out the [Known Issues] - this patch adds key modes (like in vim or emacs) where chains of keyboard shortcuts can be performed + - [killunsel](https://dwm.suckless.org/patches/killunsel/) + - kills all visible clients that are not selected (only the selected client will remain) + - [~leftlayout~](http://dwm.suckless.org/patches/leftlayout/) - ~moves the layout symbol in the status bar to the left hand side~ @@ -746,13 +749,13 @@ If you are experiencing issues then you may want to check out the [Known Issues] - lets you transfer all clients between the master and stack area while increasing or decreasing the master area (nmaster) accordingly + - [underlinetags](https://dwm.suckless.org/patches/underlinetags/) + - underlines the selected tag, or optionally all tags + - [unfloatvisible](https://dwm.suckless.org/patches/unfloatvisible/) - resets isfloating on any visible windows that have it set and optionally also applies a layout - - [killunsel](https://dwm.suckless.org/patches/killunsel/) - - kills all visible clients that are not selected (only the selected client will remain) - - [~urgentborder~](https://dwm.suckless.org/patches/urgentborder/) - ~this patch makes "urgent" windows have different colors~ diff --git a/config.def.h b/config.def.h index 2ed1a25..61dd14a 100644 --- a/config.def.h +++ b/config.def.h @@ -96,6 +96,12 @@ static const char ptagf[] = "[%s %s]"; /* format of a tag label */ static const char etagf[] = "[%s]"; /* format of an empty tag */ static const int lcaselbl = 0; /* 1 means make tag label lowercase */ #endif // BAR_TAGLABELS_PATCH +#if BAR_UNDERLINETAGS_PATCH +static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */ +static const unsigned int ulinestroke = 2; /* thickness / height of the underline */ +static const unsigned int ulinevoffset = 0; /* how far above the bottom of the bar the line should appear */ +static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */ +#endif // BAR_UNDERLINETAGS_PATCH /* Indicators: see patch/bar_indicators.h for options */ static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE; diff --git a/patch/bar_taglabels.c b/patch/bar_taglabels.c index f9c3cf8..9e6d441 100644 --- a/patch/bar_taglabels.c +++ b/patch/bar_taglabels.c @@ -63,6 +63,10 @@ draw_taglabels(Bar *bar, BarArg *a) w = TEXTW(m->taglabel[i]); drw_text(drw, x, a->y, w, a->h, lrpad / 2, m->taglabel[i], invert, False); drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype); + #if BAR_UNDERLINETAGS_PATCH + if (ulineall || m->tagset[m->seltags] & 1 << i) + drw_rect(drw, x + ulinepad, bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0); + #endif // BAR_UNDERLINETAGS_PATCH x += w; } diff --git a/patch/bar_tags.c b/patch/bar_tags.c index c00818d..c618ff5 100644 --- a/patch/bar_tags.c +++ b/patch/bar_tags.c @@ -57,6 +57,10 @@ draw_tags(Bar *bar, BarArg *a) ]); drw_text(drw, x, a->y, w, a->h, lrpad / 2, icon, invert, False); drawindicator(m, NULL, occ, x, a->y, w, a->h, i, -1, invert, tagindicatortype); + #if BAR_UNDERLINETAGS_PATCH + if (ulineall || m->tagset[m->seltags] & 1 << i) + drw_rect(drw, x + ulinepad, bh - ulinestroke - ulinevoffset, w - (ulinepad * 2), ulinestroke, 1, 0); + #endif // BAR_UNDERLINETAGS_PATCH x += w; } diff --git a/patches.def.h b/patches.def.h index 7451dc4..022a4a6 100644 --- a/patches.def.h +++ b/patches.def.h @@ -160,6 +160,11 @@ */ #define BAR_TAGLABELS_PATCH 0 +/* This patch underlines the selected tag, or optionally all tags. + * https://dwm.suckless.org/patches/underlinetags/ + */ +#define BAR_UNDERLINETAGS_PATCH 0 + /* This patch adds the window icon next to the window title in the bar. * * The patch depends on Imlib2 for icon scaling. From 40d30e5d1bc4c1a57eab850657ad5818477ac153 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 25 Nov 2021 09:15:27 +0100 Subject: [PATCH 06/49] Adding the one line of bloat that would have saved a lot of time for a lot of people --- dwm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dwm.c b/dwm.c index d1e1dbe..70ef5e7 100644 --- a/dwm.c +++ b/dwm.c @@ -3495,6 +3495,9 @@ setup(void) signal(SIGTERM, sigterm); #endif // RESTARTSIG_PATCH + /* the one line of bloat that would have saved a lot of time for a lot of people */ + putenv("_JAVA_AWT_WM_NONREPARENTING=1"); + /* init screen */ screen = DefaultScreen(dpy); sw = DisplayWidth(dpy, screen); From 8f401e1d81862333b453bb1b184caded6ee643f8 Mon Sep 17 00:00:00 2001 From: Utkarsh Verma Date: Sun, 26 Dec 2021 18:29:55 +0530 Subject: [PATCH 07/49] Add a new patch to integrate vanity gaps with bar padding --- dwm.c | 9 ++++++++- patch/vanitygaps.c | 10 ++++++++++ patches.def.h | 6 ++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 70ef5e7..938ba0e 100644 --- a/dwm.c +++ b/dwm.c @@ -4319,7 +4319,14 @@ updatebarpos(Monitor *m) m->ww = m->mw; m->wh = m->mh; Bar *bar; - #if BAR_PADDING_PATCH + #if BAR_GAPS_PADDING_PATCH + int y_pad = 0; + int x_pad = 0; + if (enablegaps) { + y_pad = gappov; + x_pad = gappoh; + } + #elif BAR_PADDING_PATCH int y_pad = vertpad; int x_pad = sidepad; #else diff --git a/patch/vanitygaps.c b/patch/vanitygaps.c index be2ef08..757aa4d 100644 --- a/patch/vanitygaps.c +++ b/patch/vanitygaps.c @@ -86,6 +86,16 @@ togglegaps(const Arg *arg) #else enablegaps = !enablegaps; #endif // PERTAG_VANITYGAPS_PATCH + + #if BAR_GAPS_PADDING_PATCH + updatebarpos(selmon); + Bar *bar = selmon->bar; + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw + gappoh, bar->bh); + + #if BAR_SYSTRAY_PATCH + drawbarwin(systray->bar); + #endif // BAR_SYSTRAY_PATCH + #endif // BAR_GAPS_PADDING_PATCH arrange(NULL); } diff --git a/patches.def.h b/patches.def.h index 022a4a6..037c5ee 100644 --- a/patches.def.h +++ b/patches.def.h @@ -347,6 +347,12 @@ */ #define BAR_PADDING_PATCH 0 +/* Same as barpadding patch but specifically written for the vanitygaps patch. It adds the same + * outer horizontal and vertical padding as vanity gaps. Moreover, the padding is toggled whenever + * vanitygaps are toggled. + */ +#define BAR_GAPS_PADDING_PATCH 0 + /* This patch adds simple markup for status messages using pango markup. * This depends on the pango library v1.44 or greater. * You need to uncomment the corresponding lines in config.mk to use the pango libraries From 0cd25db5af3d376c1ccbe3485a01f8cdd86d6bd4 Mon Sep 17 00:00:00 2001 From: Utkarsh Verma Date: Sun, 26 Dec 2021 18:53:53 +0530 Subject: [PATCH 08/49] Fix resizing of bar --- patch/vanitygaps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch/vanitygaps.c b/patch/vanitygaps.c index 757aa4d..ed9e983 100644 --- a/patch/vanitygaps.c +++ b/patch/vanitygaps.c @@ -90,7 +90,7 @@ togglegaps(const Arg *arg) #if BAR_GAPS_PADDING_PATCH updatebarpos(selmon); Bar *bar = selmon->bar; - XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw + gappoh, bar->bh); + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); #if BAR_SYSTRAY_PATCH drawbarwin(systray->bar); From 3d081ef5f928bfbf07f67975f4acced1f18e6661 Mon Sep 17 00:00:00 2001 From: Utkarsh Verma Date: Sun, 26 Dec 2021 19:30:01 +0530 Subject: [PATCH 09/49] Loop through all bars --- patch/vanitygaps.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/patch/vanitygaps.c b/patch/vanitygaps.c index ed9e983..880bf4a 100644 --- a/patch/vanitygaps.c +++ b/patch/vanitygaps.c @@ -89,8 +89,9 @@ togglegaps(const Arg *arg) #if BAR_GAPS_PADDING_PATCH updatebarpos(selmon); - Bar *bar = selmon->bar; - XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + Bar *bar; + for (bar = selmon->bar; bar; bar = bar->next) + XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); #if BAR_SYSTRAY_PATCH drawbarwin(systray->bar); From 6667f1030bcb43716c81867eecf6efcb070c2c3d Mon Sep 17 00:00:00 2001 From: Utkarsh Verma Date: Sun, 26 Dec 2021 21:26:32 +0530 Subject: [PATCH 10/49] Make sure it plays well with pertag patch --- dwm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index 938ba0e..bd57193 100644 --- a/dwm.c +++ b/dwm.c @@ -4319,10 +4319,15 @@ updatebarpos(Monitor *m) m->ww = m->mw; m->wh = m->mh; Bar *bar; - #if BAR_GAPS_PADDING_PATCH + #if BAR_GAPS_PADDING_PATCH && VANITYGAPS_PATCH int y_pad = 0; int x_pad = 0; + + #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH + if (!selmon || selmon->pertag->enablegaps[selmon->pertag->curtag]) { + #else if (enablegaps) { + #endif // PERTAG_VANITYGAPS_PATCH y_pad = gappov; x_pad = gappoh; } From 9ea0cb6c7c6863f58c332438cc4dae1cc156db56 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 7 Jan 2022 22:27:08 +0100 Subject: [PATCH 11/49] Fix for infinite loop when there is only one client and pushup is run twice --- patch/push.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/patch/push.c b/patch/push.c index 9410e61..68123a6 100644 --- a/patch/push.c +++ b/patch/push.c @@ -40,9 +40,11 @@ pushup(const Arg *arg) } else { /* move to the end */ for (c = sel; c->next; c = c->next); - detach(sel); - sel->next = NULL; - c->next = sel; + if (sel != c) { + detach(sel); + sel->next = NULL; + c->next = sel; + } } focus(sel); arrange(selmon); From 0350db1b3917d74ac0565fff3d5537f246ab4ff0 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 10 Jan 2022 17:16:09 +0100 Subject: [PATCH 12/49] drawbar: Don't expend effort drawing bar if it is occluded I noticed that a non-trivial amount of dwm's work on my machine was from drw_text, which seemed weird, because I have the bar disabled and we only use drw_text as part of bar drawing. Looking more closely, I realised that while we use m->showbar when updating the monitor bar margins, but don't skip actually drawing the bar if it is hidden. This patch skips drawing it entirely if that is the case. On my machine, this takes 10% of dwm's on-CPU time, primarily from restack() and focus(). When the bar is toggled on again, the X server will generate an Expose event, and we'll redraw the bar as normal as part of expose(). Ref. https://git.suckless.org/dwm/commit/8657affa2a61e85ca8df76b62e43cb02897d1d80.html --- dwm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 70ef5e7..99299a7 100644 --- a/dwm.c +++ b/dwm.c @@ -1753,8 +1753,10 @@ void drawbar(Monitor *m) { Bar *bar; - for (bar = m->bar; bar; bar = bar->next) - drawbarwin(bar); + + if (m->showbar) + for (bar = m->bar; bar; bar = bar->next) + drawbarwin(bar); } void @@ -3948,6 +3950,10 @@ togglebar(const Arg *arg) updatebarpos(selmon); for (bar = selmon->bar; bar; bar = bar->next) XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #if BAR_SYSTRAY_PATCH + if (!selmon->showbar && systray) + XMoveWindow(dpy, systray->win, -32000, -32000); + #endif // BAR_SYSTRAY_PATCH arrange(selmon); } From 0a4e6de5977bd57f1bdd22146c912940e09bc41d Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 10 Jan 2022 17:18:45 +0100 Subject: [PATCH 13/49] Add a configuration option for fullscreen locking Some people are annoyed to have this new behaviour forced for some application which use fake fullscreen. Ref. https://git.suckless.org/dwm/commit/138b405f0c8aa24d8a040cc1a1cf6e3eb5a0ebc7.html --- config.def.h | 1 + dwm.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 61dd14a..469f70f 100644 --- a/config.def.h +++ b/config.def.h @@ -567,6 +567,7 @@ static const int nmaster = 1; /* number of clients in master area */ static const int nstack = 0; /* number of clients in primary stack area */ #endif // FLEXTILE_DELUXE_LAYOUT static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ #if DECORATION_HINTS_PATCH static const int decorhints = 1; /* 1 means respect decoration hints */ #endif // DECORATION_HINTS_PATCH diff --git a/dwm.c b/dwm.c index 99299a7..c27f65c 100644 --- a/dwm.c +++ b/dwm.c @@ -2018,7 +2018,7 @@ focusstack(const Arg *arg) if (!selmon->sel || (selmon->sel->isfullscreen && !selmon->sel->fakefullscreen)) return; #else - if (!selmon->sel || selmon->sel->isfullscreen) + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) return; #endif // LOSEFULLSCREEN_PATCH #if BAR_WINTITLEACTIONS_PATCH From 0404e12dbaca203325f391f751f1188f91a7ef1a Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 10 Jan 2022 17:24:12 +0100 Subject: [PATCH 14/49] bump version to 6.3 --- README.md | 2 +- config.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dcc4f9c..3fc48f5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This dwm 6.2 (67d76bd, 2021-03-29) 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.3 (d39e2f3, 2022-01-07) 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 diff --git a/config.mk b/config.mk index 62d1c84..fb2310c 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.2 +VERSION = 6.3 # Customize below to fit your system From 406faa9cc3019b90760cae54414e513f61c10c73 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 14 Jan 2022 21:12:36 +0100 Subject: [PATCH 15/49] tags bar module: fix for wrong click offset ref. #215 --- patch/bar_tags.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch/bar_tags.c b/patch/bar_tags.c index c618ff5..8b9092d 100644 --- a/patch/bar_tags.c +++ b/patch/bar_tags.c @@ -70,7 +70,7 @@ draw_tags(Bar *bar, BarArg *a) int click_tags(Bar *bar, Arg *arg, BarArg *a) { - int i = 0, x = lrpad / 2; + int i = 0, x = 0; #if BAR_HIDEVACANTTAGS_PATCH Client *c; unsigned int occ = 0; From 489ac300925d156cbcc3b814234021e07e5b8e05 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 18 Jan 2022 11:04:35 +0100 Subject: [PATCH 16/49] Refactoring window title drawing with regards to icons ref. #216 --- patch/bar_awesomebar.c | 49 +++++++++++++++++++++++++++------ patch/bar_fancybar.c | 57 ++++++++++++++++++++++++-------------- patch/bar_flexwintitle.c | 59 ++++++++++++++++++++++++++++++---------- patch/bar_tabgroups.c | 57 ++++++++++++++++++++++++++++---------- patch/bar_wintitle.c | 47 ++++++++++++++++++++++++++------ 5 files changed, 201 insertions(+), 68 deletions(-) diff --git a/patch/bar_awesomebar.c b/patch/bar_awesomebar.c index b02c6e7..81711f3 100644 --- a/patch/bar_awesomebar.c +++ b/patch/bar_awesomebar.c @@ -7,8 +7,14 @@ width_awesomebar(Bar *bar, BarArg *a) int draw_awesomebar(Bar *bar, BarArg *a) { - int n = 0, scm, remainder = 0, tabw, pad; + int n = 0, scm, remainder = 0, tabw, tpad, tx, tw; unsigned int i; + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + #if BAR_WINICON_PATCH + int ipad; + #endif // BAR_WINICON_PATCH #if BAR_TITLE_LEFT_PAD_PATCH && BAR_TITLE_RIGHT_PAD_PATCH int x = a->x + lrpad / 2, w = a->w - lrpad; #elif BAR_TITLE_LEFT_PAD_PATCH @@ -39,22 +45,49 @@ draw_awesomebar(Bar *bar, BarArg *a) else scm = SchemeTitleNorm; - pad = lrpad / 2; + tpad = lrpad / 2; #if BAR_CENTEREDWINDOWNAME_PATCH + cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + #if BAR_WINICON_PATCH + ipad = c->icon ? c->icon->width + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + + tx = x; + tw = tabw; + + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + if (TEXTW(c->name) + ipad < tabw) + cpad = (tabw - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH if (TEXTW(c->name) < tabw) - pad = (tabw - TEXTW(c->name) + lrpad) / 2; + cpad = (tabw - TEXTW(c->name)) / 2; #endif // BAR_CENTEREDWINDOWNAME_PATCH drw_setscheme(drw, scheme[scm]); + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, tx, a->y, tw, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + #if BAR_WINICON_PATCH - drw_text(drw, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + pad, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, pad, c->name, 0, False); + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; + } #endif // BAR_WINICON_PATCH + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + drawstateindicator(c->mon, c, 1, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, 0, 0, c->isfixed); x += tabw + (i < remainder ? 1 : 0); } diff --git a/patch/bar_fancybar.c b/patch/bar_fancybar.c index 10bac83..623d1c3 100644 --- a/patch/bar_fancybar.c +++ b/patch/bar_fancybar.c @@ -7,7 +7,10 @@ width_fancybar(Bar *bar, BarArg *a) int draw_fancybar(Bar *bar, BarArg *a) { - int ftw, mw, ew = 0, n = 0; + int tabw, mw, ew = 0, n = 0, tx, tw; + #if BAR_WINICON_PATCH + int ipad; + #endif // BAR_WINICON_PATCH unsigned int i; Client *c; Monitor *m = bar->mon; @@ -28,25 +31,25 @@ draw_fancybar(Bar *bar, BarArg *a) } if (n > 0) { - ftw = TEXTW(m->sel->name); + tabw = TEXTW(m->sel->name); #if BAR_WINICON_PATCH if (m->sel->icon) - ftw += m->sel->icon->width + ICONSPACING; + tabw += m->sel->icon->width + ICONSPACING; #endif // BAR_WINICON_PATCH - mw = (ftw >= w || n == 1) ? 0 : (w - ftw) / (n - 1); + mw = (tabw >= w || n == 1) ? 0 : (w - tabw) / (n - 1); i = 0; for (c = m->clients; c; c = c->next) { if (!ISVISIBLE(c) || c == m->sel) continue; - ftw = TEXTW(c->name); + tabw = TEXTW(c->name); #if BAR_WINICON_PATCH if (c->icon) - ftw += c->icon->width + ICONSPACING; + tabw += c->icon->width + ICONSPACING; #endif // BAR_WINICON_PATCH - if (ftw < mw) - ew += (mw - ftw); + if (tabw < mw) + ew += (mw - tabw); else i++; } @@ -57,24 +60,36 @@ draw_fancybar(Bar *bar, BarArg *a) for (c = m->clients; c; c = c->next) { if (!ISVISIBLE(c)) continue; - ftw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); + tabw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); + #if BAR_WINICON_PATCH + ipad = c->icon ? c->icon->width + ICONSPACING : 0; + tabw += ipad; + #endif // BAR_WINICON_PATCH + tx = x; + tw = tabw; drw_setscheme(drw, scheme[m->sel == c ? SchemeTitleSel : SchemeTitleNorm]); - if (ftw > 0) { /* trap special handling of 0 in drw_text */ - drw_text(drw, x, a->y, ftw, a->h, lrpad / 2, c->name, 0, False); + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, tx, a->y, tw, a->h); - #if BAR_WINICON_PATCH - drw_text(drw, x, a->y, ftw, a->h, lrpad / 2 + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + lrpad / 2, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, a->y, ftw, a->h, lrpad / 2, c->name, 0, False); - #endif // BAR_WINICON_PATCH + if (tabw <= 0) /* trap special handling of 0 in drw_text */ + continue; + tx += lrpad / 2; + tw -= lrpad; + + #if BAR_WINICON_PATCH + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; } - drawstateindicator(c->mon, c, 1, x, a->y, ftw, a->h, 0, 0, c->isfixed); - x += ftw; - w -= ftw; + #endif // BAR_WINICON_PATCH + + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + drawstateindicator(c->mon, c, 1, x, a->y, tabw, a->h, 0, 0, c->isfixed); + x += tabw; + w -= tabw; } } return n; diff --git a/patch/bar_flexwintitle.c b/patch/bar_flexwintitle.c index 0e17443..b5d77b0 100644 --- a/patch/bar_flexwintitle.c +++ b/patch/bar_flexwintitle.c @@ -166,11 +166,21 @@ getselschemefor(int scheme) } void -flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Arg *arg, BarArg *barg) +flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Arg *arg, BarArg *a) { if (!c) return; - int i, nclienttags = 0, nviewtags = 0, pad = lrpad / 2; + int i, nclienttags = 0, nviewtags = 0; + int tpad = lrpad / 2; + #if BAR_WINICON_PATCH + int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + int tx = x; + int tw = w; + int clientscheme = ( c == selmon->sel && HIDDEN(c) ? SchemeHidSel @@ -182,30 +192,49 @@ flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Ar ? SchemeUrg : tabscheme ); + drw_setscheme(drw, scheme[clientscheme]); XSetWindowBorder(dpy, c->win, scheme[clientscheme][ColBorder].pixel); - if (w <= TEXTW("A") - lrpad + pad) // reduce text padding if wintitle is too small - pad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); - #if BAR_CENTEREDWINDOWNAME_PATCH + + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) + ipad < w) + cpad = (w - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH else if (TEXTW(c->name) < w) - pad = (w - TEXTW(c->name) + lrpad) / 2; + cpad = (w - TEXTW(c->name)) / 2; #endif // BAR_CENTEREDWINDOWNAME_PATCH + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + #if BAR_WINICON_PATCH - drw_text(drw, x, barg->y, w, barg->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + pad, barg->y + (barg->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, barg->y, w, barg->h, pad, c->name, 0, False); + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; + } #endif // BAR_WINICON_PATCH - drawstateindicator(m, c, 1, x + 2, barg->y, w, barg->h, 0, 0, 0); + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + drawstateindicator(m, c, 1, x + 2, a->y, w, a->h, 0, 0, 0); if (FLEXWINTITLE_BORDERS) { XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, barg->y, 1, barg->h); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= barg->w ? 1 : 0), barg->y, 1, barg->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, 1, a->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= a->w ? 1 : 0), a->y, 1, a->h); } + /* Optional tags icons */ for (i = 0; i < NUMTAGS; i++) { if ((m->tagset[m->seltags] >> i) & 1) @@ -215,7 +244,7 @@ flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Ar } if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) - drawindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); + drawindicator(m, c, 1, x, a->y, w, a->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); } #ifndef HIDDEN diff --git a/patch/bar_tabgroups.c b/patch/bar_tabgroups.c index 1498bc2..b89d348 100644 --- a/patch/bar_tabgroups.c +++ b/patch/bar_tabgroups.c @@ -36,11 +36,21 @@ click_bartabgroups(Bar *bar, Arg *arg, BarArg *a) } void -bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *barg) +bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *a) { if (!c) return; - int i, nclienttags = 0, nviewtags = 0, pad = lrpad / 2; + int i, nclienttags = 0, nviewtags = 0; + int tpad = lrpad / 2; + #if BAR_WINICON_PATCH + int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + int tx = x; + int tw = w; + drw_setscheme(drw, scheme[ m->sel == c #ifdef HIDDEN @@ -55,27 +65,44 @@ bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg ? SchemeTitleSel : SchemeTitleNorm ]); - if (w <= TEXTW("A") - lrpad + pad) // reduce text padding if wintitle is too small - pad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); - #if BAR_CENTEREDWINDOWNAME_PATCH + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) + ipad < w) + cpad = (w - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH else if (TEXTW(c->name) < w) - pad = (w - TEXTW(c->name) + lrpad) / 2; + cpad = (w - TEXTW(c->name)) / 2; #endif // BAR_CENTEREDWINDOWNAME_PATCH + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + #if BAR_WINICON_PATCH - drw_text(drw, x, barg->y, w, barg->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + pad, barg->y + (barg->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, barg->y, w, barg->h, pad, c->name, 0, False); + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; + } #endif // BAR_WINICON_PATCH - drawstateindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, c->isfixed); + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + + drawstateindicator(m, c, 1, x, a->y, w, a->h, 0, 0, c->isfixed); if (BARTAB_BORDERS) { XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, barg->y, 1, barg->h); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= barg->w ? 1 : 0), barg->y, 1, barg->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, 1, a->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= a->w ? 1 : 0), a->y, 1, a->h); } /* Optional tags icons */ for (i = 0; i < NUMTAGS; i++) { @@ -86,7 +113,7 @@ bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg } if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) - drawindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); + drawindicator(m, c, 1, x, a->y, w, a->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); } #ifndef HIDDEN diff --git a/patch/bar_wintitle.c b/patch/bar_wintitle.c index d2241d2..72926f2 100644 --- a/patch/bar_wintitle.c +++ b/patch/bar_wintitle.c @@ -18,7 +18,6 @@ draw_wintitle(Bar *bar, BarArg *a) #endif // BAR_TITLE_LEFT_PAD_PATCH | BAR_TITLE_RIGHT_PAD_PATCH Monitor *m = bar->mon; Client *c = m->sel; - int pad = lrpad / 2; if (!c) { drw_setscheme(drw, scheme[SchemeTitleNorm]); @@ -26,23 +25,53 @@ draw_wintitle(Bar *bar, BarArg *a) return 0; } + int tpad = lrpad / 2; + #if BAR_WINICON_PATCH + int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + int tx = x; + int tw = w; + drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]); #if BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH XSetErrorHandler(xerrordummy); #endif // BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH - #if BAR_CENTEREDWINDOWNAME_PATCH - if (TEXTW(c->name) < w) - pad = (w - TEXTW(c->name) + lrpad) / 2; + + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) + ipad < w) + cpad = (w - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) < w) + cpad = (w - TEXTW(c->name)) / 2; #endif // BAR_CENTEREDWINDOWNAME_PATCH + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + #if BAR_WINICON_PATCH - drw_text(drw, x, a->y, w, a->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + pad, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, a->y, w, a->h, pad, c->name, 0, False); + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; + } #endif // BAR_WINICON_PATCH + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + #if BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH XSync(dpy, False); XSetErrorHandler(xerror); From e6dc6a30167818f6254e98a6d7a8f9762c0c9d59 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 18 Jan 2022 11:08:34 +0100 Subject: [PATCH 17/49] Refactoring restack to allow it to work without having the bar as a reference ref. #214 --- dwm.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/dwm.c b/dwm.c index c27f65c..3e52255 100644 --- a/dwm.c +++ b/dwm.c @@ -3000,7 +3000,7 @@ resizemouse(const Arg *arg) void restack(Monitor *m) { - Client *c; + Client *c, *f = NULL; XEvent ev; XWindowChanges wc; #if WARP_PATCH && FLEXTILE_DELUXE_LAYOUT @@ -3015,11 +3015,17 @@ restack(Monitor *m) return; if (m->sel->isfloating || !m->lt[m->sellt]->arrange) XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange && m->bar) { + if (m->lt[m->sellt]->arrange) { wc.stack_mode = Below; - wc.sibling = m->bar->win; + if (m->bar) { + wc.sibling = m->bar->win; + } else { + for (f = m->stack; f && (f->isfloating || !ISVISIBLE(f)); f = f->snext); // find first tiled stack client + if (f) + wc.sibling = f->win; + } for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { + if (!c->isfloating && ISVISIBLE(c) && c != f) { XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); wc.sibling = c->win; } From 2c5f877bd20497b188b5859b2cd88ab11068b554 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 18 Jan 2022 14:29:11 +0100 Subject: [PATCH 18/49] Ignoring unused functions warnings. This is achieved by adding the -Wno-unused-function flag to the compiler. The warnings are suppressed to avoid confusion for users new to dwm. Removing the static declaration from the header files works too, but adds unnecessary data into the compiled object. --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index fb2310c..6829536 100644 --- a/config.mk +++ b/config.mk @@ -58,7 +58,7 @@ LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} LDFLAGS = ${LIBS} # Solaris From 4366f72390545fdc7ade62f4b002b5471913d0e5 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 20 Jan 2022 22:21:55 +0100 Subject: [PATCH 19/49] Fix for drw_text cropping one characters too many when the text is too long and replacing with ... ref. #216 --- drw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drw.c b/drw.c index 0fc9f05..afb6477 100644 --- a/drw.c +++ b/drw.c @@ -507,8 +507,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp if (utf8strlen) { drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); /* shorten text if necessary */ - for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(usedfont, utf8str, len, &ew, NULL); + for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; drw_font_getexts(usedfont, utf8str, len, &ew, NULL)) + len--; if (len) { memcpy(buf, utf8str, len); From 24ca9b424312b08c1c9b18d3e9d5ec965df3254f Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 11 Feb 2022 09:44:40 +0100 Subject: [PATCH 20/49] sizehints ruled: have rule checks take window type and role into account ref. #229 --- patch/sizehints_ruled.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/patch/sizehints_ruled.c b/patch/sizehints_ruled.c index 99c7e62..ce2eeb9 100644 --- a/patch/sizehints_ruled.c +++ b/patch/sizehints_ruled.c @@ -2,6 +2,10 @@ void checkfloatingrules(Client *c) { const char *class, *instance; + Atom wintype; + #if WINDOWROLERULE_PATCH + char role[64]; + #endif // WINDOWROLERULE_PATCH unsigned int i; const Rule *r; XClassHint ch = { NULL, NULL }; @@ -9,13 +13,23 @@ checkfloatingrules(Client *c) XGetClassHint(dpy, c->win, &ch); class = ch.res_class ? ch.res_class : broken; instance = ch.res_name ? ch.res_name : broken; + wintype = getatomprop(c, netatom[NetWMWindowType]); + #if WINDOWROLERULE_PATCH + gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role)); + #endif // WINDOWROLERULE_PATCH for (i = 0; i < LENGTH(rules); i++) { r = &rules[i]; if ((!r->title || strstr(c->name, r->title)) && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) + #if WINDOWROLERULE_PATCH + && (!r->role || strstr(role, r->role)) + #endif // WINDOWROLERULE_PATCH + && (!r->instance || strstr(instance, r->instance)) + && (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False))) + { c->isfloating = r->isfloating; + } } if (ch.res_class) XFree(ch.res_class); From 065c17de4c3e91071a3ed863b7d0f85d72a757d3 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 11 Feb 2022 10:10:28 +0100 Subject: [PATCH 21/49] Adding the isfreesize version of the sizehints patch ref. #229 --- README.md | 2 ++ dwm.c | 25 +++++++++++++++++++++---- patches.def.h | 13 +++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3fc48f5..abec291 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ If you are experiencing issues then you may want to check out the [Known Issues] ### Changelog: +2022-02-11 - Added the isfreesize version of the sizehints patch + 2021-11-23 - Added the taglabels and underlinetags patches 2021-09-08 - Added the alwayscenter patch diff --git a/dwm.c b/dwm.c index 3e52255..475e778 100644 --- a/dwm.c +++ b/dwm.c @@ -368,6 +368,9 @@ struct Client { #if PLACEMOUSE_PATCH int beingmoved; #endif // PLACEMOUSE_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + int isfreesize; + #endif // SIZEHINTS_ISFREESIZE_PATCH #if SWALLOW_PATCH int isterminal, noswallow; pid_t pid; @@ -515,6 +518,9 @@ typedef struct { #if SELECTIVEFAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH int isfakefullscreen; #endif // SELECTIVEFAKEFULLSCREEN_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + int isfreesize; + #endif // SIZEHINTS_ISFREESIZE_PATCH #if ISPERMANENT_PATCH int ispermanent; #endif // ISPERMANENT_PATCH @@ -825,6 +831,9 @@ applyrules(Client *c) #if SWALLOW_PATCH c->noswallow = -1; #endif // SWALLOW_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + c->isfreesize = 1; + #endif // SIZEHINTS_ISFREESIZE_PATCH c->isfloating = 0; c->tags = 0; XGetClassHint(dpy, c->win, &ch); @@ -863,6 +872,9 @@ applyrules(Client *c) c->isterminal = r->isterminal; c->noswallow = r->noswallow; #endif // SWALLOW_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + c->isfreesize = r->isfreesize; + #endif // SIZEHINTS_ISFREESIZE_PATCH c->isfloating = r->isfloating; c->tags |= r->tags; #if SCRATCHPADS_PATCH @@ -4521,11 +4533,11 @@ updatesizehints(Client *c) if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) /* size is uninitialized, ensure that size.flags aren't used */ - #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH + #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH || SIZEHINTS_ISFREESIZE_PATCH size.flags = 0; #else size.flags = PSize; - #endif // SIZEHINTS_PATCH | SIZEHINTS_RULED_PATCH + #endif // SIZEHINTS_PATCH | SIZEHINTS_RULED_PATCH | SIZEHINTS_ISFREESIZE_PATCH if (size.flags & PBaseSize) { c->basew = size.base_width; c->baseh = size.base_height; @@ -4557,8 +4569,13 @@ updatesizehints(Client *c) c->maxa = (float)size.max_aspect.x / size.max_aspect.y; } else c->maxa = c->mina = 0.0; - #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH - if (size.flags & PSize) { + #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH || SIZEHINTS_ISFREESIZE_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + if ((size.flags & PSize) && c->isfreesize) + #else + if (size.flags & PSize) + #endif // SIZEHINTS_ISFREESIZE_PATCH + { c->basew = size.base_width; c->baseh = size.base_height; c->isfloating = 1; diff --git a/patches.def.h b/patches.def.h index 022a4a6..a410afd 100644 --- a/patches.def.h +++ b/patches.def.h @@ -964,6 +964,19 @@ */ #define SIZEHINTS_RULED_PATCH 0 +/* This patch makes dwm obey even "soft" sizehints for new clients. The isfreesize + * version is similar to the sizehints ruled patch except it allows you to specify + * via client rules which clients this should apply to. Soft sizehints applies by + * default to clients that are not ruled, and will be disabled by default for clients + * that are. + * + * Example client rule enabling soft sizehints: + * - RULE(.wintype = WTYPE "DIALOG", .isfloating = 1, .isfreesize = 1) + * + * https://dwm.suckless.org/patches/sizehints/ + */ +#define SIZEHINTS_ISFREESIZE_PATCH 0 + /* In a multi-head setup monitor 0 is by default the primary screen, with the left and right * screen being monitor 1 and 2 respectively. This patch sorts screens left to right (or * top to bottom in a vertical layout) which aims to address some inconsistencies when it From aa1a7ff708572535c1e952e6318128b69142a893 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 7 Jan 2022 22:27:08 +0100 Subject: [PATCH 22/49] Fix for infinite loop when there is only one client and pushup is run twice --- patch/push.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/patch/push.c b/patch/push.c index 9410e61..68123a6 100644 --- a/patch/push.c +++ b/patch/push.c @@ -40,9 +40,11 @@ pushup(const Arg *arg) } else { /* move to the end */ for (c = sel; c->next; c = c->next); - detach(sel); - sel->next = NULL; - c->next = sel; + if (sel != c) { + detach(sel); + sel->next = NULL; + c->next = sel; + } } focus(sel); arrange(selmon); From 1920595795be273d36584e3fa884b9abcf85a92c Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 10 Jan 2022 17:16:09 +0100 Subject: [PATCH 23/49] drawbar: Don't expend effort drawing bar if it is occluded I noticed that a non-trivial amount of dwm's work on my machine was from drw_text, which seemed weird, because I have the bar disabled and we only use drw_text as part of bar drawing. Looking more closely, I realised that while we use m->showbar when updating the monitor bar margins, but don't skip actually drawing the bar if it is hidden. This patch skips drawing it entirely if that is the case. On my machine, this takes 10% of dwm's on-CPU time, primarily from restack() and focus(). When the bar is toggled on again, the X server will generate an Expose event, and we'll redraw the bar as normal as part of expose(). Ref. https://git.suckless.org/dwm/commit/8657affa2a61e85ca8df76b62e43cb02897d1d80.html --- dwm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index bd57193..a376707 100644 --- a/dwm.c +++ b/dwm.c @@ -1753,8 +1753,10 @@ void drawbar(Monitor *m) { Bar *bar; - for (bar = m->bar; bar; bar = bar->next) - drawbarwin(bar); + + if (m->showbar) + for (bar = m->bar; bar; bar = bar->next) + drawbarwin(bar); } void @@ -3948,6 +3950,10 @@ togglebar(const Arg *arg) updatebarpos(selmon); for (bar = selmon->bar; bar; bar = bar->next) XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #if BAR_SYSTRAY_PATCH + if (!selmon->showbar && systray) + XMoveWindow(dpy, systray->win, -32000, -32000); + #endif // BAR_SYSTRAY_PATCH arrange(selmon); } From 094c8ff363fbea645e65185c671ec9af4df1d333 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 10 Jan 2022 17:18:45 +0100 Subject: [PATCH 24/49] Add a configuration option for fullscreen locking Some people are annoyed to have this new behaviour forced for some application which use fake fullscreen. Ref. https://git.suckless.org/dwm/commit/138b405f0c8aa24d8a040cc1a1cf6e3eb5a0ebc7.html --- config.def.h | 1 + dwm.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config.def.h b/config.def.h index 61dd14a..469f70f 100644 --- a/config.def.h +++ b/config.def.h @@ -567,6 +567,7 @@ static const int nmaster = 1; /* number of clients in master area */ static const int nstack = 0; /* number of clients in primary stack area */ #endif // FLEXTILE_DELUXE_LAYOUT static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ #if DECORATION_HINTS_PATCH static const int decorhints = 1; /* 1 means respect decoration hints */ #endif // DECORATION_HINTS_PATCH diff --git a/dwm.c b/dwm.c index a376707..803f77a 100644 --- a/dwm.c +++ b/dwm.c @@ -2018,7 +2018,7 @@ focusstack(const Arg *arg) if (!selmon->sel || (selmon->sel->isfullscreen && !selmon->sel->fakefullscreen)) return; #else - if (!selmon->sel || selmon->sel->isfullscreen) + if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) return; #endif // LOSEFULLSCREEN_PATCH #if BAR_WINTITLEACTIONS_PATCH From 2771f3d1c918a1c89691292e64787711ebdc7f7f Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 10 Jan 2022 17:24:12 +0100 Subject: [PATCH 25/49] bump version to 6.3 --- README.md | 2 +- config.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dcc4f9c..3fc48f5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This dwm 6.2 (67d76bd, 2021-03-29) 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.3 (d39e2f3, 2022-01-07) 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 diff --git a/config.mk b/config.mk index 62d1c84..fb2310c 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.2 +VERSION = 6.3 # Customize below to fit your system From a0d5ba9369fce6736dcf8e01966c6bb5a77973aa Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 14 Jan 2022 21:12:36 +0100 Subject: [PATCH 26/49] tags bar module: fix for wrong click offset ref. #215 --- patch/bar_tags.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch/bar_tags.c b/patch/bar_tags.c index c618ff5..8b9092d 100644 --- a/patch/bar_tags.c +++ b/patch/bar_tags.c @@ -70,7 +70,7 @@ draw_tags(Bar *bar, BarArg *a) int click_tags(Bar *bar, Arg *arg, BarArg *a) { - int i = 0, x = lrpad / 2; + int i = 0, x = 0; #if BAR_HIDEVACANTTAGS_PATCH Client *c; unsigned int occ = 0; From b17ea8e2de2846b4a2dd8593cf181275854577a7 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 18 Jan 2022 11:04:35 +0100 Subject: [PATCH 27/49] Refactoring window title drawing with regards to icons ref. #216 --- patch/bar_awesomebar.c | 49 +++++++++++++++++++++++++++------ patch/bar_fancybar.c | 57 ++++++++++++++++++++++++-------------- patch/bar_flexwintitle.c | 59 ++++++++++++++++++++++++++++++---------- patch/bar_tabgroups.c | 57 ++++++++++++++++++++++++++++---------- patch/bar_wintitle.c | 47 ++++++++++++++++++++++++++------ 5 files changed, 201 insertions(+), 68 deletions(-) diff --git a/patch/bar_awesomebar.c b/patch/bar_awesomebar.c index b02c6e7..81711f3 100644 --- a/patch/bar_awesomebar.c +++ b/patch/bar_awesomebar.c @@ -7,8 +7,14 @@ width_awesomebar(Bar *bar, BarArg *a) int draw_awesomebar(Bar *bar, BarArg *a) { - int n = 0, scm, remainder = 0, tabw, pad; + int n = 0, scm, remainder = 0, tabw, tpad, tx, tw; unsigned int i; + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + #if BAR_WINICON_PATCH + int ipad; + #endif // BAR_WINICON_PATCH #if BAR_TITLE_LEFT_PAD_PATCH && BAR_TITLE_RIGHT_PAD_PATCH int x = a->x + lrpad / 2, w = a->w - lrpad; #elif BAR_TITLE_LEFT_PAD_PATCH @@ -39,22 +45,49 @@ draw_awesomebar(Bar *bar, BarArg *a) else scm = SchemeTitleNorm; - pad = lrpad / 2; + tpad = lrpad / 2; #if BAR_CENTEREDWINDOWNAME_PATCH + cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + #if BAR_WINICON_PATCH + ipad = c->icon ? c->icon->width + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + + tx = x; + tw = tabw; + + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + if (TEXTW(c->name) + ipad < tabw) + cpad = (tabw - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH if (TEXTW(c->name) < tabw) - pad = (tabw - TEXTW(c->name) + lrpad) / 2; + cpad = (tabw - TEXTW(c->name)) / 2; #endif // BAR_CENTEREDWINDOWNAME_PATCH drw_setscheme(drw, scheme[scm]); + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, tx, a->y, tw, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + #if BAR_WINICON_PATCH - drw_text(drw, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + pad, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, pad, c->name, 0, False); + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; + } #endif // BAR_WINICON_PATCH + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + drawstateindicator(c->mon, c, 1, x, a->y, tabw + (i < remainder ? 1 : 0), a->h, 0, 0, c->isfixed); x += tabw + (i < remainder ? 1 : 0); } diff --git a/patch/bar_fancybar.c b/patch/bar_fancybar.c index 10bac83..623d1c3 100644 --- a/patch/bar_fancybar.c +++ b/patch/bar_fancybar.c @@ -7,7 +7,10 @@ width_fancybar(Bar *bar, BarArg *a) int draw_fancybar(Bar *bar, BarArg *a) { - int ftw, mw, ew = 0, n = 0; + int tabw, mw, ew = 0, n = 0, tx, tw; + #if BAR_WINICON_PATCH + int ipad; + #endif // BAR_WINICON_PATCH unsigned int i; Client *c; Monitor *m = bar->mon; @@ -28,25 +31,25 @@ draw_fancybar(Bar *bar, BarArg *a) } if (n > 0) { - ftw = TEXTW(m->sel->name); + tabw = TEXTW(m->sel->name); #if BAR_WINICON_PATCH if (m->sel->icon) - ftw += m->sel->icon->width + ICONSPACING; + tabw += m->sel->icon->width + ICONSPACING; #endif // BAR_WINICON_PATCH - mw = (ftw >= w || n == 1) ? 0 : (w - ftw) / (n - 1); + mw = (tabw >= w || n == 1) ? 0 : (w - tabw) / (n - 1); i = 0; for (c = m->clients; c; c = c->next) { if (!ISVISIBLE(c) || c == m->sel) continue; - ftw = TEXTW(c->name); + tabw = TEXTW(c->name); #if BAR_WINICON_PATCH if (c->icon) - ftw += c->icon->width + ICONSPACING; + tabw += c->icon->width + ICONSPACING; #endif // BAR_WINICON_PATCH - if (ftw < mw) - ew += (mw - ftw); + if (tabw < mw) + ew += (mw - tabw); else i++; } @@ -57,24 +60,36 @@ draw_fancybar(Bar *bar, BarArg *a) for (c = m->clients; c; c = c->next) { if (!ISVISIBLE(c)) continue; - ftw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); + tabw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); + #if BAR_WINICON_PATCH + ipad = c->icon ? c->icon->width + ICONSPACING : 0; + tabw += ipad; + #endif // BAR_WINICON_PATCH + tx = x; + tw = tabw; drw_setscheme(drw, scheme[m->sel == c ? SchemeTitleSel : SchemeTitleNorm]); - if (ftw > 0) { /* trap special handling of 0 in drw_text */ - drw_text(drw, x, a->y, ftw, a->h, lrpad / 2, c->name, 0, False); + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, tx, a->y, tw, a->h); - #if BAR_WINICON_PATCH - drw_text(drw, x, a->y, ftw, a->h, lrpad / 2 + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + lrpad / 2, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, a->y, ftw, a->h, lrpad / 2, c->name, 0, False); - #endif // BAR_WINICON_PATCH + if (tabw <= 0) /* trap special handling of 0 in drw_text */ + continue; + tx += lrpad / 2; + tw -= lrpad; + + #if BAR_WINICON_PATCH + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; } - drawstateindicator(c->mon, c, 1, x, a->y, ftw, a->h, 0, 0, c->isfixed); - x += ftw; - w -= ftw; + #endif // BAR_WINICON_PATCH + + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + drawstateindicator(c->mon, c, 1, x, a->y, tabw, a->h, 0, 0, c->isfixed); + x += tabw; + w -= tabw; } } return n; diff --git a/patch/bar_flexwintitle.c b/patch/bar_flexwintitle.c index 0e17443..b5d77b0 100644 --- a/patch/bar_flexwintitle.c +++ b/patch/bar_flexwintitle.c @@ -166,11 +166,21 @@ getselschemefor(int scheme) } void -flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Arg *arg, BarArg *barg) +flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Arg *arg, BarArg *a) { if (!c) return; - int i, nclienttags = 0, nviewtags = 0, pad = lrpad / 2; + int i, nclienttags = 0, nviewtags = 0; + int tpad = lrpad / 2; + #if BAR_WINICON_PATCH + int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + int tx = x; + int tw = w; + int clientscheme = ( c == selmon->sel && HIDDEN(c) ? SchemeHidSel @@ -182,30 +192,49 @@ flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Ar ? SchemeUrg : tabscheme ); + drw_setscheme(drw, scheme[clientscheme]); XSetWindowBorder(dpy, c->win, scheme[clientscheme][ColBorder].pixel); - if (w <= TEXTW("A") - lrpad + pad) // reduce text padding if wintitle is too small - pad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); - #if BAR_CENTEREDWINDOWNAME_PATCH + + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) + ipad < w) + cpad = (w - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH else if (TEXTW(c->name) < w) - pad = (w - TEXTW(c->name) + lrpad) / 2; + cpad = (w - TEXTW(c->name)) / 2; #endif // BAR_CENTEREDWINDOWNAME_PATCH + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + #if BAR_WINICON_PATCH - drw_text(drw, x, barg->y, w, barg->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + pad, barg->y + (barg->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, barg->y, w, barg->h, pad, c->name, 0, False); + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; + } #endif // BAR_WINICON_PATCH - drawstateindicator(m, c, 1, x + 2, barg->y, w, barg->h, 0, 0, 0); + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + drawstateindicator(m, c, 1, x + 2, a->y, w, a->h, 0, 0, 0); if (FLEXWINTITLE_BORDERS) { XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, barg->y, 1, barg->h); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= barg->w ? 1 : 0), barg->y, 1, barg->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, 1, a->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= a->w ? 1 : 0), a->y, 1, a->h); } + /* Optional tags icons */ for (i = 0; i < NUMTAGS; i++) { if ((m->tagset[m->seltags] >> i) & 1) @@ -215,7 +244,7 @@ flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Ar } if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) - drawindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); + drawindicator(m, c, 1, x, a->y, w, a->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); } #ifndef HIDDEN diff --git a/patch/bar_tabgroups.c b/patch/bar_tabgroups.c index 1498bc2..b89d348 100644 --- a/patch/bar_tabgroups.c +++ b/patch/bar_tabgroups.c @@ -36,11 +36,21 @@ click_bartabgroups(Bar *bar, Arg *arg, BarArg *a) } void -bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *barg) +bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *a) { if (!c) return; - int i, nclienttags = 0, nviewtags = 0, pad = lrpad / 2; + int i, nclienttags = 0, nviewtags = 0; + int tpad = lrpad / 2; + #if BAR_WINICON_PATCH + int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + int tx = x; + int tw = w; + drw_setscheme(drw, scheme[ m->sel == c #ifdef HIDDEN @@ -55,27 +65,44 @@ bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg ? SchemeTitleSel : SchemeTitleNorm ]); - if (w <= TEXTW("A") - lrpad + pad) // reduce text padding if wintitle is too small - pad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); - #if BAR_CENTEREDWINDOWNAME_PATCH + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) + ipad < w) + cpad = (w - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH else if (TEXTW(c->name) < w) - pad = (w - TEXTW(c->name) + lrpad) / 2; + cpad = (w - TEXTW(c->name)) / 2; #endif // BAR_CENTEREDWINDOWNAME_PATCH + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + #if BAR_WINICON_PATCH - drw_text(drw, x, barg->y, w, barg->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + pad, barg->y + (barg->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, barg->y, w, barg->h, pad, c->name, 0, False); + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; + } #endif // BAR_WINICON_PATCH - drawstateindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, c->isfixed); + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + + drawstateindicator(m, c, 1, x, a->y, w, a->h, 0, 0, c->isfixed); if (BARTAB_BORDERS) { XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, barg->y, 1, barg->h); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= barg->w ? 1 : 0), barg->y, 1, barg->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, 1, a->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= a->w ? 1 : 0), a->y, 1, a->h); } /* Optional tags icons */ for (i = 0; i < NUMTAGS; i++) { @@ -86,7 +113,7 @@ bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg } if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) - drawindicator(m, c, 1, x, barg->y, w, barg->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); + drawindicator(m, c, 1, x, a->y, w, a->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); } #ifndef HIDDEN diff --git a/patch/bar_wintitle.c b/patch/bar_wintitle.c index d2241d2..72926f2 100644 --- a/patch/bar_wintitle.c +++ b/patch/bar_wintitle.c @@ -18,7 +18,6 @@ draw_wintitle(Bar *bar, BarArg *a) #endif // BAR_TITLE_LEFT_PAD_PATCH | BAR_TITLE_RIGHT_PAD_PATCH Monitor *m = bar->mon; Client *c = m->sel; - int pad = lrpad / 2; if (!c) { drw_setscheme(drw, scheme[SchemeTitleNorm]); @@ -26,23 +25,53 @@ draw_wintitle(Bar *bar, BarArg *a) return 0; } + int tpad = lrpad / 2; + #if BAR_WINICON_PATCH + int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + #endif // BAR_WINICON_PATCH + #if BAR_CENTEREDWINDOWNAME_PATCH + int cpad = 0; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + int tx = x; + int tw = w; + drw_setscheme(drw, scheme[m == selmon ? SchemeTitleSel : SchemeTitleNorm]); #if BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH XSetErrorHandler(xerrordummy); #endif // BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH - #if BAR_CENTEREDWINDOWNAME_PATCH - if (TEXTW(c->name) < w) - pad = (w - TEXTW(c->name) + lrpad) / 2; + + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + #if BAR_WINICON_PATCH && BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) + ipad < w) + cpad = (w - TEXTW(c->name) - ipad) / 2; + #elif BAR_CENTEREDWINDOWNAME_PATCH + else if (TEXTW(c->name) < w) + cpad = (w - TEXTW(c->name)) / 2; #endif // BAR_CENTEREDWINDOWNAME_PATCH + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + #if BAR_CENTEREDWINDOWNAME_PATCH + /* Apply center padding, if any */ + tx += cpad; + tw -= cpad; + #endif // BAR_CENTEREDWINDOWNAME_PATCH + + tx += tpad; + tw -= lrpad; + #if BAR_WINICON_PATCH - drw_text(drw, x, a->y, w, a->h, pad + (c->icon ? c->icon->width + ICONSPACING : 0), c->name, 0, False); - if (c->icon) - drw_img(drw, x + pad, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); - #else - drw_text(drw, x, a->y, w, a->h, pad, c->name, 0, False); + if (ipad) { + drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + tx += ipad; + tw -= ipad; + } #endif // BAR_WINICON_PATCH + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + #if BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH XSync(dpy, False); XSetErrorHandler(xerror); From 5c80a54b623a72b0855a9d46575565cc446f3bd6 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 18 Jan 2022 11:08:34 +0100 Subject: [PATCH 28/49] Refactoring restack to allow it to work without having the bar as a reference ref. #214 --- dwm.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/dwm.c b/dwm.c index 803f77a..03ea7c3 100644 --- a/dwm.c +++ b/dwm.c @@ -3000,7 +3000,7 @@ resizemouse(const Arg *arg) void restack(Monitor *m) { - Client *c; + Client *c, *f = NULL; XEvent ev; XWindowChanges wc; #if WARP_PATCH && FLEXTILE_DELUXE_LAYOUT @@ -3015,11 +3015,17 @@ restack(Monitor *m) return; if (m->sel->isfloating || !m->lt[m->sellt]->arrange) XRaiseWindow(dpy, m->sel->win); - if (m->lt[m->sellt]->arrange && m->bar) { + if (m->lt[m->sellt]->arrange) { wc.stack_mode = Below; - wc.sibling = m->bar->win; + if (m->bar) { + wc.sibling = m->bar->win; + } else { + for (f = m->stack; f && (f->isfloating || !ISVISIBLE(f)); f = f->snext); // find first tiled stack client + if (f) + wc.sibling = f->win; + } for (c = m->stack; c; c = c->snext) - if (!c->isfloating && ISVISIBLE(c)) { + if (!c->isfloating && ISVISIBLE(c) && c != f) { XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); wc.sibling = c->win; } From d1662b6636202ae5c6aea81074b539fa7f347322 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 18 Jan 2022 14:29:11 +0100 Subject: [PATCH 29/49] Ignoring unused functions warnings. This is achieved by adding the -Wno-unused-function flag to the compiler. The warnings are suppressed to avoid confusion for users new to dwm. Removing the static declaration from the header files works too, but adds unnecessary data into the compiled object. --- config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.mk b/config.mk index fb2310c..6829536 100644 --- a/config.mk +++ b/config.mk @@ -58,7 +58,7 @@ LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ${XRENDER} ${MPDCLIENT # flags CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} +CFLAGS = -std=c99 -pedantic -Wall -Wno-unused-function -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} LDFLAGS = ${LIBS} # Solaris From 8e36c36bcf4c5ba53949923d75ad46f984c12cbc Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 20 Jan 2022 22:21:55 +0100 Subject: [PATCH 30/49] Fix for drw_text cropping one characters too many when the text is too long and replacing with ... ref. #216 --- drw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drw.c b/drw.c index 0fc9f05..afb6477 100644 --- a/drw.c +++ b/drw.c @@ -507,8 +507,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp if (utf8strlen) { drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); /* shorten text if necessary */ - for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(usedfont, utf8str, len, &ew, NULL); + for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; drw_font_getexts(usedfont, utf8str, len, &ew, NULL)) + len--; if (len) { memcpy(buf, utf8str, len); From a0751271bc6f3d45f165f750915e464f90336d0d Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 11 Feb 2022 09:44:40 +0100 Subject: [PATCH 31/49] sizehints ruled: have rule checks take window type and role into account ref. #229 --- patch/sizehints_ruled.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/patch/sizehints_ruled.c b/patch/sizehints_ruled.c index 99c7e62..ce2eeb9 100644 --- a/patch/sizehints_ruled.c +++ b/patch/sizehints_ruled.c @@ -2,6 +2,10 @@ void checkfloatingrules(Client *c) { const char *class, *instance; + Atom wintype; + #if WINDOWROLERULE_PATCH + char role[64]; + #endif // WINDOWROLERULE_PATCH unsigned int i; const Rule *r; XClassHint ch = { NULL, NULL }; @@ -9,13 +13,23 @@ checkfloatingrules(Client *c) XGetClassHint(dpy, c->win, &ch); class = ch.res_class ? ch.res_class : broken; instance = ch.res_name ? ch.res_name : broken; + wintype = getatomprop(c, netatom[NetWMWindowType]); + #if WINDOWROLERULE_PATCH + gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role)); + #endif // WINDOWROLERULE_PATCH for (i = 0; i < LENGTH(rules); i++) { r = &rules[i]; if ((!r->title || strstr(c->name, r->title)) && (!r->class || strstr(class, r->class)) - && (!r->instance || strstr(instance, r->instance))) + #if WINDOWROLERULE_PATCH + && (!r->role || strstr(role, r->role)) + #endif // WINDOWROLERULE_PATCH + && (!r->instance || strstr(instance, r->instance)) + && (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False))) + { c->isfloating = r->isfloating; + } } if (ch.res_class) XFree(ch.res_class); From 90e4dfc0cf76a3126981c443dd3013a7ccf049bc Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 11 Feb 2022 10:10:28 +0100 Subject: [PATCH 32/49] Adding the isfreesize version of the sizehints patch ref. #229 --- README.md | 2 ++ dwm.c | 25 +++++++++++++++++++++---- patches.def.h | 13 +++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3fc48f5..abec291 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ If you are experiencing issues then you may want to check out the [Known Issues] ### Changelog: +2022-02-11 - Added the isfreesize version of the sizehints patch + 2021-11-23 - Added the taglabels and underlinetags patches 2021-09-08 - Added the alwayscenter patch diff --git a/dwm.c b/dwm.c index 03ea7c3..95d7cf8 100644 --- a/dwm.c +++ b/dwm.c @@ -368,6 +368,9 @@ struct Client { #if PLACEMOUSE_PATCH int beingmoved; #endif // PLACEMOUSE_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + int isfreesize; + #endif // SIZEHINTS_ISFREESIZE_PATCH #if SWALLOW_PATCH int isterminal, noswallow; pid_t pid; @@ -515,6 +518,9 @@ typedef struct { #if SELECTIVEFAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH && !FAKEFULLSCREEN_PATCH int isfakefullscreen; #endif // SELECTIVEFAKEFULLSCREEN_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + int isfreesize; + #endif // SIZEHINTS_ISFREESIZE_PATCH #if ISPERMANENT_PATCH int ispermanent; #endif // ISPERMANENT_PATCH @@ -825,6 +831,9 @@ applyrules(Client *c) #if SWALLOW_PATCH c->noswallow = -1; #endif // SWALLOW_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + c->isfreesize = 1; + #endif // SIZEHINTS_ISFREESIZE_PATCH c->isfloating = 0; c->tags = 0; XGetClassHint(dpy, c->win, &ch); @@ -863,6 +872,9 @@ applyrules(Client *c) c->isterminal = r->isterminal; c->noswallow = r->noswallow; #endif // SWALLOW_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + c->isfreesize = r->isfreesize; + #endif // SIZEHINTS_ISFREESIZE_PATCH c->isfloating = r->isfloating; c->tags |= r->tags; #if SCRATCHPADS_PATCH @@ -4533,11 +4545,11 @@ updatesizehints(Client *c) if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) /* size is uninitialized, ensure that size.flags aren't used */ - #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH + #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH || SIZEHINTS_ISFREESIZE_PATCH size.flags = 0; #else size.flags = PSize; - #endif // SIZEHINTS_PATCH | SIZEHINTS_RULED_PATCH + #endif // SIZEHINTS_PATCH | SIZEHINTS_RULED_PATCH | SIZEHINTS_ISFREESIZE_PATCH if (size.flags & PBaseSize) { c->basew = size.base_width; c->baseh = size.base_height; @@ -4569,8 +4581,13 @@ updatesizehints(Client *c) c->maxa = (float)size.max_aspect.x / size.max_aspect.y; } else c->maxa = c->mina = 0.0; - #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH - if (size.flags & PSize) { + #if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH || SIZEHINTS_ISFREESIZE_PATCH + #if SIZEHINTS_ISFREESIZE_PATCH + if ((size.flags & PSize) && c->isfreesize) + #else + if (size.flags & PSize) + #endif // SIZEHINTS_ISFREESIZE_PATCH + { c->basew = size.base_width; c->baseh = size.base_height; c->isfloating = 1; diff --git a/patches.def.h b/patches.def.h index 037c5ee..3d59e2e 100644 --- a/patches.def.h +++ b/patches.def.h @@ -970,6 +970,19 @@ */ #define SIZEHINTS_RULED_PATCH 0 +/* This patch makes dwm obey even "soft" sizehints for new clients. The isfreesize + * version is similar to the sizehints ruled patch except it allows you to specify + * via client rules which clients this should apply to. Soft sizehints applies by + * default to clients that are not ruled, and will be disabled by default for clients + * that are. + * + * Example client rule enabling soft sizehints: + * - RULE(.wintype = WTYPE "DIALOG", .isfloating = 1, .isfreesize = 1) + * + * https://dwm.suckless.org/patches/sizehints/ + */ +#define SIZEHINTS_ISFREESIZE_PATCH 0 + /* In a multi-head setup monitor 0 is by default the primary screen, with the left and right * screen being monitor 1 and 2 respectively. This patch sorts screens left to right (or * top to bottom in a vertical layout) which aims to address some inconsistencies when it From 282dc2ad22fd9483a4349064ce7e7e5e4476ef18 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 11 Feb 2022 11:43:06 +0100 Subject: [PATCH 33/49] barpadding: adding vanitygaps variant --- dwm.c | 21 +++++++++------------ patch/vanitygaps.c | 7 +++---- patches.def.h | 9 +++++---- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/dwm.c b/dwm.c index 95d7cf8..37c265f 100644 --- a/dwm.c +++ b/dwm.c @@ -4343,25 +4343,22 @@ updatebarpos(Monitor *m) m->ww = m->mw; m->wh = m->mh; Bar *bar; - #if BAR_GAPS_PADDING_PATCH && VANITYGAPS_PATCH int y_pad = 0; int x_pad = 0; - + #if BAR_PADDING_VANITYGAPS_PATCH && VANITYGAPS_PATCH #if PERTAG_VANITYGAPS_PATCH && PERTAG_PATCH - if (!selmon || selmon->pertag->enablegaps[selmon->pertag->curtag]) { + if (!selmon || selmon->pertag->enablegaps[selmon->pertag->curtag]) #else - if (enablegaps) { + if (enablegaps) #endif // PERTAG_VANITYGAPS_PATCH - y_pad = gappov; - x_pad = gappoh; + { + y_pad = gappoh; + x_pad = gappov; } #elif BAR_PADDING_PATCH - int y_pad = vertpad; - int x_pad = sidepad; - #else - int y_pad = 0; - int x_pad = 0; - #endif // BAR_PADDING_PATCH + y_pad = vertpad; + x_pad = sidepad; + #endif // BAR_PADDING_PATCH | BAR_PADDING_VANITYGAPS_PATCH #if INSETS_PATCH // Custom insets diff --git a/patch/vanitygaps.c b/patch/vanitygaps.c index 880bf4a..d322ded 100644 --- a/patch/vanitygaps.c +++ b/patch/vanitygaps.c @@ -87,16 +87,15 @@ togglegaps(const Arg *arg) enablegaps = !enablegaps; #endif // PERTAG_VANITYGAPS_PATCH - #if BAR_GAPS_PADDING_PATCH + #if BAR_PADDING_VANITYGAPS_PATCH updatebarpos(selmon); - Bar *bar; - for (bar = selmon->bar; bar; bar = bar->next) + for (Bar *bar = selmon->bar; bar; bar = bar->next) XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); #if BAR_SYSTRAY_PATCH drawbarwin(systray->bar); #endif // BAR_SYSTRAY_PATCH - #endif // BAR_GAPS_PADDING_PATCH + #endif // BAR_PADDING_VANITYGAPS_PATCH arrange(NULL); } diff --git a/patches.def.h b/patches.def.h index 3d59e2e..dbd133d 100644 --- a/patches.def.h +++ b/patches.def.h @@ -347,11 +347,12 @@ */ #define BAR_PADDING_PATCH 0 -/* Same as barpadding patch but specifically written for the vanitygaps patch. It adds the same - * outer horizontal and vertical padding as vanity gaps. Moreover, the padding is toggled whenever - * vanitygaps are toggled. +/* Same as barpadding patch but specifically tailored for the vanitygaps patch in that the outer + * bar padding is derived from the vanitygaps settings. In addition to this the bar padding is + * toggled in unison when vanitygaps are toggled. Increasing or decreasing gaps during runtime + * will not affect the bar padding. */ -#define BAR_GAPS_PADDING_PATCH 0 +#define BAR_PADDING_VANITYGAPS_PATCH 0 /* This patch adds simple markup for status messages using pango markup. * This depends on the pango library v1.44 or greater. From ae67378b200842998bb4bc178e0d67220f09fefc Mon Sep 17 00:00:00 2001 From: Bagellll Date: Fri, 11 Feb 2022 10:57:53 -0500 Subject: [PATCH 34/49] Tag-Sync patch (for syncing tags across all monitors) (#219) * Tag-Sync patch * Major compatibility updates * SWITCHTAG/TAGSYNC compatibility * tagsync: refactoring Co-authored-by: bakkeby --- config.def.h | 2 -- dwm.c | 44 +++++++++++++++++++++++++----- patch/bar_ewmhtags.c | 1 - patch/combo.c | 15 ++--------- patch/distributetags.c | 18 +++++++++++-- patch/focusadjacenttag.c | 49 +++------------------------------ patch/reorganizetags.c | 58 +++++++++++++++++++++++++--------------- patch/shiftviewclients.c | 15 ++++++++--- patch/swaptags.c | 34 ++++++++++++++--------- patches.def.h | 8 +++++- 10 files changed, 135 insertions(+), 109 deletions(-) diff --git a/config.def.h b/config.def.h index 469f70f..f74b909 100644 --- a/config.def.h +++ b/config.def.h @@ -133,8 +133,6 @@ static const char dmenufont[] = "monospace:size=10"; static char c000000[] = "#000000"; // placeholder value -#if BAR_FLEXWINTITLE_PATCH -#endif // BAR_FLEXWINTITLE_PATCH static char normfgcolor[] = "#bbbbbb"; static char normbgcolor[] = "#222222"; static char normbordercolor[] = "#444444"; diff --git a/dwm.c b/dwm.c index 37c265f..693ddf3 100644 --- a/dwm.c +++ b/dwm.c @@ -923,8 +923,14 @@ applyrules(Client *c) view(&((Arg) { .ui = newtagset })); #endif // PERTAG_PATCH } else { + #if TAGSYNC_PATCH + for (m = mons; m; m = m->next) + m->tagset[m->seltags] = newtagset; + arrange(NULL); + #else c->mon->tagset[c->mon->seltags] = newtagset; arrange(c->mon); + #endif // TAGSYNC_PATCH } } } @@ -4052,7 +4058,11 @@ toggletag(const Arg *arg) void toggleview(const Arg *arg) { - unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);; + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH #if PERTAG_PATCH int i; #endif // PERTAG_PATCH @@ -4123,11 +4133,25 @@ toggleview(const Arg *arg) togglebar(NULL); #endif // PERTAGBAR_PATCH #endif // PERTAG_PATCH + #if !TAGSYNC_PATCH focus(NULL); arrange(selmon); + #endif // TAGSYNC_PATCH #if !EMPTYVIEW_PATCH } #endif // EMPTYVIEW_PATCH + #if TAGSYNC_PATCH + } + selmon = origselmon; + #if !EMPTYVIEW_PATCH + if (newtagset) { + #endif // EMPTYVIEW_PATCH + focus(NULL); + arrange(NULL); + #if !EMPTYVIEW_PATCH + } + #endif // EMPTYVIEW_PATCH + #endif // TAGSYNC_PATCH #if BAR_EWMHTAGS_PATCH updatecurrentdesktop(); #endif // BAR_EWMHTAGS_PATCH @@ -4685,6 +4709,10 @@ updatewmhints(Client *c) void view(const Arg *arg) { + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH #if EMPTYVIEW_PATCH if (arg->ui && (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) #else @@ -4699,18 +4727,20 @@ view(const Arg *arg) selmon->seltags ^= 1; /* toggle sel tagset */ #if PERTAG_PATCH pertagview(arg); - #if SWAPFOCUS_PATCH - Client *unmodified = selmon->pertag->prevclient[selmon->pertag->curtag]; - #endif // SWAPFOCUS_PATCH #else if (arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; #endif // PERTAG_PATCH + #if TAGSYNC_PATCH + } + selmon = origselmon; + #endif // TAGSYNC_PATCH focus(NULL); - #if SWAPFOCUS_PATCH && PERTAG_PATCH - selmon->pertag->prevclient[selmon->pertag->curtag] = unmodified; - #endif // SWAPFOCUS_PATCH + #if TAGSYNC_PATCH + arrange(NULL); + #else arrange(selmon); + #endif // TAGSYNC_PATCH #if BAR_EWMHTAGS_PATCH updatecurrentdesktop(); #endif // BAR_EWMHTAGS_PATCH diff --git a/patch/bar_ewmhtags.c b/patch/bar_ewmhtags.c index d86fd88..46ee5e4 100644 --- a/patch/bar_ewmhtags.c +++ b/patch/bar_ewmhtags.c @@ -50,4 +50,3 @@ updatecurrentdesktop(void) long data[] = { i }; XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); } - diff --git a/patch/combo.c b/patch/combo.c index 058b1f9..58b31f1 100644 --- a/patch/combo.c +++ b/patch/combo.c @@ -30,21 +30,10 @@ combotag(const Arg *arg) void comboview(const Arg *arg) { - unsigned newtags = arg->ui & TAGMASK; if (combo) { - selmon->tagset[selmon->seltags] |= newtags; + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] | (arg->ui & TAGMASK) })); } else { - selmon->seltags ^= 1; /*toggle tagset*/ combo = 1; - if (newtags) { - #if PERTAG_PATCH - pertagview(&((Arg) { .ui = newtags })); - #else - selmon->tagset[selmon->seltags] = newtags; - #endif // PERTAG_PATCH - } + view(arg); } - focus(NULL); - arrange(selmon); } - diff --git a/patch/distributetags.c b/patch/distributetags.c index 284b24c..f20f53f 100644 --- a/patch/distributetags.c +++ b/patch/distributetags.c @@ -1,9 +1,16 @@ void distributetags(const Arg *arg) { + Client *c; unsigned int ui = 1; int i = 0; - for (Client *c = selmon->clients; c; c = c->next) { + + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH + + for (c = selmon->clients; c; c = c->next) { if (HIDDEN(c)) continue; if (!(c->tags & TAGMASK)) @@ -11,7 +18,14 @@ distributetags(const Arg *arg) c->tags = (ui << i) & TAGMASK; i = (i + 1) % NUMTAGS; } + + #if TAGSYNC_PATCH + } + selmon = origselmon; + focus(NULL); + arrange(NULL); + #else focus(NULL); arrange(selmon); + #endif // TAGSYNC_PATCH } - diff --git a/patch/focusadjacenttag.c b/patch/focusadjacenttag.c index 85d9d74..b311b74 100644 --- a/patch/focusadjacenttag.c +++ b/patch/focusadjacenttag.c @@ -27,17 +27,7 @@ viewtoleft(const Arg *arg) { if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 && selmon->tagset[selmon->seltags] > 1) { - selmon->seltags ^= 1; /* toggle sel tagset */ - #if PERTAG_PATCH - pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] >> 1 })); - #else - selmon->tagset[selmon->seltags] = selmon->tagset[selmon->seltags ^ 1] >> 1; - #endif // pertagview - focus(NULL); - arrange(selmon); - #if BAR_EWMHTAGS_PATCH - updatecurrentdesktop(); - #endif // BAR_EWMHTAGS_PATCH + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] >> 1 })); } } @@ -46,17 +36,7 @@ viewtoright(const Arg *arg) { if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 && selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) { - selmon->seltags ^= 1; /* toggle sel tagset */ - #if PERTAG_PATCH - pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] << 1 })); - #else - selmon->tagset[selmon->seltags] = selmon->tagset[selmon->seltags ^ 1] << 1; - #endif // pertagview - focus(NULL); - arrange(selmon); - #if BAR_EWMHTAGS_PATCH - updatecurrentdesktop(); - #endif // BAR_EWMHTAGS_PATCH + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] << 1 })); } } @@ -67,17 +47,7 @@ tagandviewtoleft(const Arg *arg) && __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 && selmon->tagset[selmon->seltags] > 1) { selmon->sel->tags >>= 1; - selmon->seltags ^= 1; /* toggle sel tagset */ - #if PERTAG_PATCH - pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] >> 1 })); - #else - selmon->tagset[selmon->seltags] = selmon->tagset[selmon->seltags ^ 1] >> 1; - #endif // pertagview - focus(selmon->sel); - arrange(selmon); - #if BAR_EWMHTAGS_PATCH - updatecurrentdesktop(); - #endif // BAR_EWMHTAGS_PATCH + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] >> 1 })); } } @@ -88,17 +58,6 @@ tagandviewtoright(const Arg *arg) && __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 && selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) { selmon->sel->tags <<= 1; - selmon->seltags ^= 1; /* toggle sel tagset */ - #if PERTAG_PATCH - pertagview(&((Arg) { .ui = selmon->tagset[selmon->seltags ^ 1] << 1 })); - #else - selmon->tagset[selmon->seltags] = selmon->tagset[selmon->seltags ^ 1] << 1; - #endif // pertagview - focus(selmon->sel); - arrange(selmon); - #if BAR_EWMHTAGS_PATCH - updatecurrentdesktop(); - #endif // BAR_EWMHTAGS_PATCH + view(&((Arg) { .ui = selmon->tagset[selmon->seltags] << 1 })); } } - diff --git a/patch/reorganizetags.c b/patch/reorganizetags.c index 1aff54a..440d75c 100644 --- a/patch/reorganizetags.c +++ b/patch/reorganizetags.c @@ -1,28 +1,42 @@ void reorganizetags(const Arg *arg) { - Client *c; - unsigned int occ, unocc, i; - unsigned int tagdest[NUMTAGS]; + Client *c; + unsigned int occ, unocc, i; + unsigned int tagdest[NUMTAGS]; - occ = 0; - for (c = selmon->clients; c; c = c->next) - occ |= (1 << (ffs(c->tags)-1)); - unocc = 0; - for (i = 0; i < NUMTAGS; ++i) { - while (unocc < i && (occ & (1 << unocc))) - unocc++; - if (occ & (1 << i)) { - tagdest[i] = unocc; - occ &= ~(1 << i); - occ |= 1 << unocc; - } - } + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH - for (c = selmon->clients; c; c = c->next) - c->tags = 1 << tagdest[ffs(c->tags)-1]; - if (selmon->sel) - selmon->tagset[selmon->seltags] = selmon->sel->tags; - arrange(selmon); + occ = 0; + for (c = selmon->clients; c; c = c->next) + occ |= (1 << (ffs(c->tags)-1)); + unocc = 0; + for (i = 0; i < NUMTAGS; ++i) { + while (unocc < i && (occ & (1 << unocc))) + unocc++; + if (occ & (1 << i)) { + tagdest[i] = unocc; + occ &= ~(1 << i); + occ |= 1 << unocc; + } + } + + for (c = selmon->clients; c; c = c->next) + c->tags = 1 << tagdest[ffs(c->tags)-1]; + #if TAGSYNC_PATCH + } + selmon = origselmon; + #endif // TAGSYNC_PATCH + + if (selmon->sel) + view(&((Arg) { .ui = selmon->sel->tags })); + else + #if TAGSYNC_PATCH + arrange(NULL); + #else + arrange(selmon); + #endif // TAGSYNC_PATCH } - diff --git a/patch/shiftviewclients.c b/patch/shiftviewclients.c index 1bf9de8..b805b51 100644 --- a/patch/shiftviewclients.c +++ b/patch/shiftviewclients.c @@ -5,7 +5,11 @@ shiftviewclients(const Arg *arg) Client *c; unsigned int tagmask = 0; - for (c = selmon->clients; c; c = c->next) + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) + #endif // TAGSYNC_PATCH + for (c = selmon->clients; c; c = c->next) { #if SCRATCHPADS_PATCH if (!(c->tags & SPTAGMASK)) tagmask = tagmask | c->tags; @@ -15,13 +19,17 @@ shiftviewclients(const Arg *arg) #else tagmask = tagmask | c->tags; #endif // SCRATCHPADS_PATCH + } + #if TAGSYNC_PATCH + selmon = origselmon; + #endif // TAGSYNC_PATCH #if SCRATCHPADS_PATCH shifted.ui = selmon->tagset[selmon->seltags] & ~SPTAGMASK; #else shifted.ui = selmon->tagset[selmon->seltags]; #endif // SCRATCHPADS_PATCH - if (arg->i > 0) // left circular shift + if (arg->i > 0) { // left circular shift do { shifted.ui = (shifted.ui << arg->i) | (shifted.ui >> (NUMTAGS - arg->i)); @@ -29,7 +37,7 @@ shiftviewclients(const Arg *arg) shifted.ui &= ~SPTAGMASK; #endif // SCRATCHPADS_PATCH } while (tagmask && !(shifted.ui & tagmask)); - else // right circular shift + } else { // right circular shift do { shifted.ui = (shifted.ui >> (- arg->i) | shifted.ui << (NUMTAGS + arg->i)); @@ -37,6 +45,7 @@ shiftviewclients(const Arg *arg) shifted.ui &= ~SPTAGMASK; #endif // SCRATCHPADS_PATCH } while (tagmask && !(shifted.ui & tagmask)); + } view(&shifted); } diff --git a/patch/swaptags.c b/patch/swaptags.c index d6a72d7..7e1e920 100644 --- a/patch/swaptags.c +++ b/patch/swaptags.c @@ -1,23 +1,31 @@ void swaptags(const Arg *arg) { - unsigned int newtag = arg->ui & TAGMASK; - unsigned int curtag = selmon->tagset[selmon->seltags]; + Client *c; + unsigned int newtag = arg->ui & TAGMASK; + unsigned int curtag = selmon->tagset[selmon->seltags]; - if (newtag == curtag || !curtag || (curtag & (curtag-1))) - return; + if (newtag == curtag || !curtag || (curtag & (curtag-1))) + return; - for (Client *c = selmon->clients; c != NULL; c = c->next) { - if ((c->tags & newtag) || (c->tags & curtag)) - c->tags ^= curtag ^ newtag; + #if TAGSYNC_PATCH + Monitor *origselmon = selmon; + for (selmon = mons; selmon; selmon = selmon->next) { + #endif // TAGSYNC_PATCH - if (!c->tags) - c->tags = newtag; - } + for (c = selmon->clients; c != NULL; c = c->next) { + if ((c->tags & newtag) || (c->tags & curtag)) + c->tags ^= curtag ^ newtag; - selmon->tagset[selmon->seltags] = newtag; + if (!c->tags) + c->tags = newtag; + } - focus(NULL); - arrange(selmon); + #if TAGSYNC_PATCH + } + selmon = origselmon; + #endif // TAGSYNC_PATCH + + view(&((Arg) { .ui = newtag })); } diff --git a/patches.def.h b/patches.def.h index dbd133d..697f6e6 100644 --- a/patches.def.h +++ b/patches.def.h @@ -1130,6 +1130,13 @@ */ #define TAGSWAPMON_PATCH 0 +/* Sync tag actions across all monitors. + * This is comparable to a sort of pseudo-desktop environment. + * Also refer to the desktop patch: + * https://github.com/bakkeby/patches/blob/master/dwm/dwm-desktop-6.3.diff + */ +#define TAGSYNC_PATCH 0 + /* This patch can be useful to the touchpad users because it allows to * resize windows using Mod + two-finger scroll. It is useful when * two-finger scrolling is configured in libinput. @@ -1328,4 +1335,3 @@ * This can be optionally disabled in favour of other layouts. */ #define MONOCLE_LAYOUT 1 - From 96820b2d51b7e1bca5ccdd9ce289e9fd278aa767 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Fri, 11 Feb 2022 17:00:44 +0100 Subject: [PATCH 35/49] tagsync: adding reference in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index abec291..a42572e 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you are experiencing issues then you may want to check out the [Known Issues] ### Changelog: -2022-02-11 - Added the isfreesize version of the sizehints patch +2022-02-11 - Added the isfreesize version of the sizehints patch and the [tagsync](https://github.com/bakkeby/dwm-flexipatch/pull/219) patch (contributed by [Bagelli](https://github.com/Bagellll)) 2021-11-23 - Added the taglabels and underlinetags patches From 55592623f585246b106bf5c4f075122d07ec7070 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 20 Feb 2022 13:24:52 +0100 Subject: [PATCH 36/49] focusadjacenttags + scratchpad compatibility issue ref. #236 --- patch/focusadjacenttag.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/patch/focusadjacenttag.c b/patch/focusadjacenttag.c index b311b74..67dd768 100644 --- a/patch/focusadjacenttag.c +++ b/patch/focusadjacenttag.c @@ -1,8 +1,9 @@ void tagtoleft(const Arg *arg) { + unsigned int MASK = (1 << NUMTAGS) - 1; if (selmon->sel != NULL - && __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 + && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 && selmon->tagset[selmon->seltags] > 1) { selmon->sel->tags >>= 1; focus(NULL); @@ -13,9 +14,10 @@ tagtoleft(const Arg *arg) void tagtoright(const Arg *arg) { + unsigned int MASK = (1 << NUMTAGS) - 1; if (selmon->sel != NULL - && __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 - && selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) { + && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 + && selmon->tagset[selmon->seltags] & (MASK >> 1)) { selmon->sel->tags <<= 1; focus(NULL); arrange(selmon); @@ -25,7 +27,8 @@ tagtoright(const Arg *arg) void viewtoleft(const Arg *arg) { - if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 + unsigned int MASK = (1 << NUMTAGS) - 1; + if (__builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 && selmon->tagset[selmon->seltags] > 1) { view(&((Arg) { .ui = selmon->tagset[selmon->seltags] >> 1 })); } @@ -34,8 +37,9 @@ viewtoleft(const Arg *arg) void viewtoright(const Arg *arg) { - if (__builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 - && selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) { + unsigned int MASK = (1 << NUMTAGS) - 1; + if (__builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 + && selmon->tagset[selmon->seltags] & (MASK >> 1)) { view(&((Arg) { .ui = selmon->tagset[selmon->seltags] << 1 })); } } @@ -43,8 +47,9 @@ viewtoright(const Arg *arg) void tagandviewtoleft(const Arg *arg) { + unsigned int MASK = (1 << NUMTAGS) - 1; if (selmon->sel != NULL - && __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 + && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 && selmon->tagset[selmon->seltags] > 1) { selmon->sel->tags >>= 1; view(&((Arg) { .ui = selmon->tagset[selmon->seltags] >> 1 })); @@ -54,9 +59,10 @@ tagandviewtoleft(const Arg *arg) void tagandviewtoright(const Arg *arg) { + unsigned int MASK = (1 << NUMTAGS) - 1; if (selmon->sel != NULL - && __builtin_popcount(selmon->tagset[selmon->seltags] & TAGMASK) == 1 - && selmon->tagset[selmon->seltags] & (TAGMASK >> 1)) { + && __builtin_popcount(selmon->tagset[selmon->seltags] & MASK) == 1 + && selmon->tagset[selmon->seltags] & (MASK >> 1)) { selmon->sel->tags <<= 1; view(&((Arg) { .ui = selmon->tagset[selmon->seltags] << 1 })); } From 5c321794f1ffb8f395de9b58e1c165e7137df711 Mon Sep 17 00:00:00 2001 From: dev-null-undefined <50732964+dev-null-undefined@users.noreply.github.com> Date: Thu, 24 Feb 2022 12:49:52 +0100 Subject: [PATCH 37/49] Fixed moving window tag issue (#237) + when moving window from monitor with different tags selected the moved window would not get the tags set properly if multiple windows are already on that monitor --- patch/placemouse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/patch/placemouse.c b/patch/placemouse.c index 0208baf..0851e89 100644 --- a/patch/placemouse.c +++ b/patch/placemouse.c @@ -88,8 +88,10 @@ placemouse(const Arg *arg) if ((r && r != prevr) || (attachmode != prevattachmode)) { detachstack(c); detach(c); - if (c->mon != r->mon) + if (c->mon != r->mon) { arrangemon(c->mon); + c->tags = r->mon->tagset[r->mon->seltags]; + } c->mon = r->mon; r->mon->sel = r; From adc05c2332b6267c4af5bf506ff071629d16f281 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 6 Mar 2022 11:38:22 +0100 Subject: [PATCH 38/49] Upgrading winicon patch to v2.1 ref. #238 --- config.mk | 2 +- drw.c | 21 ++++- drw.h | 3 + dwm.c | 4 +- patch/bar_awesomebar.c | 4 +- patch/bar_fancybar.c | 8 +- patch/bar_flexwintitle.c | 4 +- patch/bar_tabgroups.c | 4 +- patch/bar_winicon.c | 171 +++++++++++++++++++-------------------- patch/bar_winicon.h | 7 +- patch/bar_wintitle.c | 4 +- 11 files changed, 127 insertions(+), 105 deletions(-) diff --git a/config.mk b/config.mk index 6829536..f1cecb2 100644 --- a/config.mk +++ b/config.mk @@ -28,7 +28,7 @@ FREETYPEINC = /usr/include/freetype2 # OpenBSD - Uncomment this for the swallow patch / SWALLOW_PATCH #KVMLIB = -lkvm -# Uncomment this for the alpha patch / BAR_ALPHA_PATCH +# Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) #XRENDER = -lXrender # Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH diff --git a/drw.c b/drw.c index afb6477..1e53132 100644 --- a/drw.c +++ b/drw.c @@ -89,9 +89,15 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h drw->depth = depth; drw->cmap = cmap; drw->drawable = XCreatePixmap(dpy, root, w, h, depth); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, visual), 0, NULL); + #endif // BAR_WINICON_PATCH drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); #else drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(dpy, drw->drawable, XRenderFindVisualFormat(dpy, DefaultVisual(dpy, screen)), 0, NULL); + #endif // BAR_WINICON_PATCH drw->gc = XCreateGC(dpy, root, 0, NULL); #endif // BAR_ALPHA_PATCH XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); @@ -107,18 +113,31 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) drw->w = w; drw->h = h; + #if BAR_WINICON_PATCH + if (drw->picture) + XRenderFreePicture(drw->dpy, drw->picture); + #endif // BAR_WINICON_PATCH if (drw->drawable) XFreePixmap(drw->dpy, drw->drawable); #if BAR_ALPHA_PATCH drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); - #else + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, drw->visual), 0, NULL); + #endif // BAR_WINICON_PATCH + #else // !BAR_ALPHA_PATCH drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); + #if BAR_WINICON_PATCH + drw->picture = XRenderCreatePicture(drw->dpy, drw->drawable, XRenderFindVisualFormat(drw->dpy, DefaultVisual(drw->dpy, drw->screen)), 0, NULL); + #endif // BAR_WINICON_PATCH #endif // BAR_ALPHA_PATCH } void drw_free(Drw *drw) { + #if BAR_WINICON_PATCH + XRenderFreePicture(drw->dpy, drw->picture); + #endif // BAR_WINICON_PATCH XFreePixmap(drw->dpy, drw->drawable); XFreeGC(drw->dpy, drw->gc); drw_fontset_free(drw->fonts); diff --git a/drw.h b/drw.h index 42dad5a..ec24e02 100644 --- a/drw.h +++ b/drw.h @@ -35,6 +35,9 @@ typedef struct { Colormap cmap; #endif // BAR_ALPHA_PATCH Drawable drawable; + #if BAR_WINICON_PATCH + Picture picture; + #endif // BAR_WINICON_PATCH GC gc; Clr *scheme; Fnt *fonts; diff --git a/dwm.c b/dwm.c index 693ddf3..ea20c20 100644 --- a/dwm.c +++ b/dwm.c @@ -395,7 +395,8 @@ struct Client { XkbInfo *xkb; #endif // XKB_PATCH #if BAR_WINICON_PATCH - XImage *icon; + unsigned int icw, ich; + Picture icon; #endif // BAR_WINICON_PATCH }; @@ -2324,7 +2325,6 @@ manage(Window w, XWindowAttributes *wa) c->cfact = 1.0; #endif // CFACTS_PATCH #if BAR_WINICON_PATCH - c->icon = NULL; updateicon(c); #endif // BAR_WINICON_PATCH updatetitle(c); diff --git a/patch/bar_awesomebar.c b/patch/bar_awesomebar.c index 81711f3..c6fe8f1 100644 --- a/patch/bar_awesomebar.c +++ b/patch/bar_awesomebar.c @@ -50,7 +50,7 @@ draw_awesomebar(Bar *bar, BarArg *a) cpad = 0; #endif // BAR_CENTEREDWINDOWNAME_PATCH #if BAR_WINICON_PATCH - ipad = c->icon ? c->icon->width + ICONSPACING : 0; + ipad = c->icon ? c->icw + ICONSPACING : 0; #endif // BAR_WINICON_PATCH tx = x; @@ -80,7 +80,7 @@ draw_awesomebar(Bar *bar, BarArg *a) #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; } diff --git a/patch/bar_fancybar.c b/patch/bar_fancybar.c index 623d1c3..40a1883 100644 --- a/patch/bar_fancybar.c +++ b/patch/bar_fancybar.c @@ -34,7 +34,7 @@ draw_fancybar(Bar *bar, BarArg *a) tabw = TEXTW(m->sel->name); #if BAR_WINICON_PATCH if (m->sel->icon) - tabw += m->sel->icon->width + ICONSPACING; + tabw += m->sel->icw + ICONSPACING; #endif // BAR_WINICON_PATCH mw = (tabw >= w || n == 1) ? 0 : (w - tabw) / (n - 1); @@ -46,7 +46,7 @@ draw_fancybar(Bar *bar, BarArg *a) tabw = TEXTW(c->name); #if BAR_WINICON_PATCH if (c->icon) - tabw += c->icon->width + ICONSPACING; + tabw += c->icw + ICONSPACING; #endif // BAR_WINICON_PATCH if (tabw < mw) ew += (mw - tabw); @@ -62,7 +62,7 @@ draw_fancybar(Bar *bar, BarArg *a) continue; tabw = MIN(m->sel == c ? w : mw, TEXTW(c->name)); #if BAR_WINICON_PATCH - ipad = c->icon ? c->icon->width + ICONSPACING : 0; + ipad = c->icon ? c->icw + ICONSPACING : 0; tabw += ipad; #endif // BAR_WINICON_PATCH tx = x; @@ -80,7 +80,7 @@ draw_fancybar(Bar *bar, BarArg *a) #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; } diff --git a/patch/bar_flexwintitle.c b/patch/bar_flexwintitle.c index b5d77b0..e71a98d 100644 --- a/patch/bar_flexwintitle.c +++ b/patch/bar_flexwintitle.c @@ -173,7 +173,7 @@ flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Ar int i, nclienttags = 0, nviewtags = 0; int tpad = lrpad / 2; #if BAR_WINICON_PATCH - int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + int ipad = c->icon ? c->icw + ICONSPACING : 0; #endif // BAR_WINICON_PATCH #if BAR_CENTEREDWINDOWNAME_PATCH int cpad = 0; @@ -220,7 +220,7 @@ flextitledraw(Monitor *m, Client *c, int unused, int x, int w, int tabscheme, Ar #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; } diff --git a/patch/bar_tabgroups.c b/patch/bar_tabgroups.c index b89d348..b61a0db 100644 --- a/patch/bar_tabgroups.c +++ b/patch/bar_tabgroups.c @@ -43,7 +43,7 @@ bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg int i, nclienttags = 0, nviewtags = 0; int tpad = lrpad / 2; #if BAR_WINICON_PATCH - int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + int ipad = c->icon ? c->icw + ICONSPACING : 0; #endif // BAR_WINICON_PATCH #if BAR_CENTEREDWINDOWNAME_PATCH int cpad = 0; @@ -89,7 +89,7 @@ bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; } diff --git a/patch/bar_winicon.c b/patch/bar_winicon.c index a50766c..697e8b9 100644 --- a/patch/bar_winicon.c +++ b/patch/bar_winicon.c @@ -1,60 +1,12 @@ -static uint32_t tmpicon[ICONSIZE * ICONSIZE]; - static uint32_t prealpha(uint32_t p) { uint8_t a = p >> 24u; uint32_t rb = (a * (p & 0xFF00FFu)) >> 8u; uint32_t g = (a * (p & 0x00FF00u)) >> 8u; - return (rb & 0xFF00FFu) | (g & 0x00FF00u) | ((~a) << 24u); + return (rb & 0xFF00FFu) | (g & 0x00FF00u) | (a << 24u); } -#if BAR_ALPHA_PATCH -static uint8_t div255(uint16_t x) { return (x*0x8081u) >> 23u; } -static uint32_t blend(uint32_t p1rb, uint32_t p1g, uint8_t p1a, uint32_t p2) { - uint8_t a = p2 >> 24u; - uint32_t rb = (p2 & 0xFF00FFu) + ( (a * p1rb) >> 8u ); - uint32_t g = (p2 & 0x00FF00u) + ( (a * p1g) >> 8u ); - return (rb & 0xFF00FFu) | (g & 0x00FF00u) | div255(~a * 255u + a * p1a) << 24u; -} - -void -drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp) -{ - if (!drw || !drw->scheme) - return; - uint32_t *data = (uint32_t *)img->data, p = drw->scheme[ColBg].pixel, - prb = p & 0xFF00FFu, pg = p & 0x00FF00u; - uint8_t pa = p >> 24u; - int icsz = img->width * img->height, i; - for (i = 0; i < icsz; ++i) tmp[i] = blend(prb, pg, pa, data[i]); - - img->data = (char *) tmp; - XPutImage(drw->dpy, drw->drawable, drw->gc, img, 0, 0, x, y, img->width, img->height); - img->data = (char *) data; -} -#else -static uint32_t blend(uint32_t p1rb, uint32_t p1g, uint32_t p2) { - uint8_t a = p2 >> 24u; - uint32_t rb = (p2 & 0xFF00FFu) + ( (a * p1rb) >> 8u ); - uint32_t g = (p2 & 0x00FF00u) + ( (a * p1g) >> 8u ); - return (rb & 0xFF00FFu) | (g & 0x00FF00u) | ((~a) << 24u); -} - -void -drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp) -{ - if (!drw || !drw->scheme) - return; - uint32_t *data = (uint32_t *)img->data, p = drw->scheme[ColBg].pixel, prb = p & 0xFF00FFu, pg = p & 0x00FF00u; - int icsz = img->width * img->height, i; - for (i = 0; i < icsz; ++i) tmp[i] = blend(prb, pg, data[i]); - img->data = (char *) tmp; - XPutImage(drw->dpy, drw->drawable, drw->gc, img, 0, 0, x, y, img->width, img->height); - img->data = (char *) data; -} -#endif // BAR_ALPHA_PATCH - -XImage * -geticonprop(Window win) +Picture +geticonprop(Window win, unsigned int *picw, unsigned int *pich) { int format; unsigned long n, extra, *p = NULL; @@ -62,34 +14,32 @@ geticonprop(Window win) if (XGetWindowProperty(dpy, win, netatom[NetWMIcon], 0L, LONG_MAX, False, AnyPropertyType, &real, &format, &n, &extra, (unsigned char **)&p) != Success) - return NULL; - if (n == 0 || format != 32) { XFree(p); return NULL; } + return None; + if (n == 0 || format != 32) { XFree(p); return None; } unsigned long *bstp = NULL; uint32_t w, h, sz; - { - const unsigned long *end = p + n; - unsigned long *i; + unsigned long *i; const unsigned long *end = p + n; uint32_t bstd = UINT32_MAX, d, m; for (i = p; i < end - 1; i += sz) { - if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return NULL; } + if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } if ((sz = w * h) > end - i) break; if ((m = w > h ? w : h) >= ICONSIZE && (d = m - ICONSIZE) < bstd) { bstd = d; bstp = i; } } if (!bstp) { for (i = p; i < end - 1; i += sz) { - if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return NULL; } + if ((w = *i++) >= 16384 || (h = *i++) >= 16384) { XFree(p); return None; } if ((sz = w * h) > end - i) break; if ((d = ICONSIZE - (w > h ? w : h)) < bstd) { bstd = d; bstp = i; } } } - if (!bstp) { XFree(p); return NULL; } + if (!bstp) { XFree(p); return None; } } - if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return NULL; } + if ((w = *(bstp - 2)) == 0 || (h = *(bstp - 1)) == 0) { XFree(p); return None; } - uint32_t icw, ich, icsz; + uint32_t icw, ich; if (w <= h) { ich = ICONSIZE; icw = w * ICONSIZE / h; if (icw == 0) icw = 1; @@ -98,43 +48,92 @@ geticonprop(Window win) icw = ICONSIZE; ich = h * ICONSIZE / w; if (ich == 0) ich = 1; } - icsz = icw * ich; + *picw = icw; *pich = ich; - uint32_t i; -#if ULONG_MAX > UINT32_MAX - uint32_t *bstp32 = (uint32_t *)bstp; - for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = bstp[i]; -#endif - uint32_t *icbuf = malloc(icsz << 2); if(!icbuf) { XFree(p); return NULL; } - if (w == icw && h == ich) memcpy(icbuf, bstp, icsz << 2); - else { - Imlib_Image origin = imlib_create_image_using_data(w, h, (DATA32 *)bstp); - if (!origin) { XFree(p); free(icbuf); return NULL; } + uint32_t i, *bstp32 = (uint32_t *)bstp; + for (sz = w * h, i = 0; i < sz; ++i) bstp32[i] = prealpha(bstp[i]); + + Picture ret = drw_picture_create_resized(drw, (char *)bstp, w, h, icw, ich); + XFree(p); + + return ret; +} + +Picture +drw_picture_create_resized(Drw *drw, char *src, unsigned int srcw, unsigned int srch, unsigned int dstw, unsigned int dsth) { + Pixmap pm; + Picture pic; + GC gc; + + if (srcw <= (dstw << 1u) && srch <= (dsth << 1u)) { + XImage img = { + srcw, srch, 0, ZPixmap, src, + ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, + 32, 0, 32, + 0, 0, 0 + }; + XInitImage(&img); + + pm = XCreatePixmap(drw->dpy, drw->root, srcw, srch, 32); + gc = XCreateGC(drw->dpy, pm, 0, NULL); + XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, srcw, srch); + XFreeGC(drw->dpy, gc); + + pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); + XFreePixmap(drw->dpy, pm); + + XRenderSetPictureFilter(drw->dpy, pic, FilterBilinear, NULL, 0); + XTransform xf; + xf.matrix[0][0] = (srcw << 16u) / dstw; xf.matrix[0][1] = 0; xf.matrix[0][2] = 0; + xf.matrix[1][0] = 0; xf.matrix[1][1] = (srch << 16u) / dsth; xf.matrix[1][2] = 0; + xf.matrix[2][0] = 0; xf.matrix[2][1] = 0; xf.matrix[2][2] = 65536; + XRenderSetPictureTransform(drw->dpy, pic, &xf); + } else { + Imlib_Image origin = imlib_create_image_using_data(srcw, srch, (DATA32 *)src); + if (!origin) return None; imlib_context_set_image(origin); imlib_image_set_has_alpha(1); - Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, w, h, icw, ich); + Imlib_Image scaled = imlib_create_cropped_scaled_image(0, 0, srcw, srch, dstw, dsth); imlib_free_image_and_decache(); - if (!scaled) { XFree(p); free(icbuf); return NULL; } + if (!scaled) return None; imlib_context_set_image(scaled); imlib_image_set_has_alpha(1); - memcpy(icbuf, imlib_image_get_data_for_reading_only(), icsz << 2); + + XImage img = { + dstw, dsth, 0, ZPixmap, (char *)imlib_image_get_data_for_reading_only(), + ImageByteOrder(drw->dpy), BitmapUnit(drw->dpy), BitmapBitOrder(drw->dpy), 32, + 32, 0, 32, + 0, 0, 0 + }; + XInitImage(&img); + + pm = XCreatePixmap(drw->dpy, drw->root, dstw, dsth, 32); + gc = XCreateGC(drw->dpy, pm, 0, NULL); + XPutImage(drw->dpy, pm, gc, &img, 0, 0, 0, 0, dstw, dsth); imlib_free_image_and_decache(); + XFreeGC(drw->dpy, gc); + + pic = XRenderCreatePicture(drw->dpy, pm, XRenderFindStandardFormat(drw->dpy, PictStandardARGB32), 0, NULL); + XFreePixmap(drw->dpy, pm); } - XFree(p); - for (i = 0; i < icsz; ++i) icbuf[i] = prealpha(icbuf[i]); - #if BAR_ALPHA_PATCH - return XCreateImage(dpy, drw->visual, drw->depth, ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0); - #else - return XCreateImage(dpy, DefaultVisual(dpy, screen), DefaultDepth(dpy, screen), ZPixmap, 0, (char *)icbuf, icw, ich, 32, 0); - #endif // BAR_ALPHA_PATCH + + return pic; +} + +void +drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic) +{ + if (!drw) + return; + XRenderComposite(drw->dpy, PictOpOver, pic, None, drw->picture, 0, 0, 0, 0, x, y, w, h); } void freeicon(Client *c) { if (c->icon) { - XDestroyImage(c->icon); - c->icon = NULL; + XRenderFreePicture(dpy, c->icon); + c->icon = None; } } @@ -142,5 +141,5 @@ void updateicon(Client *c) { freeicon(c); - c->icon = geticonprop(c->win); -} \ No newline at end of file + c->icon = geticonprop(c->win, &c->icw, &c->ich); +} diff --git a/patch/bar_winicon.h b/patch/bar_winicon.h index 791182e..56fc6e3 100644 --- a/patch/bar_winicon.h +++ b/patch/bar_winicon.h @@ -2,7 +2,8 @@ #include #include -void drw_img(Drw *drw, int x, int y, XImage *img, uint32_t *tmp); -static XImage *geticonprop(Window win); +static Picture drw_picture_create_resized(Drw *drw, char *src, unsigned int src_w, unsigned int src_h, unsigned int dst_w, unsigned int dst_h); +static void drw_pic(Drw *drw, int x, int y, unsigned int w, unsigned int h, Picture pic); +static Picture geticonprop(Window w, unsigned int *icw, unsigned int *ich); static void freeicon(Client *c); -static void updateicon(Client *c); \ No newline at end of file +static void updateicon(Client *c); diff --git a/patch/bar_wintitle.c b/patch/bar_wintitle.c index 72926f2..fdb54ae 100644 --- a/patch/bar_wintitle.c +++ b/patch/bar_wintitle.c @@ -27,7 +27,7 @@ draw_wintitle(Bar *bar, BarArg *a) int tpad = lrpad / 2; #if BAR_WINICON_PATCH - int ipad = c->icon ? c->icon->width + ICONSPACING : 0; + int ipad = c->icon ? c->icw + ICONSPACING : 0; #endif // BAR_WINICON_PATCH #if BAR_CENTEREDWINDOWNAME_PATCH int cpad = 0; @@ -64,7 +64,7 @@ draw_wintitle(Bar *bar, BarArg *a) #if BAR_WINICON_PATCH if (ipad) { - drw_img(drw, tx, a->y + (a->h - c->icon->height) / 2, c->icon, tmpicon); + drw_pic(drw, tx, a->y + (a->h - c->ich) / 2, c->icw, c->ich, c->icon); tx += ipad; tw -= ipad; } From da5e69c4a7b322683f70f2677309017650c0c79d Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 10 Mar 2022 09:35:12 +0100 Subject: [PATCH 39/49] holdbar + systray compatibility - make systray follow the bar when being revealed and hidden ref. #239 --- patch/bar_holdbar.c | 5 +++++ patch/include.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/patch/bar_holdbar.c b/patch/bar_holdbar.c index 1e00dc8..7597a38 100644 --- a/patch/bar_holdbar.c +++ b/patch/bar_holdbar.c @@ -8,6 +8,7 @@ holdbar(const Arg *arg) updatebarpos(selmon); for (bar = selmon->bar; bar; bar = bar->next) XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + drawbar(selmon); } void @@ -29,6 +30,10 @@ keyrelease(XEvent *e) updatebarpos(selmon); for (bar = selmon->bar; bar; bar = bar->next) XMoveResizeWindow(dpy, bar->win, bar->bx, bar->by, bar->bw, bar->bh); + #if BAR_SYSTRAY_PATCH + if (!selmon->showbar && systray) + XMoveWindow(dpy, systray->win, -32000, -32000); + #endif // BAR_SYSTRAY_PATCH arrange(selmon); } #if COMBO_PATCH diff --git a/patch/include.c b/patch/include.c index d47c6fd..676e2ae 100644 --- a/patch/include.c +++ b/patch/include.c @@ -20,9 +20,6 @@ #if COMBO_PATCH #include "combo.c" #endif -#if BAR_HOLDBAR_PATCH -#include "bar_holdbar.c" -#endif #if BAR_LTSYMBOL_PATCH #include "bar_ltsymbol.c" #endif @@ -83,6 +80,9 @@ #if BAR_SYSTRAY_PATCH #include "bar_systray.c" #endif +#if BAR_HOLDBAR_PATCH +#include "bar_holdbar.c" +#endif #if BAR_VTCOLORS_PATCH #include "bar_vtcolors.c" #endif From 8f93bb8931207810107ed36672f17312e3c5157c Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 14 Mar 2022 09:39:19 +0100 Subject: [PATCH 40/49] manage: For isfloating/oldstate check/set, ensure trans client actually exists In certain instances trans may be set to a window that doesn't actually map to a client via wintoclient; in this case it doesn't make sense to set isfloating/oldstate since trans is essentially invalid in that case / correlates to the above condition check where trans is set / XGetTransientForHint is called. Ref. https://git.suckless.org/dwm/commit/bece862a0fc4fc18ef9065b18cd28e2032d0d975.html --- README.md | 2 +- dwm.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a42572e..14bf980 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This dwm 6.3 (d39e2f3, 2022-01-07) 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.3 (bece862, 2022-03-13) 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 diff --git a/dwm.c b/dwm.c index ea20c20..627afa9 100644 --- a/dwm.c +++ b/dwm.c @@ -1773,7 +1773,9 @@ drawbar(Monitor *m) { Bar *bar; + #if !BAR_FLEXWINTITLE_PATCH if (m->showbar) + #endif // BAR_FLEXWINTITLE_PATCH for (bar = m->bar; bar; bar = bar->next) drawbarwin(bar); } @@ -2437,7 +2439,7 @@ manage(Window w, XWindowAttributes *wa) #endif // MAXIMIZE_PATCH / EXRESIZE_PATCH if (!c->isfloating) - c->isfloating = c->oldstate = trans != None || c->isfixed; + c->isfloating = c->oldstate = t || c->isfixed; if (c->isfloating) { XRaiseWindow(dpy, c->win); XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); From 93f9d97e84bad4c5fae5d4381b96e77a1810ceaf Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 20 Mar 2022 16:31:16 +0100 Subject: [PATCH 41/49] Adding link to map of patches --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 14bf980..06e5a95 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t If you are experiencing issues then you may want to check out the [Known Issues](https://github.com/bakkeby/dwm-flexipatch/discussions/categories/known-issues) discussion category. +Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6PTWOM9Wz) diagram which tries to organise patches into categories. + --- ### Changelog: From 6a0f5b4250dd615557405348013fcdd889251a92 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Wed, 30 Mar 2022 14:20:27 +0200 Subject: [PATCH 42/49] setborderpx: refactoring patch --- patch/setborderpx.c | 75 ++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/patch/setborderpx.c b/patch/setborderpx.c index 948d6f6..56c7636 100644 --- a/patch/setborderpx.c +++ b/patch/setborderpx.c @@ -2,44 +2,55 @@ void setborderpx(const Arg *arg) { Client *c; - int prev_borderpx = selmon->borderpx; - - if (arg->i == 0) - selmon->borderpx = borderpx; - else if (selmon->borderpx + arg->i < 0) - selmon->borderpx = 0; - else - selmon->borderpx += arg->i; + Monitor *m = selmon; + #if BAR_BORDER_PATCH + Bar *bar; + #endif // BAR_BORDER_PATCH + int prev_borderpx = m->borderpx; + m->borderpx = arg->i + ? MAX(m->borderpx + arg->i, 0) + : m->borderpx == borderpx + ? 0 + : borderpx; + int delta = 2 * (m->borderpx - prev_borderpx); #if BAR_BORDER_PATCH - for (bar = selmon->bar; bar; bar = bar->next) { - bar->bh = bar->bh - 2 * bar->borderpx + 2 * selmon->borderpx; - bar->borderpx = selmon->borderpx; + for (bar = m->bar; bar; bar = bar->next) { + bar->bh = bar->bh - 2 * bar->borderpx + 2 * m->borderpx; + bar->borderpx = m->borderpx; } - updatebarpos(selmon); - for (bar = selmon->bar; bar; bar = bar->next) + 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 = selmon->clients; c; c = c->next) - { - if (c->bw + arg->i < 0) - c->bw = 0; - else - c->bw = selmon->borderpx; + for (c = m->clients; c; c = c->next) { + c->bw = m->borderpx; + #if !FAKEFULLSCREEN_PATCH + #if FAKEFULLSCREEN_CLIENT_PATCH + if (c->isfullscreen && !c->fakefullscreen) + continue; + #else + if (c->isfullscreen) + continue; + #endif // FAKEFULLSCREEN_CLIENT_PATCH + #endif // FAKEFULLSCREEN_PATCH + #if BAR_WINTITLEACTIONS_PATCH + if (HIDDEN(c)) + continue; + #endif // BAR_WINTITLEACTIONS_PATCH + #if SCRATCHPADS_PATCH + if ((c->tags & SPTAGMASK) && !ISVISIBLE(c)) + continue; + #endif // SCRATCHPADS_PATCH + #if SCRATCHPAD_ALT_1_PATCH + if ((c->tags & SCRATCHPAD_MASK)) + continue; + #endif // SCRATCHPAD_ALT_1_PATCH + if (!c->isfloating && m->lt[m->sellt]->arrange) + continue; - if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) - { - if (arg->i != 0 && prev_borderpx + arg->i >= 0) - resize(c, c->x, c->y, c->w-(arg->i*2), c->h-(arg->i*2), 0); - else if (arg->i != 0) - resizeclient(c, c->x, c->y, c->w, c->h); - else if (prev_borderpx > borderpx) - resize(c, c->x, c->y, c->w + 2*(prev_borderpx - borderpx), c->h + 2*(prev_borderpx - borderpx), 0); - else if (prev_borderpx < borderpx) - resize(c, c->x, c->y, c->w - 2*(borderpx - prev_borderpx), c->h - 2*(borderpx - prev_borderpx), 0); - } + resizeclient(c, c->x, c->y, c->w - delta, c->h - delta); } - arrange(selmon); + arrange(m); } - From 53d71de38d724cd9a43ad24fc83d9ef523f24c17 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 17 Apr 2022 10:15:22 +0200 Subject: [PATCH 43/49] manage: propertynotify: Reduce cost of unused size hints This patch defers all size hint calculations until they are actually needed, drastically reducing the number of calls to updatesizehints(), which can be expensive when called repeatedly (as it currently is during resizes). In my unscientific testing this reduces calls to updatesizehints() by over 90% during a typical work session. There are no functional changes for users other than an increase in responsiveness after resizes and a reduction in CPU time. In slower environments or X servers, this patch also offers an improvement in responsiveness that is often tangible after resizing a client that changes hints during resizes. There are two main motivations to defer this work to the time of hint application: 1. Some clients, especially terminals using incremental size hints, resend XA_WM_NORMAL_HINTS events on resize to avoid fighting with the WM or mouse resizing. For example, some terminals like urxvt clear PBaseSize and PResizeInc during XResizeWindow and restore them afterwards. For this reason, after the resize is concluded, we typically receive a backlogged XA_WM_NORMAL_HINTS message for each update period with movement, which is useless. In some cases one may get hundreds or thousands of XA_WM_NORMAL_HINTS messages on large resizes, and currently all of these result in a separate updatesizehints() call, of which all but the final one are immediately outdated. (We can't just blindly discard these messages during resizes like we do for EnterNotify, because some of them might actually be for other windows, and may not be XA_WM_NORMAL_HINTS events.) 2. For users which use resizehints=0 most of these updates are unused anyway -- in the normal case where the client is not floating these values won't be used, so there's no need to calculate them up front. A synthetic test using the mouse to resize a floating terminal window from roughly 256x256 to 1024x1024 and back again shows that the number of calls to updatesizehints() goes from over 500 before this patch (one for each update interval with movement) to 2 after this patch (one for each hint application), with no change in user visible behaviour. This also reduces the delay before dwm is ready to process new events again after a large resize on such a client, as it avoids the thundering herd of updatesizehints() calls when hundreds of backlogged XA_WM_NORMAL_HINTS messages appear at once after a resize is finished. ref. https://git.suckless.org/dwm/commit/8806b6e2379372900e3d9e0bf6604bc7f727350b.html#h0-0-4 --- dwm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dwm.c b/dwm.c index 627afa9..85978d8 100644 --- a/dwm.c +++ b/dwm.c @@ -336,7 +336,7 @@ struct Client { int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */ #endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH int oldx, oldy, oldw, oldh; - int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; int bw, oldbw; unsigned int tags; #if SWITCHTAG_PATCH @@ -1002,6 +1002,8 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) if (*w < bh) *w = bh; if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + if (!c->hintsvalid) + updatesizehints(c); /* see last two sentences in ICCCM 4.1.2.3 */ baseismin = c->basew == c->minw && c->baseh == c->minh; if (!baseismin) { /* temporarily remove base dimensions */ @@ -2394,7 +2396,6 @@ manage(Window w, XWindowAttributes *wa) XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); #endif // BAR_FLEXWINTITLE_PATCH configure(c); /* propagates border_width, if size doesn't change */ - updatesizehints(c); if (getatomprop(c, netatom[NetWMState]) == netatom[NetWMFullscreen]) setfullscreen(c, 1); updatewmhints(c); @@ -2730,7 +2731,7 @@ propertynotify(XEvent *e) arrange(c->mon); break; case XA_WM_NORMAL_HINTS: - updatesizehints(c); + c->hintsvalid = 0; break; case XA_WM_HINTS: updatewmhints(c); @@ -4620,6 +4621,7 @@ updatesizehints(Client *c) #endif // SIZEHINTS_RULED_PATCH #endif // SIZEHINTS_PATCH c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); + c->hintsvalid = 1; } void From b2fbf08d3cab91e379463bc26d3f13033beb55bc Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 17 Apr 2022 10:24:02 +0200 Subject: [PATCH 44/49] Update monitor positions also on removal When monitors are removed, the coordinates of existing monitors may change, if the removed monitors had smaller coordinates than the remaining ones. Remove special case handling so that the same update-if-necessary loop is run also in the case when monitors are removed. ref. https://git.suckless.org/dwm/commit/d93ff48803f04f1363bf303af1d7e6ccc5cb8d3f.html#h0-0-21 --- README.md | 2 +- dwm.c | 68 +++++++++++++++++++++++++++---------------------------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 06e5a95..eb59018 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This dwm 6.3 (bece862, 2022-03-13) 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.3 (d93ff48, 2022-04-16) 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 diff --git a/dwm.c b/dwm.c index 85978d8..87e1f6c 100644 --- a/dwm.c +++ b/dwm.c @@ -4485,43 +4485,41 @@ updategeom(void) #if SORTSCREENS_PATCH sortscreens(unique, nn); #endif // SORTSCREENS_PATCH - if (n <= nn) { /* new monitors available */ - for (i = 0; i < (nn - n); i++) { - for (m = mons; m && m->next; m = m->next); - if (m) - m->next = createmon(); - else - mons = createmon(); + /* new monitors if nn > n */ + for (i = n; i < nn; i++) { + for (m = mons; m && m->next; m = m->next); + if (m) + m->next = createmon(); + else + mons = createmon(); + } + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) + { + dirty = 1; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); } - for (i = 0, m = mons; i < nn && m; m = m->next, i++) { - if (i >= n - || unique[i].x_org != m->mx || unique[i].y_org != m->my - || unique[i].width != m->mw || unique[i].height != m->mh) - { - dirty = 1; - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); - } - } - } else { /* less monitors available nn < n */ - for (i = nn; i < n; i++) { - for (m = mons; m && m->next; m = m->next); - while ((c = m->clients)) { - dirty = 1; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachstack(c); - } - if (m == selmon) - selmon = mons; - cleanupmon(m); + /* removed monitors if n > nn */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + dirty = 1; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); } + if (m == selmon) + selmon = mons; + cleanupmon(m); } for (i = 0, m = mons; m; m = m->next, i++) m->index = i; From 49fc922f0df673527d5779ce5cafa1f51832cdcc Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 17 Apr 2022 10:33:26 +0200 Subject: [PATCH 45/49] For all intensive purposes the monitor index is the same as monitor num, thus refactoring to use the latter --- dwm.c | 15 ++++++--------- patch/bar_tagicons.c | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/dwm.c b/dwm.c index 87e1f6c..fd7587c 100644 --- a/dwm.c +++ b/dwm.c @@ -440,7 +440,6 @@ typedef struct { typedef struct Pertag Pertag; #endif // PERTAG_PATCH struct Monitor { - int index; char ltsymbol[16]; float mfact; #if FLEXTILE_DELUXE_LAYOUT @@ -1119,7 +1118,7 @@ buttonpress(XEvent *e) br = &barrules[r]; if (br->bar != bar->idx || (br->monitor == 'A' && m != selmon) || br->clickfunc == NULL) continue; - if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->index) + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) continue; if (bar->x[r] <= ev->x && ev->x <= bar->x[r] + bar->w[r]) { carg.x = ev->x - bar->x[r]; @@ -1556,11 +1555,11 @@ createmon(void) m->gappov = gappov; #endif // VANITYGAPS_PATCH for (mi = 0, mon = mons; mon; mon = mon->next, mi++); // monitor index - m->index = mi; + m->num = mi; #if MONITOR_RULES_PATCH for (j = 0; j < LENGTH(monrules); j++) { mr = &monrules[j]; - if ((mr->monitor == -1 || mr->monitor == mi) + if ((mr->monitor == -1 || mr->monitor == m->num) #if PERTAG_PATCH && (mr->tag <= 0 || (m->tagset[0] & (1 << (mr->tag - 1)))) #endif // PERTAG_PATCH @@ -1591,7 +1590,7 @@ createmon(void) /* Derive the number of bars for this monitor based on bar rules */ for (n = -1, i = 0; i < LENGTH(barrules); i++) { br = &barrules[i]; - if (br->monitor == 'A' || br->monitor == -1 || br->monitor == mi) + if (br->monitor == 'A' || br->monitor == -1 || br->monitor == m->num) n = MAX(br->bar, n); } @@ -1652,7 +1651,7 @@ createmon(void) #if MONITOR_RULES_PATCH for (j = 0; j < LENGTH(monrules); j++) { mr = &monrules[j]; - if ((mr->monitor == -1 || mr->monitor == mi) && (mr->tag == -1 || mr->tag == i)) { + if ((mr->monitor == -1 || mr->monitor == m->num) && (mr->tag == -1 || mr->tag == i)) { layout = MAX(mr->layout, 0); layout = MIN(layout, LENGTH(layouts) - 1); m->pertag->ltidxs[i][0] = &layouts[layout]; @@ -1817,7 +1816,7 @@ drawbarwin(Bar *bar) br = &barrules[r]; if (br->bar != bar->idx || !br->widthfunc || (br->monitor == 'A' && bar->mon != selmon)) continue; - if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->index) + if (br->monitor != 'A' && br->monitor != -1 && br->monitor != bar->mon->num) continue; drw_setscheme(drw, scheme[SchemeNorm]); warg.w = (br->alignment < BAR_ALIGN_RIGHT_LEFT ? lw : rw); @@ -4521,8 +4520,6 @@ updategeom(void) selmon = mons; cleanupmon(m); } - for (i = 0, m = mons; m; m = m->next, i++) - m->index = i; free(unique); } else #endif /* XINERAMA */ diff --git a/patch/bar_tagicons.c b/patch/bar_tagicons.c index 235a6e2..fa1b96c 100644 --- a/patch/bar_tagicons.c +++ b/patch/bar_tagicons.c @@ -4,7 +4,7 @@ tagicon(Monitor *m, int tag) #if BAR_ALTTAGSDECORATION_PATCH Client *c; #endif // BAR_ALTTAGSDECORATION_PATCH - int tagindex = tag + NUMTAGS * m->index; + int tagindex = tag + NUMTAGS * m->num; if (tagindex >= LENGTH(tagicons[DEFAULT_TAGS])) tagindex = tagindex % LENGTH(tagicons[DEFAULT_TAGS]); #if BAR_ALTTAGSDECORATION_PATCH From 38f709fea5fe2027892cd784110c639a17724fec Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 26 Apr 2022 17:22:11 +0200 Subject: [PATCH 46/49] Revert "manage: For isfloating/oldstate check/set, ensure trans client actually exists" This reverts commit bece862a0fc4fc18ef9065b18cd28e2032d0d975. It caused a regression, for example: https://lists.suckless.org/hackers/2203/18220.html Ref. https://git.suckless.org/dwm/commit/a4771de5ba54a38b062a7d748635f21c141b5c7e.html --- dwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dwm.c b/dwm.c index fd7587c..a4e25ef 100644 --- a/dwm.c +++ b/dwm.c @@ -2439,7 +2439,7 @@ manage(Window w, XWindowAttributes *wa) #endif // MAXIMIZE_PATCH / EXRESIZE_PATCH if (!c->isfloating) - c->isfloating = c->oldstate = t || c->isfixed; + c->isfloating = c->oldstate = trans != None || c->isfixed; if (c->isfloating) { XRaiseWindow(dpy, c->win); XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); From f2b37c411cd68bf1d3d00e7fb5889e079431247f Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 26 Apr 2022 17:23:19 +0200 Subject: [PATCH 47/49] LICENSE: add Chris Down Ref. https://git.suckless.org/dwm/commit/a83dc2031050d786ddf5f329b57d658a931c94b7.html --- LICENSE | 1 + 1 file changed, 1 insertion(+) diff --git a/LICENSE b/LICENSE index d221f09..995172f 100644 --- a/LICENSE +++ b/LICENSE @@ -17,6 +17,7 @@ MIT/X Consortium License © 2015-2016 Quentin Rameau © 2015-2016 Eric Pruitt © 2016-2017 Markus Teich +© 2020-2022 Chris Down Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), From 2ecc15a2ef8ab45d49cbf261cb3280fe9ab3d058 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 26 Apr 2022 17:25:20 +0200 Subject: [PATCH 48/49] manage: Make sure c->isfixed is applied before floating checks Commit 8806b6e23793 ("manage: propertynotify: Reduce cost of unused size hints") mistakenly removed an early size hints update that's needed to populate c->isfixed for floating checks at manage() time. This resulted in fixed (size hint min dimensions == max dimensions) subset of windows not floating when they should. See https://lists.suckless.org/dev/2204/34730.html for discussion. Ref. https://git.suckless.org/dwm/commit/8b48e309735f5fe49d35f86e967f4b5dea2a2f2d.html --- README.md | 2 +- dwm.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eb59018..44b6de3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This dwm 6.3 (d93ff48, 2022-04-16) 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.3 (8b48e30, 2022-04-26) 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 diff --git a/dwm.c b/dwm.c index a4e25ef..9f70675 100644 --- a/dwm.c +++ b/dwm.c @@ -2395,6 +2395,7 @@ manage(Window w, XWindowAttributes *wa) XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); #endif // BAR_FLEXWINTITLE_PATCH configure(c); /* propagates border_width, if size doesn't change */ + updatesizehints(c); if (getatomprop(c, netatom[NetWMState]) == netatom[NetWMFullscreen]) setfullscreen(c, 1); updatewmhints(c); From c553f93b528449ed2e7d4b424f063ef3c1d3d8f6 Mon Sep 17 00:00:00 2001 From: Bakkeby Date: Sun, 8 May 2022 21:43:57 +0200 Subject: [PATCH 49/49] shiftview + scrachpads compatibility --- patch/shiftview.c | 10 +++++----- patch/shiftview.h | 1 - patch/shiftviewclients.c | 25 ++++++++++--------------- patch/shiftviewclients.h | 1 - 4 files changed, 15 insertions(+), 22 deletions(-) diff --git a/patch/shiftview.c b/patch/shiftview.c index 423d74b..b9c811a 100644 --- a/patch/shiftview.c +++ b/patch/shiftview.c @@ -8,12 +8,12 @@ shiftview(const Arg *arg) unsigned int seltagset = selmon->tagset[selmon->seltags]; #endif // SCRATCHPADS_PATCH if (arg->i > 0) // left circular shift - shifted.ui = (seltagset << arg->i) - | (seltagset >> (NUMTAGS - arg->i)); + shifted.ui = (seltagset << arg->i) | (seltagset >> (NUMTAGS - arg->i)); else // right circular shift - shifted.ui = seltagset >> -arg->i - | seltagset << (NUMTAGS + arg->i); + shifted.ui = (seltagset >> -arg->i) | (seltagset << (NUMTAGS + arg->i)); + #if SCRATCHPADS_PATCH + shifted.ui &= ~SPTAGMASK; + #endif // SCRATCHPADS_PATCH view(&shifted); } - diff --git a/patch/shiftview.h b/patch/shiftview.h index 1d7fd1f..7bf3a14 100644 --- a/patch/shiftview.h +++ b/patch/shiftview.h @@ -1,2 +1 @@ static void shiftview(const Arg *arg); - diff --git a/patch/shiftviewclients.c b/patch/shiftviewclients.c index b805b51..adeaab7 100644 --- a/patch/shiftviewclients.c +++ b/patch/shiftviewclients.c @@ -29,23 +29,18 @@ shiftviewclients(const Arg *arg) #else shifted.ui = selmon->tagset[selmon->seltags]; #endif // SCRATCHPADS_PATCH - if (arg->i > 0) { // left circular shift - do { + + do { + if (arg->i > 0) // left circular shift shifted.ui = (shifted.ui << arg->i) | (shifted.ui >> (NUMTAGS - arg->i)); - #if SCRATCHPADS_PATCH - shifted.ui &= ~SPTAGMASK; - #endif // SCRATCHPADS_PATCH - } while (tagmask && !(shifted.ui & tagmask)); - } else { // right circular shift - do { - shifted.ui = (shifted.ui >> (- arg->i) - | shifted.ui << (NUMTAGS + arg->i)); - #if SCRATCHPADS_PATCH - shifted.ui &= ~SPTAGMASK; - #endif // SCRATCHPADS_PATCH - } while (tagmask && !(shifted.ui & tagmask)); - } + else // right circular shift + shifted.ui = (shifted.ui >> -arg->i) + | (shifted.ui << (NUMTAGS + arg->i)); + #if SCRATCHPADS_PATCH + shifted.ui &= ~SPTAGMASK; + #endif // SCRATCHPADS_PATCH + } while (tagmask && !(shifted.ui & tagmask)); view(&shifted); } diff --git a/patch/shiftviewclients.h b/patch/shiftviewclients.h index 49aeb51..2f652cd 100644 --- a/patch/shiftviewclients.h +++ b/patch/shiftviewclients.h @@ -1,2 +1 @@ static void shiftviewclients(const Arg *arg); -