all repos — dwm @ da909dd1e879f9966c77735db3fe322f0f303a1c

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