all repos — dwm @ 10885d349a8426f0a55f34e78a2592267e8e55be

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