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 519556 - gtk-demo/role_spin_button.py regression test #1 produces the wrong results.
gtk-demo/role_spin_button.py regression test #1 produces the wrong results.
Status: RESOLVED FIXED
Product: orca
Classification: Applications
Component: general
2.21.x
Other Linux
: Normal normal
: 2.24.0
Assigned To: Rich Burridge
Orca Maintainers
Depends on: 517127
Blocks: 519271
 
 
Reported: 2008-02-29 16:02 UTC by Rich Burridge
Modified: 2008-06-10 19:58 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Orca debug output whilst testing this problem. (19.27 KB, text/plain)
2008-02-29 20:45 UTC, Rich Burridge
  Details
Patch to adjust the regression test. (767 bytes, patch)
2008-06-09 20:45 UTC, Rich Burridge
committed Details | Review

Description Rich Burridge 2008-02-29 16:02:01 UTC
This is on latest Ubuntu Hardy:

EXPECTED:
     "BUG? - Text is selected, but selection not presented.",
     "BRAILLE LINE:  'gtk-demo Application Changing color ColorChooser ColorChooser Hue: 240 $l'",
     "     VISIBLE:  'Hue: 240 $l', cursor=6",
     "BRAILLE LINE:  'gtk-demo Application Changing color ColorChooser ColorChooser Hue: 240 $l'",
     "     VISIBLE:  'Hue: 240 $l', cursor=9",
     "SPEECH OUTPUT: ''",
     "SPEECH OUTPUT: 'Hue: 240 spin button'",
ACTUAL:
     "BRAILLE LINE:  'gtk-demo Application Changing color ColorChooser ColorChooser Hue: 240 $l'",
     "     VISIBLE:  'Hue: 240 $l', cursor=6",
     "BRAILLE LINE:  'gtk-demo Application Changing color ColorChooser ColorChooser Hue: 240 $l'",
     "     VISIBLE:  'Hue: 240 $l', cursor=9",
     "SPEECH OUTPUT: ''",
     "SPEECH OUTPUT: 'Hue: 240 spin button'",
[FAILURE WAS EXPECTED - LOOK FOR BUG? IN EXPECTED RESULTS]
Test 2 of 7 FAILED: /home/jd/orca/test/keystrokes/gtk-demo/role_spin_button.py:Hue spin button Where Am I
EXPECTED:
     "BUG? - Text is selected, but selection not presented.",
     "BRAILLE LINE:  'gtk-demo Application Changing color ColorChooser ColorChooser Hue: 240 $l'",
     "     VISIBLE:  'Hue: 240 $l', cursor=9",
     "SPEECH OUTPUT: 'Hue:'",
     "SPEECH OUTPUT: 'spin button'",
     "SPEECH OUTPUT: '240'",
     "SPEECH OUTPUT: 'Alt h'",
ACTUAL:
     "BRAILLE LINE:  'gtk-demo Application Changing color ColorChooser ColorChooser Hue: 240 $l'",
     "     VISIBLE:  'Hue: 240 $l', cursor=9",
     "SPEECH OUTPUT: 'Hue:'",
     "SPEECH OUTPUT: 'spin button'",
     "SPEECH OUTPUT: '240'",
     "SPEECH OUTPUT: 'Alt h'",
[FAILURE WAS EXPECTED - LOOK FOR BUG? IN EXPECTED RESULTS]

We need to determine why the text isn't being presented as selected.
Comment 1 Rich Burridge 2008-02-29 18:58:18 UTC
When I test the gtk-demo Color Selector demo with Orca "by hand", 
and Tab to the Hue spin button, it nicely speaks what we want:

...
vvvvv PROCESS OBJECT EVENT object:state-changed:focused vvvvv
OBJECT EVENT: object:state-changed:focused             detail=(1,0)
    app.name='gtk-demo' name='None' role='spin button' state='editable enabled focusable focused sensitive showing single line visible' relations='controller for labelled by'
Finding top-level object for source.name=
--> obj.name=
--> obj.name=
--> obj.name=
--> obj.name=
--> obj.name=
--> obj.name=Changing color
LOCUS OF FOCUS: app='gtk-demo' name='' role='spin button'
                event='object:state-changed:focused'
Object deemed to be for layout purposes only: [panel | ]
GENERATOR: _getDefaultBrailleRegions
           obj             =
           role            = color chooser
GENERATOR: _getDefaultBrailleRegions
           obj             = Changing color
           role            = color chooser
GENERATOR: _getDefaultBrailleRegions
           obj             = gtk-demo
           role            = application
GENERATOR: _getBrailleRegionsForSpinButton
           obj             =
           role            = spin button
GENERATOR: _getBrailleRegionsForText
           obj             =
           role            = spin button
BRAILLE LINE:  'gtk-demo Application Changing color ColorChooser ColorChooser Hue: 240 $l'
     VISIBLE:  'Hue: 240 $l', cursor=9
default.findCommonAncestor...
...default.findCommonAncestor
Object deemed to be for layout purposes only: [panel | ]
GENERATOR: _getDefaultSpeech
           obj             =
           role            = spin button
           already_focused = False
           utterances:
               (Hue:)
               (240)
               (selected)
               (spin button)
GENERATOR: _getSpeechForSpinButton
           obj             =
           role            = spin button
           already_focused = False
           utterances:
               (Hue:)
               (240)
               (selected)
               (spin button)
SPEECH OUTPUT: ''
SPEECH OUTPUT: 'Hue: 240 selected spin button'
^^^^^ PROCESS OBJECT EVENT object:state-changed:focused ^^^^^
...


Still looking...

Comment 2 Rich Burridge 2008-02-29 19:07:05 UTC
It's appears to be a synchronous/asynchronous thang. If I set

orca.settings.asyncMode = False

in my ~/.orca/orca-customizations.py file and rerun the test manually,
when I Tab to the Hue spin button, I get:

...
vvvvv PROCESS OBJECT EVENT object:state-changed:focused vvvvv
OBJECT EVENT: object:state-changed:focused             detail=(1,0)
    app.name='gtk-demo' name='None' role='spin button' state='editable enabled focusable sensitive showing single line visible' relations='controller for labelled by'
Finding top-level object for source.name=
--> obj.name= 
--> obj.name= 
--> obj.name=
--> obj.name=
--> obj.name=
--> obj.name=Changing color
LOCUS OF FOCUS: app='gtk-demo' name='' role='spin button'
                event='object:state-changed:focused'
Object deemed to be for layout purposes only: [panel | ]
GENERATOR: _getDefaultBrailleRegions
           obj             =
           role            = color chooser
GENERATOR: _getDefaultBrailleRegions
           obj             = Changing color
           role            = color chooser
GENERATOR: _getDefaultBrailleRegions
           obj             = gtk-demo
           role            = application
GENERATOR: _getBrailleRegionsForSpinButton
           obj             =
           role            = spin button
GENERATOR: _getBrailleRegionsForText
           obj             =
           role            = spin button
BRAILLE LINE:  'gtk-demo Application Changing color ColorChooser ColorChooser Hue: 240 $l'
     VISIBLE:  'Hue: 240 $l', cursor=6
default.findCommonAncestor...
...default.findCommonAncestor
Object deemed to be for layout purposes only: [panel | ]
GENERATOR: _getDefaultSpeech
           obj             =
           role            = spin button
           already_focused = False
           utterances:
               (Hue:)
               (240)
               (spin button)
GENERATOR: _getSpeechForSpinButton
           obj             = 
           role            = spin button
           already_focused = False
           utterances:
               (Hue:)
               (240) 
               (spin button)
SPEECH OUTPUT: ''
SPEECH OUTPUT: 'Hue: 240 spin button'
^^^^^ PROCESS OBJECT EVENT object:state-changed:focused ^^^^^
...

I'll ad some debug to getSpeechForSpinButton() and see if I can determine
why it doesn't think the text is selected in this case.

Comment 3 Rich Burridge 2008-02-29 19:20:42 UTC
The problem is that in synchronous mode, we are being told there
there is no text selected.

In more detail:

The _getSpeechForSpinButton() method in speechgenerator.py is
calling the _getDefaultSpeech() method. That in turn is calling
the _getSpeechForAllTextSelection() method.

The _getSpeechForAllTextSelection() method has the following
piece of code:

        try:
            textObj = obj.queryText()
        except:
            pass
        else:
            noOfSelections = textObj.getNSelections()

If we run this test asynchronously, then noOfSelections = 1.
If we run it synchronously, then noOfSelections = 0.

This suggests that there is a bug in the gail spin button
code.

Will, what do we want to do here?
Comment 4 Willie Walker 2008-02-29 19:38:24 UTC
(In reply to comment #3)
> The problem is that in synchronous mode, we are being told there
> there is no text selected.

It may be that we are getting a text selection event very soon after focus event.  If this is the case, it would most likely work in asynchronous mode because the selection had taken place by the time we get around to processing the focus event.

I'm not sure this is necessarily a gail bug, since the ordering of events is so underspecified.  :-(  It may actually be more of a bug in Orca's code, because we're assuming some particular object state to be set when a focus event is emitted for an object.

For how to solve this, I'm not sure.  It may be that we listen for that new magical text selection event (see bug 517127) and emit text selection information from that event.  If that doesn't work, we might need to punt on the selection aspect of this particular test.  :-(

Comment 5 Rich Burridge 2008-02-29 20:45:19 UTC
Created attachment 106296 [details]
Orca debug output whilst testing this problem.

> It may be that we listen for that new magical text selection event 
> (see bug 517127) and emit text selection information from that event.

Good call. I added in a handler in default.py for 
"object:text-selection-changed" event with just a
debug print statement, and indeed, that's exactly
what we are getting.

Okay, I'll make this bug dependent on bug #517127.

Thanks.
Comment 6 Willie Walker 2008-06-02 20:12:46 UTC
Rich fixed bug #517127 (thanks!), so that frees this one up.
Comment 7 Rich Burridge 2008-06-05 16:57:29 UTC
Steps to reproduce the problem (without the regression test):

1/ Start Orca
2/ Start gtk-demo and start the Color Selector demo.
3/ Press Return to activate the "Change the above color" button.
4/ When the "Changing color" dialog appears, press Tab three
   times to move the focus to the Hue: spin button.

You will notice that the "240" text is selected.

When we Tab to that spin button we get the following:

----------------------------------------------------
OBJECT EVENT: object:state-changed:focused             detail=(1,0)
    app.name='gtk-demo' name='None' role='spin button' state='editable enabled focusable focused sensitive showing single line visible' relations='controller for labelled by'

For this one (when running asynchronously), we speak:

SPEECH OUTPUT: ''
SPEECH OUTPUT: 'Hue: 240 selected spin button'

Note that when we run the regression tests (synchronously), the text
hasn't been selected at that point, so we speak:

SPEECH OUTPUT: 'Hue: 240 spin button'

(see comment #3 above for a fuller analysis).

----------------------------------------------------
OBJECT EVENT: object:text-selection-changed            detail=(0,0)
    app.name='gtk-demo' name='None' role='spin button' state='editable enabled focusable focused sensitive showing single line visible' relations='controller for labelled by'

For this one, we call onTextSelectionChanged() in default.py.
This looks to see what the last "spokenTextRange" was (stored in
self.pointOfReference.get("spokenTextRange"). This would have been
set in _saveSpokenTextRange() called at the very end of
_presentTextAtNewCaretPosition(), which would have been called by
onCaretMoved(). But as we haven't moved within this text area before,
there is no self.pointOfReference.get("spokenTextRange"), so:

        spokenRange = self.pointOfReference.get("spokenTextRange") or [0, 0]
        startOffset, endOffset = spokenRange

sets startOffset and endOffset to 0.

Then in speakTextSelectionState(), because this isn't a special keypress
case, we come to:

        ...
        if specialCaseFound:
            speech.speak(line, None, False)
            return
        elif startOffset == endOffset:
            return

and so we just return. 

I'm not sure how to improve/fix this. 

Joanie, any ideas?
Comment 8 Joanmarie Diggs (IRC: joanie) 2008-06-06 16:35:04 UTC
A thought which is crossing my mind atm, but which I've not yet accepted or rejected is this:

We recently put the responsibility of speaking text selection changes in the hands of onTextSelectionChanged() as long as we have a caret-moved event.  Should we make a similar change (or at the very least set a flag/update the spokenTextRange point of reference/something) to deal with focus events that cause selection to be changed? 
Comment 9 Joanmarie Diggs (IRC: joanie) 2008-06-06 17:08:04 UTC
Rich, regarding this event:

OBJECT EVENT: object:text-selection-changed            detail=(0,0)
    app.name='gtk-demo' name='None' role='spin button' state='editable enabled
focusable focused sensitive showing single line visible' relations='controller
for labelled by'

When I run the regression tests, the spin button doesn't have STATE_FOCUSED for me at the point at which we get the object:text-selection-changed event.  Is the above from manually performing the task, or from running the tests?
Comment 10 Joanmarie Diggs (IRC: joanie) 2008-06-06 17:43:05 UTC
After some more hacking I was able to make Orca say "selected" for the text-selection-changed event.  But here's the real problem I believe:  As you pointed out, the text is not selected at the time of the focus related events.
It's at the focus related events that we say the following:

1. Label
2. text
3. whether or not that text is selected
4. the role

*After all that* we get the text-sslection-changed event.  So the best we could do is

1. Label
2. text
3. (nothing for selected)
4. the role
5  selection state

i.e. "Hue: 240 spin button selected"  And that still ain't right.  So my temptation, unless you or Will has a clever idea, is to call this a "known issue" and move on.

Thoughts?
Comment 11 Rich Burridge 2008-06-06 18:59:01 UTC
> Is the above from manually performing the task, or from running the tests?

Following the steps in comment #7.

Asynchronously.
Comment 12 Joanmarie Diggs (IRC: joanie) 2008-06-06 19:59:21 UTC
Part of the hack I came up with to get us to say "selected" *somewhere* was to ignore the fact that the spin button wasn't focused.  In my testing, we never even got this far:

> Then in speakTextSelectionState(), because this isn't a special keypress
> case, we come to:
>
>        ...
>        if specialCaseFound:
>            speech.speak(line, None, False)
>            return
>        elif startOffset == endOffset:
>            return

because the object doesn't have STATE_FOCUSED at the point at which we get the object:text-selection-changed event.

Like I said, methinks this should be considered a "known issue" because we do the right thing when actually using Orca.
Comment 13 Willie Walker 2008-06-09 19:15:14 UTC
Just an FYI about the focus/selection event ordering.  Seems to be done in GTK+ in gtkentry.c:gtk_entry_grab_focus and is not under GAIL's control.  From the below, it looks as though the focus event will be emitted before the selection:

http://svn.gnome.org/viewvc/gtk%2B/trunk/gtk/gtkentry.c?view=markup

static void
gtk_entry_grab_focus (GtkWidget        *widget)
{
  GtkEntry *entry = GTK_ENTRY (widget);
  gboolean select_on_focus;
  
  GTK_WIDGET_CLASS (gtk_entry_parent_class)->grab_focus (widget);

  if (entry->editable && !entry->in_click)
    {
      g_object_get (gtk_widget_get_settings (widget),
                    "gtk-entry-select-on-focus",
                    &select_on_focus,
                    NULL);
  
      if (select_on_focus)
        gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
    }
}

We could potentially request a change in ordering of the events like so (move the grab_focus call to the end):

static void
gtk_entry_grab_focus (GtkWidget        *widget)
{
  GtkEntry *entry = GTK_ENTRY (widget);
  gboolean select_on_focus;

  if (entry->editable && !entry->in_click)
    {
      g_object_get (gtk_widget_get_settings (widget),
                    "gtk-entry-select-on-focus",
                    &select_on_focus,
                    NULL);
  
      if (select_on_focus)
        gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
    }
  
  GTK_WIDGET_CLASS (gtk_entry_parent_class)->grab_focus (widget);
}

Inside Orca, we could potentially ignore focus: events for editable text areas and set the locusOfFocus when we get a text-selection event on a focused editable text area.  But, it looks like the "gtk-entry-select-on-focus" property is a settable thing that would result in us not being guaranteed to get selection events when a text area got focus.  In looking at GAIL, I also don't see this property being exposed via any AT-SPI state.
Comment 14 Rich Burridge 2008-06-09 20:31:47 UTC
After discussion about this on IRC this morning, we've decided to adjust
the spin button regression test to be a "KNOWN ISSUE". Patch to follow.
Comment 15 Rich Burridge 2008-06-09 20:45:35 UTC
Created attachment 112436 [details] [review]
Patch to adjust the regression test.

Patch committed to SVN trunk. Moving to "[pending]".