all repos — dwm @ d4b7a9a3735deeab639f28b5bb2f568e0dc49616

fork of suckless dynamic window manager

tag.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 <regex.h>
  7#include <stdio.h>
  8#include <stdlib.h>
  9#include <string.h>
 10#include <sys/types.h>
 11#include <X11/Xutil.h>
 12
 13
 14typedef struct {
 15	const char *clpattern;
 16	const char *tpattern;
 17	Bool isfloat;
 18} Rule;
 19
 20typedef struct {
 21	regex_t *clregex;
 22	regex_t *tregex;
 23} RReg;
 24
 25/* static */
 26
 27TAGS
 28RULES
 29
 30static RReg *rreg = NULL;
 31static unsigned int len = 0;
 32
 33void (*arrange)(Arg *) = DEFMODE;
 34
 35/* extern */
 36
 37void
 38appendtag(Arg *arg)
 39{
 40	if(!sel)
 41		return;
 42
 43	sel->tags[arg->i] = True;
 44	arrange(NULL);
 45}
 46
 47void
 48dofloat(Arg *arg)
 49{
 50	Client *c;
 51
 52	for(c = clients; c; c = c->next) {
 53		c->ismax = False;
 54		if(isvisible(c)) {
 55			resize(c, True, TopLeft);
 56		}
 57		else
 58			ban(c);
 59	}
 60	if((sel = getnext(clients))) {
 61		focus(sel);
 62		restack();
 63	}
 64	else
 65		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
 66}
 67
 68void
 69dotile(Arg *arg)
 70{
 71	int h, i, n, w;
 72	Client *c;
 73
 74	w = sw - mw;
 75	for(n = 0, c = clients; c; c = c->next)
 76		if(isvisible(c) && !c->isfloat)
 77			n++;
 78
 79	if(n > 1)
 80		h = (sh - bh) / (n - 1);
 81	else
 82		h = sh - bh;
 83
 84	for(i = 0, c = clients; c; c = c->next) {
 85		c->ismax = False;
 86		if(isvisible(c)) {
 87			if(c->isfloat) {
 88				resize(c, True, TopLeft);
 89				continue;
 90			}
 91			if(n == 1) {
 92				c->x = sx;
 93				c->y = sy + bh;
 94				c->w = sw - 2;
 95				c->h = sh - 2 - bh;
 96			}
 97			else if(i == 0) {
 98				c->x = sx;
 99				c->y = sy + bh;
100				c->w = mw - 2;
101				c->h = sh - 2 - bh;
102			}
103			else if(h > bh) {
104				c->x = sx + mw;
105				c->y = sy + (i - 1) * h + bh;
106				c->w = w - 2;
107				if(i + 1 == n)
108					c->h = sh - c->y - 2;
109				else
110					c->h = h - 2;
111			}
112			else { /* fallback if h < bh */
113				c->x = sx + mw;
114				c->y = sy + bh;
115				c->w = w - 2;
116				c->h = sh - 2 - bh;
117			}
118			resize(c, False, TopLeft);
119			i++;
120		}
121		else
122			ban(c);
123	}
124	if((sel = getnext(clients)))
125		focus(sel);
126	else
127		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
128	restack();
129}
130
131Client *
132getnext(Client *c)
133{
134	for(; c && !isvisible(c); c = c->next);
135	return c;
136}
137
138Client *
139getprev(Client *c)
140{
141	for(; c && !isvisible(c); c = c->prev);
142	return c;
143}
144
145void
146initrregs()
147{
148	unsigned int i;
149	regex_t *reg;
150
151	if(rreg)
152		return;
153	len = sizeof(rule) / sizeof(rule[0]);
154	rreg = emallocz(len * sizeof(RReg));
155
156	for(i = 0; i < len; i++) {
157		if(rule[i].clpattern) {
158			reg = emallocz(sizeof(regex_t));
159			if(regcomp(reg, rule[i].clpattern, 0))
160				free(reg);
161			else
162				rreg[i].clregex = reg;
163		}
164		if(rule[i].tpattern) {
165			reg = emallocz(sizeof(regex_t));
166			if(regcomp(reg, rule[i].tpattern, 0))
167				free(reg);
168			else
169				rreg[i].tregex = reg;
170		}
171	}
172}
173
174Bool
175isvisible(Client *c)
176{
177	unsigned int i;
178
179	for(i = 0; i < ntags; i++)
180		if(c->tags[i] && seltag[i])
181			return True;
182	return False;
183}
184
185void
186replacetag(Arg *arg)
187{
188	int i;
189
190	if(!sel)
191		return;
192
193	for(i = 0; i < ntags; i++)
194		sel->tags[i] = False;
195	appendtag(arg);
196}
197
198void
199restack()
200{
201	static unsigned int nwins = 0;
202	static Window *wins = NULL;
203	unsigned int f, fi, m, mi, n;
204	Client *c;
205	XEvent ev;
206
207	for(f = 0, m = 0, c = clients; c; c = c->next)
208		if(isvisible(c)) {
209			if(c->isfloat || arrange == dofloat)
210				f++;
211			else
212				m++;
213		}
214
215	n = 2 * (f + m);
216	if(nwins < n) {
217		nwins = n;
218		wins = erealloc(wins, nwins * sizeof(Window));
219	}
220
221	fi = 0;
222	mi = 2 * f;
223	if(sel->isfloat || arrange == dofloat) {
224		wins[fi++] = sel->title;
225		wins[fi++] = sel->win;
226	}
227	else {
228		wins[mi++] = sel->title;
229		wins[mi++] = sel->win;
230	}
231	for(c = clients; c; c = c->next)
232		if(isvisible(c) && c != sel) {
233			if(c->isfloat || arrange == dofloat) {
234				wins[fi++] = c->title;
235				wins[fi++] = c->win;
236			}
237			else {
238				wins[mi++] = c->title;
239				wins[mi++] = c->win;
240			}
241		}
242	XRestackWindows(dpy, wins, n);
243	drawall();
244	XSync(dpy, False);
245	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
246}
247
248void
249settags(Client *c)
250{
251	char classinst[256];
252	unsigned int i, j;
253	regmatch_t tmp;
254	Bool matched = False;
255	XClassHint ch;
256
257	if(XGetClassHint(dpy, c->win, &ch)) {
258		snprintf(classinst, sizeof(classinst), "%s:%s",
259				ch.res_class ? ch.res_class : "",
260				ch.res_name ? ch.res_name : "");
261		for(i = 0; !matched && i < len; i++)
262			if(rreg[i].clregex && !regexec(rreg[i].clregex, classinst, 1, &tmp, 0)) {
263				c->isfloat = rule[i].isfloat;
264				for(j = 0; rreg[i].tregex && j < ntags; j++) {
265					if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) {
266						matched = True;
267						c->tags[j] = True;
268					}
269				}
270			}
271		if(ch.res_class)
272			XFree(ch.res_class);
273		if(ch.res_name)
274			XFree(ch.res_name);
275	}
276	if(!matched)
277		for(i = 0; i < ntags; i++)
278			c->tags[i] = seltag[i];
279}
280
281void
282togglemode(Arg *arg)
283{
284	arrange = arrange == dofloat ? dotile : dofloat;
285	arrange(NULL);
286}
287
288void
289view(Arg *arg)
290{
291	unsigned int i;
292
293	for(i = 0; i < ntags; i++)
294		seltag[i] = False;
295	seltag[arg->i] = True;
296	arrange(NULL);
297}
298
299void
300toggleview(Arg *arg)
301{
302	unsigned int i;
303
304	seltag[arg->i] = !seltag[arg->i];
305	for(i = 0; !seltag[i] && i < ntags; i++);
306	if(i == ntags)
307		seltag[arg->i] = True; /* cannot toggle last view */
308	arrange(NULL);
309}