aewl

annotate view.c @ 508:ede48935f2b3

added the new dotile as described on ml
author Anselm R. Garbe <arg@10kloc.org>
date Fri, 29 Sep 2006 16:22:20 +0200
parents 2824b5d0f0f0
children 0dfa6b752aed
rev   line source
arg@327 1 /*
arg@327 2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
arg@327 3 * See LICENSE file for license details.
arg@327 4 */
arg@327 5 #include "dwm.h"
arg@327 6
arg@380 7 /* static */
arg@380 8
arg@382 9 static Client *
arg@487 10 minclient(void) {
arg@382 11 Client *c, *min;
arg@382 12
arg@443 13 if((clients && clients->isfloat) || arrange == dofloat)
arg@443 14 return clients; /* don't touch floating order */
arg@382 15 for(min = c = clients; c; c = c->next)
arg@382 16 if(c->weight < min->weight)
arg@382 17 min = c;
arg@382 18 return min;
arg@382 19 }
arg@382 20
arg@480 21 static Client *
arg@480 22 nexttiled(Client *c) {
arg@480 23 for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
arg@480 24 return c;
arg@480 25 }
arg@480 26
arg@442 27 static void
arg@487 28 reorder(void) {
arg@382 29 Client *c, *newclients, *tail;
arg@380 30
arg@382 31 newclients = tail = NULL;
arg@382 32 while((c = minclient())) {
arg@381 33 detach(c);
arg@382 34 if(tail) {
arg@382 35 c->prev = tail;
arg@382 36 tail->next = c;
arg@382 37 tail = c;
arg@381 38 }
arg@381 39 else
arg@382 40 tail = newclients = c;
arg@380 41 }
arg@382 42 clients = newclients;
arg@380 43 }
arg@380 44
arg@480 45 static void
arg@480 46 togglemax(Client *c)
arg@480 47 {
arg@481 48 XEvent ev;
arg@480 49 if((c->ismax = !c->ismax)) {
arg@480 50 c->rx = c->x; c->x = sx;
arg@480 51 c->ry = c->y; c->y = bh;
arg@502 52 c->rw = c->w; c->w = sw - 2 * BORDERPX;
arg@502 53 c->rh = c->h; c->h = sh - bh - 2 * BORDERPX;
arg@480 54 }
arg@480 55 else {
arg@480 56 c->x = c->rx;
arg@480 57 c->y = c->ry;
arg@481 58 c->w = c->rw;
arg@481 59 c->h = c->rh;
arg@480 60 }
arg@480 61 resize(c, True, TopLeft);
arg@480 62 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
arg@430 63 }
arg@430 64
arg@327 65 /* extern */
arg@327 66
arg@327 67 void (*arrange)(Arg *) = DEFMODE;
arg@505 68 Bool isvertical = VERTICALSTACK;
arg@505 69 StackPos stackpos = STACKPOS;
arg@327 70
arg@327 71 void
arg@461 72 detach(Client *c) {
arg@378 73 if(c->prev)
arg@378 74 c->prev->next = c->next;
arg@378 75 if(c->next)
arg@378 76 c->next->prev = c->prev;
arg@378 77 if(c == clients)
arg@378 78 clients = c->next;
arg@378 79 c->next = c->prev = NULL;
arg@378 80 }
arg@378 81
arg@378 82 void
arg@461 83 dofloat(Arg *arg) {
arg@402 84 Client *c;
arg@400 85
arg@327 86 for(c = clients; c; c = c->next) {
arg@327 87 if(isvisible(c)) {
arg@327 88 resize(c, True, TopLeft);
arg@327 89 }
arg@327 90 else
arg@327 91 ban(c);
arg@327 92 }
arg@446 93 if(!sel || !isvisible(sel)) {
arg@450 94 for(c = stack; c && !isvisible(c); c = c->snext);
arg@450 95 focus(c);
arg@446 96 }
arg@327 97 restack();
arg@327 98 }
arg@327 99
arg@504 100 /* This algorithm is based on a (M)aster area and a (S)tacking area.
arg@504 101 * It supports following arrangements:
arg@507 102 * SSMMM MMMMM MMMSS
arg@507 103 * SSMMM SSSSS MMMSS
arg@504 104 */
arg@327 105 void
arg@461 106 dotile(Arg *arg) {
arg@507 107 int i, n, stackw, stackh, tw, th;
arg@402 108 Client *c;
arg@400 109
arg@488 110 for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
arg@488 111 n++;
arg@327 112
arg@507 113 if(stackpos == StackBottom) {
arg@507 114 stackw = sw;
arg@507 115 stackh = sh - bh - master;
arg@507 116 }
arg@507 117 else {
arg@507 118 stackw = sw - master;
arg@507 119 stackh = sh - bh;
arg@507 120 }
arg@507 121
arg@505 122 if(isvertical) {
arg@507 123 tw = stackw;
arg@507 124 if(n > 1)
arg@507 125 th = stackh / (n - 1);
arg@507 126 else
arg@507 127 th = stackh;
arg@505 128 }
arg@507 129 else {
arg@507 130 th = stackh;
arg@507 131 if(n > 1)
arg@507 132 tw = stackw / (n - 1);
arg@507 133 else
arg@507 134 tw = stackw;
arg@505 135 }
arg@327 136
arg@327 137 for(i = 0, c = clients; c; c = c->next) {
arg@327 138 if(isvisible(c)) {
arg@327 139 if(c->isfloat) {
arg@327 140 resize(c, True, TopLeft);
arg@327 141 continue;
arg@327 142 }
arg@488 143 c->ismax = False;
arg@507 144 if(n == 1) { /* only 1 window */
arg@327 145 c->x = sx;
arg@327 146 c->y = sy + bh;
arg@502 147 c->w = sw - 2 * BORDERPX;
arg@502 148 c->h = sh - 2 * BORDERPX - bh;
arg@327 149 }
arg@507 150 else if(i == 0) { /* master window */
arg@508 151 switch(stackpos) {
arg@508 152 case StackLeft:
arg@508 153 c->x = sx + stackw;
arg@508 154 c->y = sy + bh;
arg@507 155 c->w = master - 2 * BORDERPX;
arg@508 156 c->h = sh - bh - 2 * BORDERPX;
arg@508 157 break;
arg@508 158 case StackBottom:
arg@508 159 c->x = sx;
arg@508 160 c->y = sy + bh;
arg@508 161 c->w = sw - 2 * BORDERPX;
arg@507 162 c->h = master - 2 * BORDERPX;
arg@508 163 break;
arg@508 164 case StackRight:
arg@508 165 c->x = sx;
arg@508 166 c->y = sy + bh;
arg@508 167 c->w = master - 2 * BORDERPX;
arg@508 168 c->h = sh - bh - 2 * BORDERPX;
arg@508 169 break;
arg@507 170 }
arg@507 171 }
arg@507 172 else if((isvertical && th > bh) || (!isvertical && tw > MINW)) {
arg@507 173 /* tile window */
arg@507 174 c->w = tw - 2 * BORDERPX;
arg@507 175 c->h = th - 2 * BORDERPX;
arg@508 176 switch(stackpos) {
arg@508 177 case StackLeft:
arg@508 178 if(isvertical) {
arg@508 179 c->x = sx;
arg@508 180 c->y = sy + (i - 1) * th + bh;
arg@508 181 if(i + 1 == n)
arg@508 182 c->h = sh - c->y - 2 * BORDERPX;
arg@508 183 }
arg@507 184 else {
arg@508 185 c->x = sx + (i - 1) * tw;
arg@508 186 c->y = sy + bh;
arg@508 187 if(i + 1 == n)
arg@508 188 c->w = sx + stackw - c->x - 2 * BORDERPX;
arg@508 189 }
arg@508 190 break;
arg@508 191 case StackBottom:
arg@508 192 if(isvertical) {
arg@508 193 c->x = sx;
arg@508 194 c->y = sy + master + (i - 1) * th + bh;
arg@508 195 if(i + 1 == n)
arg@508 196 c->h = sh - c->y - 2 * BORDERPX;
arg@508 197 }
arg@508 198 else {
arg@508 199 c->x = sx + (i - 1) * tw;
arg@508 200 c->y = sy + bh + master;
arg@508 201 if(i + 1 == n)
arg@507 202 c->w = sw - c->x - 2 * BORDERPX;
arg@507 203 }
arg@508 204 break;
arg@508 205 case StackRight:
arg@508 206 if(isvertical) {
arg@508 207 c->x = sx + master;
arg@508 208 c->y = sy + (i - 1) * th + bh;
arg@508 209 if(i + 1 == n)
arg@508 210 c->h = sh - c->y - 2 * BORDERPX;
arg@508 211 }
arg@508 212 else {
arg@508 213 c->x = sx + master + (i - 1) * tw;
arg@508 214 c->y = sy + bh;
arg@508 215 if(i + 1 == n)
arg@508 216 c->w = sx + stackw - c->x - 2 * BORDERPX;
arg@508 217 }
arg@508 218 break;
arg@507 219 }
arg@507 220 }
arg@507 221 else { /* fallback if th < bh resp. tw < MINW */
arg@507 222 c->w = stackw - 2 * BORDERPX;
arg@507 223 c->h = stackh - 2 * BORDERPX;
arg@508 224 switch(stackpos) {
arg@508 225 case StackLeft:
arg@508 226 c->x = sx;
arg@508 227 c->y = sy + bh;
arg@508 228 break;
arg@508 229 case StackBottom:
arg@508 230 c->x = sx;
arg@508 231 c->y = sy + master;
arg@508 232 break;
arg@508 233 case StackRight:
arg@508 234 c->x = sx + master;
arg@508 235 c->y = sy + bh;
arg@508 236 break;
arg@508 237 }
arg@327 238 }
arg@327 239 resize(c, False, TopLeft);
arg@327 240 i++;
arg@327 241 }
arg@327 242 else
arg@327 243 ban(c);
arg@327 244 }
arg@446 245 if(!sel || !isvisible(sel)) {
arg@450 246 for(c = stack; c && !isvisible(c); c = c->snext);
arg@450 247 focus(c);
arg@446 248 }
arg@327 249 restack();
arg@327 250 }
arg@327 251
arg@327 252 void
arg@461 253 focusnext(Arg *arg) {
arg@327 254 Client *c;
arg@327 255
arg@327 256 if(!sel)
arg@327 257 return;
arg@327 258
arg@327 259 if(!(c = getnext(sel->next)))
arg@327 260 c = getnext(clients);
arg@327 261 if(c) {
arg@327 262 focus(c);
arg@327 263 restack();
arg@327 264 }
arg@327 265 }
arg@327 266
arg@327 267 void
arg@461 268 focusprev(Arg *arg) {
arg@327 269 Client *c;
arg@327 270
arg@327 271 if(!sel)
arg@327 272 return;
arg@327 273
arg@327 274 if(!(c = getprev(sel->prev))) {
arg@327 275 for(c = clients; c && c->next; c = c->next);
arg@327 276 c = getprev(c);
arg@327 277 }
arg@327 278 if(c) {
arg@327 279 focus(c);
arg@327 280 restack();
arg@327 281 }
arg@327 282 }
arg@327 283
arg@420 284 Bool
arg@461 285 isvisible(Client *c) {
arg@420 286 unsigned int i;
arg@420 287
arg@420 288 for(i = 0; i < ntags; i++)
arg@420 289 if(c->tags[i] && seltag[i])
arg@420 290 return True;
arg@420 291 return False;
arg@420 292 }
arg@420 293
arg@415 294 void
arg@461 295 resizecol(Arg *arg) {
arg@423 296 unsigned int n;
arg@423 297 Client *c;
arg@418 298
arg@430 299 for(n = 0, c = clients; c; c = c->next)
arg@430 300 if(isvisible(c) && !c->isfloat)
arg@423 301 n++;
arg@486 302 if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
arg@415 303 return;
arg@423 304
arg@415 305 if(sel == getnext(clients)) {
arg@507 306 if(master + arg->i > sw - MINW || master + arg->i < MINW)
arg@415 307 return;
arg@505 308 master += arg->i;
arg@415 309 }
arg@415 310 else {
arg@507 311 if(master - arg->i > sw - MINW || master - arg->i < MINW)
arg@415 312 return;
arg@505 313 master -= arg->i;
arg@415 314 }
arg@415 315 arrange(NULL);
arg@415 316 }
arg@415 317
arg@327 318 void
arg@487 319 restack(void) {
arg@327 320 Client *c;
arg@327 321 XEvent ev;
arg@481 322
arg@437 323 if(!sel) {
arg@437 324 drawstatus();
arg@436 325 return;
arg@437 326 }
arg@436 327 if(sel->isfloat || arrange == dofloat) {
arg@436 328 XRaiseWindow(dpy, sel->win);
arg@436 329 XRaiseWindow(dpy, sel->twin);
arg@436 330 }
arg@446 331 if(arrange != dofloat)
arg@436 332 for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
arg@436 333 XLowerWindow(dpy, c->twin);
arg@436 334 XLowerWindow(dpy, c->win);
arg@327 335 }
arg@327 336 drawall();
arg@327 337 XSync(dpy, False);
arg@327 338 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
arg@327 339 }
arg@327 340
arg@327 341 void
arg@461 342 togglemode(Arg *arg) {
arg@333 343 arrange = (arrange == dofloat) ? dotile : dofloat;
arg@327 344 if(sel)
arg@327 345 arrange(NULL);
arg@327 346 else
arg@327 347 drawstatus();
arg@327 348 }
arg@327 349
arg@327 350 void
arg@461 351 toggleview(Arg *arg) {
arg@327 352 unsigned int i;
arg@327 353
arg@327 354 seltag[arg->i] = !seltag[arg->i];
arg@327 355 for(i = 0; i < ntags && !seltag[i]; i++);
arg@327 356 if(i == ntags)
arg@327 357 seltag[arg->i] = True; /* cannot toggle last view */
arg@381 358 reorder();
arg@327 359 arrange(NULL);
arg@327 360 }
arg@327 361
arg@327 362 void
arg@508 363 togglestackdir(Arg *arg) {
arg@508 364 if(arrange == dofloat)
arg@508 365 return;
arg@508 366 isvertical = !isvertical;
arg@508 367 arrange(NULL);
arg@508 368 }
arg@508 369
arg@508 370 void
arg@508 371 togglestackpos(Arg *arg) {
arg@508 372 if(arrange == dofloat)
arg@508 373 return;
arg@508 374 if(stackpos == StackBottom)
arg@508 375 stackpos = STACKPOS;
arg@508 376 else
arg@508 377 stackpos = StackBottom;
arg@508 378 updatemaster();
arg@508 379 arrange(NULL);
arg@508 380 }
arg@508 381
arg@508 382 void
arg@508 383 updatemaster(void) {
arg@508 384 master = ((stackpos == StackBottom ? sh - bh : sw) * MASTER) / 100;
arg@508 385 }
arg@508 386
arg@508 387 void
arg@461 388 view(Arg *arg) {
arg@327 389 unsigned int i;
arg@327 390
arg@327 391 for(i = 0; i < ntags; i++)
arg@327 392 seltag[i] = False;
arg@327 393 seltag[arg->i] = True;
arg@381 394 reorder();
arg@327 395 arrange(NULL);
arg@327 396 }
arg@327 397
arg@327 398 void
arg@461 399 viewall(Arg *arg) {
arg@395 400 unsigned int i;
arg@395 401
arg@395 402 for(i = 0; i < ntags; i++)
arg@395 403 seltag[i] = True;
arg@397 404 reorder();
arg@395 405 arrange(NULL);
arg@395 406 }
arg@395 407
arg@508 408
arg@508 409
arg@395 410 void
arg@461 411 zoom(Arg *arg) {
arg@423 412 unsigned int n;
arg@423 413 Client *c;
arg@473 414
arg@473 415 if(!sel)
arg@473 416 return;
arg@473 417
arg@473 418 if(sel->isfloat || (arrange == dofloat)) {
arg@480 419 togglemax(sel);
arg@473 420 return;
arg@473 421 }
arg@327 422
arg@430 423 for(n = 0, c = clients; c; c = c->next)
arg@430 424 if(isvisible(c) && !c->isfloat)
arg@423 425 n++;
arg@486 426 if(n < 2 || (arrange == dofloat))
arg@327 427 return;
arg@327 428
arg@430 429 if((c = sel) == nexttiled(clients))
arg@433 430 if(!(c = nexttiled(c->next)))
arg@429 431 return;
arg@443 432 detach(c);
arg@443 433 if(clients)
arg@443 434 clients->prev = c;
arg@443 435 c->next = clients;
arg@443 436 clients = c;
arg@378 437 focus(c);
arg@327 438 arrange(NULL);
arg@327 439 }