all repos — dwm @ 4c368bcd24172166aab32948fc63feaa6a1bec93

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