]> git.corax.cc Git - dwm/commitdiff
Add struct rect type for the common (x, y, w, h) membership pattern
authorMatthias Kruk <matthias.kruk@miraclelinux.com>
Sat, 13 Mar 2021 02:31:34 +0000 (11:31 +0900)
committerMatthias Kruk <matthias.kruk@miraclelinux.com>
Sat, 13 Mar 2021 02:31:34 +0000 (11:31 +0900)
Several types contain members for coordinates of a rectangle on the
screen. This commit adds the struct rect type to simplify this common
pattern.

dwm.c

diff --git a/dwm.c b/dwm.c
index 3a43fb8f23c1051cc027c7f4e02a8d39c73dec72..63ffdbc9bbbf0c92ac58ae5cebfde58371c39989 100755 (executable)
--- a/dwm.c
+++ b/dwm.c
@@ -47,8 +47,6 @@
 
 #define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
 #define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
-#define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
-                                * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
 #define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
 #define LENGTH(X)               (sizeof X / sizeof X[0])
 #ifndef MAX
@@ -58,8 +56,6 @@
 #define MIN(A, B)               ((A) < (B) ? (A) : (B))
 #endif
 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
-#define WIDTH(X)                ((X)->w + 2 * (X)->bw)
-#define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
 #define TAGMASK                 ((1 << LENGTH(tags)) - 1)
 #define TEXTW(X)                (textnw(X, strlen(X)) + dc.font.height)
 
@@ -148,18 +144,19 @@ struct button {
        const union arg arg;
 };
 
-struct client {
-       char name[256];
-       float mina;
-       float maxa;
+struct rect {
        int x;
        int y;
        int w;
        int h;
-       int oldx;
-       int oldy;
-       int oldw;
-       int oldh;
+};
+
+struct client {
+       char name[256];
+       float mina;
+       float maxa;
+       struct rect geom;
+       struct rect old_geom;
        int basew;
        int baseh;
        int incw;
@@ -168,7 +165,10 @@ struct client {
        int maxh;
        int minw;
        int minh;
-       int bw, oldbw;
+       struct {
+               int w;
+               int oldw;
+       } border;
        unsigned int tags;
        Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
        struct client *next;
@@ -178,10 +178,7 @@ struct client {
 };
 
 struct draw_context {
-       int x;
-       int y;
-       int w;
-       int h;
+       struct rect geom;
 
        unsigned long norm[ColLast];
        unsigned long sel[ColLast];
@@ -220,14 +217,9 @@ struct monitor {
        int nmaster;
        int num;
        int by;
-       int mx;
-       int my;
-       int mw;
-       int mh; /* display area */
-       int wx;
-       int wy;
-       int ww;
-       int wh; /* window area */
+       struct rect geom;
+       struct rect win_geom;
+
        unsigned int seltags;
        unsigned int sellt;
        unsigned int tagset[2];
@@ -469,10 +461,22 @@ void applyrules(struct client *c)
        return;
 }
 
+static inline int client_get_width(struct client *client)
+{
+       return(client->geom.w + 2 * client->border.w);
+}
+
+static inline int client_get_height(struct client *client)
+{
+       return(client->geom.h + 2 * client->border.w);
+}
+
 Bool applysizehints(struct client *c, int *x, int *y, int *w, int *h, Bool interact)
 {
        Bool baseismin;
-        struct monitor *m = c->mon;
+        struct monitor *m;
+
+       m = c->mon;
 
        /* set minimum possible */
        *w = MAX(1, *w);
@@ -480,29 +484,29 @@ Bool applysizehints(struct client *c, int *x, int *y, int *w, int *h, Bool inter
 
        if(interact) {
                if(*x > sw) {
-                       *x = sw - WIDTH(c);
+                       *x = sw - client_get_width(c);
                }
                if(*y > sh) {
-                       *y = sh - HEIGHT(c);
+                       *y = sh - client_get_height(c);
                }
-               if(*x + *w + 2 * c->bw < 0) {
+               if(*x + *w + 2 * c->border.w < 0) {
                        *x = 0;
                }
-               if(*y + *h + 2 * c->bw < 0) {
+               if(*y + *h + 2 * c->border.w < 0) {
                        *y = 0;
                }
        } else {
-               if(*x >= m->wx + m->ww) {
-                       *x = m->wx + m->ww - WIDTH(c);
+               if(*x >= m->win_geom.x + m->win_geom.w) {
+                       *x = m->win_geom.x + m->win_geom.w - client_get_width(c);
                }
-               if(*y >= m->wy + m->wh) {
-                       *y = m->wy + m->wh - HEIGHT(c);
+               if(*y >= m->win_geom.y + m->win_geom.h) {
+                       *y = m->win_geom.y + m->win_geom.h - client_get_height(c);
                }
-               if(*x + *w + 2 * c->bw <= m->wx) {
-                       *x = m->wx;
+               if(*x + *w + 2 * c->border.w <= m->win_geom.x) {
+                       *x = m->win_geom.x;
                }
-               if(*y + *h + 2 * c->bw <= m->wy) {
-                       *y = m->wy;
+               if(*y + *h + 2 * c->border.w <= m->win_geom.y) {
+                       *y = m->win_geom.y;
                }
        }
 
@@ -556,7 +560,7 @@ Bool applysizehints(struct client *c, int *x, int *y, int *w, int *h, Bool inter
                }
        }
 
-       return(*x != c->x || *y != c->y || *w != c->w || *h != c->h);
+       return(*x != c->geom.x || *y != c->geom.y || *w != c->geom.w || *h != c->geom.h);
 }
 
 void arrange(struct monitor *m)
@@ -638,7 +642,7 @@ void buttonpress(XEvent *e)
                        arg.ui = 1 << i;
                } else if(ev->x < x + blw) {
                        click = ClkLtSymbol;
-               } else if(ev->x > selmon->ww - TEXTW(stext)) {
+               } else if(ev->x > selmon->win_geom.w - TEXTW(stext)) {
                        click = ClkStatusText;
                } else {
                        click = ClkWinTitle;
@@ -754,11 +758,16 @@ void clientmessage(XEvent *e)
                        c->next = systray->icons;
                        systray->icons = c;
                        XGetWindowAttributes(dpy, c->win, &wa);
-                       c->x = c->oldx = c->y = c->oldy = 0;
-                       c->w = c->oldw = wa.width;
-                       c->h = c->oldh = wa.height;
-                       c->oldbw = wa.border_width;
-                       c->bw = 0;
+
+                       c->geom.x = 0;
+                       c->geom.y = 0;
+                       c->geom.w = wa.width;
+                       c->geom.h = wa.height;
+                       memcpy(&c->old_geom, &c->geom, sizeof(c->old_geom));
+
+                       c->border.oldw = wa.border_width;
+                       c->border.w = 0;
+
                        c->isfloating = True;
                        /* reuse tags field as mapped status */
                        c->tags = 1;
@@ -816,11 +825,11 @@ void configure(struct client *c)
        ce.display = dpy;
        ce.event = c->win;
        ce.window = c->win;
-       ce.x = c->x;
-       ce.y = c->y;
-       ce.width = c->w;
-       ce.height = c->h;
-       ce.border_width = c->bw;
+       ce.x = c->geom.x;
+       ce.y = c->geom.y;
+       ce.width = c->geom.w;
+       ce.height = c->geom.h;
+       ce.border_width = c->border.w;
        ce.above = None;
        ce.override_redirect = False;
        XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
@@ -869,39 +878,39 @@ void configurerequest(XEvent *e)
 
        if((c = wintoclient(ev->window))) {
                if(ev->value_mask & CWBorderWidth) {
-                       c->bw = ev->border_width;
+                       c->border.w = ev->border_width;
                } else if(c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
                        m = c->mon;
 
                        if(ev->value_mask & CWX) {
-                               c->oldx = c->x;
-                               c->x = m->mx + ev->x;
+                               c->old_geom.x = c->geom.x;
+                               c->geom.x = m->geom.x + ev->x;
                        }
                        if(ev->value_mask & CWY) {
-                               c->oldy = c->y;
-                               c->y = m->my + ev->y;
+                               c->old_geom.y = c->geom.y;
+                               c->geom.y = m->geom.y + ev->y;
                        }
                        if(ev->value_mask & CWWidth) {
-                               c->oldw = c->w;
-                               c->w = ev->width;
+                               c->old_geom.w = c->geom.w;
+                               c->geom.w = ev->width;
                        }
                        if(ev->value_mask & CWHeight) {
-                               c->oldh = c->h;
-                               c->h = ev->height;
+                               c->old_geom.h = c->geom.h;
+                               c->geom.h = ev->height;
                        }
 
-                       if((c->x + c->w) > m->mx + m->mw && c->isfloating) {
-                               c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */
+                       if((c->geom.x + c->geom.w) > m->geom.x + m->geom.w && c->isfloating) {
+                               c->geom.x = m->geom.x + (m->geom.w / 2 - client_get_width(c) / 2); /* center in x direction */
                        }
-                       if((c->y + c->h) > m->my + m->mh && c->isfloating) {
-                               c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
+                       if((c->geom.y + c->geom.h) > m->geom.y + m->geom.h && c->isfloating) {
+                               c->geom.y = m->geom.y + (m->geom.h / 2 - client_get_height(c) / 2); /* center in y direction */
                        }
                        if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight))) {
                                configure(c);
                        }
 
                        if(ISVISIBLE(c)) {
-                               XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
+                               XMoveResizeWindow(dpy, c->win, c->geom.x, c->geom.y, c->geom.w, c->geom.h);
                        }
                } else {
                        configure(c);
@@ -1028,38 +1037,38 @@ void drawbar(struct monitor *m)
                }
        }
 
-       dc.x = 0;
+       dc.geom.x = 0;
 
        for(i = 0; i < LENGTH(tags); i++) {
-               dc.w = TEXTW(tags[i]);
+               dc.geom.w = TEXTW(tags[i]);
                col = m->tagset[m->seltags] & 1 << i ? dc.sel : dc.norm;
                drawtext(tags[i], col, urg & 1 << i);
                drawsquare(m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
                           occ & 1 << i, urg & 1 << i, col);
-               dc.x += dc.w;
+               dc.geom.x += dc.geom.w;
        }
 
-       dc.w = blw = TEXTW(m->ltsymbol);
+       dc.geom.w = blw = TEXTW(m->ltsymbol);
        drawtext(m->ltsymbol, dc.norm, False);
-       dc.x += dc.w;
-       x = dc.x;
+       dc.geom.x += dc.geom.w;
+       x = dc.geom.x;
 
-       dc.w = TEXTW(stext);
-       dc.x = m->ww - dc.w;
+       dc.geom.w = TEXTW(stext);
+       dc.geom.x = m->win_geom.w - dc.geom.w;
 
        if(showsystray && m == selmon) {
-               dc.x -= getsystraywidth();
+               dc.geom.x -= getsystraywidth();
        }
 
-       if(dc.x < x) {
-               dc.x = x;
-               dc.w = m->ww - x;
+       if(dc.geom.x < x) {
+               dc.geom.x = x;
+               dc.geom.w = m->win_geom.w - x;
        }
 
        drawtext(stext, dc.norm, False);
 
-       if((dc.w = dc.x - x) > bh) {
-               dc.x = x;
+       if((dc.geom.w = dc.geom.x - x) > bh) {
+               dc.geom.x = x;
 
                if(m->sel) {
                        col = m == selmon ? dc.sel : dc.norm;
@@ -1070,7 +1079,7 @@ void drawbar(struct monitor *m)
                }
        }
 
-       XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
+       XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->win_geom.w, bh, 0, 0);
        XSync(dpy, False);
 
        return;
@@ -1096,9 +1105,9 @@ void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]
        XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
        x = (dc.font.ascent + dc.font.descent + 2) / 4;
        if(filled) {
-               XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1);
+               XFillRectangle(dpy, dc.drawable, dc.gc, dc.geom.x + 1, dc.geom.y + 1, x + 1, x + 1);
        } else if(empty) {
-               XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x);
+               XDrawRectangle(dpy, dc.drawable, dc.gc, dc.geom.x + 1, dc.geom.y + 1, x, x);
        }
 
        return;
@@ -1110,7 +1119,7 @@ void drawtext(const char *text, unsigned long col[ColLast], Bool invert)
        int i, x, y, h, len, olen;
 
        XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
-       XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h);
+       XFillRectangle(dpy, dc.drawable, dc.gc, dc.geom.x, dc.geom.y, dc.geom.w, dc.geom.h);
 
        if(!text) {
                return;
@@ -1118,12 +1127,12 @@ void drawtext(const char *text, unsigned long col[ColLast], Bool invert)
 
        olen = strlen(text);
        h = dc.font.ascent + dc.font.descent;
-       y = dc.y + (dc.h / 2) - (h / 2);
-       x = dc.x + (h / 2);
+       y = dc.geom.y + (dc.geom.h / 2) - (h / 2);
+       x = dc.geom.x + (h / 2);
 
        /* shorten text if necessary (this could wreak havoc with pango markup but fortunately
           dc.w is adjusted to the width of the status text and not the other way around) */
-       for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
+       for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.geom.w - h; len--);
 
        if(!len) {
                return;
@@ -1367,35 +1376,48 @@ long getstate(Window w)
 
 unsigned int getsystraywidth(void)
 {
-       unsigned int w = 0;
-        struct client *i;
+       struct client *client;
+       unsigned int width;
+
+       width = 0;
+
        if(showsystray) {
-               for(i = systray->icons; i; w += i->w + systrayspacing, i = i->next) ;
+               for(client = systray->icons; client; client = client->next) {
+                       width += client->geom.w + systrayspacing;
+               }
        }
 
-       return(w ? w + systrayspacing : 1);
+       return(width ? width + systrayspacing : 1);
 }
 
 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size)
 {
-       char **list = NULL;
-       int n;
        XTextProperty name;
+       char **list;
+       int n;
+
+       list = NULL;
+
+       if(!text || size == 0) {
+               return(False);
+       }
 
-       if(!text || size == 0)
-               return False;
        text[0] = '\0';
        XGetTextProperty(dpy, w, &name, atom);
-       if(!name.nitems)
-               return False;
-       if(name.encoding == XA_STRING)
+
+       if(!name.nitems) {
+               return(False);
+       }
+
+       if(name.encoding == XA_STRING) {
                strncpy(text, (char *)name.value, size - 1);
-       else {
+       else {
                if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
                        strncpy(text, *list, size - 1);
                        XFreeStringList(list);
                }
        }
+
        text[size - 1] = '\0';
        XFree(name.value);
 
@@ -1484,11 +1506,14 @@ void initfont(const char *fontstr)
 }
 
 #ifdef XINERAMA
-static Bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
+static Bool isuniquegeom(XineramaScreenInfo *unique, size_t n,
+                        XineramaScreenInfo *info)
 {
        while(n--) {
-               if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org
-                  && unique[n].width == info->width && unique[n].height == info->height) {
+               if(unique[n].x_org == info->x_org &&
+                  unique[n].y_org == info->y_org &&
+                  unique[n].width == info->width &&
+                  unique[n].height == info->height) {
                        return(False);
                }
        }
@@ -1505,10 +1530,11 @@ void keypress(XEvent *e)
 
        ev = &e->xkey;
        keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
+
        for(i = 0; i < LENGTH(keys); i++) {
-               if(keysym == keys[i].keysym
-                  && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
-                  && keys[i].func) {
+               if(keysym == keys[i].keysym &&
+                  CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) &&
+                  keys[i].func) {
                        keys[i].func(&(keys[i].arg));
                }
        }
@@ -1559,25 +1585,29 @@ void manage(Window w, XWindowAttributes *wa)
        }
 
        /* geometry */
-       c->x = c->oldx = wa->x;
-       c->y = c->oldy = wa->y;
-       c->w = c->oldw = wa->width;
-       c->h = c->oldh = wa->height;
-       c->oldbw = wa->border_width;
+       c->geom.x = wa->x;
+       c->geom.y = wa->y;
+       c->geom.w = wa->width;
+       c->geom.h = wa->height;
+       memcpy(&(c->old_geom), &(c->geom), sizeof(c->old_geom));
 
-       if(c->x + WIDTH(c) > c->mon->mx + c->mon->mw) {
-               c->x = c->mon->mx + c->mon->mw - WIDTH(c);
+       c->border.oldw = wa->border_width;
+
+       if(c->geom.x + client_get_width(c) > c->mon->geom.x + c->mon->geom.w) {
+               c->geom.x = c->mon->geom.x + c->mon->geom.w - client_get_width(c);
        }
-       if(c->y + HEIGHT(c) > c->mon->my + c->mon->mh) {
-               c->y = c->mon->my + c->mon->mh - HEIGHT(c);
+       if(c->geom.y + client_get_height(c) > c->mon->geom.y + c->mon->geom.h) {
+               c->geom.y = c->mon->geom.y + c->mon->geom.h - client_get_height(c);
        }
-       c->x = MAX(c->x, c->mon->mx);
+       c->geom.x = MAX(c->geom.x, c->mon->geom.x);
+
        /* only fix client y-offset, if the client center might cover the bar */
-       c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
-                         && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
-       c->bw = borderpx;
+       c->geom.y = MAX(c->geom.y, (c->mon->by == c->mon->geom.y &&
+                                   (c->geom.x + (c->geom.w / 2) >= c->mon->win_geom.x) &&
+                                   (c->geom.x + (c->geom.w / 2) < c->mon->win_geom.x + c->mon->win_geom.w)) ? bh : c->mon->geom.y);
+       c->border.w = borderpx;
 
-       wc.border_width = c->bw;
+       wc.border_width = c->border.w;
        XConfigureWindow(dpy, w, CWBorderWidth, &wc);
        XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
        configure(c); /* propagates border_width, if size doesn't change */
@@ -1586,16 +1616,24 @@ void manage(Window w, XWindowAttributes *wa)
        updatewmhints(c);
        XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
        grabbuttons(c, False);
-       if(!c->isfloating)
+
+       if(!c->isfloating) {
                c->isfloating = c->oldstate = trans != None || c->isfixed;
-       if(c->isfloating)
+       }
+
+       if(c->isfloating) {
                XRaiseWindow(dpy, c->win);
+       }
+
        attach(c);
        attachstack(c);
-       XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
+       XMoveResizeWindow(dpy, c->win, c->geom.x + 2 * sw, c->geom.y, c->geom.w, c->geom.h); /* some windows require this */
        setclientstate(c, NormalState);
-       if (c->mon == selmon)
+
+       if (c->mon == selmon) {
                unfocus(selmon->sel, False);
+       }
+
        c->mon->sel = c;
        arrange(c->mon);
        XMapWindow(dpy, c->win);
@@ -1609,6 +1647,7 @@ void mappingnotify(XEvent *e)
        XMappingEvent *ev = &e->xmapping;
 
        XRefreshKeyboardMapping(ev);
+
        if(ev->request == MappingKeyboard) {
                grabkeys();
        }
@@ -1619,9 +1658,11 @@ void mappingnotify(XEvent *e)
 void maprequest(XEvent *e)
 {
        static XWindowAttributes wa;
-       XMapRequestEvent *ev = &e->xmaprequest;
+       XMapRequestEvent *ev;
         struct client *i;
 
+       ev = &e->xmaprequest;
+
        if((i = wintosystrayicon(ev->window))) {
                sendevent(i->win, netatom[Xembed], StructureNotifyMask,
                          CurrentTime, XEMBED_WINDOW_ACTIVATE, 0,
@@ -1655,7 +1696,13 @@ void monocle(struct monitor *m)
        }
 
        for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
-               resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, False);
+               int border;
+
+               border = 2 + c->border.w;
+
+               resize(c, m->win_geom.x, m->win_geom.y,
+                      m->win_geom.w - border, m->win_geom.h - border,
+                      False);
        }
 
        return;
@@ -1694,8 +1741,8 @@ void movemouse(const union arg *arg)
        }
 
        restack(selmon);
-       ocx = c->x;
-       ocy = c->y;
+       ocx = c->geom.x;
+       ocy = c->geom.y;
        if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
                        None, cursor[CurMove], CurrentTime) != GrabSuccess)
                return;
@@ -1712,27 +1759,38 @@ void movemouse(const union arg *arg)
                case MotionNotify:
                        nx = ocx + (ev.xmotion.x - x);
                        ny = ocy + (ev.xmotion.y - y);
-                       if(nx >= selmon->wx && nx <= selmon->wx + selmon->ww
-                          && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) {
-                               if(abs(selmon->wx - nx) < snap)
-                                       nx = selmon->wx;
-                               else if(abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
-                                       nx = selmon->wx + selmon->ww - WIDTH(c);
-                               if(abs(selmon->wy - ny) < snap)
-                                       ny = selmon->wy;
-                               else if(abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
-                                       ny = selmon->wy + selmon->wh - HEIGHT(c);
-                               if(!c->isfloating && selmon->lt[selmon->sellt]->arrange
-                                  && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
+                       if(nx >= selmon->win_geom.x &&
+                          nx <= selmon->win_geom.x + selmon->win_geom.w &&
+                          ny >= selmon->win_geom.y &&
+                          ny <= selmon->win_geom.y + selmon->win_geom.h) {
+                               if(abs(selmon->win_geom.x - nx) < snap) {
+                                       nx = selmon->win_geom.x;
+                               } else if(abs((selmon->win_geom.x + selmon->win_geom.w) - (nx + client_get_width(c))) < snap) {
+                                       nx = selmon->win_geom.x + selmon->win_geom.w - client_get_width(c);
+                               }
+
+                               if(abs(selmon->win_geom.y - ny) < snap) {
+                                       ny = selmon->win_geom.y;
+                               } else if(abs((selmon->win_geom.y + selmon->win_geom.h) - (ny + client_get_height(c))) < snap) {
+                                       ny = selmon->win_geom.y + selmon->win_geom.h - client_get_height(c);
+                               }
+
+                               if(!c->isfloating && selmon->lt[selmon->sellt]->arrange &&
+                                  (abs(nx - c->geom.x) > snap || abs(ny - c->geom.y) > snap)) {
                                        togglefloating(NULL);
+                               }
                        }
                        if(!selmon->lt[selmon->sellt]->arrange || c->isfloating)
-                               resize(c, nx, ny, c->w, c->h, True);
+                               resize(c, nx, ny, c->geom.w, c->geom.h, True);
                        break;
                }
        } while(ev.type != ButtonRelease);
+
        XUngrabPointer(dpy, CurrentTime);
-       if((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
+
+       m = recttomon(c->geom.x, c->geom.y, c->geom.w, c->geom.h);
+
+       if(m != selmon) {
                sendmon(c, m);
                selmon = m;
                focus(NULL);
@@ -1743,7 +1801,9 @@ void movemouse(const union arg *arg)
 
 struct client *nexttiled(struct client *c)
 {
-       for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
+       while(c && (c->isfloating || !ISVISIBLE(c))) {
+               c = c->next;
+       }
 
        return(c);
 }
@@ -1767,7 +1827,7 @@ void propertynotify(XEvent *e)
        if((c = wintosystrayicon(ev->window))) {
                if(ev->atom == XA_WM_NORMAL_HINTS) {
                        updatesizehints(c);
-                       updatesystrayicongeom(c, c->w, c->h);
+                       updatesystrayicongeom(c, c->geom.w, c->geom.h);
                }
                else
                        updatesystrayiconstate(c, ev);
@@ -1812,6 +1872,28 @@ void quit(const union arg *arg)
        return;
 }
 
+static inline int intersect(const int x, const int y,
+                           const int w, const int h,
+                           struct monitor *mon)
+{
+       int top;
+       int right;
+       int bottom;
+       int left;
+       int width;
+       int height;
+
+       top = MAX(y, mon->win_geom.y);
+       right = MIN(x + w, mon->win_geom.x + mon->win_geom.w);
+       bottom = MIN(y + h, mon->win_geom.y + mon->win_geom.h);
+       left = MAX(x, mon->win_geom.x);
+
+       width = MAX(0, right - left);
+        height = MAX(0, bottom - top);
+
+       return(width * height);
+}
+
 struct monitor *recttomon(int x, int y, int w, int h)
 {
         struct monitor *m;
@@ -1824,7 +1906,7 @@ struct monitor *recttomon(int x, int y, int w, int h)
        for(m = mons; m; m = m->next) {
                int a;
 
-               a = INTERSECT(x, y, w, h, m);
+               a = intersect(x, y, w, h, m);
 
                if(a > area) {
                        area = a;
@@ -1835,21 +1917,19 @@ struct monitor *recttomon(int x, int y, int w, int h)
        return(r);
 }
 
-void removesystrayicon(struct client *i)
+void removesystrayicon(struct client *client)
 {
-        struct client **ii;
+        struct client **cur;
 
-       if(!showsystray || !i) {
+       if(!showsystray || !client) {
                return;
        }
 
-       for(ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
+       for(cur = &systray->icons; *cur && *cur != client; cur = &(*cur)->next);
 
-       if(ii) {
-               *ii = i->next;
-       }
+       *cur = client->next;
 
-       free(i);
+       free(client);
        return;
 }
 
@@ -1865,13 +1945,13 @@ void resize(struct client *c, int x, int y, int w, int h, Bool interact)
 
 void resizebarwin(struct monitor *m)
 {
-       unsigned int w = m->ww;
+       unsigned int w = m->win_geom.w;
 
        if(showsystray && m == selmon) {
                w -= getsystraywidth();
        }
 
-       XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, w, bh);
+       XMoveResizeWindow(dpy, m->barwin, m->win_geom.x, m->by, w, bh);
 
        return;
 }
@@ -1880,11 +1960,18 @@ void resizeclient(struct client *c, int x, int y, int w, int h)
 {
        XWindowChanges wc;
 
-       c->oldx = c->x; c->x = wc.x = x;
-       c->oldy = c->y; c->y = wc.y = y;
-       c->oldw = c->w; c->w = wc.width = w;
-       c->oldh = c->h; c->h = wc.height = h;
-       wc.border_width = c->bw;
+       memcpy(&c->old_geom, &c->geom, sizeof(c->old_geom));
+
+       c->geom.x = x;
+       c->geom.y = y;
+       c->geom.w = w;
+       c->geom.h = h;
+
+       wc.x = x;
+       wc.y = y;
+       wc.width = w;
+       wc.height = h;
+       wc.border_width = c->border.w;
 
        XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
        configure(c);
@@ -1906,18 +1993,19 @@ void resizemouse(const union arg *arg)
        }
 
        restack(selmon);
-       ocx = c->x;
-       ocy = c->y;
+       ocx = c->geom.x;
+       ocy = c->geom.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->bw - 1, c->h + c->bw - 1);
+       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geom.w + c->border.w - 1, c->geom.h + c->border.w - 1);
 
        do {
                XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
+
                switch(ev.type) {
                case ConfigureRequest:
                case Expose:
@@ -1925,27 +2013,31 @@ void resizemouse(const union arg *arg)
                        handler[ev.type](&ev);
                        break;
                case MotionNotify:
-                       nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
-                       nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
-                       if(c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
-                          && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
+                       nw = MAX(ev.xmotion.x - ocx - 2 * c->border.w + 1, 1);
+                       nh = MAX(ev.xmotion.y - ocy - 2 * c->border.w + 1, 1);
+                       if(c->mon->win_geom.x + nw >= selmon->win_geom.x &&
+                          c->mon->win_geom.x + nw <= selmon->win_geom.x + selmon->win_geom.w &&
+                          c->mon->win_geom.y + nh >= selmon->win_geom.y &&
+                          c->mon->win_geom.y + nh <= selmon->win_geom.y + selmon->win_geom.h)
                        {
                                if(!c->isfloating && selmon->lt[selmon->sellt]->arrange
-                                  && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
+                                  && (abs(nw - c->geom.w) > snap || abs(nh - c->geom.h) > snap))
                                        togglefloating(NULL);
                        }
                        if(!selmon->lt[selmon->sellt]->arrange || c->isfloating)
-                               resize(c, c->x, c->y, nw, nh, True);
+                               resize(c, c->geom.x, c->geom.y, nw, nh, True);
                        break;
                }
        } while(ev.type != ButtonRelease);
 
-       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
+       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geom.w + c->border.w - 1, c->geom.h + c->border.w - 1);
        XUngrabPointer(dpy, CurrentTime);
 
        while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
 
-       if((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
+       m = recttomon(c->geom.x, c->geom.y, c->geom.w, c->geom.h);
+
+       if(m != selmon) {
                sendmon(c, m);
                selmon = m;
                focus(NULL);
@@ -1956,11 +2048,14 @@ void resizemouse(const union arg *arg)
 
 void resizerequest(XEvent *e)
 {
-       XResizeRequestEvent *ev = &e->xresizerequest;
-        struct client *i;
+       XResizeRequestEvent *ev;
+        struct client *client;
 
-       if((i = wintosystrayicon(ev->window))) {
-               updatesystrayicongeom(i, ev->width, ev->height);
+       ev = &e->xresizerequest;
+       client = wintosystrayicon(ev->window);
+
+       if(client) {
+               updatesystrayicongeom(client, ev->width, ev->height);
                resizebarwin(selmon);
                updatesystray();
        }
@@ -2125,7 +2220,7 @@ void setfocus(struct client *c)
                XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
        }
 
-       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
+       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->geom.w / 2, c->geom.h / 2);
        sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
 
        return;
@@ -2138,22 +2233,19 @@ void setfullscreen(struct client *c, Bool fullscreen)
                                PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
                c->isfullscreen = True;
                c->oldstate = c->isfloating;
-               c->oldbw = c->bw;
-               c->bw = 0;
+               c->border.oldw = c->border.w;
+               c->border.w = 0;
                c->isfloating = True;
-               resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
+               resizeclient(c, c->mon->geom.x, c->mon->geom.y, c->mon->geom.w, c->mon->geom.h);
                XRaiseWindow(dpy, c->win);
        } else {
                XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
                                PropModeReplace, (unsigned char*)0, 0);
                c->isfullscreen = False;
                c->isfloating = c->oldstate;
-               c->bw = c->oldbw;
-               c->x = c->oldx;
-               c->y = c->oldy;
-               c->w = c->oldw;
-               c->h = c->oldh;
-               resizeclient(c, c->x, c->y, c->w, c->h);
+               c->border.w = c->border.oldw;
+               memcpy(&(c->geom), &(c->old_geom), sizeof(c->geom));
+               resizeclient(c, c->geom.x, c->geom.y, c->geom.w, c->geom.h);
                arrange(c->mon);
        }
 
@@ -2217,7 +2309,7 @@ void setup(void)
        initfont(font);
        sw = DisplayWidth(dpy, screen);
        sh = DisplayHeight(dpy, screen);
-       bh = dc.h = dc.font.height + 2;
+       bh = dc.geom.h = dc.font.height + 2;
        updategeom();
        /* init atoms */
        wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
@@ -2277,16 +2369,16 @@ void showhide(struct client *c)
        }
 
        if(ISVISIBLE(c)) { /* show clients top down */
-               XMoveWindow(dpy, c->win, c->x, c->y);
+               XMoveWindow(dpy, c->win, c->geom.x, c->geom.y);
 
                if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen) {
-                       resize(c, c->x, c->y, c->w, c->h, False);
+                       resize(c, c->geom.x, c->geom.y, c->geom.w, c->geom.h, False);
                }
 
                showhide(c->snext);
        } else { /* hide clients bottom up */
                showhide(c->snext);
-               XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);
+               XMoveWindow(dpy, c->win, client_get_width(c) * -2, c->geom.y);
        }
 
        return;
@@ -2373,20 +2465,28 @@ void tile(struct monitor *m)
        }
 
        if(n > m->nmaster) {
-               mw = m->nmaster ? m->ww * m->mfact : 0;
+               mw = m->nmaster ? m->win_geom.w * m->mfact : 0;
        } else {
-               mw = m->ww;
+               mw = m->win_geom.w;
        }
 
        for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
+               int border;
+
+               border = 2 * c->border.w;
+
                if(i < m->nmaster) {
-                       h = (m->wh - my) / (MIN(n, m->nmaster) - i);
-                       resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False);
-                       my += HEIGHT(c);
+                       h = (m->win_geom.h - my) / (MIN(n, m->nmaster) - i);
+                       resize(c, m->win_geom.x, m->win_geom.y + my,
+                              mw - border, h - border, False);
+
+                       my += client_get_height(c);
                } else {
-                       h = (m->wh - ty) / (n - i);
-                       resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False);
-                       ty += HEIGHT(c);
+                       h = (m->win_geom.h - ty) / (n - i);
+                       resize(c, m->win_geom.x + mw, m->win_geom.y + ty,
+                              m->win_geom.w - mw - border, h - border, False);
+
+                       ty += client_get_height(c);
                }
        }
 
@@ -2431,24 +2531,27 @@ static void bookshelf(struct monitor *m)
         * first implemented this on a laptop and things broke when I
         * plugged in a second screen at work.
         */
-        w = m->ww / n;
-        x = m->wx;
+        w = m->win_geom.w / n;
+        x = m->win_geom.x;
 
        /* make the first window a bit larger if the width can't be divided evenly */
-       extraw = m->ww - (w * n);
+       extraw = m->win_geom.w - (w * n);
 
        /* assign positions and sizes to all clients on this screen */
         for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
+               int border;
+
+               border = 2 * c->border.w;
                c->incw = 0;
                c->inch = 0;
 
-                resize(c, x, m->wy, w + extraw - 2 * c->bw, m->wh - 2 * c->bw, False);
+                resize(c, x, m->win_geom.y, w + extraw - border, m->win_geom.h - border, False);
 
                /*
                 * Since all clients are horizontally aligned and the
                 * same size, only the x coordinate changes.
                 */
-                x += WIDTH(c);
+                x += client_get_width(c);
                extraw = 0;
         }
 
@@ -2472,16 +2575,19 @@ static void bookstack(struct monitor *m)
                 return;
         }
 
-        h = m->wh / n;
-        y = m->wy;
-       extrah = m->wh - (h * n);
+        h = m->win_geom.h / n;
+        y = m->win_geom.y;
+       extrah = m->win_geom.h - (h * n);
 
         for(c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
+               int border;
+
+               border = 2 * c->border.w;
                c->incw = 0;
                c->inch = 0;
 
-                resize(c, m->wx, y, m->ww - 2 * c->bw, h + extrah - 2 * c->bw, False);
-                y += HEIGHT(c);
+                resize(c, m->win_geom.x, y, m->win_geom.w - border, h + extrah - border, False);
+                y += client_get_height(c);
                extrah = 0;
         }
 
@@ -2504,7 +2610,7 @@ void togglebar(const union arg *arg)
                        wc.y = 0;
 
                        if(!selmon->topbar) {
-                               wc.y = selmon->mh - bh;
+                               wc.y = selmon->geom.h - bh;
                        }
                }
 
@@ -2526,8 +2632,8 @@ void togglefloating(const union arg *arg)
        selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed;
 
        if(selmon->sel->isfloating) {
-               resize(selmon->sel, selmon->sel->x, selmon->sel->y,
-                      selmon->sel->w, selmon->sel->h, False);
+               resize(selmon->sel, selmon->sel->geom.x, selmon->sel->geom.y,
+                      selmon->sel->geom.w, selmon->sel->geom.h, False);
        }
 
        arrange(selmon);
@@ -2593,7 +2699,7 @@ void unmanage(struct client *c, Bool destroyed)
        detachstack(c);
 
        if(!destroyed) {
-               wc.border_width = c->oldbw;
+               wc.border_width = c->border.oldw;
                XGrabServer(dpy);
                XSetErrorHandler(xerrordummy);
                XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
@@ -2643,13 +2749,13 @@ void updatebars(void)
        };
 
        for(m = mons; m; m = m->next) {
-               w = m->ww;
+               w = m->win_geom.w;
 
                if(showsystray && m == selmon) {
                        w -= getsystraywidth();
                }
 
-               m->barwin = XCreateWindow(dpy, root, m->wx, m->by, w, bh, 0, DefaultDepth(dpy, screen),
+               m->barwin = XCreateWindow(dpy, root, m->win_geom.x, m->by, w, bh, 0, DefaultDepth(dpy, screen),
                                          CopyFromParent, DefaultVisual(dpy, screen),
                                          CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
 
@@ -2662,13 +2768,13 @@ void updatebars(void)
 
 void updatebarpos(struct monitor *m)
 {
-       m->wy = m->my;
-       m->wh = m->mh;
+       m->win_geom.y = m->geom.y;
+       m->win_geom.h = m->geom.h;
 
        if(m->showbar) {
-               m->wh -= bh;
-               m->by = m->topbar ? m->wy : m->wy + m->wh;
-               m->wy = m->topbar ? m->wy + bh : m->wy;
+               m->win_geom.h -= bh;
+               m->by = m->topbar ? m->win_geom.y : m->win_geom.y + m->win_geom.h;
+               m->win_geom.y = m->topbar ? m->win_geom.y + bh : m->win_geom.y;
        } else {
                m->by = -bh;
        }
@@ -2691,13 +2797,13 @@ Bool updategeom(void)
                for(n = 0, m = mons; m; m = m->next, n++);
 
                /* only consider unique geometries as separate screens */
-               if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn))) {
-                       die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn);
+               if(!(unique = (XineramaScreenInfo *)malloc(sizeof(*unique) * nn))) {
+                       die("fatal: could not malloc() %u bytes\n", sizeof(*unique) * nn);
                }
 
                for(i = 0, j = 0; i < nn; i++) {
                        if(isuniquegeom(unique, j, &info[i])) {
-                               memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
+                               memcpy(&unique[j++], &info[i], sizeof(*unique));
                        }
                }
 
@@ -2716,14 +2822,17 @@ Bool updategeom(void)
                        }
 
                        for(i = 0, m = mons; i < nn && m; m = m->next, i++) {
-                               if(i >= n || (unique[i].x_org != m->mx || unique[i].y_org != m->my ||
-                                   unique[i].width != m->mw || unique[i].height != m->mh)) {
+                               if(i >= n || (unique[i].x_org != m->geom.x || unique[i].y_org != m->geom.y ||
+                                   unique[i].width != m->geom.w || unique[i].height != m->geom.h)) {
                                        dirty = True;
                                        m->num = i;
-                                       m->mx = m->wx = unique[i].x_org;
-                                       m->my = m->wy = unique[i].y_org;
-                                       m->mw = m->ww = unique[i].width;
-                                       m->mh = m->wh = unique[i].height;
+                                       m->geom.x = unique[i].x_org;
+                                       m->geom.y = unique[i].y_org;
+                                       m->geom.w = unique[i].width;
+                                       m->geom.h = unique[i].height;
+
+                                       memcpy(&(m->win_geom), &(m->geom), sizeof(m->win_geom));
+
                                        updatebarpos(m);
                                }
                        }
@@ -2758,10 +2867,10 @@ Bool updategeom(void)
                        mons = createmon();
                }
 
-               if(mons->mw != sw || mons->mh != sh) {
+               if(mons->geom.w != sw || mons->geom.h != sh) {
                        dirty = True;
-                       mons->mw = mons->ww = sw;
-                       mons->mh = mons->wh = sh;
+                       mons->geom.w = mons->win_geom.w = sw;
+                       mons->geom.h = mons->win_geom.h = sh;
                        updatebarpos(mons);
                }
        }
@@ -2878,27 +2987,30 @@ void updatestatus(void)
 
 void updatesystrayicongeom(struct client *i, int w, int h)
 {
-       if(i) {
-               i->h = bh;
-               if(w == h) {
-                       i->w = bh;
-               } else if(h == bh) {
-                       i->w = w;
-               } else {
-                       i->w = (int) ((float)bh * ((float)w / (float)h));
-               }
+       if(!i) {
+               return;
+       }
 
-               applysizehints(i, &(i->x), &(i->y), &(i->w), &(i->h), False);
-               /* force icons into the systray dimenons if they don't want to */
-               if(i->h > bh) {
-                       if(i->w == i->h) {
-                               i->w = bh;
-                       } else {
-                               i->w = (int) ((float)bh * ((float)i->w / (float)i->h));
-                       }
+       i->geom.h = bh;
+
+       if(w == h) {
+               i->geom.w = bh;
+       } else if(h == bh) {
+               i->geom.w = w;
+       } else {
+               i->geom.w = (int) ((float)bh * ((float)w / (float)h));
+       }
 
-                       i->h = bh;
+       applysizehints(i, &(i->geom.x), &(i->geom.y), &(i->geom.w), &(i->geom.h), False);
+       /* force icons into the systray dimenons if they don't want to */
+       if(i->geom.h > bh) {
+               if(i->geom.w == i->geom.h) {
+                       i->geom.w = bh;
+               } else {
+                       i->geom.w = (int) ((float)bh * ((float)i->geom.w / (float)i->geom.h));
                }
+
+               i->geom.h = bh;
        }
 
        return;
@@ -2938,8 +3050,11 @@ void updatesystray(void)
 {
        XSetWindowAttributes wa;
         struct client *i;
-       unsigned int x = selmon->mx + selmon->mw;
-       unsigned int w = 1;
+       unsigned int x;
+       unsigned int w;
+
+       x = selmon->geom.x + selmon->geom.w;
+       w = 1;
 
        if(!showsystray) {
                return;
@@ -2978,8 +3093,9 @@ void updatesystray(void)
        for(w = 0, i = systray->icons; i; i = i->next) {
                XMapRaised(dpy, i->win);
                w += systrayspacing;
-               XMoveResizeWindow(dpy, i->win, (i->x = w), 0, i->w, i->h);
-               w += i->w;
+               i->geom.x = w;
+               XMoveResizeWindow(dpy, i->win, i->geom.x, 0, i->geom.w, i->geom.h);
+               w += i->geom.w;
 
                if(i->mon != selmon) {
                        i->mon = selmon;