all repos — dwm @ 6646468125eb4822d8f96b2b587c66c9b1d12eec

fork of suckless dynamic window manager

view.c (view raw)

  1/*
  2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
  3 * See LICENSE file for license details.
  4 */
  5#include "dwm.h"
  6
  7/* static */
  8
  9static Client *
 10minclient(void) {
 11	Client *c, *min;
 12
 13	if((clients && clients->isfloat) || arrange == dofloat)
 14		return clients; /* don't touch floating order */
 15	for(min = c = clients; c; c = c->next)
 16		if(c->weight < min->weight)
 17			min = c;
 18	return min;
 19}
 20
 21static Client *
 22nexttiled(Client *c) {
 23	for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
 24	return c;
 25}
 26
 27static void
 28reorder(void) {
 29	Client *c, *newclients, *tail;
 30
 31	newclients = tail = NULL;
 32	while((c = minclient())) {
 33		detach(c);
 34		if(tail) {
 35			c->prev = tail;
 36			tail->next = c;
 37			tail = c;
 38		}
 39		else
 40			tail = newclients = c;
 41	}
 42	clients = newclients;
 43}
 44
 45static void
 46togglemax(Client *c)
 47{
 48	XEvent ev;
 49	if((c->ismax = !c->ismax)) {
 50		c->rx = c->x; c->x = sx;
 51		c->ry = c->y; c->y = bh;
 52		c->rw = c->w; c->w = sw - 2 * BORDERPX;
 53		c->rh = c->h; c->h = sh - bh - 2 * BORDERPX;
 54	}
 55	else {
 56		c->x = c->rx;
 57		c->y = c->ry;
 58		c->w = c->rw;
 59		c->h = c->rh;
 60	}
 61	resize(c, True, TopLeft);
 62	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
 63}
 64
 65/* extern */
 66
 67void (*arrange)(Arg *) = DEFMODE;
 68Bool isvertical = VERTICALSTACK;
 69StackPos stackpos = STACKPOS;
 70
 71void
 72detach(Client *c) {
 73	if(c->prev)
 74		c->prev->next = c->next;
 75	if(c->next)
 76		c->next->prev = c->prev;
 77	if(c == clients)
 78		clients = c->next;
 79	c->next = c->prev = NULL;
 80}
 81
 82void
 83dofloat(Arg *arg) {
 84	Client *c;
 85
 86	for(c = clients; c; c = c->next) {
 87		if(isvisible(c)) {
 88			resize(c, True, TopLeft);
 89		}
 90		else
 91			ban(c);
 92	}
 93	if(!sel || !isvisible(sel)) {
 94		for(c = stack; c && !isvisible(c); c = c->snext);
 95		focus(c);
 96	}
 97	restack();
 98}
 99
100/* This algorithm is based on a (M)aster area and a (S)tacking area.
101 * It supports following arrangements:
102 * 	SSMMM	MMMMM	MMMSS
103 * 	SSMMM	SSSSS	MMMSS
104 */
105void
106dotile(Arg *arg) {
107	int i, n, stackw, stackh, tw, th;
108	Client *c;
109
110	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
111		n++;
112
113	if(stackpos == StackBottom) {
114		stackw = sw;
115		stackh = sh - bh - master;
116	}
117	else {
118		stackw = sw - master;
119		stackh = sh - bh;
120	}
121
122	if(isvertical) {
123		tw = stackw;
124		if(n > 1)
125			th = stackh / (n - 1);
126		else
127			th = stackh;
128	}
129	else {
130		th = stackh;
131		if(n > 1)
132			tw = stackw / (n - 1);
133		else
134			tw = stackw;
135	}
136
137	for(i = 0, c = clients; c; c = c->next) {
138		if(isvisible(c)) {
139			if(c->isfloat) {
140				resize(c, True, TopLeft);
141				continue;
142			}
143			c->ismax = False;
144			if(n == 1) { /* only 1 window */
145				c->x = sx;
146				c->y = sy + bh;
147				c->w = sw - 2 * BORDERPX;
148				c->h = sh - 2 * BORDERPX - bh;
149			}
150			else if(i == 0) { /* master window */
151				switch(stackpos) {
152				case StackLeft:
153					c->x = sx + stackw;
154					c->y = sy + bh;
155					c->w = master - 2 * BORDERPX;
156					c->h = sh - bh - 2 * BORDERPX;
157					break;
158				case StackBottom:
159					c->x = sx;
160					c->y = sy + bh;
161					c->w = sw - 2 * BORDERPX;
162					c->h = master - 2 * BORDERPX;
163					break;
164				case StackRight:
165					c->x = sx;
166					c->y = sy + bh;
167					c->w = master - 2 * BORDERPX;
168					c->h = sh - bh - 2 * BORDERPX;
169					break;
170				}
171			}
172			else if((isvertical && th > bh) || (!isvertical && tw > MINW)) {
173				/* tile window */
174				c->w = tw - 2 * BORDERPX;
175				c->h = th - 2 * BORDERPX;
176				switch(stackpos) {
177				case StackLeft:
178					if(isvertical) {
179						c->x = sx;
180						c->y = sy + (i - 1) * th + bh;
181						if(i + 1 == n)
182							c->h = sh - c->y - 2 * BORDERPX;
183					}
184					else {
185						c->x = sx + (i - 1) * tw;
186						c->y = sy + bh;
187						if(i + 1 == n)
188							c->w = sx + stackw - c->x - 2 * BORDERPX;
189					}
190					break;
191				case StackBottom:
192					if(isvertical) {
193						c->x = sx;
194						c->y = sy + master + (i - 1) * th + bh;
195						if(i + 1 == n)
196							c->h = sh - c->y - 2 * BORDERPX;
197					}
198					else {
199						c->x = sx + (i - 1) * tw;
200						c->y = sy + bh + master;
201						if(i + 1 == n)
202							c->w = sw - c->x - 2 * BORDERPX;
203					}
204					break;
205				case StackRight:
206					if(isvertical) {
207						c->x = sx + master;
208						c->y = sy + (i - 1) * th + bh;
209						if(i + 1 == n)
210							c->h = sh - c->y - 2 * BORDERPX;
211					}
212					else {
213						c->x = sx + master + (i - 1) * tw;
214						c->y = sy + bh;
215						if(i + 1 == n)
216							c->w = sx + stackw - c->x - 2 * BORDERPX;
217					}
218					break;
219				}
220			}
221			else { /* fallback if th < bh resp. tw < MINW */
222				c->w = stackw - 2 * BORDERPX;
223				c->h = stackh - 2 * BORDERPX;
224				switch(stackpos) {
225				case StackLeft:
226					c->x = sx;
227					c->y = sy + bh;
228					break;
229				case StackBottom:
230					c->x = sx;
231					c->y = sy + master;
232					break;
233				case StackRight:
234					c->x = sx + master;
235					c->y = sy + bh;
236					break;
237				}
238			}
239			resize(c, False, TopLeft);
240			i++;
241		}
242		else
243			ban(c);
244	}
245	if(!sel || !isvisible(sel)) {
246		for(c = stack; c && !isvisible(c); c = c->snext);
247		focus(c);
248	}
249	restack();
250}
251
252void
253focusnext(Arg *arg) {
254	Client *c;
255   
256	if(!sel)
257		return;
258
259	if(!(c = getnext(sel->next)))
260		c = getnext(clients);
261	if(c) {
262		focus(c);
263		restack();
264	}
265}
266
267void
268focusprev(Arg *arg) {
269	Client *c;
270
271	if(!sel)
272		return;
273
274	if(!(c = getprev(sel->prev))) {
275		for(c = clients; c && c->next; c = c->next);
276		c = getprev(c);
277	}
278	if(c) {
279		focus(c);
280		restack();
281	}
282}
283
284Bool
285isvisible(Client *c) {
286	unsigned int i;
287
288	for(i = 0; i < ntags; i++)
289		if(c->tags[i] && seltag[i])
290			return True;
291	return False;
292}
293
294void
295resizecol(Arg *arg) {
296	unsigned int n;
297	Client *c;
298
299	for(n = 0, c = clients; c; c = c->next)
300		if(isvisible(c) && !c->isfloat)
301			n++;
302	if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
303		return;
304
305	if(sel == getnext(clients)) {
306		if(master + arg->i > sw - MINW || master + arg->i < MINW)
307			return;
308		master += arg->i;
309	}
310	else {
311		if(master - arg->i > sw - MINW || master - arg->i < MINW)
312			return;
313		master -= arg->i;
314	}
315	arrange(NULL);
316}
317
318void
319restack(void) {
320	Client *c;
321	XEvent ev;
322
323	if(!sel) {
324		drawstatus();
325		return;
326	}
327	if(sel->isfloat || arrange == dofloat) {
328		XRaiseWindow(dpy, sel->win);
329		XRaiseWindow(dpy, sel->twin);
330	}
331	if(arrange != dofloat)
332		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
333			XLowerWindow(dpy, c->twin);
334			XLowerWindow(dpy, c->win);
335		}
336	drawall();
337	XSync(dpy, False);
338	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
339}
340
341void
342togglemode(Arg *arg) {
343	arrange = (arrange == dofloat) ? dotile : dofloat;
344	if(sel)
345		arrange(NULL);
346	else
347		drawstatus();
348}
349
350void
351toggleview(Arg *arg) {
352	unsigned int i;
353
354	seltag[arg->i] = !seltag[arg->i];
355	for(i = 0; i < ntags && !seltag[i]; i++);
356	if(i == ntags)
357		seltag[arg->i] = True; /* cannot toggle last view */
358	reorder();
359	arrange(NULL);
360}
361
362void
363togglestackdir(Arg *arg) {
364	if(arrange == dofloat)
365		return;
366	isvertical = !isvertical;
367	arrange(NULL);
368}
369
370void
371togglestackpos(Arg *arg) {
372	if(arrange == dofloat)
373		return;
374	if(stackpos == StackBottom)
375		stackpos = STACKPOS;
376	else
377		stackpos = StackBottom;
378	updatemaster();
379	arrange(NULL);
380}
381
382void
383updatemaster(void) {
384	master = ((stackpos == StackBottom ? sh - bh : sw) * MASTER) / 100;
385}
386
387void
388view(Arg *arg) {
389	unsigned int i;
390
391	for(i = 0; i < ntags; i++)
392		seltag[i] = False;
393	seltag[arg->i] = True;
394	reorder();
395	arrange(NULL);
396}
397
398void
399viewall(Arg *arg) {
400	unsigned int i;
401
402	for(i = 0; i < ntags; i++)
403		seltag[i] = True;
404	reorder();
405	arrange(NULL);
406}
407
408
409
410void
411zoom(Arg *arg) {
412	unsigned int n;
413	Client *c;
414
415	if(!sel)
416		return;
417
418	if(sel->isfloat || (arrange == dofloat)) {
419		togglemax(sel);
420		return;
421	}
422
423	for(n = 0, c = clients; c; c = c->next)
424		if(isvisible(c) && !c->isfloat)
425			n++;
426	if(n < 2 || (arrange == dofloat))
427		return;
428
429	if((c = sel) == nexttiled(clients))
430		if(!(c = nexttiled(c->next)))
431			return;
432	detach(c);
433	if(clients)
434		clients->prev = c;
435	c->next = clients;
436	clients = c;
437	focus(c);
438	arrange(NULL);
439}