diff options
author | zachir <zachir@librem.one> | 2021-03-24 17:50:26 -0500 |
---|---|---|
committer | zachir <zachir@librem.one> | 2021-03-24 17:50:26 -0500 |
commit | f8dea854fe2144c0e48a44447dbe53719905cffb (patch) | |
tree | 21c92ffaa48630259c354b35dac3ef9c6978234a | |
parent | 2e73837eb86f927cfd0fcc669e263cfeb05797f3 (diff) |
Update patch.diff
-rw-r--r-- | patch.diff | 12916 |
1 files changed, 181 insertions, 12735 deletions
@@ -1,11 +1,3 @@ -diff --git a/.gitignore b/.gitignore -new file mode 100644 -index 0000000..095e840 ---- /dev/null -+++ b/.gitignore -@@ -0,0 +1,2 @@ -+*.o -+dwm diff --git a/Makefile b/Makefile index 77bcbc0..c6bc24b 100644 --- a/Makefile @@ -32,7 +24,7 @@ index 77bcbc0..c6bc24b 100644 .PHONY: all options clean dist install uninstall diff --git a/config.def.h b/config.def.h -index 1c0b587..8bfef3e 100644 +index 1c0b587..9b6eba9 100644 --- a/config.def.h +++ b/config.def.h @@ -2,7 +2,13 @@ @@ -49,7 +41,27 @@ index 1c0b587..8bfef3e 100644 static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ static const char *fonts[] = { "monospace:size=10" }; -@@ -26,15 +32,18 @@ static const Rule rules[] = { +@@ -18,6 +24,19 @@ static const char *colors[][3] = { + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; + ++typedef struct { ++ const char *name; ++ const void *cmd; ++} Sp; ++const char *spcmd1[] = {"st", "-n", "sphtop", "-g", "120x34", NULL }; ++const char *spcmd2[] = {"st", "-n", "spst", "-g", "120x34", NULL }; ++const char *spcmd3[] = {"st", "-n", "sppm", "-g", "120x34", NULL }; ++static Sp scratchpads[] = { ++ {"sphtop", spcmd1}, ++ {"spst", spcmd2}, ++ {"sppm", spcmd3}, ++}; ++ + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +@@ -26,15 +45,21 @@ static const Rule rules[] = { * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ @@ -57,10 +69,13 @@ index 1c0b587..8bfef3e 100644 - { "Gimp", NULL, NULL, 0, 1, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, + /* class instance title tags mask isfloating isterminal noswallow monitor */ -+ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, -+ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, -+ { "st", NULL, NULL, 0, 0, 1, -1, -1 }, -+ { NULL, NULL, "Event Tester", 0, 1, 0, 1, -1 }, /* xev */ ++ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, ++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, ++ { "st", NULL, NULL, 0, 0, 1, -1, -1 }, ++ { NULL, NULL, "Event Tester", 0, 1, 0, 1, -1 }, /* xev */ ++ { NULL, "sphtop", NULL, SPTAG(0), 1, 1, 1, -1 }, ++ { NULL, "spst", NULL, SPTAG(1), 1, 1, 1, -1 }, ++ { NULL, "sppm", NULL, SPTAG(2), 1, 1, 1, -1 }, }; /* layout(s) */ @@ -71,7 +86,15 @@ index 1c0b587..8bfef3e 100644 static const Layout layouts[] = { /* symbol arrange function */ -@@ -70,6 +79,9 @@ static Key keys[] = { +@@ -59,6 +84,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() + static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; + static const char *termcmd[] = { "st", NULL }; + ++ + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, +@@ -70,6 +96,9 @@ static Key keys[] = { { MODKEY, XK_d, incnmaster, {.i = -1 } }, { MODKEY, XK_h, setmfact, {.f = -0.05} }, { MODKEY, XK_l, setmfact, {.f = +0.05} }, @@ -81,7 +104,7 @@ index 1c0b587..8bfef3e 100644 { MODKEY, XK_Return, zoom, {0} }, { MODKEY, XK_Tab, view, {0} }, { MODKEY|ShiftMask, XK_c, killclient, {0} }, -@@ -78,6 +90,7 @@ static Key keys[] = { +@@ -78,12 +107,16 @@ static Key keys[] = { { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, { MODKEY, XK_space, setlayout, {0} }, { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, @@ -89,7 +112,16 @@ index 1c0b587..8bfef3e 100644 { MODKEY, XK_0, view, {.ui = ~0 } }, { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, { MODKEY, XK_comma, focusmon, {.i = -1 } }, -@@ -94,6 +107,7 @@ static Key keys[] = { + { MODKEY, XK_period, focusmon, {.i = +1 } }, + { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, + { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, ++ { MODKEY, XK_y, togglescratch, {.ui = 0 } }, ++ { MODKEY, XK_u, togglescratch, {.ui = 1 } }, ++ { MODKEY, XK_x, togglescratch, {.ui = 2 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) +@@ -94,6 +127,7 @@ static Key keys[] = { TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) { MODKEY|ShiftMask, XK_q, quit, {0} }, @@ -97,7 +129,7 @@ index 1c0b587..8bfef3e 100644 }; /* button definitions */ -@@ -103,7 +117,9 @@ static Button buttons[] = { +@@ -103,13 +137,85 @@ static Button buttons[] = { { ClkLtSymbol, 0, Button1, setlayout, {0} }, { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, { ClkWinTitle, 0, Button2, zoom, {0} }, @@ -107,8 +139,11 @@ index 1c0b587..8bfef3e 100644 + { ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} }, { ClkClientWin, MODKEY, Button1, movemouse, {0} }, { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, - { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, -@@ -113,3 +129,73 @@ static Button buttons[] = { +- { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, ++ { ClkClientWin, MODKEY, Button1, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} }, }; @@ -182,272 +217,6 @@ index 1c0b587..8bfef3e 100644 + { "setlayout", setlayout }, + { "setlayoutex", setlayoutex }, +}; -diff --git a/config.h b/config.h -new file mode 100644 -index 0000000..607e67f ---- /dev/null -+++ b/config.h -@@ -0,0 +1,260 @@ -+/* See LICENSE file for copyright and license details. */ -+ -+#include <X11/XF86keysym.h> -+ -+/* appearance */ -+static const unsigned int borderpx = 1; /* border pixel of windows */ -+static const unsigned int gappx = 6; /* gaps between windows */ -+static const unsigned int snap = 32; /* snap pixel */ -+static const int swallowfloating = 0; -+static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ -+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 showbar = 1; /* 0 means no bar */ -+static const int topbar = 1; /* 0 means bottom bar */ -+static const char *fonts[] = { "mononoki Nerd Font:size=9", "JoyPixels:size=9" }; -+static const char dmenufont[] = "mononoki Nerd Font:size=9"; -+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[] = "#750000"; -+static const char *colors[][3] = { -+ /* fg bg border */ -+ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, -+ [SchemeSel] = { col_gray4, col_cyan, col_cyan }, -+}; -+ -+/* tagging */ -+static const char *tags[] = { " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9" }; -+ -+static const Rule rules[] = { -+ /* xprop(1): -+ * WM_CLASS(STRING) = instance, class -+ * WM_NAME(STRING) = title -+ */ -+ /* class instance title tags mask isfloating isterminal noswallow monitor */ -+ { NULL, NULL,"Picture in picture", 511, 1, 0, 0, -1 }, -+ { "ardour-6.2.0",NULL, NULL, 0, 1, 0, 0, -1 }, -+ { "urxvt", NULL, NULL, 0, 0, 1, 0, -1 }, -+ { "URxvt", NULL, NULL, 0, 0, 1, 0, -1 }, -+ { "Ardour-6.2.0",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-256color",NULL, NULL, 0, 0, 1, 1, -1 }, -+ { "st", NULL, NULL, 0, 0, 1, 1, -1 }, -+ { "St", NULL, NULL, 0, 0, 1, 1, -1 }, -+ { "tabbed", NULL, NULL, 0, 0, 1, 0, -1 }, -+ { NULL, NULL, "abduco", 0, 0, 1, 0, -1 }, -+ { "Alacritty", NULL, NULL, 0, 0, 1, 0, -1 }, -+ { "Blueman", NULL, NULL, 0, 1, 0, 0, -1 }, -+ { "QjackCtl", NULL, NULL, 0, 1, 0, 0, -1 }, -+ { "qjackctl", NULL, NULL, 0, 1, 0, 0, -1 }, -+ { "catia.py", NULL, NULL, 0, 1, 0, 0, -1 }, -+ { "Catia", NULL, NULL, 0, 1, 0, 0, -1 }, -+ { NULL, NULL, "Event Tester", 0, 1, 0, 1, -1 }, -+ { "Steam", NULL, NULL, 4, 0, 0, 0, -1 }, -+ { "steam", NULL, NULL, 4, 0, 0, 0, -1 }, -+ { NULL, NULL, "steam", 4, 0, 0, 0, -1 }, -+ { "Lutris", NULL, NULL, 2, 0, 0, 0, -1 }, -+ { "lutris", NULL, NULL, 2, 0, 0, 0, -1 }, -+}; -+ -+/* layout(s) */ -+static const float mfact = 0.50; /* 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 int attachbelow = 1; /* 1 means attach after the currently active window */ -+ -+static const Layout layouts[] = { -+ /* symbol arrange function */ -+ { "[]=", tile }, /* first entry is default */ -+ { "><>", NULL }, /* no layout function means floating behavior */ -+ { "[M]", monocle }, -+}; -+ -+/* key definitions */ -+#define MODKEY Mod1Mask -+#define TAGKEYS(KEY,TAG) \ -+ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ -+ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ -+ { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ -+ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, -+ -+/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -+#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } -+ -+/* commands */ -+static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -+static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -+static const char *passmenu[] = { "passmenu", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -+static const char *termcmd[] = { "tabbed", "-c", "st", "-w", NULL }; -+static const char *mpdtoggle[] = { "playerctl", "--player=mpd,mpv,%any", "play-pause", NULL }; -+static const char *mpdnext[] = { "playerctl", "--player=mpd,mpv,%any", "next", NULL }; -+static const char *mpdprev[] = { "playerctl", "--player=mpd,mpv,%any", "previous", NULL }; -+static const char *plytoggle[] = { "playerctl", "--player=%any,mpd", "play-pause", NULL }; -+static const char *plyfwd[] = { "playerctl", "--player=%any,mpd", "position 5+", NULL }; -+static const char *plybck[] = { "playerctl", "--player=%any,mpd", "position 5-", NULL }; -+static const char *blightup[] = { "light", "-A", "1", NULL }; -+static const char *blightdown[] = { "light", "-U", "1", NULL }; -+static const char *audioup[] = { "volsv", "-i", NULL }; -+static const char *audiodown[] = { "volsv", "-d", NULL }; -+static const char *audiomute[] = { "volsv", "-t", NULL }; -+static const char *micmute[] = { "pamixer", "--source", "1", "-t", NULL }; -+static const char *lockscr[] = { "xscreensaver-command", "-lock", NULL }; -+static const char *xidletog[] = { "xidletog", NULL }; -+static const char *xkillcmd[] = { "xkill", NULL }; -+ -+static Key keys[] = { -+ /* modifier key function argument */ -+ { MODKEY, XK_d, spawn, {.v = dmenucmd } }, -+ { MODKEY, XK_p, spawn, {.v = passmenu } }, -+ { MODKEY, XK_c, spawn, {.v = xidletog } }, -+ { MODKEY, XK_x, spawn, {.v = xkillcmd } }, -+ { MODKEY, XK_Return, spawn, {.v = termcmd } }, -+ { 0, XF86XK_AudioPlay, spawn, {.v = mpdtoggle } }, -+ { 0, XF86XK_AudioNext, spawn, {.v = mpdnext } }, -+ { 0, XF86XK_AudioPrev, spawn, {.v = mpdprev } }, -+ { ShiftMask, XF86XK_AudioPlay, spawn, {.v = plytoggle } }, -+ { ShiftMask, XF86XK_AudioNext, spawn, {.v = plyfwd } }, -+ { ShiftMask, XF86XK_AudioPrev, spawn, {.v = plybck } }, -+ { 0, XF86XK_MonBrightnessUp, spawn, {.v = blightup } }, -+ { 0, XF86XK_MonBrightnessDown, spawn, {.v = blightdown } }, -+ { 0, XF86XK_AudioLowerVolume, spawn, {.v = audiodown } }, -+ { 0, XF86XK_AudioRaiseVolume, spawn, {.v = audioup } }, -+ { 0, XF86XK_AudioMute, spawn, {.v = audiomute } }, -+ { 0, XF86XK_AudioMicMute, spawn, {.v = micmute } }, -+ { Mod4Mask, XK_l, spawn, {.v = lockscr } }, -+ { MODKEY, XK_b, togglebar, {0} }, -+ { MODKEY, XK_j, focusstack, {.i = +1 } }, -+ { MODKEY, XK_k, focusstack, {.i = -1 } }, -+ { MODKEY|ShiftMask, XK_j, pushdown, {.i = +1 } }, -+ { MODKEY|ShiftMask, XK_k, pushup, {.i = -1 } }, -+ { MODKEY|ControlMask, XK_k, setcfact, {.f = +0.25} }, -+ { MODKEY|ControlMask, XK_j, setcfact, {.f = -0.25} }, -+ { MODKEY|ControlMask, XK_o, setcfact, {.f = 0.00} }, -+ { MODKEY|ShiftMask, XK_h, incnmaster, {.i = +1 } }, -+ { MODKEY|ShiftMask, XK_l, incnmaster, {.i = -1 } }, -+ { MODKEY, XK_h, setmfact, {.f = -0.05} }, -+ { MODKEY, XK_l, setmfact, {.f = +0.05} }, -+ { MODKEY|ShiftMask, XK_Return, zoom, {0} }, -+ { MODKEY, XK_Tab, view, {0} }, -+ { MODKEY|ShiftMask, XK_q, killclient, {0} }, -+ { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, -+ { MODKEY, XK_s, setlayout, {.v = &layouts[1]} }, -+ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -+ { MODKEY|ShiftMask, XK_space, setlayout, {-1} }, -+ { MODKEY, XK_space, togglefloating, {0} }, -+ { MODKEY, XK_f, togglefullscr, {0} }, -+ { MODKEY, XK_0, view, {.ui = ~0 } }, -+ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, -+ { MODKEY|ControlMask, XK_comma, focusmon, {.i = -1 } }, -+ { MODKEY|ControlMask, XK_period, focusmon, {.i = +1 } }, -+ { MODKEY|ControlMask|ShiftMask, XK_comma, tagmon, {.i = -1 } }, -+ { MODKEY|ControlMask|ShiftMask, XK_period, tagmon, {.i = +1 } }, -+ TAGKEYS( XK_1, 0) -+ TAGKEYS( XK_2, 1) -+ TAGKEYS( XK_3, 2) -+ TAGKEYS( XK_4, 3) -+ TAGKEYS( XK_5, 4) -+ TAGKEYS( XK_6, 5) -+ TAGKEYS( XK_7, 6) -+ TAGKEYS( XK_8, 7) -+ TAGKEYS( XK_9, 8) -+ { MODKEY|ShiftMask, XK_e, quit, {0} }, -+ { MODKEY|ShiftMask, XK_r, quit, {1} }, -+ { MODKEY|ShiftMask, XK_Tab, toggleAttachBelow, {0} }, -+}; -+ -+/* button definitions */ -+/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -+static Button buttons[] = { -+ /* click event mask button function argument */ -+ { ClkLtSymbol, 0, Button1, setlayout, {0} }, -+ { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, -+ { ClkWinTitle, 0, Button2, zoom, {0} }, -+ { ClkStatusText, 0, Button1, sigdwmblocks, {.i = 1} }, -+ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} }, -+ { ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} }, -+ { 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 -+setlayoutex(const Arg *arg) -+{ -+ setlayout(&((Arg) { .v = &layouts[arg->i] })); -+} -+ -+void -+viewex(const Arg *arg) -+{ -+ view(&((Arg) { .ui = 1 << arg->ui })); -+} -+ -+void -+viewall(const Arg *arg) -+{ -+ view(&((Arg){.ui = ~0})); -+} -+ -+void -+toggleviewex(const Arg *arg) -+{ -+ toggleview(&((Arg) { .ui = 1 << arg->ui })); -+} -+ -+void -+tagex(const Arg *arg) -+{ -+ tag(&((Arg) { .ui = 1 << arg->ui })); -+} -+ -+void -+toggletagex(const Arg *arg) -+{ -+ toggletag(&((Arg) { .ui = 1 << arg->ui })); -+} -+ -+void -+tagall(const Arg *arg) -+{ -+ tag(&((Arg){.ui = ~0})); -+} -+ -+/* signal definitions */ -+/* signum must be greater than 0 */ -+/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */ -+static Signal signals[] = { -+ /* signum function */ -+ { "focusstack", focusstack }, -+ { "setmfact", setmfact }, -+ { "togglebar", togglebar }, -+ { "incnmaster", incnmaster }, -+ { "togglefloating", togglefloating }, -+ { "togglefullscr", togglefullscr }, -+ { "focusmon", focusmon }, -+ { "tagmon", tagmon }, -+ { "zoom", zoom }, -+ { "view", view }, -+ { "viewall", viewall }, -+ { "viewex", viewex }, -+ { "toggleview", view }, -+ { "toggleviewex", toggleviewex }, -+ { "tag", tag }, -+ { "tagall", tagall }, -+ { "tagex", tagex }, -+ { "toggletag", tag }, -+ { "toggletagex", toggletagex }, -+ { "killclient", killclient }, -+ { "quit", quit }, -+ { "setlayout", setlayout }, -+ { "setlayoutex", setlayoutex }, -+}; -+ diff --git a/config.mk b/config.mk index 6d36cb7..dbbc526 100644 --- a/config.mk @@ -730,7 +499,7 @@ index 13b3729..0ec6c60 100644 .BR dmenu (1), .BR st (1) diff --git a/dwm.c b/dwm.c -index 4465af1..cecbe53 100644 +index 4465af1..5fb86a6 100644 --- a/dwm.c +++ b/dwm.c @@ -40,6 +40,8 @@ @@ -742,15 +511,19 @@ index 4465af1..cecbe53 100644 #include "drw.h" #include "util.h" -@@ -52,17 +54,35 @@ +@@ -52,17 +54,38 @@ #define ISVISIBLE(C) ((C->tags & 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) -#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +-#define TAGMASK ((1 << LENGTH(tags)) - 1) +#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) - #define TAGMASK ((1 << LENGTH(tags)) - 1) ++#define NUMTAGS (LENGTH(tags) + LENGTH(scratchpads)) ++#define TAGMASK ((1 << NUMTAGS) - 1) ++#define SPTAG(i) ((1 << LENGTH(tags) << (i))) ++#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << LENGTH(tags)) #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) +#define SYSTEM_TRAY_REQUEST_DOCK 0 @@ -780,7 +553,7 @@ index 4465af1..cecbe53 100644 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ -@@ -87,14 +107,17 @@ typedef struct Client Client; +@@ -87,14 +110,17 @@ typedef struct Client Client; struct Client { char name[256]; float mina, maxa; @@ -799,7 +572,7 @@ index 4465af1..cecbe53 100644 Monitor *mon; Window win; }; -@@ -106,6 +129,11 @@ typedef struct { +@@ -106,6 +132,11 @@ typedef struct { const Arg arg; } Key; @@ -811,7 +584,7 @@ index 4465af1..cecbe53 100644 typedef struct { const char *symbol; void (*arrange)(Monitor *); -@@ -138,16 +166,27 @@ typedef struct { +@@ -138,16 +169,27 @@ typedef struct { const char *title; unsigned int tags; int isfloating; @@ -839,7 +612,7 @@ index 4465af1..cecbe53 100644 static void buttonpress(XEvent *e); static void checkotherwm(void); static void cleanup(void); -@@ -156,6 +195,7 @@ static void clientmessage(XEvent *e); +@@ -156,6 +198,7 @@ static void clientmessage(XEvent *e); static void configure(Client *c); static void configurenotify(XEvent *e); static void configurerequest(XEvent *e); @@ -847,7 +620,7 @@ index 4465af1..cecbe53 100644 static Monitor *createmon(void); static void destroynotify(XEvent *e); static void detach(Client *c); -@@ -165,12 +205,16 @@ static void drawbar(Monitor *m); +@@ -165,12 +208,16 @@ static void drawbar(Monitor *m); static void drawbars(void); static void enternotify(XEvent *e); static void expose(XEvent *e); @@ -864,7 +637,7 @@ index 4465af1..cecbe53 100644 static int gettextprop(Window w, Atom atom, char *text, unsigned int size); static void grabbuttons(Client *c, int focused); static void grabkeys(void); -@@ -184,33 +228,46 @@ static void monocle(Monitor *m); +@@ -184,33 +231,47 @@ static void monocle(Monitor *m); static void motionnotify(XEvent *e); static void movemouse(const Arg *arg); static Client *nexttiled(Client *c); @@ -910,10 +683,11 @@ index 4465af1..cecbe53 100644 static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); +static void togglefullscr(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); -@@ -223,20 +280,36 @@ static int updategeom(void); +@@ -223,20 +284,36 @@ static int updategeom(void); static void updatenumlockmask(void); static void updatesizehints(Client *c); static void updatestatus(void); @@ -950,7 +724,7 @@ index 4465af1..cecbe53 100644 static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh, blw = 0; /* bar geometry */ -@@ -257,9 +330,11 @@ static void (*handler[LASTEvent]) (XEvent *) = { +@@ -257,9 +334,11 @@ static void (*handler[LASTEvent]) (XEvent *) = { [MapRequest] = maprequest, [MotionNotify] = motionnotify, [PropertyNotify] = propertynotify, @@ -963,7 +737,7 @@ index 4465af1..cecbe53 100644 static int running = 1; static Cur *cursor[CurLast]; static Clr **scheme; -@@ -268,6 +343,8 @@ static Drw *drw; +@@ -268,6 +347,8 @@ static Drw *drw; static Monitor *mons, *selmon; static Window root, wmcheckwin; @@ -972,7 +746,7 @@ index 4465af1..cecbe53 100644 /* configuration, allows nested code to access above variables */ #include "config.h" -@@ -285,6 +362,7 @@ applyrules(Client *c) +@@ -285,6 +366,7 @@ applyrules(Client *c) XClassHint ch = { NULL, NULL }; /* rule matching */ @@ -980,7 +754,7 @@ index 4465af1..cecbe53 100644 c->isfloating = 0; c->tags = 0; XGetClassHint(dpy, c->win, &ch); -@@ -297,6 +375,8 @@ applyrules(Client *c) +@@ -297,8 +379,15 @@ applyrules(Client *c) && (!r->class || strstr(class, r->class)) && (!r->instance || strstr(instance, r->instance))) { @@ -988,8 +762,24 @@ index 4465af1..cecbe53 100644 + c->noswallow = r->noswallow; c->isfloating = r->isfloating; c->tags |= r->tags; ++ if ((r->tags & SPTAGMASK) && r->isfloating) { ++ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); ++ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); ++ } ++ for (m = mons; m && m->num != r->monitor; m = m->next); -@@ -405,6 +485,26 @@ attach(Client *c) + if (m) + c->mon = m; +@@ -308,7 +397,7 @@ applyrules(Client *c) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); +- c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; ++ c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK); + } + + int +@@ -405,6 +494,26 @@ attach(Client *c) c->next = c->mon->clients; c->mon->clients = c; } @@ -1016,7 +806,7 @@ index 4465af1..cecbe53 100644 void attachstack(Client *c) -@@ -413,6 +513,61 @@ attachstack(Client *c) +@@ -413,6 +522,61 @@ attachstack(Client *c) c->mon->stack = c; } @@ -1078,7 +868,7 @@ index 4465af1..cecbe53 100644 void buttonpress(XEvent *e) { -@@ -439,9 +594,25 @@ buttonpress(XEvent *e) +@@ -439,9 +603,25 @@ buttonpress(XEvent *e) arg.ui = 1 << i; } else if (ev->x < x + blw) click = ClkLtSymbol; @@ -1106,7 +896,7 @@ index 4465af1..cecbe53 100644 click = ClkWinTitle; } else if ((c = wintoclient(ev->window))) { focus(c); -@@ -482,6 +653,11 @@ cleanup(void) +@@ -482,6 +662,11 @@ cleanup(void) XUngrabKey(dpy, AnyKey, AnyModifier, root); while (mons) cleanupmon(mons); @@ -1118,7 +908,7 @@ index 4465af1..cecbe53 100644 for (i = 0; i < CurLast; i++) drw_cur_free(drw, cursor[i]); for (i = 0; i < LENGTH(colors); i++) -@@ -512,9 +688,57 @@ cleanupmon(Monitor *mon) +@@ -512,9 +697,57 @@ cleanupmon(Monitor *mon) void clientmessage(XEvent *e) { @@ -1176,7 +966,7 @@ index 4465af1..cecbe53 100644 if (!c) return; if (cme->message_type == netatom[NetWMState]) { -@@ -567,7 +791,7 @@ configurenotify(XEvent *e) +@@ -567,7 +800,7 @@ configurenotify(XEvent *e) for (c = m->clients; c; c = c->next) if (c->isfullscreen) resizeclient(c, m->mx, m->my, m->mw, m->mh); @@ -1185,7 +975,7 @@ index 4465af1..cecbe53 100644 } focus(NULL); arrange(NULL); -@@ -627,6 +851,19 @@ configurerequest(XEvent *e) +@@ -627,6 +860,19 @@ configurerequest(XEvent *e) XSync(dpy, False); } @@ -1205,7 +995,7 @@ index 4465af1..cecbe53 100644 Monitor * createmon(void) { -@@ -652,6 +889,15 @@ destroynotify(XEvent *e) +@@ -652,6 +898,15 @@ destroynotify(XEvent *e) if ((c = wintoclient(ev->window))) unmanage(c, 1); @@ -1221,7 +1011,7 @@ index 4465af1..cecbe53 100644 } void -@@ -695,18 +941,24 @@ dirtomon(int dir) +@@ -695,18 +950,24 @@ dirtomon(int dir) void drawbar(Monitor *m) { @@ -1250,7 +1040,7 @@ index 4465af1..cecbe53 100644 for (c = m->clients; c; c = c->next) { occ |= c->tags; -@@ -715,20 +967,24 @@ drawbar(Monitor *m) +@@ -715,20 +976,24 @@ drawbar(Monitor *m) } x = 0; for (i = 0; i < LENGTH(tags); i++) { @@ -1280,7 +1070,7 @@ index 4465af1..cecbe53 100644 if (m->sel) { drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -@@ -739,7 +995,7 @@ drawbar(Monitor *m) +@@ -739,7 +1004,7 @@ drawbar(Monitor *m) drw_rect(drw, x, 0, w, bh, 1, 1); } } @@ -1289,7 +1079,7 @@ index 4465af1..cecbe53 100644 } void -@@ -776,8 +1032,21 @@ expose(XEvent *e) +@@ -776,8 +1041,21 @@ expose(XEvent *e) Monitor *m; XExposeEvent *ev = &e->xexpose; @@ -1312,7 +1102,7 @@ index 4465af1..cecbe53 100644 } void -@@ -862,15 +1131,34 @@ getatomprop(Client *c, Atom prop) +@@ -862,15 +1140,34 @@ getatomprop(Client *c, Atom prop) unsigned long dl; unsigned char *p = NULL; Atom da, atom = None; @@ -1348,7 +1138,7 @@ index 4465af1..cecbe53 100644 int getrootptr(int *x, int *y) { -@@ -899,6 +1187,16 @@ getstate(Window w) +@@ -899,6 +1196,16 @@ getstate(Window w) return result; } @@ -1365,7 +1155,7 @@ index 4465af1..cecbe53 100644 int gettextprop(Window w, Atom atom, char *text, unsigned int size) { -@@ -998,12 +1296,55 @@ keypress(XEvent *e) +@@ -998,12 +1305,55 @@ keypress(XEvent *e) keys[i].func(&(keys[i].arg)); } @@ -1422,7 +1212,7 @@ index 4465af1..cecbe53 100644 XGrabServer(dpy); XSetErrorHandler(xerrordummy); XSetCloseDownMode(dpy, DestroyAll); -@@ -1017,18 +1358,20 @@ killclient(const Arg *arg) +@@ -1017,18 +1367,20 @@ killclient(const Arg *arg) void manage(Window w, XWindowAttributes *wa) { @@ -1444,7 +1234,7 @@ index 4465af1..cecbe53 100644 updatetitle(c); if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { -@@ -1037,6 +1380,7 @@ manage(Window w, XWindowAttributes *wa) +@@ -1037,6 +1389,7 @@ manage(Window w, XWindowAttributes *wa) } else { c->mon = selmon; applyrules(c); @@ -1452,7 +1242,7 @@ index 4465af1..cecbe53 100644 } if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) -@@ -1062,7 +1406,10 @@ manage(Window w, XWindowAttributes *wa) +@@ -1062,7 +1415,10 @@ manage(Window w, XWindowAttributes *wa) c->isfloating = c->oldstate = trans != None || c->isfixed; if (c->isfloating) XRaiseWindow(dpy, c->win); @@ -1464,7 +1254,7 @@ index 4465af1..cecbe53 100644 attachstack(c); XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, (unsigned char *) &(c->win), 1); -@@ -1073,6 +1420,8 @@ manage(Window w, XWindowAttributes *wa) +@@ -1073,6 +1429,8 @@ manage(Window w, XWindowAttributes *wa) c->mon->sel = c; arrange(c->mon); XMapWindow(dpy, c->win); @@ -1473,7 +1263,7 @@ index 4465af1..cecbe53 100644 focus(NULL); } -@@ -1091,6 +1440,12 @@ maprequest(XEvent *e) +@@ -1091,6 +1449,12 @@ maprequest(XEvent *e) { static XWindowAttributes wa; XMapRequestEvent *ev = &e->xmaprequest; @@ -1486,7 +1276,7 @@ index 4465af1..cecbe53 100644 if (!XGetWindowAttributes(dpy, ev->window, &wa)) return; -@@ -1199,6 +1554,7 @@ nexttiled(Client *c) +@@ -1199,6 +1563,7 @@ nexttiled(Client *c) return c; } @@ -1494,7 +1284,7 @@ index 4465af1..cecbe53 100644 void pop(Client *c) { -@@ -1207,6 +1563,17 @@ pop(Client *c) +@@ -1207,6 +1572,17 @@ pop(Client *c) focus(c); arrange(c->mon); } @@ -1512,7 +1302,7 @@ index 4465af1..cecbe53 100644 void propertynotify(XEvent *e) -@@ -1215,8 +1582,20 @@ propertynotify(XEvent *e) +@@ -1215,8 +1591,20 @@ propertynotify(XEvent *e) Window trans; XPropertyEvent *ev = &e->xproperty; @@ -1535,7 +1325,7 @@ index 4465af1..cecbe53 100644 else if (ev->state == PropertyDelete) return; /* ignore */ else if ((c = wintoclient(ev->window))) { -@@ -1245,9 +1624,41 @@ propertynotify(XEvent *e) +@@ -1245,9 +1633,41 @@ propertynotify(XEvent *e) } } @@ -1577,7 +1367,7 @@ index 4465af1..cecbe53 100644 running = 0; } -@@ -1265,6 +1676,20 @@ recttomon(int x, int y, int w, int h) +@@ -1265,6 +1685,20 @@ recttomon(int x, int y, int w, int h) return r; } @@ -1598,7 +1388,7 @@ index 4465af1..cecbe53 100644 void resize(Client *c, int x, int y, int w, int h, int interact) { -@@ -1272,16 +1697,48 @@ resize(Client *c, int x, int y, int w, int h, int interact) +@@ -1272,16 +1706,48 @@ resize(Client *c, int x, int y, int w, int h, int interact) resizeclient(c, x, y, w, h); } @@ -1651,7 +1441,7 @@ index 4465af1..cecbe53 100644 XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); configure(c); XSync(dpy, False); -@@ -1344,6 +1801,19 @@ resizemouse(const Arg *arg) +@@ -1344,6 +1810,19 @@ resizemouse(const Arg *arg) } } @@ -1671,7 +1461,7 @@ index 4465af1..cecbe53 100644 void restack(Monitor *m) { -@@ -1380,10 +1850,18 @@ run(void) +@@ -1380,10 +1859,18 @@ run(void) handler[ev.type](&ev); /* call handler */ } @@ -1690,7 +1480,7 @@ index 4465af1..cecbe53 100644 Window d1, d2, *wins = NULL; XWindowAttributes wa; -@@ -1394,6 +1872,8 @@ scan(void) +@@ -1394,6 +1881,8 @@ scan(void) continue; if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) manage(wins[i], &wa); @@ -1699,7 +1489,7 @@ index 4465af1..cecbe53 100644 } for (i = 0; i < num; i++) { /* now the transients */ if (!XGetWindowAttributes(dpy, wins[i], &wa)) -@@ -1405,6 +1885,7 @@ scan(void) +@@ -1405,6 +1894,7 @@ scan(void) if (wins) XFree(wins); } @@ -1707,7 +1497,7 @@ index 4465af1..cecbe53 100644 } void -@@ -1417,7 +1898,10 @@ sendmon(Client *c, Monitor *m) +@@ -1417,7 +1907,10 @@ sendmon(Client *c, Monitor *m) detachstack(c); c->mon = m; c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ @@ -1719,7 +1509,7 @@ index 4465af1..cecbe53 100644 attachstack(c); focus(NULL); arrange(NULL); -@@ -1433,26 +1917,36 @@ setclientstate(Client *c, long state) +@@ -1433,26 +1926,36 @@ setclientstate(Client *c, long state) } int @@ -1767,7 +1557,7 @@ index 4465af1..cecbe53 100644 } return exists; } -@@ -1466,7 +1960,7 @@ setfocus(Client *c) +@@ -1466,7 +1969,7 @@ setfocus(Client *c) XA_WINDOW, 32, PropModeReplace, (unsigned char *) &(c->win), 1); } @@ -1776,7 +1566,7 @@ index 4465af1..cecbe53 100644 } void -@@ -1511,6 +2005,23 @@ setlayout(const Arg *arg) +@@ -1511,6 +2014,23 @@ setlayout(const Arg *arg) drawbar(selmon); } @@ -1800,7 +1590,7 @@ index 4465af1..cecbe53 100644 /* arg > 1.0 will set mfact absolutely */ void setmfact(const Arg *arg) -@@ -1536,6 +2047,9 @@ setup(void) +@@ -1536,6 +2056,9 @@ setup(void) /* clean up any zombies immediately */ sigchld(0); @@ -1810,7 +1600,7 @@ index 4465af1..cecbe53 100644 /* init screen */ screen = DefaultScreen(dpy); sw = DisplayWidth(dpy, screen); -@@ -1555,6 +2069,10 @@ setup(void) +@@ -1555,6 +2078,10 @@ setup(void) wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); @@ -1821,7 +1611,7 @@ index 4465af1..cecbe53 100644 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); -@@ -1562,6 +2080,9 @@ setup(void) +@@ -1562,6 +2089,9 @@ setup(void) netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); @@ -1831,7 +1621,7 @@ index 4465af1..cecbe53 100644 /* init cursors */ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); cursor[CurResize] = drw_cur_create(drw, XC_sizing); -@@ -1570,6 +2091,8 @@ setup(void) +@@ -1570,6 +2100,8 @@ setup(void) scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); for (i = 0; i < LENGTH(colors); i++) scheme[i] = drw_scm_create(drw, colors[i], 3); @@ -1840,7 +1630,18 @@ index 4465af1..cecbe53 100644 /* init bars */ updatebars(); updatestatus(); -@@ -1636,6 +2159,37 @@ sigchld(int unused) +@@ -1616,6 +2148,10 @@ showhide(Client *c) + if (!c) + return; + if (ISVISIBLE(c)) { ++ if ((c->tags & SPTAGMASK) && c->isfloating) { ++ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); ++ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); ++ } + /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) +@@ -1636,6 +2172,37 @@ sigchld(int unused) while (0 < waitpid(-1, NULL, WNOHANG)); } @@ -1878,7 +1679,7 @@ index 4465af1..cecbe53 100644 void spawn(const Arg *arg) { -@@ -1674,9 +2228,15 @@ void +@@ -1674,9 +2241,15 @@ void tile(Monitor *m) { unsigned int i, n, h, mw, my, ty; @@ -1895,7 +1696,7 @@ index 4465af1..cecbe53 100644 if (n == 0) return; -@@ -1686,13 +2246,19 @@ tile(Monitor *m) +@@ -1686,13 +2259,19 @@ tile(Monitor *m) mw = m->ww; for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) if (i < m->nmaster) { @@ -1919,7 +1720,7 @@ index 4465af1..cecbe53 100644 } } -@@ -1701,7 +2267,18 @@ togglebar(const Arg *arg) +@@ -1701,7 +2280,18 @@ togglebar(const Arg *arg) { selmon->showbar = !selmon->showbar; updatebarpos(selmon); @@ -1939,7 +1740,7 @@ index 4465af1..cecbe53 100644 arrange(selmon); } -@@ -1719,6 +2296,13 @@ togglefloating(const Arg *arg) +@@ -1719,6 +2309,39 @@ togglefloating(const Arg *arg) arrange(selmon); } @@ -1950,10 +1751,36 @@ index 4465af1..cecbe53 100644 + setfullscreen(selmon->sel, !selmon->sel->isfullscreen); +} + ++void ++togglescratch(const Arg *arg) ++{ ++ Client *c; ++ unsigned int found = 0; ++ unsigned int scratchtag = SPTAG(arg->ui); ++ Arg sparg = {.v = scratchpads[arg->ui].cmd}; ++ ++ for (c = selmon->clients; c && !(found = c->tags & scratchtag); c = c->next); ++ if (found) { ++ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ scratchtag; ++ if (newtagset) { ++ selmon->tagset[selmon->seltags] = newtagset; ++ focus(NULL); ++ arrange(selmon); ++ } ++ if (ISVISIBLE(c)) { ++ focus(c); ++ restack(selmon); ++ } ++ } else { ++ selmon->tagset[selmon->seltags] |= scratchtag; ++ spawn(&sparg); ++ } ++} ++ void toggletag(const Arg *arg) { -@@ -1765,6 +2349,20 @@ unmanage(Client *c, int destroyed) +@@ -1765,6 +2388,20 @@ unmanage(Client *c, int destroyed) Monitor *m = c->mon; XWindowChanges wc; @@ -1974,7 +1801,7 @@ index 4465af1..cecbe53 100644 detach(c); detachstack(c); if (!destroyed) { -@@ -1779,9 +2377,12 @@ unmanage(Client *c, int destroyed) +@@ -1779,9 +2416,12 @@ unmanage(Client *c, int destroyed) XUngrabServer(dpy); } free(c); @@ -1990,7 +1817,7 @@ index 4465af1..cecbe53 100644 } void -@@ -1796,11 +2397,18 @@ unmapnotify(XEvent *e) +@@ -1796,11 +2436,18 @@ unmapnotify(XEvent *e) else unmanage(c, 0); } @@ -2009,7 +1836,7 @@ index 4465af1..cecbe53 100644 Monitor *m; XSetWindowAttributes wa = { .override_redirect = True, -@@ -1811,10 +2419,15 @@ updatebars(void) +@@ -1811,10 +2458,15 @@ updatebars(void) for (m = mons; m; m = m->next) { if (m->barwin) continue; @@ -2026,7 +1853,7 @@ index 4465af1..cecbe53 100644 XMapRaised(dpy, m->barwin); XSetClassHint(dpy, m->barwin, &ch); } -@@ -1897,7 +2510,10 @@ updategeom(void) +@@ -1897,7 +2549,10 @@ updategeom(void) m->clients = c->next; detachstack(c); c->mon = mons; @@ -2038,7 +1865,7 @@ index 4465af1..cecbe53 100644 attachstack(c); } if (m == selmon) -@@ -1987,9 +2603,126 @@ updatesizehints(Client *c) +@@ -1987,9 +2642,126 @@ updatesizehints(Client *c) void updatestatus(void) { @@ -2166,7 +1993,7 @@ index 4465af1..cecbe53 100644 } void -@@ -2044,6 +2777,110 @@ view(const Arg *arg) +@@ -2044,6 +2816,110 @@ view(const Arg *arg) arrange(selmon); } @@ -2277,7 +2104,7 @@ index 4465af1..cecbe53 100644 Client * wintoclient(Window w) { -@@ -2057,6 +2894,16 @@ wintoclient(Window w) +@@ -2057,6 +2933,16 @@ wintoclient(Window w) return NULL; } @@ -2294,7 +2121,7 @@ index 4465af1..cecbe53 100644 Monitor * wintomon(Window w) { -@@ -2110,18 +2957,58 @@ xerrorstart(Display *dpy, XErrorEvent *ee) +@@ -2110,18 +2996,58 @@ xerrorstart(Display *dpy, XErrorEvent *ee) return -1; } @@ -2357,7 +2184,7 @@ index 4465af1..cecbe53 100644 } int -@@ -2135,6 +3022,8 @@ main(int argc, char *argv[]) +@@ -2135,6 +3061,8 @@ main(int argc, char *argv[]) fputs("warning: no locale support\n", stderr); if (!(dpy = XOpenDisplay(NULL))) die("dwm: cannot open display"); @@ -2366,7 +2193,7 @@ index 4465af1..cecbe53 100644 checkotherwm(); setup(); #ifdef __OpenBSD__ -@@ -2142,7 +3031,9 @@ main(int argc, char *argv[]) +@@ -2142,7 +3070,9 @@ main(int argc, char *argv[]) die("pledge"); #endif /* __OpenBSD__ */ scan(); @@ -2377,12384 +2204,3 @@ index 4465af1..cecbe53 100644 cleanup(); XCloseDisplay(dpy); return EXIT_SUCCESS; -diff --git a/dwm.desktop b/dwm.desktop -new file mode 100644 -index 0000000..5a6021f ---- /dev/null -+++ b/dwm.desktop -@@ -0,0 +1,10 @@ -+[Desktop Entry] -+Version=6.3 -+Type=Application -+Name=dwm -+Comment=Suckless' dynamic window manager -+Exec=dwm -+Icon=dwm -+Terminal=false -+StartupNotify=false -+Categories=Application; -diff --git a/dwmc b/dwmc -new file mode 100755 -index 0000000..5ff8dbc ---- /dev/null -+++ b/dwmc -@@ -0,0 +1,40 @@ -+#!/usr/bin/env sh -+ -+signal() { -+ xsetroot -name "fsignal:$*" -+} -+ -+case $# in -+1) -+ case $1 in -+ setlayout | view | viewall | togglebar | togglefloating | zoom | killclient | quit) -+ signal $1 -+ ;; -+ *) -+ echo "Unknown command or missing one argument." -+ exit 1 -+ ;; -+ esac -+ ;; -+2) -+ case $1 in -+ view) -+ signal $1 ui $2 -+ ;; -+ viewex | toggleviewex | tagex | toggletagex | setlayoutex | focusstack | incnmaster | focusmon | tagmon) -+ signal $1 i $2 -+ ;; -+ setmfact) -+ signal $1 f $2 -+ ;; -+ *) -+ echo "Unknown command or one too many arguments." -+ exit 1 -+ ;; -+ esac -+ ;; -+*) -+ echo "Too many arguments." -+ exit 1 -+ ;; -+esac -diff --git a/patches/dwm-actualfullscreen-20191112-cb3f58a.diff b/patches/dwm-actualfullscreen-20191112-cb3f58a.diff -new file mode 100644 -index 0000000..21eea19 ---- /dev/null -+++ b/patches/dwm-actualfullscreen-20191112-cb3f58a.diff -@@ -0,0 +1,53 @@ -+From 3a16816a6f5d38014c2a06ce395873c545c8789a Mon Sep 17 00:00:00 2001 -+From: Soenke Lambert <s.lambert@mittwald.de> -+Date: Tue, 12 Nov 2019 10:44:02 +0100 -+Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f] -+ -+This actually fullscreens a window, instead of just hiding the statusbar -+and applying the monocle layout. -+--- -+ config.def.h | 1 + -+ dwm.c | 8 ++++++++ -+ 2 files changed, 9 insertions(+) -+ -+diff --git a/config.def.h b/config.def.h -+index 1c0b587..8cd3204 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -78,6 +78,7 @@ static Key keys[] = { -+ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -+ { MODKEY, XK_space, setlayout, {0} }, -+ { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, -++ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} }, -+ { MODKEY, XK_0, view, {.ui = ~0 } }, -+ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, -+ { MODKEY, XK_comma, focusmon, {.i = -1 } }, -+diff --git a/dwm.c b/dwm.c -+index 4465af1..c1b899a 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg); -+ static void tile(Monitor *); -+ static void togglebar(const Arg *arg); -+ static void togglefloating(const Arg *arg); -++static void togglefullscr(const Arg *arg); -+ static void toggletag(const Arg *arg); -+ static void toggleview(const Arg *arg); -+ static void unfocus(Client *c, int setfocus); -+@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg) -+ arrange(selmon); -+ } -+ -++void -++togglefullscr(const Arg *arg) -++{ -++ if(selmon->sel) -++ setfullscreen(selmon->sel, !selmon->sel->isfullscreen); -++} -++ -+ void -+ toggletag(const Arg *arg) -+ { -+-- -+2.17.1 -+ -diff --git a/patches/dwm-attachbelow-toggleable-6.2.diff b/patches/dwm-attachbelow-toggleable-6.2.diff -new file mode 100644 -index 0000000..e5ff9fd ---- /dev/null -+++ b/patches/dwm-attachbelow-toggleable-6.2.diff -@@ -0,0 +1,199 @@ -+From ee036687ed9e1bb973b9e34694a57cf5dd67652d Mon Sep 17 00:00:00 2001 -+From: Jonathan Hodgson <git@jonathanh.co.uk> -+Date: Mon, 6 May 2019 18:34:40 +0100 -+Subject: [PATCH 1/4] Adds attach below option -+ -+--- -+ config.def.h | 1 + -+ dwm.c | 31 ++++++++++++++++++++++++++++--- -+ 2 files changed, 29 insertions(+), 3 deletions(-) -+ -+diff --git a/config.def.h b/config.def.h -+index 1c0b587..51ad933 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -35,6 +35,7 @@ static const Rule rules[] = { -+ 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 attachbelow = 1; /* 1 means attach at the end */ -+ -+ static const Layout layouts[] = { -+ /* symbol arrange function */ -+diff --git a/dwm.c b/dwm.c -+index 4465af1..bd715a2 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 attachBelow(Client *c); -+ static void attachstack(Client *c); -+ static void buttonpress(XEvent *e); -+ static void checkotherwm(void); -+@@ -405,6 +406,21 @@ attach(Client *c) -+ c->next = c->mon->clients; -+ c->mon->clients = c; -+ } -++void -++attachBelow(Client *c) -++{ -++ //If there is nothing on the monitor or the selected client is floating, attach as normal -++ if(c->mon->sel == NULL || c->mon->sel->isfloating) { -++ attach(c); -++ return; -++ } -++ -++ //Set the new client's next property to the same as the currently selected clients next -++ c->next = c->mon->sel->next; -++ //Set the currently selected clients next property to the new client -++ c->mon->sel->next = c; -++ -++} -+ -+ void -+ attachstack(Client *c) -+@@ -1062,7 +1078,10 @@ manage(Window w, XWindowAttributes *wa) -+ c->isfloating = c->oldstate = trans != None || c->isfixed; -+ if (c->isfloating) -+ XRaiseWindow(dpy, c->win); -+- attach(c); -++ if( attachbelow ) -++ attachBelow(c); -++ else -++ attach(c); -+ attachstack(c); -+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, -+ (unsigned char *) &(c->win), 1); -+@@ -1417,7 +1436,10 @@ sendmon(Client *c, Monitor *m) -+ detachstack(c); -+ c->mon = m; -+ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -+- attach(c); -++ if( attachbelow ) -++ attachBelow(c); -++ else -++ attach(c); -+ attachstack(c); -+ focus(NULL); -+ arrange(NULL); -+@@ -1897,7 +1919,10 @@ updategeom(void) -+ m->clients = c->next; -+ detachstack(c); -+ c->mon = mons; -+- attach(c); -++ if( attachbelow ) -++ attachBelow(c); -++ else -++ attach(c); -+ attachstack(c); -+ } -+ if (m == selmon) -+-- -+2.21.0 -+ -+ -+From e212c1d8cbdcc56c33c717131dfa7c1689e27e9f Mon Sep 17 00:00:00 2001 -+From: Jonathan Hodgson <git@jonathanh.co.uk> -+Date: Mon, 6 May 2019 19:27:57 +0100 -+Subject: [PATCH 2/4] fixes comment -+ -+--- -+ config.def.h | 2 +- -+ 1 file changed, 1 insertion(+), 1 deletion(-) -+ -+diff --git a/config.def.h b/config.def.h -+index 51ad933..cb8053a 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -35,7 +35,7 @@ static const Rule rules[] = { -+ 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 attachbelow = 1; /* 1 means attach at the end */ -++static const int attachbelow = 1; /* 1 means attach after the currently active window */ -+ -+ static const Layout layouts[] = { -+ /* symbol arrange function */ -+-- -+2.21.0 -+ -+ -+From 7568ea3f8756e7e82b30c4943556ae646a445d1c Mon Sep 17 00:00:00 2001 -+From: Jonathan Hodgson <git@jonathanh.co.uk> -+Date: Mon, 6 May 2019 20:00:30 +0100 -+Subject: [PATCH 3/4] Makes changes to man page to reflect attach below patch -+ -+--- -+ dwm.1 | 3 +++ -+ 1 file changed, 3 insertions(+) -+ -+diff --git a/dwm.1 b/dwm.1 -+index 13b3729..fb6e76c 100644 -+--- a/dwm.1 -++++ b/dwm.1 -+@@ -29,6 +29,9 @@ 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 -++The attach below patch makes newly spawned windows attach after the currently -++selected window -++.P -+ dwm draws a small border around windows to indicate the focus state. -+ .SH OPTIONS -+ .TP -+-- -+2.21.0 -+ -+ -+From 362b95a5b9f91673f27f3e3343b5738df3c9d6e9 Mon Sep 17 00:00:00 2001 -+From: Jonathan Hodgson <git@jonathanh.co.uk> -+Date: Sun, 2 Jun 2019 15:11:57 +0100 -+Subject: [PATCH 4/4] Allows attach below to be toggled -+ -+--- -+ config.def.h | 2 +- -+ dwm.c | 6 ++++++ -+ 2 files changed, 7 insertions(+), 1 deletion(-) -+ -+diff --git a/config.def.h b/config.def.h -+index cb8053a..b4d35aa 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -35,7 +35,7 @@ static const Rule rules[] = { -+ 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 attachbelow = 1; /* 1 means attach after the currently active window */ -++static int attachbelow = 1; /* 1 means attach after the currently active window */ -+ -+ static const Layout layouts[] = { -+ /* symbol arrange function */ -+diff --git a/dwm.c b/dwm.c -+index bd715a2..5d88653 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -148,6 +148,7 @@ static void arrange(Monitor *m); -+ static void arrangemon(Monitor *m); -+ static void attach(Client *c); -+ static void attachBelow(Client *c); -++static void toggleAttachBelow(); -+ static void attachstack(Client *c); -+ static void buttonpress(XEvent *e); -+ static void checkotherwm(void); -+@@ -422,6 +423,11 @@ attachBelow(Client *c) -+ -+ } -+ -++void toggleAttachBelow() -++{ -++ attachbelow = !attachbelow; -++} -++ -+ void -+ attachstack(Client *c) -+ { -+-- -+2.21.0 -+ -diff --git a/patches/dwm-autostart-20161205-bb3bd6f.diff b/patches/dwm-autostart-20161205-bb3bd6f.diff -new file mode 100644 -index 0000000..6f11eaf ---- /dev/null -+++ b/patches/dwm-autostart-20161205-bb3bd6f.diff -@@ -0,0 +1,39 @@ -+commit 5918623c5bd7fda155bf9dc3d33890c4ae1722d0 -+Author: Simon Bremer <simon.bremer@tum.de> -+Date: Thu Dec 22 17:31:07 2016 +0100 -+ -+ Applied and fixed autostart patch for previous version; -+ -+diff --git a/dwm.c b/dwm.c -+index d27cb67..066ed71 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -194,6 +194,7 @@ static void resizeclient(Client *c, int x, int y, int w, int h); -+ static void resizemouse(const Arg *arg); -+ static void restack(Monitor *m); -+ static void run(void); -++static void runAutostart(void); -+ static void scan(void); -+ static int sendevent(Client *c, Atom proto); -+ static void sendmon(Client *c, Monitor *m); -+@@ -1386,6 +1387,12 @@ run(void) -+ } -+ -+ void -++runAutostart(void) { -++ system("cd ~/.dwm; ./autostart_blocking.sh"); -++ system("cd ~/.dwm; ./autostart.sh &"); -++} -++ -++void -+ scan(void) -+ { -+ unsigned int i, num; -+@@ -2145,6 +2152,7 @@ main(int argc, char *argv[]) -+ checkotherwm(); -+ setup(); -+ scan(); -++ runAutostart(); -+ run(); -+ cleanup(); -+ XCloseDisplay(dpy); -diff --git a/patches/dwm-cfacts-20200913-61bb8b2.diff b/patches/dwm-cfacts-20200913-61bb8b2.diff -new file mode 100644 -index 0000000..bb70e13 ---- /dev/null -+++ b/patches/dwm-cfacts-20200913-61bb8b2.diff -@@ -0,0 +1,117 @@ -+From c32a879432573d71dec7fcb4bf68927d2f4cdf10 Mon Sep 17 00:00:00 2001 -+From: iofq <cjriddz@protonmail.com> -+Date: Sat, 12 Sep 2020 22:28:09 -0500 -+Subject: [PATCH] Fixed 'cfacts' patch failure due to upstream commit -+ 'f09418bbb...' -+ -+--- -+ config.def.h | 3 +++ -+ dwm.c | 34 +++++++++++++++++++++++++++++++--- -+ 2 files changed, 34 insertions(+), 3 deletions(-) -+ -+diff --git a/config.def.h b/config.def.h -+index 1c0b587..83910c1 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -70,6 +70,9 @@ 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_h, setcfact, {.f = +0.25} }, -++ { MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} }, -++ { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} }, -+ { MODKEY, XK_Return, zoom, {0} }, -+ { MODKEY, XK_Tab, view, {0} }, -+ { MODKEY|ShiftMask, XK_c, killclient, {0} }, -+diff --git a/dwm.c b/dwm.c -+index 664c527..5233229 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -87,6 +87,7 @@ typedef struct Client Client; -+ struct Client { -+ char name[256]; -+ float mina, maxa; -++ float cfact; -+ int x, y, w, h; -+ int oldx, oldy, oldw, oldh; -+ int basew, baseh, incw, inch, maxw, maxh, minw, minh; -+@@ -201,6 +202,7 @@ static void setclientstate(Client *c, long state); -+ static void setfocus(Client *c); -+ static void setfullscreen(Client *c, int fullscreen); -+ static void setlayout(const Arg *arg); -++static void setcfact(const Arg *arg); -+ static void setmfact(const Arg *arg); -+ static void setup(void); -+ static void seturgent(Client *c, int urg); -+@@ -1030,6 +1032,7 @@ manage(Window w, XWindowAttributes *wa) -+ c->w = c->oldw = wa->width; -+ c->h = c->oldh = wa->height; -+ c->oldbw = wa->border_width; -++ c->cfact = 1.0; -+ -+ updatetitle(c); -+ if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { -+@@ -1512,6 +1515,23 @@ setlayout(const Arg *arg) -+ drawbar(selmon); -+ } -+ -++void setcfact(const Arg *arg) { -++ float f; -++ Client *c; -++ -++ c = selmon->sel; -++ -++ if(!arg || !c || !selmon->lt[selmon->sellt]->arrange) -++ return; -++ f = arg->f + c->cfact; -++ if(arg->f == 0.0) -++ f = 1.0; -++ else if(f < 0.25 || f > 4.0) -++ return; -++ c->cfact = f; -++ arrange(selmon); -++} -++ -+ /* arg > 1.0 will set mfact absolutely */ -+ void -+ setmfact(const Arg *arg) -+@@ -1675,9 +1695,15 @@ void -+ tile(Monitor *m) -+ { -+ unsigned int i, n, h, mw, my, ty; -++ float mfacts = 0, sfacts = 0; -+ Client *c; -+ -+- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { -++ if (n < m->nmaster) -++ mfacts += c->cfact; -++ else -++ sfacts += c->cfact; -++ } -+ if (n == 0) -+ return; -+ -+@@ -1687,15 +1713,17 @@ tile(Monitor *m) -+ mw = m->ww; -+ for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -+ if (i < m->nmaster) { -+- h = (m->wh - my) / (MIN(n, m->nmaster) - i); -++ h = (m->wh - my) * (c->cfact / mfacts); -+ resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -+ if (my + HEIGHT(c) < m->wh) -+ my += HEIGHT(c); -++ mfacts -= c->cfact; -+ } else { -+- h = (m->wh - ty) / (n - i); -++ h = (m->wh - ty) * (c->cfact / sfacts); -+ resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); -+ if (ty + HEIGHT(c) < m->wh) -+ ty += HEIGHT(c); -++ sfacts -= c->cfact; -+ } -+ } -+ -+-- -+2.28.0 -+ -diff --git a/patches/dwm-clientindicators-6.2.diff b/patches/dwm-clientindicators-6.2.diff -new file mode 100644 -index 0000000..f2e9afb ---- /dev/null -+++ b/patches/dwm-clientindicators-6.2.diff -@@ -0,0 +1,48 @@ -+From 8c72f9ea7c9cd8d254b52a4f7059113c41483597 Mon Sep 17 00:00:00 2001 -+From: Miles Alan <m@milesalan.com> -+Date: Mon, 17 Aug 2020 20:33:45 -0500 -+Subject: [PATCH] Draws a dot indicator overlayed on each tag icon for each -+ client. The selected client is drawn as a larger horizontal line. -+ -+--- -+ dwm.c | 14 ++++++++++---- -+ 1 file changed, 10 insertions(+), 4 deletions(-) -+ -+diff --git a/dwm.c b/dwm.c -+index 4465af1..e0ca438 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -695,6 +695,7 @@ dirtomon(int dir) -+ void -+ drawbar(Monitor *m) -+ { -++ int indn; -+ int x, w, sw = 0; -+ int boxs = drw->fonts->h / 9; -+ int boxw = drw->fonts->h / 6 + 2; -+@@ -715,13 +716,18 @@ drawbar(Monitor *m) -+ } -+ x = 0; -+ for (i = 0; i < LENGTH(tags); i++) { -++ indn = 0; -+ 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); -++ -++ for (c = m->clients; c; c = c->next) { -++ if (c->tags & (1 << i)) { -++ drw_rect(drw, x, 1 + (indn * 2), selmon->sel == c ? 6 : 1, 1, 1, urg & 1 << i); -++ indn++; -++ } -++ } -++ -+ x += w; -+ } -+ w = blw = TEXTW(m->ltsymbol); -+-- -+2.25.4 -+ -diff --git a/patches/dwm-dwmc-6.2.diff b/patches/dwm-dwmc-6.2.diff -new file mode 100644 -index 0000000..bf606d5 ---- /dev/null -+++ b/patches/dwm-dwmc-6.2.diff -@@ -0,0 +1,240 @@ -+From d94cb6f1a553d19127f44dbdc96e8bb5041956c2 Mon Sep 17 00:00:00 2001 -+From: Nihal Jere <noocsharp@gmail.com> -+Date: Sat, 21 Mar 2020 15:16:49 -0500 -+Subject: [PATCH] dwm-client -+ -+--- -+ Makefile | 2 +- -+ config.def.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ -+ dwm.c | 55 +++++++++++++++++++++++++++++++++++++++-- -+ dwmc | 40 ++++++++++++++++++++++++++++++ -+ 4 files changed, 164 insertions(+), 3 deletions(-) -+ create mode 100755 dwmc -+ -+diff --git a/Makefile b/Makefile -+index 77bcbc0..f837f5c 100644 -+--- a/Makefile -++++ b/Makefile -+@@ -38,7 +38,7 @@ dist: clean -+ -+ install: all -+ mkdir -p ${DESTDIR}${PREFIX}/bin -+- cp -f dwm ${DESTDIR}${PREFIX}/bin -++ cp -f dwm dwmc ${DESTDIR}${PREFIX}/bin -+ chmod 755 ${DESTDIR}${PREFIX}/bin/dwm -+ mkdir -p ${DESTDIR}${MANPREFIX}/man1 -+ sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 -+diff --git a/config.def.h b/config.def.h -+index 1c0b587..efbae79 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -113,3 +113,73 @@ static Button buttons[] = { -+ { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ }; -+ -++void -++setlayoutex(const Arg *arg) -++{ -++ setlayout(&((Arg) { .v = &layouts[arg->i] })); -++} -++ -++void -++viewex(const Arg *arg) -++{ -++ view(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++viewall(const Arg *arg) -++{ -++ view(&((Arg){.ui = ~0})); -++} -++ -++void -++toggleviewex(const Arg *arg) -++{ -++ toggleview(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++tagex(const Arg *arg) -++{ -++ tag(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++toggletagex(const Arg *arg) -++{ -++ toggletag(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++tagall(const Arg *arg) -++{ -++ tag(&((Arg){.ui = ~0})); -++} -++ -++/* signal definitions */ -++/* signum must be greater than 0 */ -++/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */ -++static Signal signals[] = { -++ /* signum function */ -++ { "focusstack", focusstack }, -++ { "setmfact", setmfact }, -++ { "togglebar", togglebar }, -++ { "incnmaster", incnmaster }, -++ { "togglefloating", togglefloating }, -++ { "focusmon", focusmon }, -++ { "tagmon", tagmon }, -++ { "zoom", zoom }, -++ { "view", view }, -++ { "viewall", viewall }, -++ { "viewex", viewex }, -++ { "toggleview", view }, -++ { "toggleviewex", toggleviewex }, -++ { "tag", tag }, -++ { "tagall", tagall }, -++ { "tagex", tagex }, -++ { "toggletag", tag }, -++ { "toggletagex", toggletagex }, -++ { "killclient", killclient }, -++ { "quit", quit }, -++ { "setlayout", setlayout }, -++ { "setlayoutex", setlayoutex }, -++}; -+diff --git a/dwm.c b/dwm.c -+index 4465af1..aa53706 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -106,6 +106,11 @@ typedef struct { -+ const Arg arg; -+ } Key; -+ -++typedef struct { -++ const char * sig; -++ void (*func)(const Arg *); -++} Signal; -++ -+ typedef struct { -+ const char *symbol; -+ void (*arrange)(Monitor *); -+@@ -148,6 +153,7 @@ static void arrange(Monitor *m); -+ static void arrangemon(Monitor *m); -+ static void attach(Client *c); -+ static void attachstack(Client *c); -++static int fake_signal(void); -+ static void buttonpress(XEvent *e); -+ static void checkotherwm(void); -+ static void cleanup(void); -+@@ -998,6 +1004,49 @@ keypress(XEvent *e) -+ keys[i].func(&(keys[i].arg)); -+ } -+ -++int -++fake_signal(void) -++{ -++ char fsignal[256]; -++ char indicator[9] = "fsignal:"; -++ char str_sig[50]; -++ char param[16]; -++ int i, len_str_sig, n, paramn; -++ size_t len_fsignal, len_indicator = strlen(indicator); -++ Arg arg; -++ -++ // Get root name property -++ if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) { -++ len_fsignal = strlen(fsignal); -++ -++ // Check if this is indeed a fake signal -++ if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) { -++ paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n); -++ -++ if (paramn == 1) arg = (Arg) {0}; -++ else if (paramn > 2) return 1; -++ else if (strncmp(param, "i", n - len_str_sig) == 0) -++ sscanf(fsignal + len_indicator + n, "%i", &(arg.i)); -++ else if (strncmp(param, "ui", n - len_str_sig) == 0) -++ sscanf(fsignal + len_indicator + n, "%u", &(arg.ui)); -++ else if (strncmp(param, "f", n - len_str_sig) == 0) -++ sscanf(fsignal + len_indicator + n, "%f", &(arg.f)); -++ else return 1; -++ -++ // Check if a signal was found, and if so handle it -++ for (i = 0; i < LENGTH(signals); i++) -++ if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func) -++ signals[i].func(&(arg)); -++ -++ // A fake signal was sent -++ return 1; -++ } -++ } -++ -++ // No fake signal was sent, so proceed with update -++ return 0; -++} -++ -+ void -+ killclient(const Arg *arg) -+ { -+@@ -1215,8 +1264,10 @@ propertynotify(XEvent *e) -+ Window trans; -+ XPropertyEvent *ev = &e->xproperty; -+ -+- if ((ev->window == root) && (ev->atom == XA_WM_NAME)) -+- updatestatus(); -++ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) { -++ if (!fake_signal()) -++ updatestatus(); -++ } -+ else if (ev->state == PropertyDelete) -+ return; /* ignore */ -+ else if ((c = wintoclient(ev->window))) { -+diff --git a/dwmc b/dwmc -+new file mode 100755 -+index 0000000..5ff8dbc -+--- /dev/null -++++ b/dwmc -+@@ -0,0 +1,40 @@ -++#!/usr/bin/env sh -++ -++signal() { -++ xsetroot -name "fsignal:$*" -++} -++ -++case $# in -++1) -++ case $1 in -++ setlayout | view | viewall | togglebar | togglefloating | zoom | killclient | quit) -++ signal $1 -++ ;; -++ *) -++ echo "Unknown command or missing one argument." -++ exit 1 -++ ;; -++ esac -++ ;; -++2) -++ case $1 in -++ view) -++ signal $1 ui $2 -++ ;; -++ viewex | toggleviewex | tagex | toggletagex | setlayoutex | focusstack | incnmaster | focusmon | tagmon) -++ signal $1 i $2 -++ ;; -++ setmfact) -++ signal $1 f $2 -++ ;; -++ *) -++ echo "Unknown command or one too many arguments." -++ exit 1 -++ ;; -++ esac -++ ;; -++*) -++ echo "Too many arguments." -++ exit 1 -++ ;; -++esac -+-- -+2.25.1 -+ -diff --git a/patches/dwm-push_no_master-6.2.diff b/patches/dwm-push_no_master-6.2.diff -new file mode 100644 -index 0000000..873e438 ---- /dev/null -+++ b/patches/dwm-push_no_master-6.2.diff -@@ -0,0 +1,70 @@ -+diff --git a/dwm.c b/dwm.c -+index 4465af1..49e63f0 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -185,7 +185,10 @@ static void motionnotify(XEvent *e); -+ static void movemouse(const Arg *arg); -+ static Client *nexttiled(Client *c); -+ static void pop(Client *); -++static Client *prevtiled(Client *c); -+ static void propertynotify(XEvent *e); -++static void pushdown(const Arg *arg); -++static void pushup(const Arg *arg); -+ static void quit(const Arg *arg); -+ static Monitor *recttomon(int x, int y, int w, int h); -+ static void resize(Client *c, int x, int y, int w, int h, int interact); -+@@ -1208,6 +1211,16 @@ pop(Client *c) -+ arrange(c->mon); -+ } -+ -++Client * -++prevtiled(Client *c) { -++ Client *p, *r; -++ -++ for(p = selmon->clients, r = NULL; p && p != c; p = p->next) -++ if(!p->isfloating && ISVISIBLE(p)) -++ r = p; -++ return r; -++} -++ -+ void -+ propertynotify(XEvent *e) -+ { -+@@ -1245,6 +1258,37 @@ propertynotify(XEvent *e) -+ } -+ } -+ -++void -++pushdown(const Arg *arg) { -++ Client *sel = selmon->sel, *c; -++ -++ if(!sel || sel->isfloating || sel == nexttiled(selmon->clients)) -++ return; -++ if((c = nexttiled(sel->next))) { -++ detach(sel); -++ sel->next = c->next; -++ c->next = sel; -++ } -++ focus(sel); -++ arrange(selmon); -++} -++ -++void -++pushup(const Arg *arg) { -++ Client *sel = selmon->sel, *c; -++ -++ if(!sel || sel->isfloating) -++ return; -++ if((c = prevtiled(sel)) && c != nexttiled(selmon->clients)) { -++ detach(sel); -++ sel->next = c; -++ for(c = selmon->clients; c->next != sel->next; c = c->next); -++ c->next = sel; -++ } -++ focus(sel); -++ arrange(selmon); -++} -++ -+ void -+ quit(const Arg *arg) -+ { -diff --git a/patches/dwm-restartsig-20180523-6.2.diff b/patches/dwm-restartsig-20180523-6.2.diff -new file mode 100644 -index 0000000..f1f8680 ---- /dev/null -+++ b/patches/dwm-restartsig-20180523-6.2.diff -@@ -0,0 +1,139 @@ -+From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 -+From: Christopher Drelich <cd@cdrakka.com> -+Date: Wed, 23 May 2018 22:50:38 -0400 -+Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM -+ handlers. -+ -+Modified quit() to restart if it receives arg .i = 1 -+MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that. -+ -+Signal handlers were handled for SIGHUP and SIGTERM. -+If dwm receives these signals it calls quit() with -+arg .i = to 1 or 0, respectively. -+ -+To restart dwm: -+MOD+CTRL+SHIFT+Q -+or -+kill -HUP dwmpid -+ -+To quit dwm cleanly: -+MOD+SHIFT+Q -+or -+kill -TERM dwmpid -+--- -+ config.def.h | 1 + -+ dwm.1 | 10 ++++++++++ -+ dwm.c | 22 ++++++++++++++++++++++ -+ 3 files changed, 33 insertions(+) -+ -+diff --git a/config.def.h b/config.def.h -+index a9ac303..e559429 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -94,6 +94,7 @@ static Key keys[] = { -+ TAGKEYS( XK_8, 7) -+ TAGKEYS( XK_9, 8) -+ { MODKEY|ShiftMask, XK_q, quit, {0} }, -++ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, -+ }; -+ -+ /* button definitions */ -+diff --git a/dwm.1 b/dwm.1 -+index 13b3729..36a331c 100644 -+--- a/dwm.1 -++++ b/dwm.1 -+@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. -+ .TP -+ .B Mod1\-Shift\-q -+ Quit dwm. -++.TP -++.B Mod1\-Control\-Shift\-q -++Restart dwm. -+ .SS Mouse commands -+ .TP -+ .B Mod1\-Button1 -+@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float -+ .SH CUSTOMIZATION -+ dwm is customized by creating a custom config.h and (re)compiling the source -+ code. This keeps it fast, secure and simple. -++.SH SIGNALS -++.TP -++.B SIGHUP - 1 -++Restart the dwm process. -++.TP -++.B SIGTERM - 15 -++Cleanly terminate the dwm process. -+ .SH SEE ALSO -+ .BR dmenu (1), -+ .BR st (1) -+diff --git a/dwm.c b/dwm.c -+index bb95e26..286eecd 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -205,6 +205,8 @@ static void setup(void); -+ static void seturgent(Client *c, int urg); -+ static void showhide(Client *c); -+ static void sigchld(int unused); -++static void sighup(int unused); -++static void sigterm(int unused); -+ static void spawn(const Arg *arg); -+ static void tag(const Arg *arg); -+ static void tagmon(const Arg *arg); -+@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { -+ [UnmapNotify] = unmapnotify -+ }; -+ static Atom wmatom[WMLast], netatom[NetLast]; -++static int restart = 0; -+ static int running = 1; -+ static Cur *cursor[CurLast]; -+ static Clr **scheme; -+@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e) -+ void -+ quit(const Arg *arg) -+ { -++ if(arg->i) restart = 1; -+ running = 0; -+ } -+ -+@@ -1536,6 +1540,9 @@ setup(void) -+ /* clean up any zombies immediately */ -+ sigchld(0); -+ -++ signal(SIGHUP, sighup); -++ signal(SIGTERM, sigterm); -++ -+ /* init screen */ -+ screen = DefaultScreen(dpy); -+ sw = DisplayWidth(dpy, screen); -+@@ -1637,6 +1644,20 @@ sigchld(int unused) -+ } -+ -+ void -++sighup(int unused) -++{ -++ Arg a = {.i = 1}; -++ quit(&a); -++} -++ -++void -++sigterm(int unused) -++{ -++ Arg a = {.i = 0}; -++ quit(&a); -++} -++ -++void -+ spawn(const Arg *arg) -+ { -+ if (arg->v == dmenucmd) -+@@ -2139,6 +2160,7 @@ main(int argc, char *argv[]) -+ setup(); -+ scan(); -+ run(); -++ if(restart) execvp(argv[0], argv); -+ cleanup(); -+ XCloseDisplay(dpy); -+ return EXIT_SUCCESS; -+-- -+2.7.4 -+ -diff --git a/patches/dwm-statuscmd-signal-6.2.diff b/patches/dwm-statuscmd-signal-6.2.diff -new file mode 100644 -index 0000000..97fda1b ---- /dev/null -+++ b/patches/dwm-statuscmd-signal-6.2.diff -@@ -0,0 +1,157 @@ -+diff --git a/config.def.h b/config.def.h -+index 1c0b587..b67825e 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -103,7 +103,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, sigdwmblocks, {.i = 1} }, -++ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} }, -++ { ClkStatusText, 0, Button3, sigdwmblocks, {.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 4465af1..c600131 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); -+@@ -169,6 +170,7 @@ static void focus(Client *c); -+ static void focusin(XEvent *e); -+ static void focusmon(const Arg *arg); -+ static void focusstack(const Arg *arg); -++static int getdwmblockspid(); -+ static int getrootptr(int *x, int *y); -+ static long getstate(Window w); -+ static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -+@@ -205,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 sigdwmblocks(const Arg *arg); -+ static void spawn(const Arg *arg); -+ static void tag(const Arg *arg); -+ static void tagmon(const Arg *arg); -+@@ -237,6 +240,9 @@ static void zoom(const Arg *arg); -+ /* variables */ -+ static const char broken[] = "broken"; -+ static char stext[256]; -++static char rawstext[256]; -++static int dwmblockssig; -++pid_t dwmblockspid = 0; -+ static int screen; -+ static int sw, sh; /* X display screen geometry width, height */ -+ static int bh, blw = 0; /* bar geometry */ -+@@ -439,9 +445,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; -++ dwmblockssig = 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; -++ dwmblockssig = ch; -++ } -++ } -++ } else -+ click = ClkWinTitle; -+ } else if ((c = wintoclient(ev->window))) { -+ focus(c); -+@@ -627,6 +650,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) -+ { -+@@ -871,6 +907,18 @@ getatomprop(Client *c, Atom prop) -+ return atom; -+ } -+ -++int -++getdwmblockspid() -++{ -++ char buf[16]; -++ FILE *fp = popen("pidof -s dwmblocks", "r"); -++ fgets(buf, sizeof(buf), fp); -++ pid_t pid = strtoul(buf, NULL, 10); -++ pclose(fp); -++ dwmblockspid = pid; -++ return pid != 0 ? 0 : -1; -++} -++ -+ int -+ getrootptr(int *x, int *y) -+ { -+@@ -1636,6 +1684,23 @@ sigchld(int unused) -+ while (0 < waitpid(-1, NULL, WNOHANG)); -+ } -+ -++void -++sigdwmblocks(const Arg *arg) -++{ -++ union sigval sv; -++ sv.sival_int = (dwmblockssig << 8) | arg->i; -++ if (!dwmblockspid) -++ if (getdwmblockspid() == -1) -++ return; -++ -++ if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) { -++ if (errno == ESRCH) { -++ if (!getdwmblockspid()) -++ sigqueue(dwmblockspid, SIGUSR1, sv); -++ } -++ } -++} -++ -+ void -+ spawn(const Arg *arg) -+ { -+@@ -1987,8 +2052,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); -+ } -+ -diff --git a/patches/dwm-swallow-20200522-7accbcf.diff b/patches/dwm-swallow-20200522-7accbcf.diff -new file mode 100644 -index 0000000..1cb144f ---- /dev/null -+++ b/patches/dwm-swallow-20200522-7accbcf.diff -@@ -0,0 +1,420 @@ -+From 7accbcf7db35995d4c26c5cd69338aafa6feb89a Mon Sep 17 00:00:00 2001 -+From: wtl <wtl144000@gmail.com> -+Date: Fri, 22 May 2020 22:38:38 +0300 -+Subject: [PATCH] swallow X windows from the terminal -+ -+--- -+ config.def.h | 9 ++- -+ config.mk | 2 +- -+ dwm.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++-- -+ 3 files changed, 220 insertions(+), 9 deletions(-) -+ -+diff --git a/config.def.h b/config.def.h -+index 1c0b587..4c0b25c 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -3,6 +3,7 @@ -+ /* appearance */ -+ static const unsigned int borderpx = 1; /* border pixel of windows */ -+ static const unsigned int snap = 32; /* snap pixel */ -++static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ -+ static const int showbar = 1; /* 0 means no bar */ -+ static const int topbar = 1; /* 0 means bottom bar */ -+ static const char *fonts[] = { "monospace:size=10" }; -+@@ -26,9 +27,11 @@ static const Rule rules[] = { -+ * WM_CLASS(STRING) = instance, class -+ * WM_NAME(STRING) = title -+ */ -+- /* class instance title tags mask isfloating monitor */ -+- { "Gimp", NULL, NULL, 0, 1, -1 }, -+- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, -++ /* class instance title tags mask isfloating isterminal noswallow monitor */ -++ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, -++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, -++ { "st", NULL, NULL, 0, 0, 1, -1, -1 }, -++ { NULL, NULL, "Event Tester", 0, 1, 0, 1, -1 }, /* xev */ -+ }; -+ -+ /* layout(s) */ -+diff --git a/config.mk b/config.mk -+index 7084c33..b77641d 100644 -+--- a/config.mk -++++ b/config.mk -+@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 -+ -+ # includes and libs -+ INCS = -I${X11INC} -I${FREETYPEINC} -+-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res -+ -+ # flags -+ CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -+diff --git a/dwm.c b/dwm.c -+index 9fd0286..1befee4 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -40,6 +40,8 @@ -+ #include <X11/extensions/Xinerama.h> -+ #endif /* XINERAMA */ -+ #include <X11/Xft/Xft.h> -++#include <X11/Xlib-xcb.h> -++#include <xcb/res.h> -+ -+ #include "drw.h" -+ #include "util.h" -+@@ -92,9 +94,11 @@ struct Client { -+ int basew, baseh, incw, inch, maxw, maxh, minw, minh; -+ int bw, oldbw; -+ unsigned int tags; -+- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; -++ pid_t pid; -+ Client *next; -+ Client *snext; -++ Client *swallowing; -+ Monitor *mon; -+ Window win; -+ }; -+@@ -138,6 +142,8 @@ typedef struct { -+ const char *title; -+ unsigned int tags; -+ int isfloating; -++ int isterminal; -++ int noswallow; -+ int monitor; -+ } Rule; -+ -+@@ -235,9 +241,16 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); -+ static int xerrorstart(Display *dpy, XErrorEvent *ee); -+ static void zoom(const Arg *arg); -+ -++static pid_t getparentprocess(pid_t p); -++static int isdescprocess(pid_t p, pid_t c); -++static Client *swallowingclient(Window w); -++static Client *termforwin(const Client *c); -++static pid_t winpid(Window w); -++ -+ /* variables */ -+ static const char broken[] = "broken"; -+ static char stext[256]; -++static int scanner; -+ static int screen; -+ static int sw, sh; /* X display screen geometry width, height */ -+ static int bh, blw = 0; /* bar geometry */ -+@@ -269,6 +282,8 @@ static Drw *drw; -+ static Monitor *mons, *selmon; -+ static Window root, wmcheckwin; -+ -++static xcb_connection_t *xcon; -++ -+ /* configuration, allows nested code to access above variables */ -+ #include "config.h" -+ -+@@ -286,6 +301,7 @@ applyrules(Client *c) -+ XClassHint ch = { NULL, NULL }; -+ -+ /* rule matching */ -++ c->noswallow = -1; -+ c->isfloating = 0; -+ c->tags = 0; -+ XGetClassHint(dpy, c->win, &ch); -+@@ -298,6 +314,8 @@ applyrules(Client *c) -+ && (!r->class || strstr(class, r->class)) -+ && (!r->instance || strstr(instance, r->instance))) -+ { -++ c->isterminal = r->isterminal; -++ c->noswallow = r->noswallow; -+ c->isfloating = r->isfloating; -+ c->tags |= r->tags; -+ for (m = mons; m && m->num != r->monitor; m = m->next); -+@@ -414,6 +432,61 @@ attachstack(Client *c) -+ c->mon->stack = c; -+ } -+ -++void -++swallow(Client *p, Client *c) -++{ -++ Client *s; -++ -++ if (c->noswallow > 0 || c->isterminal) -++ return; -++ if (c->noswallow < 0 && !swallowfloating && c->isfloating) -++ return; -++ -++ detach(c); -++ detachstack(c); -++ -++ setclientstate(c, WithdrawnState); -++ XUnmapWindow(dpy, p->win); -++ -++ p->swallowing = c; -++ c->mon = p->mon; -++ -++ Window w = p->win; -++ p->win = c->win; -++ c->win = w; -++ -++ XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace, -++ (unsigned char *) &(p->win), 1); -++ -++ updatetitle(p); -++ s = scanner ? c : p; -++ XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h); -++ arrange(p->mon); -++ configure(p); -++ updateclientlist(); -++} -++ -++void -++unswallow(Client *c) -++{ -++ c->win = c->swallowing->win; -++ -++ free(c->swallowing); -++ c->swallowing = NULL; -++ -++ XDeleteProperty(dpy, c->win, netatom[NetClientList]); -++ -++ /* unfullscreen the client */ -++ setfullscreen(c, 0); -++ updatetitle(c); -++ arrange(c->mon); -++ XMapWindow(dpy, c->win); -++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); -++ setclientstate(c, NormalState); -++ focus(NULL); -++ arrange(c->mon); -++} -++ -+ void -+ buttonpress(XEvent *e) -+ { -+@@ -653,6 +726,9 @@ destroynotify(XEvent *e) -+ -+ if ((c = wintoclient(ev->window))) -+ unmanage(c, 1); -++ -++ else if ((c = swallowingclient(ev->window))) -++ unmanage(c->swallowing, 1); -+ } -+ -+ void -+@@ -1018,12 +1094,13 @@ killclient(const Arg *arg) -+ void -+ manage(Window w, XWindowAttributes *wa) -+ { -+- Client *c, *t = NULL; -++ Client *c, *t = NULL, *term = NULL; -+ Window trans = None; -+ XWindowChanges wc; -+ -+ c = ecalloc(1, sizeof(Client)); -+ c->win = w; -++ c->pid = winpid(w); -+ /* geometry */ -+ c->x = c->oldx = wa->x; -+ c->y = c->oldy = wa->y; -+@@ -1038,6 +1115,7 @@ manage(Window w, XWindowAttributes *wa) -+ } else { -+ c->mon = selmon; -+ applyrules(c); -++ term = termforwin(c); -+ } -+ -+ if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) -+@@ -1074,6 +1152,8 @@ manage(Window w, XWindowAttributes *wa) -+ c->mon->sel = c; -+ arrange(c->mon); -+ XMapWindow(dpy, c->win); -++ if (term) -++ swallow(term, c); -+ focus(NULL); -+ } -+ -+@@ -1384,7 +1464,9 @@ run(void) -+ void -+ scan(void) -+ { -++ scanner = 1; -+ unsigned int i, num; -++ char swin[256]; -+ Window d1, d2, *wins = NULL; -+ XWindowAttributes wa; -+ -+@@ -1395,6 +1477,8 @@ scan(void) -+ continue; -+ if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) -+ manage(wins[i], &wa); -++ else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin)) -++ manage(wins[i], &wa); -+ } -+ for (i = 0; i < num; i++) { /* now the transients */ -+ if (!XGetWindowAttributes(dpy, wins[i], &wa)) -+@@ -1406,6 +1490,7 @@ scan(void) -+ if (wins) -+ XFree(wins); -+ } -++ scanner = 0; -+ } -+ -+ void -+@@ -1768,6 +1853,20 @@ unmanage(Client *c, int destroyed) -+ Monitor *m = c->mon; -+ XWindowChanges wc; -+ -++ if (c->swallowing) { -++ unswallow(c); -++ return; -++ } -++ -++ Client *s = swallowingclient(c->win); -++ if (s) { -++ free(s->swallowing); -++ s->swallowing = NULL; -++ arrange(m); -++ focus(NULL); -++ return; -++ } -++ -+ detach(c); -+ detachstack(c); -+ if (!destroyed) { -+@@ -1782,9 +1881,12 @@ unmanage(Client *c, int destroyed) -+ XUngrabServer(dpy); -+ } -+ free(c); -+- focus(NULL); -+- updateclientlist(); -+- arrange(m); -++ -++ if (!s) { -++ arrange(m); -++ focus(NULL); -++ updateclientlist(); -++ } -+ } -+ -+ void -+@@ -2047,6 +2149,110 @@ view(const Arg *arg) -+ arrange(selmon); -+ } -+ -++pid_t -++winpid(Window w) -++{ -++ pid_t result = 0; -++ -++ xcb_res_client_id_spec_t spec = {0}; -++ spec.client = w; -++ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; -++ -++ xcb_generic_error_t *e = NULL; -++ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); -++ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); -++ -++ if (!r) -++ return (pid_t)0; -++ -++ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); -++ for (; i.rem; xcb_res_client_id_value_next(&i)) { -++ spec = i.data->spec; -++ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { -++ uint32_t *t = xcb_res_client_id_value_value(i.data); -++ result = *t; -++ break; -++ } -++ } -++ -++ free(r); -++ -++ if (result == (pid_t)-1) -++ result = 0; -++ return result; -++} -++ -++pid_t -++getparentprocess(pid_t p) -++{ -++ unsigned int v = 0; -++ -++#if defined(__linux__) -++ FILE *f; -++ char buf[256]; -++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); -++ -++ if (!(f = fopen(buf, "r"))) -++ return (pid_t)0; -++ -++ if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1) -++ v = (pid_t)0; -++ fclose(f); -++#elif defined(__FreeBSD__) -++ struct kinfo_proc *proc = kinfo_getproc(p); -++ if (!proc) -++ return (pid_t)0; -++ -++ v = proc->ki_ppid; -++ free(proc); -++#endif -++ return (pid_t)v; -++} -++ -++int -++isdescprocess(pid_t p, pid_t c) -++{ -++ while (p != c && c != 0) -++ c = getparentprocess(c); -++ -++ return (int)c; -++} -++ -++Client * -++termforwin(const Client *w) -++{ -++ Client *c; -++ Monitor *m; -++ -++ if (!w->pid || w->isterminal) -++ return NULL; -++ -++ for (m = mons; m; m = m->next) { -++ for (c = m->clients; c; c = c->next) { -++ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) -++ return c; -++ } -++ } -++ -++ return NULL; -++} -++ -++Client * -++swallowingclient(Window w) -++{ -++ Client *c; -++ Monitor *m; -++ -++ for (m = mons; m; m = m->next) { -++ for (c = m->clients; c; c = c->next) { -++ if (c->swallowing && c->swallowing->win == w) -++ return c; -++ } -++ } -++ -++ return NULL; -++} -++ -+ Client * -+ wintoclient(Window w) -+ { -+@@ -2138,6 +2344,8 @@ main(int argc, char *argv[]) -+ fputs("warning: no locale support\n", stderr); -+ if (!(dpy = XOpenDisplay(NULL))) -+ die("dwm: cannot open display"); -++ if (!(xcon = XGetXCBConnection(dpy))) -++ die("dwm: cannot get xcb connection\n"); -+ checkotherwm(); -+ setup(); -+ #ifdef __OpenBSD__ -+-- -+2.26.2 -+ -diff --git a/patches/dwm-systray-6.2.diff b/patches/dwm-systray-6.2.diff -new file mode 100644 -index 0000000..27187ac ---- /dev/null -+++ b/patches/dwm-systray-6.2.diff -@@ -0,0 +1,746 @@ -+From 4001ccae7b1a41bdcb247b0cf095a51af7b68c28 Mon Sep 17 00:00:00 2001 -+From: Igor Gevka <igor.gevka@gmail.com> -+Date: Sun, 16 Feb 2020 15:03:10 -0800 -+Subject: [PATCH] [PATCH] Implements a system tray for dwm. -+ -+Original author: Jan Christoph Ebersbach <jceb@e-jc.de>, inspired by http://code.google.com/p/dwm-plus -+URL: http://dwm.suckless.org/patches/systray -+dwm 6.2 port by Igor Gevka <igor.gevka@gmail.com> -+--- -+ config.def.h | 4 + -+ dwm.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++---- -+ 2 files changed, 382 insertions(+), 26 deletions(-) -+ -+diff --git a/config.def.h b/config.def.h -+index 1c0b587..2d824d1 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -3,6 +3,10 @@ -+ /* appearance */ -+ static const unsigned int borderpx = 1; /* border pixel of 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 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 showbar = 1; /* 0 means no bar */ -+ static const int topbar = 1; /* 0 means bottom bar */ -+ static const char *fonts[] = { "monospace:size=10" }; -+diff --git a/dwm.c b/dwm.c -+index 4465af1..3e361fa 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -57,12 +57,30 @@ -+ #define TAGMASK ((1 << LENGTH(tags)) - 1) -+ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -+ -++#define SYSTEM_TRAY_REQUEST_DOCK 0 -++ -++/* XEMBED messages */ -++#define XEMBED_EMBEDDED_NOTIFY 0 -++#define XEMBED_WINDOW_ACTIVATE 1 -++#define XEMBED_FOCUS_IN 4 -++#define XEMBED_MODALITY_ON 10 -++ -++#define XEMBED_MAPPED (1 << 0) -++#define XEMBED_WINDOW_ACTIVATE 1 -++#define XEMBED_WINDOW_DEACTIVATE 2 -++ -++#define VERSION_MAJOR 0 -++#define VERSION_MINOR 0 -++#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR -++ -+ /* enums */ -+ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -+ enum { SchemeNorm, SchemeSel }; /* color schemes */ -+ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, -++ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, -+ NetWMFullscreen, NetActiveWindow, NetWMWindowType, -+ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -++enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ -+ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -+ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+ ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ -+@@ -141,6 +159,12 @@ typedef struct { -+ int monitor; -+ } Rule; -+ -++typedef struct Systray Systray; -++struct Systray { -++ Window win; -++ Client *icons; -++}; -++ -+ /* function declarations */ -+ static void applyrules(Client *c); -+ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -+@@ -169,8 +193,10 @@ static void focus(Client *c); -+ static void focusin(XEvent *e); -+ static void focusmon(const Arg *arg); -+ 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 unsigned int getsystraywidth(); -+ static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -+ static void grabbuttons(Client *c, int focused); -+ static void grabkeys(void); -+@@ -188,13 +214,16 @@ static void pop(Client *); -+ static void propertynotify(XEvent *e); -+ static void quit(const Arg *arg); -+ static Monitor *recttomon(int x, int y, int w, int h); -++static void removesystrayicon(Client *i); -+ static void resize(Client *c, int x, int y, int w, int h, int interact); -++static void resizebarwin(Monitor *m); -+ static void resizeclient(Client *c, int x, int y, int w, int h); -+ static void resizemouse(const Arg *arg); -++static void resizerequest(XEvent *e); -+ static void restack(Monitor *m); -+ static void run(void); -+ static void scan(void); -+-static int sendevent(Client *c, Atom proto); -++static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); -+ static void sendmon(Client *c, Monitor *m); -+ static void setclientstate(Client *c, long state); -+ static void setfocus(Client *c); -+@@ -206,6 +235,7 @@ static void seturgent(Client *c, int urg); -+ static void showhide(Client *c); -+ static void sigchld(int unused); -+ static void spawn(const Arg *arg); -++static Monitor *systraytomon(Monitor *m); -+ static void tag(const Arg *arg); -+ static void tagmon(const Arg *arg); -+ static void tile(Monitor *); -+@@ -223,18 +253,23 @@ static int updategeom(void); -+ static void updatenumlockmask(void); -+ static void updatesizehints(Client *c); -+ static void updatestatus(void); -++static void updatesystray(void); -++static void updatesystrayicongeom(Client *i, int w, int h); -++static void updatesystrayiconstate(Client *i, XPropertyEvent *ev); -+ static void updatetitle(Client *c); -+ static void updatewindowtype(Client *c); -+ static void updatewmhints(Client *c); -+ static void view(const Arg *arg); -+ static Client *wintoclient(Window w); -+ static Monitor *wintomon(Window w); -++static Client *wintosystrayicon(Window w); -+ static int xerror(Display *dpy, XErrorEvent *ee); -+ static int xerrordummy(Display *dpy, XErrorEvent *ee); -+ static int xerrorstart(Display *dpy, XErrorEvent *ee); -+ static void zoom(const Arg *arg); -+ -+ /* variables */ -++static Systray *systray = NULL; -+ static const char broken[] = "broken"; -+ static char stext[256]; -+ static int screen; -+@@ -257,9 +292,10 @@ static void (*handler[LASTEvent]) (XEvent *) = { -+ [MapRequest] = maprequest, -+ [MotionNotify] = motionnotify, -+ [PropertyNotify] = propertynotify, -++ [ResizeRequest] = resizerequest, -+ [UnmapNotify] = unmapnotify -+ }; -+-static Atom wmatom[WMLast], netatom[NetLast]; -++static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast]; -+ static int running = 1; -+ static Cur *cursor[CurLast]; -+ static Clr **scheme; -+@@ -439,7 +475,7 @@ 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 > selmon->ww - TEXTW(stext) - getsystraywidth()) -+ click = ClkStatusText; -+ else -+ click = ClkWinTitle; -+@@ -482,6 +518,11 @@ cleanup(void) -+ XUngrabKey(dpy, AnyKey, AnyModifier, root); -+ while (mons) -+ cleanupmon(mons); -++ if (showsystray) { -++ XUnmapWindow(dpy, systray->win); -++ XDestroyWindow(dpy, systray->win); -++ free(systray); -++ } -+ for (i = 0; i < CurLast; i++) -+ drw_cur_free(drw, cursor[i]); -+ for (i = 0; i < LENGTH(colors); i++) -+@@ -512,9 +553,57 @@ cleanupmon(Monitor *mon) -+ void -+ clientmessage(XEvent *e) -+ { -++ XWindowAttributes wa; -++ XSetWindowAttributes swa; -+ XClientMessageEvent *cme = &e->xclient; -+ Client *c = wintoclient(cme->window); -+ -++ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) { -++ /* add systray icons */ -++ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) { -++ if (!(c = (Client *)calloc(1, sizeof(Client)))) -++ die("fatal: could not malloc() %u bytes\n", sizeof(Client)); -++ if (!(c->win = cme->data.l[2])) { -++ free(c); -++ return; -++ } -++ c->mon = selmon; -++ c->next = systray->icons; -++ systray->icons = c; -++ if (!XGetWindowAttributes(dpy, c->win, &wa)) { -++ /* use sane defaults */ -++ wa.width = bh; -++ wa.height = bh; -++ wa.border_width = 0; -++ } -++ c->x = c->oldx = c->y = c->oldy = 0; -++ c->w = c->oldw = wa.width; -++ c->h = c->oldh = wa.height; -++ c->oldbw = wa.border_width; -++ c->bw = 0; -++ c->isfloating = True; -++ /* reuse tags field as mapped status */ -++ c->tags = 1; -++ updatesizehints(c); -++ updatesystrayicongeom(c, wa.width, wa.height); -++ XAddToSaveSet(dpy, c->win); -++ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); -++ XReparentWindow(dpy, c->win, systray->win, 0, 0); -++ /* use parents background color */ -++ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -++ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa); -++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -++ /* FIXME not sure if I have to send these events, too */ -++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -++ XSync(dpy, False); -++ resizebarwin(selmon); -++ updatesystray(); -++ setclientstate(c, NormalState); -++ } -++ return; -++ } -+ if (!c) -+ return; -+ if (cme->message_type == netatom[NetWMState]) { -+@@ -567,7 +656,7 @@ configurenotify(XEvent *e) -+ for (c = m->clients; c; c = c->next) -+ if (c->isfullscreen) -+ resizeclient(c, m->mx, m->my, m->mw, m->mh); -+- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -++ resizebarwin(m); -+ } -+ focus(NULL); -+ arrange(NULL); -+@@ -652,6 +741,11 @@ destroynotify(XEvent *e) -+ -+ if ((c = wintoclient(ev->window))) -+ unmanage(c, 1); -++ else if ((c = wintosystrayicon(ev->window))) { -++ removesystrayicon(c); -++ resizebarwin(selmon); -++ updatesystray(); -++ } -+ } -+ -+ void -+@@ -695,19 +789,23 @@ dirtomon(int dir) -+ void -+ drawbar(Monitor *m) -+ { -+- int x, w, sw = 0; -++ int x, w, sw = 0, stw = 0; -+ int boxs = drw->fonts->h / 9; -+ int boxw = drw->fonts->h / 6 + 2; -+ unsigned int i, occ = 0, urg = 0; -+ Client *c; -+ -++ if(showsystray && m == systraytomon(m)) -++ stw = getsystraywidth(); -++ -+ /* 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]); -+- sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -+- drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); -++ sw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding */ -++ drw_text(drw, m->ww - sw - stw, 0, sw, bh, lrpad / 2 - 2, stext, 0); -+ } -+ -++ resizebarwin(m); -+ for (c = m->clients; c; c = c->next) { -+ occ |= c->tags; -+ if (c->isurgent) -+@@ -728,7 +826,7 @@ drawbar(Monitor *m) -+ drw_setscheme(drw, scheme[SchemeNorm]); -+ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); -+ -+- if ((w = m->ww - sw - x) > bh) { -++ if ((w = m->ww - sw - stw - x) > bh) { -+ if (m->sel) { -+ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -+ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -+@@ -739,7 +837,7 @@ drawbar(Monitor *m) -+ drw_rect(drw, x, 0, w, bh, 1, 1); -+ } -+ } -+- drw_map(drw, m->barwin, 0, 0, m->ww, bh); -++ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh); -+ } -+ -+ void -+@@ -776,8 +874,11 @@ expose(XEvent *e) -+ Monitor *m; -+ XExposeEvent *ev = &e->xexpose; -+ -+- if (ev->count == 0 && (m = wintomon(ev->window))) -++ if (ev->count == 0 && (m = wintomon(ev->window))) { -+ drawbar(m); -++ if (m == selmon) -++ updatesystray(); -++ } -+ } -+ -+ void -+@@ -862,10 +963,17 @@ getatomprop(Client *c, Atom prop) -+ unsigned long dl; -+ unsigned char *p = NULL; -+ Atom da, atom = None; -++ /* FIXME getatomprop should return the number of items and a pointer to -++ * the stored data instead of this workaround */ -++ Atom req = XA_ATOM; -++ if (prop == xatom[XembedInfo]) -++ req = xatom[XembedInfo]; -+ -+- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, -++ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, -+ &da, &di, &dl, &dl, &p) == Success && p) { -+ atom = *(Atom *)p; -++ if (da == xatom[XembedInfo] && dl == 2) -++ atom = ((Atom *)p)[1]; -+ XFree(p); -+ } -+ return atom; -+@@ -899,6 +1007,16 @@ getstate(Window w) -+ return result; -+ } -+ -++unsigned int -++getsystraywidth() -++{ -++ unsigned int w = 0; -++ Client *i; -++ if(showsystray) -++ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ; -++ return w ? w + systrayspacing : 1; -++} -++ -+ int -+ gettextprop(Window w, Atom atom, char *text, unsigned int size) -+ { -+@@ -1003,7 +1121,7 @@ killclient(const Arg *arg) -+ { -+ if (!selmon->sel) -+ return; -+- if (!sendevent(selmon->sel, wmatom[WMDelete])) { -++ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) { -+ XGrabServer(dpy); -+ XSetErrorHandler(xerrordummy); -+ XSetCloseDownMode(dpy, DestroyAll); -+@@ -1091,6 +1209,12 @@ maprequest(XEvent *e) -+ { -+ static XWindowAttributes wa; -+ XMapRequestEvent *ev = &e->xmaprequest; -++ Client *i; -++ if ((i = wintosystrayicon(ev->window))) { -++ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION); -++ resizebarwin(selmon); -++ updatesystray(); -++ } -+ -+ if (!XGetWindowAttributes(dpy, ev->window, &wa)) -+ return; -+@@ -1215,6 +1339,16 @@ propertynotify(XEvent *e) -+ Window trans; -+ XPropertyEvent *ev = &e->xproperty; -+ -++ if ((c = wintosystrayicon(ev->window))) { -++ if (ev->atom == XA_WM_NORMAL_HINTS) { -++ updatesizehints(c); -++ updatesystrayicongeom(c, c->w, c->h); -++ } -++ else -++ updatesystrayiconstate(c, ev); -++ resizebarwin(selmon); -++ updatesystray(); -++ } -+ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) -+ updatestatus(); -+ else if (ev->state == PropertyDelete) -+@@ -1265,6 +1399,20 @@ recttomon(int x, int y, int w, int h) -+ return r; -+ } -+ -++void -++removesystrayicon(Client *i) -++{ -++ Client **ii; -++ -++ if (!showsystray || !i) -++ return; -++ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); -++ if (ii) -++ *ii = i->next; -++ free(i); -++} -++ -++ -+ void -+ resize(Client *c, int x, int y, int w, int h, int interact) -+ { -+@@ -1272,6 +1420,14 @@ resize(Client *c, int x, int y, int w, int h, int interact) -+ resizeclient(c, x, y, w, h); -+ } -+ -++void -++resizebarwin(Monitor *m) { -++ unsigned int w = m->ww; -++ if (showsystray && m == systraytomon(m)) -++ w -= getsystraywidth(); -++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); -++} -++ -+ void -+ resizeclient(Client *c, int x, int y, int w, int h) -+ { -+@@ -1344,6 +1500,19 @@ resizemouse(const Arg *arg) -+ } -+ } -+ -++void -++resizerequest(XEvent *e) -++{ -++ XResizeRequestEvent *ev = &e->xresizerequest; -++ Client *i; -++ -++ if ((i = wintosystrayicon(ev->window))) { -++ updatesystrayicongeom(i, ev->width, ev->height); -++ resizebarwin(selmon); -++ updatesystray(); -++ } -++} -++ -+ void -+ restack(Monitor *m) -+ { -+@@ -1433,26 +1602,36 @@ setclientstate(Client *c, long state) -+ } -+ -+ int -+-sendevent(Client *c, Atom proto) -++sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) -+ { -+ int n; -+- Atom *protocols; -++ Atom *protocols, mt; -+ int exists = 0; -+ XEvent ev; -+ -+- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { -+- while (!exists && n--) -+- exists = protocols[n] == proto; -+- XFree(protocols); -++ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) { -++ mt = wmatom[WMProtocols]; -++ if (XGetWMProtocols(dpy, w, &protocols, &n)) { -++ while (!exists && n--) -++ exists = protocols[n] == proto; -++ XFree(protocols); -++ } -++ } -++ else { -++ exists = True; -++ mt = proto; -+ } -+ if (exists) { -+ ev.type = ClientMessage; -+- ev.xclient.window = c->win; -+- ev.xclient.message_type = wmatom[WMProtocols]; -++ ev.xclient.window = w; -++ ev.xclient.message_type = mt; -+ ev.xclient.format = 32; -+- ev.xclient.data.l[0] = proto; -+- ev.xclient.data.l[1] = CurrentTime; -+- XSendEvent(dpy, c->win, False, NoEventMask, &ev); -++ ev.xclient.data.l[0] = d0; -++ ev.xclient.data.l[1] = d1; -++ ev.xclient.data.l[2] = d2; -++ ev.xclient.data.l[3] = d3; -++ ev.xclient.data.l[4] = d4; -++ XSendEvent(dpy, w, False, mask, &ev); -+ } -+ return exists; -+ } -+@@ -1466,7 +1645,7 @@ setfocus(Client *c) -+ XA_WINDOW, 32, PropModeReplace, -+ (unsigned char *) &(c->win), 1); -+ } -+- sendevent(c, wmatom[WMTakeFocus]); -++ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); -+ } -+ -+ void -+@@ -1555,6 +1734,10 @@ setup(void) -+ wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); -+ netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); -+ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); -++ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False); -++ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False); -++ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False); -++ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False); -+ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); -+ netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); -+ netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); -+@@ -1562,6 +1745,9 @@ setup(void) -+ netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); -+ netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); -+ netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); -++ xatom[Manager] = XInternAtom(dpy, "MANAGER", False); -++ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); -++ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); -+ /* init cursors */ -+ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); -+ cursor[CurResize] = drw_cur_create(drw, XC_sizing); -+@@ -1570,6 +1756,8 @@ setup(void) -+ scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); -+ for (i = 0; i < LENGTH(colors); i++) -+ scheme[i] = drw_scm_create(drw, colors[i], 3); -++ /* init system tray */ -++ updatesystray(); -+ /* init bars */ -+ updatebars(); -+ updatestatus(); -+@@ -1701,7 +1889,18 @@ togglebar(const Arg *arg) -+ { -+ selmon->showbar = !selmon->showbar; -+ updatebarpos(selmon); -+- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); -++ resizebarwin(selmon); -++ if (showsystray) { -++ XWindowChanges wc; -++ if (!selmon->showbar) -++ wc.y = -bh; -++ else if (selmon->showbar) { -++ wc.y = 0; -++ if (!selmon->topbar) -++ wc.y = selmon->mh - bh; -++ } -++ XConfigureWindow(dpy, systray->win, CWY, &wc); -++ } -+ arrange(selmon); -+ } -+ -+@@ -1796,11 +1995,18 @@ unmapnotify(XEvent *e) -+ else -+ unmanage(c, 0); -+ } -++ else if ((c = wintosystrayicon(ev->window))) { -++ /* KLUDGE! sometimes icons occasionally unmap their windows, but do -++ * _not_ destroy them. We map those windows back */ -++ XMapRaised(dpy, c->win); -++ updatesystray(); -++ } -+ } -+ -+ void -+ updatebars(void) -+ { -++ unsigned int w; -+ Monitor *m; -+ XSetWindowAttributes wa = { -+ .override_redirect = True, -+@@ -1811,10 +2017,15 @@ updatebars(void) -+ for (m = mons; m; m = m->next) { -+ if (m->barwin) -+ continue; -+- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -++ w = m->ww; -++ if (showsystray && m == systraytomon(m)) -++ w -= getsystraywidth(); -++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); -++ if (showsystray && m == systraytomon(m)) -++ XMapRaised(dpy, systray->win); -+ XMapRaised(dpy, m->barwin); -+ XSetClassHint(dpy, m->barwin, &ch); -+ } -+@@ -1990,6 +2201,121 @@ updatestatus(void) -+ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) -+ strcpy(stext, "dwm-"VERSION); -+ drawbar(selmon); -++ updatesystray(); -++} -++ -++void -++updatesystrayicongeom(Client *i, int w, int h) -++{ -++ if (i) { -++ i->h = bh; -++ if (w == h) -++ i->w = bh; -++ else if (h == bh) -++ i->w = w; -++ else -++ i->w = (int) ((float)bh * ((float)w / (float)h)); -++ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False); -++ /* force icons into the systray dimensions if they don't want to */ -++ if (i->h > bh) { -++ if (i->w == i->h) -++ i->w = bh; -++ else -++ i->w = (int) ((float)bh * ((float)i->w / (float)i->h)); -++ i->h = bh; -++ } -++ } -++} -++ -++void -++updatesystrayiconstate(Client *i, XPropertyEvent *ev) -++{ -++ long flags; -++ int code = 0; -++ -++ if (!showsystray || !i || ev->atom != xatom[XembedInfo] || -++ !(flags = getatomprop(i, xatom[XembedInfo]))) -++ return; -++ -++ if (flags & XEMBED_MAPPED && !i->tags) { -++ i->tags = 1; -++ code = XEMBED_WINDOW_ACTIVATE; -++ XMapRaised(dpy, i->win); -++ setclientstate(i, NormalState); -++ } -++ else if (!(flags & XEMBED_MAPPED) && i->tags) { -++ i->tags = 0; -++ code = XEMBED_WINDOW_DEACTIVATE; -++ XUnmapWindow(dpy, i->win); -++ setclientstate(i, WithdrawnState); -++ } -++ else -++ return; -++ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0, -++ systray->win, XEMBED_EMBEDDED_VERSION); -++} -++ -++void -++updatesystray(void) -++{ -++ XSetWindowAttributes wa; -++ XWindowChanges wc; -++ Client *i; -++ Monitor *m = systraytomon(NULL); -++ unsigned int x = m->mx + m->mw; -++ unsigned int w = 1; -++ -++ if (!showsystray) -++ return; -++ if (!systray) { -++ /* init systray */ -++ if (!(systray = (Systray *)calloc(1, sizeof(Systray)))) -++ die("fatal: could not malloc() %u bytes\n", sizeof(Systray)); -++ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel); -++ wa.event_mask = ButtonPressMask | ExposureMask; -++ wa.override_redirect = True; -++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -++ XSelectInput(dpy, systray->win, SubstructureNotifyMask); -++ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, -++ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1); -++ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa); -++ XMapRaised(dpy, systray->win); -++ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime); -++ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) { -++ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0); -++ XSync(dpy, False); -++ } -++ else { -++ fprintf(stderr, "dwm: unable to obtain system tray.\n"); -++ free(systray); -++ systray = NULL; -++ return; -++ } -++ } -++ for (w = 0, i = systray->icons; i; i = i->next) { -++ /* make sure the background color stays the same */ -++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -++ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa); -++ XMapRaised(dpy, i->win); -++ w += systrayspacing; -++ i->x = w; -++ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h); -++ w += i->w; -++ if (i->mon != m) -++ i->mon = m; -++ } -++ w = w ? w + systrayspacing : 1; -++ x -= w; -++ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh); -++ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh; -++ wc.stack_mode = Above; wc.sibling = m->barwin; -++ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc); -++ XMapWindow(dpy, systray->win); -++ XMapSubwindows(dpy, systray->win); -++ /* redraw background */ -++ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel); -++ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh); -++ XSync(dpy, False); -+ } -+ -+ void -+@@ -2057,6 +2383,16 @@ wintoclient(Window w) -+ return NULL; -+ } -+ -++Client * -++wintosystrayicon(Window w) { -++ Client *i = NULL; -++ -++ if (!showsystray || !w) -++ return i; -++ for (i = systray->icons; i && i->win != w; i = i->next) ; -++ return i; -++} -++ -+ Monitor * -+ wintomon(Window w) -+ { -+@@ -2110,6 +2446,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee) -+ return -1; -+ } -+ -++Monitor * -++systraytomon(Monitor *m) { -++ Monitor *t; -++ int i, n; -++ if(!systraypinning) { -++ if(!m) -++ return selmon; -++ return m == selmon ? m : NULL; -++ } -++ for(n = 1, t = mons; t && t->next; n++, t = t->next) ; -++ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ; -++ if(systraypinningfailfirst && n < systraypinning) -++ return mons; -++ return t; -++} -++ -+ void -+ zoom(const Arg *arg) -+ { -+-- -+2.17.1 -+ -diff --git a/patches/dwm-uselessgap-6.2.diff b/patches/dwm-uselessgap-6.2.diff -new file mode 100644 -index 0000000..d9cacbe ---- /dev/null -+++ b/patches/dwm-uselessgap-6.2.diff -@@ -0,0 +1,81 @@ -+From 58a5ece9406ca6c90dc362617c065e4aac19417f Mon Sep 17 00:00:00 2001 -+From: Cyril Cressent <cyril@cressent.org> -+Date: Wed, 3 Jul 2019 21:33:45 -0700 -+Subject: [PATCH] Port the uselessgap patch to 6.2 -+ -+--- -+ config.def.h | 1 + -+ dwm.c | 36 ++++++++++++++++++++++++++++++------ -+ 2 files changed, 31 insertions(+), 6 deletions(-) -+ -+diff --git a/config.def.h b/config.def.h -+index 1c0b587..b11471d 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 = 6; /* 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 */ -+diff --git a/dwm.c b/dwm.c -+index 4465af1..4545e05 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -52,8 +52,8 @@ -+ #define ISVISIBLE(C) ((C->tags & 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) -+-#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -++#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) -++#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) -+ #define TAGMASK ((1 << LENGTH(tags)) - 1) -+ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -+ -+@@ -1276,12 +1276,36 @@ void -+ resizeclient(Client *c, int x, int y, int w, int h) -+ { -+ XWindowChanges wc; -++ unsigned int n; -++ unsigned int gapoffset; -++ unsigned int gapincr; -++ Client *nbc; -+ -+- c->oldx = c->x; c->x = wc.x = x; -+- 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; -+ wc.border_width = c->bw; -++ -++ /* Get number of clients for the selected monitor */ -++ for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); -++ -++ /* Do nothing if layout is floating */ -++ if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { -++ gapincr = gapoffset = 0; -++ } else { -++ /* Remove border and gap if layout is monocle or only one client */ -++ if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) { -++ gapoffset = 0; -++ gapincr = -2 * borderpx; -++ wc.border_width = 0; -++ } else { -++ gapoffset = gappx; -++ gapincr = 2 * gappx; -++ } -++ } -++ -++ c->oldx = c->x; c->x = wc.x = x + gapoffset; -++ c->oldy = c->y; c->y = wc.y = y + gapoffset; -++ c->oldw = c->w; c->w = wc.width = w - gapincr; -++ c->oldh = c->h; c->h = wc.height = h - gapincr; -++ -+ XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); -+ configure(c); -+ XSync(dpy, False); -+-- -+2.22.0 -+ -diff --git a/patches/dwm-zoomswap-6.2.diff b/patches/dwm-zoomswap-6.2.diff -new file mode 100644 -index 0000000..3c658e6 ---- /dev/null -+++ b/patches/dwm-zoomswap-6.2.diff -@@ -0,0 +1,95 @@ -+From 3867ef5a68e15a4faff377ddbc8371853de4a800 Mon Sep 17 00:00:00 2001 -+From: aleks <aleks.stier@icloud.com> -+Date: Sat, 19 Oct 2019 00:56:21 +0200 -+Subject: [PATCH] Put master to exact position of zoomed client -+ -+The default behaviour when zooming a client is to put the previous -+master on top of the client-stack. This patch puts the master to the -+exact position of the zoomed client in the stack. -+--- -+ dwm.c | 44 ++++++++++++++++++++++++++++++++++++++++---- -+ 1 file changed, 40 insertions(+), 4 deletions(-) -+ -+diff --git a/dwm.c b/dwm.c -+index 4465af1..1719b36 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -165,6 +165,7 @@ static void drawbar(Monitor *m); -+ static void drawbars(void); -+ static void enternotify(XEvent *e); -+ static void expose(XEvent *e); -++static Client *findbefore(Client *c); -+ static void focus(Client *c); -+ static void focusin(XEvent *e); -+ static void focusmon(const Arg *arg); -+@@ -235,6 +236,7 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee); -+ static void zoom(const Arg *arg); -+ -+ /* variables */ -++static Client *prevzoom = NULL; -+ static const char broken[] = "broken"; -+ static char stext[256]; -+ static int screen; -+@@ -780,6 +782,16 @@ expose(XEvent *e) -+ drawbar(m); -+ } -+ -++Client * -++findbefore(Client *c) -++{ -++ Client *tmp; -++ if (c == selmon->clients) -++ return NULL; -++ for (tmp = selmon->clients; tmp && tmp->next != c; tmp = tmp->next); -++ return tmp; -++} -++ -+ void -+ focus(Client *c) -+ { -+@@ -2114,14 +2126,38 @@ void -+ zoom(const Arg *arg) -+ { -+ Client *c = selmon->sel; -++ Client *at = NULL, *cold, *cprevious = NULL; -+ -+ if (!selmon->lt[selmon->sellt]->arrange -+ || (selmon->sel && selmon->sel->isfloating)) -+ return; -+- if (c == nexttiled(selmon->clients)) -+- if (!c || !(c = nexttiled(c->next))) -+- return; -+- pop(c); -++ if (c == nexttiled(selmon->clients)) { -++ at = findbefore(prevzoom); -++ if (at) -++ cprevious = nexttiled(at->next); -++ if (!cprevious || cprevious != prevzoom) { -++ prevzoom = NULL; -++ if (!c || !(c = nexttiled(c->next))) -++ return; -++ } else -++ c = cprevious; -++ } -++ cold = nexttiled(selmon->clients); -++ if (c != cold && !at) -++ at = findbefore(c); -++ detach(c); -++ attach(c); -++ /* swap windows instead of pushing the previous one down */ -++ if (c != cold && at) { -++ prevzoom = cold; -++ if (cold && at != cold) { -++ detach(cold); -++ cold->next = at->next; -++ at->next = cold; -++ } -++ } -++ focus(c); -++ arrange(c->mon); -+ } -+ -+ int -+-- -+2.23.0 -+ -diff --git a/patches/patch.diff b/patches/patch.diff -new file mode 100644 -index 0000000..aa7e708 ---- /dev/null -+++ b/patches/patch.diff -@@ -0,0 +1,9773 @@ -+diff --git a/.gitignore b/.gitignore -+new file mode 100644 -+index 0000000..095e840 -+--- /dev/null -++++ b/.gitignore -+@@ -0,0 +1,2 @@ -++*.o -++dwm -+diff --git a/Makefile b/Makefile -+index 77bcbc0..c6bc24b 100644 -+--- a/Makefile -++++ b/Makefile -+@@ -37,8 +37,9 @@ dist: clean -+ rm -rf dwm-${VERSION} -+ -+ install: all -+- mkdir -p ${DESTDIR}${PREFIX}/bin -+- cp -f dwm ${DESTDIR}${PREFIX}/bin -++ mkdir -p ${DESTDIR}${PREFIX}/bin ${DESTDIR}${XSESSIONPREFIX} -++ cp -f dwm dwmc volsv ${DESTDIR}${PREFIX}/bin -++ cp -f dwm.desktop ${DESTDIR}${XSESSIONPREFIX} -+ chmod 755 ${DESTDIR}${PREFIX}/bin/dwm -+ mkdir -p ${DESTDIR}${MANPREFIX}/man1 -+ sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 -+@@ -46,6 +47,8 @@ install: all -+ -+ uninstall: -+ rm -f ${DESTDIR}${PREFIX}/bin/dwm\ -++ ${DESTDIR}${PREFIX}/bin/dwmc\ -++ ${DESTDIR}${PREFIX}/bin/volsv\ -+ ${DESTDIR}${MANPREFIX}/man1/dwm.1 -+ -+ .PHONY: all options clean dist install uninstall -+diff --git a/config.def.h b/config.def.h -+index 1c0b587..8bfef3e 100644 -+--- a/config.def.h -++++ b/config.def.h -+@@ -2,7 +2,13 @@ -+ -+ /* appearance */ -+ static const unsigned int borderpx = 1; /* border pixel of windows */ -++static const unsigned int gappx = 6; /* 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 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 char *fonts[] = { "monospace:size=10" }; -+@@ -26,15 +32,18 @@ static const Rule rules[] = { -+ * WM_CLASS(STRING) = instance, class -+ * WM_NAME(STRING) = title -+ */ -+- /* class instance title tags mask isfloating monitor */ -+- { "Gimp", NULL, NULL, 0, 1, -1 }, -+- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, -++ /* class instance title tags mask isfloating isterminal noswallow monitor */ -++ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, -++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, -++ { "st", NULL, NULL, 0, 0, 1, -1, -1 }, -++ { NULL, NULL, "Event Tester", 0, 1, 0, 1, -1 }, /* xev */ -+ }; -+ -+ /* 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 int attachbelow = 1; /* 1 means attach after the currently active window */ -+ -+ static const Layout layouts[] = { -+ /* symbol arrange function */ -+@@ -70,6 +79,9 @@ 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_h, setcfact, {.f = +0.25} }, -++ { MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} }, -++ { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} }, -+ { MODKEY, XK_Return, zoom, {0} }, -+ { MODKEY, XK_Tab, view, {0} }, -+ { MODKEY|ShiftMask, XK_c, killclient, {0} }, -+@@ -78,6 +90,7 @@ static Key keys[] = { -+ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -+ { MODKEY, XK_space, setlayout, {0} }, -+ { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, -++ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} }, -+ { MODKEY, XK_0, view, {.ui = ~0 } }, -+ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, -+ { MODKEY, XK_comma, focusmon, {.i = -1 } }, -+@@ -94,6 +107,7 @@ static Key keys[] = { -+ TAGKEYS( XK_8, 7) -+ TAGKEYS( XK_9, 8) -+ { MODKEY|ShiftMask, XK_q, quit, {0} }, -++ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, -+ }; -+ -+ /* button definitions */ -+@@ -103,7 +117,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, sigdwmblocks, {.i = 1} }, -++ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} }, -++ { ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} }, -+ { ClkClientWin, MODKEY, Button1, movemouse, {0} }, -+ { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, -+ { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, -+@@ -113,3 +129,73 @@ static Button buttons[] = { -+ { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -+ }; -+ -++void -++setlayoutex(const Arg *arg) -++{ -++ setlayout(&((Arg) { .v = &layouts[arg->i] })); -++} -++ -++void -++viewex(const Arg *arg) -++{ -++ view(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++viewall(const Arg *arg) -++{ -++ view(&((Arg){.ui = ~0})); -++} -++ -++void -++toggleviewex(const Arg *arg) -++{ -++ toggleview(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++tagex(const Arg *arg) -++{ -++ tag(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++toggletagex(const Arg *arg) -++{ -++ toggletag(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++tagall(const Arg *arg) -++{ -++ tag(&((Arg){.ui = ~0})); -++} -++ -++/* signal definitions */ -++/* signum must be greater than 0 */ -++/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */ -++static Signal signals[] = { -++ /* signum function */ -++ { "focusstack", focusstack }, -++ { "setmfact", setmfact }, -++ { "togglebar", togglebar }, -++ { "incnmaster", incnmaster }, -++ { "togglefloating", togglefloating }, -++ { "focusmon", focusmon }, -++ { "tagmon", tagmon }, -++ { "zoom", zoom }, -++ { "view", view }, -++ { "viewall", viewall }, -++ { "viewex", viewex }, -++ { "toggleview", view }, -++ { "toggleviewex", toggleviewex }, -++ { "tag", tag }, -++ { "tagall", tagall }, -++ { "tagex", tagex }, -++ { "toggletag", tag }, -++ { "toggletagex", toggletagex }, -++ { "killclient", killclient }, -++ { "quit", quit }, -++ { "setlayout", setlayout }, -++ { "setlayoutex", setlayoutex }, -++}; -+diff --git a/config.h b/config.h -+new file mode 100644 -+index 0000000..607e67f -+--- /dev/null -++++ b/config.h -+@@ -0,0 +1,260 @@ -++/* See LICENSE file for copyright and license details. */ -++ -++#include <X11/XF86keysym.h> -++ -++/* appearance */ -++static const unsigned int borderpx = 1; /* border pixel of windows */ -++static const unsigned int gappx = 6; /* gaps between windows */ -++static const unsigned int snap = 32; /* snap pixel */ -++static const int swallowfloating = 0; -++static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ -++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 showbar = 1; /* 0 means no bar */ -++static const int topbar = 1; /* 0 means bottom bar */ -++static const char *fonts[] = { "mononoki Nerd Font:size=9", "JoyPixels:size=9" }; -++static const char dmenufont[] = "mononoki Nerd Font:size=9"; -++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[] = "#750000"; -++static const char *colors[][3] = { -++ /* fg bg border */ -++ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, -++ [SchemeSel] = { col_gray4, col_cyan, col_cyan }, -++}; -++ -++/* tagging */ -++static const char *tags[] = { " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9" }; -++ -++static const Rule rules[] = { -++ /* xprop(1): -++ * WM_CLASS(STRING) = instance, class -++ * WM_NAME(STRING) = title -++ */ -++ /* class instance title tags mask isfloating isterminal noswallow monitor */ -++ { NULL, NULL,"Picture in picture", 511, 1, 0, 0, -1 }, -++ { "ardour-6.2.0",NULL, NULL, 0, 1, 0, 0, -1 }, -++ { "urxvt", NULL, NULL, 0, 0, 1, 0, -1 }, -++ { "URxvt", NULL, NULL, 0, 0, 1, 0, -1 }, -++ { "Ardour-6.2.0",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-256color",NULL, NULL, 0, 0, 1, 1, -1 }, -++ { "st", NULL, NULL, 0, 0, 1, 1, -1 }, -++ { "St", NULL, NULL, 0, 0, 1, 1, -1 }, -++ { "tabbed", NULL, NULL, 0, 0, 1, 0, -1 }, -++ { NULL, NULL, "abduco", 0, 0, 1, 0, -1 }, -++ { "Alacritty", NULL, NULL, 0, 0, 1, 0, -1 }, -++ { "Blueman", NULL, NULL, 0, 1, 0, 0, -1 }, -++ { "QjackCtl", NULL, NULL, 0, 1, 0, 0, -1 }, -++ { "qjackctl", NULL, NULL, 0, 1, 0, 0, -1 }, -++ { "catia.py", NULL, NULL, 0, 1, 0, 0, -1 }, -++ { "Catia", NULL, NULL, 0, 1, 0, 0, -1 }, -++ { NULL, NULL, "Event Tester", 0, 1, 0, 1, -1 }, -++ { "Steam", NULL, NULL, 4, 0, 0, 0, -1 }, -++ { "steam", NULL, NULL, 4, 0, 0, 0, -1 }, -++ { NULL, NULL, "steam", 4, 0, 0, 0, -1 }, -++ { "Lutris", NULL, NULL, 2, 0, 0, 0, -1 }, -++ { "lutris", NULL, NULL, 2, 0, 0, 0, -1 }, -++}; -++ -++/* layout(s) */ -++static const float mfact = 0.50; /* 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 int attachbelow = 1; /* 1 means attach after the currently active window */ -++ -++static const Layout layouts[] = { -++ /* symbol arrange function */ -++ { "[]=", tile }, /* first entry is default */ -++ { "><>", NULL }, /* no layout function means floating behavior */ -++ { "[M]", monocle }, -++}; -++ -++/* key definitions */ -++#define MODKEY Mod1Mask -++#define TAGKEYS(KEY,TAG) \ -++ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ -++ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ -++ { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ -++ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, -++ -++/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -++#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } -++ -++/* commands */ -++static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -++static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -++static const char *passmenu[] = { "passmenu", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -++static const char *termcmd[] = { "tabbed", "-c", "st", "-w", NULL }; -++static const char *mpdtoggle[] = { "playerctl", "--player=mpd,mpv,%any", "play-pause", NULL }; -++static const char *mpdnext[] = { "playerctl", "--player=mpd,mpv,%any", "next", NULL }; -++static const char *mpdprev[] = { "playerctl", "--player=mpd,mpv,%any", "previous", NULL }; -++static const char *plytoggle[] = { "playerctl", "--player=%any,mpd", "play-pause", NULL }; -++static const char *plyfwd[] = { "playerctl", "--player=%any,mpd", "position 5+", NULL }; -++static const char *plybck[] = { "playerctl", "--player=%any,mpd", "position 5-", NULL }; -++static const char *blightup[] = { "light", "-A", "1", NULL }; -++static const char *blightdown[] = { "light", "-U", "1", NULL }; -++static const char *audioup[] = { "volsv", "-i", NULL }; -++static const char *audiodown[] = { "volsv", "-d", NULL }; -++static const char *audiomute[] = { "volsv", "-t", NULL }; -++static const char *micmute[] = { "pamixer", "--source", "1", "-t", NULL }; -++static const char *lockscr[] = { "xscreensaver-command", "-lock", NULL }; -++static const char *xidletog[] = { "xidletog", NULL }; -++static const char *xkillcmd[] = { "xkill", NULL }; -++ -++static Key keys[] = { -++ /* modifier key function argument */ -++ { MODKEY, XK_d, spawn, {.v = dmenucmd } }, -++ { MODKEY, XK_p, spawn, {.v = passmenu } }, -++ { MODKEY, XK_c, spawn, {.v = xidletog } }, -++ { MODKEY, XK_x, spawn, {.v = xkillcmd } }, -++ { MODKEY, XK_Return, spawn, {.v = termcmd } }, -++ { 0, XF86XK_AudioPlay, spawn, {.v = mpdtoggle } }, -++ { 0, XF86XK_AudioNext, spawn, {.v = mpdnext } }, -++ { 0, XF86XK_AudioPrev, spawn, {.v = mpdprev } }, -++ { ShiftMask, XF86XK_AudioPlay, spawn, {.v = plytoggle } }, -++ { ShiftMask, XF86XK_AudioNext, spawn, {.v = plyfwd } }, -++ { ShiftMask, XF86XK_AudioPrev, spawn, {.v = plybck } }, -++ { 0, XF86XK_MonBrightnessUp, spawn, {.v = blightup } }, -++ { 0, XF86XK_MonBrightnessDown, spawn, {.v = blightdown } }, -++ { 0, XF86XK_AudioLowerVolume, spawn, {.v = audiodown } }, -++ { 0, XF86XK_AudioRaiseVolume, spawn, {.v = audioup } }, -++ { 0, XF86XK_AudioMute, spawn, {.v = audiomute } }, -++ { 0, XF86XK_AudioMicMute, spawn, {.v = micmute } }, -++ { Mod4Mask, XK_l, spawn, {.v = lockscr } }, -++ { MODKEY, XK_b, togglebar, {0} }, -++ { MODKEY, XK_j, focusstack, {.i = +1 } }, -++ { MODKEY, XK_k, focusstack, {.i = -1 } }, -++ { MODKEY|ShiftMask, XK_j, pushdown, {.i = +1 } }, -++ { MODKEY|ShiftMask, XK_k, pushup, {.i = -1 } }, -++ { MODKEY|ControlMask, XK_k, setcfact, {.f = +0.25} }, -++ { MODKEY|ControlMask, XK_j, setcfact, {.f = -0.25} }, -++ { MODKEY|ControlMask, XK_o, setcfact, {.f = 0.00} }, -++ { MODKEY|ShiftMask, XK_h, incnmaster, {.i = +1 } }, -++ { MODKEY|ShiftMask, XK_l, incnmaster, {.i = -1 } }, -++ { MODKEY, XK_h, setmfact, {.f = -0.05} }, -++ { MODKEY, XK_l, setmfact, {.f = +0.05} }, -++ { MODKEY|ShiftMask, XK_Return, zoom, {0} }, -++ { MODKEY, XK_Tab, view, {0} }, -++ { MODKEY|ShiftMask, XK_q, killclient, {0} }, -++ { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, -++ { MODKEY, XK_s, setlayout, {.v = &layouts[1]} }, -++ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -++ { MODKEY|ShiftMask, XK_space, setlayout, {-1} }, -++ { MODKEY, XK_space, togglefloating, {0} }, -++ { MODKEY, XK_f, togglefullscr, {0} }, -++ { MODKEY, XK_0, view, {.ui = ~0 } }, -++ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, -++ { MODKEY|ControlMask, XK_comma, focusmon, {.i = -1 } }, -++ { MODKEY|ControlMask, XK_period, focusmon, {.i = +1 } }, -++ { MODKEY|ControlMask|ShiftMask, XK_comma, tagmon, {.i = -1 } }, -++ { MODKEY|ControlMask|ShiftMask, XK_period, tagmon, {.i = +1 } }, -++ TAGKEYS( XK_1, 0) -++ TAGKEYS( XK_2, 1) -++ TAGKEYS( XK_3, 2) -++ TAGKEYS( XK_4, 3) -++ TAGKEYS( XK_5, 4) -++ TAGKEYS( XK_6, 5) -++ TAGKEYS( XK_7, 6) -++ TAGKEYS( XK_8, 7) -++ TAGKEYS( XK_9, 8) -++ { MODKEY|ShiftMask, XK_e, quit, {0} }, -++ { MODKEY|ShiftMask, XK_r, quit, {1} }, -++ { MODKEY|ShiftMask, XK_Tab, toggleAttachBelow, {0} }, -++}; -++ -++/* button definitions */ -++/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -++static Button buttons[] = { -++ /* click event mask button function argument */ -++ { ClkLtSymbol, 0, Button1, setlayout, {0} }, -++ { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, -++ { ClkWinTitle, 0, Button2, zoom, {0} }, -++ { ClkStatusText, 0, Button1, sigdwmblocks, {.i = 1} }, -++ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} }, -++ { ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} }, -++ { 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 -++setlayoutex(const Arg *arg) -++{ -++ setlayout(&((Arg) { .v = &layouts[arg->i] })); -++} -++ -++void -++viewex(const Arg *arg) -++{ -++ view(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++viewall(const Arg *arg) -++{ -++ view(&((Arg){.ui = ~0})); -++} -++ -++void -++toggleviewex(const Arg *arg) -++{ -++ toggleview(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++tagex(const Arg *arg) -++{ -++ tag(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++toggletagex(const Arg *arg) -++{ -++ toggletag(&((Arg) { .ui = 1 << arg->ui })); -++} -++ -++void -++tagall(const Arg *arg) -++{ -++ tag(&((Arg){.ui = ~0})); -++} -++ -++/* signal definitions */ -++/* signum must be greater than 0 */ -++/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */ -++static Signal signals[] = { -++ /* signum function */ -++ { "focusstack", focusstack }, -++ { "setmfact", setmfact }, -++ { "togglebar", togglebar }, -++ { "incnmaster", incnmaster }, -++ { "togglefloating", togglefloating }, -++ { "togglefullscr", togglefullscr }, -++ { "focusmon", focusmon }, -++ { "tagmon", tagmon }, -++ { "zoom", zoom }, -++ { "view", view }, -++ { "viewall", viewall }, -++ { "viewex", viewex }, -++ { "toggleview", view }, -++ { "toggleviewex", toggleviewex }, -++ { "tag", tag }, -++ { "tagall", tagall }, -++ { "tagex", tagex }, -++ { "toggletag", tag }, -++ { "toggletagex", toggletagex }, -++ { "killclient", killclient }, -++ { "quit", quit }, -++ { "setlayout", setlayout }, -++ { "setlayoutex", setlayoutex }, -++}; -++ -+diff --git a/config.mk b/config.mk -+index 7084c33..dbbc526 100644 -+--- a/config.mk -++++ b/config.mk -+@@ -6,6 +6,7 @@ VERSION = 6.2 -+ # paths -+ PREFIX = /usr/local -+ MANPREFIX = ${PREFIX}/share/man -++XSESSIONPREFIX = /usr/share/xsessions -+ -+ X11INC = /usr/X11R6/include -+ X11LIB = /usr/X11R6/lib -+@@ -22,10 +23,10 @@ FREETYPEINC = /usr/include/freetype2 -+ -+ # includes and libs -+ INCS = -I${X11INC} -I${FREETYPEINC} -+-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res -+ -+ # flags -+-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -++CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -+ #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -+ CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -+ LDFLAGS = ${LIBS} -+diff --git a/drw.c b/drw.c -+index 8fd1ca4..4cdbcbe 100644 -+--- a/drw.c -++++ b/drw.c -+@@ -95,6 +95,7 @@ drw_free(Drw *drw) -+ { -+ XFreePixmap(drw->dpy, drw->drawable); -+ XFreeGC(drw->dpy, drw->gc); -++ drw_fontset_free(drw->fonts); -+ free(drw); -+ } -+ -+diff --git a/dwm.1 b/dwm.1 -+index 13b3729..0ec6c60 100644 -+--- a/dwm.1 -++++ b/dwm.1 -+@@ -12,10 +12,11 @@ environment for the application in use and the task performed. -+ 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. -++adjusted from zero to an arbitrary number. Windows in both the master and stack -++can be resized vertically, as well as resizing the master area. 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. -+ .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. -+@@ -24,16 +25,19 @@ 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. -++before the window's title. The selected tags are indicated with a different -++color. The focused window is represented by a long line before the tags which -++are applied to it, and all other windows are represented by dots for all their -++corresponding tags. -++.P -++The attach below patch makes newly spawned windows attach after the currently -++selected window -+ .P -+ dwm draws a small border around windows to indicate the focus state. -+ .SH OPTIONS -+ .TP -+ .B \-v -+-prints version information to standard output, then exits. -++prints version information to stderr, then exits. -+ .SH USAGE -+ .SS Status bar -+ .TP -+@@ -56,41 +60,28 @@ click on a tag label applies that tag to the focused window. -+ click on a tag label adds/removes that tag to/from the focused window. -+ .SS Keyboard commands -+ .TP -+-.B Mod1\-Shift\-Return -++.B Mod1\-Return -+ Start -++.BR tabbed(1) -++Running -+ .BR st(1). -+ .TP -+ .B Mod1\-p -++Spawn passmenu. -++.TP -++.B Mod1\-d -+ Spawn -+ .BR dmenu(1) -+ for launching other programs. -+ .TP -+-.B Mod1\-, -+-Focus previous screen, if any. -+-.TP -+-.B Mod1\-. -+-Focus next screen, if any. -+-.TP -+-.B Mod1\-Shift\-, -+-Send focused window to previous screen, if any. -+-.TP -+-.B Mod1\-Shift\-. -+-Send focused window to next screen, if any. -+-.TP -+ .B Mod1\-b -+ Toggles bar on and off. -+ .TP -+-.B Mod1\-t -+-Sets tiled layout. -++.B Mod1\-Shift\-j -++Push the selected client window down the stack -+ .TP -+-.B Mod1\-f -+-Sets floating layout. -+-.TP -+-.B Mod1\-m -+-Sets monocle layout. -+-.TP -+-.B Mod1\-space -+-Toggles between current and previous layout. -++.B Mod1\-Shift\-k -++Push the selected client window up the stack -+ .TP -+ .B Mod1\-j -+ Focus next window. -+@@ -98,50 +89,91 @@ Focus next window. -+ .B Mod1\-k -+ Focus previous window. -+ .TP -+-.B Mod1\-i -+-Increase number of windows in master area. -++.B Mod1\-, -++Increase the number of master windows. -+ .TP -+-.B Mod1\-d -+-Decrease number of windows in master area. -++.B Mod1\-. -++Decrease the number of master windows. -++.TP -++.B Mod1\-h -++Decrease master area size. -+ .TP -+ .B Mod1\-l -+ Increase master area size. -+ .TP -+-.B Mod1\-h -+-Decrease master area size. -++.B Mod1\-Shift\-h -++Increase the size ratio of the selected client -+ .TP -+-.B Mod1\-Return -++.B Mod1\-Shift\-l -++Decrease the size ratio of the selected client -++.B Mod1\-Shift\-o -++Reset the size ratio of the selected client -++.TP -++.B Mod1\-Shift\-Return -+ Zooms/cycles focused window to/from master area (tiled layouts only). -+ .TP -+-.B Mod1\-Shift\-c -++.B Mod1\-Tab -++Toggles to the previously selected tags. -++.TP -++.B Mod1\-Shift\-q -+ Close focused window. -+ .TP -++.B Mod1\-t -++Sets tiled layout. -++.TP -++.B Mod1\-s -++Sets floating layout. -++.TP -++.B Mod1\-m -++Sets monocle layout. -++.TP -+ .B Mod1\-Shift\-space -+-Toggle focused window between tiled and floating state. -++Toggles between current and previous layout. -+ .TP -+-.B Mod1\-Tab -+-Toggles to the previously selected tags. -++.B Mod1\-space -++Toggles the selected window into the floating state. -+ .TP -+-.B Mod1\-Shift\-[1..n] -+-Apply nth tag to focused window. -++.B Mod1\-f -++Toggle the selected window into the fullscreen state. -++.TP -++.B Mod1\-0 -++View all windows with any tag. -+ .TP -+ .B Mod1\-Shift\-0 -+ Apply all tags to focused window. -+ .TP -++.B Mod1\-Shift\-, -++Change focus to previous screen, if any. -++.TP -++.B Mod1\-Shift\-. -++Change focus to next screen, if any. -++.TP -++.B Mod1\-Control\-Shift\-, -++Send focused window to previous screen, if any. -++.TP -++.B Mod1\-Control\-Shift\-. -++Send focused window to next screen, if any. -++.TP -++.B Mod1\-Shift\-[1..n] -++Apply nth tag to focused window. -++.TP -+ .B Mod1\-Control\-Shift\-[1..n] -+ Add/remove nth tag to/from focused window. -+ .TP -+ .B Mod1\-[1..n] -+ View all windows with nth tag. -+ .TP -+-.B Mod1\-0 -+-View all windows with any tag. -+-.TP -+ .B Mod1\-Control\-[1..n] -+ Add/remove all windows with nth tag to/from the view. -+ .TP -+-.B Mod1\-Shift\-q -++.B Mod1\-Shift\-e -+ Quit dwm. -++.TP -++.B Mod1\-Shift\-r -++Restart dwm. -++.TP -++.B Mod1\-Shift\-Tab -++Toggle AttachBelow patch -+ .SS Mouse commands -+ .TP -+ .B Mod1\-Button1 -+@@ -155,6 +187,41 @@ Resize focused window while dragging. Tiled windows will be toggled to the float -+ .SH CUSTOMIZATION -+ dwm is customized by creating a custom config.h and (re)compiling the source -+ code. This keeps it fast, secure and simple. -++.SH SIGNALS -++.TP -++.B SIGHUP - 1 -++Restart the dwm process. -++.TP -++.B SIGTERM - 15 -++Cleanly terminate the dwm process. -++.SH PATCHES -++This version of dwm was compiled using the: -++.TP -++.B dwm-actualfullscreen-20191112-cb3f58a.diff -++.TP -++.B dwm-attachbelow-toggleable-6.2.diff -++.TP -++.B dwm-autostart-20161205-bb3bd6f.diff -++.TP -++.B dwm-cfacts-20200913-61bb8b2.diff -++.TP -++.B dwm-clientindicators-6.2.diff -++.TP -++.B dwm-dwmc-6.2.diff -++.TP -++.B dwm-push_no_master-6.2.diff -++.TP -++.B dwm-restartsig-20180523-6.2.diff -++.TP -++.B dwm-statuscmd-signal-6.2.diff -++.TP -++.B dwm-swallow-20200522-7accbcf.diff -++.TP -++.B dwm-systray-6.2.diff -++.TP -++.B dwm-uselessgap-6.2.diff -++.TP -++.B dwm-zoomswap-6.2.diff -+ .SH SEE ALSO -+ .BR dmenu (1), -+ .BR st (1) -+diff --git a/dwm.c b/dwm.c -+index 41c6767..cecbe53 100644 -+--- a/dwm.c -++++ b/dwm.c -+@@ -40,6 +40,8 @@ -+ #include <X11/extensions/Xinerama.h> -+ #endif /* XINERAMA */ -+ #include <X11/Xft/Xft.h> -++#include <X11/Xlib-xcb.h> -++#include <xcb/res.h> -+ -+ #include "drw.h" -+ #include "util.h" -+@@ -52,17 +54,35 @@ -+ #define ISVISIBLE(C) ((C->tags & 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) -+-#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -++#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) -++#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) -+ #define TAGMASK ((1 << LENGTH(tags)) - 1) -+ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -+ -++#define SYSTEM_TRAY_REQUEST_DOCK 0 -++ -++/* XEMBED messages */ -++#define XEMBED_EMBEDDED_NOTIFY 0 -++#define XEMBED_WINDOW_ACTIVATE 1 -++#define XEMBED_FOCUS_IN 4 -++#define XEMBED_MODALITY_ON 10 -++ -++#define XEMBED_MAPPED (1 << 0) -++#define XEMBED_WINDOW_ACTIVATE 1 -++#define XEMBED_WINDOW_DEACTIVATE 2 -++ -++#define VERSION_MAJOR 0 -++#define VERSION_MINOR 0 -++#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR -++ -+ /* enums */ -+ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -+ enum { SchemeNorm, SchemeSel }; /* color schemes */ -+ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, -++ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, -+ NetWMFullscreen, NetActiveWindow, NetWMWindowType, -+ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -++enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ -+ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -+ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+ ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ -+@@ -87,14 +107,17 @@ typedef struct Client Client; -+ struct Client { -+ char name[256]; -+ float mina, maxa; -++ float cfact; -+ int x, y, w, h; -+ int oldx, oldy, oldw, oldh; -+ int basew, baseh, incw, inch, maxw, maxh, minw, minh; -+ int bw, oldbw; -+ unsigned int tags; -+- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; -++ pid_t pid; -+ Client *next; -+ Client *snext; -++ Client *swallowing; -+ Monitor *mon; -+ Window win; -+ }; -+@@ -106,6 +129,11 @@ typedef struct { -+ const Arg arg; -+ } Key; -+ -++typedef struct { -++ const char * sig; -++ void (*func)(const Arg *); -++} Signal; -++ -+ typedef struct { -+ const char *symbol; -+ void (*arrange)(Monitor *); -+@@ -138,16 +166,27 @@ typedef struct { -+ const char *title; -+ unsigned int tags; -+ int isfloating; -++ int isterminal; -++ int noswallow; -+ int monitor; -+ } Rule; -+ -++typedef struct Systray Systray; -++struct Systray { -++ Window win; -++ Client *icons; -++}; -++ -+ /* function declarations */ -+ static void applyrules(Client *c); -+ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -+ static void arrange(Monitor *m); -+ static void arrangemon(Monitor *m); -+ static void attach(Client *c); -++static void attachBelow(Client *c); -++static void toggleAttachBelow(); -+ static void attachstack(Client *c); -++static int fake_signal(void); -+ static void buttonpress(XEvent *e); -+ static void checkotherwm(void); -+ static void cleanup(void); -+@@ -156,6 +195,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); -+@@ -165,12 +205,16 @@ static void drawbar(Monitor *m); -+ static void drawbars(void); -+ static void enternotify(XEvent *e); -+ static void expose(XEvent *e); -++static Client *findbefore(Client *c); -+ static void focus(Client *c); -+ static void focusin(XEvent *e); -+ static void focusmon(const Arg *arg); -+ static void focusstack(const Arg *arg); -++static int getdwmblockspid(); -++static Atom getatomprop(Client *c, Atom prop); -+ static int getrootptr(int *x, int *y); -+ static long getstate(Window w); -++static unsigned int getsystraywidth(); -+ static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -+ static void grabbuttons(Client *c, int focused); -+ static void grabkeys(void); -+@@ -184,33 +228,46 @@ static void monocle(Monitor *m); -+ static void motionnotify(XEvent *e); -+ static void movemouse(const Arg *arg); -+ static Client *nexttiled(Client *c); -+-static void pop(Client *); -++//static void pop(Client *); -++static Client *prevtiled(Client *c); -+ static void propertynotify(XEvent *e); -++static void pushdown(const Arg *arg); -++static void pushup(const Arg *arg); -+ static void quit(const Arg *arg); -+ 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); -++static void resizebarwin(Monitor *m); -+ static void resizeclient(Client *c, int x, int y, int w, int h); -+ static void resizemouse(const Arg *arg); -++static void resizerequest(XEvent *e); -+ static void restack(Monitor *m); -+ static void run(void); -++static void runAutostart(void); -+ static void scan(void); -+-static int sendevent(Client *c, Atom proto); -++static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); -+ static void sendmon(Client *c, Monitor *m); -+ static void setclientstate(Client *c, long state); -+ static void setfocus(Client *c); -+ static void setfullscreen(Client *c, int fullscreen); -+ static void setlayout(const Arg *arg); -++static void setcfact(const Arg *arg); -+ static void setmfact(const Arg *arg); -+ static void setup(void); -+ static void seturgent(Client *c, int urg); -+ static void showhide(Client *c); -+ static void sigchld(int unused); -++static void sigdwmblocks(const Arg *arg); -++static void sighup(int unused); -++static void sigterm(int unused); -+ static void spawn(const Arg *arg); -++static Monitor *systraytomon(Monitor *m); -+ static void tag(const Arg *arg); -+ static void tagmon(const Arg *arg); -+ static void tile(Monitor *); -+ static void togglebar(const Arg *arg); -+ static void togglefloating(const Arg *arg); -++static void togglefullscr(const Arg *arg); -+ static void toggletag(const Arg *arg); -+ static void toggleview(const Arg *arg); -+ static void unfocus(Client *c, int setfocus); -+@@ -223,20 +280,36 @@ static int updategeom(void); -+ static void updatenumlockmask(void); -+ static void updatesizehints(Client *c); -+ static void updatestatus(void); -++static void updatesystray(void); -++static void updatesystrayicongeom(Client *i, int w, int h); -++static void updatesystrayiconstate(Client *i, XPropertyEvent *ev); -+ static void updatetitle(Client *c); -+ static void updatewindowtype(Client *c); -+ static void updatewmhints(Client *c); -+ static void view(const Arg *arg); -+ static Client *wintoclient(Window w); -+ static Monitor *wintomon(Window w); -++static Client *wintosystrayicon(Window w); -+ static int xerror(Display *dpy, XErrorEvent *ee); -+ static int xerrordummy(Display *dpy, XErrorEvent *ee); -+ static int xerrorstart(Display *dpy, XErrorEvent *ee); -+ static void zoom(const Arg *arg); -+ -++static pid_t getparentprocess(pid_t p); -++static int isdescprocess(pid_t p, pid_t c); -++static Client *swallowingclient(Window w); -++static Client *termforwin(const Client *c); -++static pid_t winpid(Window w); -++ -+ /* variables */ -++static Client *prevzoom = NULL; -++static Systray *systray = NULL; -+ static const char broken[] = "broken"; -+ static char stext[256]; -++static char rawstext[256]; -++static int dwmblockssig; -++pid_t dwmblockspid = 0; -++static int scanner; -+ static int screen; -+ static int sw, sh; /* X display screen geometry width, height */ -+ static int bh, blw = 0; /* bar geometry */ -+@@ -257,9 +330,11 @@ static void (*handler[LASTEvent]) (XEvent *) = { -+ [MapRequest] = maprequest, -+ [MotionNotify] = motionnotify, -+ [PropertyNotify] = propertynotify, -++ [ResizeRequest] = resizerequest, -+ [UnmapNotify] = unmapnotify -+ }; -+-static Atom wmatom[WMLast], netatom[NetLast]; -++static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast]; -++static int restart = 0; -+ static int running = 1; -+ static Cur *cursor[CurLast]; -+ static Clr **scheme; -+@@ -268,6 +343,8 @@ static Drw *drw; -+ static Monitor *mons, *selmon; -+ static Window root, wmcheckwin; -+ -++static xcb_connection_t *xcon; -++ -+ /* configuration, allows nested code to access above variables */ -+ #include "config.h" -+ -+@@ -285,6 +362,7 @@ applyrules(Client *c) -+ XClassHint ch = { NULL, NULL }; -+ -+ /* rule matching */ -++ c->noswallow = -1; -+ c->isfloating = 0; -+ c->tags = 0; -+ XGetClassHint(dpy, c->win, &ch); -+@@ -297,6 +375,8 @@ applyrules(Client *c) -+ && (!r->class || strstr(class, r->class)) -+ && (!r->instance || strstr(instance, r->instance))) -+ { -++ c->isterminal = r->isterminal; -++ c->noswallow = r->noswallow; -+ c->isfloating = r->isfloating; -+ c->tags |= r->tags; -+ for (m = mons; m && m->num != r->monitor; m = m->next); -+@@ -405,6 +485,26 @@ attach(Client *c) -+ c->next = c->mon->clients; -+ c->mon->clients = c; -+ } -++void -++attachBelow(Client *c) -++{ -++ //If there is nothing on the monitor or the selected client is floating, attach as normal -++ if(c->mon->sel == NULL || c->mon->sel->isfloating) { -++ attach(c); -++ return; -++ } -++ -++ //Set the new client's next property to the same as the currently selected clients next -++ c->next = c->mon->sel->next; -++ //Set the currently selected clients next property to the new client -++ c->mon->sel->next = c; -++ -++} -++ -++void toggleAttachBelow() -++{ -++ attachbelow = !attachbelow; -++} -+ -+ void -+ attachstack(Client *c) -+@@ -413,6 +513,61 @@ attachstack(Client *c) -+ c->mon->stack = c; -+ } -+ -++void -++swallow(Client *p, Client *c) -++{ -++ Client *s; -++ -++ if (c->noswallow > 0 || c->isterminal) -++ return; -++ if (c->noswallow < 0 && !swallowfloating && c->isfloating) -++ return; -++ -++ detach(c); -++ detachstack(c); -++ -++ setclientstate(c, WithdrawnState); -++ XUnmapWindow(dpy, p->win); -++ -++ p->swallowing = c; -++ c->mon = p->mon; -++ -++ Window w = p->win; -++ p->win = c->win; -++ c->win = w; -++ -++ XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace, -++ (unsigned char *) &(p->win), 1); -++ -++ updatetitle(p); -++ s = scanner ? c : p; -++ XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h); -++ arrange(p->mon); -++ configure(p); -++ updateclientlist(); -++} -++ -++void -++unswallow(Client *c) -++{ -++ c->win = c->swallowing->win; -++ -++ free(c->swallowing); -++ c->swallowing = NULL; -++ -++ XDeleteProperty(dpy, c->win, netatom[NetClientList]); -++ -++ /* unfullscreen the client */ -++ setfullscreen(c, 0); -++ updatetitle(c); -++ arrange(c->mon); -++ XMapWindow(dpy, c->win); -++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); -++ setclientstate(c, NormalState); -++ focus(NULL); -++ arrange(c->mon); -++} -++ -+ void -+ buttonpress(XEvent *e) -+ { -+@@ -439,9 +594,25 @@ 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 - (int)TEXTW(stext) + lrpad - getsystraywidth())) { -+ click = ClkStatusText; -+- else -++ char *text = rawstext; -++ int i = -1; -++ char ch; -++ dwmblockssig = 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; -++ dwmblockssig = ch; -++ } -++ } -++ } else -+ click = ClkWinTitle; -+ } else if ((c = wintoclient(ev->window))) { -+ focus(c); -+@@ -482,6 +653,11 @@ cleanup(void) -+ XUngrabKey(dpy, AnyKey, AnyModifier, root); -+ while (mons) -+ cleanupmon(mons); -++ if (showsystray) { -++ XUnmapWindow(dpy, systray->win); -++ XDestroyWindow(dpy, systray->win); -++ free(systray); -++ } -+ for (i = 0; i < CurLast; i++) -+ drw_cur_free(drw, cursor[i]); -+ for (i = 0; i < LENGTH(colors); i++) -+@@ -512,9 +688,57 @@ cleanupmon(Monitor *mon) -+ void -+ clientmessage(XEvent *e) -+ { -++ XWindowAttributes wa; -++ XSetWindowAttributes swa; -+ XClientMessageEvent *cme = &e->xclient; -+ Client *c = wintoclient(cme->window); -+ -++ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) { -++ /* add systray icons */ -++ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) { -++ if (!(c = (Client *)calloc(1, sizeof(Client)))) -++ die("fatal: could not malloc() %u bytes\n", sizeof(Client)); -++ if (!(c->win = cme->data.l[2])) { -++ free(c); -++ return; -++ } -++ c->mon = selmon; -++ c->next = systray->icons; -++ systray->icons = c; -++ if (!XGetWindowAttributes(dpy, c->win, &wa)) { -++ /* use sane defaults */ -++ wa.width = bh; -++ wa.height = bh; -++ wa.border_width = 0; -++ } -++ c->x = c->oldx = c->y = c->oldy = 0; -++ c->w = c->oldw = wa.width; -++ c->h = c->oldh = wa.height; -++ c->oldbw = wa.border_width; -++ c->bw = 0; -++ c->isfloating = True; -++ /* reuse tags field as mapped status */ -++ c->tags = 1; -++ updatesizehints(c); -++ updatesystrayicongeom(c, wa.width, wa.height); -++ XAddToSaveSet(dpy, c->win); -++ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); -++ XReparentWindow(dpy, c->win, systray->win, 0, 0); -++ /* use parents background color */ -++ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -++ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa); -++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -++ /* FIXME not sure if I have to send these events, too */ -++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -++ XSync(dpy, False); -++ resizebarwin(selmon); -++ updatesystray(); -++ setclientstate(c, NormalState); -++ } -++ return; -++ } -+ if (!c) -+ return; -+ if (cme->message_type == netatom[NetWMState]) { -+@@ -567,7 +791,7 @@ configurenotify(XEvent *e) -+ for (c = m->clients; c; c = c->next) -+ if (c->isfullscreen) -+ resizeclient(c, m->mx, m->my, m->mw, m->mh); -+- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -++ resizebarwin(m); -+ } -+ focus(NULL); -+ arrange(NULL); -+@@ -627,6 +851,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) -+ { -+@@ -652,6 +889,15 @@ destroynotify(XEvent *e) -+ -+ if ((c = wintoclient(ev->window))) -+ unmanage(c, 1); -++ -++ else if ((c = wintosystrayicon(ev->window))) { -++ removesystrayicon(c); -++ resizebarwin(selmon); -++ updatesystray(); -++ } -++ -++ else if ((c = swallowingclient(ev->window))) -++ unmanage(c->swallowing, 1); -+ } -+ -+ void -+@@ -695,18 +941,24 @@ dirtomon(int dir) -+ void -+ drawbar(Monitor *m) -+ { -+- int x, w, sw = 0; -++ int indn; -++ int x, w, tw = 0, stw = 0; -+ int boxs = drw->fonts->h / 9; -+ int boxw = drw->fonts->h / 6 + 2; -+ unsigned int i, occ = 0, urg = 0; -+ Client *c; -+ -++ if(showsystray && m == systraytomon(m)) -++ stw = getsystraywidth(); -++ -+ /* 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]); -+- sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -+- drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); -+- } -++ tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding */ -++ drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0); -++ } -++ -++ resizebarwin(m); -+ -+ for (c = m->clients; c; c = c->next) { -+ occ |= c->tags; -+@@ -715,20 +967,24 @@ drawbar(Monitor *m) -+ } -+ x = 0; -+ for (i = 0; i < LENGTH(tags); i++) { -++ indn = 0; -+ 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); -++ for (c = m->clients; c; c = c->next) { -++ if (c->tags & (1 << i)) { -++ drw_rect(drw, x, 1 + (indn * 2), selmon->sel == c ? 6 : 1, 1, 1, urg & 1 << i); -++ indn++; -++ } -++ } -++ -+ x += w; -+ } -+ w = blw = TEXTW(m->ltsymbol); -+ drw_setscheme(drw, scheme[SchemeNorm]); -+ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); -+ -+- if ((w = m->ww - sw - x) > bh) { -++ if ((w = m->ww - tw - stw - x) > bh) { -+ if (m->sel) { -+ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -+ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -+@@ -739,7 +995,7 @@ drawbar(Monitor *m) -+ drw_rect(drw, x, 0, w, bh, 1, 1); -+ } -+ } -+- drw_map(drw, m->barwin, 0, 0, m->ww, bh); -++ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh); -+ } -+ -+ void -+@@ -776,8 +1032,21 @@ expose(XEvent *e) -+ Monitor *m; -+ XExposeEvent *ev = &e->xexpose; -+ -+- if (ev->count == 0 && (m = wintomon(ev->window))) -++ if (ev->count == 0 && (m = wintomon(ev->window))) { -+ drawbar(m); -++ if (m == selmon) -++ updatesystray(); -++ } -++} -++ -++Client * -++findbefore(Client *c) -++{ -++ Client *tmp; -++ if (c == selmon->clients) -++ return NULL; -++ for (tmp = selmon->clients; tmp && tmp->next != c; tmp = tmp->next); -++ return tmp; -+ } -+ -+ void -+@@ -862,15 +1131,34 @@ getatomprop(Client *c, Atom prop) -+ unsigned long dl; -+ unsigned char *p = NULL; -+ Atom da, atom = None; -++ /* FIXME getatomprop should return the number of items and a pointer to -++ * the stored data instead of this workaround */ -++ Atom req = XA_ATOM; -++ if (prop == xatom[XembedInfo]) -++ req = xatom[XembedInfo]; -+ -+- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, -++ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, -+ &da, &di, &dl, &dl, &p) == Success && p) { -+ atom = *(Atom *)p; -++ if (da == xatom[XembedInfo] && dl == 2) -++ atom = ((Atom *)p)[1]; -+ XFree(p); -+ } -+ return atom; -+ } -+ -++int -++getdwmblockspid() -++{ -++ char buf[16]; -++ FILE *fp = popen("pidof -s dwmblocks", "r"); -++ fgets(buf, sizeof(buf), fp); -++ pid_t pid = strtoul(buf, NULL, 10); -++ pclose(fp); -++ dwmblockspid = pid; -++ return pid != 0 ? 0 : -1; -++} -++ -+ int -+ getrootptr(int *x, int *y) -+ { -+@@ -899,6 +1187,16 @@ getstate(Window w) -+ return result; -+ } -+ -++unsigned int -++getsystraywidth() -++{ -++ unsigned int w = 0; -++ Client *i; -++ if(showsystray) -++ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ; -++ return w ? w + systrayspacing : 1; -++} -++ -+ int -+ gettextprop(Window w, Atom atom, char *text, unsigned int size) -+ { -+@@ -998,12 +1296,55 @@ keypress(XEvent *e) -+ keys[i].func(&(keys[i].arg)); -+ } -+ -++int -++fake_signal(void) -++{ -++ char fsignal[256]; -++ char indicator[9] = "fsignal:"; -++ char str_sig[50]; -++ char param[16]; -++ int i, len_str_sig, n, paramn; -++ size_t len_fsignal, len_indicator = strlen(indicator); -++ Arg arg; -++ -++ // Get root name property -++ if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) { -++ len_fsignal = strlen(fsignal); -++ -++ // Check if this is indeed a fake signal -++ if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) { -++ paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n); -++ -++ if (paramn == 1) arg = (Arg) {0}; -++ else if (paramn > 2) return 1; -++ else if (strncmp(param, "i", n - len_str_sig) == 0) -++ sscanf(fsignal + len_indicator + n, "%i", &(arg.i)); -++ else if (strncmp(param, "ui", n - len_str_sig) == 0) -++ sscanf(fsignal + len_indicator + n, "%u", &(arg.ui)); -++ else if (strncmp(param, "f", n - len_str_sig) == 0) -++ sscanf(fsignal + len_indicator + n, "%f", &(arg.f)); -++ else return 1; -++ -++ // Check if a signal was found, and if so handle it -++ for (i = 0; i < LENGTH(signals); i++) -++ if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func) -++ signals[i].func(&(arg)); -++ -++ // A fake signal was sent -++ return 1; -++ } -++ } -++ -++ // No fake signal was sent, so proceed with update -++ return 0; -++} -++ -+ void -+ killclient(const Arg *arg) -+ { -+ if (!selmon->sel) -+ return; -+- if (!sendevent(selmon->sel, wmatom[WMDelete])) { -++ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) { -+ XGrabServer(dpy); -+ XSetErrorHandler(xerrordummy); -+ XSetCloseDownMode(dpy, DestroyAll); -+@@ -1017,18 +1358,20 @@ killclient(const Arg *arg) -+ void -+ manage(Window w, XWindowAttributes *wa) -+ { -+- Client *c, *t = NULL; -++ Client *c, *t = NULL, *term = NULL; -+ Window trans = None; -+ XWindowChanges wc; -+ -+ c = ecalloc(1, sizeof(Client)); -+ c->win = w; -++ c->pid = winpid(w); -+ /* geometry */ -+ c->x = c->oldx = wa->x; -+ c->y = c->oldy = wa->y; -+ c->w = c->oldw = wa->width; -+ c->h = c->oldh = wa->height; -+ c->oldbw = wa->border_width; -++ c->cfact = 1.0; -+ -+ updatetitle(c); -+ if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { -+@@ -1037,6 +1380,7 @@ manage(Window w, XWindowAttributes *wa) -+ } else { -+ c->mon = selmon; -+ applyrules(c); -++ term = termforwin(c); -+ } -+ -+ if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) -+@@ -1062,7 +1406,10 @@ manage(Window w, XWindowAttributes *wa) -+ c->isfloating = c->oldstate = trans != None || c->isfixed; -+ if (c->isfloating) -+ XRaiseWindow(dpy, c->win); -+- attach(c); -++ if( attachbelow ) -++ attachBelow(c); -++ else -++ attach(c); -+ attachstack(c); -+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, -+ (unsigned char *) &(c->win), 1); -+@@ -1073,6 +1420,8 @@ manage(Window w, XWindowAttributes *wa) -+ c->mon->sel = c; -+ arrange(c->mon); -+ XMapWindow(dpy, c->win); -++ if (term) -++ swallow(term, c); -+ focus(NULL); -+ } -+ -+@@ -1091,6 +1440,12 @@ maprequest(XEvent *e) -+ { -+ static XWindowAttributes wa; -+ XMapRequestEvent *ev = &e->xmaprequest; -++ Client *i; -++ if ((i = wintosystrayicon(ev->window))) { -++ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION); -++ resizebarwin(selmon); -++ updatesystray(); -++ } -+ -+ if (!XGetWindowAttributes(dpy, ev->window, &wa)) -+ return; -+@@ -1199,6 +1554,7 @@ nexttiled(Client *c) -+ return c; -+ } -+ -++/* -+ void -+ pop(Client *c) -+ { -+@@ -1207,6 +1563,17 @@ pop(Client *c) -+ focus(c); -+ arrange(c->mon); -+ } -++*/ -++ -++Client * -++prevtiled(Client *c) { -++ Client *p, *r; -++ -++ for(p = selmon->clients, r = NULL; p && p != c; p = p->next) -++ if(!p->isfloating && ISVISIBLE(p)) -++ r = p; -++ return r; -++} -+ -+ void -+ propertynotify(XEvent *e) -+@@ -1215,8 +1582,20 @@ propertynotify(XEvent *e) -+ Window trans; -+ XPropertyEvent *ev = &e->xproperty; -+ -+- if ((ev->window == root) && (ev->atom == XA_WM_NAME)) -+- updatestatus(); -++ if ((c = wintosystrayicon(ev->window))) { -++ if (ev->atom == XA_WM_NORMAL_HINTS) { -++ updatesizehints(c); -++ updatesystrayicongeom(c, c->w, c->h); -++ } else -++ updatesystrayiconstate(c, ev); -++ resizebarwin(selmon); -++ updatesystray(); -++ -++ } -++ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) { -++ if (!fake_signal()) -++ updatestatus(); -++ } -+ else if (ev->state == PropertyDelete) -+ return; /* ignore */ -+ else if ((c = wintoclient(ev->window))) { -+@@ -1245,9 +1624,41 @@ propertynotify(XEvent *e) -+ } -+ } -+ -++void -++pushdown(const Arg *arg) { -++ Client *sel = selmon->sel, *c; -++ -++ if(!sel || sel->isfloating || sel == nexttiled(selmon->clients)) -++ return; -++ if((c = nexttiled(sel->next))) { -++ detach(sel); -++ sel->next = c->next; -++ c->next = sel; -++ } -++ focus(sel); -++ arrange(selmon); -++} -++ -++void -++pushup(const Arg *arg) { -++ Client *sel = selmon->sel, *c; -++ -++ if(!sel || sel->isfloating) -++ return; -++ if((c = prevtiled(sel)) && c != nexttiled(selmon->clients)) { -++ detach(sel); -++ sel->next = c; -++ for(c = selmon->clients; c->next != sel->next; c = c->next); -++ c->next = sel; -++ } -++ focus(sel); -++ arrange(selmon); -++} -++ -+ void -+ quit(const Arg *arg) -+ { -++ if(arg->i) restart = 1; -+ running = 0; -+ } -+ -+@@ -1265,6 +1676,20 @@ recttomon(int x, int y, int w, int h) -+ return r; -+ } -+ -++void -++removesystrayicon(Client *i) -++{ -++ Client **ii; -++ -++ if (!showsystray || !i) -++ return; -++ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); -++ if (ii) -++ *ii = i->next; -++ free(i); -++} -++ -++ -+ void -+ resize(Client *c, int x, int y, int w, int h, int interact) -+ { -+@@ -1272,16 +1697,48 @@ resize(Client *c, int x, int y, int w, int h, int interact) -+ resizeclient(c, x, y, w, h); -+ } -+ -++void -++resizebarwin(Monitor *m) { -++ unsigned int w = m->ww; -++ if (showsystray && m == systraytomon(m)) -++ w -= getsystraywidth(); -++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); -++} -++ -+ void -+ resizeclient(Client *c, int x, int y, int w, int h) -+ { -+ XWindowChanges wc; -++ unsigned int n; -++ unsigned int gapoffset; -++ unsigned int gapincr; -++ Client *nbc; -+ -+- c->oldx = c->x; c->x = wc.x = x; -+- 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; -+ wc.border_width = c->bw; -++ -++ /* Get number of clients for the selected monitor */ -++ for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); -++ -++ /* Do nothing if layout is floating */ -++ if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { -++ gapincr = gapoffset = 0; -++ } else { -++ /* Remove border and gap if layout is monocle or only one client */ -++ if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) { -++ gapoffset = 0; -++ gapincr = -2 * borderpx; -++ wc.border_width = 0; -++ } else { -++ gapoffset = gappx; -++ gapincr = 2 * gappx; -++ } -++ } -++ -++ c->oldx = c->x; c->x = wc.x = x + gapoffset; -++ c->oldy = c->y; c->y = wc.y = y + gapoffset; -++ c->oldw = c->w; c->w = wc.width = w - gapincr; -++ c->oldh = c->h; c->h = wc.height = h - gapincr; -++ -+ XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); -+ configure(c); -+ XSync(dpy, False); -+@@ -1344,6 +1801,19 @@ resizemouse(const Arg *arg) -+ } -+ } -+ -++void -++resizerequest(XEvent *e) -++{ -++ XResizeRequestEvent *ev = &e->xresizerequest; -++ Client *i; -++ -++ if ((i = wintosystrayicon(ev->window))) { -++ updatesystrayicongeom(i, ev->width, ev->height); -++ resizebarwin(selmon); -++ updatesystray(); -++ } -++} -++ -+ void -+ restack(Monitor *m) -+ { -+@@ -1380,10 +1850,18 @@ run(void) -+ handler[ev.type](&ev); /* call handler */ -+ } -+ -++void -++runAutostart(void) { -++ system("cd ~; ./.config/dwm/autostart_blocking.sh"); -++ system("cd ~; ./.config/dwm/autostart.sh &"); -++} -++ -+ void -+ scan(void) -+ { -++ scanner = 1; -+ unsigned int i, num; -++ char swin[256]; -+ Window d1, d2, *wins = NULL; -+ XWindowAttributes wa; -+ -+@@ -1394,6 +1872,8 @@ scan(void) -+ continue; -+ if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) -+ manage(wins[i], &wa); -++ else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin)) -++ manage(wins[i], &wa); -+ } -+ for (i = 0; i < num; i++) { /* now the transients */ -+ if (!XGetWindowAttributes(dpy, wins[i], &wa)) -+@@ -1405,6 +1885,7 @@ scan(void) -+ if (wins) -+ XFree(wins); -+ } -++ scanner = 0; -+ } -+ -+ void -+@@ -1417,7 +1898,10 @@ sendmon(Client *c, Monitor *m) -+ detachstack(c); -+ c->mon = m; -+ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -+- attach(c); -++ if( attachbelow ) -++ attachBelow(c); -++ else -++ attach(c); -+ attachstack(c); -+ focus(NULL); -+ arrange(NULL); -+@@ -1433,26 +1917,36 @@ setclientstate(Client *c, long state) -+ } -+ -+ int -+-sendevent(Client *c, Atom proto) -++sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) -+ { -+ int n; -+- Atom *protocols; -++ Atom *protocols, mt; -+ int exists = 0; -+ XEvent ev; -+ -+- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { -+- while (!exists && n--) -+- exists = protocols[n] == proto; -+- XFree(protocols); -++ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) { -++ mt = wmatom[WMProtocols]; -++ if (XGetWMProtocols(dpy, w, &protocols, &n)) { -++ while (!exists && n--) -++ exists = protocols[n] == proto; -++ XFree(protocols); -++ } -++ } -++ else { -++ exists = True; -++ mt = proto; -+ } -+ if (exists) { -+ ev.type = ClientMessage; -+- ev.xclient.window = c->win; -+- ev.xclient.message_type = wmatom[WMProtocols]; -++ ev.xclient.window = w; -++ ev.xclient.message_type = mt; -+ ev.xclient.format = 32; -+- ev.xclient.data.l[0] = proto; -+- ev.xclient.data.l[1] = CurrentTime; -+- XSendEvent(dpy, c->win, False, NoEventMask, &ev); -++ ev.xclient.data.l[0] = d0; -++ ev.xclient.data.l[1] = d1; -++ ev.xclient.data.l[2] = d2; -++ ev.xclient.data.l[3] = d3; -++ ev.xclient.data.l[4] = d4; -++ XSendEvent(dpy, w, False, mask, &ev); -+ } -+ return exists; -+ } -+@@ -1466,7 +1960,7 @@ setfocus(Client *c) -+ XA_WINDOW, 32, PropModeReplace, -+ (unsigned char *) &(c->win), 1); -+ } -+- sendevent(c, wmatom[WMTakeFocus]); -++ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); -+ } -+ -+ void -+@@ -1511,6 +2005,23 @@ setlayout(const Arg *arg) -+ drawbar(selmon); -+ } -+ -++void setcfact(const Arg *arg) { -++ float f; -++ Client *c; -++ -++ c = selmon->sel; -++ -++ if(!arg || !c || !selmon->lt[selmon->sellt]->arrange) -++ return; -++ f = arg->f + c->cfact; -++ if(arg->f == 0.0) -++ f = 1.0; -++ else if(f < 0.25 || f > 4.0) -++ return; -++ c->cfact = f; -++ arrange(selmon); -++} -++ -+ /* arg > 1.0 will set mfact absolutely */ -+ void -+ setmfact(const Arg *arg) -+@@ -1520,7 +2031,7 @@ setmfact(const Arg *arg) -+ if (!arg || !selmon->lt[selmon->sellt]->arrange) -+ return; -+ f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; -+- if (f < 0.05 || f > 0.95) -++ if (f < 0.1 || f > 0.9) -+ return; -+ selmon->mfact = f; -+ arrange(selmon); -+@@ -1536,6 +2047,9 @@ setup(void) -+ /* clean up any zombies immediately */ -+ sigchld(0); -+ -++ signal(SIGHUP, sighup); -++ signal(SIGTERM, sigterm); -++ -+ /* init screen */ -+ screen = DefaultScreen(dpy); -+ sw = DisplayWidth(dpy, screen); -+@@ -1555,6 +2069,10 @@ setup(void) -+ wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); -+ netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); -+ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); -++ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False); -++ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False); -++ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False); -++ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False); -+ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); -+ netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); -+ netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); -+@@ -1562,6 +2080,9 @@ setup(void) -+ netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); -+ netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); -+ netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); -++ xatom[Manager] = XInternAtom(dpy, "MANAGER", False); -++ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); -++ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); -+ /* init cursors */ -+ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); -+ cursor[CurResize] = drw_cur_create(drw, XC_sizing); -+@@ -1570,6 +2091,8 @@ setup(void) -+ scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); -+ for (i = 0; i < LENGTH(colors); i++) -+ scheme[i] = drw_scm_create(drw, colors[i], 3); -++ /* init system tray */ -++ updatesystray(); -+ /* init bars */ -+ updatebars(); -+ updatestatus(); -+@@ -1636,6 +2159,37 @@ sigchld(int unused) -+ while (0 < waitpid(-1, NULL, WNOHANG)); -+ } -+ -++void -++sighup(int unused) -++{ -++ Arg a = {.i = 1}; -++ quit(&a); -++} -++ -++void -++sigterm(int unused) -++{ -++ Arg a = {.i = 0}; -++ quit(&a); -++} -++ -++void -++sigdwmblocks(const Arg *arg) -++{ -++ union sigval sv; -++ sv.sival_int = (dwmblockssig << 8) | arg->i; -++ if (!dwmblockspid) -++ if (getdwmblockspid() == -1) -++ return; -++ -++ if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) { -++ if (errno == ESRCH) { -++ if (!getdwmblockspid()) -++ sigqueue(dwmblockspid, SIGUSR1, sv); -++ } -++ } -++} -++ -+ void -+ spawn(const Arg *arg) -+ { -+@@ -1674,9 +2228,15 @@ void -+ tile(Monitor *m) -+ { -+ unsigned int i, n, h, mw, my, ty; -++ float mfacts = 0, sfacts = 0; -+ Client *c; -+ -+- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { -++ if (n < m->nmaster) -++ mfacts += c->cfact; -++ else -++ sfacts += c->cfact; -++ } -+ if (n == 0) -+ return; -+ -+@@ -1686,13 +2246,19 @@ tile(Monitor *m) -+ mw = m->ww; -+ for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -+ if (i < m->nmaster) { -+- h = (m->wh - my) / (MIN(n, m->nmaster) - i); -++ h = (m->wh - my) * (c->cfact / mfacts); -+ resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -+- my += HEIGHT(c); -++ if (my + HEIGHT(c) < m->wh) { -++ my += HEIGHT(c); -++ mfacts -= c->cfact; -++ } -+ } else { -+- h = (m->wh - ty) / (n - i); -++ h = (m->wh - ty) * (c->cfact / sfacts); -+ resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); -+- ty += HEIGHT(c); -++ if (ty + HEIGHT(c) < m->wh) { -++ ty += HEIGHT(c); -++ sfacts -= c->cfact; -++ } -+ } -+ } -+ -+@@ -1701,7 +2267,18 @@ togglebar(const Arg *arg) -+ { -+ selmon->showbar = !selmon->showbar; -+ updatebarpos(selmon); -+- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); -++ resizebarwin(selmon); -++ if (showsystray) { -++ XWindowChanges wc; -++ if (!selmon->showbar) -++ wc.y = -bh; -++ else if (selmon->showbar) { -++ wc.y = 0; -++ if (!selmon->topbar) -++ wc.y = selmon->mh - bh; -++ } -++ XConfigureWindow(dpy, systray->win, CWY, &wc); -++ } -+ arrange(selmon); -+ } -+ -+@@ -1719,6 +2296,13 @@ togglefloating(const Arg *arg) -+ arrange(selmon); -+ } -+ -++void -++togglefullscr(const Arg *arg) -++{ -++ if(selmon->sel) -++ setfullscreen(selmon->sel, !selmon->sel->isfullscreen); -++} -++ -+ void -+ toggletag(const Arg *arg) -+ { -+@@ -1765,6 +2349,20 @@ unmanage(Client *c, int destroyed) -+ Monitor *m = c->mon; -+ XWindowChanges wc; -+ -++ if (c->swallowing) { -++ unswallow(c); -++ return; -++ } -++ -++ Client *s = swallowingclient(c->win); -++ if (s) { -++ free(s->swallowing); -++ s->swallowing = NULL; -++ arrange(m); -++ focus(NULL); -++ return; -++ } -++ -+ detach(c); -+ detachstack(c); -+ if (!destroyed) { -+@@ -1779,9 +2377,12 @@ unmanage(Client *c, int destroyed) -+ XUngrabServer(dpy); -+ } -+ free(c); -+- focus(NULL); -+- updateclientlist(); -+- arrange(m); -++ -++ if (!s) { -++ arrange(m); -++ focus(NULL); -++ updateclientlist(); -++ } -+ } -+ -+ void -+@@ -1796,11 +2397,18 @@ unmapnotify(XEvent *e) -+ else -+ unmanage(c, 0); -+ } -++ else if ((c = wintosystrayicon(ev->window))) { -++ /* KLUDGE! sometimes icons occasionally unmap their windows, but do -++ * _not_ destroy them. We map those windows back */ -++ XMapRaised(dpy, c->win); -++ updatesystray(); -++ } -+ } -+ -+ void -+ updatebars(void) -+ { -++ unsigned int w; -+ Monitor *m; -+ XSetWindowAttributes wa = { -+ .override_redirect = True, -+@@ -1811,10 +2419,15 @@ updatebars(void) -+ for (m = mons; m; m = m->next) { -+ if (m->barwin) -+ continue; -+- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -++ w = m->ww; -++ if (showsystray && m == systraytomon(m)) -++ w -= getsystraywidth(); -++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen), -+ CopyFromParent, DefaultVisual(dpy, screen), -+ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+ XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); -++ if (showsystray && m == systraytomon(m)) -++ XMapRaised(dpy, systray->win); -+ XMapRaised(dpy, m->barwin); -+ XSetClassHint(dpy, m->barwin, &ch); -+ } -+@@ -1897,7 +2510,10 @@ updategeom(void) -+ m->clients = c->next; -+ detachstack(c); -+ c->mon = mons; -+- attach(c); -++ if( attachbelow ) -++ attachBelow(c); -++ else -++ attach(c); -+ attachstack(c); -+ } -+ if (m == selmon) -+@@ -1987,9 +2603,126 @@ 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); -++ updatesystray(); -++} -++ -++void -++updatesystrayicongeom(Client *i, int w, int h) -++{ -++ if (i) { -++ i->h = bh; -++ if (w == h) -++ i->w = bh; -++ else if (h == bh) -++ i->w = w; -++ else -++ i->w = (int) ((float)bh * ((float)w / (float)h)); -++ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False); -++ /* force icons into the systray dimensions if they don't want to */ -++ if (i->h > bh) { -++ if (i->w == i->h) -++ i->w = bh; -++ else -++ i->w = (int) ((float)bh * ((float)i->w / (float)i->h)); -++ i->h = bh; -++ } -++ } -++} -++ -++void -++updatesystrayiconstate(Client *i, XPropertyEvent *ev) -++{ -++ long flags; -++ int code = 0; -++ -++ if (!showsystray || !i || ev->atom != xatom[XembedInfo] || -++ !(flags = getatomprop(i, xatom[XembedInfo]))) -++ return; -++ -++ if (flags & XEMBED_MAPPED && !i->tags) { -++ i->tags = 1; -++ code = XEMBED_WINDOW_ACTIVATE; -++ XMapRaised(dpy, i->win); -++ setclientstate(i, NormalState); -++ } -++ else if (!(flags & XEMBED_MAPPED) && i->tags) { -++ i->tags = 0; -++ code = XEMBED_WINDOW_DEACTIVATE; -++ XUnmapWindow(dpy, i->win); -++ setclientstate(i, WithdrawnState); -++ } -++ else -++ return; -++ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0, -++ systray->win, XEMBED_EMBEDDED_VERSION); -++} -++ -++void -++updatesystray(void) -++{ -++ XSetWindowAttributes wa; -++ XWindowChanges wc; -++ Client *i; -++ Monitor *m = systraytomon(NULL); -++ unsigned int x = m->mx + m->mw; -++ unsigned int w = 1; -++ -++ if (!showsystray) -++ return; -++ if (!systray) { -++ /* init systray */ -++ if (!(systray = (Systray *)calloc(1, sizeof(Systray)))) -++ die("fatal: could not malloc() %u bytes\n", sizeof(Systray)); -++ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel); -++ wa.event_mask = ButtonPressMask | ExposureMask; -++ wa.override_redirect = True; -++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -++ XSelectInput(dpy, systray->win, SubstructureNotifyMask); -++ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, -++ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1); -++ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa); -++ XMapRaised(dpy, systray->win); -++ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime); -++ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) { -++ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0); -++ XSync(dpy, False); -++ } -++ else { -++ fprintf(stderr, "dwm: unable to obtain system tray.\n"); -++ free(systray); -++ systray = NULL; -++ return; -++ } -++ } -++ for (w = 0, i = systray->icons; i; i = i->next) { -++ /* make sure the background color stays the same */ -++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -++ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa); -++ XMapRaised(dpy, i->win); -++ w += systrayspacing; -++ i->x = w; -++ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h); -++ w += i->w; -++ if (i->mon != m) -++ i->mon = m; -++ } -++ w = w ? w + systrayspacing : 1; -++ x -= w; -++ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh); -++ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh; -++ wc.stack_mode = Above; wc.sibling = m->barwin; -++ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc); -++ XMapWindow(dpy, systray->win); -++ XMapSubwindows(dpy, systray->win); -++ /* redraw background */ -++ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel); -++ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh); -++ XSync(dpy, False); -+ } -+ -+ void -+@@ -2044,6 +2777,110 @@ view(const Arg *arg) -+ arrange(selmon); -+ } -+ -++pid_t -++winpid(Window w) -++{ -++ pid_t result = 0; -++ -++ xcb_res_client_id_spec_t spec = {0}; -++ spec.client = w; -++ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; -++ -++ xcb_generic_error_t *e = NULL; -++ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); -++ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); -++ -++ if (!r) -++ return (pid_t)0; -++ -++ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); -++ for (; i.rem; xcb_res_client_id_value_next(&i)) { -++ spec = i.data->spec; -++ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { -++ uint32_t *t = xcb_res_client_id_value_value(i.data); -++ result = *t; -++ break; -++ } -++ } -++ -++ free(r); -++ -++ if (result == (pid_t)-1) -++ result = 0; -++ return result; -++} -++ -++pid_t -++getparentprocess(pid_t p) -++{ -++ unsigned int v = 0; -++ -++#if defined(__linux__) -++ FILE *f; -++ char buf[256]; -++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); -++ -++ if (!(f = fopen(buf, "r"))) -++ return (pid_t)0; -++ -++ if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1) -++ v = (pid_t)0; -++ fclose(f); -++#elif defined(__FreeBSD__) -++ struct kinfo_proc *proc = kinfo_getproc(p); -++ if (!proc) -++ return (pid_t)0; -++ -++ v = proc->ki_ppid; -++ free(proc); -++#endif -++ return (pid_t)v; -++} -++ -++int -++isdescprocess(pid_t p, pid_t c) -++{ -++ while (p != c && c != 0) -++ c = getparentprocess(c); -++ -++ return (int)c; -++} -++ -++Client * -++termforwin(const Client *w) -++{ -++ Client *c; -++ Monitor *m; -++ -++ if (!w->pid || w->isterminal) -++ return NULL; -++ -++ for (m = mons; m; m = m->next) { -++ for (c = m->clients; c; c = c->next) { -++ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) -++ return c; -++ } -++ } -++ -++ return NULL; -++} -++ -++Client * -++swallowingclient(Window w) -++{ -++ Client *c; -++ Monitor *m; -++ -++ for (m = mons; m; m = m->next) { -++ for (c = m->clients; c; c = c->next) { -++ if (c->swallowing && c->swallowing->win == w) -++ return c; -++ } -++ } -++ -++ return NULL; -++} -++ -+ Client * -+ wintoclient(Window w) -+ { -+@@ -2057,6 +2894,16 @@ wintoclient(Window w) -+ return NULL; -+ } -+ -++Client * -++wintosystrayicon(Window w) { -++ Client *i = NULL; -++ -++ if (!showsystray || !w) -++ return i; -++ for (i = systray->icons; i && i->win != w; i = i->next) ; -++ return i; -++} -++ -+ Monitor * -+ wintomon(Window w) -+ { -+@@ -2110,18 +2957,58 @@ xerrorstart(Display *dpy, XErrorEvent *ee) -+ return -1; -+ } -+ -++Monitor * -++systraytomon(Monitor *m) { -++ Monitor *t; -++ int i, n; -++ if(!systraypinning) { -++ if(!m) -++ return selmon; -++ return m == selmon ? m : NULL; -++ } -++ for(n = 1, t = mons; t && t->next; n++, t = t->next) ; -++ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ; -++ if(systraypinningfailfirst && n < systraypinning) -++ return mons; -++ return t; -++} -++ -+ void -+ zoom(const Arg *arg) -+ { -+ Client *c = selmon->sel; -++ Client *at = NULL, *cold, *cprevious = NULL; -+ -+ if (!selmon->lt[selmon->sellt]->arrange -+ || (selmon->sel && selmon->sel->isfloating)) -+ return; -+- if (c == nexttiled(selmon->clients)) -+- if (!c || !(c = nexttiled(c->next))) -+- return; -+- pop(c); -++ if (c == nexttiled(selmon->clients)) { -++ at = findbefore(prevzoom); -++ if (at) -++ cprevious = nexttiled(at->next); -++ if (!cprevious || cprevious != prevzoom) { -++ prevzoom = NULL; -++ if (!c || !(c = nexttiled(c->next))) -++ return; -++ } else -++ c = cprevious; -++ } -++ cold = nexttiled(selmon->clients); -++ if (c != cold && !at) -++ at = findbefore(c); -++ detach(c); -++ attach(c); -++ /* swap windows instead of pushing the previous one down */ -++ if (c != cold && at) { -++ prevzoom = cold; -++ if (cold && at != cold) { -++ detach(cold); -++ cold->next = at->next; -++ at->next = cold; -++ } -++ } -++ focus(c); -++ arrange(c->mon); -+ } -+ -+ int -+@@ -2135,6 +3022,8 @@ main(int argc, char *argv[]) -+ fputs("warning: no locale support\n", stderr); -+ if (!(dpy = XOpenDisplay(NULL))) -+ die("dwm: cannot open display"); -++ if (!(xcon = XGetXCBConnection(dpy))) -++ die("dwm: cannot get xcb connection\n"); -+ checkotherwm(); -+ setup(); -+ #ifdef __OpenBSD__ -+@@ -2142,7 +3031,9 @@ main(int argc, char *argv[]) -+ die("pledge"); -+ #endif /* __OpenBSD__ */ -+ scan(); -+- run(); -++ runAutostart(); -++run(); -++ if(restart) execvp(argv[0], argv); -+ cleanup(); -+ XCloseDisplay(dpy); -+ return EXIT_SUCCESS; -+diff --git a/dwm.desktop b/dwm.desktop -+new file mode 100644 -+index 0000000..5a6021f -+--- /dev/null -++++ b/dwm.desktop -+@@ -0,0 +1,10 @@ -++[Desktop Entry] -++Version=6.3 -++Type=Application -++Name=dwm -++Comment=Suckless' dynamic window manager -++Exec=dwm -++Icon=dwm -++Terminal=false -++StartupNotify=false -++Categories=Application; -+diff --git a/dwmc b/dwmc -+new file mode 100755 -+index 0000000..5ff8dbc -+--- /dev/null -++++ b/dwmc -+@@ -0,0 +1,40 @@ -++#!/usr/bin/env sh -++ -++signal() { -++ xsetroot -name "fsignal:$*" -++} -++ -++case $# in -++1) -++ case $1 in -++ setlayout | view | viewall | togglebar | togglefloating | zoom | killclient | quit) -++ signal $1 -++ ;; -++ *) -++ echo "Unknown command or missing one argument." -++ exit 1 -++ ;; -++ esac -++ ;; -++2) -++ case $1 in -++ view) -++ signal $1 ui $2 -++ ;; -++ viewex | toggleviewex | tagex | toggletagex | setlayoutex | focusstack | incnmaster | focusmon | tagmon) -++ signal $1 i $2 -++ ;; -++ setmfact) -++ signal $1 f $2 -++ ;; -++ *) -++ echo "Unknown command or one too many arguments." -++ exit 1 -++ ;; -++ esac -++ ;; -++*) -++ echo "Too many arguments." -++ exit 1 -++ ;; -++esac -+diff --git a/patch.diff b/patch.diff -+new file mode 100644 -+index 0000000..2ce43a2 -+--- /dev/null -++++ b/patch.diff -+@@ -0,0 +1,4773 @@ -++diff --git a/Makefile b/Makefile -++index 77bcbc0..c6bc24b 100644 -++--- a/Makefile -+++++ b/Makefile -++@@ -37,8 +37,9 @@ dist: clean -++ rm -rf dwm-${VERSION} -++ -++ install: all -++- mkdir -p ${DESTDIR}${PREFIX}/bin -++- cp -f dwm ${DESTDIR}${PREFIX}/bin -+++ mkdir -p ${DESTDIR}${PREFIX}/bin ${DESTDIR}${XSESSIONPREFIX} -+++ cp -f dwm dwmc volsv ${DESTDIR}${PREFIX}/bin -+++ cp -f dwm.desktop ${DESTDIR}${XSESSIONPREFIX} -++ chmod 755 ${DESTDIR}${PREFIX}/bin/dwm -++ mkdir -p ${DESTDIR}${MANPREFIX}/man1 -++ sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 -++@@ -46,6 +47,8 @@ install: all -++ -++ uninstall: -++ rm -f ${DESTDIR}${PREFIX}/bin/dwm\ -+++ ${DESTDIR}${PREFIX}/bin/dwmc\ -+++ ${DESTDIR}${PREFIX}/bin/volsv\ -++ ${DESTDIR}${MANPREFIX}/man1/dwm.1 -++ -++ .PHONY: all options clean dist install uninstall -++diff --git a/config.def.h b/config.def.h -++index 1c0b587..8bfef3e 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -2,7 +2,13 @@ -++ -++ /* appearance */ -++ static const unsigned int borderpx = 1; /* border pixel of windows */ -+++static const unsigned int gappx = 6; /* 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 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 char *fonts[] = { "monospace:size=10" }; -++@@ -26,15 +32,18 @@ static const Rule rules[] = { -++ * WM_CLASS(STRING) = instance, class -++ * WM_NAME(STRING) = title -++ */ -++- /* class instance title tags mask isfloating monitor */ -++- { "Gimp", NULL, NULL, 0, 1, -1 }, -++- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, -+++ /* class instance title tags mask isfloating isterminal noswallow monitor */ -+++ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, -+++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, -+++ { "st", NULL, NULL, 0, 0, 1, -1, -1 }, -+++ { NULL, NULL, "Event Tester", 0, 1, 0, 1, -1 }, /* xev */ -++ }; -++ -++ /* 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 int attachbelow = 1; /* 1 means attach after the currently active window */ -++ -++ static const Layout layouts[] = { -++ /* symbol arrange function */ -++@@ -70,6 +79,9 @@ 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_h, setcfact, {.f = +0.25} }, -+++ { MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} }, -+++ { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} }, -++ { MODKEY, XK_Return, zoom, {0} }, -++ { MODKEY, XK_Tab, view, {0} }, -++ { MODKEY|ShiftMask, XK_c, killclient, {0} }, -++@@ -78,6 +90,7 @@ static Key keys[] = { -++ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -++ { MODKEY, XK_space, setlayout, {0} }, -++ { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, -+++ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} }, -++ { MODKEY, XK_0, view, {.ui = ~0 } }, -++ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, -++ { MODKEY, XK_comma, focusmon, {.i = -1 } }, -++@@ -94,6 +107,7 @@ static Key keys[] = { -++ TAGKEYS( XK_8, 7) -++ TAGKEYS( XK_9, 8) -++ { MODKEY|ShiftMask, XK_q, quit, {0} }, -+++ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, -++ }; -++ -++ /* button definitions */ -++@@ -103,7 +117,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, sigdwmblocks, {.i = 1} }, -+++ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} }, -+++ { ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} }, -++ { ClkClientWin, MODKEY, Button1, movemouse, {0} }, -++ { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, -++ { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, -++@@ -113,3 +129,73 @@ static Button buttons[] = { -++ { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -++ }; -++ -+++void -+++setlayoutex(const Arg *arg) -+++{ -+++ setlayout(&((Arg) { .v = &layouts[arg->i] })); -+++} -+++ -+++void -+++viewex(const Arg *arg) -+++{ -+++ view(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++viewall(const Arg *arg) -+++{ -+++ view(&((Arg){.ui = ~0})); -+++} -+++ -+++void -+++toggleviewex(const Arg *arg) -+++{ -+++ toggleview(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++tagex(const Arg *arg) -+++{ -+++ tag(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++toggletagex(const Arg *arg) -+++{ -+++ toggletag(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++tagall(const Arg *arg) -+++{ -+++ tag(&((Arg){.ui = ~0})); -+++} -+++ -+++/* signal definitions */ -+++/* signum must be greater than 0 */ -+++/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */ -+++static Signal signals[] = { -+++ /* signum function */ -+++ { "focusstack", focusstack }, -+++ { "setmfact", setmfact }, -+++ { "togglebar", togglebar }, -+++ { "incnmaster", incnmaster }, -+++ { "togglefloating", togglefloating }, -+++ { "focusmon", focusmon }, -+++ { "tagmon", tagmon }, -+++ { "zoom", zoom }, -+++ { "view", view }, -+++ { "viewall", viewall }, -+++ { "viewex", viewex }, -+++ { "toggleview", view }, -+++ { "toggleviewex", toggleviewex }, -+++ { "tag", tag }, -+++ { "tagall", tagall }, -+++ { "tagex", tagex }, -+++ { "toggletag", tag }, -+++ { "toggletagex", toggletagex }, -+++ { "killclient", killclient }, -+++ { "quit", quit }, -+++ { "setlayout", setlayout }, -+++ { "setlayoutex", setlayoutex }, -+++}; -++diff --git a/config.h b/config.h -++new file mode 100644 -++index 0000000..607e67f -++--- /dev/null -+++++ b/config.h -++@@ -0,0 +1,260 @@ -+++/* See LICENSE file for copyright and license details. */ -+++ -+++#include <X11/XF86keysym.h> -+++ -+++/* appearance */ -+++static const unsigned int borderpx = 1; /* border pixel of windows */ -+++static const unsigned int gappx = 6; /* gaps between windows */ -+++static const unsigned int snap = 32; /* snap pixel */ -+++static const int swallowfloating = 0; -+++static const unsigned int systraypinning = 0; /* 0: sloppy systray follows selected monitor, >0: pin systray to monitor X */ -+++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 showbar = 1; /* 0 means no bar */ -+++static const int topbar = 1; /* 0 means bottom bar */ -+++static const char *fonts[] = { "mononoki Nerd Font:size=9", "JoyPixels:size=9" }; -+++static const char dmenufont[] = "mononoki Nerd Font:size=9"; -+++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[] = "#750000"; -+++static const char *colors[][3] = { -+++ /* fg bg border */ -+++ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, -+++ [SchemeSel] = { col_gray4, col_cyan, col_cyan }, -+++}; -+++ -+++/* tagging */ -+++static const char *tags[] = { " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9" }; -+++ -+++static const Rule rules[] = { -+++ /* xprop(1): -+++ * WM_CLASS(STRING) = instance, class -+++ * WM_NAME(STRING) = title -+++ */ -+++ /* class instance title tags mask isfloating isterminal noswallow monitor */ -+++ { NULL, NULL,"Picture in picture", 511, 1, 0, 0, -1 }, -+++ { "ardour-6.2.0",NULL, NULL, 0, 1, 0, 0, -1 }, -+++ { "urxvt", NULL, NULL, 0, 0, 1, 0, -1 }, -+++ { "URxvt", NULL, NULL, 0, 0, 1, 0, -1 }, -+++ { "Ardour-6.2.0",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-256color",NULL, NULL, 0, 0, 1, 1, -1 }, -+++ { "st", NULL, NULL, 0, 0, 1, 1, -1 }, -+++ { "St", NULL, NULL, 0, 0, 1, 1, -1 }, -+++ { "tabbed", NULL, NULL, 0, 0, 1, 0, -1 }, -+++ { NULL, NULL, "abduco", 0, 0, 1, 0, -1 }, -+++ { "Alacritty", NULL, NULL, 0, 0, 1, 0, -1 }, -+++ { "Blueman", NULL, NULL, 0, 1, 0, 0, -1 }, -+++ { "QjackCtl", NULL, NULL, 0, 1, 0, 0, -1 }, -+++ { "qjackctl", NULL, NULL, 0, 1, 0, 0, -1 }, -+++ { "catia.py", NULL, NULL, 0, 1, 0, 0, -1 }, -+++ { "Catia", NULL, NULL, 0, 1, 0, 0, -1 }, -+++ { NULL, NULL, "Event Tester", 0, 1, 0, 1, -1 }, -+++ { "Steam", NULL, NULL, 4, 0, 0, 0, -1 }, -+++ { "steam", NULL, NULL, 4, 0, 0, 0, -1 }, -+++ { NULL, NULL, "steam", 4, 0, 0, 0, -1 }, -+++ { "Lutris", NULL, NULL, 2, 0, 0, 0, -1 }, -+++ { "lutris", NULL, NULL, 2, 0, 0, 0, -1 }, -+++}; -+++ -+++/* layout(s) */ -+++static const float mfact = 0.50; /* 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 int attachbelow = 1; /* 1 means attach after the currently active window */ -+++ -+++static const Layout layouts[] = { -+++ /* symbol arrange function */ -+++ { "[]=", tile }, /* first entry is default */ -+++ { "><>", NULL }, /* no layout function means floating behavior */ -+++ { "[M]", monocle }, -+++}; -+++ -+++/* key definitions */ -+++#define MODKEY Mod1Mask -+++#define TAGKEYS(KEY,TAG) \ -+++ { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ -+++ { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ -+++ { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ -+++ { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, -+++ -+++/* helper for spawning shell commands in the pre dwm-5.0 fashion */ -+++#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } -+++ -+++/* commands */ -+++static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -+++static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -+++static const char *passmenu[] = { "passmenu", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL }; -+++static const char *termcmd[] = { "tabbed", "-c", "st", "-w", NULL }; -+++static const char *mpdtoggle[] = { "playerctl", "--player=mpd,mpv,%any", "play-pause", NULL }; -+++static const char *mpdnext[] = { "playerctl", "--player=mpd,mpv,%any", "next", NULL }; -+++static const char *mpdprev[] = { "playerctl", "--player=mpd,mpv,%any", "previous", NULL }; -+++static const char *plytoggle[] = { "playerctl", "--player=%any,mpd", "play-pause", NULL }; -+++static const char *plyfwd[] = { "playerctl", "--player=%any,mpd", "position 5+", NULL }; -+++static const char *plybck[] = { "playerctl", "--player=%any,mpd", "position 5-", NULL }; -+++static const char *blightup[] = { "light", "-A", "1", NULL }; -+++static const char *blightdown[] = { "light", "-U", "1", NULL }; -+++static const char *audioup[] = { "volsv", "-i", NULL }; -+++static const char *audiodown[] = { "volsv", "-d", NULL }; -+++static const char *audiomute[] = { "volsv", "-t", NULL }; -+++static const char *micmute[] = { "pamixer", "--source", "1", "-t", NULL }; -+++static const char *lockscr[] = { "xscreensaver-command", "-lock", NULL }; -+++static const char *xidletog[] = { "xidletog", NULL }; -+++static const char *xkillcmd[] = { "xkill", NULL }; -+++ -+++static Key keys[] = { -+++ /* modifier key function argument */ -+++ { MODKEY, XK_d, spawn, {.v = dmenucmd } }, -+++ { MODKEY, XK_p, spawn, {.v = passmenu } }, -+++ { MODKEY, XK_c, spawn, {.v = xidletog } }, -+++ { MODKEY, XK_x, spawn, {.v = xkillcmd } }, -+++ { MODKEY, XK_Return, spawn, {.v = termcmd } }, -+++ { 0, XF86XK_AudioPlay, spawn, {.v = mpdtoggle } }, -+++ { 0, XF86XK_AudioNext, spawn, {.v = mpdnext } }, -+++ { 0, XF86XK_AudioPrev, spawn, {.v = mpdprev } }, -+++ { ShiftMask, XF86XK_AudioPlay, spawn, {.v = plytoggle } }, -+++ { ShiftMask, XF86XK_AudioNext, spawn, {.v = plyfwd } }, -+++ { ShiftMask, XF86XK_AudioPrev, spawn, {.v = plybck } }, -+++ { 0, XF86XK_MonBrightnessUp, spawn, {.v = blightup } }, -+++ { 0, XF86XK_MonBrightnessDown, spawn, {.v = blightdown } }, -+++ { 0, XF86XK_AudioLowerVolume, spawn, {.v = audiodown } }, -+++ { 0, XF86XK_AudioRaiseVolume, spawn, {.v = audioup } }, -+++ { 0, XF86XK_AudioMute, spawn, {.v = audiomute } }, -+++ { 0, XF86XK_AudioMicMute, spawn, {.v = micmute } }, -+++ { Mod4Mask, XK_l, spawn, {.v = lockscr } }, -+++ { MODKEY, XK_b, togglebar, {0} }, -+++ { MODKEY, XK_j, focusstack, {.i = +1 } }, -+++ { MODKEY, XK_k, focusstack, {.i = -1 } }, -+++ { MODKEY|ShiftMask, XK_j, pushdown, {.i = +1 } }, -+++ { MODKEY|ShiftMask, XK_k, pushup, {.i = -1 } }, -+++ { MODKEY|ControlMask, XK_k, setcfact, {.f = +0.25} }, -+++ { MODKEY|ControlMask, XK_j, setcfact, {.f = -0.25} }, -+++ { MODKEY|ControlMask, XK_o, setcfact, {.f = 0.00} }, -+++ { MODKEY|ShiftMask, XK_h, incnmaster, {.i = +1 } }, -+++ { MODKEY|ShiftMask, XK_l, incnmaster, {.i = -1 } }, -+++ { MODKEY, XK_h, setmfact, {.f = -0.05} }, -+++ { MODKEY, XK_l, setmfact, {.f = +0.05} }, -+++ { MODKEY|ShiftMask, XK_Return, zoom, {0} }, -+++ { MODKEY, XK_Tab, view, {0} }, -+++ { MODKEY|ShiftMask, XK_q, killclient, {0} }, -+++ { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, -+++ { MODKEY, XK_s, setlayout, {.v = &layouts[1]} }, -+++ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -+++ { MODKEY|ShiftMask, XK_space, setlayout, {-1} }, -+++ { MODKEY, XK_space, togglefloating, {0} }, -+++ { MODKEY, XK_f, togglefullscr, {0} }, -+++ { MODKEY, XK_0, view, {.ui = ~0 } }, -+++ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, -+++ { MODKEY|ControlMask, XK_comma, focusmon, {.i = -1 } }, -+++ { MODKEY|ControlMask, XK_period, focusmon, {.i = +1 } }, -+++ { MODKEY|ControlMask|ShiftMask, XK_comma, tagmon, {.i = -1 } }, -+++ { MODKEY|ControlMask|ShiftMask, XK_period, tagmon, {.i = +1 } }, -+++ TAGKEYS( XK_1, 0) -+++ TAGKEYS( XK_2, 1) -+++ TAGKEYS( XK_3, 2) -+++ TAGKEYS( XK_4, 3) -+++ TAGKEYS( XK_5, 4) -+++ TAGKEYS( XK_6, 5) -+++ TAGKEYS( XK_7, 6) -+++ TAGKEYS( XK_8, 7) -+++ TAGKEYS( XK_9, 8) -+++ { MODKEY|ShiftMask, XK_e, quit, {0} }, -+++ { MODKEY|ShiftMask, XK_r, quit, {1} }, -+++ { MODKEY|ShiftMask, XK_Tab, toggleAttachBelow, {0} }, -+++}; -+++ -+++/* button definitions */ -+++/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ -+++static Button buttons[] = { -+++ /* click event mask button function argument */ -+++ { ClkLtSymbol, 0, Button1, setlayout, {0} }, -+++ { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, -+++ { ClkWinTitle, 0, Button2, zoom, {0} }, -+++ { ClkStatusText, 0, Button1, sigdwmblocks, {.i = 1} }, -+++ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} }, -+++ { ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} }, -+++ { 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 -+++setlayoutex(const Arg *arg) -+++{ -+++ setlayout(&((Arg) { .v = &layouts[arg->i] })); -+++} -+++ -+++void -+++viewex(const Arg *arg) -+++{ -+++ view(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++viewall(const Arg *arg) -+++{ -+++ view(&((Arg){.ui = ~0})); -+++} -+++ -+++void -+++toggleviewex(const Arg *arg) -+++{ -+++ toggleview(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++tagex(const Arg *arg) -+++{ -+++ tag(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++toggletagex(const Arg *arg) -+++{ -+++ toggletag(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++tagall(const Arg *arg) -+++{ -+++ tag(&((Arg){.ui = ~0})); -+++} -+++ -+++/* signal definitions */ -+++/* signum must be greater than 0 */ -+++/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */ -+++static Signal signals[] = { -+++ /* signum function */ -+++ { "focusstack", focusstack }, -+++ { "setmfact", setmfact }, -+++ { "togglebar", togglebar }, -+++ { "incnmaster", incnmaster }, -+++ { "togglefloating", togglefloating }, -+++ { "togglefullscr", togglefullscr }, -+++ { "focusmon", focusmon }, -+++ { "tagmon", tagmon }, -+++ { "zoom", zoom }, -+++ { "view", view }, -+++ { "viewall", viewall }, -+++ { "viewex", viewex }, -+++ { "toggleview", view }, -+++ { "toggleviewex", toggleviewex }, -+++ { "tag", tag }, -+++ { "tagall", tagall }, -+++ { "tagex", tagex }, -+++ { "toggletag", tag }, -+++ { "toggletagex", toggletagex }, -+++ { "killclient", killclient }, -+++ { "quit", quit }, -+++ { "setlayout", setlayout }, -+++ { "setlayoutex", setlayoutex }, -+++}; -+++ -++diff --git a/config.mk b/config.mk -++index 7084c33..dbbc526 100644 -++--- a/config.mk -+++++ b/config.mk -++@@ -6,6 +6,7 @@ VERSION = 6.2 -++ # paths -++ PREFIX = /usr/local -++ MANPREFIX = ${PREFIX}/share/man -+++XSESSIONPREFIX = /usr/share/xsessions -++ -++ X11INC = /usr/X11R6/include -++ X11LIB = /usr/X11R6/lib -++@@ -22,10 +23,10 @@ FREETYPEINC = /usr/include/freetype2 -++ -++ # includes and libs -++ INCS = -I${X11INC} -I${FREETYPEINC} -++-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -+++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res -++ -++ # flags -++-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -+++CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -++ #CFLAGS = -g -std=c99 -pedantic -Wall -O0 ${INCS} ${CPPFLAGS} -++ CFLAGS = -std=c99 -pedantic -Wall -Wno-deprecated-declarations -Os ${INCS} ${CPPFLAGS} -++ LDFLAGS = ${LIBS} -++diff --git a/dwm.1 b/dwm.1 -++index ddc8321..0ec6c60 100644 -++--- a/dwm.1 -+++++ b/dwm.1 -++@@ -12,10 +12,11 @@ environment for the application in use and the task performed. -++ 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. -+++adjusted from zero to an arbitrary number. Windows in both the master and stack -+++can be resized vertically, as well as resizing the master area. 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. -++ .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. -++@@ -24,10 +25,13 @@ 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. -+++before the window's title. The selected tags are indicated with a different -+++color. The focused window is represented by a long line before the tags which -+++are applied to it, and all other windows are represented by dots for all their -+++corresponding tags. -+++.P -+++The attach below patch makes newly spawned windows attach after the currently -+++selected window -++ .P -++ dwm draws a small border around windows to indicate the focus state. -++ .SH OPTIONS -++@@ -56,41 +60,28 @@ click on a tag label applies that tag to the focused window. -++ click on a tag label adds/removes that tag to/from the focused window. -++ .SS Keyboard commands -++ .TP -++-.B Mod1\-Shift\-Return -+++.B Mod1\-Return -++ Start -+++.BR tabbed(1) -+++Running -++ .BR st(1). -++ .TP -++ .B Mod1\-p -+++Spawn passmenu. -+++.TP -+++.B Mod1\-d -++ Spawn -++ .BR dmenu(1) -++ for launching other programs. -++ .TP -++-.B Mod1\-, -++-Focus previous screen, if any. -++-.TP -++-.B Mod1\-. -++-Focus next screen, if any. -++-.TP -++-.B Mod1\-Shift\-, -++-Send focused window to previous screen, if any. -++-.TP -++-.B Mod1\-Shift\-. -++-Send focused window to next screen, if any. -++-.TP -++ .B Mod1\-b -++ Toggles bar on and off. -++ .TP -++-.B Mod1\-t -++-Sets tiled layout. -+++.B Mod1\-Shift\-j -+++Push the selected client window down the stack -++ .TP -++-.B Mod1\-f -++-Sets floating layout. -++-.TP -++-.B Mod1\-m -++-Sets monocle layout. -++-.TP -++-.B Mod1\-space -++-Toggles between current and previous layout. -+++.B Mod1\-Shift\-k -+++Push the selected client window up the stack -++ .TP -++ .B Mod1\-j -++ Focus next window. -++@@ -98,50 +89,91 @@ Focus next window. -++ .B Mod1\-k -++ Focus previous window. -++ .TP -++-.B Mod1\-i -++-Increase number of windows in master area. -+++.B Mod1\-, -+++Increase the number of master windows. -++ .TP -++-.B Mod1\-d -++-Decrease number of windows in master area. -+++.B Mod1\-. -+++Decrease the number of master windows. -+++.TP -+++.B Mod1\-h -+++Decrease master area size. -++ .TP -++ .B Mod1\-l -++ Increase master area size. -++ .TP -++-.B Mod1\-h -++-Decrease master area size. -+++.B Mod1\-Shift\-h -+++Increase the size ratio of the selected client -++ .TP -++-.B Mod1\-Return -+++.B Mod1\-Shift\-l -+++Decrease the size ratio of the selected client -+++.B Mod1\-Shift\-o -+++Reset the size ratio of the selected client -+++.TP -+++.B Mod1\-Shift\-Return -++ Zooms/cycles focused window to/from master area (tiled layouts only). -++ .TP -++-.B Mod1\-Shift\-c -+++.B Mod1\-Tab -+++Toggles to the previously selected tags. -+++.TP -+++.B Mod1\-Shift\-q -++ Close focused window. -++ .TP -+++.B Mod1\-t -+++Sets tiled layout. -+++.TP -+++.B Mod1\-s -+++Sets floating layout. -+++.TP -+++.B Mod1\-m -+++Sets monocle layout. -+++.TP -++ .B Mod1\-Shift\-space -++-Toggle focused window between tiled and floating state. -+++Toggles between current and previous layout. -++ .TP -++-.B Mod1\-Tab -++-Toggles to the previously selected tags. -+++.B Mod1\-space -+++Toggles the selected window into the floating state. -++ .TP -++-.B Mod1\-Shift\-[1..n] -++-Apply nth tag to focused window. -+++.B Mod1\-f -+++Toggle the selected window into the fullscreen state. -+++.TP -+++.B Mod1\-0 -+++View all windows with any tag. -++ .TP -++ .B Mod1\-Shift\-0 -++ Apply all tags to focused window. -++ .TP -+++.B Mod1\-Shift\-, -+++Change focus to previous screen, if any. -+++.TP -+++.B Mod1\-Shift\-. -+++Change focus to next screen, if any. -+++.TP -+++.B Mod1\-Control\-Shift\-, -+++Send focused window to previous screen, if any. -+++.TP -+++.B Mod1\-Control\-Shift\-. -+++Send focused window to next screen, if any. -+++.TP -+++.B Mod1\-Shift\-[1..n] -+++Apply nth tag to focused window. -+++.TP -++ .B Mod1\-Control\-Shift\-[1..n] -++ Add/remove nth tag to/from focused window. -++ .TP -++ .B Mod1\-[1..n] -++ View all windows with nth tag. -++ .TP -++-.B Mod1\-0 -++-View all windows with any tag. -++-.TP -++ .B Mod1\-Control\-[1..n] -++ Add/remove all windows with nth tag to/from the view. -++ .TP -++-.B Mod1\-Shift\-q -+++.B Mod1\-Shift\-e -++ Quit dwm. -+++.TP -+++.B Mod1\-Shift\-r -+++Restart dwm. -+++.TP -+++.B Mod1\-Shift\-Tab -+++Toggle AttachBelow patch -++ .SS Mouse commands -++ .TP -++ .B Mod1\-Button1 -++@@ -155,6 +187,41 @@ Resize focused window while dragging. Tiled windows will be toggled to the float -++ .SH CUSTOMIZATION -++ dwm is customized by creating a custom config.h and (re)compiling the source -++ code. This keeps it fast, secure and simple. -+++.SH SIGNALS -+++.TP -+++.B SIGHUP - 1 -+++Restart the dwm process. -+++.TP -+++.B SIGTERM - 15 -+++Cleanly terminate the dwm process. -+++.SH PATCHES -+++This version of dwm was compiled using the: -+++.TP -+++.B dwm-actualfullscreen-20191112-cb3f58a.diff -+++.TP -+++.B dwm-attachbelow-toggleable-6.2.diff -+++.TP -+++.B dwm-autostart-20161205-bb3bd6f.diff -+++.TP -+++.B dwm-cfacts-20200913-61bb8b2.diff -+++.TP -+++.B dwm-clientindicators-6.2.diff -+++.TP -+++.B dwm-dwmc-6.2.diff -+++.TP -+++.B dwm-push_no_master-6.2.diff -+++.TP -+++.B dwm-restartsig-20180523-6.2.diff -+++.TP -+++.B dwm-statuscmd-signal-6.2.diff -+++.TP -+++.B dwm-swallow-20200522-7accbcf.diff -+++.TP -+++.B dwm-systray-6.2.diff -+++.TP -+++.B dwm-uselessgap-6.2.diff -+++.TP -+++.B dwm-zoomswap-6.2.diff -++ .SH SEE ALSO -++ .BR dmenu (1), -++ .BR st (1) -++diff --git a/dwm.c b/dwm.c -++index 664c527..cecbe53 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -40,6 +40,8 @@ -++ #include <X11/extensions/Xinerama.h> -++ #endif /* XINERAMA */ -++ #include <X11/Xft/Xft.h> -+++#include <X11/Xlib-xcb.h> -+++#include <xcb/res.h> -++ -++ #include "drw.h" -++ #include "util.h" -++@@ -52,17 +54,35 @@ -++ #define ISVISIBLE(C) ((C->tags & 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) -++-#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -+++#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) -+++#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) -++ #define TAGMASK ((1 << LENGTH(tags)) - 1) -++ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -++ -+++#define SYSTEM_TRAY_REQUEST_DOCK 0 -+++ -+++/* XEMBED messages */ -+++#define XEMBED_EMBEDDED_NOTIFY 0 -+++#define XEMBED_WINDOW_ACTIVATE 1 -+++#define XEMBED_FOCUS_IN 4 -+++#define XEMBED_MODALITY_ON 10 -+++ -+++#define XEMBED_MAPPED (1 << 0) -+++#define XEMBED_WINDOW_ACTIVATE 1 -+++#define XEMBED_WINDOW_DEACTIVATE 2 -+++ -+++#define VERSION_MAJOR 0 -+++#define VERSION_MINOR 0 -+++#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR -+++ -++ /* enums */ -++ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -++ enum { SchemeNorm, SchemeSel }; /* color schemes */ -++ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, -+++ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, -++ NetWMFullscreen, NetActiveWindow, NetWMWindowType, -++ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -+++enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ -++ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -++ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -++ ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ -++@@ -87,14 +107,17 @@ typedef struct Client Client; -++ struct Client { -++ char name[256]; -++ float mina, maxa; -+++ float cfact; -++ int x, y, w, h; -++ int oldx, oldy, oldw, oldh; -++ int basew, baseh, incw, inch, maxw, maxh, minw, minh; -++ int bw, oldbw; -++ unsigned int tags; -++- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -+++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; -+++ pid_t pid; -++ Client *next; -++ Client *snext; -+++ Client *swallowing; -++ Monitor *mon; -++ Window win; -++ }; -++@@ -106,6 +129,11 @@ typedef struct { -++ const Arg arg; -++ } Key; -++ -+++typedef struct { -+++ const char * sig; -+++ void (*func)(const Arg *); -+++} Signal; -+++ -++ typedef struct { -++ const char *symbol; -++ void (*arrange)(Monitor *); -++@@ -138,16 +166,27 @@ typedef struct { -++ const char *title; -++ unsigned int tags; -++ int isfloating; -+++ int isterminal; -+++ int noswallow; -++ int monitor; -++ } Rule; -++ -+++typedef struct Systray Systray; -+++struct Systray { -+++ Window win; -+++ Client *icons; -+++}; -+++ -++ /* function declarations */ -++ static void applyrules(Client *c); -++ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -++ static void arrange(Monitor *m); -++ static void arrangemon(Monitor *m); -++ static void attach(Client *c); -+++static void attachBelow(Client *c); -+++static void toggleAttachBelow(); -++ static void attachstack(Client *c); -+++static int fake_signal(void); -++ static void buttonpress(XEvent *e); -++ static void checkotherwm(void); -++ static void cleanup(void); -++@@ -156,6 +195,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); -++@@ -165,13 +205,16 @@ static void drawbar(Monitor *m); -++ static void drawbars(void); -++ static void enternotify(XEvent *e); -++ static void expose(XEvent *e); -+++static Client *findbefore(Client *c); -++ static void focus(Client *c); -++ static void focusin(XEvent *e); -++ static void focusmon(const Arg *arg); -++ static void focusstack(const Arg *arg); -+++static int getdwmblockspid(); -++ static Atom getatomprop(Client *c, Atom prop); -++ static int getrootptr(int *x, int *y); -++ static long getstate(Window w); -+++static unsigned int getsystraywidth(); -++ static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -++ static void grabbuttons(Client *c, int focused); -++ static void grabkeys(void); -++@@ -185,33 +228,46 @@ static void monocle(Monitor *m); -++ static void motionnotify(XEvent *e); -++ static void movemouse(const Arg *arg); -++ static Client *nexttiled(Client *c); -++-static void pop(Client *); -+++//static void pop(Client *); -+++static Client *prevtiled(Client *c); -++ static void propertynotify(XEvent *e); -+++static void pushdown(const Arg *arg); -+++static void pushup(const Arg *arg); -++ static void quit(const Arg *arg); -++ 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); -+++static void resizebarwin(Monitor *m); -++ static void resizeclient(Client *c, int x, int y, int w, int h); -++ static void resizemouse(const Arg *arg); -+++static void resizerequest(XEvent *e); -++ static void restack(Monitor *m); -++ static void run(void); -+++static void runAutostart(void); -++ static void scan(void); -++-static int sendevent(Client *c, Atom proto); -+++static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); -++ static void sendmon(Client *c, Monitor *m); -++ static void setclientstate(Client *c, long state); -++ static void setfocus(Client *c); -++ static void setfullscreen(Client *c, int fullscreen); -++ static void setlayout(const Arg *arg); -+++static void setcfact(const Arg *arg); -++ static void setmfact(const Arg *arg); -++ static void setup(void); -++ static void seturgent(Client *c, int urg); -++ static void showhide(Client *c); -++ static void sigchld(int unused); -+++static void sigdwmblocks(const Arg *arg); -+++static void sighup(int unused); -+++static void sigterm(int unused); -++ static void spawn(const Arg *arg); -+++static Monitor *systraytomon(Monitor *m); -++ static void tag(const Arg *arg); -++ static void tagmon(const Arg *arg); -++ static void tile(Monitor *); -++ static void togglebar(const Arg *arg); -++ static void togglefloating(const Arg *arg); -+++static void togglefullscr(const Arg *arg); -++ static void toggletag(const Arg *arg); -++ static void toggleview(const Arg *arg); -++ static void unfocus(Client *c, int setfocus); -++@@ -224,20 +280,36 @@ static int updategeom(void); -++ static void updatenumlockmask(void); -++ static void updatesizehints(Client *c); -++ static void updatestatus(void); -+++static void updatesystray(void); -+++static void updatesystrayicongeom(Client *i, int w, int h); -+++static void updatesystrayiconstate(Client *i, XPropertyEvent *ev); -++ static void updatetitle(Client *c); -++ static void updatewindowtype(Client *c); -++ static void updatewmhints(Client *c); -++ static void view(const Arg *arg); -++ static Client *wintoclient(Window w); -++ static Monitor *wintomon(Window w); -+++static Client *wintosystrayicon(Window w); -++ static int xerror(Display *dpy, XErrorEvent *ee); -++ static int xerrordummy(Display *dpy, XErrorEvent *ee); -++ static int xerrorstart(Display *dpy, XErrorEvent *ee); -++ static void zoom(const Arg *arg); -++ -+++static pid_t getparentprocess(pid_t p); -+++static int isdescprocess(pid_t p, pid_t c); -+++static Client *swallowingclient(Window w); -+++static Client *termforwin(const Client *c); -+++static pid_t winpid(Window w); -+++ -++ /* variables */ -+++static Client *prevzoom = NULL; -+++static Systray *systray = NULL; -++ static const char broken[] = "broken"; -++ static char stext[256]; -+++static char rawstext[256]; -+++static int dwmblockssig; -+++pid_t dwmblockspid = 0; -+++static int scanner; -++ static int screen; -++ static int sw, sh; /* X display screen geometry width, height */ -++ static int bh, blw = 0; /* bar geometry */ -++@@ -258,9 +330,11 @@ static void (*handler[LASTEvent]) (XEvent *) = { -++ [MapRequest] = maprequest, -++ [MotionNotify] = motionnotify, -++ [PropertyNotify] = propertynotify, -+++ [ResizeRequest] = resizerequest, -++ [UnmapNotify] = unmapnotify -++ }; -++-static Atom wmatom[WMLast], netatom[NetLast]; -+++static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast]; -+++static int restart = 0; -++ static int running = 1; -++ static Cur *cursor[CurLast]; -++ static Clr **scheme; -++@@ -269,6 +343,8 @@ static Drw *drw; -++ static Monitor *mons, *selmon; -++ static Window root, wmcheckwin; -++ -+++static xcb_connection_t *xcon; -+++ -++ /* configuration, allows nested code to access above variables */ -++ #include "config.h" -++ -++@@ -286,6 +362,7 @@ applyrules(Client *c) -++ XClassHint ch = { NULL, NULL }; -++ -++ /* rule matching */ -+++ c->noswallow = -1; -++ c->isfloating = 0; -++ c->tags = 0; -++ XGetClassHint(dpy, c->win, &ch); -++@@ -298,6 +375,8 @@ applyrules(Client *c) -++ && (!r->class || strstr(class, r->class)) -++ && (!r->instance || strstr(instance, r->instance))) -++ { -+++ c->isterminal = r->isterminal; -+++ c->noswallow = r->noswallow; -++ c->isfloating = r->isfloating; -++ c->tags |= r->tags; -++ for (m = mons; m && m->num != r->monitor; m = m->next); -++@@ -406,6 +485,26 @@ attach(Client *c) -++ c->next = c->mon->clients; -++ c->mon->clients = c; -++ } -+++void -+++attachBelow(Client *c) -+++{ -+++ //If there is nothing on the monitor or the selected client is floating, attach as normal -+++ if(c->mon->sel == NULL || c->mon->sel->isfloating) { -+++ attach(c); -+++ return; -+++ } -+++ -+++ //Set the new client's next property to the same as the currently selected clients next -+++ c->next = c->mon->sel->next; -+++ //Set the currently selected clients next property to the new client -+++ c->mon->sel->next = c; -+++ -+++} -+++ -+++void toggleAttachBelow() -+++{ -+++ attachbelow = !attachbelow; -+++} -++ -++ void -++ attachstack(Client *c) -++@@ -414,6 +513,61 @@ attachstack(Client *c) -++ c->mon->stack = c; -++ } -++ -+++void -+++swallow(Client *p, Client *c) -+++{ -+++ Client *s; -+++ -+++ if (c->noswallow > 0 || c->isterminal) -+++ return; -+++ if (c->noswallow < 0 && !swallowfloating && c->isfloating) -+++ return; -+++ -+++ detach(c); -+++ detachstack(c); -+++ -+++ setclientstate(c, WithdrawnState); -+++ XUnmapWindow(dpy, p->win); -+++ -+++ p->swallowing = c; -+++ c->mon = p->mon; -+++ -+++ Window w = p->win; -+++ p->win = c->win; -+++ c->win = w; -+++ -+++ XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace, -+++ (unsigned char *) &(p->win), 1); -+++ -+++ updatetitle(p); -+++ s = scanner ? c : p; -+++ XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h); -+++ arrange(p->mon); -+++ configure(p); -+++ updateclientlist(); -+++} -+++ -+++void -+++unswallow(Client *c) -+++{ -+++ c->win = c->swallowing->win; -+++ -+++ free(c->swallowing); -+++ c->swallowing = NULL; -+++ -+++ XDeleteProperty(dpy, c->win, netatom[NetClientList]); -+++ -+++ /* unfullscreen the client */ -+++ setfullscreen(c, 0); -+++ updatetitle(c); -+++ arrange(c->mon); -+++ XMapWindow(dpy, c->win); -+++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); -+++ setclientstate(c, NormalState); -+++ focus(NULL); -+++ arrange(c->mon); -+++} -+++ -++ void -++ buttonpress(XEvent *e) -++ { -++@@ -440,9 +594,25 @@ 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 > (x = selmon->ww - (int)TEXTW(stext) + lrpad - getsystraywidth())) { -++ click = ClkStatusText; -++- else -+++ char *text = rawstext; -+++ int i = -1; -+++ char ch; -+++ dwmblockssig = 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; -+++ dwmblockssig = ch; -+++ } -+++ } -+++ } else -++ click = ClkWinTitle; -++ } else if ((c = wintoclient(ev->window))) { -++ focus(c); -++@@ -483,6 +653,11 @@ cleanup(void) -++ XUngrabKey(dpy, AnyKey, AnyModifier, root); -++ while (mons) -++ cleanupmon(mons); -+++ if (showsystray) { -+++ XUnmapWindow(dpy, systray->win); -+++ XDestroyWindow(dpy, systray->win); -+++ free(systray); -+++ } -++ for (i = 0; i < CurLast; i++) -++ drw_cur_free(drw, cursor[i]); -++ for (i = 0; i < LENGTH(colors); i++) -++@@ -513,9 +688,57 @@ cleanupmon(Monitor *mon) -++ void -++ clientmessage(XEvent *e) -++ { -+++ XWindowAttributes wa; -+++ XSetWindowAttributes swa; -++ XClientMessageEvent *cme = &e->xclient; -++ Client *c = wintoclient(cme->window); -++ -+++ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) { -+++ /* add systray icons */ -+++ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) { -+++ if (!(c = (Client *)calloc(1, sizeof(Client)))) -+++ die("fatal: could not malloc() %u bytes\n", sizeof(Client)); -+++ if (!(c->win = cme->data.l[2])) { -+++ free(c); -+++ return; -+++ } -+++ c->mon = selmon; -+++ c->next = systray->icons; -+++ systray->icons = c; -+++ if (!XGetWindowAttributes(dpy, c->win, &wa)) { -+++ /* use sane defaults */ -+++ wa.width = bh; -+++ wa.height = bh; -+++ wa.border_width = 0; -+++ } -+++ c->x = c->oldx = c->y = c->oldy = 0; -+++ c->w = c->oldw = wa.width; -+++ c->h = c->oldh = wa.height; -+++ c->oldbw = wa.border_width; -+++ c->bw = 0; -+++ c->isfloating = True; -+++ /* reuse tags field as mapped status */ -+++ c->tags = 1; -+++ updatesizehints(c); -+++ updatesystrayicongeom(c, wa.width, wa.height); -+++ XAddToSaveSet(dpy, c->win); -+++ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); -+++ XReparentWindow(dpy, c->win, systray->win, 0, 0); -+++ /* use parents background color */ -+++ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -+++ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa); -+++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -+++ /* FIXME not sure if I have to send these events, too */ -+++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -+++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -+++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -+++ XSync(dpy, False); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ setclientstate(c, NormalState); -+++ } -+++ return; -+++ } -++ if (!c) -++ return; -++ if (cme->message_type == netatom[NetWMState]) { -++@@ -568,7 +791,7 @@ configurenotify(XEvent *e) -++ for (c = m->clients; c; c = c->next) -++ if (c->isfullscreen) -++ resizeclient(c, m->mx, m->my, m->mw, m->mh); -++- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+++ resizebarwin(m); -++ } -++ focus(NULL); -++ arrange(NULL); -++@@ -628,6 +851,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) -++ { -++@@ -653,6 +889,15 @@ destroynotify(XEvent *e) -++ -++ if ((c = wintoclient(ev->window))) -++ unmanage(c, 1); -+++ -+++ else if ((c = wintosystrayicon(ev->window))) { -+++ removesystrayicon(c); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ } -+++ -+++ else if ((c = swallowingclient(ev->window))) -+++ unmanage(c->swallowing, 1); -++ } -++ -++ void -++@@ -696,18 +941,24 @@ dirtomon(int dir) -++ void -++ drawbar(Monitor *m) -++ { -++- int x, w, tw = 0; -+++ int indn; -+++ int x, w, tw = 0, stw = 0; -++ int boxs = drw->fonts->h / 9; -++ int boxw = drw->fonts->h / 6 + 2; -++ unsigned int i, occ = 0, urg = 0; -++ Client *c; -++ -+++ if(showsystray && m == systraytomon(m)) -+++ stw = getsystraywidth(); -+++ -++ /* 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]); -++- tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -++- drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); -++- } -+++ tw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding */ -+++ drw_text(drw, m->ww - tw - stw, 0, tw, bh, lrpad / 2 - 2, stext, 0); -+++ } -+++ -+++ resizebarwin(m); -++ -++ for (c = m->clients; c; c = c->next) { -++ occ |= c->tags; -++@@ -716,20 +967,24 @@ drawbar(Monitor *m) -++ } -++ x = 0; -++ for (i = 0; i < LENGTH(tags); i++) { -+++ indn = 0; -++ 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); -+++ for (c = m->clients; c; c = c->next) { -+++ if (c->tags & (1 << i)) { -+++ drw_rect(drw, x, 1 + (indn * 2), selmon->sel == c ? 6 : 1, 1, 1, urg & 1 << i); -+++ indn++; -+++ } -+++ } -+++ -++ x += w; -++ } -++ w = blw = TEXTW(m->ltsymbol); -++ drw_setscheme(drw, scheme[SchemeNorm]); -++ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); -++ -++- if ((w = m->ww - tw - x) > bh) { -+++ if ((w = m->ww - tw - stw - x) > bh) { -++ if (m->sel) { -++ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -++ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -++@@ -740,7 +995,7 @@ drawbar(Monitor *m) -++ drw_rect(drw, x, 0, w, bh, 1, 1); -++ } -++ } -++- drw_map(drw, m->barwin, 0, 0, m->ww, bh); -+++ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh); -++ } -++ -++ void -++@@ -777,8 +1032,21 @@ expose(XEvent *e) -++ Monitor *m; -++ XExposeEvent *ev = &e->xexpose; -++ -++- if (ev->count == 0 && (m = wintomon(ev->window))) -+++ if (ev->count == 0 && (m = wintomon(ev->window))) { -++ drawbar(m); -+++ if (m == selmon) -+++ updatesystray(); -+++ } -+++} -+++ -+++Client * -+++findbefore(Client *c) -+++{ -+++ Client *tmp; -+++ if (c == selmon->clients) -+++ return NULL; -+++ for (tmp = selmon->clients; tmp && tmp->next != c; tmp = tmp->next); -+++ return tmp; -++ } -++ -++ void -++@@ -863,15 +1131,34 @@ getatomprop(Client *c, Atom prop) -++ unsigned long dl; -++ unsigned char *p = NULL; -++ Atom da, atom = None; -+++ /* FIXME getatomprop should return the number of items and a pointer to -+++ * the stored data instead of this workaround */ -+++ Atom req = XA_ATOM; -+++ if (prop == xatom[XembedInfo]) -+++ req = xatom[XembedInfo]; -++ -++- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, -+++ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, -++ &da, &di, &dl, &dl, &p) == Success && p) { -++ atom = *(Atom *)p; -+++ if (da == xatom[XembedInfo] && dl == 2) -+++ atom = ((Atom *)p)[1]; -++ XFree(p); -++ } -++ return atom; -++ } -++ -+++int -+++getdwmblockspid() -+++{ -+++ char buf[16]; -+++ FILE *fp = popen("pidof -s dwmblocks", "r"); -+++ fgets(buf, sizeof(buf), fp); -+++ pid_t pid = strtoul(buf, NULL, 10); -+++ pclose(fp); -+++ dwmblockspid = pid; -+++ return pid != 0 ? 0 : -1; -+++} -+++ -++ int -++ getrootptr(int *x, int *y) -++ { -++@@ -900,6 +1187,16 @@ getstate(Window w) -++ return result; -++ } -++ -+++unsigned int -+++getsystraywidth() -+++{ -+++ unsigned int w = 0; -+++ Client *i; -+++ if(showsystray) -+++ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ; -+++ return w ? w + systrayspacing : 1; -+++} -+++ -++ int -++ gettextprop(Window w, Atom atom, char *text, unsigned int size) -++ { -++@@ -999,12 +1296,55 @@ keypress(XEvent *e) -++ keys[i].func(&(keys[i].arg)); -++ } -++ -+++int -+++fake_signal(void) -+++{ -+++ char fsignal[256]; -+++ char indicator[9] = "fsignal:"; -+++ char str_sig[50]; -+++ char param[16]; -+++ int i, len_str_sig, n, paramn; -+++ size_t len_fsignal, len_indicator = strlen(indicator); -+++ Arg arg; -+++ -+++ // Get root name property -+++ if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) { -+++ len_fsignal = strlen(fsignal); -+++ -+++ // Check if this is indeed a fake signal -+++ if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) { -+++ paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n); -+++ -+++ if (paramn == 1) arg = (Arg) {0}; -+++ else if (paramn > 2) return 1; -+++ else if (strncmp(param, "i", n - len_str_sig) == 0) -+++ sscanf(fsignal + len_indicator + n, "%i", &(arg.i)); -+++ else if (strncmp(param, "ui", n - len_str_sig) == 0) -+++ sscanf(fsignal + len_indicator + n, "%u", &(arg.ui)); -+++ else if (strncmp(param, "f", n - len_str_sig) == 0) -+++ sscanf(fsignal + len_indicator + n, "%f", &(arg.f)); -+++ else return 1; -+++ -+++ // Check if a signal was found, and if so handle it -+++ for (i = 0; i < LENGTH(signals); i++) -+++ if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func) -+++ signals[i].func(&(arg)); -+++ -+++ // A fake signal was sent -+++ return 1; -+++ } -+++ } -+++ -+++ // No fake signal was sent, so proceed with update -+++ return 0; -+++} -+++ -++ void -++ killclient(const Arg *arg) -++ { -++ if (!selmon->sel) -++ return; -++- if (!sendevent(selmon->sel, wmatom[WMDelete])) { -+++ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) { -++ XGrabServer(dpy); -++ XSetErrorHandler(xerrordummy); -++ XSetCloseDownMode(dpy, DestroyAll); -++@@ -1018,18 +1358,20 @@ killclient(const Arg *arg) -++ void -++ manage(Window w, XWindowAttributes *wa) -++ { -++- Client *c, *t = NULL; -+++ Client *c, *t = NULL, *term = NULL; -++ Window trans = None; -++ XWindowChanges wc; -++ -++ c = ecalloc(1, sizeof(Client)); -++ c->win = w; -+++ c->pid = winpid(w); -++ /* geometry */ -++ c->x = c->oldx = wa->x; -++ c->y = c->oldy = wa->y; -++ c->w = c->oldw = wa->width; -++ c->h = c->oldh = wa->height; -++ c->oldbw = wa->border_width; -+++ c->cfact = 1.0; -++ -++ updatetitle(c); -++ if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { -++@@ -1038,6 +1380,7 @@ manage(Window w, XWindowAttributes *wa) -++ } else { -++ c->mon = selmon; -++ applyrules(c); -+++ term = termforwin(c); -++ } -++ -++ if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) -++@@ -1063,7 +1406,10 @@ manage(Window w, XWindowAttributes *wa) -++ c->isfloating = c->oldstate = trans != None || c->isfixed; -++ if (c->isfloating) -++ XRaiseWindow(dpy, c->win); -++- attach(c); -+++ if( attachbelow ) -+++ attachBelow(c); -+++ else -+++ attach(c); -++ attachstack(c); -++ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, -++ (unsigned char *) &(c->win), 1); -++@@ -1074,6 +1420,8 @@ manage(Window w, XWindowAttributes *wa) -++ c->mon->sel = c; -++ arrange(c->mon); -++ XMapWindow(dpy, c->win); -+++ if (term) -+++ swallow(term, c); -++ focus(NULL); -++ } -++ -++@@ -1092,6 +1440,12 @@ maprequest(XEvent *e) -++ { -++ static XWindowAttributes wa; -++ XMapRequestEvent *ev = &e->xmaprequest; -+++ Client *i; -+++ if ((i = wintosystrayicon(ev->window))) { -+++ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ } -++ -++ if (!XGetWindowAttributes(dpy, ev->window, &wa)) -++ return; -++@@ -1200,6 +1554,7 @@ nexttiled(Client *c) -++ return c; -++ } -++ -+++/* -++ void -++ pop(Client *c) -++ { -++@@ -1208,6 +1563,17 @@ pop(Client *c) -++ focus(c); -++ arrange(c->mon); -++ } -+++*/ -+++ -+++Client * -+++prevtiled(Client *c) { -+++ Client *p, *r; -+++ -+++ for(p = selmon->clients, r = NULL; p && p != c; p = p->next) -+++ if(!p->isfloating && ISVISIBLE(p)) -+++ r = p; -+++ return r; -+++} -++ -++ void -++ propertynotify(XEvent *e) -++@@ -1216,8 +1582,20 @@ propertynotify(XEvent *e) -++ Window trans; -++ XPropertyEvent *ev = &e->xproperty; -++ -++- if ((ev->window == root) && (ev->atom == XA_WM_NAME)) -++- updatestatus(); -+++ if ((c = wintosystrayicon(ev->window))) { -+++ if (ev->atom == XA_WM_NORMAL_HINTS) { -+++ updatesizehints(c); -+++ updatesystrayicongeom(c, c->w, c->h); -+++ } else -+++ updatesystrayiconstate(c, ev); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ -+++ } -+++ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) { -+++ if (!fake_signal()) -+++ updatestatus(); -+++ } -++ else if (ev->state == PropertyDelete) -++ return; /* ignore */ -++ else if ((c = wintoclient(ev->window))) { -++@@ -1246,9 +1624,41 @@ propertynotify(XEvent *e) -++ } -++ } -++ -+++void -+++pushdown(const Arg *arg) { -+++ Client *sel = selmon->sel, *c; -+++ -+++ if(!sel || sel->isfloating || sel == nexttiled(selmon->clients)) -+++ return; -+++ if((c = nexttiled(sel->next))) { -+++ detach(sel); -+++ sel->next = c->next; -+++ c->next = sel; -+++ } -+++ focus(sel); -+++ arrange(selmon); -+++} -+++ -+++void -+++pushup(const Arg *arg) { -+++ Client *sel = selmon->sel, *c; -+++ -+++ if(!sel || sel->isfloating) -+++ return; -+++ if((c = prevtiled(sel)) && c != nexttiled(selmon->clients)) { -+++ detach(sel); -+++ sel->next = c; -+++ for(c = selmon->clients; c->next != sel->next; c = c->next); -+++ c->next = sel; -+++ } -+++ focus(sel); -+++ arrange(selmon); -+++} -+++ -++ void -++ quit(const Arg *arg) -++ { -+++ if(arg->i) restart = 1; -++ running = 0; -++ } -++ -++@@ -1266,6 +1676,20 @@ recttomon(int x, int y, int w, int h) -++ return r; -++ } -++ -+++void -+++removesystrayicon(Client *i) -+++{ -+++ Client **ii; -+++ -+++ if (!showsystray || !i) -+++ return; -+++ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); -+++ if (ii) -+++ *ii = i->next; -+++ free(i); -+++} -+++ -+++ -++ void -++ resize(Client *c, int x, int y, int w, int h, int interact) -++ { -++@@ -1273,16 +1697,48 @@ resize(Client *c, int x, int y, int w, int h, int interact) -++ resizeclient(c, x, y, w, h); -++ } -++ -+++void -+++resizebarwin(Monitor *m) { -+++ unsigned int w = m->ww; -+++ if (showsystray && m == systraytomon(m)) -+++ w -= getsystraywidth(); -+++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); -+++} -+++ -++ void -++ resizeclient(Client *c, int x, int y, int w, int h) -++ { -++ XWindowChanges wc; -+++ unsigned int n; -+++ unsigned int gapoffset; -+++ unsigned int gapincr; -+++ Client *nbc; -++ -++- c->oldx = c->x; c->x = wc.x = x; -++- 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; -++ wc.border_width = c->bw; -+++ -+++ /* Get number of clients for the selected monitor */ -+++ for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); -+++ -+++ /* Do nothing if layout is floating */ -+++ if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { -+++ gapincr = gapoffset = 0; -+++ } else { -+++ /* Remove border and gap if layout is monocle or only one client */ -+++ if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) { -+++ gapoffset = 0; -+++ gapincr = -2 * borderpx; -+++ wc.border_width = 0; -+++ } else { -+++ gapoffset = gappx; -+++ gapincr = 2 * gappx; -+++ } -+++ } -+++ -+++ c->oldx = c->x; c->x = wc.x = x + gapoffset; -+++ c->oldy = c->y; c->y = wc.y = y + gapoffset; -+++ c->oldw = c->w; c->w = wc.width = w - gapincr; -+++ c->oldh = c->h; c->h = wc.height = h - gapincr; -+++ -++ XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); -++ configure(c); -++ XSync(dpy, False); -++@@ -1345,6 +1801,19 @@ resizemouse(const Arg *arg) -++ } -++ } -++ -+++void -+++resizerequest(XEvent *e) -+++{ -+++ XResizeRequestEvent *ev = &e->xresizerequest; -+++ Client *i; -+++ -+++ if ((i = wintosystrayicon(ev->window))) { -+++ updatesystrayicongeom(i, ev->width, ev->height); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ } -+++} -+++ -++ void -++ restack(Monitor *m) -++ { -++@@ -1381,10 +1850,18 @@ run(void) -++ handler[ev.type](&ev); /* call handler */ -++ } -++ -+++void -+++runAutostart(void) { -+++ system("cd ~; ./.config/dwm/autostart_blocking.sh"); -+++ system("cd ~; ./.config/dwm/autostart.sh &"); -+++} -+++ -++ void -++ scan(void) -++ { -+++ scanner = 1; -++ unsigned int i, num; -+++ char swin[256]; -++ Window d1, d2, *wins = NULL; -++ XWindowAttributes wa; -++ -++@@ -1395,6 +1872,8 @@ scan(void) -++ continue; -++ if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) -++ manage(wins[i], &wa); -+++ else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin)) -+++ manage(wins[i], &wa); -++ } -++ for (i = 0; i < num; i++) { /* now the transients */ -++ if (!XGetWindowAttributes(dpy, wins[i], &wa)) -++@@ -1406,6 +1885,7 @@ scan(void) -++ if (wins) -++ XFree(wins); -++ } -+++ scanner = 0; -++ } -++ -++ void -++@@ -1418,7 +1898,10 @@ sendmon(Client *c, Monitor *m) -++ detachstack(c); -++ c->mon = m; -++ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -++- attach(c); -+++ if( attachbelow ) -+++ attachBelow(c); -+++ else -+++ attach(c); -++ attachstack(c); -++ focus(NULL); -++ arrange(NULL); -++@@ -1434,26 +1917,36 @@ setclientstate(Client *c, long state) -++ } -++ -++ int -++-sendevent(Client *c, Atom proto) -+++sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) -++ { -++ int n; -++- Atom *protocols; -+++ Atom *protocols, mt; -++ int exists = 0; -++ XEvent ev; -++ -++- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { -++- while (!exists && n--) -++- exists = protocols[n] == proto; -++- XFree(protocols); -+++ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) { -+++ mt = wmatom[WMProtocols]; -+++ if (XGetWMProtocols(dpy, w, &protocols, &n)) { -+++ while (!exists && n--) -+++ exists = protocols[n] == proto; -+++ XFree(protocols); -+++ } -+++ } -+++ else { -+++ exists = True; -+++ mt = proto; -++ } -++ if (exists) { -++ ev.type = ClientMessage; -++- ev.xclient.window = c->win; -++- ev.xclient.message_type = wmatom[WMProtocols]; -+++ ev.xclient.window = w; -+++ ev.xclient.message_type = mt; -++ ev.xclient.format = 32; -++- ev.xclient.data.l[0] = proto; -++- ev.xclient.data.l[1] = CurrentTime; -++- XSendEvent(dpy, c->win, False, NoEventMask, &ev); -+++ ev.xclient.data.l[0] = d0; -+++ ev.xclient.data.l[1] = d1; -+++ ev.xclient.data.l[2] = d2; -+++ ev.xclient.data.l[3] = d3; -+++ ev.xclient.data.l[4] = d4; -+++ XSendEvent(dpy, w, False, mask, &ev); -++ } -++ return exists; -++ } -++@@ -1467,7 +1960,7 @@ setfocus(Client *c) -++ XA_WINDOW, 32, PropModeReplace, -++ (unsigned char *) &(c->win), 1); -++ } -++- sendevent(c, wmatom[WMTakeFocus]); -+++ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); -++ } -++ -++ void -++@@ -1512,6 +2005,23 @@ setlayout(const Arg *arg) -++ drawbar(selmon); -++ } -++ -+++void setcfact(const Arg *arg) { -+++ float f; -+++ Client *c; -+++ -+++ c = selmon->sel; -+++ -+++ if(!arg || !c || !selmon->lt[selmon->sellt]->arrange) -+++ return; -+++ f = arg->f + c->cfact; -+++ if(arg->f == 0.0) -+++ f = 1.0; -+++ else if(f < 0.25 || f > 4.0) -+++ return; -+++ c->cfact = f; -+++ arrange(selmon); -+++} -+++ -++ /* arg > 1.0 will set mfact absolutely */ -++ void -++ setmfact(const Arg *arg) -++@@ -1521,7 +2031,7 @@ setmfact(const Arg *arg) -++ if (!arg || !selmon->lt[selmon->sellt]->arrange) -++ return; -++ f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; -++- if (f < 0.05 || f > 0.95) -+++ if (f < 0.1 || f > 0.9) -++ return; -++ selmon->mfact = f; -++ arrange(selmon); -++@@ -1537,6 +2047,9 @@ setup(void) -++ /* clean up any zombies immediately */ -++ sigchld(0); -++ -+++ signal(SIGHUP, sighup); -+++ signal(SIGTERM, sigterm); -+++ -++ /* init screen */ -++ screen = DefaultScreen(dpy); -++ sw = DisplayWidth(dpy, screen); -++@@ -1556,6 +2069,10 @@ setup(void) -++ wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); -++ netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); -++ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); -+++ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False); -+++ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False); -+++ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False); -+++ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False); -++ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); -++ netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); -++ netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); -++@@ -1563,6 +2080,9 @@ setup(void) -++ netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); -++ netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); -++ netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); -+++ xatom[Manager] = XInternAtom(dpy, "MANAGER", False); -+++ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); -+++ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); -++ /* init cursors */ -++ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); -++ cursor[CurResize] = drw_cur_create(drw, XC_sizing); -++@@ -1571,6 +2091,8 @@ setup(void) -++ scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); -++ for (i = 0; i < LENGTH(colors); i++) -++ scheme[i] = drw_scm_create(drw, colors[i], 3); -+++ /* init system tray */ -+++ updatesystray(); -++ /* init bars */ -++ updatebars(); -++ updatestatus(); -++@@ -1637,6 +2159,37 @@ sigchld(int unused) -++ while (0 < waitpid(-1, NULL, WNOHANG)); -++ } -++ -+++void -+++sighup(int unused) -+++{ -+++ Arg a = {.i = 1}; -+++ quit(&a); -+++} -+++ -+++void -+++sigterm(int unused) -+++{ -+++ Arg a = {.i = 0}; -+++ quit(&a); -+++} -+++ -+++void -+++sigdwmblocks(const Arg *arg) -+++{ -+++ union sigval sv; -+++ sv.sival_int = (dwmblockssig << 8) | arg->i; -+++ if (!dwmblockspid) -+++ if (getdwmblockspid() == -1) -+++ return; -+++ -+++ if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) { -+++ if (errno == ESRCH) { -+++ if (!getdwmblockspid()) -+++ sigqueue(dwmblockspid, SIGUSR1, sv); -+++ } -+++ } -+++} -+++ -++ void -++ spawn(const Arg *arg) -++ { -++@@ -1675,9 +2228,15 @@ void -++ tile(Monitor *m) -++ { -++ unsigned int i, n, h, mw, my, ty; -+++ float mfacts = 0, sfacts = 0; -++ Client *c; -++ -++- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -+++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { -+++ if (n < m->nmaster) -+++ mfacts += c->cfact; -+++ else -+++ sfacts += c->cfact; -+++ } -++ if (n == 0) -++ return; -++ -++@@ -1687,15 +2246,19 @@ tile(Monitor *m) -++ mw = m->ww; -++ for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -++ if (i < m->nmaster) { -++- h = (m->wh - my) / (MIN(n, m->nmaster) - i); -+++ h = (m->wh - my) * (c->cfact / mfacts); -++ resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -++- if (my + HEIGHT(c) < m->wh) -+++ if (my + HEIGHT(c) < m->wh) { -++ my += HEIGHT(c); -+++ mfacts -= c->cfact; -+++ } -++ } else { -++- h = (m->wh - ty) / (n - i); -+++ h = (m->wh - ty) * (c->cfact / sfacts); -++ resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); -++- if (ty + HEIGHT(c) < m->wh) -+++ if (ty + HEIGHT(c) < m->wh) { -++ ty += HEIGHT(c); -+++ sfacts -= c->cfact; -+++ } -++ } -++ } -++ -++@@ -1704,7 +2267,18 @@ togglebar(const Arg *arg) -++ { -++ selmon->showbar = !selmon->showbar; -++ updatebarpos(selmon); -++- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); -+++ resizebarwin(selmon); -+++ if (showsystray) { -+++ XWindowChanges wc; -+++ if (!selmon->showbar) -+++ wc.y = -bh; -+++ else if (selmon->showbar) { -+++ wc.y = 0; -+++ if (!selmon->topbar) -+++ wc.y = selmon->mh - bh; -+++ } -+++ XConfigureWindow(dpy, systray->win, CWY, &wc); -+++ } -++ arrange(selmon); -++ } -++ -++@@ -1722,6 +2296,13 @@ togglefloating(const Arg *arg) -++ arrange(selmon); -++ } -++ -+++void -+++togglefullscr(const Arg *arg) -+++{ -+++ if(selmon->sel) -+++ setfullscreen(selmon->sel, !selmon->sel->isfullscreen); -+++} -+++ -++ void -++ toggletag(const Arg *arg) -++ { -++@@ -1768,6 +2349,20 @@ unmanage(Client *c, int destroyed) -++ Monitor *m = c->mon; -++ XWindowChanges wc; -++ -+++ if (c->swallowing) { -+++ unswallow(c); -+++ return; -+++ } -+++ -+++ Client *s = swallowingclient(c->win); -+++ if (s) { -+++ free(s->swallowing); -+++ s->swallowing = NULL; -+++ arrange(m); -+++ focus(NULL); -+++ return; -+++ } -+++ -++ detach(c); -++ detachstack(c); -++ if (!destroyed) { -++@@ -1782,9 +2377,12 @@ unmanage(Client *c, int destroyed) -++ XUngrabServer(dpy); -++ } -++ free(c); -++- focus(NULL); -++- updateclientlist(); -++- arrange(m); -+++ -+++ if (!s) { -+++ arrange(m); -+++ focus(NULL); -+++ updateclientlist(); -+++ } -++ } -++ -++ void -++@@ -1799,11 +2397,18 @@ unmapnotify(XEvent *e) -++ else -++ unmanage(c, 0); -++ } -+++ else if ((c = wintosystrayicon(ev->window))) { -+++ /* KLUDGE! sometimes icons occasionally unmap their windows, but do -+++ * _not_ destroy them. We map those windows back */ -+++ XMapRaised(dpy, c->win); -+++ updatesystray(); -+++ } -++ } -++ -++ void -++ updatebars(void) -++ { -+++ unsigned int w; -++ Monitor *m; -++ XSetWindowAttributes wa = { -++ .override_redirect = True, -++@@ -1814,10 +2419,15 @@ updatebars(void) -++ for (m = mons; m; m = m->next) { -++ if (m->barwin) -++ continue; -++- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -+++ w = m->ww; -+++ if (showsystray && m == systraytomon(m)) -+++ w -= getsystraywidth(); -+++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen), -++ CopyFromParent, DefaultVisual(dpy, screen), -++ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -++ XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); -+++ if (showsystray && m == systraytomon(m)) -+++ XMapRaised(dpy, systray->win); -++ XMapRaised(dpy, m->barwin); -++ XSetClassHint(dpy, m->barwin, &ch); -++ } -++@@ -1900,7 +2510,10 @@ updategeom(void) -++ m->clients = c->next; -++ detachstack(c); -++ c->mon = mons; -++- attach(c); -+++ if( attachbelow ) -+++ attachBelow(c); -+++ else -+++ attach(c); -++ attachstack(c); -++ } -++ if (m == selmon) -++@@ -1990,9 +2603,126 @@ 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); -+++ updatesystray(); -+++} -+++ -+++void -+++updatesystrayicongeom(Client *i, int w, int h) -+++{ -+++ if (i) { -+++ i->h = bh; -+++ if (w == h) -+++ i->w = bh; -+++ else if (h == bh) -+++ i->w = w; -+++ else -+++ i->w = (int) ((float)bh * ((float)w / (float)h)); -+++ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False); -+++ /* force icons into the systray dimensions if they don't want to */ -+++ if (i->h > bh) { -+++ if (i->w == i->h) -+++ i->w = bh; -+++ else -+++ i->w = (int) ((float)bh * ((float)i->w / (float)i->h)); -+++ i->h = bh; -+++ } -+++ } -+++} -+++ -+++void -+++updatesystrayiconstate(Client *i, XPropertyEvent *ev) -+++{ -+++ long flags; -+++ int code = 0; -+++ -+++ if (!showsystray || !i || ev->atom != xatom[XembedInfo] || -+++ !(flags = getatomprop(i, xatom[XembedInfo]))) -+++ return; -+++ -+++ if (flags & XEMBED_MAPPED && !i->tags) { -+++ i->tags = 1; -+++ code = XEMBED_WINDOW_ACTIVATE; -+++ XMapRaised(dpy, i->win); -+++ setclientstate(i, NormalState); -+++ } -+++ else if (!(flags & XEMBED_MAPPED) && i->tags) { -+++ i->tags = 0; -+++ code = XEMBED_WINDOW_DEACTIVATE; -+++ XUnmapWindow(dpy, i->win); -+++ setclientstate(i, WithdrawnState); -+++ } -+++ else -+++ return; -+++ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0, -+++ systray->win, XEMBED_EMBEDDED_VERSION); -+++} -+++ -+++void -+++updatesystray(void) -+++{ -+++ XSetWindowAttributes wa; -+++ XWindowChanges wc; -+++ Client *i; -+++ Monitor *m = systraytomon(NULL); -+++ unsigned int x = m->mx + m->mw; -+++ unsigned int w = 1; -+++ -+++ if (!showsystray) -+++ return; -+++ if (!systray) { -+++ /* init systray */ -+++ if (!(systray = (Systray *)calloc(1, sizeof(Systray)))) -+++ die("fatal: could not malloc() %u bytes\n", sizeof(Systray)); -+++ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel); -+++ wa.event_mask = ButtonPressMask | ExposureMask; -+++ wa.override_redirect = True; -+++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -+++ XSelectInput(dpy, systray->win, SubstructureNotifyMask); -+++ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, -+++ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1); -+++ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa); -+++ XMapRaised(dpy, systray->win); -+++ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime); -+++ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) { -+++ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0); -+++ XSync(dpy, False); -+++ } -+++ else { -+++ fprintf(stderr, "dwm: unable to obtain system tray.\n"); -+++ free(systray); -+++ systray = NULL; -+++ return; -+++ } -+++ } -+++ for (w = 0, i = systray->icons; i; i = i->next) { -+++ /* make sure the background color stays the same */ -+++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -+++ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa); -+++ XMapRaised(dpy, i->win); -+++ w += systrayspacing; -+++ i->x = w; -+++ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h); -+++ w += i->w; -+++ if (i->mon != m) -+++ i->mon = m; -+++ } -+++ w = w ? w + systrayspacing : 1; -+++ x -= w; -+++ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh); -+++ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh; -+++ wc.stack_mode = Above; wc.sibling = m->barwin; -+++ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc); -+++ XMapWindow(dpy, systray->win); -+++ XMapSubwindows(dpy, systray->win); -+++ /* redraw background */ -+++ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel); -+++ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh); -+++ XSync(dpy, False); -++ } -++ -++ void -++@@ -2047,6 +2777,110 @@ view(const Arg *arg) -++ arrange(selmon); -++ } -++ -+++pid_t -+++winpid(Window w) -+++{ -+++ pid_t result = 0; -+++ -+++ xcb_res_client_id_spec_t spec = {0}; -+++ spec.client = w; -+++ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; -+++ -+++ xcb_generic_error_t *e = NULL; -+++ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); -+++ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); -+++ -+++ if (!r) -+++ return (pid_t)0; -+++ -+++ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); -+++ for (; i.rem; xcb_res_client_id_value_next(&i)) { -+++ spec = i.data->spec; -+++ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { -+++ uint32_t *t = xcb_res_client_id_value_value(i.data); -+++ result = *t; -+++ break; -+++ } -+++ } -+++ -+++ free(r); -+++ -+++ if (result == (pid_t)-1) -+++ result = 0; -+++ return result; -+++} -+++ -+++pid_t -+++getparentprocess(pid_t p) -+++{ -+++ unsigned int v = 0; -+++ -+++#if defined(__linux__) -+++ FILE *f; -+++ char buf[256]; -+++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); -+++ -+++ if (!(f = fopen(buf, "r"))) -+++ return (pid_t)0; -+++ -+++ if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1) -+++ v = (pid_t)0; -+++ fclose(f); -+++#elif defined(__FreeBSD__) -+++ struct kinfo_proc *proc = kinfo_getproc(p); -+++ if (!proc) -+++ return (pid_t)0; -+++ -+++ v = proc->ki_ppid; -+++ free(proc); -+++#endif -+++ return (pid_t)v; -+++} -+++ -+++int -+++isdescprocess(pid_t p, pid_t c) -+++{ -+++ while (p != c && c != 0) -+++ c = getparentprocess(c); -+++ -+++ return (int)c; -+++} -+++ -+++Client * -+++termforwin(const Client *w) -+++{ -+++ Client *c; -+++ Monitor *m; -+++ -+++ if (!w->pid || w->isterminal) -+++ return NULL; -+++ -+++ for (m = mons; m; m = m->next) { -+++ for (c = m->clients; c; c = c->next) { -+++ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) -+++ return c; -+++ } -+++ } -+++ -+++ return NULL; -+++} -+++ -+++Client * -+++swallowingclient(Window w) -+++{ -+++ Client *c; -+++ Monitor *m; -+++ -+++ for (m = mons; m; m = m->next) { -+++ for (c = m->clients; c; c = c->next) { -+++ if (c->swallowing && c->swallowing->win == w) -+++ return c; -+++ } -+++ } -+++ -+++ return NULL; -+++} -+++ -++ Client * -++ wintoclient(Window w) -++ { -++@@ -2060,6 +2894,16 @@ wintoclient(Window w) -++ return NULL; -++ } -++ -+++Client * -+++wintosystrayicon(Window w) { -+++ Client *i = NULL; -+++ -+++ if (!showsystray || !w) -+++ return i; -+++ for (i = systray->icons; i && i->win != w; i = i->next) ; -+++ return i; -+++} -+++ -++ Monitor * -++ wintomon(Window w) -++ { -++@@ -2113,18 +2957,58 @@ xerrorstart(Display *dpy, XErrorEvent *ee) -++ return -1; -++ } -++ -+++Monitor * -+++systraytomon(Monitor *m) { -+++ Monitor *t; -+++ int i, n; -+++ if(!systraypinning) { -+++ if(!m) -+++ return selmon; -+++ return m == selmon ? m : NULL; -+++ } -+++ for(n = 1, t = mons; t && t->next; n++, t = t->next) ; -+++ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ; -+++ if(systraypinningfailfirst && n < systraypinning) -+++ return mons; -+++ return t; -+++} -+++ -++ void -++ zoom(const Arg *arg) -++ { -++ Client *c = selmon->sel; -+++ Client *at = NULL, *cold, *cprevious = NULL; -++ -++ if (!selmon->lt[selmon->sellt]->arrange -++ || (selmon->sel && selmon->sel->isfloating)) -++ return; -++- if (c == nexttiled(selmon->clients)) -++- if (!c || !(c = nexttiled(c->next))) -++- return; -++- pop(c); -+++ if (c == nexttiled(selmon->clients)) { -+++ at = findbefore(prevzoom); -+++ if (at) -+++ cprevious = nexttiled(at->next); -+++ if (!cprevious || cprevious != prevzoom) { -+++ prevzoom = NULL; -+++ if (!c || !(c = nexttiled(c->next))) -+++ return; -+++ } else -+++ c = cprevious; -+++ } -+++ cold = nexttiled(selmon->clients); -+++ if (c != cold && !at) -+++ at = findbefore(c); -+++ detach(c); -+++ attach(c); -+++ /* swap windows instead of pushing the previous one down */ -+++ if (c != cold && at) { -+++ prevzoom = cold; -+++ if (cold && at != cold) { -+++ detach(cold); -+++ cold->next = at->next; -+++ at->next = cold; -+++ } -+++ } -+++ focus(c); -+++ arrange(c->mon); -++ } -++ -++ int -++@@ -2138,6 +3022,8 @@ main(int argc, char *argv[]) -++ fputs("warning: no locale support\n", stderr); -++ if (!(dpy = XOpenDisplay(NULL))) -++ die("dwm: cannot open display"); -+++ if (!(xcon = XGetXCBConnection(dpy))) -+++ die("dwm: cannot get xcb connection\n"); -++ checkotherwm(); -++ setup(); -++ #ifdef __OpenBSD__ -++@@ -2145,7 +3031,9 @@ main(int argc, char *argv[]) -++ die("pledge"); -++ #endif /* __OpenBSD__ */ -++ scan(); -++- run(); -+++ runAutostart(); -+++run(); -+++ if(restart) execvp(argv[0], argv); -++ cleanup(); -++ XCloseDisplay(dpy); -++ return EXIT_SUCCESS; -++diff --git a/dwm.c.orig b/dwm.c.orig -++new file mode 100644 -++index 0000000..664c527 -++--- /dev/null -+++++ b/dwm.c.orig -++@@ -0,0 +1,2152 @@ -+++/* See LICENSE file for copyright and license details. -+++ * -+++ * dynamic window manager is designed like any other X client as well. It is -+++ * driven through handling X events. In contrast to other X clients, a window -+++ * manager selects for SubstructureRedirectMask on the root window, to receive -+++ * events about window (dis-)appearance. Only one X connection at a time is -+++ * allowed to select for this event mask. -+++ * -+++ * The event handlers of dwm are organized in an array which is accessed -+++ * whenever a new event has been fetched. This allows event dispatching -+++ * in O(1) time. -+++ * -+++ * Each child of the root window is called a client, except windows which have -+++ * set the override_redirect flag. Clients are organized in a linked client -+++ * list on each monitor, the focus history is remembered through a stack list -+++ * on each monitor. Each client contains a bit array to indicate the tags of a -+++ * client. -+++ * -+++ * Keys and tagging rules are organized as arrays and defined in config.h. -+++ * -+++ * To understand everything else, start reading main(). -+++ */ -+++#include <errno.h> -+++#include <locale.h> -+++#include <signal.h> -+++#include <stdarg.h> -+++#include <stdio.h> -+++#include <stdlib.h> -+++#include <string.h> -+++#include <unistd.h> -+++#include <sys/types.h> -+++#include <sys/wait.h> -+++#include <X11/cursorfont.h> -+++#include <X11/keysym.h> -+++#include <X11/Xatom.h> -+++#include <X11/Xlib.h> -+++#include <X11/Xproto.h> -+++#include <X11/Xutil.h> -+++#ifdef XINERAMA -+++#include <X11/extensions/Xinerama.h> -+++#endif /* XINERAMA */ -+++#include <X11/Xft/Xft.h> -+++ -+++#include "drw.h" -+++#include "util.h" -+++ -+++/* macros */ -+++#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -+++#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 LENGTH(X) (sizeof X / sizeof X[0]) -+++#define MOUSEMASK (BUTTONMASK|PointerMotionMask) -+++#define WIDTH(X) ((X)->w + 2 * (X)->bw) -+++#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -+++#define TAGMASK ((1 << LENGTH(tags)) - 1) -+++#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -+++ -+++/* enums */ -+++enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -+++enum { SchemeNorm, SchemeSel }; /* color schemes */ -+++enum { NetSupported, NetWMName, NetWMState, NetWMCheck, -+++ NetWMFullscreen, NetActiveWindow, NetWMWindowType, -+++ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -+++enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -+++enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -+++ ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ -+++ -+++typedef union { -+++ int i; -+++ unsigned int ui; -+++ float f; -+++ const void *v; -+++} Arg; -+++ -+++typedef struct { -+++ unsigned int click; -+++ unsigned int mask; -+++ unsigned int button; -+++ void (*func)(const Arg *arg); -+++ const Arg arg; -+++} Button; -+++ -+++typedef struct Monitor Monitor; -+++typedef struct Client Client; -+++struct Client { -+++ char name[256]; -+++ float mina, maxa; -+++ int x, y, w, h; -+++ int oldx, oldy, oldw, oldh; -+++ int basew, baseh, incw, inch, maxw, maxh, minw, minh; -+++ int bw, oldbw; -+++ unsigned int tags; -+++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -+++ Client *next; -+++ Client *snext; -+++ Monitor *mon; -+++ Window win; -+++}; -+++ -+++typedef struct { -+++ unsigned int mod; -+++ KeySym keysym; -+++ void (*func)(const Arg *); -+++ const Arg arg; -+++} Key; -+++ -+++typedef struct { -+++ const char *symbol; -+++ void (*arrange)(Monitor *); -+++} Layout; -+++ -+++struct Monitor { -+++ char ltsymbol[16]; -+++ float mfact; -+++ int nmaster; -+++ int num; -+++ int by; /* bar geometry */ -+++ int mx, my, mw, mh; /* screen size */ -+++ int wx, wy, ww, wh; /* window area */ -+++ unsigned int seltags; -+++ unsigned int sellt; -+++ unsigned int tagset[2]; -+++ int showbar; -+++ int topbar; -+++ Client *clients; -+++ Client *sel; -+++ Client *stack; -+++ Monitor *next; -+++ Window barwin; -+++ const Layout *lt[2]; -+++}; -+++ -+++typedef struct { -+++ const char *class; -+++ const char *instance; -+++ const char *title; -+++ unsigned int tags; -+++ int isfloating; -+++ int monitor; -+++} Rule; -+++ -+++/* function declarations */ -+++static void applyrules(Client *c); -+++static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -+++static void arrange(Monitor *m); -+++static void arrangemon(Monitor *m); -+++static void attach(Client *c); -+++static void attachstack(Client *c); -+++static void buttonpress(XEvent *e); -+++static void checkotherwm(void); -+++static void cleanup(void); -+++static void cleanupmon(Monitor *mon); -+++static void clientmessage(XEvent *e); -+++static void configure(Client *c); -+++static void configurenotify(XEvent *e); -+++static void configurerequest(XEvent *e); -+++static Monitor *createmon(void); -+++static void destroynotify(XEvent *e); -+++static void detach(Client *c); -+++static void detachstack(Client *c); -+++static Monitor *dirtomon(int dir); -+++static void drawbar(Monitor *m); -+++static void drawbars(void); -+++static void enternotify(XEvent *e); -+++static void expose(XEvent *e); -+++static void focus(Client *c); -+++static void focusin(XEvent *e); -+++static void focusmon(const Arg *arg); -+++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 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 keypress(XEvent *e); -+++static void killclient(const Arg *arg); -+++static void manage(Window w, XWindowAttributes *wa); -+++static void mappingnotify(XEvent *e); -+++static void maprequest(XEvent *e); -+++static void monocle(Monitor *m); -+++static void motionnotify(XEvent *e); -+++static void movemouse(const Arg *arg); -+++static Client *nexttiled(Client *c); -+++static void pop(Client *); -+++static void propertynotify(XEvent *e); -+++static void quit(const Arg *arg); -+++static Monitor *recttomon(int x, int y, int w, int h); -+++static void resize(Client *c, int x, int y, int w, int h, int interact); -+++static void resizeclient(Client *c, int x, int y, int w, int h); -+++static void resizemouse(const Arg *arg); -+++static void restack(Monitor *m); -+++static void run(void); -+++static void scan(void); -+++static int sendevent(Client *c, Atom proto); -+++static void sendmon(Client *c, Monitor *m); -+++static void setclientstate(Client *c, long state); -+++static void setfocus(Client *c); -+++static void setfullscreen(Client *c, int fullscreen); -+++static void setlayout(const Arg *arg); -+++static void setmfact(const Arg *arg); -+++static void setup(void); -+++static void seturgent(Client *c, int urg); -+++static void showhide(Client *c); -+++static void sigchld(int unused); -+++static void spawn(const Arg *arg); -+++static void tag(const Arg *arg); -+++static void tagmon(const Arg *arg); -+++static void tile(Monitor *); -+++static void togglebar(const Arg *arg); -+++static void togglefloating(const Arg *arg); -+++static void toggletag(const Arg *arg); -+++static void toggleview(const Arg *arg); -+++static void unfocus(Client *c, int setfocus); -+++static void unmanage(Client *c, int destroyed); -+++static void unmapnotify(XEvent *e); -+++static void updatebarpos(Monitor *m); -+++static void updatebars(void); -+++static void updateclientlist(void); -+++static int updategeom(void); -+++static void updatenumlockmask(void); -+++static void updatesizehints(Client *c); -+++static void updatestatus(void); -+++static void updatetitle(Client *c); -+++static void updatewindowtype(Client *c); -+++static void updatewmhints(Client *c); -+++static void view(const Arg *arg); -+++static Client *wintoclient(Window w); -+++static Monitor *wintomon(Window w); -+++static int xerror(Display *dpy, XErrorEvent *ee); -+++static int xerrordummy(Display *dpy, XErrorEvent *ee); -+++static int xerrorstart(Display *dpy, XErrorEvent *ee); -+++static void zoom(const Arg *arg); -+++ -+++/* variables */ -+++static const char broken[] = "broken"; -+++static char stext[256]; -+++static int screen; -+++static int sw, sh; /* X display screen geometry width, height */ -+++static int bh, blw = 0; /* bar geometry */ -+++static int lrpad; /* sum of left and right padding for text */ -+++static int (*xerrorxlib)(Display *, XErrorEvent *); -+++static unsigned int numlockmask = 0; -+++static void (*handler[LASTEvent]) (XEvent *) = { -+++ [ButtonPress] = buttonpress, -+++ [ClientMessage] = clientmessage, -+++ [ConfigureRequest] = configurerequest, -+++ [ConfigureNotify] = configurenotify, -+++ [DestroyNotify] = destroynotify, -+++ [EnterNotify] = enternotify, -+++ [Expose] = expose, -+++ [FocusIn] = focusin, -+++ [KeyPress] = keypress, -+++ [MappingNotify] = mappingnotify, -+++ [MapRequest] = maprequest, -+++ [MotionNotify] = motionnotify, -+++ [PropertyNotify] = propertynotify, -+++ [UnmapNotify] = unmapnotify -+++}; -+++static Atom wmatom[WMLast], netatom[NetLast]; -+++static int running = 1; -+++static Cur *cursor[CurLast]; -+++static Clr **scheme; -+++static Display *dpy; -+++static Drw *drw; -+++static Monitor *mons, *selmon; -+++static Window root, wmcheckwin; -+++ -+++/* configuration, allows nested code to access above variables */ -+++#include "config.h" -+++ -+++/* compile-time check if all tags fit into an unsigned int bit array. */ -+++struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; -+++ -+++/* function implementations */ -+++void -+++applyrules(Client *c) -+++{ -+++ const char *class, *instance; -+++ unsigned int i; -+++ const Rule *r; -+++ Monitor *m; -+++ XClassHint ch = { NULL, NULL }; -+++ -+++ /* rule matching */ -+++ c->isfloating = 0; -+++ c->tags = 0; -+++ XGetClassHint(dpy, c->win, &ch); -+++ class = ch.res_class ? ch.res_class : broken; -+++ instance = ch.res_name ? ch.res_name : broken; -+++ -+++ for (i = 0; i < LENGTH(rules); i++) { -+++ r = &rules[i]; -+++ if ((!r->title || strstr(c->name, r->title)) -+++ && (!r->class || strstr(class, r->class)) -+++ && (!r->instance || strstr(instance, r->instance))) -+++ { -+++ c->isfloating = r->isfloating; -+++ c->tags |= r->tags; -+++ for (m = mons; m && m->num != r->monitor; m = m->next); -+++ if (m) -+++ c->mon = m; -+++ } -+++ } -+++ if (ch.res_class) -+++ XFree(ch.res_class); -+++ if (ch.res_name) -+++ XFree(ch.res_name); -+++ c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; -+++} -+++ -+++int -+++applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) -+++{ -+++ int baseismin; -+++ Monitor *m = c->mon; -+++ -+++ /* set minimum possible */ -+++ *w = MAX(1, *w); -+++ *h = MAX(1, *h); -+++ if (interact) { -+++ if (*x > sw) -+++ *x = sw - WIDTH(c); -+++ if (*y > sh) -+++ *y = sh - HEIGHT(c); -+++ if (*x + *w + 2 * c->bw < 0) -+++ *x = 0; -+++ if (*y + *h + 2 * c->bw < 0) -+++ *y = 0; -+++ } else { -+++ if (*x >= m->wx + m->ww) -+++ *x = m->wx + m->ww - WIDTH(c); -+++ if (*y >= m->wy + m->wh) -+++ *y = m->wy + m->wh - HEIGHT(c); -+++ if (*x + *w + 2 * c->bw <= m->wx) -+++ *x = m->wx; -+++ if (*y + *h + 2 * c->bw <= m->wy) -+++ *y = m->wy; -+++ } -+++ if (*h < bh) -+++ *h = bh; -+++ if (*w < bh) -+++ *w = bh; -+++ if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { -+++ /* see last two sentences in ICCCM 4.1.2.3 */ -+++ baseismin = c->basew == c->minw && c->baseh == c->minh; -+++ if (!baseismin) { /* temporarily remove base dimensions */ -+++ *w -= c->basew; -+++ *h -= c->baseh; -+++ } -+++ /* adjust for aspect limits */ -+++ if (c->mina > 0 && c->maxa > 0) { -+++ if (c->maxa < (float)*w / *h) -+++ *w = *h * c->maxa + 0.5; -+++ else if (c->mina < (float)*h / *w) -+++ *h = *w * c->mina + 0.5; -+++ } -+++ if (baseismin) { /* increment calculation requires this */ -+++ *w -= c->basew; -+++ *h -= c->baseh; -+++ } -+++ /* adjust for increment value */ -+++ if (c->incw) -+++ *w -= *w % c->incw; -+++ if (c->inch) -+++ *h -= *h % c->inch; -+++ /* restore base dimensions */ -+++ *w = MAX(*w + c->basew, c->minw); -+++ *h = MAX(*h + c->baseh, c->minh); -+++ if (c->maxw) -+++ *w = MIN(*w, c->maxw); -+++ if (c->maxh) -+++ *h = MIN(*h, c->maxh); -+++ } -+++ return *x != c->x || *y != c->y || *w != c->w || *h != c->h; -+++} -+++ -+++void -+++arrange(Monitor *m) -+++{ -+++ if (m) -+++ showhide(m->stack); -+++ else for (m = mons; m; m = m->next) -+++ showhide(m->stack); -+++ if (m) { -+++ arrangemon(m); -+++ restack(m); -+++ } else for (m = mons; m; m = m->next) -+++ arrangemon(m); -+++} -+++ -+++void -+++arrangemon(Monitor *m) -+++{ -+++ strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); -+++ if (m->lt[m->sellt]->arrange) -+++ m->lt[m->sellt]->arrange(m); -+++} -+++ -+++void -+++attach(Client *c) -+++{ -+++ c->next = c->mon->clients; -+++ c->mon->clients = c; -+++} -+++ -+++void -+++attachstack(Client *c) -+++{ -+++ c->snext = c->mon->stack; -+++ c->mon->stack = c; -+++} -+++ -+++void -+++buttonpress(XEvent *e) -+++{ -+++ unsigned int i, x, click; -+++ Arg arg = {0}; -+++ Client *c; -+++ Monitor *m; -+++ XButtonPressedEvent *ev = &e->xbutton; -+++ -+++ click = ClkRootWin; -+++ /* focus monitor if necessary */ -+++ if ((m = wintomon(ev->window)) && m != selmon) { -+++ unfocus(selmon->sel, 1); -+++ selmon = m; -+++ focus(NULL); -+++ } -+++ if (ev->window == selmon->barwin) { -+++ i = x = 0; -+++ do -+++ x += TEXTW(tags[i]); -+++ while (ev->x >= x && ++i < LENGTH(tags)); -+++ if (i < LENGTH(tags)) { -+++ click = ClkTagBar; -+++ arg.ui = 1 << i; -+++ } else if (ev->x < x + blw) -+++ click = ClkLtSymbol; -+++ else if (ev->x > selmon->ww - (int)TEXTW(stext)) -+++ click = ClkStatusText; -+++ else -+++ click = ClkWinTitle; -+++ } else if ((c = wintoclient(ev->window))) { -+++ focus(c); -+++ restack(selmon); -+++ XAllowEvents(dpy, ReplayPointer, CurrentTime); -+++ click = ClkClientWin; -+++ } -+++ for (i = 0; i < LENGTH(buttons); i++) -+++ if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button -+++ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) -+++ buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); -+++} -+++ -+++void -+++checkotherwm(void) -+++{ -+++ xerrorxlib = XSetErrorHandler(xerrorstart); -+++ /* this causes an error if some other window manager is running */ -+++ XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); -+++ XSync(dpy, False); -+++ XSetErrorHandler(xerror); -+++ XSync(dpy, False); -+++} -+++ -+++void -+++cleanup(void) -+++{ -+++ Arg a = {.ui = ~0}; -+++ Layout foo = { "", NULL }; -+++ Monitor *m; -+++ size_t i; -+++ -+++ view(&a); -+++ selmon->lt[selmon->sellt] = &foo; -+++ for (m = mons; m; m = m->next) -+++ while (m->stack) -+++ unmanage(m->stack, 0); -+++ XUngrabKey(dpy, AnyKey, AnyModifier, root); -+++ while (mons) -+++ cleanupmon(mons); -+++ for (i = 0; i < CurLast; i++) -+++ drw_cur_free(drw, cursor[i]); -+++ for (i = 0; i < LENGTH(colors); i++) -+++ free(scheme[i]); -+++ XDestroyWindow(dpy, wmcheckwin); -+++ drw_free(drw); -+++ XSync(dpy, False); -+++ XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); -+++ XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -+++} -+++ -+++void -+++cleanupmon(Monitor *mon) -+++{ -+++ Monitor *m; -+++ -+++ if (mon == mons) -+++ mons = mons->next; -+++ else { -+++ for (m = mons; m && m->next != mon; m = m->next); -+++ m->next = mon->next; -+++ } -+++ XUnmapWindow(dpy, mon->barwin); -+++ XDestroyWindow(dpy, mon->barwin); -+++ free(mon); -+++} -+++ -+++void -+++clientmessage(XEvent *e) -+++{ -+++ XClientMessageEvent *cme = &e->xclient; -+++ Client *c = wintoclient(cme->window); -+++ -+++ if (!c) -+++ return; -+++ if (cme->message_type == netatom[NetWMState]) { -+++ if (cme->data.l[1] == netatom[NetWMFullscreen] -+++ || cme->data.l[2] == netatom[NetWMFullscreen]) -+++ setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ -+++ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); -+++ } else if (cme->message_type == netatom[NetActiveWindow]) { -+++ if (c != selmon->sel && !c->isurgent) -+++ seturgent(c, 1); -+++ } -+++} -+++ -+++void -+++configure(Client *c) -+++{ -+++ XConfigureEvent ce; -+++ -+++ ce.type = ConfigureNotify; -+++ ce.display = dpy; -+++ ce.event = c->win; -+++ ce.window = c->win; -+++ ce.x = c->x; -+++ ce.y = c->y; -+++ ce.width = c->w; -+++ ce.height = c->h; -+++ ce.border_width = c->bw; -+++ ce.above = None; -+++ ce.override_redirect = False; -+++ XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); -+++} -+++ -+++void -+++configurenotify(XEvent *e) -+++{ -+++ Monitor *m; -+++ Client *c; -+++ XConfigureEvent *ev = &e->xconfigure; -+++ int dirty; -+++ -+++ /* TODO: updategeom handling sucks, needs to be simplified */ -+++ if (ev->window == root) { -+++ dirty = (sw != ev->width || sh != ev->height); -+++ sw = ev->width; -+++ sh = ev->height; -+++ if (updategeom() || dirty) { -+++ drw_resize(drw, sw, bh); -+++ updatebars(); -+++ for (m = mons; m; m = m->next) { -+++ for (c = m->clients; c; c = c->next) -+++ if (c->isfullscreen) -+++ resizeclient(c, m->mx, m->my, m->mw, m->mh); -+++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+++ } -+++ focus(NULL); -+++ arrange(NULL); -+++ } -+++ } -+++} -+++ -+++void -+++configurerequest(XEvent *e) -+++{ -+++ Client *c; -+++ Monitor *m; -+++ XConfigureRequestEvent *ev = &e->xconfigurerequest; -+++ XWindowChanges wc; -+++ -+++ if ((c = wintoclient(ev->window))) { -+++ if (ev->value_mask & CWBorderWidth) -+++ c->bw = ev->border_width; -+++ else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { -+++ m = c->mon; -+++ if (ev->value_mask & CWX) { -+++ c->oldx = c->x; -+++ c->x = m->mx + ev->x; -+++ } -+++ if (ev->value_mask & CWY) { -+++ c->oldy = c->y; -+++ c->y = m->my + ev->y; -+++ } -+++ if (ev->value_mask & CWWidth) { -+++ c->oldw = c->w; -+++ c->w = ev->width; -+++ } -+++ if (ev->value_mask & CWHeight) { -+++ c->oldh = c->h; -+++ c->h = ev->height; -+++ } -+++ if ((c->x + c->w) > m->mx + m->mw && c->isfloating) -+++ c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ -+++ if ((c->y + c->h) > m->my + m->mh && c->isfloating) -+++ c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ -+++ if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) -+++ configure(c); -+++ if (ISVISIBLE(c)) -+++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); -+++ } else -+++ configure(c); -+++ } else { -+++ wc.x = ev->x; -+++ wc.y = ev->y; -+++ wc.width = ev->width; -+++ wc.height = ev->height; -+++ wc.border_width = ev->border_width; -+++ wc.sibling = ev->above; -+++ wc.stack_mode = ev->detail; -+++ XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); -+++ } -+++ XSync(dpy, False); -+++} -+++ -+++Monitor * -+++createmon(void) -+++{ -+++ Monitor *m; -+++ -+++ m = ecalloc(1, sizeof(Monitor)); -+++ m->tagset[0] = m->tagset[1] = 1; -+++ m->mfact = mfact; -+++ m->nmaster = nmaster; -+++ m->showbar = showbar; -+++ m->topbar = topbar; -+++ m->lt[0] = &layouts[0]; -+++ m->lt[1] = &layouts[1 % LENGTH(layouts)]; -+++ strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -+++ return m; -+++} -+++ -+++void -+++destroynotify(XEvent *e) -+++{ -+++ Client *c; -+++ XDestroyWindowEvent *ev = &e->xdestroywindow; -+++ -+++ if ((c = wintoclient(ev->window))) -+++ unmanage(c, 1); -+++} -+++ -+++void -+++detach(Client *c) -+++{ -+++ Client **tc; -+++ -+++ for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); -+++ *tc = c->next; -+++} -+++ -+++void -+++detachstack(Client *c) -+++{ -+++ Client **tc, *t; -+++ -+++ for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); -+++ *tc = c->snext; -+++ -+++ if (c == c->mon->sel) { -+++ for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); -+++ c->mon->sel = t; -+++ } -+++} -+++ -+++Monitor * -+++dirtomon(int dir) -+++{ -+++ Monitor *m = NULL; -+++ -+++ if (dir > 0) { -+++ if (!(m = selmon->next)) -+++ m = mons; -+++ } else if (selmon == mons) -+++ for (m = mons; m->next; m = m->next); -+++ else -+++ for (m = mons; m->next != selmon; m = m->next); -+++ return m; -+++} -+++ -+++void -+++drawbar(Monitor *m) -+++{ -+++ int x, w, tw = 0; -+++ int boxs = drw->fonts->h / 9; -+++ int boxw = drw->fonts->h / 6 + 2; -+++ unsigned int i, occ = 0, urg = 0; -+++ Client *c; -+++ -+++ /* 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]); -+++ tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -+++ drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0); -+++ } -+++ -+++ for (c = m->clients; c; c = c->next) { -+++ occ |= c->tags; -+++ if (c->isurgent) -+++ urg |= c->tags; -+++ } -+++ x = 0; -+++ for (i = 0; i < LENGTH(tags); i++) { -+++ w = TEXTW(tags[i]); -+++ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); -+++ drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); -+++ if (occ & 1 << i) -+++ drw_rect(drw, x + boxs, boxs, boxw, boxw, -+++ m == selmon && selmon->sel && selmon->sel->tags & 1 << i, -+++ urg & 1 << i); -+++ x += w; -+++ } -+++ w = blw = TEXTW(m->ltsymbol); -+++ drw_setscheme(drw, scheme[SchemeNorm]); -+++ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); -+++ -+++ if ((w = m->ww - tw - x) > bh) { -+++ if (m->sel) { -+++ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -+++ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -+++ if (m->sel->isfloating) -+++ drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); -+++ } else { -+++ drw_setscheme(drw, scheme[SchemeNorm]); -+++ drw_rect(drw, x, 0, w, bh, 1, 1); -+++ } -+++ } -+++ drw_map(drw, m->barwin, 0, 0, m->ww, bh); -+++} -+++ -+++void -+++drawbars(void) -+++{ -+++ Monitor *m; -+++ -+++ for (m = mons; m; m = m->next) -+++ drawbar(m); -+++} -+++ -+++void -+++enternotify(XEvent *e) -+++{ -+++ Client *c; -+++ Monitor *m; -+++ XCrossingEvent *ev = &e->xcrossing; -+++ -+++ if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) -+++ return; -+++ c = wintoclient(ev->window); -+++ m = c ? c->mon : wintomon(ev->window); -+++ if (m != selmon) { -+++ unfocus(selmon->sel, 1); -+++ selmon = m; -+++ } else if (!c || c == selmon->sel) -+++ return; -+++ focus(c); -+++} -+++ -+++void -+++expose(XEvent *e) -+++{ -+++ Monitor *m; -+++ XExposeEvent *ev = &e->xexpose; -+++ -+++ if (ev->count == 0 && (m = wintomon(ev->window))) -+++ drawbar(m); -+++} -+++ -+++void -+++focus(Client *c) -+++{ -+++ if (!c || !ISVISIBLE(c)) -+++ for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); -+++ if (selmon->sel && selmon->sel != c) -+++ unfocus(selmon->sel, 0); -+++ if (c) { -+++ if (c->mon != selmon) -+++ selmon = c->mon; -+++ if (c->isurgent) -+++ seturgent(c, 0); -+++ detachstack(c); -+++ attachstack(c); -+++ grabbuttons(c, 1); -+++ XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); -+++ setfocus(c); -+++ } else { -+++ XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); -+++ XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -+++ } -+++ selmon->sel = c; -+++ drawbars(); -+++} -+++ -+++/* there are some broken focus acquiring clients needing extra handling */ -+++void -+++focusin(XEvent *e) -+++{ -+++ XFocusChangeEvent *ev = &e->xfocus; -+++ -+++ if (selmon->sel && ev->window != selmon->sel->win) -+++ setfocus(selmon->sel); -+++} -+++ -+++void -+++focusmon(const Arg *arg) -+++{ -+++ Monitor *m; -+++ -+++ if (!mons->next) -+++ return; -+++ if ((m = dirtomon(arg->i)) == selmon) -+++ return; -+++ unfocus(selmon->sel, 0); -+++ selmon = m; -+++ focus(NULL); -+++} -+++ -+++void -+++focusstack(const Arg *arg) -+++{ -+++ Client *c = NULL, *i; -+++ -+++ if (!selmon->sel) -+++ return; -+++ if (arg->i > 0) { -+++ for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); -+++ if (!c) -+++ for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); -+++ } else { -+++ for (i = selmon->clients; i != selmon->sel; i = i->next) -+++ if (ISVISIBLE(i)) -+++ c = i; -+++ if (!c) -+++ for (; i; i = i->next) -+++ if (ISVISIBLE(i)) -+++ c = i; -+++ } -+++ if (c) { -+++ focus(c); -+++ restack(selmon); -+++ } -+++} -+++ -+++Atom -+++getatomprop(Client *c, Atom prop) -+++{ -+++ int di; -+++ unsigned long dl; -+++ unsigned char *p = NULL; -+++ Atom da, atom = None; -+++ -+++ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, -+++ &da, &di, &dl, &dl, &p) == Success && p) { -+++ atom = *(Atom *)p; -+++ XFree(p); -+++ } -+++ return atom; -+++} -+++ -+++int -+++getrootptr(int *x, int *y) -+++{ -+++ int di; -+++ unsigned int dui; -+++ Window dummy; -+++ -+++ return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); -+++} -+++ -+++long -+++getstate(Window w) -+++{ -+++ int format; -+++ long result = -1; -+++ unsigned char *p = NULL; -+++ unsigned long n, extra; -+++ Atom real; -+++ -+++ if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], -+++ &real, &format, &n, &extra, (unsigned char **)&p) != Success) -+++ return -1; -+++ if (n != 0) -+++ result = *p; -+++ XFree(p); -+++ return result; -+++} -+++ -+++int -+++gettextprop(Window w, Atom atom, char *text, unsigned int size) -+++{ -+++ char **list = NULL; -+++ int n; -+++ XTextProperty name; -+++ -+++ if (!text || size == 0) -+++ return 0; -+++ text[0] = '\0'; -+++ if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) -+++ return 0; -+++ if (name.encoding == XA_STRING) -+++ strncpy(text, (char *)name.value, size - 1); -+++ else { -+++ if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { -+++ strncpy(text, *list, size - 1); -+++ XFreeStringList(list); -+++ } -+++ } -+++ text[size - 1] = '\0'; -+++ XFree(name.value); -+++ return 1; -+++} -+++ -+++void -+++grabbuttons(Client *c, int focused) -+++{ -+++ updatenumlockmask(); -+++ { -+++ unsigned int i, j; -+++ unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; -+++ XUngrabButton(dpy, AnyButton, AnyModifier, c->win); -+++ if (!focused) -+++ XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, -+++ BUTTONMASK, GrabModeSync, GrabModeSync, None, None); -+++ for (i = 0; i < LENGTH(buttons); i++) -+++ if (buttons[i].click == ClkClientWin) -+++ for (j = 0; j < LENGTH(modifiers); j++) -+++ XGrabButton(dpy, buttons[i].button, -+++ buttons[i].mask | modifiers[j], -+++ c->win, False, BUTTONMASK, -+++ GrabModeAsync, GrabModeSync, None, None); -+++ } -+++} -+++ -+++void -+++grabkeys(void) -+++{ -+++ updatenumlockmask(); -+++ { -+++ unsigned int i, j; -+++ unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; -+++ KeyCode code; -+++ -+++ XUngrabKey(dpy, AnyKey, AnyModifier, root); -+++ for (i = 0; i < LENGTH(keys); i++) -+++ if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) -+++ for (j = 0; j < LENGTH(modifiers); j++) -+++ XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, -+++ True, GrabModeAsync, GrabModeAsync); -+++ } -+++} -+++ -+++void -+++incnmaster(const Arg *arg) -+++{ -+++ selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); -+++ arrange(selmon); -+++} -+++ -+++#ifdef XINERAMA -+++static int -+++isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) -+++{ -+++ while (n--) -+++ if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org -+++ && unique[n].width == info->width && unique[n].height == info->height) -+++ return 0; -+++ return 1; -+++} -+++#endif /* XINERAMA */ -+++ -+++void -+++keypress(XEvent *e) -+++{ -+++ unsigned int i; -+++ KeySym keysym; -+++ XKeyEvent *ev; -+++ -+++ ev = &e->xkey; -+++ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); -+++ for (i = 0; i < LENGTH(keys); i++) -+++ if (keysym == keys[i].keysym -+++ && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) -+++ && keys[i].func) -+++ keys[i].func(&(keys[i].arg)); -+++} -+++ -+++void -+++killclient(const Arg *arg) -+++{ -+++ if (!selmon->sel) -+++ return; -+++ if (!sendevent(selmon->sel, wmatom[WMDelete])) { -+++ XGrabServer(dpy); -+++ XSetErrorHandler(xerrordummy); -+++ XSetCloseDownMode(dpy, DestroyAll); -+++ XKillClient(dpy, selmon->sel->win); -+++ XSync(dpy, False); -+++ XSetErrorHandler(xerror); -+++ XUngrabServer(dpy); -+++ } -+++} -+++ -+++void -+++manage(Window w, XWindowAttributes *wa) -+++{ -+++ Client *c, *t = NULL; -+++ Window trans = None; -+++ XWindowChanges wc; -+++ -+++ c = ecalloc(1, sizeof(Client)); -+++ c->win = w; -+++ /* geometry */ -+++ c->x = c->oldx = wa->x; -+++ c->y = c->oldy = wa->y; -+++ c->w = c->oldw = wa->width; -+++ c->h = c->oldh = wa->height; -+++ c->oldbw = wa->border_width; -+++ -+++ updatetitle(c); -+++ if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { -+++ c->mon = t->mon; -+++ c->tags = t->tags; -+++ } else { -+++ c->mon = selmon; -+++ applyrules(c); -+++ } -+++ -+++ if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) -+++ c->x = c->mon->mx + c->mon->mw - WIDTH(c); -+++ if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) -+++ c->y = c->mon->my + c->mon->mh - HEIGHT(c); -+++ c->x = MAX(c->x, c->mon->mx); -+++ /* only fix client y-offset, if the client center might cover the bar */ -+++ c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) -+++ && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); -+++ c->bw = borderpx; -+++ -+++ wc.border_width = c->bw; -+++ XConfigureWindow(dpy, w, CWBorderWidth, &wc); -+++ XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); -+++ configure(c); /* propagates border_width, if size doesn't change */ -+++ updatewindowtype(c); -+++ updatesizehints(c); -+++ updatewmhints(c); -+++ XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); -+++ grabbuttons(c, 0); -+++ if (!c->isfloating) -+++ c->isfloating = c->oldstate = trans != None || c->isfixed; -+++ if (c->isfloating) -+++ XRaiseWindow(dpy, c->win); -+++ attach(c); -+++ attachstack(c); -+++ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, -+++ (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) -+++ unfocus(selmon->sel, 0); -+++ c->mon->sel = c; -+++ arrange(c->mon); -+++ XMapWindow(dpy, c->win); -+++ focus(NULL); -+++} -+++ -+++void -+++mappingnotify(XEvent *e) -+++{ -+++ XMappingEvent *ev = &e->xmapping; -+++ -+++ XRefreshKeyboardMapping(ev); -+++ if (ev->request == MappingKeyboard) -+++ grabkeys(); -+++} -+++ -+++void -+++maprequest(XEvent *e) -+++{ -+++ static XWindowAttributes wa; -+++ XMapRequestEvent *ev = &e->xmaprequest; -+++ -+++ if (!XGetWindowAttributes(dpy, ev->window, &wa)) -+++ return; -+++ if (wa.override_redirect) -+++ return; -+++ if (!wintoclient(ev->window)) -+++ manage(ev->window, &wa); -+++} -+++ -+++void -+++monocle(Monitor *m) -+++{ -+++ unsigned int n = 0; -+++ Client *c; -+++ -+++ for (c = m->clients; c; c = c->next) -+++ if (ISVISIBLE(c)) -+++ n++; -+++ 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); -+++} -+++ -+++void -+++motionnotify(XEvent *e) -+++{ -+++ static Monitor *mon = NULL; -+++ Monitor *m; -+++ XMotionEvent *ev = &e->xmotion; -+++ -+++ if (ev->window != root) -+++ return; -+++ if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { -+++ unfocus(selmon->sel, 1); -+++ selmon = m; -+++ focus(NULL); -+++ } -+++ mon = m; -+++} -+++ -+++void -+++movemouse(const Arg *arg) -+++{ -+++ int x, y, ocx, ocy, nx, ny; -+++ Client *c; -+++ Monitor *m; -+++ XEvent ev; -+++ Time lasttime = 0; -+++ -+++ if (!(c = selmon->sel)) -+++ return; -+++ if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ -+++ return; -+++ restack(selmon); -+++ ocx = c->x; -+++ ocy = c->y; -+++ if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, -+++ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) -+++ return; -+++ if (!getrootptr(&x, &y)) -+++ return; -+++ do { -+++ XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); -+++ switch(ev.type) { -+++ case ConfigureRequest: -+++ case Expose: -+++ case MapRequest: -+++ handler[ev.type](&ev); -+++ break; -+++ case MotionNotify: -+++ if ((ev.xmotion.time - lasttime) <= (1000 / 60)) -+++ continue; -+++ lasttime = ev.xmotion.time; -+++ -+++ nx = ocx + (ev.xmotion.x - x); -+++ ny = ocy + (ev.xmotion.y - y); -+++ if (abs(selmon->wx - nx) < snap) -+++ nx = selmon->wx; -+++ else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) -+++ nx = selmon->wx + selmon->ww - WIDTH(c); -+++ if (abs(selmon->wy - ny) < snap) -+++ ny = selmon->wy; -+++ else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) -+++ ny = selmon->wy + selmon->wh - HEIGHT(c); -+++ if (!c->isfloating && selmon->lt[selmon->sellt]->arrange -+++ && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) -+++ togglefloating(NULL); -+++ if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) -+++ resize(c, nx, ny, c->w, c->h, 1); -+++ break; -+++ } -+++ } while (ev.type != ButtonRelease); -+++ XUngrabPointer(dpy, CurrentTime); -+++ if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { -+++ sendmon(c, m); -+++ selmon = m; -+++ focus(NULL); -+++ } -+++} -+++ -+++Client * -+++nexttiled(Client *c) -+++{ -+++ for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); -+++ return c; -+++} -+++ -+++void -+++pop(Client *c) -+++{ -+++ detach(c); -+++ attach(c); -+++ focus(c); -+++ arrange(c->mon); -+++} -+++ -+++void -+++propertynotify(XEvent *e) -+++{ -+++ Client *c; -+++ Window trans; -+++ XPropertyEvent *ev = &e->xproperty; -+++ -+++ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) -+++ updatestatus(); -+++ else if (ev->state == PropertyDelete) -+++ return; /* ignore */ -+++ else if ((c = wintoclient(ev->window))) { -+++ switch(ev->atom) { -+++ default: break; -+++ case XA_WM_TRANSIENT_FOR: -+++ if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && -+++ (c->isfloating = (wintoclient(trans)) != NULL)) -+++ arrange(c->mon); -+++ break; -+++ case XA_WM_NORMAL_HINTS: -+++ updatesizehints(c); -+++ break; -+++ case XA_WM_HINTS: -+++ updatewmhints(c); -+++ drawbars(); -+++ break; -+++ } -+++ if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { -+++ updatetitle(c); -+++ if (c == c->mon->sel) -+++ drawbar(c->mon); -+++ } -+++ if (ev->atom == netatom[NetWMWindowType]) -+++ updatewindowtype(c); -+++ } -+++} -+++ -+++void -+++quit(const Arg *arg) -+++{ -+++ running = 0; -+++} -+++ -+++Monitor * -+++recttomon(int x, int y, int w, int h) -+++{ -+++ Monitor *m, *r = selmon; -+++ int a, area = 0; -+++ -+++ for (m = mons; m; m = m->next) -+++ if ((a = INTERSECT(x, y, w, h, m)) > area) { -+++ area = a; -+++ r = m; -+++ } -+++ return r; -+++} -+++ -+++void -+++resize(Client *c, int x, int y, int w, int h, int interact) -+++{ -+++ if (applysizehints(c, &x, &y, &w, &h, interact)) -+++ resizeclient(c, x, y, w, h); -+++} -+++ -+++void -+++resizeclient(Client *c, int x, int y, int w, int h) -+++{ -+++ XWindowChanges wc; -+++ -+++ c->oldx = c->x; c->x = wc.x = x; -+++ 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; -+++ wc.border_width = c->bw; -+++ XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); -+++ configure(c); -+++ XSync(dpy, False); -+++} -+++ -+++void -+++resizemouse(const Arg *arg) -+++{ -+++ int ocx, ocy, nw, nh; -+++ Client *c; -+++ Monitor *m; -+++ XEvent ev; -+++ Time lasttime = 0; -+++ -+++ if (!(c = selmon->sel)) -+++ return; -+++ if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ -+++ return; -+++ restack(selmon); -+++ ocx = c->x; -+++ ocy = c->y; -+++ if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, -+++ None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) -+++ return; -+++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); -+++ 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; -+++ -+++ nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); -+++ nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); -+++ if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww -+++ && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) -+++ { -+++ if (!c->isfloating && selmon->lt[selmon->sellt]->arrange -+++ && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) -+++ togglefloating(NULL); -+++ } -+++ if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) -+++ resize(c, c->x, c->y, nw, nh, 1); -+++ break; -+++ } -+++ } while (ev.type != ButtonRelease); -+++ XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); -+++ XUngrabPointer(dpy, CurrentTime); -+++ while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -+++ if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { -+++ sendmon(c, m); -+++ selmon = m; -+++ focus(NULL); -+++ } -+++} -+++ -+++void -+++restack(Monitor *m) -+++{ -+++ Client *c; -+++ XEvent ev; -+++ XWindowChanges wc; -+++ -+++ drawbar(m); -+++ if (!m->sel) -+++ return; -+++ if (m->sel->isfloating || !m->lt[m->sellt]->arrange) -+++ XRaiseWindow(dpy, m->sel->win); -+++ if (m->lt[m->sellt]->arrange) { -+++ wc.stack_mode = Below; -+++ wc.sibling = m->barwin; -+++ for (c = m->stack; c; c = c->snext) -+++ if (!c->isfloating && ISVISIBLE(c)) { -+++ XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); -+++ wc.sibling = c->win; -+++ } -+++ } -+++ XSync(dpy, False); -+++ while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); -+++} -+++ -+++void -+++run(void) -+++{ -+++ XEvent ev; -+++ /* main event loop */ -+++ XSync(dpy, False); -+++ while (running && !XNextEvent(dpy, &ev)) -+++ if (handler[ev.type]) -+++ handler[ev.type](&ev); /* call handler */ -+++} -+++ -+++void -+++scan(void) -+++{ -+++ unsigned int i, num; -+++ Window d1, d2, *wins = NULL; -+++ XWindowAttributes wa; -+++ -+++ if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { -+++ for (i = 0; i < num; i++) { -+++ if (!XGetWindowAttributes(dpy, wins[i], &wa) -+++ || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) -+++ continue; -+++ if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) -+++ manage(wins[i], &wa); -+++ } -+++ for (i = 0; i < num; i++) { /* now the transients */ -+++ if (!XGetWindowAttributes(dpy, wins[i], &wa)) -+++ continue; -+++ if (XGetTransientForHint(dpy, wins[i], &d1) -+++ && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) -+++ manage(wins[i], &wa); -+++ } -+++ if (wins) -+++ XFree(wins); -+++ } -+++} -+++ -+++void -+++sendmon(Client *c, Monitor *m) -+++{ -+++ if (c->mon == m) -+++ return; -+++ unfocus(c, 1); -+++ detach(c); -+++ detachstack(c); -+++ c->mon = m; -+++ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -+++ attach(c); -+++ attachstack(c); -+++ focus(NULL); -+++ arrange(NULL); -+++} -+++ -+++void -+++setclientstate(Client *c, long state) -+++{ -+++ long data[] = { state, None }; -+++ -+++ XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, -+++ PropModeReplace, (unsigned char *)data, 2); -+++} -+++ -+++int -+++sendevent(Client *c, Atom proto) -+++{ -+++ int n; -+++ Atom *protocols; -+++ int exists = 0; -+++ XEvent ev; -+++ -+++ if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { -+++ while (!exists && n--) -+++ exists = protocols[n] == proto; -+++ XFree(protocols); -+++ } -+++ if (exists) { -+++ ev.type = ClientMessage; -+++ ev.xclient.window = c->win; -+++ ev.xclient.message_type = wmatom[WMProtocols]; -+++ ev.xclient.format = 32; -+++ ev.xclient.data.l[0] = proto; -+++ ev.xclient.data.l[1] = CurrentTime; -+++ XSendEvent(dpy, c->win, False, NoEventMask, &ev); -+++ } -+++ return exists; -+++} -+++ -+++void -+++setfocus(Client *c) -+++{ -+++ if (!c->neverfocus) { -+++ XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); -+++ XChangeProperty(dpy, root, netatom[NetActiveWindow], -+++ XA_WINDOW, 32, PropModeReplace, -+++ (unsigned char *) &(c->win), 1); -+++ } -+++ sendevent(c, wmatom[WMTakeFocus]); -+++} -+++ -+++void -+++setfullscreen(Client *c, int fullscreen) -+++{ -+++ if (fullscreen && !c->isfullscreen) { -+++ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, -+++ PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); -+++ c->isfullscreen = 1; -+++ c->oldstate = c->isfloating; -+++ c->oldbw = c->bw; -+++ c->bw = 0; -+++ c->isfloating = 1; -+++ resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); -+++ XRaiseWindow(dpy, c->win); -+++ } else if (!fullscreen && c->isfullscreen){ -+++ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, -+++ PropModeReplace, (unsigned char*)0, 0); -+++ c->isfullscreen = 0; -+++ c->isfloating = c->oldstate; -+++ c->bw = c->oldbw; -+++ c->x = c->oldx; -+++ c->y = c->oldy; -+++ c->w = c->oldw; -+++ c->h = c->oldh; -+++ resizeclient(c, c->x, c->y, c->w, c->h); -+++ arrange(c->mon); -+++ } -+++} -+++ -+++void -+++setlayout(const Arg *arg) -+++{ -+++ if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) -+++ selmon->sellt ^= 1; -+++ if (arg && arg->v) -+++ selmon->lt[selmon->sellt] = (Layout *)arg->v; -+++ strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); -+++ if (selmon->sel) -+++ arrange(selmon); -+++ else -+++ drawbar(selmon); -+++} -+++ -+++/* arg > 1.0 will set mfact absolutely */ -+++void -+++setmfact(const Arg *arg) -+++{ -+++ float f; -+++ -+++ if (!arg || !selmon->lt[selmon->sellt]->arrange) -+++ return; -+++ f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; -+++ if (f < 0.05 || f > 0.95) -+++ return; -+++ selmon->mfact = f; -+++ arrange(selmon); -+++} -+++ -+++void -+++setup(void) -+++{ -+++ int i; -+++ XSetWindowAttributes wa; -+++ Atom utf8string; -+++ -+++ /* clean up any zombies immediately */ -+++ sigchld(0); -+++ -+++ /* init screen */ -+++ screen = DefaultScreen(dpy); -+++ sw = DisplayWidth(dpy, screen); -+++ sh = DisplayHeight(dpy, screen); -+++ root = RootWindow(dpy, screen); -+++ drw = drw_create(dpy, screen, root, sw, sh); -+++ if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) -+++ die("no fonts could be loaded."); -+++ lrpad = drw->fonts->h; -+++ bh = drw->fonts->h + 2; -+++ updategeom(); -+++ /* init atoms */ -+++ utf8string = XInternAtom(dpy, "UTF8_STRING", False); -+++ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); -+++ wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); -+++ wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); -+++ wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); -+++ netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); -+++ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); -+++ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); -+++ netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); -+++ netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); -+++ netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); -+++ netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); -+++ netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); -+++ netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); -+++ /* init cursors */ -+++ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); -+++ cursor[CurResize] = drw_cur_create(drw, XC_sizing); -+++ cursor[CurMove] = drw_cur_create(drw, XC_fleur); -+++ /* init appearance */ -+++ scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); -+++ for (i = 0; i < LENGTH(colors); i++) -+++ scheme[i] = drw_scm_create(drw, colors[i], 3); -+++ /* init bars */ -+++ updatebars(); -+++ updatestatus(); -+++ /* supporting window for NetWMCheck */ -+++ wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); -+++ XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, -+++ PropModeReplace, (unsigned char *) &wmcheckwin, 1); -+++ XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, -+++ PropModeReplace, (unsigned char *) "dwm", 3); -+++ XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, -+++ PropModeReplace, (unsigned char *) &wmcheckwin, 1); -+++ /* EWMH support per view */ -+++ XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, -+++ PropModeReplace, (unsigned char *) netatom, NetLast); -+++ XDeleteProperty(dpy, root, netatom[NetClientList]); -+++ /* select events */ -+++ wa.cursor = cursor[CurNormal]->cursor; -+++ wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask -+++ |ButtonPressMask|PointerMotionMask|EnterWindowMask -+++ |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; -+++ XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); -+++ XSelectInput(dpy, root, wa.event_mask); -+++ grabkeys(); -+++ focus(NULL); -+++} -+++ -+++ -+++void -+++seturgent(Client *c, int urg) -+++{ -+++ XWMHints *wmh; -+++ -+++ c->isurgent = urg; -+++ if (!(wmh = XGetWMHints(dpy, c->win))) -+++ return; -+++ wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); -+++ XSetWMHints(dpy, c->win, wmh); -+++ XFree(wmh); -+++} -+++ -+++void -+++showhide(Client *c) -+++{ -+++ if (!c) -+++ return; -+++ if (ISVISIBLE(c)) { -+++ /* show clients top down */ -+++ XMoveWindow(dpy, c->win, c->x, c->y); -+++ if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) -+++ resize(c, c->x, c->y, c->w, c->h, 0); -+++ showhide(c->snext); -+++ } else { -+++ /* hide clients bottom up */ -+++ showhide(c->snext); -+++ XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); -+++ } -+++} -+++ -+++void -+++sigchld(int unused) -+++{ -+++ if (signal(SIGCHLD, sigchld) == SIG_ERR) -+++ die("can't install SIGCHLD handler:"); -+++ while (0 < waitpid(-1, NULL, WNOHANG)); -+++} -+++ -+++void -+++spawn(const Arg *arg) -+++{ -+++ if (arg->v == dmenucmd) -+++ dmenumon[0] = '0' + selmon->num; -+++ if (fork() == 0) { -+++ if (dpy) -+++ close(ConnectionNumber(dpy)); -+++ setsid(); -+++ execvp(((char **)arg->v)[0], (char **)arg->v); -+++ fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); -+++ perror(" failed"); -+++ exit(EXIT_SUCCESS); -+++ } -+++} -+++ -+++void -+++tag(const Arg *arg) -+++{ -+++ if (selmon->sel && arg->ui & TAGMASK) { -+++ selmon->sel->tags = arg->ui & TAGMASK; -+++ focus(NULL); -+++ arrange(selmon); -+++ } -+++} -+++ -+++void -+++tagmon(const Arg *arg) -+++{ -+++ if (!selmon->sel || !mons->next) -+++ return; -+++ sendmon(selmon->sel, dirtomon(arg->i)); -+++} -+++ -+++void -+++tile(Monitor *m) -+++{ -+++ unsigned int i, n, h, mw, my, ty; -+++ Client *c; -+++ -+++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -+++ if (n == 0) -+++ return; -+++ -+++ if (n > m->nmaster) -+++ mw = m->nmaster ? m->ww * m->mfact : 0; -+++ else -+++ mw = m->ww; -+++ for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -+++ if (i < m->nmaster) { -+++ h = (m->wh - my) / (MIN(n, m->nmaster) - i); -+++ resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -+++ if (my + HEIGHT(c) < m->wh) -+++ my += HEIGHT(c); -+++ } else { -+++ h = (m->wh - ty) / (n - i); -+++ resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); -+++ if (ty + HEIGHT(c) < m->wh) -+++ ty += HEIGHT(c); -+++ } -+++} -+++ -+++void -+++togglebar(const Arg *arg) -+++{ -+++ selmon->showbar = !selmon->showbar; -+++ updatebarpos(selmon); -+++ XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); -+++ arrange(selmon); -+++} -+++ -+++void -+++togglefloating(const Arg *arg) -+++{ -+++ if (!selmon->sel) -+++ return; -+++ if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ -+++ return; -+++ selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; -+++ if (selmon->sel->isfloating) -+++ resize(selmon->sel, selmon->sel->x, selmon->sel->y, -+++ selmon->sel->w, selmon->sel->h, 0); -+++ arrange(selmon); -+++} -+++ -+++void -+++toggletag(const Arg *arg) -+++{ -+++ unsigned int newtags; -+++ -+++ if (!selmon->sel) -+++ return; -+++ newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); -+++ if (newtags) { -+++ selmon->sel->tags = newtags; -+++ focus(NULL); -+++ arrange(selmon); -+++ } -+++} -+++ -+++void -+++toggleview(const Arg *arg) -+++{ -+++ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); -+++ -+++ if (newtagset) { -+++ selmon->tagset[selmon->seltags] = newtagset; -+++ focus(NULL); -+++ arrange(selmon); -+++ } -+++} -+++ -+++void -+++unfocus(Client *c, int setfocus) -+++{ -+++ if (!c) -+++ return; -+++ grabbuttons(c, 0); -+++ XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); -+++ if (setfocus) { -+++ XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); -+++ XDeleteProperty(dpy, root, netatom[NetActiveWindow]); -+++ } -+++} -+++ -+++void -+++unmanage(Client *c, int destroyed) -+++{ -+++ Monitor *m = c->mon; -+++ XWindowChanges wc; -+++ -+++ detach(c); -+++ detachstack(c); -+++ if (!destroyed) { -+++ wc.border_width = c->oldbw; -+++ XGrabServer(dpy); /* avoid race conditions */ -+++ XSetErrorHandler(xerrordummy); -+++ XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ -+++ XUngrabButton(dpy, AnyButton, AnyModifier, c->win); -+++ setclientstate(c, WithdrawnState); -+++ XSync(dpy, False); -+++ XSetErrorHandler(xerror); -+++ XUngrabServer(dpy); -+++ } -+++ free(c); -+++ focus(NULL); -+++ updateclientlist(); -+++ arrange(m); -+++} -+++ -+++void -+++unmapnotify(XEvent *e) -+++{ -+++ Client *c; -+++ XUnmapEvent *ev = &e->xunmap; -+++ -+++ if ((c = wintoclient(ev->window))) { -+++ if (ev->send_event) -+++ setclientstate(c, WithdrawnState); -+++ else -+++ unmanage(c, 0); -+++ } -+++} -+++ -+++void -+++updatebars(void) -+++{ -+++ Monitor *m; -+++ XSetWindowAttributes wa = { -+++ .override_redirect = True, -+++ .background_pixmap = ParentRelative, -+++ .event_mask = ButtonPressMask|ExposureMask -+++ }; -+++ XClassHint ch = {"dwm", "dwm"}; -+++ for (m = mons; m; m = m->next) { -+++ if (m->barwin) -+++ continue; -+++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -+++ CopyFromParent, DefaultVisual(dpy, screen), -+++ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -+++ XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); -+++ XMapRaised(dpy, m->barwin); -+++ XSetClassHint(dpy, m->barwin, &ch); -+++ } -+++} -+++ -+++void -+++updatebarpos(Monitor *m) -+++{ -+++ m->wy = m->my; -+++ m->wh = m->mh; -+++ if (m->showbar) { -+++ m->wh -= bh; -+++ m->by = m->topbar ? m->wy : m->wy + m->wh; -+++ m->wy = m->topbar ? m->wy + bh : m->wy; -+++ } else -+++ m->by = -bh; -+++} -+++ -+++void -+++updateclientlist() -+++{ -+++ Client *c; -+++ Monitor *m; -+++ -+++ XDeleteProperty(dpy, root, netatom[NetClientList]); -+++ for (m = mons; m; m = m->next) -+++ for (c = m->clients; c; c = c->next) -+++ XChangeProperty(dpy, root, netatom[NetClientList], -+++ XA_WINDOW, 32, PropModeAppend, -+++ (unsigned char *) &(c->win), 1); -+++} -+++ -+++int -+++updategeom(void) -+++{ -+++ int dirty = 0; -+++ -+++#ifdef XINERAMA -+++ if (XineramaIsActive(dpy)) { -+++ int i, j, n, nn; -+++ Client *c; -+++ Monitor *m; -+++ XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); -+++ XineramaScreenInfo *unique = NULL; -+++ -+++ for (n = 0, m = mons; m; m = m->next, n++); -+++ /* only consider unique geometries as separate screens */ -+++ unique = ecalloc(nn, sizeof(XineramaScreenInfo)); -+++ for (i = 0, j = 0; i < nn; i++) -+++ if (isuniquegeom(unique, j, &info[i])) -+++ memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); -+++ XFree(info); -+++ nn = j; -+++ if (n <= nn) { /* new monitors available */ -+++ for (i = 0; i < (nn - n); i++) { -+++ for (m = mons; m && m->next; m = m->next); -+++ if (m) -+++ m->next = createmon(); -+++ else -+++ mons = createmon(); -+++ } -+++ for (i = 0, m = mons; i < nn && m; m = m->next, i++) -+++ if (i >= n -+++ || unique[i].x_org != m->mx || unique[i].y_org != m->my -+++ || unique[i].width != m->mw || unique[i].height != m->mh) -+++ { -+++ dirty = 1; -+++ m->num = i; -+++ m->mx = m->wx = unique[i].x_org; -+++ m->my = m->wy = unique[i].y_org; -+++ m->mw = m->ww = unique[i].width; -+++ m->mh = m->wh = unique[i].height; -+++ updatebarpos(m); -+++ } -+++ } else { /* less monitors available nn < n */ -+++ for (i = nn; i < n; i++) { -+++ for (m = mons; m && m->next; m = m->next); -+++ while ((c = m->clients)) { -+++ dirty = 1; -+++ m->clients = c->next; -+++ detachstack(c); -+++ c->mon = mons; -+++ attach(c); -+++ attachstack(c); -+++ } -+++ if (m == selmon) -+++ selmon = mons; -+++ cleanupmon(m); -+++ } -+++ } -+++ free(unique); -+++ } else -+++#endif /* XINERAMA */ -+++ { /* default monitor setup */ -+++ if (!mons) -+++ mons = createmon(); -+++ if (mons->mw != sw || mons->mh != sh) { -+++ dirty = 1; -+++ mons->mw = mons->ww = sw; -+++ mons->mh = mons->wh = sh; -+++ updatebarpos(mons); -+++ } -+++ } -+++ if (dirty) { -+++ selmon = mons; -+++ selmon = wintomon(root); -+++ } -+++ return dirty; -+++} -+++ -+++void -+++updatenumlockmask(void) -+++{ -+++ unsigned int i, j; -+++ XModifierKeymap *modmap; -+++ -+++ numlockmask = 0; -+++ modmap = XGetModifierMapping(dpy); -+++ for (i = 0; i < 8; i++) -+++ for (j = 0; j < modmap->max_keypermod; j++) -+++ if (modmap->modifiermap[i * modmap->max_keypermod + j] -+++ == XKeysymToKeycode(dpy, XK_Num_Lock)) -+++ numlockmask = (1 << i); -+++ XFreeModifiermap(modmap); -+++} -+++ -+++void -+++updatesizehints(Client *c) -+++{ -+++ long msize; -+++ XSizeHints size; -+++ -+++ if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) -+++ /* size is uninitialized, ensure that size.flags aren't used */ -+++ size.flags = PSize; -+++ if (size.flags & PBaseSize) { -+++ c->basew = size.base_width; -+++ c->baseh = size.base_height; -+++ } else if (size.flags & PMinSize) { -+++ c->basew = size.min_width; -+++ c->baseh = size.min_height; -+++ } else -+++ c->basew = c->baseh = 0; -+++ if (size.flags & PResizeInc) { -+++ c->incw = size.width_inc; -+++ c->inch = size.height_inc; -+++ } else -+++ c->incw = c->inch = 0; -+++ if (size.flags & PMaxSize) { -+++ c->maxw = size.max_width; -+++ c->maxh = size.max_height; -+++ } else -+++ c->maxw = c->maxh = 0; -+++ if (size.flags & PMinSize) { -+++ c->minw = size.min_width; -+++ c->minh = size.min_height; -+++ } else if (size.flags & PBaseSize) { -+++ c->minw = size.base_width; -+++ c->minh = size.base_height; -+++ } else -+++ c->minw = c->minh = 0; -+++ if (size.flags & PAspect) { -+++ c->mina = (float)size.min_aspect.y / size.min_aspect.x; -+++ c->maxa = (float)size.max_aspect.x / size.max_aspect.y; -+++ } else -+++ c->maxa = c->mina = 0.0; -+++ c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); -+++} -+++ -+++void -+++updatestatus(void) -+++{ -+++ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) -+++ strcpy(stext, "dwm-"VERSION); -+++ drawbar(selmon); -+++} -+++ -+++void -+++updatetitle(Client *c) -+++{ -+++ if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) -+++ gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); -+++ if (c->name[0] == '\0') /* hack to mark broken clients */ -+++ strcpy(c->name, broken); -+++} -+++ -+++void -+++updatewindowtype(Client *c) -+++{ -+++ Atom state = getatomprop(c, netatom[NetWMState]); -+++ Atom wtype = getatomprop(c, netatom[NetWMWindowType]); -+++ -+++ if (state == netatom[NetWMFullscreen]) -+++ setfullscreen(c, 1); -+++ if (wtype == netatom[NetWMWindowTypeDialog]) -+++ c->isfloating = 1; -+++} -+++ -+++void -+++updatewmhints(Client *c) -+++{ -+++ XWMHints *wmh; -+++ -+++ if ((wmh = XGetWMHints(dpy, c->win))) { -+++ if (c == selmon->sel && wmh->flags & XUrgencyHint) { -+++ wmh->flags &= ~XUrgencyHint; -+++ XSetWMHints(dpy, c->win, wmh); -+++ } else -+++ c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; -+++ if (wmh->flags & InputHint) -+++ c->neverfocus = !wmh->input; -+++ else -+++ c->neverfocus = 0; -+++ XFree(wmh); -+++ } -+++} -+++ -+++void -+++view(const Arg *arg) -+++{ -+++ if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) -+++ return; -+++ selmon->seltags ^= 1; /* toggle sel tagset */ -+++ if (arg->ui & TAGMASK) -+++ selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; -+++ focus(NULL); -+++ arrange(selmon); -+++} -+++ -+++Client * -+++wintoclient(Window w) -+++{ -+++ Client *c; -+++ Monitor *m; -+++ -+++ for (m = mons; m; m = m->next) -+++ for (c = m->clients; c; c = c->next) -+++ if (c->win == w) -+++ return c; -+++ return NULL; -+++} -+++ -+++Monitor * -+++wintomon(Window w) -+++{ -+++ int x, y; -+++ Client *c; -+++ Monitor *m; -+++ -+++ if (w == root && getrootptr(&x, &y)) -+++ return recttomon(x, y, 1, 1); -+++ for (m = mons; m; m = m->next) -+++ if (w == m->barwin) -+++ return m; -+++ if ((c = wintoclient(w))) -+++ return c->mon; -+++ return selmon; -+++} -+++ -+++/* There's no way to check accesses to destroyed windows, thus those cases are -+++ * ignored (especially on UnmapNotify's). Other types of errors call Xlibs -+++ * default error handler, which may call exit. */ -+++int -+++xerror(Display *dpy, XErrorEvent *ee) -+++{ -+++ if (ee->error_code == BadWindow -+++ || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) -+++ || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) -+++ || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) -+++ || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) -+++ || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) -+++ || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) -+++ || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) -+++ || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) -+++ return 0; -+++ fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", -+++ ee->request_code, ee->error_code); -+++ return xerrorxlib(dpy, ee); /* may call exit */ -+++} -+++ -+++int -+++xerrordummy(Display *dpy, XErrorEvent *ee) -+++{ -+++ return 0; -+++} -+++ -+++/* Startup Error handler to check if another window manager -+++ * is already running. */ -+++int -+++xerrorstart(Display *dpy, XErrorEvent *ee) -+++{ -+++ die("dwm: another window manager is already running"); -+++ return -1; -+++} -+++ -+++void -+++zoom(const Arg *arg) -+++{ -+++ Client *c = selmon->sel; -+++ -+++ if (!selmon->lt[selmon->sellt]->arrange -+++ || (selmon->sel && selmon->sel->isfloating)) -+++ return; -+++ if (c == nexttiled(selmon->clients)) -+++ if (!c || !(c = nexttiled(c->next))) -+++ return; -+++ pop(c); -+++} -+++ -+++int -+++main(int argc, char *argv[]) -+++{ -+++ if (argc == 2 && !strcmp("-v", argv[1])) -+++ die("dwm-"VERSION); -+++ else if (argc != 1) -+++ die("usage: dwm [-v]"); -+++ if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) -+++ fputs("warning: no locale support\n", stderr); -+++ if (!(dpy = XOpenDisplay(NULL))) -+++ die("dwm: cannot open display"); -+++ checkotherwm(); -+++ setup(); -+++#ifdef __OpenBSD__ -+++ if (pledge("stdio rpath proc exec", NULL) == -1) -+++ die("pledge"); -+++#endif /* __OpenBSD__ */ -+++ scan(); -+++ run(); -+++ cleanup(); -+++ XCloseDisplay(dpy); -+++ return EXIT_SUCCESS; -+++} -++diff --git a/dwm.c.rej b/dwm.c.rej -++new file mode 100644 -++index 0000000..079df04 -++--- /dev/null -+++++ b/dwm.c.rej -++@@ -0,0 +1,124 @@ -+++--- dwm.c -++++++ dwm.c -+++@@ -205,12 +245,16 @@ static void drawbar(Monitor *m); -+++ static void drawbars(void); -+++ static void enternotify(XEvent *e); -+++ static void expose(XEvent *e); -++++static Client *findbefore(Client *c); -+++ static void focus(Client *c); -+++ static void focusin(XEvent *e); -+++ static void focusmon(const Arg *arg); -+++ static void focusstack(const Arg *arg); -++++static int getdwmblockspid(); -++++static Atom getatomprop(Client *c, Atom prop); -+++ static int getrootptr(int *x, int *y); -+++ static long getstate(Window w); -++++static unsigned int getsystraywidth(); -+++ static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -+++ static void grabbuttons(Client *c, int focused); -+++ static void grabkeys(void); -+++@@ -590,9 +745,25 @@ 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 - getsystraywidth())) { -+++ click = ClkStatusText; -+++- else -++++ char *text = rawstext; -++++ int i = -1; -++++ char ch; -++++ dwmblockssig = 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; -++++ dwmblockssig = ch; -++++ } -++++ } -++++ } else -+++ click = ClkWinTitle; -+++ } else if ((c = wintoclient(ev->window))) { -+++ focus(c); -+++@@ -921,19 +1167,24 @@ dirtomon(int dir) -+++ void -+++ drawbar(Monitor *m) -+++ { -+++- int x, w, sw = 0; -++++ int indn; -++++ int x, w, sw = 0, stw = 0; -+++ int boxs = drw->fonts->h / 9; -+++ int boxw = drw->fonts->h / 6 + 2; -+++ unsigned int i, occ = 0, urg = 0; -+++ Client *c; -+++ -++++ if(showsystray && m == systraytomon(m)) -++++ stw = getsystraywidth(); -++++ -+++ /* 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]); -+++- sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -+++- drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); -++++ sw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding */ -++++ drw_text(drw, m->ww - sw - stw, 0, sw, bh, lrpad / 2 - 2, stext, 0); -+++ } -+++ -++++ resizebarwin(m); -+++ for (c = m->clients; c; c = c->next) { -+++ occ |= c->tags; -+++ if (c->isurgent) -+++@@ -941,20 +1192,25 @@ drawbar(Monitor *m) -+++ } -+++ x = 0; -+++ for (i = 0; i < LENGTH(tags); i++) { -++++ indn = 0; -+++ 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); -++++ -++++ for (c = m->clients; c; c = c->next) { -++++ if (c->tags & (1 << i)) { -++++ drw_rect(drw, x, 1 + (indn * 2), selmon->sel == c ? 6 : 1, 1, 1, urg & 1 << i); -++++ indn++; -++++ } -++++ } -++++ -+++ x += w; -+++ } -+++ w = blw = TEXTW(m->ltsymbol); -+++ drw_setscheme(drw, scheme[SchemeNorm]); -+++ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); -+++ -+++- if ((w = m->ww - sw - x) > bh) { -++++ if ((w = m->ww - sw - stw - x) > bh) { -+++ if (m->sel) { -+++ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -+++ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -+++@@ -2216,13 +2776,15 @@ tile(Monitor *m) -+++ mw = m->ww; -+++ for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -+++ if (i < m->nmaster) { -+++- h = (m->wh - my) / (MIN(n, m->nmaster) - i); -++++ h = (m->wh - my) * (c->cfact / mfacts); -+++ resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -+++ my += HEIGHT(c); -++++ mfacts -= c->cfact; -+++ } else { -+++- h = (m->wh - ty) / (n - i); -++++ h = (m->wh - ty) * (c->cfact / sfacts); -+++ resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); -+++ ty += HEIGHT(c); -++++ sfacts -= c->cfact; -+++ } -+++ } -+++ -++diff --git a/dwm.desktop b/dwm.desktop -++new file mode 100644 -++index 0000000..5a6021f -++--- /dev/null -+++++ b/dwm.desktop -++@@ -0,0 +1,10 @@ -+++[Desktop Entry] -+++Version=6.3 -+++Type=Application -+++Name=dwm -+++Comment=Suckless' dynamic window manager -+++Exec=dwm -+++Icon=dwm -+++Terminal=false -+++StartupNotify=false -+++Categories=Application; -++diff --git a/dwmc b/dwmc -++new file mode 100755 -++index 0000000..5ff8dbc -++--- /dev/null -+++++ b/dwmc -++@@ -0,0 +1,40 @@ -+++#!/usr/bin/env sh -+++ -+++signal() { -+++ xsetroot -name "fsignal:$*" -+++} -+++ -+++case $# in -+++1) -+++ case $1 in -+++ setlayout | view | viewall | togglebar | togglefloating | zoom | killclient | quit) -+++ signal $1 -+++ ;; -+++ *) -+++ echo "Unknown command or missing one argument." -+++ exit 1 -+++ ;; -+++ esac -+++ ;; -+++2) -+++ case $1 in -+++ view) -+++ signal $1 ui $2 -+++ ;; -+++ viewex | toggleviewex | tagex | toggletagex | setlayoutex | focusstack | incnmaster | focusmon | tagmon) -+++ signal $1 i $2 -+++ ;; -+++ setmfact) -+++ signal $1 f $2 -+++ ;; -+++ *) -+++ echo "Unknown command or one too many arguments." -+++ exit 1 -+++ ;; -+++ esac -+++ ;; -+++*) -+++ echo "Too many arguments." -+++ exit 1 -+++ ;; -+++esac -++diff --git a/volsv b/volsv -++new file mode 100755 -++index 0000000..f79662b -++--- /dev/null -+++++ b/volsv -++@@ -0,0 +1,52 @@ -+++#!/bin/sh -+++# calculate average of two integers (for ALSA) -+++average () { -+++ echo "$(( $(( $1 + $2 )) / 2 ))$" -+++} -+++# print error message -+++printerror () { -+++ echo "$1 is not a recognized command or flag" -+++} -+++# if pulseaudio -+++pulsesv () { -+++ case "$1" in -+++ "up" | "-i") pamixer -i 5 ;; -+++ "down" | "-d") pamixer -d 5 ;; -+++ "toggle" | "-t") pamixer -t ;; -+++ "mic" | "-m") pamixer --source 1 -t ;; -+++ "getv" | "-v") printf "%s%%\n" "$(pamixer --get-volume)" ;; -+++ "getm" | "-g") pamixer --get-mute | sed 's/[Ff]alse/\[on\]/;s/[Tt]rue/\[off\]/' ;; -+++ *) printerror "$1" ;; -+++ esac -+++} -+++# if alsa -+++alsasv () { -+++ case "$1" in -+++ "up" | "-i") amixer sset Master 5%+ ;; -+++ "down" | "-d") amixer sset Master 5%- ;; -+++ "toggle" | "-t") amixer sset Master toggle ;; -+++ "mic" | "-m") amixer sset Capture toggle ;; -+++ "getv" | "-v") amixer sget Master | grep '\[[0-9]*\%\]' | cut -d' ' -f6 | sed 's/\[//;s/\]//g' ;; -+++ "getm" | "-g") amixer sget Master | grep '\[o[fn]' | cut -d' ' -f8 | head -1 ;; -+++ *) printerror "$1" ;; -+++ esac -+++} -+++#Search input for -+++echo "$@" | grep -q ' *-h *' && echo \ -+++"Volsv is Free software. You can use it for any purpose, but I make no guerantee about its usability or fitness "\ -+++"for any particular purpose. You are also free to redistribute, modify, and distribute your modifications to "\ -+++"volsv. Volsv is distributed under the BSD 3-Clause license to ensure full license compatibility with GNU, "\ -+++"Linux, and BSD operating systems. A copy of this license is included in the repository.\n\n"\ -+++"Volsv is a script designed to control the volume of a *NIX machine. The commands/flags are as follows: -+++increase volume: 'up' or '-i' -+++decrease volume: 'down' or '-d' -+++toggle volume mute: 'toggle' or '-t' -+++toggle mic mute: 'mic' or '-m' -+++get volume level: 'getv' or '-v' -+++get mute state: 'getm' or '-g'" && exit -+++ -+++for i in $@; do -+++ pgrep -x pulseaudio >/dev/null && pulsesv $1 || alsasv $1 -+++ pgrep -x dwmblocks >/dev/null && pkill -RTMIN+10 dwmblocks -+++ pgrep -x dwmbar >/dev/null && dwmbar-signal volume -+++done -+diff --git a/patches/dwm-actualfullscreen-20191112-cb3f58a.diff b/patches/dwm-actualfullscreen-20191112-cb3f58a.diff -+new file mode 100644 -+index 0000000..21eea19 -+--- /dev/null -++++ b/patches/dwm-actualfullscreen-20191112-cb3f58a.diff -+@@ -0,0 +1,53 @@ -++From 3a16816a6f5d38014c2a06ce395873c545c8789a Mon Sep 17 00:00:00 2001 -++From: Soenke Lambert <s.lambert@mittwald.de> -++Date: Tue, 12 Nov 2019 10:44:02 +0100 -++Subject: [PATCH] Fullscreen current window with [Alt]+[Shift]+[f] -++ -++This actually fullscreens a window, instead of just hiding the statusbar -++and applying the monocle layout. -++--- -++ config.def.h | 1 + -++ dwm.c | 8 ++++++++ -++ 2 files changed, 9 insertions(+) -++ -++diff --git a/config.def.h b/config.def.h -++index 1c0b587..8cd3204 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -78,6 +78,7 @@ static Key keys[] = { -++ { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -++ { MODKEY, XK_space, setlayout, {0} }, -++ { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, -+++ { MODKEY|ShiftMask, XK_f, togglefullscr, {0} }, -++ { MODKEY, XK_0, view, {.ui = ~0 } }, -++ { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, -++ { MODKEY, XK_comma, focusmon, {.i = -1 } }, -++diff --git a/dwm.c b/dwm.c -++index 4465af1..c1b899a 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -211,6 +211,7 @@ static void tagmon(const Arg *arg); -++ static void tile(Monitor *); -++ static void togglebar(const Arg *arg); -++ static void togglefloating(const Arg *arg); -+++static void togglefullscr(const Arg *arg); -++ static void toggletag(const Arg *arg); -++ static void toggleview(const Arg *arg); -++ static void unfocus(Client *c, int setfocus); -++@@ -1719,6 +1720,13 @@ togglefloating(const Arg *arg) -++ arrange(selmon); -++ } -++ -+++void -+++togglefullscr(const Arg *arg) -+++{ -+++ if(selmon->sel) -+++ setfullscreen(selmon->sel, !selmon->sel->isfullscreen); -+++} -+++ -++ void -++ toggletag(const Arg *arg) -++ { -++-- -++2.17.1 -++ -+diff --git a/patches/dwm-attachbelow-toggleable-6.2.diff b/patches/dwm-attachbelow-toggleable-6.2.diff -+new file mode 100644 -+index 0000000..e5ff9fd -+--- /dev/null -++++ b/patches/dwm-attachbelow-toggleable-6.2.diff -+@@ -0,0 +1,199 @@ -++From ee036687ed9e1bb973b9e34694a57cf5dd67652d Mon Sep 17 00:00:00 2001 -++From: Jonathan Hodgson <git@jonathanh.co.uk> -++Date: Mon, 6 May 2019 18:34:40 +0100 -++Subject: [PATCH 1/4] Adds attach below option -++ -++--- -++ config.def.h | 1 + -++ dwm.c | 31 ++++++++++++++++++++++++++++--- -++ 2 files changed, 29 insertions(+), 3 deletions(-) -++ -++diff --git a/config.def.h b/config.def.h -++index 1c0b587..51ad933 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -35,6 +35,7 @@ static const Rule rules[] = { -++ 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 attachbelow = 1; /* 1 means attach at the end */ -++ -++ static const Layout layouts[] = { -++ /* symbol arrange function */ -++diff --git a/dwm.c b/dwm.c -++index 4465af1..bd715a2 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 attachBelow(Client *c); -++ static void attachstack(Client *c); -++ static void buttonpress(XEvent *e); -++ static void checkotherwm(void); -++@@ -405,6 +406,21 @@ attach(Client *c) -++ c->next = c->mon->clients; -++ c->mon->clients = c; -++ } -+++void -+++attachBelow(Client *c) -+++{ -+++ //If there is nothing on the monitor or the selected client is floating, attach as normal -+++ if(c->mon->sel == NULL || c->mon->sel->isfloating) { -+++ attach(c); -+++ return; -+++ } -+++ -+++ //Set the new client's next property to the same as the currently selected clients next -+++ c->next = c->mon->sel->next; -+++ //Set the currently selected clients next property to the new client -+++ c->mon->sel->next = c; -+++ -+++} -++ -++ void -++ attachstack(Client *c) -++@@ -1062,7 +1078,10 @@ manage(Window w, XWindowAttributes *wa) -++ c->isfloating = c->oldstate = trans != None || c->isfixed; -++ if (c->isfloating) -++ XRaiseWindow(dpy, c->win); -++- attach(c); -+++ if( attachbelow ) -+++ attachBelow(c); -+++ else -+++ attach(c); -++ attachstack(c); -++ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, -++ (unsigned char *) &(c->win), 1); -++@@ -1417,7 +1436,10 @@ sendmon(Client *c, Monitor *m) -++ detachstack(c); -++ c->mon = m; -++ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -++- attach(c); -+++ if( attachbelow ) -+++ attachBelow(c); -+++ else -+++ attach(c); -++ attachstack(c); -++ focus(NULL); -++ arrange(NULL); -++@@ -1897,7 +1919,10 @@ updategeom(void) -++ m->clients = c->next; -++ detachstack(c); -++ c->mon = mons; -++- attach(c); -+++ if( attachbelow ) -+++ attachBelow(c); -+++ else -+++ attach(c); -++ attachstack(c); -++ } -++ if (m == selmon) -++-- -++2.21.0 -++ -++ -++From e212c1d8cbdcc56c33c717131dfa7c1689e27e9f Mon Sep 17 00:00:00 2001 -++From: Jonathan Hodgson <git@jonathanh.co.uk> -++Date: Mon, 6 May 2019 19:27:57 +0100 -++Subject: [PATCH 2/4] fixes comment -++ -++--- -++ config.def.h | 2 +- -++ 1 file changed, 1 insertion(+), 1 deletion(-) -++ -++diff --git a/config.def.h b/config.def.h -++index 51ad933..cb8053a 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -35,7 +35,7 @@ static const Rule rules[] = { -++ 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 attachbelow = 1; /* 1 means attach at the end */ -+++static const int attachbelow = 1; /* 1 means attach after the currently active window */ -++ -++ static const Layout layouts[] = { -++ /* symbol arrange function */ -++-- -++2.21.0 -++ -++ -++From 7568ea3f8756e7e82b30c4943556ae646a445d1c Mon Sep 17 00:00:00 2001 -++From: Jonathan Hodgson <git@jonathanh.co.uk> -++Date: Mon, 6 May 2019 20:00:30 +0100 -++Subject: [PATCH 3/4] Makes changes to man page to reflect attach below patch -++ -++--- -++ dwm.1 | 3 +++ -++ 1 file changed, 3 insertions(+) -++ -++diff --git a/dwm.1 b/dwm.1 -++index 13b3729..fb6e76c 100644 -++--- a/dwm.1 -+++++ b/dwm.1 -++@@ -29,6 +29,9 @@ 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 -+++The attach below patch makes newly spawned windows attach after the currently -+++selected window -+++.P -++ dwm draws a small border around windows to indicate the focus state. -++ .SH OPTIONS -++ .TP -++-- -++2.21.0 -++ -++ -++From 362b95a5b9f91673f27f3e3343b5738df3c9d6e9 Mon Sep 17 00:00:00 2001 -++From: Jonathan Hodgson <git@jonathanh.co.uk> -++Date: Sun, 2 Jun 2019 15:11:57 +0100 -++Subject: [PATCH 4/4] Allows attach below to be toggled -++ -++--- -++ config.def.h | 2 +- -++ dwm.c | 6 ++++++ -++ 2 files changed, 7 insertions(+), 1 deletion(-) -++ -++diff --git a/config.def.h b/config.def.h -++index cb8053a..b4d35aa 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -35,7 +35,7 @@ static const Rule rules[] = { -++ 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 attachbelow = 1; /* 1 means attach after the currently active window */ -+++static int attachbelow = 1; /* 1 means attach after the currently active window */ -++ -++ static const Layout layouts[] = { -++ /* symbol arrange function */ -++diff --git a/dwm.c b/dwm.c -++index bd715a2..5d88653 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -148,6 +148,7 @@ static void arrange(Monitor *m); -++ static void arrangemon(Monitor *m); -++ static void attach(Client *c); -++ static void attachBelow(Client *c); -+++static void toggleAttachBelow(); -++ static void attachstack(Client *c); -++ static void buttonpress(XEvent *e); -++ static void checkotherwm(void); -++@@ -422,6 +423,11 @@ attachBelow(Client *c) -++ -++ } -++ -+++void toggleAttachBelow() -+++{ -+++ attachbelow = !attachbelow; -+++} -+++ -++ void -++ attachstack(Client *c) -++ { -++-- -++2.21.0 -++ -+diff --git a/patches/dwm-autostart-20161205-bb3bd6f.diff b/patches/dwm-autostart-20161205-bb3bd6f.diff -+new file mode 100644 -+index 0000000..6f11eaf -+--- /dev/null -++++ b/patches/dwm-autostart-20161205-bb3bd6f.diff -+@@ -0,0 +1,39 @@ -++commit 5918623c5bd7fda155bf9dc3d33890c4ae1722d0 -++Author: Simon Bremer <simon.bremer@tum.de> -++Date: Thu Dec 22 17:31:07 2016 +0100 -++ -++ Applied and fixed autostart patch for previous version; -++ -++diff --git a/dwm.c b/dwm.c -++index d27cb67..066ed71 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -194,6 +194,7 @@ static void resizeclient(Client *c, int x, int y, int w, int h); -++ static void resizemouse(const Arg *arg); -++ static void restack(Monitor *m); -++ static void run(void); -+++static void runAutostart(void); -++ static void scan(void); -++ static int sendevent(Client *c, Atom proto); -++ static void sendmon(Client *c, Monitor *m); -++@@ -1386,6 +1387,12 @@ run(void) -++ } -++ -++ void -+++runAutostart(void) { -+++ system("cd ~/.dwm; ./autostart_blocking.sh"); -+++ system("cd ~/.dwm; ./autostart.sh &"); -+++} -+++ -+++void -++ scan(void) -++ { -++ unsigned int i, num; -++@@ -2145,6 +2152,7 @@ main(int argc, char *argv[]) -++ checkotherwm(); -++ setup(); -++ scan(); -+++ runAutostart(); -++ run(); -++ cleanup(); -++ XCloseDisplay(dpy); -+diff --git a/patches/dwm-cfacts-20200913-61bb8b2.diff b/patches/dwm-cfacts-20200913-61bb8b2.diff -+new file mode 100644 -+index 0000000..bb70e13 -+--- /dev/null -++++ b/patches/dwm-cfacts-20200913-61bb8b2.diff -+@@ -0,0 +1,117 @@ -++From c32a879432573d71dec7fcb4bf68927d2f4cdf10 Mon Sep 17 00:00:00 2001 -++From: iofq <cjriddz@protonmail.com> -++Date: Sat, 12 Sep 2020 22:28:09 -0500 -++Subject: [PATCH] Fixed 'cfacts' patch failure due to upstream commit -++ 'f09418bbb...' -++ -++--- -++ config.def.h | 3 +++ -++ dwm.c | 34 +++++++++++++++++++++++++++++++--- -++ 2 files changed, 34 insertions(+), 3 deletions(-) -++ -++diff --git a/config.def.h b/config.def.h -++index 1c0b587..83910c1 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -70,6 +70,9 @@ 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_h, setcfact, {.f = +0.25} }, -+++ { MODKEY|ShiftMask, XK_l, setcfact, {.f = -0.25} }, -+++ { MODKEY|ShiftMask, XK_o, setcfact, {.f = 0.00} }, -++ { MODKEY, XK_Return, zoom, {0} }, -++ { MODKEY, XK_Tab, view, {0} }, -++ { MODKEY|ShiftMask, XK_c, killclient, {0} }, -++diff --git a/dwm.c b/dwm.c -++index 664c527..5233229 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -87,6 +87,7 @@ typedef struct Client Client; -++ struct Client { -++ char name[256]; -++ float mina, maxa; -+++ float cfact; -++ int x, y, w, h; -++ int oldx, oldy, oldw, oldh; -++ int basew, baseh, incw, inch, maxw, maxh, minw, minh; -++@@ -201,6 +202,7 @@ static void setclientstate(Client *c, long state); -++ static void setfocus(Client *c); -++ static void setfullscreen(Client *c, int fullscreen); -++ static void setlayout(const Arg *arg); -+++static void setcfact(const Arg *arg); -++ static void setmfact(const Arg *arg); -++ static void setup(void); -++ static void seturgent(Client *c, int urg); -++@@ -1030,6 +1032,7 @@ manage(Window w, XWindowAttributes *wa) -++ c->w = c->oldw = wa->width; -++ c->h = c->oldh = wa->height; -++ c->oldbw = wa->border_width; -+++ c->cfact = 1.0; -++ -++ updatetitle(c); -++ if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { -++@@ -1512,6 +1515,23 @@ setlayout(const Arg *arg) -++ drawbar(selmon); -++ } -++ -+++void setcfact(const Arg *arg) { -+++ float f; -+++ Client *c; -+++ -+++ c = selmon->sel; -+++ -+++ if(!arg || !c || !selmon->lt[selmon->sellt]->arrange) -+++ return; -+++ f = arg->f + c->cfact; -+++ if(arg->f == 0.0) -+++ f = 1.0; -+++ else if(f < 0.25 || f > 4.0) -+++ return; -+++ c->cfact = f; -+++ arrange(selmon); -+++} -+++ -++ /* arg > 1.0 will set mfact absolutely */ -++ void -++ setmfact(const Arg *arg) -++@@ -1675,9 +1695,15 @@ void -++ tile(Monitor *m) -++ { -++ unsigned int i, n, h, mw, my, ty; -+++ float mfacts = 0, sfacts = 0; -++ Client *c; -++ -++- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -+++ for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { -+++ if (n < m->nmaster) -+++ mfacts += c->cfact; -+++ else -+++ sfacts += c->cfact; -+++ } -++ if (n == 0) -++ return; -++ -++@@ -1687,15 +1713,17 @@ tile(Monitor *m) -++ mw = m->ww; -++ for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) -++ if (i < m->nmaster) { -++- h = (m->wh - my) / (MIN(n, m->nmaster) - i); -+++ h = (m->wh - my) * (c->cfact / mfacts); -++ resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); -++ if (my + HEIGHT(c) < m->wh) -++ my += HEIGHT(c); -+++ mfacts -= c->cfact; -++ } else { -++- h = (m->wh - ty) / (n - i); -+++ h = (m->wh - ty) * (c->cfact / sfacts); -++ resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); -++ if (ty + HEIGHT(c) < m->wh) -++ ty += HEIGHT(c); -+++ sfacts -= c->cfact; -++ } -++ } -++ -++-- -++2.28.0 -++ -+diff --git a/patches/dwm-clientindicators-6.2.diff b/patches/dwm-clientindicators-6.2.diff -+new file mode 100644 -+index 0000000..f2e9afb -+--- /dev/null -++++ b/patches/dwm-clientindicators-6.2.diff -+@@ -0,0 +1,48 @@ -++From 8c72f9ea7c9cd8d254b52a4f7059113c41483597 Mon Sep 17 00:00:00 2001 -++From: Miles Alan <m@milesalan.com> -++Date: Mon, 17 Aug 2020 20:33:45 -0500 -++Subject: [PATCH] Draws a dot indicator overlayed on each tag icon for each -++ client. The selected client is drawn as a larger horizontal line. -++ -++--- -++ dwm.c | 14 ++++++++++---- -++ 1 file changed, 10 insertions(+), 4 deletions(-) -++ -++diff --git a/dwm.c b/dwm.c -++index 4465af1..e0ca438 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -695,6 +695,7 @@ dirtomon(int dir) -++ void -++ drawbar(Monitor *m) -++ { -+++ int indn; -++ int x, w, sw = 0; -++ int boxs = drw->fonts->h / 9; -++ int boxw = drw->fonts->h / 6 + 2; -++@@ -715,13 +716,18 @@ drawbar(Monitor *m) -++ } -++ x = 0; -++ for (i = 0; i < LENGTH(tags); i++) { -+++ indn = 0; -++ 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); -+++ -+++ for (c = m->clients; c; c = c->next) { -+++ if (c->tags & (1 << i)) { -+++ drw_rect(drw, x, 1 + (indn * 2), selmon->sel == c ? 6 : 1, 1, 1, urg & 1 << i); -+++ indn++; -+++ } -+++ } -+++ -++ x += w; -++ } -++ w = blw = TEXTW(m->ltsymbol); -++-- -++2.25.4 -++ -+diff --git a/patches/dwm-dwmc-6.2.diff b/patches/dwm-dwmc-6.2.diff -+new file mode 100644 -+index 0000000..bf606d5 -+--- /dev/null -++++ b/patches/dwm-dwmc-6.2.diff -+@@ -0,0 +1,240 @@ -++From d94cb6f1a553d19127f44dbdc96e8bb5041956c2 Mon Sep 17 00:00:00 2001 -++From: Nihal Jere <noocsharp@gmail.com> -++Date: Sat, 21 Mar 2020 15:16:49 -0500 -++Subject: [PATCH] dwm-client -++ -++--- -++ Makefile | 2 +- -++ config.def.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++ -++ dwm.c | 55 +++++++++++++++++++++++++++++++++++++++-- -++ dwmc | 40 ++++++++++++++++++++++++++++++ -++ 4 files changed, 164 insertions(+), 3 deletions(-) -++ create mode 100755 dwmc -++ -++diff --git a/Makefile b/Makefile -++index 77bcbc0..f837f5c 100644 -++--- a/Makefile -+++++ b/Makefile -++@@ -38,7 +38,7 @@ dist: clean -++ -++ install: all -++ mkdir -p ${DESTDIR}${PREFIX}/bin -++- cp -f dwm ${DESTDIR}${PREFIX}/bin -+++ cp -f dwm dwmc ${DESTDIR}${PREFIX}/bin -++ chmod 755 ${DESTDIR}${PREFIX}/bin/dwm -++ mkdir -p ${DESTDIR}${MANPREFIX}/man1 -++ sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 -++diff --git a/config.def.h b/config.def.h -++index 1c0b587..efbae79 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -113,3 +113,73 @@ static Button buttons[] = { -++ { ClkTagBar, MODKEY, Button3, toggletag, {0} }, -++ }; -++ -+++void -+++setlayoutex(const Arg *arg) -+++{ -+++ setlayout(&((Arg) { .v = &layouts[arg->i] })); -+++} -+++ -+++void -+++viewex(const Arg *arg) -+++{ -+++ view(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++viewall(const Arg *arg) -+++{ -+++ view(&((Arg){.ui = ~0})); -+++} -+++ -+++void -+++toggleviewex(const Arg *arg) -+++{ -+++ toggleview(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++tagex(const Arg *arg) -+++{ -+++ tag(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++toggletagex(const Arg *arg) -+++{ -+++ toggletag(&((Arg) { .ui = 1 << arg->ui })); -+++} -+++ -+++void -+++tagall(const Arg *arg) -+++{ -+++ tag(&((Arg){.ui = ~0})); -+++} -+++ -+++/* signal definitions */ -+++/* signum must be greater than 0 */ -+++/* trigger signals using `xsetroot -name "fsignal:<signame> [<type> <value>]"` */ -+++static Signal signals[] = { -+++ /* signum function */ -+++ { "focusstack", focusstack }, -+++ { "setmfact", setmfact }, -+++ { "togglebar", togglebar }, -+++ { "incnmaster", incnmaster }, -+++ { "togglefloating", togglefloating }, -+++ { "focusmon", focusmon }, -+++ { "tagmon", tagmon }, -+++ { "zoom", zoom }, -+++ { "view", view }, -+++ { "viewall", viewall }, -+++ { "viewex", viewex }, -+++ { "toggleview", view }, -+++ { "toggleviewex", toggleviewex }, -+++ { "tag", tag }, -+++ { "tagall", tagall }, -+++ { "tagex", tagex }, -+++ { "toggletag", tag }, -+++ { "toggletagex", toggletagex }, -+++ { "killclient", killclient }, -+++ { "quit", quit }, -+++ { "setlayout", setlayout }, -+++ { "setlayoutex", setlayoutex }, -+++}; -++diff --git a/dwm.c b/dwm.c -++index 4465af1..aa53706 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -106,6 +106,11 @@ typedef struct { -++ const Arg arg; -++ } Key; -++ -+++typedef struct { -+++ const char * sig; -+++ void (*func)(const Arg *); -+++} Signal; -+++ -++ typedef struct { -++ const char *symbol; -++ void (*arrange)(Monitor *); -++@@ -148,6 +153,7 @@ static void arrange(Monitor *m); -++ static void arrangemon(Monitor *m); -++ static void attach(Client *c); -++ static void attachstack(Client *c); -+++static int fake_signal(void); -++ static void buttonpress(XEvent *e); -++ static void checkotherwm(void); -++ static void cleanup(void); -++@@ -998,6 +1004,49 @@ keypress(XEvent *e) -++ keys[i].func(&(keys[i].arg)); -++ } -++ -+++int -+++fake_signal(void) -+++{ -+++ char fsignal[256]; -+++ char indicator[9] = "fsignal:"; -+++ char str_sig[50]; -+++ char param[16]; -+++ int i, len_str_sig, n, paramn; -+++ size_t len_fsignal, len_indicator = strlen(indicator); -+++ Arg arg; -+++ -+++ // Get root name property -+++ if (gettextprop(root, XA_WM_NAME, fsignal, sizeof(fsignal))) { -+++ len_fsignal = strlen(fsignal); -+++ -+++ // Check if this is indeed a fake signal -+++ if (len_indicator > len_fsignal ? 0 : strncmp(indicator, fsignal, len_indicator) == 0) { -+++ paramn = sscanf(fsignal+len_indicator, "%s%n%s%n", str_sig, &len_str_sig, param, &n); -+++ -+++ if (paramn == 1) arg = (Arg) {0}; -+++ else if (paramn > 2) return 1; -+++ else if (strncmp(param, "i", n - len_str_sig) == 0) -+++ sscanf(fsignal + len_indicator + n, "%i", &(arg.i)); -+++ else if (strncmp(param, "ui", n - len_str_sig) == 0) -+++ sscanf(fsignal + len_indicator + n, "%u", &(arg.ui)); -+++ else if (strncmp(param, "f", n - len_str_sig) == 0) -+++ sscanf(fsignal + len_indicator + n, "%f", &(arg.f)); -+++ else return 1; -+++ -+++ // Check if a signal was found, and if so handle it -+++ for (i = 0; i < LENGTH(signals); i++) -+++ if (strncmp(str_sig, signals[i].sig, len_str_sig) == 0 && signals[i].func) -+++ signals[i].func(&(arg)); -+++ -+++ // A fake signal was sent -+++ return 1; -+++ } -+++ } -+++ -+++ // No fake signal was sent, so proceed with update -+++ return 0; -+++} -+++ -++ void -++ killclient(const Arg *arg) -++ { -++@@ -1215,8 +1264,10 @@ propertynotify(XEvent *e) -++ Window trans; -++ XPropertyEvent *ev = &e->xproperty; -++ -++- if ((ev->window == root) && (ev->atom == XA_WM_NAME)) -++- updatestatus(); -+++ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) { -+++ if (!fake_signal()) -+++ updatestatus(); -+++ } -++ else if (ev->state == PropertyDelete) -++ return; /* ignore */ -++ else if ((c = wintoclient(ev->window))) { -++diff --git a/dwmc b/dwmc -++new file mode 100755 -++index 0000000..5ff8dbc -++--- /dev/null -+++++ b/dwmc -++@@ -0,0 +1,40 @@ -+++#!/usr/bin/env sh -+++ -+++signal() { -+++ xsetroot -name "fsignal:$*" -+++} -+++ -+++case $# in -+++1) -+++ case $1 in -+++ setlayout | view | viewall | togglebar | togglefloating | zoom | killclient | quit) -+++ signal $1 -+++ ;; -+++ *) -+++ echo "Unknown command or missing one argument." -+++ exit 1 -+++ ;; -+++ esac -+++ ;; -+++2) -+++ case $1 in -+++ view) -+++ signal $1 ui $2 -+++ ;; -+++ viewex | toggleviewex | tagex | toggletagex | setlayoutex | focusstack | incnmaster | focusmon | tagmon) -+++ signal $1 i $2 -+++ ;; -+++ setmfact) -+++ signal $1 f $2 -+++ ;; -+++ *) -+++ echo "Unknown command or one too many arguments." -+++ exit 1 -+++ ;; -+++ esac -+++ ;; -+++*) -+++ echo "Too many arguments." -+++ exit 1 -+++ ;; -+++esac -++-- -++2.25.1 -++ -+diff --git a/patches/dwm-push_no_master-6.2.diff b/patches/dwm-push_no_master-6.2.diff -+new file mode 100644 -+index 0000000..873e438 -+--- /dev/null -++++ b/patches/dwm-push_no_master-6.2.diff -+@@ -0,0 +1,70 @@ -++diff --git a/dwm.c b/dwm.c -++index 4465af1..49e63f0 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -185,7 +185,10 @@ static void motionnotify(XEvent *e); -++ static void movemouse(const Arg *arg); -++ static Client *nexttiled(Client *c); -++ static void pop(Client *); -+++static Client *prevtiled(Client *c); -++ static void propertynotify(XEvent *e); -+++static void pushdown(const Arg *arg); -+++static void pushup(const Arg *arg); -++ static void quit(const Arg *arg); -++ static Monitor *recttomon(int x, int y, int w, int h); -++ static void resize(Client *c, int x, int y, int w, int h, int interact); -++@@ -1208,6 +1211,16 @@ pop(Client *c) -++ arrange(c->mon); -++ } -++ -+++Client * -+++prevtiled(Client *c) { -+++ Client *p, *r; -+++ -+++ for(p = selmon->clients, r = NULL; p && p != c; p = p->next) -+++ if(!p->isfloating && ISVISIBLE(p)) -+++ r = p; -+++ return r; -+++} -+++ -++ void -++ propertynotify(XEvent *e) -++ { -++@@ -1245,6 +1258,37 @@ propertynotify(XEvent *e) -++ } -++ } -++ -+++void -+++pushdown(const Arg *arg) { -+++ Client *sel = selmon->sel, *c; -+++ -+++ if(!sel || sel->isfloating || sel == nexttiled(selmon->clients)) -+++ return; -+++ if((c = nexttiled(sel->next))) { -+++ detach(sel); -+++ sel->next = c->next; -+++ c->next = sel; -+++ } -+++ focus(sel); -+++ arrange(selmon); -+++} -+++ -+++void -+++pushup(const Arg *arg) { -+++ Client *sel = selmon->sel, *c; -+++ -+++ if(!sel || sel->isfloating) -+++ return; -+++ if((c = prevtiled(sel)) && c != nexttiled(selmon->clients)) { -+++ detach(sel); -+++ sel->next = c; -+++ for(c = selmon->clients; c->next != sel->next; c = c->next); -+++ c->next = sel; -+++ } -+++ focus(sel); -+++ arrange(selmon); -+++} -+++ -++ void -++ quit(const Arg *arg) -++ { -+diff --git a/patches/dwm-restartsig-20180523-6.2.diff b/patches/dwm-restartsig-20180523-6.2.diff -+new file mode 100644 -+index 0000000..f1f8680 -+--- /dev/null -++++ b/patches/dwm-restartsig-20180523-6.2.diff -+@@ -0,0 +1,139 @@ -++From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 -++From: Christopher Drelich <cd@cdrakka.com> -++Date: Wed, 23 May 2018 22:50:38 -0400 -++Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM -++ handlers. -++ -++Modified quit() to restart if it receives arg .i = 1 -++MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that. -++ -++Signal handlers were handled for SIGHUP and SIGTERM. -++If dwm receives these signals it calls quit() with -++arg .i = to 1 or 0, respectively. -++ -++To restart dwm: -++MOD+CTRL+SHIFT+Q -++or -++kill -HUP dwmpid -++ -++To quit dwm cleanly: -++MOD+SHIFT+Q -++or -++kill -TERM dwmpid -++--- -++ config.def.h | 1 + -++ dwm.1 | 10 ++++++++++ -++ dwm.c | 22 ++++++++++++++++++++++ -++ 3 files changed, 33 insertions(+) -++ -++diff --git a/config.def.h b/config.def.h -++index a9ac303..e559429 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -94,6 +94,7 @@ static Key keys[] = { -++ TAGKEYS( XK_8, 7) -++ TAGKEYS( XK_9, 8) -++ { MODKEY|ShiftMask, XK_q, quit, {0} }, -+++ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, -++ }; -++ -++ /* button definitions */ -++diff --git a/dwm.1 b/dwm.1 -++index 13b3729..36a331c 100644 -++--- a/dwm.1 -+++++ b/dwm.1 -++@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. -++ .TP -++ .B Mod1\-Shift\-q -++ Quit dwm. -+++.TP -+++.B Mod1\-Control\-Shift\-q -+++Restart dwm. -++ .SS Mouse commands -++ .TP -++ .B Mod1\-Button1 -++@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float -++ .SH CUSTOMIZATION -++ dwm is customized by creating a custom config.h and (re)compiling the source -++ code. This keeps it fast, secure and simple. -+++.SH SIGNALS -+++.TP -+++.B SIGHUP - 1 -+++Restart the dwm process. -+++.TP -+++.B SIGTERM - 15 -+++Cleanly terminate the dwm process. -++ .SH SEE ALSO -++ .BR dmenu (1), -++ .BR st (1) -++diff --git a/dwm.c b/dwm.c -++index bb95e26..286eecd 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -205,6 +205,8 @@ static void setup(void); -++ static void seturgent(Client *c, int urg); -++ static void showhide(Client *c); -++ static void sigchld(int unused); -+++static void sighup(int unused); -+++static void sigterm(int unused); -++ static void spawn(const Arg *arg); -++ static void tag(const Arg *arg); -++ static void tagmon(const Arg *arg); -++@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { -++ [UnmapNotify] = unmapnotify -++ }; -++ static Atom wmatom[WMLast], netatom[NetLast]; -+++static int restart = 0; -++ static int running = 1; -++ static Cur *cursor[CurLast]; -++ static Clr **scheme; -++@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e) -++ void -++ quit(const Arg *arg) -++ { -+++ if(arg->i) restart = 1; -++ running = 0; -++ } -++ -++@@ -1536,6 +1540,9 @@ setup(void) -++ /* clean up any zombies immediately */ -++ sigchld(0); -++ -+++ signal(SIGHUP, sighup); -+++ signal(SIGTERM, sigterm); -+++ -++ /* init screen */ -++ screen = DefaultScreen(dpy); -++ sw = DisplayWidth(dpy, screen); -++@@ -1637,6 +1644,20 @@ sigchld(int unused) -++ } -++ -++ void -+++sighup(int unused) -+++{ -+++ Arg a = {.i = 1}; -+++ quit(&a); -+++} -+++ -+++void -+++sigterm(int unused) -+++{ -+++ Arg a = {.i = 0}; -+++ quit(&a); -+++} -+++ -+++void -++ spawn(const Arg *arg) -++ { -++ if (arg->v == dmenucmd) -++@@ -2139,6 +2160,7 @@ main(int argc, char *argv[]) -++ setup(); -++ scan(); -++ run(); -+++ if(restart) execvp(argv[0], argv); -++ cleanup(); -++ XCloseDisplay(dpy); -++ return EXIT_SUCCESS; -++-- -++2.7.4 -++ -+diff --git a/patches/dwm-statuscmd-signal-6.2.diff b/patches/dwm-statuscmd-signal-6.2.diff -+new file mode 100644 -+index 0000000..97fda1b -+--- /dev/null -++++ b/patches/dwm-statuscmd-signal-6.2.diff -+@@ -0,0 +1,157 @@ -++diff --git a/config.def.h b/config.def.h -++index 1c0b587..b67825e 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -103,7 +103,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, sigdwmblocks, {.i = 1} }, -+++ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} }, -+++ { ClkStatusText, 0, Button3, sigdwmblocks, {.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 4465af1..c600131 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); -++@@ -169,6 +170,7 @@ static void focus(Client *c); -++ static void focusin(XEvent *e); -++ static void focusmon(const Arg *arg); -++ static void focusstack(const Arg *arg); -+++static int getdwmblockspid(); -++ static int getrootptr(int *x, int *y); -++ static long getstate(Window w); -++ static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -++@@ -205,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 sigdwmblocks(const Arg *arg); -++ static void spawn(const Arg *arg); -++ static void tag(const Arg *arg); -++ static void tagmon(const Arg *arg); -++@@ -237,6 +240,9 @@ static void zoom(const Arg *arg); -++ /* variables */ -++ static const char broken[] = "broken"; -++ static char stext[256]; -+++static char rawstext[256]; -+++static int dwmblockssig; -+++pid_t dwmblockspid = 0; -++ static int screen; -++ static int sw, sh; /* X display screen geometry width, height */ -++ static int bh, blw = 0; /* bar geometry */ -++@@ -439,9 +445,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; -+++ dwmblockssig = 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; -+++ dwmblockssig = ch; -+++ } -+++ } -+++ } else -++ click = ClkWinTitle; -++ } else if ((c = wintoclient(ev->window))) { -++ focus(c); -++@@ -627,6 +650,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) -++ { -++@@ -871,6 +907,18 @@ getatomprop(Client *c, Atom prop) -++ return atom; -++ } -++ -+++int -+++getdwmblockspid() -+++{ -+++ char buf[16]; -+++ FILE *fp = popen("pidof -s dwmblocks", "r"); -+++ fgets(buf, sizeof(buf), fp); -+++ pid_t pid = strtoul(buf, NULL, 10); -+++ pclose(fp); -+++ dwmblockspid = pid; -+++ return pid != 0 ? 0 : -1; -+++} -+++ -++ int -++ getrootptr(int *x, int *y) -++ { -++@@ -1636,6 +1684,23 @@ sigchld(int unused) -++ while (0 < waitpid(-1, NULL, WNOHANG)); -++ } -++ -+++void -+++sigdwmblocks(const Arg *arg) -+++{ -+++ union sigval sv; -+++ sv.sival_int = (dwmblockssig << 8) | arg->i; -+++ if (!dwmblockspid) -+++ if (getdwmblockspid() == -1) -+++ return; -+++ -+++ if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) { -+++ if (errno == ESRCH) { -+++ if (!getdwmblockspid()) -+++ sigqueue(dwmblockspid, SIGUSR1, sv); -+++ } -+++ } -+++} -+++ -++ void -++ spawn(const Arg *arg) -++ { -++@@ -1987,8 +2052,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); -++ } -++ -+diff --git a/patches/dwm-swallow-20200522-7accbcf.diff b/patches/dwm-swallow-20200522-7accbcf.diff -+new file mode 100644 -+index 0000000..1cb144f -+--- /dev/null -++++ b/patches/dwm-swallow-20200522-7accbcf.diff -+@@ -0,0 +1,420 @@ -++From 7accbcf7db35995d4c26c5cd69338aafa6feb89a Mon Sep 17 00:00:00 2001 -++From: wtl <wtl144000@gmail.com> -++Date: Fri, 22 May 2020 22:38:38 +0300 -++Subject: [PATCH] swallow X windows from the terminal -++ -++--- -++ config.def.h | 9 ++- -++ config.mk | 2 +- -++ dwm.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++-- -++ 3 files changed, 220 insertions(+), 9 deletions(-) -++ -++diff --git a/config.def.h b/config.def.h -++index 1c0b587..4c0b25c 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -3,6 +3,7 @@ -++ /* appearance */ -++ static const unsigned int borderpx = 1; /* border pixel of windows */ -++ static const unsigned int snap = 32; /* snap pixel */ -+++static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ -++ static const int showbar = 1; /* 0 means no bar */ -++ static const int topbar = 1; /* 0 means bottom bar */ -++ static const char *fonts[] = { "monospace:size=10" }; -++@@ -26,9 +27,11 @@ static const Rule rules[] = { -++ * WM_CLASS(STRING) = instance, class -++ * WM_NAME(STRING) = title -++ */ -++- /* class instance title tags mask isfloating monitor */ -++- { "Gimp", NULL, NULL, 0, 1, -1 }, -++- { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, -+++ /* class instance title tags mask isfloating isterminal noswallow monitor */ -+++ { "Gimp", NULL, NULL, 0, 1, 0, 0, -1 }, -+++ { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1, -1 }, -+++ { "st", NULL, NULL, 0, 0, 1, -1, -1 }, -+++ { NULL, NULL, "Event Tester", 0, 1, 0, 1, -1 }, /* xev */ -++ }; -++ -++ /* layout(s) */ -++diff --git a/config.mk b/config.mk -++index 7084c33..b77641d 100644 -++--- a/config.mk -+++++ b/config.mk -++@@ -22,7 +22,7 @@ FREETYPEINC = /usr/include/freetype2 -++ -++ # includes and libs -++ INCS = -I${X11INC} -I${FREETYPEINC} -++-LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -+++LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} -lX11-xcb -lxcb -lxcb-res -++ -++ # flags -++ CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -++diff --git a/dwm.c b/dwm.c -++index 9fd0286..1befee4 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -40,6 +40,8 @@ -++ #include <X11/extensions/Xinerama.h> -++ #endif /* XINERAMA */ -++ #include <X11/Xft/Xft.h> -+++#include <X11/Xlib-xcb.h> -+++#include <xcb/res.h> -++ -++ #include "drw.h" -++ #include "util.h" -++@@ -92,9 +94,11 @@ struct Client { -++ int basew, baseh, incw, inch, maxw, maxh, minw, minh; -++ int bw, oldbw; -++ unsigned int tags; -++- int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; -+++ int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; -+++ pid_t pid; -++ Client *next; -++ Client *snext; -+++ Client *swallowing; -++ Monitor *mon; -++ Window win; -++ }; -++@@ -138,6 +142,8 @@ typedef struct { -++ const char *title; -++ unsigned int tags; -++ int isfloating; -+++ int isterminal; -+++ int noswallow; -++ int monitor; -++ } Rule; -++ -++@@ -235,9 +241,16 @@ static int xerrordummy(Display *dpy, XErrorEvent *ee); -++ static int xerrorstart(Display *dpy, XErrorEvent *ee); -++ static void zoom(const Arg *arg); -++ -+++static pid_t getparentprocess(pid_t p); -+++static int isdescprocess(pid_t p, pid_t c); -+++static Client *swallowingclient(Window w); -+++static Client *termforwin(const Client *c); -+++static pid_t winpid(Window w); -+++ -++ /* variables */ -++ static const char broken[] = "broken"; -++ static char stext[256]; -+++static int scanner; -++ static int screen; -++ static int sw, sh; /* X display screen geometry width, height */ -++ static int bh, blw = 0; /* bar geometry */ -++@@ -269,6 +282,8 @@ static Drw *drw; -++ static Monitor *mons, *selmon; -++ static Window root, wmcheckwin; -++ -+++static xcb_connection_t *xcon; -+++ -++ /* configuration, allows nested code to access above variables */ -++ #include "config.h" -++ -++@@ -286,6 +301,7 @@ applyrules(Client *c) -++ XClassHint ch = { NULL, NULL }; -++ -++ /* rule matching */ -+++ c->noswallow = -1; -++ c->isfloating = 0; -++ c->tags = 0; -++ XGetClassHint(dpy, c->win, &ch); -++@@ -298,6 +314,8 @@ applyrules(Client *c) -++ && (!r->class || strstr(class, r->class)) -++ && (!r->instance || strstr(instance, r->instance))) -++ { -+++ c->isterminal = r->isterminal; -+++ c->noswallow = r->noswallow; -++ c->isfloating = r->isfloating; -++ c->tags |= r->tags; -++ for (m = mons; m && m->num != r->monitor; m = m->next); -++@@ -414,6 +432,61 @@ attachstack(Client *c) -++ c->mon->stack = c; -++ } -++ -+++void -+++swallow(Client *p, Client *c) -+++{ -+++ Client *s; -+++ -+++ if (c->noswallow > 0 || c->isterminal) -+++ return; -+++ if (c->noswallow < 0 && !swallowfloating && c->isfloating) -+++ return; -+++ -+++ detach(c); -+++ detachstack(c); -+++ -+++ setclientstate(c, WithdrawnState); -+++ XUnmapWindow(dpy, p->win); -+++ -+++ p->swallowing = c; -+++ c->mon = p->mon; -+++ -+++ Window w = p->win; -+++ p->win = c->win; -+++ c->win = w; -+++ -+++ XChangeProperty(dpy, c->win, netatom[NetClientList], XA_WINDOW, 32, PropModeReplace, -+++ (unsigned char *) &(p->win), 1); -+++ -+++ updatetitle(p); -+++ s = scanner ? c : p; -+++ XMoveResizeWindow(dpy, p->win, s->x, s->y, s->w, s->h); -+++ arrange(p->mon); -+++ configure(p); -+++ updateclientlist(); -+++} -+++ -+++void -+++unswallow(Client *c) -+++{ -+++ c->win = c->swallowing->win; -+++ -+++ free(c->swallowing); -+++ c->swallowing = NULL; -+++ -+++ XDeleteProperty(dpy, c->win, netatom[NetClientList]); -+++ -+++ /* unfullscreen the client */ -+++ setfullscreen(c, 0); -+++ updatetitle(c); -+++ arrange(c->mon); -+++ XMapWindow(dpy, c->win); -+++ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); -+++ setclientstate(c, NormalState); -+++ focus(NULL); -+++ arrange(c->mon); -+++} -+++ -++ void -++ buttonpress(XEvent *e) -++ { -++@@ -653,6 +726,9 @@ destroynotify(XEvent *e) -++ -++ if ((c = wintoclient(ev->window))) -++ unmanage(c, 1); -+++ -+++ else if ((c = swallowingclient(ev->window))) -+++ unmanage(c->swallowing, 1); -++ } -++ -++ void -++@@ -1018,12 +1094,13 @@ killclient(const Arg *arg) -++ void -++ manage(Window w, XWindowAttributes *wa) -++ { -++- Client *c, *t = NULL; -+++ Client *c, *t = NULL, *term = NULL; -++ Window trans = None; -++ XWindowChanges wc; -++ -++ c = ecalloc(1, sizeof(Client)); -++ c->win = w; -+++ c->pid = winpid(w); -++ /* geometry */ -++ c->x = c->oldx = wa->x; -++ c->y = c->oldy = wa->y; -++@@ -1038,6 +1115,7 @@ manage(Window w, XWindowAttributes *wa) -++ } else { -++ c->mon = selmon; -++ applyrules(c); -+++ term = termforwin(c); -++ } -++ -++ if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) -++@@ -1074,6 +1152,8 @@ manage(Window w, XWindowAttributes *wa) -++ c->mon->sel = c; -++ arrange(c->mon); -++ XMapWindow(dpy, c->win); -+++ if (term) -+++ swallow(term, c); -++ focus(NULL); -++ } -++ -++@@ -1384,7 +1464,9 @@ run(void) -++ void -++ scan(void) -++ { -+++ scanner = 1; -++ unsigned int i, num; -+++ char swin[256]; -++ Window d1, d2, *wins = NULL; -++ XWindowAttributes wa; -++ -++@@ -1395,6 +1477,8 @@ scan(void) -++ continue; -++ if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) -++ manage(wins[i], &wa); -+++ else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin)) -+++ manage(wins[i], &wa); -++ } -++ for (i = 0; i < num; i++) { /* now the transients */ -++ if (!XGetWindowAttributes(dpy, wins[i], &wa)) -++@@ -1406,6 +1490,7 @@ scan(void) -++ if (wins) -++ XFree(wins); -++ } -+++ scanner = 0; -++ } -++ -++ void -++@@ -1768,6 +1853,20 @@ unmanage(Client *c, int destroyed) -++ Monitor *m = c->mon; -++ XWindowChanges wc; -++ -+++ if (c->swallowing) { -+++ unswallow(c); -+++ return; -+++ } -+++ -+++ Client *s = swallowingclient(c->win); -+++ if (s) { -+++ free(s->swallowing); -+++ s->swallowing = NULL; -+++ arrange(m); -+++ focus(NULL); -+++ return; -+++ } -+++ -++ detach(c); -++ detachstack(c); -++ if (!destroyed) { -++@@ -1782,9 +1881,12 @@ unmanage(Client *c, int destroyed) -++ XUngrabServer(dpy); -++ } -++ free(c); -++- focus(NULL); -++- updateclientlist(); -++- arrange(m); -+++ -+++ if (!s) { -+++ arrange(m); -+++ focus(NULL); -+++ updateclientlist(); -+++ } -++ } -++ -++ void -++@@ -2047,6 +2149,110 @@ view(const Arg *arg) -++ arrange(selmon); -++ } -++ -+++pid_t -+++winpid(Window w) -+++{ -+++ pid_t result = 0; -+++ -+++ xcb_res_client_id_spec_t spec = {0}; -+++ spec.client = w; -+++ spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; -+++ -+++ xcb_generic_error_t *e = NULL; -+++ xcb_res_query_client_ids_cookie_t c = xcb_res_query_client_ids(xcon, 1, &spec); -+++ xcb_res_query_client_ids_reply_t *r = xcb_res_query_client_ids_reply(xcon, c, &e); -+++ -+++ if (!r) -+++ return (pid_t)0; -+++ -+++ xcb_res_client_id_value_iterator_t i = xcb_res_query_client_ids_ids_iterator(r); -+++ for (; i.rem; xcb_res_client_id_value_next(&i)) { -+++ spec = i.data->spec; -+++ if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) { -+++ uint32_t *t = xcb_res_client_id_value_value(i.data); -+++ result = *t; -+++ break; -+++ } -+++ } -+++ -+++ free(r); -+++ -+++ if (result == (pid_t)-1) -+++ result = 0; -+++ return result; -+++} -+++ -+++pid_t -+++getparentprocess(pid_t p) -+++{ -+++ unsigned int v = 0; -+++ -+++#if defined(__linux__) -+++ FILE *f; -+++ char buf[256]; -+++ snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); -+++ -+++ if (!(f = fopen(buf, "r"))) -+++ return (pid_t)0; -+++ -+++ if (fscanf(f, "%*u %*s %*c %u", (unsigned *)&v) != 1) -+++ v = (pid_t)0; -+++ fclose(f); -+++#elif defined(__FreeBSD__) -+++ struct kinfo_proc *proc = kinfo_getproc(p); -+++ if (!proc) -+++ return (pid_t)0; -+++ -+++ v = proc->ki_ppid; -+++ free(proc); -+++#endif -+++ return (pid_t)v; -+++} -+++ -+++int -+++isdescprocess(pid_t p, pid_t c) -+++{ -+++ while (p != c && c != 0) -+++ c = getparentprocess(c); -+++ -+++ return (int)c; -+++} -+++ -+++Client * -+++termforwin(const Client *w) -+++{ -+++ Client *c; -+++ Monitor *m; -+++ -+++ if (!w->pid || w->isterminal) -+++ return NULL; -+++ -+++ for (m = mons; m; m = m->next) { -+++ for (c = m->clients; c; c = c->next) { -+++ if (c->isterminal && !c->swallowing && c->pid && isdescprocess(c->pid, w->pid)) -+++ return c; -+++ } -+++ } -+++ -+++ return NULL; -+++} -+++ -+++Client * -+++swallowingclient(Window w) -+++{ -+++ Client *c; -+++ Monitor *m; -+++ -+++ for (m = mons; m; m = m->next) { -+++ for (c = m->clients; c; c = c->next) { -+++ if (c->swallowing && c->swallowing->win == w) -+++ return c; -+++ } -+++ } -+++ -+++ return NULL; -+++} -+++ -++ Client * -++ wintoclient(Window w) -++ { -++@@ -2138,6 +2344,8 @@ main(int argc, char *argv[]) -++ fputs("warning: no locale support\n", stderr); -++ if (!(dpy = XOpenDisplay(NULL))) -++ die("dwm: cannot open display"); -+++ if (!(xcon = XGetXCBConnection(dpy))) -+++ die("dwm: cannot get xcb connection\n"); -++ checkotherwm(); -++ setup(); -++ #ifdef __OpenBSD__ -++-- -++2.26.2 -++ -+diff --git a/patches/dwm-systray-6.2.diff b/patches/dwm-systray-6.2.diff -+new file mode 100644 -+index 0000000..27187ac -+--- /dev/null -++++ b/patches/dwm-systray-6.2.diff -+@@ -0,0 +1,746 @@ -++From 4001ccae7b1a41bdcb247b0cf095a51af7b68c28 Mon Sep 17 00:00:00 2001 -++From: Igor Gevka <igor.gevka@gmail.com> -++Date: Sun, 16 Feb 2020 15:03:10 -0800 -++Subject: [PATCH] [PATCH] Implements a system tray for dwm. -++ -++Original author: Jan Christoph Ebersbach <jceb@e-jc.de>, inspired by http://code.google.com/p/dwm-plus -++URL: http://dwm.suckless.org/patches/systray -++dwm 6.2 port by Igor Gevka <igor.gevka@gmail.com> -++--- -++ config.def.h | 4 + -++ dwm.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++---- -++ 2 files changed, 382 insertions(+), 26 deletions(-) -++ -++diff --git a/config.def.h b/config.def.h -++index 1c0b587..2d824d1 100644 -++--- a/config.def.h -+++++ b/config.def.h -++@@ -3,6 +3,10 @@ -++ /* appearance */ -++ static const unsigned int borderpx = 1; /* border pixel of 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 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 showbar = 1; /* 0 means no bar */ -++ static const int topbar = 1; /* 0 means bottom bar */ -++ static const char *fonts[] = { "monospace:size=10" }; -++diff --git a/dwm.c b/dwm.c -++index 4465af1..3e361fa 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -57,12 +57,30 @@ -++ #define TAGMASK ((1 << LENGTH(tags)) - 1) -++ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -++ -+++#define SYSTEM_TRAY_REQUEST_DOCK 0 -+++ -+++/* XEMBED messages */ -+++#define XEMBED_EMBEDDED_NOTIFY 0 -+++#define XEMBED_WINDOW_ACTIVATE 1 -+++#define XEMBED_FOCUS_IN 4 -+++#define XEMBED_MODALITY_ON 10 -+++ -+++#define XEMBED_MAPPED (1 << 0) -+++#define XEMBED_WINDOW_ACTIVATE 1 -+++#define XEMBED_WINDOW_DEACTIVATE 2 -+++ -+++#define VERSION_MAJOR 0 -+++#define VERSION_MINOR 0 -+++#define XEMBED_EMBEDDED_VERSION (VERSION_MAJOR << 16) | VERSION_MINOR -+++ -++ /* enums */ -++ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ -++ enum { SchemeNorm, SchemeSel }; /* color schemes */ -++ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, -+++ NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation, NetSystemTrayOrientationHorz, -++ NetWMFullscreen, NetActiveWindow, NetWMWindowType, -++ NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ -+++enum { Manager, Xembed, XembedInfo, XLast }; /* Xembed atoms */ -++ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -++ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, -++ ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ -++@@ -141,6 +159,12 @@ typedef struct { -++ int monitor; -++ } Rule; -++ -+++typedef struct Systray Systray; -+++struct Systray { -+++ Window win; -+++ Client *icons; -+++}; -+++ -++ /* function declarations */ -++ static void applyrules(Client *c); -++ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); -++@@ -169,8 +193,10 @@ static void focus(Client *c); -++ static void focusin(XEvent *e); -++ static void focusmon(const Arg *arg); -++ 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 unsigned int getsystraywidth(); -++ static int gettextprop(Window w, Atom atom, char *text, unsigned int size); -++ static void grabbuttons(Client *c, int focused); -++ static void grabkeys(void); -++@@ -188,13 +214,16 @@ static void pop(Client *); -++ static void propertynotify(XEvent *e); -++ static void quit(const Arg *arg); -++ static Monitor *recttomon(int x, int y, int w, int h); -+++static void removesystrayicon(Client *i); -++ static void resize(Client *c, int x, int y, int w, int h, int interact); -+++static void resizebarwin(Monitor *m); -++ static void resizeclient(Client *c, int x, int y, int w, int h); -++ static void resizemouse(const Arg *arg); -+++static void resizerequest(XEvent *e); -++ static void restack(Monitor *m); -++ static void run(void); -++ static void scan(void); -++-static int sendevent(Client *c, Atom proto); -+++static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4); -++ static void sendmon(Client *c, Monitor *m); -++ static void setclientstate(Client *c, long state); -++ static void setfocus(Client *c); -++@@ -206,6 +235,7 @@ static void seturgent(Client *c, int urg); -++ static void showhide(Client *c); -++ static void sigchld(int unused); -++ static void spawn(const Arg *arg); -+++static Monitor *systraytomon(Monitor *m); -++ static void tag(const Arg *arg); -++ static void tagmon(const Arg *arg); -++ static void tile(Monitor *); -++@@ -223,18 +253,23 @@ static int updategeom(void); -++ static void updatenumlockmask(void); -++ static void updatesizehints(Client *c); -++ static void updatestatus(void); -+++static void updatesystray(void); -+++static void updatesystrayicongeom(Client *i, int w, int h); -+++static void updatesystrayiconstate(Client *i, XPropertyEvent *ev); -++ static void updatetitle(Client *c); -++ static void updatewindowtype(Client *c); -++ static void updatewmhints(Client *c); -++ static void view(const Arg *arg); -++ static Client *wintoclient(Window w); -++ static Monitor *wintomon(Window w); -+++static Client *wintosystrayicon(Window w); -++ static int xerror(Display *dpy, XErrorEvent *ee); -++ static int xerrordummy(Display *dpy, XErrorEvent *ee); -++ static int xerrorstart(Display *dpy, XErrorEvent *ee); -++ static void zoom(const Arg *arg); -++ -++ /* variables */ -+++static Systray *systray = NULL; -++ static const char broken[] = "broken"; -++ static char stext[256]; -++ static int screen; -++@@ -257,9 +292,10 @@ static void (*handler[LASTEvent]) (XEvent *) = { -++ [MapRequest] = maprequest, -++ [MotionNotify] = motionnotify, -++ [PropertyNotify] = propertynotify, -+++ [ResizeRequest] = resizerequest, -++ [UnmapNotify] = unmapnotify -++ }; -++-static Atom wmatom[WMLast], netatom[NetLast]; -+++static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast]; -++ static int running = 1; -++ static Cur *cursor[CurLast]; -++ static Clr **scheme; -++@@ -439,7 +475,7 @@ 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 > selmon->ww - TEXTW(stext) - getsystraywidth()) -++ click = ClkStatusText; -++ else -++ click = ClkWinTitle; -++@@ -482,6 +518,11 @@ cleanup(void) -++ XUngrabKey(dpy, AnyKey, AnyModifier, root); -++ while (mons) -++ cleanupmon(mons); -+++ if (showsystray) { -+++ XUnmapWindow(dpy, systray->win); -+++ XDestroyWindow(dpy, systray->win); -+++ free(systray); -+++ } -++ for (i = 0; i < CurLast; i++) -++ drw_cur_free(drw, cursor[i]); -++ for (i = 0; i < LENGTH(colors); i++) -++@@ -512,9 +553,57 @@ cleanupmon(Monitor *mon) -++ void -++ clientmessage(XEvent *e) -++ { -+++ XWindowAttributes wa; -+++ XSetWindowAttributes swa; -++ XClientMessageEvent *cme = &e->xclient; -++ Client *c = wintoclient(cme->window); -++ -+++ if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) { -+++ /* add systray icons */ -+++ if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) { -+++ if (!(c = (Client *)calloc(1, sizeof(Client)))) -+++ die("fatal: could not malloc() %u bytes\n", sizeof(Client)); -+++ if (!(c->win = cme->data.l[2])) { -+++ free(c); -+++ return; -+++ } -+++ c->mon = selmon; -+++ c->next = systray->icons; -+++ systray->icons = c; -+++ if (!XGetWindowAttributes(dpy, c->win, &wa)) { -+++ /* use sane defaults */ -+++ wa.width = bh; -+++ wa.height = bh; -+++ wa.border_width = 0; -+++ } -+++ c->x = c->oldx = c->y = c->oldy = 0; -+++ c->w = c->oldw = wa.width; -+++ c->h = c->oldh = wa.height; -+++ c->oldbw = wa.border_width; -+++ c->bw = 0; -+++ c->isfloating = True; -+++ /* reuse tags field as mapped status */ -+++ c->tags = 1; -+++ updatesizehints(c); -+++ updatesystrayicongeom(c, wa.width, wa.height); -+++ XAddToSaveSet(dpy, c->win); -+++ XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask); -+++ XReparentWindow(dpy, c->win, systray->win, 0, 0); -+++ /* use parents background color */ -+++ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -+++ XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa); -+++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -+++ /* FIXME not sure if I have to send these events, too */ -+++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_FOCUS_IN, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -+++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -+++ sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_MODALITY_ON, 0 , systray->win, XEMBED_EMBEDDED_VERSION); -+++ XSync(dpy, False); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ setclientstate(c, NormalState); -+++ } -+++ return; -+++ } -++ if (!c) -++ return; -++ if (cme->message_type == netatom[NetWMState]) { -++@@ -567,7 +656,7 @@ configurenotify(XEvent *e) -++ for (c = m->clients; c; c = c->next) -++ if (c->isfullscreen) -++ resizeclient(c, m->mx, m->my, m->mw, m->mh); -++- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); -+++ resizebarwin(m); -++ } -++ focus(NULL); -++ arrange(NULL); -++@@ -652,6 +741,11 @@ destroynotify(XEvent *e) -++ -++ if ((c = wintoclient(ev->window))) -++ unmanage(c, 1); -+++ else if ((c = wintosystrayicon(ev->window))) { -+++ removesystrayicon(c); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ } -++ } -++ -++ void -++@@ -695,19 +789,23 @@ dirtomon(int dir) -++ void -++ drawbar(Monitor *m) -++ { -++- int x, w, sw = 0; -+++ int x, w, sw = 0, stw = 0; -++ int boxs = drw->fonts->h / 9; -++ int boxw = drw->fonts->h / 6 + 2; -++ unsigned int i, occ = 0, urg = 0; -++ Client *c; -++ -+++ if(showsystray && m == systraytomon(m)) -+++ stw = getsystraywidth(); -+++ -++ /* 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]); -++- sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ -++- drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); -+++ sw = TEXTW(stext) - lrpad / 2 + 2; /* 2px right padding */ -+++ drw_text(drw, m->ww - sw - stw, 0, sw, bh, lrpad / 2 - 2, stext, 0); -++ } -++ -+++ resizebarwin(m); -++ for (c = m->clients; c; c = c->next) { -++ occ |= c->tags; -++ if (c->isurgent) -++@@ -728,7 +826,7 @@ drawbar(Monitor *m) -++ drw_setscheme(drw, scheme[SchemeNorm]); -++ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); -++ -++- if ((w = m->ww - sw - x) > bh) { -+++ if ((w = m->ww - sw - stw - x) > bh) { -++ if (m->sel) { -++ drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); -++ drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); -++@@ -739,7 +837,7 @@ drawbar(Monitor *m) -++ drw_rect(drw, x, 0, w, bh, 1, 1); -++ } -++ } -++- drw_map(drw, m->barwin, 0, 0, m->ww, bh); -+++ drw_map(drw, m->barwin, 0, 0, m->ww - stw, bh); -++ } -++ -++ void -++@@ -776,8 +874,11 @@ expose(XEvent *e) -++ Monitor *m; -++ XExposeEvent *ev = &e->xexpose; -++ -++- if (ev->count == 0 && (m = wintomon(ev->window))) -+++ if (ev->count == 0 && (m = wintomon(ev->window))) { -++ drawbar(m); -+++ if (m == selmon) -+++ updatesystray(); -+++ } -++ } -++ -++ void -++@@ -862,10 +963,17 @@ getatomprop(Client *c, Atom prop) -++ unsigned long dl; -++ unsigned char *p = NULL; -++ Atom da, atom = None; -+++ /* FIXME getatomprop should return the number of items and a pointer to -+++ * the stored data instead of this workaround */ -+++ Atom req = XA_ATOM; -+++ if (prop == xatom[XembedInfo]) -+++ req = xatom[XembedInfo]; -++ -++- if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, -+++ if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, -++ &da, &di, &dl, &dl, &p) == Success && p) { -++ atom = *(Atom *)p; -+++ if (da == xatom[XembedInfo] && dl == 2) -+++ atom = ((Atom *)p)[1]; -++ XFree(p); -++ } -++ return atom; -++@@ -899,6 +1007,16 @@ getstate(Window w) -++ return result; -++ } -++ -+++unsigned int -+++getsystraywidth() -+++{ -+++ unsigned int w = 0; -+++ Client *i; -+++ if(showsystray) -+++ for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ; -+++ return w ? w + systrayspacing : 1; -+++} -+++ -++ int -++ gettextprop(Window w, Atom atom, char *text, unsigned int size) -++ { -++@@ -1003,7 +1121,7 @@ killclient(const Arg *arg) -++ { -++ if (!selmon->sel) -++ return; -++- if (!sendevent(selmon->sel, wmatom[WMDelete])) { -+++ if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0 , 0, 0)) { -++ XGrabServer(dpy); -++ XSetErrorHandler(xerrordummy); -++ XSetCloseDownMode(dpy, DestroyAll); -++@@ -1091,6 +1209,12 @@ maprequest(XEvent *e) -++ { -++ static XWindowAttributes wa; -++ XMapRequestEvent *ev = &e->xmaprequest; -+++ Client *i; -+++ if ((i = wintosystrayicon(ev->window))) { -+++ sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ } -++ -++ if (!XGetWindowAttributes(dpy, ev->window, &wa)) -++ return; -++@@ -1215,6 +1339,16 @@ propertynotify(XEvent *e) -++ Window trans; -++ XPropertyEvent *ev = &e->xproperty; -++ -+++ if ((c = wintosystrayicon(ev->window))) { -+++ if (ev->atom == XA_WM_NORMAL_HINTS) { -+++ updatesizehints(c); -+++ updatesystrayicongeom(c, c->w, c->h); -+++ } -+++ else -+++ updatesystrayiconstate(c, ev); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ } -++ if ((ev->window == root) && (ev->atom == XA_WM_NAME)) -++ updatestatus(); -++ else if (ev->state == PropertyDelete) -++@@ -1265,6 +1399,20 @@ recttomon(int x, int y, int w, int h) -++ return r; -++ } -++ -+++void -+++removesystrayicon(Client *i) -+++{ -+++ Client **ii; -+++ -+++ if (!showsystray || !i) -+++ return; -+++ for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); -+++ if (ii) -+++ *ii = i->next; -+++ free(i); -+++} -+++ -+++ -++ void -++ resize(Client *c, int x, int y, int w, int h, int interact) -++ { -++@@ -1272,6 +1420,14 @@ resize(Client *c, int x, int y, int w, int h, int interact) -++ resizeclient(c, x, y, w, h); -++ } -++ -+++void -+++resizebarwin(Monitor *m) { -+++ unsigned int w = m->ww; -+++ if (showsystray && m == systraytomon(m)) -+++ w -= getsystraywidth(); -+++ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); -+++} -+++ -++ void -++ resizeclient(Client *c, int x, int y, int w, int h) -++ { -++@@ -1344,6 +1500,19 @@ resizemouse(const Arg *arg) -++ } -++ } -++ -+++void -+++resizerequest(XEvent *e) -+++{ -+++ XResizeRequestEvent *ev = &e->xresizerequest; -+++ Client *i; -+++ -+++ if ((i = wintosystrayicon(ev->window))) { -+++ updatesystrayicongeom(i, ev->width, ev->height); -+++ resizebarwin(selmon); -+++ updatesystray(); -+++ } -+++} -+++ -++ void -++ restack(Monitor *m) -++ { -++@@ -1433,26 +1602,36 @@ setclientstate(Client *c, long state) -++ } -++ -++ int -++-sendevent(Client *c, Atom proto) -+++sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4) -++ { -++ int n; -++- Atom *protocols; -+++ Atom *protocols, mt; -++ int exists = 0; -++ XEvent ev; -++ -++- if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { -++- while (!exists && n--) -++- exists = protocols[n] == proto; -++- XFree(protocols); -+++ if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) { -+++ mt = wmatom[WMProtocols]; -+++ if (XGetWMProtocols(dpy, w, &protocols, &n)) { -+++ while (!exists && n--) -+++ exists = protocols[n] == proto; -+++ XFree(protocols); -+++ } -+++ } -+++ else { -+++ exists = True; -+++ mt = proto; -++ } -++ if (exists) { -++ ev.type = ClientMessage; -++- ev.xclient.window = c->win; -++- ev.xclient.message_type = wmatom[WMProtocols]; -+++ ev.xclient.window = w; -+++ ev.xclient.message_type = mt; -++ ev.xclient.format = 32; -++- ev.xclient.data.l[0] = proto; -++- ev.xclient.data.l[1] = CurrentTime; -++- XSendEvent(dpy, c->win, False, NoEventMask, &ev); -+++ ev.xclient.data.l[0] = d0; -+++ ev.xclient.data.l[1] = d1; -+++ ev.xclient.data.l[2] = d2; -+++ ev.xclient.data.l[3] = d3; -+++ ev.xclient.data.l[4] = d4; -+++ XSendEvent(dpy, w, False, mask, &ev); -++ } -++ return exists; -++ } -++@@ -1466,7 +1645,7 @@ setfocus(Client *c) -++ XA_WINDOW, 32, PropModeReplace, -++ (unsigned char *) &(c->win), 1); -++ } -++- sendevent(c, wmatom[WMTakeFocus]); -+++ sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0); -++ } -++ -++ void -++@@ -1555,6 +1734,10 @@ setup(void) -++ wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); -++ netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); -++ netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); -+++ netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False); -+++ netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False); -+++ netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False); -+++ netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False); -++ netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); -++ netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); -++ netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); -++@@ -1562,6 +1745,9 @@ setup(void) -++ netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); -++ netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); -++ netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); -+++ xatom[Manager] = XInternAtom(dpy, "MANAGER", False); -+++ xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False); -+++ xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False); -++ /* init cursors */ -++ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); -++ cursor[CurResize] = drw_cur_create(drw, XC_sizing); -++@@ -1570,6 +1756,8 @@ setup(void) -++ scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); -++ for (i = 0; i < LENGTH(colors); i++) -++ scheme[i] = drw_scm_create(drw, colors[i], 3); -+++ /* init system tray */ -+++ updatesystray(); -++ /* init bars */ -++ updatebars(); -++ updatestatus(); -++@@ -1701,7 +1889,18 @@ togglebar(const Arg *arg) -++ { -++ selmon->showbar = !selmon->showbar; -++ updatebarpos(selmon); -++- XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); -+++ resizebarwin(selmon); -+++ if (showsystray) { -+++ XWindowChanges wc; -+++ if (!selmon->showbar) -+++ wc.y = -bh; -+++ else if (selmon->showbar) { -+++ wc.y = 0; -+++ if (!selmon->topbar) -+++ wc.y = selmon->mh - bh; -+++ } -+++ XConfigureWindow(dpy, systray->win, CWY, &wc); -+++ } -++ arrange(selmon); -++ } -++ -++@@ -1796,11 +1995,18 @@ unmapnotify(XEvent *e) -++ else -++ unmanage(c, 0); -++ } -+++ else if ((c = wintosystrayicon(ev->window))) { -+++ /* KLUDGE! sometimes icons occasionally unmap their windows, but do -+++ * _not_ destroy them. We map those windows back */ -+++ XMapRaised(dpy, c->win); -+++ updatesystray(); -+++ } -++ } -++ -++ void -++ updatebars(void) -++ { -+++ unsigned int w; -++ Monitor *m; -++ XSetWindowAttributes wa = { -++ .override_redirect = True, -++@@ -1811,10 +2017,15 @@ updatebars(void) -++ for (m = mons; m; m = m->next) { -++ if (m->barwin) -++ continue; -++- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), -+++ w = m->ww; -+++ if (showsystray && m == systraytomon(m)) -+++ w -= getsystraywidth(); -+++ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen), -++ CopyFromParent, DefaultVisual(dpy, screen), -++ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); -++ XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); -+++ if (showsystray && m == systraytomon(m)) -+++ XMapRaised(dpy, systray->win); -++ XMapRaised(dpy, m->barwin); -++ XSetClassHint(dpy, m->barwin, &ch); -++ } -++@@ -1990,6 +2201,121 @@ updatestatus(void) -++ if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) -++ strcpy(stext, "dwm-"VERSION); -++ drawbar(selmon); -+++ updatesystray(); -+++} -+++ -+++void -+++updatesystrayicongeom(Client *i, int w, int h) -+++{ -+++ if (i) { -+++ i->h = bh; -+++ if (w == h) -+++ i->w = bh; -+++ else if (h == bh) -+++ i->w = w; -+++ else -+++ i->w = (int) ((float)bh * ((float)w / (float)h)); -+++ applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False); -+++ /* force icons into the systray dimensions if they don't want to */ -+++ if (i->h > bh) { -+++ if (i->w == i->h) -+++ i->w = bh; -+++ else -+++ i->w = (int) ((float)bh * ((float)i->w / (float)i->h)); -+++ i->h = bh; -+++ } -+++ } -+++} -+++ -+++void -+++updatesystrayiconstate(Client *i, XPropertyEvent *ev) -+++{ -+++ long flags; -+++ int code = 0; -+++ -+++ if (!showsystray || !i || ev->atom != xatom[XembedInfo] || -+++ !(flags = getatomprop(i, xatom[XembedInfo]))) -+++ return; -+++ -+++ if (flags & XEMBED_MAPPED && !i->tags) { -+++ i->tags = 1; -+++ code = XEMBED_WINDOW_ACTIVATE; -+++ XMapRaised(dpy, i->win); -+++ setclientstate(i, NormalState); -+++ } -+++ else if (!(flags & XEMBED_MAPPED) && i->tags) { -+++ i->tags = 0; -+++ code = XEMBED_WINDOW_DEACTIVATE; -+++ XUnmapWindow(dpy, i->win); -+++ setclientstate(i, WithdrawnState); -+++ } -+++ else -+++ return; -+++ sendevent(i->win, xatom[Xembed], StructureNotifyMask, CurrentTime, code, 0, -+++ systray->win, XEMBED_EMBEDDED_VERSION); -+++} -+++ -+++void -+++updatesystray(void) -+++{ -+++ XSetWindowAttributes wa; -+++ XWindowChanges wc; -+++ Client *i; -+++ Monitor *m = systraytomon(NULL); -+++ unsigned int x = m->mx + m->mw; -+++ unsigned int w = 1; -+++ -+++ if (!showsystray) -+++ return; -+++ if (!systray) { -+++ /* init systray */ -+++ if (!(systray = (Systray *)calloc(1, sizeof(Systray)))) -+++ die("fatal: could not malloc() %u bytes\n", sizeof(Systray)); -+++ systray->win = XCreateSimpleWindow(dpy, root, x, m->by, w, bh, 0, 0, scheme[SchemeSel][ColBg].pixel); -+++ wa.event_mask = ButtonPressMask | ExposureMask; -+++ wa.override_redirect = True; -+++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -+++ XSelectInput(dpy, systray->win, SubstructureNotifyMask); -+++ XChangeProperty(dpy, systray->win, netatom[NetSystemTrayOrientation], XA_CARDINAL, 32, -+++ PropModeReplace, (unsigned char *)&netatom[NetSystemTrayOrientationHorz], 1); -+++ XChangeWindowAttributes(dpy, systray->win, CWEventMask|CWOverrideRedirect|CWBackPixel, &wa); -+++ XMapRaised(dpy, systray->win); -+++ XSetSelectionOwner(dpy, netatom[NetSystemTray], systray->win, CurrentTime); -+++ if (XGetSelectionOwner(dpy, netatom[NetSystemTray]) == systray->win) { -+++ sendevent(root, xatom[Manager], StructureNotifyMask, CurrentTime, netatom[NetSystemTray], systray->win, 0, 0); -+++ XSync(dpy, False); -+++ } -+++ else { -+++ fprintf(stderr, "dwm: unable to obtain system tray.\n"); -+++ free(systray); -+++ systray = NULL; -+++ return; -+++ } -+++ } -+++ for (w = 0, i = systray->icons; i; i = i->next) { -+++ /* make sure the background color stays the same */ -+++ wa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -+++ XChangeWindowAttributes(dpy, i->win, CWBackPixel, &wa); -+++ XMapRaised(dpy, i->win); -+++ w += systrayspacing; -+++ i->x = w; -+++ XMoveResizeWindow(dpy, i->win, i->x, 0, i->w, i->h); -+++ w += i->w; -+++ if (i->mon != m) -+++ i->mon = m; -+++ } -+++ w = w ? w + systrayspacing : 1; -+++ x -= w; -+++ XMoveResizeWindow(dpy, systray->win, x, m->by, w, bh); -+++ wc.x = x; wc.y = m->by; wc.width = w; wc.height = bh; -+++ wc.stack_mode = Above; wc.sibling = m->barwin; -+++ XConfigureWindow(dpy, systray->win, CWX|CWY|CWWidth|CWHeight|CWSibling|CWStackMode, &wc); -+++ XMapWindow(dpy, systray->win); -+++ XMapSubwindows(dpy, systray->win); -+++ /* redraw background */ -+++ XSetForeground(dpy, drw->gc, scheme[SchemeNorm][ColBg].pixel); -+++ XFillRectangle(dpy, systray->win, drw->gc, 0, 0, w, bh); -+++ XSync(dpy, False); -++ } -++ -++ void -++@@ -2057,6 +2383,16 @@ wintoclient(Window w) -++ return NULL; -++ } -++ -+++Client * -+++wintosystrayicon(Window w) { -+++ Client *i = NULL; -+++ -+++ if (!showsystray || !w) -+++ return i; -+++ for (i = systray->icons; i && i->win != w; i = i->next) ; -+++ return i; -+++} -+++ -++ Monitor * -++ wintomon(Window w) -++ { -++@@ -2110,6 +2446,22 @@ xerrorstart(Display *dpy, XErrorEvent *ee) -++ return -1; -++ } -++ -+++Monitor * -+++systraytomon(Monitor *m) { -+++ Monitor *t; -+++ int i, n; -+++ if(!systraypinning) { -+++ if(!m) -+++ return selmon; -+++ return m == selmon ? m : NULL; -+++ } -+++ for(n = 1, t = mons; t && t->next; n++, t = t->next) ; -+++ for(i = 1, t = mons; t && t->next && i < systraypinning; i++, t = t->next) ; -+++ if(systraypinningfailfirst && n < systraypinning) -+++ return mons; -+++ return t; -+++} -+++ -++ void -++ zoom(const Arg *arg) -++ { -++-- -++2.17.1 -++ -+diff --git a/patches/dwm-uselessgap-6.2.diff b/patches/dwm-uselessgap-6.2.diff -+new file mode 100644 -+index 0000000..d9cacbe -+--- /dev/null -++++ b/patches/dwm-uselessgap-6.2.diff -+@@ -0,0 +1,81 @@ -++From 58a5ece9406ca6c90dc362617c065e4aac19417f Mon Sep 17 00:00:00 2001 -++From: Cyril Cressent <cyril@cressent.org> -++Date: Wed, 3 Jul 2019 21:33:45 -0700 -++Subject: [PATCH] Port the uselessgap patch to 6.2 -++ -++--- -++ config.def.h | 1 + -++ dwm.c | 36 ++++++++++++++++++++++++++++++------ -++ 2 files changed, 31 insertions(+), 6 deletions(-) -++ -++diff --git a/config.def.h b/config.def.h -++index 1c0b587..b11471d 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 = 6; /* 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 */ -++diff --git a/dwm.c b/dwm.c -++index 4465af1..4545e05 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -52,8 +52,8 @@ -++ #define ISVISIBLE(C) ((C->tags & 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) -++-#define HEIGHT(X) ((X)->h + 2 * (X)->bw) -+++#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx) -+++#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx) -++ #define TAGMASK ((1 << LENGTH(tags)) - 1) -++ #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) -++ -++@@ -1276,12 +1276,36 @@ void -++ resizeclient(Client *c, int x, int y, int w, int h) -++ { -++ XWindowChanges wc; -+++ unsigned int n; -+++ unsigned int gapoffset; -+++ unsigned int gapincr; -+++ Client *nbc; -++ -++- c->oldx = c->x; c->x = wc.x = x; -++- 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; -++ wc.border_width = c->bw; -+++ -+++ /* Get number of clients for the selected monitor */ -+++ for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++); -+++ -+++ /* Do nothing if layout is floating */ -+++ if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) { -+++ gapincr = gapoffset = 0; -+++ } else { -+++ /* Remove border and gap if layout is monocle or only one client */ -+++ if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) { -+++ gapoffset = 0; -+++ gapincr = -2 * borderpx; -+++ wc.border_width = 0; -+++ } else { -+++ gapoffset = gappx; -+++ gapincr = 2 * gappx; -+++ } -+++ } -+++ -+++ c->oldx = c->x; c->x = wc.x = x + gapoffset; -+++ c->oldy = c->y; c->y = wc.y = y + gapoffset; -+++ c->oldw = c->w; c->w = wc.width = w - gapincr; -+++ c->oldh = c->h; c->h = wc.height = h - gapincr; -+++ -++ XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); -++ configure(c); -++ XSync(dpy, False); -++-- -++2.22.0 -++ -+diff --git a/patches/dwm-zoomswap-6.2.diff b/patches/dwm-zoomswap-6.2.diff -+new file mode 100644 -+index 0000000..3c658e6 -+--- /dev/null -++++ b/patches/dwm-zoomswap-6.2.diff -+@@ -0,0 +1,95 @@ -++From 3867ef5a68e15a4faff377ddbc8371853de4a800 Mon Sep 17 00:00:00 2001 -++From: aleks <aleks.stier@icloud.com> -++Date: Sat, 19 Oct 2019 00:56:21 +0200 -++Subject: [PATCH] Put master to exact position of zoomed client -++ -++The default behaviour when zooming a client is to put the previous -++master on top of the client-stack. This patch puts the master to the -++exact position of the zoomed client in the stack. -++--- -++ dwm.c | 44 ++++++++++++++++++++++++++++++++++++++++---- -++ 1 file changed, 40 insertions(+), 4 deletions(-) -++ -++diff --git a/dwm.c b/dwm.c -++index 4465af1..1719b36 100644 -++--- a/dwm.c -+++++ b/dwm.c -++@@ -165,6 +165,7 @@ static void drawbar(Monitor *m); -++ static void drawbars(void); -++ static void enternotify(XEvent *e); -++ static void expose(XEvent *e); -+++static Client *findbefore(Client *c); -++ static void focus(Client *c); -++ static void focusin(XEvent *e); -++ static void focusmon(const Arg *arg); -++@@ -235,6 +236,7 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee); -++ static void zoom(const Arg *arg); -++ -++ /* variables */ -+++static Client *prevzoom = NULL; -++ static const char broken[] = "broken"; -++ static char stext[256]; -++ static int screen; -++@@ -780,6 +782,16 @@ expose(XEvent *e) -++ drawbar(m); -++ } -++ -+++Client * -+++findbefore(Client *c) -+++{ -+++ Client *tmp; -+++ if (c == selmon->clients) -+++ return NULL; -+++ for (tmp = selmon->clients; tmp && tmp->next != c; tmp = tmp->next); -+++ return tmp; -+++} -+++ -++ void -++ focus(Client *c) -++ { -++@@ -2114,14 +2126,38 @@ void -++ zoom(const Arg *arg) -++ { -++ Client *c = selmon->sel; -+++ Client *at = NULL, *cold, *cprevious = NULL; -++ -++ if (!selmon->lt[selmon->sellt]->arrange -++ || (selmon->sel && selmon->sel->isfloating)) -++ return; -++- if (c == nexttiled(selmon->clients)) -++- if (!c || !(c = nexttiled(c->next))) -++- return; -++- pop(c); -+++ if (c == nexttiled(selmon->clients)) { -+++ at = findbefore(prevzoom); -+++ if (at) -+++ cprevious = nexttiled(at->next); -+++ if (!cprevious || cprevious != prevzoom) { -+++ prevzoom = NULL; -+++ if (!c || !(c = nexttiled(c->next))) -+++ return; -+++ } else -+++ c = cprevious; -+++ } -+++ cold = nexttiled(selmon->clients); -+++ if (c != cold && !at) -+++ at = findbefore(c); -+++ detach(c); -+++ attach(c); -+++ /* swap windows instead of pushing the previous one down */ -+++ if (c != cold && at) { -+++ prevzoom = cold; -+++ if (cold && at != cold) { -+++ detach(cold); -+++ cold->next = at->next; -+++ at->next = cold; -+++ } -+++ } -+++ focus(c); -+++ arrange(c->mon); -++ } -++ -++ int -++-- -++2.23.0 -++ -+diff --git a/volsv b/volsv -+new file mode 100755 -+index 0000000..f79662b -+--- /dev/null -++++ b/volsv -+@@ -0,0 +1,52 @@ -++#!/bin/sh -++# calculate average of two integers (for ALSA) -++average () { -++ echo "$(( $(( $1 + $2 )) / 2 ))$" -++} -++# print error message -++printerror () { -++ echo "$1 is not a recognized command or flag" -++} -++# if pulseaudio -++pulsesv () { -++ case "$1" in -++ "up" | "-i") pamixer -i 5 ;; -++ "down" | "-d") pamixer -d 5 ;; -++ "toggle" | "-t") pamixer -t ;; -++ "mic" | "-m") pamixer --source 1 -t ;; -++ "getv" | "-v") printf "%s%%\n" "$(pamixer --get-volume)" ;; -++ "getm" | "-g") pamixer --get-mute | sed 's/[Ff]alse/\[on\]/;s/[Tt]rue/\[off\]/' ;; -++ *) printerror "$1" ;; -++ esac -++} -++# if alsa -++alsasv () { -++ case "$1" in -++ "up" | "-i") amixer sset Master 5%+ ;; -++ "down" | "-d") amixer sset Master 5%- ;; -++ "toggle" | "-t") amixer sset Master toggle ;; -++ "mic" | "-m") amixer sset Capture toggle ;; -++ "getv" | "-v") amixer sget Master | grep '\[[0-9]*\%\]' | cut -d' ' -f6 | sed 's/\[//;s/\]//g' ;; -++ "getm" | "-g") amixer sget Master | grep '\[o[fn]' | cut -d' ' -f8 | head -1 ;; -++ *) printerror "$1" ;; -++ esac -++} -++#Search input for -++echo "$@" | grep -q ' *-h *' && echo \ -++"Volsv is Free software. You can use it for any purpose, but I make no guerantee about its usability or fitness "\ -++"for any particular purpose. You are also free to redistribute, modify, and distribute your modifications to "\ -++"volsv. Volsv is distributed under the BSD 3-Clause license to ensure full license compatibility with GNU, "\ -++"Linux, and BSD operating systems. A copy of this license is included in the repository.\n\n"\ -++"Volsv is a script designed to control the volume of a *NIX machine. The commands/flags are as follows: -++increase volume: 'up' or '-i' -++decrease volume: 'down' or '-d' -++toggle volume mute: 'toggle' or '-t' -++toggle mic mute: 'mic' or '-m' -++get volume level: 'getv' or '-v' -++get mute state: 'getm' or '-g'" && exit -++ -++for i in $@; do -++ pgrep -x pulseaudio >/dev/null && pulsesv $1 || alsasv $1 -++ pgrep -x dwmblocks >/dev/null && pkill -RTMIN+10 dwmblocks -++ pgrep -x dwmbar >/dev/null && dwmbar-signal volume -++done -diff --git a/volsv b/volsv -new file mode 100755 -index 0000000..f79662b ---- /dev/null -+++ b/volsv -@@ -0,0 +1,52 @@ -+#!/bin/sh -+# calculate average of two integers (for ALSA) -+average () { -+ echo "$(( $(( $1 + $2 )) / 2 ))$" -+} -+# print error message -+printerror () { -+ echo "$1 is not a recognized command or flag" -+} -+# if pulseaudio -+pulsesv () { -+ case "$1" in -+ "up" | "-i") pamixer -i 5 ;; -+ "down" | "-d") pamixer -d 5 ;; -+ "toggle" | "-t") pamixer -t ;; -+ "mic" | "-m") pamixer --source 1 -t ;; -+ "getv" | "-v") printf "%s%%\n" "$(pamixer --get-volume)" ;; -+ "getm" | "-g") pamixer --get-mute | sed 's/[Ff]alse/\[on\]/;s/[Tt]rue/\[off\]/' ;; -+ *) printerror "$1" ;; -+ esac -+} -+# if alsa -+alsasv () { -+ case "$1" in -+ "up" | "-i") amixer sset Master 5%+ ;; -+ "down" | "-d") amixer sset Master 5%- ;; -+ "toggle" | "-t") amixer sset Master toggle ;; -+ "mic" | "-m") amixer sset Capture toggle ;; -+ "getv" | "-v") amixer sget Master | grep '\[[0-9]*\%\]' | cut -d' ' -f6 | sed 's/\[//;s/\]//g' ;; -+ "getm" | "-g") amixer sget Master | grep '\[o[fn]' | cut -d' ' -f8 | head -1 ;; -+ *) printerror "$1" ;; -+ esac -+} -+#Search input for -+echo "$@" | grep -q ' *-h *' && echo \ -+"Volsv is Free software. You can use it for any purpose, but I make no guerantee about its usability or fitness "\ -+"for any particular purpose. You are also free to redistribute, modify, and distribute your modifications to "\ -+"volsv. Volsv is distributed under the BSD 3-Clause license to ensure full license compatibility with GNU, "\ -+"Linux, and BSD operating systems. A copy of this license is included in the repository.\n\n"\ -+"Volsv is a script designed to control the volume of a *NIX machine. The commands/flags are as follows: -+increase volume: 'up' or '-i' -+decrease volume: 'down' or '-d' -+toggle volume mute: 'toggle' or '-t' -+toggle mic mute: 'mic' or '-m' -+get volume level: 'getv' or '-v' -+get mute state: 'getm' or '-g'" && exit -+ -+for i in $@; do -+ pgrep -x pulseaudio >/dev/null && pulsesv $1 || alsasv $1 -+ pgrep -x dwmblocks >/dev/null && pkill -RTMIN+10 dwmblocks -+ pgrep -x dwmbar >/dev/null && dwmbar-signal volume -+done |