all repos — dwm @ 9d739090750ffb3b3a64e86e2331215b8901c360

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