mirror of
https://github.com/zoriya/dwm.git
synced 2025-12-05 23:06:19 +00:00
This patch differentiates between inner and outer gaps as well as horizontal and vertical gaps. The logic of these layouts also aims to be pixel perfect by ensuring an even split of the available space and re-distributing the remainder among the available clients.
819 lines
19 KiB
C
819 lines
19 KiB
C
/* Key binding functions */
|
|
static void defaultgaps(const Arg *arg);
|
|
static void incrgaps(const Arg *arg);
|
|
static void incrigaps(const Arg *arg);
|
|
static void incrogaps(const Arg *arg);
|
|
static void incrohgaps(const Arg *arg);
|
|
static void incrovgaps(const Arg *arg);
|
|
static void incrihgaps(const Arg *arg);
|
|
static void incrivgaps(const Arg *arg);
|
|
static void togglegaps(const Arg *arg);
|
|
/* Layouts (delete the ones you do not need) */
|
|
static void bstack(Monitor *m);
|
|
static void bstackhoriz(Monitor *m);
|
|
static void centeredmaster(Monitor *m);
|
|
static void centeredfloatingmaster(Monitor *m);
|
|
static void deck(Monitor *m);
|
|
static void dwindle(Monitor *m);
|
|
static void fibonacci(Monitor *m, int s);
|
|
static void grid(Monitor *m);
|
|
static void nrowgrid(Monitor *m);
|
|
static void spiral(Monitor *m);
|
|
static void tile(Monitor *m);
|
|
/* Internals */
|
|
static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
|
|
static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
|
|
static void setgaps(int oh, int ov, int ih, int iv);
|
|
|
|
/* Settings */
|
|
#if !PERTAG_PATCH
|
|
static int enablegaps = 1;
|
|
#endif // PERTAG_PATCH
|
|
|
|
void
|
|
setgaps(int oh, int ov, int ih, int iv)
|
|
{
|
|
if (oh < 0) oh = 0;
|
|
if (ov < 0) ov = 0;
|
|
if (ih < 0) ih = 0;
|
|
if (iv < 0) iv = 0;
|
|
|
|
selmon->gappoh = oh;
|
|
selmon->gappov = ov;
|
|
selmon->gappih = ih;
|
|
selmon->gappiv = iv;
|
|
arrange(selmon);
|
|
}
|
|
|
|
__attribute__((unused))
|
|
void
|
|
togglegaps(const Arg *arg)
|
|
{
|
|
#if PERTAG_PATCH
|
|
selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
|
|
#else
|
|
enablegaps = !enablegaps;
|
|
#endif // PERTAG_PATCH
|
|
arrange(NULL);
|
|
}
|
|
|
|
__attribute__((unused))
|
|
void
|
|
defaultgaps(const Arg *arg)
|
|
{
|
|
setgaps(gappoh, gappov, gappih, gappiv);
|
|
}
|
|
|
|
__attribute__((unused))
|
|
void
|
|
incrgaps(const Arg *arg)
|
|
{
|
|
setgaps(
|
|
selmon->gappoh + arg->i,
|
|
selmon->gappov + arg->i,
|
|
selmon->gappih + arg->i,
|
|
selmon->gappiv + arg->i
|
|
);
|
|
}
|
|
|
|
__attribute__((unused))
|
|
void
|
|
incrigaps(const Arg *arg)
|
|
{
|
|
setgaps(
|
|
selmon->gappoh,
|
|
selmon->gappov,
|
|
selmon->gappih + arg->i,
|
|
selmon->gappiv + arg->i
|
|
);
|
|
}
|
|
|
|
__attribute__((unused))
|
|
void
|
|
incrogaps(const Arg *arg)
|
|
{
|
|
setgaps(
|
|
selmon->gappoh + arg->i,
|
|
selmon->gappov + arg->i,
|
|
selmon->gappih,
|
|
selmon->gappiv
|
|
);
|
|
}
|
|
|
|
__attribute__((unused))
|
|
void
|
|
incrohgaps(const Arg *arg)
|
|
{
|
|
setgaps(
|
|
selmon->gappoh + arg->i,
|
|
selmon->gappov,
|
|
selmon->gappih,
|
|
selmon->gappiv
|
|
);
|
|
}
|
|
|
|
__attribute__((unused))
|
|
void
|
|
incrovgaps(const Arg *arg)
|
|
{
|
|
setgaps(
|
|
selmon->gappoh,
|
|
selmon->gappov + arg->i,
|
|
selmon->gappih,
|
|
selmon->gappiv
|
|
);
|
|
}
|
|
|
|
__attribute__((unused))
|
|
void
|
|
incrihgaps(const Arg *arg)
|
|
{
|
|
setgaps(
|
|
selmon->gappoh,
|
|
selmon->gappov,
|
|
selmon->gappih + arg->i,
|
|
selmon->gappiv
|
|
);
|
|
}
|
|
|
|
__attribute__((unused))
|
|
void
|
|
incrivgaps(const Arg *arg)
|
|
{
|
|
setgaps(
|
|
selmon->gappoh,
|
|
selmon->gappov,
|
|
selmon->gappih,
|
|
selmon->gappiv + arg->i
|
|
);
|
|
}
|
|
|
|
void
|
|
getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
|
|
{
|
|
unsigned int n, oe, ie;
|
|
#if PERTAG_PATCH
|
|
oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
|
|
#else
|
|
oe = ie = enablegaps;
|
|
#endif // PERTAG_PATCH
|
|
Client *c;
|
|
|
|
for (n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++);
|
|
if (n == 1) {
|
|
oe *= smartgaps; // outer gaps disabled or multiplied when only one client
|
|
}
|
|
|
|
*oh = m->gappoh*oe; // outer horizontal gap
|
|
*ov = m->gappov*oe; // outer vertical gap
|
|
*ih = m->gappih*ie; // inner horizontal gap
|
|
*iv = m->gappiv*ie; // inner vertical gap
|
|
*nc = n; // number of clients
|
|
}
|
|
|
|
void
|
|
getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
|
|
{
|
|
unsigned int n;
|
|
float mfacts, sfacts;
|
|
int mtotal = 0, stotal = 0;
|
|
Client *c;
|
|
|
|
for (n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++);
|
|
mfacts = MIN(n, m->nmaster);
|
|
sfacts = n - m->nmaster;
|
|
|
|
for (n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++)
|
|
if (n < m->nmaster)
|
|
mtotal += msize / mfacts;
|
|
else
|
|
stotal += ssize / sfacts;
|
|
|
|
*mf = mfacts; // total factor of master area
|
|
*sf = sfacts; // total factor of stack area
|
|
*mr = msize - mtotal; // the remainder (rest) of pixels after an even master split
|
|
*sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split
|
|
}
|
|
|
|
/***
|
|
* Layouts
|
|
*/
|
|
|
|
/*
|
|
* Bottomstack layout + gaps
|
|
* https://dwm.suckless.org/patches/bottomstack/
|
|
*/
|
|
static void
|
|
bstack(Monitor *m)
|
|
{
|
|
unsigned int i, n;
|
|
int oh, ov, ih, iv;
|
|
int mx = 0, my = 0, mh = 0, mw = 0;
|
|
int sx = 0, sy = 0, sh = 0, sw = 0;
|
|
float mfacts, sfacts;
|
|
int mrest, srest;
|
|
Client *c;
|
|
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
if (n == 0)
|
|
return;
|
|
|
|
sx = mx = m->wx + ov;
|
|
sy = my = m->wy + oh;
|
|
sh = mh = m->wh - 2*oh;
|
|
mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
|
sw = m->ww - 2*ov - iv * (n - m->nmaster - 1);
|
|
|
|
if (m->nmaster && n > m->nmaster) {
|
|
sh = (mh - ih) * (1 - m->mfact);
|
|
mh = mh - ih - sh;
|
|
sx = mx;
|
|
sy = my + mh + ih;
|
|
}
|
|
|
|
getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
|
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++) {
|
|
if (i < m->nmaster) {
|
|
resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
|
mx += WIDTH(c) + iv;
|
|
} else {
|
|
resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
|
sx += WIDTH(c) + iv;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
bstackhoriz(Monitor *m)
|
|
{
|
|
unsigned int i, n;
|
|
int oh, ov, ih, iv;
|
|
int mx = 0, my = 0, mh = 0, mw = 0;
|
|
int sx = 0, sy = 0, sh = 0, sw = 0;
|
|
float mfacts, sfacts;
|
|
int mrest, srest;
|
|
Client *c;
|
|
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
if (n == 0)
|
|
return;
|
|
|
|
sx = mx = m->wx + ov;
|
|
sy = my = m->wy + oh;
|
|
mh = m->wh - 2*oh;
|
|
sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
|
mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
|
|
sw = m->ww - 2*ov;
|
|
|
|
if (m->nmaster && n > m->nmaster) {
|
|
sh = (mh - ih) * (1 - m->mfact);
|
|
mh = mh - ih - sh;
|
|
sy = my + mh + ih;
|
|
sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
|
|
}
|
|
|
|
getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest);
|
|
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++) {
|
|
if (i < m->nmaster) {
|
|
resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
|
mx += WIDTH(c) + iv;
|
|
} else {
|
|
resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
|
sy += HEIGHT(c) + ih;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Centred master layout + gaps
|
|
* https://dwm.suckless.org/patches/centeredmaster/
|
|
*/
|
|
void
|
|
centeredmaster(Monitor *m)
|
|
{
|
|
unsigned int i, n;
|
|
int oh, ov, ih, iv;
|
|
int mx = 0, my = 0, mh = 0, mw = 0;
|
|
int lx = 0, ly = 0, lw = 0, lh = 0;
|
|
int rx = 0, ry = 0, rw = 0, rh = 0;
|
|
float mfacts = 0, lfacts = 0, rfacts = 0;
|
|
int mtotal = 0, ltotal = 0, rtotal = 0;
|
|
int mrest = 0, lrest = 0, rrest = 0;
|
|
Client *c;
|
|
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
if (n == 0)
|
|
return;
|
|
|
|
/* initialize areas */
|
|
mx = m->wx + ov;
|
|
my = m->wy + oh;
|
|
mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1);
|
|
mw = m->ww - 2*ov;
|
|
lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1);
|
|
rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1));
|
|
|
|
if (m->nmaster && n > m->nmaster) {
|
|
/* go mfact box in the center if more than nmaster clients */
|
|
if (n - m->nmaster > 1) {
|
|
/* ||<-S->|<---M--->|<-S->|| */
|
|
mw = (m->ww - 2*ov - 2*iv) * m->mfact;
|
|
lw = (m->ww - mw - 2*ov - 2*iv) / 2;
|
|
rw = (m->ww - mw - 2*ov - 2*iv) - lw;
|
|
mx += lw + iv;
|
|
} else {
|
|
/* ||<---M--->|<-S->|| */
|
|
mw = (mw - iv) * m->mfact;
|
|
lw = 0;
|
|
rw = m->ww - mw - iv - 2*ov;
|
|
}
|
|
lx = m->wx + ov;
|
|
ly = m->wy + oh;
|
|
rx = mx + mw + iv;
|
|
ry = m->wy + oh;
|
|
}
|
|
|
|
/* calculate facts */
|
|
for (n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++) {
|
|
if (!m->nmaster || n < m->nmaster)
|
|
mfacts += 1;
|
|
else if ((n - m->nmaster) % 2)
|
|
lfacts += 1; // total factor of left hand stack area
|
|
else
|
|
rfacts += 1; // total factor of right hand stack area
|
|
}
|
|
|
|
for (n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++)
|
|
if (!m->nmaster || n < m->nmaster)
|
|
mtotal += mh / mfacts;
|
|
else if ((n - m->nmaster) % 2)
|
|
ltotal += lh / lfacts;
|
|
else
|
|
rtotal += rh / rfacts;
|
|
|
|
mrest = mh - mtotal;
|
|
lrest = lh - ltotal;
|
|
rrest = rh - rtotal;
|
|
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++) {
|
|
if (!m->nmaster || i < m->nmaster) {
|
|
/* nmaster clients are stacked vertically, in the center of the screen */
|
|
resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
|
my += HEIGHT(c) + ih;
|
|
} else {
|
|
/* stack clients are stacked vertically */
|
|
if ((i - m->nmaster) % 2 ) {
|
|
resize(c, lx, ly, lw - (2*c->bw), (lh / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0);
|
|
ly += HEIGHT(c) + ih;
|
|
} else {
|
|
resize(c, rx, ry, rw - (2*c->bw), (rh / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0);
|
|
ry += HEIGHT(c) + ih;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
centeredfloatingmaster(Monitor *m)
|
|
{
|
|
unsigned int i, n;
|
|
float mfacts, sfacts;
|
|
float mivf = 1.0; // master inner vertical gap factor
|
|
int oh, ov, ih, iv, mrest, srest;
|
|
int mx = 0, my = 0, mh = 0, mw = 0;
|
|
int sx = 0, sy = 0, sh = 0, sw = 0;
|
|
Client *c;
|
|
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
if (n == 0)
|
|
return;
|
|
|
|
sx = mx = m->wx + ov;
|
|
sy = my = m->wy + oh;
|
|
sh = mh = m->wh - 2*oh;
|
|
mw = m->ww - 2*ov - iv*(n - 1);
|
|
sw = m->ww - 2*ov - iv*(n - m->nmaster - 1);
|
|
|
|
if (m->nmaster && n > m->nmaster) {
|
|
mivf = 0.8;
|
|
/* go mfact box in the center if more than nmaster clients */
|
|
if (m->ww > m->wh) {
|
|
mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1);
|
|
mh = m->wh * 0.9;
|
|
} else {
|
|
mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1);
|
|
mh = m->wh * m->mfact;
|
|
}
|
|
mx = m->wx + (m->ww - mw) / 2;
|
|
my = m->wy + (m->wh - mh - 2*oh) / 2;
|
|
|
|
sx = m->wx + ov;
|
|
sy = m->wy + oh;
|
|
sh = m->wh - 2*oh;
|
|
}
|
|
|
|
getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
|
|
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++)
|
|
if (i < m->nmaster) {
|
|
/* nmaster clients are stacked horizontally, in the center of the screen */
|
|
resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
|
mx += WIDTH(c) + iv*mivf;
|
|
} else {
|
|
/* stack clients are stacked horizontally */
|
|
resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
|
sx += WIDTH(c) + iv;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Deck layout + gaps
|
|
* https://dwm.suckless.org/patches/deck/
|
|
*/
|
|
void
|
|
deck(Monitor *m)
|
|
{
|
|
unsigned int i, n;
|
|
int oh, ov, ih, iv;
|
|
int mx = 0, my = 0, mh = 0, mw = 0;
|
|
int sx = 0, sy = 0, sh = 0, sw = 0;
|
|
float mfacts, sfacts;
|
|
int mrest, srest;
|
|
Client *c;
|
|
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
if (n == 0)
|
|
return;
|
|
|
|
sx = mx = m->wx + ov;
|
|
sy = my = m->wy + oh;
|
|
sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
|
sw = mw = m->ww - 2*ov;
|
|
|
|
if (m->nmaster && n > m->nmaster) {
|
|
sw = (mw - iv) * (1 - m->mfact);
|
|
mw = mw - iv - sw;
|
|
sx = mx + mw + iv;
|
|
sh = m->wh - 2*oh;
|
|
}
|
|
|
|
getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
|
|
|
if (n - m->nmaster > 0) /* override layout symbol */
|
|
snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster);
|
|
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++)
|
|
if (i < m->nmaster) {
|
|
resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
|
my += HEIGHT(c) + ih;
|
|
} else {
|
|
resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fibonacci layout + gaps
|
|
* https://dwm.suckless.org/patches/fibonacci/
|
|
*/
|
|
void
|
|
fibonacci(Monitor *m, int s)
|
|
{
|
|
unsigned int i, n;
|
|
int nx, ny, nw, nh;
|
|
int oh, ov, ih, iv;
|
|
int nv, hrest = 0, wrest = 0, r = 1;
|
|
Client *c;
|
|
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
if (n == 0)
|
|
return;
|
|
|
|
nx = m->wx + ov;
|
|
ny = m->wy + oh;
|
|
nw = m->ww - 2*ov;
|
|
nh = m->wh - 2*oh;
|
|
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m)) {
|
|
if (r) {
|
|
if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
|
|
|| (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
|
|
r = 0;
|
|
}
|
|
if (r && i < n - 1) {
|
|
if (i % 2) {
|
|
nv = (nh - ih) / 2;
|
|
hrest = nh - 2*nv - ih;
|
|
nh = nv;
|
|
} else {
|
|
nv = (nw - iv) / 2;
|
|
wrest = nw - 2*nv - iv;
|
|
nw = nv;
|
|
}
|
|
|
|
if ((i % 4) == 2 && !s)
|
|
nx += nw + iv;
|
|
else if ((i % 4) == 3 && !s)
|
|
ny += nh + ih;
|
|
}
|
|
|
|
if ((i % 4) == 0) {
|
|
if (s) {
|
|
ny += nh + ih;
|
|
nh += hrest;
|
|
}
|
|
else {
|
|
nh -= hrest;
|
|
ny -= nh + ih;
|
|
}
|
|
}
|
|
else if ((i % 4) == 1) {
|
|
nx += nw + iv;
|
|
nw += wrest;
|
|
}
|
|
else if ((i % 4) == 2) {
|
|
ny += nh + ih;
|
|
nh += hrest;
|
|
if (i < n - 1)
|
|
nw += wrest;
|
|
}
|
|
else if ((i % 4) == 3) {
|
|
if (s) {
|
|
nx += nw + iv;
|
|
nw -= wrest;
|
|
} else {
|
|
nw -= wrest;
|
|
nx -= nw + iv;
|
|
nh += hrest;
|
|
}
|
|
}
|
|
if (i == 0) {
|
|
if (n != 1) {
|
|
nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
|
|
wrest = 0;
|
|
}
|
|
ny = m->wy + oh;
|
|
}
|
|
else if (i == 1)
|
|
nw = m->ww - nw - iv - 2*ov;
|
|
i++;
|
|
}
|
|
|
|
resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False);
|
|
}
|
|
}
|
|
|
|
void
|
|
dwindle(Monitor *m)
|
|
{
|
|
fibonacci(m, 1);
|
|
}
|
|
|
|
void
|
|
spiral(Monitor *m)
|
|
{
|
|
fibonacci(m, 0);
|
|
}
|
|
|
|
/*
|
|
* Gappless grid layout + gaps (ironically)
|
|
* https://dwm.suckless.org/patches/gaplessgrid/
|
|
*/
|
|
void
|
|
gaplessgrid(Monitor *m)
|
|
{
|
|
unsigned int i, n;
|
|
int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
|
|
int oh, ov, ih, iv;
|
|
Client *c;
|
|
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
if (n == 0)
|
|
return;
|
|
|
|
/* grid dimensions */
|
|
for (cols = 0; cols <= n/2; cols++)
|
|
if (cols*cols >= n)
|
|
break;
|
|
if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
|
|
cols = 2;
|
|
rows = n/cols;
|
|
cn = rn = 0; // reset column no, row no, client count
|
|
|
|
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
|
cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
|
|
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
|
crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
|
x = m->wx + ov;
|
|
y = m->wy + oh;
|
|
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; i++, c = nexttiled(c->next, m)) {
|
|
if (i/rows + 1 > cols - n%cols) {
|
|
rows = n/cols + 1;
|
|
ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
|
|
rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
|
}
|
|
resize(c,
|
|
x,
|
|
y + rn*(ch + ih) + MIN(rn, rrest),
|
|
cw + (cn < crest ? 1 : 0) - 2*c->bw,
|
|
ch + (rn < rrest ? 1 : 0) - 2*c->bw,
|
|
0);
|
|
rn++;
|
|
if (rn >= rows) {
|
|
rn = 0;
|
|
x += cw + ih + (cn < crest ? 1 : 0);
|
|
cn++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Gridmode layout + gaps
|
|
* https://dwm.suckless.org/patches/gridmode/
|
|
*/
|
|
void
|
|
grid(Monitor *m)
|
|
{
|
|
unsigned int i, n;
|
|
int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
|
|
int oh, ov, ih, iv;
|
|
Client *c;
|
|
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
|
|
/* grid dimensions */
|
|
for (rows = 0; rows <= n/2; rows++)
|
|
if (rows*rows >= n)
|
|
break;
|
|
cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
|
|
|
|
/* window geoms (cell height/width) */
|
|
ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
|
|
cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
|
|
chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
|
|
cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++) {
|
|
cc = i / rows;
|
|
cr = i % rows;
|
|
cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
|
|
cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
|
|
resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Horizontal grid layout + gaps
|
|
* https://dwm.suckless.org/patches/horizgrid/
|
|
*/
|
|
void
|
|
horizgrid(Monitor *m) {
|
|
Client *c;
|
|
unsigned int n, i;
|
|
int oh, ov, ih, iv;
|
|
int mx = 0, my = 0, mh = 0, mw = 0;
|
|
int sx = 0, sy = 0, sh = 0, sw = 0;
|
|
int ntop, nbottom = 1;
|
|
float mfacts, sfacts;
|
|
int mrest, srest;
|
|
|
|
/* Count windows */
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
if (n == 0)
|
|
return;
|
|
|
|
if (n <= 2)
|
|
ntop = n;
|
|
else {
|
|
ntop = n / 2;
|
|
nbottom = n - ntop;
|
|
}
|
|
sx = mx = m->wx + ov;
|
|
sy = my = m->wy + oh;
|
|
sh = mh = m->wh - 2*oh;
|
|
sw = mw = m->ww - 2*ov;
|
|
|
|
if (n > ntop) {
|
|
sh = (mh - ih) / 2;
|
|
mh = mh - ih - sh;
|
|
sy = my + mh + ih;
|
|
mw = m->ww - 2*ov - iv * (ntop - 1);
|
|
sw = m->ww - 2*ov - iv * (nbottom - 1);
|
|
}
|
|
|
|
mfacts = ntop;
|
|
sfacts = nbottom;
|
|
mrest = mw - (mw / ntop) * ntop;
|
|
srest = sw - (sw / nbottom) * nbottom;
|
|
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++)
|
|
if (i < ntop) {
|
|
resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
|
|
mx += WIDTH(c) + iv;
|
|
} else {
|
|
resize(c, sx, sy, (sw / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
|
|
sx += WIDTH(c) + iv;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* nrowgrid layout + gaps
|
|
* https://dwm.suckless.org/patches/nrowgrid/
|
|
*/
|
|
void
|
|
nrowgrid(Monitor *m)
|
|
{
|
|
unsigned int n;
|
|
int ri = 0, ci = 0; /* counters */
|
|
int oh, ov, ih, iv; /* vanitygap settings */
|
|
unsigned int cx, cy, cw, ch; /* client geometry */
|
|
unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
|
|
unsigned int cols, rows = m->nmaster + 1;
|
|
Client *c;
|
|
|
|
/* count clients */
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
|
|
/* nothing to do here */
|
|
if (n == 0)
|
|
return;
|
|
|
|
/* force 2 clients to always split vertically */
|
|
if (FORCE_VSPLIT && n == 2)
|
|
rows = 1;
|
|
|
|
/* never allow empty rows */
|
|
if (n < rows)
|
|
rows = n;
|
|
|
|
/* define first row */
|
|
cols = n / rows;
|
|
uc = cols;
|
|
cy = m->wy + oh;
|
|
ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
|
|
uh = ch;
|
|
|
|
for (c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), ci++) {
|
|
if (ci == cols) {
|
|
uw = 0;
|
|
ci = 0;
|
|
ri++;
|
|
|
|
/* next row */
|
|
cols = (n - uc) / (rows - ri);
|
|
uc += cols;
|
|
cy = m->wy + oh + uh + ih;
|
|
uh += ch + ih;
|
|
}
|
|
|
|
cx = m->wx + ov + uw;
|
|
cw = (m->ww - 2*ov - uw) / (cols - ci);
|
|
uw += cw + iv;
|
|
|
|
resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Default tile layout + gaps
|
|
*/
|
|
static void
|
|
tile(Monitor *m)
|
|
{
|
|
unsigned int i, n;
|
|
int oh, ov, ih, iv;
|
|
int mx = 0, my = 0, mh = 0, mw = 0;
|
|
int sx = 0, sy = 0, sh = 0, sw = 0;
|
|
float mfacts, sfacts;
|
|
int mrest, srest;
|
|
Client *c;
|
|
|
|
getgaps(m, &oh, &ov, &ih, &iv, &n);
|
|
if (n == 0)
|
|
return;
|
|
|
|
sx = mx = m->wx + ov;
|
|
sy = my = m->wy + oh;
|
|
mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
|
|
sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
|
|
sw = mw = m->ww - 2*ov;
|
|
|
|
if (m->nmaster && n > m->nmaster) {
|
|
sw = (mw - iv) * (1 - m->mfact);
|
|
mw = mw - iv - sw;
|
|
sx = mx + mw + iv;
|
|
}
|
|
|
|
getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
|
|
|
|
for (i = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++)
|
|
if (i < m->nmaster) {
|
|
resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
|
|
my += HEIGHT(c) + ih;
|
|
} else {
|
|
resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
|
|
sy += HEIGHT(c) + ih;
|
|
}
|
|
}
|