all repos — dwm @ ca65478c8968434c78aacf4a102ccbbe4a66ad9e

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