all repos — dwm @ 492c6f10fcf9acf74d84eb3fe005ecf2dd42611a

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