After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 720558 - Focus not displayed correctly for Swing applications
Focus not displayed correctly for Swing applications
Status: RESOLVED FIXED
Product: mutter
Classification: Core
Component: general
unspecified
Other Linux
: Normal normal
: ---
Assigned To: mutter-maint
mutter-maint
Depends on:
Blocks:
 
 
Reported: 2013-12-16 20:59 UTC by Owen Taylor
Modified: 2013-12-18 14:41 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Fix problems with focus tracking (4.02 KB, patch)
2013-12-16 21:07 UTC, Owen Taylor
committed Details | Review

Description Owen Taylor 2013-12-16 20:59:19 UTC
Apparently the Java code is using "globally active focus", which means it sets the input hint to false but asks for WM_TAKE_FOCUS. This means, that we have to track the focus on Java windows reactively when the app responds to WM_TAKE_FOCUS, rather than predictively. This has been broken since the changes in bug 701017. Earlier conversation on this issue from October:

===
<Jasper> first of all, this needs to happen: http://paste.fedoraproject.org/44863/38117072
<Jasper>        otherwise, if we get an FocusOut and then an FocusIn with the same serial, we'll ignore the FocusIn, and our prediction will become incorrect
<owen>  mmm, I think care is needed here before we start changing things
<Jasper>        of course
<owen>  you changed it the other way in 7fdfbad6d495e
<Jasper>        !stop
<Jasper>        Yeah, I remember that too.
<Jasper>        aha, so that was the key.
<owen>  Though I think we do have a problem with the > vs. >= there
<Jasper>        yeah.
<owen>  which we're noticing here because we're failing to predict the focus correctly
<Jasper>        I don't remember why I changed it to >
<owen>  It's all in the bug
<owen>  (You changed it because I told you to)
<owen>  It seems to me that we basically need to distinguish the case where focus_serial was set from request_xserver_input_focus_change() - in which case we know that we have predicted *everything* for that serial (since we did the grab dance) and other cases
<Jasper>        I don't see why >= is worng.
<Jasper>        you mention something about the
<Jasper>          if (event->xany.serial > display->focus_serial &&
<Jasper>              display->focus_window &&
<Jasper>              display->focus_window->xwindow != display->server_focus_window)
<Jasper>        but as far as I can tell, that's something different. "If an event that we have is greater than the focus serial and the server's focus window isn't what we think it is, complain"
<Jasper>        so how exactly does serial counting work? Let's say that in some hypothetical scenario, my last request to the server was a while ago, for something completely unrelated. The serial for that request was 1234.
<Jasper>        A minute later, I get a FocusIn event. Will the serial be 1234, or 1235?
<owen>  OK, so with the current way we do things in request_xserver_input_focus_change it has to be > or we won't succesfully ignore our own requests
<owen>  Changing it back to >= would require us to use the serial of the *next* request in request_xserver_input_focus_change
<owen>  which is what you were doing in the patch - and that's what I thought would break the failure detection
<Jasper>        ah, right, since the failure detection is at the start of event_callback, *before* handle_window_focus_event is called.
<Jasper>        couldn't we also fix it by moving the failure detection code until after we tried to handle the event?
<Jasper>        in fact, is there a reason we try to do the failure detection for all events, instead of just when we get FocusIn/FocusOuts?
<owen>  failure detection has to be on all events - the point of failure is at times we try to change the focus and silently nothing happens
<Jasper>        ah, right, which is the case where the timestamp is too old
<Jasper>        is there a reason the code there is "event_serial > last_focus_serial"? As I understand it, if the server sends us an event with a serial == focus_serial, that means it processed our request. So *that* should be >= too.
<Jasper>        Oh, wait, erm, right, we need to ignore the focus request itself.
<owen>  I think that's the right fix - in terms of the other thing focus_set_by_us flag (set by update_focus_window only when we do the grab dance) is easiest - the code to detect failure of screenshots has no meaning in the !focus_set_by_us case so trying to figure out what the right comparisons are in that case is just going to hurt the head and be hard to maintain
<owen>  failure of focusing I mean
<Jasper>        it's a separate bug. I'm sure there's other cases where we could get a FocusOut/FocusIn pair and ignore the latter.
<owen>  Yes, it's a separate bug - basically any time that prediction fails, mostly means incompliant app
<owen>  a test program that does XOpenDiplay(); XSetInputFocus(xid_from_commandline); XSync(); could be written and used to test it
<Jasper>        all it means is that the focus moved from A to B in the same request. That could happen with any app, right?
<owen>  It means that focus moved from A to B and *we didn't expect it*
<owen>  (In addition to non-compliant, globally active also applies - probably even rarer)
===

I'll attach a patch implementing my suggestion, which seems to work to fix the problem.
Comment 1 Owen Taylor 2013-12-16 21:07:13 UTC
Created attachment 264328 [details] [review]
Fix problems with focus tracking

When a client spontaneously focuses their window, perhaps in response
to WM_TAKE_FOCUS we'll get a FocusOut/FocusIn pair with same serial.
Updating display->focus_serial in response to FocusOut then was causing
us to ignore FocusIn and think that the focus was not on any window.

We need to distinguish this spontaneous case from the case where we
set the focus ourselves - when we set the focus ourselves, we're careful
to combine the SetFocus with a property change so that we know definitively
what focus events we have already accountd for.
Comment 2 Jasper St. Pierre (not reading bugmail) 2013-12-16 21:30:15 UTC
Review of attachment 264328 [details] [review]:

::: src/core/display.c
@@ +2098,3 @@
+  if (display->server_focus_serial > display->focus_serial ||
+      (!display->focused_by_us &&
+       display->server_focus_serial == display->focus_serial))

A comment making this logic clearer would be nice. Perhaps just copy/paste the comment from display-private.h?
Comment 3 Owen Taylor 2013-12-18 14:41:11 UTC
Pushed with an added comment.

Attachment 264328 [details] pushed as 6891ce9 - Fix problems with focus tracking