all repos — dwm @ e1deda9e040c052af62aecc2fb4ee770fb2496a2

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