aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README48
-rw-r--r--README.md22
-rw-r--r--config.h130
-rw-r--r--drw.obin0 -> 10072 bytes
-rwxr-xr-xdwmbin0 -> 70224 bytes
-rw-r--r--dwm.obin0 -> 59712 bytes
-rw-r--r--patches/autostart.diff180
-rw-r--r--patches/dwm-alwayscenter-20200625-f04cac6.diff12
-rw-r--r--patches/dwm-namedscratchpads-6.2.diff138
-rw-r--r--patches/dwm-pertag-20200914-61bb8b2.diff177
-rw-r--r--patches/dwm-vanitygaps-20200610-f09418b.diff262
-rw-r--r--util.obin0 -> 2224 bytes
12 files changed, 921 insertions, 48 deletions
diff --git a/README b/README
deleted file mode 100644
index 95d4fd0..0000000
--- a/README
+++ /dev/null
@@ -1,48 +0,0 @@
-dwm - dynamic window manager
-============================
-dwm is an extremely fast, small, and dynamic window manager for X.
-
-
-Requirements
-------------
-In order to build dwm you need the Xlib header files.
-
-
-Installation
-------------
-Edit config.mk to match your local setup (dwm is installed into
-the /usr/local namespace by default).
-
-Afterwards enter the following command to build and install dwm (if
-necessary as root):
-
- make clean install
-
-
-Running dwm
------------
-Add the following line to your .xinitrc to start dwm using startx:
-
- exec dwm
-
-In order to connect dwm to a specific display, make sure that
-the DISPLAY environment variable is set correctly, e.g.:
-
- DISPLAY=foo.bar:1 exec dwm
-
-(This will start dwm on display :1 of the host foo.bar.)
-
-In order to display status info in the bar, you can do something
-like this in your .xinitrc:
-
- while xsetroot -name "`date` `uptime | sed 's/.*,//'`"
- do
- sleep 1
- done &
- exec dwm
-
-
-Configuration
--------------
-The configuration of dwm is done by creating a custom config.h
-and (re)compiling the source code.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c7b1725
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# Kumar's DWM build
+This repo has been created from the `dwm` source repo, and modified with a few patches that serve *my* workflow.
+
+## Requirements
+In order to build dwm you need the Xlib header files for your distro.
+
+## Installation
+```
+make clean install
+```
+
+## Configuration
+The configuration of dwm is done by creating a custom config.h and (re)compiling the source code.
+
+## Patches
+You can find all the patches used in the `patches/` dir. All of these can be found in the patches page in the official dwm website.
+
+- autostart
+- vanitygaps
+- pertag
+- scratchpad
+- always centered
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..209262b
--- /dev/null
+++ b/config.h
@@ -0,0 +1,130 @@
+/* See LICENSE file for copyright and license details. */
+
+/* appearance */
+static const unsigned int borderpx = 0; /* 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 = 20; /* vert inner gap between windows */
+static const unsigned int gappoh = 20; /* horiz outer gap between windows and screen edge */
+static const unsigned int gappov = 20; /* vert outer gap between windows and screen edge */
+static const 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" };
+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 },
+};
+
+/* 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 scratch key */
+ { "Gimp", NULL, NULL, 0, 1, -1, 0 },
+ { "Firefox", NULL, NULL, 1 << 8, 0, -1, 0 },
+ { "Vivaldi", NULL, NULL, 1 << 8, 0, -1, 0 },
+ { "Brave", NULL, NULL, 1 << 8, 0, -1, 0 },
+ { "KeePassXC", NULL, NULL, 1 << 3, 0, -1, 0 },
+ { "Mattermost", NULL, NULL, 1 << 0, 0, 0, 0 },
+ { "Signal", NULL, NULL, 1 << 0, 0, 0, 0 },
+ { NULL, NULL, "scratchpad", 0, 1, -1, 's' },
+};
+
+/* 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 const Layout layouts[] = {
+ /* symbol arrange function */
+ { "[]=", tile }, /* first entry is default */
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { "[M]", monocle },
+};
+
+/* 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} },
+
+/* 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 };
+static const char *scratchpadcmd[] = {"s", "st", "-t", "scratchpad", NULL };
+
+static Key keys[] = {
+ /* modifier key function argument */
+ { 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_equal, incrgaps, {.i = +2 } },
+ { MODKEY, XK_minus, incrgaps, {.i = -2 } },
+ { MODKEY|ShiftMask, XK_equal, defaultgaps, {0} },
+ { MODKEY|ShiftMask, XK_minus, togglegaps, {0} },
+ { MODKEY, XK_Return, zoom, {0} },
+ { MODKEY, XK_Tab, view, {0} },
+ { MODKEY, XK_q, 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, XK_grave, togglescratch, {.v = scratchpadcmd } },
+ 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_Escape, quit, {0} },
+};
+
+/* button definitions */
+/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
+static Button buttons[] = {
+ /* click event mask button function argument */
+ { ClkLtSymbol, 0, Button1, setlayout, {0} },
+ { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
+ { 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/drw.o b/drw.o
new file mode 100644
index 0000000..1d05dfc
--- /dev/null
+++ b/drw.o
Binary files differ
diff --git a/dwm b/dwm
new file mode 100755
index 0000000..1024aad
--- /dev/null
+++ b/dwm
Binary files differ
diff --git a/dwm.o b/dwm.o
new file mode 100644
index 0000000..7a19b11
--- /dev/null
+++ b/dwm.o
Binary files differ
diff --git a/patches/autostart.diff b/patches/autostart.diff
new file mode 100644
index 0000000..be9206f
--- /dev/null
+++ b/patches/autostart.diff
@@ -0,0 +1,180 @@
+From 37e970479dc5d40e57fc0cbfeaa5e39941483237 Mon Sep 17 00:00:00 2001
+From: Gan Ainm <gan.ainm.riomhphost@gmail.com>
+Date: Wed, 10 Jun 2020 10:59:02 +0000
+Subject: [PATCH] dwm-xdgautostart-6.2.diff
+
+===================================================================
+---
+ dwm.1 | 23 +++++++++++++++++
+ dwm.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 105 insertions(+)
+
+diff --git a/dwm.1 b/dwm.1
+index 13b3729..9533aa6 100644
+--- a/dwm.1
++++ b/dwm.1
+@@ -30,6 +30,14 @@ top left corner. The tags which are applied to one or more windows are
+ indicated with an empty square in the top left corner.
+ .P
+ dwm draws a small border around windows to indicate the focus state.
++.P
++On start, dwm can start additional programs that may be specified in two special
++shell scripts (see the FILES section below), autostart_blocking.sh and
++autostart.sh. The former is executed first and dwm will wait for its
++termination before starting. The latter is executed in the background before
++dwm enters its handler loop.
++.P
++Either of these files may be omitted.
+ .SH OPTIONS
+ .TP
+ .B \-v
+@@ -152,6 +160,21 @@ Toggles focused window between floating and tiled state.
+ .TP
+ .B Mod1\-Button3
+ Resize focused window while dragging. Tiled windows will be toggled to the floating state.
++.SH FILES
++The files containing programs to be started along with dwm are searched for in
++the following directories:
++.IP "1. $XDG_CONFIG_HOME/dwm"
++.IP "2. $HOME/.local/share/dwm"
++.IP "3. $HOME/.dwm"
++.P
++The first existing directory is scanned for any of the autostart files below.
++.TP 15
++autostart.sh
++This file is started as a shell background process before dwm enters its handler
++loop.
++.TP 15
++autostart_blocking.sh
++This file is started before any autostart.sh; dwm waits for its termination.
+ .SH CUSTOMIZATION
+ dwm is customized by creating a custom config.h and (re)compiling the source
+ code. This keeps it fast, secure and simple.
+diff --git a/dwm.c b/dwm.c
+index 4465af1..2156b49 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -29,6 +29,7 @@
+ #include <string.h>
+ #include <unistd.h>
+ #include <sys/types.h>
++#include <sys/stat.h>
+ #include <sys/wait.h>
+ #include <X11/cursorfont.h>
+ #include <X11/keysym.h>
+@@ -193,6 +194,7 @@ static void resizeclient(Client *c, int x, int y, int w, int h);
+ static void resizemouse(const Arg *arg);
+ static void restack(Monitor *m);
+ static void run(void);
++static void runautostart(void);
+ static void scan(void);
+ static int sendevent(Client *c, Atom proto);
+ static void sendmon(Client *c, Monitor *m);
+@@ -235,7 +237,11 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee);
+ static void zoom(const Arg *arg);
+
+ /* variables */
++static const char autostartblocksh[] = "autostart_blocking.sh";
++static const char autostartsh[] = "autostart.sh";
+ static const char broken[] = "broken";
++static const char dwmdir[] = "dwm";
++static const char localshare[] = ".local/share";
+ static char stext[256];
+ static int screen;
+ static int sw, sh; /* X display screen geometry width, height */
+@@ -1380,6 +1386,83 @@ run(void)
+ handler[ev.type](&ev); /* call handler */
+ }
+
++void
++runautostart(void)
++{
++ char *pathpfx;
++ char *path;
++ char *xdgdatahome;
++ char *home;
++ struct stat sb;
++
++ if ((home = getenv("HOME")) == NULL)
++ /* this is almost impossible */
++ return;
++
++ /* if $XDG_CONFIG_HOME is set and not empty, use $XDG_CONFIG_HOME/dwm,
++ * otherwise use ~/.local/share/dwm as autostart script directory
++ */
++ xdgdatahome = getenv("XDG_CONFIG_HOME");
++ if (xdgdatahome != NULL && *xdgdatahome != '\0') {
++ /* space for path segments, separators and nul */
++ pathpfx = ecalloc(1, strlen(xdgdatahome) + strlen(dwmdir) + 2);
++
++ if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) {
++ free(pathpfx);
++ return;
++ }
++ } else {
++ /* space for path segments, separators and nul */
++ pathpfx = ecalloc(1, strlen(home) + strlen(localshare)
++ + strlen(dwmdir) + 3);
++
++ if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) {
++ free(pathpfx);
++ return;
++ }
++ }
++
++ /* check if the autostart script directory exists */
++ if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) {
++ /* the XDG conformant path does not exist or is no directory
++ * so we try ~/.dwm instead
++ */
++ char *pathpfx_new = realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3);
++ if(pathpfx_new == NULL) {
++ free(pathpfx);
++ return;
++ }
++ pathpfx = pathpfx_new;
++
++ if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) {
++ free(pathpfx);
++ return;
++ }
++ }
++
++ /* try the blocking script first */
++ path = ecalloc(1, strlen(pathpfx) + strlen(autostartblocksh) + 2);
++ if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) {
++ free(path);
++ free(pathpfx);
++ }
++
++ if (access(path, X_OK) == 0)
++ system(path);
++
++ /* now the non-blocking script */
++ if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) {
++ free(path);
++ free(pathpfx);
++ }
++
++ if (access(path, X_OK) == 0)
++ system(strcat(path, " &"));
++
++ free(pathpfx);
++ free(path);
++}
++
+ void
+ scan(void)
+ {
+@@ -2142,6 +2223,7 @@ main(int argc, char *argv[])
+ die("pledge");
+ #endif /* __OpenBSD__ */
+ scan();
++ runautostart();
+ run();
+ cleanup();
+ XCloseDisplay(dpy);
+--
+2.27.0
+
+
diff --git a/patches/dwm-alwayscenter-20200625-f04cac6.diff b/patches/dwm-alwayscenter-20200625-f04cac6.diff
new file mode 100644
index 0000000..03ea9ef
--- /dev/null
+++ b/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/patches/dwm-namedscratchpads-6.2.diff b/patches/dwm-namedscratchpads-6.2.diff
new file mode 100644
index 0000000..d007118
--- /dev/null
+++ b/patches/dwm-namedscratchpads-6.2.diff
@@ -0,0 +1,138 @@
+diff '--color=auto' -up dwm-6.2/config.def.h dwm-6.2-new/config.def.h
+--- dwm-6.2/config.def.h 2019-02-02 12:55:28.000000000 +0000
++++ dwm-6.2-new/config.def.h 2020-04-26 13:51:06.713332746 +0100
+@@ -26,9 +26,10 @@ 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 scratch key */
++ { "Gimp", NULL, NULL, 0, 1, -1, 0 },
++ { "firefox", NULL, NULL, 1 << 8, 0, -1, 0 },
++ { NULL, NULL, "scratchpad", 0, 1, -1, 's' },
+ };
+
+ /* layout(s) */
+@@ -59,10 +60,14 @@ static char dmenumon[2] = "0"; /* compon
+ 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 };
+
++/*First arg only serves to match against key in rules*/
++static const char *scratchpadcmd[] = {"s", "st", "-t", "scratchpad", NULL};
++
+ static Key keys[] = {
+ /* modifier key function argument */
+ { MODKEY, XK_p, spawn, {.v = dmenucmd } },
+ { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
++ { MODKEY, XK_grave, togglescratch, {.v = scratchpadcmd } },
+ { MODKEY, XK_b, togglebar, {0} },
+ { MODKEY, XK_j, focusstack, {.i = +1 } },
+ { MODKEY, XK_k, focusstack, {.i = -1 } },
+diff '--color=auto' -up dwm-6.2/dwm.c dwm-6.2-new/dwm.c
+--- dwm-6.2/dwm.c 2019-02-02 12:55:28.000000000 +0000
++++ dwm-6.2-new/dwm.c 2020-04-26 13:55:56.820584361 +0100
+@@ -93,6 +93,7 @@ struct Client {
+ int bw, oldbw;
+ unsigned int tags;
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
++ char scratchkey;
+ Client *next;
+ Client *snext;
+ Monitor *mon;
+@@ -139,6 +140,7 @@ typedef struct {
+ unsigned int tags;
+ int isfloating;
+ int monitor;
++ const char scratchkey;
+ } Rule;
+
+ /* function declarations */
+@@ -206,11 +208,13 @@ 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 spawnscratch(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 togglescratch(const Arg *arg);
+ static void toggletag(const Arg *arg);
+ static void toggleview(const Arg *arg);
+ static void unfocus(Client *c, int setfocus);
+@@ -287,6 +291,7 @@ applyrules(Client *c)
+ /* rule matching */
+ c->isfloating = 0;
+ c->tags = 0;
++ c->scratchkey = 0;
+ XGetClassHint(dpy, c->win, &ch);
+ class = ch.res_class ? ch.res_class : broken;
+ instance = ch.res_name ? ch.res_name : broken;
+@@ -299,6 +304,7 @@ applyrules(Client *c)
+ {
+ c->isfloating = r->isfloating;
+ c->tags |= r->tags;
++ c->scratchkey = r->scratchkey;
+ for (m = mons; m && m->num != r->monitor; m = m->next);
+ if (m)
+ c->mon = m;
+@@ -308,6 +314,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];
+ }
+
+@@ -1652,6 +1659,19 @@ spawn(const Arg *arg)
+ }
+ }
+
++void spawnscratch(const Arg *arg)
++{
++ if (fork() == 0) {
++ if (dpy)
++ close(ConnectionNumber(dpy));
++ setsid();
++ execvp(((char **)arg->v)[1], ((char **)arg->v)+1);
++ fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[1]);
++ perror(" failed");
++ exit(EXIT_SUCCESS);
++ }
++}
++
+ void
+ tag(const Arg *arg)
+ {
+@@ -1720,6 +1740,28 @@ togglefloating(const Arg *arg)
+ }
+
+ void
++togglescratch(const Arg *arg)
++{
++ Client *c;
++ unsigned int found = 0;
++
++ for (c = selmon->clients; c && !(found = c->scratchkey == ((char**)arg->v)[0][0]); c = c->next);
++ if (found) {
++ c->tags = ISVISIBLE(c) ? 0 : selmon->tagset[selmon->seltags];
++ focus(NULL);
++ arrange(selmon);
++
++ if (ISVISIBLE(c)) {
++ focus(c);
++ restack(selmon);
++ }
++
++ } else{
++ spawnscratch(arg);
++ }
++}
++
++void
+ toggletag(const Arg *arg)
+ {
+ unsigned int newtags;
diff --git a/patches/dwm-pertag-20200914-61bb8b2.diff b/patches/dwm-pertag-20200914-61bb8b2.diff
new file mode 100644
index 0000000..c8d7fbc
--- /dev/null
+++ b/patches/dwm-pertag-20200914-61bb8b2.diff
@@ -0,0 +1,177 @@
+diff --git a/dwm.c b/dwm.c
+index 664c527..ac8e4ec 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 {
+@@ -272,6 +274,15 @@ 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 */
++};
++
+ /* compile-time check if all tags fit into an unsigned int bit array. */
+ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+
+@@ -632,6 +643,7 @@ Monitor *
+ createmon(void)
+ {
+ Monitor *m;
++ unsigned int i;
+
+ m = ecalloc(1, sizeof(Monitor));
+ m->tagset[0] = m->tagset[1] = 1;
+@@ -642,6 +654,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;
+ }
+
+@@ -967,7 +993,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);
+ }
+
+@@ -1502,9 +1528,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);
+@@ -1523,7 +1549,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);
+ }
+
+@@ -1702,7 +1728,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);
+@@ -1741,9 +1767,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);
+ }
+@@ -2038,11 +2088,37 @@ 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;
++ 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(NULL);
+ arrange(selmon);
+ }
diff --git a/patches/dwm-vanitygaps-20200610-f09418b.diff b/patches/dwm-vanitygaps-20200610-f09418b.diff
new file mode 100644
index 0000000..c8b13b2
--- /dev/null
+++ b/patches/dwm-vanitygaps-20200610-f09418b.diff
@@ -0,0 +1,262 @@
+From c35fd03ec002e1f4476a75203ff9b5cbcc630177 Mon Sep 17 00:00:00 2001
+From: Michel Boaventura <michel.boaventura@protonmail.com>
+Date: Wed, 10 Jun 2020 10:46:51 -0300
+Subject: [PATCH] Update Vanity Gaps to master
+
+---
+ config.def.h | 21 +++++++
+ dwm.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 163 insertions(+), 12 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..0927c2d 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 = 10; /* 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 = 10; /* vert outer gap between windows and screen edge */
++static const 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" };
+@@ -70,6 +75,22 @@ static Key keys[] = {
+ { MODKEY, XK_d, incnmaster, {.i = -1 } },
+ { MODKEY, XK_h, setmfact, {.f = -0.05} },
+ { MODKEY, XK_l, setmfact, {.f = +0.05} },
++ { MODKEY|Mod4Mask, XK_h, incrgaps, {.i = +1 } },
++ { MODKEY|Mod4Mask, XK_l, incrgaps, {.i = -1 } },
++ { MODKEY|Mod4Mask|ShiftMask, XK_h, incrogaps, {.i = +1 } },
++ { MODKEY|Mod4Mask|ShiftMask, XK_l, incrogaps, {.i = -1 } },
++ { MODKEY|Mod4Mask|ControlMask, XK_h, incrigaps, {.i = +1 } },
++ { MODKEY|Mod4Mask|ControlMask, XK_l, incrigaps, {.i = -1 } },
++ { MODKEY|Mod4Mask, XK_0, togglegaps, {0} },
++ { MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} },
++ { MODKEY, XK_y, incrihgaps, {.i = +1 } },
++ { MODKEY, XK_o, incrihgaps, {.i = -1 } },
++ { MODKEY|ControlMask, XK_y, incrivgaps, {.i = +1 } },
++ { MODKEY|ControlMask, XK_o, incrivgaps, {.i = -1 } },
++ { MODKEY|Mod4Mask, XK_y, incrohgaps, {.i = +1 } },
++ { MODKEY|Mod4Mask, XK_o, incrohgaps, {.i = -1 } },
++ { MODKEY|ShiftMask, XK_y, incrovgaps, {.i = +1 } },
++ { MODKEY|ShiftMask, XK_o, incrovgaps, {.i = -1 } },
+ { 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 9fd0286..50dbbaf 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -119,6 +119,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];
+@@ -200,6 +204,16 @@ 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 setgaps(int oh, int ov, int ih, int iv);
++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);
++static void defaultgaps(const Arg *arg);
+ static void setlayout(const Arg *arg);
+ static void setmfact(const Arg *arg);
+ static void setup(void);
+@@ -241,6 +255,7 @@ static char stext[256];
+ static int screen;
+ static int sw, sh; /* X display screen geometry width, height */
+ static int bh, blw = 0; /* bar geometry */
++static int enablegaps = 1; /* enables gaps, used by togglegaps */
+ static int lrpad; /* sum of left and right padding for text */
+ static int (*xerrorxlib)(Display *, XErrorEvent *);
+ static unsigned int numlockmask = 0;
+@@ -639,6 +654,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);
+@@ -1498,6 +1517,111 @@ setfullscreen(Client *c, int fullscreen)
+ }
+ }
+
++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)
++{
++ enablegaps = !enablegaps;
++ arrange(selmon);
++}
++
++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
+ setlayout(const Arg *arg)
+ {
+@@ -1674,28 +1798,34 @@ tagmon(const Arg *arg)
+ void
+ tile(Monitor *m)
+ {
+- unsigned int i, n, h, mw, my, ty;
++ unsigned int i, n, h, r, oe = enablegaps, ie = enablegaps, mw, my, ty;
+ Client *c;
+
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+
++ if (smartgaps == n) {
++ oe = 0; // outer gaps disabled
++ }
++
+ if (n > m->nmaster)
+- mw = m->nmaster ? m->ww * m->mfact : 0;
++ mw = m->nmaster ? (m->ww + m->gappiv*ie) * m->mfact : 0;
+ else
+- mw = m->ww;
+- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
++ mw = m->ww - 2*m->gappov*oe + m->gappiv*ie;
++ for (i = 0, my = ty = m->gappoh*oe, 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);
++ r = MIN(n, m->nmaster) - i;
++ h = (m->wh - my - m->gappoh*oe - m->gappih*ie * (r - 1)) / r;
++ resize(c, m->wx + m->gappov*oe, m->wy + my, mw - (2*c->bw) - m->gappiv*ie, h - (2*c->bw), 0);
++ if (my + HEIGHT(c) + m->gappih*ie < m->wh)
++ my += HEIGHT(c) + m->gappih*ie;
+ } 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);
++ r = n - i;
++ h = (m->wh - ty - m->gappoh*oe - m->gappih*ie * (r - 1)) / r;
++ resize(c, m->wx + mw + m->gappov*oe, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappov*oe, h - (2*c->bw), 0);
++ if (ty + HEIGHT(c) + m->gappih*ie < m->wh)
++ ty += HEIGHT(c) + m->gappih*ie;
+ }
+ }
+
+--
+2.27.0
+
diff --git a/util.o b/util.o
new file mode 100644
index 0000000..28fcd3a
--- /dev/null
+++ b/util.o
Binary files differ