diff options
author | zachir <zachir@librem.one> | 2021-09-27 13:43:31 -0500 |
---|---|---|
committer | zachir <zachir@librem.one> | 2021-09-27 13:43:31 -0500 |
commit | 60fc9232553a31061c28cf932efb5b4e0c10d80c (patch) | |
tree | 688b39ff65bc8c15c393790a3e17e0d25bcc46f0 /dwm-zir-6.2.diff | |
parent | c9d6d1b0a431e600c53aaf65857e1c295c17cea8 (diff) |
Re-make patch.diff
Diffstat (limited to 'dwm-zir-6.2.diff')
-rw-r--r-- | dwm-zir-6.2.diff | 2405 |
1 files changed, 0 insertions, 2405 deletions
diff --git a/dwm-zir-6.2.diff b/dwm-zir-6.2.diff deleted file mode 100644 index 779d950..0000000 --- a/dwm-zir-6.2.diff +++ /dev/null @@ -1,2405 +0,0 @@ -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..a66fbe2 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" }; -@@ -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,21 +45,29 @@ 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 */ -+ { 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) */ - 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 */ - -+#include "tcl.c" - static const Layout layouts[] = { - /* symbol arrange function */ - { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ - { "[M]", monocle }, -+ { "|||", tcl }, - }; - - /* key definitions */ -@@ -59,6 +86,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,20 +98,28 @@ 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} }, - { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, - { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, - { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, -+ { MODKEY|ShiftMask, XK_t, setlayout, {.v = &layouts[3]} }, - { 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 } }, - { 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 +130,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,13 +140,85 @@ 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} }, -+ { 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} }, - }; - -+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..e37feca ---- /dev/null -+++ b/config.h -@@ -0,0 +1,301 @@ -+/* 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 Mono:size=10", "JoyPixels:size=9" }; -+static const char dmenufont[] = "mononoki Nerd Font Mono:size=10"; -+static const char col_gray1[] = "#222222"; -+static const char col_gray2[] = "#444444"; -+static const char col_gray3[] = "#bbbbbb"; -+static const char col_gray4[] = "#eeeeee"; -+static const char col_cyan[] = "#750000"; -+static const char *colors[][3] = { -+ /* fg bg border */ -+ [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, -+ [SchemeSel] = { col_gray4, col_cyan, col_cyan }, -+}; -+ -+typedef struct { -+ const char *name; -+ const void *cmd; -+} Sp; -+const char *spcmd1[] = { "st", "-g", "150x50", "-c", "sphtop", "-e", "htop", NULL }; -+const char *spcmd2[] = { "st", "-g", "150x50", "-c", "spterm", NULL }; -+const char *spcmd3[] = { "st", "-g", "150x50", "-c", "sppm", "-e", "pulsemixer", NULL }; -+const char *spcmd4[] = { "st", "-g", "150x50", "-c", "spncmp", "-e", "ncmpcpp", NULL }; -+const char *spcmd5[] = { "st", "-g", "150x50", "-c", "spmutt", "-e", "neomutt", NULL }; -+const char *spcmd6[] = { "st", "-g", "150x50", "-c", "spping", "-e", "ping", "1.1.1.1", NULL }; -+static Sp scratchpads[] = { -+ { "sphtop", spcmd1 }, -+ { "spterm", spcmd2 }, -+ { "sppm", spcmd3 }, -+ { "spncmp", spcmd4 }, -+ { "spmutt", spcmd5 }, -+ { "spping", spcmd6 }, -+}; -+ -+/* 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 }, -+ { "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, "carla",NULL, 1 << 7, 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 }, -+ { "sphtop", NULL, NULL, SPTAG(0), 1, 1, 1, -1 }, -+ { "spterm", NULL, NULL, SPTAG(1), 1, 1, 1, -1 }, -+ { "sppm", NULL, NULL, SPTAG(2), 1, 1, 1, -1 }, -+ { "spncmp", NULL, NULL, SPTAG(3), 1, 1, 1, -1 }, -+ { "spmutt", NULL, NULL, SPTAG(4), 1, 1, 1, -1 }, -+ { "spping", NULL, NULL, SPTAG(5), 1, 1, 1, -1 }, -+ { NULL, "monero-wallet-gui",NULL, 256, 1, 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 */ -+ -+#include "tcl.c" -+static const Layout layouts[] = { -+ /* symbol arrange function */ -+ { "[]=", tile }, /* first entry is default */ -+ { "><>", NULL }, /* no layout function means floating behavior */ -+ { "[M]", monocle }, -+ { "|||", tcl }, -+}; -+ -+/* key definitions */ -+#define MODKEY Mod3Mask -+#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 *rmenucmd[] = { "/usr/sbin/j4-dmenu-desktop", 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[] = { "urxvtc", NULL }; -+/* static const char *termcmd[] = { "alacritty", NULL }; */ -+static const char *sxhkdsig[] = { "pkill", "-USR1", "sxhkd", 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_r, spawn, {.v = rmenucmd } }, */ -+ /* { MODKEY, XK_p, spawn, {.v = passmenu } }, */ -+ /* { MODKEY, XK_c, spawn, {.v = xidletog } }, */ -+ /* { MODKEY, XK_x, spawn, {.v = xkillcmd } }, */ -+ { MODKEY, XK_Return, spawn, {.v = termcmd } }, -+ { MODKEY|ControlMask, XK_z, togglescratch, {.ui = 0 } }, -+ { MODKEY|ControlMask, XK_x, togglescratch, {.ui = 1 } }, -+ { MODKEY|ControlMask, XK_c, togglescratch, {.ui = 2 } }, -+ { MODKEY|ControlMask, XK_b, togglescratch, {.ui = 3 } }, -+ { MODKEY|ControlMask, XK_a, togglescratch, {.ui = 4 } }, -+ { MODKEY|ControlMask, XK_s, togglescratch, {.ui = 5 } }, -+ { MODKEY, XK_Escape, spawn, {.v = sxhkdsig } }, -+ // { 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, XK_e, setlayout, {.v = &layouts[3]} }, -+ /* { 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 */ -+ { "togglescratch", togglescratch }, -+ { "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..5e93cfd 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=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -diff --git a/dwm.1 b/dwm.1 -index 13b3729..bf742fd 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 -@@ -142,6 +145,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 +161,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 4465af1..603497c 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,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 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 -+ -+/* 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 +110,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 +132,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 +169,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 +198,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 +208,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 Atom getatomprop(Client *c, Atom prop); -+static int getdwmblockspid(); - 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,32 +232,46 @@ 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 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 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 +284,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 int scanner; -+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 */ -@@ -257,9 +334,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 +347,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 +366,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,8 +379,15 @@ 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; -+ if ((r->tags & SPTAGMASK) && r->isfloating) { -+ c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2); -+ c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2); -+ } -+ - for (m = mons; m && m->num != r->monitor; m = m->next); - if (m) - c->mon = m; -@@ -308,7 +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; - } -+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 +522,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 +603,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 - 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 +663,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 +698,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 +801,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 +861,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 +899,13 @@ destroynotify(XEvent *e) - - if ((c = wintoclient(ev->window))) - unmanage(c, 1); -+ else if ((c = swallowingclient(ev->window))) -+ unmanage(c->swallowing, 1); -+ else if ((c = wintosystrayicon(ev->window))) { -+ removesystrayicon(c); -+ resizebarwin(selmon); -+ updatesystray(); -+ } - } - - void -@@ -695,19 +949,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) -@@ -715,20 +974,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); -@@ -739,7 +1003,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 +1040,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 +1139,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 +1195,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 +1304,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 +1366,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 +1388,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 +1414,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 +1428,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 +1448,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; -@@ -1208,6 +1571,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) - { -@@ -1215,8 +1588,21 @@ 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 +1631,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 +1683,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 +1704,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 +1808,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 +1857,18 @@ run(void) - handler[ev.type](&ev); /* call handler */ - } - -+void -+runAutostart(void) { -+ system("~/.config/dwm/autostart_blocking.sh"); -+ system("~/.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 +1879,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 +1892,7 @@ scan(void) - if (wins) - XFree(wins); - } -+ scanner = 0; - } - - void -@@ -1417,7 +1905,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 +1924,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 +1967,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 +2012,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) -@@ -1536,6 +2054,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 +2076,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 +2087,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 +2098,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(); -@@ -1616,6 +2146,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 +2170,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 +2239,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 +2257,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; - } - } - -@@ -1701,7 +2274,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 +2303,39 @@ togglefloating(const Arg *arg) - arrange(selmon); - } - -+void -+togglescratch(const Arg *arg) -+{ -+ Client *c; -+ unsigned int found = 0; -+ unsigned int scratchtag = SPTAG(arg->ui); -+ Arg sparg = {.v = scratchpads[arg->ui].cmd}; -+ -+ for (c = selmon->clients; c && !(found = c->tags & scratchtag); c = c->next); -+ if (found) { -+ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ scratchtag; -+ if (newtagset) { -+ selmon->tagset[selmon->seltags] = newtagset; -+ focus(NULL); -+ arrange(selmon); -+ } -+ if (ISVISIBLE(c)) { -+ focus(c); -+ restack(selmon); -+ } -+ } else { -+ selmon->tagset[selmon->seltags] |= scratchtag; -+ spawn(&sparg); -+ } -+} -+ -+void -+togglefullscr(const Arg *arg) -+{ -+ if(selmon->sel) -+ setfullscreen(selmon->sel, !selmon->sel->isfullscreen); -+} -+ - void - toggletag(const Arg *arg) - { -@@ -1765,6 +2382,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 +2410,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 +2430,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 +2452,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 +2543,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 +2636,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 +2810,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 +2927,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 +2990,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 +3055,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 +3064,9 @@ main(int argc, char *argv[]) - die("pledge"); - #endif /* __OpenBSD__ */ - scan(); -+ 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/tcl.c b/tcl.c -new file mode 100644 -index 0000000..4c94914 ---- /dev/null -+++ b/tcl.c -@@ -0,0 +1,74 @@ -+void -+tcl(Monitor * m) -+{ -+ int x, y, h, w, mw, sw, bdw; -+ unsigned int i, n; -+ Client * c; -+ -+ for (n = 0, c = nexttiled(m->clients); c; -+ c = nexttiled(c->next), n++); -+ -+ if (n == 0) -+ return; -+ -+ c = nexttiled(m->clients); -+ -+ mw = m->mfact * m->ww; -+ sw = (m->ww - mw) / 2; -+ bdw = (2 * c->bw); -+ resize(c, -+ n < 3 ? m->wx : m->wx + sw, -+ m->wy, -+ n == 1 ? m->ww - bdw : mw - bdw, -+ m->wh - bdw, -+ False); -+ -+ if (--n == 0) -+ return; -+ -+ w = (m->ww - mw) / ((n > 1) + 1); -+ c = nexttiled(c->next); -+ -+ if (n > 1) -+ { -+ x = m->wx + ((n > 1) ? mw + sw : mw); -+ y = m->wy; -+ h = m->wh / (n / 2); -+ -+ if (h < bh) -+ h = m->wh; -+ -+ for (i = 0; c && i < n / 2; c = nexttiled(c->next), i++) -+ { -+ resize(c, -+ x, -+ y, -+ w - bdw, -+ (i + 1 == n / 2) ? m->wy + m->wh - y - bdw : h - bdw, -+ False); -+ -+ if (h != m->wh) -+ y = c->y + HEIGHT(c); -+ } -+ } -+ -+ x = (n + 1 / 2) == 1 ? mw : m->wx; -+ y = m->wy; -+ h = m->wh / ((n + 1) / 2); -+ -+ if (h < bh) -+ h = m->wh; -+ -+ for (i = 0; c; c = nexttiled(c->next), i++) -+ { -+ resize(c, -+ x, -+ y, -+ (i + 1 == (n + 1) / 2) ? w - bdw : w - bdw, -+ (i + 1 == (n + 1) / 2) ? m->wy + m->wh - y - bdw : h - bdw, -+ False); -+ -+ if (h != m->wh) -+ y = c->y + HEIGHT(c); -+ } -+} |