all repos — dwm @ 587100873a66e34251041678504a8c1e28410591

fork of suckless dynamic window manager

layout.c (view raw)

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