all repos — dwm @ a118a57fe3fd13036f24ebe093a5c329608a0600

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;
 68
 69void
 70detach(Client *c) {
 71	if(c->prev)
 72		c->prev->next = c->next;
 73	if(c->next)
 74		c->next->prev = c->prev;
 75	if(c == clients)
 76		clients = c->next;
 77	c->next = c->prev = NULL;
 78}
 79
 80void
 81dofloat(Arg *arg) {
 82	Client *c;
 83
 84	for(c = clients; c; c = c->next) {
 85		if(isvisible(c)) {
 86			resize(c, True, TopLeft);
 87		}
 88		else
 89			ban(c);
 90	}
 91	if(!sel || !isvisible(sel)) {
 92		for(c = stack; c && !isvisible(c); c = c->snext);
 93		focus(c);
 94	}
 95	restack();
 96}
 97
 98/* This algorithm is based on a (M)aster area and a (S)tacking area.
 99 * It supports following arrangements:
100 *
101 * 	MMMS		MMMM
102 * 	MMMS		MMMM
103 * 	MMMS		SSSS
104 *
105 * The stacking area can be set to arrange clients vertically or horizontally.
106 * Through inverting the algorithm it can be used to achieve following setup in
107 * a dual head environment (due to running two dwm instances concurrently on
108 * the specific screen):
109 *
110 * 	SMM MMS		MMM MMM
111 * 	SMM MMS		MMM MMM
112 * 	SMM MMS		SSS SSS
113 *
114 * This uses the center of the two screens for master areas.
115 */
116void
117dotile(Arg *arg) {
118	int h, i, n, w;
119	Client *c;
120
121	w = sw - mw;
122	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
123		n++;
124
125	if(n > 1)
126		h = (sh - bh) / (n - 1);
127	else
128		h = sh - bh;
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			if(n == 1) {
138				c->x = sx;
139				c->y = sy + bh;
140				c->w = sw - 2 * BORDERPX;
141				c->h = sh - 2 * BORDERPX - bh;
142			}
143			else if(i == 0) {
144				c->x = sx;
145				c->y = sy + bh;
146				c->w = mw - 2 * BORDERPX;
147				c->h = sh - 2 * BORDERPX - bh;
148			}
149			else if(h > bh) {
150				c->x = sx + mw;
151				c->y = sy + (i - 1) * h + bh;
152				c->w = w - 2 * BORDERPX;
153				if(i + 1 == n)
154					c->h = sh - c->y - 2 * BORDERPX;
155				else
156					c->h = h - 2 * BORDERPX;
157			}
158			else { /* fallback if h < bh */
159				c->x = sx + mw;
160				c->y = sy + bh;
161				c->w = w - 2 * BORDERPX;
162				c->h = sh - 2 * BORDERPX - bh;
163			}
164			resize(c, False, TopLeft);
165			i++;
166		}
167		else
168			ban(c);
169	}
170	if(!sel || !isvisible(sel)) {
171		for(c = stack; c && !isvisible(c); c = c->snext);
172		focus(c);
173	}
174	restack();
175}
176
177void
178focusnext(Arg *arg) {
179	Client *c;
180   
181	if(!sel)
182		return;
183
184	if(!(c = getnext(sel->next)))
185		c = getnext(clients);
186	if(c) {
187		focus(c);
188		restack();
189	}
190}
191
192void
193focusprev(Arg *arg) {
194	Client *c;
195
196	if(!sel)
197		return;
198
199	if(!(c = getprev(sel->prev))) {
200		for(c = clients; c && c->next; c = c->next);
201		c = getprev(c);
202	}
203	if(c) {
204		focus(c);
205		restack();
206	}
207}
208
209Bool
210isvisible(Client *c) {
211	unsigned int i;
212
213	for(i = 0; i < ntags; i++)
214		if(c->tags[i] && seltag[i])
215			return True;
216	return False;
217}
218
219void
220resizecol(Arg *arg) {
221	unsigned int n;
222	Client *c;
223
224	for(n = 0, c = clients; c; c = c->next)
225		if(isvisible(c) && !c->isfloat)
226			n++;
227	if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
228		return;
229
230	if(sel == getnext(clients)) {
231		if(mw + arg->i > sw - 100 || mw + arg->i < 100)
232			return;
233		mw += arg->i;
234	}
235	else {
236		if(mw - arg->i > sw - 100 || mw - arg->i < 100)
237			return;
238		mw -= arg->i;
239	}
240	arrange(NULL);
241}
242
243void
244restack(void) {
245	Client *c;
246	XEvent ev;
247
248	if(!sel) {
249		drawstatus();
250		return;
251	}
252	if(sel->isfloat || arrange == dofloat) {
253		XRaiseWindow(dpy, sel->win);
254		XRaiseWindow(dpy, sel->twin);
255	}
256	if(arrange != dofloat)
257		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
258			XLowerWindow(dpy, c->twin);
259			XLowerWindow(dpy, c->win);
260		}
261	drawall();
262	XSync(dpy, False);
263	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
264}
265
266void
267togglemode(Arg *arg) {
268	arrange = (arrange == dofloat) ? dotile : dofloat;
269	if(sel)
270		arrange(NULL);
271	else
272		drawstatus();
273}
274
275void
276toggleview(Arg *arg) {
277	unsigned int i;
278
279	seltag[arg->i] = !seltag[arg->i];
280	for(i = 0; i < ntags && !seltag[i]; i++);
281	if(i == ntags)
282		seltag[arg->i] = True; /* cannot toggle last view */
283	reorder();
284	arrange(NULL);
285}
286
287void
288view(Arg *arg) {
289	unsigned int i;
290
291	for(i = 0; i < ntags; i++)
292		seltag[i] = False;
293	seltag[arg->i] = True;
294	reorder();
295	arrange(NULL);
296}
297
298void
299viewall(Arg *arg) {
300	unsigned int i;
301
302	for(i = 0; i < ntags; i++)
303		seltag[i] = True;
304	reorder();
305	arrange(NULL);
306}
307
308void
309zoom(Arg *arg) {
310	unsigned int n;
311	Client *c;
312
313	if(!sel)
314		return;
315
316	if(sel->isfloat || (arrange == dofloat)) {
317		togglemax(sel);
318		return;
319	}
320
321	for(n = 0, c = clients; c; c = c->next)
322		if(isvisible(c) && !c->isfloat)
323			n++;
324	if(n < 2 || (arrange == dofloat))
325		return;
326
327	if((c = sel) == nexttiled(clients))
328		if(!(c = nexttiled(c->next)))
329			return;
330	detach(c);
331	if(clients)
332		clients->prev = c;
333	c->next = clients;
334	clients = c;
335	focus(c);
336	arrange(NULL);
337}