all repos — dwm @ b427a2c6cb9c221075e42d0d1007e980a949a7df

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