diff --git a/config.def.h b/config.def.h --- a/config.def.h +++ b/config.def.h @@ -15,11 +15,11 @@ const char tags[][MAXTAGLEN] = { "1", "2 const char tags[][MAXTAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8", "www" }; Bool initags[LENGTH(tags)] = {[0] = True}; Rule rules[] = { - /* class:instance:title regex tags regex isfloating */ /* monitor */ - { "Firefox", "www", False, -1 }, - { "Gimp", NULL, True, -1 }, - { "MPlayer", NULL, True, -1 }, - { "Acroread", NULL, True, -1 }, + /* class:instance:title regex tags regex isfloating */ + { "Firefox", "www", False }, + { "Gimp", NULL, True }, + { "MPlayer", NULL, True }, + { "Acroread", NULL, True }, }; /* layout(s) */ diff --git a/config.mk b/config.mk --- a/config.mk +++ b/config.mk @@ -15,10 +15,10 @@ LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 -lXinerama # flags -CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\" -LDFLAGS = -s ${LIBS} -#CFLAGS = -g -std=c99 -pedantic -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" -#LDFLAGS = -g ${LIBS} +#CFLAGS = -Os ${INCS} -DVERSION=\"${VERSION}\" +#LDFLAGS = -s ${LIBS} +CFLAGS = -g -std=c99 -pedantic -Wall -O2 ${INCS} -DVERSION=\"${VERSION}\" +LDFLAGS = -g ${LIBS} # Solaris #CFLAGS = -fast ${INCS} -DVERSION=\"${VERSION}\" diff --git a/dwm.c b/dwm.c --- a/dwm.c +++ b/dwm.c @@ -75,6 +75,7 @@ struct Client { Client *snext; Window win; int monitor; + int generation; }; typedef struct { @@ -99,16 +100,16 @@ typedef struct { const char *arg; } Key; +typedef struct Monitor Monitor; typedef struct { const char *symbol; - void (*arrange)(void); + void (*arrange)(Monitor *m); } Layout; typedef struct { const char *prop; const char *tags; Bool isfloating; - int monitor; } Rule; typedef struct { @@ -116,7 +117,8 @@ typedef struct { regex_t *tagregex; } Regs; -typedef struct { +struct Monitor { + int nth; int screen; Window root; Window barwin; @@ -126,7 +128,7 @@ typedef struct { Bool *prevtags; Layout *layout; double mwfact; -} Monitor; +}; /* function declarations */ void applyrules(Client *c); @@ -151,7 +153,7 @@ void enternotify(XEvent *e); void enternotify(XEvent *e); void eprint(const char *errstr, ...); void expose(XEvent *e); -void floating(void); /* default floating layout */ +void floating(Monitor*); /* default floating layout */ void focus(Client *c); void focusin(XEvent *e); void focusnext(const char *arg); @@ -164,7 +166,7 @@ void grabkeys(void); void grabkeys(void); unsigned int idxoftag(const char *tag); void initfont(Monitor*, const char *fontstr); -Bool isoccupied(Monitor *m, unsigned int t); +Bool isoccupied(unsigned int t); Bool isprotodel(Client *c); Bool isvisible(Client *c, Monitor *m); void keypress(XEvent *e); @@ -190,7 +192,7 @@ void tag(const char *arg); void tag(const char *arg); unsigned int textnw(Monitor*, const char *text, unsigned int len); unsigned int textw(Monitor*, const char *text); -void tile(void); +void tile(Monitor*); void togglebar(const char *arg); void togglefloating(const char *arg); void toggletag(const char *arg); @@ -253,6 +255,17 @@ int selmonitor = 0; //Bool prevtags[LENGTH(tags)]; +void +dump_tagset(char *s, Bool *t) +{ + unsigned int i; + + printf("%s: ", s); + for(i = 0; i < LENGTH(tags); i++) + printf("%s ", t[i] ? "t" : "f"); + printf("\n"); +} + /* function implementations */ void applyrules(Client *c) { @@ -260,7 +273,6 @@ applyrules(Client *c) { unsigned int i, j; regmatch_t tmp; Bool matched_tag = False; - Bool matched_monitor = False; XClassHint ch = { 0 }; /* rule matching */ @@ -270,11 +282,6 @@ applyrules(Client *c) { ch.res_name ? ch.res_name : "", c->name); for(i = 0; i < LENGTH(rules); i++) if(regs[i].propregex && !regexec(regs[i].propregex, buf, 1, &tmp, 0)) { - if (rules[i].monitor >= 0 && rules[i].monitor < mcount) { - matched_monitor = True; - c->monitor = rules[i].monitor; - } - c->isfloating = rules[i].isfloating; for(j = 0; regs[i].tagregex && j < LENGTH(tags); j++) { if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { @@ -289,21 +296,36 @@ applyrules(Client *c) { XFree(ch.res_name); if(!matched_tag) memcpy(c->tags, monitors[monitorat(-1, -1)].seltags, sizeof initags); - if (!matched_monitor) - c->monitor = monitorat(-1, -1); } void arrange(void) { + static int generation = 0; + int m; Client *c; - - for(c = clients; c; c = c->next) - if(isvisible(c, &monitors[c->monitor])) - unban(c); - else - ban(c); - - monitors[selmonitor].layout->arrange(); + Monitor *mon; + + generation++; + + for(m = 0, mon = &monitors[0]; m < mcount; m++, mon++) { + + for(c = clients; c; c = c->next) { + if (c->generation != generation) { + /* This client not already placed. */ + if (isvisible(c, mon)) { + c->generation = generation; + c->monitor = m; + unban(c); + } + else { + c->monitor = -1; /* XXX dme: risky? */ + ban(c); + } + } + } + mon->layout->arrange(mon); + } + focus(NULL); restack(); } @@ -414,6 +436,7 @@ cleanup(void) { } for(i = 0; i < mcount; i++) { Monitor *m = &monitors[i]; + if(m->dc.font.set) XFreeFontSet(dpy, m->dc.font.set); else @@ -422,12 +445,12 @@ cleanup(void) { XFreePixmap(dpy, m->dc.drawable); XFreeGC(dpy, m->dc.gc); XDestroyWindow(dpy, m->barwin); - XFreeCursor(dpy, cursor[CurNormal]); - XFreeCursor(dpy, cursor[CurResize]); - XFreeCursor(dpy, cursor[CurMove]); - XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XSync(dpy, False); - } + } + XFreeCursor(dpy, cursor[CurNormal]); + XFreeCursor(dpy, cursor[CurResize]); + XFreeCursor(dpy, cursor[CurMove]); + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XSync(dpy, False); } void @@ -571,14 +594,16 @@ drawbar(void) { Monitor *m = &monitors[i]; m->dc.x = 0; for(j = 0; j < LENGTH(tags); j++) { + Bool occupied = isoccupied(j); + m->dc.w = textw(m, tags[j]); if(m->seltags[j]) { drawtext(m, tags[j], m->dc.sel); - drawsquare(m, sel && sel->tags[j] && sel->monitor == selmonitor, isoccupied(m, j), m->dc.sel); + drawsquare(m, sel && sel->tags[j] && sel->monitor == m->nth, occupied, m->dc.sel); } else { drawtext(m, tags[j], m->dc.norm); - drawsquare(m, sel && sel->tags[j] && sel->monitor == selmonitor, isoccupied(m, j), m->dc.norm); + drawsquare(m, sel && sel->tags[j] && sel->monitor == m->nth, occupied, m->dc.norm); } m->dc.x += m->dc.w; } @@ -594,13 +619,13 @@ drawbar(void) { drawtext(m, stext, m->dc.norm); if((m->dc.w = m->dc.x - x) > bh) { m->dc.x = x; - if(sel && sel->monitor == selmonitor) { + if(sel && sel->monitor == m->nth) { drawtext(m, sel->name, m->dc.sel); drawsquare(m, False, sel->isfloating, m->dc.sel); } else - drawtext(m, NULL, m->dc.norm); - } + drawtext(m, NULL, m->dc.norm); + } XCopyArea(dpy, m->dc.drawable, m->barwin, m->dc.gc, 0, 0, m->sw, bh, 0, 0); XSync(dpy, False); } @@ -717,12 +742,12 @@ expose(XEvent *e) { } void -floating(void) { /* default floating layout */ +floating(Monitor *m) { /* default floating layout */ Client *c; domwfact = dozoom = False; for(c = clients; c; c = c->next) - if(isvisible(c, &monitors[selmonitor])) + if(isvisible(c, m)) resize(c, c->x, c->y, c->w, c->h, True); } @@ -976,11 +1001,11 @@ initfont(Monitor *m, const char *fontstr } Bool -isoccupied(Monitor *m, unsigned int t) { +isoccupied(unsigned int t) { Client *c; for(c = clients; c; c = c->next) - if(c->tags[t] && c->monitor == selmonitor) + if(c->tags[t]) return True; return False; } @@ -1005,7 +1030,7 @@ isvisible(Client *c, Monitor *m) { unsigned int i; for(i = 0; i < LENGTH(tags); i++) - if(c->tags[i] && monitors[c->monitor].seltags[i] && c->monitor == selmonitor) + if(c->tags[i] && m->seltags[i]) return True; return False; } @@ -1049,7 +1074,7 @@ void void manage(Window w, XWindowAttributes *wa) { Client *c, *t = NULL; - Monitor *m = &monitors[selmonitor]; + Monitor *m; Status rettrans; Window trans; XWindowChanges wc; @@ -1057,6 +1082,9 @@ manage(Window w, XWindowAttributes *wa) c = emallocz(sizeof(Client)); c->tags = emallocz(sizeof initags); c->win = w; + + c->monitor = selmonitor; /* XXX dme: should use current position rather than selected monitor? */ + m = &monitors[c->monitor]; applyrules(c); @@ -1178,7 +1206,7 @@ movemouse(Client *c) { Client * nexttiled(Client *c, Monitor *m) { - for(; c && (c->isfloating || !isvisible(c, m)); c = c->next); + for(; c && (c->isfloating || (c->monitor != m->nth)); c = c->next); return c; } @@ -1428,32 +1456,30 @@ run(void) { void scan(void) { - unsigned int i, j, num; + unsigned int j, num; Window *wins, d1, d2; XWindowAttributes wa; - - for(i = 0; i < mcount; i++) { - Monitor *m = &monitors[i]; - wins = NULL; - if(XQueryTree(dpy, m->root, &d1, &d2, &wins, &num)) { - for(j = 0; j < num; j++) { - if(!XGetWindowAttributes(dpy, wins[j], &wa) - || wa.override_redirect || XGetTransientForHint(dpy, wins[j], &d1)) - continue; - if(wa.map_state == IsViewable || getstate(wins[j]) == IconicState) - manage(wins[j], &wa); - } - for(j = 0; j < num; j++) { /* now the transients */ - if(!XGetWindowAttributes(dpy, wins[j], &wa)) - continue; - if(XGetTransientForHint(dpy, wins[j], &d1) - && (wa.map_state == IsViewable || getstate(wins[j]) == IconicState)) - manage(wins[j], &wa); - } - } - if(wins) - XFree(wins); - } + Monitor *m = &monitors[0]; + + wins = NULL; + if(XQueryTree(dpy, m->root, &d1, &d2, &wins, &num)) { + for(j = 0; j < num; j++) { + if(!XGetWindowAttributes(dpy, wins[j], &wa) + || wa.override_redirect || XGetTransientForHint(dpy, wins[j], &d1)) + continue; + if(wa.map_state == IsViewable || getstate(wins[j]) == IconicState) + manage(wins[j], &wa); + } + for(j = 0; j < num; j++) { /* now the transients */ + if(!XGetWindowAttributes(dpy, wins[j], &wa)) + continue; + if(XGetTransientForHint(dpy, wins[j], &d1) + && (wa.map_state == IsViewable || getstate(wins[j]) == IconicState)) + manage(wins[j], &wa); + } + } + if(wins) + XFree(wins); } void @@ -1536,17 +1562,18 @@ setup(void) { if (XineramaIsActive(dpy)) { info = XineramaQueryScreens(dpy, &mcount); } - mcount = 1; monitors = emallocz(mcount * sizeof(Monitor)); for(i = 0; i < mcount; i++) { /* init geometry */ m = &monitors[i]; - - m->screen = i; - m->root = RootWindow(dpy, i); - - if (mcount != 1) { // TODO: Xinerama + m->nth = i; + + m->screen = DefaultScreen(dpy); + m->root = RootWindow(dpy, m->screen); + + if (info) { + /* Xinerama */ m->sx = info[i].x_org; m->sy = info[i].y_org; m->sw = info[i].width; @@ -1566,12 +1593,12 @@ setup(void) { memcpy(m->prevtags, initags, sizeof initags); /* init appearance */ - m->dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR, i); - m->dc.norm[ColBG] = getcolor(NORMBGCOLOR, i); - m->dc.norm[ColFG] = getcolor(NORMFGCOLOR, i); - m->dc.sel[ColBorder] = getcolor(SELBORDERCOLOR, i); - m->dc.sel[ColBG] = getcolor(SELBGCOLOR, i); - m->dc.sel[ColFG] = getcolor(SELFGCOLOR, i); + m->dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR, m->screen); + m->dc.norm[ColBG] = getcolor(NORMBGCOLOR, m->screen); + m->dc.norm[ColFG] = getcolor(NORMFGCOLOR, m->screen); + m->dc.sel[ColBorder] = getcolor(SELBORDERCOLOR, m->screen); + m->dc.sel[ColBG] = getcolor(SELBGCOLOR, m->screen); + m->dc.sel[ColFG] = getcolor(SELFGCOLOR, m->screen); initfont(m, FONT); m->dc.h = bh = m->dc.font.height + 2; @@ -1675,54 +1702,51 @@ textw(Monitor *m, const char *text) { } void -tile(void) { - unsigned int i, j, n, nx, ny, nw, nh, mw, th; +tile(Monitor *m) { + unsigned int j, n, nx, ny, nw, nh, mw, th; Client *c, *mc; domwfact = dozoom = True; - nw = 0; /* gcc stupidity requires this */ - - for (i = 0; i < mcount; i++) { - Monitor *m = &monitors[i]; - - for(n = 0, c = nexttiled(clients, m); c; c = nexttiled(c->next, m)) - n++; - - for(j = 0, c = mc = nexttiled(clients, m); c; c = nexttiled(c->next, m)) { - /* window geoms */ - mw = (n == 1) ? m->waw : m->mwfact * m->waw; - th = (n > 1) ? m->wah / (n - 1) : 0; - if(n > 1 && th < bh) - th = m->wah; - if(j == 0) { /* master */ - nx = m->wax; + nw = nx = ny = 0; /* gcc stupidity requires this */ + + for(n = 0, c = nexttiled(clients, m); c; c = nexttiled(c->next, m)) + n++; + + for(j = 0, c = mc = nexttiled(clients, m); c; c = nexttiled(c->next, m)) { + /* window geoms */ + mw = (n == 1) ? m->waw : m->mwfact * m->waw; + th = (n > 1) ? m->wah / (n - 1) : 0; + if(n > 1 && th < bh) + th = m->wah; + if(j == 0) { /* master */ + nx = m->wax; + ny = m->way; + nw = mw - 2 * c->border; + nh = m->wah - 2 * c->border; + } + else { /* tile window */ + if(j == 1) { ny = m->way; - nw = mw - 2 * c->border; - nh = m->wah - 2 * c->border; + nx += mc->w + 2 * mc->border; + nw = m->waw - mw - 2 * c->border; } - else { /* tile window */ - if(j == 1) { - ny = m->way; - nx += mc->w + 2 * mc->border; - nw = m->waw - mw - 2 * c->border; - } - if(j + 1 == n) /* remainder */ - nh = (m->way + m->wah) - ny - 2 * c->border; - else - nh = th - 2 * c->border; - } - resize(c, nx, ny, nw, nh, RESIZEHINTS); - if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw))) - /* client doesn't accept size constraints */ - resize(c, nx, ny, nw, nh, False); - if(n > 1 && th != m->wah) - ny = c->y + c->h + 2 * c->border; - - j++; - } - } -} + if(j + 1 == n) /* remainder */ + nh = (m->way + m->wah) - ny - 2 * c->border; + else + nh = th - 2 * c->border; + } + resize(c, nx, ny, nw, nh, RESIZEHINTS); + if((RESIZEHINTS) && ((c->h < bh) || (c->h > nh) || (c->w < bh) || (c->w > nw))) + /* client doesn't accept size constraints */ + resize(c, nx, ny, nw, nh, False); + if(n > 1 && th != m->wah) + ny = c->y + c->h + 2 * c->border; + + j++; + } +} + void togglebar(const char *arg) { if(bpos == BarOff) @@ -1976,7 +2000,6 @@ monitorat(int x, int y) { monitorat(int x, int y) { int i; - return 0; if(!XineramaIsActive(dpy)) return 0;