Applications ignoring focus events



Hello,

I think something needs to be said somewhere about Focus events for
applications that want to keep track of the focus state of their
windows, and I think this would be the place to do it. I appologize
that this is a little technical and specific to Xlib's focus events,
but hopefully they should be familiar enough to most of you.

As it is right now, without any standard, there is little you can do
to ensure that your application will work correctly under every window
manager. I haven't delved into the Firefox code, but I think the
notorius bug of the wrong Firefox window thinking it is focused
derives from this issue, so its not something obscure. As well, KDE
applications such as Kopete are affected. I used Kopete to test
everything that follows as it provided an easy way to test the various
cases.

The problem lies with the NotifyGrab, NotifyWhileGrabbed, NotifyUngrab
Focus events. There are two approaches to watching when your window
loses focus:

a) Ignore no events at all. Many terminal programs do this, so you get
the notorius flicker when you hit a keybinding if they key is grabbed
on the root window (or any window other than their own).  These
applications will always know when they lost focus, at the cost of
thinking they have lost focus every time you press a key.

An example of a) would be if you had Kopete set up to beep when you
received a message in the window and it wasn't active. If Kopete used
this approach (it doesn't), it would beep at you if a message came in
while you are alt-tabbing, even though the window appears to be
focused still on screen. I'm guessing that is why they don't use this
approach.

b) Ignore focus events from grabs. This fixes the problem of thinking
you are not focused when you visually are, but in its place you can
lose focus and have no idea. You can move focus off the Kopete window
and receive messages, and it won't know to beep at you, thinking that
it is still the active window.

So.. some nitty gritty details for my digging around for the cause of
this all.. I'm going to just talk about key events, even though the
same would apply to mouse buttons but they are generally not used in
these same ways. I'm also going to assume that the application is
ignoring Grab-type focus events, because having the visibly focused
window thinking it is not focused is a real inconsistancy to users.

Active grabs:

If you were to alt-tab in your window manager and bring up a focus
cycling dialog, the WM is going to make an XGrabKeyboard call. This is
going to send our Kopete window a FocusOut-NotifyGrab, which it will
ignore. If the user selected a new window and the WM moved focus there
_before_ XUngrabKeyboard'ing, the Kopete window will not get another
focus event, so it will be unaware that it has lost focus (it ignored
the Grab one).

Two solutions are to require the WM to ungrab everything before
sending focus anywhere, so the Kopete window can get a
FocusIn-NotifyUngrab -> FocusOut-NotifyNormal, or require applications
to listen to all focus events, which is undesirable.

This gets really tricky for things that hide windows like changing
desktops. Metacity currently suffers from this problem because it
grabs the keyboard (for its popup dialog) and ends up hiding the
focused window during the grab.  The window ends up with no idea it
lost focus.

Passive grabs:

For keybinds that are not causing an XGrabKeyboard, but are grabbed
regardless (on the root window or even on the client's window), when
the key is pressed a passive grab is made on the keyboard until it is
released. So if focus moves while the key is still pressed, the window
will again have no idea that it lost focus. This includes if the
window is hidden (changing desktops).  As a solution, the WM can
XUngrabKeyboard to release the passive grab, or it can wait until the
key is released. This way the application receives a
FocusOut-NotifyNormal.

I'd like to suggest that it be the requirement of WM's to ensure they
don't move the focus (or hide the focused window) during a grab, but
that can also limit the functionality a WM can provide. I can't see a
way to provide metacity's current desktop changin behavior (changing
and showing the popup dialog at the same time) without causing a
Grab-type focus out on the window, without some real tricks: You'd
need to ungrab the passive grab, move focus, then grab the keyboard
and give focus back to a window once that grab was released on their
chosen desktop.

It would be so much easier to insist that applications listen to all
focus events, but as I said, you don't want windows thinking that they
are not focused when they logically are (and visually).

I'm not really coming here with a solution to this, but rather looking
for some ideas, and to have something standardized, in any way, so
that you can at least guarantee the behavior you wanted from your app
in any compliant environment.

One possible solution to all of this would be to demand that
applications ignore all focus events, and instead only use the
_NET_ACTIVE_WINDOW hint to determine if they are focused or not. That
should really be implemented and enforced somehow at the toolkit
level, though.

Thoughts anyone?



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]