aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dir-locals.el6
-rw-r--r--.gitignore9
-rw-r--r--Makefile3
-rw-r--r--README.org41
-rw-r--r--config.def.h30
-rw-r--r--config.h189
-rw-r--r--dwm.1261
-rw-r--r--dwm.c461
-rw-r--r--fibonacci.c66
-rw-r--r--gaplessgrid.c36
-rw-r--r--patches/dwm-attachaside-6.1.diff92
-rw-r--r--patches/dwm-centeredmaster-6.1.diff142
-rw-r--r--patches/dwm-colorbar-6.2.diff68
-rw-r--r--patches/dwm-deck-6.2.diff77
-rw-r--r--patches/dwm-deck-tilegap-6.1.diff55
-rw-r--r--patches/dwm-fibonacci-6.2.diff114
-rw-r--r--patches/dwm-fullgaps-6.2.diff95
-rw-r--r--patches/dwm-gaplessgrid-20160731-56a31dc.diff43
-rw-r--r--patches/dwm-gaplessgrid-add-gaps.diff32
-rw-r--r--patches/dwm-gaplessgrid-pertag-gaps.diff39
-rw-r--r--patches/dwm-gaps-pertag.diff163
-rw-r--r--patches/dwm-hide_vacant_tags-6.2.diff55
-rw-r--r--patches/dwm-inplacerotate-6.2.diff108
-rw-r--r--patches/dwm-monocle-gaps.diff29
-rw-r--r--patches/dwm-pertag-6.2.diff177
-rw-r--r--patches/dwm-remove-dmenu.diff30
-rw-r--r--patches/dwm-scratchpad-6.2.diff90
-rw-r--r--patches/dwm-statuscmd-20210405-67d76bd.diff208
-rw-r--r--patches/dwm-statuscmd-6.2.diff142
29 files changed, 2737 insertions, 124 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
new file mode 100644
index 0000000..f7ea9f8
--- /dev/null
+++ b/.dir-locals.el
@@ -0,0 +1,6 @@
+;;; Directory Local Variables -*- no-byte-compile: t; -*-
+;;; For more information see (info "(emacs) Directory Variables")
+
+((c-mode . ((indent-tabs-mode . t)
+ (flycheck-mode . nil)
+ (eval . (clang-format-mode 0)))))
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ef35fa6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+.DS_Store
+.idea
+*.log
+tmp/
+
+
+*.o
+dwm
+.ccls-cache
diff --git a/Makefile b/Makefile
index ffa69b4..34d9c64 100644
--- a/Makefile
+++ b/Makefile
@@ -34,6 +34,9 @@ install: all
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f dwm ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
+ $(MAKE) manpage
+
+manpage:
mkdir -p ${DESTDIR}${MANPREFIX}/man1
sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
diff --git a/README.org b/README.org
new file mode 100644
index 0000000..643dafd
--- /dev/null
+++ b/README.org
@@ -0,0 +1,41 @@
+* Key layout
+Notation:
++ S = Super
++ C = Control
++ ^k = Shift-k
+
+S-b = toggle bar
+S-grave = toggle scratch terminal
+S-j = focus next on the stack
+S-k = focus prev on the stack
+** Gaps
+S-period = Increase gaps
+S-comma = Decrease gaps
+S-slash = Turn gaps off and on
+S-^slash = Print current gaps (notify-send)
+** Master manipulation
+S-h = Decrease size of master
+S-l = Increase size of master
+S-c = Set current focused client to master
+S-C-period = Decrease number of master clients
+S-C-comma = Increase number of master clients
+** Layouts
+S-^t = Tiling
+S-^f = Floating
+S-^m = Monocle
+S-^u = Centred monocle
+S-^o = Centred floating monocle
+S-^s = Spiral fibonacci
+S-^d = Dwindle fibonacci
+S-^g = 2 row grid
+S-^i = Deck
+S-^space = Toggle between current and previous layout
+S-space = Toggle floating on currently focused client
+** Monitors
+S-m = Focus on the next monitor (wraps around)
+S-^comma = Send to previous monitor
+S-^period = Send to next monitor
+** Tags and quit
+S-Tab = Go to previously viewed tag
+S-q = killclient
+S-^q = quit
diff --git a/config.def.h b/config.def.h
index 9efa774..ccd0df6 100644
--- a/config.def.h
+++ b/config.def.h
@@ -16,11 +16,24 @@ 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 */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+/* launcher commands (They must be NULL terminated) */
+static const char* surf[] = { "surf", "duckduckgo.com", NULL };
+
+static const Launcher launchers[] = {
+ /* command name to display */
+ { surf, "surf" },
+};
+
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
@@ -42,6 +55,8 @@ static const Layout layouts[] = {
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "|M|", centeredmaster },
+ { ">M>", centeredfloatingmaster },
};
/* key definitions */
@@ -55,18 +70,27 @@ 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 };
static const char *termcmd[] = { "st", NULL };
+static const char scratchpadname[] = "scratchpad";
+static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-g", "120x34", NULL };
static const 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 } },
+ { MODKEY|ShiftMask, XK_j, inplacerotate, {.i = +1} },
+ { MODKEY|ShiftMask, XK_k, inplacerotate, {.i = -1} },
+ { MODKEY|ShiftMask, XK_h, inplacerotate, {.i = +2} },
+ { MODKEY|ShiftMask, XK_l, inplacerotate, {.i = -2} },
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
@@ -77,6 +101,8 @@ static const 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_u, setlayout, {.v = &layouts[3]} },
+ { MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
@@ -104,7 +130,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/config.h b/config.h
new file mode 100644
index 0000000..fb514c7
--- /dev/null
+++ b/config.h
@@ -0,0 +1,189 @@
+/* See LICENSE file for copyright and license details. */
+#define true 1
+#define false 0
+
+#define GTMask(X) 1 << (X - 1)
+#define STATUSBAR "dwmblocks"
+
+/* appearance */
+static const unsigned int borderpx = 0; /* border pixel of windows */
+static const unsigned int snap = 32; /* snap pixel */
+static const unsigned int opengap = 20; /* optional gaps between windows */
+static const unsigned int gappx = 0; /* default gaps between windows */
+static const int showbar = true; /* 0 means no bar */
+static const int topbar = 0; /* 0 means bottom bar */
+static const char *fonts[] = { "Noto Sans Mono:size=13" };
+static const char dmenufont[] = "monospace:size=9";
+static const char col_black[] = "#161616";
+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 col_lblue[] = "#77aafc";
+static const char col_dblue[] = "#225599";
+static const char col_lgreen[] = "#55f055";
+static const char col_dgreen[] = "#008000";
+static const char *colors[][3] = {
+ /* Scheme fg bg border */
+ [SchemeNorm] = { col_gray3, col_gray1, col_black },
+ [SchemeSel] = { col_gray4, col_cyan, "#230142" },
+ [SchemeStatus] = { col_lblue, col_black, col_black },
+ [SchemeTagsSel] = { col_gray4, col_dblue, col_black },
+ [SchemeTagsNorm] = { col_lblue, col_black, col_black },
+ [SchemeInfoSel] = { col_gray4, col_black, col_black },
+ [SchemeInfoNorm] = { col_gray3, col_gray1, col_black },
+};
+
+/* tagging */
+
+static const char *tags[] = { "", "", "", "", "", "6", "7", "8", "9" };
+
+/* Custom functions */
+static void togglegaps(const Arg *arg);
+static void printgaps(const Arg *arg);
+
+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 },
+ { "Onboard", NULL, NULL, 0, 1, -1 },
+ { "qutebrowser", NULL, NULL, GTMask(2), 0, -1 },
+ { "firefox", NULL, NULL, GTMask(2), 0, -1 },
+ { "Chromium", NULL, NULL, GTMask(2), 0, -1 },
+ { "media-term", NULL, NULL, GTMask(3), 0, -1 },
+ { "Spotify", NULL, NULL, GTMask(3), 0, -1 },
+ { "Zathura", NULL, NULL, GTMask(4), 0, -1 },
+ { "Com.github.xournalpp.xournalpp", NULL, NULL, GTMask(5), 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 resizehints = 1; /* 1 means respect size hints in tiled resizals */
+static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
+
+#include "./fibonacci.c"
+#include "./gaplessgrid.c"
+
+static const Layout layouts[] = {
+ /* symbol arrange function */
+ { "[T]=", tile }, /* first entry is default */
+ { "<F>=", NULL }, /* no layout function means floating behavior */
+ { "{M}", monocle },
+ { "|M|", centeredmaster },
+ { ">M>", centeredfloatingmaster },
+ { "[@]", spiral },
+ { "[\\]", dwindle },
+ { "###", gaplessgrid },
+ { "[D]", deck },
+};
+
+/* key definitions */
+#define MODKEY Mod4Mask
+#define TAGKEYS(KEY,TAG) \
+ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
+ { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
+ { MODKEY|ControlMask, KEY, toggleview, {.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 const char scratchpadname[] = "scratchpad";
+static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-e", "tmux",
+ NULL };
+
+static char *statuscmds[] = { "notify-send Mouse$BUTTON" };
+
+static const Key keys[] = {
+ /* modifier key function argument */
+ { MODKEY, XK_b, togglebar, {0} },
+ { MODKEY, XK_grave, togglescratch, {.v = scratchpadcmd } },
+ { MODKEY, XK_j, focusstack, {.i = +1 } },
+ { MODKEY, XK_k, focusstack, {.i = -1 } },
+ { MODKEY, XK_period, setgaps, {.i = +1} },
+ { MODKEY, XK_comma, setgaps, {.i = -1} },
+ { MODKEY, XK_slash, togglegaps, {0} },
+ { MODKEY|ShiftMask, XK_slash, printgaps, {0} },
+ { MODKEY, XK_h, setmfact, {.f = -0.01} },
+ { MODKEY, XK_l, setmfact, {.f = +0.01} },
+ { MODKEY|ControlMask, XK_period, incnmaster, {.i = -1 } },
+ { MODKEY|ControlMask, XK_comma, incnmaster, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_k, inplacerotate, {.i = +1} },
+ { MODKEY|ShiftMask, XK_j, inplacerotate, {.i = -1} },
+ { MODKEY|ShiftMask, XK_h, inplacerotate, {.i = -2} },
+ { MODKEY|ShiftMask, XK_l, inplacerotate, {.i = +2} },
+ { MODKEY, XK_c, zoom, {0} },
+ { MODKEY|ShiftMask, XK_t, setlayout, {.v = &layouts[0]} }, //tiling
+ { MODKEY|ShiftMask, XK_f, setlayout, {.v = &layouts[1]} }, //floating
+ { MODKEY|ShiftMask, XK_m, setlayout, {.v = &layouts[2]} }, //monocle
+ { MODKEY|ShiftMask, XK_u, setlayout, {.v = &layouts[3]} }, //cmonocle
+ { MODKEY|ShiftMask, XK_o, setlayout, {.v = &layouts[4]} }, //cfmonocle
+ { MODKEY|ShiftMask, XK_s, setlayout, {.v = &layouts[5]} }, //fib-spiral
+ { MODKEY|ShiftMask, XK_d, setlayout, {.v = &layouts[6]} }, //fib-spiral
+ { MODKEY|ShiftMask, XK_g, setlayout, {.v = &layouts[7]} }, //gapless-grid
+ { MODKEY|ShiftMask, XK_i, setlayout, {.v = &layouts[8]} }, //deck
+ { MODKEY|ShiftMask, XK_space, setlayout, {0} },
+ { MODKEY, XK_space, togglefloating, {0} },
+ { MODKEY, XK_m, focusmon, {.i = -1 } },
+ { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
+ { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+ { MODKEY, XK_Tab, view, {.ui = 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)
+ { MODKEY, XK_q, killclient, {0} },
+ { 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]} },
+ { ClkWinTitle, 0, Button2, zoom, {0} },
+ { 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} },
+};
+
+void
+togglegaps(const Arg *arg)
+{
+ if (!selmon)
+ return;
+ int *gap_size = &selmon->pertag->gaps[selmon->pertag->curtag];
+ if (*gap_size == gappx)
+ selmon->pertag->gaps[selmon->pertag->curtag] = opengap;
+ else
+ selmon->pertag->gaps[selmon->pertag->curtag] = gappx;
+ arrange(selmon);
+}
+
+void
+printgaps(const Arg *arg)
+{
+ if (!selmon)
+ return;
+ char *cmd = malloc(sizeof(*cmd) * 38);
+ sprintf(cmd, "notify-send -u low \"Gaps=%d\"",
+ selmon->pertag->gaps[selmon->pertag->curtag]);
+ system(cmd);
+ free(cmd);
+}
diff --git a/dwm.1 b/dwm.1
index ddc8321..5c68e2e 100644
--- a/dwm.1
+++ b/dwm.1
@@ -5,29 +5,59 @@ dwm \- dynamic window manager
.B dwm
.RB [ \-v ]
.SH DESCRIPTION
-dwm is a dynamic window manager for X. It manages windows in tiled, monocle
-and floating layouts. Either layout can be applied dynamically, optimising the
-environment for the application in use and the task performed.
+dwm is a dynamic window manager for X. It manages windows in a
+variety of layouts:
+.nr PI 1n
+.IP \[bu]
+floating: windows can be resized and moved freely, a la usual window
+managers.
+.IP \[bu]
+tiled: windows are managed in a master and stacking area. The master
+area on the left contains one window by default, and the stacking area
+on the right contains all other windows. The number of master area
+windows can be adjusted from zero to an arbitrary number.
+.IP \[bu]
+monocle (normal, centred or floating)
+
+Normal: all windows are maximised to the screen size.
+
+Centred: the screen is split into three sections with the master
+clients getting the second section and the stacking clients get the
+remaining 2 sections to be laid out in.
+
+Floating: the master clients are placed floating in the centre of the
+screen while the remaining stacking clients are placed side by side
+vertically.
+.IP \[bu]
+fibonacci (dwindle and spiral): windows are tiled in a spiralling or
+dwindling pattern.
+
+In the dwindle layout new clients tend towards the bottom left of the
+monitor while in the spiral layout clients tend towards the centre
+bottom left.
+.IP \[bu]
+deck: the stacking clients are placed floating on top of each other
+such that there are only two partitions of the screen space.
+.IP \[bu]
+gapless grid: n clients are arranged into a square of ceil(sqrt(n))
+length, where the top left is the latest client opened.
.P
-In tiled layouts windows are managed in a master and stacking area. The master
-area on the left contains one window by default, and the stacking area on the
-right contains all other windows. The number of master area windows can be
-adjusted from zero to an arbitrary number. In monocle layout all windows are
-maximised to the screen size. In floating layout windows can be resized and
-moved freely. Dialog windows are always managed floating, regardless of the
-layout applied.
+Dialog windows are always managed floating, regardless of the layout
+applied.
.P
-Windows are grouped by tags. Each window can be tagged with one or multiple
-tags. Selecting certain tags displays all windows with these tags.
+Windows are grouped by tags. Each window can be tagged with one or
+multiple tags. Selecting certain tags displays all windows with these
+tags.
.P
-Each screen contains a small status bar which displays all available tags, the
-layout, the title of the focused window, and the text read from the root window
-name property, if the screen is focused. A floating window is indicated with an
-empty square and a maximised floating window is indicated with a filled square
-before the windows title. The selected tags are indicated with a different
-color. The tags of the focused window are indicated with a filled square in the
-top left corner. The tags which are applied to one or more windows are
-indicated with an empty square in the top left corner.
+Each screen contains a small status bar which displays all available
+tags, the layout, the title of the focused window, and the text read
+from the root window name property, if the screen is focused. A
+floating window is indicated with an empty square and a maximised
+floating window is indicated with a filled square before the windows
+title. The selected tags are indicated with a different color. The
+tags of the focused window are indicated with a filled square in the
+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.
.SH OPTIONS
@@ -39,119 +69,172 @@ prints version information to stderr, then exits.
.TP
.B X root window name
is read and displayed in the status text area. It can be set with the
-.BR xsetroot (1)
+.BR xsetroot (1). This fork uses dwmblocks to generate system status information.
command.
+.SS Keyboard commands
+Mod is set to Super (the "windows" key).
.TP
-.B Button1
-click on a tag label to display all windows with that tag, click on the layout
-label toggles between tiled and floating layout.
+.B Mod\-b
+Toggle status bar
+
.TP
-.B Button3
-click on a tag label adds/removes all windows with that tag to/from the view.
+.B Mod\-`
+Toggle scratchpad terminal (set to
+.BR st(1)
+)
+
+.TP
+.B Mod\-j
+Focus next window
+
+.TP
+.B Mod\-k
+Focus previous window
+
.TP
-.B Mod1\-Button1
-click on a tag label applies that tag to the focused window.
+.B Mod\-.
+Increase gap size
+
.TP
-.B Mod1\-Button3
-click on a tag label adds/removes that tag to/from the focused window.
-.SS Keyboard commands
+.B Mod\-,
+Decrease gap size
+
.TP
-.B Mod1\-Shift\-Return
-Start
-.BR st(1).
+.B Mod\-/
+Toggle gaps
+
.TP
-.B Mod1\-p
-Spawn
-.BR dmenu(1)
-for launching other programs.
+.B Mod\-Shift\-/
+Print current gap value (using
+.BR notify-send(1)
+)
+
.TP
-.B Mod1\-,
-Focus previous screen, if any.
+.B Mod\-h
+Decrease size of master area
+
.TP
-.B Mod1\-.
-Focus next screen, if any.
+.B Mod\-l
+Increase size of master are
+
.TP
-.B Mod1\-Shift\-,
-Send focused window to previous screen, if any.
+.B Mod\-Control\-.
+Decrease number of master clients
+
.TP
-.B Mod1\-Shift\-.
-Send focused window to next screen, if any.
+.B Mod\-Control\-,
+Increase number of master clients
+
.TP
-.B Mod1\-b
-Toggles bar on and off.
+.B Mod\-Shift\-h
+Rotate the stack clockwise but keep focus on the same position.
+
.TP
-.B Mod1\-t
-Sets tiled layout.
+.B Mod\-Shift\-l
+Rotate the stack anticlockwise but keep focus on the same position.
+
.TP
-.B Mod1\-f
-Sets floating layout.
+.B Mod\-Shift\-k
+Rotate the master clients clockwise but keep focus on the same position.
+
.TP
-.B Mod1\-m
-Sets monocle layout.
+.B Mod\-Shift\-j
+Rotate the master clients anticlockwise but keep focus on the same position.
+
.TP
-.B Mod1\-space
-Toggles between current and previous layout.
+.B Mod\-c
+If in stack area, swap currently focused client with master. If in master area, swap currently focused client with top of stack area.
+
.TP
-.B Mod1\-j
-Focus next window.
+.B Mod\-Shift\-t
+Set layout to tiling
+
.TP
-.B Mod1\-k
-Focus previous window.
+.B Mod\-Shift\-f
+Set layout to floating
+
.TP
-.B Mod1\-i
-Increase number of windows in master area.
+.B Mod\-Shift\-m
+Set layout to monocle
+
.TP
-.B Mod1\-d
-Decrease number of windows in master area.
+.B Mod\-Shift\-u
+Set layout to centred monocle
+
.TP
-.B Mod1\-l
-Increase master area size.
+.B Mod\-Shift\-o
+Set layout to centred floating monocle
+
.TP
-.B Mod1\-h
-Decrease master area size.
+.B Mod\-Shift\-s
+Set layout to spiral fibonacci
+
.TP
-.B Mod1\-Return
-Zooms/cycles focused window to/from master area (tiled layouts only).
+.B Mod\-Shift\-d
+Set layout to dwindle fibonacci
+
.TP
-.B Mod1\-Shift\-c
-Close focused window.
+.B Mod\-Shift\-g
+Set layout to gapless grid
+
.TP
-.B Mod1\-Shift\-space
-Toggle focused window between tiled and floating state.
+.B Mod\-Shift\-i
+Set layout to deck
+
.TP
-.B Mod1\-Tab
-Toggles to the previously selected tags.
+.B Mod\-Shift\-space
+Toggle between current layout and previous layout
+
+.TP
+.B Mod\-space
+Toggle current client's floating (floating -> not floating, not floating -> floating)
+
+.TP
+.B Mod1\-[1..n]
+Go to nth tag
+
.TP
.B Mod1\-Shift\-[1..n]
-Apply nth tag to focused window.
+Send focused client to nth tag.
+
.TP
-.B Mod1\-Shift\-0
-Apply all tags to focused window.
+.B Mod\-m
+Focus on the next monitor in monitor stack
+
.TP
-.B Mod1\-Control\-Shift\-[1..n]
-Add/remove nth tag to/from focused window.
+.B Mod\-Shift\-,
+Send client to previous monitor in monitor stack
+
.TP
-.B Mod1\-[1..n]
-View all windows with nth tag.
+.B Mod\-Shift\-.
+Send client to next monitor in monitor stack
+
.TP
-.B Mod1\-0
-View all windows with any tag.
+.B Mod\-Tab
+View the previous tag
+
.TP
-.B Mod1\-Control\-[1..n]
-Add/remove all windows with nth tag to/from the view.
+.B Mod\-q
+Kill the currently focused client
+
.TP
-.B Mod1\-Shift\-q
-Quit dwm.
+.B Mod\-Shift\-q
+Kill dwm
+
.SS Mouse commands
+
.TP
.B Mod1\-Button1
Move focused window while dragging. Tiled windows will be toggled to the floating state.
+
.TP
.B Mod1\-Button2
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 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 f1d86b2..01a8a97 100644
--- a/dwm.c
+++ b/dwm.c
@@ -49,7 +49,9 @@
#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 ISVISIBLEONTAG(C, T) ((C->tags & T))
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
+/* #define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) */
#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
@@ -59,7 +61,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 */
@@ -111,6 +113,7 @@ typedef struct {
void (*arrange)(Monitor *);
} Layout;
+typedef struct Pertag Pertag;
struct Monitor {
char ltsymbol[16];
float mfact;
@@ -130,6 +133,7 @@ struct Monitor {
Monitor *next;
Window barwin;
const Layout *lt[2];
+ Pertag *pertag;
};
typedef struct {
@@ -147,6 +151,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac
static void arrange(Monitor *m);
static void arrangemon(Monitor *m);
static void attach(Client *c);
+static void attachaside(Client *c);
static void attachstack(Client *c);
static void buttonpress(XEvent *e);
static void checkotherwm(void);
@@ -156,7 +161,9 @@ static void clientmessage(XEvent *e);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
+static void copyvalidchars(char *text, char *rawtext);
static Monitor *createmon(void);
+static void deck(Monitor *m);
static void destroynotify(XEvent *e);
static void detach(Client *c);
static void detachstack(Client *c);
@@ -176,6 +183,7 @@ static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
static void incnmaster(const Arg *arg);
+static void inplacerotate(const Arg *arg);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
static void manage(Window w, XWindowAttributes *wa);
@@ -184,6 +192,7 @@ static void maprequest(XEvent *e);
static void monocle(Monitor *m);
static void motionnotify(XEvent *e);
static void movemouse(const Arg *arg);
+static Client *nexttagged(Client *c);
static Client *nexttiled(Client *c);
static void pop(Client *c);
static void propertynotify(XEvent *e);
@@ -200,6 +209,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 setgaps(const Arg *arg);
static void setlayout(const Arg *arg);
static void setmfact(const Arg *arg);
static void setup(void);
@@ -211,6 +221,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 togglescratch(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void unfocus(Client *c, int setfocus);
@@ -233,10 +244,15 @@ 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 centeredmaster(Monitor *m);
+static void centeredfloatingmaster(Monitor *m);
/* variables */
static const char broken[] = "broken";
static char stext[256];
+static char rawstext[256];
+static int statuscmdn;
+static char lastbutton[] = "-";
static int screen;
static int sw, sh; /* X display screen geometry width, height */
static int bh; /* bar height */
@@ -269,8 +285,22 @@ static Monitor *mons, *selmon;
static Window root, wmcheckwin;
/* configuration, allows nested code to access above variables */
+// TODO: Figure out if there is a better way of doing this
+#define TAG_SIZE 9
+struct Pertag {
+ unsigned int curtag, prevtag; /* current and previous tag */
+ int nmasters[TAG_SIZE + 1]; /* number of windows in master area */
+ float mfacts[TAG_SIZE + 1]; /* mfacts per tag */
+ unsigned int sellts[TAG_SIZE + 1]; /* selected layouts */
+ const Layout *ltidxs[TAG_SIZE + 1][2]; /* matrix of tags and layouts indexes */
+ int showbars[TAG_SIZE + 1]; /* display bar for the current tag */
+ int gaps[TAG_SIZE + 1]; /* size of gaps for the current tag*/
+};
+
#include "config.h"
+static unsigned int scratchtag = 1 << LENGTH(tags);
+
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
@@ -409,6 +439,17 @@ attach(Client *c)
}
void
+attachaside(Client *c) {
+ Client *at = nexttagged(c);
+ if(!at) {
+ attach(c);
+ return;
+ }
+ c->next = at->next;
+ at->next = c;
+}
+
+void
attachstack(Client *c)
{
c->snext = c->mon->stack;
@@ -418,11 +459,12 @@ attachstack(Client *c)
void
buttonpress(XEvent *e)
{
- unsigned int i, x, click;
- Arg arg = {0};
+ unsigned int i, x, click, occ = 0;
Client *c;
+ Arg arg = {0};
Monitor *m;
XButtonPressedEvent *ev = &e->xbutton;
+ *lastbutton = '0' + ev->button;
click = ClkRootWin;
/* focus monitor if necessary */
@@ -433,9 +475,14 @@ buttonpress(XEvent *e)
}
if (ev->window == selmon->barwin) {
i = x = 0;
- do
+ for (c = m->clients; c; c = c->next)
+ occ |= c->tags == 255 ? 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;
@@ -445,6 +492,22 @@ buttonpress(XEvent *e)
click = ClkStatusText;
else
click = ClkWinTitle;
+ char *text = rawstext;
+ int i = -1;
+ char ch;
+ statuscmdn = 0;
+ while (text[++i]) {
+ if ((unsigned char)text[i] < ' ') {
+ ch = text[i];
+ text[i] = '\0';
+ x += TEXTW(text) - lrpad;
+ text[i] = ch;
+ text += i+1;
+ i = -1;
+ if (x >= ev->x) break;
+ if (ch <= LENGTH(statuscmds)) statuscmdn = ch - 1;
+ }
+ }
} else if ((c = wintoclient(ev->window))) {
focus(c);
restack(selmon);
@@ -630,10 +693,24 @@ configurerequest(XEvent *e)
XSync(dpy, False);
}
+void
+copyvalidchars(char *text, char *rawtext)
+{
+ int i = -1, j = 0;
+
+ while(rawtext[++i]) {
+ if ((unsigned char)rawtext[i] >= ' ') {
+ text[j++] = rawtext[i];
+ }
+ }
+ text[j] = '\0';
+}
+
Monitor *
createmon(void)
{
Monitor *m;
+ unsigned int i;
m = ecalloc(1, sizeof(Monitor));
m->tagset[0] = m->tagset[1] = 1;
@@ -644,6 +721,21 @@ 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;
+ m->pertag->gaps[i] = gappx;
+ }
+
return m;
}
@@ -658,6 +750,35 @@ destroynotify(XEvent *e)
}
void
+deck(Monitor *m) {
+ unsigned int i, n, h, mw, my, ns, gap_size;
+ 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;
+ ns = m->nmaster > 0 ? 2 : 1;
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n - m->nmaster);
+ } else {
+ mw = m->ww;
+ ns = 1;
+ }
+
+ gap_size = m->pertag->gaps[m->pertag->curtag];
+ for(i = 0, my = gap_size, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if(i < m->nmaster) {
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - gap_size;
+ resize(c, m->wx + gap_size, m->wy + my, mw - (2*c->bw) - gap_size*(5-ns)/2, h - (2*c->bw), False);
+ my += HEIGHT(c) + gap_size;
+ }
+ else
+ resize(c, m->wx + mw + gap_size/ns, m->wy + gap_size, m->ww - mw - (2*c->bw) - gap_size*(5-ns)/2, m->wh - (2*c->bw) - 2*gap_size, False);
+}
+
+void
detach(Client *c)
{
Client **tc;
@@ -709,25 +830,28 @@ 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);
}
for (c = m->clients; c; c = c->next) {
- occ |= c->tags;
+ occ |= c->tags == 255 ? 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_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,
- m == selmon && selmon->sel && selmon->sel->tags & 1 << 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);
@@ -736,12 +860,12 @@ drawbar(Monitor *m)
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);
}
}
@@ -980,7 +1104,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);
}
@@ -1061,6 +1185,14 @@ manage(Window w, XWindowAttributes *wa)
c->y = MAX(c->y, c->mon->wy);
c->bw = borderpx;
+ selmon->tagset[selmon->seltags] &= ~scratchtag;
+ if (!strcmp(c->name, scratchpadname)) {
+ c->mon->tagset[c->mon->seltags] |= c->tags = scratchtag;
+ c->isfloating = True;
+ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
+ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
+ }
+
wc.border_width = c->bw;
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
@@ -1074,10 +1206,11 @@ manage(Window w, XWindowAttributes *wa)
c->isfloating = c->oldstate = trans != None || c->isfixed;
if (c->isfloating)
XRaiseWindow(dpy, c->win);
+ /* attachaside(c); */
attach(c);
attachstack(c);
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
- (unsigned char *) &(c->win), 1);
+ (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 (c->mon == selmon)
@@ -1121,8 +1254,12 @@ monocle(Monitor *m)
n++;
if (n > 0) /* override layout symbol */
snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
+ const int gap_size = m->pertag->gaps[m->pertag->curtag];
for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
+ resize(c, m->wx + gap_size, m->wy + gap_size,
+ m->ww - 2 * c->bw - (2 * gap_size),
+ m->wh - 2 * c->bw - (2 * gap_size),
+ 0);
}
void
@@ -1203,6 +1340,16 @@ movemouse(const Arg *arg)
}
Client *
+nexttagged(Client *c) {
+ Client *walked = c->mon->clients;
+ for(;
+ walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags));
+ walked = walked->next
+ );
+ return walked;
+}
+
+Client *
nexttiled(Client *c)
{
for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
@@ -1427,6 +1574,7 @@ sendmon(Client *c, Monitor *m)
detachstack(c);
c->mon = m;
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
+ /* attachaside(c); */
attach(c);
attachstack(c);
focus(NULL);
@@ -1508,12 +1656,23 @@ setfullscreen(Client *c, int fullscreen)
}
void
+setgaps(const Arg *arg)
+{
+ int *gap_size = &selmon->pertag->gaps[selmon->pertag->curtag];
+ if ((arg->i == 0) || ((*gap_size) + arg->i < 0))
+ *gap_size = 0;
+ else
+ *gap_size += arg->i;
+ arrange(selmon);
+}
+
+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 +1691,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);
}
@@ -1648,9 +1807,7 @@ void
spawn(const Arg *arg)
{
struct sigaction sa;
-
- if (arg->v == dmenucmd)
- dmenumon[0] = '0' + selmon->num;
+ selmon->tagset[selmon->seltags] &= ~scratchtag;
if (fork() == 0) {
if (dpy)
close(ConnectionNumber(dpy));
@@ -1694,28 +1851,29 @@ tile(Monitor *m)
if (n == 0)
return;
+ const int gap_size = m->pertag->gaps[m->pertag->curtag];
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++)
+ mw = m->ww - gap_size;
+ for (i = 0, my = ty = gap_size, 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);
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - gap_size;
+ resize(c, m->wx + gap_size, m->wy + my, mw - (2*c->bw) - gap_size, h - (2*c->bw), 0);
if (my + HEIGHT(c) < m->wh)
- my += HEIGHT(c);
+ my += HEIGHT(c) + gap_size;
} 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);
+ h = (m->wh - ty) / (n - i) - gap_size;
+ resize(c, m->wx + mw + gap_size, m->wy + ty, m->ww - mw - (2*c->bw) - 2*gap_size, h - (2*c->bw), 0);
if (ty + HEIGHT(c) < m->wh)
- ty += HEIGHT(c);
+ ty += HEIGHT(c) + gap_size;
}
}
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);
@@ -1736,6 +1894,28 @@ togglefloating(const Arg *arg)
}
void
+togglescratch(const Arg *arg)
+{
+ Client *c;
+ unsigned int found = 0;
+
+ 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
+ spawn(arg);
+}
+
+void
toggletag(const Arg *arg)
{
unsigned int newtags;
@@ -1754,9 +1934,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);
}
@@ -2005,8 +2209,10 @@ updatesizehints(Client *c)
void
updatestatus(void)
{
- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
+ if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext)))
strcpy(stext, "dwm-"VERSION);
+ else
+ copyvalidchars(stext, rawstext);
drawbar(selmon);
}
@@ -2053,11 +2259,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);
}
@@ -2163,3 +2395,164 @@ main(int argc, char *argv[])
XCloseDisplay(dpy);
return EXIT_SUCCESS;
}
+
+void
+insertclient(Client *item, Client *insertItem, int after) {
+ Client *c;
+ if (item == NULL || insertItem == NULL || item == insertItem) return;
+ detach(insertItem);
+ if (!after && selmon->clients == item) {
+ attach(insertItem);
+ return;
+ }
+ if (after) {
+ c = item;
+ } else {
+ for (c = selmon->clients; c; c = c->next) { if (c->next == item) break; }
+ }
+ insertItem->next = c->next;
+ c->next = insertItem;
+}
+
+void
+inplacerotate(const Arg *arg)
+{
+ if(!selmon->sel || (selmon->sel->isfloating && !arg->f)) return;
+
+ unsigned int selidx = 0, i = 0;
+ Client *c = NULL, *stail = NULL, *mhead = NULL, *mtail = NULL, *shead = NULL;
+
+ // Determine positionings for insertclient
+ for (c = selmon->clients; c; c = c->next) {
+ if (ISVISIBLE(c) && !(c->isfloating)) {
+ if (selmon->sel == c) { selidx = i; }
+ if (i == selmon->nmaster - 1) { mtail = c; }
+ if (i == selmon->nmaster) { shead = c; }
+ if (mhead == NULL) { mhead = c; }
+ stail = c;
+ i++;
+ }
+ }
+
+ // All clients rotate
+ if (arg->i == 2) insertclient(selmon->clients, stail, 0);
+ if (arg->i == -2) insertclient(stail, selmon->clients, 1);
+ // Stack xor master rotate
+ if (arg->i == -1 && selidx >= selmon->nmaster) insertclient(stail, shead, 1);
+ if (arg->i == 1 && selidx >= selmon->nmaster) insertclient(shead, stail, 0);
+ if (arg->i == -1 && selidx < selmon->nmaster) insertclient(mtail, mhead, 1);
+ if (arg->i == 1 && selidx < selmon->nmaster) insertclient(mhead, mtail, 0);
+
+ // Restore focus position
+ i = 0;
+ for (c = selmon->clients; c; c = c->next) {
+ if (!ISVISIBLE(c) || (c->isfloating)) continue;
+ if (i == selidx) { focus(c); break; }
+ i++;
+ }
+ arrange(selmon);
+ focus(c);
+}
+
+void
+centeredmaster(Monitor *m)
+{
+ unsigned int i, n, h, mw, mx, my, oty, ety, tw;
+ Client *c;
+
+ /* count number of clients in the selected monitor */
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+
+ /* initialize areas */
+ mw = m->ww;
+ mx = 0;
+ my = 0;
+ tw = mw;
+
+ if (n > m->nmaster) {
+ /* go mfact box in the center if more than nmaster clients */
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ tw = m->ww - mw;
+
+ if (n - m->nmaster > 1) {
+ /* only one client */
+ mx = (m->ww - mw) / 2;
+ tw = (m->ww - mw) / 2;
+ }
+ }
+
+ oty = 0;
+ ety = 0;
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if (i < m->nmaster) {
+ /* nmaster clients are stacked vertically, in the center
+ * of the screen */
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw),
+ h - (2*c->bw), 0);
+ my += HEIGHT(c);
+ } else {
+ /* stack clients are stacked vertically */
+ if ((i - m->nmaster) % 2 ) {
+ h = (m->wh - ety) / ( (1 + n - i) / 2);
+ resize(c, m->wx, m->wy + ety, tw - (2*c->bw),
+ h - (2*c->bw), 0);
+ ety += HEIGHT(c);
+ } else {
+ h = (m->wh - oty) / ((1 + n - i) / 2);
+ resize(c, m->wx + mx + mw, m->wy + oty,
+ tw - (2*c->bw), h - (2*c->bw), 0);
+ oty += HEIGHT(c);
+ }
+ }
+}
+
+void
+centeredfloatingmaster(Monitor *m)
+{
+ unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx;
+ Client *c;
+
+ /* count number of clients in the selected monitor */
+ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if (n == 0)
+ return;
+
+ /* initialize nmaster area */
+ if (n > m->nmaster) {
+ /* go mfact box in the center if more than nmaster clients */
+ if (m->ww > m->wh) {
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ mh = m->nmaster ? m->wh * 0.9 : 0;
+ } else {
+ mh = m->nmaster ? m->wh * m->mfact : 0;
+ mw = m->nmaster ? m->ww * 0.9 : 0;
+ }
+ mx = mxo = (m->ww - mw) / 2;
+ my = myo = (m->wh - mh) / 2;
+ } else {
+ /* go fullscreen if all clients are in the master area */
+ mh = m->wh;
+ mw = m->ww;
+ mx = mxo = 0;
+ my = myo = 0;
+ }
+
+ for(i = tx = 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 */
+ w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx + mx, m->wy + my, w - (2*c->bw),
+ mh - (2*c->bw), 0);
+ mx += WIDTH(c);
+ } else {
+ /* stack clients are stacked horizontally */
+ w = (m->ww - tx) / (n - i);
+ resize(c, m->wx + tx, m->wy, w - (2*c->bw),
+ m->wh - (2*c->bw), 0);
+ tx += WIDTH(c);
+ }
+}
diff --git a/fibonacci.c b/fibonacci.c
new file mode 100644
index 0000000..32cb89b
--- /dev/null
+++ b/fibonacci.c
@@ -0,0 +1,66 @@
+void
+fibonacci(Monitor *mon, int s) {
+ unsigned int i, n, nx, ny, nw, nh;
+ Client *c;
+
+ for(n = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next), n++);
+ if(n == 0)
+ return;
+
+ nx = mon->wx;
+ ny = 0;
+ nw = mon->ww;
+ nh = mon->wh;
+
+ for(i = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next)) {
+ if((i % 2 && nh / 2 > 2 * c->bw)
+ || (!(i % 2) && nw / 2 > 2 * c->bw)) {
+ if(i < n - 1) {
+ if(i % 2)
+ nh /= 2;
+ else
+ nw /= 2;
+ if((i % 4) == 2 && !s)
+ nx += nw;
+ else if((i % 4) == 3 && !s)
+ ny += nh;
+ }
+ if((i % 4) == 0) {
+ if(s)
+ ny += nh;
+ else
+ ny -= nh;
+ }
+ else if((i % 4) == 1)
+ nx += nw;
+ else if((i % 4) == 2)
+ ny += nh;
+ else if((i % 4) == 3) {
+ if(s)
+ nx += nw;
+ else
+ nx -= nw;
+ }
+ if(i == 0)
+ {
+ if(n != 1)
+ nw = mon->ww * mon->mfact;
+ ny = mon->wy;
+ }
+ else if(i == 1)
+ nw = mon->ww - nw;
+ i++;
+ }
+ resize(c, nx, ny, nw - 2 * c->bw, nh - 2 * c->bw, False);
+ }
+}
+
+void
+dwindle(Monitor *mon) {
+ fibonacci(mon, 1);
+}
+
+void
+spiral(Monitor *mon) {
+ fibonacci(mon, 0);
+}
diff --git a/gaplessgrid.c b/gaplessgrid.c
new file mode 100644
index 0000000..3c9ad76
--- /dev/null
+++ b/gaplessgrid.c
@@ -0,0 +1,36 @@
+void
+gaplessgrid(Monitor *m) {
+ unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch;
+ Client *c;
+
+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), 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;
+
+ const int gap_size = m->pertag->gaps[m->pertag->curtag];
+ /* window geometries */
+ cw = cols ? m->ww / cols : m->ww;
+ cn = 0; /* current column number */
+ rn = 0; /* current row number */
+ 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 = (rows ? m->wh / rows : m->wh) - gap_size;
+ cx = (m->wx + cn*cw) + gap_size;
+ cy = (m->wy + rn*ch) + gap_size;
+ resize(c, cx + gap_size, cy + gap_size, cw - 2 * c->bw - gap_size, ch - 2 * c->bw - gap_size, False);
+ rn++;
+ if(rn >= rows) {
+ rn = 0;
+ cn++;
+ }
+ }
+}
diff --git a/patches/dwm-attachaside-6.1.diff b/patches/dwm-attachaside-6.1.diff
new file mode 100644
index 0000000..176cdb0
--- /dev/null
+++ b/patches/dwm-attachaside-6.1.diff
@@ -0,0 +1,92 @@
+diff --git a/dwm.c b/dwm.c
+index 0362114..be7e7a6 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -49,7 +49,8 @@
+ #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 ISVISIBLEONTAG(C, T) ((C->tags & T))
++#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
+ #define LENGTH(X) (sizeof X / sizeof X[0])
+ #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
+ #define WIDTH(X) ((X)->w + 2 * (X)->bw)
+@@ -147,6 +148,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac
+ static void arrange(Monitor *m);
+ static void arrangemon(Monitor *m);
+ static void attach(Client *c);
++static void attachaside(Client *c);
+ static void attachstack(Client *c);
+ static void buttonpress(XEvent *e);
+ static void checkotherwm(void);
+@@ -184,6 +186,7 @@ static void maprequest(XEvent *e);
+ static void monocle(Monitor *m);
+ static void motionnotify(XEvent *e);
+ static void movemouse(const Arg *arg);
++static Client *nexttagged(Client *c);
+ static Client *nexttiled(Client *c);
+ static void pop(Client *);
+ static void propertynotify(XEvent *e);
+@@ -406,6 +409,17 @@ attach(Client *c)
+ }
+
+ void
++attachaside(Client *c) {
++ Client *at = nexttagged(c);
++ if(!at) {
++ attach(c);
++ return;
++ }
++ c->next = at->next;
++ at->next = c;
++}
++
++void
+ attachstack(Client *c)
+ {
+ c->snext = c->mon->stack;
+@@ -1076,7 +1090,7 @@ manage(Window w, XWindowAttributes *wa)
+ c->isfloating = c->oldstate = trans != None || c->isfixed;
+ if (c->isfloating)
+ XRaiseWindow(dpy, c->win);
+- attach(c);
++ attachaside(c);
+ attachstack(c);
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
+ (unsigned char *) &(c->win), 1);
+@@ -1210,6 +1224,16 @@ movemouse(const Arg *arg)
+ }
+
+ Client *
++nexttagged(Client *c) {
++ Client *walked = c->mon->clients;
++ for(;
++ walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags));
++ walked = walked->next
++ );
++ return walked;
++}
++
++Client *
+ nexttiled(Client *c)
+ {
+ for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
+@@ -1434,7 +1458,7 @@ sendmon(Client *c, Monitor *m)
+ detachstack(c);
+ c->mon = m;
+ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
+- attach(c);
++ attachaside(c);
+ attachstack(c);
+ focus(NULL);
+ arrange(NULL);
+@@ -1891,7 +1915,7 @@ updategeom(void)
+ m->clients = c->next;
+ detachstack(c);
+ c->mon = mons;
+- attach(c);
++ attachaside(c);
+ attachstack(c);
+ }
+ if (m == selmon)
diff --git a/patches/dwm-centeredmaster-6.1.diff b/patches/dwm-centeredmaster-6.1.diff
new file mode 100644
index 0000000..6926892
--- /dev/null
+++ b/patches/dwm-centeredmaster-6.1.diff
@@ -0,0 +1,142 @@
+diff --git a/config.def.h b/config.def.h
+index 7054c06..527b214 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -39,6 +39,8 @@ static const Layout layouts[] = {
+ { "[]=", tile }, /* first entry is default */
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { "[M]", monocle },
++ { "|M|", centeredmaster },
++ { ">M>", centeredfloatingmaster },
+ };
+
+ /* key definitions */
+@@ -74,6 +76,8 @@ 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_u, setlayout, {.v = &layouts[3]} },
++ { MODKEY, XK_o, setlayout, {.v = &layouts[4]} },
+ { 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 0362114..1e81412 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -233,6 +233,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 centeredmaster(Monitor *m);
++static void centeredfloatingmaster(Monitor *m);
+
+ /* variables */
+ static const char broken[] = "broken";
+@@ -2139,3 +2141,106 @@ main(int argc, char *argv[])
+ XCloseDisplay(dpy);
+ return EXIT_SUCCESS;
+ }
++
++void
++centeredmaster(Monitor *m)
++{
++ unsigned int i, n, h, mw, mx, my, oty, ety, tw;
++ Client *c;
++
++ /* count number of clients in the selected monitor */
++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
++ if (n == 0)
++ return;
++
++ /* initialize areas */
++ mw = m->ww;
++ mx = 0;
++ my = 0;
++ tw = mw;
++
++ if (n > m->nmaster) {
++ /* go mfact box in the center if more than nmaster clients */
++ mw = m->nmaster ? m->ww * m->mfact : 0;
++ tw = m->ww - mw;
++
++ if (n - m->nmaster > 1) {
++ /* only one client */
++ mx = (m->ww - mw) / 2;
++ tw = (m->ww - mw) / 2;
++ }
++ }
++
++ oty = 0;
++ ety = 0;
++ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
++ if (i < m->nmaster) {
++ /* nmaster clients are stacked vertically, in the center
++ * of the screen */
++ h = (m->wh - my) / (MIN(n, m->nmaster) - i);
++ resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw),
++ h - (2*c->bw), 0);
++ my += HEIGHT(c);
++ } else {
++ /* stack clients are stacked vertically */
++ if ((i - m->nmaster) % 2 ) {
++ h = (m->wh - ety) / ( (1 + n - i) / 2);
++ resize(c, m->wx, m->wy + ety, tw - (2*c->bw),
++ h - (2*c->bw), 0);
++ ety += HEIGHT(c);
++ } else {
++ h = (m->wh - oty) / ((1 + n - i) / 2);
++ resize(c, m->wx + mx + mw, m->wy + oty,
++ tw - (2*c->bw), h - (2*c->bw), 0);
++ oty += HEIGHT(c);
++ }
++ }
++}
++
++void
++centeredfloatingmaster(Monitor *m)
++{
++ unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx;
++ Client *c;
++
++ /* count number of clients in the selected monitor */
++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
++ if (n == 0)
++ return;
++
++ /* initialize nmaster area */
++ if (n > m->nmaster) {
++ /* go mfact box in the center if more than nmaster clients */
++ if (m->ww > m->wh) {
++ mw = m->nmaster ? m->ww * m->mfact : 0;
++ mh = m->nmaster ? m->wh * 0.9 : 0;
++ } else {
++ mh = m->nmaster ? m->wh * m->mfact : 0;
++ mw = m->nmaster ? m->ww * 0.9 : 0;
++ }
++ mx = mxo = (m->ww - mw) / 2;
++ my = myo = (m->wh - mh) / 2;
++ } else {
++ /* go fullscreen if all clients are in the master area */
++ mh = m->wh;
++ mw = m->ww;
++ mx = mxo = 0;
++ my = myo = 0;
++ }
++
++ for(i = tx = 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 */
++ w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i);
++ resize(c, m->wx + mx, m->wy + my, w - (2*c->bw),
++ mh - (2*c->bw), 0);
++ mx += WIDTH(c);
++ } else {
++ /* stack clients are stacked horizontally */
++ w = (m->ww - tx) / (n - i);
++ resize(c, m->wx + tx, m->wy, w - (2*c->bw),
++ m->wh - (2*c->bw), 0);
++ tx += WIDTH(c);
++ }
++}
diff --git a/patches/dwm-colorbar-6.2.diff b/patches/dwm-colorbar-6.2.diff
new file mode 100644
index 0000000..91c067d
--- /dev/null
+++ b/patches/dwm-colorbar-6.2.diff
@@ -0,0 +1,68 @@
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..a516645 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 */
+diff --git a/dwm.c b/dwm.c
+index 4465af1..0d1d2f7 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 */
+@@ -703,7 +703,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]);
+ sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
+ drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
+ }
+@@ -716,7 +716,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,
+@@ -725,17 +725,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 - sw - 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);
+ }
+ }
diff --git a/patches/dwm-deck-6.2.diff b/patches/dwm-deck-6.2.diff
new file mode 100644
index 0000000..b5afed7
--- /dev/null
+++ b/patches/dwm-deck-6.2.diff
@@ -0,0 +1,77 @@
+From a071b060a1b9b94bcb167b988cf7774ceb870aad Mon Sep 17 00:00:00 2001
+From: Jack Bird <jack.bird@durham.ac.uk>
+Date: Mon, 2 Aug 2021 18:44:05 +0100
+Subject: [PATCH] deck patch works with 6.2
+
+---
+ config.def.h | 2 ++
+ dwm.c | 26 ++++++++++++++++++++++++++
+ 2 files changed, 28 insertions(+)
+
+diff --git a/config.def.h b/config.def.h
+index a2ac963..d865e18 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -42,6 +42,7 @@ static const Layout layouts[] = {
+ { "[]=", tile }, /* first entry is default */
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { "[M]", monocle },
++ { "[D]", deck },
+ };
+
+ /* key definitions */
+@@ -77,6 +78,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_r, 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 5e4d494..c67ff91 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -157,6 +157,7 @@ static void configure(Client *c);
+ static void configurenotify(XEvent *e);
+ static void configurerequest(XEvent *e);
+ static Monitor *createmon(void);
++static void deck(Monitor *m);
+ static void destroynotify(XEvent *e);
+ static void detach(Client *c);
+ static void detachstack(Client *c);
+@@ -655,6 +656,31 @@ destroynotify(XEvent *e)
+ unmanage(c, 1);
+ }
+
++void
++deck(Monitor *m) {
++ unsigned int i, n, h, mw, my;
++ 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;
++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n - m->nmaster);
++ }
++ else
++ mw = m->ww;
++ for(i = my = 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), False);
++ my += HEIGHT(c);
++ }
++ else
++ resize(c, m->wx + mw, m->wy, m->ww - mw - (2*c->bw), m->wh - (2*c->bw), False);
++}
++
+ void
+ detach(Client *c)
+ {
+--
+2.32.0
+
diff --git a/patches/dwm-deck-tilegap-6.1.diff b/patches/dwm-deck-tilegap-6.1.diff
new file mode 100644
index 0000000..30b6e83
--- /dev/null
+++ b/patches/dwm-deck-tilegap-6.1.diff
@@ -0,0 +1,55 @@
+From a9e442ec18683e2255ffef74404c283bbb0b6381 Mon Sep 17 00:00:00 2001
+From: aleks <aleks.stier@icloud.com>
+Date: Thu, 23 May 2019 23:27:59 +0200
+Subject: [PATCH] Make deck-patch work with the tilegap-patch
+
+Apply this patch on top of the deck-patch to make it work with the
+tilegap-patch.
+---
+ dwm.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/dwm.c b/dwm.c
+index 5b68242..1c17891 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -656,7 +656,7 @@ createmon(void)
+
+ void
+ deck(Monitor *m) {
+- unsigned int i, n, h, mw, my;
++ unsigned int i, n, h, mw, my, ns;
+ Client *c;
+
+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+@@ -665,18 +665,20 @@ deck(Monitor *m) {
+
+ if(n > m->nmaster) {
+ mw = m->nmaster ? m->ww * m->mfact : 0;
++ ns = m->nmaster > 0 ? 2 : 1;
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n - m->nmaster);
+- }
+- else
++ } else {
+ mw = m->ww;
+- for(i = my = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
++ ns = 1;
++ }
++ for(i = 0, my = gappx, 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), False);
+- my += HEIGHT(c);
++ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - gappx;
++ resize(c, m->wx + gappx, m->wy + my, mw - (2*c->bw) - gappx*(5-ns)/2, h - (2*c->bw), False);
++ my += HEIGHT(c) + gappx;
+ }
+ else
+- resize(c, m->wx + mw, m->wy, m->ww - mw - (2*c->bw), m->wh - (2*c->bw), False);
++ resize(c, m->wx + mw + gappx/ns, m->wy + gappx, m->ww - mw - (2*c->bw) - gappx*(5-ns)/2, m->wh - (2*c->bw) - 2*gappx, False);
+ }
+
+ void
+--
+2.21.0
+
diff --git a/patches/dwm-fibonacci-6.2.diff b/patches/dwm-fibonacci-6.2.diff
new file mode 100644
index 0000000..81bba7a
--- /dev/null
+++ b/patches/dwm-fibonacci-6.2.diff
@@ -0,0 +1,114 @@
+From ec9f55b6005cfa3b025b3d700c61af3ce539d057 Mon Sep 17 00:00:00 2001
+From: Niki Yoshiuchi <nyoshiuchi@gmail.com>
+Date: Sat, 18 Apr 2020 09:55:26 -0700
+Subject: [PATCH] Adding the fibonacci layout patch
+
+---
+ config.def.h | 5 ++++
+ fibonacci.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 71 insertions(+)
+ create mode 100644 fibonacci.c
+
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..5708487 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -36,11 +36,14 @@ 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 */
+
++#include "fibonacci.c"
+ static const Layout layouts[] = {
+ /* symbol arrange function */
+ { "[]=", tile }, /* first entry is default */
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { "[M]", monocle },
++ { "[@]", spiral },
++ { "[\\]", dwindle },
+ };
+
+ /* key definitions */
+@@ -76,6 +79,8 @@ 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_r, setlayout, {.v = &layouts[3]} },
++ { MODKEY|ShiftMask, XK_r, setlayout, {.v = &layouts[4]} },
+ { MODKEY, XK_space, setlayout, {0} },
+ { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+ { MODKEY, XK_0, view, {.ui = ~0 } },
+diff --git a/fibonacci.c b/fibonacci.c
+new file mode 100644
+index 0000000..fce0a57
+--- /dev/null
++++ b/fibonacci.c
+@@ -0,0 +1,66 @@
++void
++fibonacci(Monitor *mon, int s) {
++ unsigned int i, n, nx, ny, nw, nh;
++ Client *c;
++
++ for(n = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next), n++);
++ if(n == 0)
++ return;
++
++ nx = mon->wx;
++ ny = 0;
++ nw = mon->ww;
++ nh = mon->wh;
++
++ for(i = 0, c = nexttiled(mon->clients); c; c = nexttiled(c->next)) {
++ if((i % 2 && nh / 2 > 2 * c->bw)
++ || (!(i % 2) && nw / 2 > 2 * c->bw)) {
++ if(i < n - 1) {
++ if(i % 2)
++ nh /= 2;
++ else
++ nw /= 2;
++ if((i % 4) == 2 && !s)
++ nx += nw;
++ else if((i % 4) == 3 && !s)
++ ny += nh;
++ }
++ if((i % 4) == 0) {
++ if(s)
++ ny += nh;
++ else
++ ny -= nh;
++ }
++ else if((i % 4) == 1)
++ nx += nw;
++ else if((i % 4) == 2)
++ ny += nh;
++ else if((i % 4) == 3) {
++ if(s)
++ nx += nw;
++ else
++ nx -= nw;
++ }
++ if(i == 0)
++ {
++ if(n != 1)
++ nw = mon->ww * mon->mfact;
++ ny = mon->wy;
++ }
++ else if(i == 1)
++ nw = mon->ww - nw;
++ i++;
++ }
++ resize(c, nx, ny, nw - 2 * c->bw, nh - 2 * c->bw, False);
++ }
++}
++
++void
++dwindle(Monitor *mon) {
++ fibonacci(mon, 1);
++}
++
++void
++spiral(Monitor *mon) {
++ fibonacci(mon, 0);
++}
+--
+2.20.1
+
diff --git a/patches/dwm-fullgaps-6.2.diff b/patches/dwm-fullgaps-6.2.diff
new file mode 100644
index 0000000..7206aec
--- /dev/null
+++ b/patches/dwm-fullgaps-6.2.diff
@@ -0,0 +1,95 @@
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..38d2f6c 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -2,6 +2,7 @@
+
+ /* appearance */
+ static const unsigned int borderpx = 1; /* border pixel of windows */
++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 */
+@@ -84,6 +85,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_minus, setgaps, {.i = -1 } },
++ { MODKEY, XK_equal, setgaps, {.i = +1 } },
++ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } },
+ TAGKEYS( XK_1, 0)
+ TAGKEYS( XK_2, 1)
+ TAGKEYS( XK_3, 2)
+diff --git a/dwm.c b/dwm.c
+index 4465af1..4363627 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -119,6 +119,7 @@ struct Monitor {
+ int by; /* bar geometry */
+ int mx, my, mw, mh; /* screen size */
+ int wx, wy, ww, wh; /* window area */
++ int gappx; /* gaps between windows */
+ unsigned int seltags;
+ unsigned int sellt;
+ unsigned int tagset[2];
+@@ -199,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 setgaps(const Arg *arg);
+ static void setlayout(const Arg *arg);
+ static void setmfact(const Arg *arg);
+ static void setup(void);
+@@ -638,6 +640,7 @@ createmon(void)
+ m->nmaster = nmaster;
+ m->showbar = showbar;
+ m->topbar = topbar;
++ m->gappx = gappx;
+ m->lt[0] = &layouts[0];
+ m->lt[1] = &layouts[1 % LENGTH(layouts)];
+ strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+@@ -1497,6 +1500,16 @@ setfullscreen(Client *c, int fullscreen)
+ }
+ }
+
++void
++setgaps(const Arg *arg)
++{
++ if ((arg->i == 0) || (selmon->gappx + arg->i < 0))
++ selmon->gappx = 0;
++ else
++ selmon->gappx += arg->i;
++ arrange(selmon);
++}
++
+ void
+ setlayout(const Arg *arg)
+ {
+@@ -1683,16 +1696,16 @@ tile(Monitor *m)
+ 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++)
++ mw = m->ww - m->gappx;
++ for (i = 0, my = ty = 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);
+- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
+- my += HEIGHT(c);
++ 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);
++ my += HEIGHT(c) + m->gappx;
+ } 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);
+- ty += HEIGHT(c);
++ h = (m->wh - ty) / (n - i) - m->gappx;
++ resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0);
++ ty += HEIGHT(c) + m->gappx;
+ }
+ }
+
+--
+2.20.1
+
diff --git a/patches/dwm-gaplessgrid-20160731-56a31dc.diff b/patches/dwm-gaplessgrid-20160731-56a31dc.diff
new file mode 100644
index 0000000..4f3bb13
--- /dev/null
+++ b/patches/dwm-gaplessgrid-20160731-56a31dc.diff
@@ -0,0 +1,43 @@
+URL: http://dwm.suckless.org/patches/gapless_grid
+Add gapless grid layout.
+
+Index: dwm/gaplessgrid.c
+===================================================================
+--- /dev/null
++++ dwm/gaplessgrid.c
+@@ -0,0 +1,35 @@
++void
++gaplessgrid(Monitor *m) {
++ unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch;
++ Client *c;
++
++ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), 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;
++
++ /* window geometries */
++ cw = cols ? m->ww / cols : m->ww;
++ cn = 0; /* current column number */
++ rn = 0; /* current row number */
++ 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 = rows ? m->wh / rows : m->wh;
++ cx = m->wx + cn*cw;
++ cy = m->wy + rn*ch;
++ resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, False);
++ rn++;
++ if(rn >= rows) {
++ rn = 0;
++ cn++;
++ }
++ }
++}
diff --git a/patches/dwm-gaplessgrid-add-gaps.diff b/patches/dwm-gaplessgrid-add-gaps.diff
new file mode 100644
index 0000000..1b2b758
--- /dev/null
+++ b/patches/dwm-gaplessgrid-add-gaps.diff
@@ -0,0 +1,32 @@
+From f84237584b76348058bc205b2e0fcf5dfc005d47 Mon Sep 17 00:00:00 2001
+From: Aryadev Chavali <aryadev@aryadevchavali.com>
+Date: Tue, 23 Apr 2024 15:42:04 +0530
+Subject: [PATCH] Add gaps to gapless-grid (properly)
+
+This adjusts both the x and y of each client now.
+---
+ gaplessgrid.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/gaplessgrid.c b/gaplessgrid.c
+index 09d9ac8..649f656 100644
+--- a/gaplessgrid.c
++++ b/gaplessgrid.c
+@@ -22,11 +22,10 @@ gaplessgrid(Monitor *m) {
+ 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 = (rows ? m->wh / rows : m->wh);
+- cx = (m->wx + cn*cw);
+- cy = (m->wy + rn*ch);
+- resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, False);
++ ch = (rows ? m->wh / rows : m->wh) - m->gappx;
++ cx = (m->wx + cn*cw) + m->gappx;
++ cy = (m->wy + rn*ch) + m->gappx;
++ resize(c, cx + m->gappx, cy + m->gappx, cw - 2 * c->bw - m->gappx, ch - 2 * c->bw - m->gappx, False);
+ rn++;
+ if(rn >= rows) {
+ rn = 0;
+--
+2.44.0
+
diff --git a/patches/dwm-gaplessgrid-pertag-gaps.diff b/patches/dwm-gaplessgrid-pertag-gaps.diff
new file mode 100644
index 0000000..e38f041
--- /dev/null
+++ b/patches/dwm-gaplessgrid-pertag-gaps.diff
@@ -0,0 +1,39 @@
+From d15f7fd6781e8916538efcb62011167d5b540ada Mon Sep 17 00:00:00 2001
+From: Aryadev Chavali <aryadev@aryadevchavali.com>
+Date: Wed, 22 May 2024 12:58:03 +0530
+Subject: [PATCH] [PATCH] Adjust gapless grid for pertag gaps
+
+---
+ gaplessgrid.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/gaplessgrid.c b/gaplessgrid.c
+index 649f656..3c9ad76 100644
+--- a/gaplessgrid.c
++++ b/gaplessgrid.c
+@@ -15,6 +15,7 @@ gaplessgrid(Monitor *m) {
+ cols = 2;
+ rows = n/cols;
+
++ const int gap_size = m->pertag->gaps[m->pertag->curtag];
+ /* window geometries */
+ cw = cols ? m->ww / cols : m->ww;
+ cn = 0; /* current column number */
+@@ -22,10 +23,10 @@ gaplessgrid(Monitor *m) {
+ 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 = (rows ? m->wh / rows : m->wh) - m->gappx;
+- cx = (m->wx + cn*cw) + m->gappx;
+- cy = (m->wy + rn*ch) + m->gappx;
+- resize(c, cx + m->gappx, cy + m->gappx, cw - 2 * c->bw - m->gappx, ch - 2 * c->bw - m->gappx, False);
++ ch = (rows ? m->wh / rows : m->wh) - gap_size;
++ cx = (m->wx + cn*cw) + gap_size;
++ cy = (m->wy + rn*ch) + gap_size;
++ resize(c, cx + gap_size, cy + gap_size, cw - 2 * c->bw - gap_size, ch - 2 * c->bw - gap_size, False);
+ rn++;
+ if(rn >= rows) {
+ rn = 0;
+--
+2.45.0
+
diff --git a/patches/dwm-gaps-pertag.diff b/patches/dwm-gaps-pertag.diff
new file mode 100644
index 0000000..c5f1221
--- /dev/null
+++ b/patches/dwm-gaps-pertag.diff
@@ -0,0 +1,163 @@
+From f8aa7781bb890992b75fbc2c9039e2477f1a09c6 Mon Sep 17 00:00:00 2001
+From: Aryadev Chavali <aryadev@aryadevchavali.com>
+Date: Wed, 22 May 2024 12:55:50 +0530
+Subject: [PATCH] [PATCH] Gaps are set on a pertag basis
+
+For each tag there is a gap (set to the default gappx on
+construction). When adjusting gaps or arranging a monitor use the
+gaps of the currently selected tag. This means I can have gaps
+activated in some tags and not activated on others.
+---
+ dwm.c | 64 ++++++++++++++++++++++++++++++++---------------------------
+ 1 file changed, 35 insertions(+), 29 deletions(-)
+
+diff --git a/dwm.c b/dwm.c
+index af66670..c9dd38a 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -122,7 +122,6 @@ struct Monitor {
+ int by; /* bar geometry */
+ int mx, my, mw, mh; /* screen size */
+ int wx, wy, ww, wh; /* window area */
+- int gappx; /* gaps between windows */
+ unsigned int seltags;
+ unsigned int sellt;
+ unsigned int tagset[2];
+@@ -287,16 +286,19 @@ static Monitor *mons, *selmon;
+ static Window root, wmcheckwin;
+
+ /* configuration, allows nested code to access above variables */
+-#include "config.h"
++// TODO: Figure out if there is a better way of doing this
++#define TAG_SIZE 9
+ 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 */
++ int nmasters[TAG_SIZE + 1]; /* number of windows in master area */
++ float mfacts[TAG_SIZE + 1]; /* mfacts per tag */
++ unsigned int sellts[TAG_SIZE + 1]; /* selected layouts */
++ const Layout *ltidxs[TAG_SIZE + 1][2]; /* matrix of tags and layouts indexes */
++ int showbars[TAG_SIZE + 1]; /* display bar for the current tag */
++ int gaps[TAG_SIZE + 1]; /* size of gaps for the current tag*/
+ };
+
++#include "config.h"
+
+ static unsigned int scratchtag = 1 << LENGTH(tags);
+
+@@ -715,7 +717,6 @@ createmon(void)
+ m->nmaster = nmaster;
+ m->showbar = showbar;
+ m->topbar = topbar;
+- m->gappx = gappx;
+ m->lt[0] = &layouts[0];
+ m->lt[1] = &layouts[1 % LENGTH(layouts)];
+ strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
+@@ -731,6 +732,7 @@ createmon(void)
+ m->pertag->sellts[i] = m->sellt;
+
+ m->pertag->showbars[i] = m->showbar;
++ m->pertag->gaps[i] = gappx;
+ }
+
+ return m;
+@@ -748,7 +750,7 @@ destroynotify(XEvent *e)
+
+ void
+ deck(Monitor *m) {
+- unsigned int i, n, h, mw, my, ns;
++ unsigned int i, n, h, mw, my, ns, gap_size;
+ Client *c;
+
+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+@@ -763,15 +765,16 @@ deck(Monitor *m) {
+ mw = m->ww;
+ ns = 1;
+ }
+- for(i = 0, my = gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
++
++ gap_size = m->pertag->gaps[m->pertag->curtag];
++ for(i = 0, my = gap_size, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
+ if(i < m->nmaster) {
+- h = (m->wh - my) / (MIN(n, m->nmaster) - i) - gappx;
+- resize(c, m->wx + gappx, m->wy + my, mw - (2*c->bw) - gappx*(5-ns)/2, h - (2*c->bw), False);
+- if (my + HEIGHT(c) < m->wh)
+- my += HEIGHT(c) + m->gappx;
++ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - gap_size;
++ resize(c, m->wx + gap_size, m->wy + my, mw - (2*c->bw) - gap_size*(5-ns)/2, h - (2*c->bw), False);
++ my += HEIGHT(c) + gap_size;
+ }
+ else
+- resize(c, m->wx + mw + gappx/ns, m->wy + gappx, m->ww - mw - (2*c->bw) - gappx*(5-ns)/2, m->wh - (2*c->bw) - 2*gappx, False);
++ resize(c, m->wx + mw + gap_size/ns, m->wy + gap_size, m->ww - mw - (2*c->bw) - gap_size*(5-ns)/2, m->wh - (2*c->bw) - 2*gap_size, False);
+ }
+
+ void
+@@ -1243,10 +1246,11 @@ monocle(Monitor *m)
+ n++;
+ if (n > 0) /* override layout symbol */
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
++ const int gap_size = m->pertag->gaps[m->pertag->curtag];
+ for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
+- resize(c, m->wx + m->gappx, m->wy + m->gappx,
+- m->ww - 2 * c->bw - (2 * m->gappx),
+- m->wh - 2 * c->bw - (2 * m->gappx),
++ resize(c, m->wx + gap_size, m->wy + gap_size,
++ m->ww - 2 * c->bw - (2 * gap_size),
++ m->wh - 2 * c->bw - (2 * gap_size),
+ 0);
+ }
+
+@@ -1646,10 +1650,11 @@ setfullscreen(Client *c, int fullscreen)
+ void
+ setgaps(const Arg *arg)
+ {
+- if ((arg->i == 0) || (selmon->gappx + arg->i < 0))
+- selmon->gappx = 0;
++ int *gap_size = &selmon->pertag->gaps[selmon->pertag->curtag];
++ if ((arg->i == 0) || ((*gap_size) + arg->i < 0))
++ *gap_size = 0;
+ else
+- selmon->gappx += arg->i;
++ *gap_size += arg->i;
+ arrange(selmon);
+ }
+
+@@ -1839,21 +1844,22 @@ tile(Monitor *m)
+ if (n == 0)
+ return;
+
++ const int gap_size = m->pertag->gaps[m->pertag->curtag];
+ if (n > m->nmaster)
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ else
+- mw = m->ww - m->gappx;
+- for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
++ mw = m->ww - gap_size;
++ for (i = 0, my = ty = gap_size, 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);
++ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - gap_size;
++ resize(c, m->wx + gap_size, m->wy + my, mw - (2*c->bw) - gap_size, h - (2*c->bw), 0);
+ if (my + HEIGHT(c) < m->wh)
+- my += HEIGHT(c) + m->gappx;
++ my += HEIGHT(c) + gap_size;
+ } else {
+- h = (m->wh - ty) / (n - i) - m->gappx;
+- resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0);
++ h = (m->wh - ty) / (n - i) - gap_size;
++ resize(c, m->wx + mw + gap_size, m->wy + ty, m->ww - mw - (2*c->bw) - 2*gap_size, h - (2*c->bw), 0);
+ if (ty + HEIGHT(c) < m->wh)
+- ty += HEIGHT(c) + m->gappx;
++ ty += HEIGHT(c) + gap_size;
+ }
+ }
+
+--
+2.45.0
+
diff --git a/patches/dwm-hide_vacant_tags-6.2.diff b/patches/dwm-hide_vacant_tags-6.2.diff
new file mode 100644
index 0000000..a981b23
--- /dev/null
+++ b/patches/dwm-hide_vacant_tags-6.2.diff
@@ -0,0 +1,55 @@
+diff --git a/dwm.c b/dwm.c
+index 4465af1..c4aa3de 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -416,7 +416,7 @@ attachstack(Client *c)
+ void
+ buttonpress(XEvent *e)
+ {
+- unsigned int i, x, click;
++ unsigned int i, x, click, occ = 0;
+ Arg arg = {0};
+ Client *c;
+ Monitor *m;
+@@ -431,9 +431,14 @@ buttonpress(XEvent *e)
+ }
+ if (ev->window == selmon->barwin) {
+ i = x = 0;
+- do
++ for (c = m->clients; c; c = c->next)
++ occ |= c->tags == 255 ? 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;
+@@ -709,19 +714,19 @@ drawbar(Monitor *m)
+ }
+
+ for (c = m->clients; c; c = c->next) {
+- occ |= c->tags;
++ occ |= c->tags == 255 ? 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 = blw = TEXTW(m->ltsymbol);
diff --git a/patches/dwm-inplacerotate-6.2.diff b/patches/dwm-inplacerotate-6.2.diff
new file mode 100644
index 0000000..d331368
--- /dev/null
+++ b/patches/dwm-inplacerotate-6.2.diff
@@ -0,0 +1,108 @@
+From 75012a6ab9cc1b6c319af7f4ae7d682b16a66ce3 Mon Sep 17 00:00:00 2001
+From: Miles Alan <m@milesalan.com>
+Date: Sun, 26 Apr 2020 16:05:43 -0500
+Subject: [PATCH] Add inplacerotate fn to rotate all, master, or stacks clients
+ inplace
+
+CW (+2) or CCW (-2) Rotates all windows.
+CW (+1) or CCW (-1) Rotates master xor stack windows (depending on focus).
+
+Focus position stays 'in-place' so the area of the screen you are focused
+on remains unchanged.
+---
+ config.def.h | 4 ++++
+ dwm.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 63 insertions(+)
+
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..9bcb792 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -66,6 +66,10 @@ static Key keys[] = {
+ { MODKEY, XK_b, togglebar, {0} },
+ { MODKEY, XK_j, focusstack, {.i = +1 } },
+ { MODKEY, XK_k, focusstack, {.i = -1 } },
++ { MODKEY|ShiftMask, XK_j, inplacerotate, {.i = +1} },
++ { MODKEY|ShiftMask, XK_k, inplacerotate, {.i = -1} },
++ { MODKEY|ShiftMask, XK_h, inplacerotate, {.i = +2} },
++ { MODKEY|ShiftMask, XK_l, inplacerotate, {.i = -2} },
+ { MODKEY, XK_i, incnmaster, {.i = +1 } },
+ { MODKEY, XK_d, incnmaster, {.i = -1 } },
+ { MODKEY, XK_h, setmfact, {.f = -0.05} },
+diff --git a/dwm.c b/dwm.c
+index 4465af1..3930680 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -175,6 +175,7 @@ static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
+ static void grabbuttons(Client *c, int focused);
+ static void grabkeys(void);
+ static void incnmaster(const Arg *arg);
++static void inplacerotate(const Arg *arg);
+ static void keypress(XEvent *e);
+ static void killclient(const Arg *arg);
+ static void manage(Window w, XWindowAttributes *wa);
+@@ -2147,3 +2148,61 @@ main(int argc, char *argv[])
+ XCloseDisplay(dpy);
+ return EXIT_SUCCESS;
+ }
++
++void
++insertclient(Client *item, Client *insertItem, int after) {
++ Client *c;
++ if (item == NULL || insertItem == NULL || item == insertItem) return;
++ detach(insertItem);
++ if (!after && selmon->clients == item) {
++ attach(insertItem);
++ return;
++ }
++ if (after) {
++ c = item;
++ } else {
++ for (c = selmon->clients; c; c = c->next) { if (c->next == item) break; }
++ }
++ insertItem->next = c->next;
++ c->next = insertItem;
++}
++
++void
++inplacerotate(const Arg *arg)
++{
++ if(!selmon->sel || (selmon->sel->isfloating && !arg->f)) return;
++
++ unsigned int selidx = 0, i = 0;
++ Client *c = NULL, *stail = NULL, *mhead = NULL, *mtail = NULL, *shead = NULL;
++
++ // Determine positionings for insertclient
++ for (c = selmon->clients; c; c = c->next) {
++ if (ISVISIBLE(c) && !(c->isfloating)) {
++ if (selmon->sel == c) { selidx = i; }
++ if (i == selmon->nmaster - 1) { mtail = c; }
++ if (i == selmon->nmaster) { shead = c; }
++ if (mhead == NULL) { mhead = c; }
++ stail = c;
++ i++;
++ }
++ }
++
++ // All clients rotate
++ if (arg->i == 2) insertclient(selmon->clients, stail, 0);
++ if (arg->i == -2) insertclient(stail, selmon->clients, 1);
++ // Stack xor master rotate
++ if (arg->i == -1 && selidx >= selmon->nmaster) insertclient(stail, shead, 1);
++ if (arg->i == 1 && selidx >= selmon->nmaster) insertclient(shead, stail, 0);
++ if (arg->i == -1 && selidx < selmon->nmaster) insertclient(mtail, mhead, 1);
++ if (arg->i == 1 && selidx < selmon->nmaster) insertclient(mhead, mtail, 0);
++
++ // Restore focus position
++ i = 0;
++ for (c = selmon->clients; c; c = c->next) {
++ if (!ISVISIBLE(c) || (c->isfloating)) continue;
++ if (i == selidx) { focus(c); break; }
++ i++;
++ }
++ arrange(selmon);
++ focus(c);
++}
+--
+2.23.1
+
diff --git a/patches/dwm-monocle-gaps.diff b/patches/dwm-monocle-gaps.diff
new file mode 100644
index 0000000..83698af
--- /dev/null
+++ b/patches/dwm-monocle-gaps.diff
@@ -0,0 +1,29 @@
+From 09ed528140fadeb5641bf6871f92ce83aa3d4880 Mon Sep 17 00:00:00 2001
+From: Aryadev Chavali <aryadev@aryadevchavali.com>
+Date: Tue, 23 Apr 2024 16:12:19 +0530
+Subject: [PATCH] Monocle now uses gaps
+
+Just added gaps to moncole layout.
+---
+ dwm.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/dwm.c b/dwm.c
+index 19ee521..a6aaace 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -1244,8 +1244,10 @@ monocle(Monitor *m)
+ if (n > 0) /* override layout symbol */
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
+ for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
+- resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
++ resize(c, m->wx + m->gappx, m->wy + m->gappx,
++ m->ww - 2 * c->bw - (2 * m->gappx),
++ m->wh - 2 * c->bw - (2 * m->gappx),
++ 0);
+ }
+
+ void
+--
+2.44.0
+
diff --git a/patches/dwm-pertag-6.2.diff b/patches/dwm-pertag-6.2.diff
new file mode 100644
index 0000000..d753727
--- /dev/null
+++ b/patches/dwm-pertag-6.2.diff
@@ -0,0 +1,177 @@
+diff --git a/dwm.c b/dwm.c
+index 4465af1..6474055 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,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]; };
+
+@@ -631,6 +642,7 @@ Monitor *
+ createmon(void)
+ {
+ Monitor *m;
++ unsigned int i;
+
+ m = ecalloc(1, sizeof(Monitor));
+ m->tagset[0] = m->tagset[1] = 1;
+@@ -641,6 +653,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;
+ }
+
+@@ -966,7 +992,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);
+ }
+
+@@ -1501,9 +1527,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);
+@@ -1522,7 +1548,7 @@ setmfact(const Arg *arg)
+ f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
+ if (f < 0.1 || f > 0.9)
+ return;
+- selmon->mfact = f;
++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
+ arrange(selmon);
+ }
+
+@@ -1699,7 +1725,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);
+@@ -1738,9 +1764,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);
+ }
+@@ -2035,11 +2085,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-remove-dmenu.diff b/patches/dwm-remove-dmenu.diff
new file mode 100644
index 0000000..f0fac2a
--- /dev/null
+++ b/patches/dwm-remove-dmenu.diff
@@ -0,0 +1,30 @@
+From 6fc206cb7cce97f947d121b5ce80b665bcc37a6f Mon Sep 17 00:00:00 2001
+From: Aryadev Chavali <aryadev@aryadevchavali.com>
+Date: Wed, 22 May 2024 12:27:59 +0530
+Subject: [PATCH] [Patch] Remove dmenu functionality from DWM
+
+If using an external keyboard client such as sxhkdrc then dwm has no
+business or need to spawn something like dmenu.
+---
+ config.h | 2 --
+ dwm.c | 4 +---
+ 2 files changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/dwm.c b/dwm.c
+index a6aaace..af66670 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -1795,10 +1795,7 @@ sigchld(int unused)
+ void
+ spawn(const Arg *arg)
+ {
+- if (arg->v == dmenucmd)
+- dmenumon[0] = '0' + selmon->num;
+- else if (arg->v == statuscmd) {
++ if (arg->v == statuscmd) {
+ statuscmd[2] = statuscmds[statuscmdn];
+ setenv("BUTTON", lastbutton, 1);
+ }
+--
+2.45.0
+
diff --git a/patches/dwm-scratchpad-6.2.diff b/patches/dwm-scratchpad-6.2.diff
new file mode 100644
index 0000000..2062263
--- /dev/null
+++ b/patches/dwm-scratchpad-6.2.diff
@@ -0,0 +1,90 @@
+diff -up a/config.def.h b/config.def.h
+--- a/config.def.h 2019-06-06 21:23:27.006661784 +0200
++++ b/config.def.h 2019-06-20 15:05:59.083102462 +0200
+@@ -58,11 +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 };
++static const char scratchpadname[] = "scratchpad";
++static const char *scratchpadcmd[] = { "st", "-t", scratchpadname, "-g", "120x34", 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 -up a/dwm.c b/dwm.c
+--- a/dwm.c 2019-06-06 21:23:27.023328450 +0200
++++ b/dwm.c 2019-06-20 15:07:01.089767947 +0200
+@@ -213,6 +213,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);
+@@ -273,6 +274,8 @@ static Window root, wmcheckwin;
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+
++static unsigned int scratchtag = 1 << LENGTH(tags);
++
+ /* compile-time check if all tags fit into an unsigned int bit array. */
+ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+
+@@ -1052,6 +1055,14 @@ manage(Window w, XWindowAttributes *wa)
+ && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
+ c->bw = borderpx;
+
++ selmon->tagset[selmon->seltags] &= ~scratchtag;
++ if (!strcmp(c->name, scratchpadname)) {
++ c->mon->tagset[c->mon->seltags] |= c->tags = scratchtag;
++ c->isfloating = True;
++ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
++ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
++ }
++
+ wc.border_width = c->bw;
+ XConfigureWindow(dpy, w, CWBorderWidth, &wc);
+ XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
+@@ -1661,6 +1672,7 @@ spawn(const Arg *arg)
+ {
+ if (arg->v == dmenucmd)
+ dmenumon[0] = '0' + selmon->num;
++ selmon->tagset[selmon->seltags] &= ~scratchtag;
+ if (fork() == 0) {
+ if (dpy)
+ close(ConnectionNumber(dpy));
+@@ -1748,6 +1760,28 @@ togglefloating(const Arg *arg)
+ }
+
+ void
++togglescratch(const Arg *arg)
++{
++ Client *c;
++ unsigned int found = 0;
++
++ 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
++ spawn(arg);
++}
++
++void
+ toggletag(const Arg *arg)
+ {
+ unsigned int newtags;
diff --git a/patches/dwm-statuscmd-20210405-67d76bd.diff b/patches/dwm-statuscmd-20210405-67d76bd.diff
new file mode 100644
index 0000000..4b26420
--- /dev/null
+++ b/patches/dwm-statuscmd-20210405-67d76bd.diff
@@ -0,0 +1,208 @@
+From f58c7e4fd05ec13383518ccd51663167d45e92d0 Mon Sep 17 00:00:00 2001
+From: Daniel Bylinka <daniel.bylinka@gmail.com>
+Date: Fri, 2 Apr 2021 19:02:58 +0200
+Subject: [PATCH] [statuscmd] Signal mouse button and click location to status
+ monitor
+
+---
+ config.def.h | 6 +++-
+ dwm.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++---
+ 2 files changed, 100 insertions(+), 6 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..154a59b 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -54,6 +54,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 };
+@@ -103,7 +105,9 @@ static 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 b0b3466..d871457 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -172,6 +172,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);
+@@ -206,6 +207,7 @@ static void setup(void);
+ static void seturgent(Client *c, int urg);
+ static void showhide(Client *c);
+ static void sigchld(int unused);
++static void sigstatusbar(const Arg *arg);
+ static void spawn(const Arg *arg);
+ static void tag(const Arg *arg);
+ static void tagmon(const Arg *arg);
+@@ -238,6 +240,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, blw = 0; /* bar geometry */
+@@ -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,23 @@ buttonpress(XEvent *e)
+ arg.ui = 1 << i;
+ } else if (ev->x < x + blw)
+ 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;
++ statussig = ch;
++ }
++ }
++ } else
+ click = ClkWinTitle;
+ } else if ((c = wintoclient(ev->window))) {
+ focus(c);
+@@ -704,9 +724,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) {
+@@ -872,6 +907,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)
+ {
+@@ -1637,6 +1696,20 @@ sigchld(int unused)
+ while (0 < waitpid(-1, NULL, WNOHANG));
+ }
+
++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)
+ {
+@@ -1990,8 +2063,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.31.0
+
diff --git a/patches/dwm-statuscmd-6.2.diff b/patches/dwm-statuscmd-6.2.diff
new file mode 100644
index 0000000..c825749
--- /dev/null
+++ b/patches/dwm-statuscmd-6.2.diff
@@ -0,0 +1,142 @@
+From 2761ad72b4b8a80e434e7eba1a24676119ab666d Mon Sep 17 00:00:00 2001
+From: Daniel Bylinka <daniel.bylinka@gmail.com>
+Date: Sat, 18 Apr 2020 01:41:03 +0200
+Subject: [PATCH] statuscmd: run shell commands based on mouse button and
+ position when clicking statusbar
+
+---
+ config.def.h | 8 +++++++-
+ dwm.c | 47 ++++++++++++++++++++++++++++++++++++++++++++---
+ 2 files changed, 51 insertions(+), 4 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1c0b587..5cd7efa 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -59,6 +59,10 @@ 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 };
+
++/* commands spawned when clicking statusbar, the mouse button pressed is exported as BUTTON */
++static char *statuscmds[] = { "notify-send Mouse$BUTTON" };
++static char *statuscmd[] = { "/bin/sh", "-c", NULL, NULL };
++
+ static Key keys[] = {
+ /* modifier key function argument */
+ { MODKEY, XK_p, spawn, {.v = dmenucmd } },
+@@ -103,7 +107,9 @@ static 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, spawn, {.v = statuscmd } },
++ { ClkStatusText, 0, Button2, spawn, {.v = statuscmd } },
++ { ClkStatusText, 0, Button3, spawn, {.v = statuscmd } },
+ { ClkClientWin, MODKEY, Button1, movemouse, {0} },
+ { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
+ { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
+diff --git a/dwm.c b/dwm.c
+index 4465af1..d35d173 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -156,6 +156,7 @@ static void clientmessage(XEvent *e);
+ static void configure(Client *c);
+ static void configurenotify(XEvent *e);
+ static void configurerequest(XEvent *e);
++static void copyvalidchars(char *text, char *rawtext);
+ static Monitor *createmon(void);
+ static void destroynotify(XEvent *e);
+ static void detach(Client *c);
+@@ -237,6 +238,9 @@ static void zoom(const Arg *arg);
+ /* variables */
+ static const char broken[] = "broken";
+ static char stext[256];
++static char rawstext[256];
++static int statuscmdn;
++static char lastbutton[] = "-";
+ static int screen;
+ static int sw, sh; /* X display screen geometry width, height */
+ static int bh, blw = 0; /* bar geometry */
+@@ -421,6 +425,7 @@ buttonpress(XEvent *e)
+ Client *c;
+ Monitor *m;
+ XButtonPressedEvent *ev = &e->xbutton;
++ *lastbutton = '0' + ev->button;
+
+ click = ClkRootWin;
+ /* focus monitor if necessary */
+@@ -439,9 +444,26 @@ buttonpress(XEvent *e)
+ arg.ui = 1 << i;
+ } else if (ev->x < x + blw)
+ click = ClkLtSymbol;
+- else if (ev->x > selmon->ww - TEXTW(stext))
++ else if (ev->x > (x = selmon->ww - TEXTW(stext) + lrpad)) {
+ click = ClkStatusText;
+- else
++
++ char *text = rawstext;
++ int i = -1;
++ char ch;
++ statuscmdn = 0;
++ while (text[++i]) {
++ if ((unsigned char)text[i] < ' ') {
++ ch = text[i];
++ text[i] = '\0';
++ x += TEXTW(text) - lrpad;
++ text[i] = ch;
++ text += i+1;
++ i = -1;
++ if (x >= ev->x) break;
++ if (ch <= LENGTH(statuscmds)) statuscmdn = ch - 1;
++ }
++ }
++ } else
+ click = ClkWinTitle;
+ } else if ((c = wintoclient(ev->window))) {
+ focus(c);
+@@ -627,6 +649,19 @@ configurerequest(XEvent *e)
+ XSync(dpy, False);
+ }
+
++void
++copyvalidchars(char *text, char *rawtext)
++{
++ int i = -1, j = 0;
++
++ while(rawtext[++i]) {
++ if ((unsigned char)rawtext[i] >= ' ') {
++ text[j++] = rawtext[i];
++ }
++ }
++ text[j] = '\0';
++}
++
+ Monitor *
+ createmon(void)
+ {
+@@ -1641,6 +1676,10 @@ spawn(const Arg *arg)
+ {
+ if (arg->v == dmenucmd)
+ dmenumon[0] = '0' + selmon->num;
++ else if (arg->v == statuscmd) {
++ statuscmd[2] = statuscmds[statuscmdn];
++ setenv("BUTTON", lastbutton, 1);
++ }
+ if (fork() == 0) {
+ if (dpy)
+ close(ConnectionNumber(dpy));
+@@ -1987,8 +2026,10 @@ updatesizehints(Client *c)
+ void
+ updatestatus(void)
+ {
+- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
++ if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext)))
+ strcpy(stext, "dwm-"VERSION);
++ else
++ copyvalidchars(stext, rawstext);
+ drawbar(selmon);
+ }
+
+--
+2.26.1
+