X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=dwm.c;h=3168ee08bb1a6bdf50eb871a415d441e56d8f4ee;hb=a026617c657bea56d93b586b50a016477d52cc85;hp=d497f4cfd4e36227c012101c85910f0514b2fdfb;hpb=0235a84ef286db5c97239615ae525ce973641941;p=dwm.git diff --git a/dwm.c b/dwm.c index d497f4c..3168ee0 100644 --- a/dwm.c +++ b/dwm.c @@ -1,4 +1,33 @@ -/* See LICENSE file for copyright and license details. */ +/* See LICENSE file for copyright and license details. + * + * dynamic window manager is designed like any other X client as well. It is + * driven through handling X events. In contrast to other X clients, a window + * manager selects for SubstructureRedirectMask on the root window, to receive + * events about window (dis-)appearance. Only one X connection at a time is + * allowed to select for this event mask. + * + * Calls to fetch an X event from the event queue are blocking. Due reading + * status text from standard input, a select()-driven main loop has been + * implemented which selects for reads on the X connection and STDIN_FILENO to + * handle all data smoothly. The event handlers of dwm are organized in an + * array which is accessed whenever a new event has been fetched. This allows + * event dispatching in O(1) time. + * + * Each child of the root window is called a client, except windows which have + * set the override_redirect flag. Clients are organized in a global + * doubly-linked client list, the focus history is remembered through a global + * stack list. Each client contains an array of Bools of the same size as the + * global tags array to indicate the tags of a client. For each client dwm + * creates a small title window, which is resized whenever the (_NET_)WM_NAME + * properties are updated or the client is moved/resized. + * + * Keys and tagging rules are organized as arrays and defined in the config.h + * file. These arrays are kept static in event.o and tag.o respectively, + * because no other part of dwm needs access to them. The current layout is + * represented by the lt pointer. + * + * To understand everything else, start reading main(). + */ #include #include #include @@ -84,101 +113,97 @@ typedef struct { } Regs; /* functions */ -static void eprint(const char *errstr, ...); -static void *emallocz(unsigned int size); -static void spawn(const char *arg); -static void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]); -static unsigned long initcolor(const char *colstr); -static void initfont(const char *fontstr); -static Bool isoccupied(unsigned int t); -static unsigned int textnw(const char *text, unsigned int len); -static void drawtext(const char *text, unsigned long col[ColLast]); -static void drawbar(void); -static void initstyle(void); -static void initbar(void); -static unsigned int textw(const char *text); -static void togglebar(const char *arg); -static void updatebarpos(void); + +static void applyrules(Client *c); +static void arrange(void); +static void attach(Client *c); static void attachstack(Client *c); -static void detachstack(Client *c); -static void grabbuttons(Client *c, Bool focused); -static Bool isprotodel(Client *c); -static void setclientstate(Client *c, long state); -static int xerrordummy(Display *dsply, XErrorEvent *ee); static void ban(Client *c); -static void configure(Client *c); -static void killclient(const char *arg); -static void manage(Window w, XWindowAttributes *wa); -static void resize(Client *c, int x, int y, int w, int h, Bool sizehints); -static void unban(Client *c); -static void unmanage(Client *c); -static void updatesizehints(Client *c); -static void updatetitle(Client *c); -static Client *getclient(Window w); -static void movemouse(Client *c); -static void resizemouse(Client *c); static void buttonpress(XEvent *e); -static void configurerequest(XEvent *e); +static void cleanup(void); +static void compileregs(void); +static void configure(Client *c); static void configurenotify(XEvent *e); +static void configurerequest(XEvent *e); static void destroynotify(XEvent *e); +static void detach(Client *c); +static void detachstack(Client *c); +static void drawbar(void); +static void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]); +static void drawtext(const char *text, unsigned long col[ColLast]); +static void *emallocz(unsigned int size); static void enternotify(XEvent *e); +static void eprint(const char *errstr, ...); static void expose(XEvent *e); -static void keypress(XEvent *e); -static void leavenotify(XEvent *e); -static void mappingnotify(XEvent *e); -static void maprequest(XEvent *e); -static void propertynotify(XEvent *e); -static void unmapnotify(XEvent *e); -static void grabkeys(void); -static unsigned int idxoftag(const char *tag); static void floating(void); /* default floating layout */ -static void applyrules(Client *c); -static void compileregs(void); +static void focus(Client *c); static void focusnext(const char *arg); static void focusprev(const char *arg); +static Client *getclient(Window w); +static long getstate(Window w); +static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); +static void grabbuttons(Client *c, Bool focused); +static unsigned int idxoftag(const char *tag); +static void initbar(void); +static unsigned long initcolor(const char *colstr); +static void initfont(const char *fontstr); static void initlayouts(void); +static void initstyle(void); +static Bool isarrange(void (*func)()); static Bool isfloating(void); +static Bool isoccupied(unsigned int t); +static Bool isprotodel(Client *c); static Bool isvisible(Client *c); +static void keypress(XEvent *e); +static void killclient(const char *arg); +static void leavenotify(XEvent *e); +static void manage(Window w, XWindowAttributes *wa); +static void mappingnotify(XEvent *e); +static void maprequest(XEvent *e); +static void movemouse(Client *c); +static Client *nexttiled(Client *c); +static void propertynotify(XEvent *e); +static void quit(const char *arg); +static void resize(Client *c, int x, int y, int w, int h, Bool sizehints); +static void resizemouse(Client *c); static void restack(void); +static void scan(void); +static void setclientstate(Client *c, long state); static void setlayout(const char *arg); +static void setmwfact(const char *arg); +static void setup(void); +static void spawn(const char *arg); static void tag(const char *arg); +static unsigned int textnw(const char *text, unsigned int len); +static unsigned int textw(const char *text); +static void tile(void); +static void togglebar(const char *arg); static void togglefloating(const char *arg); static void togglemax(const char *arg); static void toggletag(const char *arg); static void toggleview(const char *arg); +static void unban(Client *c); +static void unmanage(Client *c); +static void unmapnotify(XEvent *e); +static void updatebarpos(void); +static void updatesizehints(Client *c); +static void updatetitle(Client *c); static void view(const char *arg); -static void cleanup(void); -static long getstate(Window w); -static void scan(void); -static void setup(void); -static int xerrorstart(Display *dsply, XErrorEvent *ee); -static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); -static void quit(const char *arg); static int xerror(Display *dpy, XErrorEvent *ee); -static void arrange(void); -static void attach(Client *c); -static void detach(Client *c); -static void focus(Client *c); -static Bool isarrange(void (*func)()); -static Client *nexttiled(Client *c); -static void setmwfact(const char *arg); -static void tile(void); +static int xerrordummy(Display *dsply, XErrorEvent *ee); +static int xerrorstart(Display *dsply, XErrorEvent *ee); static void zoom(const char *arg); -#include "config.h" - /* variables */ static char stext[256]; -static double mwfact = MWFACT; +static double mwfact; static int screen, sx, sy, sw, sh, wax, way, waw, wah; static int (*xerrorxlib)(Display *, XErrorEvent *); -static unsigned int bh; +static unsigned int bh, bpos, ntags; static unsigned int blw = 0; -static unsigned int bpos = BARPOS; static unsigned int ltidx = 0; /* default */ static unsigned int nlayouts = 0; static unsigned int nrules = 0; -static unsigned int ntags; static unsigned int numlockmask = 0; static void (*handler[LASTEvent]) (XEvent *) = { [ButtonPress] = buttonpress, @@ -208,6 +233,9 @@ static DC dc = {0}; static Window barwin, root; static Regs *regs = NULL; +/* configuration, allows nested code to work on above variables */ +#include "config.h" + static void eprint(const char *errstr, ...) { va_list ap; @@ -1070,9 +1098,26 @@ keypress(XEvent *e) { KEYS unsigned int len = sizeof keys / sizeof keys[0]; unsigned int i; + KeyCode code; KeySym keysym; - XKeyEvent *ev = &e->xkey; - + XKeyEvent *ev; + + if(!e) { /* grabkeys */ + XUngrabKey(dpy, AnyKey, AnyModifier, root); + for(i = 0; i < len; i++) { + code = XKeysymToKeycode(dpy, keys[i].keysym); + XGrabKey(dpy, code, keys[i].mod, root, True, + GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod | LockMask, root, True, + GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True, + GrabModeAsync, GrabModeAsync); + XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True, + GrabModeAsync, GrabModeAsync); + } + return; + } + ev = &e->xkey; keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); for(i = 0; i < len; i++) if(keysym == keys[i].keysym @@ -1099,7 +1144,7 @@ mappingnotify(XEvent *e) { XRefreshKeyboardMapping(ev); if(ev->request == MappingKeyboard) - grabkeys(); + keypress(NULL); } static void @@ -1152,27 +1197,6 @@ unmapnotify(XEvent *e) { unmanage(c); } -static void -grabkeys(void) { - KEYS - unsigned int len = sizeof keys / sizeof keys[0]; - unsigned int i; - KeyCode code; - - XUngrabKey(dpy, AnyKey, AnyModifier, root); - for(i = 0; i < len; i++) { - code = XKeysymToKeycode(dpy, keys[i].keysym); - XGrabKey(dpy, code, keys[i].mod, root, True, - GrabModeAsync, GrabModeAsync); - XGrabKey(dpy, code, keys[i].mod | LockMask, root, True, - GrabModeAsync, GrabModeAsync); - XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True, - GrabModeAsync, GrabModeAsync); - XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True, - GrabModeAsync, GrabModeAsync); - } -} - static unsigned int idxoftag(const char *tag) { unsigned int i; @@ -1546,7 +1570,7 @@ setup(void) { wa.cursor = cursor[CurNormal]; XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); - grabkeys(); + keypress(NULL); /* grabkeys */ compileregs(); for(ntags = 0; tags[ntags]; ntags++); seltags = emallocz(sizeof(Bool) * ntags); @@ -1781,6 +1805,11 @@ main(int argc, char *argv[]) { eprint("dwm-"VERSION", © 2006-2007 A. R. Garbe, S. van Dijk, J. Salmi, P. Hruby, S. Nagy\n"); else if(argc != 1) eprint("usage: dwm [-v]\n"); + + /* macros from config.h can be used beginning within main() */ + mwfact = MWFACT; + bpos = BARPOS; + setlocale(LC_CTYPE, ""); if(!(dpy = XOpenDisplay(0))) eprint("dwm: cannot open display\n");