paulo@0: /* (C)opyright MMVI-MMVII Anselm R. Garbe paulo@0: * See LICENSE file for license details. paulo@0: */ paulo@0: #include "dwm.h" paulo@0: paulo@0: unsigned int master = MASTER; paulo@0: unsigned int nmaster = NMASTER; paulo@0: unsigned int blw = 0; paulo@0: Layout *lt = NULL; paulo@0: paulo@0: /* static */ paulo@0: paulo@0: static unsigned int nlayouts = 0; paulo@0: paulo@0: static void paulo@0: spiral(void) { paulo@0: unsigned int i, n, nx, ny, nw, nh; paulo@0: Client *c; paulo@0: paulo@0: nx = wax; paulo@0: ny = way + wah; paulo@0: nw = waw; paulo@0: nh = wah; paulo@0: for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) paulo@0: n++; paulo@0: for(i = 0, c = clients; c; c = c->next) paulo@0: if(isvisible(c)) { paulo@0: if(c->isbanned) paulo@0: XMoveWindow(dpy, c->win, c->x, c->y); paulo@0: c->isbanned = False; paulo@0: if(c->isversatile) paulo@0: continue; paulo@0: c->ismax = False; paulo@0: if((i % 2 && nh / 2 > 2 * c->border) paulo@0: || (!(i % 2) && nw / 2 > 2 * c->border)) paulo@0: { paulo@0: if(i < n - 1) { paulo@0: if(i % 2) paulo@0: nh /= 2; paulo@0: else paulo@0: nw /= 2; paulo@0: if((i % 4) == 2) paulo@0: nx += nw; paulo@0: else if((i % 4) == 3) paulo@0: ny += nh; paulo@0: } paulo@0: if((i % 4) == 0) paulo@0: ny -= nh; paulo@0: else if((i % 4) == 1) paulo@0: nx += nw; paulo@0: else if((i % 4) == 2) paulo@0: ny += nh; paulo@0: else paulo@0: nx -= nw; paulo@0: i++; paulo@0: } paulo@0: resize(c, nx, ny, nw - 2 * c->border, nh - 2 * c->border, False); paulo@0: } paulo@0: else { paulo@0: c->isbanned = True; paulo@0: XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); paulo@0: } paulo@0: if(!sel || !isvisible(sel)) { paulo@0: for(c = stack; c && !isvisible(c); c = c->snext); paulo@0: focus(c); paulo@0: } paulo@0: restack(); paulo@0: } paulo@0: paulo@0: static void paulo@0: spiral_h(void) { paulo@0: unsigned int i, n, nx, ny, nw, nh; paulo@0: Client *c; paulo@0: paulo@0: nx = wax + waw; paulo@0: ny = way; paulo@0: nw = waw; paulo@0: nh = wah; paulo@0: for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) paulo@0: n++; paulo@0: for(i = 0, c = clients; c; c = c->next) paulo@0: if(isvisible(c)) { paulo@0: if(c->isbanned) paulo@0: XMoveWindow(dpy, c->win, c->x, c->y); paulo@0: c->isbanned = False; paulo@0: if(c->isversatile) paulo@0: continue; paulo@0: c->ismax = False; paulo@0: if((i % 2 && nw / 2 > 2 * c->border) paulo@0: || (!(i % 2) && nh / 2 > 2 * c->border)) paulo@0: { paulo@0: if(i < n - 1) { paulo@0: if(i % 2) paulo@0: nw /= 2; paulo@0: else paulo@0: nh /= 2; paulo@0: if((i % 4) == 2) paulo@0: ny += nh; paulo@0: else if((i % 4) == 3) paulo@0: nx += nw; paulo@0: } paulo@0: if((i % 4) == 0) paulo@0: nx -= nw; paulo@0: else if((i % 4) == 1) paulo@0: ny += nh; paulo@0: else if((i % 4) == 2) paulo@0: nx += nw; paulo@0: else paulo@0: ny -= nh; paulo@0: i++; paulo@0: } paulo@0: resize(c, nx, ny, nw - 2 * c->border, nh - 2 * c->border, False); paulo@0: } paulo@0: else { paulo@0: c->isbanned = True; paulo@0: XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); paulo@0: } paulo@0: if(!sel || !isvisible(sel)) { paulo@0: for(c = stack; c && !isvisible(c); c = c->snext); paulo@0: focus(c); paulo@0: } paulo@0: restack(); paulo@0: } paulo@0: paulo@0: static void paulo@0: monocle(void) { paulo@0: Client *c; paulo@0: paulo@0: for(c = clients; c; c = c->next) paulo@0: if(isvisible(c) && c->isbanned) { paulo@0: XMoveWindow(dpy, c->win, c->x, c->y); paulo@0: c->isbanned = False; paulo@0: } paulo@0: else if(!isvisible(c)) { paulo@0: c->isbanned = True; paulo@0: XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); paulo@0: } paulo@0: paulo@0: for(c = nexttiled(clients); c; c = nexttiled(c->next)) paulo@0: resize(c, wax, way, waw - 2*c->border, wah - 2*c->border, False); paulo@0: paulo@0: restack(); paulo@0: } paulo@0: paulo@0: static void paulo@0: cascade(void) { paulo@0: unsigned int i, n, px = 20; paulo@0: Client *c; paulo@0: paulo@0: for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++); paulo@0: paulo@0: for(i = 0, c = clients; c; c = c->next) paulo@0: if(isvisible(c)) { paulo@0: if(c->isbanned) { paulo@0: XMoveWindow(dpy, c->win, c->x, c->y); paulo@0: c->isbanned = False; paulo@0: } paulo@0: if(!c->isversatile) { paulo@0: resize(c, wax+(px*i), way+(px*i), waw-(px*(n-1))-2*c->border, wah-(px*(n-1))-2*c->border, True); paulo@0: i++; paulo@0: } paulo@0: } paulo@0: else if(!isvisible(c)) { paulo@0: c->isbanned = True; paulo@0: XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); paulo@0: } paulo@0: paulo@0: restack(); paulo@0: } paulo@0: paulo@0: static void paulo@0: bstack(void) { paulo@0: unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th; paulo@0: Client *c; paulo@0: paulo@0: for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) paulo@0: n++; paulo@0: /* window geoms */ paulo@0: mh = (n > nmaster) ? (wah * master) / 1000 : wah; paulo@0: mw = (n > nmaster) ? waw / nmaster : waw / (n > 0 ? n : 1); paulo@0: th = wah - mh; paulo@0: tw = (n > nmaster) ? waw / (n - nmaster) : 0; paulo@0: paulo@0: for(i = 0, c = clients; c; c = c->next) paulo@0: if(isvisible(c)) { paulo@0: if(c->isbanned) paulo@0: XMoveWindow(dpy, c->win, c->x, c->y); paulo@0: c->isbanned = False; paulo@0: if(c->isversatile) paulo@0: continue; paulo@0: c->ismax = False; paulo@0: nx = wax; paulo@0: ny = way; paulo@0: if(i < nmaster) { paulo@0: nx += i * mw; paulo@0: nw = mw - 2 * BORDERPX; paulo@0: nh = mh - 2 * BORDERPX; paulo@0: } paulo@0: else { /* tile window */ paulo@0: ny += mh; paulo@0: nh = th - 2 * BORDERPX; paulo@0: if(tw > 2 * BORDERPX) { paulo@0: nx += (i - nmaster) * tw; paulo@0: nw = tw - 2 * BORDERPX; paulo@0: } paulo@0: else /* fallback if th <= 2 * BORDERPX */ paulo@0: nw = waw - 2 * BORDERPX; paulo@0: } paulo@0: resize(c, nx, ny, nw, nh, False); paulo@0: i++; paulo@0: } paulo@0: else { paulo@0: c->isbanned = True; paulo@0: XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); paulo@0: } paulo@0: if(!sel || !isvisible(sel)) { paulo@0: for(c = stack; c && !isvisible(c); c = c->snext); paulo@0: focus(c); paulo@0: } paulo@0: restack(); paulo@0: } paulo@0: paulo@0: static void paulo@0: grid(void) { paulo@5: unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch; paulo@0: Client *c; paulo@0: paulo@0: for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) paulo@0: n++; paulo@5: if(n == 0) paulo@5: return; paulo@0: paulo@5: /* grid dimensions */ paulo@5: for(cols = 0; cols <= n/2; cols++) paulo@5: if(cols*cols >= n) paulo@0: break; paulo@5: if(n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */ paulo@5: cols = 2; paulo@5: rows = n/cols; paulo@0: paulo@5: /* window geometries */ paulo@5: cw = cols ? waw / cols : waw; paulo@5: cn = 0; /* current column number */ paulo@5: rn = 0; /* current row number */ paulo@0: for(i = 0, c = clients; c; c = c->next) paulo@0: if(isvisible(c)) { paulo@5: if(i/rows + 1 > cols - n%cols) paulo@5: rows = n/cols + 1; paulo@5: ch = rows ? wah / rows : wah; paulo@5: cx = cn*cw; paulo@5: cy = (TOPBAR ? dc.h : 0) + rn*ch; paulo@5: resize(c, cx, cy, cw - 2 * BORDERPX, ch - 2 * BORDERPX, False); paulo@5: rn++; paulo@5: if(rn >= rows) { paulo@5: rn = 0; paulo@5: cn++; paulo@5: } paulo@0: i++; paulo@0: } paulo@0: else { paulo@0: c->isbanned = True; paulo@0: XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); paulo@0: } paulo@5: paulo@0: if(!sel || !isvisible(sel)) { paulo@0: for(c = stack; c && !isvisible(c); c = c->snext); paulo@0: focus(c); paulo@0: } paulo@0: restack(); paulo@0: } paulo@0: paulo@0: static void paulo@0: tile(void) { paulo@0: unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th; paulo@0: Client *c; paulo@0: paulo@0: for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) paulo@0: n++; paulo@0: /* window geoms */ paulo@0: mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1); paulo@0: mw = (n > nmaster) ? (waw * master) / 1000 : waw; paulo@0: th = (n > nmaster) ? wah / (n - nmaster) : 0; paulo@0: tw = waw - mw; paulo@0: paulo@0: for(i = 0, c = clients; c; c = c->next) paulo@0: if(isvisible(c)) { paulo@0: if(c->isbanned) paulo@0: XMoveWindow(dpy, c->win, c->x, c->y); paulo@0: c->isbanned = False; paulo@0: if(c->isversatile) paulo@0: continue; paulo@0: c->ismax = False; paulo@0: nx = wax; paulo@0: ny = way; paulo@0: if(i < nmaster) { paulo@0: ny += i * mh; paulo@0: nw = mw - 2 * BORDERPX; paulo@0: nh = mh - 2 * BORDERPX; paulo@0: } paulo@0: else { /* tile window */ paulo@0: nx += mw; paulo@0: nw = tw - 2 * BORDERPX; paulo@0: if(th > 2 * BORDERPX) { paulo@0: ny += (i - nmaster) * th; paulo@0: nh = th - 2 * BORDERPX; paulo@0: } paulo@0: else /* fallback if th <= 2 * BORDERPX */ paulo@0: nh = wah - 2 * BORDERPX; paulo@0: } paulo@0: resize(c, nx, ny, nw, nh, False); paulo@0: i++; paulo@0: } paulo@0: else { paulo@0: c->isbanned = True; paulo@0: XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); paulo@0: } paulo@0: if(!sel || !isvisible(sel)) { paulo@0: for(c = stack; c && !isvisible(c); c = c->snext); paulo@0: focus(c); paulo@0: } paulo@0: restack(); paulo@0: } paulo@0: paulo@0: LAYOUTS paulo@0: paulo@0: /* extern */ paulo@0: paulo@0: void paulo@0: focusnext(Arg *arg) { paulo@0: Client *c; paulo@0: paulo@0: if(!sel) paulo@0: return; paulo@0: for(c = sel->next; c && !isvisible(c); c = c->next); paulo@0: if(!c) paulo@0: for(c = clients; c && !isvisible(c); c = c->next); paulo@0: if(c) { paulo@0: focus(c); paulo@0: restack(); paulo@0: } paulo@0: } paulo@0: paulo@0: void paulo@0: focusprev(Arg *arg) { paulo@0: Client *c; paulo@0: paulo@0: if(!sel) paulo@0: return; paulo@0: for(c = sel->prev; c && !isvisible(c); c = c->prev); paulo@0: if(!c) { paulo@0: for(c = clients; c && c->next; c = c->next); paulo@0: for(; c && !isvisible(c); c = c->prev); paulo@0: } paulo@0: if(c) { paulo@0: focus(c); paulo@0: restack(); paulo@0: } paulo@0: } paulo@0: paulo@0: void paulo@0: incnmaster(Arg *arg) { paulo@0: //if((lt->arrange != tile) || (nmaster + arg->i < 1) paulo@0: //|| (wah / (nmaster + arg->i) <= 2 * BORDERPX)) paulo@0: // return; paulo@0: if(nmaster + arg->i < 1 && nmaster + arg->i <= MAX_TASKS) paulo@0: return; paulo@0: nmaster += arg->i; paulo@0: if(sel) paulo@0: lt->arrange(); paulo@0: else paulo@0: drawstatus(); paulo@0: } paulo@0: paulo@0: void paulo@0: initlayouts(void) { paulo@0: unsigned int i, w; paulo@0: paulo@0: lt = &layout[0]; paulo@0: nlayouts = sizeof layout / sizeof layout[0]; paulo@0: for(blw = i = 0; i < nlayouts; i++) { paulo@0: w = textw(layout[i].symbol); paulo@0: if(w > blw) paulo@0: blw = w; paulo@0: } paulo@0: } paulo@0: paulo@0: Client * paulo@0: nexttiled(Client *c) { paulo@0: for(; c && (c->isversatile || !isvisible(c)); c = c->next); paulo@0: return c; paulo@0: } paulo@0: paulo@0: void paulo@0: resizemaster(Arg *arg) { paulo@0: //if(lt->arrange != tile) paulo@0: // return; paulo@0: if(arg->i == 0) paulo@0: master = MASTER; paulo@0: else { paulo@0: //if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX paulo@0: //|| waw * (master + arg->i) / 1000 <= 2 * BORDERPX) paulo@0: // return; paulo@0: master += arg->i; paulo@0: } paulo@0: lt->arrange(); paulo@0: } paulo@0: paulo@0: void paulo@0: restack(void) { paulo@0: Client *c; paulo@0: XEvent ev; paulo@0: paulo@0: drawstatus(); paulo@0: if(!sel) paulo@0: return; paulo@0: if(sel->isversatile || lt->arrange == versatile) paulo@0: XRaiseWindow(dpy, sel->win); paulo@0: if(lt->arrange != versatile) { paulo@0: if(!sel->isversatile) paulo@0: XLowerWindow(dpy, sel->win); paulo@0: for(c = nexttiled(clients); c; c = nexttiled(c->next)) { paulo@0: if(c == sel) paulo@0: continue; paulo@0: XLowerWindow(dpy, c->win); paulo@0: } paulo@0: } paulo@0: XSync(dpy, False); paulo@0: while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); paulo@0: } paulo@0: paulo@0: void paulo@0: setlayout(Arg *arg) { paulo@1: int i; paulo@0: paulo@1: if(arg->i < 0) { paulo@0: for(i = 0; i < nlayouts && lt != &layout[i]; i++); paulo@1: if(arg->i == -1) paulo@1: lt = &layout[(i + 1) % nlayouts]; paulo@1: else if(arg->i == -2) paulo@1: lt = &layout[(i - 1) >= 0 ? i - 1 : nlayouts - 1]; paulo@0: } paulo@0: else { paulo@0: if(arg->i < 0 || arg->i >= nlayouts) paulo@0: return; paulo@0: lt = &layout[arg->i]; paulo@0: } paulo@0: if(sel) paulo@0: lt->arrange(); paulo@0: else paulo@0: drawstatus(); paulo@0: } paulo@0: paulo@0: void paulo@0: versatile(void) { paulo@0: Client *c; paulo@0: paulo@0: for(c = clients; c; c = c->next) { paulo@0: if(isvisible(c)) { paulo@0: if(c->isbanned) paulo@0: XMoveWindow(dpy, c->win, c->x, c->y); paulo@0: c->isbanned = False; paulo@0: resize(c, c->x, c->y, c->w, c->h, True); paulo@0: } paulo@0: else { paulo@0: c->isbanned = True; paulo@0: XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); paulo@0: } paulo@0: } paulo@0: if(!sel || !isvisible(sel)) { paulo@0: for(c = stack; c && !isvisible(c); c = c->snext); paulo@0: focus(c); paulo@0: } paulo@0: restack(); paulo@0: }