all repos — dwm @ bcaf6a7a0f492c3fafc4baabd2dc06f5191417ee

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
  7#include <regex.h>
  8#include <stdio.h>
  9#include <string.h>
 10#include <sys/types.h>
 11#include <X11/Xutil.h>
 12
 13/* static */
 14
 15typedef struct {
 16	const char *pattern;
 17	char *tags[TLast];
 18	Bool isfloat;
 19} Rule;
 20
 21/* CUSTOMIZE */ 
 22static Rule rule[] = {
 23	/* class			instance	tags		isfloat */
 24	{ "Firefox.*",	{ [Twww] = "www" },			False },
 25	{ "Gimp.*",		{ 0 },						True},
 26};
 27
 28/* extern */
 29
 30/* CUSTOMIZE */
 31char *tags[TLast] = {
 32	[Tscratch] = "scratch",
 33	[Tdev] = "dev",
 34	[Twww] = "www",
 35	[Twork] = "work",
 36};
 37void (*arrange)(Arg *) = dotile;
 38
 39void
 40appendtag(Arg *arg)
 41{
 42	if(!sel)
 43		return;
 44
 45	sel->tags[arg->i] = tags[arg->i];
 46	arrange(NULL);
 47}
 48
 49void
 50dofloat(Arg *arg)
 51{
 52	Client *c;
 53
 54	arrange = dofloat;
 55	for(c = clients; c; c = c->next) {
 56		setgeom(c);
 57		if(c->tags[tsel]) {
 58			resize(c, True, TopLeft);
 59		}
 60		else
 61			ban(c);
 62	}
 63	if(sel && !sel->tags[tsel]) {
 64		if((sel = getnext(clients, tsel))) {
 65			higher(sel);
 66			focus(sel);
 67		}
 68	}
 69	drawall();
 70}
 71
 72void
 73dotile(Arg *arg)
 74{
 75	Client *c;
 76	int n, i, w, h;
 77
 78	w = sw - mw;
 79	arrange = dotile;
 80	for(n = 0, c = clients; c; c = c->next)
 81		if(c->tags[tsel] && !c->isfloat)
 82			n++;
 83
 84	if(n > 1)
 85		h = (sh - bh) / (n - 1);
 86	else
 87		h = sh - bh;
 88
 89	for(i = 0, c = clients; c; c = c->next) {
 90		setgeom(c);
 91		if(c->tags[tsel]) {
 92			if(c->isfloat) {
 93				higher(c);
 94				resize(c, True, TopLeft);
 95				continue;
 96			}
 97			if(n == 1) {
 98				*c->x = sx;
 99				*c->y = sy + bh;
100				*c->w = sw - 2 * c->border;
101				*c->h = sh - 2 * c->border - bh;
102			}
103			else if(i == 0) {
104				*c->x = sx;
105				*c->y = sy + bh;
106				*c->w = mw - 2 * c->border;
107				*c->h = sh - 2 * c->border - bh;
108			}
109			else if(h > bh) {
110				*c->x = sx + mw;
111				*c->y = sy + (i - 1) * h + bh;
112				*c->w = w - 2 * c->border;
113				*c->h = h - 2 * c->border;
114			}
115			else { /* fallback if h < bh */
116				*c->x = sx + mw;
117				*c->y = sy + bh;
118				*c->w = w - 2 * c->border;
119				*c->h = sh - 2 * c->border - bh;
120			}
121			resize(c, False, TopLeft);
122			i++;
123		}
124		else
125			ban(c);
126	}
127	if(!sel || (sel && !sel->tags[tsel])) {
128		if((sel = getnext(clients, tsel))) {
129			higher(sel);
130			focus(sel);
131		}
132	}
133	drawall();
134}
135
136Client *
137getnext(Client *c, unsigned int t)
138{
139	for(; c && !c->tags[t]; c = c->next);
140	return c;
141}
142
143void
144heretag(Arg *arg)
145{
146	int i;
147	Client *c;
148
149	if(arg->i == tsel)
150		return;
151
152	if(!(c = getnext(clients, arg->i)))
153		return;
154
155	for(i = 0; i < TLast; i++)
156		c->tags[i] = NULL;
157	c->tags[tsel] = tags[tsel];
158	pop(c);
159	focus(c);
160}
161
162void
163replacetag(Arg *arg)
164{
165	int i;
166	if(!sel)
167		return;
168
169	for(i = 0; i < TLast; i++)
170		sel->tags[i] = NULL;
171	appendtag(arg);
172}
173
174void
175settags(Client *c)
176{
177	char classinst[256];
178	static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0;
179	unsigned int i, j;
180	regex_t regex;
181	regmatch_t tmp;
182	Bool matched = False;
183	XClassHint ch;
184
185	if(!len) {
186		c->tags[tsel] = tags[tsel];
187		return;
188	}
189
190	if(XGetClassHint(dpy, c->win, &ch)) {
191		snprintf(classinst, sizeof(classinst), "%s:%s",
192				ch.res_class ? ch.res_class : "",
193				ch.res_name ? ch.res_name : "");
194		for(i = 0; !matched && i < len; i++) {
195			if(!regcomp(&regex, rule[i].pattern, 0)) {
196				if(!regexec(&regex, classinst, 1, &tmp, 0)) {
197					for(j = 0; j < TLast; j++) {
198						if(rule[i].tags[j])
199							matched = True;
200						c->tags[j] = rule[i].tags[j];
201					}
202					c->isfloat = rule[i].isfloat;
203				}
204				regfree(&regex);
205			}
206		}
207		if(ch.res_class)
208			XFree(ch.res_class);
209		if(ch.res_name)
210			XFree(ch.res_name);
211	}
212	if(!matched)
213		c->tags[tsel] = tags[tsel];
214}
215
216void
217view(Arg *arg)
218{
219	tsel = arg->i;
220	arrange(NULL);
221	drawall();
222}