GNOME Bugzilla – Bug 126727
GOK getting focus due to gtk+ internals change
Last modified: 2004-12-22 21:47:04 UTC
metacity is now focussing the GOK window, after upgrading to gtk+ 2.3 series (i.e. HEAD). (I haven't upgraded metacity, so this bug might end up being transferred to gtk+ soon) GOK attempts to reject focus by registering a filter when 'realize' is called for the GOK window; the filter code is shown below: GdkFilterReturn gok_discard_focus_filter (GdkXEvent *xevent, GdkEvent *event, gpointer data) { XEvent *xev = (XEvent *)xevent; GList *list, *l; gint n_mapped; GtkWindow *window; gboolean has_focus; if (xev->xany.type == ClientMessage && (Atom) xev->xclient.data.l[0] == gdk_x11_atom_to_xatom ( gdk_atom_intern ("WM_TAKE_FOCUS", False))) { list = gtk_window_list_toplevels (); n_mapped = 0; has_focus = FALSE; for (l = list; l; l = l->next) { if (GTK_WIDGET_MAPPED (GTK_WIDGET (l->data))) { n_mapped++; window = GTK_WINDOW (l->data); if (window->has_focus) has_focus = TRUE; } } if (!has_focus && n_mapped > 1) XSetInputFocus (xev->xany.display, GDK_WINDOW_XID (GTK_WIDGET (window)->window), RevertToPointerRoot, CurrentTime); g_list_free (list); return GDK_FILTER_REMOVE; } ... This works fine with gtk+-2.2 but doesn't work anymore. What gives?
I can confirm this (using gnome build from Nov 5th)
changed severity to 'critical' because, although not a build blocker or SEGV, it makes a core desktop component unusable. reasonable? I am doing some diagnostics to see if the filter-func is getting called.
David: just as a reality check, can you confirm that this happens with an older version of GOK? i.e. do a cvs checkout from a few weeks back and build/install. Or perhaps build-install glib/pango/gtk+ 2.2.X instead of 2.3.X. It'd be nice to be sure which module's behavior has changed, i.e. glib, gtk+, metacity, or gok. My evidence points to gtk+/glib since I haven't upgraded metacity and gok was working prior to switching gtk+ versions, but it's really easy to accidentally get confused about what got installed when ;-) thanks.
It is difficult for me to test this since my hard drive is bursting at the seams and I use the sun gnome build tarballs, deleting the old tree when I install the new one. This definitely started happening right after I updated to the latest sun gnome build for redhat. Perhaps David H could test this? Is DH over there in Ireland?
Created attachment 21410 [details] small test program to illustrate the problem, test-focus-reject.c
Havoc and Owen: I attached a small test program to illustrate the issue. Of course this breaks GOK completely since an onscreen keyboard is of no use if it steals focus from the app you're trying to enter keystrokes into :-) The code for WM_TAKE_FOCUS, i.e. get the event and then do nothing, has always worked in the past. Also I can confirm that the gdk filter is getting called. Looks like a metacity bug, but seems to have only been exposed by switch to gtk+ HEAD, which seems a bit odd.
It looks like a change in gtk+, probably gdk, has caused this problem. I will try to narrow it down further.
Created attachment 21537 [details] [review] Proposed patch
A) Can you *explain* the patch B) Introducing a round-trip here is not acceptable. It may not be possible to fix this without introducing new GDK API. (Note that there are no compatibility guarantees for applications that change the hints that GDK sets on X windows after GDK sets them. There's just no way we can make that guarantee and retain the ability to make forward progress.)
gok and the attached test program calls XSetWMHints with flags set to InputHint and input set to False. This is so that gok main window is not given focus. This setting is overwritten by the call to XSetWMHints in update_wm_hints. It does look like GDK needs new API that gok can call instead of XSetWMHints.
owen: the method used by GOK (calling XSetWMHints) is what you yourself recommended. New API is not the nicest solution since that won't be backwards compatible. IMO changing hints after emission of the 'realize' signal is broken. Can't we just make gdk change hints _after_ realize? or does that not work due to window mapping... ? Is there an event we can listen for that's guaranteed to be emitted _after_ gdk has done all its X tweaking with the window? Let me see if I have this straight; the problem is not with TAKE_FOCUS, but with the fact that the 'INPUT' hint is overriding the TAKE_FOCUS policy? Is the WM supposed to focus a TAKE_FOCUS window without an explicit SetFocus call from the app? Thanks for clarifying.
I suspect that any mention I made of XSetWMHints was prefaced with some disclaimer like "we won't break this in the GTK+-2.2 series, but long term, there's no guarantee one way or the other" Trying to fix how GDK interacts with X is *not* something we can do. A breakpoint and backtrace in your example will reveal why GTK+ is resetting the Wm hints. It might be a bug/inefficiency, it might be needed. Certainly GTK+ can't guarantee that it won't call XSetWMHints after realization ... if someone changes the Icon, GTK+ needs to change the WM Hints. And that could happen at any time the app decided to do so. The ICCCM describes what different combinations of WM_TAKE_FOCUS and the input hint mean. WM_TAKE_FOCUS+Input is the "locally active model", which means "give me the focus, but also send a WM_TAKE_FOCUS message so that I can move it elsewhere" inside the toplevel. Input alone just means "just give me the focus"
See also bug 64613 for related discussion of "output only" windows.
Created attachment 21574 [details] Stack trace of when update_wm_hints is called
we need to escalate the API issue then, and quickly, since this completely breaks GOK and there doesn't appear to be a reliable workaround (unless we can suppress the set_icon call be, perhaps, calling it prior to gtk_window_show()). Even then, it wouldn't be a reliable long-term solution.
I think the backtrace above is the *first* call of update_wm_hints(), before the manual tweaking of the input hint is done, so doesn't really show what's going on. Duping on 64613, since the conclusion here seems to be that we need to add new API. *** This bug has been marked as a duplicate of 64613 ***
owen: Duping this loses the GOK context. I'd like to reopen it for that reason; although the resolution may be "add API", the current behavioral bug is already present and is a user regression.
owen: note that this is 'AP0' so we need to keep this for accessibility bug tracking purposes.
Please reassign to GOK, then.
(reluctantly) reassigning to GOK.
*** Bug 127395 has been marked as a duplicate of this bug. ***
removing PATCH keyword since patch is not acceptable to GTK+ maintainers.
*** Bug 128438 has been marked as a duplicate of this bug. ***
Created attachment 22326 [details] [review] Patch for gok after fix for bug #64613
Padraig: Thanks! This is excellent. I think perhaps we can remove the focus-handler gdkfilterfunc from gok also, it's either in gok-main.c or callbacks.c. Do you want to prepare the patch and apply or should I? I don't mind in the least. Or maybe I am misunderstanding...
I will check.
Created attachment 22330 [details] [review] Updated patch
thanks Padraig. Not sure we need the WM_TAKE_FOCUS protocol registration in main.c either; I'm checking to see if it's needed.
it appears that the WM_TAKE_FOCUS protocol request in main.c is still needed, otherwise the GOK main window sometimes gets focus despite the gtk+ patch. Maybe this is a gtk+ bug, but still... Please feel free to commit the patch as revised, or I'll do it.
I was trying to put this into the bug report but you beat me to it. It looks like a bug in gtk. I will commit the patch to gok.
Patch committed to CVS HEAD.