| tseveral other additions/fixes, dwm is quite usable already - dwm - [fork] cust… | |
| git clone git://src.adamsgaard.dk/dwm | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| commit efa7e514012865fcb3e9ea6e7d5b5c87d84353e5 | |
| parent c47da143bdf5b4e3924a411f42648d4b3e86ff00 | |
| Author: Anselm R. Garbe <[email protected]> | |
| Date: Thu, 13 Jul 2006 18:21:38 +0200 | |
| several other additions/fixes, dwm is quite usable already | |
| Diffstat: | |
| M client.c | 235 ++++++++++++++++++-----------… | |
| M dev.c | 22 ++++++++++++++-------- | |
| M dwm.h | 8 +++++--- | |
| M main.c | 11 ++++++----- | |
| 4 files changed, 165 insertions(+), 111 deletions(-) | |
| --- | |
| diff --git a/client.c b/client.c | |
| t@@ -13,60 +13,105 @@ | |
| static void (*arrange)(Arg *) = floating; | |
| +static void | |
| +center(Client *c) | |
| +{ | |
| + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); | |
| +} | |
| + | |
| static Client * | |
| next(Client *c) | |
| { | |
| - for(c = c->next; c && !c->tags[tsel]; c = c->next); | |
| + for(; c && !c->tags[tsel]; c = c->next); | |
| return c; | |
| } | |
| -static Client * | |
| -prev(Client *c) | |
| +void | |
| +zoom(Arg *arg) | |
| { | |
| - for(c = c->prev; c && !c->tags[tsel]; c = c->prev); | |
| - return c; | |
| + Client **l; | |
| + | |
| + if(!sel) | |
| + return; | |
| + | |
| + for(l = &clients; *l && *l != sel; l = &(*l)->next); | |
| + *l = sel->next; | |
| + | |
| + sel->next = clients; /* pop */ | |
| + clients = sel; | |
| + arrange(NULL); | |
| + center(sel); | |
| + focus(sel); | |
| } | |
| void | |
| max(Arg *arg) | |
| { | |
| - if(!csel) | |
| + if(!sel) | |
| return; | |
| - csel->x = sx; | |
| - csel->y = sy; | |
| - csel->w = sw - 2 * csel->border; | |
| - csel->h = sh - 2 * csel->border; | |
| - craise(csel); | |
| - resize(csel); | |
| + sel->x = sx; | |
| + sel->y = sy; | |
| + sel->w = sw - 2 * sel->border; | |
| + sel->h = sh - 2 * sel->border; | |
| + craise(sel); | |
| + resize(sel); | |
| discard_events(EnterWindowMask); | |
| } | |
| void | |
| +view(Arg *arg) | |
| +{ | |
| + tsel = arg->i; | |
| + arrange(NULL); | |
| +} | |
| + | |
| +void | |
| tag(Arg *arg) | |
| { | |
| - if(!csel) | |
| + int i, n; | |
| + if(!sel) | |
| return; | |
| - if(arg->i == tsel) | |
| - return; | |
| + if(arg->i == tsel) { | |
| + for(n = i = 0; i < TLast; i++) | |
| + if(sel->tags[i]) | |
| + n++; | |
| + if(n < 2) | |
| + return; | |
| + } | |
| - if(csel->tags[arg->i]) | |
| - csel->tags[arg->i] = NULL; /* toggle tag */ | |
| + if(sel->tags[arg->i]) | |
| + sel->tags[arg->i] = NULL; /* toggle tag */ | |
| else | |
| - csel->tags[arg->i] = tags[arg->i]; | |
| + sel->tags[arg->i] = tags[arg->i]; | |
| arrange(NULL); | |
| } | |
| +static void | |
| +ban_client(Client *c) | |
| +{ | |
| + XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); | |
| + XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty); | |
| +} | |
| + | |
| void | |
| floating(Arg *arg) | |
| { | |
| Client *c; | |
| arrange = floating; | |
| - if(!csel) | |
| - return; | |
| - for(c = csel; c; c = next(c)) | |
| - resize(c); | |
| + for(c = clients; c; c = c->next) { | |
| + if(c->tags[tsel]) | |
| + resize(c); | |
| + else | |
| + ban_client(c); | |
| + } | |
| + if(sel && !sel->tags[tsel]) { | |
| + if((sel = next(clients))) { | |
| + craise(sel); | |
| + focus(sel); | |
| + } | |
| + } | |
| discard_events(EnterWindowMask); | |
| } | |
| t@@ -78,31 +123,43 @@ tiling(Arg *arg) | |
| float rt, fd; | |
| arrange = tiling; | |
| - if(!csel) | |
| - return; | |
| - for(n = 0, c = csel; c; c = next(c), n++); | |
| - rt = sqrt(n); | |
| - if(modff(rt, &fd) < 0.5) | |
| - rows = floor(rt); | |
| - else | |
| - rows = ceil(rt); | |
| - if(rows * rows < n) | |
| - cols = rows + 1; | |
| + for(n = 0, c = clients; c; c = next(c->next), n++); | |
| + if(n) { | |
| + rt = sqrt(n); | |
| + if(modff(rt, &fd) < 0.5) | |
| + rows = floor(rt); | |
| + else | |
| + rows = ceil(rt); | |
| + if(rows * rows < n) | |
| + cols = rows + 1; | |
| + else | |
| + cols = rows; | |
| + | |
| + gw = (sw - 2) / cols; | |
| + gh = (sh - 2) / rows; | |
| + } | |
| else | |
| - cols = rows; | |
| - | |
| - gw = (sw - 2) / cols; | |
| - gh = (sh - 2) / rows; | |
| - | |
| - for(i = j = 0, c = csel; c; c = next(c)) { | |
| - c->x = i * gw; | |
| - c->y = j * gh; | |
| - c->w = gw; | |
| - c->h = gh; | |
| - resize(c); | |
| - if(++i == cols) { | |
| - j++; | |
| - i = 0; | |
| + cols = rows = gw = gh = 0; | |
| + | |
| + for(i = j = 0, c = clients; c; c = c->next) { | |
| + if(c->tags[tsel]) { | |
| + c->x = i * gw; | |
| + c->y = j * gh; | |
| + c->w = gw; | |
| + c->h = gh; | |
| + resize(c); | |
| + if(++i == cols) { | |
| + j++; | |
| + i = 0; | |
| + } | |
| + } | |
| + else | |
| + ban_client(c); | |
| + } | |
| + if(sel && !sel->tags[tsel]) { | |
| + if((sel = next(clients))) { | |
| + craise(sel); | |
| + focus(sel); | |
| } | |
| } | |
| discard_events(EnterWindowMask); | |
| t@@ -113,14 +170,12 @@ prevc(Arg *arg) | |
| { | |
| Client *c; | |
| - if(!csel) | |
| + if(!sel) | |
| return; | |
| - if(!(c = prev(csel))) | |
| - c = prev(cend); | |
| - if(c) { | |
| + if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) { | |
| craise(c); | |
| - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2… | |
| + center(c); | |
| focus(c); | |
| } | |
| } | |
| t@@ -130,15 +185,15 @@ nextc(Arg *arg) | |
| { | |
| Client *c; | |
| - if(!csel) | |
| + if(!sel) | |
| return; | |
| - if(!(c = next(csel))) | |
| - c = next(cstart); | |
| - | |
| + if(!(c = next(sel->next))) | |
| + c = next(clients); | |
| if(c) { | |
| craise(c); | |
| - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2… | |
| + center(c); | |
| + c->revert = sel; | |
| focus(c); | |
| } | |
| } | |
| t@@ -146,14 +201,12 @@ nextc(Arg *arg) | |
| void | |
| ckill(Arg *arg) | |
| { | |
| - Client *c = csel; | |
| - | |
| - if(!c) | |
| + if(!sel) | |
| return; | |
| - if(c->proto & WM_PROTOCOL_DELWIN) | |
| - send_message(c->win, wm_atom[WMProtocols], wm_atom[WMDelete]); | |
| + if(sel->proto & WM_PROTOCOL_DELWIN) | |
| + send_message(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]… | |
| else | |
| - XKillClient(dpy, c->win); | |
| + XKillClient(dpy, sel->win); | |
| } | |
| static void | |
| t@@ -256,12 +309,12 @@ lower(Client *c) | |
| void | |
| focus(Client *c) | |
| { | |
| - if(csel && csel != c) { | |
| - XSetWindowBorder(dpy, csel->win, dc.bg); | |
| - XMapWindow(dpy, csel->title); | |
| - draw_client(csel); | |
| + if(sel && sel != c) { | |
| + XSetWindowBorder(dpy, sel->win, dc.bg); | |
| + XMapWindow(dpy, sel->title); | |
| + draw_client(sel); | |
| } | |
| - csel = c; | |
| + sel = c; | |
| XUnmapWindow(dpy, c->title); | |
| XSetWindowBorder(dpy, c->win, dc.fg); | |
| draw_client(c); | |
| t@@ -273,7 +326,7 @@ focus(Client *c) | |
| void | |
| manage(Window w, XWindowAttributes *wa) | |
| { | |
| - Client *c; | |
| + Client *c, **l; | |
| XSetWindowAttributes twa; | |
| c = emallocz(sizeof(Client)); | |
| t@@ -284,6 +337,7 @@ manage(Window w, XWindowAttributes *wa) | |
| c->h = wa->height; | |
| c->th = th; | |
| c->border = 1; | |
| + c->proto = win_proto(c->win); | |
| update_size(c); | |
| XSelectInput(dpy, c->win, | |
| StructureNotifyMask | PropertyChangeMask | EnterWindow… | |
| t@@ -300,13 +354,9 @@ manage(Window w, XWindowAttributes *wa) | |
| update_name(c); | |
| - if(!cstart) | |
| - cstart = cend = c; | |
| - else { | |
| - cend->next = c; | |
| - c->prev = cend; | |
| - cend = c; | |
| - } | |
| + for(l = &clients; *l; l = &(*l)->next); | |
| + c->next = *l; /* *l == nil */ | |
| + *l = c; | |
| XSetWindowBorderWidth(dpy, c->win, 1); | |
| XMapRaised(dpy, c->win); | |
| t@@ -318,7 +368,7 @@ manage(Window w, XWindowAttributes *wa) | |
| XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask, | |
| GrabModeAsync, GrabModeSync, None, None); | |
| arrange(NULL); | |
| - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); | |
| + center(c); | |
| focus(c); | |
| } | |
| t@@ -420,26 +470,21 @@ dummy_error_handler(Display *dsply, XErrorEvent *err) | |
| void | |
| unmanage(Client *c) | |
| { | |
| + Client **l; | |
| + | |
| XGrabServer(dpy); | |
| XSetErrorHandler(dummy_error_handler); | |
| XUngrabButton(dpy, AnyButton, AnyModifier, c->win); | |
| XDestroyWindow(dpy, c->title); | |
| - if(c->prev) { | |
| - c->prev->next = c->next; | |
| - if(csel == c) | |
| - csel = c->prev; | |
| - } | |
| - if(c->next) { | |
| - c->next->prev = c->prev; | |
| - if(csel == c) | |
| - csel = c->next; | |
| - } | |
| - if(cstart == c) | |
| - cstart = c->next; | |
| - if(cend == c) | |
| - cend = c->prev; | |
| + for(l = &clients; *l && *l != c; l = &(*l)->next); | |
| + *l = c->next; | |
| + for(l = &clients; *l; l = &(*l)->next) | |
| + if((*l)->revert == c) | |
| + (*l)->revert = NULL; | |
| + if(sel == c) | |
| + sel = sel->revert ? sel->revert : clients; | |
| free(c); | |
| t@@ -447,15 +492,15 @@ unmanage(Client *c) | |
| XSetErrorHandler(error_handler); | |
| XUngrabServer(dpy); | |
| arrange(NULL); | |
| - if(csel) | |
| - focus(csel); | |
| + if(sel) | |
| + focus(sel); | |
| } | |
| Client * | |
| gettitle(Window w) | |
| { | |
| Client *c; | |
| - for(c = cstart; c; c = c->next) | |
| + for(c = clients; c; c = c->next) | |
| if(c->title == w) | |
| return c; | |
| return NULL; | |
| t@@ -465,7 +510,7 @@ Client * | |
| getclient(Window w) | |
| { | |
| Client *c; | |
| - for(c = cstart; c; c = c->next) | |
| + for(c = clients; c; c = c->next) | |
| if(c->win == w) | |
| return c; | |
| return NULL; | |
| t@@ -475,7 +520,7 @@ void | |
| draw_client(Client *c) | |
| { | |
| int i; | |
| - if(c == csel) | |
| + if(c == sel) | |
| return; | |
| dc.x = dc.y = 0; | |
| diff --git a/dev.c b/dev.c | |
| t@@ -20,19 +20,25 @@ const char *browse[] = { "firefox", NULL }; | |
| const char *xlock[] = { "xlock", NULL }; | |
| static Key key[] = { | |
| - { Mod1Mask, XK_Return, spawn, { .argv = term } }, | |
| + { Mod1Mask, XK_Return, zoom, { 0 } }, | |
| + { Mod1Mask, XK_t, spawn, { .argv = term } }, | |
| { Mod1Mask, XK_w, spawn, { .argv = browse } }, | |
| { Mod1Mask, XK_l, spawn, { .argv = xlock } }, | |
| { Mod1Mask, XK_k, prevc, { 0 } }, | |
| { Mod1Mask, XK_j, nextc, { 0 } }, | |
| - { Mod1Mask, XK_t, tiling, { 0 } }, | |
| - { Mod1Mask, XK_f, floating, { 0 } }, | |
| { Mod1Mask, XK_m, max, { 0 } }, | |
| - { Mod1Mask, XK_0, tag, { .i = Tscratch } }, | |
| - { Mod1Mask, XK_1, tag, { .i = Tdev } }, | |
| - { Mod1Mask, XK_2, tag, { .i = Tirc } }, | |
| - { Mod1Mask, XK_3, tag, { .i = Twww } }, | |
| - { Mod1Mask, XK_4, tag, { .i = Twork } }, | |
| + { Mod1Mask, XK_0, view, { .i = Tscratch } }, | |
| + { Mod1Mask, XK_1, view, { .i = Tdev } }, | |
| + { Mod1Mask, XK_2, view, { .i = Tirc } }, | |
| + { Mod1Mask, XK_3, view, { .i = Twww } }, | |
| + { Mod1Mask, XK_4, view, { .i = Twork } }, | |
| + { Mod1Mask, XK_space, tiling, { 0 } }, | |
| + { Mod1Mask | ShiftMask, XK_space, floating, { 0 } }, | |
| + { Mod1Mask | ShiftMask, XK_0, tag, { .i = Tscratch } }, | |
| + { Mod1Mask | ShiftMask, XK_1, tag, { .i = Tdev } }, | |
| + { Mod1Mask | ShiftMask, XK_2, tag, { .i = Tirc } }, | |
| + { Mod1Mask | ShiftMask, XK_3, tag, { .i = Twww } }, | |
| + { Mod1Mask | ShiftMask, XK_4, tag, { .i = Twork } }, | |
| { Mod1Mask | ShiftMask, XK_c, ckill, { 0 } }, | |
| { Mod1Mask | ShiftMask, XK_q, quit, { 0 } }, | |
| }; | |
| diff --git a/dwm.h b/dwm.h | |
| t@@ -68,7 +68,7 @@ struct Client { | |
| Window trans; | |
| Window title; | |
| Client *next; | |
| - Client *prev; | |
| + Client *revert; | |
| }; | |
| struct Key { | |
| t@@ -89,7 +89,7 @@ extern int tsel, screen, sx, sy, sw, sh, th; | |
| extern char stext[1024], *tags[TLast]; | |
| extern DC dc; | |
| -extern Client *cstart, *cend, *csel; | |
| +extern Client *clients, *sel; | |
| /* client.c */ | |
| extern void manage(Window w, XWindowAttributes *wa); | |
| t@@ -109,7 +109,9 @@ extern void prevc(Arg *arg); | |
| extern void max(Arg *arg); | |
| extern void floating(Arg *arg); | |
| extern void tiling(Arg *arg); | |
| -void tag(Arg *arg); | |
| +extern void tag(Arg *arg); | |
| +extern void view(Arg *arg); | |
| +extern void zoom(Arg *arg); | |
| extern void gravitate(Client *c, Bool invert); | |
| /* draw.c */ | |
| diff --git a/main.c b/main.c | |
| t@@ -38,9 +38,8 @@ int tsel = Tdev; /* default tag */ | |
| int screen, sx, sy, sw, sh, th; | |
| DC dc = {0}; | |
| -Client *cstart = NULL; | |
| -Client *cend = NULL; | |
| -Client *csel = NULL; | |
| +Client *clients = NULL; | |
| +Client *sel = NULL; | |
| static Bool other_wm_running; | |
| static const char version[] = | |
| t@@ -169,8 +168,10 @@ startup_error_handler(Display *dpy, XErrorEvent *error) | |
| static void | |
| cleanup() | |
| { | |
| - while(csel) | |
| - unmanage(csel); | |
| + while(sel) { | |
| + resize(sel); | |
| + unmanage(sel); | |
| + } | |
| XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); | |
| } | |