[xmonad] darcs patch: quick hack to avoid infinite (but breakable) loop when...

Klaus Weidner kweidner at pobox.com
Sat May 17 14:18:53 EDT 2008

On Sat, May 17, 2008 at 05:09:41AM -0700, David Roundy wrote:
> On Sat, May 17, 2008 at 03:12:49AM -0700, Klaus Weidner wrote:
> > The unpatched behaviour restored by your patch is to clear the step (b)
> > enter event. However, that does the wrong thing if moving the mouse
> > quickly across multiple windows A-B-C, in that case B keeps the focus
> > even though the mouse ended in window C.
> I've never observed this, myself.  Perhaps it requires an even slower
> computer than mine, or maybe a really slow layout?

The notebook I saw this on is pretty fast (Core 2 Duo), and I commonly
saw this with a moderately complex (but not unreasonable) dualscreen
setup including combineTwo and tabs on one screen, something like this:

     Screen A                              Screen B
     -- firefox windows --  -- other -
     [tab][tab][tab][tab] | [tab][tab]     [any layout]

Moving the mouse from screen B to the "firefox" tab section on the left
would often get focus stuck on the "other" tab, and I was often closing
the wrong window when intending to close a browser window. I did
generally have my 9 workspaces filled with windows and updating layouts
takes a noticeable amount of time. If I understand it right, the
not-visible windows still slow down the recomputations.

> > Probably the right thing to do would be to clear the pending crossing
> > events in 'windows' whenever the layout manipulation moves/resizes/remaps
> > windows, and not clear it if only the focus has changed. What would be
> > a clean way to make that distinction?
> Probably a better option would be to not clear crossing events at all, but
> instead when we handle crossing events to first check if the mouse is still
> in the said window.  If it's not, then we should ignore the event.

That sounds reasonable - how about a something like the following (not a
real patch - I'm still away from my computer including next week and
can't test this):

 handle e@(CrossingEvent {ev_window = w, ev_event_type = t})
     | t == enterNotify && ev_mode   e == notifyNormal
                        && ev_detail e /= notifyInferior
-    = whenX (asks $ focusFollowsMouse . config) (focus w)
+    = whenX (asks $ focusFollowsMouse . config) $ do
+        dpy <- asks display
+        root <- asks theRoot
+        (_,_,w',_,_,_,_,_) <- io $ queryPointer dpy root
+        when (w == w') (focus w)

     mapM_ (flip setWMState withdrawnState) (W.allWindows old \\ W.allWindows ws)
-    unless isMouseFocused $ clearEvents enterWindowMask

The change should be noticeable if you put a large number of windows on
the screen and quickly move the mouse across them. The three behaviors to
look for would be:

- focus stays in one of the first windows entered (before the
  mouseFocused patch)

- each window crossed briefly gets focused (the border flashes), with
  focus staying in the final one (with mouseFocused patch)

- the final window gets focused, and maybe one or two of the ones crossed
  along the way, but most skip getting focused along the way (hopefully
  the new behavior with the above change)


More information about the xmonad mailing list