annotate layout.c @ 5:e060ab82b136

gapless grid
author paulo@thepaulopc
date Wed, 27 Jan 2010 23:28:29 -0800
parents faa4cb9d7bd6
children
rev   line source
paulo@0 1 /* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
paulo@0 2 * See LICENSE file for license details.
paulo@0 3 */
paulo@0 4 #include "dwm.h"
paulo@0 5
paulo@0 6 unsigned int master = MASTER;
paulo@0 7 unsigned int nmaster = NMASTER;
paulo@0 8 unsigned int blw = 0;
paulo@0 9 Layout *lt = NULL;
paulo@0 10
paulo@0 11 /* static */
paulo@0 12
paulo@0 13 static unsigned int nlayouts = 0;
paulo@0 14
paulo@0 15 static void
paulo@0 16 spiral(void) {
paulo@0 17 unsigned int i, n, nx, ny, nw, nh;
paulo@0 18 Client *c;
paulo@0 19
paulo@0 20 nx = wax;
paulo@0 21 ny = way + wah;
paulo@0 22 nw = waw;
paulo@0 23 nh = wah;
paulo@0 24 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
paulo@0 25 n++;
paulo@0 26 for(i = 0, c = clients; c; c = c->next)
paulo@0 27 if(isvisible(c)) {
paulo@0 28 if(c->isbanned)
paulo@0 29 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 30 c->isbanned = False;
paulo@0 31 if(c->isversatile)
paulo@0 32 continue;
paulo@0 33 c->ismax = False;
paulo@0 34 if((i % 2 && nh / 2 > 2 * c->border)
paulo@0 35 || (!(i % 2) && nw / 2 > 2 * c->border))
paulo@0 36 {
paulo@0 37 if(i < n - 1) {
paulo@0 38 if(i % 2)
paulo@0 39 nh /= 2;
paulo@0 40 else
paulo@0 41 nw /= 2;
paulo@0 42 if((i % 4) == 2)
paulo@0 43 nx += nw;
paulo@0 44 else if((i % 4) == 3)
paulo@0 45 ny += nh;
paulo@0 46 }
paulo@0 47 if((i % 4) == 0)
paulo@0 48 ny -= nh;
paulo@0 49 else if((i % 4) == 1)
paulo@0 50 nx += nw;
paulo@0 51 else if((i % 4) == 2)
paulo@0 52 ny += nh;
paulo@0 53 else
paulo@0 54 nx -= nw;
paulo@0 55 i++;
paulo@0 56 }
paulo@0 57 resize(c, nx, ny, nw - 2 * c->border, nh - 2 * c->border, False);
paulo@0 58 }
paulo@0 59 else {
paulo@0 60 c->isbanned = True;
paulo@0 61 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 62 }
paulo@0 63 if(!sel || !isvisible(sel)) {
paulo@0 64 for(c = stack; c && !isvisible(c); c = c->snext);
paulo@0 65 focus(c);
paulo@0 66 }
paulo@0 67 restack();
paulo@0 68 }
paulo@0 69
paulo@0 70 static void
paulo@0 71 spiral_h(void) {
paulo@0 72 unsigned int i, n, nx, ny, nw, nh;
paulo@0 73 Client *c;
paulo@0 74
paulo@0 75 nx = wax + waw;
paulo@0 76 ny = way;
paulo@0 77 nw = waw;
paulo@0 78 nh = wah;
paulo@0 79 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
paulo@0 80 n++;
paulo@0 81 for(i = 0, c = clients; c; c = c->next)
paulo@0 82 if(isvisible(c)) {
paulo@0 83 if(c->isbanned)
paulo@0 84 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 85 c->isbanned = False;
paulo@0 86 if(c->isversatile)
paulo@0 87 continue;
paulo@0 88 c->ismax = False;
paulo@0 89 if((i % 2 && nw / 2 > 2 * c->border)
paulo@0 90 || (!(i % 2) && nh / 2 > 2 * c->border))
paulo@0 91 {
paulo@0 92 if(i < n - 1) {
paulo@0 93 if(i % 2)
paulo@0 94 nw /= 2;
paulo@0 95 else
paulo@0 96 nh /= 2;
paulo@0 97 if((i % 4) == 2)
paulo@0 98 ny += nh;
paulo@0 99 else if((i % 4) == 3)
paulo@0 100 nx += nw;
paulo@0 101 }
paulo@0 102 if((i % 4) == 0)
paulo@0 103 nx -= nw;
paulo@0 104 else if((i % 4) == 1)
paulo@0 105 ny += nh;
paulo@0 106 else if((i % 4) == 2)
paulo@0 107 nx += nw;
paulo@0 108 else
paulo@0 109 ny -= nh;
paulo@0 110 i++;
paulo@0 111 }
paulo@0 112 resize(c, nx, ny, nw - 2 * c->border, nh - 2 * c->border, False);
paulo@0 113 }
paulo@0 114 else {
paulo@0 115 c->isbanned = True;
paulo@0 116 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 117 }
paulo@0 118 if(!sel || !isvisible(sel)) {
paulo@0 119 for(c = stack; c && !isvisible(c); c = c->snext);
paulo@0 120 focus(c);
paulo@0 121 }
paulo@0 122 restack();
paulo@0 123 }
paulo@0 124
paulo@0 125 static void
paulo@0 126 monocle(void) {
paulo@0 127 Client *c;
paulo@0 128
paulo@0 129 for(c = clients; c; c = c->next)
paulo@0 130 if(isvisible(c) && c->isbanned) {
paulo@0 131 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 132 c->isbanned = False;
paulo@0 133 }
paulo@0 134 else if(!isvisible(c)) {
paulo@0 135 c->isbanned = True;
paulo@0 136 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 137 }
paulo@0 138
paulo@0 139 for(c = nexttiled(clients); c; c = nexttiled(c->next))
paulo@0 140 resize(c, wax, way, waw - 2*c->border, wah - 2*c->border, False);
paulo@0 141
paulo@0 142 restack();
paulo@0 143 }
paulo@0 144
paulo@0 145 static void
paulo@0 146 cascade(void) {
paulo@0 147 unsigned int i, n, px = 20;
paulo@0 148 Client *c;
paulo@0 149
paulo@0 150 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
paulo@0 151
paulo@0 152 for(i = 0, c = clients; c; c = c->next)
paulo@0 153 if(isvisible(c)) {
paulo@0 154 if(c->isbanned) {
paulo@0 155 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 156 c->isbanned = False;
paulo@0 157 }
paulo@0 158 if(!c->isversatile) {
paulo@0 159 resize(c, wax+(px*i), way+(px*i), waw-(px*(n-1))-2*c->border, wah-(px*(n-1))-2*c->border, True);
paulo@0 160 i++;
paulo@0 161 }
paulo@0 162 }
paulo@0 163 else if(!isvisible(c)) {
paulo@0 164 c->isbanned = True;
paulo@0 165 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 166 }
paulo@0 167
paulo@0 168 restack();
paulo@0 169 }
paulo@0 170
paulo@0 171 static void
paulo@0 172 bstack(void) {
paulo@0 173 unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
paulo@0 174 Client *c;
paulo@0 175
paulo@0 176 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
paulo@0 177 n++;
paulo@0 178 /* window geoms */
paulo@0 179 mh = (n > nmaster) ? (wah * master) / 1000 : wah;
paulo@0 180 mw = (n > nmaster) ? waw / nmaster : waw / (n > 0 ? n : 1);
paulo@0 181 th = wah - mh;
paulo@0 182 tw = (n > nmaster) ? waw / (n - nmaster) : 0;
paulo@0 183
paulo@0 184 for(i = 0, c = clients; c; c = c->next)
paulo@0 185 if(isvisible(c)) {
paulo@0 186 if(c->isbanned)
paulo@0 187 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 188 c->isbanned = False;
paulo@0 189 if(c->isversatile)
paulo@0 190 continue;
paulo@0 191 c->ismax = False;
paulo@0 192 nx = wax;
paulo@0 193 ny = way;
paulo@0 194 if(i < nmaster) {
paulo@0 195 nx += i * mw;
paulo@0 196 nw = mw - 2 * BORDERPX;
paulo@0 197 nh = mh - 2 * BORDERPX;
paulo@0 198 }
paulo@0 199 else { /* tile window */
paulo@0 200 ny += mh;
paulo@0 201 nh = th - 2 * BORDERPX;
paulo@0 202 if(tw > 2 * BORDERPX) {
paulo@0 203 nx += (i - nmaster) * tw;
paulo@0 204 nw = tw - 2 * BORDERPX;
paulo@0 205 }
paulo@0 206 else /* fallback if th <= 2 * BORDERPX */
paulo@0 207 nw = waw - 2 * BORDERPX;
paulo@0 208 }
paulo@0 209 resize(c, nx, ny, nw, nh, False);
paulo@0 210 i++;
paulo@0 211 }
paulo@0 212 else {
paulo@0 213 c->isbanned = True;
paulo@0 214 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 215 }
paulo@0 216 if(!sel || !isvisible(sel)) {
paulo@0 217 for(c = stack; c && !isvisible(c); c = c->snext);
paulo@0 218 focus(c);
paulo@0 219 }
paulo@0 220 restack();
paulo@0 221 }
paulo@0 222
paulo@0 223 static void
paulo@0 224 grid(void) {
paulo@5 225 unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch;
paulo@0 226 Client *c;
paulo@0 227
paulo@0 228 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
paulo@0 229 n++;
paulo@5 230 if(n == 0)
paulo@5 231 return;
paulo@0 232
paulo@5 233 /* grid dimensions */
paulo@5 234 for(cols = 0; cols <= n/2; cols++)
paulo@5 235 if(cols*cols >= n)
paulo@0 236 break;
paulo@5 237 if(n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
paulo@5 238 cols = 2;
paulo@5 239 rows = n/cols;
paulo@0 240
paulo@5 241 /* window geometries */
paulo@5 242 cw = cols ? waw / cols : waw;
paulo@5 243 cn = 0; /* current column number */
paulo@5 244 rn = 0; /* current row number */
paulo@0 245 for(i = 0, c = clients; c; c = c->next)
paulo@0 246 if(isvisible(c)) {
paulo@5 247 if(i/rows + 1 > cols - n%cols)
paulo@5 248 rows = n/cols + 1;
paulo@5 249 ch = rows ? wah / rows : wah;
paulo@5 250 cx = cn*cw;
paulo@5 251 cy = (TOPBAR ? dc.h : 0) + rn*ch;
paulo@5 252 resize(c, cx, cy, cw - 2 * BORDERPX, ch - 2 * BORDERPX, False);
paulo@5 253 rn++;
paulo@5 254 if(rn >= rows) {
paulo@5 255 rn = 0;
paulo@5 256 cn++;
paulo@5 257 }
paulo@0 258 i++;
paulo@0 259 }
paulo@0 260 else {
paulo@0 261 c->isbanned = True;
paulo@0 262 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 263 }
paulo@5 264
paulo@0 265 if(!sel || !isvisible(sel)) {
paulo@0 266 for(c = stack; c && !isvisible(c); c = c->snext);
paulo@0 267 focus(c);
paulo@0 268 }
paulo@0 269 restack();
paulo@0 270 }
paulo@0 271
paulo@0 272 static void
paulo@0 273 tile(void) {
paulo@0 274 unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
paulo@0 275 Client *c;
paulo@0 276
paulo@0 277 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
paulo@0 278 n++;
paulo@0 279 /* window geoms */
paulo@0 280 mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
paulo@0 281 mw = (n > nmaster) ? (waw * master) / 1000 : waw;
paulo@0 282 th = (n > nmaster) ? wah / (n - nmaster) : 0;
paulo@0 283 tw = waw - mw;
paulo@0 284
paulo@0 285 for(i = 0, c = clients; c; c = c->next)
paulo@0 286 if(isvisible(c)) {
paulo@0 287 if(c->isbanned)
paulo@0 288 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 289 c->isbanned = False;
paulo@0 290 if(c->isversatile)
paulo@0 291 continue;
paulo@0 292 c->ismax = False;
paulo@0 293 nx = wax;
paulo@0 294 ny = way;
paulo@0 295 if(i < nmaster) {
paulo@0 296 ny += i * mh;
paulo@0 297 nw = mw - 2 * BORDERPX;
paulo@0 298 nh = mh - 2 * BORDERPX;
paulo@0 299 }
paulo@0 300 else { /* tile window */
paulo@0 301 nx += mw;
paulo@0 302 nw = tw - 2 * BORDERPX;
paulo@0 303 if(th > 2 * BORDERPX) {
paulo@0 304 ny += (i - nmaster) * th;
paulo@0 305 nh = th - 2 * BORDERPX;
paulo@0 306 }
paulo@0 307 else /* fallback if th <= 2 * BORDERPX */
paulo@0 308 nh = wah - 2 * BORDERPX;
paulo@0 309 }
paulo@0 310 resize(c, nx, ny, nw, nh, False);
paulo@0 311 i++;
paulo@0 312 }
paulo@0 313 else {
paulo@0 314 c->isbanned = True;
paulo@0 315 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 316 }
paulo@0 317 if(!sel || !isvisible(sel)) {
paulo@0 318 for(c = stack; c && !isvisible(c); c = c->snext);
paulo@0 319 focus(c);
paulo@0 320 }
paulo@0 321 restack();
paulo@0 322 }
paulo@0 323
paulo@0 324 LAYOUTS
paulo@0 325
paulo@0 326 /* extern */
paulo@0 327
paulo@0 328 void
paulo@0 329 focusnext(Arg *arg) {
paulo@0 330 Client *c;
paulo@0 331
paulo@0 332 if(!sel)
paulo@0 333 return;
paulo@0 334 for(c = sel->next; c && !isvisible(c); c = c->next);
paulo@0 335 if(!c)
paulo@0 336 for(c = clients; c && !isvisible(c); c = c->next);
paulo@0 337 if(c) {
paulo@0 338 focus(c);
paulo@0 339 restack();
paulo@0 340 }
paulo@0 341 }
paulo@0 342
paulo@0 343 void
paulo@0 344 focusprev(Arg *arg) {
paulo@0 345 Client *c;
paulo@0 346
paulo@0 347 if(!sel)
paulo@0 348 return;
paulo@0 349 for(c = sel->prev; c && !isvisible(c); c = c->prev);
paulo@0 350 if(!c) {
paulo@0 351 for(c = clients; c && c->next; c = c->next);
paulo@0 352 for(; c && !isvisible(c); c = c->prev);
paulo@0 353 }
paulo@0 354 if(c) {
paulo@0 355 focus(c);
paulo@0 356 restack();
paulo@0 357 }
paulo@0 358 }
paulo@0 359
paulo@0 360 void
paulo@0 361 incnmaster(Arg *arg) {
paulo@0 362 //if((lt->arrange != tile) || (nmaster + arg->i < 1)
paulo@0 363 //|| (wah / (nmaster + arg->i) <= 2 * BORDERPX))
paulo@0 364 // return;
paulo@0 365 if(nmaster + arg->i < 1 && nmaster + arg->i <= MAX_TASKS)
paulo@0 366 return;
paulo@0 367 nmaster += arg->i;
paulo@0 368 if(sel)
paulo@0 369 lt->arrange();
paulo@0 370 else
paulo@0 371 drawstatus();
paulo@0 372 }
paulo@0 373
paulo@0 374 void
paulo@0 375 initlayouts(void) {
paulo@0 376 unsigned int i, w;
paulo@0 377
paulo@0 378 lt = &layout[0];
paulo@0 379 nlayouts = sizeof layout / sizeof layout[0];
paulo@0 380 for(blw = i = 0; i < nlayouts; i++) {
paulo@0 381 w = textw(layout[i].symbol);
paulo@0 382 if(w > blw)
paulo@0 383 blw = w;
paulo@0 384 }
paulo@0 385 }
paulo@0 386
paulo@0 387 Client *
paulo@0 388 nexttiled(Client *c) {
paulo@0 389 for(; c && (c->isversatile || !isvisible(c)); c = c->next);
paulo@0 390 return c;
paulo@0 391 }
paulo@0 392
paulo@0 393 void
paulo@0 394 resizemaster(Arg *arg) {
paulo@0 395 //if(lt->arrange != tile)
paulo@0 396 // return;
paulo@0 397 if(arg->i == 0)
paulo@0 398 master = MASTER;
paulo@0 399 else {
paulo@0 400 //if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX
paulo@0 401 //|| waw * (master + arg->i) / 1000 <= 2 * BORDERPX)
paulo@0 402 // return;
paulo@0 403 master += arg->i;
paulo@0 404 }
paulo@0 405 lt->arrange();
paulo@0 406 }
paulo@0 407
paulo@0 408 void
paulo@0 409 restack(void) {
paulo@0 410 Client *c;
paulo@0 411 XEvent ev;
paulo@0 412
paulo@0 413 drawstatus();
paulo@0 414 if(!sel)
paulo@0 415 return;
paulo@0 416 if(sel->isversatile || lt->arrange == versatile)
paulo@0 417 XRaiseWindow(dpy, sel->win);
paulo@0 418 if(lt->arrange != versatile) {
paulo@0 419 if(!sel->isversatile)
paulo@0 420 XLowerWindow(dpy, sel->win);
paulo@0 421 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
paulo@0 422 if(c == sel)
paulo@0 423 continue;
paulo@0 424 XLowerWindow(dpy, c->win);
paulo@0 425 }
paulo@0 426 }
paulo@0 427 XSync(dpy, False);
paulo@0 428 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
paulo@0 429 }
paulo@0 430
paulo@0 431 void
paulo@0 432 setlayout(Arg *arg) {
paulo@1 433 int i;
paulo@0 434
paulo@1 435 if(arg->i < 0) {
paulo@0 436 for(i = 0; i < nlayouts && lt != &layout[i]; i++);
paulo@1 437 if(arg->i == -1)
paulo@1 438 lt = &layout[(i + 1) % nlayouts];
paulo@1 439 else if(arg->i == -2)
paulo@1 440 lt = &layout[(i - 1) >= 0 ? i - 1 : nlayouts - 1];
paulo@0 441 }
paulo@0 442 else {
paulo@0 443 if(arg->i < 0 || arg->i >= nlayouts)
paulo@0 444 return;
paulo@0 445 lt = &layout[arg->i];
paulo@0 446 }
paulo@0 447 if(sel)
paulo@0 448 lt->arrange();
paulo@0 449 else
paulo@0 450 drawstatus();
paulo@0 451 }
paulo@0 452
paulo@0 453 void
paulo@0 454 versatile(void) {
paulo@0 455 Client *c;
paulo@0 456
paulo@0 457 for(c = clients; c; c = c->next) {
paulo@0 458 if(isvisible(c)) {
paulo@0 459 if(c->isbanned)
paulo@0 460 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 461 c->isbanned = False;
paulo@0 462 resize(c, c->x, c->y, c->w, c->h, True);
paulo@0 463 }
paulo@0 464 else {
paulo@0 465 c->isbanned = True;
paulo@0 466 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 467 }
paulo@0 468 }
paulo@0 469 if(!sel || !isvisible(sel)) {
paulo@0 470 for(c = stack; c && !isvisible(c); c = c->snext);
paulo@0 471 focus(c);
paulo@0 472 }
paulo@0 473 restack();
paulo@0 474 }