all repos — dwm @ ecd9c3e22289b1627f7239e393bfb9c1967eee32

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