[orca] Create a dedicated object:state-changed callback for "focused" events



commit e96a40263fcff0ef2a88c0d894fa37e152e69764
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Wed Nov 6 18:07:26 2013 -0500

    Create a dedicated object:state-changed callback for "focused" events

 src/orca/scripts/apps/Eclipse/script.py            |   12 +-
 src/orca/scripts/apps/Instantbird/script.py        |   12 +-
 src/orca/scripts/apps/Thunderbird/script.py        |   68 ++-----
 src/orca/scripts/apps/gnome-panel/script.py        |   24 --
 .../apps/gnome-screensaver-dialog/script.py        |   23 +--
 src/orca/scripts/apps/soffice/script.py            |   10 +-
 src/orca/scripts/default.py                        |  227 +++++---------------
 src/orca/scripts/toolkits/CALLY/script.py          |   67 +++---
 src/orca/scripts/toolkits/Gecko/script.py          |   48 +----
 .../scripts/toolkits/J2SE-access-bridge/script.py  |   83 ++------
 src/orca/scripts/toolkits/WebKitGtk/script.py      |   12 +-
 11 files changed, 151 insertions(+), 435 deletions(-)
---
diff --git a/src/orca/scripts/apps/Eclipse/script.py b/src/orca/scripts/apps/Eclipse/script.py
index b522e2e..ffaa8cb 100644
--- a/src/orca/scripts/apps/Eclipse/script.py
+++ b/src/orca/scripts/apps/Eclipse/script.py
@@ -79,18 +79,12 @@ class Script(default.Script):
 
         self._saveLastTextPosition(obj)
 
-    def onFocus(self, event):
-        """Called whenever an object gets focus.  Overridden here so that
-        so that we can avoid speaking text when caret moves after new text
-        receives focus and is spoken.
-
-        Arguments:
-        - event: the Event
-        """
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
 
         # Let the default script's normal behavior do its thing
         #
-        default.Script.onFocus(self, event)
+        default.Script.onFocusedChanged(self, event)
 
         self._saveLastTextPosition(event.source)
 
diff --git a/src/orca/scripts/apps/Instantbird/script.py b/src/orca/scripts/apps/Instantbird/script.py
index de0994b..1d1290b 100644
--- a/src/orca/scripts/apps/Instantbird/script.py
+++ b/src/orca/scripts/apps/Instantbird/script.py
@@ -179,12 +179,8 @@ class Script(Gecko.Script):
 
         default.Script.onNameChanged(self, event)
 
-    def onFocus(self, event):
-        """Called whenever an object gets focus.
-
-        Arguments:
-        - event: the Event
-        """
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
 
         # This seems to be the most reliable way to identify that the
         # active chatroom was changed via keyboard from within the entry.
@@ -204,9 +200,9 @@ class Script(Gecko.Script):
                 return
 
         if self.inDocumentContent(event.source):
-            Gecko.Script.onFocus(self, event)
+            Gecko.Script.onFocusedChanged(self, event)
         else:
-            default.Script.onFocus(self, event)
+            default.Script.onFocusedChanged(self, event)
 
     def onWindowActivated(self, event):
         """Called whenever a toplevel window is activated."""
diff --git a/src/orca/scripts/apps/Thunderbird/script.py b/src/orca/scripts/apps/Thunderbird/script.py
index 345ccb1..ed89dec 100644
--- a/src/orca/scripts/apps/Thunderbird/script.py
+++ b/src/orca/scripts/apps/Thunderbird/script.py
@@ -238,13 +238,19 @@ class Script(Gecko.Script):
 
         return Gecko.Script.onCaretMoved(self, event)
 
-    def onFocus(self, event):
-        """ Called whenever an object gets focus.
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
 
-        Arguments:
-        - event: the Event
+        # If we get an "object:state-changed:focused" event for a list
+        # item in the spell checking dialog, and it doesn't have a
+        # FOCUSED state (i.e. we didn't navigate to it), then ignore it.
+        # See bug #535192 for more details.
+        #
+        if self._isSpellCheckListItemFocus(event):
+            return
+
+        # TODO - JD: Determine how much of the stuff below is still needed.
 
-        """
         obj = event.source
         parent = obj.parent
         top = self.utilities.topLevelObject(obj)
@@ -279,8 +285,7 @@ class Script(Gecko.Script):
                     # True when it's not actually True. Therefore,
                     # we'll force the propagation as a precaution.
                     #
-                    force = event.type.startswith("focus:")
-                    orca.setLocusOfFocus(event, acc, force=force)
+                    orca.setLocusOfFocus(event, acc, force=True)
                     consume = True
                     break
 
@@ -305,35 +310,6 @@ class Script(Gecko.Script):
             self.textArea = event.source
             # Fall-thru to process the event with the default handler.
 
-        if event.type.startswith("focus:"):
-            # If we get a "focus:" event for the "Replace with:" entry in the
-            # spell checking dialog, then clear the current locus of focus so
-            # that this item will be spoken and brailled. See bug #535192 for
-            # more details.
-            #
-            rolesList = [pyatspi.ROLE_ENTRY, \
-                         pyatspi.ROLE_DIALOG, \
-                         pyatspi.ROLE_APPLICATION]
-            if self.utilities.hasMatchingHierarchy(obj, rolesList):
-                dialog = obj.parent
-
-                # Translators: this is what the name of the spell checking
-                # dialog in Thunderbird begins with. The translated form
-                # has to match what Thunderbird is using.  We hate keying
-                # off stuff like this, but we're forced to do so in this case.
-                #
-                if dialog.name.startswith(_("Check Spelling")):
-                    orca_state.locusOfFocus = None
-                    orca.setLocusOfFocus(event, obj)
-
-            # If we get a "focus:" event for a list item in the spell
-            # checking dialog, and it doesn't have a FOCUSED state (i.e.
-            # we didn't navigate to it), then ignore it. See bug #535192
-            # for more details.
-            #
-            if self._isSpellCheckListItemFocus(event):
-                return
-
         # Handle dialogs.
         #
         if top and top.getRole() == pyatspi.ROLE_DIALOG:
@@ -377,9 +353,9 @@ class Script(Gecko.Script):
             # handle navigation in that case.
             #
             if self.isEditableMessage(event.source):
-                default.Script.onFocus(self, event)
+                default.Script.onFocusedChanged(self, event)
             else:
-                Gecko.Script.onFocus(self, event)
+                Gecko.Script.onFocusedChanged(self, event)
 
     def locusOfFocusChanged(self, event, oldLocusOfFocus, newLocusOfFocus):
         """Called when the visual object with focus changes.
@@ -435,22 +411,6 @@ class Script(Gecko.Script):
             if self.inDocumentContent():
                 self._presentMessage(obj)
 
-    def onStateFocused(self, event):
-        """Called whenever an object's state changes focus.
-
-        Arguments:
-        - event: the Event
-        """
-
-        # If we get an "object:state-changed:focused" event for a list
-        # item in the spell checking dialog, and it doesn't have a
-        # FOCUSED state (i.e. we didn't navigate to it), then ignore it.
-        # See bug #535192 for more details.
-        #
-        if self._isSpellCheckListItemFocus(event):
-            return
-
-        Gecko.Script.onStateChanged(self, event)
 
     def onTextDeleted(self, event):
         """Called whenever text is from an an object.
diff --git a/src/orca/scripts/apps/gnome-panel/script.py b/src/orca/scripts/apps/gnome-panel/script.py
index 983275e..ab39894 100644
--- a/src/orca/scripts/apps/gnome-panel/script.py
+++ b/src/orca/scripts/apps/gnome-panel/script.py
@@ -52,27 +52,3 @@ class Script(default.Script):
         """Returns the speech generator for this script."""
 
         return SpeechGenerator(self)
-
-    def onStateChanged(self, event):
-        """Called whenever an object's state changes.
-
-        Arguments:
-        - event: the Event
-        """
-
-        obj = event.source
-
-        # If focus moves to something within a panel and focus was not
-        # already in the containing panel, the panel will issue its
-        # own state-changed:focused event with detail1 == 1 after the
-        # event for the item with focus.  The panel is not focused,
-        # plus the extraneous event results in unnecessary chattiness
-        # and updates the braille display to "panel."
-        #
-        if obj.getRole() == pyatspi.ROLE_PANEL and \
-             event.type.startswith("object:state-changed:focused") and \
-             event.detail1 == 1 \
-             and not obj.getState().contains(pyatspi.STATE_FOCUSED):
-            return
-
-        default.Script.onStateChanged(self, event)
diff --git a/src/orca/scripts/apps/gnome-screensaver-dialog/script.py 
b/src/orca/scripts/apps/gnome-screensaver-dialog/script.py
index 8bee44d..69dc308 100644
--- a/src/orca/scripts/apps/gnome-screensaver-dialog/script.py
+++ b/src/orca/scripts/apps/gnome-screensaver-dialog/script.py
@@ -32,27 +32,24 @@ import orca.speech as speech
 
 class Script(default.Script):
 
-    def onStateChanged(self, event):
-        """Called whenever an object's state changes.
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
 
-        Arguments:
-        - event: the Event
-        """
+        obj = event.source
 
         # If we are focused in a password text area, we need to check if
         # there are any useful messages displayed in a couple of labels that
         # are visually below that password area. If there are, then speak
         # them for the user. See bug #529655 for more details.
         #
-        if event.type.startswith("object:state-changed:focused") and \
-           event.source.getRole() == pyatspi.ROLE_PASSWORD_TEXT:
-            obj = event.source.parent.parent.parent
+        if obj.getRole() == pyatspi.ROLE_PASSWORD_TEXT:
+            obj = obj.parent.parent.parent
             for child in obj:
-                if child.getRole() == pyatspi.ROLE_LABEL:
-                    if child.name:
-                        speech.speak(child.name)
-        else:
-            default.Script.onStateChanged(self, event)
+                if child.getRole() == pyatspi.ROLE_LABEL and child.name:
+                    speech.speak(child.name)
+                return
+
+        default.Script.onFocusedChanged(self, event)
 
     def skipObjectEvent(self, event):
         # NOTE: This is here temporarily as part of the preparation for the
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index 3aa4730..3b0b397 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -892,12 +892,8 @@ class Script(default.Script):
 
         default.Script.onChildrenChanged(self, event)
 
-    def onStateChanged(self, event):
-        """Called whenever an object's state changes.
-
-        Arguments:
-        - event: the Event
-        """
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
 
         if self.isStructuralNavigationCommand():
             return
@@ -912,7 +908,7 @@ class Script(default.Script):
         if parent and parent.getRoleName() == 'text frame':
             return
 
-        default.Script.onStateChanged(self, event)
+        default.Script.onFocusedChanged(self, event)
 
     def onCaretMoved(self, event):
         """Called whenever the caret moves.
diff --git a/src/orca/scripts/default.py b/src/orca/scripts/default.py
index c3e7755..e21eae3 100644
--- a/src/orca/scripts/default.py
+++ b/src/orca/scripts/default.py
@@ -530,7 +530,7 @@ class Script(script.Script):
         listeners["object:state-changed:busy"]              = \
             self.onBusyChanged
         listeners["object:state-changed:focused"]           = \
-            self.onStateChanged
+            self.onFocusedChanged
         listeners["object:state-changed:showing"]           = \
             self.onShowingChanged
         listeners["object:state-changed:checked"]           = \
@@ -758,8 +758,14 @@ class Script(script.Script):
         - newLocusOfFocus: Accessible that is the new locus of focus
         """
 
-        if newLocusOfFocus \
-           and newLocusOfFocus.getState().contains(pyatspi.STATE_DEFUNCT):
+        if not newLocusOfFocus:
+            orca_state.noFocusTimeStamp = time.time()
+            return
+
+        if newLocusOfFocus.getState().contains(pyatspi.STATE_DEFUNCT):
+            return
+
+        if self.utilities.isSameObject(oldLocusOfFocus, newLocusOfFocus):
             return
 
         try:
@@ -771,71 +777,24 @@ class Script(script.Script):
         except:
             pass
 
-        # We always automatically go back to focus tracking mode when
-        # the focus changes.
-        #
         if self.flatReviewContext:
             self.toggleFlatReviewMode()
 
-        # [[[TODO: WDW - HACK because parents that manage their descendants
-        # can give us a different object each time we ask for the same
-        # exact child.  So...we do a check here to see if the old object
-        # and new object have the same index in the parent and if they
-        # have the same name.  If so, then they are likely to be the same
-        # object.  The reason we check for the name here is a small sanity
-        # check.  This whole algorithm could fail because one might be
-        # deleting/adding identical elements from/to a list or table, thus
-        # the objects really could be different even though they seem the
-        # same.  Logged as bug 319675.]]]
-        #
-        if self.utilities.isSameObject(oldLocusOfFocus, newLocusOfFocus):
-            return
-
-        # Well...now that we got that behind us, let's do what we're supposed
-        # to do.
-        #
-        if oldLocusOfFocus:
-            oldParent = oldLocusOfFocus.parent
-        else:
-            oldParent = None
-
-        if newLocusOfFocus:
-            newParent = newLocusOfFocus.parent
-        else:
-            newParent = None
-
-        if newLocusOfFocus:
-            self.updateBraille(newLocusOfFocus)
-
-            # We might be automatically speaking the unbound labels
-            # in a dialog box as the result of the dialog box suddenly
-            # appearing.  If so, don't interrupt this because of a
-            # focus event that occurs when something like the "OK"
-            # button gets focus shortly after the window appears.
-            #
-            shouldNotInterrupt = (event and event.type.startswith("focus:")) \
-                and self.windowActivateTime \
-                and ((time.time() - self.windowActivateTime) < 1.0)
-
-            # [[[TODO: WDW - this should move to the generator.]]]
-            #
-            try:
-                newRole = newLocusOfFocus.getRole()
-            except:
-                newRole = None
-            if newRole == pyatspi.ROLE_LINK:
-                voice = self.voices[settings.HYPERLINK_VOICE]
-            else:
-                voice = self.voices[settings.DEFAULT_VOICE]
-            utterances = self.speechGenerator.generateSpeech(
-                newLocusOfFocus,
-                priorObj=oldLocusOfFocus)
-            speech.speak(utterances, voice, not shouldNotInterrupt)
+        self.updateBraille(newLocusOfFocus)
 
-            self._saveFocusedObjectInfo(newLocusOfFocus)
+        shouldNotInterrupt = \
+           self.windowActivateTime and time.time() - self.windowActivateTime < 1
 
+        # [[[TODO: WDW - this should move to the generator.]]]
+        if newLocusOfFocus.getRole() == pyatspi.ROLE_LINK:
+            voice = self.voices[settings.HYPERLINK_VOICE]
         else:
-            orca_state.noFocusTimeStamp = time.time()
+            voice = self.voices[settings.DEFAULT_VOICE]
+        utterances = self.speechGenerator.generateSpeech(
+            newLocusOfFocus,
+            priorObj=oldLocusOfFocus)
+        speech.speak(utterances, voice, not shouldNotInterrupt)
+        self._saveFocusedObjectInfo(newLocusOfFocus)
 
     def activate(self):
         """Called when this script is activated."""
@@ -2145,16 +2104,6 @@ class Script(script.Script):
         else:
             orca.setLocusOfFocus(event, event.source)
 
-        # We'll tuck away the activeDescendant information for future
-        # reference since the AT-SPI gives us little help in finding
-        # this.
-        #
-        if orca_state.locusOfFocus \
-           and (orca_state.locusOfFocus != event.source):
-            self.pointOfReference['activeDescendantInfo'] = \
-                [orca_state.locusOfFocus.parent,
-                 orca_state.locusOfFocus.getIndexInParent()]
-
     def onBusyChanged(self, event):
         """Callback for object:state-changed:busy accessibility events."""
         pass
@@ -2238,79 +2187,6 @@ class Script(script.Script):
         self.updateBraille(obj)
         speech.speak(self.speechGenerator.generateSpeech(obj, alreadyFocused=True))
 
-    def onFocus(self, event):
-        """Called whenever an object gets focus.
-
-        Arguments:
-        - event: the Event
-        """
-
-        state = event.source.getState()
-        if event.type.startswith("focus:") \
-           and state.contains(pyatspi.STATE_FOCUSABLE) \
-           and not state.contains(pyatspi.STATE_FOCUSED):
-            return
-
-        # [[[TODO: WDW - HACK to deal with quirky GTK+ menu behavior.
-        # The problem is that when moving to submenus in a menu, the
-        # menu gets focus first and then the submenu gets focus all
-        # with a single keystroke.  So...focus in menus really means
-        # that the object has focus *and* it is selected.  Now, this
-        # assumes the selected state will be set before focus is given,
-        # which appears to be the case from empirical analysis of the
-        # event stream.  But of course, all menu items and menus in
-        # the complete menu path will have their selected state set,
-        # so, we really only care about the leaf menu or menu item
-        # that it selected.]]]
-        #
-        role = event.source.getRole()
-        if role in (pyatspi.ROLE_MENU,
-                    pyatspi.ROLE_MENU_ITEM,
-                    pyatspi.ROLE_CHECK_MENU_ITEM,
-                    pyatspi.ROLE_RADIO_MENU_ITEM):
-            try:
-                if event.source.querySelection().nSelectedChildren > 0:
-                    return
-            except:
-                pass
-
-        # When tabbing into an egg-list-box, we get a focus: event after the
-        # object:active-descendant-changed event. We already presented the
-        # list box from its object:state-changed:focused event, so we can and
-        # should ignore this event.
-        if role == pyatspi.ROLE_LIST_BOX and orca_state.locusOfFocus \
-                and orca_state.locusOfFocus.parent == event.source:
-            return
-
-        # [[[TODO: WDW - HACK to deal with the fact that active cells
-        # may or may not get focus.  Their parents, however, do tend to
-        # get focus, but when the parent gets focus, it really means
-        # that the selected child in it has focus.  Of course, this all
-        # breaks when more than one child is selected.  Then, we really
-        # need to depend upon the model where focus really works.]]]
-        #
-        newFocus = event.source
-
-        if role in (pyatspi.ROLE_LAYERED_PANE,
-                    pyatspi.ROLE_TABLE,
-                    pyatspi.ROLE_TREE_TABLE,
-                    pyatspi.ROLE_TREE):
-            if event.source.childCount:
-                # We might have tucked away some information for this
-                # thing in the onActiveDescendantChanged method.
-                #
-                if "activeDescendantInfo" in self.pointOfReference:
-                    [parent, index] = \
-                        self.pointOfReference['activeDescendantInfo']
-                    newFocus = parent[index]
-
-                else:
-                    selectedChildren = self.utilities.selectedChildren(newFocus)
-                    if selectedChildren:
-                        newFocus = selectedChildren[0]
-
-        orca.setLocusOfFocus(event, newFocus)
-
     def onIndeterminateChanged(self, event):
         """Callback for object:state-changed:indeterminate accessibility events."""
 
@@ -2467,32 +2343,45 @@ class Script(script.Script):
                 orca.setLocusOfFocus(event, child)
                 break
 
-    def onStateChanged(self, event):
-        """Called whenever an object's state changes.
+    def onFocus(self, event):
+        """Callback for focus: accessibility events."""
 
-        Arguments:
-        - event: the Event
-        """
+        # NOTE: This event type is deprecated and Orca should no longer use it.
+        # This callback remains just to handle bugs in applications and toolkits
+        # during the remainder of the unstable (3.11) development cycle.
 
-        if event.type.startswith("object:state-changed:focused"):
-            iconified = False
-            try:
-                window = self.utilities.topLevelObject(event.source)
-                iconified = window.getState().contains(pyatspi.STATE_ICONIFIED)
-            except:
-                debug.println(debug.LEVEL_FINEST,
-                        "onStateChanged: could not get frame of focused item")
-            if not iconified:
-                if event.detail1:
-                    self.onFocus(event)
-                # We don't set locus of focus of None here because it
-                # wreaks havoc on the code that determines the context
-                # when you tab from widget to widget.  For example,
-                # tabbing between panels in the gtk-demo buttons demo.
-                #
-                #else:
-                #    orca.setLocusOfFocus(event, None)
-                return
+        role = event.source.getRole()
+
+        # https://bugzilla.gnome.org/show_bug.cgi?id=711397
+        if role == pyatspi.ROLE_COMBO_BOX:
+            orca.setLocusOfFocus(event, event.source)
+
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
+
+        if not event.detail1:
+            return
+
+        obj = event.source
+        state = obj.getState()
+        if not state.contains(pyatspi.STATE_FOCUSED):
+            return
+
+        try:
+            window = self.utilities.topLevelObject(obj)
+            iconified = window.getState().contains(pyatspi.STATE_ICONIFIED)
+        except:
+            return
+
+        if iconified:
+            return
+
+        if obj.childCount:
+            selectedChildren = self.utilities.selectedChildren(obj)
+            if len(selectedChildren) == 1:
+                obj = selectedChildren[0]
+
+        orca.setLocusOfFocus(event, obj)
 
     def onShowingChanged(self, event):
         """Callback for object:state-changed:showing accessibility events."""
diff --git a/src/orca/scripts/toolkits/CALLY/script.py b/src/orca/scripts/toolkits/CALLY/script.py
index ecf2f8d..c013216 100644
--- a/src/orca/scripts/toolkits/CALLY/script.py
+++ b/src/orca/scripts/toolkits/CALLY/script.py
@@ -311,49 +311,46 @@ class Script(default.Script):
 
         default.Script.onSelectedChanged(self, event)
 
-    def onStateChanged(self, event):
-        """Called whenever an object's state changes.
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
 
-        Arguments:
-        - event: the Event
-        """
+        if not event.detail1:
+            return
 
+        obj = event.source
         try:
-            role = event.source.getRole()
-            name = event.source.name
-            state = event.source.getState()
+            role = obj.getRole()
+            name = obj.name
         except:
             return
 
-        activeDialog, timestamp = self._activeDialog
-        eType = event.type
-        if eType.startswith("object:state-changed:focused") and event.detail1:
-            # The dialog will get presented when its first child gets focus.
-            if role == pyatspi.ROLE_DIALOG:
+        # The dialog will get presented when its first child gets focus.
+        if role == pyatspi.ROLE_DIALOG:
+            return
+
+        if role == pyatspi.ROLE_MENU_ITEM and not name \
+           and not self.utilities.labelsForObject(obj):
+            isRealFocus = lambda x: x and x.getRole() == pyatspi.ROLE_SLIDER
+            descendant = pyatspi.findDescendant(obj, isRealFocus)
+            if descendant:
+                orca.setLocusOfFocus(event, descendant)
                 return
 
-            if role == pyatspi.ROLE_MENU_ITEM and not event.source.name \
-               and not self.utilities.labelsForObject(event.source):
-                isRealFocus = lambda x: x and x.getRole() == pyatspi.ROLE_SLIDER
-                descendant = pyatspi.findDescendant(event.source, isRealFocus)
-                if descendant:
-                    orca.setLocusOfFocus(event, descendant)
-                    return
-
-            # This is to present dialog boxes which are, to the user, newly
-            # activated. And if something is claiming to be focused that is
-            # not in a dialog, that's good to know as well, so update our
-            # state regardless.
-            if not activeDialog:
-                dialog = _parentDialog(event.source)
-                self._activeDialog = (dialog, time.time())
-                if dialog:
-                    orca.setLocusOfFocus(None, dialog)
-                    labels = self.utilities.unrelatedLabels(dialog)
-                    for label in labels:
-                        self._activeDialogLabels[hash(label)] = label.name
-
-        default.Script.onStateChanged(self, event)
+        # This is to present dialog boxes which are, to the user, newly
+        # activated. And if something is claiming to be focused that is
+        # not in a dialog, that's good to know as well, so update our
+        # state regardless.
+        activeDialog, timestamp = self._activeDialog
+        if not activeDialog:
+            dialog = _parentDialog(obj)
+            self._activeDialog = (dialog, time.time())
+            if dialog:
+                orca.setLocusOfFocus(None, dialog)
+                labels = self.utilities.unrelatedLabels(dialog)
+                for label in labels:
+                    self._activeDialogLabels[hash(label)] = label.name
+
+        default.Script.onFocusedChanged(self, event)
 
     def getTextLineAtCaret(self, obj, offset=None):
         """Gets the line of text where the caret is."""
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 398e64e..82298cf 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -441,8 +441,6 @@ class Script(default.Script):
             self.onDocumentLoadComplete
         listeners["document:load-stopped"]                  = \
             self.onDocumentLoadStopped
-        listeners["object:state-changed:focused"]           = \
-            self.onStateFocused
 
         return listeners
 
@@ -1295,12 +1293,10 @@ class Script(default.Script):
         if event.source.getRole() == pyatspi.ROLE_FRAME:
             self.liveMngr.flushMessages()
 
-    def onFocus(self, event):
-        """Called whenever an object gets focus.
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
 
-        Arguments:
-        - event: the Event
-        """
+        # TODO - JD: Go through all of the crap below. :-/
 
         try:
             eventSourceRole = event.source.getRole()
@@ -1396,7 +1392,7 @@ class Script(default.Script):
                         self.presentLine(obj, characterOffset)
                 return
 
-        default.Script.onFocus(self, event)
+        default.Script.onFocusedChanged(self, event)
 
     def onShowingChanged(self, event):
         """Callback for object:state-changed:showing accessibility events."""
@@ -1429,42 +1425,6 @@ class Script(default.Script):
 
         default.Script.onShowingChanged(self, event)
 
-    def onStateFocused(self, event):
-        default.Script.onStateChanged(self, event)
-        if event.source.getRole() == pyatspi.ROLE_DOCUMENT_FRAME and \
-               event.detail1:
-            documentFrame = event.source
-
-            parent_attribs = self._getAttrDictionary(documentFrame.parent)
-            parent_tag = parent_attribs.get('tag', '')
-
-            if self._loadingDocumentContent or \
-                   documentFrame == self._currentFrame or \
-                   not parent_tag.endswith('browser'):
-                return
-
-            self._currentFrame = documentFrame
-
-            self.displayBrailleMessage(documentFrame.name)
-            speech.stop()
-            speech.speak(
-                "%s %s" \
-                % (documentFrame.name,
-                   self.speechGenerator.getLocalizedRoleName(
-                        documentFrame, pyatspi.ROLE_PAGE_TAB)))
-
-            [obj, characterOffset] = self.getCaretContext()
-            if not obj:
-                [obj, characterOffset] = self.findNextCaretInOrder()
-                self.setCaretContext(obj, characterOffset)
-            if not obj:
-                return
-
-            # When a document tab is tabbed to, we will just present the
-            # line where the caret currently is.
-            #
-            self.presentLine(obj, characterOffset)
-
     def onWindowDeactivated(self, event):
         """Called whenever a toplevel window is deactivated.
 
diff --git a/src/orca/scripts/toolkits/J2SE-access-bridge/script.py 
b/src/orca/scripts/toolkits/J2SE-access-bridge/script.py
index 76e30e0..ec789a8 100644
--- a/src/orca/scripts/toolkits/J2SE-access-bridge/script.py
+++ b/src/orca/scripts/toolkits/J2SE-access-bridge/script.py
@@ -112,45 +112,6 @@ class Script(default.Script):
             if 0 < keyval < 256:
                 keyboardEvent.event_string = chr(keyval)
 
-    def onFocus(self, event):
-        """Called whenever an object gets focus.
-
-        Arguments:
-        - event: the Event
-        """
-
-        role = event.source.getRole()
-
-        # Ignore bogus/senseless focus claims because they just cause us to
-        # be more chatty as a result of the event and then later as a result
-        # of the changed locusOfFocus.
-        #
-        if role == pyatspi.ROLE_ROOT_PANE:
-            return
-
-        if role == pyatspi.ROLE_PAGE_TAB_LIST and orca_state.locusOfFocus \
-           and orca_state.locusOfFocus.getRole() == pyatspi.ROLE_PAGE_TAB \
-           and orca_state.locusOfFocus.getState().\
-               contains(pyatspi.STATE_FOCUSED):
-            return
-
-        if role == pyatspi.ROLE_MENU:
-            # Override default.py's onFocus decision to ignore focus
-            # events on MENU items with selected children.  This is
-            # because JMenu's pop up without their children selected,
-            # but for some reason they always have
-            # selection.nSelectedChildren > 0.  I suspect this is a
-            # bug in JMenu.java:getAccessibleSelectionCount, but the
-            # details of Swing's MenuSelectionManager are foreign to
-            # me.  So, for now, we'll just be happy knowing that
-            # Java's menu items will give us focus events when they
-            # are selected.
-            #
-            orca.setLocusOfFocus(event, event.source)
-            return
-
-        default.Script.onFocus(self, event)
-
     def onCaretMoved(self, event):
         # Java's SpinButtons are the most caret movement happy thing
         # I've seen to date.  If you Up or Down on the keyboard to
@@ -207,12 +168,13 @@ class Script(default.Script):
         else:
             default.Script.onSelectionChanged(self, event)
 
-    def onStateChanged(self, event):
-        """Called whenever an object's state changes.
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
 
-        Arguments:
-        - event: the Event
-        """
+        obj = event.source
+        if not (event.detail1 and obj.getRole() == pyatspi.ROLE_ROOT_PANE):
+            default.Script.onFocusedChangedself, event)
+            return
 
         # This is a workaround for a java-access-bridge bug (Bug 355011)
         # where popup menu events are not sent to Orca.
@@ -220,26 +182,19 @@ class Script(default.Script):
         # When a root pane gets focus, a popup menu may have been invoked.
         # If there is a popup menu, give locus of focus to the armed menu
         # item.
-        #
-        if event.source.getRole() == pyatspi.ROLE_ROOT_PANE and \
-               event.type.startswith("object:state-changed:focused") and \
-               event.detail1 == 1:
-
-            for child in event.source:
-                # search the layered pane for a popup menu
-                if child.getRole() == pyatspi.ROLE_LAYERED_PANE:
-                    popup = self.utilities.descendantsWithRole(
-                        child, pyatspi.ROLE_POPUP_MENU, False)
-                    if len(popup) > 0:
-                        # set the locus of focus to the armed menu item
-                        items = self.utilities.descendantsWithRole(
-                            popup[0], pyatspi.ROLE_MENU_ITEM, False)
-                        for item in items:
-                            if item.getState().contains(pyatspi.STATE_ARMED):
-                                orca.setLocusOfFocus(event, item)
-                                return
-
-        default.Script.onStateChanged(self, event)
+        for child in obj:
+            if child.getRole() == pyatspi.ROLE_LAYERED_PANE:
+                popup = self.utilities.descendantsWithRole(
+                    child, pyatspi.ROLE_POPUP_MENU, False)
+                if len(popup) > 0:
+                    items = self.utilities.descendantsWithRole(
+                        popup[0], pyatspi.ROLE_MENU_ITEM, False)
+                    for item in items:
+                        if item.getState().contains(pyatspi.STATE_ARMED):
+                            orca.setLocusOfFocus(event, item)
+                            return
+
+        default.Script.onFocusedChanged(self, event)
 
     def onValueChanged(self, event):
         """Called whenever an object's value changes.
diff --git a/src/orca/scripts/toolkits/WebKitGtk/script.py b/src/orca/scripts/toolkits/WebKitGtk/script.py
index e8838fc..3f87003 100644
--- a/src/orca/scripts/toolkits/WebKitGtk/script.py
+++ b/src/orca/scripts/toolkits/WebKitGtk/script.py
@@ -257,12 +257,8 @@ class Script(default.Script):
         if event.source.getRole() == pyatspi.ROLE_DOCUMENT_FRAME:
             self._loadingDocumentContent = False
 
-    def onFocus(self, event):
-        """Called whenever an object gets focus.
-
-        Arguments:
-        - event: the Event
-        """
+    def onFocusedChanged(self, event):
+        """Callback for object:state-changed:focused accessibility events."""
 
         obj = event.source
         role = obj.getRole()
@@ -274,7 +270,7 @@ class Script(default.Script):
                        pyatspi.ROLE_LIST_ITEM,
                        pyatspi.ROLE_RADIO_BUTTON]
         if role in widgetRoles:
-            default.Script.onFocus(self, event)
+            default.Script.onFocusedChanged(self, event)
             return
 
         textRoles = [pyatspi.ROLE_HEADING,
@@ -290,7 +286,7 @@ class Script(default.Script):
             if lastKey in self.CARET_NAVIGATION_KEYS:
                 return
 
-        default.Script.onFocus(self, event)
+        default.Script.onFocusedChanged(self, event)
 
     def onBusyChanged(self, event):
         """Callback for object:state-changed:busy accessibility events."""


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