From 242e653ecff57ac874caa4aeabb616005a69b578 Mon Sep 17 00:00:00 2001 From: lucy Date: Thu, 26 Feb 2026 11:53:01 +0100 Subject: [PATCH] add patched defaults --- config.def.h | 50 +++- config.h | 147 +++++++++ drw.o | Bin 0 -> 11848 bytes dwm | Bin 0 -> 89616 bytes dwm.1 | 23 ++ dwm.c | 601 +++++++++++++++++++++++++++++++++---- dwm.o | Bin 0 -> 85392 bytes util.o | Bin 0 -> 2488 bytes vanitygaps.c | 822 +++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 1578 insertions(+), 65 deletions(-) create mode 100644 config.h create mode 100644 drw.o create mode 100755 dwm create mode 100644 dwm.o create mode 100644 util.o create mode 100644 vanitygaps.c diff --git a/config.def.h b/config.def.h index 81c3fc0..9afbe99 100644 --- a/config.def.h +++ b/config.def.h @@ -3,6 +3,16 @@ /* 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 systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */ +static const unsigned int systrayspacing = 2; /* systray spacing */ +static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ +static const int showsystray = 1; /* 0 means no systray */ +static const unsigned int gappih = 20; /* horiz inner gap between windows */ +static const unsigned int gappiv = 10; /* vert inner gap between windows */ +static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ +static const unsigned int gappov = 30; /* vert outer gap between windows and screen edge */ +static int smartgaps = 0; /* 1 means no outer gap when there is only one window */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ static const char *fonts[] = { "monospace:size=10" }; @@ -38,11 +48,26 @@ static const int resizehints = 1; /* 1 means respect size hints in tiled resi static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ static const int refreshrate = 120; /* refresh rate (per second) for client move/resize */ +#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */ +#include "vanitygaps.c" + static const Layout layouts[] = { /* symbol arrange function */ { "[]=", tile }, /* first entry is default */ - { "><>", NULL }, /* no layout function means floating behavior */ { "[M]", monocle }, + { "[@]", spiral }, + { "[\\]", dwindle }, + { "H[]", deck }, + { "TTT", bstack }, + { "===", bstackhoriz }, + { "HHH", grid }, + { "###", nrowgrid }, + { "---", horizgrid }, + { ":::", gaplessgrid }, + { "|M|", centeredmaster }, + { ">M>", centeredfloatingmaster }, + { "><>", NULL }, /* no layout function means floating behavior */ + { NULL, NULL }, }; /* key definitions */ @@ -72,7 +97,26 @@ static const 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|Mod4Mask, XK_u, incrgaps, {.i = +1 } }, + { MODKEY|Mod4Mask|ShiftMask, XK_u, incrgaps, {.i = -1 } }, + { MODKEY|Mod4Mask, XK_i, incrigaps, {.i = +1 } }, + { MODKEY|Mod4Mask|ShiftMask, XK_i, incrigaps, {.i = -1 } }, + { MODKEY|Mod4Mask, XK_o, incrogaps, {.i = +1 } }, + { MODKEY|Mod4Mask|ShiftMask, XK_o, incrogaps, {.i = -1 } }, + { MODKEY|Mod4Mask, XK_6, incrihgaps, {.i = +1 } }, + { MODKEY|Mod4Mask|ShiftMask, XK_6, incrihgaps, {.i = -1 } }, + { MODKEY|Mod4Mask, XK_7, incrivgaps, {.i = +1 } }, + { MODKEY|Mod4Mask|ShiftMask, XK_7, incrivgaps, {.i = -1 } }, + { MODKEY|Mod4Mask, XK_8, incrohgaps, {.i = +1 } }, + { MODKEY|Mod4Mask|ShiftMask, XK_8, incrohgaps, {.i = -1 } }, + { MODKEY|Mod4Mask, XK_9, incrovgaps, {.i = +1 } }, + { MODKEY|Mod4Mask|ShiftMask, XK_9, incrovgaps, {.i = -1 } }, + { MODKEY|Mod4Mask, XK_0, togglegaps, {0} }, + { MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} }, { MODKEY, XK_Tab, view, {0} }, { MODKEY|ShiftMask, XK_c, killclient, {0} }, { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, @@ -102,8 +146,8 @@ static const Key keys[] = { /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ static const Button buttons[] = { /* click event mask button function argument */ - { ClkLtSymbol, 0, Button1, setlayout, {0} }, - { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, { ClkWinTitle, 0, Button2, zoom, {0} }, { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, { ClkClientWin, MODKEY, Button1, movemouse, {0} }, diff --git a/config.h b/config.h new file mode 100644 index 0000000..0167977 --- /dev/null +++ b/config.h @@ -0,0 +1,147 @@ +/* See LICENSE file for copyright and license details. */ +#include + +/* appearance */ +static const unsigned int borderpx = 2; /* 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 systrayonleft = 0; /* 0: systray in the right corner, >0: systray on left of status text */ +static const unsigned int systrayspacing = 2; /* systray spacing */ +static const int systraypinningfailfirst = 1; /* 1: if pinning fails, display systray on the first monitor, False: display systray on the last monitor*/ +static const int showsystray = 1; /* 0 means no systray */ +static const unsigned int gappih = 10; /* horiz inner gap between windows */ +static const unsigned int gappiv = 10; /* vert inner gap between windows */ +static const unsigned int gappoh = 10; /* horiz outer gap between windows and screen edge */ +static const unsigned int gappov = 10; /* vert outer gap between windows and screen edge */ +static int smartgaps = 0; /* 1 means no outer gap when there is only one window */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = {"FiraCode Nerd Font Mono:size=10"}; +static const char dmenufont[] = "FiraCode 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[] = "#aaaaff"; +static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = {col_gray3, col_gray1, col_gray2}, + [SchemeSel] = {col_gray1, col_cyan, col_cyan}, +}; + +/* tagging */ +static const char *tags[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9"}; + +static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ + /* class instance title tags mask isfloating monitor */ + {"Gimp", NULL, NULL, 0, 1, -1}, + {"Firefox", NULL, NULL, 1 << 8, 0, -1}, +}; + +/* layout(s) */ +static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +static const int nmaster = 1; /* number of clients in master area */ +static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ +static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ +static const int refreshrate = 120; /* refresh rate (per second) for client move/resize */ + +#define FORCE_VSPLIT 1 /* nrowgrid layout: force two clients to always split vertically */ +#include "vanitygaps.c" + +static const Layout layouts[] = { + /* symbol arrange function */ + {"[]=", tile}, /* first entry is default */ + {"[M]", monocle}, {"[@]", spiral}, {"[\\]", dwindle}, {"H[]", deck}, {"TTT", bstack}, {"===", bstackhoriz}, {"HHH", grid}, {"###", nrowgrid}, {"---", horizgrid}, {":::", gaplessgrid}, {"|M|", centeredmaster}, {">M>", centeredfloatingmaster}, + {"><>", NULL}, /* no layout function means floating behavior */ + {NULL, NULL}, +}; + +/* key definitions */ +#define MODKEY Mod4Mask +#define TAGKEYS(KEY, TAG) {MODKEY, KEY, view, {.ui = 1 << TAG}}, {MODKEY | ControlMask, KEY, toggleview, {.ui = 1 << TAG}}, {MODKEY | ShiftMask, KEY, tag, {.ui = 1 << TAG}}, {MODKEY | ControlMask | ShiftMask, KEY, toggletag, {.ui = 1 << TAG}}, + +/* 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_gray2, NULL}; +static const char *termcmd[] = {"st", NULL}; +static const char *up_vol[] = {"pactl", "set-sink-volume", "@DEFAULT_SINK@", "+10%", NULL}; +static const char *down_vol[] = {"pactl", "set-sink-volume", "@DEFAULT_SINK@", "-10%", NULL}; +static const char *mute_vol[] = {"pactl", "set-sink-mute", "@DEFAULT_SINK@", "toggle", NULL}; +static const char *brighter[] = {"brightnessctl", "set", "10%+", NULL}; +static const char *dimmer[] = {"brightnessctl", "set", "10%-", NULL}; + +static const Key keys[] = { + /* modifier key function argument */ + {MODKEY, XK_p, spawn, {.v = dmenucmd}}, + {MODKEY, XK_Return, spawn, {.v = termcmd}}, + {MODKEY, XK_b, togglebar, {0}}, + {MODKEY, XK_j, focusstack, {.i = +1}}, + {MODKEY, XK_k, focusstack, {.i = -1}}, + {MODKEY, XK_i, incnmaster, {.i = +1}}, + {MODKEY, XK_d, incnmaster, {.i = -1}}, + {MODKEY, XK_h, setmfact, {.f = -0.05}}, + {MODKEY, XK_l, setmfact, {.f = +0.05}}, + {MODKEY | ShiftMask, XK_h, setcfact, {.f = +0.25}}, + {MODKEY | ShiftMask, XK_l, setcfact, {.f = -0.25}}, + {MODKEY | ShiftMask, XK_o, setcfact, {.f = 0.00}}, + {MODKEY | ShiftMask, XK_Return, zoom, {0}}, + {MODKEY | Mod4Mask, XK_u, incrgaps, {.i = +1}}, + {MODKEY | Mod4Mask, XK_i, incrigaps, {.i = +1}}, + {MODKEY | Mod4Mask, XK_o, incrogaps, {.i = +1}}, + {MODKEY | Mod4Mask, XK_6, incrihgaps, {.i = +1}}, + {MODKEY | Mod4Mask, XK_7, incrivgaps, {.i = +1}}, + {MODKEY | Mod4Mask, XK_8, incrohgaps, {.i = +1}}, + {MODKEY | Mod4Mask, XK_9, incrovgaps, {.i = +1}}, + {MODKEY | Mod4Mask, XK_0, togglegaps, {0}}, + {MODKEY, XK_Tab, view, {0}}, + {MODKEY, XK_q, killclient, {0}}, + {MODKEY, XK_t, setlayout, {.v = &layouts[0]}}, + {MODKEY, XK_f, setlayout, {.v = &layouts[1]}}, + {MODKEY, XK_m, setlayout, {.v = &layouts[2]}}, + {MODKEY, XK_space, setlayout, {0}}, + {MODKEY | ShiftMask, XK_space, togglefloating, {0}}, + {MODKEY, XK_0, view, {.ui = ~0}}, + {MODKEY | ShiftMask, XK_0, tag, {.ui = ~0}}, + {MODKEY, XK_comma, focusmon, {.i = -1}}, + {MODKEY, XK_period, focusmon, {.i = +1}}, + {MODKEY | ShiftMask, XK_comma, tagmon, {.i = -1}}, + {MODKEY | ShiftMask, XK_period, tagmon, {.i = +1}}, + 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_q, quit, {0}}, + // screenshot and multimedia keys + {Mod1Mask | ShiftMask, XK_s, spawn, SHCMD("shotgun -s - | xclip -t 'image/png' -selection clipboard")}, + {Mod4Mask | ShiftMask, XK_s, spawn, SHCMD("shotgun -g $(hacksaw) - | xclip -t 'image/png' -selection clipboard")}, + {0, XF86XK_AudioMute, spawn, {.v = mute_vol}}, + {0, XF86XK_AudioLowerVolume, spawn, {.v = down_vol}}, + {0, XF86XK_AudioRaiseVolume, spawn, {.v = up_vol}}, + {0, XF86XK_MonBrightnessDown, spawn, {.v = dimmer}}, + {0, XF86XK_MonBrightnessUp, spawn, {.v = brighter}}, + +}; + +/* button definitions */ +/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ +static const Button buttons[] = { + /* click event mask button function argument */ + {ClkLtSymbol, 0, Button1, setlayout, {0}}, + {ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]}}, + {ClkWinTitle, 0, Button2, zoom, {0}}, + {ClkStatusText, 0, Button2, spawn, {.v = termcmd}}, + {ClkClientWin, MODKEY, Button1, movemouse, {0}}, + {ClkClientWin, Mod1Mask, Button1, resizemouse, {0}}, + {ClkClientWin, MODKEY, Button2, togglefloating, {0}}, + {ClkClientWin, MODKEY, Button3, resizemouse, {0}}, + {ClkTagBar, 0, Button1, view, {0}}, + {ClkTagBar, 0, Button3, toggleview, {0}}, + {ClkTagBar, MODKEY, Button1, tag, {0}}, + {ClkTagBar, MODKEY, Button3, toggletag, {0}}, +}; diff --git a/drw.o b/drw.o new file mode 100644 index 0000000000000000000000000000000000000000..af6027a2a5af5207816f5eb2c07c5b60b5ff283d GIT binary patch literal 11848 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 Un~m3=Urtb$mkq^R3}+PmKW4Vd@c;k- literal 0 HcmV?d00001 diff --git a/dwm b/dwm new file mode 100755 index 0000000000000000000000000000000000000000..1e704d3d1e96eea5d1a0e95b2552e0c292066ddb GIT binary patch literal 89616 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%0DQ(53yc&v3v@;LXSBUighJewL~1l8P1OJP zXU{q0f2Hlupi1R*VHjIn(6Y=)J|&g+*d7EA+}pr1B{2@WjN+h30x!-=l!CvZ2AEc} zIV8Py-oRm%Kl~mPhXd+bfJm+=l~Yz8_}_0pGJR3-YM_44kQ|Ws$X>9I(m@zS@pws+ z_uPIjNztpNYv8h@AJw_xI4DqE;FZ(nHLeS(6pxwfu;9hE4GidM#rH-2-4{h3!-bJ@>!hAjLh~r7BE^?_Z!o zajYWS+t3Ha&bx8V9+9J_&P^ybNgcEje}<0U!E6*Ud*xFMqYv<&C+^Fo@*}f{0ED52 zR;JxTcS&&=W$?xwR7+@Q3Jmp2jJ(jwOe;Q<3s9<|(+uY6?X{?gMpGIFP+DLv{(7-; z4V@nxoI|=S{u&kT!#o?wS5GJDe_2CQQS)k)6^=FjJ5 zs@zW~+SXg$@W-ow_|i5`>~vHuIszq{we^2*e3rNL!wusI`RNOT!-w(_0{`&vSBB25mnK%%zV}zg0us zi|P7%>GOlsCS|sZB(b}AykI+vLl?X-8`(2D!1~bcwtp4FW|+w@hQUi z3}L)ecpy`FAWayPC5#y=P5zepj!DNw8*)SSNs)DaPrnBtP4Ei8(5HaTf`pIhYleH; zF=RZSuUzC8`}hFkMVN8WXo+F%SLl6!il_!D{vr8V2E9h2IqRqdFg2lw&XPYOp6xN#7ACTYt(T6jn@^`@?0h zpg9H13=ZI*cr6imut8caU4!Wl+ZY)16>M`9OLdB9<43#m93qb|VC7(C*RT2^M4o+KL>8}L zdkR0&!@twNqdRRG@o0h0%aBi+O~E*#VC*$!_rC=|@^wfTZTBM)F=8e*B?Q|TFrkZa zHjcO@{X{CrPDc)E)bQxd0PkWQlignfI|0H`NjE5Xf`&&JZrcf3ilTvFBrR7Ng;77` z+DvI*DQO>QX*-p2FHl;GlD1h(drL`MM`^DrX-{iue^t^*F6nV4ty)XlsHANHEmbLL zGqkh~O4|Qx@5|$(tgilVCP5?UBnW8SN5KjLF+iYzL}s#)Xn=tPiGWTf$%KqdX2w|{ zLBvP^jUh@aD(PPQN*=a?JF*|Y25~)O0`vNeVyO;+VYn&D*&?>570CtjxE z9cbmeZ!o+<;(bWA)>X7ec&iQ1LA)0X@0Y^6-0+Sj-p>qgv+!CCFOPUP7~U%3g;V^k zFuXe9g$(Zy+=<18S1PvT_^ z5~ININ!&qeNg|5s0Ey-liE&y2gQHXGNn##JbYh2n_bF$P`zbuzNsM_7KVRwkKY2J% zT870cSfkscAB8p`l z1@ADyKZpBEkAa6BxS`-HKq-+lZG-GZa2lV9kFQ4rT_e5#0yzf}L&~Nxgw?(K?2{IPK-At|GAc_!Rx49lb^?Z;@)nk_OiFp045V_ zFm$EK4mF>>qfCsrhF%B!s;8-$#bk$u^N4(t4ygibzR$%9@RanbTClJBOA^2MVC1P2 z_FOn2*{Q+A**e^!diZeF?)wFL1`cHMTtImKTJFB;&*ZV9W5@8Wn)TV!o{yb8;rWFK z0FK0dJ*g}jX}rhCd&RUzs9TIJq(>aOU!l2+J29WuaL`x$=w9S%FMhhp+`MwvRl2UW zQ}>REl6NSdWv%pu+78nbUEG>ji)d)8*dM@^O#TeUS%rrIvoStA6Pdn`jJ0E1JIV{6 z@O5|1Ox%Y~2)mK-4%n`JP3Swc&y=lAR~<+|wqNhG7XZqsT8AA%*!Z5vn;4#-;Yt*~j!{w9I$H5~vUg6VuG+E4Gv0t&U651pR2e?vfUl=iWNg#I*f;=fd>X;T?sr{od^xQ-W7_LE z8#aNN>7I()>#>rlx>grB_ProDdUauh)wVo>n_9gCK_r!{^$G(*~V zb^VHp1TWpvAYE_XP3*=XXaADU=UroOBu#bh`C>1gW_KKNTsfliBY>pQK5+F!7&e}I zB^2B}8Aez9(E^y{qXUPo!s-SH{#XTB;x9pOyKK6*M7z&&(V(QFDSfyN6Dq_o}_?f;D^ z`~mDFO$6ScSke}@mQvcWu+_WnFk6G0^BB4}gLzH{ECrxDZ(qN&BZY9mO7g!EN&(}@ z-!VTUEp^XB8(oR_N1lt1!qEd{OnN#nII%|;RFR7!xqmlB^88;YcZ0DPG4@(T_xH4H zSEshWCr#uXSGwW-5UrrakLYNvv0>78Zqes0XuK|2P(3fP8g_+g0A(4o!OdiW`?C{2 zd6v+fXmMVHBwkd)iCWlJrjwo+j`j%Eb~`xxhfs|eT5;~OaBK)VH@w}vuK^WH+cu8? zuGJyTa>OsJ?pjgR_sU_{l@*EA^q^bE^UDC40ggkcn6@)E5)m(kH=`;3jn5j&kjhWA?Hf7o{)Ja_Kf1})=x26jJZjoN>1;-7aVlaCJqL@67G!hW1a zdWjQt+(q*#+&RCabQE2J`w73-?<*y~Pu9?V%H{LXFPeR_)5gYU;-Ifw8f#6VuW;4S ze&cangN{d1uzS`usb*BluJ2)3(l`olg?3z?hxd{yXy^AUz58VMUyAzn`ZA=ctEdM= z@6JfvgtgDiQ}!YiI%hd+F2`5~`gzC*K0>5>asqr8DWR)&YN7#NI(OmG(Hl@r=H%PK z8}r$iozwQ8@YjxKGWAZlZ>-%tOIho{SD|?$__rS|ov9Pz!Eh7Lf}1gr;WtZi)-9&N z(vjHDSlabt>Xzv3m|svgg^D-mJMfk|P@+wplV7=%hg8V|DB)eWFs8ZvN}V)4P|8M- zv}SA-zDwCR!^W&KL$scSb;c^gkF2Fd7yF*1rQ+O=t|QN+iB0UJdC1n9THGd1)`1q)Kfu^yG!D+A?X|`3t{gK-ie+_Ht*OPB<5f(Jk=r5gR=e-wzJLaO ziE(_j9!=JUvHyu*%%WGC>Zn6rESf{l+}fO&eG6$~uij`z9ZX^d0cg9?W)(m!iHkN< zJp54C-7HUYJ8PR0Zk+_Zj*s(vUZE%E+&RRN2G#;*H!zZp?O_CtM>Q{zW2Rb-ZKm5P zK3dO3zo7Th%SQ%oCQaq6yPk~8d}3}t_Exmg+HcO<4I0(!qB#4qi(X7Ni=quFvd(4{ zj zhw{S#vv_^Ryzff$Q2nqSBfnZq`{XHpfWG$p5B<NJFoy(yP;Kcd!4T-h~+K)l(6N1ch|7@h}VjI1C` z>-vh(b6s8KCqn@=r^9WY>nLp~$i_R3h?Vl{>YC%2R*^?zr1o|wZ2vyaPi4oh(MaC9 zg=nGiIjnU-bcl2qW;P8zPirM*(y#$GF({D>CqCp#`P9`tZm%@!_H3U>0`d4;udc2q zsoW}!$-B(P{EQtL&zf^t(E6U|nznoOkTH1e|9ahG;^T7HQ`x&RO#!c*k-4%Eav82^ zhgJ{4JInaiuomblrXFo5GKVBr?LrwNYHdcvg?df^!*C-Y^lxg~?wqQps_^o$u`8^G z7Z9BI#R|&Xpw}97p*=%{_GMCSb|luf(Q-#Ju^N3o(I@|G=(Tv#M(z<9y&?tI8()aB z9`gYdIljdW?o!N}T=LSw2(}Z5*Fik-8^pVR+%}{R9SY{U`cxiB>o*&4ObOB%ARUKgF|_^fqKXIaOrTPwT96v{R|B?q^V7+>bx?XxCcpx3ND5$N0j(E0z~`%+55yv`)td)l>oo_ z*%tHY9X?c`k{Sm-fpqdeh(PR>VEG&VXBW`eyXyI<7_c-o7sjC~9fmpOP~ zMVpoA*wdnC0At6Mow#FAkO+EIN6~UPaiR=9mV^0^i7|c*28bWlVc@>+0G^xob_6jB zK$grVRb$C4_B*6xUXH)jlXUgnI!nVmUfu-zzU%w;cwxKcyN@-=la_muVO2;sF}=b*~+D5FT)LOg0FK z>(@gas6SZ+jNq%i%k?Jh*d*#eUF2AmnVcRUg~q8`*RP@_2+T}_x<_ovrI4ONwB<1> zjL9>>d~z^COWYeznh(k*E(eQLF)uL`_JK0iPmV5z*TkC`_bl2;?_OYOw&MV{fjpfJ z=i%$H1`ccBum%om;IIY`Yv8a34r}1B2L7MXK!%>gw$FU&#j2TD=Qt04PG2Mvii~qK zc!R-E%n=BA8y!udV9e1J3AH$a-WK0<$604a&l;@y3x>UssLx1}kRujyguSttFA@~_ zV92neVPAv4$?t2-PYc2u2!tBEF`uI$6bMChEGj=gU&Wdcus;$-8Ym(Dpo5SGZv%c? z;(+UYI-NeGloILXcw!NMaB043Xr`paRJ6ex@YV->X|bl|kQ1FhSm9-u=?*WH(Cmvi zR``RBp%so6Z_v9GPJh(l4Mcq2#x_SJ9t@lundy#*@3OcL$!iET`ijnM z9A|KG4pya(GaJ?7GaD}^zsA3>)z`2*th4TD^7;e5#_39jIUU~Ofkp?FNsCt0=rN8n zP|0svltF(Nzpr(APr@Cf-<(ye+ z;cSn4{@j|mC3CB)$x&KXRaR5xSy(xzbnZd|YFrnTdCKROET~qVIb}5-S4mCfg}nkA zs$SrB&z)aWR%#@wFRHF7gU9)(DESpn<53tOg^KY4+in;R_ z8409sj%zlD1xGc!OUNcs$fF00l8UmD3wr%%F;Dq|s;cUe`DJAs9mGtwJvA4(`@&4Y zJf)Scs=2dFI3-n-Tu)VHb&ZAqp z0a-sYdXD~2H~D8qmE$|=oO*xooM^Ke-=Lz+q1e)R&@q0gW7OzoZ^N>vcf}aTc*iP7 zYeT>vc8rfX&hob)QRjq%OV4tQkNN_>hL}GTbP&5f_=0f{>Z2OpqQ*CY1ncqFq{c@y1K`mUNrxVHo~+%d-&X>^oR3pG0w3{8*vSNe)36etJE00oKCoIYT`(M~8WgQyI3 zXRoQ7id5_(u=F9NsX-6ml|29FEw(azW!s{^R*4abi5It zZlvlXp=G|H^2TGKXv`al<-@8{u3p?z51-4Z`Are%K|e#+ftk17Le~Q`oAmYZ%#4#V z&s~+J6uqCi`J!ZUEADrDlgYiHdqEF^9`YxXxu+;~O*om{4EJT1C6n2BE_^5GDA3|a zG8q891N3&#&!Sj{109AXpDa8gm<8$py$7@ubOaWK+Ck3;-2{3Q=pN#Oz6bg+=poQ0 zSa_;MsoV~_7W6nQJ^d22ZZ*O|x!nlb2>L4M2GEo743yqOnhClWbUEk&&_98yqm()p z&kKfwmVk~1y&tp&v3fb7^^NZ8BL1 z`ZBhbgh5-eePaXY5bXQ72XqhU)1aqgAl09|$;^pK;}A3*a!lb};UFS$RNtONZDv>kNH11M+E@BJ9@fDXdD z30YXEyLBt#2i*?(H0bw!j(mYW`7rb`RH?ImfrUNLhd@_>&if_o3G@lj1n9J1A)Uu6 zwd&X4gWe2!JLrRtK(CWtx(C3~)dO+KLi*(@m&_6+^f{xmW_(9Kk z7Ucoz2R#J(0BG*iN>w7?-0?p1->J04sDg<4HO&6`8^L`II0bPwH z@I9b^+lzQkK>59qOu9kipv|EF1-c0|_swMTC!llwh;U9+>iBn{PtaTcg#3bj0s1y* ztOs^-66!JN4A8}YMtVTcdl&fw9sB|G3|ay@{A8szfQ|#r{Sf&B%}k(Pg04A$dIWmH zUr`T1>p`2*jv5*q%KOeh=dBWrVYs!nwenyTMj!&s(2aVs~_8 z(XC5Mx_0h*5o_uYaX=SeLjFQfO4Ic=1b1B~g6+;Krg&WxuZ!X>wYxK?WDFEByi)$? z`BNqy1Uhi9&Zqpjb^eG)4|I+Mk94cbh<7PvT{-Y~4|u16cQNkOBH~>>7#_=pxa`?3 zEYwd0yc;sLkhzRxD($(~*(&XM-K3ulSta(->nWWbN7&}rN4ruq0-J$&mJM|WekYS( zTohg&u!n$E5#YAxc9Xt0WR}_;>nXgBK~V3-_R*y~?GD#2DELL_?Iom`!mEMbC*T)N zp1ug9JvZA@FtUwRz#aznAW1EuG$W2~((Q&U6dk9z6va7ru)Sc`PNaPo68|EidkN9K zOe&a%QXYVzMkC0#5&l;Q-$~(Dk>2J~0mC3hm)Q$y?71ac{fg`&I}^GHC6g;j7UjIb z<|4a*bVnAYz>j>2b!>phRLC!a{P{F$8OSc6pY=zSl3mQQZ_Tj%mwj7CnSDow8`K3L zb7&^+ih*3L>DG*upcQa0WQoQ!cc#x~VOvyBcOyN+(NF6#thMK!Z_k5GU!ZM>>TCl1 zG2mmO%l5U%o>xHMv|uks=*N0NFEtC)H!&3v*hv77af?ss)`l9+d8rT6~YY2hH zI&8Lfij4A93f}zI{^_p;b{Vjzn1aNW`My)S>658Ki*NO}1?{9d?<>zyt)+nv;s zP}`h~ao>C3-GFWov#G2{1NU5!Og=-n&OgB(1`5kfX+>dN zhwg))0#(*iLyw)I094nb5d;K5q5I*ehzWtcq(vys9)Yv3?Re?17Z8{_=r(f(0AN$tP&xFOZ<5Y)dcY=!FTILtk2 zZ|L8zIf2awhG~SpC?7PZsRUN_Kh4M3f%8H2@_vNr!aN1TL*0JYpd}cMTbd`80PiN; zc9A`IJvDS4nU!`2Iy>~4x#%;Y1FH82AbSsF*J@c^iCd__rZi_`esuIrXv4l`nm>T< zYe@Ge51i&v2y+R-+<$X2xrO4xm}WiN10)T7s%@iguF;%P-qu2{VKY8&MRG`%t=Y6W zw*&tb@Ut23u=xhtvx{liqsO6-f&V1<*lSH~Re{$&)opi{+bdjlH->{3QNF2dqPgGa zkh`-t91LS@H|w^E;?F|i#coL^r!zkWj}F|Q4E!eGv_;sA$!u{U?!S*5wtAYw^G$5K+-@7H5%-88bVr*PtFR;zi9WPRd3?PNnX9wW#W%#?C`~l`MN!obVwiv_e zeq;0+h|{{mF<4(HA^pK`YCHCgc}Upyvc0teO}NM2ip0kT?p}1cDGbsNAzVx+*~Vcs zW@@390CIr;8Ti9E-s>o@JVw{!478se80WfeE%sViS*142O1pc7y|ygH*{u6=J@{sg z@c0Me{|M_O)CSR&i@#04{sL@;Mhtd8u(ErT$!Uy{Jw68PQeb*atL<@>wnyU8ddmjz z&Lnx15z1AMO=rOQckpfmZ$8^%2S)dK)Fg!Ld6??Bv;yW~RtxBIW177>q4uH>Ycls? zO-Iia!uH%KVx@Mb3OIcig*dbuQ21e~PT_krjes%%Vb4bP1zt~ICl$VpM>mkl0`YLr#WH=&1-Fos7`YSmr|=ScZVqD>uvb`5`I4-zq&op zZB8lL!aqwiWGh)imHN$tn9H#o#`YCtNEL89z}pAjjQ;hmZ{0zUAM`x$eEU{g=J0{L zL!F)g!g>R1dRr-;CHA}pc1M*?hwai{L!oqUf}Hm!$>dcer|lYsc>!`oVf5zhcsTi1srSW}#fwMyNuqMU=hximIIYmk2Mok%L> zb0w7S!0jgB-vd5{aIDdE*c$q+caY3B$lMK?CXzwlf4O~XIraTC(5H?+2Ka5rybqZt zsZZ5*rptepeT&U@AB?9|cjRS5GB3=q-;ZI_R@-dQMW8jHi$SZIt^zG4Z{d`Fqz(75 zNZqG+q-3aW(^}~`thqjpdsBW$THIbyozkb2=spFJQl|p3(fHc{e?NymFZn~+ZGaid z8iZ}WjzRZzPO!H@_5;W+;<3qkTCeE9`bK{|PneCoV2x2vV!qMF zQ`@}*et!nP&E$8!UY9{}yLLL^d>g!ff%h)u6Y0E;#)AW`FJ|t}7^n@?;~%X5-}-Da z`Qm?`7wLAT0;RYBr8oy=Tgl~}dCtI-O0v~{{F=fZzNAbj!5HbJJR3eWPe&ST20Z_L@ZE(~>NW`1O|-=A4w-=&ut42^q-o|T2N3S3Naql;hra&ceDr;~-8dT0X8wq@odUMDRp^{9QW=I4ioDI5 zvjD$X$HyO;#Nq3(1`ccBum%om;IIb%f7Zakg(mk~nNnX#mr(Byj9Y#Mr+$KZ$3T9w-|b`XxT~?!w=^1CEqS{7d*BZb@O{ zR``<6bpIkP;lJ>rApNQMf8xphIJuno6aU{Iz(4WDe_NV=;?Wg0M2UXtSU*n2k4c&v z;fwx+U(a%H-_18ngnuc!H*@(&dWF9%ji1CtknsJ?e}uzN_urVtPxr6K{g9c<{;{81 zPrD`j0Q*nj7ZK!QT>QWDLk9F-@IJoyPvJk2>OaKZ`uGNr@I}Ar_UmMSai-fj{`CBd zer~nkOZ+P>_)|FiB^LbeGXFda{#53VwBXBnY_wzhi{lTnI6UVmtH@Fe;Lco zyPt2E2tUSdX+O4b`yqV2J_H%zZ%yO3r1_WjNBld|`0VVpAK`zvML32!*(v##{E7XF zeF$IbxA4XPI1c9rubP{5etsHX>_@^E|Cj9O?_c=hU-;tR$>C05D(M$~X&PVJFX2o0 z;$QM7e7$CaFoZAdm++k&{zRq{zm44zzwjk~;Y<9&m-vM*@e5z#7rw+lDJ}l2wD^TD z@e5z#7rw+Ve2HK962I^z{=&5Qsn4RT)DXQFk8UM?;Y$-nR=e&I{}!k74kFYyas;upS9X@4dDc4aP!U-%Ng@FjlXOZ>u@_=PX=3*V{C zCGES!F9Q;ZU-%Ng@FjlXOZ>u@_=PX=3t#+8`#-Fi6U5{wrctIcesLCLXhi&{^Bv4* zZ|c~jeoWOnKH8GTADYJRN#hSo<2!hKCE;hL@$1t3+tT>$%>U#)6T$=fVK$z@vb(z5 z;9sztP8Oo;U+mtrjvfFU~^Y2;zMxIJo`oVEla>fjL<rcTbldYH1{28 z?g!X?v;^-oH^;Dh_#e#83G8;CWMY!%(bC_Y$oyL7(^@-S!vDwDNp0ypnFb$Zi0a`E z>j-vdXPKM9?B37m!}cD1R0s#FwvILFlW|A^XKXkNa&YQ+c4zYdPH-n@MAA*~ zXV4|>rNn=#fqV1!ucXNzV%J{3W_J%O4)smvU&`qqyIJ? zrdyfrV7iBC57UE8Rk4XTm#Kqk0aGVaH`6+%VW#a&H!|JAbSu*xO!qMDVS13MD&hE< zI+zwPbux7`tz#Ny+Rk(%(=AN5GTp&+57Qo|2bs!%H@B4a&$NK4lc}3&9n&z=cBUJd zZehBW=?SXF>TE{fZw4Lcjrdyb9Wx9ju9;Q7^4>DD=IDV!MrUgu$Ox;ZDn1-3Q zGu_B^3)8JkcQD<T zh%B=6lT_VzDW<;h4ecQ#`CD0D)@5jYfbbU>=V;Un;2G*fHJr;8!Rm{uE6EouHEyXk zZpLLEC*!jPz$u)(v~VtFc}KGeXN@6>f~EB5P41umAmffSJPMrB^Ft0t^gz=d!vDay z?4jGpxNLYNz0-9&{z(1^R`78e#k-@7pUk*^X9w7$_@i_dq^0L^mcND<&h`5{z+Pne z8BQhk4*A0w6!}wT? zI|;AVqdvUr$~YM&;WDq&@67-^4#_55=70L#7vN_yF7rtJ9t-d>Lyf%5H}yLyz-fOt zg(LG){eB7X>5R+#Rlg$w+{Jj?S~zg&_dGx^U|i`lxXicpyBm=A zF#eBD?H!hCu4RnpTx;Cjj7NY|xsT>@$!7ctmcO0lIl211Ps*>%)Ajoo@YBumGT-0A z;oQjhXB;7$k-AIAd%TkM?}IFVAIo2SodM2f{9(qgX57O#eb1fJpPOd4zh(IkSpH6y ze}VC}*Bf9u<9ivG`Q&1oVeDi4gzp=-es2P|d%>r8ooV*`cgSm;(e( z351i$;fzj8KfU));Y>}#k7W5eju%4uI)?FrwDb(qIA&j?jbMcl*YC?xIi7K|0UV6e z*^z`7GyXc`XET1nW&`N=B5*sA@maSRoSP>#gYlm+el>@4KI2nvHNf4BR|BW~Do($H zaoR6R>5=saZYETlmOozgoNV$%?-kMI=WrZpdT8Kq%5O7rmm8w!kRS^GDaQ5t3gE3~ zT-E`QGJS1e{4`!4(C-<5vk`a(X1R4dA8+S!+0612*#N0uq3Z{XuVH+Jfz?kL|B~@( zjBl54?lQo6j6cVCnDH|ie}(ZI8K2MT`4e!`b35CWl-GwW|KS!Bz)BA1bH?R)6!lN~ z$~1a=?FYsw>+;D=(82Pwzm?*Z z=Z=C`FuwhVMsO6%&tv=@#(9}gEn-}rzlweu7=Pq$6M*PB$hbUj{t<`Y%D6m7l>Bxu zF6+N9vwSCT8du2k?l9xuXI#dkC=Pwy#^Efx*SME6emCQPX8a?@f5Z3-oWS!Le^!S- zR89E605X1fndL{^XK?*K0dC)8T%K=k<#0Y>Jc9-pxUMop9b#P81*JX5pi!6CPgq{> z|A!wtaI(+3wDxm2%gg$nwA*Je{h4IQ?7`N9DwVH8RZ`AwU!Rux`>(@q5?_tO79ju=>wi#USPsi?C)hsnFSmt?psGhu8B982_=xPg2=w{m8F5e0h#h#_~HDm**oh z8GnKC|9;W{lHXSuzhsBOrCi=*d^6*E|2afH0Iu6f?vETM8|q`0mv!CeOmOOJ#_xLC z0D2ENZjT&f>_^s#Y5YysFveva`3eK8(;1ib>MI!^&$z5-OMRaXT-#w`e?2={Ue?3) zUTuU`#klO-(fhA~KgQ{o=Sk9@?_yk@Q&n<$F63}z|HWFy7c(yVRz71~G2X=uiQX>_ zUK4QA^Omzr`la8YclxQFl=XD(=G6)#x2M~Nb<1+6Td+1pF1LcdD1L0dCk2g-#H6IY|yLRgEPw0JaA)Gff zo~P2+?avvkl!InbT)raz7swwgjuiTt1)hbDbs+f@Eby@w_yh~Q$O5mlz?WFylaSwI zVJEq4C*R?``7PvES>V@M;CE>}M~z!-0+w;tLl*M8E$|)-oW2<`kex!U8|?sDbl!y2f+VcWRA(?qS8zH!TJ#FQ)}Q8@Pl0rV>B!q4=kI3@Ytd zt3^21Sl~BV;Pm~AfztV?1^&DR{)PqquEulJ@3|gTapn$M$SYm1Q#D}jhw1k1oA`L( zxdXI&(=EcezyhalY7C@@Wfpjw#>rOH7)aoV2SfgK8qZO8@_=1`j|_gcTFCFTz~8XI4_M&z!5iw=PVt!p z%KFKPSU0Bh%X2kOzB&sy$v@BS4_7laQR5=jM@ud6c^uAkF2@Ji%OVT;OD*uY1%8zU zeuD*mp9TJN3;byd{1pqlN8>r_9@g_n&hK9>t-=`fYoR|fEjRk&_1^$2q zzTE=fWr4qCf&W9}IqKB3_B<T^o;7JR77$%ql+0R)Pc##D@8#s-N()+s_3;B8r zyu|{)T;n-vF}I(UT*TK}$Zxj5f5qY4!5x>(FMeww|9cDkj~vcNubPAm;qld_VVPR$i_z%~IJsekzcJRVg1**RjLw4~&QfnUs(kvi z2Ym~u37^o9s>|a3n34l2BKUBBEYuPT;;Z=qBKV6c9Aps-;amRL+hOiG8h-;MTJ^~l zjq#S2HpRFJAs%kT!5s8S`)2r$s>X1e@`l5KwmvAjLe)1b7BoqxFqis5Eef>Bzch}I z$VYS_9Df56;fwehn{Wn43?GYc@#4ISh!U8c!ANMu(uluN)oax>ha&!!e6O1P^`W4* zp}`ML;)IR>P6!C&d;9@Ky5j8U57qNMlh%O0UNr=K-e5dTnrZYw<+y=je5wKGdf?a$ zz&KnX6i05ok%$)=Aqc9DghH`!ETV`S6%xZ_tlk?zI{NaGr z3b;X6;OqjFt_noL-bNMkE`@pxGfGD-tZ4Q(YQ1T@zyS#H$Wkgiqv;hbra;JEVo0`H z(c(pssb#*lFp?Byv0%J~KFAM^!n7jZda$Fa1tkcr<46&IQ=5kC{G<_MPhAi0EVyYD-s$HD>`il_DYBGpxtP}aXSsm$hwX8V5oez-0y=8BlDy; zz5y|@qkZTyC`*qH-CZ=proP=hP^A)4{yMnbkTc^g+9e1 z+T3^E1@6&8wUDKFJPpuqC?0I|1pENK0VHSuaDt-qOguQSMBxOXpuUNRjoaVS0=<}H zQE;QJkhD%p_n@A(P3XOwr0*KqywtiF=0s{d(0#O$7f%zaobm;5N=wuq_2^zBe~R)4 zmwN;LMs`mYcYdJ?_=3^=i6GuaGy)!K8lV*@F%m$ljl2XyXi8A%(fmm&j`kEWc|7>? zi>Iu@Q$8Q3?070lal*~4s=39kD$m^V@@kw0RO2eHD)T5$=|wn)r?NzqH;y};=V{*wQe|~s?)FpiXpHF+AEm-YIb1YOq7_d)&9<_mmn`iPv_re#&Nv(VO7`yx;(?tQU^v*&~& zIKHVuccLB-RTU46G!pZ8P`l~ur`~WW5587^tRGMdO_or?OJPd0aq0}B_WGlu5>Jyq zh^`RHCX;|tJZJ~Z0HSt5kQ#n>2vJLFv>x5u3K)GNOgftji42nlOVJTk>vOag#G0n+ zF@dk8e~KuJy`h>&pax}9>WxMzuTq|@*IuJArL1aO>TA%(N=j-%J_gBCSu@+yi1EZy`1D0;WKDS=I`lQPmWV#~S)&lIm7Jpq3*=PU&5%7b1C76OlGclt@Cs#_|mry=0QX;U6gV>IM3J*UpS85U^UjP?tp)`hdB zR_JV*0;F+2DjfCJv(cz?hEdR>72Ob-CWs85`gaPWVGhpi!wF>mSU9~YHT4u4M=E{6 z<^AKY)<=X@22pFYS?arTJ$RxFV!UgN-{XO1gCP%fwBJye$5S7TifwbEbc^5Ha>Hhd zL+C_ntJ{JNIwBJ>R6lnGx)AgYeYvg1XvAdPLxDCdqbA!!C+hX4y-?LI^hUzHO_%8| zs6o+spyF!j-x{YDm#)q}j2Muc-fBawEzBg^*X#AR2i#E9gm4pWYcVEVty@;z&`B>? z8Fj&$mczzNeW+PJ?%zyAy=mwEjp}<@D@r65)y*??G17peylHT+JkW%yt)xaj=%T?m zG8SwIxAhN8cfJFtg8OP!Ym%*#PYs^w*^2da!Srmp1xYb?=-r~TBsHQga}TAJ*AR$E zGmlmpX3{Tp=q_}}jD{+T0XLlv2lJ*GS#LwCJ6fbs+eI0jU|GR~PTf|x{jF$XP^qFp zi$q}#iIH=^Xq!TjzFwX*j;ii!3CG%y_pUlJ; zORJ`O{;ucq)JQIzZ5pC--TJucq)r$cdW#aXM1eUP2JcZVPYF>TjBs@GM&)mEo?>;W ztpyJ}v5JEV7xUJG#v+C`%N=GDzWk-Zcz#$$LHWHQ8Y&V93Jo@zJQkm`7RuYQHaPyK5p}uVi7^#M12h^U-vTkdK8x* z3F-38_cf#aMAPhPZbWF}QYN9U;>z(f6VoAjXrZD_Y5#IhVNenfoKCK{#gBMQ$Y^pE z=Bk*4piBJUxK2VK*b*VzYm^)N5b5fr#@YKT>(2t@<0jSr7WOZ6ln64F=j#Hya6?Op zygaC$X8%G@7D1-G?AVLay6ES4hgbZ|d(J{fv*aMA>FKWqj#a_l_~kulp?mSXiY{#D z(diWbc^btTXP}hi-uSV;Nmmb3d5_wlCJebJ+JHZLM_K&Kd&xqN$^MItHzn_N3zhf4$^QxXOZR^R zFv=pOPhZadl7`-_C)v0lF`U4M_Tf1614@D0;z zdJD$j4rU9XZNQ{I@h|)Agsw`9FwLo6O7ow+--Il56d6s*m8MShI(Vt=&$ui~4ZdT} z)S+E{Kk4zm4;CKD={ihO@|^`YKj27@PuxQP20wVz)azfq!%+Jz{r@-oQi{3R>wRye zj{Va)7O9sb)q(rL@JvM{{$<}{`w2!51za#vjFN7#qdVX?HGcVy!&ZKO#hs=w@h_C# zdr9@*yFb!l;-~ZYQZGlU1NW3n3QN*2&;RqzF#ao~;bDIcrb14I7)cfgz*PJLFk(yI1ta=? OjgjPS+r6xG|NjR&maT;V literal 0 HcmV?d00001 diff --git a/dwm.1 b/dwm.1 index ddc8321..86e73f9 100644 --- a/dwm.1 +++ b/dwm.1 @@ -30,6 +30,14 @@ top left corner. The tags which are applied to one or more windows are indicated with an empty square in the top left corner. .P dwm draws a small border around windows to indicate the focus state. +.P +On start, dwm can start additional programs that may be specified in two special +shell scripts (see the FILES section below), autostart_blocking.sh and +autostart.sh. The former is executed first and dwm will wait for its +termination before starting. The latter is executed in the background before +dwm enters its handler loop. +.P +Either of these files may be omitted. .SH OPTIONS .TP .B \-v @@ -152,6 +160,21 @@ Toggles focused window between floating and tiled state. .TP .B Mod1\-Button3 Resize focused window while dragging. Tiled windows will be toggled to the floating state. +.SH FILES +The files containing programs to be started along with dwm are searched for in +the following directories: +.IP "1. $XDG_DATA_HOME/dwm" +.IP "2. $HOME/.local/share/dwm" +.IP "3. $HOME/.dwm" +.P +The first existing directory is scanned for any of the autostart files below. +.TP 15 +autostart.sh +This file is started as a shell background process before dwm enters its handler +loop. +.TP 15 +autostart_blocking.sh +This file is started before any autostart.sh; dwm waits for its termination. .SH CUSTOMIZATION dwm is customized by creating a custom config.h and (re)compiling the source code. This keeps it fast, secure and simple. diff --git a/dwm.c b/dwm.c index 0a67103..743a4b7 100644 --- a/dwm.c +++ b/dwm.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -49,19 +50,35 @@ #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#define ISVISIBLEONTAG(C, T) ((C->tags & T)) +#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) #define 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) +#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 */ @@ -86,6 +103,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, hintsvalid; @@ -118,6 +136,10 @@ struct Monitor { int by; /* bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ + int gappih; /* horizontal gap between windows */ + int gappiv; /* vertical gap between windows */ + int gappoh; /* horizontal outer gaps */ + int gappov; /* vertical outer gaps */ unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; @@ -140,12 +162,19 @@ 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); 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); @@ -171,6 +200,7 @@ static void focusstack(const Arg *arg); static Atom getatomprop(Client *c, Atom prop); static int getrootptr(int *x, int *y); static long getstate(Window w); +static 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); @@ -183,31 +213,37 @@ static void maprequest(XEvent *e); static void monocle(Monitor *m); static void motionnotify(XEvent *e); static void movemouse(const Arg *arg); +static Client *nexttagged(Client *c); static Client *nexttiled(Client *c); static void pop(Client *c); static void propertynotify(XEvent *e); 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 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 *m); static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); static void toggletag(const Arg *arg); @@ -222,19 +258,28 @@ 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 autostartblocksh[] = "autostart_blocking.sh"; +static const char autostartsh[] = "autostart.sh"; static const char broken[] = "broken"; +static const char dwmdir[] = "dwm"; +static const char localshare[] = ".local/share"; static char stext[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ @@ -256,9 +301,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; @@ -406,6 +452,27 @@ 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) { + Client *at = nexttagged(c); + if(!at) { + attach(c); + return; + } + c->next = at->next; + at->next = 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) @@ -440,7 +507,7 @@ buttonpress(XEvent *e) arg.ui = 1 << i; } else if (ev->x < x + TEXTW(selmon->ltsymbol)) click = ClkLtSymbol; - else if (ev->x > selmon->ww - (int)TEXTW(stext)) + else if (ev->x > selmon->ww - (int)TEXTW(stext) - getsystraywidth()) click = ClkStatusText; else click = ClkWinTitle; @@ -483,6 +550,13 @@ 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++) @@ -514,9 +588,58 @@ 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]) { @@ -569,7 +692,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); @@ -640,6 +763,10 @@ createmon(void) m->nmaster = nmaster; m->showbar = showbar; m->topbar = topbar; + m->gappih = gappih; + m->gappiv = gappiv; + m->gappoh = gappoh; + m->gappov = gappov; m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); @@ -654,6 +781,11 @@ destroynotify(XEvent *e) if ((c = wintoclient(ev->window))) unmanage(c, 1); + else if ((c = wintosystrayicon(ev->window))) { + removesystrayicon(c); + resizebarwin(selmon); + updatesystray(); + } } void @@ -697,7 +829,7 @@ dirtomon(int dir) void drawbar(Monitor *m) { - int x, w, tw = 0; + 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; @@ -706,13 +838,17 @@ drawbar(Monitor *m) if (!m->showbar) return; + if(showsystray && m == systraytomon(m) && !systrayonleft) + 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 extra 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; if (c->isurgent) @@ -733,7 +869,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 - 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); @@ -744,7 +880,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 @@ -781,8 +917,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 @@ -863,20 +1002,37 @@ focusstack(const Arg *arg) Atom getatomprop(Client *c, Atom prop) { - int format; + int di; unsigned long nitems, dl; unsigned char *p = NULL; Atom da, atom = None; - if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &format, &nitems, &dl, &p) == Success && p) { - if (nitems > 0 && format == 32) - atom = *(long *)p; + /* 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, req, + &da, &di, &nitems, &dl, &p) == Success && p) { + atom = *(Atom *)p; + if (da == xatom[XembedInfo] && nitems == 2) + atom = ((Atom *)p)[1]; XFree(p); } return atom; } +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 getrootptr(int *x, int *y) { @@ -1017,7 +1173,8 @@ 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); @@ -1043,6 +1200,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))) { @@ -1074,7 +1232,7 @@ manage(Window w, XWindowAttributes *wa) c->isfloating = c->oldstate = trans != None || c->isfixed; if (c->isfloating) XRaiseWindow(dpy, c->win); - attach(c); + attachBelow(c); attachstack(c); XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, (unsigned char *) &(c->win), 1); @@ -1104,6 +1262,13 @@ 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) || wa.override_redirect) return; if (!wintoclient(ev->window)) @@ -1202,6 +1367,16 @@ movemouse(const Arg *arg) } } + Client * +nexttagged(Client *c) { + Client *walked = c->mon->clients; + for(; + walked && (walked->isfloating || !ISVISIBLEONTAG(walked, c->tags)); + walked = walked->next + ); + return walked; +} + Client * nexttiled(Client *c) { @@ -1225,6 +1400,17 @@ 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) @@ -1275,6 +1461,19 @@ 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) { @@ -1282,6 +1481,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) && !systrayonleft) + w -= getsystraywidth(); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh); +} + void resizeclient(Client *c, int x, int y, int w, int h) { @@ -1297,6 +1504,19 @@ resizeclient(Client *c, int x, int y, int w, int h) XSync(dpy, False); } +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 resizemouse(const Arg *arg) { @@ -1390,6 +1610,83 @@ run(void) handler[ev.type](&ev); /* call handler */ } +void +runautostart(void) +{ + char *pathpfx; + char *path; + char *xdgdatahome; + char *home; + struct stat sb; + + if ((home = getenv("HOME")) == NULL) + /* this is almost impossible */ + return; + + /* if $XDG_DATA_HOME is set and not empty, use $XDG_DATA_HOME/dwm, + * otherwise use ~/.local/share/dwm as autostart script directory + */ + xdgdatahome = getenv("XDG_DATA_HOME"); + if (xdgdatahome != NULL && *xdgdatahome != '\0') { + /* space for path segments, separators and nul */ + pathpfx = ecalloc(1, strlen(xdgdatahome) + strlen(dwmdir) + 2); + + if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) { + free(pathpfx); + return; + } + } else { + /* space for path segments, separators and nul */ + pathpfx = ecalloc(1, strlen(home) + strlen(localshare) + + strlen(dwmdir) + 3); + + if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) { + free(pathpfx); + return; + } + } + + /* check if the autostart script directory exists */ + if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) { + /* the XDG conformant path does not exist or is no directory + * so we try ~/.dwm instead + */ + char *pathpfx_new = realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3); + if(pathpfx_new == NULL) { + free(pathpfx); + return; + } + pathpfx = pathpfx_new; + + if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) { + free(pathpfx); + return; + } + } + + /* try the blocking script first */ + path = ecalloc(1, strlen(pathpfx) + strlen(autostartblocksh) + 2); + if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) { + free(path); + free(pathpfx); + } + + if (access(path, X_OK) == 0) + system(path); + + /* now the non-blocking script */ + if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) { + free(path); + free(pathpfx); + } + + if (access(path, X_OK) == 0) + system(strcat(path, " &")); + + free(pathpfx); + free(path); +} + void scan(void) { @@ -1427,7 +1724,7 @@ sendmon(Client *c, Monitor *m) detachstack(c); c->mon = m; c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ - attach(c); + attachBelow(c); attachstack(c); focus(NULL); arrange(NULL); @@ -1443,26 +1740,37 @@ 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; } @@ -1474,7 +1782,7 @@ setfocus(Client *c) XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); XChangeProperty(dpy, root, netatom[NetActiveWindow], 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 @@ -1519,6 +1827,24 @@ 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) @@ -1570,6 +1896,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); @@ -1577,6 +1907,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); @@ -1585,6 +1918,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(); @@ -1682,40 +2017,23 @@ tagmon(const Arg *arg) 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); + 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); } @@ -1811,11 +2129,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, @@ -1826,10 +2151,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); } @@ -1914,6 +2244,7 @@ updategeom(void) detachstack(c); c->mon = mons; attach(c); + attachBelow(c); attachstack(c); } if (m == selmon) @@ -2006,6 +2337,125 @@ 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 sw = TEXTW(stext) - lrpad + systrayspacing; + unsigned int w = 1; + + if (!showsystray) + return; + if (systrayonleft) + x -= sw + lrpad / 2; + 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 @@ -2073,6 +2523,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) { @@ -2126,6 +2586,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) { @@ -2156,6 +2632,7 @@ main(int argc, char *argv[]) die("pledge"); #endif /* __OpenBSD__ */ scan(); + runautostart(); run(); cleanup(); XCloseDisplay(dpy); diff --git a/dwm.o b/dwm.o new file mode 100644 index 0000000000000000000000000000000000000000..67ec344ec96b77e97427d2b0f8c297af64d386ea GIT binary patch literal 85392 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 literal 0 HcmV?d00001 diff --git a/util.o b/util.o new file mode 100644 index 0000000000000000000000000000000000000000..e162c5ab2c99a339ec2a3280bd6d537d66f6e146 GIT binary patch literal 2488 zcmbuA&u<$=6vv+vmjs&HX$2@!DO#Z^*b=O4mp~ML$S5vZkc$GeLcqanopoc?@tXA* zrGP{b1+j`E^$*~{0SOKqIP|~)QCA$wt+xtsL2%+wiK1Q*KNQ|~b|x9NwuInGrYQ)GGrt}PtxAZP@;v~_Ux)MtCXVybTfbN@26h$;y=81uYbqfi=`-d z@kvqg;<{L<$2C!{v*n#1%186Xnpnvf>*BS1@ucYGiyw(i&dC=)5f_yHTzstbMe&8w zUx^{>Rc|YMw7`bP)#l2>pV?&lM=$>VYxKHR@V1^%Z2P>p!N!%Wm{uV*G3{;Fgma}P zvL#JsRr=;*B#(LV56R^1$(_Z4h<`~cC&g50Z~HD)IKFI_-I@oubO-;a=u7B8S=fr_ zlM3$-2Q%Kb>PdlDzHyHBsp)q*VRMmad1-0UDJ%zF8HP@I-mSRhMz2z;JW{HZA9i~4 zMGYOph_bxOERTIWmY+LC6GTI>Ngfc`4v#&5M)}blBtyyk_GC(TYMpuW1~(OdNY3TyJg{GBd4Rzv?vCL&!%^|IG5o|B{^}U+kKrxm zcrNoiYOk4{852(f+3vVaa_dVa{FG_69Z;hYL{T?v@U`=0JM2t-a{B_MyXTQa7YM!q1mlZ!_#ZT$0iaNN9 zrv5>T=PiCjbJRzUiNDW^$1OM9VH<*Y3?o%-7;f$Zx&3qN(m%~wMu}cCRupu6R|XrB z+*M!tF)0WAj^u*$C<-4U#K}a zS?=cnZoZ#jkhRph2~A>+4gDYw)cmjcWzNM?6&|*j^>O!XF>M)LWhd;C9mKZO0mo9@ zEnnIvWU0=l}LE^E;e7>ij>{e;sCD zaQ^tNnDx#1k6N3<$kPpN>OOD|D4EVj&GgwbqHi_qVq%Fdw@VJPH7fs0-Tzy=k%^Jc F{~L;QMMMAq literal 0 HcmV?d00001 diff --git a/vanitygaps.c b/vanitygaps.c new file mode 100644 index 0000000..1a816b6 --- /dev/null +++ b/vanitygaps.c @@ -0,0 +1,822 @@ +/* Key binding functions */ +static void defaultgaps(const Arg *arg); +static void incrgaps(const Arg *arg); +static void incrigaps(const Arg *arg); +static void incrogaps(const Arg *arg); +static void incrohgaps(const Arg *arg); +static void incrovgaps(const Arg *arg); +static void incrihgaps(const Arg *arg); +static void incrivgaps(const Arg *arg); +static void togglegaps(const Arg *arg); +/* Layouts (delete the ones you do not need) */ +static void bstack(Monitor *m); +static void bstackhoriz(Monitor *m); +static void centeredmaster(Monitor *m); +static void centeredfloatingmaster(Monitor *m); +static void deck(Monitor *m); +static void dwindle(Monitor *m); +static void fibonacci(Monitor *m, int s); +static void grid(Monitor *m); +static void nrowgrid(Monitor *m); +static void spiral(Monitor *m); +static void tile(Monitor *m); +/* Internals */ +static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc); +static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr); +static void setgaps(int oh, int ov, int ih, int iv); + +/* Settings */ +#if !PERTAG_PATCH +static int enablegaps = 1; +#endif // PERTAG_PATCH + +void +setgaps(int oh, int ov, int ih, int iv) +{ + if (oh < 0) oh = 0; + if (ov < 0) ov = 0; + if (ih < 0) ih = 0; + if (iv < 0) iv = 0; + + selmon->gappoh = oh; + selmon->gappov = ov; + selmon->gappih = ih; + selmon->gappiv = iv; + arrange(selmon); +} + +void +togglegaps(const Arg *arg) +{ + #if PERTAG_PATCH + selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag]; + #else + enablegaps = !enablegaps; + #endif // PERTAG_PATCH + arrange(NULL); +} + +void +defaultgaps(const Arg *arg) +{ + setgaps(gappoh, gappov, gappih, gappiv); +} + +void +incrgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov + arg->i, + selmon->gappih + arg->i, + selmon->gappiv + arg->i + ); +} + +void +incrigaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov, + selmon->gappih + arg->i, + selmon->gappiv + arg->i + ); +} + +void +incrogaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov + arg->i, + selmon->gappih, + selmon->gappiv + ); +} + +void +incrohgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh + arg->i, + selmon->gappov, + selmon->gappih, + selmon->gappiv + ); +} + +void +incrovgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov + arg->i, + selmon->gappih, + selmon->gappiv + ); +} + +void +incrihgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov, + selmon->gappih + arg->i, + selmon->gappiv + ); +} + +void +incrivgaps(const Arg *arg) +{ + setgaps( + selmon->gappoh, + selmon->gappov, + selmon->gappih, + selmon->gappiv + arg->i + ); +} + +void +getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc) +{ + unsigned int n, oe, ie; + #if PERTAG_PATCH + oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag]; + #else + oe = ie = enablegaps; + #endif // PERTAG_PATCH + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (smartgaps && n == 1) { + oe = 0; // outer gaps disabled when only one client + } + + *oh = m->gappoh*oe; // outer horizontal gap + *ov = m->gappov*oe; // outer vertical gap + *ih = m->gappih*ie; // inner horizontal gap + *iv = m->gappiv*ie; // inner vertical gap + *nc = n; // number of clients +} + +void +getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr) +{ + unsigned int n; + float mfacts = 0, sfacts = 0; + int mtotal = 0, stotal = 0; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (n < m->nmaster) + mfacts += c->cfact; + else + sfacts += c->cfact; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (n < m->nmaster) + mtotal += msize * (c->cfact / mfacts); + else + stotal += ssize * (c->cfact / sfacts); + + *mf = mfacts; // total factor of master area + *sf = sfacts; // total factor of stack area + *mr = msize - mtotal; // the remainder (rest) of pixels after a cfacts master split + *sr = ssize - stotal; // the remainder (rest) of pixels after a cfacts stack split +} + +/*** + * Layouts + */ + +/* + * Bottomstack layout + gaps + * https://dwm.suckless.org/patches/bottomstack/ + */ +static void +bstack(Monitor *m) +{ + unsigned int i, n; + int oh, ov, ih, iv; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh; + mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); + sw = m->ww - 2*ov - iv * (n - m->nmaster - 1); + + if (m->nmaster && n > m->nmaster) { + sh = (mh - ih) * (1 - m->mfact); + mh = mh - ih - sh; + sx = mx; + sy = my + mh + ih; + } + + getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i < m->nmaster) { + resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + mx += WIDTH(c) + iv; + } else { + resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + sx += WIDTH(c) + iv; + } + } +} + +static void +bstackhoriz(Monitor *m) +{ + unsigned int i, n; + int oh, ov, ih, iv; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + mh = m->wh - 2*oh; + sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); + mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1); + sw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sh = (mh - ih) * (1 - m->mfact); + mh = mh - ih - sh; + sy = my + mh + ih; + sh = m->wh - mh - 2*oh - ih * (n - m->nmaster); + } + + getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (i < m->nmaster) { + resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + mx += WIDTH(c) + iv; + } else { + resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + sy += HEIGHT(c) + ih; + } + } +} + +/* + * Centred master layout + gaps + * https://dwm.suckless.org/patches/centeredmaster/ + */ +void +centeredmaster(Monitor *m) +{ + unsigned int i, n; + int oh, ov, ih, iv; + int mx = 0, my = 0, mh = 0, mw = 0; + int lx = 0, ly = 0, lw = 0, lh = 0; + int rx = 0, ry = 0, rw = 0, rh = 0; + float mfacts = 0, lfacts = 0, rfacts = 0; + int mtotal = 0, ltotal = 0, rtotal = 0; + int mrest = 0, lrest = 0, rrest = 0; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + /* initialize areas */ + mx = m->wx + ov; + my = m->wy + oh; + mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1); + mw = m->ww - 2*ov; + lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1); + rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1)); + + if (m->nmaster && n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + if (n - m->nmaster > 1) { + /* ||<-S->|<---M--->|<-S->|| */ + mw = (m->ww - 2*ov - 2*iv) * m->mfact; + lw = (m->ww - mw - 2*ov - 2*iv) / 2; + rw = (m->ww - mw - 2*ov - 2*iv) - lw; + mx += lw + iv; + } else { + /* ||<---M--->|<-S->|| */ + mw = (mw - iv) * m->mfact; + lw = 0; + rw = m->ww - mw - iv - 2*ov; + } + lx = m->wx + ov; + ly = m->wy + oh; + rx = mx + mw + iv; + ry = m->wy + oh; + } + + /* calculate facts */ + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) { + if (!m->nmaster || n < m->nmaster) + mfacts += c->cfact; + else if ((n - m->nmaster) % 2) + lfacts += c->cfact; // total factor of left hand stack area + else + rfacts += c->cfact; // total factor of right hand stack area + } + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) + if (!m->nmaster || n < m->nmaster) + mtotal += mh * (c->cfact / mfacts); + else if ((n - m->nmaster) % 2) + ltotal += lh * (c->cfact / lfacts); + else + rtotal += rh * (c->cfact / rfacts); + + mrest = mh - mtotal; + lrest = lh - ltotal; + rrest = rh - rtotal; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + if (!m->nmaster || i < m->nmaster) { + /* nmaster clients are stacked vertically, in the center of the screen */ + resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + my += HEIGHT(c) + ih; + } else { + /* stack clients are stacked vertically */ + if ((i - m->nmaster) % 2 ) { + resize(c, lx, ly, lw - (2*c->bw), lh * (c->cfact / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0); + ly += HEIGHT(c) + ih; + } else { + resize(c, rx, ry, rw - (2*c->bw), rh * (c->cfact / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0); + ry += HEIGHT(c) + ih; + } + } + } +} + +void +centeredfloatingmaster(Monitor *m) +{ + unsigned int i, n; + float mfacts, sfacts; + float mivf = 1.0; // master inner vertical gap factor + int oh, ov, ih, iv, mrest, srest; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh; + mw = m->ww - 2*ov - iv*(n - 1); + sw = m->ww - 2*ov - iv*(n - m->nmaster - 1); + + if (m->nmaster && n > m->nmaster) { + mivf = 0.8; + /* go mfact box in the center if more than nmaster clients */ + if (m->ww > m->wh) { + mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1); + mh = m->wh * 0.9; + } else { + mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1); + mh = m->wh * m->mfact; + } + mx = m->wx + (m->ww - mw) / 2; + my = m->wy + (m->wh - mh - 2*oh) / 2; + + sx = m->wx + ov; + sy = m->wy + oh; + sh = m->wh - 2*oh; + } + + getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + /* nmaster clients are stacked horizontally, in the center of the screen */ + resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + mx += WIDTH(c) + iv*mivf; + } else { + /* stack clients are stacked horizontally */ + resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + sx += WIDTH(c) + iv; + } +} + +/* + * Deck layout + gaps + * https://dwm.suckless.org/patches/deck/ + */ +void +deck(Monitor *m) +{ + unsigned int i, n; + int oh, ov, ih, iv; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); + sw = mw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sw = (mw - iv) * (1 - m->mfact); + mw = mw - iv - sw; + sx = mx + mw + iv; + sh = m->wh - 2*oh; + } + + getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); + + if (n - m->nmaster > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + my += HEIGHT(c) + ih; + } else { + resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0); + } +} + +/* + * Fibonacci layout + gaps + * https://dwm.suckless.org/patches/fibonacci/ + */ +void +fibonacci(Monitor *m, int s) +{ + unsigned int i, n; + int nx, ny, nw, nh; + int oh, ov, ih, iv; + int nv, hrest = 0, wrest = 0, r = 1; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + nx = m->wx + ov; + ny = m->wy + oh; + nw = m->ww - 2*ov; + nh = m->wh - 2*oh; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) { + if (r) { + if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw)) + || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) { + r = 0; + } + if (r && i < n - 1) { + if (i % 2) { + nv = (nh - ih) / 2; + hrest = nh - 2*nv - ih; + nh = nv; + } else { + nv = (nw - iv) / 2; + wrest = nw - 2*nv - iv; + nw = nv; + } + + if ((i % 4) == 2 && !s) + nx += nw + iv; + else if ((i % 4) == 3 && !s) + ny += nh + ih; + } + + if ((i % 4) == 0) { + if (s) { + ny += nh + ih; + nh += hrest; + } + else { + nh -= hrest; + ny -= nh + ih; + } + } + else if ((i % 4) == 1) { + nx += nw + iv; + nw += wrest; + } + else if ((i % 4) == 2) { + ny += nh + ih; + nh += hrest; + if (i < n - 1) + nw += wrest; + } + else if ((i % 4) == 3) { + if (s) { + nx += nw + iv; + nw -= wrest; + } else { + nw -= wrest; + nx -= nw + iv; + nh += hrest; + } + } + if (i == 0) { + if (n != 1) { + nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact); + wrest = 0; + } + ny = m->wy + oh; + } + else if (i == 1) + nw = m->ww - nw - iv - 2*ov; + i++; + } + + resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False); + } +} + +void +dwindle(Monitor *m) +{ + fibonacci(m, 1); +} + +void +spiral(Monitor *m) +{ + fibonacci(m, 0); +} + +/* + * Gappless grid layout + gaps (ironically) + * https://dwm.suckless.org/patches/gaplessgrid/ + */ +void +gaplessgrid(Monitor *m) +{ + unsigned int i, n; + int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters + int oh, ov, ih, iv; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + /* grid dimensions */ + for (cols = 0; cols <= n/2; cols++) + if (cols*cols >= n) + break; + if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ + cols = 2; + rows = n/cols; + cn = rn = 0; // reset column no, row no, client count + + ch = (m->wh - 2*oh - ih * (rows - 1)) / rows; + cw = (m->ww - 2*ov - iv * (cols - 1)) / cols; + rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; + crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols; + x = m->wx + ov; + y = m->wy + oh; + + for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) { + if (i/rows + 1 > cols - n%cols) { + rows = n/cols + 1; + ch = (m->wh - 2*oh - ih * (rows - 1)) / rows; + rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; + } + resize(c, + x, + y + rn*(ch + ih) + MIN(rn, rrest), + cw + (cn < crest ? 1 : 0) - 2*c->bw, + ch + (rn < rrest ? 1 : 0) - 2*c->bw, + 0); + rn++; + if (rn >= rows) { + rn = 0; + x += cw + ih + (cn < crest ? 1 : 0); + cn++; + } + } +} + +/* + * Gridmode layout + gaps + * https://dwm.suckless.org/patches/gridmode/ + */ +void +grid(Monitor *m) +{ + unsigned int i, n; + int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows; + int oh, ov, ih, iv; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + + /* grid dimensions */ + for (rows = 0; rows <= n/2; rows++) + if (rows*rows >= n) + break; + cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; + + /* window geoms (cell height/width) */ + ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1); + cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1); + chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows; + cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols; + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) { + cc = i / rows; + cr = i % rows; + cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest); + cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest); + resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False); + } +} + +/* + * Horizontal grid layout + gaps + * https://dwm.suckless.org/patches/horizgrid/ + */ +void +horizgrid(Monitor *m) { + Client *c; + unsigned int n, i; + int oh, ov, ih, iv; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + int ntop, nbottom = 1; + float mfacts = 0, sfacts = 0; + int mrest, srest, mtotal = 0, stotal = 0; + + /* Count windows */ + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + if (n <= 2) + ntop = n; + else { + ntop = n / 2; + nbottom = n - ntop; + } + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + sh = mh = m->wh - 2*oh; + sw = mw = m->ww - 2*ov; + + if (n > ntop) { + sh = (mh - ih) / 2; + mh = mh - ih - sh; + sy = my + mh + ih; + mw = m->ww - 2*ov - iv * (ntop - 1); + sw = m->ww - 2*ov - iv * (nbottom - 1); + } + + /* calculate facts */ + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < ntop) + mfacts += c->cfact; + else + sfacts += c->cfact; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < ntop) + mtotal += mh * (c->cfact / mfacts); + else + stotal += sw * (c->cfact / sfacts); + + mrest = mh - mtotal; + srest = sw - stotal; + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < ntop) { + resize(c, mx, my, mw * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0); + mx += WIDTH(c) + iv; + } else { + resize(c, sx, sy, sw * (c->cfact / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0); + sx += WIDTH(c) + iv; + } +} + +/* + * nrowgrid layout + gaps + * https://dwm.suckless.org/patches/nrowgrid/ + */ +void +nrowgrid(Monitor *m) +{ + unsigned int n; + int ri = 0, ci = 0; /* counters */ + int oh, ov, ih, iv; /* vanitygap settings */ + unsigned int cx, cy, cw, ch; /* client geometry */ + unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */ + unsigned int cols, rows = m->nmaster + 1; + Client *c; + + /* count clients */ + getgaps(m, &oh, &ov, &ih, &iv, &n); + + /* nothing to do here */ + if (n == 0) + return; + + /* force 2 clients to always split vertically */ + if (FORCE_VSPLIT && n == 2) + rows = 1; + + /* never allow empty rows */ + if (n < rows) + rows = n; + + /* define first row */ + cols = n / rows; + uc = cols; + cy = m->wy + oh; + ch = (m->wh - 2*oh - ih*(rows - 1)) / rows; + uh = ch; + + for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) { + if (ci == cols) { + uw = 0; + ci = 0; + ri++; + + /* next row */ + cols = (n - uc) / (rows - ri); + uc += cols; + cy = m->wy + oh + uh + ih; + uh += ch + ih; + } + + cx = m->wx + ov + uw; + cw = (m->ww - 2*ov - uw) / (cols - ci); + uw += cw + iv; + + resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0); + } +} + +/* + * Default tile layout + gaps + */ +static void +tile(Monitor *m) +{ + unsigned int i, n; + int oh, ov, ih, iv; + int mx = 0, my = 0, mh = 0, mw = 0; + int sx = 0, sy = 0, sh = 0, sw = 0; + float mfacts, sfacts; + int mrest, srest; + Client *c; + + getgaps(m, &oh, &ov, &ih, &iv, &n); + if (n == 0) + return; + + sx = mx = m->wx + ov; + sy = my = m->wy + oh; + mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1); + sh = m->wh - 2*oh - ih * (n - m->nmaster - 1); + sw = mw = m->ww - 2*ov; + + if (m->nmaster && n > m->nmaster) { + sw = (mw - iv) * (1 - m->mfact); + mw = mw - iv - sw; + sx = mx + mw + iv; + } + + getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest); + + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + resize(c, mx, my, mw - (2*c->bw), mh * (c->cfact / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0); + my += HEIGHT(c) + ih; + } else { + resize(c, sx, sy, sw - (2*c->bw), sh * (c->cfact / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0); + sy += HEIGHT(c) + ih; + } +} \ No newline at end of file