From: Matthias Kruk Date: Sat, 13 Mar 2021 02:31:34 +0000 (+0900) Subject: Add struct rect type for the common (x, y, w, h) membership pattern X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=8284c2ef69d3d9607945f44a89a67186070b3f71;p=dwm Add struct rect type for the common (x, y, w, h) membership pattern Several types contain members for coordinates of a rectangle on the screen. This commit adds the struct rect type to simplify this common pattern. --- diff --git a/dwm.c b/dwm.c index 3a43fb8..63ffdbc 100755 --- 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;