all repos — dwm @ a33150eb4b041b243d0493cd4b53bfbcace3299e

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