[dev] [patch] Xinerama bugfix + map new window *after* arrange(), again
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 #include #include #include 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); }
Re: [dev] [dwm] code cleanup
Hi, > void > grabkeys(void) { > + unsigned int i, j; > + unsigned int modifiers[] = { 0, LockMask, numlockmask, > numlockmask|LockMask }; > + KeyCode code; > + > updatenumlockmask(); > - { > - unsigned int i, j; > - unsigned int modifiers[] = { 0, LockMask, numlockmask, > numlockmask|LockMask }; > - KeyCode code; That would break the numlockmask stuff. Regards, Peter
Re: [dev] [patch] map new window *after* arrange()
> To prevent the first restack, maybe something like the attached patch? ... which causes the title bar to flicker, as restack calls drawbar before bailing out. Not sure why that's needed. Peter
Re: [dev] [patch] map new window *after* arrange()
> just one annoying issue with floating apps. eg. running save as in gimp, > will open a window in the background. Oh man, sorry. I should've tested it more with floating windows. So arrange calls arrangemon, which calls restack, but the new floating window hasn't become selmon->sel yet. Restacking again at the end of manage fixes it, but then there's another redraw. To prevent the first restack, maybe something like the attached patch? Or split off (un)select functions from (un)focus, which also came up in connection to virtual keyboards some time ago. Regards, Peter --- dwm/dwm.c.orig 2011-07-10 02:34:59.982409153 +0200 +++ dwm/dwm.c 2011-07-10 03:49:19.114387186 +0200 @@ -1150,9 +1150,12 @@ manage(Window w, XWindowAttributes *wa) attachstack(c); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ setclientstate(c, NormalState); + unfocus(selmon->sel, False); + selmon->sel = NULL; arrange(c->mon); XMapWindow(dpy, c->win); focus(c); + restack(c->mon); } void
Re: [dev] [patch] map new window *after* arrange()
Hi Anselm, > I reviewed your patch and concluded I can't apply it as is, because > focus() would be called twice, once on the unmapped window, and then > on again. It seems to me that focusing and arranging should be independent operations. So here comes another patch to remove focus(NULL) from arrange and add it, if missing, everywhere arrange is called after either a window might have vanished from selmon's view, or selmon itself might have vanished. Regards, Peter --- dwm/dwm.c.orig 2011-07-09 01:21:43.924293041 +0200 +++ dwm/dwm.c 2011-07-09 01:25:06.127245938 +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); } } @@ -1616,6 +1616,7 @@ void tag(const Arg *arg) { if(selmon->sel && arg->ui & TAGMASK) { selmon->sel->tags = arg->ui & TAGMASK; + focus(NULL); arrange(selmon); } } @@ -1696,6 +1697,7 @@ toggletag(const Arg *arg) { newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); if(newtags) { selmon->sel->tags = newtags; + focus(NULL); arrange(selmon); } } @@ -1706,6 +1708,7 @@ toggleview(const Arg *arg) { if(newtagset) { selmon->tagset[selmon->seltags] = newtagset; + focus(NULL); arrange(selmon); } } @@ -1971,6 +1974,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); }
[dev] [patch] map new window *after* arrange()
Couldn't dwm map newly created windows *after* they have been moved to their proper position? Less flickering (especially noticeable with the attachabove/attachaside patches), and it feels snappier on a slow computer. I haven't experienced any problems with the attached patch so far. Peter diff -r c787646ca93f dwm.c --- a/dwm.c Sat Jul 02 11:01:58 2011 +0200 +++ b/dwm.c Wed Jul 06 22:55:49 2011 +0200 @@ -1149,9 +1149,10 @@ 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); arrange(c->mon); + XMapWindow(dpy, c->win); + focus(c); } void
[dev] [patch] enternotify: fewer winto{mon,client} calls; small simplification
diff -r 014df3c34b64 dwm.c --- a/dwm.c Sat Jun 25 09:07:04 2011 +0100 +++ b/dwm.c Sat Jun 25 22:46:04 2011 +0200 @@ -827,13 +827,14 @@ if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) return; c = wintoclient(ev->window); - if((m = wintomon(ev->window)) && m != selmon) { + m = c ? c->mon : wintomon(ev->window); + if(m != selmon) { unfocus(selmon->sel, True); selmon = m; } - else if(c == selmon->sel || c == NULL) + else if(!c || c == selmon->sel) return; - focus((wintoclient(ev->window))); + focus(c); } void