all repos — dwm @ e0f64e63db654330bf4219a25b8989a72123d661

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;
 68StackPos stackpos = STACKPOS;
 69
 70void
 71detach(Client *c) {
 72	if(c->prev)
 73		c->prev->next = c->next;
 74	if(c->next)
 75		c->next->prev = c->prev;
 76	if(c == clients)
 77		clients = c->next;
 78	c->next = c->prev = NULL;
 79}
 80
 81void
 82dofloat(Arg *arg) {
 83	Client *c;
 84
 85	for(c = clients; c; c = c->next) {
 86		if(isvisible(c)) {
 87			resize(c, True, TopLeft);
 88		}
 89		else
 90			ban(c);
 91	}
 92	if(!sel || !isvisible(sel)) {
 93		for(c = stack; c && !isvisible(c); c = c->snext);
 94		focus(c);
 95	}
 96	restack();
 97}
 98
 99/* This algorithm is based on a (M)aster area and a (S)tacking area.
100 * It supports following arrangements:
101 * 	SSMMM	MMMMM	MMMSS
102 * 	SSMMM	SSSSS	MMMSS
103 */
104void
105dotile(Arg *arg) {
106	int i, n, stackw, stackh, tw, th;
107	Client *c;
108
109	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
110		n++;
111
112	if(stackpos == StackBottom) {
113		stackw = sw;
114		stackh = sh - bh - master;
115	}
116	else {
117		stackw = sw - master;
118		stackh = sh - bh;
119	}
120
121	tw = stackw;
122	if(n > 1)
123		th = stackh / (n - 1);
124	else
125		th = stackh;
126
127	for(i = 0, c = clients; c; c = c->next) {
128		if(isvisible(c)) {
129			if(c->isfloat) {
130				resize(c, True, TopLeft);
131				continue;
132			}
133			c->ismax = False;
134			if(n == 1) { /* only 1 window */
135				c->x = sx;
136				c->y = sy + bh;
137				c->w = sw - 2 * BORDERPX;
138				c->h = sh - 2 * BORDERPX - bh;
139			}
140			else if(i == 0) { /* master window */
141				switch(stackpos) {
142				case StackLeft:
143					c->x = sx + stackw;
144					c->y = sy + bh;
145					c->w = master - 2 * BORDERPX;
146					c->h = sh - bh - 2 * BORDERPX;
147					break;
148				case StackBottom:
149					c->x = sx;
150					c->y = sy + bh;
151					c->w = sw - 2 * BORDERPX;
152					c->h = master - 2 * BORDERPX;
153					break;
154				case StackRight:
155					c->x = sx;
156					c->y = sy + bh;
157					c->w = master - 2 * BORDERPX;
158					c->h = sh - bh - 2 * BORDERPX;
159					break;
160				}
161			}
162			else if(th > bh) {
163				/* tile window */
164				c->w = tw - 2 * BORDERPX;
165				c->h = th - 2 * BORDERPX;
166				switch(stackpos) {
167				case StackLeft:
168					c->x = sx;
169					c->y = sy + (i - 1) * th + bh;
170					if(i + 1 == n)
171						c->h = sh - c->y - 2 * BORDERPX;
172					break;
173				case StackBottom:
174					c->x = sx;
175					c->y = sy + master + (i - 1) * th + bh;
176					if(i + 1 == n)
177						c->h = sh - c->y - 2 * BORDERPX;
178					break;
179				case StackRight:
180					c->x = sx + master;
181					c->y = sy + (i - 1) * th + bh;
182					if(i + 1 == n)
183						c->h = sh - c->y - 2 * BORDERPX;
184					break;
185				}
186			}
187			else { /* fallback if th < bh */
188				c->w = stackw - 2 * BORDERPX;
189				c->h = stackh - 2 * BORDERPX;
190				switch(stackpos) {
191				case StackLeft:
192					c->x = sx;
193					c->y = sy + bh;
194					break;
195				case StackBottom:
196					c->x = sx;
197					c->y = sy + master + bh;
198					break;
199				case StackRight:
200					c->x = sx + master;
201					c->y = sy + bh;
202					break;
203				}
204			}
205			resize(c, False, TopLeft);
206			i++;
207		}
208		else
209			ban(c);
210	}
211	if(!sel || !isvisible(sel)) {
212		for(c = stack; c && !isvisible(c); c = c->snext);
213		focus(c);
214	}
215	restack();
216}
217
218void
219focusnext(Arg *arg) {
220	Client *c;
221   
222	if(!sel)
223		return;
224
225	if(!(c = getnext(sel->next)))
226		c = getnext(clients);
227	if(c) {
228		focus(c);
229		restack();
230	}
231}
232
233void
234focusprev(Arg *arg) {
235	Client *c;
236
237	if(!sel)
238		return;
239
240	if(!(c = getprev(sel->prev))) {
241		for(c = clients; c && c->next; c = c->next);
242		c = getprev(c);
243	}
244	if(c) {
245		focus(c);
246		restack();
247	}
248}
249
250Bool
251isvisible(Client *c) {
252	unsigned int i;
253
254	for(i = 0; i < ntags; i++)
255		if(c->tags[i] && seltag[i])
256			return True;
257	return False;
258}
259
260void
261resizecol(Arg *arg) {
262	unsigned int n;
263	Client *c;
264
265	for(n = 0, c = clients; c; c = c->next)
266		if(isvisible(c) && !c->isfloat)
267			n++;
268	if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
269		return;
270
271	if(sel == getnext(clients)) {
272		if(master + arg->i > sw - MINW || master + arg->i < MINW)
273			return;
274		master += arg->i;
275	}
276	else {
277		if(master - arg->i > sw - MINW || master - arg->i < MINW)
278			return;
279		master -= arg->i;
280	}
281	arrange(NULL);
282}
283
284void
285restack(void) {
286	Client *c;
287	XEvent ev;
288
289	if(!sel) {
290		drawstatus();
291		return;
292	}
293	if(sel->isfloat || arrange == dofloat) {
294		XRaiseWindow(dpy, sel->win);
295		XRaiseWindow(dpy, sel->twin);
296	}
297	if(arrange != dofloat) {
298		if(!sel->isfloat) {
299			XLowerWindow(dpy, sel->twin);
300			XLowerWindow(dpy, sel->win);
301		}
302		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
303			if(c == sel)
304				continue;
305			XLowerWindow(dpy, c->twin);
306			XLowerWindow(dpy, c->win);
307		}
308	}
309	drawall();
310	XSync(dpy, False);
311	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
312}
313
314void
315togglemode(Arg *arg) {
316	arrange = (arrange == dofloat) ? dotile : dofloat;
317	if(sel)
318		arrange(NULL);
319	else
320		drawstatus();
321}
322
323void
324toggleview(Arg *arg) {
325	unsigned int i;
326
327	seltag[arg->i] = !seltag[arg->i];
328	for(i = 0; i < ntags && !seltag[i]; i++);
329	if(i == ntags)
330		seltag[arg->i] = True; /* cannot toggle last view */
331	reorder();
332	arrange(NULL);
333}
334
335void
336togglestackpos(Arg *arg) {
337	if(arrange == dofloat)
338		return;
339	if(stackpos == StackBottom)
340		stackpos = STACKPOS;
341	else
342		stackpos = StackBottom;
343	master = ((stackpos == StackBottom ? sh - bh : sw) * MASTER) / 100;
344	arrange(NULL);
345}
346
347void
348view(Arg *arg) {
349	unsigned int i;
350
351	for(i = 0; i < ntags; i++)
352		seltag[i] = False;
353	seltag[arg->i] = True;
354	reorder();
355	arrange(NULL);
356}
357
358void
359viewall(Arg *arg) {
360	unsigned int i;
361
362	for(i = 0; i < ntags; i++)
363		seltag[i] = True;
364	reorder();
365	arrange(NULL);
366}
367
368
369
370void
371zoom(Arg *arg) {
372	unsigned int n;
373	Client *c;
374
375	if(!sel)
376		return;
377
378	if(sel->isfloat || (arrange == dofloat)) {
379		togglemax(sel);
380		return;
381	}
382
383	for(n = 0, c = clients; c; c = c->next)
384		if(isvisible(c) && !c->isfloat)
385			n++;
386	if(n < 2 || (arrange == dofloat))
387		return;
388
389	if((c = sel) == nexttiled(clients))
390		if(!(c = nexttiled(c->next)))
391			return;
392	detach(c);
393	if(clients)
394		clients->prev = c;
395	c->next = clients;
396	clients = c;
397	focus(c);
398	arrange(NULL);
399}