all repos — dwm @ e461e60997f83d69561ad0ca4754c299145c00b8

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