all repos — dwm @ 199a6016114875656102d11e79a80939bfaff3b3

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