From 8cc69be15608d45f00feb80852a0df5b3f6ea8b8 Mon Sep 17 00:00:00 2001 From: rinri Date: Sun, 31 Jan 2021 16:43:10 +0000 Subject: [PATCH] minor updates --- config.def.h | 37 +- config.def.h.orig | 160 ++ config.def.h.rej | 33 + config.h | 37 +- drw.o | Bin dwm | Bin 78312 -> 78632 bytes dwm-tab-v2b-pertab-56a31dc.diff | 808 ++++++++++ dwm.1 | 33 +- dwm.1.orig | 176 +++ dwm.c | 348 ++++- dwm.c.orig | 2596 +++++++++++++++++++++++++++++++ dwm.c.rej | 233 +++ dwm.o | Bin 69936 -> 74416 bytes util.o | Bin 14 files changed, 4389 insertions(+), 72 deletions(-) create mode 100755 config.def.h.orig create mode 100644 config.def.h.rej mode change 100755 => 100644 drw.o create mode 100644 dwm-tab-v2b-pertab-56a31dc.diff create mode 100755 dwm.1.orig create mode 100755 dwm.c.orig create mode 100644 dwm.c.rej mode change 100755 => 100644 dwm.o mode change 100755 => 100644 util.o diff --git a/config.def.h b/config.def.h index 1d9b5ef..ccefed9 100755 --- a/config.def.h +++ b/config.def.h @@ -7,6 +7,14 @@ static const unsigned int snap = 32; /* snap pixel */ static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ + +/* Display modes of the tab bar: never shown, always shown, shown only in */ +/* monocle mode in presence of several windows. */ +/* Modes after showtab_nmodes are disabled */ +enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; +static const int showtab = showtab_auto; /* Default tab bar show mode */ +static const Bool toptab = False; /* False means bottom tab bar */ + static const char *fonts[] = { "fontawesome:size=15", "DejaVuSansMono Nerd Font Mono:size=13"} ; static const char dmenufont[] = "monospace:size=13"; static const char col_gray1[] = "#222222"; @@ -22,27 +30,30 @@ static const char *colors[][3] = { static const char *const autostart[] = { "sh", "-c", "sh ~/scripts/xinit.sh", NULL, - "dunst", NULL, - "slstatus", NULL, NULL /* terminate */ }; /* tagging */ static const char *tags[] = { "", "", "", "", "", "", "", "", "" }; +/* default layout per tags */ +/* The first element is for all-tag view, following i-th element corresponds to */ +/* tags[i]. Layout is referred using the layouts array index.*/ +static int def_layouts[1 + LENGTH(tags)] = { 0, 0, 0, 0, 0, 0, 2, 0, 2, 2}; + + static const Rule rules[] = { /* xprop(1): * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ - /* class instance title tags mask iscentered isfloating monitor */ - { "Gimp", NULL, NULL, 0, 0, 1, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1 }, - /* class instance title tags mask iscentered isfloating isterminal noswallow monitor */ - { "Gimp", NULL, NULL, 0,0, 1, 0, 0, -1 }, - { "Firefox", NULL, NULL, 1 << 8,0, 0, 0, -1, -1 }, - { "St", NULL, NULL, 0,0, 0, 1, 0, -1 }, - { NULL, NULL, "Event Tester", 0,0, 0, 0, 1, -1 }, /* xev */ + + /* class instance title tags mask iscentered isfloating isterminal noswallow monitor */ + { "Gimp", NULL, NULL, 1 << 7, 0, 1, 0, 0, -1 }, + { "LibreWolf", NULL, NULL, 1 << 0, 0, 0, 0, -1, -1 }, + { "firefox", NULL, NULL, 1 << 0, 0, 0, 0, -1, -1 }, + { "St", NULL, NULL, 0, 0, 0, 1, 0, -1 }, + { NULL, NULL, "Event Tester", 0, 0, 0, 0, 1, -1 }, /* xev */ }; /* layout(s) */ @@ -82,8 +93,8 @@ static Key keys[] = { { 0, XK_Print, spawn, SHCMD("~/scripts/screenshot.sh") }, { 0, XF86XK_PowerOff, spawn, SHCMD("~/scripts/poweroff.sh") }, { 0, XF86XK_AudioMute, spawn, SHCMD("pulsemixer --toggle-mute") }, - { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("pulsemixer --change-volume +1") }, - { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("pulsemixer --change-volume -1") }, + { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("amixer -c 1 sset Master 1+") }, + { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("amixer -c 1 sset Master 1-") }, { 0, XF86XK_AudioPrev, spawn, SHCMD("cmus-remote --prev") }, { 0, XF86XK_AudioNext, spawn, SHCMD("cmus-remote --next") }, { 0, XF86XK_AudioPause, spawn, SHCMD("cmus-remote --pause") }, @@ -104,6 +115,7 @@ static Key keys[] = { { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_w, tabmode, {-1} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_i, incnmaster, {.i = +1 } }, @@ -156,5 +168,6 @@ static Button buttons[] = { { ClkTagBar, 0, Button3, toggleview, {0} }, { ClkTagBar, MODKEY, Button1, tag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + { ClkTabBar, 0, Button1, focuswin, {0} }, }; diff --git a/config.def.h.orig b/config.def.h.orig new file mode 100755 index 0000000..cad0e5c --- /dev/null +++ b/config.def.h.orig @@ -0,0 +1,160 @@ +/* See LICENSE file for copyright and license details. */ + +/* appearance */ +static const unsigned int borderpx = 2; /* border pixel of windows */ +static const unsigned int gappx = 15; +static const unsigned int snap = 32; /* snap pixel */ +static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ +static const int showbar = 1; /* 0 means no bar */ +static const int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = { "fontawesome:size=15", "DejaVuSansMono Nerd Font Mono:size=13"} ; +static const char dmenufont[] = "monospace:size=13"; +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[] = "#41008c"; +static const char *colors[][3] = { + /* fg bg border */ + [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, +}; + +static const char *const autostart[] = { + "sh", "-c", "sh ~/scripts/xinit.sh", NULL, + "dunst", NULL, + "slstatus", NULL, + NULL /* terminate */ +}; + +/* tagging */ +static const char *tags[] = { "", "", "", "", "", "", "", "", "" }; + +static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class + * WM_NAME(STRING) = title + */ + /* class instance title tags mask iscentered isfloating monitor */ + { "Gimp", NULL, NULL, 0, 0, 1, -1 }, + { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1 }, + /* class instance title tags mask iscentered isfloating isterminal noswallow monitor */ + { "Gimp", NULL, NULL, 0,0, 1, 0, 0, -1 }, + { "Firefox", NULL, NULL, 1 << 8,0, 0, 0, -1, -1 }, + { "St", NULL, NULL, 0,0, 0, 1, 0, -1 }, + { NULL, NULL, "Event Tester", 0,0, 0, 0, 1, -1 }, /* xev */ +}; + +/* layout(s) */ +static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +static const int nmaster = 1; /* number of clients in master area */ +static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ + +static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, /* first entry is default */ + { "><>", NULL }, /* no layout function means floating behavior */ + { "[M]", monocle }, + { "|M|", centeredmaster }, + { ">M>", centeredfloatingmaster }, +}; + +/* 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_gray4, NULL }; +static const char *termcmd[] = { "st", NULL }; + +#include + +static Key keys[] = { + /* modifier key function argument */ + { 0, XK_Print, spawn, SHCMD("~/scripts/screenshot.sh") }, + { 0, XF86XK_PowerOff, spawn, SHCMD("~/scripts/poweroff.sh") }, + { 0, XF86XK_AudioMute, spawn, SHCMD("pulsemixer --toggle-mute") }, + { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("amixer -c 1 sset Master 1+") }, + { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("amixer -c 1 sset Master 1-") }, + { 0, XF86XK_AudioPrev, spawn, SHCMD("cmus-remote --prev") }, + { 0, XF86XK_AudioNext, spawn, SHCMD("cmus-remote --next") }, + { 0, XF86XK_AudioPause, spawn, SHCMD("cmus-remote --pause") }, + { 0, XF86XK_AudioPlay, spawn, SHCMD("cmus-remote --pause") }, + { 0, XF86XK_AudioStop, spawn, SHCMD("cmus-remote --stop") }, + { 0, XF86XK_AudioRewind, spawn, SHCMD("cmus-remote --seek -10") }, + { 0, XF86XK_AudioForward, spawn, SHCMD("cmus-remote --seek +10") }, + { 0, XF86XK_MonBrightnessUp, spawn, SHCMD("brightnessctl s +5%")}, + { 0, XF86XK_MonBrightnessDown, spawn, SHCMD("brightnessctl s 5%-")}, + { MODKEY|ShiftMask, XK_space, togglealwaysontop, {0} }, + { MODKEY, XK_w, spawn, SHCMD("firefox") }, + { MODKEY|ShiftMask, XK_l, spawn, SHCMD("slock") }, + { MODKEY|ShiftMask, XK_m, spawn, SHCMD("st ~/scripts/autostart.sh") }, + { MODKEY|ShiftMask, XK_j, spawn, SHCMD("joplin-desktop") }, + { MODKEY|ShiftMask, XK_s, spawn, SHCMD("~/scripts/screenshot.sh 1") }, + { MODKEY|ShiftMask, XK_n, spawn, SHCMD("connman-gtk") }, + { MODKEY|ShiftMask, XK_x, spawn, SHCMD("mixer.sh") }, + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_j, focusstack, {.i = +1 } }, + { MODKEY, XK_k, focusstack, {.i = -1 } }, + { MODKEY, XK_i, incnmaster, {.i = +1 } }, + { MODKEY, XK_d, incnmaster, {.i = -1 } }, + { MODKEY, XK_h, setmfact, {.f = -0.05} }, + { MODKEY, XK_l, setmfact, {.f = +0.05} }, + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_u, setlayout, {.v = &layouts[3]} }, + { MODKEY, XK_o, setlayout, {.v = &layouts[4]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { 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_minus, setgaps, {.i = -5 } }, + { MODKEY, XK_equal, setgaps, {.i = +5 } }, + { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, + TAGKEYS( XK_1, 0) + TAGKEYS( XK_2, 1) + TAGKEYS( XK_3, 2) + TAGKEYS( XK_4, 3) + TAGKEYS( XK_5, 4) + TAGKEYS( XK_6, 5) + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {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, Button2, spawn, {.v = termcmd } }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, + { ClkTagBar, 0, Button1, view, {0} }, + { ClkTagBar, 0, Button3, toggleview, {0} }, + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, +}; + diff --git a/config.def.h.rej b/config.def.h.rej new file mode 100644 index 0000000..7fd8e84 --- /dev/null +++ b/config.def.h.rej @@ -0,0 +1,33 @@ +--- config.def.h ++++ config.def.h +@@ -5,6 +5,14 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ + static const unsigned int snap = 32; /* snap pixel */ + static const int showbar = 1; /* 0 means no bar */ + static const int topbar = 1; /* 0 means bottom bar */ ++ ++/* Display modes of the tab bar: never shown, always shown, shown only in */ ++/* monocle mode in presence of several windows. */ ++/* Modes after showtab_nmodes are disabled */ ++enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; ++static const int showtab = showtab_auto; /* Default tab bar show mode */ ++static const Bool toptab = False; /* False means bottom tab bar */ ++ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +@@ -18,9 +26,15 @@ static const char *colors[SchemeLast][3] = { + [SchemeSel] = { col_gray4, col_cyan, col_cyan }, + }; + ++ + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + ++/* default layout per tags */ ++/* The first element is for all-tag view, following i-th element corresponds to */ ++/* tags[i]. Layout is referred using the layouts array index.*/ ++static int def_layouts[1 + LENGTH(tags)] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++ + static const Rule rules[] = { + /* xprop(1): + * WM_CLASS(STRING) = instance, class diff --git a/config.h b/config.h index 1d9b5ef..ccefed9 100755 --- a/config.h +++ b/config.h @@ -7,6 +7,14 @@ static const unsigned int snap = 32; /* snap pixel */ static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ + +/* Display modes of the tab bar: never shown, always shown, shown only in */ +/* monocle mode in presence of several windows. */ +/* Modes after showtab_nmodes are disabled */ +enum showtab_modes { showtab_never, showtab_auto, showtab_nmodes, showtab_always}; +static const int showtab = showtab_auto; /* Default tab bar show mode */ +static const Bool toptab = False; /* False means bottom tab bar */ + static const char *fonts[] = { "fontawesome:size=15", "DejaVuSansMono Nerd Font Mono:size=13"} ; static const char dmenufont[] = "monospace:size=13"; static const char col_gray1[] = "#222222"; @@ -22,27 +30,30 @@ static const char *colors[][3] = { static const char *const autostart[] = { "sh", "-c", "sh ~/scripts/xinit.sh", NULL, - "dunst", NULL, - "slstatus", NULL, NULL /* terminate */ }; /* tagging */ static const char *tags[] = { "", "", "", "", "", "", "", "", "" }; +/* default layout per tags */ +/* The first element is for all-tag view, following i-th element corresponds to */ +/* tags[i]. Layout is referred using the layouts array index.*/ +static int def_layouts[1 + LENGTH(tags)] = { 0, 0, 0, 0, 0, 0, 2, 0, 2, 2}; + + static const Rule rules[] = { /* xprop(1): * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title */ - /* class instance title tags mask iscentered isfloating monitor */ - { "Gimp", NULL, NULL, 0, 0, 1, -1 }, - { "Firefox", NULL, NULL, 1 << 8, 0, 0, -1 }, - /* class instance title tags mask iscentered isfloating isterminal noswallow monitor */ - { "Gimp", NULL, NULL, 0,0, 1, 0, 0, -1 }, - { "Firefox", NULL, NULL, 1 << 8,0, 0, 0, -1, -1 }, - { "St", NULL, NULL, 0,0, 0, 1, 0, -1 }, - { NULL, NULL, "Event Tester", 0,0, 0, 0, 1, -1 }, /* xev */ + + /* class instance title tags mask iscentered isfloating isterminal noswallow monitor */ + { "Gimp", NULL, NULL, 1 << 7, 0, 1, 0, 0, -1 }, + { "LibreWolf", NULL, NULL, 1 << 0, 0, 0, 0, -1, -1 }, + { "firefox", NULL, NULL, 1 << 0, 0, 0, 0, -1, -1 }, + { "St", NULL, NULL, 0, 0, 0, 1, 0, -1 }, + { NULL, NULL, "Event Tester", 0, 0, 0, 0, 1, -1 }, /* xev */ }; /* layout(s) */ @@ -82,8 +93,8 @@ static Key keys[] = { { 0, XK_Print, spawn, SHCMD("~/scripts/screenshot.sh") }, { 0, XF86XK_PowerOff, spawn, SHCMD("~/scripts/poweroff.sh") }, { 0, XF86XK_AudioMute, spawn, SHCMD("pulsemixer --toggle-mute") }, - { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("pulsemixer --change-volume +1") }, - { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("pulsemixer --change-volume -1") }, + { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("amixer -c 1 sset Master 1+") }, + { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("amixer -c 1 sset Master 1-") }, { 0, XF86XK_AudioPrev, spawn, SHCMD("cmus-remote --prev") }, { 0, XF86XK_AudioNext, spawn, SHCMD("cmus-remote --next") }, { 0, XF86XK_AudioPause, spawn, SHCMD("cmus-remote --pause") }, @@ -104,6 +115,7 @@ static Key keys[] = { { MODKEY, XK_p, spawn, {.v = dmenucmd } }, { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_b, togglebar, {0} }, + { MODKEY, XK_w, tabmode, {-1} }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_i, incnmaster, {.i = +1 } }, @@ -156,5 +168,6 @@ static Button buttons[] = { { ClkTagBar, 0, Button3, toggleview, {0} }, { ClkTagBar, MODKEY, Button1, tag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + { ClkTabBar, 0, Button1, focuswin, {0} }, }; diff --git a/drw.o b/drw.o old mode 100755 new mode 100644 diff --git a/dwm b/dwm index 961042cefa03180c70aec97067011a792ee8515c..78f65e5f8814553299f400b8fd4a154de1df8dd4 100755 GIT binary patch literal 78632 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 31 ? -1 : 1]; }; + +@@ -395,6 +420,8 @@ arrange(Monitor *m) + void + arrangemon(Monitor *m) + { ++ updatebarpos(m); ++ XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); +@@ -444,14 +471,33 @@ buttonpress(XEvent *e) + click = ClkStatusText; + else + click = ClkWinTitle; +- } else if ((c = wintoclient(ev->window))) { ++ } ++ if(ev->window == selmon->tabwin) { ++ i = 0; x = 0; ++ for(c = selmon->clients; c; c = c->next){ ++ if(!ISVISIBLE(c)) continue; ++ x += selmon->tab_widths[i]; ++ if (ev->x > x) ++ ++i; ++ else ++ break; ++ if(i >= m->ntabs) break; ++ } ++ if(c) { ++ click = ClkTabBar; ++ arg.ui = i; ++ } ++ } ++ else if((c = wintoclient(ev->window))) { + focus(c); + click = ClkClientWin; + } +- for (i = 0; i < LENGTH(buttons); i++) +- if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button +- && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) +- buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); ++ for(i = 0; i < LENGTH(buttons); i++) ++ if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button ++ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ ++ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) ++ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); ++ } + } + + void +@@ -476,8 +522,8 @@ cleanup(void) + view(&a); + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) +- while (m->stack) +- unmanage(m->stack, 0); ++ while(m->stack) ++ unmanage(m->stack, False); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); +@@ -504,6 +550,8 @@ cleanupmon(Monitor *mon) + } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); ++ XUnmapWindow(dpy, mon->tabwin); ++ XDestroyWindow(dpy, mon->tabwin); + free(mon); + } + +@@ -525,6 +573,7 @@ clientmessage(XEvent *e) + { + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); ++ int i; + + if (!c) + return; +@@ -536,6 +585,8 @@ clientmessage(XEvent *e) + if (!ISVISIBLE(c)) { + c->mon->seltags ^= 1; + c->mon->tagset[c->mon->seltags] = c->tags; ++ for(i=0; !(c->tags & 1 << i); i++); ++ view(&(Arg){.ui = 1 << i}); + } + pop(c); + } +@@ -564,11 +615,10 @@ void + configurenotify(XEvent *e) + { + Monitor *m; +- Client *c; + XConfigureEvent *ev = &e->xconfigure; + int dirty; + +- /* TODO: updategeom handling sucks, needs to be simplified */ ++ // TODO: updategeom handling sucks, needs to be simplified + if (ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); + sw = ev->width; +@@ -576,10 +626,9 @@ configurenotify(XEvent *e) + if (updategeom() || dirty) { + drw_resize(drw, sw, bh); + updatebars(); +- for (m = mons; m; m = m->next) { +- for (c = m->clients; c; c = c->next) +- if (c->isfullscreen) +- resizeclient(c, m->mx, m->my, m->mw, m->mh); ++ //refreshing display of status bar. The tab bar is handled by the arrange() ++ //method, which is called below ++ for (m = mons; m; m = m->next){ + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + } + focus(NULL); +@@ -644,16 +693,41 @@ Monitor * + createmon(void) + { + Monitor *m; ++ int i; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; ++ m->showtab = showtab; + m->topbar = topbar; +- m->lt[0] = &layouts[0]; ++ m->toptab = toptab; ++ m->ntabs = 0; ++ m->lt[0] = &layouts[def_layouts[1] % LENGTH(layouts)]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); ++ m->pertag->curtag = m->pertag->prevtag = 1; ++ for(i=0; i <= LENGTH(tags); i++) { ++ /* init nmaster */ ++ m->pertag->nmasters[i] = m->nmaster; ++ ++ /* init mfacts */ ++ m->pertag->mfacts[i] = m->mfact; ++ ++ /* init layouts */ ++ m->pertag->ltidxs[i][0] = &layouts[def_layouts[i % LENGTH(def_layouts)] % LENGTH(layouts)]; ++ m->pertag->ltidxs[i][1] = m->lt[1]; ++ m->pertag->sellts[i] = m->sellt; ++ ++ /* init showbar */ ++ m->pertag->showbars[i] = m->showbar; ++ ++ /* swap focus and zoomswap*/ ++ m->pertag->prevzooms[i] = NULL; ++ } + return m; + } + +@@ -765,6 +839,104 @@ drawbars(void) + } + + void ++drawtabs(void) { ++ Monitor *m; ++ ++ for(m = mons; m; m = m->next) ++ drawtab(m); ++} ++ ++static int ++cmpint(const void *p1, const void *p2) { ++ /* The actual arguments to this function are "pointers to ++ pointers to char", but strcmp(3) arguments are "pointers ++ to char", hence the following cast plus dereference */ ++ return *((int*) p1) > * (int*) p2; ++} ++ ++ ++void ++drawtab(Monitor *m) { ++ Client *c; ++ int i; ++ int itag = -1; ++ char view_info[50]; ++ int view_info_w = 0; ++ int sorted_label_widths[MAXTABS]; ++ int tot_width; ++ int maxsize = bh; ++ int x = 0; ++ int w = 0; ++ ++ //view_info: indicate the tag which is displayed in the view ++ for(i = 0; i < LENGTH(tags); ++i){ ++ if((selmon->tagset[selmon->seltags] >> i) & 1) { ++ if(itag >=0){ //more than one tag selected ++ itag = -1; ++ break; ++ } ++ itag = i; ++ } ++ } ++ if(0 <= itag && itag < LENGTH(tags)){ ++ snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); ++ } else { ++ strncpy(view_info, "[...]", sizeof view_info); ++ } ++ view_info[sizeof(view_info) - 1 ] = 0; ++ view_info_w = TEXTW(view_info); ++ tot_width = view_info_w; ++ ++ /* Calculates number of labels and their width */ ++ m->ntabs = 0; ++ for(c = m->clients; c; c = c->next){ ++ if(!ISVISIBLE(c)) continue; ++ m->tab_widths[m->ntabs] = TEXTW(c->name); ++ tot_width += m->tab_widths[m->ntabs]; ++ ++m->ntabs; ++ if(m->ntabs >= MAXTABS) break; ++ } ++ ++ if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated ++ memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); ++ qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); ++ tot_width = view_info_w; ++ for(i = 0; i < m->ntabs; ++i){ ++ if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) ++ break; ++ tot_width += sorted_label_widths[i]; ++ } ++ maxsize = (m->ww - tot_width) / (m->ntabs - i); ++ } else{ ++ maxsize = m->ww; ++ } ++ i = 0; ++ for(c = m->clients; c; c = c->next){ ++ if(!ISVISIBLE(c)) continue; ++ if(i >= m->ntabs) break; ++ if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; ++ w = m->tab_widths[i]; ++ drw_setscheme(drw, (c == m->sel) ? scheme[SchemeSel] : scheme[SchemeNorm]); ++ drw_text(drw, x, 0, w, th, lrpad / 2, c->name, 0); ++ x += w; ++ ++i; ++ } ++ ++ drw_setscheme(drw, scheme[SchemeNorm]); ++ ++ /* cleans interspace between window names and current viewed tag label */ ++ w = m->ww - view_info_w - x; ++ drw_text(drw, x, 0, w, th, lrpad / 2, "", 0); ++ ++ /* view info */ ++ x += w; ++ w = view_info_w; ++ drw_text(drw, x, 0, w, th, lrpad / 2, view_info, 0); ++ ++ drw_map(drw, m->tabwin, 0, 0, m->ww, th); ++} ++ ++void + enternotify(XEvent *e) + { + Client *c; +@@ -789,8 +961,10 @@ 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); ++ drawtab(m); ++ } + } + + void +@@ -817,6 +991,7 @@ focus(Client *c) + } + selmon->sel = c; + drawbars(); ++ drawtabs(); + } + + /* there are some broken focus acquiring clients */ +@@ -870,6 +1045,19 @@ focusstack(const Arg *arg) + } + } + ++void ++focuswin(const Arg* arg){ ++ int iwin = arg->i; ++ Client* c = NULL; ++ for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ ++ if(ISVISIBLE(c)) --iwin; ++ }; ++ if(c) { ++ focus(c); ++ restack(selmon); ++ } ++} ++ + Atom + getatomprop(Client *c, Atom prop) + { +@@ -983,7 +1171,7 @@ grabkeys(void) + void + incnmaster(const Arg *arg) + { +- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); + } + +@@ -1142,7 +1330,7 @@ motionnotify(XEvent *e) + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { +- unfocus(selmon->sel, 1); ++ unfocus(selmon->sel, True); + selmon = m; + focus(NULL); + } +@@ -1162,11 +1350,13 @@ movemouse(const Arg *arg) + return; + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; ++ if(c->isfullscreen) /* no support moving fullscreen windows by mouse */ ++ return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, +- None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) ++ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; +@@ -1253,12 +1443,14 @@ propertynotify(XEvent *e) + case XA_WM_HINTS: + updatewmhints(c); + drawbars(); ++ drawtabs(); + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); ++ drawtab(c->mon); + } + if (ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); +@@ -1320,11 +1512,13 @@ resizemouse(const Arg *arg) + return; + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; ++ if(c->isfullscreen) /* no support resizing fullscreen windows by mouse */ ++ return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, +- None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) ++ None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + do { +@@ -1372,6 +1566,7 @@ restack(Monitor *m) + XWindowChanges wc; + + drawbar(m); ++ drawtab(m); + if (!m->sel) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) +@@ -1480,11 +1675,11 @@ sendevent(Client *c, Atom proto) + void + setfocus(Client *c) + { +- if (!c->neverfocus) { ++ if(!c->neverfocus) { + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], +- XA_WINDOW, 32, PropModeReplace, +- (unsigned char *) &(c->win), 1); ++ XA_WINDOW, 32, PropModeReplace, ++ (unsigned char *) &(c->win), 1); + } + sendevent(c, wmatom[WMTakeFocus]); + } +@@ -1520,10 +1715,13 @@ setfullscreen(Client *c, int fullscreen) + void + setlayout(const Arg *arg) + { +- if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) +- selmon->sellt ^= 1; +- if (arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { ++ selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ } ++ if(arg && arg->v) ++ selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); +@@ -1542,7 +1740,7 @@ setmfact(const Arg *arg) + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.1 || f > 0.9) + return; +- selmon->mfact = f; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; + arrange(selmon); + } + +@@ -1564,6 +1762,7 @@ setup(void) + die("no fonts could be loaded.\n"); + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; ++ th = bh; + updategeom(); + /* init atoms */ + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); +@@ -1631,10 +1830,10 @@ sigchld(int unused) + void + spawn(const Arg *arg) + { +- if (arg->v == dmenucmd) ++ if(arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; +- if (fork() == 0) { +- if (dpy) ++ if(fork() == 0) { ++ if(dpy) + close(ConnectionNumber(dpy)); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); +@@ -1691,18 +1890,29 @@ tile(Monitor *m) + void + togglebar(const Arg *arg) + { +- selmon->showbar = !selmon->showbar; ++ selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); + } + + void ++tabmode(const Arg *arg) ++{ ++ if(arg && arg->i >= 0) ++ selmon->showtab = arg->ui % showtab_nmodes; ++ else ++ selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; ++ arrange(selmon); ++} ++ ++ ++void + togglefloating(const Arg *arg) + { +- if (!selmon->sel) ++ if(!selmon->sel) + return; +- if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ ++ if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; + if (selmon->sel->isfloating) +@@ -1730,9 +1940,29 @@ void + toggleview(const Arg *arg) + { + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); ++ int i; + + if (newtagset) { ++ if(newtagset == ~0) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = 0; ++ } ++ /* test if the user did not select the same tag */ ++ if(!(newtagset & 1 << (selmon->pertag->curtag - 1))) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ for (i=0; !(newtagset & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } + selmon->tagset[selmon->seltags] = newtagset; ++ ++ /* apply settings for this view */ ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); + focus(NULL); + arrange(selmon); + } +@@ -1808,20 +2038,44 @@ updatebars(void) + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); ++ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), ++ CopyFromParent, DefaultVisual(dpy, screen), ++ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); ++ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); ++ XMapRaised(dpy, m->tabwin); + } + } + + void + updatebarpos(Monitor *m) + { ++ Client *c; ++ int nvis = 0; ++ + m->wy = m->my; + m->wh = m->mh; + if (m->showbar) { + m->wh -= bh; + m->by = m->topbar ? m->wy : m->wy + m->wh; +- m->wy = m->topbar ? m->wy + bh : m->wy; +- } else ++ if ( m->topbar ) ++ m->wy += bh; ++ } else { + m->by = -bh; ++ } ++ ++ for(c = m->clients; c; c = c->next){ ++ if(ISVISIBLE(c)) ++nvis; ++ } ++ ++ if(m->showtab == showtab_always ++ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ ++ m->wh -= th; ++ m->ty = m->toptab ? m->wy : m->wy + m->wh; ++ if ( m->toptab ) ++ m->wy += th; ++ } else { ++ m->ty = -th; ++ } + } + + void +@@ -2003,9 +2257,9 @@ updatewindowtype(Client *c) + Atom wtype = getatomprop(c, netatom[NetWMWindowType]); + + if (state == netatom[NetWMFullscreen]) +- setfullscreen(c, 1); ++ setfullscreen(c, True); + if (wtype == netatom[NetWMWindowTypeDialog]) +- c->isfloating = 1; ++ c->isfloating = True; + } + + void +@@ -2030,11 +2284,33 @@ updatewmhints(Client *c) + void + view(const Arg *arg) + { +- if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) ++ int i; ++ unsigned int tmptag; ++ ++ if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ +- if (arg->ui & TAGMASK) ++ if(arg->ui & TAGMASK) { ++ selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; ++ if(arg->ui == ~0) ++ selmon->pertag->curtag = 0; ++ else { ++ for (i=0; !(arg->ui & 1 << i); i++) ; ++ selmon->pertag->curtag = i + 1; ++ } ++ } else { ++ tmptag = selmon->pertag->prevtag; ++ selmon->pertag->prevtag = selmon->pertag->curtag; ++ selmon->pertag->curtag = tmptag; ++ } ++ selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; ++ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; ++ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; ++ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; ++ selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; ++ if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) ++ togglebar(NULL); + focus(NULL); + arrange(selmon); + } +@@ -2062,7 +2338,7 @@ wintomon(Window w) + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) +- if (w == m->barwin) ++ if(w == m->barwin || w == m->tabwin) + return m; + if ((c = wintoclient(w))) + return c->mon; diff --git a/dwm.1 b/dwm.1 index 13b3729..0bcc9b7 100755 --- a/dwm.1 +++ b/dwm.1 @@ -20,14 +20,22 @@ layout applied. Windows are grouped by tags. Each window can be tagged with one or multiple tags. Selecting certain tags displays all windows with these tags. .P -Each screen contains a small status bar which displays all available tags, the -layout, the title of the focused window, and the text read from the root window -name property, if the screen is focused. A floating window is indicated with an -empty square and a maximised floating window is indicated with a filled square -before the windows title. The selected tags are indicated with a different -color. The tags of the focused window are indicated with a filled square in the -top left corner. The tags which are applied to one or more windows are -indicated with an empty square in the top left corner. +Each screen contains two small status bars. +.P +One bar displays all available tags, the layout, the title of the focused +window, and the text read from the root window name property, if the screen is +focused. A floating window is indicated with an empty square and a maximised +floating window is indicated with a filled square before the windows title. The +selected tags are indicated with a different color. The tags of the focused +window are indicated with a filled square in the top left corner. The tags +which are applied to one or more windows are indicated with an empty square in +the top left corner. +.P +Another bar contains a tab for each window of the current view and allows +navigation between windows, especially in the monocle mode. The different +display modes of this bar are described under the Mod1\-w Keybord command +section. When a single tag is selected, that tag is indicated in the left corner +of the tab bar. .P dwm draws a small border around windows to indicate the focus state. .SH OPTIONS @@ -44,7 +52,8 @@ command. .TP .B Button1 click on a tag label to display all windows with that tag, click on the layout -label toggles between tiled and floating layout. +label toggles between tiled and floating layout, click on a window name in the +tab bar brings focus to that window. .TP .B Button3 click on a tag label adds/removes all windows with that tag to/from the view. @@ -110,6 +119,12 @@ Increase master area size. .B Mod1\-h Decrease master area size. .TP +.B Mod1\-w +Cycle over the tab bar display modes: never displayed, always displayed, +displayed only in monocle mode when the view contains than one window (auto +mode). Some display modes can be disabled in the configuration, config.h. In +the default configuration only "never" and "auto" display modes are enabled. +.TP .B Mod1\-Return Zooms/cycles focused window to/from master area (tiled layouts only). .TP diff --git a/dwm.1.orig b/dwm.1.orig new file mode 100755 index 0000000..13b3729 --- /dev/null +++ b/dwm.1.orig @@ -0,0 +1,176 @@ +.TH DWM 1 dwm\-VERSION +.SH NAME +dwm \- dynamic window manager +.SH SYNOPSIS +.B dwm +.RB [ \-v ] +.SH DESCRIPTION +dwm is a dynamic window manager for X. It manages windows in tiled, monocle +and floating layouts. Either layout can be applied dynamically, optimising the +environment for the application in use and the task performed. +.P +In tiled layouts windows are managed in a master and stacking area. The master +area on the left contains one window by default, and the stacking area on the +right contains all other windows. The number of master area windows can be +adjusted from zero to an arbitrary number. In monocle layout all windows are +maximised to the screen size. In floating layout windows can be resized and +moved freely. Dialog windows are always managed floating, regardless of the +layout applied. +.P +Windows are grouped by tags. Each window can be tagged with one or multiple +tags. Selecting certain tags displays all windows with these tags. +.P +Each screen contains a small status bar which displays all available tags, the +layout, the title of the focused window, and the text read from the root window +name property, if the screen is focused. A floating window is indicated with an +empty square and a maximised floating window is indicated with a filled square +before the windows title. The selected tags are indicated with a different +color. The tags of the focused window are indicated with a filled square in the +top left corner. The tags which are applied to one or more windows are +indicated with an empty square in the top left corner. +.P +dwm draws a small border around windows to indicate the focus state. +.SH OPTIONS +.TP +.B \-v +prints version information to standard output, then exits. +.SH USAGE +.SS Status bar +.TP +.B X root window name +is read and displayed in the status text area. It can be set with the +.BR xsetroot (1) +command. +.TP +.B Button1 +click on a tag label to display all windows with that tag, click on the layout +label toggles between tiled and floating layout. +.TP +.B Button3 +click on a tag label adds/removes all windows with that tag to/from the view. +.TP +.B Mod1\-Button1 +click on a tag label applies that tag to the focused window. +.TP +.B Mod1\-Button3 +click on a tag label adds/removes that tag to/from the focused window. +.SS Keyboard commands +.TP +.B Mod1\-Shift\-Return +Start +.BR st(1). +.TP +.B Mod1\-p +Spawn +.BR dmenu(1) +for launching other programs. +.TP +.B Mod1\-, +Focus previous screen, if any. +.TP +.B Mod1\-. +Focus next screen, if any. +.TP +.B Mod1\-Shift\-, +Send focused window to previous screen, if any. +.TP +.B Mod1\-Shift\-. +Send focused window to next screen, if any. +.TP +.B Mod1\-b +Toggles bar on and off. +.TP +.B Mod1\-t +Sets tiled layout. +.TP +.B Mod1\-f +Sets floating layout. +.TP +.B Mod1\-m +Sets monocle layout. +.TP +.B Mod1\-space +Toggles between current and previous layout. +.TP +.B Mod1\-j +Focus next window. +.TP +.B Mod1\-k +Focus previous window. +.TP +.B Mod1\-i +Increase number of windows in master area. +.TP +.B Mod1\-d +Decrease number of windows in master area. +.TP +.B Mod1\-l +Increase master area size. +.TP +.B Mod1\-h +Decrease master area size. +.TP +.B Mod1\-Return +Zooms/cycles focused window to/from master area (tiled layouts only). +.TP +.B Mod1\-Shift\-c +Close focused window. +.TP +.B Mod1\-Shift\-space +Toggle focused window between tiled and floating state. +.TP +.B Mod1\-Tab +Toggles to the previously selected tags. +.TP +.B Mod1\-Shift\-[1..n] +Apply nth tag to focused window. +.TP +.B Mod1\-Shift\-0 +Apply all tags to focused window. +.TP +.B Mod1\-Control\-Shift\-[1..n] +Add/remove nth tag to/from focused window. +.TP +.B Mod1\-[1..n] +View all windows with nth tag. +.TP +.B Mod1\-0 +View all windows with any tag. +.TP +.B Mod1\-Control\-[1..n] +Add/remove all windows with nth tag to/from the view. +.TP +.B Mod1\-Shift\-q +Quit dwm. +.SS Mouse commands +.TP +.B Mod1\-Button1 +Move focused window while dragging. Tiled windows will be toggled to the floating state. +.TP +.B Mod1\-Button2 +Toggles focused window between floating and tiled state. +.TP +.B Mod1\-Button3 +Resize focused window while dragging. Tiled windows will be toggled to the floating state. +.SH CUSTOMIZATION +dwm is customized by creating a custom config.h and (re)compiling the source +code. This keeps it fast, secure and simple. +.SH SEE ALSO +.BR dmenu (1), +.BR st (1) +.SH ISSUES +Java applications which use the XToolkit/XAWT backend may draw grey windows +only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early +JDK 1.6 versions, because it assumes a reparenting window manager. Possible workarounds +are using JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or setting the +environment variable +.BR AWT_TOOLKIT=MToolkit +(to use the older Motif backend instead) or running +.B xprop -root -f _NET_WM_NAME 32a -set _NET_WM_NAME LG3D +or +.B wmname LG3D +(to pretend that a non-reparenting window manager is running that the +XToolkit/XAWT backend can recognize) or when using OpenJDK setting the environment variable +.BR _JAVA_AWT_WM_NONREPARENTING=1 . +.SH BUGS +Send all bug reports with a patch to hackers@suckless.org. diff --git a/dwm.c b/dwm.c index a1f36c3..b698bd1 100755 --- a/dwm.c +++ b/dwm.c @@ -70,7 +70,7 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ -enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, +enum { ClkTagBar, ClkTabBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ typedef union { @@ -119,12 +119,16 @@ typedef struct { void (*arrange)(Monitor *); } Layout; +#define MAXTABS 50 + +typedef struct Pertag Pertag; struct Monitor { char ltsymbol[16]; float mfact; int nmaster; int num; int by; /* bar geometry */ + int ty; /* tab bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ int gappx; /* gaps between windows */ @@ -132,13 +136,19 @@ struct Monitor { unsigned int sellt; unsigned int tagset[2]; int showbar; + int showtab; int topbar; + int toptab; Client *clients; Client *sel; Client *stack; Monitor *next; Window barwin; + Window tabwin; + int ntabs; + int tab_widths[MAXTABS] ; const Layout *lt[2]; + Pertag *pertag; }; typedef struct { @@ -175,12 +185,15 @@ static void detachstack(Client *c); static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); +static void drawtab(Monitor *m); +static void drawtabs(void); static void enternotify(XEvent *e); static void expose(XEvent *e); static void focus(Client *c); static void focusin(XEvent *e); static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); +static void focuswin(const Arg* arg); static int getrootptr(int *x, int *y); static long getstate(Window w); static int gettextprop(Window w, Atom atom, char *text, unsigned int size); @@ -219,6 +232,7 @@ static void seturgent(Client *c, int urg); static void showhide(Client *c); static void sigchld(int unused); static void spawn(const Arg *arg); +static void tabmode(const Arg *arg); static void tag(const Arg *arg); static void tagmon(const Arg *arg); static void tile(Monitor *); @@ -263,6 +277,7 @@ static char stext[256]; static int screen; static int sw, sh; /* X display screen geometry width, height */ static int bh, blw = 0; /* bar geometry */ +static int th = 0; /* tab bar geometry */ static int lrpad; /* sum of left and right padding for text */ static int (*xerrorxlib)(Display *, XErrorEvent *); static unsigned int numlockmask = 0; @@ -296,6 +311,16 @@ static xcb_connection_t *xcon; /* configuration, allows nested code to access above variables */ #include "config.h" +struct Pertag { + unsigned int curtag, prevtag; /* current and previous tag */ + int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ + float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ + unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ + const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ + Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ + Client *prevzooms[LENGTH(tags) + 1]; /* store zoom information */ +}; + /* compile-time check if all tags fit into an unsigned int bit array. */ struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; @@ -451,6 +476,8 @@ arrange(Monitor *m) void arrangemon(Monitor *m) { + updatebarpos(m); + XMoveResizeWindow(dpy, m->tabwin, m->wx, m->ty, m->ww, th); strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); if (m->lt[m->sellt]->arrange) m->lt[m->sellt]->arrange(m); @@ -547,16 +574,35 @@ buttonpress(XEvent *e) click = ClkStatusText; else click = ClkWinTitle; - } else if ((c = wintoclient(ev->window))) { + } + if(ev->window == selmon->tabwin) { + i = 0; x = 0; + for(c = selmon->clients; c; c = c->next){ + if(!ISVISIBLE(c)) continue; + x += selmon->tab_widths[i]; + if (ev->x > x) + ++i; + else + break; + if(i >= m->ntabs) break; + } + if(c) { + click = ClkTabBar; + arg.ui = i; + } + } + else if((c = wintoclient(ev->window))) { focus(c); restack(selmon); XAllowEvents(dpy, ReplayPointer, CurrentTime); click = ClkClientWin; } - for (i = 0; i < LENGTH(buttons); i++) - if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button - && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) - buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); + for(i = 0; i < LENGTH(buttons); i++) + if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ + buttons[i].func(((click == ClkTagBar || click == ClkTabBar) + && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); + } } void @@ -581,8 +627,8 @@ cleanup(void) view(&a); selmon->lt[selmon->sellt] = &foo; for (m = mons; m; m = m->next) - while (m->stack) - unmanage(m->stack, 0); + while(m->stack) + unmanage(m->stack, False); XUngrabKey(dpy, AnyKey, AnyModifier, root); while (mons) cleanupmon(mons); @@ -610,6 +656,8 @@ cleanupmon(Monitor *mon) } XUnmapWindow(dpy, mon->barwin); XDestroyWindow(dpy, mon->barwin); + XUnmapWindow(dpy, mon->tabwin); + XDestroyWindow(dpy, mon->tabwin); free(mon); } @@ -618,6 +666,7 @@ clientmessage(XEvent *e) { XClientMessageEvent *cme = &e->xclient; Client *c = wintoclient(cme->window); + int i; if (!c) return; @@ -655,11 +704,10 @@ void configurenotify(XEvent *e) { Monitor *m; - Client *c; XConfigureEvent *ev = &e->xconfigure; int dirty; - /* TODO: updategeom handling sucks, needs to be simplified */ + // TODO: updategeom handling sucks, needs to be simplified if (ev->window == root) { dirty = (sw != ev->width || sh != ev->height); sw = ev->width; @@ -667,10 +715,9 @@ configurenotify(XEvent *e) if (updategeom() || dirty) { drw_resize(drw, sw, bh); updatebars(); - for (m = mons; m; m = m->next) { - for (c = m->clients; c; c = c->next) - if (c->isfullscreen) - resizeclient(c, m->mx, m->my, m->mw, m->mh); + //refreshing display of status bar. The tab bar is handled by the arrange() + //method, which is called below + for (m = mons; m; m = m->next){ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); } focus(NULL); @@ -735,17 +782,42 @@ Monitor * createmon(void) { Monitor *m; + int i ; m = ecalloc(1, sizeof(Monitor)); m->tagset[0] = m->tagset[1] = 1; m->mfact = mfact; m->nmaster = nmaster; m->showbar = showbar; - m->topbar = topbar; + m->showtab = showtab; + m->topbar = topbar; m->gappx = gappx; - m->lt[0] = &layouts[0]; + m->toptab = toptab; + m->ntabs = 0; + m->lt[0] = &layouts[def_layouts[1] % LENGTH(layouts)]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) + die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); + m->pertag->curtag = m->pertag->prevtag = 1; + for(i=0; i <= LENGTH(tags); i++) { + /* init nmaster */ + m->pertag->nmasters[i] = m->nmaster; + + /* init mfacts */ + m->pertag->mfacts[i] = m->mfact; + + /* init layouts */ + m->pertag->ltidxs[i][0] = &layouts[def_layouts[i % LENGTH(def_layouts)] % LENGTH(layouts)]; + m->pertag->ltidxs[i][1] = m->lt[1]; + m->pertag->sellts[i] = m->sellt; + + /* init showbar */ + m->pertag->showbars[i] = m->showbar; + + /* swap focus and zoomswap*/ + m->pertag->prevzooms[i] = NULL; + } return m; } @@ -862,6 +934,104 @@ drawbars(void) drawbar(m); } +void +drawtabs(void) { + Monitor *m; + + for(m = mons; m; m = m->next) + drawtab(m); +} + +static int +cmpint(const void *p1, const void *p2) { + /* The actual arguments to this function are "pointers to + pointers to char", but strcmp(3) arguments are "pointers + to char", hence the following cast plus dereference */ + return *((int*) p1) > * (int*) p2; +} + + +void +drawtab(Monitor *m) { + Client *c; + int i; + int itag = -1; + char view_info[50]; + int view_info_w = 0; + int sorted_label_widths[MAXTABS]; + int tot_width; + int maxsize = bh; + int x = 0; + int w = 0; + + //view_info: indicate the tag which is displayed in the view + for(i = 0; i < LENGTH(tags); ++i){ + if((selmon->tagset[selmon->seltags] >> i) & 1) { + if(itag >=0){ //more than one tag selected + itag = -1; + break; + } + itag = i; + } + } + if(0 <= itag && itag < LENGTH(tags)){ + snprintf(view_info, sizeof view_info, "[%s]", tags[itag]); + } else { + strncpy(view_info, "[...]", sizeof view_info); + } + view_info[sizeof(view_info) - 1 ] = 0; + view_info_w = TEXTW(view_info); + tot_width = view_info_w; + + /* Calculates number of labels and their width */ + m->ntabs = 0; + for(c = m->clients; c; c = c->next){ + if(!ISVISIBLE(c)) continue; + m->tab_widths[m->ntabs] = TEXTW(c->name); + tot_width += m->tab_widths[m->ntabs]; + ++m->ntabs; + if(m->ntabs >= MAXTABS) break; + } + + if(tot_width > m->ww){ //not enough space to display the labels, they need to be truncated + memcpy(sorted_label_widths, m->tab_widths, sizeof(int) * m->ntabs); + qsort(sorted_label_widths, m->ntabs, sizeof(int), cmpint); + tot_width = view_info_w; + for(i = 0; i < m->ntabs; ++i){ + if(tot_width + (m->ntabs - i) * sorted_label_widths[i] > m->ww) + break; + tot_width += sorted_label_widths[i]; + } + maxsize = (m->ww - tot_width) / (m->ntabs - i); + } else{ + maxsize = m->ww; + } + i = 0; + for(c = m->clients; c; c = c->next){ + if(!ISVISIBLE(c)) continue; + if(i >= m->ntabs) break; + if(m->tab_widths[i] > maxsize) m->tab_widths[i] = maxsize; + w = m->tab_widths[i]; + drw_setscheme(drw, (c == m->sel) ? scheme[SchemeSel] : scheme[SchemeNorm]); + drw_text(drw, x, 0, w, th, lrpad / 2, c->name, 0); + x += w; + ++i; + } + + drw_setscheme(drw, scheme[SchemeNorm]); + + /* cleans interspace between window names and current viewed tag label */ + w = m->ww - view_info_w - x; + drw_text(drw, x, 0, w, th, lrpad / 2, "", 0); + + /* view info */ + x += w; + w = view_info_w; + drw_text(drw, x, 0, w, th, lrpad / 2, view_info, 0); + + drw_map(drw, m->tabwin, 0, 0, m->ww, th); +} + void enternotify(XEvent *e) { @@ -887,8 +1057,10 @@ 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); + drawtab(m); + } } void @@ -914,6 +1086,7 @@ focus(Client *c) } selmon->sel = c; drawbars(); + drawtabs(); } /* there are some broken focus acquiring clients needing extra handling */ @@ -966,6 +1139,19 @@ focusstack(const Arg *arg) } } +void +focuswin(const Arg* arg){ + int iwin = arg->i; + Client* c = NULL; + for(c = selmon->clients; c && (iwin || !ISVISIBLE(c)) ; c = c->next){ + if(ISVISIBLE(c)) --iwin; + }; + if(c) { + focus(c); + restack(selmon); + } +} + Atom getatomprop(Client *c, Atom prop) { @@ -1077,7 +1263,7 @@ grabkeys(void) void incnmaster(const Arg *arg) { - selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0); arrange(selmon); } @@ -1244,7 +1430,7 @@ motionnotify(XEvent *e) if (ev->window != root) return; if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { - unfocus(selmon->sel, 1); + unfocus(selmon->sel, True); selmon = m; focus(NULL); } @@ -1352,12 +1538,14 @@ propertynotify(XEvent *e) case XA_WM_HINTS: updatewmhints(c); drawbars(); + drawtabs(); break; } if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { updatetitle(c); if (c == c->mon->sel) drawbar(c->mon); + drawtab(c->mon); } if (ev->atom == netatom[NetWMWindowType]) updatewindowtype(c); @@ -1481,6 +1669,7 @@ restack(Monitor *m) XWindowChanges wc; drawbar(m); + drawtab(m); if (!m->sel) return; if (m->sel->isfloating || !m->lt[m->sellt]->arrange) @@ -1650,10 +1839,13 @@ setgaps(const Arg *arg) void setlayout(const Arg *arg) { - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; + if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) { + selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + } + if(arg && arg->v) + selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); if (selmon->sel) arrange(selmon); @@ -1672,7 +1864,7 @@ setmfact(const Arg *arg) f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; if (f < 0.1 || f > 0.9) return; - selmon->mfact = f; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; arrange(selmon); } @@ -1696,6 +1888,7 @@ setup(void) die("no fonts could be loaded."); lrpad = drw->fonts->h; bh = drw->fonts->h + 2; + th = bh; updategeom(); /* init atoms */ utf8string = XInternAtom(dpy, "UTF8_STRING", False); @@ -1805,10 +1998,10 @@ sigchld(int unused) void spawn(const Arg *arg) { - if (arg->v == dmenucmd) + if(arg->v == dmenucmd) dmenumon[0] = '0' + selmon->num; - if (fork() == 0) { - if (dpy) + if(fork() == 0) { + if(dpy) close(ConnectionNumber(dpy)); setsid(); execvp(((char **)arg->v)[0], (char **)arg->v); @@ -1865,18 +2058,29 @@ tile(Monitor *m) void togglebar(const Arg *arg) { - selmon->showbar = !selmon->showbar; + selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; updatebarpos(selmon); XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); arrange(selmon); } +void +tabmode(const Arg *arg) +{ + if(arg && arg->i >= 0) + selmon->showtab = arg->ui % showtab_nmodes; + else + selmon->showtab = (selmon->showtab + 1 ) % showtab_nmodes; + arrange(selmon); +} + + void togglefloating(const Arg *arg) { - if (!selmon->sel) + if(!selmon->sel) return; - if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ + if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ return; selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; if (selmon->sel->isfloating) @@ -1930,9 +2134,29 @@ void toggleview(const Arg *arg) { unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + int i; if (newtagset) { + if(newtagset == ~0) { + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = 0; + } + /* test if the user did not select the same tag */ + if(!(newtagset & 1 << (selmon->pertag->curtag - 1))) { + selmon->pertag->prevtag = selmon->pertag->curtag; + for (i=0; !(newtagset & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } selmon->tagset[selmon->seltags] = newtagset; + + /* apply settings for this view */ + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); focus(NULL); arrange(selmon); } @@ -2025,6 +2249,11 @@ updatebars(void) CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); XMapRaised(dpy, m->barwin); + m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->tabwin); XSetClassHint(dpy, m->barwin, &ch); } } @@ -2032,14 +2261,33 @@ updatebars(void) void updatebarpos(Monitor *m) { - m->wy = m->my; + Client *c; + int nvis = 0; + + m->wy = m->my; m->wh = m->mh; if (m->showbar) { m->wh -= bh; m->by = m->topbar ? m->wy : m->wy + m->wh; - m->wy = m->topbar ? m->wy + bh : m->wy; - } else - m->by = -bh; + if ( m->topbar ) + m->wy += bh; + } else { + m->by = -bh; + } + + for(c = m->clients; c; c = c->next){ + if(ISVISIBLE(c)) ++nvis; + } + + if(m->showtab == showtab_always + || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ + m->wh -= th; + m->ty = m->toptab ? m->wy : m->wy + m->wh; + if ( m->toptab ) + m->wy += th; + } else { + m->ty = -th; + } } void @@ -2217,10 +2465,10 @@ updatewindowtype(Client *c) Atom wtype = getatomprop(c, netatom[NetWMWindowType]); if (state == netatom[NetWMFullscreen]) - setfullscreen(c, 1); + setfullscreen(c, True); if (wtype == netatom[NetWMWindowTypeDialog]) { c->iscentered = 1; - c->isfloating = 1; + c->isfloating = True; } } @@ -2246,11 +2494,33 @@ updatewmhints(Client *c) void view(const Arg *arg) { - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + int i; + unsigned int tmptag; + + if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) return; selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) + if(arg->ui & TAGMASK) { + selmon->pertag->prevtag = selmon->pertag->curtag; selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + if(arg->ui == ~0) + selmon->pertag->curtag = 0; + else { + for (i=0; !(arg->ui & 1 << i); i++) ; + selmon->pertag->curtag = i + 1; + } + } else { + tmptag = selmon->pertag->prevtag; + selmon->pertag->prevtag = selmon->pertag->curtag; + selmon->pertag->curtag = tmptag; + } + selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; + selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; + selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; + selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; + selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; + if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag]) + togglebar(NULL); focus(NULL); arrange(selmon); } @@ -2408,7 +2678,7 @@ wintomon(Window w) if (w == root && getrootptr(&x, &y)) return recttomon(x, y, 1, 1); for (m = mons; m; m = m->next) - if (w == m->barwin) + if(w == m->barwin || w == m->tabwin) return m; if ((c = wintoclient(w))) return c->mon; diff --git a/dwm.c.orig b/dwm.c.orig new file mode 100755 index 0000000..a1f36c3 --- /dev/null +++ b/dwm.c.orig @@ -0,0 +1,2596 @@ +/* See LICENSE file for copyright and license details. + * + * dynamic window manager is designed like any other X client as well. It is + * driven through handling X events. In contrast to other X clients, a window + * manager selects for SubstructureRedirectMask on the root window, to receive + * events about window (dis-)appearance. Only one X connection at a time is + * allowed to select for this event mask. + * + * The event handlers of dwm are organized in an array which is accessed + * whenever a new event has been fetched. This allows event dispatching + * in O(1) time. + * + * Each child of the root window is called a client, except windows which have + * set the override_redirect flag. Clients are organized in a linked client + * list on each monitor, the focus history is remembered through a stack list + * on each monitor. Each client contains a bit array to indicate the tags of a + * client. + * + * Keys and tagging rules are organized as arrays and defined in config.h. + * + * To understand everything else, start reading main(). + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XINERAMA +#include +#endif /* XINERAMA */ +#include +#include +#include +#ifdef __OpenBSD__ +#include +#include +#endif /* __OpenBSD */ + +#include "drw.h" +#include "util.h" + +/* macros */ +#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) +#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ + * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) +#define LENGTH(X) (sizeof X / sizeof X[0]) +#define MOUSEMASK (BUTTONMASK|PointerMotionMask) +#define WIDTH(X) ((X)->w + 2 * (X)->bw) +#define HEIGHT(X) ((X)->h + 2 * (X)->bw) +#define TAGMASK ((1 << LENGTH(tags)) - 1) +#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + +/* enums */ +enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +enum { SchemeNorm, SchemeSel }; /* color schemes */ +enum { NetSupported, NetWMName, NetWMState, NetWMCheck, + NetWMFullscreen, NetActiveWindow, NetWMWindowType, + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ +enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, + ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ + +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct { + unsigned int click; + unsigned int mask; + unsigned int button; + void (*func)(const Arg *arg); + const Arg arg; +} Button; + +typedef struct Monitor Monitor; +typedef struct Client Client; +struct Client { + char name[256]; + float mina, maxa; + int x, y, w, h; + int oldx, oldy, oldw, oldh; + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int bw, oldbw; + unsigned int tags; + int isfixed, iscentered, isfloating, isalwaysontop, isurgent, neverfocus, oldstate, isfullscreen, isterminal, noswallow; + pid_t pid; + Client *next; + Client *snext; + Client *swallowing; + Monitor *mon; + Window win; +}; + +typedef struct { + unsigned int mod; + KeySym keysym; + void (*func)(const Arg *); + const Arg arg; +} Key; + +typedef struct { + const char *symbol; + void (*arrange)(Monitor *); +} Layout; + +struct Monitor { + char ltsymbol[16]; + float mfact; + int nmaster; + int num; + int by; /* bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + int gappx; /* gaps between windows */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; + int topbar; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Window barwin; + const Layout *lt[2]; +}; + +typedef struct { + const char *class; + const char *instance; + const char *title; + unsigned int tags; + int iscentered; + int isfloating; + int isterminal; + int noswallow; + int monitor; +} Rule; + +/* function declarations */ +static void applyrules(Client *c); +static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); +static void arrange(Monitor *m); +static void arrangemon(Monitor *m); +static void attach(Client *c); +static void attachstack(Client *c); +static void buttonpress(XEvent *e); +static void checkotherwm(void); +static void cleanup(void); +static void cleanupmon(Monitor *mon); +static void clientmessage(XEvent *e); +static void configure(Client *c); +static void configurenotify(XEvent *e); +static void configurerequest(XEvent *e); +static Monitor *createmon(void); +static void destroynotify(XEvent *e); +static void detach(Client *c); +static void detachstack(Client *c); +static Monitor *dirtomon(int dir); +static void drawbar(Monitor *m); +static void drawbars(void); +static void enternotify(XEvent *e); +static void expose(XEvent *e); +static void focus(Client *c); +static void focusin(XEvent *e); +static void focusmon(const Arg *arg); +static void focusstack(const Arg *arg); +static int getrootptr(int *x, int *y); +static long getstate(Window w); +static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, int focused); +static void grabkeys(void); +static void incnmaster(const Arg *arg); +static void keypress(XEvent *e); +static void killclient(const Arg *arg); +static void manage(Window w, XWindowAttributes *wa); +static void mappingnotify(XEvent *e); +static void maprequest(XEvent *e); +static void monocle(Monitor *m); +static void motionnotify(XEvent *e); +static void movemouse(const Arg *arg); +static Client *nexttiled(Client *c); +static void pop(Client *); +static void propertynotify(XEvent *e); +static void quit(const Arg *arg); +static Monitor *recttomon(int x, int y, int w, int h); +static void resize(Client *c, int x, int y, int w, int h, int interact); +static void resizeclient(Client *c, int x, int y, int w, int h); +static void resizemouse(const Arg *arg); +static void restack(Monitor *m); +static void run(void); +static void scan(void); +static int sendevent(Client *c, Atom proto); +static void sendmon(Client *c, Monitor *m); +static void setclientstate(Client *c, long state); +static void setfocus(Client *c); +static void setfullscreen(Client *c, int fullscreen); +static void setgaps(const Arg *arg); +static void setlayout(const Arg *arg); +static void setmfact(const Arg *arg); +static void setup(void); +static void seturgent(Client *c, int urg); +static void showhide(Client *c); +static void sigchld(int unused); +static void spawn(const Arg *arg); +static void tag(const Arg *arg); +static void tagmon(const Arg *arg); +static void tile(Monitor *); +static void togglebar(const Arg *arg); +static void togglefloating(const Arg *arg); +static void togglealwaysontop(const Arg *arg); +static void toggletag(const Arg *arg); +static void toggleview(const Arg *arg); +static void unfocus(Client *c, int setfocus); +static void unmanage(Client *c, int destroyed); +static void unmapnotify(XEvent *e); +static void updatebarpos(Monitor *m); +static void updatebars(void); +static void updateclientlist(void); +static int updategeom(void); +static void updatenumlockmask(void); +static void updatesizehints(Client *c); +static void updatestatus(void); +static void updatetitle(Client *c); +static void updatewindowtype(Client *c); +static void updatewmhints(Client *c); +static void view(const Arg *arg); +static Client *wintoclient(Window w); +static Monitor *wintomon(Window w); +static int xerror(Display *dpy, XErrorEvent *ee); +static int xerrordummy(Display *dpy, XErrorEvent *ee); +static int xerrorstart(Display *dpy, XErrorEvent *ee); +static void zoom(const Arg *arg); +static void centeredmaster(Monitor *m); +static void centeredfloatingmaster(Monitor *m); +static void autostart_exec(void); + +static pid_t getparentprocess(pid_t p); +static int isdescprocess(pid_t p, pid_t c); +static Client *swallowingclient(Window w); +static Client *termforwin(const Client *c); +static pid_t winpid(Window w); + +/* variables */ +static const char broken[] = "broken"; +static char stext[256]; +static int screen; +static int sw, sh; /* X display screen geometry width, height */ +static int bh, blw = 0; /* bar geometry */ +static int lrpad; /* sum of left and right padding for text */ +static int (*xerrorxlib)(Display *, XErrorEvent *); +static unsigned int numlockmask = 0; +static void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ClientMessage] = clientmessage, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [Expose] = expose, + [FocusIn] = focusin, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [MotionNotify] = motionnotify, + [PropertyNotify] = propertynotify, + [UnmapNotify] = unmapnotify +}; +static Atom wmatom[WMLast], netatom[NetLast]; +static int running = 1; +static Cur *cursor[CurLast]; +static Clr **scheme; +static Display *dpy; +static Drw *drw; +static Monitor *mons, *selmon; +static Window root, wmcheckwin; + +static xcb_connection_t *xcon; + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +/* compile-time check if all tags fit into an unsigned int bit array. */ +struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; + +/* dwm will keep pid's of processes from autostart array and kill them at quit */ +static pid_t *autostart_pids; +static size_t autostart_len; + +/* execute command from autostart array */ +static void +autostart_exec() { + const char *const *p; + size_t i = 0; + + /* count entries */ + for (p = autostart; *p; autostart_len++, p++) + while (*++p); + + autostart_pids = malloc(autostart_len * sizeof(pid_t)); + for (p = autostart; *p; i++, p++) { + if ((autostart_pids[i] = fork()) == 0) { + setsid(); + execvp(*p, (char *const *)p); + fprintf(stderr, "dwm: execvp %s\n", *p); + perror(" failed"); + _exit(EXIT_FAILURE); + } + /* skip arguments */ + while (*++p); + } +} + +/* function implementations */ +void +applyrules(Client *c) +{ + const char *class, *instance; + unsigned int i; + const Rule *r; + Monitor *m; + XClassHint ch = { NULL, NULL }; + + /* rule matching */ + c->iscentered = 0; + c->isfloating = 0; + c->tags = 0; + XGetClassHint(dpy, c->win, &ch); + class = ch.res_class ? ch.res_class : broken; + instance = ch.res_name ? ch.res_name : broken; + + for (i = 0; i < LENGTH(rules); i++) { + r = &rules[i]; + if ((!r->title || strstr(c->name, r->title)) + && (!r->class || strstr(class, r->class)) + && (!r->instance || strstr(instance, r->instance))) + { + c->isterminal = r->isterminal; + c->noswallow = r->noswallow; + c->iscentered = r->iscentered; + c->isfloating = r->isfloating; + c->tags |= r->tags; + for (m = mons; m && m->num != r->monitor; m = m->next); + if (m) + c->mon = m; + } + } + if (ch.res_class) + XFree(ch.res_class); + if (ch.res_name) + XFree(ch.res_name); + c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags]; +} + +int +applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact) +{ + int baseismin; + Monitor *m = c->mon; + + /* set minimum possible */ + *w = MAX(1, *w); + *h = MAX(1, *h); + if (interact) { + if (*x > sw) + *x = sw - WIDTH(c); + if (*y > sh) + *y = sh - HEIGHT(c); + if (*x + *w + 2 * c->bw < 0) + *x = 0; + if (*y + *h + 2 * c->bw < 0) + *y = 0; + } else { + if (*x >= m->wx + m->ww) + *x = m->wx + m->ww - WIDTH(c); + if (*y >= m->wy + m->wh) + *y = m->wy + m->wh - HEIGHT(c); + if (*x + *w + 2 * c->bw <= m->wx) + *x = m->wx; + if (*y + *h + 2 * c->bw <= m->wy) + *y = m->wy; + } + if (*h < bh) + *h = bh; + if (*w < bh) + *w = bh; + if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + /* see last two sentences in ICCCM 4.1.2.3 */ + baseismin = c->basew == c->minw && c->baseh == c->minh; + if (!baseismin) { /* temporarily remove base dimensions */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for aspect limits */ + if (c->mina > 0 && c->maxa > 0) { + if (c->maxa < (float)*w / *h) + *w = *h * c->maxa + 0.5; + else if (c->mina < (float)*h / *w) + *h = *w * c->mina + 0.5; + } + if (baseismin) { /* increment calculation requires this */ + *w -= c->basew; + *h -= c->baseh; + } + /* adjust for increment value */ + if (c->incw) + *w -= *w % c->incw; + if (c->inch) + *h -= *h % c->inch; + /* restore base dimensions */ + *w = MAX(*w + c->basew, c->minw); + *h = MAX(*h + c->baseh, c->minh); + if (c->maxw) + *w = MIN(*w, c->maxw); + if (c->maxh) + *h = MIN(*h, c->maxh); + } + return *x != c->x || *y != c->y || *w != c->w || *h != c->h; +} + +void +arrange(Monitor *m) +{ + if (m) + showhide(m->stack); + else for (m = mons; m; m = m->next) + showhide(m->stack); + if (m) { + arrangemon(m); + restack(m); + } else for (m = mons; m; m = m->next) + arrangemon(m); +} + +void +arrangemon(Monitor *m) +{ + strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol); + if (m->lt[m->sellt]->arrange) + m->lt[m->sellt]->arrange(m); +} + +void +attach(Client *c) +{ + c->next = c->mon->clients; + c->mon->clients = c; +} + +void +attachstack(Client *c) +{ + c->snext = c->mon->stack; + c->mon->stack = c; +} + +void +swallow(Client *p, Client *c) +{ + + if (c->noswallow || c->isterminal) + return; + if (c->noswallow && !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; + updatetitle(p); + XMoveResizeWindow(dpy, p->win, p->x, p->y, p->w, p->h); + arrange(p->mon); + configure(p); + updateclientlist(); +} + +void +unswallow(Client *c) +{ + c->win = c->swallowing->win; + + free(c->swallowing); + c->swallowing = NULL; + + /* 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) +{ + unsigned int i, x, click; + Arg arg = {0}; + Client *c; + Monitor *m; + XButtonPressedEvent *ev = &e->xbutton; + + click = ClkRootWin; + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + if (ev->window == selmon->barwin) { + i = x = 0; + do + x += TEXTW(tags[i]); + while (ev->x >= x && ++i < LENGTH(tags)); + if (i < LENGTH(tags)) { + click = ClkTagBar; + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; + else if (ev->x > selmon->ww - TEXTW(stext)) + click = ClkStatusText; + else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); + click = ClkClientWin; + } + for (i = 0; i < LENGTH(buttons); i++) + if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button + && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) + buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); +} + +void +checkotherwm(void) +{ + xerrorxlib = XSetErrorHandler(xerrorstart); + /* this causes an error if some other window manager is running */ + XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask); + XSync(dpy, False); + XSetErrorHandler(xerror); + XSync(dpy, False); +} + +void +cleanup(void) +{ + Arg a = {.ui = ~0}; + Layout foo = { "", NULL }; + Monitor *m; + size_t i; + + view(&a); + selmon->lt[selmon->sellt] = &foo; + for (m = mons; m; m = m->next) + while (m->stack) + unmanage(m->stack, 0); + XUngrabKey(dpy, AnyKey, AnyModifier, root); + while (mons) + cleanupmon(mons); + for (i = 0; i < CurLast; i++) + drw_cur_free(drw, cursor[i]); + for (i = 0; i < LENGTH(colors); i++) + free(scheme[i]); + XDestroyWindow(dpy, wmcheckwin); + drw_free(drw); + XSync(dpy, False); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); +} + +void +cleanupmon(Monitor *mon) +{ + Monitor *m; + + if (mon == mons) + mons = mons->next; + else { + for (m = mons; m && m->next != mon; m = m->next); + m->next = mon->next; + } + XUnmapWindow(dpy, mon->barwin); + XDestroyWindow(dpy, mon->barwin); + free(mon); +} + +void +clientmessage(XEvent *e) +{ + XClientMessageEvent *cme = &e->xclient; + Client *c = wintoclient(cme->window); + + if (!c) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) + setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); + } +} + +void +configure(Client *c) +{ + XConfigureEvent ce; + + ce.type = ConfigureNotify; + ce.display = dpy; + ce.event = c->win; + ce.window = c->win; + ce.x = c->x; + ce.y = c->y; + ce.width = c->w; + ce.height = c->h; + ce.border_width = c->bw; + ce.above = None; + ce.override_redirect = False; + XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce); +} + +void +configurenotify(XEvent *e) +{ + Monitor *m; + Client *c; + XConfigureEvent *ev = &e->xconfigure; + int dirty; + + /* TODO: updategeom handling sucks, needs to be simplified */ + if (ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); + sw = ev->width; + sh = ev->height; + if (updategeom() || dirty) { + drw_resize(drw, sw, bh); + updatebars(); + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) + if (c->isfullscreen) + resizeclient(c, m->mx, m->my, m->mw, m->mh); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + } + focus(NULL); + arrange(NULL); + } + } +} + +void +configurerequest(XEvent *e) +{ + Client *c; + Monitor *m; + XConfigureRequestEvent *ev = &e->xconfigurerequest; + XWindowChanges wc; + + if ((c = wintoclient(ev->window))) { + if (ev->value_mask & CWBorderWidth) + c->bw = ev->border_width; + else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) { + m = c->mon; + if (ev->value_mask & CWX) { + c->oldx = c->x; + c->x = m->mx + ev->x; + } + if (ev->value_mask & CWY) { + c->oldy = c->y; + c->y = m->my + ev->y; + } + if (ev->value_mask & CWWidth) { + c->oldw = c->w; + c->w = ev->width; + } + if (ev->value_mask & CWHeight) { + c->oldh = c->h; + c->h = ev->height; + } + if ((c->x + c->w) > m->mx + m->mw && c->isfloating) + c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */ + if ((c->y + c->h) > m->my + m->mh && c->isfloating) + c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */ + if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) + configure(c); + if (ISVISIBLE(c)) + XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); + } else + configure(c); + } else { + wc.x = ev->x; + wc.y = ev->y; + wc.width = ev->width; + wc.height = ev->height; + wc.border_width = ev->border_width; + wc.sibling = ev->above; + wc.stack_mode = ev->detail; + XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); + } + XSync(dpy, False); +} + +Monitor * +createmon(void) +{ + Monitor *m; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; + m->topbar = topbar; + m->gappx = gappx; + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); + return m; +} + +void +destroynotify(XEvent *e) +{ + Client *c; + XDestroyWindowEvent *ev = &e->xdestroywindow; + + if ((c = wintoclient(ev->window))) + unmanage(c, 1); + + else if ((c = swallowingclient(ev->window))) + unmanage(c->swallowing, 1); +} + +void +detach(Client *c) +{ + Client **tc; + + for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); + *tc = c->next; +} + +void +detachstack(Client *c) +{ + Client **tc, *t; + + for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext); + *tc = c->snext; + + if (c == c->mon->sel) { + for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); + c->mon->sel = t; + } +} + +Monitor * +dirtomon(int dir) +{ + Monitor *m = NULL; + + if (dir > 0) { + if (!(m = selmon->next)) + m = mons; + } else if (selmon == mons) + for (m = mons; m->next; m = m->next); + else + for (m = mons; m->next != selmon; m = m->next); + return m; +} + +void +drawbar(Monitor *m) +{ + int x, w, sw = 0; + int boxs = drw->fonts->h / 9; + int boxw = drw->fonts->h / 6 + 2; + unsigned int i, occ = 0, urg = 0; + Client *c; + + /* draw status first so it can be overdrawn by tags later */ + if (m == selmon) { /* status is only drawn on selected monitor */ + drw_setscheme(drw, scheme[SchemeNorm]); + sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */ + drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0); + } + + for (c = m->clients; c; c = c->next) { + occ |= c->tags; + if (c->isurgent) + urg |= c->tags; + } + x = 0; + for (i = 0; i < LENGTH(tags); i++) { + w = TEXTW(tags[i]); + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) + drw_rect(drw, x + boxs, boxs, boxw, boxw, + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); + x += w; + } + w = blw = TEXTW(m->ltsymbol); + drw_setscheme(drw, scheme[SchemeNorm]); + x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); + + if ((w = m->ww - sw - x) > bh) { + if (m->sel) { + drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0); + if (m->sel->isfloating) { + drw_rect(drw, x + boxs, boxs, boxw, boxw, m->sel->isfixed, 0); + if (m->sel->isalwaysontop) + drw_rect(drw, x + boxs, bh - boxw, boxw, boxw, 0, 0); + } + } else { + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, x, 0, w, bh, 1, 1); + } + } + drw_map(drw, m->barwin, 0, 0, m->ww, bh); +} + +void +drawbars(void) +{ + Monitor *m; + + for (m = mons; m; m = m->next) + drawbar(m); +} + +void +enternotify(XEvent *e) +{ + Client *c; + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) + return; + c = wintoclient(ev->window); + m = c ? c->mon : wintomon(ev->window); + if (m != selmon) { + unfocus(selmon->sel, 1); + selmon = m; + } else if (!c || c == selmon->sel) + return; + focus(c); +} + +void +expose(XEvent *e) +{ + Monitor *m; + XExposeEvent *ev = &e->xexpose; + + if (ev->count == 0 && (m = wintomon(ev->window))) + drawbar(m); +} + +void +focus(Client *c) +{ + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + if (selmon->sel && selmon->sel != c) + unfocus(selmon->sel, 0); + if (c) { + if (c->mon != selmon) + selmon = c->mon; + if (c->isurgent) + seturgent(c, 0); + detachstack(c); + attachstack(c); + grabbuttons(c, 1); + XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel); + setfocus(c); + } else { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } + selmon->sel = c; + drawbars(); +} + +/* there are some broken focus acquiring clients needing extra handling */ +void +focusin(XEvent *e) +{ + XFocusChangeEvent *ev = &e->xfocus; + + if (selmon->sel && ev->window != selmon->sel->win) + setfocus(selmon->sel); +} + +void +focusmon(const Arg *arg) +{ + Monitor *m; + + if (!mons->next) + return; + if ((m = dirtomon(arg->i)) == selmon) + return; + unfocus(selmon->sel, 0); + selmon = m; + focus(NULL); +} + +void +focusstack(const Arg *arg) +{ + Client *c = NULL, *i; + + if (!selmon->sel) + return; + if (arg->i > 0) { + for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + if (!c) + for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + } else { + for (i = selmon->clients; i != selmon->sel; i = i->next) + if (ISVISIBLE(i)) + c = i; + if (!c) + for (; i; i = i->next) + if (ISVISIBLE(i)) + c = i; + } + if (c) { + focus(c); + restack(selmon); + } +} + +Atom +getatomprop(Client *c, Atom prop) +{ + int di; + unsigned long dl; + unsigned char *p = NULL; + Atom da, atom = None; + + if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, + &da, &di, &dl, &dl, &p) == Success && p) { + atom = *(Atom *)p; + XFree(p); + } + return atom; +} + +int +getrootptr(int *x, int *y) +{ + int di; + unsigned int dui; + Window dummy; + + return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); +} + +long +getstate(Window w) +{ + int format; + long result = -1; + unsigned char *p = NULL; + unsigned long n, extra; + Atom real; + + if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], + &real, &format, &n, &extra, (unsigned char **)&p) != Success) + return -1; + if (n != 0) + result = *p; + XFree(p); + return result; +} + +int +gettextprop(Window w, Atom atom, char *text, unsigned int size) +{ + char **list = NULL; + int n; + XTextProperty name; + + if (!text || size == 0) + return 0; + text[0] = '\0'; + if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems) + return 0; + if (name.encoding == XA_STRING) + strncpy(text, (char *)name.value, size - 1); + else { + if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) { + strncpy(text, *list, size - 1); + XFreeStringList(list); + } + } + text[size - 1] = '\0'; + XFree(name.value); + return 1; +} + +void +grabbuttons(Client *c, int focused) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + if (!focused) + XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabButton(dpy, buttons[i].button, + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); + } +} + +void +grabkeys(void) +{ + updatenumlockmask(); + { + unsigned int i, j; + unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; + KeyCode code; + + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for (i = 0; i < LENGTH(keys); i++) + if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, + True, GrabModeAsync, GrabModeAsync); + } +} + +void +incnmaster(const Arg *arg) +{ + selmon->nmaster = MAX(selmon->nmaster + arg->i, 0); + arrange(selmon); +} + +#ifdef XINERAMA +static int +isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) +{ + while (n--) + if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org + && unique[n].width == info->width && unique[n].height == info->height) + return 0; + return 1; +} +#endif /* XINERAMA */ + +void +keypress(XEvent *e) +{ + unsigned int i; + KeySym keysym; + XKeyEvent *ev; + + ev = &e->xkey; + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + for (i = 0; i < LENGTH(keys); i++) + if (keysym == keys[i].keysym + && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) + && keys[i].func) + keys[i].func(&(keys[i].arg)); +} + +void +killclient(const Arg *arg) +{ + if (!selmon->sel) + return; + if (!sendevent(selmon->sel, wmatom[WMDelete])) { + XGrabServer(dpy); + XSetErrorHandler(xerrordummy); + XSetCloseDownMode(dpy, DestroyAll); + XKillClient(dpy, selmon->sel->win); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } +} + +void +manage(Window w, XWindowAttributes *wa) +{ + Client *c, *t = NULL, *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; + + updatetitle(c); + if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) { + c->mon = t->mon; + c->tags = t->tags; + } else { + c->mon = selmon; + applyrules(c); + term = termforwin(c); + } + + if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw) + c->x = c->mon->mx + c->mon->mw - WIDTH(c); + if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh) + c->y = c->mon->my + c->mon->mh - HEIGHT(c); + c->x = MAX(c->x, c->mon->mx); + /* only fix client y-offset, if the client center might cover the bar */ + c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + c->bw = borderpx; + + wc.border_width = c->bw; + XConfigureWindow(dpy, w, CWBorderWidth, &wc); + XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel); + configure(c); /* propagates border_width, if size doesn't change */ + updatewindowtype(c); + updatesizehints(c); + updatewmhints(c); + if (c->iscentered) { + c->x = c->mon->mx + (c->mon->mw - WIDTH(c)) / 2; + c->y = c->mon->my + (c->mon->mh - HEIGHT(c)) / 2; + } + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); + grabbuttons(c, 0); + if (!c->isfloating) + c->isfloating = c->oldstate = trans != None || c->isfixed; + if (c->isfloating) + XRaiseWindow(dpy, c->win); + attach(c); + attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + setclientstate(c, NormalState); + if (c->mon == selmon) + unfocus(selmon->sel, 0); + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); + if (term) + swallow(term, c); + focus(NULL); +} + +void +mappingnotify(XEvent *e) +{ + XMappingEvent *ev = &e->xmapping; + + XRefreshKeyboardMapping(ev); + if (ev->request == MappingKeyboard) + grabkeys(); +} + +void +maprequest(XEvent *e) +{ + static XWindowAttributes wa; + XMapRequestEvent *ev = &e->xmaprequest; + + if (!XGetWindowAttributes(dpy, ev->window, &wa)) + return; + if (wa.override_redirect) + return; + if (!wintoclient(ev->window)) + manage(ev->window, &wa); +} + +void +monocle(Monitor *m) +{ + unsigned int n = 0; + Client *c; + + for (c = m->clients; c; c = c->next) + if (ISVISIBLE(c)) + n++; + if (n > 0) /* override layout symbol */ + snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n); + for (c = nexttiled(m->clients); c; c = nexttiled(c->next)) + resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0); +} + +void +motionnotify(XEvent *e) +{ + static Monitor *mon = NULL; + Monitor *m; + XMotionEvent *ev = &e->xmotion; + + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { + unfocus(selmon->sel, 1); + selmon = m; + focus(NULL); + } + mon = m; +} + +void +movemouse(const Arg *arg) +{ + int x, y, ocx, ocy, nx, ny; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nx = ocx + (ev.xmotion.x - x); + ny = ocy + (ev.xmotion.y - y); + if (abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + nx = selmon->wx + selmon->ww - WIDTH(c); + if (abs(selmon->wy - ny) < snap) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) + togglefloating(NULL); + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, nx, ny, c->w, c->h, 1); + break; + } + } while (ev.type != ButtonRelease); + XUngrabPointer(dpy, CurrentTime); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +Client * +nexttiled(Client *c) +{ + for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + return c; +} + +void +pop(Client *c) +{ + detach(c); + attach(c); + focus(c); + arrange(c->mon); +} + +void +propertynotify(XEvent *e) +{ + Client *c; + Window trans; + XPropertyEvent *ev = &e->xproperty; + + if ((ev->window == root) && (ev->atom == XA_WM_NAME)) + updatestatus(); + else if (ev->state == PropertyDelete) + return; /* ignore */ + else if ((c = wintoclient(ev->window))) { + switch(ev->atom) { + default: break; + case XA_WM_TRANSIENT_FOR: + if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && + (c->isfloating = (wintoclient(trans)) != NULL)) + arrange(c->mon); + break; + case XA_WM_NORMAL_HINTS: + updatesizehints(c); + break; + case XA_WM_HINTS: + updatewmhints(c); + drawbars(); + break; + } + if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) { + updatetitle(c); + if (c == c->mon->sel) + drawbar(c->mon); + } + if (ev->atom == netatom[NetWMWindowType]) + updatewindowtype(c); + } +} + +void +quit(const Arg *arg) +{ + size_t i; + + /* kill child processes */ + for (i = 0; i < autostart_len; i++) { + if (0 < autostart_pids[i]) { + kill(autostart_pids[i], SIGTERM); + waitpid(autostart_pids[i], NULL, 0); + } + } + + running = 0; +} + +Monitor * +recttomon(int x, int y, int w, int h) +{ + Monitor *m, *r = selmon; + int a, area = 0; + + for (m = mons; m; m = m->next) + if ((a = INTERSECT(x, y, w, h, m)) > area) { + area = a; + r = m; + } + return r; +} + +void +resize(Client *c, int x, int y, int w, int h, int interact) +{ + if (applysizehints(c, &x, &y, &w, &h, interact)) + resizeclient(c, x, y, w, h); +} + +void +resizeclient(Client *c, int x, int y, int w, int h) +{ + XWindowChanges wc; + + c->oldx = c->x; c->x = wc.x = x; + c->oldy = c->y; c->y = wc.y = y; + c->oldw = c->w; c->w = wc.width = w; + c->oldh = c->h; c->h = wc.height = h; + wc.border_width = c->bw; + XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); + configure(c); + XSync(dpy, False); +} + +void +resizemouse(const Arg *arg) +{ + int ocx, ocy, nw, nh; + Client *c; + Monitor *m; + XEvent ev; + Time lasttime = 0; + + if (!(c = selmon->sel)) + return; + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + switch(ev.type) { + case ConfigureRequest: + case Expose: + case MapRequest: + handler[ev.type](&ev); + break; + case MotionNotify: + if ((ev.xmotion.time - lasttime) <= (1000 / 60)) + continue; + lasttime = ev.xmotion.time; + + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww + && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh) + { + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nw - c->w) > snap || abs(nh - c->h) > snap)) + togglefloating(NULL); + } + if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) + resize(c, c->x, c->y, nw, nh, 1); + break; + } + } while (ev.type != ButtonRelease); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + XUngrabPointer(dpy, CurrentTime); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { + sendmon(c, m); + selmon = m; + focus(NULL); + } +} + +void +restack(Monitor *m) +{ + Client *c; + XEvent ev; + XWindowChanges wc; + + drawbar(m); + if (!m->sel) + return; + if (m->sel->isfloating || !m->lt[m->sellt]->arrange) + XRaiseWindow(dpy, m->sel->win); + + /* raise the aot window */ + for(Monitor *m_search = mons; m_search; m_search = m_search->next){ + for(c = m_search->clients; c; c = c->next){ + if(c->isalwaysontop){ + XRaiseWindow(dpy, c->win); + break; + } + } + } + + if (m->lt[m->sellt]->arrange) { + wc.stack_mode = Below; + wc.sibling = m->barwin; + for (c = m->stack; c; c = c->snext) + if (!c->isfloating && ISVISIBLE(c)) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } + } + XSync(dpy, False); + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} + +void +run(void) +{ + XEvent ev; + /* main event loop */ + XSync(dpy, False); + while (running && !XNextEvent(dpy, &ev)) + if (handler[ev.type]) + handler[ev.type](&ev); /* call handler */ +} + +void +scan(void) +{ + unsigned int i, num; + Window d1, d2, *wins = NULL; + XWindowAttributes wa; + + if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { + for (i = 0; i < num; i++) { + if (!XGetWindowAttributes(dpy, wins[i], &wa) + || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) + continue; + if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) + manage(wins[i], &wa); + } + for (i = 0; i < num; i++) { /* now the transients */ + if (!XGetWindowAttributes(dpy, wins[i], &wa)) + continue; + if (XGetTransientForHint(dpy, wins[i], &d1) + && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) + manage(wins[i], &wa); + } + if (wins) + XFree(wins); + } +} + +void +sendmon(Client *c, Monitor *m) +{ + if (c->mon == m) + return; + unfocus(c, 1); + detach(c); + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ + attach(c); + attachstack(c); + focus(NULL); + arrange(NULL); +} + +void +setclientstate(Client *c, long state) +{ + long data[] = { state, None }; + + XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, + PropModeReplace, (unsigned char *)data, 2); +} + +int +sendevent(Client *c, Atom proto) +{ + int n; + Atom *protocols; + int exists = 0; + XEvent ev; + + if (XGetWMProtocols(dpy, c->win, &protocols, &n)) { + while (!exists && n--) + exists = protocols[n] == proto; + XFree(protocols); + } + if (exists) { + ev.type = ClientMessage; + ev.xclient.window = c->win; + ev.xclient.message_type = wmatom[WMProtocols]; + ev.xclient.format = 32; + ev.xclient.data.l[0] = proto; + ev.xclient.data.l[1] = CurrentTime; + XSendEvent(dpy, c->win, False, NoEventMask, &ev); + } + return exists; +} + +void +setfocus(Client *c) +{ + if (!c->neverfocus) { + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } + sendevent(c, wmatom[WMTakeFocus]); +} + +void +setfullscreen(Client *c, int fullscreen) +{ + if (fullscreen && !c->isfullscreen) { + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->isfullscreen = 1; + c->oldstate = c->isfloating; + c->oldbw = c->bw; + c->bw = 0; + c->isfloating = 1; + resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + XRaiseWindow(dpy, c->win); + } else if (!fullscreen && c->isfullscreen){ + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = 0; + c->isfloating = c->oldstate; + c->bw = c->oldbw; + c->x = c->oldx; + c->y = c->oldy; + c->w = c->oldw; + c->h = c->oldh; + resizeclient(c, c->x, c->y, c->w, c->h); + arrange(c->mon); + } +} + +void +setgaps(const Arg *arg) +{ + if ((arg->i == 0) || (selmon->gappx + arg->i < 0)) + selmon->gappx = 0; + else + selmon->gappx += arg->i; + arrange(selmon); +} + +void +setlayout(const Arg *arg) +{ + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) + selmon->sellt ^= 1; + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if (selmon->sel) + arrange(selmon); + else + drawbar(selmon); +} + +/* arg > 1.0 will set mfact absolutely */ +void +setmfact(const Arg *arg) +{ + float f; + + if (!arg || !selmon->lt[selmon->sellt]->arrange) + return; + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if (f < 0.1 || f > 0.9) + return; + selmon->mfact = f; + arrange(selmon); +} + +void +setup(void) +{ + int i; + XSetWindowAttributes wa; + Atom utf8string; + + /* clean up any zombies immediately */ + sigchld(0); + + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); + sh = DisplayHeight(dpy, screen); + root = RootWindow(dpy, screen); + drw = drw_create(dpy, screen, root, sw, sh); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; + bh = drw->fonts->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); + wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); + wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); + wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); + netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); + netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False); + netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); + netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); + netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); + netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + /* init cursors */ + cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); + cursor[CurResize] = drw_cur_create(drw, XC_sizing); + cursor[CurMove] = drw_cur_create(drw, XC_fleur); + /* init appearance */ + scheme = ecalloc(LENGTH(colors), sizeof(Clr *)); + for (i = 0; i < LENGTH(colors); i++) + scheme[i] = drw_scm_create(drw, colors[i], 3); + /* init bars */ + updatebars(); + updatestatus(); + /* supporting window for NetWMCheck */ + wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8, + PropModeReplace, (unsigned char *) "dwm", 3); + XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32, + PropModeReplace, (unsigned char *) &wmcheckwin, 1); + /* EWMH support per view */ + XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, + PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); + /* select events */ + wa.cursor = cursor[CurNormal]->cursor; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); + XSelectInput(dpy, root, wa.event_mask); + grabkeys(); + focus(NULL); +} + + +void +seturgent(Client *c, int urg) +{ + XWMHints *wmh; + + c->isurgent = urg; + if (!(wmh = XGetWMHints(dpy, c->win))) + return; + wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint); + XSetWMHints(dpy, c->win, wmh); + XFree(wmh); +} + +void +showhide(Client *c) +{ + if (!c) + return; + if (ISVISIBLE(c)) { + /* show clients top down */ + XMoveWindow(dpy, c->win, c->x, c->y); + if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) + resize(c, c->x, c->y, c->w, c->h, 0); + showhide(c->snext); + } else { + /* hide clients bottom up */ + showhide(c->snext); + XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y); + } +} + +void +sigchld(int unused) +{ + pid_t pid; + + if (signal(SIGCHLD, sigchld) == SIG_ERR) + die("can't install SIGCHLD handler:"); + while (0 < (pid = waitpid(-1, NULL, WNOHANG))) { + pid_t *p, *lim; + + if (!(p = autostart_pids)) + continue; + lim = &p[autostart_len]; + + for (; p < lim; p++) { + if (*p == pid) { + *p = -1; + break; + } + } + + } +} + +void +spawn(const Arg *arg) +{ + if (arg->v == dmenucmd) + dmenumon[0] = '0' + selmon->num; + if (fork() == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + setsid(); + execvp(((char **)arg->v)[0], (char **)arg->v); + fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]); + perror(" failed"); + exit(EXIT_SUCCESS); + } +} + +void +tag(const Arg *arg) +{ + if (selmon->sel && arg->ui & TAGMASK) { + selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); + } +} + +void +tagmon(const Arg *arg) +{ + if (!selmon->sel || !mons->next) + return; + sendmon(selmon->sel, dirtomon(arg->i)); +} + +void +tile(Monitor *m) +{ + unsigned int i, n, h, mw, my, ty; + Client *c; + + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + if (n > m->nmaster) + mw = m->nmaster ? m->ww * m->mfact : 0; + else + mw = m->ww - m->gappx; + for (i = 0, my = ty = m->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx; + resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0); + my += HEIGHT(c) + m->gappx; + } else { + h = (m->wh - ty) / (n - i) - m->gappx; + resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0); + ty += HEIGHT(c) + m->gappx; + } +} + +void +togglebar(const Arg *arg) +{ + selmon->showbar = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +} + +void +togglefloating(const Arg *arg) +{ + if (!selmon->sel) + return; + if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; + selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; + if (selmon->sel->isfloating) + resize(selmon->sel, selmon->sel->x, selmon->sel->y, + selmon->sel->w, selmon->sel->h, 0); + else + selmon->sel->isalwaysontop = 0; /* disabled, turn this off too */ + arrange(selmon); +} + +void +togglealwaysontop(const Arg *arg) +{ + if (!selmon->sel) + return; + if (selmon->sel->isfullscreen) + return; + + if(selmon->sel->isalwaysontop){ + selmon->sel->isalwaysontop = 0; + }else{ + /* disable others */ + for(Monitor *m = mons; m; m = m->next) + for(Client *c = m->clients; c; c = c->next) + c->isalwaysontop = 0; + + /* turn on, make it float too */ + selmon->sel->isfloating = 1; + selmon->sel->isalwaysontop = 1; + } + + arrange(selmon); +} + +void +toggletag(const Arg *arg) +{ + unsigned int newtags; + + if (!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if (newtags) { + selmon->sel->tags = newtags; + focus(NULL); + arrange(selmon); + } +} + +void +toggleview(const Arg *arg) +{ + unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); + + if (newtagset) { + selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); + arrange(selmon); + } +} + +void +unfocus(Client *c, int setfocus) +{ + if (!c) + return; + grabbuttons(c, 0); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { + XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } +} + +void +unmanage(Client *c, int destroyed) +{ + Monitor *m = c->mon; + XWindowChanges wc; + + 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) { + wc.border_width = c->oldbw; + XGrabServer(dpy); /* avoid race conditions */ + XSetErrorHandler(xerrordummy); + XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ + XUngrabButton(dpy, AnyButton, AnyModifier, c->win); + setclientstate(c, WithdrawnState); + XSync(dpy, False); + XSetErrorHandler(xerror); + XUngrabServer(dpy); + } + free(c); + + if (!s) { + arrange(m); + focus(NULL); + updateclientlist(); + } +} + +void +unmapnotify(XEvent *e) +{ + Client *c; + XUnmapEvent *ev = &e->xunmap; + + if ((c = wintoclient(ev->window))) { + if (ev->send_event) + setclientstate(c, WithdrawnState); + else + unmanage(c, 0); + } +} + +void +updatebars(void) +{ + Monitor *m; + XSetWindowAttributes wa = { + .override_redirect = True, + .background_pixmap = ParentRelative, + .event_mask = ButtonPressMask|ExposureMask + }; + XClassHint ch = {"dwm", "dwm"}; + for (m = mons; m; m = m->next) { + if (m->barwin) + continue; + m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); + } +} + +void +updatebarpos(Monitor *m) +{ + m->wy = m->my; + m->wh = m->mh; + if (m->showbar) { + m->wh -= bh; + m->by = m->topbar ? m->wy : m->wy + m->wh; + m->wy = m->topbar ? m->wy + bh : m->wy; + } else + m->by = -bh; +} + +void +updateclientlist() +{ + Client *c; + Monitor *m; + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +} + +int +updategeom(void) +{ + int dirty = 0; + +#ifdef XINERAMA + if (XineramaIsActive(dpy)) { + int i, j, n, nn; + Client *c; + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + XineramaScreenInfo *unique = NULL; + + for (n = 0, m = mons; m; m = m->next, n++); + /* only consider unique geometries as separate screens */ + unique = ecalloc(nn, sizeof(XineramaScreenInfo)); + for (i = 0, j = 0; i < nn; i++) + if (isuniquegeom(unique, j, &info[i])) + memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); + XFree(info); + nn = j; + if (n <= nn) { /* new monitors available */ + for (i = 0; i < (nn - n); i++) { + for (m = mons; m && m->next; m = m->next); + if (m) + m->next = createmon(); + else + mons = createmon(); + } + for (i = 0, m = mons; i < nn && m; m = m->next, i++) + if (i >= n + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) + { + dirty = 1; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } + } else { /* less monitors available nn < n */ + for (i = nn; i < n; i++) { + for (m = mons; m && m->next; m = m->next); + while ((c = m->clients)) { + dirty = 1; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + if (m == selmon) + selmon = mons; + cleanupmon(m); + } + } + free(unique); + } else +#endif /* XINERAMA */ + { /* default monitor setup */ + if (!mons) + mons = createmon(); + if (mons->mw != sw || mons->mh != sh) { + dirty = 1; + mons->mw = mons->ww = sw; + mons->mh = mons->wh = sh; + updatebarpos(mons); + } + } + if (dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; +} + +void +updatenumlockmask(void) +{ + unsigned int i, j; + XModifierKeymap *modmap; + + numlockmask = 0; + modmap = XGetModifierMapping(dpy); + for (i = 0; i < 8; i++) + for (j = 0; j < modmap->max_keypermod; j++) + if (modmap->modifiermap[i * modmap->max_keypermod + j] + == XKeysymToKeycode(dpy, XK_Num_Lock)) + numlockmask = (1 << i); + XFreeModifiermap(modmap); +} + +void +updatesizehints(Client *c) +{ + long msize; + XSizeHints size; + + if (!XGetWMNormalHints(dpy, c->win, &size, &msize)) + /* size is uninitialized, ensure that size.flags aren't used */ + size.flags = PSize; + if (size.flags & PBaseSize) { + c->basew = size.base_width; + c->baseh = size.base_height; + } else if (size.flags & PMinSize) { + c->basew = size.min_width; + c->baseh = size.min_height; + } else + c->basew = c->baseh = 0; + if (size.flags & PResizeInc) { + c->incw = size.width_inc; + c->inch = size.height_inc; + } else + c->incw = c->inch = 0; + if (size.flags & PMaxSize) { + c->maxw = size.max_width; + c->maxh = size.max_height; + } else + c->maxw = c->maxh = 0; + if (size.flags & PMinSize) { + c->minw = size.min_width; + c->minh = size.min_height; + } else if (size.flags & PBaseSize) { + c->minw = size.base_width; + c->minh = size.base_height; + } else + c->minw = c->minh = 0; + if (size.flags & PAspect) { + c->mina = (float)size.min_aspect.y / size.min_aspect.x; + c->maxa = (float)size.max_aspect.x / size.max_aspect.y; + } else + c->maxa = c->mina = 0.0; + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); +} + +void +updatestatus(void) +{ + if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) + strcpy(stext, "dwm-"VERSION); + drawbar(selmon); +} + +void +updatetitle(Client *c) +{ + if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name)) + gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name); + if (c->name[0] == '\0') /* hack to mark broken clients */ + strcpy(c->name, broken); +} + +void +updatewindowtype(Client *c) +{ + Atom state = getatomprop(c, netatom[NetWMState]); + Atom wtype = getatomprop(c, netatom[NetWMWindowType]); + + if (state == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + if (wtype == netatom[NetWMWindowTypeDialog]) { + c->iscentered = 1; + c->isfloating = 1; + } +} + +void +updatewmhints(Client *c) +{ + XWMHints *wmh; + + if ((wmh = XGetWMHints(dpy, c->win))) { + if (c == selmon->sel && wmh->flags & XUrgencyHint) { + wmh->flags &= ~XUrgencyHint; + XSetWMHints(dpy, c->win, wmh); + } else + c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0; + if (wmh->flags & InputHint) + c->neverfocus = !wmh->input; + else + c->neverfocus = 0; + XFree(wmh); + } +} + +void +view(const Arg *arg) +{ + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); + arrange(selmon); +} + +pid_t +winpid(Window w) +{ + + pid_t result = 0; + + #ifdef __linux__ + 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; + + #endif /* __linux__ */ + + #ifdef __OpenBSD__ + Atom type; + int format; + unsigned long len, bytes; + unsigned char *prop; + pid_t ret; + + if (XGetWindowProperty(dpy, w, XInternAtom(dpy, "_NET_WM_PID", 1), 0, 1, False, AnyPropertyType, &type, &format, &len, &bytes, &prop) != Success || !prop) + return 0; + + ret = *(pid_t*)prop; + XFree(prop); + result = ret; + + #endif /* __OpenBSD__ */ + return result; +} + +pid_t +getparentprocess(pid_t p) +{ + unsigned int v = 0; + +#ifdef __linux__ + FILE *f; + char buf[256]; + snprintf(buf, sizeof(buf) - 1, "/proc/%u/stat", (unsigned)p); + + if (!(f = fopen(buf, "r"))) + return 0; + + fscanf(f, "%*u %*s %*c %u", &v); + fclose(f); +#endif /* __linux__*/ + +#ifdef __OpenBSD__ + int n; + kvm_t *kd; + struct kinfo_proc *kp; + + kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, NULL); + if (!kd) + return 0; + + kp = kvm_getprocs(kd, KERN_PROC_PID, p, sizeof(*kp), &n); + v = kp->p_ppid; +#endif /* __OpenBSD__ */ + + 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) +{ + Client *c; + Monitor *m; + + for (m = mons; m; m = m->next) + for (c = m->clients; c; c = c->next) + if (c->win == w) + return c; + return NULL; +} + +Monitor * +wintomon(Window w) +{ + int x, y; + Client *c; + Monitor *m; + + if (w == root && getrootptr(&x, &y)) + return recttomon(x, y, 1, 1); + for (m = mons; m; m = m->next) + if (w == m->barwin) + return m; + if ((c = wintoclient(w))) + return c->mon; + return selmon; +} + +/* There's no way to check accesses to destroyed windows, thus those cases are + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ +int +xerror(Display *dpy, XErrorEvent *ee) +{ + if (ee->error_code == BadWindow + || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch) + || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable) + || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) + || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) + || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) + || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) + || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) + || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) + return 0; + fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", + ee->request_code, ee->error_code); + return xerrorxlib(dpy, ee); /* may call exit */ +} + +int +xerrordummy(Display *dpy, XErrorEvent *ee) +{ + return 0; +} + +/* Startup Error handler to check if another window manager + * is already running. */ +int +xerrorstart(Display *dpy, XErrorEvent *ee) +{ + die("dwm: another window manager is already running"); + return -1; +} + +void +zoom(const Arg *arg) +{ + Client *c = selmon->sel; + + if (!selmon->lt[selmon->sellt]->arrange + || (selmon->sel && selmon->sel->isfloating)) + return; + if (c == nexttiled(selmon->clients)) + if (!c || !(c = nexttiled(c->next))) + return; + pop(c); +} + +int +main(int argc, char *argv[]) +{ + if (argc == 2 && !strcmp("-v", argv[1])) + die("dwm-"VERSION); + else if (argc != 1) + die("usage: dwm [-v]"); + if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) + fputs("warning: no locale support\n", stderr); + if (!(dpy = XOpenDisplay(NULL))) + die("dwm: cannot open display"); + if (!(xcon = XGetXCBConnection(dpy))) + die("dwm: cannot get xcb connection\n"); + checkotherwm(); + autostart_exec(); + setup(); +#ifdef __OpenBSD__ + if (pledge("stdio rpath proc exec ps", NULL) == -1) + die("pledge"); +#endif /* __OpenBSD__ */ + scan(); + run(); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +} + +void +centeredmaster(Monitor *m) +{ + unsigned int i, n, h, mw, mx, my, oty, ety, tw; + Client *c; + + /* count number of clients in the selected monitor */ + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + /* initialize areas */ + mw = m->ww; + mx = 0; + my = 0; + tw = mw; + + if (n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + mw = m->nmaster ? m->ww * m->mfact : 0; + tw = m->ww - mw; + + if (n - m->nmaster > 1) { + /* only one client */ + mx = (m->ww - mw) / 2; + tw = (m->ww - mw) / 2; + } + } + + oty = 0; + ety = 0; + for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + /* nmaster clients are stacked vertically, in the center + * of the screen */ + h = (m->wh - my) / (MIN(n, m->nmaster) - i); + resize(c, m->wx + mx, m->wy + my, mw - (2*c->bw), + h - (2*c->bw), 0); + my += HEIGHT(c); + } else { + /* stack clients are stacked vertically */ + if ((i - m->nmaster) % 2 ) { + h = (m->wh - ety) / ( (1 + n - i) / 2); + resize(c, m->wx, m->wy + ety, tw - (2*c->bw), + h - (2*c->bw), 0); + ety += HEIGHT(c); + } else { + h = (m->wh - oty) / ((1 + n - i) / 2); + resize(c, m->wx + mx + mw, m->wy + oty, + tw - (2*c->bw), h - (2*c->bw), 0); + oty += HEIGHT(c); + } + } +} + +void +centeredfloatingmaster(Monitor *m) +{ + unsigned int i, n, w, mh, mw, mx, mxo, my, myo, tx; + Client *c; + + /* count number of clients in the selected monitor */ + for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); + if (n == 0) + return; + + /* initialize nmaster area */ + if (n > m->nmaster) { + /* go mfact box in the center if more than nmaster clients */ + if (m->ww > m->wh) { + mw = m->nmaster ? m->ww * m->mfact : 0; + mh = m->nmaster ? m->wh * 0.9 : 0; + } else { + mh = m->nmaster ? m->wh * m->mfact : 0; + mw = m->nmaster ? m->ww * 0.9 : 0; + } + mx = mxo = (m->ww - mw) / 2; + my = myo = (m->wh - mh) / 2; + } else { + /* go fullscreen if all clients are in the master area */ + mh = m->wh; + mw = m->ww; + mx = mxo = 0; + my = myo = 0; + } + + for(i = tx = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) + if (i < m->nmaster) { + /* nmaster clients are stacked horizontally, in the center + * of the screen */ + w = (mw + mxo - mx) / (MIN(n, m->nmaster) - i); + resize(c, m->wx + mx, m->wy + my, w - (2*c->bw), + mh - (2*c->bw), 0); + mx += WIDTH(c); + } else { + /* stack clients are stacked horizontally */ + w = (m->ww - tx) / (n - i); + resize(c, m->wx + tx, m->wy, w - (2*c->bw), + m->wh - (2*c->bw), 0); + tx += WIDTH(c); + } +} diff --git a/dwm.c.rej b/dwm.c.rej new file mode 100644 index 0000000..e78ee37 --- /dev/null +++ b/dwm.c.rej @@ -0,0 +1,233 @@ +--- dwm.c ++++ dwm.c +@@ -112,25 +112,35 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + ++#define MAXTABS 50 ++ ++typedef struct Pertag Pertag; + struct Monitor { + char ltsymbol[16]; + float mfact; + int nmaster; + int num; + int by; /* bar geometry */ ++ int ty; /* tab bar geometry */ + int mx, my, mw, mh; /* screen size */ + int wx, wy, ww, wh; /* window area */ + unsigned int seltags; + unsigned int sellt; + unsigned int tagset[2]; + int showbar; ++ int showtab; + int topbar; ++ int toptab; + Client *clients; + Client *sel; + Client *stack; + Monitor *next; + Window barwin; ++ Window tabwin; ++ int ntabs; ++ int tab_widths[MAXTABS]; + const Layout *lt[2]; ++ Pertag *pertag; + }; + + typedef struct { +@@ -461,14 +488,33 @@ buttonpress(XEvent *e) + click = ClkStatusText; + else + click = ClkWinTitle; +- } else if ((c = wintoclient(ev->window))) { ++ } ++ if(ev->window == selmon->tabwin) { ++ i = 0; x = 0; ++ for(c = selmon->clients; c; c = c->next){ ++ if(!ISVISIBLE(c)) continue; ++ x += selmon->tab_widths[i]; ++ if (ev->x > x) ++ ++i; ++ else ++ break; ++ if(i >= m->ntabs) break; ++ } ++ if(c) { ++ click = ClkTabBar; ++ arg.ui = i; ++ } ++ } ++ else if((c = wintoclient(ev->window))) { + focus(c); + click = ClkClientWin; + } +- for (i = 0; i < LENGTH(buttons); i++) +- if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button +- && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) +- buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); ++ for(i = 0; i < LENGTH(buttons); i++) ++ if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button ++ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)){ ++ buttons[i].func(((click == ClkTagBar || click == ClkTabBar) ++ && buttons[i].arg.i == 0) ? &arg : &buttons[i].arg); ++ } + } + + void +@@ -556,6 +605,8 @@ clientmessage(XEvent *e) + if (!ISVISIBLE(c)) { + c->mon->seltags ^= 1; + c->mon->tagset[c->mon->seltags] = c->tags; ++ for(i=0; !(c->tags & 1 << i); i++); ++ view(&(Arg){.ui = 1 << i}); + } + pop(c); + } +@@ -662,16 +711,41 @@ Monitor * + createmon(void) + { + Monitor *m; ++ int i; + + m = ecalloc(1, sizeof(Monitor)); + m->tagset[0] = m->tagset[1] = 1; + m->mfact = mfact; + m->nmaster = nmaster; + m->showbar = showbar; ++ m->showtab = showtab; + m->topbar = topbar; +- m->lt[0] = &layouts[0]; ++ m->toptab = toptab; ++ m->ntabs = 0; ++ m->lt[0] = &layouts[def_layouts[1] % LENGTH(layouts)]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ if(!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag)))) ++ die("fatal: could not malloc() %u bytes\n", sizeof(Pertag)); ++ m->pertag->curtag = m->pertag->prevtag = 1; ++ for(i=0; i <= LENGTH(tags); i++) { ++ /* init nmaster */ ++ m->pertag->nmasters[i] = m->nmaster; ++ ++ /* init mfacts */ ++ m->pertag->mfacts[i] = m->mfact; ++ ++ /* init layouts */ ++ m->pertag->ltidxs[i][0] = &layouts[def_layouts[i % LENGTH(def_layouts)] % LENGTH(layouts)]; ++ m->pertag->ltidxs[i][1] = m->lt[1]; ++ m->pertag->sellts[i] = m->sellt; ++ ++ /* init showbar */ ++ m->pertag->showbars[i] = m->showbar; ++ ++ /* swap focus and zoomswap*/ ++ m->pertag->prevzooms[i] = NULL; ++ } + return m; + } + +@@ -1294,11 +1482,13 @@ movemouse(const Arg *arg) + return; + if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; ++ if(c->isfullscreen) /* no support moving fullscreen windows by mouse */ ++ return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, +- None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) ++ None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + if (!getrootptr(&x, &y)) + return; +@@ -1454,11 +1646,13 @@ resizemouse(const Arg *arg) + return; + if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; ++ if(c->isfullscreen) /* no support resizing fullscreen windows by mouse */ ++ return; + restack(selmon); + ocx = c->x; + ocy = c->y; + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, +- None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) ++ None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + return; + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); + do { +@@ -1615,11 +1810,11 @@ sendevent(Client *c, Atom proto) + void + setfocus(Client *c) + { +- if (!c->neverfocus) { ++ if(!c->neverfocus) { + XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], +- XA_WINDOW, 32, PropModeReplace, +- (unsigned char *) &(c->win), 1); ++ XA_WINDOW, 32, PropModeReplace, ++ (unsigned char *) &(c->win), 1); + } + sendevent(c, wmatom[WMTakeFocus]); + } +@@ -1978,20 +2208,44 @@ updatebars(void) + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, m->barwin); ++ m->tabwin = XCreateWindow(dpy, root, m->wx, m->ty, m->ww, th, 0, DefaultDepth(dpy, screen), ++ CopyFromParent, DefaultVisual(dpy, screen), ++ CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); ++ XDefineCursor(dpy, m->tabwin, cursor[CurNormal]->cursor); ++ XMapRaised(dpy, m->tabwin); + } + } + + void + updatebarpos(Monitor *m) + { ++ Client *c; ++ int nvis = 0; ++ + m->wy = m->my; + m->wh = m->mh; + if (m->showbar) { + m->wh -= bh; + m->by = m->topbar ? m->wy : m->wy + m->wh; +- m->wy = m->topbar ? m->wy + bh : m->wy; +- } else ++ if ( m->topbar ) ++ m->wy += bh; ++ } else { + m->by = -bh; ++ } ++ ++ for(c = m->clients; c; c = c->next){ ++ if(ISVISIBLE(c)) ++nvis; ++ } ++ ++ if(m->showtab == showtab_always ++ || ((m->showtab == showtab_auto) && (nvis > 1) && (m->lt[m->sellt]->arrange == monocle))){ ++ m->wh -= th; ++ m->ty = m->toptab ? m->wy : m->wy + m->wh; ++ if ( m->toptab ) ++ m->wy += th; ++ } else { ++ m->ty = -th; ++ } + } + + void +@@ -2173,9 +2427,9 @@ updatewindowtype(Client *c) + Atom wtype = getatomprop(c, netatom[NetWMWindowType]); + + if (state == netatom[NetWMFullscreen]) +- setfullscreen(c, 1); ++ setfullscreen(c, True); + if (wtype == netatom[NetWMWindowTypeDialog]) +- c->isfloating = 1; ++ c->isfloating = True; + } + + void diff --git a/dwm.o b/dwm.o old mode 100755 new mode 100644 index 30847aea4113e259019ec9784b6c99ba2e19a2c4..da48b9ce4fa912e6393334663a66ecf09434d0f2 GIT binary patch literal 74416 zcmeFadw5huwgZqjP4Qqcb|=@rgQOAUxGkKu7V7%4o+1Unmb9&Hb&aRY_%&J)ZM@_n-US zvp+h!_ODj0TD59b)vCwdTvr$wpW^Wt>hc(u8of^nHH^Gdd(nIW=Nrcx#~G%*>TblC z?WMJ*onLDP4@QqO+d86|X8WxxD8gPrx8x@v6wg*lr)l3M(%9o#&GrecdYaX%Wg5DP zG~(Ivn8BYn#fF)b0?bc0?bXD=zRI*C|6O|K>QX$!1|ctz?p@Ow*VJhb2oCh!*Wr7r zqtmnwQnH-*npq$;qC_dA>N4$H1)~Y3UH*&GGjAnE(GNRA*4Bu992Ij~Vc;FpK8k{6 z;r6r>0`G)8Uzu%Nqs8`=(ROI8T{p(FEgb9!`6hP+zw<@j%-v>B$@iI^p3lO;7lCdM ze(Q^Tp8J{4e9iaQ^`T(rwF5#{XR-C7X9S7FGEt)em3 zhJHlo;Oa7udYYeXxBAo`2ZY8eJ+#oaf z%>AV2A*veQGwojqUAz=PW%VY{R>_YsgKPRGLCwh|Zz2i)O*5?@%BCcq`mwv)p6s`$ zk2dY6Z$kHGqccUnKvSv-cU z4Wamk6f<}#KqEHIl&UxFJkC)FX11SC(E?g%*ezoV16#xGwJB!1sHm_^6xdP9IfipT z4_jS=JTxOTb8|SGN`w|yP>XPe2%{W+TUhm=^6ZTGnri6Xh^FBoQz`!)b8}iY5f=vb zoA!`w&hB}lwjIgN z3R&x9X)8ikwAE*4L<^xIRw^+X5<4D+Z=%XO3NdFsNUb^KyJOuHmad?E^o51iuF%x5 z^Kxdr*YT13#dATnu~S*pRg;oZFSVE+{&fijej98NT*UNb&Kjo1lHpL8!;K@;*eM zg-a{)-M$_=-KOc3GVSVaY2th#!9AR}o-1jH%tiHuSBLG@<3Z>eJb6}ws)dOo7M-3ntxGM{bmKQ02nn(g)3r#zd6 z6lVM5ln|ZYg!YU!gp7TEFx!uM9}eBBXY&(`F7xm)fz@T0XcVqaa04iv*`Nn5vX<+I>lEPV*750o%; z<|-3I~5fE-SZ_BV(iU;b4xLPB@tD9m2OuH#P znF@34F}hjV8B%i5sHm}gF1n!5bT-zW)^dnCo8ERBwr6FZ5>Bnp&Z?LZ>h3JDUmy*3 zUD8dqr?=413)EMrCLp7rW;CgGY4{RC#`jDQ=c+CrI%2Dn5JqN+GPrD&{ zSo$}x0%~}_5)DuEwZ4^SfCqOcv19BqxDdC$CPviw&(n?Av8Mefjop0(8V-JF$9tne z(=HS)!r7{CIj)}s$sU*Ob+TZjO|G{KkkiUenNurrLPDWujAQMyvU5ZclZ~bwUk!Q; ziGD}{yN2Rtwwg4SQ9trh{5jzi#x4P&-q7Nrp`8s4Ytoxm*RylMMXJw^izva${>^Hz zPd>~tnAY2CX*d>yZ5^=$M9rp$e(Hdf4IksM-fj5zeR?-I8?_PX%D}%cj1;|w!r2vp z4*1yVLeo!^T*cNdjO@pQITaQSVO1v3hy~*&V2r)W6wj}kRy5mBe{ullo6wYrM5M7& zx^r2P!(p<=H`EHx3!>#|<`T}%k&;+XlRVaFIC4TH4C!geA5Ib+6l)cA#`dZVBDstH zK6^T{vsRrVU=r54h5nk>ht?{pJbTp;{0&>;X06H=5EX)z4z8I}TJ%zX?;XYiY7m29 z{gfeZcIO%}G1|74g{&RENm~lrI>Nq59a2G_jzT!CC33(EetoSkYzwKZH$t9u;oMhb zL^!zP+DycdfC7IJtitUX0kl=mx}x@sOrQBRMfl7e$(cL@3fnVAhwTYt3q5azf?r*C zlzkr+H*CG)>CAl}5o7Eb`C-pX*4yFWYZOb&5%o4$w+{(;Fq?R-pnXVY$XBw@vn>={ zSLiF*u6m@qa)_0EpS;~NjN}TUSdot4I$vZ9tRWwe8C)M75YBz8Fn7y7U*;+UkZ<}9 z-+AkoT#n~k(&+iT7nc<8^PTh7zL4*nZN8k3_xY~;$amg{OOD^?yW+)tz8PD;_EiY~ z3^vbEI58bz`!*9nJ1#irva}DuC@OlvnTvM(D7>bbqKO8!mQAH8B2N(I zw6_@^&|^I96;8XD7RTSh1Q9krggqS5k*R^-w6CpA{P{~720Dq?2skF_%#{H&!qm|T7qW}GH0wG)+IOhq85I(w)nS@MWLM`2($M(Nzn?R&Q; zt@`Zr8Ls*@Q!CE!sIO(fxXn1316lYk0IGMFOmQ2E| zCd0laJ3W^q4*81y;dvhl3t8JR`kxDSp#xvi?4*6jMG>nzl)EK&3uX%QFbIU~yGY02 zP4(TLR_f_YhC=rEv4vKG(|SG!D~!^UEWnDU~s{tL;9E%>Ok*dr^eyEE}ipvfdPp_?J9T{t9c*NhGB zY{|py5|lpbL^hyjD9qdk#eZqNU6}h#VW2yAJxff*lSaQ@nOed&UK@ML4HRDxl@e zP;e*aiW!C0zOb*TGnD&M*z;rV+lAJ;kY_tO>jPiWloZPJd>664$lVgQ-oolj;+;cO z4R^?DXruN?)c|%~H$xtpeS+i1VXTkjzEs#g!4ulvwc;aBG>9C@l@wgF4&&P9!Zj;- zF%k|5?7+126q$I)VTnzb#6ybh=c(x=j@XOZjAUn^mb%`g(Xh{q3bQ3yv9NQsm?4|t z-}m&>3^yd60!+-Vw^?XZ1!GaS1)^>f$$?>bzoFc{XgnFH ze$hsDL0cjFY0+hr!8j(uU(Kf)Y8f34er;bpW?cJd?~+NmiE!|vLMw?@@_J$JOHit4 zCWX0Q!o1suoCiw}=Wc;YdMfB5c&5GWgexeuAne(gtU#-RIx}dtGIK0=ggu{w4KeU+ zCGJ*-jc9Ny%uS-vAh-4*11SsZt;9zMT=*gdx1dn>ro=r-p|h?N4sSqMnmSa5W`jA~ zQn(*IlTkP$aM`Q_iNUBR(_U7ArsP}sIBL$cHsB7@XH)Qv<->_f4s#LHILYOZwF%Bd=)fUsUG7(5&pNA}l0n$i zs5gJbrx~$y8pj^{h7{hGh;E7GN5c3HvpzZ7X*Fh|VH9fPyc3Osfz{d$lTfVLi7A6lN&FWm9Uu=I{_BjU*ihfIyV6@uM}8^;=>eI@2f50+I?7yk zFg?D@W5r4MK*#<##-slJtQ09c(et#3o6_IUsN zOVZE5Lf-sK22IHK-M(qi*8nn9Xz(dLp)*uy(4`d0Pyaf0{)*k-Bi*>@uwv_9zNe<0 z!HPncqOBuefd!(7^(nO4J(Pr*5$GTdW5HZV@dF&*edhIhb|I>-zO{a8W%f=)6JLxa zW;;elQDjVN(=l{(-5}Cl1G}$6m)Ks~jkPP(({X0^7BhIt=Gb1?eMabS(5{h8qp(O# zma&doSfrf>Nh|;=4a@4IG5-u=j+v=wNcliazd&YXm(o170uO3_D#bi(dUySXU7*1- zJh?QT)8a2sJ%i^Du}OVP9N79S#R%z~4M(*Z3=yIYv93d+@rV?(m?;}2jJfMRG4~X0 zj`p7HpJP$FJ9><1-$L!t44VGv5nW9fD&&kKzGrS9qcmTBE8Q2WW%ltLP&s0G+= zKM*a(Ij9bU$Ur~_8yqrp1@68hL*;8%K>8Q(Gtk4fpNhLQ#I<)Tyx7`cuKD}R8J7`J zu^4BDzl=u;meQXJv%MfQ1iJ`RuT+e{Tp|r^UYUJ2?sOGf_hys%7h@s3iSAe*nmPLt zK}^OZ^Q72T#F7e*76S14r6_l?{WlSd3F{i-Pd_;InHcy=?Ary~h%CTbQn+ai4B7SB zm<&a-BZX8w#Z_rX26kBWzI2#C*q3J>*dMWOzeOl>-A8Gr=WP>@E08v9MSK-uYo*Um z(!|%Lnejt8u@}sCF&heWJVR3f(|U8?pCjD7OIcE0lgG;bj82-c6k7+2t*^LZ`ZTUA z>es{`6t~{(-~rcL{LLyY6=jy|saQ8d?~)<564U}JJZiN7mf44II`{^~$R5iz+oRcO zruAv!Dztc*au!--nmsmKY>voI$NmsbM4{^cKy$Jge2`RvE!5zHWJ1xiX~PbIPYHpA>khNe-JUhJ~K{K(7DR)N1bX&;g6j_v(ywL9jBS9mi59}3DG~ZJ> zc0`Y4iMlr?zcj0^$xd5Kn~s5Z1Zl+jEP(mph9L0e6HP4LTkA~g6|;M*i4EgZ%|%~j zVEHR8;`t;TyfQ7e8xQFSrN`b*9%nA<$T01}-JKB+3Y%_ENVm-N?#*U=eMa)Hn3Z9^ zA@ab?FfEw$-Sir=g=wX+6GW4T#PZX`Le77Pg2YL2uxH=O|DoMzgfSzz*;V z2QfYO-MmlGVCMQ60wLcE0sM+n@MlUI{)7gEf}dSGg>m@hanCpI`(HY|2Tuplpb zPS`3#Kk`9HY?)duqpg-~YvLGdVvbcd)+!rj735n5d5M#Ek<%&mszTlCi{tAuk~cT{gV@PM6uP8{H)k+g`d|QeFlqp z)PG0;imm+G#69n0I%0=vBi1d#CM-b!q_x;uR%=?TR)ZeF*5tEr4}>zYz7m@l=n(T+ zGcKy$h-D<^(jv6l>J+H-C8Zezr;`$j@}irp>0_powt0*sV-Un1xQ8sRL%p&nB zEe1(;qWehxEb-%aJrGuVx<+B_OnfFVQEf>$i~U=4mRzOioc7E~sIfBmG1Sqq5oo5p zGJ7>}YUtNsB*aEn77d?S(15Y;&%E7D$lSCQVugXaMi_}0SjnHK)r=9q%=mM}2-7T@ z5U7GxiDJ^Wi#_oabKS0iX6hn_A*>=+CP>n9c!spWe-SRJ^PrVq?Coo2NRb< z>s#wB__d+e{%IFt|8dunJl|j8JxohqdtG;rRAJAq@Gr*76Ahs;n_~mRme|n>b#F*+ z>F$hwpB{Uv0{wLFI+_^rwUspZ-SIts%}U7!?nq3*5Fr|dX}8}GiLsZpZkO`ypEXuM z0y0dg2ZS=A2Hb`S@!Q^soktt^B4uHqBd~v=5qgF?Wtmczd7+_9kG2WrSRKI-l^$vT zGj${Ji;sw13Jut0X?9DxOb=!SM-KVpLZi5Q1M_DM61RmOsXg#3j{hqywo%qVGWG;H zWHf4~IYv#tQcR~(NxRTrS)}~|QThGoCW4lmp2&k~2?dEFDfNgJ#uEJ-1(`M$05m6V zCFZMGnesig)1GD&99jOPQEI(U(`CW0xOtpkC<14*3eo=U~6&wWh~U~$y3u@DQzD+p=BfZ zDCuGnfJB(mmt{9vu%$TNP zI*FyV?iY?mMlu1;NL?E1V&IFNACcCc9Hue}Zi^j_5s=*v@>9P` z`ZNIXUqviB6o%39RN?Vo*P1x}6B=i}NNj&g+-G-hW`66*ACFRJ^W_My*D0*SkhkaKoH60w^!+gXZY_0qSIjvSvMdHkz*shsA z+MbLPdQYzgTbCng%xgy1cqq!o^h&U%!9KMpyll|sqA=1L$yBQ-+;t{M#G%IS=t3qG zNB3@*NB3yoJvs#&c$i&f3RCu-w`Iw|eZGpK%w*a=->h|C`!dD62m5nd=KIduzVuA| z6_iU)gf~HDu`|g(zcmkki!!_Z8_f=<7BQCeOTEzlP(X3>qT{KH9KXqfD?~pZpR@W3UV#qPgE)r+BYT|3eNF1A` zP6lLbUNIMv(Ulyh8VKg1Lrr@EJfW@8V>e%~2QhFM}2#L3?zjiIa4E@Nng;#8aIX!TK!@d|8{L17>s;Lad4| z>rJvX9*JAU0zz&41*wra@fWB7w5|98&3ldL1)En9LSb|!rMB4YlpEEy*Z~d8&GW=D z!svyfXC#j?Wiq6KBm(T(3=d5#OW3O@v$p+knh_1>xh;riM0+i{W%4)W$WF~mP(vw$dM#p`jCdx)FGP9i{{5uljo-%XL`FuN(+F3kzs`FV-< z54yXrVD?w?df!YjxRQH+7ZUSQ%0g1aGb9oXiNf0ZlZ~>6Z1!!ZP*#s;(O=t-zfxK$ z4HW>}vSOKAh-QghTTATMT0(3~?B<58IQfQ&Pv57?dyd4fm@%`f1y1zL&dae8fPGGX z;>3R-7L8&lDjciDIp)Qpn&}9NtnXkbAI{9hAv0Ev_%Xt8&Gu}0R7mTZ=PGz6maPyn^>`s5Q?U#Iuy!DtFqTVVxJLA`lF=9h;E*8pp zMC>h#eMR)Sn-kX~YxKRdyG}z#I=d65DbK^wR()_F9WN54wez#$9eJxoSmc3H^c=K> zuG8&S>CUnMsiuuZ#ZA3WvIuhR6l>VLgrF~d1f=j-OTw_yG|l=pu%8C?P-!B2KUKHX zdf)Rx)J2y1r9gY57pg@<9yjzQM`@yc39irzWgNaL~s2OxN12KPl z01ul|VAEg8sg8wJaalI&HLQrUZleDnZy?Wz{+;gr(_>gwi)Lp%3m2D~gP=+lsgyk{ zzv{dp`toy-F2h)UritYp^lLH9ulHls*ZM&4kb1?CNuq6v6I*EF8a_X~hD?&Cbz}Nj zs4y`#Q2x0(fp9kH6W_zgQLD%D0=Hf@ENDen*^cgRR68%`V5#qg`;ixw`+1of<$Ru@ zwSwydz*k(07J`oa3uY}B=w^$xBkntdi{^(IeJX&KkFY$Q4j)eGs;54z?F(^s8?_@B zk!Xdue`h#{3<{^eL?0EU@t67ySe9)f$?8&hATpL?+B5L_!#ni)19yxvTAWm)*B|5& zw0G5d^H4MRK@98!G4~G9i9GvGjzb$BMMq39YrrcGQe*!^yOicp6Ms(hEz!Z~m0&Y( zlk0^0DX&m#5V^{p%Pwuj;xH{am{vt=V*l4#YvG=Q5836zJ?G{^oJtbClvYJk;``Uo zk9NI=jzG2g6VQc;MUYEbZGChG-@u1%Grj}#;?!pHb#w*$N)tBqm$I-kx&~sT?d=gw z47FRMdG-nR^`(&b`j5KtH@Gc&T43Adfo@BHiHW`GLls@Of2%Vn1%n;YY%Pxh1QnPYrDGFh1$N1?z0A4;AM|A+s8g;diL9s)8Tzq zz$+}uvtOW5&N7EYtaVrn%gcn{GRe+(F>K{Wu;%9__b(p}d&t+5teZN7uVUT4h3>)D zis(RehCg8E6SvF6IVDk#@LGT=UD_AoNUwF^`cFv@7hiL0sXXpG#k97oBEeNM&9I$< z4i(F2)H-PzfBIbC!`UvHMrk`{cnn7KTS%& zg0n1GlPp-aEZBT;aES}{=)T^9!A7Z$eJi)3CgPVF%g;0IXIBs-I?{X-K={SfhV2R1 z8Nqu+cTx4ns+1A#q*tW^-E{a4gZ1IBGMTDGI(&SkpV5A z^*#PC5~&U7S72s4u_PEk>pvU4$4qh=N^#Pm$R8UJzpgwbHYmd0PvtZ$qT)@UCtpH# zSguBUN6&aS)kZQsQA!;O4z4K=X=ju=kS5VhC5B?2Yg(s59NH+ujPPjl;zdo-Bjt-g zUDF`|ZRYl-M(&rFVJ6VKkZ)gSCSKUuH;>L}4oPt)XUbh-Yg6J$94&zr$Q%;~ah!+4 zD4sf;qfX|a^S|z})uNuUKhgRr9Y5JX`G8V5B9Y*(D5jjMaHhyCVhyF@C2Yz}(mhXa zD#6;Q8q8pU-`7Svx>yzu?2X8C>l5wKcuPvOgD{=t5mghmTk_>w3!aS_$TLF0&wV#s z4lNgVZ!C`gFetWFviBs!8#JNdrskd(O*Q_c%^I2+T(VtnHQ=fQ--Vg}3y*2<%u({jQKS(k_%p zYi5}x?GI-YuTXGUb}U>BO=QyWagkk69tvWOCYC4F5W)^=+Nd&Z)$)Y+51yq*hTuhI z;ZXJgtm$KUI;(qoF;>w^f_q|*Bu}OFJ+Y~fylD;cz*)oBb`jRKOAI6~-h^6O3(e`V z)cBeeNNz+&mD!gi?!*y2y$y8IicM=1+<|NiNo<1D(&octV2Wn&Y0`7FijFM^>m{$Z zG_fDOBn{GsHo~jV*@Q)lLesSVOtgV+JKR=k3CF~w^Ziy_bdPo+9D&*ND4l`XtqBh@ znStD9cTIv^O5%uZHkCk+nAr+Yj-H5&$X9d@xKI6|fkzRdmPv9ZZ4ZlU6m3k%ul#YvuQ%B594zN5z(ej%V4To|> zXSdMk&eIlFX})|VxZ2|U7Q9EX9viXmxF0!Ap~t=U9ojwuw>8iD?iZ(~ilasmYe)B% zo^1kJtChAHX|K-CS{qrB3A6b~7$lv%$ci7#h@N!a;P}A-(bK!~kV*XD5UdXzJi*uY zGdy9NC)7P;bJy_*n|PxIBlFHkZUVE(Oy7<405{-LW_;ey-S%QPA>H0i4{!S(L={uqY}DHWP&vIkSuYQc1G9*m{pz;t{^K zJJGhJE&}^ywQ;3Q4Q%aGW3E-j-5YAGXPPWJPgGamcS7XJGW(89QDjl@=hG2RT+@lB zCC6E`R7?plGr?T784gMBfUy}KiD|nYdm+ovx&m!L`5!ltU+PU{B{h+EF{;|XB^k*` z9w3p?DGTN5&4X54M57Q5sXLD?*U>yif+OuN%l$6?-Ra9Omi2|jsIm6*CRh}Dz6@Efw2%FH z*g|W_@P%{n?#K4fxQ=dYOqaeMZ$v>$3SC#yPZr5M;57r z!TXlI&FI*_qZwTpw!S=99tvFtF#|YhPEF}}YumZEGCU~?xfkVKLuf-_(5&j@s8X};t z`?_EykQ*I?g9DKM&1PmP1E@=1&|0O=`_KvyV_waO!|%-8*J zE0#%!TVf6GnkL}w$HVC_m-O8g1)1Jd3c z2!bLC-m{2zpY<|PK>2cwe9%xq=LnoQesH2U0^d}4V6@gkC9d{_)@W< z)R*-K&bQ^prjHz3>+o)f*B9&7n`OWBbLEnW+#Z_=VF9X<5l}56Hv`eCt_rn*YoJe$o;#8 zs>dO5Vjh-d`f9KDe3Ve1TKdjOoJJOomgJ8w!&W5rJFs~#KJ5_Le??b2rig+4GrCI9 zZB%ql!SpT%lexra&m#?1$}!2sV#VgfZ|E63uwf^(F6w?p*9jsO?WcY%7VFZXJo2-4 z%k5PCG_mFvqGDhKSf-PQLXbvor{e4vq41ONH@|dYn$!R)4Pqc?3`aEKPLJ6Cqis}( zB}YUtp<~U;NwW0;W^MwB1cy@on6}1_lG8*qn5(Ff1jXbic69HVJ2dPH*ag{-JTQ$? zW*s(3q+@6oiwcaLg>MSvoEADf?^YN?4czi40g&2uu zn4z3P`&Pb0a@hqr7&&vIi|{v$SwsBbnXv_AwG*)Fnz#}@c;Z4#29jlJD8TZE-hG+u zuZo@&2jCK!lmiU?4snFDjl9ArzTqHyo=b7WEtyX2-xRADBJ;B`o9CJSSrnBCkvV}G zY;1}hk(fd}nMG1`)xtf&)HX++{=W)#(pL$+)(S23P9{w2hZi6bP8M1F);>sTx_(bB zZkqM1%%)0!lCkQW1ybH2XAcm^V{*72AEcfU$5=3b&H?Q(_&5e7^7og>&-)U^I1tn( zj1vP-T6VMy^F(Pn=m!9mXXBG2)!Ad{Fg2Elu%2&X;}~%{`zed)U_l(V{aDT*byHr+ zzbhu8_`kYisdUgIwa|Lt8pwyEbs_nh2yW>B?1D6ePC*Da;hz?yBjlGrrl80GKpSJY zQBRGdI0#Xfm57SfTVZ{4#xkpS^B{@^Gc=$?=Ch*yqkgr%wW1UWi>*7Tp9LFw>ROIJ zJd_tpbK<#@_*#inb+IMh<{*vcQ7I`fh62T#+o*=<3T+nrC@5PSsg9;XdAy?pb(gg5 zF7Xw9gYn<=g|SR0O$QoHFSeIrX1_mrG?XOkfPB?9Fe|n%q==)GUa4zp0(rVXY0RT6 z37rwLi?UHH8vPN>L9kT@PeG961nNhS8Ulh@p+Q1qVXegA#E?CCSkTO(C9M@Jz%|*$ zB`=O|R>g<}5Bl0lFkYcB=%4s_pEM8jSn}2XkS#ciCF+>BxX;Tlq4@J;4XOgv=_7x>4{Cg$#{95GaTls*X`&+go99&}mL9CA?KPry@Et|$jBbE%o zg`*ruuPD_!A-kO(gP3qeuf(kXMYZk2yHSA-Rj*Q&yh+EJ#hDo~I7D9%27$1Q=N&xE z0YoayZ1a-$wr%yTtc7lp871~pDAt&S0 zOPQWSg`Rbx;MV1X!+5#X5^p!zldv;AJ`d#7LPDuxRv+?g!TW@T!F9_A<2B|&*?K}j zF}=h4+VXCR+r^VkiTUO6AH2DA(7t@M=U{N#HAkghJ~p`R+5z$`QYa|7`%1)}&k%eL znRlF~iyX~F>-Kpcr+(l0^K94>C0)(ty zN+@~;lw=-8Joy6tT-6uPKI$Fl-y5p0cEwe+}JJRXO5bdI&H#qGkkUg(iqdT2zV zY$6^;OvPexVGTp@R47fU_pNME7kELFh66D)B<}tgjy3l*R}=?DKNdrOEmq`yh0_|K zCgY4)jZKMj-l1oGOce~Nr5_m)ulk5*_`nZ=ElriE-g-uRHPBtZp%$>VIv}0--f!JV zD-pcVK(p0xU>tzCIwvvX3DIlEj^c(kvui6>PG@#f&kMGFu9-tyW*aj{j2JN+`3A7Jp@Zb4_LSGJkWd zp`or}0g)S3l?`V{{dEm35T)KW)5^z>nNwCiwRlpIF}-9?>D0;PlM5zC z%IG0n7%40-oHM<6Qh4%o0?Num<%JX|4^1qbGk$Wxv@&DPq{8w!p@Q<_%X=sVR5q=& zbn?{l!my-3qDi5W!k!1oN~eSbb3j#K78XqGOEzcxv`D0^U}|CEq@D;V)SU7wN_%-~ z*qm^2C^ET7k{3jZ3n!J&i4>QW8|TfdYdEi^))-!8EUs&u)udZoX6m4uWV41zNm9c0eYP^|9jTThnB4d7C zbItt5R%2ds-GbU^LrqIdRkYsU;y-`r@WZfk&mU@3EsnJeZ?0L~7_IRSAKp?^v&esL zAg@1o_~9@K)R#e1Wvr#ffi={$MjcR7bIlT?QfR_IyviT&x3s{VN-A5TXd!{&?osC& zO|klx8csPp+PGjrea-O2v1pB^!luThHO-Cl=aW`?mDNYF(4$ekxTYaC2aV7ezStN( zAGd~i_{}$lx8U9~A3f3~#-(E~HD;E~Hm)hT#<;ZPQlqGDag!0Lo7Y@3y|I42Q5H1{ zm((;w{pIL0YMPBNtcQ#*R{jpZ`;9MFTyK2wi>Hh)uD9`f&iG>0-*EpggX*eQtHsv3 zhB{G$)K)5&*0eM(uDPhC?&md^1kN|YH47^*kCjz6w3IZWIZdi*uJ(@you3|=YLvmp zmg%K~Ceg$8yw<%koBCF~SlXRJFKRDI?{iK??xX<)5M^D`?pXs0kctcZ+s}k4xaaWqd>G4r6nw(4Lw`$cc%Axng z27FqJ*B~VK-bDk@DQ82-pkmndXm9oOoZVWFGr#!Y9*%wC9Q@CbTl=_7vwgBBdW31c zn*6}D1Os#3rzwHG`U`O^Rm2|JlUcE6PYAOkl>JgJ^u_pY9|v(fOp1bOlu)F^wK9t- zo4bQ1&hK z>NR$8L_6ubi__;-5iF_+Pr2uF0@#w0Cu*^tE}N?^l02ok5K;*D7#Rq=1eZw9LS<+T z6t!C6JaNNapqSQr}qtQCRF`t?|v$MEY44x`C0M}6G((9 zfNXWvThAIMJqlq|F)?$(+^RNe%s_3+x16L<*dM9wODk~kNA(~$OPN_>eTnxY`%*^e zg+$`pyN=X`6^0)n4Z1)q+GSl_pPkmyj87gZIjpxQ*rRs|?(ovfF~Po@gpXm_4dhIP zj5Mm)2+W+WNugu2L}I-^!5%9)BylnlP|q_~_fn&8;oZ(SWslVwk$o*?FY^7A`K#>z zO{UTReWvZSxXNECq!cy?nIF;EQ zP4Z}$#LQZ}Nx}U1JtdYxwiA#K6hLw>zNn-&I-~FP$bh#%MOotCr^Y@}r>5+SnaS1i zLjZm4N6$bH_YA^v9F#|n<aRR&FC;^_+ou26)YZ%A;MEtQo5r6bg#2^0?@hAL5eBdYIhx|nRaX%4% z=}*Mp^%L>w|JGmTfEBOEnek+ftEJ~{rs%*cZ*l~yTz;g-Qx2(p9}e}ZVFfVyTz;g-QrdL zZt*IgF)Cxeui(4N-z{F{?-sA}cZ<*Ge1d%Mxp`zrSpQ}IJ=yViMv~=}HOW6OGUgx9I{yY9Uy~^)@L+?!gf6xEl z(tz?`=}x~hM+frq##9++)`-hEbDp?>i_183q_~X5*raS}s;pA`nWL}=-MFa6G5y|k z+23ELYtLoBzK5=7E;Ec3ml;I`1sC~qiY86V^#}4sj2wYU%@9_b=jT%mPiv;<ra_9 z*qap=S&ut1j`RB4(+a&gHysi3=G{0TTRm>)`q=vukqH7 z_cm1vswv)D)7vytgv-3Oh2AFf$O>^U6)7vdV~}6Sn}htvd9xtTI4CO%qWz8K^dn4V zi>F*kY7~0j$#LU)%7Ain8OHT3!vycHl++Vayor71X`GgKN+o#4GSC3Ue!Y1a^PN14_SQeAGc#alVdX&l3&#(nyGgo8J?I(iO)o^%l1_-n9;SH{VVQ5r%OEj{ zBpXl$8_q2pe`CscWh*OH2~5O|X1c#nS%rO|UT#h;?8iRB-qO@tJpHSUHlBD{lZM=7G>T~~&*UQX{&L?Pc_3{d9c3YZS?8b}gGb;^$aEW^DZ8ub&u_;O! zh^ICdX4>m0fuI$2k2coo%_;Hb&GqJ(UVo$~74;{roJOp>L5DX{yS$OwWjrmVOtwte zIaMFEOfq?q*Q1=y>YG;>?YR}HK#Iy#skmNubDHA5X$p`=at9sFe=?3B0>ikC{!AvB z5Pc)nYf24x7j1$ZFMHF+lS~CdrqCwpb4Uj!r`=C!MR`P8$Q4hU;9ZfD@}Ad^5~`vY z*&w@y(}=Z2p|?hF7Bn?a&`lI}Oa0m(nC>j%jmwYU8pi6Vu8}sLQsiw)o#PSZ2SoP% zF4NqLFtv#rQ&QSQlfWa@@xM5}nC;~z>W{e&QZMxMNK5T9hu$K`MPbTsDx{+_`g9&4NOhgfSQ78#wJ6)&;lQBJZP~l$*S3JcZs4&jjxlPqBBK zC+ywn8Ry;QDW%BLe;0|mfSfQ5gX}eDApYPI>%0#6!X%&R%}bfmSG+Lj=W;q>uSjW>^^EsC5>Sp58PGizdq@Nq1pS<{h@!ryu za&N^X?_4n)H5GeHo4gfe-nrvwc%jEy!5vCOa-~EQ{Kdz{aqq&9^nVzClrKJDBKR-y zR$v6H@>ZaR59da8U5+}Z>je4(9mZ28_w>ZnR-zn#KgA=jn^G?K<}db|kbbev3D=(3?&+_aLVcJ_LAToDv&a9gLR}FI<%W>x|7MK-k)Bk^eQQOXBqn$Isw+ zs7&z67(@VkF?kcdho3RwvjC^|IGQoF=1Q2!m|909Y!+in5T=V{YhvtP0^oh5wD+h+ z$aX8oFQfQn-pu)sc`SktGCqxMJf2cV-itrwD(W&aO~GY~H){f*Yo+D(F!m#Tg45dw zlTK2u5Ygz@$Hu_-qE3wbtzk?vlIj3; z2OlHXgE-39a!&DBH$88qLxghpVu`XF75 z$)H3ydQN{P3I1qBp-vNzX%;Gij7viD3Fs1fcDc4~0JI-^zS{N=m)= zLFDo%df_$rbs&5{yzd9`dlZ@WVyP=UK+83>6qG3|`YZA*WPK~kvG0GPJ1{B+_i5lh z33(Q?9I03IuTekvf64rBM40Lvc2TV>l-lVKFGa$J=nv|)r>*%@p80p}l_dT zW&8glRBS}>SkH0S^BBhdmGF_^ST+w9Lpu@)$1i0no(n|Vmd|f#(S{%V{>J=9BTRW! ziw0ewnzd;6yO>7QH)tAqVtFp>qr`?G<{M%xnx@90kQ$4`$eG_L#-be1j^;G8DWOPX z_V`Vx26H|+39BlUw{GH=nIkbOMm+8&LpKzt?*T)0l8@d9}t<_Can zd_WOpyFLxM!S>*Utii7%6>R_$z6VpM0GkEO1Xcws0;~+!G{#ye^@LP!UV-qJG*3ii z-R~b#Uz+h%cYl$ohppC0s#KR#HK{$jcfH)my-Lye2%7>%=0mu8p3h0>i}Zy5nxDBV zHO^rC0mjw($GMD)ejQ=uPf-8wfjrxo9!*7DWAT@8(FPG#cnD$2SNQA*zla}Qlkg*Y zwI+}zP{a5P1ta_kQXnpc(>O(Z9$oLGO8Gn`iGO=y~>?Ou0vO)RrOxNr95uZhji~b52jr)YB@VK@S&vbnOe~0kR zjEi*<;7R;QKN}q7{haX*2mTds;`0hM1YBb61o!XoBYZUX7h)|0*wIK&_(wq^GUY0$!D$(up%783n?j2AP074s*1p(|b9jO!SGl%ExTv%q_M8f8Cs zGXJwqlnHL*biY;nai>f1d64O!Vfy_t+IWoVS1`Swar#sp$^TdCpl~gcH)B2HC!H*T zvlxGo@qEU`dII9!X8a)6hAGJek45@2&TmMD70?`Qh!82^y*dd62VUcwcn>XFuENzcD! zd@j@9&G-+D&tUvN8K0gjfioHZ6XQQ;T#bW|GrpJc;Y?3o<)eI0I!6L(evL063p~O& zjYD+pWPCm2%5Fbm{K|7B-7M;^aovm$V?k`DKMDgJ$@4VhYTV3XeEbMW zIE?8}XS|v5IO9Wsd(g`BdHii+e1yR9hcAdBt_uNCzTYw*Ro=@OUv!?N+r#wJ8K0gf z0Wlv&u$uAP8K1!PO~5@y2Hw?{7lv1HEoJ)mnZB0sAmif$5)gA@1lt*J<%*iZ^mj78 zmGKbc_cA`19SU_0=zhj8WBd)K|0Cnau|xJ2<9}xSbH>Gd7;#TA{xUOugy}aizU%@C zh&eEVI~f0l@oJ|3066s<>PqLpKbgMbLJ5dDFM?k&{vSb!7c%{KjDO7dV#ZUzn(DXo zA_;Kz#vsOTWL(ToL2?{$(ciLx__@D1mFXYi3K#Q8(4Wotz4?;=jq+v;WBiZfBp~Ky z2%gXQ*-`#H&0#?`!5;qNov!G4;;_c4CI z15ZDK^o;S#fuG9wTn9dq@q7nf#JJyq&tlwg;8!ue>nK?uCFhNdcR28S8Nc6wKgRe9 z2fl^zxeok&#`7KcH;nro_+Xd_>Bn&3e#UpPOQYn!fbk9o9${RqV=4N1jIVIew+cMN zD3$6lj^XKH3Gp$OWJ1 zg3olp=eyv|F8B>D_^({>|8T+orVF8JU<{o6wr zLr#BoLhJ4Q;U~G^XSm=)UGPyZc-RHM!UbR8g2!C&6)yPAF8F;e_~S141{eGvF8IeT z_!lntcP@D9;Qs6DWEXsd3x2)}9&*8_y5Q9=c#{jh+yx&A$EQC#jJweP!Ug}O3;u`; z|GQo2A9BH;b-`bE!FRjhNf&&-3!Vx`vOoP~y5Og};5jaM5cn~edHgIS2S?>+UC8)% zj6cj{XUK(5gz0}7mV|dPeT57CVi){I7yJPi{3RE>%LO0cVh=-H@RMEeGhFb13r^=3 z`m4u67kmcrW3+Vxu|Eo(&T*li?}9hE;7eTa8(r|*T<`~6@P}RS$6WB|UGQx#_`5E6 z(gpv{1^2p)k7v2y0T+C%3tsGkPj$iR3w`4NHC0zeYvxrpH#N2x^J>Kb{;K*Kqh%?5CExlwd>O6*`h#wa=ElY-)Dw+0 zFQ76@aR6=D#tcmoB4+Nr)gobP8&%t*Y8)Fbhau;6%H1KUk z61^$fEbEDArSJ=CP^_LxhH_)gEsf2_qMBv+BwvfF|AyFN`j{Y;w#Zn}Tsd!E45k9> zpfE^VjK!5rFsB9hKxEzgWt1KA#V7b$>K0Vh*5k93bIF}}LV)Rpy1E0?w4Q+M>$!lTbu~+6tTgo=3uk=_Q|2%} z%!p5G_B=FzudEGOUm_1G0$CK@kqg~qQ(4?dUt{Eth@veofz=T5^G31)`uHU2i2_ZW z13ohe(^ra7wOTOm2DyuLQ?*EFrKWi?)xw-PRgH_A8eboVMt1UWmY2XNRf7=NIO!b9Vya|6lq6_v?E2@ zQ6lXqk#>|wJ4&P-CDM)(X-A2)qeR+KBJC)Vb~I|gC^C6mC^BdA`0-`T0 zQBi_6IaLg6(?u)8AlckdB?iu=bI`4{pt&rrq2Y6mXh${CIq0O8)>TI_yaNt$rV9^^MkI&qSE*hUA zu8U&4MA56^NEq{3_6m^_jNxZA*0+!V(c*@tSaiG?C}s4d#%6qfnb}XHj;vQM(Ub9G z4Zd)UAq^u_jZrZrR@1z!v=K7li>(!P4d`8@YjW^ox;X?>I%bk zLnW+%IF{8kFClF}$%W+2nexliTp|pf;l`y6kP7lm#JE}@y+9U?6VGpKUPL2u3o287 z1=_%90cL`W%zPXiMal=#lw+vvk)>ksJpH-6k)9&tj0t^|MPbkj#51Z@H4r(<85JS& zO@(d3OsF(Hl{+1tY|n#c%u;bGCf30IEgEEx1uc+HU=u7`iVMfKg?!)f&<<5EzJ85n z*D?p+3vXUFM>+s=$nSHD0CiLSGWTetog+rTC{(7H^zfatq_RF%BmcU_if=8Ga(k^1 z`ocd9!}yXnx`Miv#;Ra&&it0DN_^^gepNj=MyU3BbReR6iNeat3PquIxEo@8ha*F( z$LEhx#b`_TWH{O?xtI9aa|E0hCh*R51x=CVMr- zAFYQwTtQGk3Q~o6m)9j|n*dwY#>@QtsRMtVpVj#sMX%0viT_3uGzwSeIgjW42Zi_W zal!w~fh#_Lap1dI9y+%~7s>txe*dDE_;J0W;csgA5jg)r7e!MVRsQoFxYENI2fl|A zXrB7y88xTD8`W)q;SNw|{xYBdA16TTK zVw`Te9#%T&RlPstz!m@JH9qfvm(u6kF7%&j^t#^mI_OoozH#6x-ya-!&v|m*a94U( z`c&`IQZiki$2jO!zNa~GrMICDT*-4GfmM*fB z_wZBghlt9&;*a5X-@>cAEM4>bO|J$taP)}Nf|4qWj$ zo^hv~r#R@9oH-i)7i6ULbDoA1FD3t_4qWA1$~e*L@?Y+tSNT>uaK*pDfh+!3yYO#! z&?`RoI&j73cN!nURC%A#@DDV6IQF;bQg*UiJ{lt#r}FN?Pw@#l=v6zt(t#^JRW5vP zb)mmkqyJFLm-grAa>{v7qyGr;O3oqJXQInVe+J`Ju8;9k^p|M3uAj*cKB~OU4qTOY zx5kGs#s83o>-?<@5aDvl`76drPQ6^ebD@7wqu2FD`!{qEA3a~%kD*KD+rj=)8umYQ zT%AX{&4H`_Je`l85ud-}r^7bI zyvaxT{@p^?^6z3<-65^t9)N! zJPmn%s^y!OB?Wfse-PtDpU~(pa-qLWqwmt_t6k{pG5f6q9{_<@%1vkrPC|En7PA&vfh7y8dM`tLOQZyfYW&g1+b!bS4v^}EbZ=;8g( zt$qRb=t1!bozWLp<(=Sy&vD?2&nCu6o^S9|_41a3{xzAMk#OLO&lfKEw+>wSd*3^7 zOCe}e;8<^6*LSM$ohIB-?o=NNaEcfEsN$@!)OSLOXct&RG_LyML(GFG(`WX>1Tw7>vm-_PJAr~!{OFp;IAPuRsrtH#aV5{a z9-=mk=N$NM2^;Gi_}xtZBI9X92Tbwb=b+!se7ZGyk4AswP)XpFr_O;ZKFb`qlHX!H z4eU}i{(p7QD?V#9`ZSHcQ==z6t8)FI;gpBslYW+zpD>+Io`&o7IFWH@J+9Vp;D&Jo_aHWSoF-|;=(8~3sgI@7@R-@PJWv7E)$&+y4iqAfc&j2mo6VH|fA$fE? zoTuRfHTqeMD|@&JadcHVaFy@<8lQBH&sq)F{qxr}T$kqy4IiZO`JQo-=PCS@J*4E2 zRI+c@{hT8iSMonB$&3>m_#YS#YJBzpQ~XOE^lF@1;K0>*)Z~J9y5JwW;GSG5n37-R zdyxZI<4(wdt9lvFIMutp&QRi@SNvzW;B7AW?=}2sO>fU>_!P0nR5^ba|3#s4V>uJ}La!rvU;znoJXxGLAp4m`}|y32vTEZG{* zy5KK4@RiKx9S5%D-^DoThu-y6^|(jFkJRveE_}Yz=rc5W&xpQyQ1Yica3xO`<0Q{f z8lTf$=+DyVKSUZO|40qjS)$<<_>ATC%{C1unUws$)bLa--#Zy6TAwEW?=*Uf z+l?Pxf6?eOHTuUjoWAj-%C%0zkJ0d#H2!R;pZw5;&pwU*1dY#$d9vWdU*~g%hG%K?I4CME zqW=s(RbLSe*Zqf?jH~+EAd?&O9QeD)gRZ3-{v4ha|K%D^c`N!j4Xy2lQ8%SYoZ#)(!R7cS9oT|XrbK1$AqUGOJe z@E0BU29{^L16Ojs$2iIPC4NfJyB+k(o|6t-@&DR^EB*&G{-0?4FCHlcQ}&?R?>Gmp z_*~97$*H&B8V9}7+tn`kS{M9f7yL&T{HRfVcCY!CLFk0U;5U8|Bc(rj}BbXr(MuDUqyec16O|Xi4I)x@jLK$C0k=C<75vf zY3&^c+r_2q>UE}{e60(!WkRKgds%*)apI$oBfoRdEBk-mfh+l6cfrdp>YJ~kuX5mu|F0dm zqW{!^D?R+^z|*)~11|2H?*{p39L+eD_Y_TUg${bfKceAepZ{Y1)f%5uH9n0RJ>{YJ zT(8lerqLgA(5v!3G*$|%>Pz7V9Ju1|yF}7cp1M58Gp_h3`ZF~8(=~Z=THgX-fDsLX+q#wQBXKVC*>Q}=l zjpDOJC}QtF^reCk~A8#O+kVpX}B)u zZWlgX8ogK3^H&fCJwk#W8Zn%Yc$|H{$`u)9_4lMAeR#IOx^< z@c{>}jMwPtTic4h#D)F}jh?=#rs$hB{A>-s zPs4LG{1FY$)$pe^T(`F~O)0RFU+FWCai=~PI_OnD*{b0WfaNUKLtMj&m*W4l#{V2m z&Mg}KA3=X5^Vy~0#OHO!_iKF4)%f^|B>~au_)r)87RE^rB)_tU2Q+%U9X;WKf2Z-$ z<-B5ol!y5L4L?=CO^g%mdm6q}qkmq*uhZzMjVeBOY4mF~`v1`AhimkI)bJ4+UOf?s zaVdLH^RIRXzFU$R4=_&he}tcs=V1r^9;ScXfh#`iH9q>f!6gxyP|2g{CooR=o~OxQ z??Qi-M!ySbl$?+JKc$_2kX2Z+Cl3J_bNRB$!#EG29jf9|9TP-J3nigG^%pcdEVWG1cA(=UM5+^iAd!PG$pUcw& z_piP)ch5PW^Ssadp7)%4-gDk__P(a?&)F6Fj5FVD#?McABi<4J*U~cm2hXUlZqz65 zm&X~W{|UjdUE0om&h(FG+rm}G>2r^@o)5j#Soq#1vXRAL5+^1od0w3}$aZM9`o%kFmK0gqy&*N4L*XMCP!LhyieYsb7e_F?K z-Y-6H3g0OD`-MLudVL;O6@E&Zr~g~xgEGA|I{iuUu5i@P);dkkf+0%5{na13(ay81 zaJ+H0cjJw7|MGWjktdD;mUD{ezn9j%5$FBS3r8BX4TxF6!9FcM9io3Yt)u@u(d+qe zq3G3rsd4VtYmD=HX}NK}?{}kc%&tE={YkMxIP%?Er-i~Q;W)Rj{21p00WI#O$k&Tr zeeMzdXi7u<{Y`u}ie7yl6TV4&o)!-Mm2sTB(8T{G({D{_5Zi?RAuY3<{}c}YW#Rv? zCjRf3p8k97ja>5a{8*aOe_!G7zajh&2o9$8e5mQ^f0Xb)ivKaf;k6?C$2Rdl!SwV$ zRXDBzS^kN_;XgV2r#A7QVS4(1NjTap`hQh8{6~cU+$R1DOi%yC!k-lXrNZGqD*V6Q z#Q$2;)Bh&nPl^An!r_m5C&X<{{C{G4`u|*bHKk|$+$|jbxYj{n925kY9zVY`J^e90 z3Id1k)9FM1Cxp`rI*glwAfx_8)6@S|;kfpo{_n!!H9gAzW)uInO;7*#g+D9)`@l2> zwhObf!hgTum}vbBGd<7q7-t1RpYy|Kr1+ek7`N*<)6)mztfd9iS66CaGfqI&ww zFg_^Cb8Zu#3rs&W^z%ip{Yw~^Wl#BDAsp@FhG-u#{)+0~$cqJxvx30n45^=+P0#IG zB^>_Gh5yflW0w9HPX&RA`v1oC8|tc5Ug6l6T_f{~jmBrj{n94knC%ar=ZtR+{*U08 zU@QV24;;dR#}B`!!}iGu$>}rPILnXmS`hHp`~6X($GrpdJzhA{@ced?ar#d(&hpF% z?)jc)dT!T+#`{y=h|7)B|H>x*-!(nY|2H(@D~vPWpBiVrcLg7m%BJ;suj%=H-(Z~n zj~b`{U&LSU$6q!5d-d8$<475&|4!rdA2v8A9F!()a=aZGoW~V?Mj5BiapI%*ajl|< z*XhUR{7y1HDc<8bOE}8Je9tk?eCGs*cA}KOtBD@t-yopZex9{W^!JD!$3DLoPl_Jf z_0&|jrtvk6pC0!qgFlqlvp!k=4+r=1=eM9t` z@8!bRr1HF%>H?9+1j`9y1pZ=uym2i{? z*N%vXjk90<1>>x@mxIG&lI%x}tARkC_^h6UrSyzdIMVdjX&NWeIQ>ry4z2#*$0?>~ zInNZ1eAkS~8Jr^=Ui@Bv#rT#iFU$=N?U}M&i%ieq@Z;?KtW zGcM@w)oe?Q^|{UT^vAd$2;@0Mws-G+>$uLfAG?@w0mVRBIZkCHJ>`i_p~K_ z5bb%=(Eq3{gR*gsJIVe}<1-eKVG3?9$8*HF zS~J^Uqr=I;KSPlKa0qIYQY7_lt;n4Smz9wA# zcM6BTJM=|}Qed^}hYN?kEA%Dds>e9B2>3wX5&CxFs-G8Pg=-W-t@oF*ND#G*a6pnn`!lxo!^Ia(%`j*i53RnGo!l5sOzA9Yxn}tI^FcgW> zyWhf9zf(B$eW5Sn1ewCOcerrqyF*_RuKp8*L*EtpcHyd@Egbr`IPaB(tG-h>^o{eR zaOgSSaj$WXQ(QI9acOH!crmW$Sw9>HxzvQW8|Qe+L&wCfRf=h9I%X%YkH_q{b%T0L2ILG7eZNjTfc+EJs3**}% zSk6ZKZk*fOZoJXH8>fH8IQ@H#)4yt*{x#$DFYeo<{Ko0e-vi|K(!Xqa`d5rM%5R+h zRpa!p8K-}7zb553PXBh}^v5`12yPes`Fnljjq;nG{#E1juNkL5#?8`v>0dHV|90c_ zFB_+S#W?+Yjnltsoc=ZA^e;yH9TQ!>6KeASgld^(KNXTEXzl#Rb0K3&G?v)nj+ zD#qUrpKjyyS!bL+y~YoU>%uUC!#I8B8>dg%__xBR%Q$_O8>dgj z_>JMyZJa*qjMJyr_`2}vGftmP#_3Zv{!sV~7^ly6-Z{p0>&n)w_Syj?hph<0JNaI_akguX-g+Qi!-PBC9N^hbrhEFAi2 z5U1!A4n3cPb_s``{aMR}Lw{`eSA;`9CVdbqg+o6!^xeXt=XHLcapt?pILlu(-j=)& zn~l?dz&Ojfy$P=gNBMso<=<)ip5XP&(;x2l*5E^81vpO44;-99Q8@fh41J67PX%Xr z>9Z!v!R=$dd=Aa}qyE)l*|^R8&j^3kEA``}fE}iv6#9zsvx4^-XZu(){)Nz&kYNgz ze^&4g<8y+~H$E?T+4zFsoyIQ--evro!IvAqEO^EE(%>tNUlqLD_|?JtjPtqsCgVK+ zRE;kWpJKH0SdH1!Mxho9g%;zpcGH25^*M|>pvcNm}AnmONFV|mV- zoO#9cql0%Fe{@FH_Zolvq|CLy5t5G`n)!g~ubqQ*5F*`_l5e~BK`U1gT4twIZqlsct;Gz8JhsTXS z8oXxw$!PDnf3X@Lo+l^7ekbSoZJBYNC)vMBJ8s9tKYvp?a^uIIsCetq)8Tm$k7xg?JUTA#HsI2$r-L1!D zK6FT)(r4nad3m;Ro;Ny;PmJ?PkMUQ6_Zy!vCi`zTzAE@m$1WLXyEDr;pAVLe zza8yVkMWB?k;{W|=n>5K%cZ>hhVd1_hsJq}`j>;3j8BdCYB0V#f_gp=z0f%Om##F< z{-_nk*+14}oc&$>#`#=hi*dHIg*d;moV*@5%{Z?gW*g`A#vR7lAI^R!`v3KmTrWFJ z&wlcu(GNg9pI@&q&gbAejPtq4@Ms_CGjd|icb4&YgO`o3os{*wpQR74XSSN2*FS^e zI-UBPCug4t#>Y&_{6gcrp5grzeV(0~^*c<@>!?GDc|G*Y@@)RwnuglMDC4bZD8oFR z&$-3(7S3s{kEhz2#z3D_Xq}tJ!){%?2n&#(kVZ9bZHN+?vv|p65?=|Y~+y^(pa)-Fyu5W^^!ts8iRRW>sjY~@%TJQbk2I-{I7jIjaE8O zx9R_wZ%Ju!X%o##!>KLihMvv(cBl% zynx4LNSezrJ@TcV9C>MsOAF9=`i@9HfCE6HMdmS!(-ZPP5epJbzu7Y6_H&BE7V}x1<-J280fw*9;ikMBW})T1S)oS>L{ z%D?iTtQd1ho+5wb?fGAl*dFs=nA5db!CEqI{GFfX_LTp9_~)?{eUTpdqbc(IyAp%a zc5|U?QGzKJ9O4!xmI$S!GDoHWU4zl(ksKfYx{zE{k25;N)f4c1-F~zfi$zH{nv?qs!Opw z5@0*f1;g~LSExMigbKY~_?w;&#dR_c!{^h-)8p%9hgc%%d~|z#Qs{{GFfZ-C{V3C( Q(s#s*+K(||Ouhd83zV_%yZ`_I literal 69936 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