all repos — dwm @ 671442e89d6e8e8c42912df08a82466f126a7b3b

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