X-Git-Url: https://jasonwoof.com/gitweb/?p=dwm.git;a=blobdiff_plain;f=dwm.c;h=6299b63d6df661d02d3039e202bfad6d9aa428e8;hp=91b0149e0fb36951558b866c1139915d961a7c0b;hb=489ac07e83f5dabd23d494630c7bb61690bb56e0;hpb=c982bb1389c37262cbcc6ffcc343ec78528c4a81 diff --git a/dwm.c b/dwm.c index 91b0149..6299b63 100644 --- a/dwm.c +++ b/dwm.c @@ -41,19 +41,13 @@ #include /* macros */ -#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) -#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) -#define LENGTH(x) (sizeof x / sizeof x[0]) -#define MAXTAGLEN 16 -#define MOUSEMASK (BUTTONMASK|PointerMotionMask) -#define DEFGEOM(GEONAME,BX,BY,BW,WX,WY,WW,WH,MX,MY,MW,MH,TX,TY,TW,TH,MOX,MOY,MOW,MOH) \ -void GEONAME(void) { \ - bx = (BX); by = (BY); bw = (BW); \ - wx = (WX); wy = (WY); ww = (WW); wh = (WH); \ - mx = (MX); my = (MY); mw = (MW); mh = (MH); \ - tx = (TX); ty = (TY); tw = (TW); th = (TH); \ - mox = (MOX); moy = (MOY); mow = (MOW); moh = (MOH); \ -} +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) +#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) +#define LENGTH(x) (sizeof x / sizeof x[0]) +#define MAXTAGLEN 16 +#define MOUSEMASK (BUTTONMASK|PointerMotionMask) /* enums */ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ @@ -66,6 +60,7 @@ typedef struct Client Client; struct Client { char name[256]; int x, y, w, h; + int fx, fy, fw, fh; int basew, baseh, incw, inch, maxw, maxh, minw, minh; int minax, maxax, minay, maxay; long flags; @@ -94,11 +89,6 @@ typedef struct { } DC; /* draw context */ typedef struct { - const char *symbol; - void (*apply)(void); -} Geom; - -typedef struct { unsigned long mod; KeySym keysym; void (*func)(const char *arg); @@ -109,7 +99,7 @@ typedef struct { const char *symbol; void (*arrange)(void); Bool isfloating; -} Layout; +} Layout; typedef struct { const char *class; @@ -142,7 +132,6 @@ 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 focusin(XEvent *e); void focusnext(const char *arg); @@ -158,7 +147,7 @@ void initfont(const char *fontstr); Bool isoccupied(unsigned int t); Bool isprotodel(Client *c); Bool isurgent(unsigned int t); -Bool isvisible(Client *c); +Bool isvisible(Client *c, Bool *cmp); void keypress(XEvent *e); void killclient(const char *arg); void manage(Window w, XWindowAttributes *wa); @@ -169,15 +158,12 @@ void movemouse(Client *c); Client *nexttiled(Client *c); void propertynotify(XEvent *e); void quit(const char *arg); -void reapply(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 setgeom(const char *arg); -void setlayout(const char *arg); void setmfact(const char *arg); void setup(void); void spawn(const char *arg); @@ -191,12 +177,14 @@ void tileresize(Client *c, int x, int y, int w, int h); void tilev(void); void tilevstack(unsigned int n); void togglefloating(const char *arg); +void togglelayout(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 updatebar(void); +void updategeom(void); void updatesizehints(Client *c); void updatetitle(Client *c); void updatewmhints(Client *c); @@ -208,10 +196,11 @@ int xerrorstart(Display *dpy, XErrorEvent *ee); void zoom(const char *arg); /* variables */ -char stext[256], buf[256]; +char stext[256]; int screen, sx, sy, sw, sh; int (*xerrorxlib)(Display *, XErrorEvent *); -int bx, by, bw, bh, blw, bgw, mx, my, mw, mh, mox, moy, mow, moh, tx, ty, tw, th, wx, wy, ww, wh; +int bx, by, bw, bh, blw, mx, my, mw, mh, tx, ty, tw, th, wx, wy, ww, wh; +int seltags = 0; double mfact; unsigned int numlockmask = 0; void (*handler[LASTEvent]) (XEvent *) = { @@ -231,22 +220,20 @@ void (*handler[LASTEvent]) (XEvent *) = { Atom wmatom[WMLast], netatom[NetLast]; Bool otherwm, readin; Bool running = True; -Bool *prevtags; -Bool *seltags; +Bool *tagset[2]; Client *clients = NULL; Client *sel = NULL; Client *stack = NULL; Cursor cursor[CurLast]; Display *dpy; DC dc = {0}; -Geom *geom = NULL; -Layout *lt = NULL; +Layout layouts[]; +Layout *lt = layouts; Window root, barwin; /* configuration, allows nested code to access above variables */ #include "config.h" #define TAGSZ (LENGTH(tags) * sizeof(Bool)) -static Bool tmp[LENGTH(tags)]; /* function implementations */ @@ -261,10 +248,9 @@ applyrules(Client *c) { XGetClassHint(dpy, c->win, &ch); for(i = 0; i < LENGTH(rules); i++) { r = &rules[i]; - if((r->title && strstr(c->name, r->title)) - || (ch.res_class && r->class && strstr(ch.res_class, r->class)) - || (ch.res_name && r->instance && strstr(ch.res_name, r->instance))) - { + if((!r->title || strstr(c->name, r->title)) + && (!r->class || (ch.res_class && strstr(ch.res_class, r->class))) + && (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) { c->isfloating = r->isfloating; if(r->tag) { c->tags[idxoftag(r->tag)] = True; @@ -277,7 +263,7 @@ applyrules(Client *c) { if(ch.res_name) XFree(ch.res_name); if(!matched) - memcpy(c->tags, seltags, TAGSZ); + memcpy(c->tags, tagset[seltags], TAGSZ); } void @@ -285,13 +271,17 @@ arrange(void) { Client *c; for(c = clients; c; c = c->next) - if(isvisible(c)) + if(isvisible(c, NULL)) { unban(c); + if(lt->isfloating || c->isfloating) + resize(c, c->fx, c->fy, c->fw, c->fh, True); + } else ban(c); focus(NULL); - lt->arrange(); + if(lt->arrange) + lt->arrange(); restack(); } @@ -324,14 +314,10 @@ buttonpress(XEvent *e) { XButtonPressedEvent *ev = &e->xbutton; if(ev->window == barwin) { - if((ev->x < bgw) && ev->button == Button1) { - setgeom(NULL); - return; - } - x = bgw; + x = 0; for(i = 0; i < LENGTH(tags); i++) { x += textw(tags[i]); - if(ev->x >= bgw && ev->x < x) { + if(ev->x < x) { if(ev->button == Button1) { if(ev->state & MODKEY) tag(tags[i]); @@ -348,7 +334,7 @@ buttonpress(XEvent *e) { } } if((ev->x < x + blw) && ev->button == Button1) - setlayout(NULL); + togglelayout(NULL); } else if((c = getclient(ev->window))) { focus(c); @@ -359,7 +345,7 @@ buttonpress(XEvent *e) { movemouse(c); } else if(ev->button == Button2) { - if((floating != lt->arrange) && c->isfloating) + if(!lt->isfloating && c->isfloating) togglefloating(NULL); else zoom(NULL); @@ -434,7 +420,9 @@ configurenotify(XEvent *e) { if(ev->window == root && (ev->width != sw || ev->height != sh)) { sw = ev->width; sh = ev->height; - setgeom(geom->symbol); + updategeom(); + updatebar(); + arrange(); } } @@ -463,7 +451,7 @@ configurerequest(XEvent *e) { if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) configure(c); - if(isvisible(c)) + if(isvisible(c, NULL)) XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); } else @@ -515,7 +503,7 @@ void detachstack(Client *c) { Client **tc; - for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext); + for(tc = &stack; *tc && *tc != c; tc = &(*tc)->snext); *tc = c->snext; } @@ -525,15 +513,10 @@ drawbar(void) { Client *c; dc.x = 0; - if(bgw > 0) { - dc.w = bgw; - drawtext(geom->symbol, dc.norm, False); - dc.x += bgw; - } - for(c = stack; c && !isvisible(c); c = c->snext); + for(c = stack; c && !isvisible(c, NULL); c = c->snext); for(i = 0; i < LENGTH(tags); i++) { dc.w = textw(tags[i]); - if(seltags[i]) { + if(tagset[seltags][i]) { drawtext(tags[i], dc.sel, isurgent(i)); drawsquare(c && c->tags[i], isoccupied(i), isurgent(i), dc.sel); } @@ -596,23 +579,23 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) { int x, y, w, h; unsigned int len, olen; XRectangle r = { dc.x, dc.y, dc.w, dc.h }; + char buf[256]; XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]); XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); if(!text) return; - w = 0; - olen = len = strlen(text); - if(len >= sizeof buf) - len = sizeof buf - 1; + olen = strlen(text); + len = MIN(olen, sizeof buf); memcpy(buf, text, len); - buf[len] = 0; + w = 0; h = dc.font.ascent + dc.font.descent; y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; x = dc.x + (h / 2); /* shorten text if necessary */ - while(len && (w = textnw(buf, len)) > dc.w - h) - buf[--len] = 0; + for(; len && (w = textnw(buf, len)) > dc.w - h; len--); + if(!len) + return; if(len < olen) { if(len > 1) buf[len - 1] = '.'; @@ -621,8 +604,6 @@ drawtext(const char *text, unsigned long col[ColLast], Bool invert) { if(len > 3) buf[len - 3] = '.'; } - if(w > dc.w) - return; /* too long */ XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]); if(dc.font.set) XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); @@ -671,18 +652,9 @@ expose(XEvent *e) { } void -floating(void) { /* default floating layout */ - Client *c; - - for(c = clients; c; c = c->next) - if(isvisible(c)) - resize(c, c->x, c->y, c->w, c->h, True); -} - -void focus(Client *c) { - if(!c || (c && !isvisible(c))) - for(c = stack; c && !isvisible(c); c = c->snext); + if(!c || (c && !isvisible(c, NULL))) + for(c = stack; c && !isvisible(c, NULL); c = c->snext); if(sel && sel != c) { grabbuttons(sel, False); XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]); @@ -716,9 +688,9 @@ focusnext(const char *arg) { if(!sel) return; - for(c = sel->next; c && !isvisible(c); c = c->next); + for(c = sel->next; c && !isvisible(c, arg ? sel->tags : NULL); c = c->next); if(!c) - for(c = clients; c && !isvisible(c); c = c->next); + for(c = clients; c && !isvisible(c, arg ? sel->tags : NULL); c = c->next); if(c) { focus(c); restack(); @@ -731,10 +703,10 @@ focusprev(const char *arg) { if(!sel) return; - for(c = sel->prev; c && !isvisible(c); c = c->prev); + for(c = sel->prev; c && !isvisible(c, arg ? sel->tags : NULL); c = c->prev); if(!c) { for(c = clients; c && c->next; c = c->next); - for(; c && !isvisible(c); c = c->prev); + for(; c && !isvisible(c, arg ? sel->tags : NULL); c = c->prev); } if(c) { focus(c); @@ -809,21 +781,21 @@ grabbuttons(Client *c, Bool focused) { int i, j; unsigned int buttons[] = { Button1, Button2, Button3 }; unsigned int modifiers[] = { MODKEY, MODKEY|LockMask, MODKEY|numlockmask, - MODKEY|numlockmask|LockMask} ; + MODKEY|numlockmask|LockMask} ; XUngrabButton(dpy, AnyButton, AnyModifier, c->win); if(focused) for(i = 0; i < LENGTH(buttons); i++) for(j = 0; j < LENGTH(modifiers); j++) XGrabButton(dpy, buttons[i], modifiers[j], c->win, False, - BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); + BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); else XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); + BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); } void -grabkeys(void) { +grabkeys(void) { unsigned int i, j; KeyCode code; XModifierKeymap *modmap; @@ -881,10 +853,8 @@ initfont(const char *fontstr) { font_extents = XExtentsOfFontSet(dc.font.set); n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { - if(dc.font.ascent < (*xfonts)->ascent) - dc.font.ascent = (*xfonts)->ascent; - if(dc.font.descent < (*xfonts)->descent) - dc.font.descent = (*xfonts)->descent; + dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); + dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent); xfonts++; } } @@ -937,11 +907,13 @@ isurgent(unsigned int t) { } Bool -isvisible(Client *c) { +isvisible(Client *c, Bool *cmp) { unsigned int i; + if(!cmp) + cmp = tagset[seltags]; for(i = 0; i < LENGTH(tags); i++) - if(c->tags[i] && seltags[i]) + if(c->tags[i] && cmp[i]) return True; return False; } @@ -996,8 +968,8 @@ manage(Window w, XWindowAttributes *wa) { /* geometry */ c->x = wa->x; c->y = wa->y; - c->w = wa->width; - c->h = wa->height; + c->w = c->fw = wa->width; + c->h = c->fh = wa->height; c->oldbw = wa->border_width; if(c->w == sw && c->h == sh) { c->x = sx; @@ -1009,12 +981,12 @@ manage(Window w, XWindowAttributes *wa) { c->x = wx + ww - c->w - 2 * c->bw; if(c->y + c->h + 2 * c->bw > wy + wh) c->y = wy + wh - c->h - 2 * c->bw; - if(c->x < wx) - c->x = wx; - if(c->y < wy) - c->y = wy; + c->x = MAX(c->x, wx); + c->y = MAX(c->y, wy); c->bw = BORDERPX; } + c->fx = c->x; + c->fy = c->y; wc.border_width = c->bw; XConfigureWindow(dpy, w, CWBorderWidth, &wc); @@ -1068,8 +1040,8 @@ monocle(void) { Client *c; for(c = clients; c; c = c->next) - if(isvisible(c)) - resize(c, mox, moy, mow - 2 * c->bw, moh - 2 * c->bw, RESIZEHINTS); + if((lt->isfloating || !c->isfloating) && isvisible(c, NULL)) + resize(c, wx, wy, ww - 2 * c->bw, wh - 2 * c->bw, RESIZEHINTS); } void @@ -1082,7 +1054,7 @@ movemouse(Client *c) { ocx = nx = c->x; ocy = ny = c->y; if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove], CurrentTime) != GrabSuccess) + None, cursor[CurMove], CurrentTime) != GrabSuccess) return; XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui); for(;;) { @@ -1110,8 +1082,11 @@ movemouse(Client *c) { ny = wy + wh - c->h - 2 * c->bw; if(!c->isfloating && !lt->isfloating && (abs(nx - c->x) > SNAP || abs(ny - c->y) > SNAP)) togglefloating(NULL); - if((lt->isfloating) || c->isfloating) + if(lt->isfloating || c->isfloating) { + c->fx = nx; + c->fy = ny; resize(c, nx, ny, c->w, c->h, False); + } break; } } @@ -1119,7 +1094,7 @@ movemouse(Client *c) { Client * nexttiled(Client *c) { - for(; c && (c->isfloating || !isvisible(c)); c = c->next); + for(; c && (c->isfloating || !isvisible(c, NULL)); c = c->next); return c; } @@ -1161,27 +1136,13 @@ quit(const char *arg) { } void -reapply(const char *arg) { - static Bool zerotags[LENGTH(tags)] = { 0 }; - Client *c; - - for(c = clients; c; c = c->next) { - memcpy(c->tags, zerotags, sizeof zerotags); - applyrules(c); - } - arrange(); -} - -void resize(Client *c, int x, int y, int w, int h, Bool sizehints) { XWindowChanges wc; if(sizehints) { /* set minimum possible */ - if(w < 1) - w = 1; - if(h < 1) - h = 1; + w = MAX(1, w); + h = MAX(1, h); /* temporarily remove base dimensions */ w -= c->basew; @@ -1189,11 +1150,10 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) { /* adjust for aspect limits */ if(c->minax != c->maxax && c->minay != c->maxay - && c->minax > 0 && c->maxax > 0 && c->minay > 0 && c->maxay > 0) - { - if (w * c->maxay > h * c->maxax) + && c->minax > 0 && c->maxax > 0 && c->minay > 0 && c->maxay > 0) { + if(w * c->maxay > h * c->maxax) w = h * c->maxax / c->maxay; - else if (w * c->minay < h * c->minax) + else if(w * c->minay < h * c->minax) h = w * c->minay / c->minax; } @@ -1207,14 +1167,14 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) { w += c->basew; h += c->baseh; - if(c->minw > 0 && w < c->minw) - w = c->minw; - if(c->minh > 0 && h < c->minh) - h = c->minh; - if(c->maxw > 0 && w > c->maxw) - w = c->maxw; - if(c->maxh > 0 && h > c->maxh) - h = c->maxh; + w = MAX(w, c->minw); + h = MAX(h, c->minh); + + if (c->maxw) + w = MIN(w, c->maxw); + + if (c->maxh) + h = MIN(h, c->maxh); } if(w <= 0 || h <= 0) return; @@ -1248,7 +1208,7 @@ resizemouse(Client *c) { ocx = c->x; ocy = c->y; if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize], CurrentTime) != GrabSuccess) + None, cursor[CurResize], CurrentTime) != GrabSuccess) return; XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); for(;;) { @@ -1267,14 +1227,18 @@ resizemouse(Client *c) { break; case MotionNotify: XSync(dpy, False); - if((nw = ev.xmotion.x - ocx - 2 * c->bw + 1) <= 0) - nw = 1; - if((nh = ev.xmotion.y - ocy - 2 * c->bw + 1) <= 0) - nh = 1; - if(!c->isfloating && !lt->isfloating && (abs(nw - c->w) > SNAP || abs(nh - c->h) > SNAP)) + nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1); + nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1); + if(!c->isfloating && !lt->isfloating && (abs(nw - c->w) > SNAP || abs(nh - c->h) > SNAP)) { + c->fx = c->x; + c->fy = c->y; togglefloating(NULL); - if((lt->isfloating) || c->isfloating) + } + if((lt->isfloating) || c->isfloating) { resize(c, c->x, c->y, nw, nh, True); + c->fw = nw; + c->fh = nh; + } break; } } @@ -1294,16 +1258,11 @@ restack(void) { if(!lt->isfloating) { wc.stack_mode = Below; wc.sibling = barwin; - if(!sel->isfloating) { - XConfigureWindow(dpy, sel->win, CWSibling|CWStackMode, &wc); - wc.sibling = sel->win; - } - for(c = nexttiled(clients); c; c = nexttiled(c->next)) { - if(c == sel) - continue; - XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); - wc.sibling = c->win; - } + for(c = stack; c; c = c->snext) + if(!c->isfloating && isvisible(c, NULL)) { + XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc); + wc.sibling = c->win; + } } XSync(dpy, False); while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); @@ -1379,7 +1338,7 @@ scan(void) { if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { for(i = 0; i < num; i++) { if(!XGetWindowAttributes(dpy, wins[i], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) + || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) continue; if(wa.map_state == IsViewable || getstate(wins[i]) == IconicState) manage(wins[i], &wa); @@ -1388,7 +1347,7 @@ scan(void) { if(!XGetWindowAttributes(dpy, wins[i], &wa)) continue; if(XGetTransientForHint(dpy, wins[i], &d1) - && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) + && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)) manage(wins[i], &wa); } } @@ -1405,49 +1364,6 @@ setclientstate(Client *c, long state) { } void -setgeom(const char *arg) { - unsigned int i; - - if(!arg) { - if(++geom == &geoms[LENGTH(geoms)]) - geom = &geoms[0]; - } - else { - for(i = 0; i < LENGTH(geoms); i++) - if(!strcmp(geoms[i].symbol, arg)) - break; - if(i == LENGTH(geoms)) - return; - geom = &geoms[i]; - } - geom->apply(); - updatebarpos(); - arrange(); -} - -void -setlayout(const char *arg) { - unsigned int i; - - if(!arg) { - if(++lt == &layouts[LENGTH(layouts)]) - lt = &layouts[0]; - } - else { - for(i = 0; i < LENGTH(layouts); i++) - if(!strcmp(arg, layouts[i].symbol)) - break; - if(i == LENGTH(layouts)) - return; - lt = &layouts[i]; - } - if(sel) - arrange(); - else - drawbar(); -} - -void setmfact(const char *arg) { double d; @@ -1463,7 +1379,8 @@ setmfact(const char *arg) { return; mfact = d; } - setgeom(geom->symbol); + updategeom(); + arrange(); } void @@ -1475,16 +1392,13 @@ setup(void) { screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); initfont(FONT); - - /* apply default geometry */ sx = 0; sy = 0; sw = DisplayWidth(dpy, screen); sh = DisplayHeight(dpy, screen); bh = dc.font.height + 2; mfact = MFACT; - geom = &geoms[0]; - geom->apply(); + updategeom(); /* init atoms */ wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); @@ -1515,23 +1429,14 @@ setup(void) { XSetFont(dpy, dc.gc, dc.font.xfont->fid); /* init tags */ - seltags = emallocz(TAGSZ); - prevtags = emallocz(TAGSZ); - seltags[0] = prevtags[0] = True; - - /* init layouts */ - lt = &layouts[0]; + tagset[0] = emallocz(TAGSZ); + tagset[1] = emallocz(TAGSZ); + tagset[0][0] = tagset[1][0] = True; /* init bar */ for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { w = textw(layouts[i].symbol); - if(w > blw) - blw = w; - } - for(bgw = i = 0; LENGTH(geoms) > 1 && i < LENGTH(geoms); i++) { - w = textw(geoms[i].symbol); - if(w > bgw) - bgw = w; + blw = MAX(blw, w); } wa.override_redirect = 1; @@ -1539,8 +1444,8 @@ setup(void) { wa.event_mask = ButtonPressMask|ExposureMask; barwin = XCreateWindow(dpy, root, bx, by, bw, bh, 0, DefaultDepth(dpy, screen), - CopyFromParent, DefaultVisual(dpy, screen), - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); XDefineCursor(dpy, barwin, cursor[CurNormal]); XMapRaised(dpy, barwin); strcpy(stext, "dwm-"VERSION); @@ -1592,7 +1497,7 @@ tag(const char *arg) { if(!sel) return; for(i = 0; i < LENGTH(tags); i++) - sel->tags[i] = (NULL == arg); + sel->tags[i] = (arg == NULL); sel->tags[idxoftag(arg)] = True; arrange(); } @@ -1645,7 +1550,7 @@ tilemaster(unsigned int n) { Client *c = nexttiled(clients); if(n == 1) - tileresize(c, mox, moy, mow - 2 * c->bw, moh - 2 * c->bw); + tileresize(c, wx, wy, ww - 2 * c->bw, wh - 2 * c->bw); else tileresize(c, mx, my, mw - 2 * c->bw, mh - 2 * c->bw); return c; @@ -1697,6 +1602,28 @@ togglefloating(const char *arg) { } void +togglelayout(const char *arg) { + unsigned int i; + + if(!arg) { + if(++lt == &layouts[LENGTH(layouts)]) + lt = &layouts[0]; + } + else { + for(i = 0; i < LENGTH(layouts); i++) + if(!strcmp(arg, layouts[i].symbol)) + break; + if(i == LENGTH(layouts)) + return; + lt = &layouts[i]; + } + if(sel) + arrange(); + else + drawbar(); +} + +void toggletag(const char *arg) { unsigned int i, j; @@ -1715,10 +1642,10 @@ toggleview(const char *arg) { unsigned int i, j; i = idxoftag(arg); - seltags[i] = !seltags[i]; - for(j = 0; j < LENGTH(tags) && !seltags[j]; j++); + tagset[seltags][i] = !tagset[seltags][i]; + for(j = 0; j < LENGTH(tags) && !tagset[seltags][j]; j++); if(j == LENGTH(tags)) - seltags[i] = True; /* at least one tag must be viewed */ + tagset[seltags][i] = True; /* at least one tag must be viewed */ arrange(); } @@ -1763,8 +1690,7 @@ unmapnotify(XEvent *e) { } void -updatebarpos(void) { - +updatebar(void) { if(dc.drawable != 0) XFreePixmap(dpy, dc.drawable); dc.drawable = XCreatePixmap(dpy, root, bw, bh, DefaultDepth(dpy, screen)); @@ -1772,6 +1698,33 @@ updatebarpos(void) { } void +updategeom(void) { + + /* bar geometry */ + bx = 0; + by = 0; + bw = sw; + + /* window area geometry */ + wx = sx; + wy = sy + bh; + ww = sw; + wh = sh - bh; + + /* master area geometry */ + mx = wx; + my = wy; + mw = mfact * ww; + mh = wh; + + /* tile area geometry */ + tx = mx + mw; + ty = wy; + tw = ww - mw; + th = wh; +} + +void updatesizehints(Client *c) { long msize; XSizeHints size; @@ -1842,28 +1795,17 @@ updatewmhints(Client *c) { } } - void view(const char *arg) { - unsigned int i; - - for(i = 0; i < LENGTH(tags); i++) - tmp[i] = (NULL == arg); - tmp[idxoftag(arg)] = True; - - if(memcmp(seltags, tmp, TAGSZ) != 0) { - memcpy(prevtags, seltags, TAGSZ); - memcpy(seltags, tmp, TAGSZ); - arrange(); - } + seltags ^= 1; /* toggle sel tagset */ + memset(tagset[seltags], (NULL == arg), TAGSZ); + tagset[seltags][idxoftag(arg)] = True; + arrange(); } void viewprevtag(const char *arg) { - - memcpy(tmp, seltags, TAGSZ); - memcpy(seltags, prevtags, TAGSZ); - memcpy(prevtags, tmp, TAGSZ); + seltags ^= 1; /* toggle sel tagset */ arrange(); } @@ -1878,11 +1820,12 @@ xerror(Display *dpy, XErrorEvent *ee) { || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable) || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable) || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch) + || (ee->request_code == X_GrabButton && ee->error_code == BadAccess) || (ee->request_code == X_GrabKey && ee->error_code == BadAccess) || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) return 0; fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); + ee->request_code, ee->error_code); return xerrorxlib(dpy, ee); /* may call exit */ } @@ -1903,14 +1846,14 @@ void zoom(const char *arg) { Client *c = sel; - if(!sel || lt->isfloating || sel->isfloating) - return; if(c == nexttiled(clients)) - if(!(c = nexttiled(c->next))) + if(!c || !(c = nexttiled(c->next))) return; - detach(c); - attach(c); - focus(c); + if(!lt->isfloating && !sel->isfloating) { + detach(c); + attach(c); + focus(c); + } arrange(); }