all repos — dwm @ 317137149804c759e14a9e7d4704ac89262bd4e6

fork of suckless dynamic window manager

layout.c (view raw)

  1/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
  2 * See LICENSE file for license details.
  3 */
  4#include "dwm.h"
  5
  6unsigned int blw = 0;
  7Layout *lt = NULL;
  8
  9/* static */
 10
 11static unsigned int nlayouts = 0;
 12static unsigned int masterw = MASTERWIDTH;
 13static unsigned int nmaster = NMASTER;
 14
 15static void
 16tile(void) {
 17	unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
 18	Client *c;
 19
 20	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
 21		n++;
 22	/* window geoms */
 23	mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
 24	mw = (n > nmaster) ? (waw * masterw) / 1000 : waw;
 25	th = (n > nmaster) ? wah / (n - nmaster) : 0;
 26	tw = waw - mw;
 27
 28	for(i = 0, c = clients; c; c = c->next)
 29		if(isvisible(c)) {
 30			if(c->isbanned)
 31				XMoveWindow(dpy, c->win, c->x, c->y);
 32			c->isbanned = False;
 33			if(c->isversatile)
 34				continue;
 35			c->ismax = False;
 36			nx = wax;
 37			ny = way;
 38			if(i < nmaster) {
 39				ny += i * mh;
 40				nw = mw - 2 * BORDERPX;
 41				nh = mh - 2 * BORDERPX;
 42			}
 43			else {  /* tile window */
 44				nx += mw;
 45				nw = tw - 2 * BORDERPX;
 46				if(th > 2 * BORDERPX) {
 47					ny += (i - nmaster) * th;
 48					nh = th - 2 * BORDERPX;
 49				}
 50				else /* fallback if th <= 2 * BORDERPX */
 51					nh = wah - 2 * BORDERPX;
 52			}
 53			resize(c, nx, ny, nw, nh, False);
 54			i++;
 55		}
 56		else {
 57			c->isbanned = True;
 58			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
 59		}
 60	if(!sel || !isvisible(sel)) {
 61		for(c = stack; c && !isvisible(c); c = c->snext);
 62		focus(c);
 63	}
 64	restack();
 65}
 66
 67LAYOUTS
 68
 69/* extern */
 70
 71void
 72focusnext(Arg arg) {
 73	Client *c;
 74   
 75	if(!sel)
 76		return;
 77	for(c = sel->next; c && !isvisible(c); c = c->next);
 78	if(!c)
 79		for(c = clients; c && !isvisible(c); c = c->next);
 80	if(c) {
 81		focus(c);
 82		restack();
 83	}
 84}
 85
 86void
 87focusprev(Arg arg) {
 88	Client *c;
 89
 90	if(!sel)
 91		return;
 92	for(c = sel->prev; c && !isvisible(c); c = c->prev);
 93	if(!c) {
 94		for(c = clients; c && c->next; c = c->next);
 95		for(; c && !isvisible(c); c = c->prev);
 96	}
 97	if(c) {
 98		focus(c);
 99		restack();
100	}
101}
102
103void
104incmasterw(Arg arg) {
105	if(lt->arrange != tile)
106		return;
107	if(arg.i == 0)
108		masterw = MASTERWIDTH;
109	else {
110		if(waw * (masterw + arg.i) / 1000 >= waw - 2 * BORDERPX
111		|| waw * (masterw + arg.i) / 1000 <= 2 * BORDERPX)
112			return;
113		masterw += arg.i;
114	}
115	lt->arrange();
116}
117
118void
119incnmaster(Arg arg) {
120	if((lt->arrange != tile) || (nmaster + arg.i < 1)
121	|| (wah / (nmaster + arg.i) <= 2 * BORDERPX))
122		return;
123	nmaster += arg.i;
124	if(sel)
125		lt->arrange();
126	else
127		drawstatus();
128}
129
130void
131initlayouts(void) {
132	unsigned int i, w;
133
134	lt = &layout[0];
135	nlayouts = sizeof layout / sizeof layout[0];
136	for(blw = i = 0; i < nlayouts; i++) {
137		w = textw(layout[i].symbol);
138		if(w > blw)
139			blw = w;
140	}
141}
142
143Client *
144nexttiled(Client *c) {
145	for(; c && (c->isversatile || !isvisible(c)); c = c->next);
146	return c;
147}
148
149void
150restack(void) {
151	Client *c;
152	XEvent ev;
153
154	drawstatus();
155	if(!sel)
156		return;
157	if(sel->isversatile || lt->arrange == versatile)
158		XRaiseWindow(dpy, sel->win);
159	if(lt->arrange != versatile) {
160		if(!sel->isversatile)
161			XLowerWindow(dpy, sel->win);
162		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
163			if(c == sel)
164				continue;
165			XLowerWindow(dpy, c->win);
166		}
167	}
168	XSync(dpy, False);
169	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
170}
171
172void
173setlayout(Arg arg) {
174	unsigned int i;
175
176	if(arg.i == -1) {
177		for(i = 0; i < nlayouts && lt != &layout[i]; i++);
178		if(i == nlayouts - 1)
179			lt = &layout[0];
180		else
181			lt = &layout[++i];
182	}
183	else {
184		if(arg.i < 0 || arg.i >= nlayouts)
185			return;
186		lt = &layout[arg.i];
187	}
188	if(sel)
189		lt->arrange();
190	else
191		drawstatus();
192}
193
194void
195togglemax(Arg arg) {
196	XEvent ev;
197
198	if(!sel || (lt->arrange != versatile && !sel->isversatile) || sel->isfixed)
199		return;
200	if((sel->ismax = !sel->ismax)) {
201		sel->rx = sel->x;
202		sel->ry = sel->y;
203		sel->rw = sel->w;
204		sel->rh = sel->h;
205		resize(sel, wax, way, waw - 2 * BORDERPX, wah - 2 * BORDERPX, True);
206	}
207	else
208		resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
209	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
210}
211
212void
213versatile(void) {
214	Client *c;
215
216	for(c = clients; c; c = c->next) {
217		if(isvisible(c)) {
218			if(c->isbanned)
219				XMoveWindow(dpy, c->win, c->x, c->y);
220			c->isbanned = False;
221			resize(c, c->x, c->y, c->w, c->h, True);
222		}
223		else {
224			c->isbanned = True;
225			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
226		}
227	}
228	if(!sel || !isvisible(sel)) {
229		for(c = stack; c && !isvisible(c); c = c->snext);
230		focus(c);
231	}
232	restack();
233}
234
235void
236zoom(Arg arg) {
237	unsigned int n;
238	Client *c;
239
240	if(!sel || lt->arrange != tile || sel->isversatile)
241		return;
242	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
243		n++;
244	if((c = sel) == nexttiled(clients))
245		if(!(c = nexttiled(c->next)))
246			return;
247	detach(c);
248	attach(c);
249	focus(c);
250	lt->arrange();
251}