Created attachment 4095
TRACE() log for events.c and focus.c
First off, thanks for a great desktop environment.
I've noticed this problem for some months and finally tried to figure out its cause, which I have (at least approximately). I'll give my stab at an explanation below with some logs. I use a trackball, which makes the bug much easier to reproduce (and therefore much more annoying!)
Steps to reproduce:
1. Put the window manager in "focus follows mouse" mode with the delay bar set at the minimum.
2. Set up several windows (4-5 should work) that mostly overlap.
3. From standing still, move the mouse quickly across them. Repeat as necessary.
Often the focus will be left in a window the mouse cursor has already passed through.
Focus should always end up on the window where the mouse cursor has stopped.
Platform / Version:
Gentoo linux x86_64
built on 2011-05-07
Also, here are a couple of downstream bug reports on the same problem:
As to the cause, I think it's a race between handlers for the second of two closely-spaced EnterNotify events and the FocusIn handler that's eventually triggered by the first EnterNotify. handleFocusIn() calls clientUpdateFocus() calls clientClearDelayedFocus(), which clobbers the timer set by the second EnterNotify, and so the latter never gets its own timer callback. Disabling the focus-delay timer entirely in handleEnterNotify() makes the problem go away.
I'm attaching a log of the TRACE calls in events.c and focus.c from a test that caught it in the act. Windows were arranged as Konsole (note, client name is "aanderson : xev" since that's where an xev was launched from),
xev 1, xev 2, xev 3 from left to right. Mouse went across them from Konsole into xev 3, but focus was left in xev 2.
Line 4: setting focus to Konsole (this is window 0x180001)
Line 103: setting focus to xev 1 (this is window 0x1e0001)
Line 182: setting focus to xev 2 (this is window 0x200001)
Line 191: handleEnterNotify() for xev 3 (I think) (xev 3 is window 0x220001)
Line 232: handleFocusIn() for xev 2
Line 443: (test completed) setting focus back to Konsole
You're right, there's a race in there. The clientUpdateFocus() should not cancel the pending focus transition.
Fixed in git.