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 343897 - Orca's preferences should get focus when is activated.
Orca's preferences should get focus when is activated.
Status: RESOLVED FIXED
Product: orca
Classification: Applications
Component: general
0.2.x
Other All
: Normal normal
: ---
Assigned To: Rich Burridge
Orca Maintainers
Depends on:
Blocks:
 
 
Reported: 2006-06-05 10:59 UTC by Javier
Modified: 2006-06-29 16:14 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Patch that seems to fix the problem nicely. (1.24 KB, application/octet-stream)
2006-06-28 15:29 UTC, Rich Burridge
  Details
Adjustment to first attemp to fix this. (1.47 KB, patch)
2006-06-29 16:11 UTC, Rich Burridge
none Details | Review

Description Javier 2006-06-05 10:59:35 UTC
Please describe the problem:
When the Orca preferences window is activated by pressing insert + space, the window doesn't get focus.

Steps to reproduce:
1. Press insert + space
2. Orca preferences appears but "locus of focus" has not changed.
3. Press alt + tab to give focus to the preferences' window.


Actual results:
The preferences window appears but does not get focus.

Expected results:
The preferences' window should get focus wherever We are. What do you think?

Does this happen every time?
yes

Other information:
Using latest CVS with Ubuntu 6.06 system.
Comment 1 Willie Walker 2006-06-05 13:40:38 UTC
I believe this is an issue with the metacity window manager's attempt at smart focus stealing.  Metacity was rather eager to refuse new windows from getting focus when they are activated, but I believe this has been fixed.  I've tested this on a fresh install of Ubuntu 6.06 and I don't see the problem any more.  It looks like you are still seeing the problem, though.  :-(
   
Comment 2 Elijah Newren 2006-06-05 17:08:46 UTC
I've got a small patch around for debugging focus problems with new windows that you can use.  A few questions, though: Is insert+space a global keybinding, or one you press when the program already has focus?  Is the process that gets the insert+space keybinding separate from the preferences window being launched?
Comment 3 Willie Walker 2006-06-05 18:27:25 UTC
Orca is a screen reader and is mostly an application that has no visible windows.  Instead, it listens for AT-SPI events from all desktop applications (well, those that support the AT-SPI, anyway) via CORBA and presents their information in a non-visual way, such as through speech and/or braille.  Orca also includes a magnification component, but it provides that support by speaking to a magnification service via CORBA.

As such, the preferences UI is the primary GUI window that Orca will ever show.  Insert+space is global in the sense that Orca will listen for keystrokes for the entire desktop, and will show the preferences UI when it detects Insert+space has been pressed no matter which application has focus.  Thus, I guess the answers to your questions are that Orca launches the GUI window and Insert+space is handled in a global manner.

If you can provide some sort of magic to make sure we can give the preferences GUI focus, it would be great!  Thanks!
Comment 4 Elijah Newren 2006-06-05 19:11:27 UTC
So, let's see if I understand you correctly (I'm not very sure that I am, so please correct me):  It isn't orca that receives the insert+space keypress, rather it's one of any of the normal desktop applications -- and then those applications, via at-spi, tell orca that insert+space was pressed.  Is that correct?

(By way of contrast, the way I normally think of global keybindings is how metacity does it -- it actually grabs keys from each and every non-override-redirect window so that X reports those keypresses directly to metacity _instead_ of reporting them to the app; i.e. the app need not communicate anything to metacity and isn't even aware that any keybinding was pressed)
Comment 5 Willie Walker 2006-06-05 19:27:23 UTC
(In reply to comment #4)
> So, let's see if I understand you correctly (I'm not very sure that I am, so
> please correct me):  It isn't orca that receives the insert+space keypress,
> rather it's one of any of the normal desktop applications -- and then those
> applications, via at-spi, tell orca that insert+space was pressed.  Is that
> correct?

Pretty much right on, with the clarification that this is done at the toolkit/at-spi support layer in the application.  For our intents and purposes, one can view the AT-SPI as an in-process application/toolkit layer sitting in between the higher-level application/toolkit logic and the keyboard, giving an out-of-process process such as Orca the first chance at consuming the events.  If Orca consumes the events (which it does in the case of Insert+space), the AT-SPI support doesn't send the event to the higher-level application/toolkit logic.

> (By way of contrast, the way I normally think of global keybindings is how
> metacity does it -- it actually grabs keys from each and every
> non-override-redirect window so that X reports those keypresses directly to
> metacity _instead_ of reporting them to the app; i.e. the app need not
> communicate anything to metacity and isn't even aware that any keybinding was
> pressed)

Understood.  I think the AT-SPI plays similar tricks sometimes, and it may also eventually (if it doesn't already do so) support the XEvIE extension, which will allow assistive technologies such as Orca to get keyboard events at a much lower level.
Comment 6 Elijah Newren 2006-06-05 19:46:35 UTC
(In reply to comment #5)
> Pretty much right on, with the clarification that this is done at the
> toolkit/at-spi support layer in the application. For our intents and purposes,
> one can view the AT-SPI as an in-process application/toolkit layer sitting in
> between the higher-level application/toolkit logic and the keyboard, giving an
> out-of-process process such as Orca the first chance at consuming the events.

Makes sense.  So it looks something like app/gtkwidget-handling <- at-spi <- gdk <- X.  Right?
 
> If Orca consumes the events (which it does in the case of Insert+space), the
> AT-SPI support doesn't send the event to the higher-level application/toolkit
> logic.

Okay, this is beginning to make sense now and I'm pretty sure I know where the bug is.  To verify, though, what are the contents of the message sent by the toolkit via AT-SPI to orca when insert+space is pressed?  I'm almost certain you have a missing bit of data here (unfortunately, an extremely common bit of data to ignore), but want to verify before jumping to conclusions to quickly. 

> Understood.  I think the AT-SPI plays similar tricks sometimes, and it may
> also eventually (if it doesn't already do so) support the XEvIE extension,
> which will allow assistive technologies such as Orca to get keyboard events
> at a much lower level.

If I'm right above about the missing piece of data, I believe that something like this would fix this bug as a side-effect.
Comment 7 Willie Walker 2006-06-08 16:04:34 UTC
> Makes sense.  So it looks something like app/gtkwidget-handling <- at-spi <-
> gdk <- X.  Right?

Something like that, though I believe it can vary (e.g., if XEvIE is used, the AT-SPI logic gets closer to X).  But the basic idea is that the at-spi is in there as a filter between the X server and the app/toolkit logic.

> > If Orca consumes the events (which it does in the case of Insert+space), the
> > AT-SPI support doesn't send the event to the higher-level application/toolkit
> > logic.
> 
> Okay, this is beginning to make sense now and I'm pretty sure I know where the
> bug is.  To verify, though, what are the contents of the message sent by the
> toolkit via AT-SPI to orca when insert+space is pressed?  I'm almost certain
> you have a missing bit of data here (unfortunately, an extremely common bit of
> data to ignore), but want to verify before jumping to conclusions to quickly. 

We just know the details of the keystroke: keycode, press/release, modifiers, keysym.  If we're lucky, we can infer which application has focus.
Comment 8 Elijah Newren 2006-06-08 16:11:48 UTC
(In reply to comment #7)
> We just know the details of the keystroke: keycode, press/release, modifiers,
> keysym.  If we're lucky, we can infer which application has focus.

Yes, you would have to be lucky, because determining which window has focus is a race condition at best (even for the window manager due to some braindead behavior in the design of X).  Anyway, so far, sounds about right.  Are those (keycode, press/release, modifiers, & keysym) the only details of the keystroke you know?
Comment 9 Willie Walker 2006-06-08 19:12:26 UTC
(In reply to comment #8)
> > We just know the details of the keystroke: keycode, press/release, modifiers,
> > keysym.  If we're lucky, we can infer which application has focus.
> 
> Yes, you would have to be lucky, because determining which window has focus is
> a race condition at best (even for the window manager due to some braindead
> behavior in the design of X).  Anyway, so far, sounds about right.  Are those
> (keycode, press/release, modifiers, & keysym) the only details of the keystroke
> you know?

The complete details can be found by looking for "struct DeviceEvent" on this page:  http://cvs.gnome.org/viewcvs/*checkout*/at-spi/idl/Accessibility_Registry.idl

If you're looking for something in particular (your line of questioning makes me think you are ;-)), please let me know.  Orca keeps track of various things, such as what it thinks is the active object/application, though these are in AT-SPI terms and not in raw-X11 terms.
Comment 10 Elijah Newren 2006-06-08 19:19:05 UTC
Ah, you have the timestamp in that struct.  That's great; most ignore that important field.  What does the receiving end do with it?
Comment 11 Willie Walker 2006-06-08 20:28:07 UTC
For the intents and purposes of this discussion, Orca does nothing with the timestamp.  Would you like it to do something?  If so, just what is it exactly?
Comment 12 Elijah Newren 2006-06-08 20:49:24 UTC
Absolutely, doing nothing with the timestamp is what I belive would cause this bug.  You should use the timestamp to update the user_time of the preferences window before showing it.

Here's the little explanation:  When a user launches a new app/window, it should typically get focused when it appears.  But if the user started using a different application between launch time and window-appears time, then the new window should not get focus.  Metacity can only get this right if it knows the timestamp of the user event that caused the window to appear and the last time the user interacted with the currently focused window.

In the case of this bug, the user pressed a key (shift+insert), gdk updates the user time of the application that had focus when this key was pressed, at-spi intercepts the keypress and sends a message to orca to open a window, and orca opens the preferences window.  However, if orca does nothing to help gtk+ know the timestamp of the user interaction that caused it to be opened (i.e. neglects the timestamp sent by at-spi), gtk+ takes its best guess and uses the timestamp of the last time the user interacted with one of the orca windows.  Thus, the orca preferences window has a really old timestamp, and the currently focused window has a very new timestamp; therefore, metacity won't transfer focus.

To fix this, call gdk_x11_window_set_user_time() before showing the preferences window (you'll have to make sure the widget is realized, since this is at the gdk level).
Comment 13 Rich Burridge 2006-06-09 15:14:04 UTC
Just been chatting with jdahlin on IRC. There is no Python binding for 
gdk_x11_window_set_user_time(). Elijah, is there any other way we can force
the timestamp for the Orca configuration GUI window to be updated?
Comment 14 Elijah Newren 2006-06-09 15:38:06 UTC
Are there python bindings to core X functions such as XChangeProperty()?  If so, you could write your own version of such a function (see the first block of http://cvs.gnome.org/viewcvs/metacity/src/metacity-dialog.c?r1=1.11&r2=1.12 for an example of an app writing their own version of that gtk+ function back before gtk+-2.6 was released).

I guess, as a last resort, you could write a separate program and call it with the X Window ID of the preferences dialog and the timestamp to update it with (assuming you've run gtk_widget_realize() on the window and haven't yet shown it) and then run that program when necessary.  Sounds kind of ugly, though.
Comment 15 Matthias Clasen 2006-06-09 15:43:11 UTC
it was your choice to pick python as an implementation language...
Comment 16 Rich Burridge 2006-06-09 16:11:50 UTC
Elijah, jdahlin informs me that they are there in a separate library called pyxlib, but it would "probably be quite tricky and have lots of issues". His
suggestion is to wait and use the "soon-to-be-wrapped x11 specific functions 
in pygtk". I think we'll take that approach. 
Comment 17 Gustavo Carneiro 2006-06-11 01:01:55 UTC
gtk.gdk.Window.set_user_time is now wrapped in CVS
Comment 18 Rich Burridge 2006-06-11 17:07:45 UTC
Thanks Gustavo! I'll work on this next week.
Comment 19 Rich Burridge 2006-06-27 13:36:33 UTC
Just to tell you where I am with this. I niavely thought I could
install a copy of pygtk-2.9.2 on top of my GNOME 2.14 system and test
out a fix for this problem using that.

When I do the "./configure --prefix=/usr" of pygtk-2.9.2, it seems to
go through nicely and summarises with:

  The following modules will be built:

  atk
  pango
  gtk with 2.8 API
  gtk.glade

  The following modules will NOT be built:

  pangocairo
  gtk.unixprint

I then type "make". This fails with:

...
/bin/bash ../libtool --mode=compile /opt/SUNWspro/bin/cc -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/python2.4 -I/usr/include/pygtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include      -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I../../cairo-1.0.2/src -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include    -g -std=c9x -fno-strict-aliasing -c -o _gtk_la-gtkmodule.lo `test -f 'gtkmodule.c' || echo './'`gtkmodule.c
 /opt/SUNWspro/bin/cc -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/include/python2.4 -I/usr/include/pygtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I../../cairo-1.0.2/src -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -g -std=c9x -fno-strict-aliasing -c gtkmodule.c  -KPIC -DPIC -o .libs/_gtk_la-gtkmodule.o
cc: Warning: illegal option -d=c9x
cc: Warning: illegal option -fno-strict-aliasing
"gtkmodule.c", line 33: cannot find include file: <pycairo.h>
"gtkmodule.c", line 34: warning: old-style declaration or incorrect type for: Pycairo_CAPI_t
"gtkmodule.c", line 34: syntax error before or at: *
"gtkmodule.c", line 34: warning: old-style declaration or incorrect type for: Pycairo_CAPI
"gtkmodule.c", line 201: undefined symbol: Pycairo_IMPORT
cc: acomp failed for gtkmodule.c
make[2]: *** [_gtk_la-gtkmodule.lo] Error 1
make[2]: Leaving directory `/export/home/richb/gnome/pygtk-2.9.2/gtk'

Looks like I'll have to wait awhile until I've got a GNOME 2.15/16 system
before I can try to fix this bug.


Comment 20 Gustavo Carneiro 2006-06-27 13:52:25 UTC
pygtk 2.9.2 is supposed to build with gtk 2.8, so i guess there is a bug somewhere preventing this.  I did test compiling pygtk on breezy (gnome 2.14 based), but I guess i must have missed something...

But please make sure you have pycairo development package installed and re-configure pygtk.

In any case, the X11-specific functions are only enabled when compiling against gtk+ 2.9 because I have no idea (or don't have time to check) which of them are new in pygtk 2.9 and which are old.
Comment 21 Rich Burridge 2006-06-27 14:36:02 UTC
Thanks Gustavo. I don't have pycairo on my system.
I see from:

http://cairographics.org/pycairo

that the latest stable version is 1.0.2 and the
latest development snapshot is 1.1.6. Presumably 
I need the latter? ...

Just wanted to check as I don't want to blow my 
development system out of the water if I can help it.

Thanks.
Comment 22 Gustavo Carneiro 2006-06-27 15:49:00 UTC
It should work with both pycairo 1.0.2 or 1.1.x.
Comment 23 Rich Burridge 2006-06-27 16:53:17 UTC
I had to use pycairo 1.0.2 (to find the matching Cairo lib).
I now have pycairo 1.0.2 installed and pygtk-2.9.2. Thanks!
Onto the bug.
Comment 24 Rich Burridge 2006-06-28 15:29:59 UTC
Created attachment 68125 [details]
Patch that seems to fix the problem nicely.

Thanks to Gustavo for creating a pygtk 2.9.3 snapshot for me
that works with Gtk 2.8.X (to save me having to upgrade to the
GTK 2.9/2.10 series).

I've surronded the code with a try:/except: clause so that if this
call isn't present with the version of pygtk that a user has installed,
then is should hopefully fail gracefully.

At some point, we will need to make Orca dependent upon pygtk 2.9.3,
but this approach is probably okay for now.
Comment 25 Rich Burridge 2006-06-28 15:37:31 UTC
Changes checked into CVS HEAD. Thanks for everybodies help
with this one.
Comment 26 Gustavo Carneiro 2006-06-28 17:07:56 UTC
A couple of comments, since i'm listening on this bug anyway.. :)

+        try:
+            self.orcaSetupWindow.window.set_user_time(int(time.time()))

  time.time() returns the time in seconds as floating point; here you are rounding it to an integer, so it loses a lot of precision.  I'm not sure the "X server time" has any relation to real "clock time" at all.  Maybe you want to pass 0 here, which is equivalent to GDK_CURRENT_TIME in C?... or pass a timestamp you received from another gdk event that triggered this code?...

+        except:
+            debug.printException(debug.LEVEL_FINEST)

Bare except: clauses are discouraged and will be disallowed in python3k; instead you should catch a specific exception, in this case AttributeError.
Comment 27 Rich Burridge 2006-06-28 19:11:00 UTC
So changed. Many thanks!
(And yes, I did test these changes before I checked it in. ;-) )
Comment 28 Elijah Newren 2006-06-29 09:59:32 UTC
As Gustavo said, wall clock time has no relation to xserver time (the latter measures time in milliseconds since the xserver was started), so it's definitely not what you want.  I also have a tirade about using 0/GDK_CURRENT_TIME, but you can ignore it if you took Gustavo's suggestion of using the real timestamp passed by at-spi.  If you did that, ignore the rest of this comment.  Otherwise:

Don't use 0 (i.e. GDK_CURRENT_TIME) here.  You're not sending a message to the Xserver saying "I don't know the time so just use whatever you know the current time to be."  You're sending a message to the window manager which would have to ask the Xserver for the actual time.  Even if it was the Xserver, though, using 0 would still cause a race condition.  We have buggy workarounds in Metacity to try to make apps that use 0 work correctly as much as possible, but since the workarounds cause some nasty bugs in special cases we intend to remove that in the future.  So, if you use 0, your app can break right now with a focus race condition, and _will_ be broken in the future when Metacity is modified (or when you happen to use another window manager).  Using 0 gives you undefined behavior.


Thanks for all your awesome work, everyone!
Comment 29 Rich Burridge 2006-06-29 13:29:58 UTC
Okay, I'm now confused what I should put here. I originally had:

self.orcaSetupWindow.window.set_user_time(int(time.time()))

(which seemed to work nicely). Gustavo suggested I replace this with:

self.orcaSetupWindow.window.set_user_time(0)

(which also seems to work nicely). Now I'm being told mot to use 0,
but use the real timestamp passed by at-spi. What real timestamp?

If somebody would like to spell it out in words of one syllable or less
I'd be grateful. Thanks.
Comment 30 Gustavo Carneiro 2006-06-29 13:56:17 UTC
It means that, if this code is triggered by receiving a gdk/X event, then you should use the timestamp found in the event structure.  But probably at-spi communicates with orca using CORBA, in which case you don't have any event structure, in which case you have no choice but to keep using 0.
Comment 31 Rich Burridge 2006-06-29 14:35:07 UTC
Yes, at-spi does use CORBA. The configuration GUI (for the
situation we are trying to fixup) will have been started by the
user typing Insert-<space>. I'll look around to see if there is
a timestamp somewhere that I can use as this is happening.
Thanks.
Comment 32 Elijah Newren 2006-06-29 15:40:18 UTC
Rich: This was the reason for my questions to Willie.  In comment 9, he linked to a file that seems to claim that a timestamp is already part of the struct that is passed (which is unusual).  So, it looks like you just need to use the timestamp field of the DeviceEvent struct.
Comment 33 Rich Burridge 2006-06-29 16:11:06 UTC
Created attachment 68173 [details] [review]
Adjustment to first attemp to fix this.

Thanks Elijah. I see what's going on now. We do get AT-SPI DeviceEvents
coming in when you use types at the keyboard (in _processKeyboardEvent()
in orca.py), but what was confusing me was that when Orca generates it's
own KeyboardEvent() from them, it doesn't use the timestamp, but instead
sets the time field to time.time(). 

What I've done is go back to _processKeyboardEvent() and save the timestamp
field from each event (in orca.lastTimestamp), and I now use that in the
call to set_user_time() in orca_gui_prefs.py
Comment 34 Rich Burridge 2006-06-29 16:14:05 UTC
Changes checked into CVS HEAD. Thanks ago Gustavo and 
Elijah for help on this.