all repos — dwm @ 6fc8a6304163fb63551e54acc62e6e9b7e96c820

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