X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=dwm.c;h=5bd7221f04e2a4cffeb2f80b0476d2bc6c84fd0d;hb=c36f7c3c5e5db297689765142c64977f6317a21c;hp=8f5ed6d3d0dd7cdeaa14acd6359c1904a156b3f7;hpb=206eb344e2efcb29922b5b89f7b11f227d701240;p=dwm.git diff --git a/dwm.c b/dwm.c index 8f5ed6d..5bd7221 100644 --- a/dwm.c +++ b/dwm.c @@ -43,13 +43,195 @@ #include #include -#include "dwm.h" - /* macros */ #define BUTTONMASK (ButtonPressMask | ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) #define MOUSEMASK (BUTTONMASK | PointerMotionMask) +/* enums */ +enum { BarTop, BarBot, BarOff }; /* bar position */ +enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ +enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ +enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ +enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */ + +/* typedefs */ +typedef struct Client Client; +struct Client { + char name[256]; + int x, y, w, h; + int rx, ry, rw, rh; /* revert geometry */ + int basew, baseh, incw, inch, maxw, maxh, minw, minh; + int minax, maxax, minay, maxay; + long flags; + unsigned int border, oldborder; + Bool isbanned, isfixed, ismax, isfloating, wasfloating; + Bool *tags; + Client *next; + Client *prev; + Client *snext; + Window win; +}; + +typedef struct { + int x, y, w, h; + unsigned long norm[ColLast]; + unsigned long sel[ColLast]; + Drawable drawable; + GC gc; + struct { + int ascent; + int descent; + int height; + XFontSet set; + XFontStruct *xfont; + } font; +} DC; /* draw context */ + +typedef struct { + unsigned long mod; + KeySym keysym; + void (*func)(const char *arg); + const char *arg; +} Key; + +typedef struct { + const char *symbol; + void (*arrange)(void); +} Layout; + +typedef struct { + const char *prop; + const char *tags; + Bool isfloating; +} Rule; + +typedef struct { + regex_t *propregex; + regex_t *tagregex; +} Regs; + +/* function declarations */ +void applyrules(Client *c); +void arrange(void); +void attach(Client *c); +void attachstack(Client *c); +void ban(Client *c); +void buttonpress(XEvent *e); +void checkotherwm(void); +void cleanup(void); +void compileregs(void); +void configure(Client *c); +void configurenotify(XEvent *e); +void configurerequest(XEvent *e); +void destroynotify(XEvent *e); +void detach(Client *c); +void detachstack(Client *c); +void drawbar(void); +void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]); +void drawtext(const char *text, unsigned long col[ColLast]); +void *emallocz(unsigned int size); +void enternotify(XEvent *e); +void eprint(const char *errstr, ...); +void expose(XEvent *e); +void floating(void); /* default floating layout */ +void focus(Client *c); +void focusnext(const char *arg); +void focusprev(const char *arg); +Client *getclient(Window w); +unsigned long getcolor(const char *colstr); +long getstate(Window w); +Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); +void grabbuttons(Client *c, Bool focused); +unsigned int idxoftag(const char *tag); +void initfont(const char *fontstr); +Bool isoccupied(unsigned int t); +Bool isprotodel(Client *c); +Bool isvisible(Client *c); +void keypress(XEvent *e); +void killclient(const char *arg); +void leavenotify(XEvent *e); +void manage(Window w, XWindowAttributes *wa); +void mappingnotify(XEvent *e); +void maprequest(XEvent *e); +void movemouse(Client *c); +Client *nexttiled(Client *c); +void propertynotify(XEvent *e); +void quit(const char *arg); +void resize(Client *c, int x, int y, int w, int h, Bool sizehints); +void resizemouse(Client *c); +void restack(void); +void run(void); +void scan(void); +void setclientstate(Client *c, long state); +void setlayout(const char *arg); +void setmwfact(const char *arg); +void setup(void); +void spawn(const char *arg); +void tag(const char *arg); +unsigned int textnw(const char *text, unsigned int len); +unsigned int textw(const char *text); +void tile(void); +void togglebar(const char *arg); +void togglefloating(const char *arg); +void togglemax(const char *arg); +void toggletag(const char *arg); +void toggleview(const char *arg); +void unban(Client *c); +void unmanage(Client *c); +void unmapnotify(XEvent *e); +void updatebarpos(void); +void updatesizehints(Client *c); +void updatetitle(Client *c); +void view(const char *arg); +void viewprevtag(const char *arg); /* views previous selected tags */ +int xerror(Display *dpy, XErrorEvent *ee); +int xerrordummy(Display *dsply, XErrorEvent *ee); +int xerrorstart(Display *dsply, XErrorEvent *ee); +void zoom(const char *arg); + +/* variables */ +char stext[256]; +double mwfact; +int screen, sx, sy, sw, sh, wax, way, waw, wah; +int (*xerrorxlib)(Display *, XErrorEvent *); +unsigned int bh, bpos; +unsigned int blw = 0; +unsigned int numlockmask = 0; +void (*handler[LASTEvent]) (XEvent *) = { + [ButtonPress] = buttonpress, + [ConfigureRequest] = configurerequest, + [ConfigureNotify] = configurenotify, + [DestroyNotify] = destroynotify, + [EnterNotify] = enternotify, + [LeaveNotify] = leavenotify, + [Expose] = expose, + [KeyPress] = keypress, + [MappingNotify] = mappingnotify, + [MapRequest] = maprequest, + [PropertyNotify] = propertynotify, + [UnmapNotify] = unmapnotify +}; +Atom wmatom[WMLast], netatom[NetLast]; +Bool domwfact = True; +Bool dozoom = True; +Bool otherwm, readin; +Bool running = True; +Bool selscreen = True; +Client *clients = NULL; +Client *sel = NULL; +Client *stack = NULL; +Cursor cursor[CurLast]; +Display *dpy; +DC dc = {0}; +Layout *layout = NULL; +Window barwin, root; +Regs *regs = NULL; + +/* configuration, allows nested code to access above variables */ +#include "config.h" + +/* function implementations */ void applyrules(Client *c) { static char buf[512]; @@ -63,10 +245,10 @@ applyrules(Client *c) { snprintf(buf, sizeof buf, "%s:%s:%s", ch.res_class ? ch.res_class : "", ch.res_name ? ch.res_name : "", c->name); - for(i = 0; i < nrules; i++) + for(i = 0; i < NRULES; i++) if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) { c->isfloating = rules[i].isfloating; - for(j = 0; regs[i].tagregex && j < ntags; j++) { + for(j = 0; regs[i].tagregex && j < NTAGS; j++) { if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { matched = True; c->tags[j] = True; @@ -90,7 +272,7 @@ arrange(void) { unban(c); else ban(c); - layouts[ltidx].arrange(); + layout->arrange(); focus(NULL); restack(); } @@ -125,7 +307,7 @@ buttonpress(XEvent *e) { if(barwin == ev->window) { x = 0; - for(i = 0; i < ntags; i++) { + for(i = 0; i < NTAGS; i++) { x += textw(tags[i]); if(ev->x < x) { if(ev->button == Button1) { @@ -151,20 +333,20 @@ buttonpress(XEvent *e) { if(CLEANMASK(ev->state) != MODKEY) return; if(ev->button == Button1) { - if(isarrange(floating) || c->isfloating) + if((floating == layout->arrange) || c->isfloating) restack(); else togglefloating(NULL); movemouse(c); } else if(ev->button == Button2) { - if(ISTILE && !c->isfixed && c->isfloating) + if((floating != layout->arrange) && !c->isfixed && c->isfloating) togglefloating(NULL); else zoom(NULL); } else if(ev->button == Button3 && !c->isfixed) { - if(isarrange(floating) || c->isfloating) + if((floating == layout->arrange) || c->isfloating) restack(); else togglefloating(NULL); @@ -218,9 +400,8 @@ compileregs(void) { if(regs) return; - nrules = sizeof rules / sizeof rules[0]; - regs = emallocz(nrules * sizeof(Regs)); - for(i = 0; i < nrules; i++) { + regs = emallocz(NRULES * sizeof(Regs)); + for(i = 0; i < NRULES; i++) { if(rules[i].prop) { reg = emallocz(sizeof(regex_t)); if(regcomp(reg, rules[i].prop, REG_EXTENDED)) @@ -281,7 +462,7 @@ configurerequest(XEvent *e) { c->ismax = False; if(ev->value_mask & CWBorderWidth) c->border = ev->border_width; - if(c->isfixed || c->isfloating || isarrange(floating)) { + if(c->isfixed || c->isfloating || (floating == layout->arrange)) { if(ev->value_mask & CWX) c->x = ev->x; if(ev->value_mask & CWY) @@ -349,7 +530,7 @@ drawbar(void) { int i, x; dc.x = dc.y = 0; - for(i = 0; i < ntags; i++) { + for(i = 0; i < NTAGS; i++) { dc.w = textw(tags[i]); if(seltags[i]) { drawtext(tags[i], dc.sel); @@ -362,7 +543,7 @@ drawbar(void) { dc.x += dc.w; } dc.w = blw; - drawtext(layouts[ltidx].symbol, dc.norm); + drawtext(layout->symbol, dc.norm); x = dc.x + dc.w; dc.w = textw(stext); dc.x = sw - dc.w; @@ -483,7 +664,7 @@ void expose(XEvent *e) { XExposeEvent *ev = &e->xexpose; - if(ev->count == 0) { + if(0 == ev->count) { if(barwin == ev->window) drawbar(); } @@ -493,6 +674,7 @@ void floating(void) { /* default floating layout */ Client *c; + domwfact = dozoom = False; for(c = clients; c; c = c->next) if(isvisible(c)) resize(c, c->x, c->y, c->w, c->h, True); @@ -597,7 +779,7 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) { int n; XTextProperty name; - if(!text || size == 0) + if(!text || 0 == size) return False; text[0] = '\0'; XGetTextProperty(dpy, w, &name, atom); @@ -659,10 +841,8 @@ unsigned int idxoftag(const char *tag) { unsigned int i; - for(i = 0; i < ntags; i++) - if(tags[i] == tag) - return i; - return 0; + for(i = 0; (i < NTAGS) && (tags[i] != tag); i++); + return (i < NTAGS) ? i : 0; } void @@ -708,12 +888,6 @@ initfont(const char *fontstr) { } Bool -isarrange(void (*func)()) -{ - return func == layouts[ltidx].arrange; -} - -Bool isoccupied(unsigned int t) { Client *c; @@ -742,7 +916,7 @@ Bool isvisible(Client *c) { unsigned int i; - for(i = 0; i < ntags; i++) + for(i = 0; i < NTAGS; i++) if(c->tags[i] && seltags[i]) return True; return False; @@ -751,7 +925,6 @@ isvisible(Client *c) { void keypress(XEvent *e) { KEYS - unsigned int len = sizeof keys / sizeof keys[0]; unsigned int i; KeyCode code; KeySym keysym; @@ -759,7 +932,7 @@ keypress(XEvent *e) { if(!e) { /* grabkeys */ XUngrabKey(dpy, AnyKey, AnyModifier, root); - for(i = 0; i < len; i++) { + for(i = 0; i < NKEYS; i++) { code = XKeysymToKeycode(dpy, keys[i].keysym); XGrabKey(dpy, code, keys[i].mod, root, True, GrabModeAsync, GrabModeAsync); @@ -774,7 +947,7 @@ keypress(XEvent *e) { } ev = &e->xkey; keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); - for(i = 0; i < len; i++) + for(i = 0; i < NKEYS; i++) if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)) { @@ -952,7 +1125,7 @@ propertynotify(XEvent *e) { default: break; case XA_WM_TRANSIENT_FOR: XGetTransientForHint(dpy, c->win, &trans); - if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL))) + if(!c->isfloating && (c->isfloating = (NULL != getclient(trans)))) arrange(); break; case XA_WM_NORMAL_HINTS: @@ -1085,9 +1258,9 @@ restack(void) { drawbar(); if(!sel) return; - if(sel->isfloating || isarrange(floating)) + if(sel->isfloating || (floating == layout->arrange)) XRaiseWindow(dpy, sel->win); - if(!isarrange(floating)) { + if(floating != layout->arrange) { wc.stack_mode = Below; wc.sibling = barwin; if(!sel->isfloating) { @@ -1193,16 +1366,16 @@ setlayout(const char *arg) { unsigned int i; if(!arg) { - if(++ltidx == nlayouts) - ltidx = 0;; + if(++layout == &layouts[NLAYOUTS]) + layout = &layouts[0]; } else { - for(i = 0; i < nlayouts; i++) + for(i = 0; i < NLAYOUTS; i++) if(!strcmp(arg, layouts[i].symbol)) break; - if(i == nlayouts) + if(i == NLAYOUTS) return; - ltidx = i; + layout = &layouts[i]; } if(sel) arrange(); @@ -1214,10 +1387,10 @@ void setmwfact(const char *arg) { double delta; - if(!ISTILE) + if(!domwfact) return; /* arg handling, manipulate mwfact */ - if(arg == NULL) + if(NULL == arg) mwfact = MWFACT; else if(1 == sscanf(arg, "%lf", &delta)) { if(arg[0] == '+' || arg[0] == '-') @@ -1295,8 +1468,8 @@ setup(void) { /* init layouts */ mwfact = MWFACT; - nlayouts = sizeof layouts / sizeof layouts[0]; - for(blw = i = 0; i < nlayouts; i++) { + layout = &layouts[0]; + for(blw = i = 0; i < NLAYOUTS; i++) { j = textw(layouts[i].symbol); if(j > blw) blw = j; @@ -1334,8 +1507,8 @@ spawn(const char *arg) { return; /* The double-fork construct avoids zombie processes and keeps the code * clean from stupid signal handlers. */ - if(fork() == 0) { - if(fork() == 0) { + if(0 == fork()) { + if(0 == fork()) { if(dpy) close(ConnectionNumber(dpy)); setsid(); @@ -1354,11 +1527,9 @@ tag(const char *arg) { if(!sel) return; - for(i = 0; i < ntags; i++) - sel->tags[i] = arg == NULL; - i = idxoftag(arg); - if(i >= 0 && i < ntags) - sel->tags[i] = True; + for(i = 0; i < NTAGS; i++) + sel->tags[i] = (NULL == arg); + sel->tags[idxoftag(arg)] = True; arrange(); } @@ -1383,6 +1554,7 @@ tile(void) { unsigned int i, n, nx, ny, nw, nh, mw, th; Client *c, *mc; + domwfact = dozoom = True; for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) n++; @@ -1397,7 +1569,7 @@ tile(void) { nw = 0; /* gcc stupidity requires this */ for(i = 0, c = mc = nexttiled(clients); c; c = nexttiled(c->next), i++) { c->ismax = False; - if(i == 0) { /* master */ + if(0 == i) { /* master */ nw = mw - 2 * c->border; nh = wah - 2 * c->border; } @@ -1412,7 +1584,10 @@ tile(void) { else nh = th - 2 * c->border; } - resize(c, nx, ny, nw, nh, RESIZEHINTS); + resize(c, nx, ny, nw, nh, True); + if((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw)) + /* client doesn't accept size constraints */ + resize(c, nx, ny, nw, nh, False); if(n > 1 && th != wah) ny = c->y + c->h + 2 * c->border; } @@ -1445,7 +1620,7 @@ togglemax(const char *arg) { if(!sel || sel->isfixed) return; if((sel->ismax = !sel->ismax)) { - if(isarrange(floating) || sel->isfloating) + if((floating == layout->arrange) || sel->isfloating) sel->wasfloating = True; else { togglefloating(NULL); @@ -1474,9 +1649,9 @@ toggletag(const char *arg) { return; i = idxoftag(arg); sel->tags[i] = !sel->tags[i]; - for(j = 0; j < ntags && !sel->tags[j]; j++); - if(j == ntags) - sel->tags[i] = True; + for(j = 0; j < NTAGS && !sel->tags[j]; j++); + if(j == NTAGS) + sel->tags[i] = True; /* at least one tag must be enabled */ arrange(); } @@ -1486,8 +1661,8 @@ toggleview(const char *arg) { i = idxoftag(arg); seltags[i] = !seltags[i]; - for(j = 0; j < ntags && !seltags[j]; j++); - if(j == ntags) + for(j = 0; j < NTAGS && !seltags[j]; j++); + if(j == NTAGS) seltags[i] = True; /* at least one tag must be viewed */ arrange(); } @@ -1653,11 +1828,9 @@ view(const char *arg) { unsigned int i; memcpy(prevtags, seltags, sizeof seltags); - for(i = 0; i < ntags; i++) - seltags[i] = arg == NULL; - i = idxoftag(arg); - if(i >= 0 && i < ntags) - seltags[i] = True; + for(i = 0; i < NTAGS; i++) + seltags[i] = (NULL == arg); + seltags[idxoftag(arg)] = True; arrange(); } @@ -1675,7 +1848,7 @@ void zoom(const char *arg) { Client *c; - if(!sel || !ISTILE || sel->isfloating) + if(!sel || !dozoom || sel->isfloating) return; if((c = sel) == nexttiled(clients)) if(!(c = nexttiled(c->next)))