JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
applied Peter Hartlich's patch regarding aspect calculation with slight modifications
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index 8591a7d..ae2952b 100644 (file)
--- a/dwm.c
+++ b/dwm.c
@@ -24,7 +24,6 @@
  * To understand everything else, start reading main().
  */
 #include <errno.h>
-#include <locale.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -202,8 +201,10 @@ static void zoom(const Arg *arg);
 
 /* variables */
 static char stext[256];
-static int screen, sx, sy, sw, sh;
-static int by, bh, blw, wx, wy, ww, wh;
+static int screen;
+static int sx, sy, sw, sh; /* X display screen geometry x, y, width, height */ 
+static int by, bh, blw;    /* bar geometry y, height and layout symbol width */
+static int wx, wy, ww, wh; /* window area geometry x, y, width, height, bar excluded */
 static unsigned int seltags = 0, sellt = 0;
 static int (*xerrorxlib)(Display *, XErrorEvent *);
 static unsigned int numlockmask = 0;
@@ -567,24 +568,23 @@ drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
 
 void
 drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
+       char buf[256];
        int i, x, y, h, 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;
        olen = strlen(text);
-       len = MIN(olen, sizeof buf);
-       memcpy(buf, text, len);
        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 */
-       for(; len && (i = textnw(buf, len)) > dc.w - h; len--);
+       for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
        if(!len)
                return;
+       memcpy(buf, text, len);
        if(len < olen)
                for(i = len; i && i > len - 3; buf[--i] = '.');
        XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
@@ -751,25 +751,27 @@ grabbuttons(Client *c, Bool focused) {
 void
 grabkeys(void) {
        unsigned int i, j;
-       unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
-       KeyCode code;
        XModifierKeymap *modmap;
 
-       /* init modifier map */
+       /* update modifier map */
        modmap = XGetModifierMapping(dpy);
        for(i = 0; i < 8; i++)
-               for(j = 0; j < modmap->max_keypermod; j++) {
+               for(j = 0; j < modmap->max_keypermod; j++)
                        if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock))
                                numlockmask = (1 << i);
-               }
        XFreeModifiermap(modmap);
 
-       XUngrabKey(dpy, AnyKey, AnyModifier, root);
-       for(i = 0; i < LENGTH(keys); i++) {
-               code = XKeysymToKeycode(dpy, keys[i].keysym);
-               for(j = 0; j < LENGTH(modifiers); j++)
-                       XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, True,
-                                GrabModeAsync, GrabModeAsync);
+       { /* grab keys */
+               unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
+               KeyCode code;
+
+               XUngrabKey(dpy, AnyKey, AnyModifier, root);
+               for(i = 0; i < LENGTH(keys); i++) {
+                       code = XKeysymToKeycode(dpy, keys[i].keysym);
+                       for(j = 0; j < LENGTH(modifiers); j++)
+                               XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, True,
+                                        GrabModeAsync, GrabModeAsync);
+               }
        }
 }
 
@@ -779,8 +781,6 @@ initfont(const char *fontstr) {
        int i, n;
 
        missing = NULL;
-       if(dc.font.set)
-               XFreeFontSet(dpy, dc.font.set);
        dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
        if(missing) {
                while(n--)
@@ -865,7 +865,7 @@ killclient(const Arg *arg) {
 void
 manage(Window w, XWindowAttributes *wa) {
        Client *c, *t = NULL;
-       Window trans;
+       Window trans = None;
        XWindowChanges wc;
 
        if(!(c = calloc(1, sizeof(Client))))
@@ -909,7 +909,7 @@ manage(Window w, XWindowAttributes *wa) {
        else
                applyrules(c);
        if(!c->isfloating)
-               c->isfloating = trans || c->isfixed;
+               c->isfloating = trans != None || c->isfixed;
        if(c->isfloating)
                XRaiseWindow(dpy, c->win);
        attach(c);
@@ -961,18 +961,15 @@ movemouse(const Arg *arg) {
        if(!(c = sel))
                return;
        restack();
-       ocx = nx = c->x;
-       ocy = ny = c->y;
+       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, &x, &y, &di, &di, &dui);
-       for(;;) {
+       do {
                XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
                switch (ev.type) {
-               case ButtonRelease:
-                       XUngrabPointer(dpy, CurrentTime);
-                       return;
                case ConfigureRequest:
                case Expose:
                case MapRequest:
@@ -1000,6 +997,8 @@ movemouse(const Arg *arg) {
                        break;
                }
        }
+       while(ev.type != ButtonRelease);
+       XUngrabPointer(dpy, CurrentTime);
 }
 
 Client *
@@ -1047,23 +1046,34 @@ quit(const Arg *arg) {
 
 void
 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
+       float a;
        XWindowChanges wc;
 
        if(sizehints) {
+               /* see last two sentences in ICCCM 4.1.2.3 */
+               Bool baseismin = c->basew == c->minw && c->baseh == c->minh;
+
                /* set minimum possible */
                w = MAX(1, w);
                h = MAX(1, h);
 
-               /* temporarily remove base dimensions */
-               w -= c->basew;
-               h -= c->baseh;
+               if(!baseismin) { /* temporarily remove base dimensions */
+                       w -= c->basew;
+                       h -= c->baseh;
+               }
 
                /* adjust for aspect limits */
                if(c->mina > 0 && c->maxa > 0) {
-                       if(c->maxa < (float) w/h)
+                       a = (float) w/h;
+                       if(a > c->maxa)
                                w = h * c->maxa;
-                       else if(c->mina > (float) h/w)
-                               h = w * c->mina;
+                       else if(a < c->mina)
+                               h = w / c->mina;
+               }
+
+               if(baseismin) { /* increment calculation requires this */
+                       w -= c->basew;
+                       h -= c->baseh;
                }
 
                /* adjust for increment value */
@@ -1128,15 +1138,9 @@ resizemouse(const Arg *arg) {
        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(;;) {
-               XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask , &ev);
+       do {
+               XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
                switch(ev.type) {
-               case ButtonRelease:
-                       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
-                                       c->w + c->bw - 1, c->h + c->bw - 1);
-                       XUngrabPointer(dpy, CurrentTime);
-                       while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
-                       return;
                case ConfigureRequest:
                case Expose:
                case MapRequest:
@@ -1158,6 +1162,10 @@ resizemouse(const Arg *arg) {
                        break;
                }
        }
+       while(ev.type != ButtonRelease);
+       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
+       XUngrabPointer(dpy, CurrentTime);
+       while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
 }
 
 void
@@ -1246,10 +1254,9 @@ run(void) {
 void
 scan(void) {
        unsigned int i, num;
-       Window *wins, d1, d2;
+       Window d1, d2, *wins = NULL;
        XWindowAttributes wa;
 
-       wins = NULL;
        if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
                for(i = 0; i < num; i++) {
                        if(!XGetWindowAttributes(dpy, wins[i], &wa)
@@ -1265,9 +1272,9 @@ scan(void) {
                        && (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
                                manage(wins[i], &wa);
                }
+               if(wins)
+                       XFree(wins);
        }
-       if(wins)
-               XFree(wins);
 }
 
 void
@@ -1377,8 +1384,6 @@ setup(void) {
        XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
        XSelectInput(dpy, root, wa.event_mask);
 
-
-       /* grab keys */
        grabkeys();
 }
 
@@ -1473,8 +1478,12 @@ togglefloating(const Arg *arg) {
 
 void
 toggletag(const Arg *arg) {
-       unsigned int mask = sel->tags ^ (arg->ui & TAGMASK);
+       unsigned int mask;
 
+       if (!sel)
+               return;
+       
+       mask = sel->tags ^ (arg->ui & TAGMASK);
        if(sel && mask) {
                sel->tags = mask;
                arrange();
@@ -1639,10 +1648,10 @@ updatewmhints(Client *c) {
 
 void
 view(const Arg *arg) {
-       if(arg && (arg->ui & TAGMASK) == tagset[seltags])
+       if((arg->ui & TAGMASK) == tagset[seltags])
                return;
        seltags ^= 1; /* toggle sel tagset */
-       if(arg && (arg->ui & TAGMASK))
+       if(arg->ui & TAGMASK)
                tagset[seltags] = arg->ui & TAGMASK;
        clearurgent();
        arrange();
@@ -1703,7 +1712,7 @@ main(int argc, char *argv[]) {
        else if(argc != 1)
                die("usage: dwm [-v]\n");
 
-       if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
+       if(!XSupportsLocale())
                fprintf(stderr, "warning: no locale support\n");
 
        if(!(dpy = XOpenDisplay(0)))