annotate layout.c @ 2:de6bb7885c97

add right-click eventon layout icon to go to previous layout
author pang@hit-nxdomain.opendns.com
date Tue, 24 Mar 2009 12:52:45 -0700
parents 7024076fa948
children faa4cb9d7bd6
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@0 225 unsigned int i, n, nx, ny, nw, nh, aw, ah, tw, th, cols, rows;
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@0 230
paulo@0 231 for(rows = 0; rows <= n/2; rows++)
paulo@0 232 if(rows*rows >= n)
paulo@0 233 break;
paulo@0 234 cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
paulo@0 235
paulo@0 236 th = (sh - dc.h) / (rows ? rows : 1);
paulo@0 237 tw = sw / (cols ? cols : 1);
paulo@0 238 nw = tw - 2 * BORDERPX;
paulo@0 239 nh = th - 2 * BORDERPX;
paulo@0 240
paulo@0 241 for(i = 0, c = clients; c; c = c->next)
paulo@0 242 if(isvisible(c)) {
paulo@0 243 if(c->isbanned)
paulo@0 244 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 245 c->isbanned = False;
paulo@0 246 if(c->isversatile)
paulo@0 247 continue;
paulo@0 248 c->ismax = False;
paulo@0 249 nx = (i / rows) * tw;
paulo@0 250 ny = (i % rows) * th + (TOPBAR ? dc.h : 0);
paulo@0 251 /* adjust height and width of last row's and last column's windows */
paulo@0 252 ah = ((i + 1) % rows == 0) ? sh - th * rows - dc.h : 0;
paulo@0 253 aw = (i >= rows * (cols - 1)) ? sw - tw * cols : 0;
paulo@0 254 resize(c, nx, ny, nw + aw, nh + ah, False);
paulo@0 255 i++;
paulo@0 256 }
paulo@0 257 else {
paulo@0 258 c->isbanned = True;
paulo@0 259 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 260 }
paulo@0 261
paulo@0 262 if(!sel || !isvisible(sel)) {
paulo@0 263 for(c = stack; c && !isvisible(c); c = c->snext);
paulo@0 264 focus(c);
paulo@0 265 }
paulo@0 266 restack();
paulo@0 267 }
paulo@0 268
paulo@0 269 static void
paulo@0 270 tile(void) {
paulo@0 271 unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
paulo@0 272 Client *c;
paulo@0 273
paulo@0 274 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
paulo@0 275 n++;
paulo@0 276 /* window geoms */
paulo@0 277 mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
paulo@0 278 mw = (n > nmaster) ? (waw * master) / 1000 : waw;
paulo@0 279 th = (n > nmaster) ? wah / (n - nmaster) : 0;
paulo@0 280 tw = waw - mw;
paulo@0 281
paulo@0 282 for(i = 0, c = clients; c; c = c->next)
paulo@0 283 if(isvisible(c)) {
paulo@0 284 if(c->isbanned)
paulo@0 285 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 286 c->isbanned = False;
paulo@0 287 if(c->isversatile)
paulo@0 288 continue;
paulo@0 289 c->ismax = False;
paulo@0 290 nx = wax;
paulo@0 291 ny = way;
paulo@0 292 if(i < nmaster) {
paulo@0 293 ny += i * mh;
paulo@0 294 nw = mw - 2 * BORDERPX;
paulo@0 295 nh = mh - 2 * BORDERPX;
paulo@0 296 }
paulo@0 297 else { /* tile window */
paulo@0 298 nx += mw;
paulo@0 299 nw = tw - 2 * BORDERPX;
paulo@0 300 if(th > 2 * BORDERPX) {
paulo@0 301 ny += (i - nmaster) * th;
paulo@0 302 nh = th - 2 * BORDERPX;
paulo@0 303 }
paulo@0 304 else /* fallback if th <= 2 * BORDERPX */
paulo@0 305 nh = wah - 2 * BORDERPX;
paulo@0 306 }
paulo@0 307 resize(c, nx, ny, nw, nh, False);
paulo@0 308 i++;
paulo@0 309 }
paulo@0 310 else {
paulo@0 311 c->isbanned = True;
paulo@0 312 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 313 }
paulo@0 314 if(!sel || !isvisible(sel)) {
paulo@0 315 for(c = stack; c && !isvisible(c); c = c->snext);
paulo@0 316 focus(c);
paulo@0 317 }
paulo@0 318 restack();
paulo@0 319 }
paulo@0 320
paulo@0 321 LAYOUTS
paulo@0 322
paulo@0 323 /* extern */
paulo@0 324
paulo@0 325 void
paulo@0 326 focusnext(Arg *arg) {
paulo@0 327 Client *c;
paulo@0 328
paulo@0 329 if(!sel)
paulo@0 330 return;
paulo@0 331 for(c = sel->next; c && !isvisible(c); c = c->next);
paulo@0 332 if(!c)
paulo@0 333 for(c = clients; c && !isvisible(c); c = c->next);
paulo@0 334 if(c) {
paulo@0 335 focus(c);
paulo@0 336 restack();
paulo@0 337 }
paulo@0 338 }
paulo@0 339
paulo@0 340 void
paulo@0 341 focusprev(Arg *arg) {
paulo@0 342 Client *c;
paulo@0 343
paulo@0 344 if(!sel)
paulo@0 345 return;
paulo@0 346 for(c = sel->prev; c && !isvisible(c); c = c->prev);
paulo@0 347 if(!c) {
paulo@0 348 for(c = clients; c && c->next; c = c->next);
paulo@0 349 for(; c && !isvisible(c); c = c->prev);
paulo@0 350 }
paulo@0 351 if(c) {
paulo@0 352 focus(c);
paulo@0 353 restack();
paulo@0 354 }
paulo@0 355 }
paulo@0 356
paulo@0 357 void
paulo@0 358 incnmaster(Arg *arg) {
paulo@0 359 //if((lt->arrange != tile) || (nmaster + arg->i < 1)
paulo@0 360 //|| (wah / (nmaster + arg->i) <= 2 * BORDERPX))
paulo@0 361 // return;
paulo@0 362 if(nmaster + arg->i < 1 && nmaster + arg->i <= MAX_TASKS)
paulo@0 363 return;
paulo@0 364 nmaster += arg->i;
paulo@0 365 if(sel)
paulo@0 366 lt->arrange();
paulo@0 367 else
paulo@0 368 drawstatus();
paulo@0 369 }
paulo@0 370
paulo@0 371 void
paulo@0 372 initlayouts(void) {
paulo@0 373 unsigned int i, w;
paulo@0 374
paulo@0 375 lt = &layout[0];
paulo@0 376 nlayouts = sizeof layout / sizeof layout[0];
paulo@0 377 for(blw = i = 0; i < nlayouts; i++) {
paulo@0 378 w = textw(layout[i].symbol);
paulo@0 379 if(w > blw)
paulo@0 380 blw = w;
paulo@0 381 }
paulo@0 382 }
paulo@0 383
paulo@0 384 Client *
paulo@0 385 nexttiled(Client *c) {
paulo@0 386 for(; c && (c->isversatile || !isvisible(c)); c = c->next);
paulo@0 387 return c;
paulo@0 388 }
paulo@0 389
paulo@0 390 void
paulo@0 391 resizemaster(Arg *arg) {
paulo@0 392 //if(lt->arrange != tile)
paulo@0 393 // return;
paulo@0 394 if(arg->i == 0)
paulo@0 395 master = MASTER;
paulo@0 396 else {
paulo@0 397 //if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX
paulo@0 398 //|| waw * (master + arg->i) / 1000 <= 2 * BORDERPX)
paulo@0 399 // return;
paulo@0 400 master += arg->i;
paulo@0 401 }
paulo@0 402 lt->arrange();
paulo@0 403 }
paulo@0 404
paulo@0 405 void
paulo@0 406 restack(void) {
paulo@0 407 Client *c;
paulo@0 408 XEvent ev;
paulo@0 409
paulo@0 410 drawstatus();
paulo@0 411 if(!sel)
paulo@0 412 return;
paulo@0 413 if(sel->isversatile || lt->arrange == versatile)
paulo@0 414 XRaiseWindow(dpy, sel->win);
paulo@0 415 if(lt->arrange != versatile) {
paulo@0 416 if(!sel->isversatile)
paulo@0 417 XLowerWindow(dpy, sel->win);
paulo@0 418 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
paulo@0 419 if(c == sel)
paulo@0 420 continue;
paulo@0 421 XLowerWindow(dpy, c->win);
paulo@0 422 }
paulo@0 423 }
paulo@0 424 XSync(dpy, False);
paulo@0 425 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
paulo@0 426 }
paulo@0 427
paulo@0 428 void
paulo@0 429 setlayout(Arg *arg) {
paulo@1 430 int i;
paulo@0 431
paulo@1 432 if(arg->i < 0) {
paulo@0 433 for(i = 0; i < nlayouts && lt != &layout[i]; i++);
paulo@1 434 if(arg->i == -1)
paulo@1 435 lt = &layout[(i + 1) % nlayouts];
paulo@1 436 else if(arg->i == -2)
paulo@1 437 lt = &layout[(i - 1) >= 0 ? i - 1 : nlayouts - 1];
paulo@0 438 }
paulo@0 439 else {
paulo@0 440 if(arg->i < 0 || arg->i >= nlayouts)
paulo@0 441 return;
paulo@0 442 lt = &layout[arg->i];
paulo@0 443 }
paulo@0 444 if(sel)
paulo@0 445 lt->arrange();
paulo@0 446 else
paulo@0 447 drawstatus();
paulo@0 448 }
paulo@0 449
paulo@0 450 void
paulo@0 451 versatile(void) {
paulo@0 452 Client *c;
paulo@0 453
paulo@0 454 for(c = clients; c; c = c->next) {
paulo@0 455 if(isvisible(c)) {
paulo@0 456 if(c->isbanned)
paulo@0 457 XMoveWindow(dpy, c->win, c->x, c->y);
paulo@0 458 c->isbanned = False;
paulo@0 459 resize(c, c->x, c->y, c->w, c->h, True);
paulo@0 460 }
paulo@0 461 else {
paulo@0 462 c->isbanned = True;
paulo@0 463 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
paulo@0 464 }
paulo@0 465 }
paulo@0 466 if(!sel || !isvisible(sel)) {
paulo@0 467 for(c = stack; c && !isvisible(c); c = c->snext);
paulo@0 468 focus(c);
paulo@0 469 }
paulo@0 470 restack();
paulo@0 471 }