all repos — dwm @ 141beb27041371672d54da7f541a3855fab0ac5b

fork of suckless dynamic window manager

layout.c (view raw)

  1/* See LICENSE file for copyright and license details. */
  2#include "dwm.h"
  3#include <stdlib.h>
  4
  5unsigned int blw = 0;
  6Layout *lt = NULL;
  7
  8/* static */
  9
 10static unsigned int nlayouts = 0;
 11static unsigned int masterw = MASTERWIDTH;
 12static unsigned int nmaster = NMASTER;
 13
 14static void
 15ban(Client *c) {
 16	if (c->isbanned)
 17		return;
 18	XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
 19	c->isbanned = True;
 20}
 21
 22static void
 23unban(Client *c) {
 24	if (!c->isbanned)
 25		return;
 26	XMoveWindow(dpy, c->win, c->x, c->y);
 27	c->isbanned = False;
 28}
 29
 30static void
 31tile(void) {
 32	unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
 33	Client *c;
 34
 35	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
 36		n++;
 37	/* window geoms */
 38	mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
 39	mw = (n > nmaster) ? (waw * masterw) / 1000 : waw;
 40	th = (n > nmaster) ? wah / (n - nmaster) : 0;
 41	tw = waw - mw;
 42
 43	for(i = 0, c = clients; c; c = c->next)
 44		if(isvisible(c)) {
 45			unban(c);
 46			if(c->isfloating)
 47				continue;
 48			c->ismax = False;
 49			nx = wax;
 50			ny = way;
 51			if(i < nmaster) {
 52				ny += i * mh;
 53				nw = mw - 2 * c->border;
 54				nh = mh;
 55				if(i + 1 == (n < nmaster ? n : nmaster)) /* remainder */
 56					nh = wah - mh * i;
 57				nh -= 2 * c->border;
 58			}
 59			else {  /* tile window */
 60				nx += mw;
 61				nw = tw - 2 * c->border;
 62				if(th > 2 * c->border) {
 63					ny += (i - nmaster) * th;
 64					nh = th;
 65					if(i + 1 == n) /* remainder */
 66						nh = wah - th * (i - nmaster);
 67					nh -= 2 * c->border;
 68				}
 69				else /* fallback if th <= 2 * c->border */
 70					nh = wah - 2 * c->border;
 71			}
 72			resize(c, nx, ny, nw, nh, False);
 73			i++;
 74		}
 75		else
 76			ban(c);
 77	focus(NULL);
 78	restack();
 79}
 80
 81LAYOUTS
 82
 83/* extern */
 84
 85void
 86floating(void) {
 87	Client *c;
 88
 89	for(c = clients; c; c = c->next)
 90		if(isvisible(c)) {
 91			if(c->isbanned)
 92				XMoveWindow(dpy, c->win, c->x, c->y);
 93			c->isbanned = False;
 94			resize(c, c->x, c->y, c->w, c->h, True);
 95		}
 96		else
 97			ban(c);
 98	focus(NULL);
 99	restack();
100}
101
102void
103focusclient(const char *arg) {
104	Client *c;
105   
106	if(!sel || !arg)
107		return;
108	if(atoi(arg) < 0) {
109		for(c = sel->prev; c && !isvisible(c); c = c->prev);
110		if(!c) {
111			for(c = clients; c && c->next; c = c->next);
112			for(; c && !isvisible(c); c = c->prev);
113		}
114	}
115	else {
116		for(c = sel->next; c && !isvisible(c); c = c->next);
117		if(!c)
118			for(c = clients; c && !isvisible(c); c = c->next);
119	}
120	if(c) {
121		focus(c);
122		restack();
123	}
124}
125
126void
127incmasterw(const char *arg) {
128	int i;
129	if(lt->arrange != tile)
130		return;
131	if(!arg)
132		masterw = MASTERWIDTH;
133	else {
134		i = atoi(arg);
135		if(waw * (masterw + i) / 1000 >= waw - 2 * BORDERPX 
136		|| waw * (masterw + i) / 1000 <= 2 * BORDERPX)
137			return;
138		masterw += i;
139	}
140	lt->arrange();
141}
142
143void
144incnmaster(const char *arg) {
145	int i;
146
147	if(!arg)
148		nmaster = NMASTER;
149	else {
150		i = atoi(arg);
151		if((lt->arrange != tile) || (nmaster + i < 1)
152		|| (wah / (nmaster + i) <= 2 * BORDERPX))
153			return;
154		nmaster += i;
155	}
156	if(sel)
157		lt->arrange();
158	else
159		drawstatus();
160}
161
162void
163initlayouts(void) {
164	unsigned int i, w;
165
166	lt = &layout[0];
167	nlayouts = sizeof layout / sizeof layout[0];
168	for(blw = i = 0; i < nlayouts; i++) {
169		w = textw(layout[i].symbol);
170		if(w > blw)
171			blw = w;
172	}
173}
174
175Client *
176nexttiled(Client *c) {
177	for(; c && (c->isfloating || !isvisible(c)); c = c->next);
178	return c;
179}
180
181void
182restack(void) {
183	Client *c;
184	XEvent ev;
185
186	drawstatus();
187	if(!sel)
188		return;
189	if(sel->isfloating || lt->arrange == floating)
190		XRaiseWindow(dpy, sel->win);
191	if(lt->arrange != floating) {
192		if(!sel->isfloating)
193			XLowerWindow(dpy, sel->win);
194		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
195			if(c == sel)
196				continue;
197			XLowerWindow(dpy, c->win);
198		}
199	}
200	XSync(dpy, False);
201	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
202}
203
204void
205setlayout(const char *arg) {
206	int i;
207
208	if(!arg) {
209		lt++;
210		if(lt == layout + nlayouts)
211			lt = layout;
212	}
213	else {
214		i = atoi(arg);
215		if(i < 0 || i >= nlayouts)
216			return;
217		lt = &layout[i];
218	}
219	if(sel)
220		lt->arrange();
221	else
222		drawstatus();
223}
224
225void
226togglebar(const char *arg) {
227	if(bpos == BarOff)
228		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
229	else
230		bpos = BarOff;
231	updatebarpos();
232	lt->arrange();
233}
234
235void
236togglemax(const char *arg) {
237	XEvent ev;
238
239	if(!sel || (lt->arrange != floating && !sel->isfloating) || sel->isfixed)
240		return;
241	if((sel->ismax = !sel->ismax)) {
242		sel->rx = sel->x;
243		sel->ry = sel->y;
244		sel->rw = sel->w;
245		sel->rh = sel->h;
246		resize(sel, wax, way, waw - 2 * sel->border, wah - 2 * sel->border, True);
247	}
248	else
249		resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
250	drawstatus();
251	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
252}
253
254void
255zoom(const char *arg) {
256	Client *c;
257
258	if(!sel || lt->arrange == floating || sel->isfloating)
259		return;
260	if((c = sel) == nexttiled(clients))
261		if(!(c = nexttiled(c->next)))
262			return;
263	detach(c);
264	attach(c);
265	focus(c);
266	lt->arrange();
267}