all repos — dwm @ df9fd28f9a32dcff356c349b9a64b4e8cfb82980

fork of suckless dynamic window manager

screen.c (view raw)

  1/* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
  2 * See LICENSE file for license details.
  3 */
  4#include "dwm.h"
  5#include <regex.h>
  6#include <stdio.h>
  7#include <stdlib.h>
  8#include <string.h>
  9#include <sys/types.h>
 10#include <X11/Xutil.h>
 11
 12void (*arrange)(void) = DEFMODE;
 13unsigned int master = MASTER;
 14unsigned int nmaster = NMASTER;
 15
 16/* static */
 17
 18typedef struct {
 19	const char *prop;
 20	const char *tags;
 21	Bool isfloat;
 22} Rule;
 23
 24typedef struct {
 25	regex_t *propregex;
 26	regex_t *tagregex;
 27} Regexps;
 28
 29TAGS
 30RULES
 31
 32static Regexps *regexps = NULL;
 33static unsigned int len = 0;
 34
 35/* extern */
 36
 37void
 38compileregexps(void) {
 39	unsigned int i;
 40	regex_t *reg;
 41
 42	if(regexps)
 43		return;
 44	len = sizeof rule / sizeof rule[0];
 45	regexps = emallocz(len * sizeof(Regexps));
 46	for(i = 0; i < len; i++) {
 47		if(rule[i].prop) {
 48			reg = emallocz(sizeof(regex_t));
 49			if(regcomp(reg, rule[i].prop, REG_EXTENDED))
 50				free(reg);
 51			else
 52				regexps[i].propregex = reg;
 53		}
 54		if(rule[i].tags) {
 55			reg = emallocz(sizeof(regex_t));
 56			if(regcomp(reg, rule[i].tags, REG_EXTENDED))
 57				free(reg);
 58			else
 59				regexps[i].tagregex = reg;
 60		}
 61	}
 62}
 63
 64void
 65dofloat(void) {
 66	Client *c;
 67
 68	for(c = clients; c; c = c->next) {
 69		if(isvisible(c)) {
 70			if(c->isbanned)
 71				XMoveWindow(dpy, c->win, c->x, c->y);
 72			c->isbanned = False;
 73			resize(c, c->x, c->y, c->w, c->h, True);
 74		}
 75		else {
 76			c->isbanned = True;
 77			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
 78		}
 79	}
 80	if(!sel || !isvisible(sel)) {
 81		for(c = stack; c && !isvisible(c); c = c->snext);
 82		focus(c);
 83	}
 84	restack();
 85}
 86void
 87dotile(void) {
 88	unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
 89	Client *c;
 90
 91	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
 92		n++;
 93	/* window geoms */
 94	mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
 95	mw = (n > nmaster) ? (waw * master) / 1000 : waw;
 96	th = (n > nmaster) ? wah / (n - nmaster) : 0;
 97	tw = waw - mw;
 98
 99	for(i = 0, c = clients; c; c = c->next)
100		if(isvisible(c)) {
101			if(c->isbanned)
102				XMoveWindow(dpy, c->win, c->x, c->y);
103			c->isbanned = False;
104			if(c->isfloat)
105				continue;
106			c->ismax = False;
107			nx = wax;
108			ny = way;
109			if(i < nmaster) {
110				ny += i * mh;
111				nw = mw - 2 * BORDERPX;
112				nh = mh - 2 * BORDERPX;
113			}
114			else {  /* tile window */
115				nx += mw;
116				nw = tw - 2 * BORDERPX;
117				if(th > 2 * BORDERPX) {
118					ny += (i - nmaster) * th;
119					nh = th - 2 * BORDERPX;
120				}
121				else /* fallback if th <= 2 * BORDERPX */
122					nh = wah - 2 * BORDERPX;
123			}
124			resize(c, nx, ny, nw, nh, False);
125			i++;
126		}
127		else {
128			c->isbanned = True;
129			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
130		}
131	if(!sel || !isvisible(sel)) {
132		for(c = stack; c && !isvisible(c); c = c->snext);
133		focus(c);
134	}
135	restack();
136}
137
138void
139incnmaster(Arg *arg) {
140	if((arrange == dofloat) || (nmaster + arg->i < 1)
141	|| (wah / (nmaster + arg->i) <= 2 * BORDERPX))
142		return;
143	nmaster += arg->i;
144	if(sel)
145		arrange();
146	else
147		drawstatus();
148}
149
150Bool
151isvisible(Client *c) {
152	unsigned int i;
153
154	for(i = 0; i < ntags; i++)
155		if(c->tags[i] && seltag[i])
156			return True;
157	return False;
158}
159
160void
161resizemaster(Arg *arg) {
162	if(arrange != dotile)
163		return;
164	if(arg->i == 0)
165		master = MASTER;
166	else {
167		if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX
168		|| waw * (master + arg->i) / 1000 <= 2 * BORDERPX)
169			return;
170		master += arg->i;
171	}
172	arrange();
173}
174
175void
176restack(void) {
177	Client *c;
178	XEvent ev;
179
180	drawstatus();
181	if(!sel)
182		return;
183	if(sel->isfloat || arrange == dofloat)
184		XRaiseWindow(dpy, sel->win);
185	if(arrange != dofloat) {
186		if(!sel->isfloat)
187			XLowerWindow(dpy, sel->win);
188		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
189			if(c == sel)
190				continue;
191			XLowerWindow(dpy, c->win);
192		}
193	}
194	XSync(dpy, False);
195	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
196}
197
198void
199settags(Client *c, Client *trans) {
200	char prop[512];
201	unsigned int i, j;
202	regmatch_t tmp;
203	Bool matched = trans != NULL;
204	XClassHint ch = { 0 };
205
206	if(matched)
207		for(i = 0; i < ntags; i++)
208			c->tags[i] = trans->tags[i];
209	else {
210		XGetClassHint(dpy, c->win, &ch);
211		snprintf(prop, sizeof prop, "%s:%s:%s",
212				ch.res_class ? ch.res_class : "",
213				ch.res_name ? ch.res_name : "", c->name);
214		for(i = 0; i < len; i++)
215			if(regexps[i].propregex && !regexec(regexps[i].propregex, prop, 1, &tmp, 0)) {
216				c->isfloat = rule[i].isfloat;
217				for(j = 0; regexps[i].tagregex && j < ntags; j++) {
218					if(!regexec(regexps[i].tagregex, tags[j], 1, &tmp, 0)) {
219						matched = True;
220						c->tags[j] = True;
221					}
222				}
223			}
224		if(ch.res_class)
225			XFree(ch.res_class);
226		if(ch.res_name)
227			XFree(ch.res_name);
228	}
229	if(!matched)
230		for(i = 0; i < ntags; i++)
231			c->tags[i] = seltag[i];
232}
233
234void
235tag(Arg *arg) {
236	unsigned int i;
237
238	if(!sel)
239		return;
240	for(i = 0; i < ntags; i++)
241		sel->tags[i] = (arg->i == -1) ? True : False;
242	if(arg->i >= 0 && arg->i < ntags)
243		sel->tags[arg->i] = True;
244	arrange();
245}
246
247void
248togglefloat(Arg *arg) {
249	if(!sel || arrange == dofloat)
250		return;
251	sel->isfloat = !sel->isfloat;
252	arrange();
253}
254
255void
256toggletag(Arg *arg) {
257	unsigned int i;
258
259	if(!sel)
260		return;
261	sel->tags[arg->i] = !sel->tags[arg->i];
262	for(i = 0; i < ntags && !sel->tags[i]; i++);
263	if(i == ntags)
264		sel->tags[arg->i] = True;
265	arrange();
266}
267
268void
269togglemode(Arg *arg) {
270	arrange = (arrange == dofloat) ? dotile : dofloat;
271	if(sel)
272		arrange();
273	else
274		drawstatus();
275}
276
277void
278toggleview(Arg *arg) {
279	unsigned int i;
280
281	seltag[arg->i] = !seltag[arg->i];
282	for(i = 0; i < ntags && !seltag[i]; i++);
283	if(i == ntags)
284		seltag[arg->i] = True; /* cannot toggle last view */
285	arrange();
286}
287
288void
289view(Arg *arg) {
290	unsigned int i;
291
292	for(i = 0; i < ntags; i++)
293		seltag[i] = (arg->i == -1) ? True : False;
294	if(arg->i >= 0 && arg->i < ntags)
295		seltag[arg->i] = True;
296	arrange();
297}