URI: 
       rearranged - dwm - dynamic window manager
  HTML git clone https://git.parazyd.org/dwm
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 29355bd38284ed9aec8d3ffabde61db73947c9f9
   DIR parent 91a1f6926e2594156219c1caaf4729c5d86498a5
  HTML Author: Anselm R. Garbe <garbeam@wmii.de>
       Date:   Fri, 14 Jul 2006 22:33:38 +0200
       
       rearranged
       
       Diffstat:
         M Makefile                            |       2 +-
         D bar.c                               |      54 -------------------------------
         M client.c                            |     230 +------------------------------
         D dev.c                               |     151 -------------------------------
         M draw.c                              |      67 ++++++++++++++++++++++++++++++-
         M dwm.h                               |      31 ++++++++++++-------------------
         M event.c                             |      96 +++++++++++++++++++++++++++----
         A key.c                               |     192 +++++++++++++++++++++++++++++++
         M main.c                              |       2 +-
         A screen.c                            |     100 +++++++++++++++++++++++++++++++
       
       10 files changed, 461 insertions(+), 464 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       @@ -3,7 +3,7 @@
        
        include config.mk
        
       -SRC = bar.c client.c dev.c draw.c event.c main.c util.c
       +SRC = client.c draw.c event.c key.c main.c screen.c util.c
        OBJ = ${SRC:.c=.o}
        MAN1 = dwm.1 
        BIN = dwm
   DIR diff --git a/bar.c b/bar.c
       @@ -1,54 +0,0 @@
       -/*
       - * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
       - * See LICENSE file for license details.
       - */
       -
       -#include "dwm.h"
       -
       -void
       -barclick(XButtonPressedEvent *e)
       -{
       -        int x = 0;
       -        Arg a;
       -        for(a.i = 0; a.i < TLast; a.i++) {
       -                x += textw(tags[a.i]) + dc.font.height;
       -                if(e->x < x) {
       -                        view(&a);
       -                        return;
       -                }
       -        }
       -}
       -
       -void
       -draw_bar()
       -{
       -        int i, modw;
       -        char *mode = arrange == tiling ? "#" : "~";
       -
       -        dc.x = dc.y = 0;
       -        dc.w = bw;
       -        drawtext(NULL, False, False);
       -
       -        modw = textw(mode) + dc.font.height;
       -        dc.w = 0;
       -        for(i = 0; i < TLast; i++) {
       -                dc.x += dc.w;
       -                dc.w = textw(tags[i]) + dc.font.height;
       -                drawtext(tags[i], i == tsel, True);
       -        }
       -        if(sel) {
       -                dc.x += dc.w;
       -                dc.w = textw(sel->name) + dc.font.height;
       -                drawtext(sel->name, True, True);
       -        }
       -        dc.w = textw(stext) + dc.font.height;
       -        dc.x = bx + bw - dc.w - modw;
       -        drawtext(stext, False, False);
       -
       -        dc.x = bx + bw - modw;
       -        dc.w = modw;
       -        drawtext(mode, True, True);
       -
       -        XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
       -        XFlush(dpy);
       -}
   DIR diff --git a/client.c b/client.c
       @@ -11,14 +11,12 @@
        
        #include "dwm.h"
        
       -void (*arrange)(Arg *) = tiling;
       -
        static Rule rule[] = {
                /* class                        instance        tags                                                floating */
                { "Firefox-bin",        "Gecko",        { [Twww] = "www" },                        False },
        };
        
       -static Client *
       +Client *
        next(Client *c)
        {
                for(; c && !c->tags[tsel]; c = c->next);
       @@ -26,202 +24,12 @@ next(Client *c)
        }
        
        void
       -zoom(Arg *arg)
       -{
       -        Client **l, *c;
       -
       -        if(!sel)
       -                return;
       -
       -        if(sel == next(clients) && sel->next)  {
       -                if((c = next(sel->next)))
       -                        sel = c;
       -        }
       -
       -        for(l = &clients; *l && *l != sel; l = &(*l)->next);
       -        *l = sel->next;
       -
       -        sel->next = clients; /* pop */
       -        clients = sel;
       -        arrange(NULL);
       -        focus(sel);
       -}
       -
       -void
       -max(Arg *arg)
       -{
       -        if(!sel)
       -                return;
       -        sel->x = sx;
       -        sel->y = sy + bh;
       -        sel->w = sw - 2 * sel->border;
       -        sel->h = sh - 2 * sel->border - bh;
       -        craise(sel);
       -        resize(sel, False);
       -}
       -
       -void
       -view(Arg *arg)
       -{
       -        Client *c;
       -
       -        tsel = arg->i;
       -        arrange(NULL);
       -
       -        for(c = clients; c; c = next(c->next))
       -                draw_client(c);
       -        draw_bar();
       -}
       -
       -void
       -tappend(Arg *arg)
       -{
       -        if(!sel)
       -                return;
       -
       -        sel->tags[arg->i] = tags[arg->i];
       -        arrange(NULL);
       -}
       -
       -void
       -ttrunc(Arg *arg)
       -{
       -        int i;
       -        if(!sel)
       -                return;
       -
       -        for(i = 0; i < TLast; i++)
       -                sel->tags[i] = NULL;
       -        tappend(arg);
       -}
       -
       -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;
       -        for(c = clients; c; c = c->next) {
       -                if(c->tags[tsel])
       -                        resize(c, True);
       -                else
       -                        ban_client(c);
       -        }
       -        if(sel && !sel->tags[tsel]) {
       -                if((sel = next(clients))) {
       -                        craise(sel);
       -                        focus(sel);
       -                }
       -        }
       -        draw_bar();
       -}
       -
       -void
       -tiling(Arg *arg)
       -{
       -        Client *c;
       -        int n, i, w, h;
       -
       -        w = sw - mw;
       -        arrange = tiling;
       -        for(n = 0, c = clients; c; c = c->next)
       -                if(c->tags[tsel] && !c->floating)
       -                        n++;
       -
       -        if(n > 1)
       -                h = (sh - bh) / (n - 1);
       -        else
       -                h = sh - bh;
       -
       -        for(i = 0, c = clients; c; c = c->next) {
       -                if(c->tags[tsel]) {
       -                        if(c->floating) {
       -                                craise(c);
       -                                resize(c, True);
       -                                continue;
       -                        }
       -                        if(n == 1) {
       -                                c->x = sx;
       -                                c->y = sy + bh;
       -                                c->w = sw - 2 * c->border;
       -                                c->h = sh - 2 * c->border - bh;
       -                        }
       -                        else if(i == 0) {
       -                                c->x = sx;
       -                                c->y = sy + bh;
       -                                c->w = mw - 2 * c->border;
       -                                c->h = sh - 2 * c->border - bh;
       -                        }
       -                        else {
       -                                c->x = sx + mw;
       -                                c->y = sy + (i - 1) * h + bh;
       -                                c->w = w - 2 * c->border;
       -                                c->h = h - 2 * c->border;
       -                        }
       -                        resize(c, False);
       -                        i++;
       -                }
       -                else
       -                        ban_client(c);
       -        }
       -        if(!sel || (sel && !sel->tags[tsel])) {
       -                if((sel = next(clients))) {
       -                        craise(sel);
       -                        focus(sel);
       -                }
       -        }
       -        draw_bar();
       -}
       -
       -void
       -prevc(Arg *arg)
       -{
       -        Client *c;
       -
       -        if(!sel)
       -                return;
       -
       -        if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
       -                craise(c);
       -                focus(c);
       -        }
       -}
       -
       -void
       -nextc(Arg *arg)
       -{
       -        Client *c;
       -   
       -        if(!sel)
       -                return;
       -
       -        if(!(c = next(sel->next)))
       -                c = next(clients);
       -        if(c) {
       -                craise(c);
       -                c->revert = sel;
       -                focus(c);
       -        }
       -}
       -
       -void
       -ckill(Arg *arg)
       -{
       -        if(!sel)
       -                return;
       -        if(sel->proto & WM_PROTOCOL_DELWIN)
       -                send_message(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
       -        else
       -                XKillClient(dpy, sel->win);
       -}
       -
        static void
        resize_title(Client *c)
        {
       @@ -230,8 +38,8 @@ resize_title(Client *c)
                c->tw = 0;
                for(i = 0; i < TLast; i++)
                        if(c->tags[i])
       -                        c->tw += textw(c->tags[i]) + dc.font.height;
       -        c->tw += textw(c->name) + dc.font.height;
       +                        c->tw += textw(c->tags[i]);
       +        c->tw += textw(c->name);
                if(c->tw > c->w)
                        c->tw = c->w + 2;
                c->tx = c->x + c->w - c->tw + 2;
       @@ -584,35 +392,3 @@ getclient(Window w)
                                return c;
                return NULL;
        }
       -
       -void
       -draw_client(Client *c)
       -{
       -        int i;
       -        if(c == sel) {
       -                draw_bar();
       -                XUnmapWindow(dpy, c->title);
       -                XSetWindowBorder(dpy, c->win, dc.fg);
       -                return;
       -        }
       -
       -        XSetWindowBorder(dpy, c->win, dc.bg);
       -        XMapWindow(dpy, c->title);
       -
       -        dc.x = dc.y = 0;
       -
       -        dc.w = 0;
       -        for(i = 0; i < TLast; i++) {
       -                if(c->tags[i]) {
       -                        dc.x += dc.w;
       -                        dc.w = textw(c->tags[i]) + dc.font.height;
       -                        drawtext(c->tags[i], False, True);
       -                }
       -        }
       -        dc.x += dc.w;
       -        dc.w = textw(c->name) + dc.font.height;
       -        drawtext(c->name, False, True);
       -        XCopyArea(dpy, dc.drawable, c->title, dc.gc,
       -                        0, 0, c->tw, c->th, 0, 0);
       -        XFlush(dpy);
       -}
   DIR diff --git a/dev.c b/dev.c
       @@ -1,151 +0,0 @@
       -/*
       - * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
       - * See LICENSE file for license details.
       - */
       -
       -#include "dwm.h"
       -
       -#include <stdlib.h>
       -#include <string.h>
       -#include <unistd.h>
       -#include <X11/keysym.h>
       -
       -/********** CUSTOMIZE **********/
       -
       -const char *term[] = { 
       -        "urxvtc", "-tr", "+sb", "-bg", "black", "-fg", "white", "-fn",
       -        "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*",NULL
       -};
       -const char *browse[] = { "firefox", NULL };
       -const char *xlock[] = { "xlock", NULL };
       -
       -static Key key[] = {
       -        /* modifier                                key                        function        arguments */
       -        { Mod1Mask,                                XK_Return,        zoom,                { 0 } },
       -        { Mod1Mask,                                XK_k,                prevc,                { 0 } },
       -        { Mod1Mask,                                XK_j,                nextc,                { 0 } }, 
       -        { Mod1Mask,                                XK_m,                max,                { 0 } }, 
       -        { Mod1Mask,                                XK_0,                view,                { .i = Tscratch } }, 
       -        { Mod1Mask,                                XK_1,                view,                { .i = Tdev } }, 
       -        { Mod1Mask,                                XK_2,                view,                { .i = Twww } }, 
       -        { Mod1Mask,                                XK_3,                view,                { .i = Twork } }, 
       -        { Mod1Mask,                                XK_space,        tiling,                { 0 } }, 
       -        { Mod1Mask|ShiftMask,        XK_space,        floating,        { 0 } }, 
       -        { Mod1Mask|ShiftMask,        XK_0,                ttrunc,                { .i = Tscratch } }, 
       -        { Mod1Mask|ShiftMask,        XK_1,                ttrunc,                { .i = Tdev } }, 
       -        { Mod1Mask|ShiftMask,        XK_2,                ttrunc,                { .i = Twww } }, 
       -        { Mod1Mask|ShiftMask,        XK_3,                ttrunc,                { .i = Twork } }, 
       -        { Mod1Mask|ShiftMask,        XK_c,                ckill,                { 0 } }, 
       -        { Mod1Mask|ShiftMask,        XK_q,                quit,                { 0 } },
       -        { Mod1Mask|ShiftMask,        XK_Return,        spawn,                { .argv = term } },
       -        { Mod1Mask|ShiftMask,        XK_w,                spawn,                { .argv = browse } },
       -        { Mod1Mask|ShiftMask,        XK_l,                spawn,                { .argv = xlock } },
       -        { ControlMask,                        XK_0,                tappend,        { .i = Tscratch } }, 
       -        { ControlMask,                        XK_1,                tappend,        { .i = Tdev } }, 
       -        { ControlMask,                        XK_2,                tappend,        { .i = Twww } }, 
       -        { ControlMask,                        XK_3,                tappend,        { .i = Twork } }, 
       -};
       -
       -/********** CUSTOMIZE **********/
       -
       -void
       -update_keys(void)
       -{
       -        static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
       -        unsigned int i;
       -        KeyCode code;
       -
       -        for(i = 0; i < len; i++) {
       -                code = XKeysymToKeycode(dpy, key[i].keysym);
       -                XUngrabKey(dpy, code, key[i].mod, root);
       -                XGrabKey(dpy, code, key[i].mod, root, True, GrabModeAsync, GrabModeAsync);
       -        }
       -}
       -
       -void
       -keypress(XEvent *e)
       -{
       -        XKeyEvent *ev = &e->xkey;
       -        static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
       -        unsigned int i;
       -        KeySym keysym;
       -
       -        keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
       -        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].arg);
       -                        return;
       -                }
       -}
       -
       -#define ButtonMask      (ButtonPressMask | ButtonReleaseMask)
       -#define MouseMask       (ButtonMask | PointerMotionMask)
       -
       -void
       -mresize(Client *c)
       -{
       -        XEvent ev;
       -        int ocx, ocy;
       -
       -        ocx = c->x;
       -        ocy = c->y;
       -        if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
       -                                None, cursor[CurResize], CurrentTime) != GrabSuccess)
       -                return;
       -        XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
       -        for(;;) {
       -                XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
       -                switch(ev.type) {
       -                default: break;
       -                case Expose:
       -                        handler[Expose](&ev);
       -                        break;
       -                case MotionNotify:
       -                        XFlush(dpy);
       -                        c->w = abs(ocx - ev.xmotion.x);
       -                        c->h = abs(ocy - ev.xmotion.y);
       -                        c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
       -                        c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
       -                        resize(c, True);
       -                        break;
       -                case ButtonRelease:
       -                        XUngrabPointer(dpy, CurrentTime);
       -                        return;
       -                }
       -        }
       -}
       -
       -void
       -mmove(Client *c)
       -{
       -        XEvent ev;
       -        int x1, y1, ocx, ocy, di;
       -        unsigned int dui;
       -        Window dummy;
       -
       -        ocx = c->x;
       -        ocy = c->y;
       -        if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
       -                                None, cursor[CurMove], CurrentTime) != GrabSuccess)
       -                return;
       -        XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
       -        for(;;) {
       -                XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
       -                switch (ev.type) {
       -                default: break;
       -                case Expose:
       -                        handler[Expose](&ev);
       -                        break;
       -                case MotionNotify:
       -                        XFlush(dpy);
       -                        c->x = ocx + (ev.xmotion.x - x1);
       -                        c->y = ocy + (ev.xmotion.y - y1);
       -                        resize(c, False);
       -                        break;
       -                case ButtonRelease:
       -                        XUngrabPointer(dpy, CurrentTime);
       -                        return;
       -                }
       -        }
       -}
   DIR diff --git a/draw.c b/draw.c
       @@ -10,6 +10,71 @@
        
        #include "dwm.h"
        
       +void
       +draw_bar()
       +{
       +        int i;
       +
       +        dc.x = dc.y = 0;
       +        dc.w = bw;
       +        drawtext(NULL, False, False);
       +
       +        if(arrange == floating) {
       +                dc.w = textw("~");
       +                drawtext("~", False, False);
       +        }
       +        else
       +                dc.w = 0;
       +        for(i = 0; i < TLast; i++) {
       +                dc.x += dc.w;
       +                dc.w = textw(tags[i]);
       +                drawtext(tags[i], i == tsel, True);
       +        }
       +        if(sel) {
       +                dc.x += dc.w;
       +                dc.w = textw(sel->name);
       +                drawtext(sel->name, True, True);
       +        }
       +        dc.w = textw(stext);
       +        dc.x = bx + bw - dc.w;
       +        drawtext(stext, False, False);
       +
       +        XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, bw, bh, 0, 0);
       +        XFlush(dpy);
       +}
       +
       +void
       +draw_client(Client *c)
       +{
       +        int i;
       +        if(c == sel) {
       +                draw_bar();
       +                XUnmapWindow(dpy, c->title);
       +                XSetWindowBorder(dpy, c->win, dc.fg);
       +                return;
       +        }
       +
       +        XSetWindowBorder(dpy, c->win, dc.bg);
       +        XMapWindow(dpy, c->title);
       +
       +        dc.x = dc.y = 0;
       +
       +        dc.w = 0;
       +        for(i = 0; i < TLast; i++) {
       +                if(c->tags[i]) {
       +                        dc.x += dc.w;
       +                        dc.w = textw(c->tags[i]);
       +                        drawtext(c->tags[i], False, True);
       +                }
       +        }
       +        dc.x += dc.w;
       +        dc.w = textw(c->name);
       +        drawtext(c->name, False, True);
       +        XCopyArea(dpy, dc.drawable, c->title, dc.gc,
       +                        0, 0, c->tw, c->th, 0, 0);
       +        XFlush(dpy);
       +}
       +
        static void
        drawborder(void)
        {
       @@ -103,7 +168,7 @@ textnw(char *text, unsigned int len)
        unsigned int
        textw(char *text)
        {
       -        return textnw(text, strlen(text));
       +        return textnw(text, strlen(text)) + dc.font.height;
        }
        
        void
   DIR diff --git a/dwm.h b/dwm.h
       @@ -94,6 +94,7 @@ extern Cursor cursor[CurLast];
        extern Bool running, issel;
        extern void (*handler[LASTEvent])(XEvent *);
        extern void (*arrange)(Arg *);
       +extern Key key[];
        
        extern int tsel, screen, sx, sy, sw, sh, bx, by, bw, bh, mw;
        extern char *tags[TLast], stext[1024];
       @@ -101,35 +102,24 @@ extern char *tags[TLast], stext[1024];
        extern DC dc;
        extern Client *clients, *sel;
        
       -/* bar.c */
       -extern void draw_bar();
       -extern void barclick(XButtonPressedEvent *e);
       -
        /* client.c */
        extern void manage(Window w, XWindowAttributes *wa);
        extern void unmanage(Client *c);
        extern Client *getclient(Window w);
        extern void focus(Client *c);
        extern void update_name(Client *c);
       -extern void draw_client(Client *c);
        extern void resize(Client *c, Bool inc);
        extern void update_size(Client *c);
        extern Client *gettitle(Window w);
        extern void craise(Client *c);
        extern void lower(Client *c);
       -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);
       -extern void ttrunc(Arg *arg);
       -extern void tappend(Arg *arg);
       -extern void view(Arg *arg);
       -extern void zoom(Arg *arg);
        extern void gravitate(Client *c, Bool invert);
       +extern void ban_client(Client *c);
       +extern Client *next(Client *c);
        
        /* draw.c */
       +extern void draw_bar();
       +extern void draw_client(Client *c);
        extern void drawtext(const char *text, Bool invert, Bool border);
        extern unsigned long initcolor(const char *colstr);
        extern void initfont(const char *fontstr);
       @@ -137,11 +127,9 @@ extern unsigned int textnw(char *text, unsigned int len);
        extern unsigned int textw(char *text);
        extern unsigned int texth(void);
        
       -/* dev.c */
       -extern void update_keys(void);
       +/* key.c */
       +extern void grabkeys();
        extern void keypress(XEvent *e);
       -extern void mresize(Client *c);
       -extern void mmove(Client *c);
        
        /* main.c */
        extern int error_handler(Display *dsply, XErrorEvent *e);
       @@ -149,6 +137,11 @@ extern void send_message(Window w, Atom a, long value);
        extern int win_proto(Window w);
        extern void quit(Arg *arg);
        
       +/* screen.c */
       +extern void floating(Arg *arg);
       +extern void tiling(Arg *arg);
       +extern void view(Arg *arg);
       +
        /* util.c */
        extern void error(const char *errstr, ...);
        extern void *emallocz(unsigned int size);
   DIR diff --git a/event.c b/event.c
       @@ -7,11 +7,15 @@
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
       +#include <unistd.h>
        #include <X11/keysym.h>
        #include <X11/Xatom.h>
        
        #include "dwm.h"
        
       +#define ButtonMask      (ButtonPressMask | ButtonReleaseMask)
       +#define MouseMask       (ButtonMask | PointerMotionMask)
       +
        /* local functions */
        static void buttonpress(XEvent *e);
        static void configurerequest(XEvent *e);
       @@ -19,7 +23,6 @@ static void destroynotify(XEvent *e);
        static void enternotify(XEvent *e);
        static void leavenotify(XEvent *e);
        static void expose(XEvent *e);
       -static void keymapnotify(XEvent *e);
        static void maprequest(XEvent *e);
        static void propertynotify(XEvent *e);
        static void unmapnotify(XEvent *e);
       @@ -32,21 +35,100 @@ void (*handler[LASTEvent]) (XEvent *) = {
                [LeaveNotify] = leavenotify,
                [Expose] = expose,
                [KeyPress] = keypress,
       -        [KeymapNotify] = keymapnotify,
                [MapRequest] = maprequest,
                [PropertyNotify] = propertynotify,
                [UnmapNotify] = unmapnotify
        };
        
        static void
       +mresize(Client *c)
       +{
       +        XEvent ev;
       +        int ocx, ocy;
       +
       +        ocx = c->x;
       +        ocy = c->y;
       +        if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
       +                                None, cursor[CurResize], CurrentTime) != GrabSuccess)
       +                return;
       +        XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
       +        for(;;) {
       +                XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
       +                switch(ev.type) {
       +                default: break;
       +                case Expose:
       +                        handler[Expose](&ev);
       +                        break;
       +                case MotionNotify:
       +                        XFlush(dpy);
       +                        c->w = abs(ocx - ev.xmotion.x);
       +                        c->h = abs(ocy - ev.xmotion.y);
       +                        c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
       +                        c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
       +                        resize(c, True);
       +                        break;
       +                case ButtonRelease:
       +                        XUngrabPointer(dpy, CurrentTime);
       +                        return;
       +                }
       +        }
       +}
       +
       +static void
       +mmove(Client *c)
       +{
       +        XEvent ev;
       +        int x1, y1, ocx, ocy, di;
       +        unsigned int dui;
       +        Window dummy;
       +
       +        ocx = c->x;
       +        ocy = c->y;
       +        if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
       +                                None, cursor[CurMove], CurrentTime) != GrabSuccess)
       +                return;
       +        XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
       +        for(;;) {
       +                XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
       +                switch (ev.type) {
       +                default: break;
       +                case Expose:
       +                        handler[Expose](&ev);
       +                        break;
       +                case MotionNotify:
       +                        XFlush(dpy);
       +                        c->x = ocx + (ev.xmotion.x - x1);
       +                        c->y = ocy + (ev.xmotion.y - y1);
       +                        resize(c, False);
       +                        break;
       +                case ButtonRelease:
       +                        XUngrabPointer(dpy, CurrentTime);
       +                        return;
       +                }
       +        }
       +}
       +
       +static void
        buttonpress(XEvent *e)
        {
       +        int x;
       +        Arg a;
                XButtonPressedEvent *ev = &e->xbutton;
                Client *c;
        
       -        if(barwin == ev->window)
       -                barclick(ev);
       +        if(barwin == ev->window) {
       +                x = (arrange == floating) ? textw("~") : 0;
       +                for(a.i = 0; a.i < TLast; a.i++) {
       +                        x += textw(tags[a.i]);
       +                        if(ev->x < x) {
       +                                view(&a);
       +                                break;
       +                        }
       +                }
       +        }
                else if((c = getclient(ev->window))) {
       +                if(arrange == tiling && !c->floating)
       +                        return;
                        craise(c);
                        switch(ev->button) {
                        default:
       @@ -150,12 +232,6 @@ expose(XEvent *e)
        }
        
        static void
       -keymapnotify(XEvent *e)
       -{
       -        update_keys();
       -}
       -
       -static void
        maprequest(XEvent *e)
        {
                XMapRequestEvent *ev = &e->xmaprequest;
   DIR diff --git a/key.c b/key.c
       @@ -0,0 +1,192 @@
       +/*
       + * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
       + * See LICENSE file for license details.
       + */
       +
       +#include <fcntl.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include <unistd.h>
       +#include <X11/keysym.h>
       +#include <X11/Xatom.h>
       +
       +#include "dwm.h"
       +
       +static void ckill(Arg *arg);
       +static void nextc(Arg *arg);
       +static void prevc(Arg *arg);
       +static void max(Arg *arg);
       +static void ttrunc(Arg *arg);
       +static void tappend(Arg *arg);
       +static void zoom(Arg *arg);
       +
       +/********** CUSTOMIZE **********/
       +
       +const char *term[] = { 
       +        "urxvtc", "-tr", "+sb", "-bg", "black", "-fg", "white", "-fn",
       +        "-*-terminus-medium-*-*-*-13-*-*-*-*-*-iso10646-*",NULL
       +};
       +const char *browse[] = { "firefox", NULL };
       +const char *xlock[] = { "xlock", NULL };
       +
       +Key key[] = {
       +        /* modifier                                key                        function        arguments */
       +        { Mod1Mask,                                XK_Return,        zoom,                { 0 } },
       +        { Mod1Mask,                                XK_k,                prevc,                { 0 } },
       +        { Mod1Mask,                                XK_j,                nextc,                { 0 } }, 
       +        { Mod1Mask,                                XK_m,                max,                { 0 } }, 
       +        { Mod1Mask,                                XK_0,                view,                { .i = Tscratch } }, 
       +        { Mod1Mask,                                XK_1,                view,                { .i = Tdev } }, 
       +        { Mod1Mask,                                XK_2,                view,                { .i = Twww } }, 
       +        { Mod1Mask,                                XK_3,                view,                { .i = Twork } }, 
       +        { Mod1Mask,                                XK_space,        tiling,                { 0 } }, 
       +        { Mod1Mask|ShiftMask,        XK_space,        floating,        { 0 } }, 
       +        { Mod1Mask|ShiftMask,        XK_0,                ttrunc,                { .i = Tscratch } }, 
       +        { Mod1Mask|ShiftMask,        XK_1,                ttrunc,                { .i = Tdev } }, 
       +        { Mod1Mask|ShiftMask,        XK_2,                ttrunc,                { .i = Twww } }, 
       +        { Mod1Mask|ShiftMask,        XK_3,                ttrunc,                { .i = Twork } }, 
       +        { Mod1Mask|ShiftMask,        XK_c,                ckill,                { 0 } }, 
       +        { Mod1Mask|ShiftMask,        XK_q,                quit,                { 0 } },
       +        { Mod1Mask|ShiftMask,        XK_Return,        spawn,                { .argv = term } },
       +        { Mod1Mask|ShiftMask,        XK_w,                spawn,                { .argv = browse } },
       +        { Mod1Mask|ShiftMask,        XK_l,                spawn,                { .argv = xlock } },
       +        { ControlMask,                        XK_0,                tappend,        { .i = Tscratch } }, 
       +        { ControlMask,                        XK_1,                tappend,        { .i = Tdev } }, 
       +        { ControlMask,                        XK_2,                tappend,        { .i = Twww } }, 
       +        { ControlMask,                        XK_3,                tappend,        { .i = Twork } }, 
       +};
       +
       +/********** CUSTOMIZE **********/
       +
       +void
       +grabkeys()
       +{
       +        static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
       +        unsigned int i;
       +        KeyCode code;
       +
       +        for(i = 0; i < len; i++) {
       +                code = XKeysymToKeycode(dpy, key[i].keysym);
       +                XUngrabKey(dpy, code, key[i].mod, root);
       +                XGrabKey(dpy, code, key[i].mod, root, True,
       +                                GrabModeAsync, GrabModeAsync);
       +        }
       +}
       +
       +void
       +keypress(XEvent *e)
       +{
       +        XKeyEvent *ev = &e->xkey;
       +        static unsigned int len = key ? sizeof(key) / sizeof(key[0]) : 0;
       +        unsigned int i;
       +        KeySym keysym;
       +
       +        keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
       +        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].arg);
       +                        return;
       +                }
       +}
       +
       +static void
       +zoom(Arg *arg)
       +{
       +        Client **l, *c;
       +
       +        if(!sel)
       +                return;
       +
       +        if(sel == next(clients) && sel->next)  {
       +                if((c = next(sel->next)))
       +                        sel = c;
       +        }
       +
       +        for(l = &clients; *l && *l != sel; l = &(*l)->next);
       +        *l = sel->next;
       +
       +        sel->next = clients; /* pop */
       +        clients = sel;
       +        arrange(NULL);
       +        focus(sel);
       +}
       +
       +static void
       +max(Arg *arg)
       +{
       +        if(!sel)
       +                return;
       +        sel->x = sx;
       +        sel->y = sy + bh;
       +        sel->w = sw - 2 * sel->border;
       +        sel->h = sh - 2 * sel->border - bh;
       +        craise(sel);
       +        resize(sel, False);
       +}
       +
       +static void
       +tappend(Arg *arg)
       +{
       +        if(!sel)
       +                return;
       +
       +        sel->tags[arg->i] = tags[arg->i];
       +        arrange(NULL);
       +}
       +
       +static void
       +ttrunc(Arg *arg)
       +{
       +        int i;
       +        if(!sel)
       +                return;
       +
       +        for(i = 0; i < TLast; i++)
       +                sel->tags[i] = NULL;
       +        tappend(arg);
       +}
       +
       +static void
       +prevc(Arg *arg)
       +{
       +        Client *c;
       +
       +        if(!sel)
       +                return;
       +
       +        if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) {
       +                craise(c);
       +                focus(c);
       +        }
       +}
       +
       +static void
       +nextc(Arg *arg)
       +{
       +        Client *c;
       +   
       +        if(!sel)
       +                return;
       +
       +        if(!(c = next(sel->next)))
       +                c = next(clients);
       +        if(c) {
       +                craise(c);
       +                c->revert = sel;
       +                focus(c);
       +        }
       +}
       +
       +static void
       +ckill(Arg *arg)
       +{
       +        if(!sel)
       +                return;
       +        if(sel->proto & WM_PROTOCOL_DELWIN)
       +                send_message(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]);
       +        else
       +                XKillClient(dpy, sel->win);
       +}
       +
   DIR diff --git a/main.c b/main.c
       @@ -239,7 +239,7 @@ main(int argc, char *argv[])
                cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
                cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
        
       -        update_keys();
       +        grabkeys();
        
                /* style */
                dc.bg = initcolor(BGCOLOR);
   DIR diff --git a/screen.c b/screen.c
       @@ -0,0 +1,100 @@
       +/*
       + * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
       + * See LICENSE file for license details.
       + */
       +
       +#include "dwm.h"
       +
       +void (*arrange)(Arg *) = tiling;
       +
       +void
       +view(Arg *arg)
       +{
       +        Client *c;
       +
       +        tsel = arg->i;
       +        arrange(NULL);
       +
       +        for(c = clients; c; c = next(c->next))
       +                draw_client(c);
       +        draw_bar();
       +}
       +
       +void
       +floating(Arg *arg)
       +{
       +        Client *c;
       +
       +        arrange = floating;
       +        for(c = clients; c; c = c->next) {
       +                if(c->tags[tsel])
       +                        resize(c, True);
       +                else
       +                        ban_client(c);
       +        }
       +        if(sel && !sel->tags[tsel]) {
       +                if((sel = next(clients))) {
       +                        craise(sel);
       +                        focus(sel);
       +                }
       +        }
       +        draw_bar();
       +}
       +
       +void
       +tiling(Arg *arg)
       +{
       +        Client *c;
       +        int n, i, w, h;
       +
       +        w = sw - mw;
       +        arrange = tiling;
       +        for(n = 0, c = clients; c; c = c->next)
       +                if(c->tags[tsel] && !c->floating)
       +                        n++;
       +
       +        if(n > 1)
       +                h = (sh - bh) / (n - 1);
       +        else
       +                h = sh - bh;
       +
       +        for(i = 0, c = clients; c; c = c->next) {
       +                if(c->tags[tsel]) {
       +                        if(c->floating) {
       +                                craise(c);
       +                                resize(c, True);
       +                                continue;
       +                        }
       +                        if(n == 1) {
       +                                c->x = sx;
       +                                c->y = sy + bh;
       +                                c->w = sw - 2 * c->border;
       +                                c->h = sh - 2 * c->border - bh;
       +                        }
       +                        else if(i == 0) {
       +                                c->x = sx;
       +                                c->y = sy + bh;
       +                                c->w = mw - 2 * c->border;
       +                                c->h = sh - 2 * c->border - bh;
       +                        }
       +                        else {
       +                                c->x = sx + mw;
       +                                c->y = sy + (i - 1) * h + bh;
       +                                c->w = w - 2 * c->border;
       +                                c->h = h - 2 * c->border;
       +                        }
       +                        resize(c, False);
       +                        i++;
       +                }
       +                else
       +                        ban_client(c);
       +        }
       +        if(!sel || (sel && !sel->tags[tsel])) {
       +                if((sel = next(clients))) {
       +                        craise(sel);
       +                        focus(sel);
       +                }
       +        }
       +        draw_bar();
       +}
       +