all repos — dwm @ 157ea539a2d1926ee3a9d2fe713eba0b9428f685

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	for(c = clients; c; c = c->next) {
 63		c->ismax = False;
 64		if(isvisible(c)) {
 65			resize(c, True, TopLeft);
 66		}
 67		else
 68			ban(c);
 69	}
 70	if((sel = getnext(clients)))
 71		focus(sel);
 72	else
 73		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
 74	restack();
 75}
 76
 77void
 78dotile(Arg *arg)
 79{
 80	int h, i, n, w;
 81	Client *c;
 82
 83	w = sw - mw;
 84	for(n = 0, c = clients; c; c = c->next)
 85		if(isvisible(c) && !c->isfloat)
 86			n++;
 87
 88	if(n > 1)
 89		h = (sh - bh) / (n - 1);
 90	else
 91		h = sh - bh;
 92
 93	for(i = 0, c = clients; c; c = c->next) {
 94		c->ismax = False;
 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 = getnext(clients)))
134		focus(sel);
135	else
136		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
137	restack();
138}
139
140void
141focusnext(Arg *arg)
142{
143	Client *c;
144   
145	if(!sel)
146		return;
147
148	if(!(c = getnext(sel->next)))
149		c = getnext(clients);
150	if(c) {
151		focus(c);
152		restack();
153	}
154}
155
156void
157focusprev(Arg *arg)
158{
159	Client *c;
160
161	if(!sel)
162		return;
163
164	if(!(c = getprev(sel->prev))) {
165		for(c = clients; c && c->next; c = c->next);
166		c = getprev(c);
167	}
168	if(c) {
169		focus(c);
170		restack();
171	}
172}
173
174Bool
175isvisible(Client *c)
176{
177	unsigned int i;
178
179	for(i = 0; i < ntags; i++)
180		if(c->tags[i] && seltag[i])
181			return True;
182	return False;
183}
184
185void
186restack()
187{
188	static unsigned int nwins = 0;
189	static Window *wins = NULL;
190	unsigned int f, fi, m, mi, n;
191	Client *c;
192	XEvent ev;
193
194	for(f = 0, m = 0, c = clients; c; c = c->next)
195		if(isvisible(c)) {
196			if(c->isfloat || arrange == dofloat)
197				f++;
198			else
199				m++;
200		}
201	if(!(n = 2 * (f + m))) {
202		drawstatus();
203		return;
204	}
205	if(nwins < n) {
206		nwins = n;
207		wins = erealloc(wins, nwins * sizeof(Window));
208	}
209
210	fi = 0;
211	mi = 2 * f;
212	if(sel->isfloat || arrange == dofloat) {
213		wins[fi++] = sel->twin;
214		wins[fi++] = sel->win;
215	}
216	else {
217		wins[mi++] = sel->twin;
218		wins[mi++] = sel->win;
219	}
220	for(c = clients; c; c = c->next)
221		if(isvisible(c) && c != sel) {
222			if(c->isfloat || arrange == dofloat) {
223				wins[fi++] = c->twin;
224				wins[fi++] = c->win;
225			}
226			else {
227				wins[mi++] = c->twin;
228				wins[mi++] = c->win;
229			}
230		}
231	XRestackWindows(dpy, wins, n);
232	drawall();
233	XSync(dpy, False);
234	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
235}
236
237void
238togglemode(Arg *arg)
239{
240	arrange = (arrange == dofloat) ? dotile : dofloat;
241	if(sel)
242		arrange(NULL);
243	else
244		drawstatus();
245}
246
247void
248toggleview(Arg *arg)
249{
250	unsigned int i;
251
252	seltag[arg->i] = !seltag[arg->i];
253	for(i = 0; i < ntags && !seltag[i]; i++);
254	if(i == ntags)
255		seltag[arg->i] = True; /* cannot toggle last view */
256	reorder();
257	arrange(NULL);
258}
259
260void
261view(Arg *arg)
262{
263	unsigned int i;
264	Client *c;
265
266	for(i = 0; i < ntags; i++)
267		seltag[i] = False;
268	seltag[arg->i] = True;
269	reorder();
270	arrange(NULL);
271}
272
273void
274zoom(Arg *arg)
275{
276	Client *c = sel;
277
278	if(!c || (arrange != dotile) || c->isfloat || c->ismax)
279		return;
280
281	if(c == getnext(clients))
282		if(!(c = getnext(c->next)))
283			return;
284	detach(c);
285	c->next = clients;
286	clients->prev = c;
287	clients = c;
288	focus(c);
289	arrange(NULL);
290}