#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
#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)
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;
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;
};
struct draw_context {
- int x;
- int y;
- int w;
- int h;
+ struct rect geom;
unsigned long norm[ColLast];
unsigned long sel[ColLast];
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];
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);
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;
}
}
}
}
- 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)
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;
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;
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);
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);
}
}
- 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;
}
}
- 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;
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;
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;
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;
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);
}
#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);
}
}
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));
}
}
}
/* 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 */
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);
XMappingEvent *ev = &e->xmapping;
XRefreshKeyboardMapping(ev);
+
if(ev->request == MappingKeyboard) {
grabkeys();
}
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,
}
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;
}
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;
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);
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);
}
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);
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;
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;
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;
}
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;
}
{
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);
}
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:
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);
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();
}
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;
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);
}
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);
}
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;
}
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);
}
}
* 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;
}
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;
}
wc.y = 0;
if(!selmon->topbar) {
- wc.y = selmon->mh - bh;
+ wc.y = selmon->geom.h - bh;
}
}
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);
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 */
};
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);
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;
}
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));
}
}
}
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);
}
}
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);
}
}
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;
{
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;
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;