all repos — dwm @ 9eb226ff78a0d8fc733c31d98170d33824231370

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() {
 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 void
 22reorder() {
 23	Client *c, *newclients, *tail;
 24
 25	newclients = tail = NULL;
 26	while((c = minclient())) {
 27		detach(c);
 28		if(tail) {
 29			c->prev = tail;
 30			tail->next = c;
 31			tail = c;
 32		}
 33		else
 34			tail = newclients = c;
 35	}
 36	clients = newclients;
 37}
 38
 39static Client *
 40nexttiled(Client *c) {
 41	for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
 42	return c;
 43}
 44
 45/* extern */
 46
 47void (*arrange)(Arg *) = DEFMODE;
 48
 49void
 50detach(Client *c) {
 51	if(c->prev)
 52		c->prev->next = c->next;
 53	if(c->next)
 54		c->next->prev = c->prev;
 55	if(c == clients)
 56		clients = c->next;
 57	c->next = c->prev = NULL;
 58}
 59
 60void
 61dofloat(Arg *arg) {
 62	Client *c;
 63
 64	for(c = clients; c; c = c->next) {
 65		if(isvisible(c)) {
 66			resize(c, True, TopLeft);
 67		}
 68		else
 69			ban(c);
 70	}
 71	if(!sel || !isvisible(sel)) {
 72		for(c = stack; c && !isvisible(c); c = c->snext);
 73		focus(c);
 74	}
 75	restack();
 76}
 77
 78void
 79dotile(Arg *arg) {
 80	int h, i, n, w;
 81	Client *c;
 82
 83	w = sw - mw;
 84	for(n = 0, c = clients; c; c = c->next)
 85		if(isvisible(c) && !c->isfloat)
 86			n++;
 87
 88	if(n > 1)
 89		h = (sh - bh) / (n - 1);
 90	else
 91		h = sh - bh;
 92
 93	for(i = 0, c = clients; c; c = c->next) {
 94		if(isvisible(c)) {
 95			if(c->isfloat) {
 96				resize(c, True, TopLeft);
 97				continue;
 98			}
 99			if(n == 1) {
100				c->x = sx;
101				c->y = sy + bh;
102				c->w = sw - 2;
103				c->h = sh - 2 - bh;
104			}
105			else if(i == 0) {
106				c->x = sx;
107				c->y = sy + bh;
108				c->w = mw - 2;
109				c->h = sh - 2 - bh;
110			}
111			else if(h > bh) {
112				c->x = sx + mw;
113				c->y = sy + (i - 1) * h + bh;
114				c->w = w - 2;
115				if(i + 1 == n)
116					c->h = sh - c->y - 2;
117				else
118					c->h = h - 2;
119			}
120			else { /* fallback if h < bh */
121				c->x = sx + mw;
122				c->y = sy + bh;
123				c->w = w - 2;
124				c->h = sh - 2 - bh;
125			}
126			resize(c, False, TopLeft);
127			i++;
128		}
129		else
130			ban(c);
131	}
132	if(!sel || !isvisible(sel)) {
133		for(c = stack; c && !isvisible(c); c = c->snext);
134		focus(c);
135	}
136	restack();
137}
138
139void
140focusnext(Arg *arg) {
141	Client *c;
142   
143	if(!sel)
144		return;
145
146	if(!(c = getnext(sel->next)))
147		c = getnext(clients);
148	if(c) {
149		focus(c);
150		restack();
151	}
152}
153
154void
155focusprev(Arg *arg) {
156	Client *c;
157
158	if(!sel)
159		return;
160
161	if(!(c = getprev(sel->prev))) {
162		for(c = clients; c && c->next; c = c->next);
163		c = getprev(c);
164	}
165	if(c) {
166		focus(c);
167		restack();
168	}
169}
170
171Bool
172isvisible(Client *c) {
173	unsigned int i;
174
175	for(i = 0; i < ntags; i++)
176		if(c->tags[i] && seltag[i])
177			return True;
178	return False;
179}
180
181void
182resizecol(Arg *arg) {
183	unsigned int n;
184	Client *c;
185
186	for(n = 0, c = clients; c; c = c->next)
187		if(isvisible(c) && !c->isfloat)
188			n++;
189	if(!sel || sel->isfloat || n < 2 || (arrange != dotile))
190		return;
191
192	if(sel == getnext(clients)) {
193		if(mw + arg->i > sw - 100 || mw + arg->i < 100)
194			return;
195		mw += arg->i;
196	}
197	else {
198		if(mw - arg->i > sw - 100 || mw - arg->i < 100)
199			return;
200		mw -= arg->i;
201	}
202	arrange(NULL);
203}
204
205void
206restack() {
207	Client *c;
208	XEvent ev;
209	
210	if(!sel) {
211		drawstatus();
212		return;
213	}
214	if(sel->isfloat || arrange == dofloat) {
215		XRaiseWindow(dpy, sel->win);
216		XRaiseWindow(dpy, sel->twin);
217	}
218	if(arrange != dofloat)
219		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
220			XLowerWindow(dpy, c->twin);
221			XLowerWindow(dpy, c->win);
222		}
223	drawall();
224	XSync(dpy, False);
225	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
226}
227
228void
229togglemode(Arg *arg) {
230	arrange = (arrange == dofloat) ? dotile : dofloat;
231	if(sel)
232		arrange(NULL);
233	else
234		drawstatus();
235}
236
237void
238toggleview(Arg *arg) {
239	unsigned int i;
240
241	seltag[arg->i] = !seltag[arg->i];
242	for(i = 0; i < ntags && !seltag[i]; i++);
243	if(i == ntags)
244		seltag[arg->i] = True; /* cannot toggle last view */
245	reorder();
246	arrange(NULL);
247}
248
249void
250view(Arg *arg) {
251	unsigned int i;
252
253	for(i = 0; i < ntags; i++)
254		seltag[i] = False;
255	seltag[arg->i] = True;
256	reorder();
257	arrange(NULL);
258}
259
260void
261viewall(Arg *arg) {
262	unsigned int i;
263
264	for(i = 0; i < ntags; i++)
265		seltag[i] = True;
266	reorder();
267	arrange(NULL);
268}
269
270void
271zoom(Arg *arg) {
272	int tmp;
273	unsigned int n;
274	Client *c;
275	XEvent ev;
276
277	if(!sel)
278		return;
279
280	if(sel->isfloat || (arrange == dofloat)) {
281		tmp = sel->x; sel->x = sel->rx; sel->rx = tmp;
282		tmp = sel->y; sel->y = sel->ry; sel->ry = tmp;
283		tmp = sel->w; sel->w = sel->rw; sel->rw = tmp;
284		tmp = sel->h; sel->h = sel->rh; sel->rh = tmp;
285		resize(sel, True, TopLeft);
286		while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
287		return;
288	}
289
290	for(n = 0, c = clients; c; c = c->next)
291		if(isvisible(c) && !c->isfloat)
292			n++;
293	if(n < 2 || (arrange != dotile))
294		return;
295
296	if((c = sel) == nexttiled(clients))
297		if(!(c = nexttiled(c->next)))
298			return;
299	detach(c);
300	if(clients)
301		clients->prev = c;
302	c->next = clients;
303	clients = c;
304	focus(c);
305	arrange(NULL);
306}