@@ -12,6 +12,7 @@ static const char selbordercolor[] = "#005577"; | |||||
static const char selbgcolor[] = "#005577"; | static const char selbgcolor[] = "#005577"; | ||||
static const char selfgcolor[] = "#eeeeee"; | static const char selfgcolor[] = "#eeeeee"; | ||||
static const unsigned int borderpx = 1; /* border pixel of windows */ | static const unsigned int borderpx = 1; /* border pixel of windows */ | ||||
static const Gap default_gap = {.isgap = 1, .realgap = 10, .gappx = 10}; | |||||
static const unsigned int snap = 32; /* snap pixel */ | static const unsigned int snap = 32; /* snap pixel */ | ||||
static const int showbar = 1; /* 0 means no bar */ | static const int showbar = 1; /* 0 means no bar */ | ||||
static const int topbar = 1; /* 0 means bottom bar */ | static const int topbar = 1; /* 0 means bottom bar */ | ||||
@@ -91,6 +92,11 @@ static Key keys[] = { | |||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, | { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, | ||||
{ MODKEY, XK_s, show, {0} }, | { MODKEY, XK_s, show, {0} }, | ||||
{ MODKEY, XK_h, hide, {0} }, | { MODKEY, XK_h, hide, {0} }, | ||||
{ MODKEY|ShiftMask, XK_b, toggleAttachBelow, {0} }, | |||||
{ MODKEY, XK_minus, setgaps, {.i = -5 } }, | |||||
{ MODKEY, XK_equal, setgaps, {.i = +5 } }, | |||||
{ MODKEY|ShiftMask, XK_minus, setgaps, {.i = GAP_RESET } }, | |||||
{ MODKEY|ShiftMask, XK_equal, setgaps, {.i = GAP_TOGGLE} }, | |||||
TAGKEYS( XK_1, 0) | TAGKEYS( XK_1, 0) | ||||
TAGKEYS( XK_2, 1) | TAGKEYS( XK_2, 1) | ||||
TAGKEYS( XK_3, 2) | TAGKEYS( XK_3, 2) | ||||
@@ -12,6 +12,7 @@ static const char selbordercolor[] = "#005577"; | |||||
static const char selbgcolor[] = "#005577"; | static const char selbgcolor[] = "#005577"; | ||||
static const char selfgcolor[] = "#eeeeee"; | static const char selfgcolor[] = "#eeeeee"; | ||||
static const unsigned int borderpx = 1; /* border pixel of windows */ | static const unsigned int borderpx = 1; /* border pixel of windows */ | ||||
static const Gap default_gap = {.isgap = 1, .realgap = 10, .gappx = 10}; | |||||
static const unsigned int snap = 32; /* snap pixel */ | static const unsigned int snap = 32; /* snap pixel */ | ||||
static const int showbar = 1; /* 0 means no bar */ | static const int showbar = 1; /* 0 means no bar */ | ||||
static const int topbar = 1; /* 0 means bottom bar */ | static const int topbar = 1; /* 0 means bottom bar */ | ||||
@@ -33,6 +34,7 @@ static const Rule rules[] = { | |||||
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ | 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 nmaster = 1; /* number of clients in master area */ | ||||
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ | static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ | ||||
static int attachbelow = 1; /* 1 means attach after the currently active window */ | |||||
static const Layout layouts[] = { | static const Layout layouts[] = { | ||||
/* symbol arrange function */ | /* symbol arrange function */ | ||||
@@ -90,6 +92,11 @@ static Key keys[] = { | |||||
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, | { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, | ||||
{ MODKEY|ShiftMask, XK_s, show, {0} }, | { MODKEY|ShiftMask, XK_s, show, {0} }, | ||||
{ MODKEY|ShiftMask, XK_h, hide, {0} }, | { MODKEY|ShiftMask, XK_h, hide, {0} }, | ||||
{ MODKEY|ShiftMask, XK_b, toggleAttachBelow, {0} }, | |||||
{ MODKEY, XK_minus, setgaps, {.i = -5 } }, | |||||
{ MODKEY, XK_equal, setgaps, {.i = +5 } }, | |||||
{ MODKEY|ShiftMask, XK_minus, setgaps, {.i = GAP_RESET } }, | |||||
{ MODKEY|ShiftMask, XK_equal, setgaps, {.i = GAP_TOGGLE} }, | |||||
TAGKEYS( XK_1, 0) | TAGKEYS( XK_1, 0) | ||||
TAGKEYS( XK_2, 1) | TAGKEYS( XK_2, 1) | ||||
TAGKEYS( XK_3, 2) | TAGKEYS( XK_3, 2) | ||||
@@ -1,95 +0,0 @@ | |||||
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 | |||||
@@ -0,0 +1,148 @@ | |||||
diff --git a/config.def.h b/config.def.h | |||||
index 1c0b587..b172f63 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 Gap default_gap = {.isgap = 1, .realgap = 10, .gappx = 10}; | |||||
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,10 @@ 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 = -5 } }, | |||||
+ { MODKEY, XK_equal, setgaps, {.i = +5 } }, | |||||
+ { MODKEY|ShiftMask, XK_minus, setgaps, {.i = GAP_RESET } }, | |||||
+ { MODKEY|ShiftMask, XK_equal, setgaps, {.i = GAP_TOGGLE} }, | |||||
TAGKEYS( XK_1, 0) | |||||
TAGKEYS( XK_2, 1) | |||||
TAGKEYS( XK_3, 2) | |||||
diff --git a/dwm.c b/dwm.c | |||||
index 664c527..25bc9b7 100644 | |||||
--- a/dwm.c | |||||
+++ b/dwm.c | |||||
@@ -57,6 +57,9 @@ | |||||
#define TAGMASK ((1 << LENGTH(tags)) - 1) | |||||
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) | |||||
+#define GAP_TOGGLE 100 | |||||
+#define GAP_RESET 0 | |||||
+ | |||||
/* enums */ | |||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ | |||||
enum { SchemeNorm, SchemeSel }; /* color schemes */ | |||||
@@ -111,6 +114,12 @@ typedef struct { | |||||
void (*arrange)(Monitor *); | |||||
} Layout; | |||||
+typedef struct { | |||||
+ int isgap; | |||||
+ int realgap; | |||||
+ int gappx; | |||||
+} Gap; | |||||
+ | |||||
struct Monitor { | |||||
char ltsymbol[16]; | |||||
float mfact; | |||||
@@ -119,6 +128,7 @@ struct Monitor { | |||||
int by; /* bar geometry */ | |||||
int mx, my, mw, mh; /* screen size */ | |||||
int wx, wy, ww, wh; /* window area */ | |||||
+ Gap *gap; | |||||
unsigned int seltags; | |||||
unsigned int sellt; | |||||
unsigned int tagset[2]; | |||||
@@ -169,6 +179,7 @@ static void focus(Client *c); | |||||
static void focusin(XEvent *e); | |||||
static void focusmon(const Arg *arg); | |||||
static void focusstack(const Arg *arg); | |||||
+static void gap_copy(Gap *to, const Gap *from); | |||||
static Atom getatomprop(Client *c, Atom prop); | |||||
static int getrootptr(int *x, int *y); | |||||
static long getstate(Window w); | |||||
@@ -200,6 +211,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); | |||||
@@ -639,6 +651,8 @@ createmon(void) | |||||
m->nmaster = nmaster; | |||||
m->showbar = showbar; | |||||
m->topbar = topbar; | |||||
+ m->gap = malloc(sizeof(Gap)); | |||||
+ gap_copy(m->gap, &default_gap); | |||||
m->lt[0] = &layouts[0]; | |||||
m->lt[1] = &layouts[1 % LENGTH(layouts)]; | |||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); | |||||
@@ -1498,6 +1512,35 @@ setfullscreen(Client *c, int fullscreen) | |||||
} | |||||
} | |||||
+void | |||||
+gap_copy(Gap *to, const Gap *from) | |||||
+{ | |||||
+ to->isgap = from->isgap; | |||||
+ to->realgap = from->realgap; | |||||
+ to->gappx = from->gappx; | |||||
+} | |||||
+ | |||||
+void | |||||
+setgaps(const Arg *arg) | |||||
+{ | |||||
+ Gap *p = selmon->gap; | |||||
+ switch(arg->i) | |||||
+ { | |||||
+ case GAP_TOGGLE: | |||||
+ p->isgap = 1 - p->isgap; | |||||
+ break; | |||||
+ case GAP_RESET: | |||||
+ gap_copy(p, &default_gap); | |||||
+ break; | |||||
+ default: | |||||
+ p->realgap += arg->i; | |||||
+ p->isgap = 1; | |||||
+ } | |||||
+ p->realgap = MAX(p->realgap, 0); | |||||
+ p->gappx = p->realgap * p->isgap; | |||||
+ arrange(selmon); | |||||
+} | |||||
+ | |||||
void | |||||
setlayout(const Arg *arg) | |||||
{ | |||||
@@ -1684,18 +1727,18 @@ 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->gap->gappx; | |||||
+ for (i = 0, my = ty = m->gap->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); | |||||
- if (my + HEIGHT(c) < m->wh) | |||||
- my += HEIGHT(c); | |||||
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gap->gappx; | |||||
+ resize(c, m->wx + m->gap->gappx, m->wy + my, mw - (2*c->bw) - m->gap->gappx, h - (2*c->bw), 0); | |||||
+ if (my + HEIGHT(c) + m->gap->gappx < m->wh) | |||||
+ my += HEIGHT(c) + m->gap->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); | |||||
- if (ty + HEIGHT(c) < m->wh) | |||||
- ty += HEIGHT(c); | |||||
+ h = (m->wh - ty) / (n - i) - m->gap->gappx; | |||||
+ resize(c, m->wx + mw + m->gap->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gap->gappx, h - (2*c->bw), 0); | |||||
+ if (ty + HEIGHT(c) + m->gap->gappx < m->wh) | |||||
+ ty += HEIGHT(c) + m->gap->gappx; | |||||
} | |||||
} | |||||
@@ -0,0 +1,177 @@ | |||||
diff --git a/dwm.c b/dwm.c | |||||
index 664c527..ac8e4ec 100644 | |||||
--- a/dwm.c | |||||
+++ b/dwm.c | |||||
@@ -111,6 +111,7 @@ typedef struct { | |||||
void (*arrange)(Monitor *); | |||||
} Layout; | |||||
+typedef struct Pertag Pertag; | |||||
struct Monitor { | |||||
char ltsymbol[16]; | |||||
float mfact; | |||||
@@ -130,6 +131,7 @@ struct Monitor { | |||||
Monitor *next; | |||||
Window barwin; | |||||
const Layout *lt[2]; | |||||
+ Pertag *pertag; | |||||
}; | |||||
typedef struct { | |||||
@@ -272,6 +274,15 @@ static Window root, wmcheckwin; | |||||
/* 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 */ | |||||
+ int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ | |||||
+}; | |||||
+ | |||||
/* compile-time check if all tags fit into an unsigned int bit array. */ | |||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; | |||||
@@ -632,6 +643,7 @@ Monitor * | |||||
createmon(void) | |||||
{ | |||||
Monitor *m; | |||||
+ unsigned int i; | |||||
m = ecalloc(1, sizeof(Monitor)); | |||||
m->tagset[0] = m->tagset[1] = 1; | |||||
@@ -642,6 +654,20 @@ createmon(void) | |||||
m->lt[0] = &layouts[0]; | |||||
m->lt[1] = &layouts[1 % LENGTH(layouts)]; | |||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); | |||||
+ m->pertag = ecalloc(1, sizeof(Pertag)); | |||||
+ m->pertag->curtag = m->pertag->prevtag = 1; | |||||
+ | |||||
+ for (i = 0; i <= LENGTH(tags); i++) { | |||||
+ m->pertag->nmasters[i] = m->nmaster; | |||||
+ m->pertag->mfacts[i] = m->mfact; | |||||
+ | |||||
+ m->pertag->ltidxs[i][0] = m->lt[0]; | |||||
+ m->pertag->ltidxs[i][1] = m->lt[1]; | |||||
+ m->pertag->sellts[i] = m->sellt; | |||||
+ | |||||
+ m->pertag->showbars[i] = m->showbar; | |||||
+ } | |||||
+ | |||||
return m; | |||||
} | |||||
@@ -967,7 +993,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); | |||||
} | |||||
@@ -1502,9 +1528,9 @@ void | |||||
setlayout(const Arg *arg) | |||||
{ | |||||
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) | |||||
- selmon->sellt ^= 1; | |||||
+ selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; | |||||
if (arg && arg->v) | |||||
- selmon->lt[selmon->sellt] = (Layout *)arg->v; | |||||
+ selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; | |||||
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); | |||||
if (selmon->sel) | |||||
arrange(selmon); | |||||
@@ -1523,7 +1549,7 @@ setmfact(const Arg *arg) | |||||
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; | |||||
if (f < 0.05 || f > 0.95) | |||||
return; | |||||
- selmon->mfact = f; | |||||
+ selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; | |||||
arrange(selmon); | |||||
} | |||||
@@ -1702,7 +1728,7 @@ 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); | |||||
@@ -1741,9 +1767,33 @@ void | |||||
toggleview(const Arg *arg) | |||||
{ | |||||
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); | |||||
+ int i; | |||||
if (newtagset) { | |||||
selmon->tagset[selmon->seltags] = 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; | |||||
+ } | |||||
+ | |||||
+ /* 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); | |||||
} | |||||
@@ -2038,11 +2088,37 @@ updatewmhints(Client *c) | |||||
void | |||||
view(const Arg *arg) | |||||
{ | |||||
+ 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->tagset[selmon->seltags] = arg->ui & TAGMASK; | |||||
+ selmon->pertag->prevtag = selmon->pertag->curtag; | |||||
+ | |||||
+ 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); | |||||
} |
@@ -58,6 +58,9 @@ | |||||
#define TAGMASK ((1 << LENGTH(tags)) - 1) | #define TAGMASK ((1 << LENGTH(tags)) - 1) | ||||
#define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h) | #define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h) | ||||
#define GAP_TOGGLE 100 | |||||
#define GAP_RESET 0 | |||||
/* enums */ | /* enums */ | ||||
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ | enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ | ||||
enum { SchemeNorm, SchemeSel, SchemeHid, SchemeLast }; /* color schemes */ | enum { SchemeNorm, SchemeSel, SchemeHid, SchemeLast }; /* color schemes */ | ||||
@@ -112,6 +115,13 @@ typedef struct { | |||||
void (*arrange)(Monitor *); | void (*arrange)(Monitor *); | ||||
} Layout; | } Layout; | ||||
typedef struct { | |||||
int isgap; | |||||
int realgap; | |||||
int gappx; | |||||
} Gap; | |||||
typedef struct Pertag Pertag; | |||||
struct Monitor { | struct Monitor { | ||||
char ltsymbol[16]; | char ltsymbol[16]; | ||||
float mfact; | float mfact; | ||||
@@ -122,6 +132,7 @@ struct Monitor { | |||||
int bt; /* number of tasks */ | 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 */ | ||||
Gap *gap; | |||||
unsigned int seltags; | unsigned int seltags; | ||||
unsigned int sellt; | unsigned int sellt; | ||||
unsigned int tagset[2]; | unsigned int tagset[2]; | ||||
@@ -134,6 +145,7 @@ struct Monitor { | |||||
Monitor *next; | Monitor *next; | ||||
Window barwin; | Window barwin; | ||||
const Layout *lt[2]; | const Layout *lt[2]; | ||||
Pertag *pertag; | |||||
}; | }; | ||||
typedef struct { | typedef struct { | ||||
@@ -145,6 +157,7 @@ typedef struct { | |||||
int monitor; | int monitor; | ||||
} Rule; | } Rule; | ||||
/* function declarations */ | /* function declarations */ | ||||
static void applyrules(Client *c); | static void applyrules(Client *c); | ||||
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); | static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); | ||||
@@ -178,6 +191,7 @@ static void focusmon(const Arg *arg); | |||||
static void focusstackvis(const Arg *arg); | static void focusstackvis(const Arg *arg); | ||||
static void focusstackhid(const Arg *arg); | static void focusstackhid(const Arg *arg); | ||||
static void focusstack(int inc, int vis); | static void focusstack(int inc, int vis); | ||||
static void gap_copy(Gap *to, const Gap *from); | |||||
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); | ||||
@@ -210,6 +224,7 @@ static void sendmon(Client *c, Monitor *m); | |||||
static void setclientstate(Client *c, long state); | static void setclientstate(Client *c, long state); | ||||
static void setfocus(Client *c); | static void setfocus(Client *c); | ||||
static void setfullscreen(Client *c, int fullscreen); | static void setfullscreen(Client *c, int fullscreen); | ||||
static void setgaps(const Arg *arg); | |||||
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); | ||||
@@ -285,6 +300,15 @@ static Window root; | |||||
/* configuration, allows nested code to access above variables */ | /* configuration, allows nested code to access above variables */ | ||||
#include "config.h" | #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 */ | |||||
int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ | |||||
}; | |||||
/* compile-time check if all tags fit into an unsigned int bit array. */ | /* compile-time check if all tags fit into an unsigned int bit array. */ | ||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; | struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; | ||||
@@ -690,6 +714,7 @@ Monitor * | |||||
createmon(void) | createmon(void) | ||||
{ | { | ||||
Monitor *m; | Monitor *m; | ||||
unsigned int i; | |||||
m = ecalloc(1, sizeof(Monitor)); | m = ecalloc(1, sizeof(Monitor)); | ||||
m->tagset[0] = m->tagset[1] = 1; | m->tagset[0] = m->tagset[1] = 1; | ||||
@@ -697,9 +722,25 @@ createmon(void) | |||||
m->nmaster = nmaster; | m->nmaster = nmaster; | ||||
m->showbar = showbar; | m->showbar = showbar; | ||||
m->topbar = topbar; | m->topbar = topbar; | ||||
m->gap = malloc(sizeof(Gap)); | |||||
gap_copy(m->gap, &default_gap); | |||||
m->lt[0] = &layouts[0]; | m->lt[0] = &layouts[0]; | ||||
m->lt[1] = &layouts[1 % LENGTH(layouts)]; | m->lt[1] = &layouts[1 % LENGTH(layouts)]; | ||||
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); | strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); | ||||
m->pertag = ecalloc(1, sizeof(Pertag)); | |||||
m->pertag->curtag = m->pertag->prevtag = 1; | |||||
for (i = 0; i <= LENGTH(tags); i++) { | |||||
m->pertag->nmasters[i] = m->nmaster; | |||||
m->pertag->mfacts[i] = m->mfact; | |||||
m->pertag->ltidxs[i][0] = m->lt[0]; | |||||
m->pertag->ltidxs[i][1] = m->lt[1]; | |||||
m->pertag->sellts[i] = m->sellt; | |||||
m->pertag->showbars[i] = m->showbar; | |||||
} | |||||
return m; | return m; | ||||
} | } | ||||
@@ -1121,7 +1162,7 @@ hidewin(Client *c) { | |||||
void | void | ||||
incnmaster(const Arg *arg) | 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); | arrange(selmon); | ||||
} | } | ||||
@@ -1672,13 +1713,42 @@ setfullscreen(Client *c, int fullscreen) | |||||
} | } | ||||
} | } | ||||
void | |||||
gap_copy(Gap *to, const Gap *from) | |||||
{ | |||||
to->isgap = from->isgap; | |||||
to->realgap = from->realgap; | |||||
to->gappx = from->gappx; | |||||
} | |||||
void | |||||
setgaps(const Arg *arg) | |||||
{ | |||||
Gap *p = selmon->gap; | |||||
switch(arg->i) | |||||
{ | |||||
case GAP_TOGGLE: | |||||
p->isgap = 1 - p->isgap; | |||||
break; | |||||
case GAP_RESET: | |||||
gap_copy(p, &default_gap); | |||||
break; | |||||
default: | |||||
p->realgap += arg->i; | |||||
p->isgap = 1; | |||||
} | |||||
p->realgap = MAX(p->realgap, 0); | |||||
p->gappx = p->realgap * p->isgap; | |||||
arrange(selmon); | |||||
} | |||||
void | void | ||||
setlayout(const Arg *arg) | setlayout(const Arg *arg) | ||||
{ | { | ||||
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) | if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) | ||||
selmon->sellt ^= 1; | |||||
selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1; | |||||
if (arg && arg->v) | if (arg && arg->v) | ||||
selmon->lt[selmon->sellt] = (Layout *)arg->v; | |||||
selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v; | |||||
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); | strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); | ||||
if (selmon->sel) | if (selmon->sel) | ||||
arrange(selmon); | arrange(selmon); | ||||
@@ -1697,7 +1767,7 @@ setmfact(const Arg *arg) | |||||
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; | f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; | ||||
if (f < 0.1 || f > 0.9) | if (f < 0.1 || f > 0.9) | ||||
return; | return; | ||||
selmon->mfact = f; | |||||
selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; | |||||
arrange(selmon); | arrange(selmon); | ||||
} | } | ||||
@@ -1853,23 +1923,25 @@ tile(Monitor *m) | |||||
if (n > m->nmaster) | if (n > m->nmaster) | ||||
mw = m->nmaster ? m->ww * m->mfact : 0; | mw = m->nmaster ? m->ww * m->mfact : 0; | ||||
else | else | ||||
mw = m->ww; | |||||
for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) | |||||
mw = m->ww - m->gap->gappx; | |||||
for (i = 0, my = ty = m->gap->gappx, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) | |||||
if (i < m->nmaster) { | 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->gap->gappx; | |||||
resize(c, m->wx + m->gap->gappx, m->wy + my, mw - (2*c->bw) - m->gap->gappx, h - (2*c->bw), 0); | |||||
if (my + HEIGHT(c) + m->gap->gappx < m->wh) | |||||
my += HEIGHT(c) + m->gap->gappx; | |||||
} else { | } 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->gap->gappx; | |||||
resize(c, m->wx + mw + m->gap->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gap->gappx, h - (2*c->bw), 0); | |||||
if (ty + HEIGHT(c) + m->gap->gappx < m->wh) | |||||
ty += HEIGHT(c) + m->gap->gappx; | |||||
} | } | ||||
} | } | ||||
void | void | ||||
togglebar(const Arg *arg) | togglebar(const Arg *arg) | ||||
{ | { | ||||
selmon->showbar = !selmon->showbar; | |||||
selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar; | |||||
updatebarpos(selmon); | updatebarpos(selmon); | ||||
XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); | XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); | ||||
arrange(selmon); | arrange(selmon); | ||||
@@ -1908,9 +1980,33 @@ void | |||||
toggleview(const Arg *arg) | toggleview(const Arg *arg) | ||||
{ | { | ||||
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); | unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK); | ||||
int i; | |||||
if (newtagset) { | if (newtagset) { | ||||
selmon->tagset[selmon->seltags] = newtagset; | selmon->tagset[selmon->seltags] = 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; | |||||
} | |||||
/* 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); | focus(NULL); | ||||
arrange(selmon); | arrange(selmon); | ||||
} | } | ||||
@@ -2229,11 +2325,37 @@ updatewmhints(Client *c) | |||||
void | void | ||||
view(const Arg *arg) | view(const Arg *arg) | ||||
{ | { | ||||
int i; | |||||
unsigned int tmptag; | |||||
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) | if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) | ||||
return; | return; | ||||
selmon->seltags ^= 1; /* toggle sel tagset */ | selmon->seltags ^= 1; /* toggle sel tagset */ | ||||
if (arg->ui & TAGMASK) | |||||
if (arg->ui & TAGMASK) { | |||||
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; | selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; | ||||
selmon->pertag->prevtag = selmon->pertag->curtag; | |||||
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); | focus(NULL); | ||||
arrange(selmon); | arrange(selmon); | ||||
} | } | ||||