all repos — dwm @ 825b7c3eb17fd0a79005110bf28e92c4ed2f1a90

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