diff options
Diffstat (limited to 'dwm/patches')
64 files changed, 8572 insertions, 0 deletions
diff --git a/dwm/patches/alwaysontop-6.2.diff b/dwm/patches/alwaysontop-6.2.diff new file mode 100644 index 0000000..1feb033 --- /dev/null +++ b/dwm/patches/alwaysontop-6.2.diff @@ -0,0 +1,109 @@ +# From 9cd160c4ba9c345c24644a7da77cc4f04fc93c4e Mon Sep 17 00:00:00 2001 +# From: Rob Pilling <robpilling@gmail.com> +# Date: Mon, 27 Jul 2020 20:11:08 +0100 +# Subject: [PATCH] alwaysontop +# +# --- +# config.def.h | 1 + +# dwm.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- +# 2 files changed, 44 insertions(+), 2 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..c3c7edd 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -78,6 +78,7 @@ static Key keys[] = { + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, ++ { MODKEY|ShiftMask, XK_space, togglealwaysontop, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, +diff --git a/dwm.c b/dwm.c +index 4465af1..8d54b26 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -92,7 +92,7 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; +- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int isfixed, iscentered, isfloating, isalwaysontop, isurgent, neverfocus, oldstate, isfullscreen; + Client *next; + Client *snext; + Monitor *mon; +@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void togglealwaysontop(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); +@@ -732,8 +733,11 @@ drawbar(Monitor *m) + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); +- if (m->sel->isfloating) ++ if (m->sel->isfloating) { + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); ++ if (m->sel->isalwaysontop) ++ drw_rect(drw, x + boxs, bh - boxw, boxw, boxw, 0, 0); ++ } + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); +@@ -1356,6 +1360,17 @@ restack(Monitor *m) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); ++ ++ /* raise the aot window */ ++ for(Monitor *m_search = mons; m_search; m_search = m_search->next){ ++ for(c = m_search->clients; c; c = c->next){ ++ if(c->isalwaysontop){ ++ XRaiseWindow(dpy, c->win); ++ break; ++ } ++ } ++ } ++ + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + wc.sibling = m->barwin; +@@ -1716,6 +1731,32 @@ togglefloating(const Arg *arg) + if (selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, 0); ++ else ++ selmon->sel->isalwaysontop = 0; /* disabled, turn this off too */ ++ arrange(selmon); ++} ++ ++void ++togglealwaysontop(const Arg *arg) ++{ ++ if (!selmon->sel) ++ return; ++ if (selmon->sel->isfullscreen) ++ return; ++ ++ if(selmon->sel->isalwaysontop){ ++ selmon->sel->isalwaysontop = 0; ++ }else{ ++ /* disable others */ ++ for(Monitor *m = mons; m; m = m->next) ++ for(Client *c = m->clients; c; c = c->next) ++ c->isalwaysontop = 0; ++ ++ /* turn on, make it float too */ ++ selmon->sel->isfloating = 1; ++ selmon->sel->isalwaysontop = 1; ++ } ++ + arrange(selmon); + } + +-- +2.31.1 diff --git a/dwm/patches/dwm-accessnthmon.diff b/dwm/patches/dwm-accessnthmon.diff new file mode 100644 index 0000000..a65ec15 --- /dev/null +++ b/dwm/patches/dwm-accessnthmon.diff @@ -0,0 +1,100 @@ +diff --git a/config.def.h b/config.def.h +index 1c0b587..8595a71 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -49,7 +49,10 @@ static const Layout layouts[] = { + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ +- { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, ++ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \ ++ { ALTMOD, KEY, focusnthmon, {.i = TAG } }, \ ++ { ALTMOD|ShiftMask, KEY, tagnthmon, {.i = TAG } }, ++ + + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +diff --git a/dwm.c b/dwm.c +index b0b3466..96fa0bd 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -161,6 +161,7 @@ static void destroynotify(XEvent *e); + static void detach(Client *c); + static void detachstack(Client *c); + static Monitor *dirtomon(int dir); ++static Monitor *numtomon(int num); + static void drawbar(Monitor *m); + static void drawbars(void); + static void enternotify(XEvent *e); +@@ -168,6 +169,7 @@ static void expose(XEvent *e); + static void focus(Client *c); + static void focusin(XEvent *e); + static void focusmon(const Arg *arg); ++static void focusnthmon(const Arg *arg); + static void focusstack(const Arg *arg); + static Atom getatomprop(Client *c, Atom prop); + static int getrootptr(int *x, int *y); +@@ -209,6 +211,7 @@ static void sigchld(int unused); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); ++static void tagnthmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); +@@ -693,6 +696,18 @@ dirtomon(int dir) + return m; + } + ++Monitor * ++numtomon(int num) ++{ ++ Monitor *m = NULL; ++ int i = 0; ++ ++ for(m = mons, i=0; m->next && i < num; m = m->next){ ++ i++; ++ } ++ return m; ++} ++ + void + drawbar(Monitor *m) + { +@@ -830,6 +845,21 @@ focusmon(const Arg *arg) + focus(NULL); + } + ++void ++focusnthmon(const Arg *arg) ++{ ++ Monitor *m; ++ ++ if (!mons->next) ++ return; ++ ++ if ((m = numtomon(arg->i)) == selmon) ++ return; ++ unfocus(selmon->sel, 0); ++ selmon = m; ++ focus(NULL); ++} ++ + void + focusstack(const Arg *arg) + { +@@ -1671,6 +1701,14 @@ tagmon(const Arg *arg) + sendmon(selmon->sel, dirtomon(arg->i)); + } + ++void ++tagnthmon(const Arg *arg) ++{ ++ if (!selmon->sel || !mons->next) ++ return; ++ sendmon(selmon->sel, numtomon(arg->i)); ++} ++ + void + tile(Monitor *m) + { diff --git a/dwm/patches/dwm-actualfullscreen-20211013-cb3f58a.diff b/dwm/patches/dwm-actualfullscreen-20211013-cb3f58a.diff new file mode 100644 index 0000000..364b3bd --- /dev/null +++ b/dwm/patches/dwm-actualfullscreen-20211013-cb3f58a.diff @@ -0,0 +1,67 @@ +# From eea13010ffc3983392857ee1e3804e3aa1064d7a Mon Sep 17 00:00:00 2001 +# From: Soenke Lambert <s.lambert@mittwald.de> +# Date: Wed, 13 Oct 2021 18:21:09 +0200 +# Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f] +# +# This actually fullscreens a window, instead of just hiding the statusbar +# and applying the monocle layout. +# --- +# config.def.h | 1 + +# dwm.1 | 3 +++ +# dwm.c | 8 ++++++++ +# 3 files changed, 12 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..8cd3204 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -78,6 +78,7 @@ static Key keys[] = { + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, ++ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, +diff --git a/dwm.1 b/dwm.1 +index 13b3729..a368d05 100644 +--- a/dwm.1 ++++ b/dwm.1 +@@ -116,6 +116,9 @@ Zooms/cycles focused window to/from master area (tiled layouts only). + .B Mod1\-Shift\-c + Close focused window. + .TP ++.B Mod1\-Shift\-f ++Toggle fullscreen for focused window. ++.TP + .B Mod1\-Shift\-space + Toggle focused window between tiled and floating state. + .TP +diff --git a/dwm.c b/dwm.c +index 4465af1..c1b899a 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void togglefullscr(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); +@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg) + arrange(selmon); + } + ++void ++togglefullscr(const Arg *arg) ++{ ++ if(selmon->sel) ++ setfullscreen(selmon->sel, !selmon->sel->isfullscreen); ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.30.2 diff --git a/dwm/patches/dwm-allowkillrule-6.4.diff b/dwm/patches/dwm-allowkillrule-6.4.diff new file mode 100644 index 0000000..33365d7 --- /dev/null +++ b/dwm/patches/dwm-allowkillrule-6.4.diff @@ -0,0 +1,98 @@ +diff -up a/config.def.h b/config.def.h +--- a/config.def.h 2022-10-04 19:38:18.000000000 +0200 ++++ b/config.def.h 2023-05-06 22:19:27.298742237 +0200 +@@ -5,6 +5,7 @@ static const unsigned int borderpx = 1; + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const int allowkill = 1; /* allow killing clients by default? */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +@@ -26,9 +27,9 @@ static const Rule rules[] = { + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ /* class instance title tags mask allowkill isfloating monitor */ ++ { "Gimp", NULL, NULL, 0, 1, 1, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, 1, 0, -1 }, + }; + + /* layout(s) */ +@@ -78,6 +79,7 @@ static const Key keys[] = { + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, ++ { MODKEY, XK_q, toggleallowkill,{0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, +diff -up a/dwm.c b/dwm.c +--- a/dwm.c 2022-10-04 19:38:18.000000000 +0200 ++++ b/dwm.c 2023-05-06 22:18:43.239357744 +0200 +@@ -93,6 +93,7 @@ struct Client { + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int allowkill; + Client *next; + Client *snext; + Monitor *mon; +@@ -137,6 +138,7 @@ typedef struct { + const char *instance; + const char *title; + unsigned int tags; ++ int allowkill; + int isfloating; + int monitor; + } Rule; +@@ -212,6 +214,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void toggleallowkill(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); +@@ -288,6 +291,7 @@ applyrules(Client *c) + /* rule matching */ + c->isfloating = 0; + c->tags = 0; ++ c->allowkill = allowkill; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; +@@ -300,6 +304,7 @@ applyrules(Client *c) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; ++ c->allowkill = r->allowkill; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; +@@ -1006,7 +1011,7 @@ keypress(XEvent *e) + void + killclient(const Arg *arg) + { +- if (!selmon->sel) ++ if (!selmon->sel || !selmon->sel->allowkill) + return; + if (!sendevent(selmon->sel, wmatom[WMDelete])) { + XGrabServer(dpy); +@@ -1704,6 +1709,13 @@ togglebar(const Arg *arg) + } + + void ++toggleallowkill(const Arg *arg) ++{ ++ if (!selmon->sel) return; ++ selmon->sel->allowkill = !selmon->sel->allowkill; ++} ++ ++void + togglefloating(const Arg *arg) + { + if (!selmon->sel) diff --git a/dwm/patches/dwm-alpha-20230401-348f655.diff b/dwm/patches/dwm-alpha-20230401-348f655.diff new file mode 100644 index 0000000..8096f04 --- /dev/null +++ b/dwm/patches/dwm-alpha-20230401-348f655.diff @@ -0,0 +1,287 @@ +# From ad5887df95fda706291c81ee143d0786a1717b12 Mon Sep 17 00:00:00 2001 +# From: getimiskon <getimiskon@disroot.org> +# Date: Sat, 1 Apr 2023 16:22:01 +0300 +# Subject: [PATCH] Allow dwm to have translucent bars, while keeping all the +# text on it opaque, just like the alpha-patch for st. Updated for 348f655. +# +# --- +# config.def.h | 7 +++++++ +# config.mk | 2 +- +# drw.c | 26 ++++++++++++----------- +# drw.h | 9 +++++--- +# dwm.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++------ +# 5 files changed, 81 insertions(+), 22 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..8b3789a 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -12,11 +12,18 @@ static const char col_gray2[] = "#444444"; + static const char col_gray3[] = "#bbbbbb"; + static const char col_gray4[] = "#eeeeee"; + static const char col_cyan[] = "#005577"; ++static const unsigned int baralpha = 0xd0; ++static const unsigned int borderalpha = OPAQUE; + static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; ++static const unsigned int alphas[][3] = { ++ /* fg bg border*/ ++ [SchemeNorm] = { OPAQUE, baralpha, borderalpha }, ++ [SchemeSel] = { OPAQUE, baralpha, borderalpha }, ++}; + + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +diff --git a/config.mk b/config.mk +index ba64d3d..d609c42 100644 +--- a/config.mk ++++ b/config.mk +@@ -23,7 +23,7 @@ FREETYPEINC = /usr/include/freetype2 + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lXrender + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/drw.c b/drw.c +index a58a2b4..d18e8d8 100644 +--- a/drw.c ++++ b/drw.c +@@ -61,7 +61,7 @@ utf8decode(const char *c, long *u, size_t clen) + } + + Drw * +-drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) ++drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap) + { + Drw *drw = ecalloc(1, sizeof(Drw)); + +@@ -70,8 +70,11 @@ drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h + drw->root = root; + drw->w = w; + drw->h = h; +- drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); +- drw->gc = XCreateGC(dpy, root, 0, NULL); ++ drw->visual = visual; ++ drw->depth = depth; ++ drw->cmap = cmap; ++ drw->drawable = XCreatePixmap(dpy, root, w, h, depth); ++ drw->gc = XCreateGC(dpy, drw->drawable, 0, NULL); + XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); + + return drw; +@@ -87,7 +90,7 @@ drw_resize(Drw *drw, unsigned int w, unsigned int h) + drw->h = h; + if (drw->drawable) + XFreePixmap(drw->dpy, drw->drawable); +- drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); ++ drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, drw->depth); + } + + void +@@ -181,21 +184,22 @@ drw_fontset_free(Fnt *font) + } + + void +-drw_clr_create(Drw *drw, Clr *dest, const char *clrname) ++drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha) + { + if (!drw || !dest || !clrname) + return; + +- if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), +- DefaultColormap(drw->dpy, drw->screen), ++ if (!XftColorAllocName(drw->dpy, drw->visual, drw->cmap, + clrname, dest)) + die("error, cannot allocate color '%s'", clrname); ++ ++ dest->pixel = (dest->pixel & 0x00ffffffU) | (alpha << 24); + } + + /* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ + Clr * +-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) ++drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount) + { + size_t i; + Clr *ret; +@@ -205,7 +209,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) + return NULL; + + for (i = 0; i < clrcount; i++) +- drw_clr_create(drw, &ret[i], clrnames[i]); ++ drw_clr_create(drw, &ret[i], clrnames[i], alphas[i]); + return ret; + } + +@@ -263,9 +267,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + } else { + XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); +- d = XftDrawCreate(drw->dpy, drw->drawable, +- DefaultVisual(drw->dpy, drw->screen), +- DefaultColormap(drw->dpy, drw->screen)); ++ d = XftDrawCreate(drw->dpy, drw->drawable, drw->visual, drw->cmap); + x += lpad; + w -= lpad; + } +diff --git a/drw.h b/drw.h +index 6471431..2143533 100644 +--- a/drw.h ++++ b/drw.h +@@ -20,6 +20,9 @@ typedef struct { + Display *dpy; + int screen; + Window root; ++ Visual *visual; ++ unsigned int depth; ++ Colormap cmap; + Drawable drawable; + GC gc; + Clr *scheme; +@@ -27,7 +30,7 @@ typedef struct { + } Drw; + + /* Drawable abstraction */ +-Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); ++Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h, Visual *visual, unsigned int depth, Colormap cmap); + void drw_resize(Drw *drw, unsigned int w, unsigned int h); + void drw_free(Drw *drw); + +@@ -39,8 +42,8 @@ unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int + void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); + + /* Colorscheme abstraction */ +-void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); +-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); ++void drw_clr_create(Drw *drw, Clr *dest, const char *clrname, unsigned int alpha); ++Clr *drw_scm_create(Drw *drw, const char *clrnames[], const unsigned int alphas[], size_t clrcount); + + /* Cursor abstraction */ + Cur *drw_cur_create(Drw *drw, int shape); +diff --git a/dwm.c b/dwm.c +index c2bd871..3b34de8 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -56,6 +56,7 @@ + #define HEIGHT(X) ((X)->h + 2 * (X)->bw) + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) ++#define OPAQUE 0xffU + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +@@ -232,6 +233,7 @@ static Monitor *wintomon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); ++static void xinitvisual(); + static void zoom(const Arg *arg); + + /* variables */ +@@ -268,6 +270,11 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++static int useargb = 0; ++static Visual *visual; ++static int depth; ++static Colormap cmap; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -1558,7 +1565,8 @@ setup(void) + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); +- drw = drw_create(dpy, screen, root, sw, sh); ++ xinitvisual(); ++ drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; +@@ -1586,7 +1594,7 @@ setup(void) + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) +- scheme[i] = drw_scm_create(drw, colors[i], 3); ++ scheme[i] = drw_scm_create(drw, colors[i], alphas[i], 3); + /* init bars */ + updatebars(); + updatestatus(); +@@ -1813,16 +1821,18 @@ updatebars(void) + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, +- .background_pixmap = ParentRelative, ++ .background_pixel = 0, ++ .border_pixel = 0, ++ .colormap = cmap, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + if (m->barwin) + continue; +- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), +- CopyFromParent, DefaultVisual(dpy, screen), +- CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); ++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, depth, ++ InputOutput, visual, ++ CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); +@@ -2120,6 +2130,43 @@ xerrorstart(Display *dpy, XErrorEvent *ee) + return -1; + } + ++void ++xinitvisual() ++{ ++ XVisualInfo *infos; ++ XRenderPictFormat *fmt; ++ int nitems; ++ int i; ++ ++ XVisualInfo tpl = { ++ .screen = screen, ++ .depth = 32, ++ .class = TrueColor ++ }; ++ long masks = VisualScreenMask | VisualDepthMask | VisualClassMask; ++ ++ infos = XGetVisualInfo(dpy, masks, &tpl, &nitems); ++ visual = NULL; ++ for(i = 0; i < nitems; i ++) { ++ fmt = XRenderFindVisualFormat(dpy, infos[i].visual); ++ if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { ++ visual = infos[i].visual; ++ depth = infos[i].depth; ++ cmap = XCreateColormap(dpy, root, visual, AllocNone); ++ useargb = 1; ++ break; ++ } ++ } ++ ++ XFree(infos); ++ ++ if (! visual) { ++ visual = DefaultVisual(dpy, screen); ++ depth = DefaultDepth(dpy, screen); ++ cmap = DefaultColormap(dpy, screen); ++ } ++} ++ + void + zoom(const Arg *arg) + { +-- +2.40.0 diff --git a/dwm/patches/dwm-alttab2+winview-6.4.diff b/dwm/patches/dwm-alttab2+winview-6.4.diff new file mode 100644 index 0000000..38cb482 --- /dev/null +++ b/dwm/patches/dwm-alttab2+winview-6.4.diff @@ -0,0 +1,217 @@ +diff --git a/config.def.h b/config.def.h +index 9efa774..95499bd 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -2,6 +2,8 @@ + + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int tabModKey = 0x40; ++static const unsigned int tabCycleKey = 0x17; + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ +@@ -95,6 +97,8 @@ static const Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY, XK_o, winview, {0} }, ++ { Mod1Mask, XK_Tab, alttab, {0} }, + }; + + /* button definitions */ +diff --git a/dwm.1 b/dwm.1 +index ddc8321..f8a809e 100644 +--- a/dwm.1 ++++ b/dwm.1 +@@ -110,6 +110,9 @@ Increase master area size. + .B Mod1\-h + Decrease master area size. + .TP ++.B Mod1\-o ++Select view of the window in focus. The list of tags to be displayed is matched to the window tag list. ++.TP + .B Mod1\-Return + Zooms/cycles focused window to/from master area (tiled layouts only). + .TP +diff --git a/dwm.c b/dwm.c +index f1d86b2..71d0ebc 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -28,6 +28,7 @@ + #include <stdlib.h> + #include <string.h> + #include <unistd.h> ++#include <time.h> + #include <sys/types.h> + #include <sys/wait.h> + #include <X11/cursorfont.h> +@@ -142,6 +143,7 @@ typedef struct { + } Rule; + + /* function declarations */ ++static void alttab(const Arg *arg); + static void applyrules(Client *c); + static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); + static void arrange(Monitor *m); +@@ -168,6 +170,7 @@ static void expose(XEvent *e); + static void focus(Client *c); + static void focusin(XEvent *e); + static void focusmon(const Arg *arg); ++static void focusnext(const Arg *arg); + static void focusstack(const Arg *arg); + static Atom getatomprop(Client *c, Atom prop); + static int getrootptr(int *x, int *y); +@@ -229,6 +232,7 @@ static void updatewmhints(Client *c); + static void view(const Arg *arg); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); ++static void winview(const Arg* arg); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); +@@ -268,6 +272,8 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++static int alt_tab_direction = 0; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -275,6 +281,79 @@ static Window root, wmcheckwin; + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + + /* function implementations */ ++ ++static void ++alttab(const Arg *arg) { ++ ++ view(&(Arg){ .ui = ~0 }); ++ focusnext(&(Arg){ .i = alt_tab_direction }); ++ ++ int grabbed = 1; ++ int grabbed_keyboard = 1000; ++ for (int i = 0; i < 100; i += 1) { ++ struct timespec ts; ++ ts.tv_sec = 0; ++ ts.tv_nsec = 1000000; ++ ++ if (grabbed_keyboard != GrabSuccess) { ++ grabbed_keyboard = XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, ++ GrabModeAsync, GrabModeAsync, CurrentTime); ++ } ++ if (grabbed_keyboard == GrabSuccess) { ++ XGrabButton(dpy, AnyButton, AnyModifier, None, False, ++ BUTTONMASK, GrabModeAsync, GrabModeAsync, ++ None, None); ++ break; ++ } ++ nanosleep(&ts, NULL); ++ if (i == 100 - 1) ++ grabbed = 0; ++ } ++ ++ XEvent event; ++ Client *c; ++ Monitor *m; ++ XButtonPressedEvent *ev; ++ ++ while (grabbed) { ++ XNextEvent(dpy, &event); ++ switch (event.type) { ++ case KeyPress: ++ if (event.xkey.keycode == tabCycleKey) ++ focusnext(&(Arg){ .i = alt_tab_direction }); ++ break; ++ case KeyRelease: ++ if (event.xkey.keycode == tabModKey) { ++ XUngrabKeyboard(dpy, CurrentTime); ++ XUngrabButton(dpy, AnyButton, AnyModifier, None); ++ grabbed = 0; ++ alt_tab_direction = !alt_tab_direction; ++ winview(0); ++ } ++ break; ++ case ButtonPress: ++ ev = &(event.xbutton); ++ if ((m = wintomon(ev->window)) && m != selmon) { ++ unfocus(selmon->sel, 1); ++ selmon = m; ++ focus(NULL); ++ } ++ if ((c = wintoclient(ev->window))) ++ focus(c); ++ XAllowEvents(dpy, AsyncBoth, CurrentTime); ++ break; ++ case ButtonRelease: ++ XUngrabKeyboard(dpy, CurrentTime); ++ XUngrabButton(dpy, AnyButton, AnyModifier, None); ++ grabbed = 0; ++ alt_tab_direction = !alt_tab_direction; ++ winview(0); ++ break; ++ } ++ } ++ return; ++} ++ + void + applyrules(Client *c) + { +@@ -835,6 +914,28 @@ focusmon(const Arg *arg) + focus(NULL); + } + ++static void ++focusnext(const Arg *arg) { ++ Monitor *m; ++ Client *c; ++ m = selmon; ++ c = m->sel; ++ ++ if (arg->i) { ++ if (c->next) ++ c = c->next; ++ else ++ c = m->clients; ++ } else { ++ Client *last = c; ++ if (last == m->clients) ++ last = NULL; ++ for (c = m->clients; c->next != last; c = c->next); ++ } ++ focus(c); ++ return; ++} ++ + void + focusstack(const Arg *arg) + { +@@ -2092,6 +2193,26 @@ wintomon(Window w) + return selmon; + } + ++/* Selects for the view of the focused window. The list of tags */ ++/* to be displayed is matched to the focused window tag list. */ ++void ++winview(const Arg* arg){ ++ Window win, win_r, win_p, *win_c; ++ unsigned nc; ++ int unused; ++ Client* c; ++ Arg a; ++ ++ if (!XGetInputFocus(dpy, &win, &unused)) return; ++ while(XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc) ++ && win_p != win_r) win = win_p; ++ ++ if (!(c = wintoclient(win))) return; ++ ++ a.ui = c->tags; ++ view(&a); ++} ++ + /* There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ diff --git a/dwm/patches/dwm-alwayscenter-20200625-f04cac6.diff b/dwm/patches/dwm-alwayscenter-20200625-f04cac6.diff new file mode 100644 index 0000000..03ea9ef --- /dev/null +++ b/dwm/patches/dwm-alwayscenter-20200625-f04cac6.diff @@ -0,0 +1,12 @@ +diff -up dwm/dwm.c dwmmod/dwm.c +--- dwm/dwm.c 2020-06-25 00:21:30.383692180 -0300 ++++ dwmmod/dwm.c 2020-06-25 00:20:35.643692330 -0300 +@@ -1057,6 +1057,8 @@ manage(Window w, XWindowAttributes *wa) + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); ++ c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2; ++ c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2; + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + if (!c->isfloating) diff --git a/dwm/patches/dwm-bar-height-spacing-6.3.diff b/dwm/patches/dwm-bar-height-spacing-6.3.diff new file mode 100644 index 0000000..cbdeb9a --- /dev/null +++ b/dwm/patches/dwm-bar-height-spacing-6.3.diff @@ -0,0 +1,25 @@ +diff --git a/config.def.h b/config.def.h +index 1c0b587..9814500 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -5,6 +5,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const int user_bh = 2; /* 2 is the default spacing around the bar's font */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +diff --git a/dwm.c b/dwm.c +index 4465af1..2c27cb3 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1545,7 +1545,7 @@ setup(void) + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; +- bh = drw->fonts->h + 2; ++ bh = drw->fonts->h + user_bh; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); diff --git a/dwm/patches/dwm-barpadding-20211020-a786211.diff b/dwm/patches/dwm-barpadding-20211020-a786211.diff new file mode 100644 index 0000000..19a3150 --- /dev/null +++ b/dwm/patches/dwm-barpadding-20211020-a786211.diff @@ -0,0 +1,117 @@ +# From a3cfb215f7f647d83d67e33df8f33a73e43bd65f Mon Sep 17 00:00:00 2001 +# From: Bakkeby <bakkeby@gmail.com> +# Date: Wed, 20 Oct 2021 09:14:07 +0200 +# Subject: [PATCH] barpadding: adds space between the statusbar and the edge of +# the screen +# +# --- +# config.def.h | 2 ++ +# dwm.c | 25 +++++++++++++++---------- +# 2 files changed, 17 insertions(+), 10 deletions(-) + +diff --git a/config.def.h b/config.def.h +index a2ac963..f0b739f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const int vertpad = 10; /* vertical padding of bar */ ++static const int sidepad = 10; /* horizontal padding of bar */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +diff --git a/dwm.c b/dwm.c +index 5e4d494..df6d0d7 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -242,6 +242,8 @@ static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh, blw = 0; /* bar geometry */ + static int lrpad; /* sum of left and right padding for text */ ++static int vp; /* vertical padding for bar */ ++static int sp; /* side padding for bar */ + static int (*xerrorxlib)(Display *, XErrorEvent *); + static unsigned int numlockmask = 0; + static void (*handler[LASTEvent]) (XEvent *) = { +@@ -568,7 +570,7 @@ configurenotify(XEvent *e) + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); +- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); ++ XMoveResizeWindow(dpy, m->barwin, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh); + } + focus(NULL); + arrange(NULL); +@@ -706,7 +708,7 @@ drawbar(Monitor *m) + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ +- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); ++ drw_text(drw, m->ww - tw - 2 * sp, 0, tw, bh, 0, stext, 0); + } + + for (c = m->clients; c; c = c->next) { +@@ -732,12 +734,12 @@ drawbar(Monitor *m) + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); +- drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); ++ drw_text(drw, x, 0, w - 2 * sp, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { + drw_setscheme(drw, scheme[SchemeNorm]); +- drw_rect(drw, x, 0, w, bh, 1, 1); ++ drw_rect(drw, x, 0, w - 2 * sp, bh, 1, 1); + } + } + drw_map(drw, m->barwin, 0, 0, m->ww, bh); +@@ -1547,7 +1549,10 @@ setup(void) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; ++ sp = sidepad; ++ vp = (topbar == 1) ? vertpad : - vertpad; + updategeom(); ++ + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); +@@ -1704,7 +1709,7 @@ togglebar(const Arg *arg) + { + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); +- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); ++ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx + sp, selmon->by + vp, selmon->ww - 2 * sp, bh); + arrange(selmon); + } + +@@ -1814,7 +1819,7 @@ updatebars(void) + for (m = mons; m; m = m->next) { + if (m->barwin) + continue; +- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), ++ m->barwin = XCreateWindow(dpy, root, m->wx + sp, m->by + vp, m->ww - 2 * sp, bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); +@@ -1829,11 +1834,11 @@ updatebarpos(Monitor *m) + m->wy = m->my; + m->wh = m->mh; + if (m->showbar) { +- m->wh -= bh; +- m->by = m->topbar ? m->wy : m->wy + m->wh; +- m->wy = m->topbar ? m->wy + bh : m->wy; ++ m->wh = m->wh - vertpad - bh; ++ m->by = m->topbar ? m->wy : m->wy + m->wh + vertpad; ++ m->wy = m->topbar ? m->wy + bh + vp : m->wy; + } else +- m->by = -bh; ++ m->by = -bh - vp; + } + + void +-- +2.33.0 diff --git a/dwm/patches/dwm-bartoggle-keybinds-6.4.diff b/dwm/patches/dwm-bartoggle-keybinds-6.4.diff new file mode 100644 index 0000000..d06bedf --- /dev/null +++ b/dwm/patches/dwm-bartoggle-keybinds-6.4.diff @@ -0,0 +1,214 @@ +# This patch adds keybinds to toggle each part of the dwm bar. This include the title, tags, layout indicator, status and floating indicator. +# It also allows you to show/hide parts by default, similar to showbar. +# +# There is also a version without keybinds if you don't want keybinds, see the dwm-bartoggle-6.4.diff patch. + +diff -up a/config.def.h b/config.def.h +--- a/config.def.h 2022-10-04 19:38:18.000000000 +0200 ++++ b/config.def.h 2022-10-22 14:40:36.113933644 +0200 +@@ -4,6 +4,11 @@ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ ++static const int showtitle = 1; /* 0 means no title */ ++static const int showtags = 1; /* 0 means no tags */ ++static const int showlayout = 1; /* 0 means no layout indicator */ ++static const int showstatus = 1; /* 0 means no status bar */ ++static const int showfloating = 1; /* 0 means no floating indicator */ + static const int topbar = 1; /* 0 means bottom bar */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; +@@ -78,6 +83,11 @@ static const Key keys[] = { + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, ++ { MODKEY, XK_t, togglebartitle, {0} }, ++ { MODKEY, XK_s, togglebarstatus,{0} }, ++ { MODKEY|ShiftMask, XK_t, togglebartags, {0} }, ++ { MODKEY|ShiftMask, XK_s, togglebarlt, {0} }, ++ { MODKEY|ShiftMask, XK_f, togglebarfloat, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, +diff -up a/dwm.c b/dwm.c +--- a/dwm.c 2022-10-04 19:38:18.000000000 +0200 ++++ b/dwm.c 2022-10-22 14:41:29.903932288 +0200 +@@ -123,6 +123,11 @@ struct Monitor { + unsigned int sellt; + unsigned int tagset[2]; + int showbar; ++ int showtitle; ++ int showtags; ++ int showlayout; ++ int showstatus; ++ int showfloating; + int topbar; + Client *clients; + Client *sel; +@@ -211,6 +216,11 @@ static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglebar(const Arg *arg); ++static void togglebartags(const Arg *arg); ++static void togglebartitle(const Arg *arg); ++static void togglebarlt(const Arg *arg); ++static void togglebarstatus(const Arg *arg); ++static void togglebarfloat(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); +@@ -435,16 +445,17 @@ buttonpress(XEvent *e) + if (ev->window == selmon->barwin) { + i = x = 0; + do +- x += TEXTW(tags[i]); ++ if (selmon->showtags) ++ x += TEXTW(tags[i]); + while (ev->x >= x && ++i < LENGTH(tags)); +- if (i < LENGTH(tags)) { ++ if (i < LENGTH(tags) && selmon->showtags) { + click = ClkTagBar; + arg.ui = 1 << i; +- } else if (ev->x < x + TEXTW(selmon->ltsymbol)) ++ } else if (ev->x < x + TEXTW(selmon->ltsymbol) && selmon->showlayout) + click = ClkLtSymbol; +- else if (ev->x > selmon->ww - (int)TEXTW(stext)) ++ else if (ev->x > selmon->ww - (int)TEXTW(stext) && selmon->showstatus) + click = ClkStatusText; +- else ++ else if (selmon->showtitle) + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); +@@ -641,6 +652,11 @@ createmon(void) + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; ++ m->showtitle = showtitle; ++ m->showtags = showtags; ++ m->showlayout = showlayout; ++ m->showstatus = showstatus; ++ m->showfloating = showfloating; + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; +@@ -709,7 +725,7 @@ drawbar(Monitor *m) + return; + + /* draw status first so it can be overdrawn by tags later */ +- if (m == selmon) { /* status is only drawn on selected monitor */ ++ if (m == selmon && selmon->showstatus) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); +@@ -717,29 +733,35 @@ drawbar(Monitor *m) + + for (c = m->clients; c; c = c->next) { + occ |= c->tags; +- if (c->isurgent) ++ if (c->isurgent && selmon->showtags) + urg |= c->tags; + } + x = 0; + for (i = 0; i < LENGTH(tags); i++) { +- w = TEXTW(tags[i]); +- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); +- drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); +- if (occ & 1 << i) +- drw_rect(drw, x + boxs, boxs, boxw, boxw, +- m == selmon && selmon->sel && selmon->sel->tags & 1 << i, +- urg & 1 << i); +- x += w; +- } +- w = TEXTW(m->ltsymbol); +- drw_setscheme(drw, scheme[SchemeNorm]); +- x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); ++ if (selmon->showtags) { ++ w = TEXTW(tags[i]); ++ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); ++ drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); ++ if (occ & 1 << i && selmon->showfloating) ++ drw_rect(drw, x + boxs, boxs, boxw, boxw, ++ m == selmon && selmon->sel && selmon->sel->tags & 1 << i, ++ urg & 1 << i); ++ x += w; ++ } ++ } ++ ++ /* draw layout indicator if selmon->showlayout */ ++ if (selmon->showlayout) { ++ w = TEXTW(m->ltsymbol); ++ drw_setscheme(drw, scheme[SchemeNorm]); ++ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); ++ } + + if ((w = m->ww - tw - x) > bh) { +- if (m->sel) { ++ if (m->sel && selmon->showtitle) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); +- if (m->sel->isfloating) ++ if (m->sel->isfloating && selmon->showfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { + drw_setscheme(drw, scheme[SchemeNorm]); +@@ -1238,7 +1260,7 @@ propertynotify(XEvent *e) + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); +- if (c == c->mon->sel) ++ if (c == c->mon->sel && selmon->showtitle) + drawbar(c->mon); + } + if (ev->atom == netatom[NetWMWindowType]) +@@ -1704,6 +1726,41 @@ togglebar(const Arg *arg) + } + + void ++togglebartags(const Arg *arg) ++{ ++ selmon->showtags = !selmon->showtags; ++ arrange(selmon); ++} ++ ++void ++togglebartitle(const Arg *arg) ++{ ++ selmon->showtitle = !selmon->showtitle; ++ arrange(selmon); ++} ++ ++void ++togglebarlt(const Arg *arg) ++{ ++ selmon->showlayout = !selmon->showlayout; ++ arrange(selmon); ++} ++ ++void ++togglebarstatus(const Arg *arg) ++{ ++ selmon->showstatus = !selmon->showstatus; ++ arrange(selmon); ++} ++ ++void ++togglebarfloat(const Arg *arg) ++{ ++ selmon->showfloating = !selmon->showfloating; ++ arrange(selmon); ++} ++ ++void + togglefloating(const Arg *arg) + { + if (!selmon->sel) +@@ -1987,7 +2044,7 @@ updatesizehints(Client *c) + void + updatestatus(void) + { +- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) ++ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)) && selmon->showstatus) + strcpy(stext, "dwm-"VERSION); + drawbar(selmon); + } diff --git a/dwm/patches/dwm-borderrule-20231226-e7f651b.diff b/dwm/patches/dwm-borderrule-20231226-e7f651b.diff new file mode 100644 index 0000000..6426ba5 --- /dev/null +++ b/dwm/patches/dwm-borderrule-20231226-e7f651b.diff @@ -0,0 +1,66 @@ +# From e7f651b1321747fb92521522f0aa07a01160d4af Mon Sep 17 00:00:00 2001 +# From: Jasper Shovelton <Beanie.github@proton.me> +# Date: Tue, 26 Dec 2023 12:57:35 +0000 +# Subject: [PATCH] Add a `borderpx` value to `rules` in `config.def.h`. +# +# --- +# config.def.h | 6 +++--- +# dwm.c | 5 ++++- +# 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..bdddfa5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -26,9 +26,9 @@ static const Rule rules[] = { + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ /* class instance title tags mask isfloating monitor border width */ ++ { "Gimp", NULL, NULL, 0, 1, -1, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, 0, -1, 0 }, + }; + + /* layout(s) */ +diff --git a/dwm.c b/dwm.c +index f1d86b2..48403c2 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -139,6 +139,7 @@ typedef struct { + unsigned int tags; + int isfloating; + int monitor; ++ int bw; + } Rule; + + /* function declarations */ +@@ -287,6 +288,7 @@ applyrules(Client *c) + /* rule matching */ + c->isfloating = 0; + c->tags = 0; ++ c->bw = borderpx; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; +@@ -299,6 +301,8 @@ applyrules(Client *c) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; ++ if (r->bw != -1) ++ c->bw = r->bw; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; +@@ -1059,7 +1063,6 @@ manage(Window w, XWindowAttributes *wa) + c->y = c->mon->wy + c->mon->wh - HEIGHT(c); + c->x = MAX(c->x, c->mon->wx); + c->y = MAX(c->y, c->mon->wy); +- c->bw = borderpx; + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); +-- +2.43.0 diff --git a/dwm/patches/dwm-bulkill-20231029-9f88553.diff b/dwm/patches/dwm-bulkill-20231029-9f88553.diff new file mode 100644 index 0000000..d4e6bc9 --- /dev/null +++ b/dwm/patches/dwm-bulkill-20231029-9f88553.diff @@ -0,0 +1,85 @@ +# From 70a21457fdbcbcdf26efb1329dd29872b7fcd8e3 Mon Sep 17 00:00:00 2001 +# From: ysl2 <www.songli.yu@gmail.com> +# Date: Sun, 29 Oct 2023 15:45:05 +0800 +# Subject: [PATCH] Give killclient an augument to control the beheviour: arg.ui +# == 0 for normal kill current client; arg.ui == 1 for kill other clients in +# current tag (except current focusing client); arg.ui == 2 for kill all +# clients in current tag (include focusing client). +# +# --- +# config.def.h | 2 ++ +# dwm.c | 30 ++++++++++++++++++++++++------ +# 2 files changed, 26 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..d39e6dd 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -74,6 +74,8 @@ static const Key keys[] = { + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, ++ { MODKEY|ControlMask, XK_c, killclient, {.ui = 1} }, // kill unselect ++ { MODKEY|ShiftMask|ControlMask, XK_c, killclient, {.ui = 2} }, // killall + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, +diff --git a/dwm.c b/dwm.c +index f1d86b2..011744d 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -177,6 +177,7 @@ static void grabbuttons(Client *c, int focused); + static void grabkeys(void); + static void incnmaster(const Arg *arg); + static void keypress(XEvent *e); ++static void killthis(Client *c); + static void killclient(const Arg *arg); + static void manage(Window w, XWindowAttributes *wa); + static void mappingnotify(XEvent *e); +@@ -1013,21 +1014,38 @@ keypress(XEvent *e) + } + + void +-killclient(const Arg *arg) +-{ +- if (!selmon->sel) +- return; +- if (!sendevent(selmon->sel, wmatom[WMDelete])) { ++killthis(Client *c) { ++ if (!sendevent(c, wmatom[WMDelete])) { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); +- XKillClient(dpy, selmon->sel->win); ++ XKillClient(dpy, c->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + } + ++void ++killclient(const Arg *arg) ++{ ++ Client *c; ++ ++ if (!selmon->sel) ++ return; ++ ++ if (!arg->ui || arg->ui == 0) { ++ killthis(selmon->sel); ++ return; ++ } ++ ++ for (c = selmon->clients; c; c = c->next) { ++ if (!ISVISIBLE(c) || (arg->ui == 1 && c == selmon->sel)) ++ continue; ++ killthis(c); ++ } ++} ++ + void + manage(Window w, XWindowAttributes *wa) + { +-- +2.20.1 diff --git a/dwm/patches/dwm-canfocusfloating-20210724-b914109.diff b/dwm/patches/dwm-canfocusfloating-20210724-b914109.diff new file mode 100644 index 0000000..851e4ed --- /dev/null +++ b/dwm/patches/dwm-canfocusfloating-20210724-b914109.diff @@ -0,0 +1,144 @@ +# From b9141091994ba657af534453ab913663a8258f9a Mon Sep 17 00:00:00 2001 +# From: oxinosg <georgios.oxinos.extern@elinvar.de> +# Date: Sat, 24 Jul 2021 23:31:30 +0200 +# Subject: [PATCH] [dwm][cantogglefloating] patch that allows disabling focus on +# floating clients +# +# --- +# config.def.h | 1 + +# dwm.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++---- +# 2 files changed, 63 insertions(+), 5 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..005fb5d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -70,6 +70,7 @@ static Key keys[] = { + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, ++ { MODKEY, XK_s, togglecanfocusfloating, {0} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, +diff --git a/dwm.c b/dwm.c +index 4465af1..ae0a0ea 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -92,7 +92,7 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; +- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, cantfocus; + Client *next; + Client *snext; + Monitor *mon; +@@ -191,6 +191,7 @@ static Monitor *recttomon(int x, int y, int w, int h); + static void resize(Client *c, int x, int y, int w, int h, int interact); + static void resizeclient(Client *c, int x, int y, int w, int h); + static void resizemouse(const Arg *arg); ++static void resetcanfocusfloating(); + static void restack(Monitor *m); + static void run(void); + static void scan(void); +@@ -211,6 +212,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void togglecanfocusfloating(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); +@@ -788,6 +790,8 @@ focus(Client *c) + if (selmon->sel && selmon->sel != c) + unfocus(selmon->sel, 0); + if (c) { ++ if (c->cantfocus) ++ return; + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) +@@ -837,16 +841,16 @@ focusstack(const Arg *arg) + if (!selmon->sel) + return; + if (arg->i > 0) { +- for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); ++ for (c = selmon->sel->next; c && (!ISVISIBLE(c) || c->cantfocus); c = c->next); + if (!c) +- for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); ++ for (c = selmon->clients; c && (!ISVISIBLE(c) || c->cantfocus); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) +- if (ISVISIBLE(i)) ++ if (ISVISIBLE(i) && !i->cantfocus) + c = i; + if (!c) + for (; i; i = i->next) +- if (ISVISIBLE(i)) ++ if (ISVISIBLE(i) && !i->cantfocus) + c = i; + } + if (c) { +@@ -1716,6 +1720,59 @@ togglefloating(const Arg *arg) + if (selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, 0); ++ ++ resetcanfocusfloating(); ++ ++ arrange(selmon); ++} ++ ++void ++resetcanfocusfloating() ++{ ++ unsigned int i, n; ++ Client *c; ++ ++ for (n = 0, c = selmon->clients; c; c = c->next, n++); ++ if (n == 0) ++ return; ++ ++ for (i = 0, c = selmon->clients; c; c = c->next, i++) ++ if (c->isfloating) ++ c->cantfocus = 0; ++ ++ arrange(selmon); ++} ++ ++void ++togglecanfocusfloating(const Arg *arg) ++{ ++ unsigned int n; ++ Client *c, *cf = NULL; ++ ++ if (!selmon->sel) ++ return; ++ ++ for (c = selmon->clients; c; c = c->next) ++ if (c->cantfocus == 1) { ++ cf = c; ++ } ++ ++ if (cf) { ++ resetcanfocusfloating(); ++ focus(cf); ++ } else { ++ for (n = 0, c = selmon->clients; c; c = c->next) ++ if (c->isfloating) ++ c->cantfocus = !c->cantfocus; ++ else ++ n++; ++ ++ if (n && selmon->sel->isfloating) { ++ c = nexttiled(selmon->clients); ++ focus(c); ++ } ++ } ++ + arrange(selmon); + } + +-- +2.27.0 diff --git a/dwm/patches/dwm-cfacts-vanitygaps-6.4_combo.diff b/dwm/patches/dwm-cfacts-vanitygaps-6.4_combo.diff new file mode 100644 index 0000000..371fce0 --- /dev/null +++ b/dwm/patches/dwm-cfacts-vanitygaps-6.4_combo.diff @@ -0,0 +1,1018 @@ +diff --git a/config.def.h b/config.def.h +index 9efa774..357dc6f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,6 +3,11 @@ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ ++static const unsigned int gappih = 20; /* horiz inner gap between windows */ ++static const unsigned int gappiv = 10; /* vert inner gap between windows */ ++static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ ++static const unsigned int gappov = 30; /* vert outer gap between windows and screen edge */ ++static int smartgaps = 0; /* 1 means no outer gap when there is only one window */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ + static const char *fonts[] = { "monospace:size=10" }; +@@ -37,11 +42,26 @@ static const int nmaster = 1; /* number of clients in master area */ + static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ + static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + ++#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */ ++#include "vanitygaps.c" ++ + static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ +- { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "[@]", spiral }, ++ { "[\\]", dwindle }, ++ { "H[]", deck }, ++ { "TTT", bstack }, ++ { "===", bstackhoriz }, ++ { "HHH", grid }, ++ { "###", nrowgrid }, ++ { "---", horizgrid }, ++ { ":::", gaplessgrid }, ++ { "|M|", centeredmaster }, ++ { ">M>", centeredfloatingmaster }, ++ { "><>", NULL }, /* no layout function means floating behavior */ ++ { NULL, NULL }, + }; + + /* key definitions */ +@@ -71,7 +91,26 @@ static const Key keys[] = { + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, ++ { MODKEY|ShiftMask, XK_h, setcfact, {.f = +0.25} }, ++ { MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} }, ++ { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} }, + { MODKEY, XK_Return, zoom, {0} }, ++ { MODKEY|Mod4Mask, XK_u, incrgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_i, incrigaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_o, incrogaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_6, incrihgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_7, incrivgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_8, incrohgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_9, incrovgaps, {.i = +1 } }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } }, ++ { MODKEY|Mod4Mask, XK_0, togglegaps, {0} }, ++ { MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, +diff --git a/dwm.c b/dwm.c +index f1d86b2..5bbd733 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -87,6 +87,7 @@ typedef struct Client Client; + struct Client { + char name[256]; + float mina, maxa; ++ float cfact; + int x, y, w, h; + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; +@@ -119,6 +120,10 @@ struct Monitor { + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ ++ int gappih; /* horizontal gap between windows */ ++ int gappiv; /* vertical gap between windows */ ++ int gappoh; /* horizontal outer gaps */ ++ int gappov; /* vertical outer gaps */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; +@@ -201,6 +206,7 @@ static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); + static void setlayout(const Arg *arg); ++static void setcfact(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); + static void seturgent(Client *c, int urg); +@@ -208,7 +214,6 @@ static void showhide(Client *c); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +-static void tile(Monitor *m); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -641,6 +646,10 @@ createmon(void) + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; ++ m->gappih = gappih; ++ m->gappiv = gappiv; ++ m->gappoh = gappoh; ++ m->gappov = gappov; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); +@@ -1043,6 +1052,7 @@ manage(Window w, XWindowAttributes *wa) + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; ++ c->cfact = 1.0; + + updatetitle(c); + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { +@@ -1521,6 +1531,24 @@ setlayout(const Arg *arg) + drawbar(selmon); + } + ++void ++setcfact(const Arg *arg) { ++ float f; ++ Client *c; ++ ++ c = selmon->sel; ++ ++ if(!arg || !c || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ f = arg->f + c->cfact; ++ if(arg->f == 0.0) ++ f = 1.0; ++ else if(f < 0.25 || f > 4.0) ++ return; ++ c->cfact = f; ++ arrange(selmon); ++} ++ + /* arg > 1.0 will set mfact absolutely */ + void + setmfact(const Arg *arg) +@@ -1684,34 +1712,6 @@ tagmon(const Arg *arg) + sendmon(selmon->sel, dirtomon(arg->i)); + } + +-void +-tile(Monitor *m) +-{ +- unsigned int i, n, h, mw, my, ty; +- Client *c; +- +- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +- if (n == 0) +- return; +- +- if (n > m->nmaster) +- mw = m->nmaster ? m->ww * m->mfact : 0; +- else +- mw = m->ww; +- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) +- if (i < m->nmaster) { +- h = (m->wh - my) / (MIN(n, m->nmaster) - i); +- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); +- if (my + HEIGHT(c) < m->wh) +- my += HEIGHT(c); +- } else { +- h = (m->wh - ty) / (n - i); +- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); +- if (ty + HEIGHT(c) < m->wh) +- ty += HEIGHT(c); +- } +-} +- + void + togglebar(const Arg *arg) + { +diff --git a/vanitygaps.c b/vanitygaps.c +new file mode 100644 +index 0000000..1a816b6 +--- /dev/null ++++ b/vanitygaps.c +@@ -0,0 +1,822 @@ ++/* Key binding functions */ ++static void defaultgaps(const Arg *arg); ++static void incrgaps(const Arg *arg); ++static void incrigaps(const Arg *arg); ++static void incrogaps(const Arg *arg); ++static void incrohgaps(const Arg *arg); ++static void incrovgaps(const Arg *arg); ++static void incrihgaps(const Arg *arg); ++static void incrivgaps(const Arg *arg); ++static void togglegaps(const Arg *arg); ++/* Layouts (delete the ones you do not need) */ ++static void bstack(Monitor *m); ++static void bstackhoriz(Monitor *m); ++static void centeredmaster(Monitor *m); ++static void centeredfloatingmaster(Monitor *m); ++static void deck(Monitor *m); ++static void dwindle(Monitor *m); ++static void fibonacci(Monitor *m, int s); ++static void grid(Monitor *m); ++static void nrowgrid(Monitor *m); ++static void spiral(Monitor *m); ++static void tile(Monitor *m); ++/* Internals */ ++static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc); ++static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr); ++static void setgaps(int oh, int ov, int ih, int iv); ++ ++/* Settings */ ++#if !PERTAG_PATCH ++static int enablegaps = 1; ++#endif // PERTAG_PATCH ++ ++void ++setgaps(int oh, int ov, int ih, int iv) ++{ ++ if (oh < 0) oh = 0; ++ if (ov < 0) ov = 0; ++ if (ih < 0) ih = 0; ++ if (iv < 0) iv = 0; ++ ++ selmon->gappoh = oh; ++ selmon->gappov = ov; ++ selmon->gappih = ih; ++ selmon->gappiv = iv; ++ arrange(selmon); ++} ++ ++void ++togglegaps(const Arg *arg) ++{ ++ #if PERTAG_PATCH ++ selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag]; ++ #else ++ enablegaps = !enablegaps; ++ #endif // PERTAG_PATCH ++ arrange(NULL); ++} ++ ++void ++defaultgaps(const Arg *arg) ++{ ++ setgaps(gappoh, gappov, gappih, gappiv); ++} ++ ++void ++incrgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incrigaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++incrogaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incrohgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh + arg->i, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incrovgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov + arg->i, ++ selmon->gappih, ++ selmon->gappiv ++ ); ++} ++ ++void ++incrihgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih + arg->i, ++ selmon->gappiv ++ ); ++} ++ ++void ++incrivgaps(const Arg *arg) ++{ ++ setgaps( ++ selmon->gappoh, ++ selmon->gappov, ++ selmon->gappih, ++ selmon->gappiv + arg->i ++ ); ++} ++ ++void ++getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc) ++{ ++ unsigned int n, oe, ie; ++ #if PERTAG_PATCH ++ oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag]; ++ #else ++ oe = ie = enablegaps; ++ #endif // PERTAG_PATCH ++ Client *c; ++ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ if (smartgaps && n == 1) { ++ oe = 0; // outer gaps disabled when only one client ++ } ++ ++ *oh = m->gappoh*oe; // outer horizontal gap ++ *ov = m->gappov*oe; // outer vertical gap ++ *ih = m->gappih*ie; // inner horizontal gap ++ *iv = m->gappiv*ie; // inner vertical gap ++ *nc = n; // number of clients ++} ++ ++void ++getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) ++{ ++ unsigned int n; ++ float mfacts = 0, sfacts = 0; ++ int mtotal = 0, stotal = 0; ++ Client *c; ++ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) ++ if (n < m->nmaster) ++ mfacts += c->cfact; ++ else ++ sfacts += c->cfact; ++ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) ++ if (n < m->nmaster) ++ mtotal += msize * (c->cfact / mfacts); ++ else ++ stotal += ssize * (c->cfact / sfacts); ++ ++ *mf = mfacts; // total factor of master area ++ *sf = sfacts; // total factor of stack area ++ *mr = msize - mtotal; // the remainder (rest) of pixels after a cfacts master split ++ *sr = ssize - stotal; // the remainder (rest) of pixels after a cfacts stack split ++} ++ ++/*** ++ * Layouts ++ */ ++ ++/* ++ * Bottomstack layout + gaps ++ * https://dwm.suckless.org/patches/bottomstack/ ++ */ ++static void ++bstack(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ float mfacts, sfacts; ++ int mrest, srest; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ sh = mh = m->wh - 2*oh; ++ mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); ++ sw = m->ww - 2*ov - iv * (n - m->nmaster - 1); ++ ++ if (m->nmaster && n > m->nmaster) { ++ sh = (mh - ih) * (1 - m->mfact); ++ mh = mh - ih - sh; ++ sx = mx; ++ sy = my + mh + ih; ++ } ++ ++ getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i < m->nmaster) { ++ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); ++ mx += WIDTH(c) + iv; ++ } else { ++ resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); ++ sx += WIDTH(c) + iv; ++ } ++ } ++} ++ ++static void ++bstackhoriz(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ float mfacts, sfacts; ++ int mrest, srest; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ mh = m->wh - 2*oh; ++ sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); ++ mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); ++ sw = m->ww - 2*ov; ++ ++ if (m->nmaster && n > m->nmaster) { ++ sh = (mh - ih) * (1 - m->mfact); ++ mh = mh - ih - sh; ++ sy = my + mh + ih; ++ sh = m->wh - mh - 2*oh - ih * (n - m->nmaster); ++ } ++ ++ getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i < m->nmaster) { ++ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); ++ mx += WIDTH(c) + iv; ++ } else { ++ resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); ++ sy += HEIGHT(c) + ih; ++ } ++ } ++} ++ ++/* ++ * Centred master layout + gaps ++ * https://dwm.suckless.org/patches/centeredmaster/ ++ */ ++void ++centeredmaster(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int lx = 0, ly = 0, lw = 0, lh = 0; ++ int rx = 0, ry = 0, rw = 0, rh = 0; ++ float mfacts = 0, lfacts = 0, rfacts = 0; ++ int mtotal = 0, ltotal = 0, rtotal = 0; ++ int mrest = 0, lrest = 0, rrest = 0; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ /* initialize areas */ ++ mx = m->wx + ov; ++ my = m->wy + oh; ++ mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1); ++ mw = m->ww - 2*ov; ++ lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1); ++ rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1)); ++ ++ if (m->nmaster && n > m->nmaster) { ++ /* go mfact box in the center if more than nmaster clients */ ++ if (n - m->nmaster > 1) { ++ /* ||<-S->|<---M--->|<-S->|| */ ++ mw = (m->ww - 2*ov - 2*iv) * m->mfact; ++ lw = (m->ww - mw - 2*ov - 2*iv) / 2; ++ rw = (m->ww - mw - 2*ov - 2*iv) - lw; ++ mx += lw + iv; ++ } else { ++ /* ||<---M--->|<-S->|| */ ++ mw = (mw - iv) * m->mfact; ++ lw = 0; ++ rw = m->ww - mw - iv - 2*ov; ++ } ++ lx = m->wx + ov; ++ ly = m->wy + oh; ++ rx = mx + mw + iv; ++ ry = m->wy + oh; ++ } ++ ++ /* calculate facts */ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { ++ if (!m->nmaster || n < m->nmaster) ++ mfacts += c->cfact; ++ else if ((n - m->nmaster) % 2) ++ lfacts += c->cfact; // total factor of left hand stack area ++ else ++ rfacts += c->cfact; // total factor of right hand stack area ++ } ++ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) ++ if (!m->nmaster || n < m->nmaster) ++ mtotal += mh * (c->cfact / mfacts); ++ else if ((n - m->nmaster) % 2) ++ ltotal += lh * (c->cfact / lfacts); ++ else ++ rtotal += rh * (c->cfact / rfacts); ++ ++ mrest = mh - mtotal; ++ lrest = lh - ltotal; ++ rrest = rh - rtotal; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (!m->nmaster || i < m->nmaster) { ++ /* nmaster clients are stacked vertically, in the center of the screen */ ++ resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); ++ my += HEIGHT(c) + ih; ++ } else { ++ /* stack clients are stacked vertically */ ++ if ((i - m->nmaster) % 2 ) { ++ resize(c, lx, ly, lw - (2*c->bw), lh * (c->cfact / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0); ++ ly += HEIGHT(c) + ih; ++ } else { ++ resize(c, rx, ry, rw - (2*c->bw), rh * (c->cfact / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0); ++ ry += HEIGHT(c) + ih; ++ } ++ } ++ } ++} ++ ++void ++centeredfloatingmaster(Monitor *m) ++{ ++ unsigned int i, n; ++ float mfacts, sfacts; ++ float mivf = 1.0; // master inner vertical gap factor ++ int oh, ov, ih, iv, mrest, srest; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ sh = mh = m->wh - 2*oh; ++ mw = m->ww - 2*ov - iv*(n - 1); ++ sw = m->ww - 2*ov - iv*(n - m->nmaster - 1); ++ ++ if (m->nmaster && n > m->nmaster) { ++ mivf = 0.8; ++ /* go mfact box in the center if more than nmaster clients */ ++ if (m->ww > m->wh) { ++ mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1); ++ mh = m->wh * 0.9; ++ } else { ++ mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1); ++ mh = m->wh * m->mfact; ++ } ++ mx = m->wx + (m->ww - mw) / 2; ++ my = m->wy + (m->wh - mh - 2*oh) / 2; ++ ++ sx = m->wx + ov; ++ sy = m->wy + oh; ++ sh = m->wh - 2*oh; ++ } ++ ++ getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ /* nmaster clients are stacked horizontally, in the center of the screen */ ++ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); ++ mx += WIDTH(c) + iv*mivf; ++ } else { ++ /* stack clients are stacked horizontally */ ++ resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); ++ sx += WIDTH(c) + iv; ++ } ++} ++ ++/* ++ * Deck layout + gaps ++ * https://dwm.suckless.org/patches/deck/ ++ */ ++void ++deck(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ float mfacts, sfacts; ++ int mrest, srest; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); ++ sw = mw = m->ww - 2*ov; ++ ++ if (m->nmaster && n > m->nmaster) { ++ sw = (mw - iv) * (1 - m->mfact); ++ mw = mw - iv - sw; ++ sx = mx + mw + iv; ++ sh = m->wh - 2*oh; ++ } ++ ++ getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); ++ ++ if (n - m->nmaster > 0) /* override layout symbol */ ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); ++ my += HEIGHT(c) + ih; ++ } else { ++ resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0); ++ } ++} ++ ++/* ++ * Fibonacci layout + gaps ++ * https://dwm.suckless.org/patches/fibonacci/ ++ */ ++void ++fibonacci(Monitor *m, int s) ++{ ++ unsigned int i, n; ++ int nx, ny, nw, nh; ++ int oh, ov, ih, iv; ++ int nv, hrest = 0, wrest = 0, r = 1; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ nx = m->wx + ov; ++ ny = m->wy + oh; ++ nw = m->ww - 2*ov; ++ nh = m->wh - 2*oh; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { ++ if (r) { ++ if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw)) ++ || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) { ++ r = 0; ++ } ++ if (r && i < n - 1) { ++ if (i % 2) { ++ nv = (nh - ih) / 2; ++ hrest = nh - 2*nv - ih; ++ nh = nv; ++ } else { ++ nv = (nw - iv) / 2; ++ wrest = nw - 2*nv - iv; ++ nw = nv; ++ } ++ ++ if ((i % 4) == 2 && !s) ++ nx += nw + iv; ++ else if ((i % 4) == 3 && !s) ++ ny += nh + ih; ++ } ++ ++ if ((i % 4) == 0) { ++ if (s) { ++ ny += nh + ih; ++ nh += hrest; ++ } ++ else { ++ nh -= hrest; ++ ny -= nh + ih; ++ } ++ } ++ else if ((i % 4) == 1) { ++ nx += nw + iv; ++ nw += wrest; ++ } ++ else if ((i % 4) == 2) { ++ ny += nh + ih; ++ nh += hrest; ++ if (i < n - 1) ++ nw += wrest; ++ } ++ else if ((i % 4) == 3) { ++ if (s) { ++ nx += nw + iv; ++ nw -= wrest; ++ } else { ++ nw -= wrest; ++ nx -= nw + iv; ++ nh += hrest; ++ } ++ } ++ if (i == 0) { ++ if (n != 1) { ++ nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact); ++ wrest = 0; ++ } ++ ny = m->wy + oh; ++ } ++ else if (i == 1) ++ nw = m->ww - nw - iv - 2*ov; ++ i++; ++ } ++ ++ resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False); ++ } ++} ++ ++void ++dwindle(Monitor *m) ++{ ++ fibonacci(m, 1); ++} ++ ++void ++spiral(Monitor *m) ++{ ++ fibonacci(m, 0); ++} ++ ++/* ++ * Gappless grid layout + gaps (ironically) ++ * https://dwm.suckless.org/patches/gaplessgrid/ ++ */ ++void ++gaplessgrid(Monitor *m) ++{ ++ unsigned int i, n; ++ int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters ++ int oh, ov, ih, iv; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ /* grid dimensions */ ++ for (cols = 0; cols <= n/2; cols++) ++ if (cols*cols >= n) ++ break; ++ if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ ++ cols = 2; ++ rows = n/cols; ++ cn = rn = 0; // reset column no, row no, client count ++ ++ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows; ++ cw = (m->ww - 2*ov - iv * (cols - 1)) / cols; ++ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; ++ crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols; ++ x = m->wx + ov; ++ y = m->wy + oh; ++ ++ for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) { ++ if (i/rows + 1 > cols - n%cols) { ++ rows = n/cols + 1; ++ ch = (m->wh - 2*oh - ih * (rows - 1)) / rows; ++ rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; ++ } ++ resize(c, ++ x, ++ y + rn*(ch + ih) + MIN(rn, rrest), ++ cw + (cn < crest ? 1 : 0) - 2*c->bw, ++ ch + (rn < rrest ? 1 : 0) - 2*c->bw, ++ 0); ++ rn++; ++ if (rn >= rows) { ++ rn = 0; ++ x += cw + ih + (cn < crest ? 1 : 0); ++ cn++; ++ } ++ } ++} ++ ++/* ++ * Gridmode layout + gaps ++ * https://dwm.suckless.org/patches/gridmode/ ++ */ ++void ++grid(Monitor *m) ++{ ++ unsigned int i, n; ++ int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows; ++ int oh, ov, ih, iv; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ ++ /* grid dimensions */ ++ for (rows = 0; rows <= n/2; rows++) ++ if (rows*rows >= n) ++ break; ++ cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; ++ ++ /* window geoms (cell height/width) */ ++ ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1); ++ cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1); ++ chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; ++ cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols; ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ cc = i / rows; ++ cr = i % rows; ++ cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest); ++ cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest); ++ resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False); ++ } ++} ++ ++/* ++ * Horizontal grid layout + gaps ++ * https://dwm.suckless.org/patches/horizgrid/ ++ */ ++void ++horizgrid(Monitor *m) { ++ Client *c; ++ unsigned int n, i; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ int ntop, nbottom = 1; ++ float mfacts = 0, sfacts = 0; ++ int mrest, srest, mtotal = 0, stotal = 0; ++ ++ /* Count windows */ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ if (n <= 2) ++ ntop = n; ++ else { ++ ntop = n / 2; ++ nbottom = n - ntop; ++ } ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ sh = mh = m->wh - 2*oh; ++ sw = mw = m->ww - 2*ov; ++ ++ if (n > ntop) { ++ sh = (mh - ih) / 2; ++ mh = mh - ih - sh; ++ sy = my + mh + ih; ++ mw = m->ww - 2*ov - iv * (ntop - 1); ++ sw = m->ww - 2*ov - iv * (nbottom - 1); ++ } ++ ++ /* calculate facts */ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < ntop) ++ mfacts += c->cfact; ++ else ++ sfacts += c->cfact; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < ntop) ++ mtotal += mh * (c->cfact / mfacts); ++ else ++ stotal += sw * (c->cfact / sfacts); ++ ++ mrest = mh - mtotal; ++ srest = sw - stotal; ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < ntop) { ++ resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); ++ mx += WIDTH(c) + iv; ++ } else { ++ resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); ++ sx += WIDTH(c) + iv; ++ } ++} ++ ++/* ++ * nrowgrid layout + gaps ++ * https://dwm.suckless.org/patches/nrowgrid/ ++ */ ++void ++nrowgrid(Monitor *m) ++{ ++ unsigned int n; ++ int ri = 0, ci = 0; /* counters */ ++ int oh, ov, ih, iv; /* vanitygap settings */ ++ unsigned int cx, cy, cw, ch; /* client geometry */ ++ unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */ ++ unsigned int cols, rows = m->nmaster + 1; ++ Client *c; ++ ++ /* count clients */ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ ++ /* nothing to do here */ ++ if (n == 0) ++ return; ++ ++ /* force 2 clients to always split vertically */ ++ if (FORCE_VSPLIT && n == 2) ++ rows = 1; ++ ++ /* never allow empty rows */ ++ if (n < rows) ++ rows = n; ++ ++ /* define first row */ ++ cols = n / rows; ++ uc = cols; ++ cy = m->wy + oh; ++ ch = (m->wh - 2*oh - ih*(rows - 1)) / rows; ++ uh = ch; ++ ++ for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) { ++ if (ci == cols) { ++ uw = 0; ++ ci = 0; ++ ri++; ++ ++ /* next row */ ++ cols = (n - uc) / (rows - ri); ++ uc += cols; ++ cy = m->wy + oh + uh + ih; ++ uh += ch + ih; ++ } ++ ++ cx = m->wx + ov + uw; ++ cw = (m->ww - 2*ov - uw) / (cols - ci); ++ uw += cw + iv; ++ ++ resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0); ++ } ++} ++ ++/* ++ * Default tile layout + gaps ++ */ ++static void ++tile(Monitor *m) ++{ ++ unsigned int i, n; ++ int oh, ov, ih, iv; ++ int mx = 0, my = 0, mh = 0, mw = 0; ++ int sx = 0, sy = 0, sh = 0, sw = 0; ++ float mfacts, sfacts; ++ int mrest, srest; ++ Client *c; ++ ++ getgaps(m, &oh, &ov, &ih, &iv, &n); ++ if (n == 0) ++ return; ++ ++ sx = mx = m->wx + ov; ++ sy = my = m->wy + oh; ++ mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); ++ sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); ++ sw = mw = m->ww - 2*ov; ++ ++ if (m->nmaster && n > m->nmaster) { ++ sw = (mw - iv) * (1 - m->mfact); ++ mw = mw - iv - sw; ++ sx = mx + mw + iv; ++ } ++ ++ getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); ++ ++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) ++ if (i < m->nmaster) { ++ resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); ++ my += HEIGHT(c) + ih; ++ } else { ++ resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); ++ sy += HEIGHT(c) + ih; ++ } ++} +\ No newline at end of file diff --git a/dwm/patches/dwm-clientopacity-6.4.diff b/dwm/patches/dwm-clientopacity-6.4.diff new file mode 100644 index 0000000..4564e08 --- /dev/null +++ b/dwm/patches/dwm-clientopacity-6.4.diff @@ -0,0 +1,274 @@ +# From 10dd5df95f551d81d0a814dcdb2bde20e405fb91 Mon Sep 17 00:00:00 2001 +# From: sympodius <mail@sympodius.net> +# Date: Mon, 13 Mar 2023 16:28:16 +0000 +# Subject: [PATCH] [dwm][patch][clientopacity] Adds opacity on a per client +# basis +# +# --- +# config.def.h | 80 ++++++++++++++++++++++++++++------------------------ +# dwm.c | 61 ++++++++++++++++++++++++++++++++++++++- +# 2 files changed, 103 insertions(+), 38 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..9ca812d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -5,6 +5,8 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const double activeopacity = 0.9f; /* Window opacity when it's focused (0 <= opacity <= 1) */ ++static const double inactiveopacity = 0.7f; /* Window opacity when it's inactive (0 <= opacity <= 1) */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +@@ -26,9 +28,9 @@ static const Rule rules[] = { + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ /* class instance title tags mask isfloating focusopacity unfocusopacity monitor */ ++ { "Gimp", NULL, NULL, 0, 1, 1.0, inactiveopacity, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, 0, activeopacity, inactiveopacity, -1 }, + }; + + /* layout(s) */ +@@ -61,40 +63,44 @@ static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, + static const char *termcmd[] = { "st", NULL }; + + static const Key keys[] = { +- /* modifier key function argument */ +- { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, +- { MODKEY, XK_b, togglebar, {0} }, +- { MODKEY, XK_j, focusstack, {.i = +1 } }, +- { MODKEY, XK_k, focusstack, {.i = -1 } }, +- { MODKEY, XK_i, incnmaster, {.i = +1 } }, +- { MODKEY, XK_d, incnmaster, {.i = -1 } }, +- { MODKEY, XK_h, setmfact, {.f = -0.05} }, +- { MODKEY, XK_l, setmfact, {.f = +0.05} }, +- { MODKEY, XK_Return, zoom, {0} }, +- { MODKEY, XK_Tab, view, {0} }, +- { MODKEY|ShiftMask, XK_c, killclient, {0} }, +- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, +- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, +- { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, +- { MODKEY, XK_space, setlayout, {0} }, +- { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, +- { MODKEY, XK_0, view, {.ui = ~0 } }, +- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, +- { MODKEY, XK_comma, focusmon, {.i = -1 } }, +- { MODKEY, XK_period, focusmon, {.i = +1 } }, +- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, +- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, +- TAGKEYS( XK_1, 0) +- TAGKEYS( XK_2, 1) +- TAGKEYS( XK_3, 2) +- TAGKEYS( XK_4, 3) +- TAGKEYS( XK_5, 4) +- TAGKEYS( XK_6, 5) +- TAGKEYS( XK_7, 6) +- TAGKEYS( XK_8, 7) +- TAGKEYS( XK_9, 8) +- { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ /* modifier key function argument */ ++ { MODKEY, XK_p, spawn, {.v = dmenucmd } }, ++ { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, ++ { MODKEY, XK_b, togglebar, {0} }, ++ { MODKEY, XK_j, focusstack, {.i = +1 } }, ++ { MODKEY, XK_k, focusstack, {.i = -1 } }, ++ { MODKEY, XK_i, incnmaster, {.i = +1 } }, ++ { MODKEY, XK_d, incnmaster, {.i = -1 } }, ++ { MODKEY, XK_h, setmfact, {.f = -0.05} }, ++ { MODKEY, XK_l, setmfact, {.f = +0.05} }, ++ { MODKEY, XK_Return, zoom, {0} }, ++ { MODKEY, XK_Tab, view, {0} }, ++ { MODKEY|ShiftMask, XK_c, killclient, {0} }, ++ { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, ++ { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, ++ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XK_space, setlayout, {0} }, ++ { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, ++ { MODKEY, XK_0, view, {.ui = ~0 } }, ++ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, ++ { MODKEY, XK_comma, focusmon, {.i = -1 } }, ++ { MODKEY, XK_period, focusmon, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, ++ { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_a, changefocusopacity, {.f = +0.025}}, ++ { MODKEY|ShiftMask, XK_s, changefocusopacity, {.f = -0.025}}, ++ { MODKEY|ShiftMask, XK_z, changeunfocusopacity, {.f = +0.025}}, ++ { MODKEY|ShiftMask, XK_x, changeunfocusopacity, {.f = -0.025}}, ++ TAGKEYS( XK_1, 0) ++ TAGKEYS( XK_2, 1) ++ TAGKEYS( XK_3, 2) ++ TAGKEYS( XK_4, 3) ++ TAGKEYS( XK_5, 4) ++ TAGKEYS( XK_6, 5) ++ TAGKEYS( XK_7, 6) ++ TAGKEYS( XK_8, 7) ++ TAGKEYS( XK_9, 8) ++ { MODKEY|ShiftMask, XK_q, quit, {0} }, + }; + + /* button definitions */ +diff --git a/dwm.c b/dwm.c +index c2bd871..71cf33c 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -62,7 +62,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ + enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, +- NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ ++ NetWMWindowTypeDialog, NetClientList, NetWMWindowsOpacity, NetLast }; /* EWMH atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ + enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ +@@ -95,6 +95,8 @@ struct Client { + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + Client *next; + Client *snext; ++ double opacity; ++ double unfocusopacity; + Monitor *mon; + Window win; + }; +@@ -138,6 +140,8 @@ typedef struct { + const char *title; + unsigned int tags; + int isfloating; ++ double opacity; ++ double unfocusopacity; + int monitor; + } Rule; + +@@ -149,6 +153,8 @@ static void arrangemon(Monitor *m); + static void attach(Client *c); + static void attachstack(Client *c); + static void buttonpress(XEvent *e); ++static void changefocusopacity(const Arg *arg); ++static void changeunfocusopacity(const Arg *arg); + static void checkotherwm(void); + static void cleanup(void); + static void cleanupmon(Monitor *mon); +@@ -185,6 +191,7 @@ static void monocle(Monitor *m); + static void motionnotify(XEvent *e); + static void movemouse(const Arg *arg); + static Client *nexttiled(Client *c); ++static void opacity(Client *c, double opacity); + static void pop(Client *c); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); +@@ -287,6 +294,8 @@ applyrules(Client *c) + /* rule matching */ + c->isfloating = 0; + c->tags = 0; ++ c->opacity = activeopacity; ++ c->unfocusopacity = inactiveopacity; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; +@@ -299,6 +308,8 @@ applyrules(Client *c) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; ++ c->opacity = r->opacity; ++ c->unfocusopacity = r->unfocusopacity; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; +@@ -457,6 +468,36 @@ buttonpress(XEvent *e) + buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); + } + ++void ++changefocusopacity(const Arg *arg) ++{ ++ if (!selmon->sel) ++ return; ++ selmon->sel->opacity+=arg->f; ++ if(selmon->sel->opacity > 1.0) ++ selmon->sel->opacity = 1.0; ++ ++ if(selmon->sel->opacity < 0.1) ++ selmon->sel->opacity = 0.1; ++ ++ opacity(selmon->sel, selmon->sel->opacity); ++} ++ ++void ++changeunfocusopacity(const Arg *arg) ++{ ++ if (!selmon->sel) ++ return; ++ selmon->sel->unfocusopacity+=arg->f; ++ if(selmon->sel->unfocusopacity > 1.0) ++ selmon->sel->unfocusopacity = 1.0; ++ ++ if(selmon->sel->unfocusopacity < 0.1) ++ selmon->sel->unfocusopacity = 0.1; ++ ++ opacity(selmon->sel, selmon->sel->unfocusopacity); ++} ++ + void + checkotherwm(void) + { +@@ -803,6 +844,8 @@ focus(Client *c) + grabbuttons(c, 1); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); ++ c->opacity = MIN(1.0, MAX(0, c->opacity)); ++ opacity(c, c->opacity); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +@@ -1052,6 +1095,7 @@ manage(Window w, XWindowAttributes *wa) + c->mon = selmon; + applyrules(c); + } ++ opacity(c, c->opacity); + + if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) + c->x = c->mon->wx + c->mon->ww - WIDTH(c); +@@ -1209,6 +1253,18 @@ nexttiled(Client *c) + return c; + } + ++void ++opacity(Client *c, double opacity) ++{ ++ if(opacity > 0 && opacity < 1) { ++ unsigned long real_opacity[] = { opacity * 0xffffffff }; ++ XChangeProperty(dpy, c->win, netatom[NetWMWindowsOpacity], XA_CARDINAL, ++ 32, PropModeReplace, (unsigned char *)real_opacity, ++ 1); ++ } else ++ XDeleteProperty(dpy, c->win, netatom[NetWMWindowsOpacity]); ++} ++ + void + pop(Client *c) + { +@@ -1579,6 +1635,7 @@ setup(void) + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); ++ netatom[NetWMWindowsOpacity] = XInternAtom(dpy, "_NET_WM_WINDOW_OPACITY", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); +@@ -1760,6 +1817,8 @@ unfocus(Client *c, int setfocus) + if (!c) + return; + grabbuttons(c, 0); ++ c->unfocusopacity = MIN(1.0, MAX(0, c->unfocusopacity)); ++ opacity(c, c->unfocusopacity); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); +-- +2.39.2 diff --git a/dwm/patches/dwm-clientresizehints-6.5.diff b/dwm/patches/dwm-clientresizehints-6.5.diff new file mode 100644 index 0000000..8c35e8b --- /dev/null +++ b/dwm/patches/dwm-clientresizehints-6.5.diff @@ -0,0 +1,75 @@ +# From b2de13e11e7b4d67b4982ef51befa87ed9202080 Mon Sep 17 00:00:00 2001 +# From: Fred Frey <fred@fpf3.net> +# Date: Sun, 22 Sep 2024 16:09:53 -0400 +# Subject: [PATCH] implement per-client resizehints +# +# --- +# config.def.h | 6 +++--- +# dwm.c | 7 +++++-- +# 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..67e7a9c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -26,9 +26,9 @@ static const Rule rules[] = { + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ /* class instance title tags mask isfloating monitor resizehints */ ++ { "Gimp", NULL, NULL, 0, 1, -1, 1}, ++ { "Firefox", NULL, NULL, 1 << 8, 0, -1, 1}, + }; + + /* layout(s) */ +diff --git a/dwm.c b/dwm.c +index 67c6b2b..f179b4c 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -92,7 +92,7 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + int bw, oldbw; + unsigned int tags; +- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, resizehints; + Client *next; + Client *snext; + Monitor *mon; +@@ -139,6 +139,7 @@ typedef struct { + unsigned int tags; + int isfloating; + int monitor; ++ int resizehints; + } Rule; + + /* function declarations */ +@@ -299,6 +300,7 @@ applyrules(Client *c) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; ++ c->resizehints = r->resizehints; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; +@@ -343,7 +345,7 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) + *h = bh; + if (*w < bh) + *w = bh; +- if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { ++ if (c->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 */ +@@ -1043,6 +1045,7 @@ manage(Window w, XWindowAttributes *wa) + c->w = c->oldw = wa->width; + c->h = c->oldh = wa->height; + c->oldbw = wa->border_width; ++ c->resizehints = resizehints; + + updatetitle(c); + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { +-- +2.46.0 diff --git a/dwm/patches/dwm-colorbar-6.3.diff b/dwm/patches/dwm-colorbar-6.3.diff new file mode 100644 index 0000000..976a2e5 --- /dev/null +++ b/dwm/patches/dwm-colorbar-6.3.diff @@ -0,0 +1,85 @@ +# From 647a2a56cf7cab6dea868f9800671770940ce3c3 Mon Sep 17 00:00:00 2001 +# From: Alessandro Sisto <alessandro.sisto@studioform.net> +# Date: Sun, 5 Jun 2022 12:03:43 +0200 +# Subject: [PATCH] colorbar +# +# --- +# config.def.h | 6 +++++- +# dwm.c | 12 ++++++------ +# 2 files changed, 11 insertions(+), 7 deletions(-) + +diff --git a/config.def.h b/config.def.h +index a2ac963..56bc324 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -16,6 +16,11 @@ static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, ++ [SchemeStatus] = { col_gray3, col_gray1, "#000000" }, // Statusbar right {text,background,not used but cannot be empty} ++ [SchemeTagsSel] = { col_gray4, col_cyan, "#000000" }, // Tagbar left selected {text,background,not used but cannot be empty} ++ [SchemeTagsNorm] = { col_gray3, col_gray1, "#000000" }, // Tagbar left unselected {text,background,not used but cannot be empty} ++ [SchemeInfoSel] = { col_gray4, col_cyan, "#000000" }, // infobar middle selected {text,background,not used but cannot be empty} ++ [SchemeInfoNorm] = { col_gray3, col_gray1, "#000000" }, // infobar middle unselected {text,background,not used but cannot be empty} + }; + + /* tagging */ +@@ -113,4 +118,3 @@ static Button buttons[] = { + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; +- +diff --git a/dwm.c b/dwm.c +index a96f33c..0eaa4cd 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -59,7 +59,7 @@ + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +-enum { SchemeNorm, SchemeSel }; /* color schemes */ ++enum { SchemeNorm, SchemeSel, SchemeStatus, SchemeTagsSel, SchemeTagsNorm, SchemeInfoSel, SchemeInfoNorm }; /* color schemes */ + enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ +@@ -707,7 +707,7 @@ drawbar(Monitor *m) + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ +- drw_setscheme(drw, scheme[SchemeNorm]); ++ drw_setscheme(drw, scheme[SchemeStatus]); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); + } +@@ -720,7 +720,7 @@ drawbar(Monitor *m) + x = 0; + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(tags[i]); +- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); ++ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeTagsSel : SchemeTagsNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, +@@ -729,17 +729,17 @@ drawbar(Monitor *m) + x += w; + } + w = blw = TEXTW(m->ltsymbol); +- drw_setscheme(drw, scheme[SchemeNorm]); ++ drw_setscheme(drw, scheme[SchemeTagsNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { +- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); ++ drw_setscheme(drw, scheme[m == selmon ? SchemeInfoSel : SchemeInfoNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { +- drw_setscheme(drw, scheme[SchemeNorm]); ++ drw_setscheme(drw, scheme[SchemeInfoNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); + } + } +-- +2.36.1 diff --git a/dwm/patches/dwm-exresize-r1606.diff b/dwm/patches/dwm-exresize-r1606.diff new file mode 100644 index 0000000..dcc93c0 --- /dev/null +++ b/dwm/patches/dwm-exresize-r1606.diff @@ -0,0 +1,372 @@ +diff --git a/config.def.h b/config.def.h +index 7fb4d82..959a119 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -88,6 +88,33 @@ static Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ ++ { MODKEY, XK_KP_7, explace, {.ui = EX_NW }}, ++ { MODKEY, XK_KP_8, explace, {.ui = EX_N }}, ++ { MODKEY, XK_KP_9, explace, {.ui = EX_NE }}, ++ { MODKEY, XK_KP_4, explace, {.ui = EX_W }}, ++ { MODKEY, XK_KP_5, explace, {.ui = EX_C }}, ++ { MODKEY, XK_KP_6, explace, {.ui = EX_E }}, ++ { MODKEY, XK_KP_1, explace, {.ui = EX_SW }}, ++ { MODKEY, XK_KP_2, explace, {.ui = EX_S }}, ++ { MODKEY, XK_KP_3, explace, {.ui = EX_SE }}, ++ ++ { MODKEY|ShiftMask, XK_KP_8, exresize, {.v = (int []){ 0, 25 }}}, ++ { MODKEY|ShiftMask, XK_KP_2, exresize, {.v = (int []){ 0, -25 }}}, ++ { MODKEY|ShiftMask, XK_KP_6, exresize, {.v = (int []){ 25, 0 }}}, ++ { MODKEY|ShiftMask, XK_KP_4, exresize, {.v = (int []){ -25, 0 }}}, ++ { MODKEY|ShiftMask, XK_KP_5, exresize, {.v = (int []){ 25, 25 }}}, ++ { MODKEY|ShiftMask|ControlMask, XK_KP_5, exresize, {.v = (int []){ -25, -25 }}}, ++ ++ { MODKEY|ControlMask, XK_KP_6, togglehorizontalexpand, {.i = +1} }, ++ { MODKEY|ControlMask, XK_KP_3, togglehorizontalexpand, {.i = 0} }, ++ { MODKEY|ControlMask, XK_KP_4, togglehorizontalexpand, {.i = -1} }, ++ { MODKEY|ControlMask, XK_KP_8, toggleverticalexpand, {.i = +1} }, ++ { MODKEY|ControlMask, XK_KP_1, toggleverticalexpand, {.i = 0} }, ++ { MODKEY|ControlMask, XK_KP_2, toggleverticalexpand, {.i = -1} }, ++ { MODKEY|ControlMask, XK_KP_9, togglemaximize, {.i = -1} }, ++ { MODKEY|ControlMask, XK_KP_7, togglemaximize, {.i = +1} }, ++ { MODKEY|ControlMask, XK_KP_5, togglemaximize, {.i = 0} }, + }; + + /* button definitions */ +diff --git a/dwm.c b/dwm.c +index 4986b07..8fc0c57 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -89,11 +89,14 @@ struct Client { + char name[256]; + float mina, maxa; + int x, y, w, h; ++ int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */ + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; +- Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ unsigned char expandmask; ++ int expandx1, expandy1, expandx2, expandy2; ++ Bool wasfloating, isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; + Client *next; + Client *snext; + Monitor *mon; +@@ -1132,8 +1135,14 @@ manage(Window w, XWindowAttributes *wa) { + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); ++ c->sfx = c->x; ++ c->sfy = c->y; ++ c->sfw = c->w; ++ c->sfh = c->h; + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, False); ++ c->wasfloating = False; ++ c->expandmask = 0; + if(!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if(c->isfloating) +@@ -1234,8 +1243,9 @@ movemouse(const Arg *arg) { + case MotionNotify: + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); +- if(nx >= selmon->wx && nx <= selmon->wx + selmon->ww +- && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) { ++ if ((m = recttomon(nx, ny, c->w, c->h))) { ++ if (m != selmon) ++ sendmon(c, m); + if(abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if(abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) +@@ -1343,6 +1353,7 @@ resizeclient(Client *c, int x, int y, int w, int h) { + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; ++ c->expandmask = 0; + wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); +@@ -1379,9 +1390,9 @@ resizemouse(const Arg *arg) { + case MotionNotify: + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); +- if(c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww +- && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) +- { ++ if ((m = recttomon(c->x, c->y, nw, nh))) { ++ if (m != selmon) ++ sendmon(c, m); + if(!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) + togglefloating(NULL); +@@ -1463,6 +1474,7 @@ scan(void) { + + void + sendmon(Client *c, Monitor *m) { ++ Monitor *oldm = selmon; + if(c->mon == m) + return; + unfocus(c, True); +@@ -1472,8 +1484,11 @@ sendmon(Client *c, Monitor *m) { + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); +- focus(NULL); +- arrange(NULL); ++ if (oldm != m) ++ arrange(oldm); ++ arrange(m); ++ focus(c); ++ restack(m); + } + + void +@@ -1549,8 +1564,18 @@ setfullscreen(Client *c, Bool fullscreen) { + + void + setlayout(const Arg *arg) { +- if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) ++ if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { + selmon->sellt ^= 1; ++ if (!selmon->lt[selmon->sellt]->arrange) { ++ for (Client *c = selmon->clients ; c ; c = c->next) { ++ if(!c->isfloating) { ++ /*restore last known float dimensions*/ ++ resize(c, selmon->mx + c->sfx, selmon->my + c->sfy, ++ c->sfw, c->sfh, False); ++ } ++ } ++ } ++ } + if(arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); +@@ -1732,9 +1757,19 @@ togglefloating(const Arg *arg) { + if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; +- if(selmon->sel->isfloating) +- resize(selmon->sel, selmon->sel->x, selmon->sel->y, +- selmon->sel->w, selmon->sel->h, False); ++ if(selmon->sel->isfloating) { ++ /*restore last known float dimensions*/ ++ resize(selmon->sel, selmon->mx + selmon->sel->sfx, selmon->my + selmon->sel->sfy, ++ selmon->sel->sfw, selmon->sel->sfh, False); ++ } else { ++ if (selmon->sel->isfullscreen) ++ setfullscreen(selmon->sel, False); ++ /*save last known float dimensions*/ ++ selmon->sel->sfx = selmon->sel->x - selmon->mx; ++ selmon->sel->sfy = selmon->sel->y - selmon->my; ++ selmon->sel->sfw = selmon->sel->w; ++ selmon->sel->sfh = selmon->sel->h; ++ } + arrange(selmon); + } + +diff --git a/exresize.c b/exresize.c +new file mode 100644 +index 0000000..2343ffe +--- /dev/null ++++ b/exresize.c +@@ -0,0 +1,195 @@ ++#define EXPAND_LEFT (1 << 0) ++#define EXPAND_RIGHT (1 << 2) ++#define EXPAND_UP (1 << 4) ++#define EXPAND_DOWN (1 << 6) ++ ++#define IS_SET(q, w) ((q & w) != 0) ++#define IS_FORCED(q, w) IS_SET((q << 1), w) ++ ++#define EXPANDALL (EXPAND_LEFT | EXPAND_RIGHT | EXPAND_UP | EXPAND_DOWN) ++#define UNEXPAND (EXPANDALL << 1) // Force all directions to 0 ++#define FORCE_EXPANDALL ~0 // Force expand in all directions ++ ++enum { EX_NW, EX_N, EX_NE, EX_W, EX_C, EX_E, EX_SW, EX_S, EX_SE }; ++ ++void expand(unsigned char mask); ++ ++void togglemaximize(const Arg *arg); ++void toggleverticalexpand(const Arg *arg); ++void togglehorizontalexpand(const Arg *arg); ++void exresize(const Arg *arg); ++void explace(const Arg *arg); ++ ++void ++exresize(const Arg *arg) { ++ Client *c; ++ int x, y, nx, ny, nw, nh; ++ c = selmon->sel; ++ ++ if (!c || !arg) return; ++ if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) ++ togglefloating(NULL); ++ if (c->expandmask != 0) ++ expand(UNEXPAND); ++ ++ x = ((int *)arg->v)[0]; ++ y = ((int *)arg->v)[1]; ++ ++ nw = MIN(selmon->ww - c->bw*2, c->w + x); ++ nh = MIN(selmon->wh - c->bw*2, c->h + y); ++ nx = c->x - x/2; ++ ny = c->y - y/2; ++ ++ if (!((abs(c->x + c->w/2 - (selmon->wx + selmon->ww/2)) < snap))) { ++ if ((nw == selmon->ww) || ++ (nx < selmon->wx) || ++ (abs(selmon->wx - c->x) < snap)) ++ nx = selmon->wx; ++ else if ((nx+nw > (selmon->wx + selmon->ww)) || ++ (abs((selmon->wx + selmon->ww) - (c->x + c->w)) < snap)) ++ nx = (selmon->wx + selmon->ww) - nw - c->bw*2; ++ } else ++ nx = selmon->wx + selmon->ww/2 - nw/2; ++ ++ if (!((abs(c->y + c->h/2 - (selmon->wy + selmon->wh/2)) < snap))) { ++ ++ if ((nh == selmon->wh) || ++ (ny < selmon->wy) || ++ (abs(selmon->wy - c->y) < snap)) ++ ny = selmon->wy; ++ else if ((ny+nh > (selmon->wy + selmon->wh)) || ++ (abs((selmon->wy + selmon->wh) - (c->y + c->h)) < snap)) ++ ny = (selmon->wy + selmon->wh) - nh - c->bw*2; ++ } else ++ ny = selmon->wy + selmon->wh/2 - nh/2; ++ ++ ++ resizeclient(c, nx, ny, MAX(nw, 32), MAX(nh, 32)); ++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); ++} ++ ++void ++explace(const Arg *arg) { ++ Client *c; ++ int nx, ny; ++ ++ c = selmon->sel; ++ if (!c || (arg->ui >= 9)) return; ++ if (selmon->lt[selmon->sellt]->arrange && !c->isfloating) ++ togglefloating(NULL); ++ ++ nx = (arg->ui % 3) - 1; ++ ny = (arg->ui / 3) - 1; ++ ++ if (nx < 0) nx = selmon->wx; ++ else if (nx > 0) nx = selmon->wx + selmon->ww - c->w - c->bw*2; ++ else nx = selmon->wx + selmon->ww/2 - c->w/2; ++ ++ if (ny < 0) ny = selmon->wy; ++ else if (ny > 0) ny = selmon->wy + selmon->wh - c->h - c->bw*2; ++ else ny = selmon->wy + selmon->wh/2 - c->h/2; ++ ++ resize(c, nx, ny, c->w, c->h, 0); ++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w/2, c->h/2); ++} ++ ++int ++calculate_expand(unsigned char mask, unsigned char curmask, ++ unsigned char *newmask, unsigned char key, ++ int *reset_value, int new_reset_value, ++ int max_value, int old_value) { ++ if (IS_SET(key, mask) || ++ (IS_SET(key, curmask) && (!IS_SET(key, mask) && IS_FORCED(key, mask))) || ++ (!IS_SET(key, curmask) && (IS_SET(key, mask) && IS_FORCED(key, mask)))) { ++ ++ if (IS_SET(key, mask) && (!IS_SET(key,curmask) || IS_FORCED(key,mask))) ++ { ++ if (!IS_SET(key, curmask)) ++ *reset_value = new_reset_value; ++ *newmask |= key; ++ return max_value; ++ } else if ((IS_SET(key,curmask) && IS_SET(key, mask)) || ++ (!IS_SET(key, mask) && IS_FORCED(key, mask))) { ++ *newmask &= ~key; ++ return *reset_value; ++ } else { ++ *newmask &= ~key; ++ return old_value; ++ } ++ } else ++ return new_reset_value; ++} ++ ++void ++expand(unsigned char mask) { ++ XEvent ev; ++ int nx1, ny1, nx2, ny2; ++ unsigned char curmask; ++ unsigned char newmask; ++ ++ if(!selmon->sel || selmon->sel->isfixed) ++ return; ++ XRaiseWindow(dpy, selmon->sel->win); ++ newmask = curmask = selmon->sel->expandmask; ++ ++ if (curmask == 0) { ++ if(!selmon->lt[selmon->sellt]->arrange || selmon->sel->isfloating) ++ selmon->sel->wasfloating = 0; ++ else { ++ togglefloating(NULL); ++ selmon->sel->wasfloating = 0; ++ } ++ } ++ ++ nx1 = calculate_expand(mask, curmask, &newmask, ++ EXPAND_LEFT, &selmon->sel->expandx1, ++ selmon->sel->x, ++ selmon->wx, ++ selmon->sel->oldx); ++ nx2 = calculate_expand(mask, curmask, &newmask, ++ EXPAND_RIGHT, &selmon->sel->expandx2, ++ selmon->sel->x + selmon->sel->w, ++ selmon->wx + selmon->ww - 2*borderpx, ++ selmon->sel->oldw + selmon->sel->x); ++ ny1 = calculate_expand(mask, curmask, &newmask, ++ EXPAND_UP, &selmon->sel->expandy1, ++ selmon->sel->y, ++ selmon->wy, ++ selmon->sel->oldy); ++ ny2 = calculate_expand(mask, curmask, &newmask, ++ EXPAND_DOWN, &selmon->sel->expandy2, ++ selmon->sel->y + selmon->sel->h, ++ selmon->wy + selmon->wh - 2*borderpx, ++ selmon->sel->oldh + selmon->sel->y); ++ ++ ++ resizeclient(selmon->sel, nx1, ny1, MAX(nx2-nx1, 32), MAX(ny2-ny1, 32)); ++ ++ if ((newmask == 0) && (!selmon->sel->wasfloating)) ++ togglefloating(NULL); ++ selmon->sel->expandmask = newmask; ++ drawbar(selmon); ++ while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); ++} ++ ++void ++togglemaximize(const Arg *arg) { ++ if (arg->i > 0) expand(FORCE_EXPANDALL); ++ else if (arg->i < 0) expand(UNEXPAND); ++ else expand(EXPANDALL); ++} ++ ++void ++toggleverticalexpand(const Arg *arg) { ++ if (arg->i < 0) expand(EXPAND_DOWN); ++ else if (arg->i > 0) expand(EXPAND_UP); ++ else expand(EXPAND_DOWN | EXPAND_UP); ++} ++ ++void ++togglehorizontalexpand(const Arg *arg) { ++ if (arg->i < 0) expand(EXPAND_LEFT); ++ else if (arg->i > 0) expand(EXPAND_RIGHT); ++ else expand(EXPAND_LEFT | EXPAND_RIGHT); ++} ++ diff --git a/dwm/patches/dwm-float-border-color-20231008-3a7ea45f.diff b/dwm/patches/dwm-float-border-color-20231008-3a7ea45f.diff new file mode 100644 index 0000000..dc1106b --- /dev/null +++ b/dwm/patches/dwm-float-border-color-20231008-3a7ea45f.diff @@ -0,0 +1,108 @@ +# From 5f6716fa3fb7e28e6592872ce3de32b7aa0965a7 Mon Sep 17 00:00:00 2001 +# From: glpzzz <glpz@daxslab.com> +# Date: Sun, 8 Oct 2023 16:44:37 -0400 +# Subject: [PATCH] set the custom colored floating border on unfocus too. +# +# --- +# config.def.h | 8 ++++---- +# dwm.c | 24 ++++++++++++++++++++---- +# 2 files changed, 24 insertions(+), 8 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..ce68d1e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -12,10 +12,10 @@ static const char col_gray2[] = "#444444"; + static const char col_gray3[] = "#bbbbbb"; + static const char col_gray4[] = "#eeeeee"; + static const char col_cyan[] = "#005577"; +-static const char *colors[][3] = { +- /* fg bg border */ +- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, +- [SchemeSel] = { col_gray4, col_cyan, col_cyan }, ++static const char *colors[][4] = { ++ /* fg bg border float */ ++ [SchemeNorm] = { col_gray3, col_gray1, col_gray2, col_gray2 }, ++ [SchemeSel] = { col_gray4, col_cyan, col_gray2, col_cyan }, + }; + + /* tagging */ +diff --git a/dwm.c b/dwm.c +index f1d86b2..4182083 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -56,6 +56,7 @@ + #define HEIGHT(X) ((X)->h + 2 * (X)->bw) + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) ++#define ColFloat 3 + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +@@ -801,7 +802,10 @@ focus(Client *c) + detachstack(c); + attachstack(c); + grabbuttons(c, 1); +- XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); ++ if(c->isfloating) ++ XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel); ++ else ++ XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); +@@ -1063,7 +1067,10 @@ manage(Window w, XWindowAttributes *wa) + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); +- XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); ++ if(c->isfloating) ++ XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); ++ else ++ XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); + updatesizehints(c); +@@ -1074,6 +1081,8 @@ manage(Window w, XWindowAttributes *wa) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) + XRaiseWindow(dpy, c->win); ++ if(c->isfloating) ++ XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); + attach(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, +@@ -1586,7 +1595,7 @@ setup(void) + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) +- scheme[i] = drw_scm_create(drw, colors[i], 3); ++ scheme[i] = drw_scm_create(drw, colors[i], 4); + /* init bars */ + updatebars(); + updatestatus(); +@@ -1730,6 +1739,10 @@ togglefloating(const Arg *arg) + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; + if (selmon->sel->isfloating) ++ XSetWindowBorder(dpy, selmon->sel->win, scheme[SchemeSel][ColFloat].pixel); ++ else ++ XSetWindowBorder(dpy, selmon->sel->win, scheme[SchemeSel][ColBorder].pixel); ++ if(selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, 0); + arrange(selmon); +@@ -1768,7 +1781,10 @@ unfocus(Client *c, int setfocus) + if (!c) + return; + grabbuttons(c, 0); +- XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); ++ if (c->isfloating) ++ XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel); ++ else ++ XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +-- +2.39.2 diff --git a/dwm/patches/dwm-floatborderwidth-6.3.diff b/dwm/patches/dwm-floatborderwidth-6.3.diff new file mode 100644 index 0000000..d41bed2 --- /dev/null +++ b/dwm/patches/dwm-floatborderwidth-6.3.diff @@ -0,0 +1,68 @@ +# From 54b88e6663364d561fc0feb3ea9d4c79c0f4e3b0 Mon Sep 17 00:00:00 2001 +# From: Dylan Cairns-Howarth <dairnarth@dylancairns.co.uk> +# Date: Sun, 20 Feb 2022 07:48:59 +0000 +# Subject: [PATCH] Floating Windows have seperate border width +# +# This dwm patch adds the int fborderpx to config.def.h that assigns a +# border width to floating windows. +# +# By default, this patch sets borderpx to 0 and fborderpx to 1 (no borders +# for tiled windows and a 1px border for floating windows). +# --- +# config.def.h | 4 ++-- +# dwm.c | 13 +++++++++++-- +# 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/config.def.h b/config.def.h +index a2ac963..ce35589 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -1,7 +1,8 @@ + /* See LICENSE file for copyright and license details. */ + + /* appearance */ +-static const unsigned int borderpx = 1; /* border pixel of windows */ ++static const unsigned int borderpx = 0; /* border pixel of windows */ ++static const unsigned int fborderpx = 1; /* border pixel of floating windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ +@@ -113,4 +114,3 @@ static Button buttons[] = { + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; +- +diff --git a/dwm.c b/dwm.c +index a96f33c..a63e9cd 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1052,6 +1052,8 @@ manage(Window w, XWindowAttributes *wa) + c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + c->bw = borderpx; ++ if (c->isfloating) ++ c->bw = fborderpx; + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); +@@ -1719,9 +1721,16 @@ togglefloating(const Arg *arg) + if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; +- if (selmon->sel->isfloating) ++ if (selmon->sel->isfloating) { ++ selmon->sel->bw = fborderpx; ++ configure(selmon->sel); ++ int borderdiff = (fborderpx - borderpx) * 2; + resize(selmon->sel, selmon->sel->x, selmon->sel->y, +- selmon->sel->w, selmon->sel->h, 0); ++ selmon->sel->w - borderdiff, selmon->sel->h - borderdiff, 0); ++ } else { ++ selmon->sel->bw = borderpx; ++ configure(selmon->sel); ++ } + arrange(selmon); + } + +-- +2.35.1 diff --git a/dwm/patches/dwm-focusmaster-return-6.2.diff b/dwm/patches/dwm-focusmaster-return-6.2.diff new file mode 100644 index 0000000..9a02054 --- /dev/null +++ b/dwm/patches/dwm-focusmaster-return-6.2.diff @@ -0,0 +1,89 @@ +# From 8f662e7a556f94bda83ec724fb036e15b2badaac Mon Sep 17 00:00:00 2001 +# From: Jack Bird <jack.bird@durham.ac.uk> +# Date: Fri, 27 Aug 2021 01:14:44 +0100 +# Subject: [PATCH] 6.2 focusmaster return +# +# --- +# dwm.c | 39 +++++++++++++++++++++++++++++++++++++++ +# 1 file changed, 39 insertions(+) + +diff --git a/dwm.c b/dwm.c +index 4465af1..5219cbd 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -127,6 +127,7 @@ struct Monitor { + Client *clients; + Client *sel; + Client *stack; ++ Client *tagmarked[32]; + Monitor *next; + Window barwin; + const Layout *lt[2]; +@@ -167,6 +168,7 @@ static void enternotify(XEvent *e); + static void expose(XEvent *e); + static void focus(Client *c); + static void focusin(XEvent *e); ++static void focusmaster(const Arg *arg); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); + static int getrootptr(int *x, int *y); +@@ -659,6 +661,10 @@ detach(Client *c) + { + Client **tc; + ++ for (int i = 1; i < LENGTH(tags); i++) ++ if (c == c->mon->tagmarked[i]) ++ c->mon->tagmarked[i] = NULL; ++ + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; + } +@@ -815,6 +821,34 @@ focusin(XEvent *e) + setfocus(selmon->sel); + } + ++void ++focusmaster(const Arg *arg) ++{ ++ Client *master; ++ ++ if (selmon->nmaster > 1) ++ return; ++ if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) ++ return; ++ ++ master = nexttiled(selmon->clients); ++ ++ if (!master) ++ return; ++ ++ int i; ++ for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); ++ i++; ++ ++ if (selmon->sel == master) { ++ if (selmon->tagmarked[i] && ISVISIBLE(selmon->tagmarked[i])) ++ focus(selmon->tagmarked[i]); ++ } else { ++ selmon->tagmarked[i] = selmon->sel; ++ focus(master); ++ } ++} ++ + void + focusmon(const Arg *arg) + { +@@ -1202,6 +1236,11 @@ nexttiled(Client *c) + void + pop(Client *c) + { ++ int i; ++ for (i = 0; !(selmon->tagset[selmon->seltags] & 1 << i); i++); ++ i++; ++ ++ c->mon->tagmarked[i] = nexttiled(c->mon->clients); + detach(c); + attach(c); + focus(c); +-- +2.33.0 diff --git a/dwm/patches/dwm-gestures-6.4.diff b/dwm/patches/dwm-gestures-6.4.diff new file mode 100644 index 0000000..d3ed528 --- /dev/null +++ b/dwm/patches/dwm-gestures-6.4.diff @@ -0,0 +1,126 @@ +diff -up a/config.def.h b/config.def.h +--- a/config.def.h 2023-01-13 15:14:16.536118429 +0100 ++++ b/config.def.h 2023-01-13 15:21:25.946360539 +0100 +@@ -78,6 +78,7 @@ static const Key keys[] = { + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, ++ { MODKEY, XK_g, gesture, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, +@@ -107,9 +108,21 @@ static const Button buttons[] = { + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, ++ { ClkClientWin, MODKEY|ShiftMask,Button3, gesture, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; + ++/* gestures ++ * u means up ++ * d means down ++ * l means left ++ * r means right ++ * ud means up and down ++ */ ++static Gesture gestures[] = { ++ { "u", spawn, {.v = termcmd } }, ++ { "d", spawn, {.v = dmenucmd } }, ++}; +diff -up a/dwm.c b/dwm.c +--- a/dwm.c 2023-01-13 15:14:16.536118429 +0100 ++++ b/dwm.c 2023-01-13 15:14:41.094075080 +0100 +@@ -75,6 +75,12 @@ typedef union { + } Arg; + + typedef struct { ++ char *gname; ++ void (*func)(const Arg *arg); ++ const Arg arg; ++} Gesture; ++ ++typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; +@@ -183,6 +189,7 @@ static void mappingnotify(XEvent *e); + static void maprequest(XEvent *e); + static void monocle(Monitor *m); + static void motionnotify(XEvent *e); ++static void gesture(const Arg *arg); + static void movemouse(const Arg *arg); + static Client *nexttiled(Client *c); + static void pop(Client *c); +@@ -1134,6 +1141,68 @@ motionnotify(XEvent *e) + } + + void ++gesture(const Arg *arg) { ++ int x, y, dx, dy, q; ++ int valid=0, listpos=0, gestpos=0, count=0; ++ char move, currGest[10]; ++ XEvent ev; ++ ++ if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, ++ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) ++ return; ++ if(!getrootptr(&x, &y)) ++ return; ++ do { ++ XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); ++ switch (ev.type) { ++ case ConfigureRequest: ++ case Expose: ++ case MapRequest: ++ handler[ev.type](&ev); ++ break; ++ case MotionNotify: ++ if(count++ < 10) ++ break; ++ count = 0; ++ dx = ev.xmotion.x - x; ++ dy = ev.xmotion.y - y; ++ x = ev.xmotion.x; ++ y = ev.xmotion.y; ++ ++ if( abs(dx)/(abs(dy)+1) == 0 ) ++ move = dy<0?'u':'d'; ++ else ++ move = dx<0?'l':'r'; ++ ++ if(move!=currGest[gestpos-1]) ++ { ++ if(gestpos>9) ++ { ev.type++; ++ break; ++ } ++ ++ currGest[gestpos] = move; ++ currGest[++gestpos] = '\0'; ++ ++ valid = 0; ++ for(q = 0; q<LENGTH(gestures); q++) ++ { if(!strcmp(currGest, gestures[q].gname)) ++ { valid++; ++ listpos = q; ++ } ++ } ++ } ++ ++ } ++ } while(ev.type != ButtonRelease); ++ ++ if(valid) ++ gestures[listpos].func(&(gestures[listpos].arg)); ++ ++ XUngrabPointer(dpy, CurrentTime); ++} ++ ++void + movemouse(const Arg *arg) + { + int x, y, ocx, ocy, nx, ny; diff --git a/dwm/patches/dwm-hide_vacant_tags-6.4.diff b/dwm/patches/dwm-hide_vacant_tags-6.4.diff new file mode 100644 index 0000000..42d9c05 --- /dev/null +++ b/dwm/patches/dwm-hide_vacant_tags-6.4.diff @@ -0,0 +1,48 @@ +:100644 100644 f1d86b2 0000000 M dwm.c + +diff --git a/dwm.c b/dwm.c +index f1d86b2..d41cc14 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -433,9 +433,15 @@ buttonpress(XEvent *e) + } + if (ev->window == selmon->barwin) { + i = x = 0; +- do ++ unsigned int occ = 0; ++ for(c = m->clients; c; c=c->next) ++ occ |= c->tags == TAGMASK ? 0 : c->tags; ++ do { ++ /* Do not reserve space for vacant tags */ ++ if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) ++ continue; + x += TEXTW(tags[i]); +- while (ev->x >= x && ++i < LENGTH(tags)); ++ } while (ev->x >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; +@@ -715,19 +721,18 @@ drawbar(Monitor *m) + } + + for (c = m->clients; c; c = c->next) { +- occ |= c->tags; ++ occ |= c->tags == TAGMASK ? 0 : c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + for (i = 0; i < LENGTH(tags); i++) { ++ /* Do not draw vacant tags */ ++ if(!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) ++ continue; + w = TEXTW(tags[i]); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); +- if (occ & 1 << i) +- drw_rect(drw, x + boxs, boxs, boxw, boxw, +- m == selmon && selmon->sel && selmon->sel->tags & 1 << i, +- urg & 1 << i); + x += w; + } + w = TEXTW(m->ltsymbol); diff --git a/dwm/patches/dwm-keychord-6.4.diff b/dwm/patches/dwm-keychord-6.4.diff new file mode 100644 index 0000000..cd22e03 --- /dev/null +++ b/dwm/patches/dwm-keychord-6.4.diff @@ -0,0 +1,234 @@ +# From cb7ea178ac8e60cf123b333af64df8228762f669 Mon Sep 17 00:00:00 2001 +# From: =?UTF-8?q?Aaron=20Z=C3=BCger?= <contact@azureorange.xyz> +# Date: Wed, 19 Jul 2023 14:17:39 +0200 +# Subject: [PATCH] Update dwm-keychord patch to comply with the changes in dwm +# from version 6.2 to version 6.4. Namely changes in the grabkey function to +# match the newer implementation of said function. +# +# --- +# config.def.h | 81 ++++++++++++++++++++++++++-------------------------- +# dwm.c | 72 +++++++++++++++++++++++++++++++++++++--------- +# 2 files changed, 99 insertions(+), 54 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..49f0558 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -46,11 +46,11 @@ static const Layout layouts[] = { + + /* key definitions */ + #define MODKEY Mod1Mask +-#define TAGKEYS(KEY,TAG) \ +- { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ +- { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ +- { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ +- { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, ++#define TAGKEYS(KEY,TAG) \ ++ &((Keychord){1, {{MODKEY, KEY}}, view, {.ui = 1 << TAG} }), \ ++ &((Keychord){1, {{MODKEY|ControlMask, KEY}}, toggleview, {.ui = 1 << TAG} }), \ ++ &((Keychord){1, {{MODKEY|ShiftMask, KEY}}, tag, {.ui = 1 << TAG} }), \ ++ &((Keychord){1, {{MODKEY|ControlMask|ShiftMask, KEY}}, toggletag, {.ui = 1 << TAG} }), + + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +@@ -60,41 +60,42 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { "st", NULL }; + +-static const Key keys[] = { +- /* modifier key function argument */ +- { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, +- { MODKEY, XK_b, togglebar, {0} }, +- { MODKEY, XK_j, focusstack, {.i = +1 } }, +- { MODKEY, XK_k, focusstack, {.i = -1 } }, +- { MODKEY, XK_i, incnmaster, {.i = +1 } }, +- { MODKEY, XK_d, incnmaster, {.i = -1 } }, +- { MODKEY, XK_h, setmfact, {.f = -0.05} }, +- { MODKEY, XK_l, setmfact, {.f = +0.05} }, +- { MODKEY, XK_Return, zoom, {0} }, +- { MODKEY, XK_Tab, view, {0} }, +- { MODKEY|ShiftMask, XK_c, killclient, {0} }, +- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, +- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, +- { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, +- { MODKEY, XK_space, setlayout, {0} }, +- { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, +- { MODKEY, XK_0, view, {.ui = ~0 } }, +- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, +- { MODKEY, XK_comma, focusmon, {.i = -1 } }, +- { MODKEY, XK_period, focusmon, {.i = +1 } }, +- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, +- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, +- TAGKEYS( XK_1, 0) +- TAGKEYS( XK_2, 1) +- TAGKEYS( XK_3, 2) +- TAGKEYS( XK_4, 3) +- TAGKEYS( XK_5, 4) +- TAGKEYS( XK_6, 5) +- TAGKEYS( XK_7, 6) +- TAGKEYS( XK_8, 7) +- TAGKEYS( XK_9, 8) +- { MODKEY|ShiftMask, XK_q, quit, {0} }, ++static Keychord *keychords[] = { ++ /* Keys function argument */ ++ &((Keychord){1, {{MODKEY, XK_p}}, spawn, {.v = dmenucmd } }), ++ &((Keychord){1, {{MODKEY|ShiftMask, XK_Return}}, spawn, {.v = termcmd } }), ++ &((Keychord){2, {{MODKEY, XK_e}, {MODKEY, XK_e}}, spawn, {.v = termcmd } }), ++ &((Keychord){1, {{MODKEY, XK_b}}, togglebar, {0} }), ++ &((Keychord){1, {{MODKEY, XK_j}}, focusstack, {.i = +1 } }), ++ &((Keychord){1, {{MODKEY, XK_k}}, focusstack, {.i = -1 } }), ++ &((Keychord){1, {{MODKEY, XK_i}}, incnmaster, {.i = +1 } }), ++ &((Keychord){1, {{MODKEY, XK_d}}, incnmaster, {.i = -1 } }), ++ &((Keychord){1, {{MODKEY, XK_h}}, setmfact, {.f = -0.05} }), ++ &((Keychord){1, {{MODKEY, XK_l}}, setmfact, {.f = +0.05} }), ++ &((Keychord){1, {{MODKEY, XK_Return}}, zoom, {0} }), ++ &((Keychord){1, {{MODKEY, XK_Tab}}, view, {0} }), ++ &((Keychord){1, {{MODKEY|ShiftMask, XK_c}}, killclient, {0} }), ++ &((Keychord){1, {{MODKEY, XK_t}}, setlayout, {.v = &layouts[0]} }), ++ &((Keychord){1, {{MODKEY, XK_f}}, setlayout, {.v = &layouts[1]} }), ++ &((Keychord){1, {{MODKEY, XK_m}}, setlayout, {.v = &layouts[2]} }), ++ &((Keychord){1, {{MODKEY, XK_space}}, setlayout, {0} }), ++ &((Keychord){1, {{MODKEY|ShiftMask, XK_space}}, togglefloating, {0} }), ++ &((Keychord){1, {{MODKEY, XK_0}}, view, {.ui = ~0 } }), ++ &((Keychord){1, {{MODKEY|ShiftMask, XK_0}}, tag, {.ui = ~0 } }), ++ &((Keychord){1, {{MODKEY, XK_comma}}, focusmon, {.i = -1 } }), ++ &((Keychord){1, {{MODKEY, XK_period}}, focusmon, {.i = +1 } }), ++ &((Keychord){1, {{MODKEY|ShiftMask, XK_comma}}, tagmon, {.i = -1 } }), ++ &((Keychord){1, {{MODKEY|ShiftMask, XK_period}}, tagmon, {.i = +1 } }), ++ &((Keychord){1, {{MODKEY|ShiftMask, XK_q}}, quit, {0} }), ++ TAGKEYS( XK_1, 0) ++ TAGKEYS( XK_2, 1) ++ TAGKEYS( XK_3, 2) ++ TAGKEYS( XK_4, 3) ++ TAGKEYS( XK_5, 4) ++ TAGKEYS( XK_6, 5) ++ TAGKEYS( XK_7, 6) ++ TAGKEYS( XK_8, 7) ++ TAGKEYS( XK_9, 8) + }; + + /* button definitions */ +diff --git a/dwm.c b/dwm.c +index f1d86b2..e4885a4 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -102,9 +102,14 @@ struct Client { + typedef struct { + unsigned int mod; + KeySym keysym; ++} Key; ++ ++typedef struct { ++ unsigned int n; ++ const Key keys[5]; + void (*func)(const Arg *); + const Arg arg; +-} Key; ++} Keychord; + + typedef struct { + const char *symbol; +@@ -267,6 +272,7 @@ static Display *dpy; + static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; ++unsigned int currentkey = 0; + + /* configuration, allows nested code to access above variables */ + #include "config.h" +@@ -954,7 +960,8 @@ grabkeys(void) + { + updatenumlockmask(); + { +- unsigned int i, j, k; ++ /* unsigned int i, j, k; */ ++ unsigned int i, c, k; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + int start, end, skip; + KeySym *syms; +@@ -964,15 +971,18 @@ grabkeys(void) + syms = XGetKeyboardMapping(dpy, start, end - start + 1, &skip); + if (!syms) + return; ++ + for (k = start; k <= end; k++) +- for (i = 0; i < LENGTH(keys); i++) ++ for (i = 0; i < LENGTH(keychords); i++) + /* skip modifier codes, we do that ourselves */ +- if (keys[i].keysym == syms[(k - start) * skip]) +- for (j = 0; j < LENGTH(modifiers); j++) ++ if (keychords[i]->keys[currentkey].keysym == syms[(k - start) * skip]) ++ for (c = 0; c < LENGTH(modifiers); c++) + XGrabKey(dpy, k, +- keys[i].mod | modifiers[j], ++ keychords[i]->keys[currentkey].mod | modifiers[c], + root, True, + GrabModeAsync, GrabModeAsync); ++ if(currentkey > 0) ++ XGrabKey(dpy, XKeysymToKeycode(dpy, XK_Escape), AnyModifier, root, True, GrabModeAsync, GrabModeAsync); + XFree(syms); + } + } +@@ -999,17 +1009,51 @@ isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) + void + keypress(XEvent *e) + { +- unsigned int i; ++ /* unsigned int i; */ ++ XEvent event = *e; ++ unsigned int ran = 0; + KeySym keysym; + XKeyEvent *ev; + +- ev = &e->xkey; +- keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); +- for (i = 0; i < LENGTH(keys); i++) +- if (keysym == keys[i].keysym +- && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) +- && keys[i].func) +- keys[i].func(&(keys[i].arg)); ++ Keychord *arr1[sizeof(keychords) / sizeof(Keychord*)]; ++ Keychord *arr2[sizeof(keychords) / sizeof(Keychord*)]; ++ memcpy(arr1, keychords, sizeof(keychords)); ++ Keychord **rpointer = arr1; ++ Keychord **wpointer = arr2; ++ ++ size_t r = sizeof(keychords)/ sizeof(Keychord*); ++ ++ while(1){ ++ ev = &event.xkey; ++ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); ++ size_t w = 0; ++ for (int i = 0; i < r; i++){ ++ if(keysym == (*(rpointer + i))->keys[currentkey].keysym ++ && CLEANMASK((*(rpointer + i))->keys[currentkey].mod) == CLEANMASK(ev->state) ++ && (*(rpointer + i))->func){ ++ if((*(rpointer + i))->n == currentkey +1){ ++ (*(rpointer + i))->func(&((*(rpointer + i))->arg)); ++ ran = 1; ++ }else{ ++ *(wpointer + w) = *(rpointer + i); ++ w++; ++ } ++ } ++ } ++ currentkey++; ++ if(w == 0 || ran == 1) ++ break; ++ grabkeys(); ++ while (running && !XNextEvent(dpy, &event) && !ran) ++ if(event.type == KeyPress) ++ break; ++ r = w; ++ Keychord **holder = rpointer; ++ rpointer = wpointer; ++ wpointer = holder; ++ } ++ currentkey = 0; ++ grabkeys(); + } + + void +-- +2.41.0 diff --git a/dwm/patches/dwm-layoutmenu-6.2.diff b/dwm/patches/dwm-layoutmenu-6.2.diff new file mode 100644 index 0000000..9a2417e --- /dev/null +++ b/dwm/patches/dwm-layoutmenu-6.2.diff @@ -0,0 +1,88 @@ +# From e45e286b3d639b90ef202996d87054cced1fd80e Mon Sep 17 00:00:00 2001 +# From: tdu <tdukv@protonmail.com> +# Date: Mon, 31 Aug 2020 00:07:32 +0300 +# Subject: [PATCH] Right clicking the layout symbol opens an xmenu prompt to +# select layout. +# +# Xmenu need to be installed for this to work. +# Edit layoutmenu with the correct layout table, and place in PATH. +# --- +# config.def.h | 3 ++- +# dwm.c | 19 +++++++++++++++++++ +# layoutmenu | 7 +++++++ +# 3 files changed, 28 insertions(+), 1 deletion(-) +# create mode 100755 layoutmenu + +diff --git a/config.def.h b/config.def.h +index 1c0b587..c9e0833 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -58,6 +58,7 @@ static const Layout layouts[] = { + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { "st", NULL }; ++static const char *layoutmenu_cmd = "layoutmenu"; + + static Key keys[] = { + /* modifier key function argument */ +@@ -101,7 +102,7 @@ static Key keys[] = { + static Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, +- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, ++ { ClkLtSymbol, 0, Button3, layoutmenu, {0} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, +diff --git a/dwm.c b/dwm.c +index 4465af1..2508a0a 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -177,6 +177,7 @@ static void grabkeys(void); + static void incnmaster(const Arg *arg); + static void keypress(XEvent *e); + static void killclient(const Arg *arg); ++static void layoutmenu(const Arg *arg); + static void manage(Window w, XWindowAttributes *wa); + static void mappingnotify(XEvent *e); + static void maprequest(XEvent *e); +@@ -1014,6 +1015,24 @@ killclient(const Arg *arg) + } + } + ++void ++layoutmenu(const Arg *arg) { ++ FILE *p; ++ char c[3], *s; ++ int i; ++ ++ if (!(p = popen(layoutmenu_cmd, "r"))) ++ return; ++ s = fgets(c, sizeof(c), p); ++ pclose(p); ++ ++ if (!s || *s == '\0' || c[0] == '\0') ++ return; ++ ++ i = atoi(c); ++ setlayout(&((Arg) { .v = &layouts[i] })); ++} ++ + void + manage(Window w, XWindowAttributes *wa) + { +diff --git a/layoutmenu b/layoutmenu +new file mode 100755 +index 0000000..1bf95f2 +--- /dev/null ++++ b/layoutmenu +@@ -0,0 +1,7 @@ ++#!/bin/sh ++ ++cat <<EOF | xmenu ++[]= Tiled Layout 0 ++><> Floating Layout 1 ++[M] Monocle Layout 2 ++EOF +-- +2.28.0 diff --git a/dwm/patches/dwm-layoutscroll-6.2.diff b/dwm/patches/dwm-layoutscroll-6.2.diff new file mode 100644 index 0000000..95e621d --- /dev/null +++ b/dwm/patches/dwm-layoutscroll-6.2.diff @@ -0,0 +1,67 @@ +diff --git a/config.def.h b/config.def.h +index 4c56466..11ee7b5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -90,6 +90,8 @@ static Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_h, layoutscroll, {.i = -1 } }, ++ { MODKEY|ShiftMask, XK_l, layoutscroll, {.i = +1 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) +diff --git a/dwm.c b/dwm.c +index 1e37fcf..24effbc 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -148,6 +148,7 @@ struct Monitor { + Monitor *next; + Window barwin; + const Layout *lt[2]; ++ int ltcur; /* current layout */ + }; + + typedef struct { +@@ -227,6 +228,7 @@ static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); ++static void layoutscroll(const Arg *arg); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); +@@ -725,6 +727,7 @@ createmon(void) + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; ++ m->ltcur = 0; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); +@@ -1667,6 +1670,25 @@ setfullscreen(Client *c, int fullscreen) + } + } + ++void ++layoutscroll(const Arg *arg) ++{ ++ if (!arg || !arg->i) ++ return; ++ int switchto = selmon->ltcur + arg->i; ++ int l = LENGTH(layouts); ++ ++ if (switchto == l) ++ switchto = 0; ++ else if(switchto < 0) ++ switchto = l - 1; ++ ++ selmon->ltcur = switchto; ++ Arg arg2 = {.v= &layouts[switchto] }; ++ setlayout(&arg2); ++ ++} ++ + void + setlayout(const Arg *arg) + { diff --git a/dwm/patches/dwm-mark-new-6.2.diff b/dwm/patches/dwm-mark-new-6.2.diff new file mode 100644 index 0000000..711c3fd --- /dev/null +++ b/dwm/patches/dwm-mark-new-6.2.diff @@ -0,0 +1,247 @@ +# From 753860d3435e2968358f2bf8daf70bf625fe75fe Mon Sep 17 00:00:00 2001 +# From: Kajetan Puchalski <kajetan.puchalski@tuta.io> +# Date: Mon, 5 Oct 2020 11:04:31 +0100 +# Subject: [PATCH] Updated Mark patch to work with 6.2 +# +# --- +# config.def.h | 14 +++++-- +# drw.h | 2 +- +# dwm.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- +# 3 files changed, 118 insertions(+), 9 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 3858d75..a416c97 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -12,10 +12,13 @@ static const char col_gray2[] = "#444444"; + static const char col_gray3[] = "#bbbbbb"; + static const char col_gray4[] = "#eeeeee"; + static const char col_cyan[] = "#005577"; +-static const char *colors[][3] = { +- /* fg bg border */ +- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, +- [SchemeSel] = { col_gray4, col_cyan, col_cyan }, ++static const char normmarkcolor[] = "#775500"; /*border color for marked client*/ ++static const char selmarkcolor[] = "#775577"; /*border color for marked client on focus*/ ++ ++static const char *colors[][4] = { ++ /* fg bg border mark */ ++ [SchemeNorm] = { col_gray3, col_gray1, col_gray2, normmarkcolor }, ++ [SchemeSel] = { col_gray4, col_cyan, col_cyan, selmarkcolor }, + }; + + /* tagging */ +@@ -94,6 +97,9 @@ static Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY, XK_semicolon, togglemark, {0} }, ++ { MODKEY, XK_o, swapfocus, {0} }, ++ { MODKEY, XK_u, swapclient, {0} }, + }; + + /* button definitions */ +diff --git a/drw.h b/drw.h +index 4bcd5ad..97aae99 100644 +--- a/drw.h ++++ b/drw.h +@@ -12,7 +12,7 @@ typedef struct Fnt { + struct Fnt *next; + } Fnt; + +-enum { ColFg, ColBg, ColBorder }; /* Clr scheme index */ ++enum { ColFg, ColBg, ColBorder, ColMark }; /* Clr scheme index */ + typedef XftColor Clr; + + typedef struct { +diff --git a/dwm.c b/dwm.c +index 664c527..195b8eb 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -201,17 +201,21 @@ static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); + static void setlayout(const Arg *arg); ++static void setmark(Client *c); + static void setmfact(const Arg *arg); + static void setup(void); + static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); ++static void swapclient(const Arg *arg); ++static void swapfocus(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void togglemark(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); +@@ -268,6 +272,7 @@ static Display *dpy; + static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; ++static Client *mark; + + /* configuration, allows nested code to access above variables */ + #include "config.h" +@@ -796,7 +801,10 @@ focus(Client *c) + detachstack(c); + attachstack(c); + grabbuttons(c, 1); +- XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); ++ if (c == mark) ++ XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColMark].pixel); ++ else ++ XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); +@@ -1052,7 +1060,10 @@ manage(Window w, XWindowAttributes *wa) + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); +- XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); ++ if (c == mark) ++ XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColMark].pixel); ++ else ++ XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); + updatesizehints(c); +@@ -1512,6 +1523,23 @@ setlayout(const Arg *arg) + drawbar(selmon); + } + ++void ++setmark(Client *c) ++{ ++ if (c == mark) ++ return; ++ if (mark) { ++ XSetWindowBorder(dpy, mark->win, scheme[mark == selmon->sel ++ ? SchemeSel : SchemeNorm][ColBorder].pixel); ++ mark = 0; ++ } ++ if (c) { ++ XSetWindowBorder(dpy, c->win, scheme[c == selmon->sel ++ ? SchemeSel : SchemeNorm][ColMark].pixel); ++ mark = c; ++ } ++} ++ + /* arg > 1.0 will set mfact absolutely */ + void + setmfact(const Arg *arg) +@@ -1570,7 +1598,7 @@ setup(void) + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) +- scheme[i] = drw_scm_create(drw, colors[i], 3); ++ scheme[i] = drw_scm_create(drw, colors[i], 4); + /* init bars */ + updatebars(); + updatestatus(); +@@ -1653,6 +1681,75 @@ spawn(const Arg *arg) + } + } + ++void ++swapclient(const Arg *arg) ++{ ++ Client *s, *m, t; ++ ++ if (!mark || !selmon->sel || mark == selmon->sel ++ || !selmon->lt[selmon->sellt]->arrange) ++ return; ++ s = selmon->sel; ++ m = mark; ++ t = *s; ++ strcpy(s->name, m->name); ++ s->win = m->win; ++ s->x = m->x; ++ s->y = m->y; ++ s->w = m->w; ++ s->h = m->h; ++ ++ m->win = t.win; ++ strcpy(m->name, t.name); ++ m->x = t.x; ++ m->y = t.y; ++ m->w = t.w; ++ m->h = t.h; ++ ++ selmon->sel = m; ++ mark = s; ++ focus(s); ++ setmark(m); ++ ++ arrange(s->mon); ++ if (s->mon != m->mon) { ++ arrange(m->mon); ++ } ++} ++ ++void ++swapfocus(const Arg *arg) ++{ ++ Client *t; ++ ++ if (!selmon->sel || !mark || selmon->sel == mark) ++ return; ++ t = selmon->sel; ++ if (mark->mon != selmon) { ++ unfocus(selmon->sel, 0); ++ selmon = mark->mon; ++ } ++ if (ISVISIBLE(mark)) { ++ focus(mark); ++ restack(selmon); ++ } else { ++ selmon->seltags ^= 1; ++ selmon->tagset[selmon->seltags] = mark->tags; ++ focus(mark); ++ arrange(selmon); ++ } ++ setmark(t); ++} ++ ++void ++togglemark(const Arg *arg) ++{ ++ if (!selmon->sel) ++ return; ++ setmark(selmon->sel == mark ? 0 : selmon->sel); ++} ++ ++ + void + tag(const Arg *arg) + { +@@ -1755,7 +1852,10 @@ unfocus(Client *c, int setfocus) + if (!c) + return; + grabbuttons(c, 0); +- XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); ++ if (c == mark) ++ XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColMark].pixel); ++ else ++ XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +@@ -1768,6 +1868,9 @@ unmanage(Client *c, int destroyed) + Monitor *m = c->mon; + XWindowChanges wc; + ++ if (c == mark) ++ setmark(0); ++ + detach(c); + detachstack(c); + if (!destroyed) { +-- +2.28.0 diff --git a/dwm/patches/dwm-movecenter-6.5.diff b/dwm/patches/dwm-movecenter-6.5.diff new file mode 100644 index 0000000..b24977a --- /dev/null +++ b/dwm/patches/dwm-movecenter-6.5.diff @@ -0,0 +1,41 @@ +diff --git a/config.def.h b/config.def.h +index 9efa774..89a958a 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -85,6 +85,7 @@ static const Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY, XK_x, movecenter, {0} }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) +diff --git a/dwm.c b/dwm.c +index f1d86b2..ad534ad 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -184,6 +184,7 @@ static void maprequest(XEvent *e); + static void monocle(Monitor *m); + static void motionnotify(XEvent *e); + static void movemouse(const Arg *arg); ++static void movecenter(const Arg *arg); + static Client *nexttiled(Client *c); + static void pop(Client *c); + static void propertynotify(XEvent *e); +@@ -1202,6 +1203,16 @@ movemouse(const Arg *arg) + } + } + ++void ++movecenter(const Arg *arg) ++{ ++ if (selmon->sel) { ++ selmon->sel->x = selmon->sel->mon->mx + (selmon->sel->mon->mw - WIDTH(selmon->sel)) / 2; ++ selmon->sel->y = selmon->sel->mon->my + (selmon->sel->mon->mh - HEIGHT(selmon->sel)) / 2; ++ arrange(selmon); ++ } ++} ++ + Client * + nexttiled(Client *c) + { diff --git a/dwm/patches/dwm-multimon-1-monitor_marker-6.4.diff b/dwm/patches/dwm-multimon-1-monitor_marker-6.4.diff new file mode 100644 index 0000000..ea4b851 --- /dev/null +++ b/dwm/patches/dwm-multimon-1-monitor_marker-6.4.diff @@ -0,0 +1,194 @@ +# From c13f9b5a379422525ec7f714d83a1cbb0e3251c2 Mon Sep 17 00:00:00 2001 +# From: "Gary B. Genett" <me@garybgenett.net> +# Date: Sun, 19 Feb 2023 08:56:42 -0800 +# Subject: added monitor marker to bar +# MIME-Version: 1.0 +# Content-Type: multipart/mixed; boundary="------------2.37.4" +# +# This is a multi-part message in MIME format. +# --------------2.37.4 +# Content-Type: text/plain; charset=UTF-8; format=fixed +# Content-Transfer-Encoding: 8bit +# +# --- +# config.def.h | 2 ++ +# dwm.c | 12 +++++++++++- +# 2 files changed, 13 insertions(+), 1 deletion(-) +# +# +# --------------2.37.4 +# Content-Type: text/x-patch; name="0001-added-monitor-marker-to-bar.patch" +# Content-Transfer-Encoding: 8bit +# Content-Disposition: attachment; filename="0001-added-monitor-marker-to-bar.patch" + +diff --git a/config.def.h b/config.def.h +index 9efa7744b39c8b0ff0cf09a504a2539910c2881c..9d549ce8628e1a7769ee2a3d5c0a4c6d56ce6931 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -96,20 +96,22 @@ static const Key keys[] = { + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, + }; + + /* button definitions */ + /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ + static const Button buttons[] = { + /* click event mask button function argument */ + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, ++ { ClkMonNum, 0, Button1, focusmon, {.i = +1} }, ++ { ClkMonNum, 0, Button3, focusmon, {.i = -1} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; +diff --git a/dwm.c b/dwm.c +index c2bd8710544eb4b4e7eaa4a1307e1f1dfd8d16ba..bc5160a7d46ab07da82f0595abb7700debb2b891 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -57,21 +57,21 @@ + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ + enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +-enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ++enum { ClkTagBar, ClkLtSymbol, ClkMonNum, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + + typedef union { + int i; + unsigned int ui; + float f; + const void *v; + } Arg; + + typedef struct { +@@ -106,20 +106,21 @@ typedef struct { + const Arg arg; + } Key; + + typedef struct { + const char *symbol; + void (*arrange)(Monitor *); + } Layout; + + struct Monitor { + char ltsymbol[16]; ++ char monmark[16]; + float mfact; + int nmaster; + int num; + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; +@@ -434,20 +435,22 @@ buttonpress(XEvent *e) + if (ev->window == selmon->barwin) { + i = x = 0; + do + x += TEXTW(tags[i]); + while (ev->x >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; + } else if (ev->x < x + TEXTW(selmon->ltsymbol)) + click = ClkLtSymbol; ++ else if (ev->x < x + TEXTW(selmon->ltsymbol) + TEXTW(selmon->monmark)) ++ click = ClkMonNum; + else if (ev->x > selmon->ww - (int)TEXTW(stext)) + click = ClkStatusText; + else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } +@@ -637,20 +640,22 @@ createmon(void) + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ /* this is actually set in updategeom, to avoid a race condition */ ++// snprintf(m->monmark, sizeof(m->monmark), "(%d)", m->num); + return m; + } + + void + destroynotify(XEvent *e) + { + Client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) +@@ -726,20 +731,23 @@ drawbar(Monitor *m) + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); + x += w; + } + w = TEXTW(m->ltsymbol); + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); ++ w = TEXTW(m->monmark); ++ drw_setscheme(drw, scheme[SchemeNorm]); ++ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->monmark, 0); + + if ((w = m->ww - tw - x) > bh) { + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); +@@ -1886,20 +1894,22 @@ updategeom(void) + 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; ++ /* this is ugly, but it is a race condition otherwise */ ++ snprintf(m->monmark, sizeof(m->monmark), "(%d)", m->num); + 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); + } + /* removed monitors if n > nn */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + +--------------2.37.4-- diff --git a/dwm/patches/dwm-multimon-2-unified_view-6.4.diff b/dwm/patches/dwm-multimon-2-unified_view-6.4.diff new file mode 100644 index 0000000..9815e92 --- /dev/null +++ b/dwm/patches/dwm-multimon-2-unified_view-6.4.diff @@ -0,0 +1,181 @@ +# From 96ebf3ddfad143aec93a7d2aa212389121ccae41 Mon Sep 17 00:00:00 2001 +# From: "Gary B. Genett" <me@garybgenett.net> +# Date: Sun, 19 Feb 2023 08:57:30 -0800 +# Subject: added n*view wrappers, for unified multi-monitor +# MIME-Version: 1.0 +# Content-Type: multipart/mixed; boundary="------------2.37.4" +# +# This is a multi-part message in MIME format. +# --------------2.37.4 +# Content-Type: text/plain; charset=UTF-8; format=fixed +# Content-Transfer-Encoding: 8bit +# +# --- +# config.def.h | 5 +++++ +# dwm.c | 26 ++++++++++++++++++++++++++ +# 2 files changed, 31 insertions(+) +# +# +# --------------2.37.4 +# Content-Type: text/x-patch; name="0002-added-n-view-wrappers-for-unified-multi-monitor.patch" +# Content-Transfer-Encoding: 8bit +# Content-Disposition: attachment; filename="0002-added-n-view-wrappers-for-unified-multi-monitor.patch" + +diff --git a/config.def.h b/config.def.h +index 9d549ce8628e1a7769ee2a3d5c0a4c6d56ce6931..c59d27597a62ddf884baacded2830a318db1b45c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -38,24 +38,27 @@ static const int resizehints = 1; /* 1 means respect size hints in tiled resi + static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + + static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, + }; + + /* key definitions */ ++#define WINKEY Mod4Mask + #define MODKEY Mod1Mask + #define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ ++ { MODKEY|WINKEY, KEY, nview, {.ui = 1 << TAG} }, \ ++ { MODKEY|WINKEY|ControlMask, KEY, ntoggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, + + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + + /* commands */ + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { "st", NULL }; +@@ -105,14 +108,16 @@ static const Button buttons[] = { + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkMonNum, 0, Button1, focusmon, {.i = +1} }, + { ClkMonNum, 0, Button3, focusmon, {.i = -1} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, ++ { ClkTagBar, MODKEY|WINKEY, Button1, nview, {0} }, ++ { ClkTagBar, MODKEY|WINKEY, Button3, ntoggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; + +diff --git a/dwm.c b/dwm.c +index bc5160a7d46ab07da82f0595abb7700debb2b891..2cf8d78c22c64ff26eda6195b6bd503f213a4d5f 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -206,34 +206,36 @@ static void setmfact(const Arg *arg); + static void setup(void); + static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); ++static void ntoggleview(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); + static void unmanage(Client *c, int destroyed); + static void unmapnotify(XEvent *e); + static void updatebarpos(Monitor *m); + static void updatebars(void); + static void updateclientlist(void); + static int updategeom(void); + static void updatenumlockmask(void); + static void updatesizehints(Client *c); + static void updatestatus(void); + static void updatetitle(Client *c); + static void updatewindowtype(Client *c); + static void updatewmhints(Client *c); ++static void nview(const Arg *arg); + static void view(const Arg *arg); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + + /* variables */ + static const char broken[] = "broken"; +@@ -1743,20 +1745,32 @@ toggletag(const Arg *arg) + if (!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; + focus(NULL); + arrange(selmon); + } + } + ++void ++ntoggleview(const Arg *arg) ++{ ++ const Arg n = {.i = +1}; ++ const int mon = selmon->num; ++ do { ++ focusmon(&n); ++ toggleview(arg); ++ } ++ while (selmon->num != mon); ++} ++ + void + toggleview(const Arg *arg) + { + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); + } +@@ -2045,20 +2059,32 @@ updatewmhints(Client *c) + } else + c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; + if (wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = 0; + XFree(wmh); + } + } + ++void ++nview(const Arg *arg) ++{ ++ const Arg n = {.i = +1}; ++ const int mon = selmon->num; ++ do { ++ focusmon(&n); ++ view(arg); ++ } ++ while (selmon->num != mon); ++} ++ + void + view(const Arg *arg) + { + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); + +--------------2.37.4-- diff --git a/dwm/patches/dwm-multimon-4-status_all-6.4.diff b/dwm/patches/dwm-multimon-4-status_all-6.4.diff new file mode 100644 index 0000000..5059958 --- /dev/null +++ b/dwm/patches/dwm-multimon-4-status_all-6.4.diff @@ -0,0 +1,102 @@ +# From 34d7ca93ff7fff443f9cf0ce6ba6da6acbcfe06c Mon Sep 17 00:00:00 2001 +# From: "Gary B. Genett" <me@garybgenett.net> +# Date: Sun, 19 Feb 2023 08:59:36 -0800 +# Subject: added statusall toggle +# MIME-Version: 1.0 +# Content-Type: multipart/mixed; boundary="------------2.37.4" +# +# This is a multi-part message in MIME format. +# --------------2.37.4 +# Content-Type: text/plain; charset=UTF-8; format=fixed +# Content-Transfer-Encoding: 8bit +# +# --- +# config.def.h | 1 + +# dwm.c | 4 ++-- +# 2 files changed, 3 insertions(+), 2 deletions(-) +# +# +# --------------2.37.4 +# Content-Type: text/x-patch; name="0004-added-statusall-toggle.patch" +# Content-Transfer-Encoding: 8bit +# Content-Disposition: attachment; filename="0004-added-statusall-toggle.patch" + +diff --git a/config.def.h b/config.def.h +index a664c793845c4c7c0ebe8ac69c96885c76193819..fcfe8245a438686f276ffc9a4df17695382ed58b 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -29,20 +29,21 @@ static const Rule rules[] = { + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, 1, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, + }; + + /* layout(s) */ + static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ + static const int nmaster = 1; /* number of clients in master area */ + static const int nviews = 3; /* mask of tags highlighted by default (tags 1-4) */ + static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ ++static const int statusall = 1; /* 1 means status is shown in all bars, not just active monitor */ + static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + + static const float facts[1]; //static const float facts[] = { 0, 0.5 }; // = mfact // 50% + static const int masters[1]; //static const int masters[] = { 0, -1 }; // = nmaster // vertical stacking (for rotated monitor) + static const int views[1]; //static const int views[] = { 0, ~0 }; // = nviews // all tags + /* invert tags after nviews */ /* array dimentions can both be as big as needed */ // final highlighted tags + static const int toggles[1][1]; //static const int toggles[2][2] = { {0,8}, {~0,~0} }; // 2-4+9 // all (leave as views above) + static const int toggles[1][1] = {{~0}}; + + static const Layout layouts[] = { + /* symbol arrange function */ +diff --git a/dwm.c b/dwm.c +index 93da0f4565d7a17ef96a1b167cfcb2c9f0ac6ad3..77ff310e03edbf42ac2dd55471962ce259b63071 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -709,21 +709,21 @@ drawbar(Monitor *m) + int x, w, tw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; + Client *c; + + if (!m->showbar) + return; + + /* draw status first so it can be overdrawn by tags later */ +- if (m == selmon) { /* status is only drawn on selected monitor */ ++ if (m == selmon || statusall) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); + } + + for (c = m->clients; c; c = c->next) { + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; + } +@@ -2017,21 +2017,21 @@ updatesizehints(Client *c) + c->maxa = c->mina = 0.0; + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); + c->hintsvalid = 1; + } + + void + updatestatus(void) + { + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); +- drawbar(selmon); ++ statusall ? drawbars() : drawbar(selmon); + } + + void + updatetitle(Client *c) + { + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) + gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); + if (c->name[0] == '\0') /* hack to mark broken clients */ + strcpy(c->name, broken); + } + +--------------2.37.4-- diff --git a/dwm/patches/dwm-multimon-6-swap_focus-6.4.diff b/dwm/patches/dwm-multimon-6-swap_focus-6.4.diff new file mode 100644 index 0000000..9bd091a --- /dev/null +++ b/dwm/patches/dwm-multimon-6-swap_focus-6.4.diff @@ -0,0 +1,185 @@ +# From de73c72af0250f56f9ac30a5c3f4520da250282a Mon Sep 17 00:00:00 2001 +# From: "Gary B. Genett" <me@garybgenett.net> +# Date: Sun, 19 Feb 2023 09:40:00 -0800 +# Subject: patches/swapfocus: dwm-swapfocus-20160731-56a31dc.diff +# MIME-Version: 1.0 +# Content-Type: multipart/mixed; boundary="------------2.37.4" +# +# This is a multi-part message in MIME format. +# --------------2.37.4 +# Content-Type: text/plain; charset=UTF-8; format=fixed +# Content-Transfer-Encoding: 8bit +# +# +# modified from sites: 38b351cf3689ff3fa4845d35ce9894fd9253dbb8 +# --- +# config.def.h | 1 + +# dwm.c | 19 ++++++++++++++++++- +# 2 files changed, 19 insertions(+), 1 deletion(-) +# +# +# --------------2.37.4 +# Content-Type: text/x-patch; name="0006-patches-swapfocus-dwm-swapfocus-20160731-56a31dc.dif.patch" +# Content-Transfer-Encoding: 8bit +# Content-Disposition: attachment; filename="0006-patches-swapfocus-dwm-swapfocus-20160731-56a31dc.dif.patch" + +diff --git a/config.def.h b/config.def.h +index fd00f7080db9271912d0e4352434739d3c08e1b3..9a1118791c3a2f875b58bf3979db5074416b8634 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -79,20 +79,21 @@ static const Key keys[] = { + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY|ShiftMask, XK_j, pushdown, {0} }, + { MODKEY|ShiftMask, XK_k, pushup, {0} }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, ++ { MODKEY|ShiftMask, XK_Tab, swapfocus, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, + { MODKEY, XK_period, focusmon, {.i = +1 } }, +diff --git a/dwm.c b/dwm.c +index 5aa229611a27b8aa943308314b494c10e2364137..ac52b8c25991a073db15b55fae774e9c47a05708 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -203,20 +203,21 @@ static int sendevent(Client *c, Atom proto); + static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); + static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void spawn(const Arg *arg); ++static void swapfocus(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); + static void ntoggleview(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); + static void unmanage(Client *c, int destroyed); +@@ -235,20 +236,21 @@ static void nview(const Arg *arg); + static void view(const Arg *arg); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + static void reset_view(const Arg *arg); + + /* variables */ ++static Client *prevclient = NULL; + static const char broken[] = "broken"; + static char stext[256]; + static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh; /* bar height */ + static int lrpad; /* sum of left and right padding for text */ + static int (*xerrorxlib)(Display *, XErrorEvent *); + static unsigned int numlockmask = 0; + static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, +@@ -1721,20 +1723,32 @@ spawn(const Arg *arg) + dmenumon[0] = '0' + selmon->num; + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + die("dwm: execvp '%s' failed:", ((char **)arg->v)[0]); + } + } + ++void ++swapfocus(const Arg *arg) ++{ ++ Client *c; ++ ++ for(c = selmon->clients; c && c != prevclient; c = c->next) ; ++ if(c == prevclient) { ++ focus(prevclient); ++ restack(prevclient->mon); ++ } ++} ++ + void + tag(const Arg *arg) + { + if (selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); + } + } + +@@ -1834,20 +1848,21 @@ toggleview(const Arg *arg) + focus(NULL); + arrange(selmon); + } + } + + void + unfocus(Client *c, int setfocus) + { + if (!c) + return; ++ prevclient = c; + grabbuttons(c, 0); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + } + + void + unmanage(Client *c, int destroyed) +@@ -2213,25 +2228,27 @@ int + xerrorstart(Display *dpy, XErrorEvent *ee) + { + die("dwm: another window manager is already running"); + return -1; + } + + void + zoom(const Arg *arg) + { + Client *c = selmon->sel; ++ prevclient = nexttiled(selmon->clients); + + if (!selmon->lt[selmon->sellt]->arrange || !c || c->isfloating) + return; + if (c == nexttiled(selmon->clients) && !(c = nexttiled(c->next))) +- return; ++ if (!c || !(c = prevclient = nexttiled(c->next))) ++ return; + pop(c); + } + + void + reset_view(const Arg *arg) { + const int mon = selmon->num; + Arg n = {.i = +1}; // focusmon(next monitor) + Arg m = {.f = 0}; // mfact -> facts[] + Arg i = {.i = 0}; // nmaster -> masters[] + Arg v = {.ui = 0}; // nviews -> views[] + +--------------2.37.4-- diff --git a/dwm/patches/dwm-multimon-7-focus_on_active-6.4.diff b/dwm/patches/dwm-multimon-7-focus_on_active-6.4.diff new file mode 100644 index 0000000..958ae04 --- /dev/null +++ b/dwm/patches/dwm-multimon-7-focus_on_active-6.4.diff @@ -0,0 +1,59 @@ +# From ef123521987ec72df95a05542f6558999b673863 Mon Sep 17 00:00:00 2001 +# From: "Gary B. Genett" <me@garybgenett.net> +# Date: Sun, 19 Feb 2023 09:09:23 -0800 +# Subject: patches/focusonnetactive: dwm-focusonnetactive-6.2.diff +# MIME-Version: 1.0 +# Content-Type: multipart/mixed; boundary="------------2.37.4" +# +# This is a multi-part message in MIME format. +# --------------2.37.4 +# Content-Type: text/plain; charset=UTF-8; format=fixed +# Content-Transfer-Encoding: 8bit +# +# +# modified from sites: 38b351cf3689ff3fa4845d35ce9894fd9253dbb8 +# used old dwm code instead: bb3bd6fec37174e8d4bb9457ca815c00609e5157 +# --- +# dwm.c | 7 +++++-- +# 1 file changed, 5 insertions(+), 2 deletions(-) +# +# +# --------------2.37.4 +# Content-Type: text/x-patch; name="0007-patches-focusonnetactive-dwm-focusonnetactive-6.2.di.patch" +# Content-Transfer-Encoding: 8bit +# Content-Disposition: attachment; filename="0007-patches-focusonnetactive-dwm-focusonnetactive-6.2.di.patch" + +diff --git a/dwm.c b/dwm.c +index ac52b8c25991a073db15b55fae774e9c47a05708..3294c2fe53785473397b6e978c79a704cb7e8f25 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -530,22 +530,25 @@ clientmessage(XEvent *e) + Client *c = wintoclient(cme->window); + + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); + } else if (cme->message_type == netatom[NetActiveWindow]) { +- if (c != selmon->sel && !c->isurgent) +- seturgent(c, 1); ++ if (!ISVISIBLE(c)) { ++ c->mon->seltags ^= 1; ++ c->mon->tagset[c->mon->seltags] = c->tags; ++ } ++ pop(c); + } + } + + void + configure(Client *c) + { + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.display = dpy; + +--------------2.37.4-- diff --git a/dwm/patches/dwm-multiple-dynamic-scratchpads.diff b/dwm/patches/dwm-multiple-dynamic-scratchpads.diff new file mode 100644 index 0000000..22d0000 --- /dev/null +++ b/dwm/patches/dwm-multiple-dynamic-scratchpads.diff @@ -0,0 +1,207 @@ +diff --git a/config.def.h b/config.def.h +index a2ac963..1c82453 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -95,6 +95,13 @@ static Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY, XK_s, scratchpad_show, {.i = 1} }, ++ { MODKEY, XK_y, scratchpad_show, {.i = 2} }, ++ { MODKEY, XK_u, scratchpad_show, {.i = 3} }, ++ { MODKEY|ShiftMask, XK_s, scratchpad_hide, {.i = 1} }, ++ { MODKEY|ShiftMask, XK_y, scratchpad_hide, {.i = 2} }, ++ { MODKEY|ShiftMask, XK_u, scratchpad_hide, {.i = 3} }, ++ { MODKEY|ShiftMask, XK_r, scratchpad_remove, {0} }, + }; + + /* button definitions */ +diff --git a/dwm.c b/dwm.c +index 5f16260..202038f 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -195,6 +195,11 @@ static void resizemouse(const Arg *arg); + static void restack(Monitor *m); + static void run(void); + static void scan(void); ++static void scratchpad_hide(); ++static void scratchpad_remove(); ++static void scratchpad_show(); ++static void scratchpad_show_client(Client *c); ++static void scratchpad_show_first(int scratchNum); + static int sendevent(Client *c, Atom proto); + static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); +@@ -269,11 +274,19 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++/* scratchpad */ ++#define SCRATCHPAD_MASK_1 (1u << sizeof tags / sizeof * tags) ++#define SCRATCHPAD_MASK_2 (1u << (sizeof tags / sizeof * tags + 1)) ++#define SCRATCHPAD_MASK_3 (1u << (sizeof tags / sizeof * tags + 2)) ++static int scratchpad_hide_flag = 0; ++static Client *scratchpad_last_showed_1 = NULL; ++static Client *scratchpad_last_showed_2 = NULL; ++static Client *scratchpad_last_showed_3 = NULL; + /* configuration, allows nested code to access above variables */ + #include "config.h" + + /* compile-time check if all tags fit into an unsigned int bit array. */ +-struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; ++struct NumTags { char limitexceeded[LENGTH(tags) > 28 ? -1 : 1]; }; + + /* function implementations */ + void +@@ -309,7 +322,9 @@ applyrules(Client *c) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); ++ if(c->tags != SCRATCHPAD_MASK_1 && c->tags != SCRATCHPAD_MASK_2 && c->tags != SCRATCHPAD_MASK_3) { + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; ++ } + } + + int +@@ -1412,6 +1427,124 @@ scan(void) + } + } + ++static void scratchpad_hide(const Arg *arg) { ++ if(scratchpad_hide_flag < 4) { ++ if(arg->i == 1) { ++ if(selmon->sel) { ++ selmon->sel->tags = SCRATCHPAD_MASK_1; ++ selmon->sel->isfloating = 1; ++ focus(NULL); ++ arrange(selmon); ++ scratchpad_hide_flag++; ++ } ++ } ++ else if(arg->i == 2) { ++ if(selmon->sel) { ++ selmon->sel->tags = SCRATCHPAD_MASK_2; ++ selmon->sel->isfloating = 1; ++ focus(NULL); ++ arrange(selmon); ++ scratchpad_hide_flag++; ++ } ++ } ++ else if(arg->i == 3) { ++ if(selmon->sel) { ++ selmon->sel->tags = SCRATCHPAD_MASK_3; ++ selmon->sel->isfloating = 1; ++ focus(NULL); ++ arrange(selmon); ++ scratchpad_hide_flag++; ++ } ++ } ++ } ++} ++ ++static void scratchpad_remove() { ++ if(selmon->sel && (scratchpad_last_showed_1 != NULL || scratchpad_last_showed_2 != NULL ||scratchpad_last_showed_3 != NULL) && (selmon->sel == scratchpad_last_showed_1 || selmon->sel == scratchpad_last_showed_2 || selmon->sel == scratchpad_last_showed_3)) { ++ if(scratchpad_last_showed_1 == selmon->sel) { ++ scratchpad_last_showed_1 = NULL; ++ scratchpad_hide_flag--; ++ } ++ else if(scratchpad_last_showed_2 == selmon->sel) { ++ scratchpad_last_showed_2 = NULL; ++ scratchpad_hide_flag--; ++ } ++ else if(scratchpad_last_showed_3 == selmon->sel) { ++ scratchpad_last_showed_3 = NULL; ++ scratchpad_hide_flag--; ++ } ++ } ++} ++ ++static void scratchpad_show(const Arg *arg) { ++ if(arg->i == 1) { ++ if(scratchpad_last_showed_1 == NULL) { ++ scratchpad_show_first(arg->i); ++ } ++ else { ++ if(scratchpad_last_showed_1->tags != SCRATCHPAD_MASK_1) { ++ scratchpad_last_showed_1->tags = SCRATCHPAD_MASK_1; ++ focus(NULL); ++ arrange(selmon); ++ } ++ else { ++ scratchpad_show_first(arg->i); ++ } ++ } ++ } ++ else if(arg->i == 2) { ++ if(scratchpad_last_showed_2 == NULL) { ++ scratchpad_show_first(arg->i); ++ } ++ else { ++ if(scratchpad_last_showed_2->tags != SCRATCHPAD_MASK_2) { ++ scratchpad_last_showed_2->tags = SCRATCHPAD_MASK_2; ++ focus(NULL); ++ arrange(selmon); ++ } ++ else { ++ scratchpad_show_first(arg->i); ++ } ++ } ++ } ++ else if(arg->i == 3) { ++ if(scratchpad_last_showed_3 == NULL) { ++ scratchpad_show_first(arg->i); ++ } ++ else { ++ if(scratchpad_last_showed_3->tags != SCRATCHPAD_MASK_3) { ++ scratchpad_last_showed_3->tags = SCRATCHPAD_MASK_3; ++ focus(NULL); ++ arrange(selmon); ++ } ++ else { ++ scratchpad_show_first(arg->i); ++ } ++ } ++ } ++} ++ ++static void scratchpad_show_client(Client *c) { ++ c->tags = selmon->tagset[selmon->seltags]; ++ focus(c); ++ arrange(selmon); ++} ++ ++static void scratchpad_show_first(int scratchNum) { ++ for(Client *c = selmon->clients; c !=NULL; c = c->next) { ++ if(c->tags == SCRATCHPAD_MASK_1 && scratchNum == 1) { ++ scratchpad_last_showed_1 = c; ++ scratchpad_show_client(c); ++ } else if(c->tags == SCRATCHPAD_MASK_2 && scratchNum == 2) { ++ scratchpad_last_showed_2 = c; ++ scratchpad_show_client(c); ++ } else if(c->tags == SCRATCHPAD_MASK_3 && scratchNum == 3) { ++ scratchpad_last_showed_3 = c; ++ scratchpad_show_client(c); ++ } ++ } ++} ++ + void + sendmon(Client *c, Monitor *m) + { +@@ -1785,6 +1918,16 @@ unmanage(Client *c, int destroyed) + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } ++ if(scratchpad_last_showed_1 == c) { ++ scratchpad_last_showed_1 = NULL; ++ } ++ if(scratchpad_last_showed_2 == c) { ++ scratchpad_last_showed_2 = NULL; ++ } ++ if(scratchpad_last_showed_3 == c) { ++ scratchpad_last_showed_3 = NULL; ++ } ++ + free(c); + focus(NULL); + updateclientlist(); diff --git a/dwm/patches/dwm-pertag_with_sel-20231003-9f88553.diff b/dwm/patches/dwm-pertag_with_sel-20231003-9f88553.diff new file mode 100644 index 0000000..70e3b5d --- /dev/null +++ b/dwm/patches/dwm-pertag_with_sel-20231003-9f88553.diff @@ -0,0 +1,214 @@ +# From b47a32da69a1bb6f60b9c81619f3e504278cc780 Mon Sep 17 00:00:00 2001 +# From: Leonardo-Boss <70913810+Leonardo-Boss@users.noreply.github.com> +# Date: Tue, 3 Oct 2023 12:33:58 -0300 +# Subject: [PATCH] pertag with last selection +# +# --- +# dwm.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- +# 1 file changed, 90 insertions(+), 7 deletions(-) + +diff --git a/dwm.c b/dwm.c +index f1d86b2..0e4d444 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -111,6 +111,7 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + ++typedef struct Pertag Pertag; + struct Monitor { + char ltsymbol[16]; + float mfact; +@@ -130,6 +131,7 @@ struct Monitor { + Monitor *next; + Window barwin; + const Layout *lt[2]; ++ Pertag *pertag; + }; + + typedef struct { +@@ -271,6 +273,16 @@ static Window root, wmcheckwin; + /* configuration, allows nested code to access above variables */ + #include "config.h" + ++struct Pertag { ++ unsigned int curtag, prevtag; /* current and previous tag */ ++ int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ ++ float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ ++ unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ ++ const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ ++ int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ ++ Client *sel[LENGTH(tags) + 1]; /* selected client */ ++}; ++ + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +@@ -634,6 +646,7 @@ Monitor * + createmon(void) + { + Monitor *m; ++ unsigned int i; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; +@@ -644,6 +657,20 @@ createmon(void) + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ m->pertag = ecalloc(1, sizeof(Pertag)); ++ m->pertag->curtag = m->pertag->prevtag = 1; ++ ++ for (i = 0; i <= LENGTH(tags); i++) { ++ m->pertag->nmasters[i] = m->nmaster; ++ m->pertag->mfacts[i] = m->mfact; ++ ++ m->pertag->ltidxs[i][0] = m->lt[0]; ++ m->pertag->ltidxs[i][1] = m->lt[1]; ++ m->pertag->sellts[i] = m->sellt; ++ ++ m->pertag->showbars[i] = m->showbar; ++ } ++ + return m; + } + +@@ -808,6 +835,7 @@ focus(Client *c) + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; ++ selmon->pertag->sel[selmon->pertag->curtag] = c; + drawbars(); + } + +@@ -980,7 +1008,7 @@ grabkeys(void) + void + incnmaster(const Arg *arg) + { +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); + } + +@@ -1511,9 +1539,9 @@ void + setlayout(const Arg *arg) + { + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +- selmon->sellt ^= 1; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; + if (arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); +@@ -1532,7 +1560,7 @@ setmfact(const Arg *arg) + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.05 || f > 0.95) + return; +- selmon->mfact = f; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; + arrange(selmon); + } + +@@ -1715,7 +1743,7 @@ tile(Monitor *m) + void + togglebar(const Arg *arg) + { +- selmon->showbar = !selmon->showbar; ++ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +@@ -1754,9 +1782,33 @@ void + toggleview(const Arg *arg) + { + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); ++ int i; + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; ++ ++ if (newtagset == ~0) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = 0; ++ } ++ ++ /* test if the user did not select the same tag */ ++ if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ for (i = 0; !(newtagset & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } ++ ++ /* apply settings for this view */ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); ++ + focus(NULL); + arrange(selmon); + } +@@ -1778,9 +1830,14 @@ unfocus(Client *c, int setfocus) + void + unmanage(Client *c, int destroyed) + { ++ int i; + Monitor *m = c->mon; + XWindowChanges wc; + ++ for (i = 0; i < LENGTH(tags) + 1; i++) ++ if (c->mon->pertag->sel[i] == c) ++ c->mon->pertag->sel[i] = NULL; ++ + detach(c); + detachstack(c); + if (!destroyed) { +@@ -2053,12 +2110,38 @@ updatewmhints(Client *c) + void + view(const Arg *arg) + { ++ int i; ++ unsigned int tmptag; ++ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ +- if (arg->ui & TAGMASK) ++ if (arg->ui & TAGMASK) { + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; +- focus(NULL); ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ ++ if (arg->ui == ~0) ++ selmon->pertag->curtag = 0; ++ else { ++ for (i = 0; !(arg->ui & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } ++ } else { ++ tmptag = selmon->pertag->prevtag; ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = tmptag; ++ } ++ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); ++ ++ focus(selmon->pertag->sel[selmon->pertag->curtag]); + arrange(selmon); + } + +-- +2.41.0 diff --git a/dwm/patches/dwm-preserveonrestart-6.3.diff b/dwm/patches/dwm-preserveonrestart-6.3.diff new file mode 100644 index 0000000..9fed4d8 --- /dev/null +++ b/dwm/patches/dwm-preserveonrestart-6.3.diff @@ -0,0 +1,118 @@ +# From 713fa8650f5a20006451ebcccf57a4512e83bae8 Mon Sep 17 00:00:00 2001 +# From: Arda Atci <arda@phytech.io> +# Date: Wed, 18 May 2022 17:23:16 +0300 +# Subject: [PATCH] preserve clients on old tags when renewing dwm +# +# By default, when dwm is recompiled-restarted all clients will +# lose it's current tag and collapse to first tag. This patch preserves +# clients on old tags, however note that layout order is not preserved. +# +# --- +# dwm.c | 38 +++++++++++++++++++++++++++++++++++++- +# 1 file changed, 37 insertions(+), 1 deletion(-) + +diff --git a/dwm.c b/dwm.c +index a96f33c..a12e0bd 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -62,7 +62,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ + enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, +- NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ ++ NetWMWindowTypeDialog, NetClientList, NetClientInfo, NetLast }; /* EWMH atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ + enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ +@@ -198,6 +198,7 @@ static void scan(void); + static int sendevent(Client *c, Atom proto); + static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); ++static void setclienttagprop(Client *c); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); + static void setlayout(const Arg *arg); +@@ -1060,6 +1061,26 @@ manage(Window w, XWindowAttributes *wa) + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); ++ { ++ int format; ++ unsigned long *data, n, extra; ++ Monitor *m; ++ Atom atom; ++ if (XGetWindowProperty(dpy, c->win, netatom[NetClientInfo], 0L, 2L, False, XA_CARDINAL, ++ &atom, &format, &n, &extra, (unsigned char **)&data) == Success && n == 2) { ++ c->tags = *data; ++ for (m = mons; m; m = m->next) { ++ if (m->num == *(data+1)) { ++ c->mon = m; ++ break; ++ } ++ } ++ } ++ if (n > 0) ++ XFree(data); ++ } ++ setclienttagprop(c); ++ + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + if (!c->isfloating) +@@ -1423,6 +1444,7 @@ sendmon(Client *c, Monitor *m) + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); ++ setclienttagprop(c); + focus(NULL); + arrange(NULL); + } +@@ -1566,6 +1588,7 @@ setup(void) + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); ++ netatom[NetClientInfo] = XInternAtom(dpy, "_NET_CLIENT_INFO", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); +@@ -1589,6 +1612,7 @@ setup(void) + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, + PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); ++ XDeleteProperty(dpy, root, netatom[NetClientInfo]); + /* select events */ + wa.cursor = cursor[CurNormal]->cursor; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask +@@ -1656,11 +1680,22 @@ spawn(const Arg *arg) + } + } + ++void ++setclienttagprop(Client *c) ++{ ++ long data[] = { (long) c->tags, (long) c->mon->num }; ++ XChangeProperty(dpy, c->win, netatom[NetClientInfo], XA_CARDINAL, 32, ++ PropModeReplace, (unsigned char *) data, 2); ++} ++ + void + tag(const Arg *arg) + { ++ Client *c; + if (selmon->sel && arg->ui & TAGMASK) { ++ c = selmon->sel; + selmon->sel->tags = arg->ui & TAGMASK; ++ setclienttagprop(c); + focus(NULL); + arrange(selmon); + } +@@ -1735,6 +1770,7 @@ toggletag(const Arg *arg) + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; ++ setclienttagprop(selmon->sel); + focus(NULL); + arrange(selmon); + } +-- +2.36.1 diff --git a/dwm/patches/dwm-preventfocusshift-20240831-6.5.diff b/dwm/patches/dwm-preventfocusshift-20240831-6.5.diff new file mode 100644 index 0000000..a779208 --- /dev/null +++ b/dwm/patches/dwm-preventfocusshift-20240831-6.5.diff @@ -0,0 +1,24 @@ +# From 554f5a8a2205a7c52280babf5685462d8991b038 Mon Sep 17 00:00:00 2001 +# From: Suleyman Farajli <suleyman@farajli.net> +# Date: Sat, 31 Aug 2024 13:34:58 +0400 +# Subject: [PATCH] prevent focus shifting when a window is spawned in fullscreen +# +# --- +# dwm.c | 2 ++ +# 1 file changed, 2 insertions(+) + +diff --git a/dwm.c b/dwm.c +index f1d86b2..31b5d07 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1080,6 +1080,8 @@ manage(Window w, XWindowAttributes *wa) + (unsigned char *) &(c->win), 1); + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + setclientstate(c, NormalState); ++ if(selmon->sel && selmon->sel->isfullscreen && !c->isfloating) ++ setfullscreen(selmon->sel, 0); + if (c->mon == selmon) + unfocus(selmon->sel, 0); + c->mon->sel = c; +-- +2.44.2 diff --git a/dwm/patches/dwm-refreshrate-20230826-9554a10.diff b/dwm/patches/dwm-refreshrate-20230826-9554a10.diff new file mode 100644 index 0000000..aa93b19 --- /dev/null +++ b/dwm/patches/dwm-refreshrate-20230826-9554a10.diff @@ -0,0 +1,55 @@ +# From 9554a109e240789f76f0ece3e62f9014ceb8a4bc Mon Sep 17 00:00:00 2001 +# From: sewn <sewn@disroot.org> +# Date: Sat, 26 Aug 2023 22:57:51 +0300 +# Subject: [PATCH] dwm: remove resize/move limitation +# +# we have modern machines, and we have high refresh rate monitors; +# this makes resizing and moving windows have no limit when refreshing. +# --- +# dwm.c | 10 ---------- +# 1 file changed, 10 deletions(-) + +diff --git a/dwm.c b/dwm.c +index f1d86b2..4c00cbe 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1149,7 +1149,6 @@ movemouse(const Arg *arg) + Client *c; + Monitor *m; + XEvent ev; +- Time lasttime = 0; + + if (!(c = selmon->sel)) + return; +@@ -1172,10 +1171,6 @@ movemouse(const Arg *arg) + handler[ev.type](&ev); + break; + case MotionNotify: +- if ((ev.xmotion.time - lasttime) <= (1000 / 60)) +- continue; +- lasttime = ev.xmotion.time; +- + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + if (abs(selmon->wx - nx) < snap) +@@ -1304,7 +1299,6 @@ resizemouse(const Arg *arg) + Client *c; + Monitor *m; + XEvent ev; +- Time lasttime = 0; + + if (!(c = selmon->sel)) + return; +@@ -1326,10 +1320,6 @@ resizemouse(const Arg *arg) + handler[ev.type](&ev); + break; + case MotionNotify: +- if ((ev.xmotion.time - lasttime) <= (1000 / 60)) +- continue; +- lasttime = ev.xmotion.time; +- + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww +-- +2.42.0 diff --git a/dwm/patches/dwm-resetlayout-6.2.diff b/dwm/patches/dwm-resetlayout-6.2.diff new file mode 100644 index 0000000..e3cd587 --- /dev/null +++ b/dwm/patches/dwm-resetlayout-6.2.diff @@ -0,0 +1,64 @@ +# From 4df827a2ec7820f41bdb8576cc39b55fbf35be44 Mon Sep 17 00:00:00 2001 +# From: Jack Bird <jack.bird@durham.ac.uk> +# Date: Mon, 16 Aug 2021 23:25:16 +0100 +# Subject: [PATCH] Patch applies cleanly +# +# --- +# config.def.h | 1 + +# dwm.c | 15 +++++++++++++++ +# 2 files changed, 16 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..5d118cf 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -70,6 +70,7 @@ static Key keys[] = { + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, ++ { MODKEY, XK_r, resetlayout, {0} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, +diff --git a/dwm.c b/dwm.c +index 4465af1..77727ea 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -188,6 +188,7 @@ static void pop(Client *); + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); + static Monitor *recttomon(int x, int y, int w, int h); ++static void resetlayout(const Arg *arg); + static void resize(Client *c, int x, int y, int w, int h, int interact); + static void resizeclient(Client *c, int x, int y, int w, int h); + static void resizemouse(const Arg *arg); +@@ -1265,6 +1266,16 @@ recttomon(int x, int y, int w, int h) + return r; + } + ++void ++resetlayout(const Arg *arg) ++{ ++ Arg default_layout = {.v = &layouts[0]}; ++ Arg default_mfact = {.f = mfact + 1}; ++ ++ setlayout(&default_layout); ++ setmfact(&default_mfact); ++} ++ + void + resize(Client *c, int x, int y, int w, int h, int interact) + { +@@ -1282,6 +1293,10 @@ resizeclient(Client *c, int x, int y, int w, int h) + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; ++ ++ if ((nexttiled(c->mon->clients) == c) && !(nexttiled(c->next))) ++ resetlayout(NULL); ++ + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +-- +2.32.0 diff --git a/dwm/patches/dwm-resetnmaster-pertag-6.3.diff b/dwm/patches/dwm-resetnmaster-pertag-6.3.diff new file mode 100644 index 0000000..a3d12c0 --- /dev/null +++ b/dwm/patches/dwm-resetnmaster-pertag-6.3.diff @@ -0,0 +1,36 @@ +diff -r -u a/config.def.h b/config.def.h +--- a/config.def.h 2022-01-07 06:42:18.000000000 -0500 ++++ b/config.def.h 2022-01-23 16:03:42.521951418 -0500 +@@ -69,6 +69,7 @@ + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, ++ { MODKEY, XK_o, resetnmaster, {0} }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, +diff -r -u a/dwm.c b/dwm.c +--- a/dwm.c 2022-01-23 16:06:01.221948285 -0500 ++++ b/dwm.c 2022-01-23 16:05:35.949948855 -0500 +@@ -191,6 +191,7 @@ + static void propertynotify(XEvent *e); + static void quit(const Arg *arg); + static Monitor *recttomon(int x, int y, int w, int h); ++static void resetnmaster(const Arg *arg); + static void resize(Client *c, int x, int y, int w, int h, int interact); + static void resizeclient(Client *c, int x, int y, int w, int h); + static void resizemouse(const Arg *arg); +@@ -1296,6 +1297,13 @@ + } + + void ++resetnmaster(const Arg *arg) ++{ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = 1; ++ arrange(selmon); ++} ++ ++void + resize(Client *c, int x, int y, int w, int h, int interact) + { + if (applysizehints(c, &x, &y, &w, &h, interact)) diff --git a/dwm/patches/dwm-resizehere-20230824-e81f17d.diff b/dwm/patches/dwm-resizehere-20230824-e81f17d.diff new file mode 100644 index 0000000..2e353f1 --- /dev/null +++ b/dwm/patches/dwm-resizehere-20230824-e81f17d.diff @@ -0,0 +1,60 @@ +# From d2824944615917697c18555a397bf84f2249a722 Mon Sep 17 00:00:00 2001 +# From: =?UTF-8?q?Gutyina=20Gerg=C5=91?= <gutyina.gergo.2@gmail.com> +# Date: Thu, 24 Aug 2023 15:06:56 +0200 +# Subject: [PATCH] Resize clients without wrapping the pointer +# +# --- +# dwm.c | 14 +++++++------- +# 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/dwm.c b/dwm.c +index f1d86b2..8c661a2 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1300,7 +1300,7 @@ resizeclient(Client *c, int x, int y, int w, int h) + void + resizemouse(const Arg *arg) + { +- int ocx, ocy, nw, nh; ++ int x, y, ocw, och, nw, nh; + Client *c; + Monitor *m; + XEvent ev; +@@ -1311,12 +1311,13 @@ resizemouse(const Arg *arg) + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); +- ocx = c->x; +- ocy = c->y; ++ ocw = c->w; ++ och = c->h; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; +- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); ++ if(!getrootptr(&x, &y)) ++ return; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { +@@ -1330,8 +1331,8 @@ resizemouse(const Arg *arg) + continue; + lasttime = ev.xmotion.time; + +- nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); +- nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); ++ nw = MAX(ocw + (ev.xmotion.x - x), 1); ++ nh = MAX(och + (ev.xmotion.y - y), 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) + { +@@ -1344,7 +1345,6 @@ resizemouse(const Arg *arg) + break; + } + } while (ev.type != ButtonRelease); +- XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { +-- +2.41.0 diff --git a/dwm/patches/dwm-restartsig-20180523-6.2.diff b/dwm/patches/dwm-restartsig-20180523-6.2.diff new file mode 100644 index 0000000..5aa979b --- /dev/null +++ b/dwm/patches/dwm-restartsig-20180523-6.2.diff @@ -0,0 +1,138 @@ +# From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 +# From: Christopher Drelich <cd@cdrakka.com> +# Date: Wed, 23 May 2018 22:50:38 -0400 +# Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM +# handlers. +# +# Modified quit() to restart if it receives arg .i = 1 +# MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that. +# +# Signal handlers were handled for SIGHUP and SIGTERM. +# If dwm receives these signals it calls quit() with +# arg .i = to 1 or 0, respectively. +# +# To restart dwm: +# MOD+CTRL+SHIFT+Q +# or +# kill -HUP dwmpid +# +# To quit dwm cleanly: +# MOD+SHIFT+Q +# or +# kill -TERM dwmpid +# --- +# config.def.h | 1 + +# dwm.1 | 10 ++++++++++ +# dwm.c | 22 ++++++++++++++++++++++ +# 3 files changed, 33 insertions(+) + +diff --git a/config.def.h b/config.def.h +index a9ac303..e559429 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -94,6 +94,7 @@ static Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, + }; + + /* button definitions */ +diff --git a/dwm.1 b/dwm.1 +index 13b3729..36a331c 100644 +--- a/dwm.1 ++++ b/dwm.1 +@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. + .TP + .B Mod1\-Shift\-q + Quit dwm. ++.TP ++.B Mod1\-Control\-Shift\-q ++Restart dwm. + .SS Mouse commands + .TP + .B Mod1\-Button1 +@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float + .SH CUSTOMIZATION + dwm is customized by creating a custom config.h and (re)compiling the source + code. This keeps it fast, secure and simple. ++.SH SIGNALS ++.TP ++.B SIGHUP - 1 ++Restart the dwm process. ++.TP ++.B SIGTERM - 15 ++Cleanly terminate the dwm process. + .SH SEE ALSO + .BR dmenu (1), + .BR st (1) +diff --git a/dwm.c b/dwm.c +index bb95e26..286eecd 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -205,6 +205,8 @@ static void setup(void); + static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); ++static void sighup(int unused); ++static void sigterm(int unused); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { + [UnmapNotify] = unmapnotify + }; + static Atom wmatom[WMLast], netatom[NetLast]; ++static int restart = 0; + static int running = 1; + static Cur *cursor[CurLast]; + static Clr **scheme; +@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e) + void + quit(const Arg *arg) + { ++ if(arg->i) restart = 1; + running = 0; + } + +@@ -1536,6 +1540,9 @@ setup(void) + /* clean up any zombies immediately */ + sigchld(0); + ++ signal(SIGHUP, sighup); ++ signal(SIGTERM, sigterm); ++ + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); +@@ -1637,6 +1644,20 @@ sigchld(int unused) + } + + void ++sighup(int unused) ++{ ++ Arg a = {.i = 1}; ++ quit(&a); ++} ++ ++void ++sigterm(int unused) ++{ ++ Arg a = {.i = 0}; ++ quit(&a); ++} ++ ++void + spawn(const Arg *arg) + { + if (arg->v == dmenucmd) +@@ -2139,6 +2160,7 @@ main(int argc, char *argv[]) + setup(); + scan(); + run(); ++ if(restart) execvp(argv[0], argv); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +-- +2.7.4 diff --git a/dwm/patches/dwm-scratchpads-20200414-728d397b.diff b/dwm/patches/dwm-scratchpads-20200414-728d397b.diff new file mode 100644 index 0000000..050e367 --- /dev/null +++ b/dwm/patches/dwm-scratchpads-20200414-728d397b.diff @@ -0,0 +1,198 @@ +# From 728d397b21982af88737277fd9d6939a7b558786 Mon Sep 17 00:00:00 2001 +# From: Christian Tenllado <ctenllado@gmail.com> +# Date: Tue, 14 Apr 2020 23:31:15 +0200 +# Subject: [PATCH] Multiple scratchpads +# +# This patch enables multiple scratchpads, each with one asigned window. +# This enables the same scratchpad workflow that you have in i3. +# +# Scratchpads are implemented as special tags, whose mask does not +# apply to new spawned windows. To assign a window to a scratchpad you +# have to set up a rule, as you do with regular tags. +# +# Windows tagged with scratchpad tags can be set floating or not in the +# rules array. Most users would probably want them floating (i3 style), +# but having them tiled does also perfectly work and might fit better the +# DWM approach. In case they are set floating, the patch moves them to the +# center of the screen whenever they are shown. The patch can easily be +# modified to make this last feature configurable in the rules array (see +# the center patch). +# +# The togglescratch function, borrowed from the previous scratchpad patch +# and slightly modified, can be used to spawn a registered scratchpad +# process or toggle its view. This function looks for a window tagged with +# the selected scratchpad tag. If it is found its view is toggled. If it is +# not found the corresponding registered command is spawned. The +# config.def.h shows three examples of its use to spawn a terminal in the +# first scratchpad tag, a second terminal running ranger on the second +# scratchpad tag and the keepassxc application to manage passwords on a +# third scratchpad tag. +# +# If you prefer to spawn your scratchpad applications from the startup +# script, you might opt for binding keys to toggleview instead, as +# scratchpads are just special tags (you may even extend the TAGKEYS macro +# to generalize the key bindings). +# --- +# config.def.h | 28 ++++++++++++++++++++++++---- +# dwm.c | 43 +++++++++++++++++++++++++++++++++++++++++-- +# 2 files changed, 65 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..06265e1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -18,17 +18,33 @@ static const char *colors[][3] = { + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; + ++typedef struct { ++ const char *name; ++ const void *cmd; ++} Sp; ++const char *spcmd1[] = {"st", "-n", "spterm", "-g", "120x34", NULL }; ++const char *spcmd2[] = {"st", "-n", "spfm", "-g", "144x41", "-e", "ranger", NULL }; ++const char *spcmd3[] = {"keepassxc", NULL }; ++static Sp scratchpads[] = { ++ /* name cmd */ ++ {"spterm", spcmd1}, ++ {"spranger", spcmd2}, ++ {"keepassxc", spcmd3}, ++}; ++ + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +- + static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ + /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ { "Gimp", NULL, NULL, 0, 1, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ { NULL, "spterm", NULL, SPTAG(0), 1, -1 }, ++ { NULL, "spfm", NULL, SPTAG(1), 1, -1 }, ++ { NULL, "keepassxc", NULL, SPTAG(2), 0, -1 }, + }; + + /* layout(s) */ +@@ -59,6 +75,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { "st", NULL }; + ++ + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +@@ -84,6 +101,9 @@ static Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY, XK_y, togglescratch, {.ui = 0 } }, ++ { MODKEY, XK_u, togglescratch, {.ui = 1 } }, ++ { MODKEY, XK_x, togglescratch, {.ui = 2 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) +@@ -106,7 +126,7 @@ static Button buttons[] = { + { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, +- { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, ++ { ClkClientWin, MODKEY, Button1, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, +diff --git a/dwm.c b/dwm.c +index 4465af1..646aa1a 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -54,7 +54,10 @@ + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) + #define HEIGHT(X) ((X)->h + 2 * (X)->bw) +-#define TAGMASK ((1 << LENGTH(tags)) - 1) ++#define NUMTAGS (LENGTH(tags) + LENGTH(scratchpads)) ++#define TAGMASK ((1 << NUMTAGS) - 1) ++#define SPTAG(i) ((1 << LENGTH(tags)) << (i)) ++#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << LENGTH(tags)) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + + /* enums */ +@@ -211,6 +214,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void togglescratch(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); +@@ -299,6 +303,11 @@ applyrules(Client *c) + { + c->isfloating = r->isfloating; + c->tags |= r->tags; ++ if ((r->tags & SPTAGMASK) && r->isfloating) { ++ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); ++ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); ++ } ++ + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; +@@ -308,7 +317,7 @@ applyrules(Client *c) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); +- c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; ++ c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK); + } + + int +@@ -1616,6 +1625,10 @@ showhide(Client *c) + if (!c) + return; + if (ISVISIBLE(c)) { ++ if ((c->tags & SPTAGMASK) && c->isfloating) { ++ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); ++ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); ++ } + /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) +@@ -1719,6 +1732,32 @@ togglefloating(const Arg *arg) + arrange(selmon); + } + ++void ++togglescratch(const Arg *arg) ++{ ++ Client *c; ++ unsigned int found = 0; ++ unsigned int scratchtag = SPTAG(arg->ui); ++ Arg sparg = {.v = scratchpads[arg->ui].cmd}; ++ ++ for (c = selmon->clients; c && !(found = c->tags & scratchtag); c = c->next); ++ if (found) { ++ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ scratchtag; ++ if (newtagset) { ++ selmon->tagset[selmon->seltags] = newtagset; ++ focus(NULL); ++ arrange(selmon); ++ } ++ if (ISVISIBLE(c)) { ++ focus(c); ++ restack(selmon); ++ } ++ } else { ++ selmon->tagset[selmon->seltags] |= scratchtag; ++ spawn(&sparg); ++ } ++} ++ + void + toggletag(const Arg *arg) + { +-- +2.20.1 diff --git a/dwm/patches/dwm-sendmoncenter-20210805-138b405f.diff b/dwm/patches/dwm-sendmoncenter-20210805-138b405f.diff new file mode 100644 index 0000000..3efdca4 --- /dev/null +++ b/dwm/patches/dwm-sendmoncenter-20210805-138b405f.diff @@ -0,0 +1,27 @@ +# From 449324adbe53240a734cb5f8f72763bb3419829a Mon Sep 17 00:00:00 2001 +# From: Rizqi Nur Assyaufi <bandithijo@gmail.com> +# Date: Sat, 5 Aug 2021 00:04:32 +0800 +# Subject: [PATCH] [sendmoncenter] Send floating window to another monitor will +# centered +# +# This patch will allows you to send floating window client to another monitor +# will be centered position. +# --- +# dwm.c | 2 ++ +# 1 file changed, 2 insertions(+) + +diff --git a/dwm.c b/dwm.c +index 5e4d494..c20023e 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1418,6 +1418,8 @@ sendmon(Client *c, Monitor *m) + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ ++ c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2; ++ c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2; + attach(c); + attachstack(c); + focus(NULL); +-- +2.31.1 diff --git a/dwm/patches/dwm-setborderpx-6.2.diff b/dwm/patches/dwm-setborderpx-6.2.diff new file mode 100644 index 0000000..6a82087 --- /dev/null +++ b/dwm/patches/dwm-setborderpx-6.2.diff @@ -0,0 +1,90 @@ +diff -up a/config.def.h b/config.def.h +--- a/config.def.h 2020-05-12 02:17:20.070933833 +0200 ++++ b/config.def.h 2020-05-13 03:27:51.018695798 +0200 +@@ -84,6 +84,9 @@ static Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_minus, setborderpx, {.i = -1 } }, ++ { MODKEY|ShiftMask, XK_plus, setborderpx, {.i = +1 } }, ++ { MODKEY|ShiftMask, XK_numbersign, setborderpx, {.i = 0 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) +diff -up a/dwm.c b/dwm.c +--- a/dwm.c 2020-05-12 02:17:20.070933833 +0200 ++++ b/dwm.c 2020-05-14 00:17:35.047919771 +0200 +@@ -119,6 +119,7 @@ struct Monitor { + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ ++ unsigned int borderpx; + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; +@@ -196,6 +197,7 @@ static void run(void); + static void scan(void); + static int sendevent(Client *c, Atom proto); + static void sendmon(Client *c, Monitor *m); ++static void setborderpx(const Arg *arg); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); +@@ -638,6 +640,7 @@ createmon(void) + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; ++ m->borderpx = borderpx; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); +@@ -1047,7 +1050,7 @@ manage(Window w, XWindowAttributes *wa) + /* only fix client y-offset, if the client center might cover the bar */ + c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); +- c->bw = borderpx; ++ c->bw = c->mon->borderpx; + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); +@@ -1424,6 +1427,40 @@ sendmon(Client *c, Monitor *m) + } + + 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; ++ ++ for (c = selmon->clients; c; c = c->next) ++ { ++ if (c->bw + arg->i < 0) ++ c->bw = selmon->borderpx = 0; ++ else ++ c->bw = selmon->borderpx; ++ 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); ++ } ++ } ++ arrange(selmon); ++} ++ ++void + setclientstate(Client *c, long state) + { + long data[] = { state, None }; diff --git a/dwm/patches/dwm-shift-tools-6.2.diff b/dwm/patches/dwm-shift-tools-6.2.diff new file mode 100644 index 0000000..e9b9803 --- /dev/null +++ b/dwm/patches/dwm-shift-tools-6.2.diff @@ -0,0 +1,55 @@ +# From d57c8508c9f26be40667d402a2daaa2b27ae759f Mon Sep 17 00:00:00 2001 +# From: explosion-mental <explosion0mental@gmail.com> +# Date: Wed, 11 Aug 2021 21:05:44 -0500 +# Subject: [PATCH] shift-tools-scratchpads - shifttag, moves the current selected client to +# the adjacent tag - shifttagclients, moves the current selected client to the +# adjacent tag that has at least one client else acts as shifttag - +# shiftview, view adjacent tag - shiftviewclients, view the closes tag that has +# a client. If none acts as shiftview - shiftboth, shifttag and shiftview. +# Basically moves the window to the next/prev tag and follows it. - +# shiftswaptags, its a shift implementation on the swaptags function (see +# https://github.com/moizifty/DWM-Build/blob/65379c62640788881486401a0d8c79333751b02f/config.h#L48 +# for more details), which in short 'swaps tags' (swaps all clients with +# the clients on the adjacent tag). A pretty useful example of this is +# chosing a tag empty and sending all your clients to that tag. - swapfunction +# is the 'helper' function for the shiftswaptags. remember that these functions +# **shift**, which means you can go from tag 1 to 9 or 9 to 1. Also remember +# that the default argument is 1 and you can change it. +# +# --- +# config.def.h | 9 ++++ +# shift-tools-scratchpads.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++ +# 2 files changed, 144 insertions(+) +# create mode 100644 shift-tools-scratchpads.c + +diff --git a/config.def.h b/config.def.h +index 1c0b587..1390d17 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -58,9 +58,14 @@ static const Layout layouts[] = { + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { "st", NULL }; ++#include "shift-tools-scratchpads.c" + + static Key keys[] = { + /* modifier key function argument */ ++ { MODKEY, XK_o, shiftviewclients, { .i = +1 } }, ++ { MODKEY|ShiftMask, XK_o, shiftview, { .i = +1 } }, ++ { MODKEY|ShiftMask, XK_i, shiftview, { .i = -1 } }, ++ { MODKEY, XK_i, shiftviewclients, { .i = -1 } }, + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, +@@ -69,6 +74,10 @@ static Key keys[] = { + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, ++ { MODKEY|ShiftMask, XK_h, shiftboth, { .i = -1 } }, ++ { MODKEY|ControlMask, XK_h, shiftswaptags, { .i = -1 } }, ++ { MODKEY|ControlMask, XK_l, shiftswaptags, { .i = +1 } }, ++ { MODKEY|ShiftMask, XK_l, shiftboth, { .i = +1 } }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, +2.32.0 diff --git a/dwm/patches/dwm-showselmon-6.2.diff b/dwm/patches/dwm-showselmon-6.2.diff new file mode 100644 index 0000000..bbf837e --- /dev/null +++ b/dwm/patches/dwm-showselmon-6.2.diff @@ -0,0 +1,46 @@ +diff -up a/config.def.h b/config.def.h +--- a/config.def.h 2020-07-04 13:56:23.316739958 +0200 ++++ b/config.def.h 2020-07-04 13:57:58.020554340 +0200 +@@ -15,6 +15,7 @@ static const char col_cyan[] = "# + static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, ++ [SchemeInv] = { col_gray1, col_gray3, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; + +diff -up a/dwm.c b/dwm.c +--- a/dwm.c 2020-07-04 13:56:23.316739958 +0200 ++++ b/dwm.c 2020-07-04 14:14:54.124590755 +0200 +@@ -59,7 +59,7 @@ + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +-enum { SchemeNorm, SchemeSel }; /* color schemes */ ++enum { SchemeNorm, SchemeInv, SchemeSel }; /* color schemes */ + enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ +@@ -716,7 +716,12 @@ drawbar(Monitor *m) + x = 0; + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(tags[i]); +- drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); ++ if (m == selmon) { ++ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); ++ } ++ else { ++ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeInv : SchemeNorm]); ++ } + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, +@@ -730,7 +735,7 @@ drawbar(Monitor *m) + + if ((w = m->ww - sw - x) > bh) { + if (m->sel) { +- drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); ++ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeInv]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); diff --git a/dwm/patches/dwm-spawntag-6.2.diff b/dwm/patches/dwm-spawntag-6.2.diff new file mode 100644 index 0000000..9dba2da --- /dev/null +++ b/dwm/patches/dwm-spawntag-6.2.diff @@ -0,0 +1,84 @@ +# From abace8a090f579a9bd2513e78e0ebe9d9fa1e0bb Mon Sep 17 00:00:00 2001 +# From: Piyush Pangtey <gokuvsvegita@gmail.com> +# Date: Wed, 19 May 2021 19:27:34 +0530 +# Subject: [PATCH] [Feature] spawntag +# +# spawn application whenever a tag is middle clicked +# --- +# config.def.h | 16 ++++++++++++++++ +# dwm.c | 14 ++++++++++++++ +# 2 files changed, 30 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..442b556 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -54,11 +54,26 @@ static const Layout layouts[] = { + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + ++/* helper for launching gtk application */ ++#define GTKCMD(cmd) { .v = (const char*[]){ "/usr/bin/gtk-launch", cmd, NULL } } ++ + /* commands */ + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { "st", NULL }; + ++static const Arg tagexec[] = { ++ { .v = termcmd }, ++ { .v = termcmd }, ++ { .v = termcmd }, ++ { .v = termcmd }, ++ { .v = termcmd }, ++ { .v = termcmd }, ++ { .v = termcmd }, ++ { .v = termcmd }, ++ { .v = termcmd } ++}; ++ + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +@@ -108,6 +123,7 @@ static Button buttons[] = { + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, ++ { ClkTagBar, 0, Button2, spawntag, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +diff --git a/dwm.c b/dwm.c +index 4465af1..89b3220 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -207,6 +207,7 @@ static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); ++static void spawntag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); +@@ -1662,6 +1663,19 @@ tag(const Arg *arg) + } + } + ++void ++spawntag(const Arg *arg) ++{ ++ if (arg->ui & TAGMASK) { ++ for (int i = LENGTH(tags); i >= 0; i--) { ++ if (arg->ui & 1<<i) { ++ spawn(&tagexec[i]); ++ return; ++ } ++ } ++ } ++} ++ + void + tagmon(const Arg *arg) + { +-- +2.31.1 diff --git a/dwm/patches/dwm-stacker-6.2.diff b/dwm/patches/dwm-stacker-6.2.diff new file mode 100644 index 0000000..91837f0 --- /dev/null +++ b/dwm/patches/dwm-stacker-6.2.diff @@ -0,0 +1,196 @@ +# From d04f2d00688c8b0969d4f10f460c980dd91dac37 Mon Sep 17 00:00:00 2001 +# From: MLquest8 <miskuzius@gmail.com> +# Date: Fri, 12 Jun 2020 16:04:18 +0400 +# Subject: [PATCH] stacker updated for version 6.2 +# +# --- +# config.def.h | 14 +++++++-- +# dwm.c | 88 ++++++++++++++++++++++++++++++++++++++++------------ +# 2 files changed, 80 insertions(+), 22 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..d28f8fc 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -50,6 +50,14 @@ static const Layout layouts[] = { + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, ++#define STACKKEYS(MOD,ACTION) \ ++ { MOD, XK_j, ACTION##stack, {.i = INC(+1) } }, \ ++ { MOD, XK_k, ACTION##stack, {.i = INC(-1) } }, \ ++ { MOD, XK_grave, ACTION##stack, {.i = PREVSEL } }, \ ++ { MOD, XK_q, ACTION##stack, {.i = 0 } }, \ ++ { MOD, XK_a, ACTION##stack, {.i = 1 } }, \ ++ { MOD, XK_z, ACTION##stack, {.i = 2 } }, \ ++ { MOD, XK_x, ACTION##stack, {.i = -1 } }, + + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } +@@ -64,8 +72,8 @@ static Key keys[] = { + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, +- { MODKEY, XK_j, focusstack, {.i = +1 } }, +- { MODKEY, XK_k, focusstack, {.i = -1 } }, ++ STACKKEYS(MODKEY, focus) ++ STACKKEYS(MODKEY|ShiftMask, push) + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, +@@ -93,7 +101,7 @@ static Key keys[] = { + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) +- { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY|ShiftMask, XK_BackSpace, quit, {0} }, + }; + + /* button definitions */ +diff --git a/dwm.c b/dwm.c +index 9fd0286..6c302c3 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -47,15 +47,21 @@ + /* macros */ + #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) + #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) ++#define GETINC(X) ((X) - 2000) ++#define INC(X) ((X) + 2000) + #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) ++#define ISINC(X) ((X) > 1000 && (X) < 3000) + #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) ++#define PREVSEL 3000 + #define LENGTH(X) (sizeof X / sizeof X[0]) ++#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M)) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) + #define HEIGHT(X) ((X)->h + 2 * (X)->bw) + #define TAGMASK ((1 << LENGTH(tags)) - 1) + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) ++#define TRUNC(X,A,B) (MAX((A), MIN((X), (B)))) + + /* enums */ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +@@ -187,6 +193,7 @@ static void movemouse(const Arg *arg); + static Client *nexttiled(Client *c); + static void pop(Client *); + static void propertynotify(XEvent *e); ++static void pushstack(const Arg *arg); + static void quit(const Arg *arg); + static Monitor *recttomon(int x, int y, int w, int h); + static void resize(Client *c, int x, int y, int w, int h, int interact); +@@ -207,6 +214,7 @@ static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); ++static int stackpos(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); +@@ -833,27 +841,16 @@ focusmon(const Arg *arg) + void + focusstack(const Arg *arg) + { +- Client *c = NULL, *i; ++ int i = stackpos(arg); ++ Client *c, *p; + +- if (!selmon->sel) ++ if(i < 0) + return; +- if (arg->i > 0) { +- for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); +- if (!c) +- for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); +- } else { +- for (i = selmon->clients; i != selmon->sel; i = i->next) +- if (ISVISIBLE(i)) +- c = i; +- if (!c) +- for (; i; i = i->next) +- if (ISVISIBLE(i)) +- c = i; +- } +- if (c) { +- focus(c); +- restack(selmon); +- } ++ ++ for(p = NULL, c = selmon->clients; c && (i || !ISVISIBLE(c)); ++ i -= ISVISIBLE(c) ? 1 : 0, p = c, c = c->next); ++ focus(c ? c : p); ++ restack(selmon); + } + + Atom +@@ -1246,6 +1243,29 @@ propertynotify(XEvent *e) + } + } + ++void ++pushstack(const Arg *arg) { ++ int i = stackpos(arg); ++ Client *sel = selmon->sel, *c, *p; ++ ++ if(i < 0) ++ return; ++ else if(i == 0) { ++ detach(sel); ++ attach(sel); ++ } ++ else { ++ for(p = NULL, c = selmon->clients; c; p = c, c = c->next) ++ if(!(i -= (ISVISIBLE(c) && c != sel))) ++ break; ++ c = c ? c : p; ++ detach(sel); ++ sel->next = c->next; ++ c->next = sel; ++ } ++ arrange(selmon); ++} ++ + void + quit(const Arg *arg) + { +@@ -1653,6 +1673,36 @@ spawn(const Arg *arg) + } + } + ++int ++stackpos(const Arg *arg) { ++ int n, i; ++ Client *c, *l; ++ ++ if(!selmon->clients) ++ return -1; ++ ++ if(arg->i == PREVSEL) { ++ for(l = selmon->stack; l && (!ISVISIBLE(l) || l == selmon->sel); l = l->snext); ++ if(!l) ++ return -1; ++ for(i = 0, c = selmon->clients; c != l; i += ISVISIBLE(c) ? 1 : 0, c = c->next); ++ return i; ++ } ++ else if(ISINC(arg->i)) { ++ if(!selmon->sel) ++ return -1; ++ for(i = 0, c = selmon->clients; c != selmon->sel; i += ISVISIBLE(c) ? 1 : 0, c = c->next); ++ for(n = i; c; n += ISVISIBLE(c) ? 1 : 0, c = c->next); ++ return MOD(i + GETINC(arg->i), n); ++ } ++ else if(arg->i < 0) { ++ for(i = 0, c = selmon->clients; c; i += ISVISIBLE(c) ? 1 : 0, c = c->next); ++ return MAX(i + arg->i, 0); ++ } ++ else ++ return arg->i; ++} ++ + void + tag(const Arg *arg) + { +-- +2.26.2 diff --git a/dwm/patches/dwm-stairs-fullgaps-20220430-8b48e30.diff b/dwm/patches/dwm-stairs-fullgaps-20220430-8b48e30.diff new file mode 100644 index 0000000..75b47fd --- /dev/null +++ b/dwm/patches/dwm-stairs-fullgaps-20220430-8b48e30.diff @@ -0,0 +1,98 @@ +# From 2004db267a9478918699961ab2f3579c2c8113fb Mon Sep 17 00:00:00 2001 +# From: Ehsan Ghorbannezhad <ehsan@disroot.org> +# Date: Sat, 30 Apr 2022 02:48:58 +0430 +# Subject: [PATCH] add the stairs layout with fullgaps support +# +# --- +# config.def.h | 5 +++++ +# dwm.c | 38 ++++++++++++++++++++++++++++++++++++++ +# 2 files changed, 43 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 5b0d4de..c0f24f4 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -6,6 +6,9 @@ static const unsigned int gappx = 5; /* gaps between windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++static const unsigned int stairpx = 20; /* depth of the stairs layout */ ++static const int stairdirection = 1; /* 0: left-aligned, 1: right-aligned */ ++static const int stairsamesize = 1; /* 1 means shrink all the staired windows to the same size */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +@@ -43,6 +46,7 @@ static const Layout layouts[] = { + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, ++ { "[S]", stairs }, + }; + + /* key definitions */ +@@ -78,6 +82,7 @@ static Key keys[] = { + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XK_s, setlayout, {.v = &layouts[3]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +diff --git a/dwm.c b/dwm.c +index 5b7348c..2c5380f 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -209,6 +209,7 @@ static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); + static void spawn(const Arg *arg); ++static void stairs(Monitor *m); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); +@@ -1672,6 +1673,43 @@ spawn(const Arg *arg) + } + } + ++void ++stairs(Monitor *m) ++{ ++ unsigned int i, n, h, mw, my; ++ unsigned int ox, oy, ow, oh; /* stair offset values */ ++ Client *c; ++ ++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ if (n == 0) ++ return; ++ ++ if (n > m->nmaster) ++ mw = m->nmaster ? m->ww * m->mfact : 0; ++ else ++ mw = m->ww - m->gappx; ++ ++ for (i = 0, my = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { ++ if (i < m->nmaster) { ++ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; ++ resize(c, m->wx + m->gappx, m->wy + my, mw - (2 * c->bw) - m->gappx, h - (2 * c->bw), 0); ++ if (my + HEIGHT(c) + m->gappx < m->wh) ++ my += HEIGHT(c) + m->gappx; ++ } else { ++ oy = i - m->nmaster; ++ ox = stairdirection ? n - i - 1 : (stairsamesize ? i - m->nmaster : 0); ++ ow = stairsamesize ? n - m->nmaster - 1 : n - i - 1; ++ oh = stairsamesize ? ow : i - m->nmaster; ++ resize(c, ++ m->wx + mw + (ox * stairpx) + m->gappx, ++ m->wy + (oy * stairpx) + m->gappx, ++ m->ww - mw - (2 * c->bw) - (ow * stairpx) - (2 * m->gappx), ++ m->wh - (2 * c->bw) - (oh * stairpx) - (2 * m->gappx), ++ 0); ++ } ++ } ++} ++ + void + tag(const Arg *arg) + { +-- +2.36.0 diff --git a/dwm/patches/dwm-statuscmd-20241009-8933ebc.diff b/dwm/patches/dwm-statuscmd-20241009-8933ebc.diff new file mode 100644 index 0000000..4e68a8a --- /dev/null +++ b/dwm/patches/dwm-statuscmd-20241009-8933ebc.diff @@ -0,0 +1,219 @@ +# From ca2a2e6386a746ebfc3480787e5d99da11e7abee Mon Sep 17 00:00:00 2001 +# From: Justinas Grigas <dev@jstnas.com> +# Date: Wed, 9 Oct 2024 01:00:20 +0100 +# Subject: [PATCH] [dwm][statuscmd] better click regions +# +# The main improvement of this patch over the previous version 20210405 is that +# the click region now ends on a matching signal raw byte. +# +# The matching byte is optional, and without it dwm will behave as before. +# +# To take advantage of this feature, scripts need to be modified to print the raw +# byte at the end as well. +# +# In addition, this patch cleanly applies onto master branch. +# --- +# config.def.h | 6 ++- +# dwm.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++--- +# 2 files changed, 104 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..d008275 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -55,6 +55,8 @@ static const Layout layouts[] = { + /* helper for spawning shell commands in the pre dwm-5.0 fashion */ + #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + ++#define STATUSBAR "dwmblocks" ++ + /* commands */ + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; +@@ -104,7 +106,9 @@ static const Button buttons[] = { + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, +- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, ++ { ClkStatusText, 0, Button1, sigstatusbar, {.i = 1} }, ++ { ClkStatusText, 0, Button2, sigstatusbar, {.i = 2} }, ++ { ClkStatusText, 0, Button3, sigstatusbar, {.i = 3} }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, +diff --git a/dwm.c b/dwm.c +index 1443802..94ee0c7 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -171,6 +171,7 @@ static void focusstack(const Arg *arg); + static Atom getatomprop(Client *c, Atom prop); + static int getrootptr(int *x, int *y); + static long getstate(Window w); ++static pid_t getstatusbarpid(); + static int gettextprop(Window w, Atom atom, char *text, unsigned int size); + static void grabbuttons(Client *c, int focused); + static void grabkeys(void); +@@ -204,6 +205,7 @@ static void setmfact(const Arg *arg); + static void setup(void); + static void seturgent(Client *c, int urg); + static void showhide(Client *c); ++static void sigstatusbar(const Arg *arg); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +@@ -236,6 +238,9 @@ static void zoom(const Arg *arg); + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; ++static int statusw; ++static int statussig; ++static pid_t statuspid = -1; + static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh; /* bar height */ +@@ -422,6 +427,7 @@ buttonpress(XEvent *e) + Client *c; + Monitor *m; + XButtonPressedEvent *ev = &e->xbutton; ++ char *text, *s, ch; + + click = ClkRootWin; + /* focus monitor if necessary */ +@@ -440,9 +446,27 @@ buttonpress(XEvent *e) + arg.ui = 1 << i; + } else if (ev->x < x + TEXTW(selmon->ltsymbol)) + click = ClkLtSymbol; +- else if (ev->x > selmon->ww - (int)TEXTW(stext)) ++ else if (ev->x > selmon->ww - statusw) { ++ x = selmon->ww - statusw; + click = ClkStatusText; +- else ++ statussig = 0; ++ for (text = s = stext; *s && x <= ev->x; s++) { ++ if ((unsigned char)(*s) < ' ') { ++ ch = *s; ++ *s = '\0'; ++ x += TEXTW(text) - lrpad; ++ *s = ch; ++ text = s + 1; ++ if (x >= ev->x) ++ break; ++ /* reset on matching signal raw byte */ ++ if (ch == statussig) ++ statussig = 0; ++ else ++ statussig = ch; ++ } ++ } ++ } else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); +@@ -708,9 +732,24 @@ drawbar(Monitor *m) + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ ++ char *text, *s, ch; + drw_setscheme(drw, scheme[SchemeNorm]); +- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ +- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); ++ ++ x = 0; ++ for (text = s = stext; *s; s++) { ++ if ((unsigned char)(*s) < ' ') { ++ ch = *s; ++ *s = '\0'; ++ tw = TEXTW(text) - lrpad; ++ drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0); ++ x += tw; ++ *s = ch; ++ text = s + 1; ++ } ++ } ++ tw = TEXTW(text) - lrpad + 2; ++ drw_text(drw, m->ww - statusw + x, 0, tw, bh, 0, text, 0); ++ tw = statusw; + } + + for (c = m->clients; c; c = c->next) { +@@ -876,6 +915,30 @@ getatomprop(Client *c, Atom prop) + return atom; + } + ++pid_t ++getstatusbarpid() ++{ ++ char buf[32], *str = buf, *c; ++ FILE *fp; ++ ++ if (statuspid > 0) { ++ snprintf(buf, sizeof(buf), "/proc/%u/cmdline", statuspid); ++ if ((fp = fopen(buf, "r"))) { ++ fgets(buf, sizeof(buf), fp); ++ while ((c = strchr(str, '/'))) ++ str = c + 1; ++ fclose(fp); ++ if (!strcmp(str, STATUSBAR)) ++ return statuspid; ++ } ++ } ++ if (!(fp = popen("pidof -s "STATUSBAR, "r"))) ++ return -1; ++ fgets(buf, sizeof(buf), fp); ++ pclose(fp); ++ return strtol(buf, NULL, 10); ++} ++ + int + getrootptr(int *x, int *y) + { +@@ -1643,6 +1706,20 @@ showhide(Client *c) + } + } + ++void ++sigstatusbar(const Arg *arg) ++{ ++ union sigval sv; ++ ++ if (!statussig) ++ return; ++ sv.sival_int = arg->i; ++ if ((statuspid = getstatusbarpid()) <= 0) ++ return; ++ ++ sigqueue(statuspid, SIGRTMIN+statussig, sv); ++} ++ + void + spawn(const Arg *arg) + { +@@ -2004,8 +2081,25 @@ updatesizehints(Client *c) + void + updatestatus(void) + { +- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) ++ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) { + strcpy(stext, "dwm-"VERSION); ++ statusw = TEXTW(stext) - lrpad + 2; ++ } else { ++ char *text, *s, ch; ++ ++ statusw = 0; ++ for (text = s = stext; *s; s++) { ++ if ((unsigned char)(*s) < ' ') { ++ ch = *s; ++ *s = '\0'; ++ statusw += TEXTW(text) - lrpad; ++ *s = ch; ++ text = s + 1; ++ } ++ } ++ statusw += TEXTW(text) - lrpad + 2; ++ ++ } + drawbar(selmon); + } + +-- +2.46.2 diff --git a/dwm/patches/dwm-sticky-6.5.diff b/dwm/patches/dwm-sticky-6.5.diff new file mode 100644 index 0000000..50a4066 --- /dev/null +++ b/dwm/patches/dwm-sticky-6.5.diff @@ -0,0 +1,145 @@ +# From 60f7034ca1573e10cf9e005e2ef5a44e6b76ea9b Mon Sep 17 00:00:00 2001 +# From: elbachir-one <bachiralfa@gmail.com> +# Date: Fri, 27 Sep 2024 12:35:36 +0100 +# Subject: [PATCH] Added the missing keybinding +# +# --- +# config.def.h | 1 + +# dwm.c | 43 ++++++++++++++++++++++++++++++++++++++++--- +# 2 files changed, 41 insertions(+), 3 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 9efa774..55c0a6c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -95,6 +95,7 @@ static const Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY, XK_s, togglesticky, {0} }, + }; + + /* button definitions */ +diff --git a/dwm.c b/dwm.c +index 67c6b2b..e8ed755 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -49,7 +49,7 @@ + #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) + #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +-#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) ++#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky) + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define MOUSEMASK (BUTTONMASK|PointerMotionMask) + #define WIDTH(X) ((X)->w + 2 * (X)->bw) +@@ -61,7 +61,7 @@ + enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ + enum { SchemeNorm, SchemeSel }; /* color schemes */ + enum { NetSupported, NetWMName, NetWMState, NetWMCheck, +- NetWMFullscreen, NetActiveWindow, NetWMWindowType, ++ NetWMFullscreen, NetWMSticky, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ + enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ + enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, +@@ -92,7 +92,7 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + int bw, oldbw; + unsigned int tags; +- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky; + Client *next; + Client *snext; + Monitor *mon; +@@ -200,6 +200,7 @@ static void sendmon(Client *c, Monitor *m); + static void setclientstate(Client *c, long state); + static void setfocus(Client *c); + static void setfullscreen(Client *c, int fullscreen); ++static void setsticky(Client *c, int sticky); + static void setlayout(const Arg *arg); + static void setmfact(const Arg *arg); + static void setup(void); +@@ -211,6 +212,7 @@ static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void togglesticky(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); + static void unfocus(Client *c, int setfocus); +@@ -525,6 +527,10 @@ clientmessage(XEvent *e) + || cme->data.l[2] == netatom[NetWMFullscreen]) + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); ++ ++ if (cme->data.l[1] == netatom[NetWMSticky] ++ || cme->data.l[2] == netatom[NetWMSticky]) ++ setsticky(c, (cme->data.l[0] == 1 || (cme->data.l[0] == 2 && !c->issticky))); + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); +@@ -1507,6 +1513,23 @@ setfullscreen(Client *c, int fullscreen) + } + } + ++void ++ setsticky(Client *c, int sticky) ++ { ++ ++ if(sticky && !c->issticky) { ++ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, ++ PropModeReplace, (unsigned char *) &netatom[NetWMSticky], 1); ++ c->issticky = 1; ++ } else if(!sticky && c->issticky){ ++ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, ++ PropModeReplace, (unsigned char *)0, 0); ++ c->issticky = 0; ++ arrange(c->mon); ++ } ++ } ++ ++ + void + setlayout(const Arg *arg) + { +@@ -1576,6 +1599,7 @@ setup(void) + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); ++ netatom[NetWMSticky] = XInternAtom(dpy, "_NET_WM_STATE_STICKY", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); +@@ -1735,6 +1759,15 @@ togglefloating(const Arg *arg) + arrange(selmon); + } + ++void ++togglesticky(const Arg *arg) ++{ ++ if (!selmon->sel) ++ return; ++ setsticky(selmon->sel, !selmon->sel->issticky); ++ arrange(selmon); ++} ++ + void + toggletag(const Arg *arg) + { +@@ -2027,6 +2060,9 @@ updatewindowtype(Client *c) + + if (state == netatom[NetWMFullscreen]) + setfullscreen(c, 1); ++ if (state == netatom[NetWMSticky]) { ++ setsticky(c, 1); ++ } + if (wtype == netatom[NetWMWindowTypeDialog]) + c->isfloating = 1; + } +@@ -2163,3 +2199,4 @@ main(int argc, char *argv[]) + XCloseDisplay(dpy); + return EXIT_SUCCESS; + } ++ +-- +2.46.0 diff --git a/dwm/patches/dwm-stickyindicator-6.2.diff b/dwm/patches/dwm-stickyindicator-6.2.diff new file mode 100644 index 0000000..8b6ec41 --- /dev/null +++ b/dwm/patches/dwm-stickyindicator-6.2.diff @@ -0,0 +1,65 @@ +diff -pu dwm.stickypatch/config.def.h dwm.stickyindicator/config.def.h +--- dwm.stickypatch/config.def.h 2021-02-28 23:51:25.118904642 -0600 ++++ dwm.stickyindicator/config.def.h 2021-03-15 20:19:53.533323727 -0500 +@@ -17,6 +17,8 @@ static const char *colors[][3] = { + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; ++static const XPoint stickyicon[] = { {0,0}, {4,0}, {4,8}, {2,6}, {0,8}, {0,0} }; /* represents the icon as an array of vertices */ ++static const XPoint stickyiconbb = {4,8}; /* defines the bottom right corner of the polygon's bounding box (speeds up scaling) */ + + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; +diff -pu dwm.stickypatch/drw.c dwm.stickyindicator/drw.c +--- dwm.stickypatch/drw.c 2021-02-28 23:51:06.992237482 -0600 ++++ dwm.stickyindicator/drw.c 2021-03-15 20:19:19.499990633 -0500 +@@ -248,6 +248,26 @@ drw_rect(Drw *drw, int x, int y, unsigne + XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); + } + ++void ++drw_polygon(Drw *drw, int x, int y, int ow, int oh, int sw, int sh, const XPoint *points, int npoints, int shape, int filled) /* wrapper function to scale and draw a polygon with X11 */ ++{ ++ if (!drw || !drw->scheme) ++ return; ++ XSetForeground(drw->dpy, drw->gc, drw->scheme[ColFg].pixel); ++ if (!filled) { /* reduces the scaled width and height by 1 when drawing the outline to compensate for X11 drawing the line 1 pixel over */ ++ sw -= 1; ++ sh -= 1; ++ } ++ XPoint scaledpoints[npoints]; ++ memcpy(scaledpoints, points, npoints); ++ for (int v = 0; v < npoints; v++) ++ scaledpoints[v] = (XPoint){ .x = points[v].x * sw / ow + x, .y = points[v].y * sh / oh + y }; ++ if (filled) ++ XFillPolygon(drw->dpy, drw->drawable, drw->gc, scaledpoints, npoints, shape, CoordModeOrigin); /* Change shape to 'Convex' or 'Complex' in dwm.c if the shape is not 'Nonconvex' */ ++ else ++ XDrawLines(drw->dpy, drw->drawable, drw->gc, scaledpoints, npoints, CoordModeOrigin); ++} ++ + int + drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) + { +diff -pu dwm.stickypatch/drw.h dwm.stickyindicator/drw.h +--- dwm.stickypatch/drw.h 2021-02-28 23:51:06.992237482 -0600 ++++ dwm.stickyindicator/drw.h 2021-03-01 01:34:02.739074730 -0600 +@@ -51,6 +51,7 @@ void drw_setscheme(Drw *drw, Clr *scm); + + /* Drawing functions */ + void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); ++void drw_polygon(Drw *drw, int x, int y, int ow, int oh, int sw, int sh, const XPoint *points, int npoints, int shape, int filled); + int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); + + /* Map functions */ +diff -pu dwm.stickypatch/dwm.c dwm.stickyindicator/dwm.c +--- dwm.stickypatch/dwm.c 2021-02-28 23:51:25.118904642 -0600 ++++ dwm.stickyindicator/dwm.c 2021-03-15 20:12:32.063326766 -0500 +@@ -736,6 +736,8 @@ drawbar(Monitor *m) + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); ++ if (m->sel->issticky) ++ drw_polygon(drw, x + boxs, m->sel->isfloating ? boxs * 2 + boxw : boxs, stickyiconbb.x, stickyiconbb.y, boxw, boxw * stickyiconbb.y / stickyiconbb.x, stickyicon, LENGTH(stickyicon), Nonconvex, m->sel->tags & m->tagset[m->seltags]); + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); diff --git a/dwm/patches/dwm-swallow-6.3.diff b/dwm/patches/dwm-swallow-6.3.diff new file mode 100644 index 0000000..d2d3835 --- /dev/null +++ b/dwm/patches/dwm-swallow-6.3.diff @@ -0,0 +1,410 @@ +# From 0cf9a007511f7dfd7dd94171b172562ebac9b6d5 Mon Sep 17 00:00:00 2001 +# From: Tom Schwindl <schwindl@posteo.de> +# Date: Sat, 10 Sep 2022 12:51:09 +0200 +# Subject: [PATCH] 6.3 swallow patch +# +# --- +# config.def.h | 9 +- +# config.mk | 3 +- +# dwm.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++-- +# 3 files changed, 237 insertions(+), 10 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 061ad662f82a..0b2b8ffd30d5 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -3,6 +3,7 @@ + /* appearance */ + static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ ++static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ + static const char *fonts[] = { "monospace:size=10" }; +@@ -26,9 +27,11 @@ static const Rule rules[] = { + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ +- /* class instance title tags mask isfloating monitor */ +- { "Gimp", NULL, NULL, 0, 1, -1 }, +- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, ++ /* class instance title tags mask isfloating isterminal noswallow monitor */ ++ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, ++ { "St", NULL, NULL, 0, 0, 1, 0, -1 }, ++ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */ + }; + + /* layout(s) */ +diff --git a/config.mk b/config.mk +index 81c493ef4aff..52d1ebf30bec 100644 +--- a/config.mk ++++ b/config.mk +@@ -20,10 +20,11 @@ FREETYPEINC = /usr/include/freetype2 + # OpenBSD (uncomment) + #FREETYPEINC = ${X11INC}/freetype2 + #MANPREFIX = ${PREFIX}/man ++#KVMLIB = -lkvm + + # includes and libs + INCS = -I${X11INC} -I${FREETYPEINC} +-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} ++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res ${KVMLIB} + + # flags + CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} +diff --git a/dwm.c b/dwm.c +index e5efb6a22806..e68294b6b679 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -40,6 +40,12 @@ + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ + #include <X11/Xft/Xft.h> ++#include <X11/Xlib-xcb.h> ++#include <xcb/res.h> ++#ifdef __OpenBSD__ ++#include <sys/sysctl.h> ++#include <kvm.h> ++#endif /* __OpenBSD */ + + #include "drw.h" + #include "util.h" +@@ -92,9 +98,11 @@ struct Client { + int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; + int bw, oldbw; + unsigned int tags; +- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; ++ pid_t pid; + Client *next; + Client *snext; ++ Client *swallowing; + Monitor *mon; + Window win; + }; +@@ -138,6 +146,8 @@ typedef struct { + const char *title; + unsigned int tags; + int isfloating; ++ int isterminal; ++ int noswallow; + int monitor; + } Rule; + +@@ -235,6 +245,12 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); + ++static pid_t getparentprocess(pid_t p); ++static int isdescprocess(pid_t p, pid_t c); ++static Client *swallowingclient(Window w); ++static Client *termforwin(const Client *c); ++static pid_t winpid(Window w); ++ + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; +@@ -269,6 +285,8 @@ static Drw *drw; + static Monitor *mons, *selmon; + static Window root, wmcheckwin; + ++static xcb_connection_t *xcon; ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -298,6 +316,8 @@ applyrules(Client *c) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { ++ c->isterminal = r->isterminal; ++ c->noswallow = r->noswallow; + c->isfloating = r->isfloating; + c->tags |= r->tags; + for (m = mons; m && m->num != r->monitor; m = m->next); +@@ -416,6 +436,53 @@ attachstack(Client *c) + c->mon->stack = c; + } + ++void ++swallow(Client *p, Client *c) ++{ ++ ++ if (c->noswallow || c->isterminal) ++ return; ++ if (c->noswallow && !swallowfloating && c->isfloating) ++ return; ++ ++ detach(c); ++ detachstack(c); ++ ++ setclientstate(c, WithdrawnState); ++ XUnmapWindow(dpy, p->win); ++ ++ p->swallowing = c; ++ c->mon = p->mon; ++ ++ Window w = p->win; ++ p->win = c->win; ++ c->win = w; ++ updatetitle(p); ++ XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); ++ arrange(p->mon); ++ configure(p); ++ updateclientlist(); ++} ++ ++void ++unswallow(Client *c) ++{ ++ c->win = c->swallowing->win; ++ ++ free(c->swallowing); ++ c->swallowing = NULL; ++ ++ /* unfullscreen the client */ ++ setfullscreen(c, 0); ++ updatetitle(c); ++ arrange(c->mon); ++ XMapWindow(dpy, c->win); ++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); ++ setclientstate(c, NormalState); ++ focus(NULL); ++ arrange(c->mon); ++} ++ + void + buttonpress(XEvent *e) + { +@@ -656,6 +723,9 @@ destroynotify(XEvent *e) + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); ++ ++ else if ((c = swallowingclient(ev->window))) ++ unmanage(c->swallowing, 1); + } + + void +@@ -1022,12 +1092,13 @@ killclient(const Arg *arg) + void + manage(Window w, XWindowAttributes *wa) + { +- Client *c, *t = NULL; ++ Client *c, *t = NULL, *term = NULL; + Window trans = None; + XWindowChanges wc; + + c = ecalloc(1, sizeof(Client)); + c->win = w; ++ c->pid = winpid(w); + /* geometry */ + c->x = c->oldx = wa->x; + c->y = c->oldy = wa->y; +@@ -1042,6 +1113,7 @@ manage(Window w, XWindowAttributes *wa) + } else { + c->mon = selmon; + applyrules(c); ++ term = termforwin(c); + } + + if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) +@@ -1076,6 +1148,8 @@ manage(Window w, XWindowAttributes *wa) + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); ++ if (term) ++ swallow(term, c); + focus(NULL); + } + +@@ -1763,6 +1837,20 @@ unmanage(Client *c, int destroyed) + Monitor *m = c->mon; + XWindowChanges wc; + ++ if (c->swallowing) { ++ unswallow(c); ++ return; ++ } ++ ++ Client *s = swallowingclient(c->win); ++ if (s) { ++ free(s->swallowing); ++ s->swallowing = NULL; ++ arrange(m); ++ focus(NULL); ++ return; ++ } ++ + detach(c); + detachstack(c); + if (!destroyed) { +@@ -1778,9 +1866,12 @@ unmanage(Client *c, int destroyed) + XUngrabServer(dpy); + } + free(c); +- focus(NULL); +- updateclientlist(); +- arrange(m); ++ ++ if (!s) { ++ arrange(m); ++ focus(NULL); ++ updateclientlist(); ++ } + } + + void +@@ -2044,6 +2135,136 @@ view(const Arg *arg) + arrange(selmon); + } + ++pid_t ++winpid(Window w) ++{ ++ ++ pid_t result = 0; ++ ++#ifdef __linux__ ++ xcb_res_client_id_spec_t spec = {0}; ++ spec.client = w; ++ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; ++ ++ xcb_generic_error_t *e = NULL; ++ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); ++ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); ++ ++ if (!r) ++ return (pid_t)0; ++ ++ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); ++ for (; i.rem; xcb_res_client_id_value_next(&i)) { ++ spec = i.data->spec; ++ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { ++ uint32_t *t = xcb_res_client_id_value_value(i.data); ++ result = *t; ++ break; ++ } ++ } ++ ++ free(r); ++ ++ if (result == (pid_t)-1) ++ result = 0; ++ ++#endif /* __linux__ */ ++ ++#ifdef __OpenBSD__ ++ Atom type; ++ int format; ++ unsigned long len, bytes; ++ unsigned char *prop; ++ pid_t ret; ++ ++ if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 0), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) ++ return 0; ++ ++ ret = *(pid_t*)prop; ++ XFree(prop); ++ result = ret; ++#endif /* __OpenBSD__ */ ++ return result; ++} ++ ++pid_t ++getparentprocess(pid_t p) ++{ ++ unsigned int v = 0; ++ ++#ifdef __linux__ ++ FILE *f; ++ char buf[256]; ++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); ++ ++ if (!(f = fopen(buf, "r"))) ++ return 0; ++ ++ fscanf(f, "%*u %*s %*c %u", &v); ++ fclose(f); ++#endif /* __linux__*/ ++ ++#ifdef __OpenBSD__ ++ int n; ++ kvm_t *kd; ++ struct kinfo_proc *kp; ++ ++ kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); ++ if (!kd) ++ return 0; ++ ++ kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); ++ v = kp->p_ppid; ++#endif /* __OpenBSD__ */ ++ ++ return (pid_t)v; ++} ++ ++int ++isdescprocess(pid_t p, pid_t c) ++{ ++ while (p != c && c != 0) ++ c = getparentprocess(c); ++ ++ return (int)c; ++} ++ ++Client * ++termforwin(const Client *w) ++{ ++ Client *c; ++ Monitor *m; ++ ++ if (!w->pid || w->isterminal) ++ return NULL; ++ ++ for (m = mons; m; m = m->next) { ++ for (c = m->clients; c; c = c->next) { ++ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) ++ return c; ++ } ++ } ++ ++ return NULL; ++} ++ ++Client * ++swallowingclient(Window w) ++{ ++ Client *c; ++ Monitor *m; ++ ++ for (m = mons; m; m = m->next) { ++ for (c = m->clients; c; c = c->next) { ++ if (c->swallowing && c->swallowing->win == w) ++ return c; ++ } ++ } ++ ++ return NULL; ++} ++ + Client * + wintoclient(Window w) + { +@@ -2133,10 +2354,12 @@ main(int argc, char *argv[]) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); ++ if (!(xcon = XGetXCBConnection(dpy))) ++ die("dwm: cannot get xcb connection\n"); + checkotherwm(); + setup(); + #ifdef __OpenBSD__ +- if (pledge("stdio rpath proc exec", NULL) == -1) ++ if (pledge("stdio rpath proc exec ps", NULL) == -1) + die("pledge"); + #endif /* __OpenBSD__ */ + scan(); +-- +2.37.2 diff --git a/dwm/patches/dwm-switchallmonitortags-6.3.diff b/dwm/patches/dwm-switchallmonitortags-6.3.diff new file mode 100644 index 0000000..44b751f --- /dev/null +++ b/dwm/patches/dwm-switchallmonitortags-6.3.diff @@ -0,0 +1,62 @@ +# From 31b89fe119b4a0298da98891aa37b134facb6311 Mon Sep 17 00:00:00 2001 +# From: yasumori <ysmr@protonmail.com> +# Date: Fri, 27 May 2022 00:21:27 -0400 +# Subject: [PATCH] This patch allows the user to switch the selected tag of all +# monitors. +# +# For example, if monitor A is currently on tag 1, and monitor B is on tag 2, +# and the user presses MODKEY+SUPERKEY+3, both monitor A and B will switch to +# tag 3 (without changing the currently selected monitor). +# --- +# config.def.h | 2 ++ +# dwm.c | 13 +++++++++++++ +# 2 files changed, 15 insertions(+) + +diff --git a/config.def.h b/config.def.h +index a2ac963..3f504ab 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -46,8 +46,10 @@ static const Layout layouts[] = { + + /* key definitions */ + #define MODKEY Mod1Mask ++#define SUPERKEY Mod4Mask + #define TAGKEYS(KEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ ++ { MODKEY|SUPERKEY, KEY, viewall, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, +diff --git a/dwm.c b/dwm.c +index 5646a5c..28736ee 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -228,6 +228,7 @@ static void updatetitle(Client *c); + static void updatewindowtype(Client *c); + static void updatewmhints(Client *c); + static void view(const Arg *arg); ++static void viewall(const Arg *arg); + static Client *wintoclient(Window w); + static Monitor *wintomon(Window w); + static int xerror(Display *dpy, XErrorEvent *ee); +@@ -2054,6 +2055,18 @@ view(const Arg *arg) + arrange(selmon); + } + ++void ++viewall(const Arg *arg) ++{ ++ Monitor *m; ++ ++ for (m = mons; m; m = m->next) { ++ m->tagset[m->seltags] = arg->ui; ++ arrange(m); ++ } ++ focus(NULL); ++} ++ + Client * + wintoclient(Window w) + { +-- +2.36.1 diff --git a/dwm/patches/dwm-taglabels-hide_vacant_tags_funcionality-6.2.diff b/dwm/patches/dwm-taglabels-hide_vacant_tags_funcionality-6.2.diff new file mode 100644 index 0000000..d27b0d8 --- /dev/null +++ b/dwm/patches/dwm-taglabels-hide_vacant_tags_funcionality-6.2.diff @@ -0,0 +1,91 @@ +diff -pu dwm.hide_vacant_tags/config.def.h dwm.programtags+hidewithvacanttags/config.def.h +--- dwm.hide_vacant_tags/config.def.h 2021-03-15 16:37:24.586622415 -0500 ++++ dwm.programtags+hidewithvacanttags/config.def.h 2021-03-15 16:32:37.586956549 -0500 +@@ -21,6 +21,10 @@ static const char *colors[][3] = { + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + ++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 */ ++ + static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class +diff -pu dwm.hide_vacant_tags/dwm.c dwm.programtags+hidewithvacanttags/dwm.c +--- dwm.hide_vacant_tags/dwm.c 2021-03-15 16:37:38.189939908 -0500 ++++ dwm.programtags+hidewithvacanttags/dwm.c 2021-03-15 16:32:23.693639390 -0500 +@@ -20,6 +20,7 @@ + * + * To understand everything else, start reading main(). + */ ++#include <ctype.h> /* for making tab label lowercase, very tiny standard library */ + #include <errno.h> + #include <locale.h> + #include <signal.h> +@@ -272,6 +273,8 @@ static Window root, wmcheckwin; + /* configuration, allows nested code to access above variables */ + #include "config.h" + ++unsigned int tagw[LENGTH(tags)]; ++ + /* compile-time check if all tags fit into an unsigned int bit array. */ + struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +@@ -438,7 +441,7 @@ buttonpress(XEvent *e) + /* do not reserve space for vacant tags */ + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) + continue; +- x += TEXTW(tags[i]); ++ x += tagw[i]; + } while (ev->x >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; +@@ -706,6 +709,8 @@ drawbar(Monitor *m) + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; + Client *c; ++ char tagdisp[64]; ++ char *masterclientontag[LENGTH(tags)]; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ +@@ -714,10 +719,21 @@ drawbar(Monitor *m) + drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); + } + ++ for (i = 0; i < LENGTH(tags); i++) ++ masterclientontag[i] = NULL; ++ + for (c = m->clients; c; c = c->next) { + occ |= c->tags == 255 ? 0 : c->tags; + if (c->isurgent) + urg |= c->tags; ++ for (i = 0; i < LENGTH(tags); i++) ++ if (!masterclientontag[i] && c->tags & (1<<i)) { ++ XClassHint ch = { NULL, NULL }; ++ XGetClassHint(dpy, c->win, &ch); ++ masterclientontag[i] = ch.res_class; ++ if (lcaselbl) ++ masterclientontag[i][0] = tolower(masterclientontag[i][0]); ++ } + } + x = 0; + for (i = 0; i < LENGTH(tags); i++) { +@@ -725,9 +741,14 @@ drawbar(Monitor *m) + if (!(occ & 1 << i || m->tagset[m->seltags] & 1 << i)) + continue; + +- w = TEXTW(tags[i]); ++ if (masterclientontag[i]) ++ snprintf(tagdisp, 64, ptagf, tags[i], masterclientontag[i]); ++ else ++ snprintf(tagdisp, 64, etagf, tags[i]); ++ masterclientontag[i] = tagdisp; ++ tagw[i] = w = TEXTW(masterclientontag[i]); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); +- drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); ++ drw_text(drw, x, 0, w, bh, lrpad / 2, masterclientontag[i], urg & 1 << i); + x += w; + } + w = blw = TEXTW(m->ltsymbol); diff --git a/dwm/patches/dwm-tiledmove-20231210-b731.diff b/dwm/patches/dwm-tiledmove-20231210-b731.diff new file mode 100644 index 0000000..8ede0c6 --- /dev/null +++ b/dwm/patches/dwm-tiledmove-20231210-b731.diff @@ -0,0 +1,82 @@ +# From 427c5fef13676179621949f0a8a4036e49d4b74e Mon Sep 17 00:00:00 2001 +# From: Niki <> +# Date: Sun, 10 Dec 2023 00:29:59 +0000 +# Subject: [PATCH] The function `movemouse` now doesn't force clients to be +# floating. +# +# Tiling clients when moved will swap with any existing clients that +# overlap with the cursor, and snap to other monitors. +# --- +# dwm.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- +# 1 file changed, 53 insertions(+), 3 deletions(-) + +diff --git a/dwm.c b/dwm.c +index d12be2d..b1023e0 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1189,11 +1189,60 @@ movemouse(const Arg *arg) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); +- if (!c->isfloating && selmon->lt[selmon->sellt]->arrange +- && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) +- togglefloating(NULL); + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, nx, ny, c->w, c->h, 1); ++ else if (selmon->lt[selmon->sellt]->arrange || !c->isfloating) { ++ if ((m = recttomon(ev.xmotion.x_root, ev.xmotion.y_root, 1, 1)) != selmon) { ++ sendmon(c, m); ++ selmon = m; ++ focus(NULL); ++ } ++ ++ Client *cc = c->mon->clients; ++ while (1) { ++ if (cc == 0) break; ++ if( ++ cc != c && !cc->isfloating && ISVISIBLE(cc) && ++ ev.xmotion.x_root > cc->x && ++ ev.xmotion.x_root < cc->x + cc->w && ++ ev.xmotion.y_root > cc->y && ++ ev.xmotion.y_root < cc->y + cc->h ) { ++ break; ++ } ++ ++ cc = cc->next; ++ } ++ ++ if (cc) { ++ Client *cl1, *cl2, ocl1; ++ ++ if (!selmon->lt[selmon->sellt]->arrange) return; ++ ++ cl1 = c; ++ cl2 = cc; ++ ocl1 = *cl1; ++ strcpy(cl1->name, cl2->name); ++ cl1->win = cl2->win; ++ cl1->x = cl2->x; ++ cl1->y = cl2->y; ++ cl1->w = cl2->w; ++ cl1->h = cl2->h; ++ ++ cl2->win = ocl1.win; ++ strcpy(cl2->name, ocl1.name); ++ cl2->x = ocl1.x; ++ cl2->y = ocl1.y; ++ cl2->w = ocl1.w; ++ cl2->h = ocl1.h; ++ ++ selmon->sel = cl2; ++ ++ c = cc; ++ focus(c); ++ ++ arrange(cl1->mon); ++ } ++ } + break; + } + } while (ev.type != ButtonRelease); +-- +2.43.0 diff --git a/dwm/patches/dwm-toggleallmonspertag-6.4.diff b/dwm/patches/dwm-toggleallmonspertag-6.4.diff new file mode 100644 index 0000000..32527f6 --- /dev/null +++ b/dwm/patches/dwm-toggleallmonspertag-6.4.diff @@ -0,0 +1,74 @@ +diff --git a/config.def.h b/config.def.h +index 061ad66..67afc6d 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -71,6 +71,7 @@ static const Key keys[] = { + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, ++ { MODKEY|ShiftMask, XK_Tab, toggleall, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, +diff --git a/dwm.c b/dwm.c +index e5efb6a..62f711b 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -210,6 +210,7 @@ static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); ++static void toggleall(const Arg *arg); + static void togglebar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); +@@ -1694,6 +1695,49 @@ tile(Monitor *m) + } + } + ++ ++void ++toggleall(const Arg *arg) ++{ ++ int i; ++ unsigned int tmptag; ++ ++ Monitor* m; ++ for(m = mons; m; m = m->next){ ++ ++ if ((arg->ui & TAGMASK) == m->tagset[m->seltags]) ++ return; ++ m->seltags ^= 1; /* toggle sel tagset */ ++ if (arg->ui & TAGMASK) { ++ m->tagset[m->seltags] = arg->ui & TAGMASK; ++ m->pertag->prevtag = m->pertag->curtag; ++ ++ if (arg->ui == ~0) ++ m->pertag->curtag = 0; ++ else { ++ for (i = 0; !(arg->ui & 1 << i); i++) ; ++ m->pertag->curtag = i + 1; ++ } ++ } else { ++ tmptag = m->pertag->prevtag; ++ m->pertag->prevtag = m->pertag->curtag; ++ m->pertag->curtag = tmptag; ++ } ++ ++ m->nmaster = m->pertag->nmasters[m->pertag->curtag]; ++ m->mfact = m->pertag->mfacts[m->pertag->curtag]; ++ m->sellt = m->pertag->sellts[m->pertag->curtag]; ++ m->lt[m->sellt] = m->pertag->ltidxs[m->pertag->curtag][m->sellt]; ++ m->lt[m->sellt^1] = m->pertag->ltidxs[m->pertag->curtag][m->sellt^1]; ++ ++ if (m->showbar != m->pertag->showbars[m->pertag->curtag]) ++ togglebar(NULL); ++ ++ focus(NULL); ++ arrange(m); ++ } ++} ++ + void + togglebar(const Arg *arg) + { diff --git a/dwm/patches/dwm-toggleborder-6.3.diff b/dwm/patches/dwm-toggleborder-6.3.diff new file mode 100644 index 0000000..adc6bd0 --- /dev/null +++ b/dwm/patches/dwm-toggleborder-6.3.diff @@ -0,0 +1,52 @@ +# From ef85b0473590615fda4ba4b20a717e42c99e3f99 Mon Sep 17 00:00:00 2001 +# From: Stanisław Bitner <sbitner420@tutanota.com> +# Date: Tue, 9 Aug 2022 23:17:47 +0200 +# Subject: [PATCH] toggleborder +# +# This patch allows you to toggle client border. It works by setting the +# border of the client to 0 or to borderpx defined in configuration file. +# --- +# config.def.h | 1 + +# dwm.c | 8 ++++++++ +# 2 files changed, 9 insertions(+) + +diff --git a/config.def.h b/config.def.h +index a2ac963..60b811f 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -65,6 +65,7 @@ static Key keys[] = { + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, ++ { MODKEY|ShiftMask, XK_b, toggleborder, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, +diff --git a/dwm.c b/dwm.c +index 967c9e8..91d00f6 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -211,6 +211,7 @@ static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglebar(const Arg *arg); ++static void toggleborder(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); +@@ -1707,6 +1708,13 @@ togglebar(const Arg *arg) + arrange(selmon); + } + ++void ++toggleborder(const Arg *arg) ++{ ++ selmon->sel->bw = (selmon->sel->bw == borderpx ? 0 : borderpx); ++ arrange(selmon); ++} ++ + void + togglefloating(const Arg *arg) + { +-- +2.37.1 diff --git a/dwm/patches/dwm-togglefloatingcenter-20210806-138b405f.diff b/dwm/patches/dwm-togglefloatingcenter-20210806-138b405f.diff new file mode 100644 index 0000000..6e3c3d0 --- /dev/null +++ b/dwm/patches/dwm-togglefloatingcenter-20210806-138b405f.diff @@ -0,0 +1,30 @@ +# From efa326b2c71f0df1d097fd52a17684f5ccc5df6c Mon Sep 17 00:00:00 2001 +# From: Rizqi Nur Assyaufi <bandithijo@gmail.com> +# Date: Sat, 7 Aug 2021 00:24:01 +0800 +# Subject: [PATCH] [dwm][patch][togglefloatingcenter] centered togglefloating +# window +# +# Default behaviour when togglefloating() is floating from top-left corner. +# This patch will allows you to toggle floating window client will be centered +# position. +# --- +# dwm.c | 4 ++++ +# 1 file changed, 4 insertions(+) + +diff --git a/dwm.c b/dwm.c +index 5e4d494..cbedb09 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1719,6 +1719,10 @@ togglefloating(const Arg *arg) + if (selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, 0); ++ ++ selmon->sel->x = selmon->sel->mon->mx + (selmon->sel->mon->mw - WIDTH(selmon->sel)) / 2; ++ selmon->sel->y = selmon->sel->mon->my + (selmon->sel->mon->mh - HEIGHT(selmon->sel)) / 2; ++ + arrange(selmon); + } + +-- +2.31.1 diff --git a/dwm/patches/dwm-toggletopbar-barpadding-6.4.diff b/dwm/patches/dwm-toggletopbar-barpadding-6.4.diff new file mode 100644 index 0000000..982fa3d --- /dev/null +++ b/dwm/patches/dwm-toggletopbar-barpadding-6.4.diff @@ -0,0 +1,43 @@ +diff -up a/config.def.h b/config.def.h +--- a/config.def.h 2022-10-28 22:20:44.531059708 +0200 ++++ b/config.def.h 2022-10-28 22:21:12.621059000 +0200 +@@ -67,6 +67,7 @@ static const Key keys[] = { + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, ++ { MODKEY, XK_t, toggletopbar, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, +diff -up a/b.c b/b.c +--- a/b.c 2022-10-28 22:20:44.532059708 +0200 ++++ b/b.c 2022-10-28 22:23:27.019055613 +0200 +@@ -211,6 +211,7 @@ static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *m); + static void togglebar(const Arg *arg); ++static void toggletopbar(const Arg *arg); + static void togglefloating(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); +@@ -1710,6 +1711,20 @@ togglebar(const Arg *arg) + arrange(selmon); + } + ++void ++toggletopbar(const Arg *arg) ++{ ++ selmon->topbar = !selmon->topbar; ++ updatebarpos(selmon); ++ ++ if (selmon->topbar) ++ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx + sp, selmon->by + vp, selmon->ww - 2 * sp, bh); ++ else ++ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx + sp, selmon->by - vp, selmon->ww - 2 * sp, bh); ++ ++ arrange(selmon); ++} ++ + void + togglefloating(const Arg *arg) + { diff --git a/dwm/patches/dwm-unicode_ellipsis-20222909-d3f93c7.diff b/dwm/patches/dwm-unicode_ellipsis-20222909-d3f93c7.diff new file mode 100644 index 0000000..a03f88f --- /dev/null +++ b/dwm/patches/dwm-unicode_ellipsis-20222909-d3f93c7.diff @@ -0,0 +1,22 @@ +diff --git a/drw.c b/drw.c +index ced7d37..95da860 100644 +--- a/drw.c ++++ b/drw.c +@@ -285,7 +285,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + + usedfont = drw->fonts; + if (!ellipsis_width && render) +- ellipsis_width = drw_fontset_getwidth(drw, "..."); ++ ellipsis_width = drw_fontset_getwidth(drw, "…"); + while (1) { + ew = ellipsis_len = utf8strlen = 0; + utf8str = text; +@@ -339,7 +339,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + w -= ew; + } + if (render && overflow) +- drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert); ++ drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "…", invert); + + if (!*text || overflow) { + break; diff --git a/dwm/patches/dwm-xresources-20210827-138b405.diff b/dwm/patches/dwm-xresources-20210827-138b405.diff new file mode 100644 index 0000000..2a3a594 --- /dev/null +++ b/dwm/patches/dwm-xresources-20210827-138b405.diff @@ -0,0 +1,239 @@ +# From f30583c6e2ab5e7de6ef4ebf156076ac0f6e69fc Mon Sep 17 00:00:00 2001 +# From: Jack Bird <jack.bird@durham.ac.uk> +# Date: Fri, 27 Aug 2021 00:53:14 +0100 +# Subject: [PATCH] xresources updated for 138b405 +# +# --- +# config.def.h | 61 ++++++++++++++++++++++++++++++-------------- +# drw.c | 2 +- +# drw.h | 2 +- +# dwm.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ +# 4 files changed, 116 insertions(+), 21 deletions(-) + +diff --git a/config.def.h b/config.def.h +index a2ac963..87ac198 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -1,21 +1,23 @@ + /* See LICENSE file for copyright and license details. */ + + /* appearance */ +-static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const unsigned int snap = 32; /* snap pixel */ +-static const int showbar = 1; /* 0 means no bar */ +-static const int topbar = 1; /* 0 means bottom bar */ +-static const char *fonts[] = { "monospace:size=10" }; +-static const char dmenufont[] = "monospace:size=10"; +-static const char col_gray1[] = "#222222"; +-static const char col_gray2[] = "#444444"; +-static const char col_gray3[] = "#bbbbbb"; +-static const char col_gray4[] = "#eeeeee"; +-static const char col_cyan[] = "#005577"; +-static const char *colors[][3] = { +- /* fg bg border */ +- [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, +- [SchemeSel] = { col_gray4, col_cyan, col_cyan }, ++static unsigned int borderpx = 1; /* border pixel of windows */ ++static unsigned int snap = 32; /* snap pixel */ ++static int showbar = 1; /* 0 means no bar */ ++static int topbar = 1; /* 0 means bottom bar */ ++static char font[] = "monospace:size=10"; ++static char dmenufont[] = "monospace:size=10"; ++static const char *fonts[] = { font }; ++static char normbgcolor[] = "#222222"; ++static char normbordercolor[] = "#444444"; ++static char normfgcolor[] = "#bbbbbb"; ++static char selfgcolor[] = "#eeeeee"; ++static char selbordercolor[] = "#005577"; ++static char selbgcolor[] = "#005577"; ++static char *colors[][3] = { ++ /* fg bg border */ ++ [SchemeNorm] = { normfgcolor, normbgcolor, normbordercolor }, ++ [SchemeSel] = { selfgcolor, selbgcolor, selbordercolor }, + }; + + /* tagging */ +@@ -32,9 +34,9 @@ static const Rule rules[] = { + }; + + /* layout(s) */ +-static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +-static const int nmaster = 1; /* number of clients in master area */ +-static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ ++static float mfact = 0.55; /* factor of master area size [0.05..0.95] */ ++static int nmaster = 1; /* number of clients in master area */ ++static int resizehints = 1; /* 1 means respect size hints in tiled resizals */ + static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ + + static const Layout layouts[] = { +@@ -57,9 +59,30 @@ static const Layout layouts[] = { + + /* commands */ + static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ +-static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; ++static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbordercolor, "-sf", selfgcolor, NULL }; + static const char *termcmd[] = { "st", NULL }; + ++/* ++ * Xresources preferences to load at startup ++ */ ++ResourcePref resources[] = { ++ { "font", STRING, &font }, ++ { "dmenufont", STRING, &dmenufont }, ++ { "normbgcolor", STRING, &normbgcolor }, ++ { "normbordercolor", STRING, &normbordercolor }, ++ { "normfgcolor", STRING, &normfgcolor }, ++ { "selbgcolor", STRING, &selbgcolor }, ++ { "selbordercolor", STRING, &selbordercolor }, ++ { "selfgcolor", STRING, &selfgcolor }, ++ { "borderpx", INTEGER, &borderpx }, ++ { "snap", INTEGER, &snap }, ++ { "showbar", INTEGER, &showbar }, ++ { "topbar", INTEGER, &topbar }, ++ { "nmaster", INTEGER, &nmaster }, ++ { "resizehints", INTEGER, &resizehints }, ++ { "mfact", FLOAT, &mfact }, ++}; ++ + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +diff --git a/drw.c b/drw.c +index 4cdbcbe..8f1059e 100644 +--- a/drw.c ++++ b/drw.c +@@ -208,7 +208,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) + /* Wrapper to create color schemes. The caller has to call free(3) on the + * returned color scheme when done using it. */ + Clr * +-drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) ++drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount) + { + size_t i; + Clr *ret; +diff --git a/drw.h b/drw.h +index 4bcd5ad..42b04ce 100644 +--- a/drw.h ++++ b/drw.h +@@ -39,7 +39,7 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in + + /* Colorscheme abstraction */ + void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); +-Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); ++Clr *drw_scm_create(Drw *drw, char *clrnames[], size_t clrcount); + + /* Cursor abstraction */ + Cur *drw_cur_create(Drw *drw, int shape); +diff --git a/dwm.c b/dwm.c +index 5e4d494..2214b19 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -36,6 +36,7 @@ + #include <X11/Xlib.h> + #include <X11/Xproto.h> + #include <X11/Xutil.h> ++#include <X11/Xresource.h> + #ifdef XINERAMA + #include <X11/extensions/Xinerama.h> + #endif /* XINERAMA */ +@@ -141,6 +142,19 @@ typedef struct { + int monitor; + } Rule; + ++/* Xresources preferences */ ++enum resource_type { ++ STRING = 0, ++ INTEGER = 1, ++ FLOAT = 2 ++}; ++ ++typedef struct { ++ char *name; ++ enum resource_type type; ++ void *dst; ++} ResourcePref; ++ + /* function declarations */ + static void applyrules(Client *c); + static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +@@ -234,6 +248,8 @@ static int xerror(Display *dpy, XErrorEvent *ee); + static int xerrordummy(Display *dpy, XErrorEvent *ee); + static int xerrorstart(Display *dpy, XErrorEvent *ee); + static void zoom(const Arg *arg); ++static void load_xresources(void); ++static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst); + + /* variables */ + static const char broken[] = "broken"; +@@ -2127,6 +2143,60 @@ zoom(const Arg *arg) + pop(c); + } + ++void ++resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst) ++{ ++ char *sdst = NULL; ++ int *idst = NULL; ++ float *fdst = NULL; ++ ++ sdst = dst; ++ idst = dst; ++ fdst = dst; ++ ++ char fullname[256]; ++ char *type; ++ XrmValue ret; ++ ++ snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name); ++ fullname[sizeof(fullname) - 1] = '\0'; ++ ++ XrmGetResource(db, fullname, "*", &type, &ret); ++ if (!(ret.addr == NULL || strncmp("String", type, 64))) ++ { ++ switch (rtype) { ++ case STRING: ++ strcpy(sdst, ret.addr); ++ break; ++ case INTEGER: ++ *idst = strtoul(ret.addr, NULL, 10); ++ break; ++ case FLOAT: ++ *fdst = strtof(ret.addr, NULL); ++ break; ++ } ++ } ++} ++ ++void ++load_xresources(void) ++{ ++ Display *display; ++ char *resm; ++ XrmDatabase db; ++ ResourcePref *p; ++ ++ display = XOpenDisplay(NULL); ++ resm = XResourceManagerString(display); ++ if (!resm) ++ return; ++ ++ db = XrmGetStringDatabase(resm); ++ for (p = resources; p < resources + LENGTH(resources); p++) ++ resource_load(db, p->name, p->type, p->dst); ++ XCloseDisplay(display); ++} ++ + int + main(int argc, char *argv[]) + { +@@ -2139,6 +2209,8 @@ main(int argc, char *argv[]) + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + checkotherwm(); ++ XrmInitialize(); ++ load_xresources(); + setup(); + #ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec", NULL) == -1) +-- +2.33.0 diff --git a/dwm/patches/dwmblocks-statuscmd-20210402-96cbb45.diff b/dwm/patches/dwmblocks-statuscmd-20210402-96cbb45.diff new file mode 100644 index 0000000..982f93a --- /dev/null +++ b/dwm/patches/dwmblocks-statuscmd-20210402-96cbb45.diff @@ -0,0 +1,126 @@ +# From 1669878c08607f481e3f879d6914fc4d3c9d7206 Mon Sep 17 00:00:00 2001 +# From: Daniel Bylinka <daniel.bylinka@gmail.com> +# Date: Fri, 2 Apr 2021 19:20:17 +0200 +# Subject: [PATCH] [statuscmd] Format status text and handle button signals +# +# --- +# dwmblocks.c | 48 +++++++++++++++++++++++++++++++++++++++++------- +# 1 file changed, 41 insertions(+), 7 deletions(-) + +diff --git a/dwmblocks.c b/dwmblocks.c +index ded717c..78fdeb5 100644 +--- a/dwmblocks.c ++++ b/dwmblocks.c +@@ -3,6 +3,7 @@ + #include<string.h> + #include<unistd.h> + #include<signal.h> ++#include<sys/wait.h> + #ifndef NO_X + #include<X11/Xlib.h> + #endif +@@ -27,14 +28,14 @@ typedef struct { + #ifndef __OpenBSD__ + void dummysighandler(int num); + #endif +-void sighandler(int num); + void getcmds(int time); + void getsigcmds(unsigned int signal); + void setupsignals(); +-void sighandler(int signum); ++void sighandler(int signum, siginfo_t *si, void *ucontext); + int getstatus(char *str, char *last); + void statusloop(); + void termhandler(); ++void chldhandler(); + void pstdout(); + #ifndef NO_X + void setroot(); +@@ -58,6 +59,8 @@ static int returnStatus = 0; + //opens process *cmd and stores output in *output + void getcmd(const Block *block, char *output) + { ++ if (block->signal) ++ *output++ = block->signal; + strcpy(output, block->icon); + FILE *cmdf = popen(block->command, "r"); + if (!cmdf) +@@ -102,15 +105,18 @@ void getsigcmds(unsigned int signal) + + void setupsignals() + { ++ struct sigaction sa = { .sa_sigaction = sighandler, .sa_flags = SA_SIGINFO }; + #ifndef __OpenBSD__ + /* initialize all real time signals with dummy handler */ +- for (int i = SIGRTMIN; i <= SIGRTMAX; i++) ++ for (int i = SIGRTMIN; i <= SIGRTMAX; i++) { + signal(i, dummysighandler); ++ sigaddset(&sa.sa_mask, i); ++ } + #endif + + for (unsigned int i = 0; i < LENGTH(blocks); i++) { + if (blocks[i].signal > 0) +- signal(SIGMINUS+blocks[i].signal, sighandler); ++ sigaction(SIGMINUS+blocks[i].signal, &sa, NULL); + } + + } +@@ -178,10 +184,32 @@ void dummysighandler(int signum) + } + #endif + +-void sighandler(int signum) ++void sighandler(int signum, siginfo_t *si, void *ucontext) + { +- getsigcmds(signum-SIGPLUS); +- writestatus(); ++ if (si->si_value.sival_int) { ++ pid_t parent = getpid(); ++ if (fork() == 0) { ++#ifndef NO_X ++ if (dpy) ++ close(ConnectionNumber(dpy)); ++#endif ++ int i; ++ for (i = 0; i < LENGTH(blocks) && blocks[i].signal != signum-SIGRTMIN; i++); ++ ++ char shcmd[1024]; ++ sprintf(shcmd, "%s; kill -%d %d", blocks[i].command, SIGRTMIN+blocks[i].signal, parent); ++ char *cmd[] = { "/bin/sh", "-c", shcmd, NULL }; ++ char button[2] = { '0' + si->si_value.sival_int, '\0' }; ++ setenv("BUTTON", button, 1); ++ setsid(); ++ execvp(cmd[0], cmd); ++ perror(cmd[0]); ++ exit(EXIT_SUCCESS); ++ } ++ } else { ++ getsigcmds(signum-SIGPLUS); ++ writestatus(); ++ } + } + + void termhandler() +@@ -189,6 +217,11 @@ void termhandler() + statusContinue = 0; + } + ++void chldhandler() ++{ ++ while (0 < waitpid(-1, NULL, WNOHANG)); ++} ++ + int main(int argc, char** argv) + { + for (int i = 0; i < argc; i++) {//Handle command line arguments +@@ -205,6 +238,7 @@ int main(int argc, char** argv) + delim[delimLen++] = '\0'; + signal(SIGTERM, termhandler); + signal(SIGINT, termhandler); ++ signal(SIGCHLD, chldhandler); + statusloop(); + #ifndef NO_X + XCloseDisplay(dpy); +-- +2.31.0 |
