all repos — dwm @ 346bdea946887d83f857a8944a0189bca51a3e47

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