dwm-meillo

annotate tag.c @ 270:dacd3f3c5823

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