So here's another go at mapping new windows after everything has been arranged.
This time, floating windows are stacked correctly and there are no flickers or redraws of the title bar or the new window. The two patches add 8 short lines. Seems not too gross as an interim solution. The line "c->mon->sel = c;" also fixes a vanilla dwm bug on Xinerama setups: 1. Focus a floating window w belonging to a client c 2. Focus another monitor with focusmon() 3. When c pops up a transient window w' on the unfocused monitor, w' is stacked behind w. For testing, transient.c opens a floating window and then after 5 seconds a transient one. Peter
--- dwm/dwm.c.orig 2011-07-28 17:55:50.482916191 +0200 +++ dwm/dwm.c 2011-07-28 17:56:27.387448688 +0200 @@ -389,7 +389,6 @@ arrange(Monitor *m) { 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) @@ -598,6 +597,7 @@ configurenotify(XEvent *e) { updatebars(); for(m = mons; m; m = m->next) XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + focus(NULL); arrange(NULL); } } @@ -1157,6 +1157,7 @@ manage(Window w, XWindowAttributes *wa) XMapWindow(dpy, c->win); setclientstate(c, NormalState); arrange(c->mon); + focus(NULL); } void @@ -1621,6 +1622,7 @@ void tag(const Arg *arg) { if(selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); arrange(selmon); } } @@ -1701,6 +1703,7 @@ toggletag(const Arg *arg) { newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if(newtags) { selmon->sel->tags = newtags; + focus(NULL); arrange(selmon); } } @@ -1711,6 +1714,7 @@ toggleview(const Arg *arg) { if(newtagset) { selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); arrange(selmon); } } @@ -1976,6 +1980,7 @@ view(const Arg *arg) { selmon->seltags ^= 1; /* toggle sel tagset */ if(arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + focus(NULL); arrange(selmon); }
--- dwm/dwm.c.orig 2011-07-29 16:35:14.265835028 +0200 +++ dwm/dwm.c 2011-07-29 16:35:41.523589947 +0200 @@ -1154,9 +1154,12 @@ manage(Window w, XWindowAttributes *wa) 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); }
/* cc transient.c -o transient -lX11 */ #include <stdlib.h> #include <unistd.h> #include <X11/Xlib.h> #include <X11/Xutil.h> int main(void) { Display *d; Window r, f, t = None; XSizeHints h; XEvent e; d = XOpenDisplay(NULL); if (!d) exit(1); r = DefaultRootWindow(d); f = XCreateSimpleWindow(d, r, 100, 100, 400, 400, 0, 0, 0); h.min_width = h.max_width = h.min_height = h.max_height = 400; h.flags = PMinSize | PMaxSize; XSetWMNormalHints(d, f, &h); XStoreName(d, f, "floating"); XMapWindow(d, f); XSelectInput(d, f, ExposureMask); while (1) { XNextEvent(d, &e); if (t == None) { sleep(5); t = XCreateSimpleWindow(d, r, 50, 50, 100, 100, 0, 0, 0); XSetTransientForHint(d, t, f); XStoreName(d, t, "transient"); XMapWindow(d, t); XSelectInput(d, t, ExposureMask); } } XCloseDisplay(d); exit(0); }