all repos — dwm @ 5a1a2edf0e584e660e16d2e01094851e0f9161e2

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			unban(c);
 92			resize(c, c->x, c->y, c->w, c->h, True);
 93		}
 94		else
 95			ban(c);
 96	focus(NULL);
 97	restack();
 98}
 99
100void
101focusclient(const char *arg) {
102	Client *c;
103   
104	if(!sel || !arg)
105		return;
106	if(atoi(arg) < 0) {
107		for(c = sel->prev; c && !isvisible(c); c = c->prev);
108		if(!c) {
109			for(c = clients; c && c->next; c = c->next);
110			for(; c && !isvisible(c); c = c->prev);
111		}
112	}
113	else {
114		for(c = sel->next; c && !isvisible(c); c = c->next);
115		if(!c)
116			for(c = clients; c && !isvisible(c); c = c->next);
117	}
118	if(c) {
119		focus(c);
120		restack();
121	}
122}
123
124void
125incmasterw(const char *arg) {
126	int i;
127	if(lt->arrange != tile)
128		return;
129	if(!arg)
130		masterw = MASTERWIDTH;
131	else {
132		i = atoi(arg);
133		if(waw * (masterw + i) / 1000 >= waw - 2 * BORDERPX 
134		|| waw * (masterw + i) / 1000 <= 2 * BORDERPX)
135			return;
136		masterw += i;
137	}
138	lt->arrange();
139}
140
141void
142incnmaster(const char *arg) {
143	int i;
144
145	if(!arg)
146		nmaster = NMASTER;
147	else {
148		i = atoi(arg);
149		if((lt->arrange != tile) || (nmaster + i < 1)
150		|| (wah / (nmaster + i) <= 2 * BORDERPX))
151			return;
152		nmaster += i;
153	}
154	if(sel)
155		lt->arrange();
156	else
157		drawstatus();
158}
159
160void
161initlayouts(void) {
162	unsigned int i, w;
163
164	lt = &layout[0];
165	nlayouts = sizeof layout / sizeof layout[0];
166	for(blw = i = 0; i < nlayouts; i++) {
167		w = textw(layout[i].symbol);
168		if(w > blw)
169			blw = w;
170	}
171}
172
173Client *
174nexttiled(Client *c) {
175	for(; c && (c->isfloating || !isvisible(c)); c = c->next);
176	return c;
177}
178
179void
180restack(void) {
181	Client *c;
182	XEvent ev;
183
184	drawstatus();
185	if(!sel)
186		return;
187	if(sel->isfloating || lt->arrange == floating)
188		XRaiseWindow(dpy, sel->win);
189	if(lt->arrange != floating) {
190		if(!sel->isfloating)
191			XLowerWindow(dpy, sel->win);
192		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
193			if(c == sel)
194				continue;
195			XLowerWindow(dpy, c->win);
196		}
197	}
198	XSync(dpy, False);
199	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
200}
201
202void
203setlayout(const char *arg) {
204	int i;
205
206	if(!arg) {
207		lt++;
208		if(lt == layout + nlayouts)
209			lt = layout;
210	}
211	else {
212		i = atoi(arg);
213		if(i < 0 || i >= nlayouts)
214			return;
215		lt = &layout[i];
216	}
217	if(sel)
218		lt->arrange();
219	else
220		drawstatus();
221}
222
223void
224togglebar(const char *arg) {
225	if(bpos == BarOff)
226		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
227	else
228		bpos = BarOff;
229	updatebarpos();
230	lt->arrange();
231}
232
233void
234togglemax(const char *arg) {
235	XEvent ev;
236
237	if(!sel || (lt->arrange != floating && !sel->isfloating) || sel->isfixed)
238		return;
239	if((sel->ismax = !sel->ismax)) {
240		sel->rx = sel->x;
241		sel->ry = sel->y;
242		sel->rw = sel->w;
243		sel->rh = sel->h;
244		resize(sel, wax, way, waw - 2 * sel->border, wah - 2 * sel->border, True);
245	}
246	else
247		resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
248	drawstatus();
249	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
250}
251
252void
253zoom(const char *arg) {
254	Client *c;
255
256	if(!sel || lt->arrange == floating || sel->isfloating)
257		return;
258	if((c = sel) == nexttiled(clients))
259		if(!(c = nexttiled(c->next)))
260			return;
261	detach(c);
262	attach(c);
263	focus(c);
264	lt->arrange();
265}