all repos — dwm @ ba96131af0e3a46b8dfbe7c938954f833339e77a

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(const char *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(const char *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(const char *arg) {
105	int i;
106	if(lt->arrange != tile)
107		return;
108	if(!arg)
109		masterw = MASTERWIDTH;
110	else {
111		i = atoi(arg);
112		if(waw * (masterw + i) / 1000 >= waw - 2 * BORDERPX
113		|| waw * (masterw + i) / 1000 <= 2 * BORDERPX)
114			return;
115		masterw += i;
116	}
117	lt->arrange();
118}
119
120void
121incnmaster(const char *arg) {
122	int i = arg ? atoi(arg) : 0;
123	if((lt->arrange != tile) || (nmaster + i < 1)
124	|| (wah / (nmaster + i) <= 2 * BORDERPX))
125		return;
126	nmaster += i;
127	if(sel)
128		lt->arrange();
129	else
130		drawstatus();
131}
132
133void
134initlayouts(void) {
135	unsigned int i, w;
136
137	lt = &layout[0];
138	nlayouts = sizeof layout / sizeof layout[0];
139	for(blw = i = 0; i < nlayouts; i++) {
140		w = textw(layout[i].symbol);
141		if(w > blw)
142			blw = w;
143	}
144}
145
146Client *
147nexttiled(Client *c) {
148	for(; c && (c->isversatile || !isvisible(c)); c = c->next);
149	return c;
150}
151
152void
153restack(void) {
154	Client *c;
155	XEvent ev;
156
157	drawstatus();
158	if(!sel)
159		return;
160	if(sel->isversatile || lt->arrange == versatile)
161		XRaiseWindow(dpy, sel->win);
162	if(lt->arrange != versatile) {
163		if(!sel->isversatile)
164			XLowerWindow(dpy, sel->win);
165		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
166			if(c == sel)
167				continue;
168			XLowerWindow(dpy, c->win);
169		}
170	}
171	XSync(dpy, False);
172	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
173}
174
175void
176setlayout(const char *arg) {
177	unsigned int i;
178
179	if(!arg) {
180		for(i = 0; i < nlayouts && lt != &layout[i]; i++);
181		if(i == nlayouts - 1)
182			lt = &layout[0];
183		else
184			lt = &layout[++i];
185	}
186	else {
187		i = atoi(arg);
188		if(i < 0 || i >= nlayouts)
189			return;
190		lt = &layout[i];
191	}
192	if(sel)
193		lt->arrange();
194	else
195		drawstatus();
196}
197
198void
199togglemax(const char *arg) {
200	XEvent ev;
201
202	if(!sel || (lt->arrange != versatile && !sel->isversatile) || sel->isfixed)
203		return;
204	if((sel->ismax = !sel->ismax)) {
205		sel->rx = sel->x;
206		sel->ry = sel->y;
207		sel->rw = sel->w;
208		sel->rh = sel->h;
209		resize(sel, wax, way, waw - 2 * BORDERPX, wah - 2 * BORDERPX, True);
210	}
211	else
212		resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
213	drawstatus();
214	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
215}
216
217void
218versatile(void) {
219	Client *c;
220
221	for(c = clients; c; c = c->next) {
222		if(isvisible(c)) {
223			if(c->isbanned)
224				XMoveWindow(dpy, c->win, c->x, c->y);
225			c->isbanned = False;
226			resize(c, c->x, c->y, c->w, c->h, True);
227		}
228		else {
229			c->isbanned = True;
230			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
231		}
232	}
233	if(!sel || !isvisible(sel)) {
234		for(c = stack; c && !isvisible(c); c = c->snext);
235		focus(c);
236	}
237	restack();
238}
239
240void
241zoom(const char *arg) {
242	unsigned int n;
243	Client *c;
244
245	if(!sel || lt->arrange != tile || sel->isversatile)
246		return;
247	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
248		n++;
249	if((c = sel) == nexttiled(clients))
250		if(!(c = nexttiled(c->next)))
251			return;
252	detach(c);
253	attach(c);
254	focus(c);
255	lt->arrange();
256}