all repos — dwm @ e1315fd40cf7f3df911e1b4f6876c47ce1feb61c

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#include <stdio.h>
  7
  8/* static */
  9
 10static Client *
 11minclient()
 12{
 13	Client *c, *min;
 14
 15	for(min = c = clients; c; c = c->next)
 16		if(c->weight < min->weight)
 17			min = c;
 18	return min;
 19}
 20
 21
 22static void
 23reorder()
 24{
 25	Client *c, *newclients, *tail;
 26
 27	newclients = tail = NULL;
 28	while((c = minclient())) {
 29		detach(c);
 30		if(tail) {
 31			c->prev = tail;
 32			tail->next = c;
 33			tail = c;
 34		}
 35		else
 36			tail = newclients = c;
 37	}
 38	clients = newclients;
 39}
 40
 41/* extern */
 42
 43void (*arrange)(Arg *) = DEFMODE;
 44
 45void
 46detach(Client *c)
 47{
 48	if(c->prev)
 49		c->prev->next = c->next;
 50	if(c->next)
 51		c->next->prev = c->prev;
 52	if(c == clients)
 53		clients = c->next;
 54	c->next = c->prev = NULL;
 55}
 56
 57void
 58dofloat(Arg *arg)
 59{
 60	Client *c;
 61
 62	maximized = False;
 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		focus(getnext(clients));
 73	restack();
 74}
 75
 76void
 77dotile(Arg *arg)
 78{
 79	int h, i, n, w;
 80	Client *c;
 81
 82	maximized = False;
 83
 84	w = sw - mw;
 85	for(n = 0, c = clients; c; c = c->next)
 86		if(isvisible(c) && !c->isfloat)
 87			n++;
 88
 89	if(n > 1)
 90		h = (sh - bh) / (n - 1);
 91	else
 92		h = sh - bh;
 93
 94	for(i = 0, c = clients; c; c = c->next) {
 95		if(isvisible(c)) {
 96			if(c->isfloat) {
 97				resize(c, True, TopLeft);
 98				continue;
 99			}
100			if(n == 1) {
101				c->x = sx;
102				c->y = sy + bh;
103				c->w = sw - 2;
104				c->h = sh - 2 - bh;
105			}
106			else if(i == 0) {
107				c->x = sx;
108				c->y = sy + bh;
109				c->w = mw - 2;
110				c->h = sh - 2 - bh;
111			}
112			else if(h > bh) {
113				c->x = sx + mw;
114				c->y = sy + (i - 1) * h + bh;
115				c->w = w - 2;
116				if(i + 1 == n)
117					c->h = sh - c->y - 2;
118				else
119					c->h = h - 2;
120			}
121			else { /* fallback if h < bh */
122				c->x = sx + mw;
123				c->y = sy + bh;
124				c->w = w - 2;
125				c->h = sh - 2 - bh;
126			}
127			resize(c, False, TopLeft);
128			i++;
129		}
130		else
131			ban(c);
132	}
133	if(!sel || !isvisible(sel))
134		focus(getnext(clients));
135	restack();
136}
137
138void
139focusnext(Arg *arg)
140{
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{
157	Client *c;
158
159	if(!sel)
160		return;
161
162	if(!(c = getprev(sel->prev))) {
163		for(c = clients; c && c->next; c = c->next);
164		c = getprev(c);
165	}
166	if(c) {
167		focus(c);
168		restack();
169	}
170}
171
172Bool
173isvisible(Client *c)
174{
175	unsigned int i;
176
177	for(i = 0; i < ntags; i++)
178		if(c->tags[i] && seltag[i])
179			return True;
180	return False;
181}
182
183void
184resizecol(Arg *arg)
185{
186	unsigned int n;
187	Client *c;
188
189	for(n = 0, c = clients; c; c = c->next)
190		if(isvisible(c) && !c->isfloat)
191			n++;
192	if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized)
193		return;
194
195	if(sel == getnext(clients)) {
196		if(mw + arg->i > sw - 100 || mw + arg->i < 100)
197			return;
198		mw += arg->i;
199	}
200	else {
201		if(mw - arg->i > sw - 100 || mw - arg->i < 100)
202			return;
203		mw -= arg->i;
204	}
205	arrange(NULL);
206}
207
208void
209restack()
210{
211	static unsigned int nwins = 0;
212	static Window *wins = NULL;
213	unsigned int f, fi, m, mi, n;
214	Client *c;
215	XEvent ev;
216
217	for(f = 0, m = 0, c = clients; c; c = c->next)
218		if(isvisible(c)) {
219			if(c->isfloat || arrange == dofloat)
220				f++;
221			else
222				m++;
223		}
224	if(!(n = 2 * (f + m))) {
225		drawstatus();
226		return;
227	}
228	if(nwins < n) {
229		nwins = n;
230		wins = erealloc(wins, nwins * sizeof(Window));
231	}
232
233	fi = 0;
234	mi = 2 * f;
235	if(sel) {
236		if(sel->isfloat || arrange == dofloat) {
237			wins[fi++] = sel->twin;
238			wins[fi++] = sel->win;
239		}
240		else {
241			wins[mi++] = sel->twin;
242			wins[mi++] = sel->win;
243		}
244	}
245	for(c = clients; c; c = c->next)
246		if(isvisible(c) && c != sel) {
247			if(c->isfloat || arrange == dofloat) {
248				wins[fi++] = c->twin;
249				wins[fi++] = c->win;
250			}
251			else {
252				wins[mi++] = c->twin;
253				wins[mi++] = c->win;
254			}
255		}
256	XRestackWindows(dpy, wins, n);
257	drawall();
258	XSync(dpy, False);
259	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
260}
261
262void
263togglemode(Arg *arg)
264{
265	arrange = (arrange == dofloat) ? dotile : dofloat;
266	if(sel)
267		arrange(NULL);
268	else
269		drawstatus();
270}
271
272void
273toggleview(Arg *arg)
274{
275	unsigned int i;
276
277	seltag[arg->i] = !seltag[arg->i];
278	for(i = 0; i < ntags && !seltag[i]; i++);
279	if(i == ntags)
280		seltag[arg->i] = True; /* cannot toggle last view */
281	reorder();
282	arrange(NULL);
283}
284
285void
286view(Arg *arg)
287{
288	unsigned int i;
289
290	for(i = 0; i < ntags; i++)
291		seltag[i] = False;
292	seltag[arg->i] = True;
293	reorder();
294	arrange(NULL);
295}
296
297void
298viewall(Arg *arg)
299{
300	unsigned int i;
301
302	for(i = 0; i < ntags; i++)
303		seltag[i] = True;
304	reorder();
305	arrange(NULL);
306}
307
308void
309zoom(Arg *arg)
310{
311	unsigned int n;
312	Client *c;
313
314	for(n = 0, c = clients; c; c = c->next)
315		if(isvisible(c) && !c->isfloat)
316			n++;
317	if(!sel || sel->isfloat || n < 2 || (arrange != dotile) || maximized)
318		return;
319
320	/* this is somewhat tricky, it asserts to only zoom tiled clients */
321	for(c = clients; c && c->isfloat; c = getnext(c->next));
322	if(c) {
323		if(c == sel)
324			for(c = getnext(c->next); c && c->isfloat; c = getnext(c->next));
325		else
326			c = sel;
327	}
328	if(!c)
329		return;
330	detach(c);
331	c->next = clients;
332	clients->prev = c;
333	clients = c;
334	focus(c);
335	arrange(NULL);
336}