/* macros */
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
-#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask))
+#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
#define LENGTH(X) (sizeof X / sizeof X[0])
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int bw, oldbw;
unsigned int tags;
- Bool isfixed, isfloating, isurgent, neverfocus, oldstate;
+ Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
Client *next;
Client *snext;
Monitor *mon;
static void monocle(Monitor *m);
static void movemouse(const Arg *arg);
static Client *nexttiled(Client *c);
-static Monitor *ptrtomon(int x, int y);
+static void pop(Client *);
static void propertynotify(XEvent *e);
+static Monitor *ptrtomon(int x, int y);
static void quit(const Arg *arg);
static void resize(Client *c, int x, int y, int w, int h, Bool interact);
static void resizeclient(Client *c, int x, int y, int w, int h);
showhide(m->stack);
else for(m = mons; m; m = m->next)
showhide(m->stack);
- focus(NULL);
if(m)
arrangemon(m);
else for(m = mons; m; m = m->next)
}
if(ev->window == selmon->barwin) {
i = x = 0;
- do {
+ do
x += TEXTW(tags[i]);
- } while(ev->x >= x && ++i < LENGTH(tags));
+ while(ev->x >= x && ++i < LENGTH(tags));
if(i < LENGTH(tags)) {
click = ClkTagBar;
arg.ui = 1 << i;
}
else if(ev->x < x + blw)
click = ClkLtSymbol;
- else if(ev->x > selmon->wx + selmon->ww - TEXTW(stext))
+ else if(ev->x > selmon->ww - TEXTW(stext))
click = ClkStatusText;
else
click = ClkWinTitle;
if(!c)
return;
if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) {
- if(cme->data.l[0]) {
+ if(cme->data.l[0] && !c->isfullscreen) {
XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32,
PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
+ c->isfullscreen = True;
c->oldstate = c->isfloating;
c->oldbw = c->bw;
c->bw = 0;
else {
XChangeProperty(dpy, cme->window, 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;
}
else if(cme->message_type == netatom[NetActiveWindow]) {
if(!ISVISIBLE(c)) {
- c->mon->seltags ^= 1;
- c->mon->tagset[c->mon->seltags] = c->tags;
+ c->mon->seltags ^= 1;
+ c->mon->tagset[c->mon->seltags] = c->tags;
}
pop(c);
}
configurenotify(XEvent *e) {
Monitor *m;
XConfigureEvent *ev = &e->xconfigure;
+ Bool dirty;
if(ev->window == root) {
+ dirty = (sw != ev->width);
sw = ev->width;
sh = ev->height;
- if(updategeom()) {
+ if(updategeom() || dirty) {
if(dc.drawable != 0)
XFreePixmap(dpy, dc.drawable);
dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
updatebars();
for(m = mons; m; m = m->next)
XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
+ focus(NULL);
arrange(NULL);
}
}
c->bw = ev->border_width;
else if(c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
m = c->mon;
- if(ev->value_mask & CWX)
+ if(ev->value_mask & CWX) {
+ c->oldx = c->x;
c->x = m->mx + ev->x;
- if(ev->value_mask & CWY)
+ }
+ if(ev->value_mask & CWY) {
+ c->oldy = c->y;
c->y = m->my + ev->y;
- if(ev->value_mask & CWWidth)
+ }
+ if(ev->value_mask & CWWidth) {
+ c->oldw = c->w;
c->w = ev->width;
- if(ev->value_mask & CWHeight)
+ }
+ if(ev->value_mask & CWHeight) {
+ c->oldh = c->h;
c->h = ev->height;
+ }
if((c->x + c->w) > m->mx + m->mw && c->isfloating)
- c->x = m->mx + (m->mw / 2 - c->w / 2); /* center in x direction */
+ c->x = m->mx + (m->mw / 2 - 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 - c->h / 2); /* center in y direction */
+ c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
if((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
configure(c);
if(ISVISIBLE(c))
if(!(m = selmon->next))
m = mons;
}
- else {
- if(selmon == mons)
- for(m = mons; m->next; m = m->next);
- else
- for(m = mons; m->next != selmon; m = m->next);
- }
+ else if(selmon == mons)
+ for(m = mons; m->next; m = m->next);
+ else
+ for(m = mons; m->next != selmon; m = m->next);
return m;
}
void
drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
int x;
- XGCValues gcv;
- XRectangle r = { dc.x, dc.y, dc.w, dc.h };
- gcv.foreground = col[invert ? ColBG : ColFG];
- XChangeGC(dpy, dc.gc, GCForeground, &gcv);
+ XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
x = (dc.font.ascent + dc.font.descent + 2) / 4;
- r.x = dc.x + 1;
- r.y = dc.y + 1;
- if(filled) {
- r.width = r.height = x + 1;
- XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
- }
- else if(empty) {
- r.width = r.height = x;
- XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
- }
+ if(filled)
+ XFillRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x+1, x+1);
+ else if(empty)
+ XDrawRectangle(dpy, dc.drawable, dc.gc, dc.x+1, dc.y+1, x, x);
}
void
drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
char buf[256];
int i, x, y, h, len, olen;
- XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
- XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
+ XFillRectangle(dpy, dc.drawable, dc.gc, dc.x, dc.y, dc.w, dc.h);
if(!text)
return;
olen = strlen(text);
void
enternotify(XEvent *e) {
+ Client *c;
Monitor *m;
XCrossingEvent *ev = &e->xcrossing;
if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
return;
- if((m = wintomon(ev->window)) && m != selmon) {
+ c = wintoclient(ev->window);
+ m = c ? c->mon : wintomon(ev->window);
+ if(m != selmon) {
unfocus(selmon->sel, True);
selmon = m;
}
- focus((wintoclient(ev->window)));
+ else if(!c || c == selmon->sel)
+ return;
+ focus(c);
}
void
KeyCode code;
XUngrabKey(dpy, AnyKey, AnyModifier, root);
- for(i = 0; i < LENGTH(keys); i++) {
+ for(i = 0; i < LENGTH(keys); i++)
if((code = XKeysymToKeycode(dpy, keys[i].keysym)))
for(j = 0; j < LENGTH(modifiers); j++)
XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
True, GrabModeAsync, GrabModeAsync);
- }
}
}
char *def, **missing;
int n;
- missing = NULL;
dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
if(missing) {
while(n--)
applyrules(c);
}
/* geometry */
- c->x = c->oldx = wa->x + c->mon->wx;
- c->y = c->oldy = wa->y + c->mon->wy;
+ 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;
if(c->w == c->mon->mw && c->h == c->mon->mh) {
- c->isfloating = True;
+ c->isfloating = True; // regression with flash, XXXX
c->x = c->mon->mx;
c->y = c->mon->my;
c->bw = 0;
attach(c);
attachstack(c);
XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
- XMapWindow(dpy, c->win);
setclientstate(c, NormalState);
+ if (c->mon == selmon)
+ unfocus(selmon->sel, False);
+ c->mon->sel = c;
arrange(c->mon);
+ XMapWindow(dpy, c->win);
+ focus(NULL);
}
void
return;
do {
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
- switch (ev.type) {
+ switch(ev.type) {
case ConfigureRequest:
case Expose:
case MapRequest:
else if(ev->state == PropertyDelete)
return; /* ignore */
else if((c = wintoclient(ev->window))) {
- switch (ev->atom) {
+ switch(ev->atom) {
default: break;
case XA_WM_TRANSIENT_FOR:
if(!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) &&
return m;
return selmon;
}
+
void
quit(const Arg *arg) {
running = False;
XEvent ev;
/* main event loop */
XSync(dpy, False);
- while(running && !XNextEvent(dpy, &ev)) {
+ while(running && !XNextEvent(dpy, &ev))
if(handler[ev.type])
handler[ev.type](&ev); /* call handler */
- }
}
void
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
- netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
+ netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
return;
if(ISVISIBLE(c)) { /* show clients top down */
XMoveWindow(dpy, c->win, c->x, c->y);
- if(!c->mon->lt[c->mon->sellt]->arrange || c->isfloating)
+ if((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
resize(c, c->x, c->y, c->w, c->h, False);
showhide(c->snext);
}
execvp(((char **)arg->v)[0], (char **)arg->v);
fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
perror(" failed");
- exit(0);
+ exit(EXIT_SUCCESS);
}
}
tag(const Arg *arg) {
if(selmon->sel && arg->ui & TAGMASK) {
selmon->sel->tags = arg->ui & TAGMASK;
+ focus(NULL);
arrange(selmon);
}
}
if(--n == 0)
return;
/* tile stack */
- x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw;
+ x = (m->wx > c->x) ? c->x + mw + 2 * c->bw : m->wx + mw;
y = m->wy;
- w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw;
+ w = (m->wx > c->x) ? m->wx + m->ww - x : m->ww - mw;
h = m->wh / n;
if(h < bh)
h = m->wh;
newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
if(newtags) {
selmon->sel->tags = newtags;
+ focus(NULL);
arrange(selmon);
}
}
if(newtagset) {
selmon->tagset[selmon->seltags] = newtagset;
+ focus(NULL);
arrange(selmon);
}
}
void
updatebars(void) {
Monitor *m;
- XSetWindowAttributes wa;
-
- wa.override_redirect = True;
- wa.background_pixmap = ParentRelative;
- wa.event_mask = ButtonPressMask|ExposureMask;
+ XSetWindowAttributes wa = {
+ .override_redirect = True,
+ .background_pixmap = ParentRelative,
+ .event_mask = ButtonPressMask|ExposureMask
+ };
for(m = mons; m; m = m->next) {
m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
selmon->seltags ^= 1; /* toggle sel tagset */
if(arg->ui & TAGMASK)
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
+ focus(NULL);
arrange(selmon);
}
Client *c = selmon->sel;
if(!selmon->lt[selmon->sellt]->arrange
- || selmon->lt[selmon->sellt]->arrange == monocle
|| (selmon->sel && selmon->sel->isfloating))
return;
if(c == nexttiled(selmon->clients))
int
main(int argc, char *argv[]) {
if(argc == 2 && !strcmp("-v", argv[1]))
- die("dwm-"VERSION", © 2006-2010 dwm engineers, see LICENSE for details\n");
+ die("dwm-"VERSION", © 2006-2011 dwm engineers, see LICENSE for details\n");
else if(argc != 1)
die("usage: dwm [-v]\n");
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
run();
cleanup();
XCloseDisplay(dpy);
- return 0;
+ return EXIT_SUCCESS;
}