@@ -0,0 +1,5 @@ | |||||
*.sw[op] | |||||
*.o | |||||
*.rej | |||||
*.orig | |||||
ses |
@@ -39,6 +39,8 @@ static const Layout layouts[] = { | |||||
{ "[]=", tile }, /* first entry is default */ | { "[]=", tile }, /* first entry is default */ | ||||
{ "><>", NULL }, /* no layout function means floating behavior */ | { "><>", NULL }, /* no layout function means floating behavior */ | ||||
{ "[M]", monocle }, | { "[M]", monocle }, | ||||
{ "|M|", centeredmaster }, | |||||
{ ">M>", centeredfloatingmaster }, | |||||
}; | }; | ||||
/* key definitions */ | /* key definitions */ | ||||
@@ -62,8 +64,10 @@ static Key keys[] = { | |||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } }, | { MODKEY, XK_p, spawn, {.v = dmenucmd } }, | ||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, | { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, | ||||
{ MODKEY, XK_b, togglebar, {0} }, | { MODKEY, XK_b, togglebar, {0} }, | ||||
{ MODKEY, XK_j, focusstack, {.i = +1 } }, | |||||
{ MODKEY, XK_k, focusstack, {.i = -1 } }, | |||||
{ MODKEY, XK_j, focusstackvis, {.i = +1 } }, | |||||
{ MODKEY, XK_k, focusstackvis, {.i = -1 } }, | |||||
{ MODKEY|ShiftMask, XK_j, focusstackhid, {.i = +1 } }, | |||||
{ MODKEY|ShiftMask, XK_k, focusstackhid, {.i = -1 } }, | |||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } }, | { MODKEY, XK_i, incnmaster, {.i = +1 } }, | ||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } }, | { MODKEY, XK_d, incnmaster, {.i = -1 } }, | ||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} }, | { MODKEY, XK_h, setmfact, {.f = -0.05} }, | ||||
@@ -74,6 +78,8 @@ static Key keys[] = { | |||||
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, | { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, | ||||
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, | { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, | ||||
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, | { 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, XK_space, setlayout, {0} }, | ||||
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} }, | { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, | ||||
{ MODKEY, XK_0, view, {.ui = ~0 } }, | { MODKEY, XK_0, view, {.ui = ~0 } }, | ||||
@@ -82,6 +88,8 @@ static Key keys[] = { | |||||
{ MODKEY, XK_period, focusmon, {.i = +1 } }, | { MODKEY, XK_period, focusmon, {.i = +1 } }, | ||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, | { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, | ||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, | { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, | ||||
{ MODKEY, XK_s, show, {0} }, | |||||
{ MODKEY, XK_h, hide, {0} }, | |||||
TAGKEYS( XK_1, 0) | TAGKEYS( XK_1, 0) | ||||
TAGKEYS( XK_2, 1) | TAGKEYS( XK_2, 1) | ||||
TAGKEYS( XK_3, 2) | TAGKEYS( XK_3, 2) | ||||
@@ -100,6 +108,7 @@ static Button buttons[] = { | |||||
/* click event mask button function argument */ | /* click event mask button function argument */ | ||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} }, | { ClkLtSymbol, 0, Button1, setlayout, {0} }, | ||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, | { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, | ||||
{ ClkWinTitle, 0, Button1, togglewin, {0} }, | |||||
{ ClkWinTitle, 0, Button2, zoom, {0} }, | { ClkWinTitle, 0, Button2, zoom, {0} }, | ||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, | { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, | ||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} }, | { ClkClientWin, MODKEY, Button1, movemouse, {0} }, | ||||
@@ -0,0 +1,121 @@ | |||||
/* See LICENSE file for copyright and license details. */ | |||||
/* appearance */ | |||||
static const char *fonts[] = { | |||||
"monospace:size=10" | |||||
}; | |||||
static const char dmenufont[] = "monospace:size=10"; | |||||
static const char normbordercolor[] = "#444444"; | |||||
static const char normbgcolor[] = "#222222"; | |||||
static const char normfgcolor[] = "#bbbbbb"; | |||||
static const char selbordercolor[] = "#005577"; | |||||
static const char selbgcolor[] = "#005577"; | |||||
static const char selfgcolor[] = "#eeeeee"; | |||||
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 */ | |||||
/* tagging */ | |||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; | |||||
static const Rule rules[] = { | |||||
/* xprop(1): | |||||
* WM_CLASS(STRING) = instance, class | |||||
* WM_NAME(STRING) = title | |||||
*/ | |||||
/* class instance title tags mask isfloating monitor */ | |||||
{ "Gimp", NULL, NULL, 0, 1, -1 }, | |||||
{ "Iceweasel", NULL, NULL, 1 << 8, 0, -1 }, | |||||
}; | |||||
/* layout(s) */ | |||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ | |||||
static const int nmaster = 1; /* number of clients in master area */ | |||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ | |||||
static const 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", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; | |||||
static const char *termcmd[] = { "x-terminal-emulator", NULL }; | |||||
static Key keys[] = { | |||||
/* modifier key function argument */ | |||||
{ MODKEY, XK_p, spawn, {.v = dmenucmd } }, | |||||
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, | |||||
{ MODKEY, XK_b, togglebar, {0} }, | |||||
{ MODKEY, XK_j, focusstackvis, {.i = +1 } }, | |||||
{ MODKEY, XK_k, focusstackvis, {.i = -1 } }, | |||||
{ MODKEY|ShiftMask, XK_j, focusstackhid, {.i = +1 } }, | |||||
{ MODKEY|ShiftMask, XK_k, focusstackhid, {.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|ShiftMask, XK_s, show, {0} }, | |||||
{ MODKEY|ShiftMask, XK_h, hide, {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 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, Button1, togglewin, {0} }, | |||||
{ ClkWinTitle, 0, Button2, zoom, {0} }, | |||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, | |||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} }, | |||||
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} }, | |||||
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} }, | |||||
{ ClkTagBar, 0, Button1, view, {0} }, | |||||
{ ClkTagBar, 0, Button3, toggleview, {0} }, | |||||
{ ClkTagBar, MODKEY, Button1, tag, {0} }, | |||||
{ ClkTagBar, MODKEY, Button3, toggletag, {0} }, | |||||
}; |
@@ -0,0 +1,199 @@ | |||||
From ee036687ed9e1bb973b9e34694a57cf5dd67652d Mon Sep 17 00:00:00 2001 | |||||
From: Jonathan Hodgson <git@jonathanh.co.uk> | |||||
Date: Mon, 6 May 2019 18:34:40 +0100 | |||||
Subject: [PATCH 1/4] Adds attach below option | |||||
--- | |||||
config.def.h | 1 + | |||||
dwm.c | 31 ++++++++++++++++++++++++++++--- | |||||
2 files changed, 29 insertions(+), 3 deletions(-) | |||||
diff --git a/config.def.h b/config.def.h | |||||
index 1c0b587..51ad933 100644 | |||||
--- a/config.def.h | |||||
+++ b/config.def.h | |||||
@@ -35,6 +35,7 @@ static const Rule rules[] = { | |||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ | |||||
static const int nmaster = 1; /* number of clients in master area */ | |||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ | |||||
+static const int attachbelow = 1; /* 1 means attach at the end */ | |||||
static const Layout layouts[] = { | |||||
/* symbol arrange function */ | |||||
diff --git a/dwm.c b/dwm.c | |||||
index 4465af1..bd715a2 100644 | |||||
--- a/dwm.c | |||||
+++ b/dwm.c | |||||
@@ -147,6 +147,7 @@ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interac | |||||
static void arrange(Monitor *m); | |||||
static void arrangemon(Monitor *m); | |||||
static void attach(Client *c); | |||||
+static void attachBelow(Client *c); | |||||
static void attachstack(Client *c); | |||||
static void buttonpress(XEvent *e); | |||||
static void checkotherwm(void); | |||||
@@ -405,6 +406,21 @@ attach(Client *c) | |||||
c->next = c->mon->clients; | |||||
c->mon->clients = c; | |||||
} | |||||
+void | |||||
+attachBelow(Client *c) | |||||
+{ | |||||
+ //If there is nothing on the monitor or the selected client is floating, attach as normal | |||||
+ if(c->mon->sel == NULL || c->mon->sel == c || c->mon->sel->isfloating) { | |||||
+ attach(c); | |||||
+ return; | |||||
+ } | |||||
+ | |||||
+ //Set the new client's next property to the same as the currently selected clients next | |||||
+ c->next = c->mon->sel->next; | |||||
+ //Set the currently selected clients next property to the new client | |||||
+ c->mon->sel->next = c; | |||||
+ | |||||
+} | |||||
void | |||||
attachstack(Client *c) | |||||
@@ -1062,7 +1078,10 @@ manage(Window w, XWindowAttributes *wa) | |||||
c->isfloating = c->oldstate = trans != None || c->isfixed; | |||||
if (c->isfloating) | |||||
XRaiseWindow(dpy, c->win); | |||||
- attach(c); | |||||
+ if( attachbelow ) | |||||
+ attachBelow(c); | |||||
+ else | |||||
+ attach(c); | |||||
attachstack(c); | |||||
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, | |||||
(unsigned char *) &(c->win), 1); | |||||
@@ -1417,7 +1436,10 @@ sendmon(Client *c, Monitor *m) | |||||
detachstack(c); | |||||
c->mon = m; | |||||
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ | |||||
- attach(c); | |||||
+ if( attachbelow ) | |||||
+ attachBelow(c); | |||||
+ else | |||||
+ attach(c); | |||||
attachstack(c); | |||||
focus(NULL); | |||||
arrange(NULL); | |||||
@@ -1897,7 +1919,10 @@ updategeom(void) | |||||
m->clients = c->next; | |||||
detachstack(c); | |||||
c->mon = mons; | |||||
- attach(c); | |||||
+ if( attachbelow ) | |||||
+ attachBelow(c); | |||||
+ else | |||||
+ attach(c); | |||||
attachstack(c); | |||||
} | |||||
if (m == selmon) | |||||
-- | |||||
2.21.0 | |||||
From e212c1d8cbdcc56c33c717131dfa7c1689e27e9f Mon Sep 17 00:00:00 2001 | |||||
From: Jonathan Hodgson <git@jonathanh.co.uk> | |||||
Date: Mon, 6 May 2019 19:27:57 +0100 | |||||
Subject: [PATCH 2/4] fixes comment | |||||
--- | |||||
config.def.h | 2 +- | |||||
1 file changed, 1 insertion(+), 1 deletion(-) | |||||
diff --git a/config.def.h b/config.def.h | |||||
index 51ad933..cb8053a 100644 | |||||
--- a/config.def.h | |||||
+++ b/config.def.h | |||||
@@ -35,7 +35,7 @@ static const Rule rules[] = { | |||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ | |||||
static const int nmaster = 1; /* number of clients in master area */ | |||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ | |||||
-static const int attachbelow = 1; /* 1 means attach at the end */ | |||||
+static const int attachbelow = 1; /* 1 means attach after the currently active window */ | |||||
static const Layout layouts[] = { | |||||
/* symbol arrange function */ | |||||
-- | |||||
2.21.0 | |||||
From 7568ea3f8756e7e82b30c4943556ae646a445d1c Mon Sep 17 00:00:00 2001 | |||||
From: Jonathan Hodgson <git@jonathanh.co.uk> | |||||
Date: Mon, 6 May 2019 20:00:30 +0100 | |||||
Subject: [PATCH 3/4] Makes changes to man page to reflect attach below patch | |||||
--- | |||||
dwm.1 | 3 +++ | |||||
1 file changed, 3 insertions(+) | |||||
diff --git a/dwm.1 b/dwm.1 | |||||
index 13b3729..fb6e76c 100644 | |||||
--- a/dwm.1 | |||||
+++ b/dwm.1 | |||||
@@ -29,6 +29,9 @@ color. The tags of the focused window are indicated with a filled square in the | |||||
top left corner. The tags which are applied to one or more windows are | |||||
indicated with an empty square in the top left corner. | |||||
.P | |||||
+The attach below patch makes newly spawned windows attach after the currently | |||||
+selected window | |||||
+.P | |||||
dwm draws a small border around windows to indicate the focus state. | |||||
.SH OPTIONS | |||||
.TP | |||||
-- | |||||
2.21.0 | |||||
From 362b95a5b9f91673f27f3e3343b5738df3c9d6e9 Mon Sep 17 00:00:00 2001 | |||||
From: Jonathan Hodgson <git@jonathanh.co.uk> | |||||
Date: Sun, 2 Jun 2019 15:11:57 +0100 | |||||
Subject: [PATCH 4/4] Allows attach below to be toggled | |||||
--- | |||||
config.def.h | 2 +- | |||||
dwm.c | 6 ++++++ | |||||
2 files changed, 7 insertions(+), 1 deletion(-) | |||||
diff --git a/config.def.h b/config.def.h | |||||
index cb8053a..b4d35aa 100644 | |||||
--- a/config.def.h | |||||
+++ b/config.def.h | |||||
@@ -35,7 +35,7 @@ static const Rule rules[] = { | |||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ | |||||
static const int nmaster = 1; /* number of clients in master area */ | |||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ | |||||
-static const int attachbelow = 1; /* 1 means attach after the currently active window */ | |||||
+static int attachbelow = 1; /* 1 means attach after the currently active window */ | |||||
static const Layout layouts[] = { | |||||
/* symbol arrange function */ | |||||
diff --git a/dwm.c b/dwm.c | |||||
index bd715a2..5d88653 100644 | |||||
--- a/dwm.c | |||||
+++ b/dwm.c | |||||
@@ -148,6 +148,7 @@ static void arrange(Monitor *m); | |||||
static void arrangemon(Monitor *m); | |||||
static void attach(Client *c); | |||||
static void attachBelow(Client *c); | |||||
+static void toggleAttachBelow(); | |||||
static void attachstack(Client *c); | |||||
static void buttonpress(XEvent *e); | |||||
static void checkotherwm(void); | |||||
@@ -422,6 +423,11 @@ attachBelow(Client *c) | |||||
} | |||||
+void toggleAttachBelow() | |||||
+{ | |||||
+ attachbelow = !attachbelow; | |||||
+} | |||||
+ | |||||
void | |||||
attachstack(Client *c) | |||||
{ | |||||
-- | |||||
2.21.0 | |||||
@@ -0,0 +1,431 @@ | |||||
diff --git a/config.def.h b/config.def.h | |||||
index 1c0b587..bb8f3f7 100644 | |||||
--- a/config.def.h | |||||
+++ b/config.def.h | |||||
@@ -16,6 +16,7 @@ static const char *colors[][3] = { | |||||
/* fg bg border */ | |||||
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, | |||||
[SchemeSel] = { col_gray4, col_cyan, col_cyan }, | |||||
+ [SchemeHid] = { col_cyan, col_gray1, col_cyan }, | |||||
}; | |||||
/* tagging */ | |||||
@@ -64,8 +65,10 @@ static Key keys[] = { | |||||
{ 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_j, focusstackvis, {.i = +1 } }, | |||||
+ { MODKEY, XK_k, focusstackvis, {.i = -1 } }, | |||||
+ { MODKEY|ShiftMask, XK_j, focusstackhid, {.i = +1 } }, | |||||
+ { MODKEY|ShiftMask, XK_k, focusstackhid, {.i = -1 } }, | |||||
{ MODKEY, XK_i, incnmaster, {.i = +1 } }, | |||||
{ MODKEY, XK_d, incnmaster, {.i = -1 } }, | |||||
{ MODKEY, XK_h, setmfact, {.f = -0.05} }, | |||||
@@ -84,6 +87,8 @@ static Key keys[] = { | |||||
{ MODKEY, XK_period, focusmon, {.i = +1 } }, | |||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, | |||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, | |||||
+ { MODKEY, XK_s, show, {0} }, | |||||
+ { MODKEY, XK_h, hide, {0} }, | |||||
TAGKEYS( XK_1, 0) | |||||
TAGKEYS( XK_2, 1) | |||||
TAGKEYS( XK_3, 2) | |||||
@@ -102,6 +107,7 @@ static Button buttons[] = { | |||||
/* click event mask button function argument */ | |||||
{ ClkLtSymbol, 0, Button1, setlayout, {0} }, | |||||
{ ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, | |||||
+ { ClkWinTitle, 0, Button1, togglewin, {0} }, | |||||
{ ClkWinTitle, 0, Button2, zoom, {0} }, | |||||
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, | |||||
{ ClkClientWin, MODKEY, Button1, movemouse, {0} }, | |||||
diff --git a/dwm.c b/dwm.c | |||||
index 4465af1..e780189 100644 | |||||
--- a/dwm.c | |||||
+++ b/dwm.c | |||||
@@ -50,6 +50,7 @@ | |||||
#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 HIDDEN(C) ((getstate(C->win) == IconicState)) | |||||
#define LENGTH(X) (sizeof X / sizeof X[0]) | |||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask) | |||||
#define WIDTH(X) ((X)->w + 2 * (X)->bw) | |||||
@@ -59,7 +60,7 @@ | |||||
/* enums */ | |||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ | |||||
-enum { SchemeNorm, SchemeSel }; /* color schemes */ | |||||
+enum { SchemeNorm, SchemeSel, SchemeHid }; /* color schemes */ | |||||
enum { NetSupported, NetWMName, NetWMState, NetWMCheck, | |||||
NetWMFullscreen, NetActiveWindow, NetWMWindowType, | |||||
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ | |||||
@@ -117,6 +118,8 @@ struct Monitor { | |||||
int nmaster; | |||||
int num; | |||||
int by; /* bar geometry */ | |||||
+ int btw; /* width of tasks portion of bar */ | |||||
+ int bt; /* number of tasks */ | |||||
int mx, my, mw, mh; /* screen size */ | |||||
int wx, wy, ww, wh; /* window area */ | |||||
unsigned int seltags; | |||||
@@ -124,6 +127,7 @@ struct Monitor { | |||||
unsigned int tagset[2]; | |||||
int showbar; | |||||
int topbar; | |||||
+ int hidsel; | |||||
Client *clients; | |||||
Client *sel; | |||||
Client *stack; | |||||
@@ -168,12 +172,16 @@ 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 focusstackvis(const Arg *arg); | |||||
+static void focusstackhid(const Arg *arg); | |||||
+static void focusstack(int inc, int vis); | |||||
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 hide(const Arg *arg); | |||||
+static void hidewin(Client *c); | |||||
static void incnmaster(const Arg *arg); | |||||
static void keypress(XEvent *e); | |||||
static void killclient(const Arg *arg); | |||||
@@ -203,6 +211,8 @@ 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 show(const Arg *arg); | |||||
+static void showwin(Client *c); | |||||
static void showhide(Client *c); | |||||
static void sigchld(int unused); | |||||
static void spawn(const Arg *arg); | |||||
@@ -213,6 +223,7 @@ static void togglebar(const Arg *arg); | |||||
static void togglefloating(const Arg *arg); | |||||
static void toggletag(const Arg *arg); | |||||
static void toggleview(const Arg *arg); | |||||
+static void togglewin(const Arg *arg); | |||||
static void unfocus(Client *c, int setfocus); | |||||
static void unmanage(Client *c, int destroyed); | |||||
static void unmapnotify(XEvent *e); | |||||
@@ -439,10 +450,25 @@ buttonpress(XEvent *e) | |||||
arg.ui = 1 << i; | |||||
} else if (ev->x < x + blw) | |||||
click = ClkLtSymbol; | |||||
- else if (ev->x > selmon->ww - TEXTW(stext)) | |||||
+ /* 2px right padding */ | |||||
+ else if (ev->x > selmon->ww - TEXTW(stext) + lrpad - 2) | |||||
click = ClkStatusText; | |||||
- else | |||||
- click = ClkWinTitle; | |||||
+ else { | |||||
+ x += blw; | |||||
+ c = m->clients; | |||||
+ | |||||
+ if (c) { | |||||
+ do { | |||||
+ if (!ISVISIBLE(c)) | |||||
+ continue; | |||||
+ else | |||||
+ x += (1.0 / (double)m->bt) * m->btw; | |||||
+ } while (ev->x > x && (c = c->next)); | |||||
+ | |||||
+ click = ClkWinTitle; | |||||
+ arg.v = c; | |||||
+ } | |||||
+ } | |||||
} else if ((c = wintoclient(ev->window))) { | |||||
focus(c); | |||||
restack(selmon); | |||||
@@ -452,7 +478,7 @@ buttonpress(XEvent *e) | |||||
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); | |||||
+ buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); | |||||
} | |||||
void | |||||
@@ -695,7 +721,7 @@ dirtomon(int dir) | |||||
void | |||||
drawbar(Monitor *m) | |||||
{ | |||||
- int x, w, sw = 0; | |||||
+ int x, w, sw = 0, n = 0, scm; | |||||
int boxs = drw->fonts->h / 9; | |||||
int boxw = drw->fonts->h / 6 + 2; | |||||
unsigned int i, occ = 0, urg = 0; | |||||
@@ -709,6 +735,8 @@ drawbar(Monitor *m) | |||||
} | |||||
for (c = m->clients; c; c = c->next) { | |||||
+ if (ISVISIBLE(c)) | |||||
+ n++; | |||||
occ |= c->tags; | |||||
if (c->isurgent) | |||||
urg |= c->tags; | |||||
@@ -729,16 +757,37 @@ drawbar(Monitor *m) | |||||
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 (n > 0) { | |||||
+ int remainder = w % n; | |||||
+ int tabw = (1.0 / (double)n) * w + 1; | |||||
+ for (c = m->clients; c; c = c->next) { | |||||
+ if (!ISVISIBLE(c)) | |||||
+ continue; | |||||
+ if (m->sel == c) | |||||
+ scm = SchemeSel; | |||||
+ else if (HIDDEN(c)) | |||||
+ scm = SchemeHid; | |||||
+ else | |||||
+ scm = SchemeNorm; | |||||
+ drw_setscheme(drw, scheme[scm]); | |||||
+ | |||||
+ if (remainder >= 0) { | |||||
+ if (remainder == 0) { | |||||
+ tabw--; | |||||
+ } | |||||
+ remainder--; | |||||
+ } | |||||
+ drw_text(drw, x, 0, tabw, bh, lrpad / 2, c->name, 0); | |||||
+ x += tabw; | |||||
+ } | |||||
} else { | |||||
drw_setscheme(drw, scheme[SchemeNorm]); | |||||
drw_rect(drw, x, 0, w, bh, 1, 1); | |||||
} | |||||
} | |||||
+ | |||||
+ m->bt = n; | |||||
+ m->btw = w; | |||||
drw_map(drw, m->barwin, 0, 0, m->ww, bh); | |||||
} | |||||
@@ -784,9 +833,17 @@ void | |||||
focus(Client *c) | |||||
{ | |||||
if (!c || !ISVISIBLE(c)) | |||||
- for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); | |||||
- if (selmon->sel && selmon->sel != c) | |||||
+ for (c = selmon->stack; c && (!ISVISIBLE(c) || HIDDEN(c)); c = c->snext); | |||||
+ if (selmon->sel && selmon->sel != c) { | |||||
unfocus(selmon->sel, 0); | |||||
+ | |||||
+ if (selmon->hidsel) { | |||||
+ hidewin(selmon->sel); | |||||
+ if (c) | |||||
+ arrange(c->mon); | |||||
+ selmon->hidsel = 0; | |||||
+ } | |||||
+ } | |||||
if (c) { | |||||
if (c->mon != selmon) | |||||
selmon = c->mon; | |||||
@@ -830,28 +887,57 @@ focusmon(const Arg *arg) | |||||
} | |||||
void | |||||
-focusstack(const Arg *arg) | |||||
+focusstackvis(const Arg *arg) | |||||
+{ | |||||
+ focusstack(arg->i, 0); | |||||
+} | |||||
+ | |||||
+void | |||||
+focusstackhid(const Arg *arg) | |||||
+{ | |||||
+ focusstack(arg->i, 1); | |||||
+} | |||||
+ | |||||
+void | |||||
+focusstack(int inc, int hid) | |||||
{ | |||||
Client *c = NULL, *i; | |||||
- if (!selmon->sel) | |||||
+ if (!selmon->sel && !hid) | |||||
return; | |||||
- if (arg->i > 0) { | |||||
- for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); | |||||
+ if (!selmon->clients) | |||||
+ return; | |||||
+ | |||||
+ if (inc > 0) { | |||||
+ if (selmon->sel) | |||||
+ for (c = selmon->sel->next; | |||||
+ c && (!ISVISIBLE(c) || (!hid && HIDDEN(c))); | |||||
+ c = c->next); | |||||
if (!c) | |||||
- for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); | |||||
+ for (c = selmon->clients; | |||||
+ c && (!ISVISIBLE(c) || (!hid && HIDDEN(c))); | |||||
+ c = c->next); | |||||
} else { | |||||
- for (i = selmon->clients; i != selmon->sel; i = i->next) | |||||
- if (ISVISIBLE(i)) | |||||
- c = i; | |||||
+ if (selmon->sel) { | |||||
+ for (i = selmon->clients; i != selmon->sel; i = i->next) | |||||
+ if (ISVISIBLE(i) && !(!hid && HIDDEN(i))) | |||||
+ c = i; | |||||
+ } else | |||||
+ c = selmon->clients; | |||||
if (!c) | |||||
for (; i; i = i->next) | |||||
- if (ISVISIBLE(i)) | |||||
+ if (ISVISIBLE(i) && !(!hid && HIDDEN(i))) | |||||
c = i; | |||||
} | |||||
+ | |||||
if (c) { | |||||
focus(c); | |||||
restack(selmon); | |||||
+ | |||||
+ if (HIDDEN(c)) { | |||||
+ showwin(c); | |||||
+ c->mon->hidsel = 1; | |||||
+ } | |||||
} | |||||
} | |||||
@@ -963,6 +1049,36 @@ grabkeys(void) | |||||
} | |||||
} | |||||
+void | |||||
+hide(const Arg *arg) | |||||
+{ | |||||
+ hidewin(selmon->sel); | |||||
+ focus(NULL); | |||||
+ arrange(selmon); | |||||
+} | |||||
+ | |||||
+void | |||||
+hidewin(Client *c) { | |||||
+ if (!c || HIDDEN(c)) | |||||
+ return; | |||||
+ | |||||
+ Window w = c->win; | |||||
+ static XWindowAttributes ra, ca; | |||||
+ | |||||
+ // more or less taken directly from blackbox's hide() function | |||||
+ XGrabServer(dpy); | |||||
+ XGetWindowAttributes(dpy, root, &ra); | |||||
+ XGetWindowAttributes(dpy, w, &ca); | |||||
+ // prevent UnmapNotify events | |||||
+ XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask); | |||||
+ XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask); | |||||
+ XUnmapWindow(dpy, w); | |||||
+ setclientstate(c, IconicState); | |||||
+ XSelectInput(dpy, root, ra.your_event_mask); | |||||
+ XSelectInput(dpy, w, ca.your_event_mask); | |||||
+ XUngrabServer(dpy); | |||||
+} | |||||
+ | |||||
void | |||||
incnmaster(const Arg *arg) | |||||
{ | |||||
@@ -1067,12 +1183,14 @@ manage(Window w, XWindowAttributes *wa) | |||||
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 (!HIDDEN(c)) | |||||
+ setclientstate(c, NormalState); | |||||
if (c->mon == selmon) | |||||
unfocus(selmon->sel, 0); | |||||
c->mon->sel = c; | |||||
arrange(c->mon); | |||||
- XMapWindow(dpy, c->win); | |||||
+ if (!HIDDEN(c)) | |||||
+ XMapWindow(dpy, c->win); | |||||
focus(NULL); | |||||
} | |||||
@@ -1195,7 +1313,7 @@ movemouse(const Arg *arg) | |||||
Client * | |||||
nexttiled(Client *c) | |||||
{ | |||||
- for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); | |||||
+ for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next); | |||||
return c; | |||||
} | |||||
@@ -1248,6 +1366,16 @@ propertynotify(XEvent *e) | |||||
void | |||||
quit(const Arg *arg) | |||||
{ | |||||
+ // fix: reloading dwm keeps all the hidden clients hidden | |||||
+ Monitor *m; | |||||
+ Client *c; | |||||
+ for (m = mons; m; m = m->next) { | |||||
+ if (m) { | |||||
+ for (c = m->stack; c; c = c->next) | |||||
+ if (c && HIDDEN(c)) showwin(c); | |||||
+ } | |||||
+ } | |||||
+ | |||||
running = 0; | |||||
} | |||||
@@ -1610,6 +1738,25 @@ seturgent(Client *c, int urg) | |||||
XFree(wmh); | |||||
} | |||||
+void | |||||
+show(const Arg *arg) | |||||
+{ | |||||
+ if (selmon->hidsel) | |||||
+ selmon->hidsel = 0; | |||||
+ showwin(selmon->sel); | |||||
+} | |||||
+ | |||||
+void | |||||
+showwin(Client *c) | |||||
+{ | |||||
+ if (!c || !HIDDEN(c)) | |||||
+ return; | |||||
+ | |||||
+ XMapWindow(dpy, c->win); | |||||
+ setclientstate(c, NormalState); | |||||
+ arrange(c->mon); | |||||
+} | |||||
+ | |||||
void | |||||
showhide(Client *c) | |||||
{ | |||||
@@ -1746,6 +1893,23 @@ toggleview(const Arg *arg) | |||||
} | |||||
} | |||||
+void | |||||
+togglewin(const Arg *arg) | |||||
+{ | |||||
+ Client *c = (Client*)arg->v; | |||||
+ | |||||
+ if (c == selmon->sel) { | |||||
+ hidewin(c); | |||||
+ focus(NULL); | |||||
+ arrange(c->mon); | |||||
+ } else { | |||||
+ if (HIDDEN(c)) | |||||
+ showwin(c); | |||||
+ focus(c); | |||||
+ restack(selmon); | |||||
+ } | |||||
+} | |||||
+ | |||||
void | |||||
unfocus(Client *c, int setfocus) | |||||
{ |
@@ -0,0 +1,142 @@ | |||||
diff --git a/config.def.h b/config.def.h | |||||
index 7054c06..527b214 100644 | |||||
--- a/config.def.h | |||||
+++ b/config.def.h | |||||
@@ -39,6 +39,8 @@ static const Layout layouts[] = { | |||||
{ "[]=", tile }, /* first entry is default */ | |||||
{ "><>", NULL }, /* no layout function means floating behavior */ | |||||
{ "[M]", monocle }, | |||||
+ { "|M|", centeredmaster }, | |||||
+ { ">M>", centeredfloatingmaster }, | |||||
}; | |||||
/* key definitions */ | |||||
@@ -74,6 +76,8 @@ static Key keys[] = { | |||||
{ 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 } }, | |||||
diff --git a/dwm.c b/dwm.c | |||||
index 0362114..1e81412 100644 | |||||
--- a/dwm.c | |||||
+++ b/dwm.c | |||||
@@ -233,6 +233,8 @@ 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); | |||||
/* variables */ | |||||
static const char broken[] = "broken"; | |||||
@@ -2139,3 +2141,106 @@ main(int argc, char *argv[]) | |||||
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); | |||||
+ } | |||||
+} |
@@ -0,0 +1,95 @@ | |||||
diff --git a/config.def.h b/config.def.h | |||||
index 1c0b587..38d2f6c 100644 | |||||
--- a/config.def.h | |||||
+++ b/config.def.h | |||||
@@ -2,6 +2,7 @@ | |||||
/* appearance */ | |||||
static const unsigned int borderpx = 1; /* border pixel of windows */ | |||||
+static const unsigned int gappx = 5; /* gaps between windows */ | |||||
static const unsigned int snap = 32; /* snap pixel */ | |||||
static const int showbar = 1; /* 0 means no bar */ | |||||
static const int topbar = 1; /* 0 means bottom bar */ | |||||
@@ -84,6 +85,9 @@ static Key keys[] = { | |||||
{ MODKEY, XK_period, focusmon, {.i = +1 } }, | |||||
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, | |||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, | |||||
+ { MODKEY, XK_minus, setgaps, {.i = -1 } }, | |||||
+ { MODKEY, XK_equal, setgaps, {.i = +1 } }, | |||||
+ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, | |||||
TAGKEYS( XK_1, 0) | |||||
TAGKEYS( XK_2, 1) | |||||
TAGKEYS( XK_3, 2) | |||||
diff --git a/dwm.c b/dwm.c | |||||
index 4465af1..4363627 100644 | |||||
--- a/dwm.c | |||||
+++ b/dwm.c | |||||
@@ -119,6 +119,7 @@ struct Monitor { | |||||
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]; | |||||
@@ -199,6 +200,7 @@ 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); | |||||
@@ -638,6 +640,7 @@ createmon(void) | |||||
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); | |||||
@@ -1497,6 +1500,16 @@ setfullscreen(Client *c, int fullscreen) | |||||
} | |||||
} | |||||
+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) | |||||
{ | |||||
@@ -1683,16 +1696,16 @@ tile(Monitor *m) | |||||
if (n > m->nmaster) | |||||
mw = m->nmaster ? m->ww * m->mfact : 0; | |||||
else | |||||
- mw = m->ww; | |||||
- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) | |||||
+ 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); | |||||
- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0); | |||||
- my += HEIGHT(c); | |||||
+ 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); | |||||
- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), 0); | |||||
- ty += HEIGHT(c); | |||||
+ 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; | |||||
} | |||||
} | |||||
-- | |||||
2.20.1 | |||||
@@ -50,6 +50,7 @@ | |||||
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ | #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))) | * 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 ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) | ||||
#define HIDDEN(C) ((getstate(C->win) == IconicState)) | |||||
#define LENGTH(X) (sizeof X / sizeof X[0]) | #define LENGTH(X) (sizeof X / sizeof X[0]) | ||||
#define MOUSEMASK (BUTTONMASK|PointerMotionMask) | #define MOUSEMASK (BUTTONMASK|PointerMotionMask) | ||||
#define WIDTH(X) ((X)->w + 2 * (X)->bw) | #define WIDTH(X) ((X)->w + 2 * (X)->bw) | ||||
@@ -59,7 +60,7 @@ | |||||
/* enums */ | /* enums */ | ||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ | enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ | ||||
enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */ | |||||
enum { SchemeNorm, SchemeSel, SchemeHid, SchemeLast }; /* color schemes */ | |||||
enum { NetSupported, NetWMName, NetWMState, | enum { NetSupported, NetWMName, NetWMState, | ||||
NetWMFullscreen, NetActiveWindow, NetWMWindowType, | NetWMFullscreen, NetActiveWindow, NetWMWindowType, | ||||
NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ | NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ | ||||
@@ -117,6 +118,8 @@ struct Monitor { | |||||
int nmaster; | int nmaster; | ||||
int num; | int num; | ||||
int by; /* bar geometry */ | int by; /* bar geometry */ | ||||
int btw; /* width of tasks portion of bar */ | |||||
int bt; /* number of tasks */ | |||||
int mx, my, mw, mh; /* screen size */ | int mx, my, mw, mh; /* screen size */ | ||||
int wx, wy, ww, wh; /* window area */ | int wx, wy, ww, wh; /* window area */ | ||||
unsigned int seltags; | unsigned int seltags; | ||||
@@ -124,6 +127,7 @@ struct Monitor { | |||||
unsigned int tagset[2]; | unsigned int tagset[2]; | ||||
int showbar; | int showbar; | ||||
int topbar; | int topbar; | ||||
int hidsel; | |||||
Client *clients; | Client *clients; | ||||
Client *sel; | Client *sel; | ||||
Client *stack; | Client *stack; | ||||
@@ -169,12 +173,16 @@ static void expose(XEvent *e); | |||||
static void focus(Client *c); | static void focus(Client *c); | ||||
static void focusin(XEvent *e); | static void focusin(XEvent *e); | ||||
static void focusmon(const Arg *arg); | static void focusmon(const Arg *arg); | ||||
static void focusstack(const Arg *arg); | |||||
static void focusstackvis(const Arg *arg); | |||||
static void focusstackhid(const Arg *arg); | |||||
static void focusstack(int inc, int vis); | |||||
static int getrootptr(int *x, int *y); | static int getrootptr(int *x, int *y); | ||||
static long getstate(Window w); | static long getstate(Window w); | ||||
static int gettextprop(Window w, Atom atom, char *text, unsigned int size); | static int gettextprop(Window w, Atom atom, char *text, unsigned int size); | ||||
static void grabbuttons(Client *c, int focused); | static void grabbuttons(Client *c, int focused); | ||||
static void grabkeys(void); | static void grabkeys(void); | ||||
static void hide(const Arg *arg); | |||||
static void hidewin(Client *c); | |||||
static void incnmaster(const Arg *arg); | static void incnmaster(const Arg *arg); | ||||
static void keypress(XEvent *e); | static void keypress(XEvent *e); | ||||
static void killclient(const Arg *arg); | static void killclient(const Arg *arg); | ||||
@@ -203,6 +211,8 @@ static void setfullscreen(Client *c, int fullscreen); | |||||
static void setlayout(const Arg *arg); | static void setlayout(const Arg *arg); | ||||
static void setmfact(const Arg *arg); | static void setmfact(const Arg *arg); | ||||
static void setup(void); | static void setup(void); | ||||
static void show(const Arg *arg); | |||||
static void showwin(Client *c); | |||||
static void showhide(Client *c); | static void showhide(Client *c); | ||||
static void sigchld(int unused); | static void sigchld(int unused); | ||||
static void spawn(const Arg *arg); | static void spawn(const Arg *arg); | ||||
@@ -213,6 +223,7 @@ static void togglebar(const Arg *arg); | |||||
static void togglefloating(const Arg *arg); | static void togglefloating(const Arg *arg); | ||||
static void toggletag(const Arg *arg); | static void toggletag(const Arg *arg); | ||||
static void toggleview(const Arg *arg); | static void toggleview(const Arg *arg); | ||||
static void togglewin(const Arg *arg); | |||||
static void unfocus(Client *c, int setfocus); | static void unfocus(Client *c, int setfocus); | ||||
static void unmanage(Client *c, int destroyed); | static void unmanage(Client *c, int destroyed); | ||||
static void unmapnotify(XEvent *e); | static void unmapnotify(XEvent *e); | ||||
@@ -233,6 +244,8 @@ static int xerror(Display *dpy, XErrorEvent *ee); | |||||
static int xerrordummy(Display *dpy, XErrorEvent *ee); | static int xerrordummy(Display *dpy, XErrorEvent *ee); | ||||
static int xerrorstart(Display *dpy, XErrorEvent *ee); | static int xerrorstart(Display *dpy, XErrorEvent *ee); | ||||
static void zoom(const Arg *arg); | static void zoom(const Arg *arg); | ||||
static void centeredmaster(Monitor *m); | |||||
static void centeredfloatingmaster(Monitor *m); | |||||
/* variables */ | /* variables */ | ||||
static const char broken[] = "broken"; | static const char broken[] = "broken"; | ||||
@@ -438,10 +451,25 @@ buttonpress(XEvent *e) | |||||
arg.ui = 1 << i; | arg.ui = 1 << i; | ||||
} else if (ev->x < x + blw) | } else if (ev->x < x + blw) | ||||
click = ClkLtSymbol; | click = ClkLtSymbol; | ||||
/* 2px right padding */ | |||||
else if (ev->x > selmon->ww - TEXTW(stext)) | else if (ev->x > selmon->ww - TEXTW(stext)) | ||||
click = ClkStatusText; | click = ClkStatusText; | ||||
else | |||||
click = ClkWinTitle; | |||||
else { | |||||
x += blw; | |||||
c = m->clients; | |||||
if (c) { | |||||
do { | |||||
if (!ISVISIBLE(c)) | |||||
continue; | |||||
else | |||||
x += (1.0 / (double)m->bt) * m->btw; | |||||
} while (ev->x > x && (c = c->next)); | |||||
click = ClkWinTitle; | |||||
arg.v = c; | |||||
} | |||||
} | |||||
} else if ((c = wintoclient(ev->window))) { | } else if ((c = wintoclient(ev->window))) { | ||||
focus(c); | focus(c); | ||||
click = ClkClientWin; | click = ClkClientWin; | ||||
@@ -449,7 +477,7 @@ buttonpress(XEvent *e) | |||||
for (i = 0; i < LENGTH(buttons); i++) | for (i = 0; i < LENGTH(buttons); i++) | ||||
if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button | if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button | ||||
&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) | && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) | ||||
buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); | |||||
buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg); | |||||
} | } | ||||
void | void | ||||
@@ -704,13 +732,15 @@ dirtomon(int dir) | |||||
void | void | ||||
drawbar(Monitor *m) | drawbar(Monitor *m) | ||||
{ | { | ||||
int x, xx, w, dx; | |||||
int xx, x, w, sw = 0, n = 0, scm; | |||||
unsigned int i, occ = 0, urg = 0; | unsigned int i, occ = 0, urg = 0; | ||||
Client *c; | Client *c; | ||||
dx = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4; | |||||
x = (drw->fonts[0]->ascent + drw->fonts[0]->descent + 2) / 4; | |||||
for (c = m->clients; c; c = c->next) { | for (c = m->clients; c; c = c->next) { | ||||
if (ISVISIBLE(c)) | |||||
n++; | |||||
occ |= c->tags; | occ |= c->tags; | ||||
if (c->isurgent) | if (c->isurgent) | ||||
urg |= c->tags; | urg |= c->tags; | ||||
@@ -720,7 +750,7 @@ drawbar(Monitor *m) | |||||
w = TEXTW(tags[i]); | w = TEXTW(tags[i]); | ||||
drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]); | drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]); | ||||
drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i); | drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i); | ||||
drw_rect(drw, x + 1, 1, dx, dx, m == selmon && selmon->sel && selmon->sel->tags & 1 << i, | |||||
drw_rect(drw, x + 1, 1, x, x, m == selmon && selmon->sel && selmon->sel->tags & 1 << i, | |||||
occ & 1 << i, urg & 1 << i); | occ & 1 << i, urg & 1 << i); | ||||
x += w; | x += w; | ||||
} | } | ||||
@@ -741,10 +771,29 @@ drawbar(Monitor *m) | |||||
x = m->ww; | x = m->ww; | ||||
if ((w = x - xx) > bh) { | if ((w = x - xx) > bh) { | ||||
x = xx; | x = xx; | ||||
if (m->sel) { | |||||
drw_setscheme(drw, m == selmon ? &scheme[SchemeSel] : &scheme[SchemeNorm]); | |||||
drw_text(drw, x, 0, w, bh, m->sel->name, 0); | |||||
drw_rect(drw, x + 1, 1, dx, dx, m->sel->isfixed, m->sel->isfloating, 0); | |||||
if (n > 0) { | |||||
int remainder = w % n; | |||||
int tabw = (1.0 / (double)n) * w + 1; | |||||
for (c = m->clients; c; c = c->next) { | |||||
if (!ISVISIBLE(c)) | |||||
continue; | |||||
if (m->sel == c) | |||||
scm = SchemeSel; | |||||
else if (HIDDEN(c)) | |||||
scm = SchemeHid; | |||||
else | |||||
scm = SchemeNorm; | |||||
drw_setscheme(drw, &scheme[scm]); | |||||
if (remainder >= 0) { | |||||
if (remainder == 0) { | |||||
tabw--; | |||||
} | |||||
remainder--; | |||||
} | |||||
drw_text(drw, x, 0, tabw, bh, c->name, 0); | |||||
x += tabw; | |||||
} | |||||
} else { | } else { | ||||
drw_setscheme(drw, &scheme[SchemeNorm]); | drw_setscheme(drw, &scheme[SchemeNorm]); | ||||
drw_rect(drw, x, 0, w, bh, 1, 0, 1); | drw_rect(drw, x, 0, w, bh, 1, 0, 1); | ||||
@@ -795,10 +844,17 @@ void | |||||
focus(Client *c) | focus(Client *c) | ||||
{ | { | ||||
if (!c || !ISVISIBLE(c)) | if (!c || !ISVISIBLE(c)) | ||||
for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); | |||||
/* was if (selmon->sel) */ | |||||
if (selmon->sel && selmon->sel != c) | |||||
for (c = selmon->stack; c && (!ISVISIBLE(c) || HIDDEN(c)); c = c->snext); | |||||
if (selmon->sel && selmon->sel != c) { | |||||
unfocus(selmon->sel, 0); | unfocus(selmon->sel, 0); | ||||
if (selmon->hidsel) { | |||||
hidewin(selmon->sel); | |||||
if (c) | |||||
arrange(c->mon); | |||||
selmon->hidsel = 0; | |||||
} | |||||
} | |||||
if (c) { | if (c) { | ||||
if (c->mon != selmon) | if (c->mon != selmon) | ||||
selmon = c->mon; | selmon = c->mon; | ||||
@@ -843,28 +899,57 @@ focusmon(const Arg *arg) | |||||
} | } | ||||
void | void | ||||
focusstack(const Arg *arg) | |||||
focusstackvis(const Arg *arg) | |||||
{ | |||||
focusstack(arg->i, 0); | |||||
} | |||||
void | |||||
focusstackhid(const Arg *arg) | |||||
{ | |||||
focusstack(arg->i, 1); | |||||
} | |||||
void | |||||
focusstack(int inc, int hid) | |||||
{ | { | ||||
Client *c = NULL, *i; | Client *c = NULL, *i; | ||||
if (!selmon->sel) | |||||
if (!selmon->sel && !hid) | |||||
return; | return; | ||||
if (arg->i > 0) { | |||||
for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); | |||||
if (!selmon->clients) | |||||
return; | |||||
if (inc > 0) { | |||||
if (selmon->sel) | |||||
for (c = selmon->sel->next; | |||||
c && (!ISVISIBLE(c) || (!hid && HIDDEN(c))); | |||||
c = c->next); | |||||
if (!c) | if (!c) | ||||
for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); | |||||
for (c = selmon->clients; | |||||
c && (!ISVISIBLE(c) || (!hid && HIDDEN(c))); | |||||
c = c->next); | |||||
} else { | } else { | ||||
for (i = selmon->clients; i != selmon->sel; i = i->next) | |||||
if (ISVISIBLE(i)) | |||||
c = i; | |||||
if (selmon->sel) { | |||||
for (i = selmon->clients; i != selmon->sel; i = i->next) | |||||
if (ISVISIBLE(i) && !(!hid && HIDDEN(i))) | |||||
c = i; | |||||
} else | |||||
c = selmon->clients; | |||||
if (!c) | if (!c) | ||||
for (; i; i = i->next) | for (; i; i = i->next) | ||||
if (ISVISIBLE(i)) | |||||
if (ISVISIBLE(i) && !(!hid && HIDDEN(i))) | |||||
c = i; | c = i; | ||||
} | } | ||||
if (c) { | if (c) { | ||||
focus(c); | focus(c); | ||||
restack(selmon); | restack(selmon); | ||||
if (HIDDEN(c)) { | |||||
showwin(c); | |||||
c->mon->hidsel = 1; | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -978,6 +1063,36 @@ grabkeys(void) | |||||
} | } | ||||
} | } | ||||
void | |||||
hide(const Arg *arg) | |||||
{ | |||||
hidewin(selmon->sel); | |||||
focus(NULL); | |||||
arrange(selmon); | |||||
} | |||||
void | |||||
hidewin(Client *c) { | |||||
if (!c || HIDDEN(c)) | |||||
return; | |||||
Window w = c->win; | |||||
static XWindowAttributes ra, ca; | |||||
// more or less taken directly from blackbox's hide() function | |||||
XGrabServer(dpy); | |||||
XGetWindowAttributes(dpy, root, &ra); | |||||
XGetWindowAttributes(dpy, w, &ca); | |||||
// prevent UnmapNotify events | |||||
XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask); | |||||
XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask); | |||||
XUnmapWindow(dpy, w); | |||||
setclientstate(c, IconicState); | |||||
XSelectInput(dpy, root, ra.your_event_mask); | |||||
XSelectInput(dpy, w, ca.your_event_mask); | |||||
XUngrabServer(dpy); | |||||
} | |||||
void | void | ||||
incnmaster(const Arg *arg) | incnmaster(const Arg *arg) | ||||
{ | { | ||||
@@ -1081,12 +1196,14 @@ manage(Window w, XWindowAttributes *wa) | |||||
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, | XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, | ||||
(unsigned char *) &(c->win), 1); | (unsigned char *) &(c->win), 1); | ||||
XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ | XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ | ||||
setclientstate(c, NormalState); | |||||
if (!HIDDEN(c)) | |||||
setclientstate(c, NormalState); | |||||
if (c->mon == selmon) | if (c->mon == selmon) | ||||
unfocus(selmon->sel, 0); | unfocus(selmon->sel, 0); | ||||
c->mon->sel = c; | c->mon->sel = c; | ||||
arrange(c->mon); | arrange(c->mon); | ||||
XMapWindow(dpy, c->win); | |||||
if (!HIDDEN(c)) | |||||
XMapWindow(dpy, c->win); | |||||
focus(NULL); | focus(NULL); | ||||
} | } | ||||
@@ -1212,7 +1329,7 @@ movemouse(const Arg *arg) | |||||
Client * | Client * | ||||
nexttiled(Client *c) | nexttiled(Client *c) | ||||
{ | { | ||||
for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); | |||||
for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next); | |||||
return c; | return c; | ||||
} | } | ||||
@@ -1265,6 +1382,16 @@ propertynotify(XEvent *e) | |||||
void | void | ||||
quit(const Arg *arg) | quit(const Arg *arg) | ||||
{ | { | ||||
// fix: reloading dwm keeps all the hidden clients hidden | |||||
Monitor *m; | |||||
Client *c; | |||||
for (m = mons; m; m = m->next) { | |||||
if (m) { | |||||
for (c = m->stack; c; c = c->next) | |||||
if (c && HIDDEN(c)) showwin(c); | |||||
} | |||||
} | |||||
running = 0; | running = 0; | ||||
} | } | ||||
@@ -1603,6 +1730,25 @@ setup(void) | |||||
focus(NULL); | focus(NULL); | ||||
} | } | ||||
void | |||||
show(const Arg *arg) | |||||
{ | |||||
if (selmon->hidsel) | |||||
selmon->hidsel = 0; | |||||
showwin(selmon->sel); | |||||
} | |||||
void | |||||
showwin(Client *c) | |||||
{ | |||||
if (!c || !HIDDEN(c)) | |||||
return; | |||||
XMapWindow(dpy, c->win); | |||||
setclientstate(c, NormalState); | |||||
arrange(c->mon); | |||||
} | |||||
void | void | ||||
showhide(Client *c) | showhide(Client *c) | ||||
{ | { | ||||
@@ -1739,6 +1885,23 @@ toggleview(const Arg *arg) | |||||
} | } | ||||
} | } | ||||
void | |||||
togglewin(const Arg *arg) | |||||
{ | |||||
Client *c = (Client*)arg->v; | |||||
if (c == selmon->sel) { | |||||
hidewin(c); | |||||
focus(NULL); | |||||
arrange(c->mon); | |||||
} else { | |||||
if (HIDDEN(c)) | |||||
showwin(c); | |||||
focus(c); | |||||
restack(selmon); | |||||
} | |||||
} | |||||
void | void | ||||
unfocus(Client *c, int setfocus) | unfocus(Client *c, int setfocus) | ||||
{ | { | ||||
@@ -2139,3 +2302,106 @@ main(int argc, char *argv[]) | |||||
XCloseDisplay(dpy); | XCloseDisplay(dpy); | ||||
return EXIT_SUCCESS; | 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); | |||||
} | |||||
} |