dwm

[fork] dynamic window manager
Log | Files | Refs | README | LICENSE

commit c47da143bdf5b4e3924a411f42648d4b3e86ff00
parent b72588746f3d1548283ca98f90961b4f8c2e2800
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Thu, 13 Jul 2006 17:09:35 +0200

implemented tagging a client

Diffstat:
Mclient.c | 170++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mdev.c | 27++++++++++++++++-----------
Mdwm.h | 30+++++++++++++++++++-----------
Mmain.c | 11++++++-----
Mutil.c | 3++-
5 files changed, 156 insertions(+), 85 deletions(-)

diff --git a/client.c b/client.c @@ -11,44 +11,76 @@ #include "dwm.h" -static void (*arrange)(void *) = floating; +static void (*arrange)(Arg *) = floating; + +static Client * +next(Client *c) +{ + for(c = c->next; c && !c->tags[tsel]; c = c->next); + return c; +} + +static Client * +prev(Client *c) +{ + for(c = c->prev; c && !c->tags[tsel]; c = c->prev); + return c; +} void -max(void *aux) +max(Arg *arg) { - if(!stack) + if(!csel) return; - stack->x = sx; - stack->y = sy; - stack->w = sw - 2 * stack->border; - stack->h = sh - 2 * stack->border; - craise(stack); - resize(stack); + csel->x = sx; + csel->y = sy; + csel->w = sw - 2 * csel->border; + csel->h = sh - 2 * csel->border; + craise(csel); + resize(csel); discard_events(EnterWindowMask); } void -floating(void *aux) +tag(Arg *arg) +{ + if(!csel) + return; + + if(arg->i == tsel) + return; + + if(csel->tags[arg->i]) + csel->tags[arg->i] = NULL; /* toggle tag */ + else + csel->tags[arg->i] = tags[arg->i]; + arrange(NULL); +} + +void +floating(Arg *arg) { Client *c; arrange = floating; - for(c = stack; c; c = c->snext) + if(!csel) + return; + for(c = csel; c; c = next(c)) resize(c); discard_events(EnterWindowMask); } void -tiling(void *aux) +tiling(Arg *arg) { Client *c; int n, cols, rows, gw, gh, i, j; float rt, fd; arrange = tiling; - if(!clients) + if(!csel) return; - for(n = 0, c = clients; c; c = c->next, n++); + for(n = 0, c = csel; c; c = next(c), n++); rt = sqrt(n); if(modff(rt, &fd) < 0.5) rows = floor(rt); @@ -62,7 +94,7 @@ tiling(void *aux) gw = (sw - 2) / cols; gh = (sh - 2) / rows; - for(i = j = 0, c = clients; c; c = c->next) { + for(i = j = 0, c = csel; c; c = next(c)) { c->x = i * gw; c->y = j * gh; c->w = gw; @@ -77,28 +109,44 @@ tiling(void *aux) } void -sel(void *aux) +prevc(Arg *arg) { - const char *arg = aux; - Client *c = NULL; + Client *c; - if(!arg || !stack) + if(!csel) return; - if(!strncmp(arg, "next", 5)) - c = stack->snext ? stack->snext : stack; - else if(!strncmp(arg, "prev", 5)) - for(c = stack; c && c->snext; c = c->snext); - if(!c) - c = stack; - craise(c); - XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); - focus(c); + + if(!(c = prev(csel))) + c = prev(cend); + if(c) { + craise(c); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); + focus(c); + } +} + +void +nextc(Arg *arg) +{ + Client *c; + + if(!csel) + return; + + if(!(c = next(csel))) + c = next(cstart); + + if(c) { + craise(c); + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); + focus(c); + } } void -ckill(void *aux) +ckill(Arg *arg) { - Client *c = stack; + Client *c = csel; if(!c) return; @@ -208,19 +256,12 @@ lower(Client *c) void focus(Client *c) { - Client **l, *old; - - old = stack; - for(l = &stack; *l && *l != c; l = &(*l)->snext); - if(*l) - *l = c->snext; - c->snext = stack; - stack = c; - if(old && old != c) { - XSetWindowBorder(dpy, old->win, dc.bg); - XMapWindow(dpy, old->title); - draw_client(old); + if(csel && csel != c) { + XSetWindowBorder(dpy, csel->win, dc.bg); + XMapWindow(dpy, csel->title); + draw_client(csel); } + csel = c; XUnmapWindow(dpy, c->title); XSetWindowBorder(dpy, c->win, dc.fg); draw_client(c); @@ -232,7 +273,7 @@ focus(Client *c) void manage(Window w, XWindowAttributes *wa) { - Client *c, **l; + Client *c; XSetWindowAttributes twa; c = emallocz(sizeof(Client)); @@ -258,9 +299,15 @@ manage(Window w, XWindowAttributes *wa) CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); update_name(c); - for(l=&clients; *l; l=&(*l)->next); - c->next = *l; /* *l == nil */ - *l = c; + + if(!cstart) + cstart = cend = c; + else { + cend->next = c; + c->prev = cend; + cend = c; + } + XSetWindowBorderWidth(dpy, c->win, 1); XMapRaised(dpy, c->win); XMapRaised(dpy, c->title); @@ -373,33 +420,42 @@ 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); - for(l=&clients; *l && *l != c; l=&(*l)->next); - *l = c->next; - for(l=&stack; *l && *l != c; l=&(*l)->snext); - *l = c->snext; + 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; + free(c); XFlush(dpy); XSetErrorHandler(error_handler); XUngrabServer(dpy); arrange(NULL); - if(stack) - focus(stack); + if(csel) + focus(csel); } Client * gettitle(Window w) { Client *c; - for(c = clients; c; c = c->next) + for(c = cstart; c; c = c->next) if(c->title == w) return c; return NULL; @@ -409,7 +465,7 @@ Client * getclient(Window w) { Client *c; - for(c = clients; c; c = c->next) + for(c = cstart; c; c = c->next) if(c->win == w) return c; return NULL; @@ -419,7 +475,7 @@ void draw_client(Client *c) { int i; - if(c == stack) + if(c == csel) return; dc.x = dc.y = 0; diff --git a/dev.c b/dev.c @@ -20,16 +20,21 @@ const char *browse[] = { "firefox", NULL }; const char *xlock[] = { "xlock", NULL }; static Key key[] = { - { Mod1Mask, XK_Return, (void (*)(void *))spawn, term }, - { Mod1Mask, XK_w, (void (*)(void *))spawn, browse }, - { Mod1Mask, XK_l, (void (*)(void *))spawn, xlock }, - { Mod1Mask, XK_k, sel, "prev" }, - { Mod1Mask, XK_j, sel, "next" }, - { Mod1Mask, XK_t, tiling, NULL }, - { Mod1Mask, XK_f, floating, NULL }, - { Mod1Mask, XK_m, max, NULL }, - { Mod1Mask | ShiftMask, XK_c, ckill, NULL }, - { Mod1Mask | ShiftMask, XK_q, quit, NULL }, + { Mod1Mask, XK_Return, 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 | ShiftMask, XK_c, ckill, { 0 } }, + { Mod1Mask | ShiftMask, XK_q, quit, { 0 } }, }; /********** CUSTOMIZE **********/ @@ -60,7 +65,7 @@ keypress(XEvent *e) for(i = 0; i < len; i++) if((keysym == key[i].keysym) && (key[i].mod == ev->state)) { if(key[i].func) - key[i].func(key[i].aux); + key[i].func(&key[i].arg); return; } } diff --git a/dwm.h b/dwm.h @@ -22,6 +22,12 @@ typedef struct DC DC; typedef struct Client Client; typedef struct Fnt Fnt; typedef struct Key Key; +typedef union Arg Arg; + +union Arg { + const char **argv; + int i; +}; /* atoms */ enum { WMProtocols, WMDelete, WMLast }; @@ -62,14 +68,14 @@ struct Client { Window trans; Window title; Client *next; - Client *snext; + Client *prev; }; struct Key { unsigned long mod; KeySym keysym; - void (*func)(void *aux); - void *aux; + void (*func)(Arg *arg); + Arg arg; }; extern Display *dpy; @@ -83,7 +89,7 @@ extern int tsel, screen, sx, sy, sw, sh, th; extern char stext[1024], *tags[TLast]; extern DC dc; -extern Client *clients, *stack; +extern Client *cstart, *cend, *csel; /* client.c */ extern void manage(Window w, XWindowAttributes *wa); @@ -97,11 +103,13 @@ extern void update_size(Client *c); extern Client *gettitle(Window w); extern void craise(Client *c); extern void lower(Client *c); -extern void ckill(void *aux); -extern void sel(void *aux); -extern void max(void *aux); -extern void floating(void *aux); -extern void tiling(void *aux); +extern void ckill(Arg *arg); +extern void nextc(Arg *arg); +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 gravitate(Client *c, Bool invert); /* draw.c */ @@ -125,7 +133,7 @@ extern void mmove(Client *c); extern int error_handler(Display *dsply, XErrorEvent *e); extern void send_message(Window w, Atom a, long value); extern int win_proto(Window w); -extern void quit(void *aux); +extern void quit(Arg *arg); /* util.c */ extern void error(const char *errstr, ...); @@ -133,5 +141,5 @@ extern void *emallocz(unsigned int size); extern void *emalloc(unsigned int size); extern void *erealloc(void *ptr, unsigned int size); extern char *estrdup(const char *str); -extern void spawn(char *argv[]); +extern void spawn(Arg *arg); extern void swap(void **p1, void **p2); diff --git a/main.c b/main.c @@ -38,8 +38,9 @@ int tsel = Tdev; /* default tag */ int screen, sx, sy, sw, sh, th; DC dc = {0}; -Client *clients = NULL; -Client *stack = NULL; +Client *cstart = NULL; +Client *cend = NULL; +Client *csel = NULL; static Bool other_wm_running; static const char version[] = @@ -168,13 +169,13 @@ startup_error_handler(Display *dpy, XErrorEvent *error) static void cleanup() { - while(clients) - unmanage(clients); + while(csel) + unmanage(csel); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); } void -quit(void *aux) +quit(Arg *arg) { running = False; } diff --git a/util.c b/util.c @@ -75,8 +75,9 @@ swap(void **p1, void **p2) } void -spawn(char *argv[]) +spawn(Arg *arg) { + char **argv = (char **)arg->argv; if(!argv || !argv[0]) return; if(fork() == 0) {