GNOME Bugzilla – Bug 519556
gtk-demo/role_spin_button.py regression test #1 produces the wrong results.
Last modified: 2008-06-10 19:58:00 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.
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...
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.
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?
(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. :-(
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.
Rich fixed bug #517127 (thanks!), so that frees this one up.
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?
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?
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?
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?
> Is the above from manually performing the task, or from running the tests? Following the steps in comment #7. Asynchronously.
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.
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.
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.
Created attachment 112436 [details] [review] Patch to adjust the regression test. Patch committed to SVN trunk. Moving to "[pending]".