all repos — dwm @ 0b7c0f10eeee1c473b1adcee3a8b90db61b854e9

fork of suckless dynamic window manager

view.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
  6/* static */
  7
  8static Client *
  9nexttiled(Client *c) {
 10	for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
 11	return c;
 12}
 13
 14static Bool
 15ismaster(Client *c) {
 16	Client *cl;
 17	unsigned int i;
 18
 19	for(cl = nexttiled(clients), i = 0; cl && cl != c; cl = nexttiled(cl->next), i++);
 20	return i < nmaster;
 21}
 22
 23static void
 24pop(Client *c) {
 25	detach(c);
 26	if(clients)
 27		clients->prev = c;
 28	c->next = clients;
 29	clients = c;
 30}
 31
 32static void
 33swap(Client *c1, Client *c2) {
 34	Client tmp = *c1;
 35	Client *c1p = c1->prev;
 36	Client *c1n = c1->next;
 37	Client *c1s = c1->snext;
 38	Client *c2p = c2->prev;
 39	Client *c2n = c2->next;
 40	Client *c2s = c2->snext;
 41
 42	*c1 = *c2;
 43	*c2 = tmp;
 44	c1->prev = c1p;
 45	c1->next = c1n;
 46	c1->snext = c1s;
 47	c2->prev = c2p;
 48	c2->next = c2n;
 49	c2->snext = c2s;
 50}
 51
 52static void
 53togglemax(Client *c) {
 54	XEvent ev;
 55		
 56	if(c->isfixed)
 57		return;
 58
 59	if((c->ismax = !c->ismax)) {
 60		c->rx = c->x; c->x = wax;
 61		c->ry = c->y; c->y = way;
 62		c->rw = c->w; c->w = waw - 2 * BORDERPX;
 63		c->rh = c->h; c->h = wah - 2 * BORDERPX;
 64	}
 65	else {
 66		c->x = c->rx;
 67		c->y = c->ry;
 68		c->w = c->rw;
 69		c->h = c->rh;
 70	}
 71	resize(c, True, TopLeft);
 72	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
 73}
 74
 75static Client *
 76topofstack() {
 77	Client *c;
 78	unsigned int i;
 79
 80	for(c = nexttiled(clients), i = 0; c && i < nmaster; c = nexttiled(c->next), i++);
 81	return (i < nmaster) ? NULL : c;
 82}
 83
 84/* extern */
 85
 86void (*arrange)(void) = DEFMODE;
 87
 88void
 89detach(Client *c) {
 90	if(c->prev)
 91		c->prev->next = c->next;
 92	if(c->next)
 93		c->next->prev = c->prev;
 94	if(c == clients)
 95		clients = c->next;
 96	c->next = c->prev = NULL;
 97}
 98
 99void
100dofloat(void) {
101	Client *c;
102
103	for(c = clients; c; c = c->next) {
104		if(isvisible(c)) {
105			resize(c, True, TopLeft);
106		}
107		else
108			ban(c);
109	}
110	if(!sel || !isvisible(sel)) {
111		for(c = stack; c && !isvisible(c); c = c->snext);
112		focus(c);
113	}
114	restack();
115}
116
117void
118dotile(void) {
119	unsigned int i, n, mw, mh, tw, th;
120	Client *c;
121
122	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
123		n++;
124	/* window geoms */
125	mw = (n > nmaster) ? (waw * master) / 1000 : waw;
126	mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
127	tw = waw - mw;
128	th = (n > nmaster) ? wah / (n - nmaster) : 0;
129
130	for(i = 0, c = clients; c; c = c->next)
131		if(isvisible(c)) {
132			if(c->isfloat) {
133				resize(c, True, TopLeft);
134				continue;
135			}
136			c->ismax = False;
137			c->x = wax;
138			c->y = way;
139			if(i < nmaster) {
140				c->y += i * mh;
141				c->w = mw - 2 * BORDERPX;
142				c->h = mh - 2 * BORDERPX;
143			}
144			else {  /* tile window */
145				c->x += mw;
146				c->w = tw - 2 * BORDERPX;
147				if(th > bh) {
148					c->y += (i - nmaster) * th;
149					c->h = th - 2 * BORDERPX;
150				}
151				else /* fallback if th < bh */
152					c->h = wah - 2 * BORDERPX;
153			}
154			resize(c, False, TopLeft);
155			i++;
156		}
157		else
158			ban(c);
159
160	if(!sel || !isvisible(sel)) {
161		for(c = stack; c && !isvisible(c); c = c->snext);
162		focus(c);
163	}
164	restack();
165}
166
167void
168focusnext(Arg *arg) {
169	Client *c;
170   
171	if(!sel)
172		return;
173	if(!(c = getnext(sel->next)))
174		c = getnext(clients);
175	if(c) {
176		focus(c);
177		restack();
178	}
179}
180
181void
182focusprev(Arg *arg) {
183	Client *c;
184
185	if(!sel)
186		return;
187	if(!(c = getprev(sel->prev))) {
188		for(c = clients; c && c->next; c = c->next);
189		c = getprev(c);
190	}
191	if(c) {
192		focus(c);
193		restack();
194	}
195}
196
197void
198incnmaster(Arg *arg) {
199	if((nmaster + arg->i < 1) || (wah / (nmaster + arg->i) < bh))
200		return;
201	nmaster += arg->i;
202	arrange();
203}
204
205Bool
206isvisible(Client *c) {
207	unsigned int i;
208
209	for(i = 0; i < ntags; i++)
210		if(c->tags[i] && seltag[i])
211			return True;
212	return False;
213}
214
215void
216resizemaster(Arg *arg) {
217	if(arg->i == 0)
218		master = MASTER;
219	else {
220		if(master + arg->i > 950 || master + arg->i < 50)
221			return;
222		master += arg->i;
223	}
224	arrange();
225}
226
227void
228restack(void) {
229	Client *c;
230	XEvent ev;
231
232	if(!sel) {
233		drawstatus();
234		return;
235	}
236	if(sel->isfloat || arrange == dofloat) {
237		XRaiseWindow(dpy, sel->win);
238		XRaiseWindow(dpy, sel->twin);
239	}
240	if(arrange != dofloat) {
241		if(!sel->isfloat) {
242			XLowerWindow(dpy, sel->twin);
243			XLowerWindow(dpy, sel->win);
244		}
245		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
246			if(c == sel)
247				continue;
248			XLowerWindow(dpy, c->twin);
249			XLowerWindow(dpy, c->win);
250		}
251	}
252	drawall();
253	XSync(dpy, False);
254	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
255}
256
257void
258togglefloat(Arg *arg) {
259	if (!sel || arrange == dofloat)
260		return;
261	sel->isfloat = !sel->isfloat;
262	arrange();
263}
264
265void
266togglemode(Arg *arg) {
267	arrange = (arrange == dofloat) ? dotile : dofloat;
268	if(sel)
269		arrange();
270	else
271		drawstatus();
272}
273
274void
275toggleview(Arg *arg) {
276	unsigned int i;
277
278	seltag[arg->i] = !seltag[arg->i];
279	for(i = 0; i < ntags && !seltag[i]; i++);
280	if(i == ntags)
281		seltag[arg->i] = True; /* cannot toggle last view */
282	arrange();
283}
284
285void
286view(Arg *arg) {
287	unsigned int i;
288
289	for(i = 0; i < ntags; i++)
290		seltag[i] = (arg->i == -1) ? True : False;
291	if(arg->i >= 0 && arg->i < ntags)
292		seltag[arg->i] = True;
293	arrange();
294}
295
296void
297zoom(Arg *arg) {
298	unsigned int n;
299	Client *c;
300
301	if(!sel)
302		return;
303	if(sel->isfloat || (arrange == dofloat)) {
304		togglemax(sel);
305		return;
306	}
307	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
308		n++;
309
310	c = sel;
311	if(arrange == dofloat)
312		return;
313	else if(n <= nmaster)
314		pop(c);
315	else if(ismaster(sel)) {
316		if(!(c = topofstack()))
317			return;
318		swap(c, sel);
319		c = sel;
320	}
321	else
322		pop(c);
323
324	focus(c);
325	arrange();
326}