all repos — dwm @ a967d7f66447b1b3023cdb4b5a10fca2cfb23b05

fork of suckless dynamic window manager

layout.c (view raw)

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