all repos — dwm @ 1.3

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
184restack()
185{
186	static unsigned int nwins = 0;
187	static Window *wins = NULL;
188	unsigned int f, fi, m, mi, n;
189	Client *c;
190	XEvent ev;
191
192	for(f = 0, m = 0, c = clients; c; c = c->next)
193		if(isvisible(c)) {
194			if(c->isfloat || arrange == dofloat)
195				f++;
196			else
197				m++;
198		}
199	if(!(n = 2 * (f + m))) {
200		drawstatus();
201		return;
202	}
203	if(nwins < n) {
204		nwins = n;
205		wins = erealloc(wins, nwins * sizeof(Window));
206	}
207
208	fi = 0;
209	mi = 2 * f;
210	if(sel->isfloat || arrange == dofloat) {
211		wins[fi++] = sel->twin;
212		wins[fi++] = sel->win;
213	}
214	else {
215		wins[mi++] = sel->twin;
216		wins[mi++] = sel->win;
217	}
218	for(c = clients; c; c = c->next)
219		if(isvisible(c) && c != sel) {
220			if(c->isfloat || arrange == dofloat) {
221				wins[fi++] = c->twin;
222				wins[fi++] = c->win;
223			}
224			else {
225				wins[mi++] = c->twin;
226				wins[mi++] = c->win;
227			}
228		}
229	XRestackWindows(dpy, wins, n);
230	drawall();
231	XSync(dpy, False);
232	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
233}
234
235void
236togglemode(Arg *arg)
237{
238	arrange = (arrange == dofloat) ? dotile : dofloat;
239	if(sel)
240		arrange(NULL);
241	else
242		drawstatus();
243}
244
245void
246toggleview(Arg *arg)
247{
248	unsigned int i;
249
250	seltag[arg->i] = !seltag[arg->i];
251	for(i = 0; i < ntags && !seltag[i]; i++);
252	if(i == ntags)
253		seltag[arg->i] = True; /* cannot toggle last view */
254	reorder();
255	arrange(NULL);
256}
257
258void
259view(Arg *arg)
260{
261	unsigned int i;
262
263	for(i = 0; i < ntags; i++)
264		seltag[i] = False;
265	seltag[arg->i] = True;
266	reorder();
267	arrange(NULL);
268}
269
270void
271viewall(Arg *arg)
272{
273	unsigned int i;
274
275	for(i = 0; i < ntags; i++)
276		seltag[i] = True;
277	reorder();
278	arrange(NULL);
279}
280
281void
282zoom(Arg *arg)
283{
284	Client *c = sel;
285
286	if(!c || (arrange != dotile) || c->isfloat || maximized)
287		return;
288
289	if(c == getnext(clients))
290		if(!(c = getnext(c->next)))
291			return;
292	detach(c);
293	c->next = clients;
294	clients->prev = c;
295	clients = c;
296	focus(c);
297	arrange(NULL);
298}