new stuff
3aad9220
5 file(s) · +103 −61
| 3 | 3 | * See LICENSE file for license details. |
|
| 4 | 4 | */ |
|
| 5 | 5 | ||
| 6 | - | #include <math.h> |
|
| 7 | 6 | #include <stdlib.h> |
|
| 7 | + | #include <stdio.h> |
|
| 8 | 8 | #include <string.h> |
|
| 9 | 9 | #include <X11/Xatom.h> |
|
| 10 | 10 | #include <X11/Xutil.h> |
|
| 11 | 11 | ||
| 12 | 12 | #include "dwm.h" |
|
| 13 | 13 | ||
| 14 | - | static void (*arrange)(Arg *) = floating; |
|
| 14 | + | static void (*arrange)(Arg *) = tiling; |
|
| 15 | 15 | ||
| 16 | - | static void |
|
| 17 | - | center(Client *c) |
|
| 18 | - | { |
|
| 19 | - | XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); |
|
| 20 | - | } |
|
| 16 | + | static Rule rule[] = { |
|
| 17 | + | { "Firefox-bin", "Gecko", { [Twww] = "www" } }, |
|
| 18 | + | }; |
|
| 21 | 19 | ||
| 22 | 20 | static Client * |
|
| 23 | 21 | next(Client *c) |
|
| 29 | 27 | void |
|
| 30 | 28 | zoom(Arg *arg) |
|
| 31 | 29 | { |
|
| 32 | - | Client **l; |
|
| 30 | + | Client **l, *old; |
|
| 33 | 31 | ||
| 34 | - | if(!sel) |
|
| 32 | + | if(!(old = sel)) |
|
| 35 | 33 | return; |
|
| 36 | 34 | ||
| 37 | 35 | for(l = &clients; *l && *l != sel; l = &(*l)->next); |
|
| 38 | 36 | *l = sel->next; |
|
| 39 | 37 | ||
| 40 | - | sel->next = clients; /* pop */ |
|
| 41 | - | clients = sel; |
|
| 38 | + | old->next = clients; /* pop */ |
|
| 39 | + | clients = old; |
|
| 40 | + | sel = old; |
|
| 42 | 41 | arrange(NULL); |
|
| 43 | - | center(sel); |
|
| 44 | 42 | focus(sel); |
|
| 45 | 43 | } |
|
| 46 | 44 | ||
| 119 | 117 | tiling(Arg *arg) |
|
| 120 | 118 | { |
|
| 121 | 119 | Client *c; |
|
| 122 | - | int n, cols, rows, gw, gh, i, j; |
|
| 123 | - | float rt, fd; |
|
| 120 | + | int n, i, w, h; |
|
| 124 | 121 | ||
| 122 | + | w = sw - mw; |
|
| 125 | 123 | arrange = tiling; |
|
| 126 | - | for(n = 0, c = clients; c; c = next(c->next), n++); |
|
| 127 | - | if(n) { |
|
| 128 | - | rt = sqrt(n); |
|
| 129 | - | if(modff(rt, &fd) < 0.5) |
|
| 130 | - | rows = floor(rt); |
|
| 131 | - | else |
|
| 132 | - | rows = ceil(rt); |
|
| 133 | - | if(rows * rows < n) |
|
| 134 | - | cols = rows + 1; |
|
| 135 | - | else |
|
| 136 | - | cols = rows; |
|
| 124 | + | for(n = 0, c = clients; c; c = c->next) |
|
| 125 | + | if(c->tags[tsel]) |
|
| 126 | + | n++; |
|
| 137 | 127 | ||
| 138 | - | gw = (sw - 2) / cols; |
|
| 139 | - | gh = (sh - 2) / rows; |
|
| 140 | - | } |
|
| 141 | - | else |
|
| 142 | - | cols = rows = gw = gh = 0; |
|
| 128 | + | h = (n > 2) ? sh / (n - 2) : sh; |
|
| 143 | 129 | ||
| 144 | - | for(i = j = 0, c = clients; c; c = c->next) { |
|
| 130 | + | for(i = 0, c = clients; c; c = c->next) { |
|
| 145 | 131 | if(c->tags[tsel]) { |
|
| 146 | - | c->x = i * gw; |
|
| 147 | - | c->y = j * gh; |
|
| 148 | - | c->w = gw; |
|
| 149 | - | c->h = gh; |
|
| 150 | - | resize(c); |
|
| 151 | - | if(++i == cols) { |
|
| 152 | - | j++; |
|
| 153 | - | i = 0; |
|
| 132 | + | if(n == 1) { |
|
| 133 | + | c->x = sx; |
|
| 134 | + | c->y = sy; |
|
| 135 | + | c->w = sw; |
|
| 136 | + | c->h = sh; |
|
| 154 | 137 | } |
|
| 138 | + | else if(i == 1) { |
|
| 139 | + | c->x = sx; |
|
| 140 | + | c->y = sy; |
|
| 141 | + | c->w = mw; |
|
| 142 | + | c->h = sh; |
|
| 143 | + | } |
|
| 144 | + | else { |
|
| 145 | + | c->x = sx + mw; |
|
| 146 | + | c->y = sy + (i - 2) * h; |
|
| 147 | + | c->w = w; |
|
| 148 | + | c->h = h; |
|
| 149 | + | } |
|
| 150 | + | resize(c); |
|
| 151 | + | i++; |
|
| 155 | 152 | } |
|
| 156 | 153 | else |
|
| 157 | 154 | ban_client(c); |
|
| 175 | 172 | ||
| 176 | 173 | if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) { |
|
| 177 | 174 | craise(c); |
|
| 178 | - | center(c); |
|
| 179 | 175 | focus(c); |
|
| 180 | 176 | } |
|
| 181 | 177 | } |
|
| 192 | 188 | c = next(clients); |
|
| 193 | 189 | if(c) { |
|
| 194 | 190 | craise(c); |
|
| 195 | - | center(c); |
|
| 196 | 191 | c->revert = sel; |
|
| 197 | 192 | focus(c); |
|
| 198 | 193 | } |
|
| 323 | 318 | discard_events(EnterWindowMask); |
|
| 324 | 319 | } |
|
| 325 | 320 | ||
| 321 | + | static void |
|
| 322 | + | init_tags(Client *c) |
|
| 323 | + | { |
|
| 324 | + | XClassHint ch; |
|
| 325 | + | static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0; |
|
| 326 | + | unsigned int i, j; |
|
| 327 | + | Bool matched = False; |
|
| 328 | + | ||
| 329 | + | if(!len) { |
|
| 330 | + | c->tags[tsel] = tags[tsel]; |
|
| 331 | + | return; |
|
| 332 | + | } |
|
| 333 | + | ||
| 334 | + | if(XGetClassHint(dpy, c->win, &ch)) { |
|
| 335 | + | if(ch.res_class && ch.res_name) { |
|
| 336 | + | fprintf(stderr, "%s:%s\n", ch.res_class, ch.res_name); |
|
| 337 | + | for(i = 0; i < len; i++) |
|
| 338 | + | if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class)) |
|
| 339 | + | && !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance))) |
|
| 340 | + | { |
|
| 341 | + | fprintf(stderr, "->>>%s:%s\n", ch.res_class, ch.res_name); |
|
| 342 | + | for(j = 0; j < TLast; j++) |
|
| 343 | + | c->tags[j] = rule[i].tags[j]; |
|
| 344 | + | matched = True; |
|
| 345 | + | break; |
|
| 346 | + | } |
|
| 347 | + | } |
|
| 348 | + | if(ch.res_class) |
|
| 349 | + | XFree(ch.res_class); |
|
| 350 | + | if(ch.res_name) |
|
| 351 | + | XFree(ch.res_name); |
|
| 352 | + | } |
|
| 353 | + | ||
| 354 | + | if(!matched) |
|
| 355 | + | c->tags[tsel] = tags[tsel]; |
|
| 356 | + | } |
|
| 357 | + | ||
| 326 | 358 | void |
|
| 327 | 359 | manage(Window w, XWindowAttributes *wa) |
|
| 328 | 360 | { |
|
| 346 | 378 | twa.background_pixmap = ParentRelative; |
|
| 347 | 379 | twa.event_mask = ExposureMask; |
|
| 348 | 380 | ||
| 349 | - | c->tags[tsel] = tags[tsel]; |
|
| 350 | 381 | c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th, |
|
| 351 | 382 | 0, DefaultDepth(dpy, screen), CopyFromParent, |
|
| 352 | 383 | DefaultVisual(dpy, screen), |
|
| 353 | 384 | CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); |
|
| 354 | 385 | ||
| 355 | 386 | update_name(c); |
|
| 387 | + | init_tags(c); |
|
| 356 | 388 | ||
| 357 | 389 | for(l = &clients; *l; l = &(*l)->next); |
|
| 358 | 390 | c->next = *l; /* *l == nil */ |
|
| 368 | 400 | XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask, |
|
| 369 | 401 | GrabModeAsync, GrabModeSync, None, None); |
|
| 370 | 402 | arrange(NULL); |
|
| 371 | - | center(c); |
|
| 372 | - | focus(c); |
|
| 403 | + | if(c->tags[tsel]) |
|
| 404 | + | focus(c); |
|
| 405 | + | else |
|
| 406 | + | ban_client(c); |
|
| 373 | 407 | } |
|
| 374 | 408 | ||
| 375 | 409 | void |
|
| 11 | 11 | VERSION = 0.0 |
|
| 12 | 12 | ||
| 13 | 13 | # includes and libs |
|
| 14 | - | LIBS = -L${PREFIX}/lib -L/usr/lib -lc -lm -L${X11LIB} -lX11 |
|
| 14 | + | LIBS = -L${PREFIX}/lib -L/usr/lib -lc -L${X11LIB} -lX11 |
|
| 15 | 15 | ||
| 16 | 16 | # Linux/BSD |
|
| 17 | 17 | CFLAGS = -g -Wall -O2 -I. -I${PREFIX}/include -I/usr/include -I${X11INC} \ |
| 20 | 20 | const char *xlock[] = { "xlock", NULL }; |
|
| 21 | 21 | ||
| 22 | 22 | static Key key[] = { |
|
| 23 | - | { Mod1Mask, XK_Return, zoom, { 0 } }, |
|
| 24 | - | { Mod1Mask, XK_t, spawn, { .argv = term } }, |
|
| 23 | + | { Mod1Mask, XK_Return, spawn, { .argv = term } }, |
|
| 25 | 24 | { Mod1Mask, XK_w, spawn, { .argv = browse } }, |
|
| 26 | 25 | { Mod1Mask, XK_l, spawn, { .argv = xlock } }, |
|
| 27 | 26 | { Mod1Mask, XK_k, prevc, { 0 } }, |
|
| 33 | 32 | { Mod1Mask, XK_3, view, { .i = Twww } }, |
|
| 34 | 33 | { Mod1Mask, XK_4, view, { .i = Twork } }, |
|
| 35 | 34 | { Mod1Mask, XK_space, tiling, { 0 } }, |
|
| 35 | + | { Mod1Mask | ShiftMask, XK_Return, zoom, { 0 } }, |
|
| 36 | 36 | { Mod1Mask | ShiftMask, XK_space, floating, { 0 } }, |
|
| 37 | 37 | { Mod1Mask | ShiftMask, XK_0, tag, { .i = Tscratch } }, |
|
| 38 | 38 | { Mod1Mask | ShiftMask, XK_1, tag, { .i = Tdev } }, |
|
| 48 | 48 | void |
|
| 49 | 49 | update_keys(void) |
|
| 50 | 50 | { |
|
| 51 | - | unsigned int i, len; |
|
| 51 | + | static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0; |
|
| 52 | + | unsigned int i; |
|
| 52 | 53 | KeyCode code; |
|
| 53 | 54 | ||
| 54 | - | len = sizeof(key) / sizeof(key[0]); |
|
| 55 | 55 | for(i = 0; i < len; i++) { |
|
| 56 | 56 | code = XKeysymToKeycode(dpy, key[i].keysym); |
|
| 57 | 57 | XUngrabKey(dpy, code, key[i].mod, root); |
|
| 63 | 63 | keypress(XEvent *e) |
|
| 64 | 64 | { |
|
| 65 | 65 | XKeyEvent *ev = &e->xkey; |
|
| 66 | - | unsigned int i, len; |
|
| 66 | + | static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0; |
|
| 67 | + | unsigned int i; |
|
| 67 | 68 | KeySym keysym; |
|
| 68 | 69 | ||
| 69 | 70 | keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); |
|
| 70 | - | len = sizeof(key) / sizeof(key[0]); |
|
| 71 | 71 | for(i = 0; i < len; i++) |
|
| 72 | 72 | if((keysym == key[i].keysym) && (key[i].mod == ev->state)) { |
|
| 73 | 73 | if(key[i].func) |
|
| 7 | 7 | ||
| 8 | 8 | /********** CUSTOMIZE **********/ |
|
| 9 | 9 | ||
| 10 | - | #define FONT "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*" |
|
| 11 | - | #define BGCOLOR "DarkSlateGrey" |
|
| 12 | - | #define FGCOLOR "LightSteelBlue" |
|
| 13 | - | #define BORDERCOLOR "SlateGray" |
|
| 14 | - | #define WM_PROTOCOL_DELWIN 1 |
|
| 10 | + | #define FONT "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*" |
|
| 11 | + | #define BGCOLOR "#666699" |
|
| 12 | + | #define FGCOLOR "#ffffff" |
|
| 13 | + | #define BORDERCOLOR "#9999CC" |
|
| 14 | + | #define MASTERW 52 /* percent */ |
|
| 15 | + | #define WM_PROTOCOL_DELWIN 1 |
|
| 15 | 16 | ||
| 16 | 17 | /* tags */ |
|
| 17 | 18 | enum { Tscratch, Tdev, Tirc, Twww, Twork, TLast }; |
|
| 18 | 19 | ||
| 19 | 20 | /********** CUSTOMIZE **********/ |
|
| 20 | 21 | ||
| 22 | + | typedef union Arg Arg; |
|
| 21 | 23 | typedef struct DC DC; |
|
| 22 | 24 | typedef struct Client Client; |
|
| 23 | 25 | typedef struct Fnt Fnt; |
|
| 24 | 26 | typedef struct Key Key; |
|
| 25 | - | typedef union Arg Arg; |
|
| 27 | + | typedef struct Rule Rule; |
|
| 26 | 28 | ||
| 27 | 29 | union Arg { |
|
| 28 | 30 | const char **argv; |
|
| 71 | 73 | Client *revert; |
|
| 72 | 74 | }; |
|
| 73 | 75 | ||
| 76 | + | struct Rule { |
|
| 77 | + | const char *class; |
|
| 78 | + | const char *instance; |
|
| 79 | + | char *tags[TLast]; |
|
| 80 | + | }; |
|
| 81 | + | ||
| 74 | 82 | struct Key { |
|
| 75 | 83 | unsigned long mod; |
|
| 76 | 84 | KeySym keysym; |
|
| 85 | 93 | extern Bool running, issel; |
|
| 86 | 94 | extern void (*handler[LASTEvent]) (XEvent *); |
|
| 87 | 95 | ||
| 88 | - | extern int tsel, screen, sx, sy, sw, sh, th; |
|
| 89 | - | extern char stext[1024], *tags[TLast]; |
|
| 96 | + | extern int tsel, screen, sx, sy, sw, sh, mw, th; |
|
| 97 | + | extern char *tags[TLast]; |
|
| 90 | 98 | ||
| 91 | 99 | extern DC dc; |
|
| 92 | 100 | extern Client *clients, *sel; |
|
| 33 | 33 | Bool running = True; |
|
| 34 | 34 | Bool issel; |
|
| 35 | 35 | ||
| 36 | - | char stext[1024]; |
|
| 37 | 36 | int tsel = Tdev; /* default tag */ |
|
| 38 | - | int screen, sx, sy, sw, sh, th; |
|
| 37 | + | int screen, sx, sy, sw, sh, mw, th; |
|
| 39 | 38 | ||
| 40 | 39 | DC dc = {0}; |
|
| 41 | 40 | Client *clients = NULL; |
|
| 223 | 222 | sx = sy = 0; |
|
| 224 | 223 | sw = DisplayWidth(dpy, screen); |
|
| 225 | 224 | sh = DisplayHeight(dpy, screen); |
|
| 225 | + | mw = (sw * MASTERW) / 100; |
|
| 226 | 226 | issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); |
|
| 227 | 227 | ||
| 228 | 228 | XSetErrorHandler(0); |
|