commit 1afeee85838fab506a47bea3830eed8e4d715d60
parent bd464e94f36a05777abfc7022bda89f7698b5a26
Author: Mahdi Mirzade <[email protected]>
Date: Thu, 24 Mar 2022 00:33:40 +0430
attachaside -> attachbottom, more functions
Diffstat:
8 files changed, 1001 insertions(+), 328 deletions(-)
diff --git a/config.def.h b/config.def.h
@@ -1,210 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-
-/* Load XF86 Multimedia Keybinds */
-#include <X11/XF86keysym.h>
-
-/* appearance */
-static const char *fonts[] = { "monospace:size=8", "ubvazir:size=8" };
-static const unsigned int borderpx = 4; /* border pixel of windows */
-static const unsigned int gappx = 5; /* gaps between windows */
-static const unsigned int snap = 32; /* snap pixel */
-static const unsigned int systraypinning= 0; /* 0: sloppy systray follows selected monitor, 0: pin systray to monitor X */
-static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
-static const unsigned int systrayspacing= 2; /* systray spacing */
-static const int systraypinningfailfirst= 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
-static const int showsystray = 1; /* 0 means no systray */
-static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
-static const int showbar = 1; /* 0 means no bar */
-static const int topbar = 1; /* 0 means bottom bar */
-static const int barheight = 20; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */
-static const int hidevacanttags = 1; /* 1 means hide empty tags / 0: show every tag */
-static const int hidetagindicator = 1; /* 1 means hide default top-left square-shaped tag indicator */
-static const int centeredwindowname = 0; /* 1 means center the WM_NAME of the currently selected window on the status bar */
-static const unsigned int colorfultag = 1; /* 0 means use SchemeSel for selected tag */
-static char fgcolor[] = "#D8DEE9";
-static char bgcolor[] = "#2E3440";
-static char color0[] = "#3B4252";
-static char color1[] = "#BF616A";
-static char color2[] = "#A3BE8C";
-static char color3[] = "#EBCB8B";
-static char color4[] = "#81A1C1";
-static char color5[] = "#B48EAD";
-static char color6[] = "#88C0D0";
-static char color7[] = "#E5E9F0";
-static char color8[] = "#4C566A";
-static char color9[] = "#BF616A";
-static char color10[] = "#A3BE8C";
-static char color11[] = "#EBCB8B";
-static char color12[] = "#81A1C1";
-static char color13[] = "#B48EAD";
-static char color14[] = "#8FBCBB";
-static char color15[] = "#ECEFF4";
-static const char *colors[][3] = {
- /* fg bg border */
- [SchemeNorm] = { color7, bgcolor, bgcolor },
- [SchemeSel] = { fgcolor, color0, color0 },
- [SchemeTag] = { color0, bgcolor, bgcolor },
- [SchemeTag1] = { color1, bgcolor, bgcolor },
- [SchemeTag2] = { color2, bgcolor, bgcolor },
- [SchemeTag3] = { color3, bgcolor, bgcolor },
- [SchemeTag4] = { color4, bgcolor, bgcolor },
- [SchemeTag5] = { color5, bgcolor, bgcolor },
- [SchemeTag6] = { color6, bgcolor, bgcolor },
- [SchemeTag7] = { color9, bgcolor, bgcolor },
- [SchemeTag8] = { color10, bgcolor, bgcolor },
- [SchemeTag9] = { color11, bgcolor, bgcolor },
- [SchemeLayout] = { color12, bgcolor, bgcolor },
-
-};
-
-
-/* tagging */
-static const char *tags[] = { "𐎠", "𐎡", "𐎢", "𐎣", "𐎤", "𐎥", "𐎦", "𐎧", "𐎨" };
-//static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
-
-static const int tagschemes[] = { SchemeTag1, SchemeTag2, SchemeTag3,
- SchemeTag4, SchemeTag5, SchemeTag6,
- SchemeTag7, SchemeTag8, SchemeTag9,
-};
-
-static const char *tagsel[][2] = {
- { color1, bgcolor },
- { color2, bgcolor },
- { color3, bgcolor },
- { color4, bgcolor },
- { color5, bgcolor },
- { color6, bgcolor },
- { color9, bgcolor },
- { color10, bgcolor },
- { color11, bgcolor },
-};
-
-static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */
-static const unsigned int ulinestroke = 1; /* thickness / height of the underline */
-static const unsigned int ulinevoffset = 1; /* how far above the bottom of the bar the line should appear */
-static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */
-
-static const Rule rules[] = {
- /* xprop(1):
- * WM_CLASS(STRING) = instance, class
- * WM_NAME(STRING) = title
- */
- /* class instance title tags mask isfloating isterminal noswallow monitor */
- { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 },
- { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 },
- { "st-256color",NULL, NULL, 0, 0, 1, 0, -1 },
- { "st-float", NULL, NULL, 0, 1, 1, 0, -1 },
- { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
-};
-
-/* layout(s) */
-static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */
-static const int nmaster = 1; /* number of clients in master area */
-static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
-static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
-
-static const Layout layouts[] = {
- /* symbol arrange function */
- { "[]=", tile }, /* first entry is default */
- { "><>", NULL }, /* no layout function means floating behavior */
- { "[M]", monocle },
- { NULL, NULL },
-};
-
-/* key definitions */
-#define MODKEY Mod4Mask
-#define TAGKEYS(KEY,TAG) \
- { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
- { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
- { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \
- { Mod1Mask, KEY, focusnthmon, {.i = TAG } }, \
- { Mod1Mask|ShiftMask, KEY, tagnthmon, {.i = TAG } },
-
-/* helper for spawning shell commands in the pre dwm-5.0 fashion */
-#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
-
-/* commands */
-static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
-static const char *dmenucmd[] = { "dmenu_run", "-i", "-c", "-l", "20", "-bw", "4", NULL };
-static const char *termcmd[] = { "st", NULL };
-
-static Key keys[] = {
- /* modifier key function argument */
- { MODKEY, XK_c, spawn, {.v = dmenucmd } },
- { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
- { MODKEY, XK_b, togglebar, {0} },
- { MODKEY, XK_j, focusstack, {.i = +1 } },
- { MODKEY, XK_k, focusstack, {.i = -1 } },
- { MODKEY, XK_i, incnmaster, {.i = +1 } },
- { MODKEY, XK_d, incnmaster, {.i = -1 } },
- { MODKEY, XK_h, setmfact, {.f = -0.05} },
- { MODKEY, XK_l, setmfact, {.f = +0.05} },
- { MODKEY, XK_Return, zoom, {0} },
- { MODKEY, XK_Tab, view, {0} },
- { MODKEY|ShiftMask, XK_c, killclient, {0} },
- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
- { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
- { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } },
- { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } },
- { MODKEY, XK_space, setlayout, {0} },
- { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
- { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
- { MODKEY, XK_s, togglesticky, {0} },
- { MODKEY, XK_0, view, {.ui = ~0 } },
- { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
- { MODKEY, XK_comma, focusmon, {.i = -1 } },
- { MODKEY, XK_period, focusmon, {.i = +1 } },
- { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
- { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
- { MODKEY, XK_F5, xrdb, {.v = NULL } },
- { 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)
- TAGKEYS( XK_4, 3)
- TAGKEYS( XK_5, 4)
- TAGKEYS( XK_6, 5)
- TAGKEYS( XK_7, 6)
- TAGKEYS( XK_8, 7)
- TAGKEYS( XK_9, 8)
- { MODKEY|ShiftMask, XK_r, quit, {1} },
- { MODKEY|ShiftMask, XK_q, quit, {0} },
- { MODKEY, XK_w, spawn, SHCMD("st -c \"st-float\" -g \"80x24+400+150\" -e sh -c \"set-bg -s\"") },
- { MODKEY|ShiftMask, XK_t, spawn, SHCMD("set-theme -s") },
- { MODKEY|ControlMask, XK_l, spawn, SHCMD("lock") },
- { MODKEY, XK_period, spawn, SHCMD("emoji") },
- { 0, XK_Print, spawn, SHCMD("screenshot") },
- { ShiftMask, XK_Print, spawn, SHCMD("screenshot -t 5") },
- { ControlMask, XK_Print, spawn, SHCMD("screenshot -s yes") },
- { ControlMask|ShiftMask, XK_Print, spawn, SHCMD("screenshot -s yes -t 5") },
- { 0, XF86XK_WebCam, spawn, SHCMD("webcam") },
- { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("backlight up") },
- { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("backlight down") },
- { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("volume up") },
- { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("volume down") },
- { 0, XF86XK_AudioMute, spawn, SHCMD("volume mute") },
-
-};
-
-/* button definitions */
-/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
-static Button buttons[] = {
- /* click event mask button function argument */
- { ClkTagBar, MODKEY, Button1, tag, {0} },
- { ClkTagBar, MODKEY, Button3, toggletag, {0} },
- { ClkWinTitle, 0, Button2, zoom, {0} },
- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
- { ClkClientWin, MODKEY, Button1, movemouse, {0} },
- { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
- { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
- { ClkTagBar, 0, Button1, view, {0} },
- { ClkTagBar, 0, Button3, toggleview, {0} },
- { ClkTagBar, MODKEY, Button1, tag, {0} },
- { ClkTagBar, MODKEY, Button3, toggletag, {0} },
- { ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1} },
- { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
-};
diff --git a/config.h b/config.h
@@ -0,0 +1,229 @@
+/* See LICENSE file for copyright and license details. */
+
+/* Load essentials */
+#include <X11/XF86keysym.h> /* For XF86 multimedia binds */
+
+/* appearance */
+static const char *fonts[] = { "monospace:size=8", "Vazir:size=8" };
+static const unsigned int borderpx = 2; /* border pixel of windows */
+static const unsigned int gappx = 5; /* gaps between windows */
+static const unsigned int snap = 32; /* snap pixel */
+static const unsigned int systraypinning= 0; /* 0: sloppy systray follows selected monitor, 0: pin systray to monitor X */
+static const unsigned int systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */
+static const unsigned int systrayspacing= 2; /* systray spacing */
+static const int systraypinningfailfirst= 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/
+static const int showsystray = 1; /* 0 means no systray */
+static const int swallowfloating = 0; /* 1 means swallow floating windows by default */
+static const int showbar = 1; /* 0 means no bar */
+static const int topbar = 1; /* 0 means bottom bar */
+static const int barheight = 20; /* 0 means that dwm will calculate bar height, >= 1 means dwm will barheight as bar height */
+static const int hidevacanttags = 1; /* 1 means hide empty tags / 0: show every tag */
+static const int hidetagindicator = 1; /* 1 means hide default top-left square-shaped tag indicator */
+static const int centeredwindowname = 0; /* 1 means center the WM_NAME of the currently selected window on the status bar */
+static const unsigned int colorfultag = 1; /* 0 means use SchemeSel for selected tag */
+static char fgcolor[] = "#D8DEE9";
+static char bgcolor[] = "#2E3440";
+static char color0[] = "#3B4252";
+static char color1[] = "#BF616A";
+static char color2[] = "#A3BE8C";
+static char color3[] = "#EBCB8B";
+static char color4[] = "#81A1C1";
+static char color5[] = "#B48EAD";
+static char color6[] = "#88C0D0";
+static char color7[] = "#E5E9F0";
+static char color8[] = "#4C566A";
+static char color9[] = "#BF616A";
+static char color10[] = "#A3BE8C";
+static char color11[] = "#EBCB8B";
+static char color12[] = "#81A1C1";
+static char color13[] = "#B48EAD";
+static char color14[] = "#8FBCBB";
+static char color15[] = "#ECEFF4";
+static const char *colors[][3] = {
+ /* fg bg border */
+ [SchemeNorm] = { color7, bgcolor, bgcolor },
+ [SchemeSel] = { fgcolor, color0, color0 },
+ [SchemeTag] = { color0, bgcolor, bgcolor },
+ [SchemeTag1] = { color1, bgcolor, bgcolor },
+ [SchemeTag2] = { color2, bgcolor, bgcolor },
+ [SchemeTag3] = { color3, bgcolor, bgcolor },
+ [SchemeTag4] = { color4, bgcolor, bgcolor },
+ [SchemeTag5] = { color5, bgcolor, bgcolor },
+ [SchemeTag6] = { color6, bgcolor, bgcolor },
+ [SchemeTag7] = { color9, bgcolor, bgcolor },
+ [SchemeTag8] = { color10, bgcolor, bgcolor },
+ [SchemeTag9] = { color11, bgcolor, bgcolor },
+ [SchemeLayout] = { color12, bgcolor, bgcolor },
+
+};
+
+
+/* tagging */
+static const char *tags[] = { "𐎠", "𐎡", "𐎢", "𐎣", "𐎤", "𐎥", "𐎦", "𐎧", "𐎨" };
+//static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+static const int tagschemes[] = { SchemeTag1, SchemeTag2, SchemeTag3,
+ SchemeTag4, SchemeTag5, SchemeTag6,
+ SchemeTag7, SchemeTag8, SchemeTag9,
+};
+
+static const char *tagsel[][2] = {
+ { color1, bgcolor },
+ { color2, bgcolor },
+ { color3, bgcolor },
+ { color4, bgcolor },
+ { color5, bgcolor },
+ { color6, bgcolor },
+ { color9, bgcolor },
+ { color10, bgcolor },
+ { color11, bgcolor },
+};
+
+static const unsigned int ulinepad = 5; /* horizontal padding between the underline and tag */
+static const unsigned int ulinestroke = 1; /* thickness / height of the underline */
+static const unsigned int ulinevoffset = 1; /* how far above the bottom of the bar the line should appear */
+static const int ulineall = 0; /* 1 to show underline on all tags, 0 for just the active ones */
+
+static const Rule rules[] = {
+ /* xprop(1):
+ * WM_CLASS(STRING) = instance, class
+ * WM_NAME(STRING) = title
+ */
+ /* class instance title tags mask isfloating isterminal noswallow monitor */
+ { "mpv", NULL, NULL, 0, 1, 0, 0, -1 },
+ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 },
+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 },
+ { "st-float", NULL, NULL, 0, 1, 1, 0, -1 },
+ { "st-256color",NULL, NULL, 0, 0, 1, 0, -1 },
+ { NULL, NULL, "Event Tester", 0, 0, 0, 1, -1 }, /* xev */
+};
+
+/* layout(s) */
+static const float mfact = 0.5; /* factor of master area size [0.05..0.95] */
+static const int nmaster = 1; /* number of clients in master area */
+static const int resizehints = 0; /* 1 means respect size hints in tiled resizals */
+static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
+
+static const Layout layouts[] = {
+ /* symbol arrange function */
+ { "[]=", tile }, /* first entry is default */
+ { "><>", NULL }, /* no layout function means floating behavior */
+ { "[M]", monocle },
+ { NULL, NULL },
+};
+
+/* key definitions */
+#define MODKEY Mod4Mask
+#define TAGKEYS(KEY,TAG) \
+ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \
+ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
+ { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
+ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, \
+ { Mod1Mask, KEY, focusnthmon, {.i = TAG } }, \
+ { Mod1Mask|ShiftMask, KEY, tagnthmon, {.i = TAG } },
+
+/* helper for spawning shell commands in the pre dwm-5.0 fashion */
+#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
+
+/* commands */
+static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */
+static const char *dmenucmd[] = { "dmenu_run", "-i", "-c", "-l", "20", "-bw", "4", NULL };
+static const char *termcmd[] = { "st", NULL };
+static const char *termcmdfloat[] = { "st", "-c", "st-float", NULL };
+
+static Key keys[] = {
+ /* modifier key function argument */
+ { MODKEY, XK_a, spawn, SHCMD("dmenu_drun") },
+ { MODKEY, XK_c, spawn, {.v = dmenucmd } },
+ { MODKEY, XK_Return, spawn, {.v = termcmd } },
+ { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmdfloat } },
+ { MODKEY|ShiftMask, XK_b, spawn, SHCMD("dmenu_bar") },
+ { MODKEY, XK_b, togglebar, {0} },
+ { MODKEY, XK_j, focusstack, {.i = +1 } },
+ { MODKEY, XK_k, focusstack, {.i = -1 } },
+ { MODKEY, XK_i, incnmaster, {.i = +1 } },
+ { MODKEY, XK_d, incnmaster, {.i = -1 } },
+ { MODKEY, XK_h, setmfact, {.f = -0.05} },
+ { MODKEY, XK_l, setmfact, {.f = +0.05} },
+ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
+ { MODKEY, XK_space, zoom, {0} },
+ { MODKEY, XK_Tab, view, {0} },
+ { MODKEY|ShiftMask, XK_c, killclient, {0} },
+ { MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
+ { MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
+ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } },
+ { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_space, togglefloating, {0} },
+ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} },
+ { MODKEY, XK_s, togglesticky, {0} },
+ { MODKEY, XK_0, view, {.ui = ~0 } },
+ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
+ { MODKEY, XK_comma, focusmon, {.i = -1 } },
+ { MODKEY, XK_period, focusmon, {.i = +1 } },
+ { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
+ { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
+ { MODKEY, XK_F5, xrdb, {.v = NULL } },
+ { 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)
+ TAGKEYS( XK_4, 3)
+ TAGKEYS( XK_5, 4)
+ TAGKEYS( XK_6, 5)
+ TAGKEYS( XK_7, 6)
+ TAGKEYS( XK_8, 7)
+ TAGKEYS( XK_9, 8)
+ { MODKEY|ShiftMask, XK_r, quit, {1} },
+ { MODKEY|ShiftMask, XK_q, quit, {0} },
+ { MODKEY, XK_w, spawn, SHCMD("st -c \"st-float\" -g \"80x24+400+150\" -e sh -c \"set-bg -s\"") },
+ { MODKEY|ShiftMask, XK_t, spawn, SHCMD("set-theme -s") },
+ { MODKEY|ControlMask, XK_l, spawn, SHCMD("lock") },
+ { MODKEY, XK_grave, spawn, SHCMD("emoji insert") },
+ { ControlMask, XK_grave, spawn, SHCMD("emoji clipboard") },
+ { 0, XK_Print, spawn, SHCMD("screenshot") },
+ { ShiftMask, XK_Print, spawn, SHCMD("screenshot -t 5") },
+ { ControlMask, XK_Print, spawn, SHCMD("screenshot -s yes") },
+ { ControlMask|ShiftMask, XK_Print, spawn, SHCMD("screenshot -s yes -t 5") },
+ { 0, XF86XK_WebCam, spawn, SHCMD("webcam") },
+ { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("backlight up") },
+ { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("backlight down") },
+ { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("volume up") },
+ { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("volume down") },
+ { 0, XF86XK_AudioMute, spawn, SHCMD("volume mute") },
+
+};
+
+/* button definitions */
+/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
+static Button buttons[] = {
+ /* click event mask button function argument */
+ /* placemouse options, choose which feels more natural:
+ * 0 - tiled position is relative to mouse cursor
+ * 1 - tiled postiion is relative to window center
+ * 2 - mouse pointer warps to window center
+ *
+ * The moveorplace uses movemouse or placemouse depending on the floating state
+ * of the selected client. Set up individual keybindings for the two if you want
+ * to control these separately (i.e. to retain the feature to move a tiled window
+ * into a floating position).
+ */
+ { ClkClientWin, MODKEY, Button1, moveorplace, {.i = 1} },
+ { 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} },
+ { ClkLtSymbol, 0, Button1, cyclelayout, {.i = +1} },
+ { ClkLtSymbol, 0, Button2, setlayout, {.v = &layouts[0]} },
+ { ClkLtSymbol, 0, Button3, cyclelayout, {.i = -1} },
+ { ClkWinTitle, 0, Button1, zoom, {0} },
+ { ClkWinTitle, 0, Button2, spawn, {.v = termcmd} },
+ { ClkWinTitle, 0, Button3, togglesticky, {0} },
+ { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
+ { ClkStatusText, 0, Button3, spawn, SHCMD("dmenu_bar") },
+};
diff --git a/dwm.c b/dwm.c
@@ -58,8 +58,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) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags] || C->issticky)
+#define INTERSECTC(x,y,w,h,z) (MAX(0, MIN((x)+(w),(z)->x+(z)->w) - MAX((x),(z)->x)) \
+ * MAX(0, MIN((y)+(h),(z)->y+(z)->h) - MAX((y),(z)->y)))
+#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky)
#define LENGTH(X) (sizeof X / sizeof X[0])
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
@@ -132,7 +133,7 @@ struct Client {
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int bw, oldbw;
unsigned int tags;
- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky, isterminal, noswallow;
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, issticky, isterminal, noswallow, beingmoved;
pid_t pid;
Client *next;
Client *snext;
@@ -199,7 +200,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 attachbottom(Client *c);
static void attachstack(Client *c);
static void buttonpress(XEvent *e);
static void checkotherwm(void);
@@ -243,11 +244,13 @@ 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 void moveorplace(const Arg *arg);
static Client *nexttiled(Client *c);
+static void placemouse(const Arg *arg);
static void pop(Client *);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
+static Client *recttoclient(int x, int y, int w, int h);
static Monitor *recttomon(int x, int y, int w, int h);
static void removesystrayicon(Client *i);
static void resize(Client *c, int x, int y, int w, int h, int interact);
@@ -302,6 +305,7 @@ static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
+static void warp(const Client *c);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
static Client *wintosystrayicon(Window w);
@@ -309,6 +313,7 @@ static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void xrdb(const Arg *arg);
+static void movestack(const Arg *arg);
static void zoom(const Arg *arg);
static pid_t getparentprocess(pid_t p);
@@ -523,14 +528,12 @@ attach(Client *c)
}
void
-attachaside(Client *c) {
- Client *at = nexttagged(c);
- if(!at) {
- attach(c);
- return;
- }
- c->next = at->next;
- at->next = c;
+attachbottom(Client *c)
+{
+ Client **tc;
+ c->next = NULL;
+ for (tc = &c->mon->clients; *tc; tc = &(*tc)->next);
+ *tc = c;
}
void
@@ -1241,6 +1244,7 @@ focusmon(const Arg *arg)
unfocus(selmon->sel, 0);
selmon = m;
focus(NULL);
+ warp(selmon->sel);
}
void
@@ -1256,6 +1260,7 @@ focusnthmon(const Arg *arg)
unfocus(selmon->sel, 0);
selmon = m;
focus(NULL);
+ warp(selmon->sel);
}
void
@@ -1480,6 +1485,45 @@ loadxrdb()
xrdb = XrmGetStringDatabase(resm);
if (xrdb != NULL) {
+ /* Load ^color* */
+ XRDB_LOAD_COLOR("foreground", fgcolor);
+ XRDB_LOAD_COLOR("background", bgcolor);
+ XRDB_LOAD_COLOR("color0", color0);
+ XRDB_LOAD_COLOR("color1", color1);
+ XRDB_LOAD_COLOR("color2", color2);
+ XRDB_LOAD_COLOR("color3", color3);
+ XRDB_LOAD_COLOR("color4", color4);
+ XRDB_LOAD_COLOR("color5", color5);
+ XRDB_LOAD_COLOR("color6", color6);
+ XRDB_LOAD_COLOR("color7", color7);
+ XRDB_LOAD_COLOR("color8", color8);
+ XRDB_LOAD_COLOR("color9", color9);
+ XRDB_LOAD_COLOR("color10", color10);
+ XRDB_LOAD_COLOR("color11", color11);
+ XRDB_LOAD_COLOR("color12", color12);
+ XRDB_LOAD_COLOR("color13", color13);
+ XRDB_LOAD_COLOR("color14", color14);
+ XRDB_LOAD_COLOR("color15", color15);
+ /* Load ^*color* */
+ XRDB_LOAD_COLOR("*foreground", fgcolor);
+ XRDB_LOAD_COLOR("*background", bgcolor);
+ XRDB_LOAD_COLOR("*color0", color0);
+ XRDB_LOAD_COLOR("*color1", color1);
+ XRDB_LOAD_COLOR("*color2", color2);
+ XRDB_LOAD_COLOR("*color3", color3);
+ XRDB_LOAD_COLOR("*color4", color4);
+ XRDB_LOAD_COLOR("*color5", color5);
+ XRDB_LOAD_COLOR("*color6", color6);
+ XRDB_LOAD_COLOR("*color7", color7);
+ XRDB_LOAD_COLOR("*color8", color8);
+ XRDB_LOAD_COLOR("*color9", color9);
+ XRDB_LOAD_COLOR("*color10", color10);
+ XRDB_LOAD_COLOR("*color11", color11);
+ XRDB_LOAD_COLOR("*color12", color12);
+ XRDB_LOAD_COLOR("*color13", color13);
+ XRDB_LOAD_COLOR("*color14", color14);
+ XRDB_LOAD_COLOR("*color15", color15);
+ /* Load ^*.color* */
XRDB_LOAD_COLOR("*.foreground", fgcolor);
XRDB_LOAD_COLOR("*.background", bgcolor);
XRDB_LOAD_COLOR("*.color0", color0);
@@ -1556,7 +1600,7 @@ manage(Window w, XWindowAttributes *wa)
c->isfloating = c->oldstate = trans != None || c->isfixed;
if (c->isfloating)
XRaiseWindow(dpy, c->win);
- attachaside(c);
+ attachbottom(c);
attachstack(c);
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
(unsigned char *) &(c->win), 1);
@@ -1636,6 +1680,14 @@ motionnotify(XEvent *e)
}
void
+moveorplace(const Arg *arg) {
+ if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating)))
+ movemouse(arg);
+ else
+ placemouse(arg);
+}
+
+void
movemouse(const Arg *arg)
{
int x, y, ocx, ocy, nx, ny;
@@ -1696,16 +1748,6 @@ 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);
@@ -1713,6 +1755,139 @@ nexttiled(Client *c)
}
void
+placemouse(const Arg *arg)
+{
+ int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0;
+ Client *c, *r = NULL, *at, *prevr;
+ Monitor *m;
+ XEvent ev;
+ XWindowAttributes wa;
+ Time lasttime = 0;
+ int attachmode, prevattachmode;
+ attachmode = prevattachmode = -1;
+
+ if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */
+ return;
+ if (c->isfullscreen) /* no support placing fullscreen windows by mouse */
+ return;
+ restack(selmon);
+ prevr = c;
+ if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
+ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
+ return;
+
+ c->isfloating = 0;
+ c->beingmoved = 1;
+
+ XGetWindowAttributes(dpy, c->win, &wa);
+ ocx = wa.x;
+ ocy = wa.y;
+
+ if (arg->i == 2) // warp cursor to client center
+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2);
+
+ if (!getrootptr(&x, &y))
+ return;
+
+ do {
+ XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
+ switch (ev.type) {
+ case ConfigureRequest:
+ case Expose:
+ case MapRequest:
+ handler[ev.type](&ev);
+ break;
+ case MotionNotify:
+ if ((ev.xmotion.time - lasttime) <= (1000 / 60))
+ continue;
+ lasttime = ev.xmotion.time;
+
+ nx = ocx + (ev.xmotion.x - x);
+ ny = ocy + (ev.xmotion.y - y);
+
+ if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap))
+ freemove = 1;
+
+ if (freemove)
+ XMoveWindow(dpy, c->win, nx, ny);
+
+ if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon)
+ selmon = m;
+
+ if (arg->i == 1) { // tiled position is relative to the client window center point
+ px = nx + wa.width / 2;
+ py = ny + wa.height / 2;
+ } else { // tiled position is relative to the mouse cursor
+ px = ev.xmotion.x;
+ py = ev.xmotion.y;
+ }
+
+ r = recttoclient(px, py, 1, 1);
+
+ if (!r || r == c)
+ break;
+
+ attachmode = 0; // below
+ if (((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w)) {
+ if (abs(r->y - py) < r->h / 2)
+ attachmode = 1; // above
+ } else if (abs(r->x - px) < r->w / 2)
+ attachmode = 1; // above
+
+ if ((r && r != prevr) || (attachmode != prevattachmode)) {
+ detachstack(c);
+ detach(c);
+ if (c->mon != r->mon) {
+ arrangemon(c->mon);
+ c->tags = r->mon->tagset[r->mon->seltags];
+ }
+
+ c->mon = r->mon;
+ r->mon->sel = r;
+
+ if (attachmode) {
+ if (r == r->mon->clients)
+ attach(c);
+ else {
+ for (at = r->mon->clients; at->next != r; at = at->next);
+ c->next = at->next;
+ at->next = c;
+ }
+ } else {
+ c->next = r->next;
+ r->next = c;
+ }
+
+ attachstack(c);
+ arrangemon(r->mon);
+ prevr = r;
+ prevattachmode = attachmode;
+ }
+ break;
+ }
+ } while (ev.type != ButtonRelease);
+ XUngrabPointer(dpy, CurrentTime);
+
+ if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) {
+ detach(c);
+ detachstack(c);
+ arrangemon(c->mon);
+ c->mon = m;
+ c->tags = m->tagset[m->seltags];
+ attach(c);
+ attachstack(c);
+ selmon = m;
+ }
+
+ focus(c);
+ c->beingmoved = 0;
+
+ if (nx != -9999)
+ resize(c, nx, ny, c->w, c->h, 0);
+ arrangemon(c->mon);
+}
+
+void
pop(Client *c)
{
detach(c);
@@ -1776,6 +1951,21 @@ quit(const Arg *arg)
running = 0;
}
+Client *
+recttoclient(int x, int y, int w, int h)
+{
+ Client *c, *r = NULL;
+ int a, area = 0;
+
+ for (c = nexttiled(selmon->clients); c; c = nexttiled(c->next)) {
+ if ((a = INTERSECTC(x, y, w, h, c)) > area) {
+ area = a;
+ r = c;
+ }
+ }
+ return r;
+}
+
Monitor *
recttomon(int x, int y, int w, int h)
{
@@ -1827,6 +2017,10 @@ resizeclient(Client *c, int x, int y, int w, int h)
c->oldy = c->y; c->y = wc.y = y;
c->oldw = c->w; c->w = wc.width = w;
c->oldh = c->h; c->h = wc.height = h;
+
+ if (c->beingmoved)
+ return;
+
wc.border_width = c->bw;
if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next))
|| &monocle == c->mon->lt[c->mon->sellt]->arrange)
@@ -1934,6 +2128,8 @@ restack(Monitor *m)
}
XSync(dpy, False);
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
+ if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2])
+ warp(m->sel);
}
void
@@ -2061,7 +2257,7 @@ sendmon(Client *c, Monitor *m)
detachstack(c);
c->mon = m;
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
- attachaside(c);
+ attachbottom(c);
attachstack(c);
focus(NULL);
arrange(NULL);
@@ -2661,7 +2857,7 @@ updategeom(void)
m->clients = c->next;
detachstack(c);
c->mon = mons;
- attachaside(c);
+ attachbottom(c);
attachstack(c);
}
if (m == selmon)
@@ -3058,6 +3254,28 @@ swallowingclient(Window w)
return NULL;
}
+void
+warp(const Client *c)
+{
+ int x, y;
+
+ if (!c) {
+ XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww/2, selmon->wy + selmon->wh/2);
+ return;
+ }
+
+ if (!getrootptr(&x, &y) ||
+ (x > c->x - c->bw &&
+ y > c->y - c->bw &&
+ x < c->x + c->w + c->bw*2 &&
+ y < c->y + c->h + c->bw*2) ||
+ (y > c->mon->by && y < c->mon->by + bh) ||
+ (c->mon->topbar && !y))
+ return;
+
+ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
+}
+
Client *
wintoclient(Window w)
{
@@ -3162,6 +3380,55 @@ systraytomon(Monitor *m) {
}
void
+movestack(const Arg *arg) {
+ Client *c = NULL, *p = NULL, *pc = NULL, *i;
+
+ if(arg->i > 0) {
+ /* find the client after selmon->sel */
+ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
+ if(!c)
+ for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
+
+ }
+ else {
+ /* find the client before selmon->sel */
+ for(i = selmon->clients; i != selmon->sel; i = i->next)
+ if(ISVISIBLE(i) && !i->isfloating)
+ c = i;
+ if(!c)
+ for(; i; i = i->next)
+ if(ISVISIBLE(i) && !i->isfloating)
+ c = i;
+ }
+ /* find the client before selmon->sel and c */
+ for(i = selmon->clients; i && (!p || !pc); i = i->next) {
+ if(i->next == selmon->sel)
+ p = i;
+ if(i->next == c)
+ pc = i;
+ }
+
+ /* swap c and selmon->sel selmon->clients in the selmon->clients list */
+ if(c && c != selmon->sel) {
+ Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
+ selmon->sel->next = c->next==selmon->sel?c:c->next;
+ c->next = temp;
+
+ if(p && p != c)
+ p->next = c;
+ if(pc && pc != selmon->sel)
+ pc->next = selmon->sel;
+
+ if(selmon->sel == selmon->clients)
+ selmon->clients = c;
+ else if(c == selmon->clients)
+ selmon->clients = selmon->sel;
+
+ arrange(selmon);
+ }
+}
+
+void
zoom(const Arg *arg)
{
Client *c = selmon->sel;
diff --git a/patches/dwm-attachaside-6.3.diff b/patches/dwm-attachaside-6.3.diff
@@ -1,92 +0,0 @@
-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-attachbottom-20201227-61bb8b2.diff b/patches/dwm-attachbottom-20201227-61bb8b2.diff
@@ -0,0 +1,67 @@
+From eea05f94baf707114ea882e8755520ba30d73cb2 Mon Sep 17 00:00:00 2001
+From: Szabolcs Szucs <[email protected]>
+Date: Sat, 26 Dec 2020 21:17:40 +0100
+Subject: [PATCH] attachbottom patch
+
+---
+ dwm.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/dwm.c b/dwm.c
+index 664c527..7ee3566 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -147,6 +147,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 attachbottom(Client *c);
+ static void attachstack(Client *c);
+ static void buttonpress(XEvent *e);
+ static void checkotherwm(void);
+@@ -407,6 +408,15 @@ attach(Client *c)
+ c->mon->clients = c;
+ }
+
++void
++attachbottom(Client *c)
++{
++ Client **tc;
++ c->next = NULL;
++ for (tc = &c->mon->clients; *tc; tc = &(*tc)->next);
++ *tc = c;
++}
++
+ void
+ attachstack(Client *c)
+ {
+@@ -1063,7 +1073,7 @@ manage(Window w, XWindowAttributes *wa)
+ c->isfloating = c->oldstate = trans != None || c->isfixed;
+ if (c->isfloating)
+ XRaiseWindow(dpy, c->win);
+- attach(c);
++ attachbottom(c);
+ attachstack(c);
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
+ (unsigned char *) &(c->win), 1);
+@@ -1418,7 +1428,7 @@ sendmon(Client *c, Monitor *m)
+ detachstack(c);
+ c->mon = m;
+ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
+- attach(c);
++ attachbottom(c);
+ attachstack(c);
+ focus(NULL);
+ arrange(NULL);
+@@ -1900,7 +1910,7 @@ updategeom(void)
+ m->clients = c->next;
+ detachstack(c);
+ c->mon = mons;
+- attach(c);
++ attachbottom(c);
+ attachstack(c);
+ }
+ if (m == selmon)
+--
+2.29.2
+
diff --git a/patches/dwm-movestack-20211115-a786211.diff b/patches/dwm-movestack-20211115-a786211.diff
@@ -0,0 +1,95 @@
+From 9a4037dc0ef56f91c009317e78e9e3790dafbb58 Mon Sep 17 00:00:00 2001
+From: BrunoCooper17 <[email protected]>
+Date: Mon, 15 Nov 2021 14:04:53 -0600
+Subject: [PATCH] MoveStack patch
+
+This plugin allows you to move clients around in the stack and swap them
+with the master. It emulates the behavior off mod+shift+j and mod+shift+k
+in Xmonad. movestack(+1) will swap the client with the current focus with
+the next client. movestack(-1) will swap the client with the current focus
+with the previous client.
+---
+ config.def.h | 3 +++
+ movestack.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 51 insertions(+)
+ create mode 100644 movestack.c
+
+diff --git a/config.def.h b/config.def.h
+index a2ac963..33efa5b 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -60,6 +60,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn()
+ static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
+ static const char *termcmd[] = { "st", NULL };
+
++#include "movestack.c"
+ static Key keys[] = {
+ /* modifier key function argument */
+ { MODKEY, XK_p, spawn, {.v = dmenucmd } },
+@@ -71,6 +72,8 @@ static Key keys[] = {
+ { MODKEY, XK_d, incnmaster, {.i = -1 } },
+ { MODKEY, XK_h, setmfact, {.f = -0.05} },
+ { MODKEY, XK_l, setmfact, {.f = +0.05} },
++ { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
++ { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
+ { MODKEY, XK_Return, zoom, {0} },
+ { MODKEY, XK_Tab, view, {0} },
+ { MODKEY|ShiftMask, XK_c, killclient, {0} },
+diff --git a/movestack.c b/movestack.c
+new file mode 100644
+index 0000000..520f4ae
+--- /dev/null
++++ b/movestack.c
+@@ -0,0 +1,48 @@
++void
++movestack(const Arg *arg) {
++ Client *c = NULL, *p = NULL, *pc = NULL, *i;
++
++ if(arg->i > 0) {
++ /* find the client after selmon->sel */
++ for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
++ if(!c)
++ for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
++
++ }
++ else {
++ /* find the client before selmon->sel */
++ for(i = selmon->clients; i != selmon->sel; i = i->next)
++ if(ISVISIBLE(i) && !i->isfloating)
++ c = i;
++ if(!c)
++ for(; i; i = i->next)
++ if(ISVISIBLE(i) && !i->isfloating)
++ c = i;
++ }
++ /* find the client before selmon->sel and c */
++ for(i = selmon->clients; i && (!p || !pc); i = i->next) {
++ if(i->next == selmon->sel)
++ p = i;
++ if(i->next == c)
++ pc = i;
++ }
++
++ /* swap c and selmon->sel selmon->clients in the selmon->clients list */
++ if(c && c != selmon->sel) {
++ Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
++ selmon->sel->next = c->next==selmon->sel?c:c->next;
++ c->next = temp;
++
++ if(p && p != c)
++ p->next = c;
++ if(pc && pc != selmon->sel)
++ pc->next = selmon->sel;
++
++ if(selmon->sel == selmon->clients)
++ selmon->clients = c;
++ else if(c == selmon->clients)
++ selmon->clients = selmon->sel;
++
++ arrange(selmon);
++ }
++}
+\ No newline at end of file
+--
+2.33.1
+
diff --git a/patches/dwm-placemouse-6.3.diff b/patches/dwm-placemouse-6.3.diff
@@ -0,0 +1,259 @@
+From 399cb51f86d259d0d15d2db767d31c9e030c0528 Mon Sep 17 00:00:00 2001
+From: Bakkeby <[email protected]>
+Date: Mon, 10 Jan 2022 13:18:37 +0100
+Subject: [PATCH] Adding placemouse patch
+
+---
+ config.def.h | 12 +++-
+ dwm.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 177 insertions(+), 1 deletion(-)
+
+diff --git a/config.def.h b/config.def.h
+index a2ac963..caaebf6 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -105,7 +105,17 @@ static Button buttons[] = {
+ { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} },
+ { ClkWinTitle, 0, Button2, zoom, {0} },
+ { ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
+- { ClkClientWin, MODKEY, Button1, movemouse, {0} },
++ /* placemouse options, choose which feels more natural:
++ * 0 - tiled position is relative to mouse cursor
++ * 1 - tiled postiion is relative to window center
++ * 2 - mouse pointer warps to window center
++ *
++ * The moveorplace uses movemouse or placemouse depending on the floating state
++ * of the selected client. Set up individual keybindings for the two if you want
++ * to control these separately (i.e. to retain the feature to move a tiled window
++ * into a floating position).
++ */
++ { ClkClientWin, MODKEY, Button1, moveorplace, {.i = 1} },
+ { ClkClientWin, MODKEY, Button2, togglefloating, {0} },
+ { ClkClientWin, MODKEY, Button3, resizemouse, {0} },
+ { ClkTagBar, 0, Button1, view, {0} },
+diff --git a/dwm.c b/dwm.c
+index a96f33c..5d57e18 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -49,6 +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 INTERSECTC(x,y,w,h,z) (MAX(0, MIN((x)+(w),(z)->x+(z)->w) - MAX((x),(z)->x)) \
++ * MAX(0, MIN((y)+(h),(z)->y+(z)->h) - MAX((y),(z)->y)))
+ #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
+ #define LENGTH(X) (sizeof X / sizeof X[0])
+ #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
+@@ -93,6 +95,7 @@ struct Client {
+ int bw, oldbw;
+ unsigned int tags;
+ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
++ int beingmoved;
+ Client *next;
+ Client *snext;
+ Monitor *mon;
+@@ -184,10 +187,13 @@ static void maprequest(XEvent *e);
+ static void monocle(Monitor *m);
+ static void motionnotify(XEvent *e);
+ static void movemouse(const Arg *arg);
++static void moveorplace(const Arg *arg);
+ static Client *nexttiled(Client *c);
++static void placemouse(const Arg *arg);
+ static void pop(Client *);
+ static void propertynotify(XEvent *e);
+ static void quit(const Arg *arg);
++static Client *recttoclient(int x, int y, int w, int h);
+ static Monitor *recttomon(int x, int y, int w, int h);
+ static void resize(Client *c, int x, int y, int w, int h, int interact);
+ static void resizeclient(Client *c, int x, int y, int w, int h);
+@@ -1136,6 +1142,14 @@ motionnotify(XEvent *e)
+ mon = m;
+ }
+
++void
++moveorplace(const Arg *arg) {
++ if ((!selmon->lt[selmon->sellt]->arrange || (selmon->sel && selmon->sel->isfloating)))
++ movemouse(arg);
++ else
++ placemouse(arg);
++}
++
+ void
+ movemouse(const Arg *arg)
+ {
+@@ -1203,6 +1217,139 @@ nexttiled(Client *c)
+ return c;
+ }
+
++void
++placemouse(const Arg *arg)
++{
++ int x, y, px, py, ocx, ocy, nx = -9999, ny = -9999, freemove = 0;
++ Client *c, *r = NULL, *at, *prevr;
++ Monitor *m;
++ XEvent ev;
++ XWindowAttributes wa;
++ Time lasttime = 0;
++ int attachmode, prevattachmode;
++ attachmode = prevattachmode = -1;
++
++ if (!(c = selmon->sel) || !c->mon->lt[c->mon->sellt]->arrange) /* no support for placemouse when floating layout is used */
++ return;
++ if (c->isfullscreen) /* no support placing fullscreen windows by mouse */
++ return;
++ restack(selmon);
++ prevr = c;
++ if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
++ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
++ return;
++
++ c->isfloating = 0;
++ c->beingmoved = 1;
++
++ XGetWindowAttributes(dpy, c->win, &wa);
++ ocx = wa.x;
++ ocy = wa.y;
++
++ if (arg->i == 2) // warp cursor to client center
++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, WIDTH(c) / 2, HEIGHT(c) / 2);
++
++ if (!getrootptr(&x, &y))
++ return;
++
++ do {
++ XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
++ switch (ev.type) {
++ case ConfigureRequest:
++ case Expose:
++ case MapRequest:
++ handler[ev.type](&ev);
++ break;
++ case MotionNotify:
++ if ((ev.xmotion.time - lasttime) <= (1000 / 60))
++ continue;
++ lasttime = ev.xmotion.time;
++
++ nx = ocx + (ev.xmotion.x - x);
++ ny = ocy + (ev.xmotion.y - y);
++
++ if (!freemove && (abs(nx - ocx) > snap || abs(ny - ocy) > snap))
++ freemove = 1;
++
++ if (freemove)
++ XMoveWindow(dpy, c->win, nx, ny);
++
++ if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != selmon)
++ selmon = m;
++
++ if (arg->i == 1) { // tiled position is relative to the client window center point
++ px = nx + wa.width / 2;
++ py = ny + wa.height / 2;
++ } else { // tiled position is relative to the mouse cursor
++ px = ev.xmotion.x;
++ py = ev.xmotion.y;
++ }
++
++ r = recttoclient(px, py, 1, 1);
++
++ if (!r || r == c)
++ break;
++
++ attachmode = 0; // below
++ if (((float)(r->y + r->h - py) / r->h) > ((float)(r->x + r->w - px) / r->w)) {
++ if (abs(r->y - py) < r->h / 2)
++ attachmode = 1; // above
++ } else if (abs(r->x - px) < r->w / 2)
++ attachmode = 1; // above
++
++ if ((r && r != prevr) || (attachmode != prevattachmode)) {
++ detachstack(c);
++ detach(c);
++ if (c->mon != r->mon) {
++ arrangemon(c->mon);
++ c->tags = r->mon->tagset[r->mon->seltags];
++ }
++
++ c->mon = r->mon;
++ r->mon->sel = r;
++
++ if (attachmode) {
++ if (r == r->mon->clients)
++ attach(c);
++ else {
++ for (at = r->mon->clients; at->next != r; at = at->next);
++ c->next = at->next;
++ at->next = c;
++ }
++ } else {
++ c->next = r->next;
++ r->next = c;
++ }
++
++ attachstack(c);
++ arrangemon(r->mon);
++ prevr = r;
++ prevattachmode = attachmode;
++ }
++ break;
++ }
++ } while (ev.type != ButtonRelease);
++ XUngrabPointer(dpy, CurrentTime);
++
++ if ((m = recttomon(ev.xmotion.x, ev.xmotion.y, 1, 1)) && m != c->mon) {
++ detach(c);
++ detachstack(c);
++ arrangemon(c->mon);
++ c->mon = m;
++ c->tags = m->tagset[m->seltags];
++ attach(c);
++ attachstack(c);
++ selmon = m;
++ }
++
++ focus(c);
++ c->beingmoved = 0;
++
++ if (nx != -9999)
++ resize(c, nx, ny, c->w, c->h, 0);
++ arrangemon(c->mon);
++}
++
+ void
+ pop(Client *c)
+ {
+@@ -1255,6 +1402,21 @@ quit(const Arg *arg)
+ running = 0;
+ }
+
++Client *
++recttoclient(int x, int y, int w, int h)
++{
++ Client *c, *r = NULL;
++ int a, area = 0;
++
++ for (c = nexttiled(selmon->clients); c; c = nexttiled(c->next)) {
++ if ((a = INTERSECTC(x, y, w, h, c)) > area) {
++ area = a;
++ r = c;
++ }
++ }
++ return r;
++}
++
+ Monitor *
+ recttomon(int x, int y, int w, int h)
+ {
+@@ -1285,6 +1447,10 @@ resizeclient(Client *c, int x, int y, int w, int h)
+ c->oldy = c->y; c->y = wc.y = y;
+ c->oldw = c->w; c->w = wc.width = w;
+ c->oldh = c->h; c->h = wc.height = h;
++
++ if (c->beingmoved)
++ return;
++
+ wc.border_width = c->bw;
+ XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
+ configure(c);
+--
+2.19.1
+
diff --git a/patches/dwm-warp-6.2.diff b/patches/dwm-warp-6.2.diff
@@ -0,0 +1,58 @@
+diff --git a/dwm.c b/dwm.c
+index 4465af1..bf74f60 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -227,6 +227,7 @@ static void updatetitle(Client *c);
+ static void updatewindowtype(Client *c);
+ static void updatewmhints(Client *c);
+ static void view(const Arg *arg);
++static void warp(const Client *c);
+ static Client *wintoclient(Window w);
+ static Monitor *wintomon(Window w);
+ static int xerror(Display *dpy, XErrorEvent *ee);
+@@ -827,6 +828,7 @@ focusmon(const Arg *arg)
+ unfocus(selmon->sel, 0);
+ selmon = m;
+ focus(NULL);
++ warp(selmon->sel);
+ }
+
+ void
+@@ -1367,6 +1369,8 @@ restack(Monitor *m)
+ }
+ XSync(dpy, False);
+ while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
++ if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2])
++ warp(m->sel);
+ }
+
+ void
+@@ -2044,6 +2048,28 @@ view(const Arg *arg)
+ arrange(selmon);
+ }
+
++void
++warp(const Client *c)
++{
++ int x, y;
++
++ if (!c) {
++ XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww/2, selmon->wy + selmon->wh/2);
++ return;
++ }
++
++ if (!getrootptr(&x, &y) ||
++ (x > c->x - c->bw &&
++ y > c->y - c->bw &&
++ x < c->x + c->w + c->bw*2 &&
++ y < c->y + c->h + c->bw*2) ||
++ (y > c->mon->by && y < c->mon->by + bh) ||
++ (c->mon->topbar && !y))
++ return;
++
++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
++}
++
+ Client *
+ wintoclient(Window w)
+ {