garbeam@75: /* garbeam@75: * (C)opyright MMVI Anselm R. Garbe garbeam@75: * See LICENSE file for license details. garbeam@75: */ garbeam@76: #include "dwm.h" garbeam@75: arg@114: #include arg@114: #include garbeam@75: #include arg@114: #include garbeam@75: #include garbeam@75: garbeam@84: /* static */ garbeam@76: arg@114: typedef struct { arg@114: const char *pattern; arg@114: char *tags[TLast]; arg@114: Bool isfloat; arg@114: } Rule; arg@114: garbeam@84: /* CUSTOMIZE */ garbeam@84: static Rule rule[] = { arg@123: /* class:instance tags isfloat */ arg@123: { "Firefox.*", { [Twww] = "www" }, False }, arg@123: { "Gimp.*", { 0 }, True}, garbeam@84: }; garbeam@84: garbeam@76: char *tags[TLast] = { garbeam@76: [Tscratch] = "scratch", garbeam@76: [Tdev] = "dev", garbeam@76: [Twww] = "www", garbeam@76: [Twork] = "work", garbeam@76: }; arg@125: garbeam@75: void (*arrange)(Arg *) = dotile; garbeam@75: arg@125: /* END CUSTOMIZE */ arg@125: arg@125: /* extern */ arg@125: garbeam@76: void garbeam@76: appendtag(Arg *arg) garbeam@75: { garbeam@76: if(!sel) garbeam@76: return; garbeam@75: garbeam@76: sel->tags[arg->i] = tags[arg->i]; garbeam@75: arrange(NULL); garbeam@75: } garbeam@75: garbeam@75: void garbeam@75: dofloat(Arg *arg) garbeam@75: { garbeam@75: Client *c; garbeam@75: garbeam@75: for(c = clients; c; c = c->next) { arg@124: c->ismax = False; garbeam@95: if(c->tags[tsel]) { arg@99: resize(c, True, TopLeft); garbeam@95: } garbeam@75: else garbeam@75: ban(c); garbeam@75: } garbeam@75: if(sel && !sel->tags[tsel]) { garbeam@93: if((sel = getnext(clients, tsel))) { garbeam@75: higher(sel); garbeam@75: focus(sel); garbeam@75: } garbeam@75: } garbeam@75: drawall(); garbeam@75: } garbeam@75: garbeam@75: void garbeam@75: dotile(Arg *arg) garbeam@75: { arg@123: int n, i, w, h; garbeam@75: Client *c; garbeam@75: garbeam@75: w = sw - mw; garbeam@75: for(n = 0, c = clients; c; c = c->next) garbeam@80: if(c->tags[tsel] && !c->isfloat) garbeam@75: n++; garbeam@75: garbeam@75: if(n > 1) garbeam@75: h = (sh - bh) / (n - 1); garbeam@75: else garbeam@75: h = sh - bh; garbeam@75: garbeam@75: for(i = 0, c = clients; c; c = c->next) { arg@124: c->ismax = False; garbeam@75: if(c->tags[tsel]) { garbeam@80: if(c->isfloat) { garbeam@75: higher(c); arg@99: resize(c, True, TopLeft); garbeam@75: continue; garbeam@75: } garbeam@75: if(n == 1) { arg@115: c->x = sx; arg@115: c->y = sy + bh; arg@115: c->w = sw - 2 * c->border; arg@115: c->h = sh - 2 * c->border - bh; garbeam@75: } garbeam@75: else if(i == 0) { arg@115: c->x = sx; arg@115: c->y = sy + bh; arg@115: c->w = mw - 2 * c->border; arg@115: c->h = sh - 2 * c->border - bh; garbeam@75: } arg@104: else if(h > bh) { arg@115: c->x = sx + mw; arg@115: c->y = sy + (i - 1) * h + bh; arg@115: c->w = w - 2 * c->border; arg@115: c->h = h - 2 * c->border; garbeam@75: } arg@104: else { /* fallback if h < bh */ arg@115: c->x = sx + mw; arg@115: c->y = sy + bh; arg@115: c->w = w - 2 * c->border; arg@115: c->h = sh - 2 * c->border - bh; arg@104: } arg@99: resize(c, False, TopLeft); garbeam@75: i++; garbeam@75: } garbeam@75: else garbeam@75: ban(c); garbeam@75: } garbeam@75: if(!sel || (sel && !sel->tags[tsel])) { garbeam@93: if((sel = getnext(clients, tsel))) { garbeam@75: higher(sel); garbeam@75: focus(sel); garbeam@75: } garbeam@75: } garbeam@75: drawall(); garbeam@75: } garbeam@75: garbeam@76: Client * garbeam@93: getnext(Client *c, unsigned int t) garbeam@75: { garbeam@93: for(; c && !c->tags[t]; c = c->next); garbeam@76: return c; garbeam@75: } garbeam@75: arg@127: Client * arg@127: getprev(Client *c) arg@127: { arg@127: for(; c && !c->tags[tsel]; c = c->prev); arg@127: return c; arg@127: } arg@127: garbeam@75: void garbeam@93: heretag(Arg *arg) garbeam@93: { garbeam@93: int i; garbeam@93: Client *c; garbeam@93: garbeam@93: if(arg->i == tsel) garbeam@93: return; garbeam@93: garbeam@93: if(!(c = getnext(clients, arg->i))) garbeam@93: return; garbeam@93: garbeam@93: for(i = 0; i < TLast; i++) garbeam@93: c->tags[i] = NULL; garbeam@93: c->tags[tsel] = tags[tsel]; garbeam@94: pop(c); garbeam@93: focus(c); garbeam@93: } garbeam@93: garbeam@93: void garbeam@75: replacetag(Arg *arg) garbeam@75: { garbeam@75: int i; arg@123: garbeam@75: if(!sel) garbeam@75: return; garbeam@75: garbeam@75: for(i = 0; i < TLast; i++) garbeam@75: sel->tags[i] = NULL; garbeam@75: appendtag(arg); garbeam@75: } garbeam@75: garbeam@76: void garbeam@76: settags(Client *c) garbeam@76: { arg@114: char classinst[256]; garbeam@76: static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0; garbeam@76: unsigned int i, j; arg@114: regex_t regex; arg@114: regmatch_t tmp; garbeam@76: Bool matched = False; arg@114: XClassHint ch; garbeam@76: garbeam@76: if(!len) { garbeam@76: c->tags[tsel] = tags[tsel]; garbeam@76: return; garbeam@76: } garbeam@76: garbeam@76: if(XGetClassHint(dpy, c->win, &ch)) { arg@114: snprintf(classinst, sizeof(classinst), "%s:%s", arg@114: ch.res_class ? ch.res_class : "", arg@114: ch.res_name ? ch.res_name : ""); arg@114: for(i = 0; !matched && i < len; i++) { arg@114: if(!regcomp(®ex, rule[i].pattern, 0)) { arg@114: if(!regexec(®ex, classinst, 1, &tmp, 0)) { arg@114: for(j = 0; j < TLast; j++) { arg@114: if(rule[i].tags[j]) arg@114: matched = True; garbeam@76: c->tags[j] = rule[i].tags[j]; arg@114: } garbeam@80: c->isfloat = rule[i].isfloat; garbeam@76: } arg@114: regfree(®ex); arg@114: } garbeam@76: } garbeam@76: if(ch.res_class) garbeam@76: XFree(ch.res_class); garbeam@76: if(ch.res_name) garbeam@76: XFree(ch.res_name); garbeam@76: } garbeam@76: if(!matched) garbeam@76: c->tags[tsel] = tags[tsel]; garbeam@76: } garbeam@76: garbeam@76: void arg@124: togglemode(Arg *arg) arg@124: { arg@124: arrange = arrange == dofloat ? dotile : dofloat; arg@124: arrange(NULL); arg@124: } arg@124: arg@124: void garbeam@76: view(Arg *arg) garbeam@76: { garbeam@76: tsel = arg->i; garbeam@76: arrange(NULL); garbeam@76: drawall(); garbeam@76: }