all repos — dwm @ 2b13e7466f4912e3778bf59e6aec3065443f08fe

fork of suckless dynamic window manager

view.c (view raw)

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