Closed Bug 230097 Opened 21 years ago Closed 3 years ago

Improper focus of text-fields in certain window managers -> Can't type in text-fields

Categories

(Core :: DOM: UI Events & Focus Handling, defect)

x86
Linux
defect
Not set
major

Tracking

()

RESOLVED INCOMPLETE

People

(Reporter: lillesvin, Unassigned)

References

Details

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031225 Firebird/0.7
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031225 Firebird/0.7

I'm using the Kahakai wm (http://kahakai.sf.net), but the problem has occured in
fluxbox and papuawm (http://papuaos.org/papuawm) too...

Sometimes it seems like Firebird doesn't take 100% focus, though the window has
focus... I can't write in the location-bar, text-fields in web-pages,
anything... I can copy/paste, click buttons etc... Although the menus don't work
properly either. Fx: Bookmarks -> Mozilla Firebird & Mozilla Information ->
MozillaZine will cause nothing to happen.

Reproducible: Sometimes

Steps to Reproduce:
1. Use the Kahakai window manager (it has the highest frequency of occurences of
this bug).
2. Open Firebird
3. Jump a little around between the desktops
4. Try to enter an url into the location bar/google search bar or into a
text-field in a loaded web-page.
Actual Results:  
Can't write in ANY text-field in Firebird... Read additional information.

Expected Results:  
Uhm... Allowed me to write in text-fields. :-)

I've found a way to get around this problem...
1: Give Firebird focus and hope it fails.
2: Open some bookmark from the Bookmarks Toolbar (they work just fine).
3: Try editing the url in the location bar (should fail).
4: Double-click (hold the mouse-button down on the last click), this will select
the entire url.
5: While holding the key, drag the url to some pointless place to drag an url.
(fx. the window titlebar). (Remember to let go of the mousebutton when done
dragging.) :)
6: Edit your url in the location bar or write in the text-fields...

This works with any text-field, be it location bar or the google search-field.
With the ion window manager this happens to me continually, probably because ion
does some things with focus that firefox doesn't understand.  I only encounter
the problem when I have multiple firefox windows open, and the typing seems to
always be routed to another window.  Bookmarks, the location bar, text fields,
pg-up, pg-dn, etc are all broken when this bug is in effect, but it is not
always reproducible.  This may be the same as bug 216694, which is marked as
"worksforme" but still does not work for me.  The bug was introduced between
firebird 0.6 and 0.7, as 0.6 works perfectly, while 0.7 and 0.8 don't.

(Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040207 Firefox/0.8)
This bug only seems to occur under Mozilla* built against Gtk2. Gtk1 versions
have no such problems. I have not noticed the problem with other Gtk2 programs,
though.
I hit this all the time as well (I use ion for a WM).

It seems to occur (focus goes awry) whenever an alert() comes up.
Assignee: firefox → jag
Component: General → XP Apps
Product: Firefox → Browser
QA Contact: pawyskoczka
Version: unspecified → Trunk
Assignee: jag → blizzard
Component: XP Apps → GFX: Gtk
QA Contact: pawyskoczka → ian
*** Bug 246697 has been marked as a duplicate of this bug. ***
I had this problem with Firefox <= 0.7 with KDE and on Debian, see
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=196489

...but I haven't seen it lately, and I've been on 0.8 for a while. Still waiting
for Debian packages of 0.9.x to propagate to Testing. 
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7) Gecko/20040712 Firefox/0.9.1

I can confirm that this bug still exists in Debian package for firefox 0.9.1
under the ion window manager.  When a second window of firefox is opened, focus
does not change correctly between the two windows.

This is mentioned in the ion FAQ (scroll down to point 3.9) as a problem
occuring with mozilla built with gtk2 only:
http://modeemi.cs.tut.fi/~tuomov/ion/faq.html
I have the symptom with Firefox 0.9.2 and the ion window manager, too. If I open
a new window with Ctrl-N, the original window can't get keyboard focus even if I
click anywhere in the window.

I've found two ways to restore the keyboard focus to the original window:

1. close the new window and click on the original window

  or

2. in the original window, open any dialog (e.g. File/Open File) with the mouse,
cancel the dialog and click on the browser window (now kbd focus works in both
the original and the new window)
For reference, the "open and close a dialog" trick doesn't work with
epiphany-1.2.6 (presumably because it's a gtk+ container that embeds gecko, so
the dialogs are native instead of going through the Mozilla display system).  
This problem happens consistently for me using ff 0.9.1 with ion.  One of the
most annoying aspects is that ctrl-w will close a window that isn't focused...
Happens very frequently to me with Firefox 0.9.3 under Ion, too.
I have a workaround, which may be of some use to someone:
when one of my Firefox windows starts refusing to take focus,
if I fullscreen it with alt-enter and then leave fullscreen
mode with alt-enter again then it starts accepting focus again
for a while.

It also appears that the ability to take focus depends on what
window focus is being taken *from*. Right now I have three Firefox
windows up in an Ion workspace. Call them A, B, C. Then I observe
the following. (I should mention, first of all, that Ion has a
focus-follows-mouse policy.)

  - B (the one in which I am typing this, thankfully)
    consistently behaves as it ought.

  - If B has focus, moving the mouse over A or C results
    in neither window having focus. But *clicking* in A or C
    works fine (even if the mouse has moved over the other
    one).

  - At that point, the other one of {A,C} will not take focus
    even when clicked in. But B is still fine, and takes focus
    as soon as the mouse moves over it.

I don't remember in what order A, B, C were created or anything
else similarly useful, but this behaviour seems odd enough that
it might be useful for diagnosis. I have just tried the experiment
of closing A and recreating it (by control-N in window B); the
behaviour remains as above. And again, closing A and recreating
it by control-N in window C; now A and B are perfectly behaved
and C will take focus only when actually clicked in.
This bug is now over eight months old and is still marked as "NEW". It happens
with the latest version of Firefox (0.9.3) and makes it look like a very flaky
product for some users.
I have spent some time debugging this focus problem, as it is 100% reproducible
for me using the Ion window manager (ion2 version 20040601-2 in the Debian
distribution). In a nutshell, it seems to be caused by unpaired X pointer 
focus events: a FocusIn NotifyPointer event without a corresponding FocusOut
event.

The bug concerns gtk2 builds of Mozilla variants, tested with:

- firefox (0.9.3,  Debian mozilla-firefox package 0.9.3-5)
- mozilla (1.7.3,  Debian mozilla-browser package 2:1.7.3-5)
- galeon  (1.3.17, Debian package 1.3.17-2)

and tested with gtk2 versions
- 2.4.10 (Debian package libgtk2.0-0 2.4.10-1)
- 2.4.13 (Debian package libgtk2.0-0 2.4.13-1)

Only gtk2 builds are affected, a self-built firefox gtk1 binary works flawlessly.

The bug depends on pointer events, and a short explanation of the ion
window manager is probably needed. Ion never overlaps windows, but rather
opens them in tabs (not related to the Mozilla tabs), so that only one of 
the windows is visible in a tab at one time. So when mozilla creates a new
window, it opens in the same ion tab, replacing (unmapping) the original one.
When the window is closed, the original one is restored. (Of course, you can
switch between the windows in the meantime if you want). See
<http://modeemi.cs.tut.fi/~tuomov/ion/> for more info.

The bug manifests itself in the simplest case by starting a new browser, hitting
Ctrl-N for a new window and then closing the new window immediately with Ctrl-W.
If the mouse pointer is inside the browser window all the time, the original
window will not get keyboard focus back. If the pointer is outside the browser
window all the time, the keyboard focus works fine.

Note that this is just the simplest case. If I don't close the second
window but rather just switch from it back to the original window, I
end up with the keyboard focus still in the second (but now non-visible)
window. I can include logs of this too if needed.

I have made tests with --enable-debug builds of firefox and gtk2, running
them with NSPR_LOG_MODULES=WidgetFocus:5 and GDK_DEBUG=events . Below are
parts of the logs in both the buggy and the non-buggy case. There's some
discussion after the logs as well.

Case 1: mouse pointer in the window (buggy situation):

Start firefox:

[...]
Gdk-Message: focus in:          window: 10485829, detail: NotifyPointer, mode:
NotifyNormal
16384[8078468]: entering focus in event callback, widget [8295370]
16384[8078468]: OnContainerFocusInEvent [8295070]
[...]
Gdk-Message: client message:    window: 10485829
Gdk-Message: *take focus:                window: 10485829
Gdk-Message: focus in:          window: 10485829, detail: NotifyAncestor, mode:
NotifyNormal
[no OnContainerFocusInEvent, because first window already got focus]
[...]

Press 'Ctrl-N':

[...]
Gdk-Message: focus out:         window: 10485829, detail: NotifyAncestor, mode:
NotifyNormal
[no OnContainerFocusOutEvent, see discussion below]
Gdk-Message: focus in:          window: 10486208, detail: NotifyPointer, mode:
NotifyNormal
16384[8078468]: entering focus in event callback, widget [814e7e8]
16384[8078468]: OnContainerFocusInEvent [86546f8]
[...]
Gdk-Message: client message:    window: 10486208
Gdk-Message: *take focus:                window: 10486208
Gdk-Message: focus in:          window: 10486208, detail: NotifyAncestor, mode:
NotifyNormal
[no OnContainerFocusInEvent, because second window already got focus]
[...]

Press 'Ctrl-W':

[...]
16384[8078468]: entering focus out event callback, widget [814e7e8]
16384[8078468]: OnContainerFocusOutEvent [86546f8]
[...]
Gdk-Message: client message:    window: 10485829
Gdk-Message: *take focus:                window: 10485829
Gdk-Message: focus in:          window: 10485829, detail: NotifyAncestor, mode:
NotifyNormal
[no OnContainerFocusInEvent, see discussion below]
[...]

Keyboard focus in the original window is now lost.


Case 2: mouse outside the window (no bug exhibited):
start firefox

[...]
Gdk-Message: client message:    window: 10485829
Gdk-Message: *take focus:                window: 10485829
Gdk-Message: focus in:          window: 10485829, detail: NotifyAncestor, mode:
NotifyNormal
16384[8078468]: entering focus in event callback, widget [82950e0]
16384[8078468]: OnContainerFocusInEvent [8294de0]
[...]

Press 'Ctrl-N':

[...]
Gdk-Message: focus out:         window: 10485829, detail: NotifyAncestor, mode:
NotifyNormal
16384[8078468]: entering focus out event callback, widget [82950e0]
16384[8078468]: OnContainerFocusOutEvent [8294de0]
[...]
Gdk-Message: client message:    window: 10486123
Gdk-Message: *take focus:                window: 10486123
Gdk-Message: focus in:          window: 10486123, detail: NotifyAncestor, mode:
NotifyNormal
16384[8078468]: entering focus in event callback, widget [85b4658]
16384[8078468]: OnContainerFocusInEvent [83555d0]
[...]

Ctrl-W:
[...]
16384[8078468]: entering focus out event callback, widget [85b4658]
16384[8078468]: OnContainerFocusOutEvent [83555d0]
[...]
Gdk-Message: client message:    window: 10485829
Gdk-Message: *take focus:                window: 10485829
Gdk-Message: focus in:          window: 10485829, detail: NotifyAncestor, mode:
NotifyNormal
16384[8078468]: entering focus in event callback, widget [82950e0]
16384[8078468]: OnContainerFocusInEvent [8294de0]
[...]

The keyboard focus is now in the original window, as it should be.

Note: the lines with 'client message' are all WM_TAKE_FOCUS messages from
the window manager, which I have verified with  a local addition to gtk2,
printing the '*take focus' lines.

Discussion:

Most of the focus action takes place around widget/src/gtk2/nsWindow.cpp
in the mozilla/firefox source tree, and around gdk/x11/gdkevents-x11.c
in the gtk2 source tree. My interpretation is as follows:

Mozilla uses the gtk2 focus_in_event and focus_out_event events
to keep track of which window has the focus and to send corresponding
internal activation/deactivation signals. The OnContainerFocusInEvent
and OnContainerFocusOutEvent lines in the logs show when these events
arrive to mozilla.

The gtk2 focus events are sent from gdk_event_translate() when the
HAS_FOCUS state changes as a result of FocusIn and FocusOut X events.
The 'focus in' and 'focus out' Gdk-Messages in the logs show when the
X events are handled.

The HAS_FOCUS is defined in gdk/x11/gdkevents-x11.c :

#define HAS_FOCUS(toplevel)                           \
  ((toplevel)->has_focus || (toplevel)->has_pointer_focus)

and used by gdk_event_translate() in the same file.

Here has_focus gets set / cleared by these X focus event details:
            case NotifyAncestor:
            case NotifyNonlinear:
            case NotifyVirtual:
            case NotifyNonlinearVirtual:
and has_pointer_focus just by this:
            case NotifyPointer:

Now in the buggy case there is a FocusIn event with NotifyPointer, but
no corresponding FocusOut event, and so the HAS_FOCUS state remains true
for the first window all the time. Thus the gtk2 events are not triggered
and mozilla doesn't activate/deactivate its windows properly.

I don't know enough of X events to say who is wrong here.
The window manager has no control over the detail (or mode) field of           
focus change events. The X server decides those. It is my understanding        
that NotifyPointer focus events do not convey actual focus information.        
They are simply used to inform that, "hey, even if the focus changed, the      
pointer is still in this window, so keep still drawing all indications of      
that." No FocusOut corresponding to the NotifyPointer FocusIn event is         
sent as when the window containing the pointer is unmapped because the         
window does not have the focus. It would seem that firefox is taking           
NotifyPointer for a normal focus event.                                        
                                                                               
http://www.tronche.com/gui/x/xlib/events/input-focus/normal-and-grabbed.html   
As this bug seems to be in gtk2, I have reported it in the GNOME bugzilla.
My submission was #158038 (http://bugzilla.gnome.org/show_bug.cgi?id=158038), 
and it is being tracked as duplicate of bug #109246 
(http://bugzilla.gnome.org/show_bug.cgi?id=109246).
The even logs here don't contain sufficient information to diagnose
the problem. What would be needed would be:

 - Enter/leave events (preferrable with xevent->xcrossing.focus ...
   you'd have to hack gdkevents-x11.c a bit to spew that as well)

 - Map/unmap events

FocusIn/NotifyPointer *is* a real focus event... it indicates that
the window is receiving keystrokes because the server is in PointerRoot
mode, which it appears that ion leaves the server in frequently for
short periods of time.

> No FocusOut corresponding to the NotifyPointer FocusIn event is         
> sent as when the window containing the pointer is unmapped because the         
> window does not have the focus

Is correct as far as it goes, but the window should be getting a LeaveNotify
event with the focus flag set. dix/events.c line 3191:

        if ((focus != NoneWin) &&
            ((pWin == focus) || (focus == PointerRootWin) ||
             IsParent(focus, pWin)))
            event.u.enterLeave.flags |= ELFlagFocus;

(Also specified in the protocol spec page 72, but the X server code was easier
to cut and paste)

And that will result in has_pointer_focus getting unset in GTK+. There is 
probably some code path that I'm missing with a bug in it, but I'd need a more 
complete event log to figure 
OK, I see what is going on for ion ... ion quite unusually focuses an 
intermediate window between the root window and the pointer window, which
the GTK+ logic doesn't handle properly.

[ This is not a mozilla bug and could be resolved in this bug tracker,
  it seems to me. Though there seems to be some indication from the
  reported symptoms that Mozilla has effectively a global:

   GtkWindow *active_window;

  rather than considering "active" to be a boolean property of a window,
  and then refuses to send events to a window if it isn't the 
  global active window, which is rather a silly way to go about things ]

I should note that I'm not at all convinced that the problem with ion is the
same as the original problems reported with other window managers, which
are much more likely to be bad implementations of locally active focus
in the window manager resulting in the window manager getting confused.
For the record, I frequently see behaviour similar to this when running Firefox
in WindowMaker.  (Perhaps three or four times a day with regular use.)

The versions I'm currently using in which it definitely happens are "Mozilla/5.0
(X11; U; NetBSD i386; en-US; rv:1.7.6) Gecko/20050327 Firefox/1.0.2" with
"Window Maker 0.91.0", running on NetBSD ( 2.99.10 NetBSD 2.99.10).

I've also seen it occur in Debian Linux (sarge), but don't have the system in
front of me to comment on specific versions involved, and unfortunately it's
difficult to reliably reproduce.

I think both of these are Firefox compiled with gtk2, so from reading the other
comments, it's quite possible that gtk2 is the problem.
> FocusIn/NotifyPointer *is* a real focus event... it indicates that
the window is receiving keystrokes because the server is in PointerRoot
mode, which it appears that ion leaves the server in frequently for
short periods of time.

According to this page,
http://tronche.com/gui/x/xlib/events/input-focus/normal-and-grabbed.html
NotifyPointer is generated when the focus moves normally between windows.

However, the focus indeed jumps back to the frame window (by RevertToParent) 
temporarily after the client window switched out of has been unmapped, until we 
can safely give focus to the newly switched to window in the mainloop.
Does this bug still occur in a recent trunk build?
http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/
Assignee: blizzard → nobody
Component: GFX: Gtk → Event Handling
QA Contact: ian → events
Component: Event Handling → User events and focus handling

Marking this as Resolved > Incomplete since the last activity on this issue was 15 years ago, the reporter doesn't reply and it might not be relevant anymore. Feel free to re-open if the issue is still reproducible on your end in the latest FF versions.

Status: NEW → RESOLVED
Closed: 3 years ago
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.