all repos — dwm @ 016c54196e682ae8658854febb746b0437a010dc

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 *
 10getslot(Client *c)
 11{
 12	unsigned int i, tic;
 13	Client *p;
 14
 15	for(tic = 0; tic < ntags && !c->tags[tic]; tic++);
 16	for(p = clients; p; p = p->next) {
 17		for(i = 0; i < ntags && !p->tags[i]; i++);
 18		if(tic < i)
 19			return p;
 20	}
 21	return p;
 22}
 23
 24static Client *
 25tail()
 26{
 27	Client *c;
 28	for(c = clients; c && c->next; c = c->next);
 29	return c;
 30}
 31
 32/* extern */
 33
 34void (*arrange)(Arg *) = DEFMODE;
 35
 36void
 37attach(Client *c)
 38{
 39	Client *p;
 40
 41	if(!clients) {
 42		clients = c;
 43		return;
 44	}
 45	if(!(p = getnext(clients)) && !(p = getslot(c))) {
 46		p = tail();
 47		c->prev = p;
 48		p->next = c;
 49		return;
 50	}
 51
 52	if(p == clients) {
 53		c->next = clients;
 54		clients->prev = c;
 55		clients = c;
 56	}
 57	else {
 58		p->prev->next = c;
 59		c->prev = p->prev;
 60		p->prev = c;
 61		c->next = p;
 62	}
 63}
 64
 65void
 66detach(Client *c)
 67{
 68	if(c->prev)
 69		c->prev->next = c->next;
 70	if(c->next)
 71		c->next->prev = c->prev;
 72	if(c == clients)
 73		clients = c->next;
 74	c->next = c->prev = NULL;
 75}
 76
 77void
 78dofloat(Arg *arg)
 79{
 80	Client *c;
 81
 82	for(c = clients; c; c = c->next) {
 83		c->ismax = False;
 84		if(isvisible(c)) {
 85			resize(c, True, TopLeft);
 86		}
 87		else
 88			ban(c);
 89	}
 90	if(!sel || !isvisible(sel))
 91		sel = getnext(clients);
 92	if(sel)
 93		focus(sel);
 94	else
 95		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
 96	restack();
 97}
 98
 99void
100dotile(Arg *arg)
101{
102	int h, i, n, w;
103	Client *c;
104
105	w = sw - mw;
106	for(n = 0, c = clients; c; c = c->next)
107		if(isvisible(c) && !c->isfloat)
108			n++;
109
110	if(n > 1)
111		h = (sh - bh) / (n - 1);
112	else
113		h = sh - bh;
114
115	for(i = 0, c = clients; c; c = c->next) {
116		c->ismax = False;
117		if(isvisible(c)) {
118			if(c->isfloat) {
119				resize(c, True, TopLeft);
120				continue;
121			}
122			if(n == 1) {
123				c->x = sx;
124				c->y = sy + bh;
125				c->w = sw - 2;
126				c->h = sh - 2 - bh;
127			}
128			else if(i == 0) {
129				c->x = sx;
130				c->y = sy + bh;
131				c->w = mw - 2;
132				c->h = sh - 2 - bh;
133			}
134			else if(h > bh) {
135				c->x = sx + mw;
136				c->y = sy + (i - 1) * h + bh;
137				c->w = w - 2;
138				if(i + 1 == n)
139					c->h = sh - c->y - 2;
140				else
141					c->h = h - 2;
142			}
143			else { /* fallback if h < bh */
144				c->x = sx + mw;
145				c->y = sy + bh;
146				c->w = w - 2;
147				c->h = sh - 2 - bh;
148			}
149			resize(c, False, TopLeft);
150			i++;
151		}
152		else
153			ban(c);
154	}
155	if(!sel || !isvisible(sel))
156		sel = getnext(clients);
157	if(sel)
158		focus(sel);
159	else
160		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
161	restack();
162}
163
164void
165focusnext(Arg *arg)
166{
167	Client *c;
168   
169	if(!sel)
170		return;
171
172	if(!(c = getnext(sel->next)))
173		c = getnext(clients);
174	if(c) {
175		focus(c);
176		restack();
177	}
178}
179
180void
181focusprev(Arg *arg)
182{
183	Client *c;
184
185	if(!sel)
186		return;
187
188	if(!(c = getprev(sel->prev))) {
189		for(c = clients; c && c->next; c = c->next);
190		c = getprev(c);
191	}
192	if(c) {
193		focus(c);
194		restack();
195	}
196}
197
198Bool
199isvisible(Client *c)
200{
201	unsigned int i;
202
203	for(i = 0; i < ntags; i++)
204		if(c->tags[i] && seltag[i])
205			return True;
206	return False;
207}
208
209void
210restack()
211{
212	static unsigned int nwins = 0;
213	static Window *wins = NULL;
214	unsigned int f, fi, m, mi, n;
215	Client *c;
216	XEvent ev;
217
218	for(f = 0, m = 0, c = clients; c; c = c->next)
219		if(isvisible(c)) {
220			if(c->isfloat || arrange == dofloat)
221				f++;
222			else
223				m++;
224		}
225	if(!(n = 2 * (f + m))) {
226		drawstatus();
227		return;
228	}
229	if(nwins < n) {
230		nwins = n;
231		wins = erealloc(wins, nwins * sizeof(Window));
232	}
233
234	fi = 0;
235	mi = 2 * f;
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	for(c = clients; c; c = c->next)
245		if(isvisible(c) && c != sel) {
246			if(c->isfloat || arrange == dofloat) {
247				wins[fi++] = c->twin;
248				wins[fi++] = c->win;
249			}
250			else {
251				wins[mi++] = c->twin;
252				wins[mi++] = c->win;
253			}
254		}
255	XRestackWindows(dpy, wins, n);
256	drawall();
257	XSync(dpy, False);
258	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
259}
260
261void
262togglemode(Arg *arg)
263{
264	arrange = (arrange == dofloat) ? dotile : dofloat;
265	if(sel)
266		arrange(NULL);
267	else
268		drawstatus();
269}
270
271void
272toggleview(Arg *arg)
273{
274	unsigned int i;
275
276	seltag[arg->i] = !seltag[arg->i];
277	for(i = 0; i < ntags && !seltag[i]; i++);
278	if(i == ntags)
279		seltag[arg->i] = True; /* cannot toggle last view */
280	arrange(NULL);
281}
282
283void
284view(Arg *arg)
285{
286	unsigned int i;
287
288	for(i = 0; i < ntags; i++)
289		seltag[i] = False;
290	seltag[arg->i] = True;
291	arrange(NULL);
292}
293
294void
295zoom(Arg *arg)
296{
297	Client *c = sel;
298
299	if(!c || (arrange != dotile) || c->isfloat || c->ismax)
300		return;
301
302	if(c == getnext(clients))
303		if(!(c = getnext(c->next)))
304			return;
305	detach(c);
306	attach(c);
307	focus(c);
308	arrange(NULL);
309}