aewl

annotate tag.c @ 306:71f02d14dce1

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