[orca] Create a dedicated object:state-changed callback for the "busy" state



commit faefeb9fad0b5399f973d96457afe0ad619fea55
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Mon Nov 4 13:17:35 2013 -0500

    Create a dedicated object:state-changed callback for the "busy" state

 src/orca/script_utilities.py                  |    7 +-
 src/orca/scripts/apps/Thunderbird/script.py   |   22 +---
 src/orca/scripts/default.py                   |    6 +
 src/orca/scripts/toolkits/Gecko/script.py     |  165 +++++++++++--------------
 src/orca/scripts/toolkits/WebKitGtk/script.py |   30 ++---
 5 files changed, 105 insertions(+), 125 deletions(-)
---
diff --git a/src/orca/script_utilities.py b/src/orca/script_utilities.py
index 912591a..7c5720a 100644
--- a/src/orca/script_utilities.py
+++ b/src/orca/script_utilities.py
@@ -607,8 +607,13 @@ class Utilities:
             except (LookupError, RuntimeError):
                 pass
 
+        try:
+            parentRole = obj.parent.getRole()
+        except:
+            parentRole = None
+
         # egg-list-box, e.g. privacy panel in gnome-control-center
-        if not displayedText and obj.parent.getRole() == pyatspi.ROLE_LIST_BOX:
+        if not displayedText and parentRole == pyatspi.ROLE_LIST_BOX:
             labels = self.unrelatedLabels(obj, onlyShowing=False)
             displayedText = " ".join(map(self.displayedText, labels))
 
diff --git a/src/orca/scripts/apps/Thunderbird/script.py b/src/orca/scripts/apps/Thunderbird/script.py
index 4085b4d..345ccb1 100644
--- a/src/orca/scripts/apps/Thunderbird/script.py
+++ b/src/orca/scripts/apps/Thunderbird/script.py
@@ -426,22 +426,14 @@ class Script(Gecko.Script):
         Gecko.Script.locusOfFocusChanged(self, event,
                                          oldLocusOfFocus, newLocusOfFocus)
 
-    def onStateChanged(self, event):
-        """Called whenever an object's state changes.
+    def onBusyChanged(self, event):
+        """Callback for object:state-changed:busy accessibility events."""
 
-        Arguments:
-        - event: the Event
-        """
-
-        if event.type.startswith("object:state-changed:busy"):
-            if event.source.getRole() == pyatspi.ROLE_DOCUMENT_FRAME \
-               and not event.detail1:
-                self._messageLoaded = True
-                if self.inDocumentContent():
-                    self._presentMessage(event.source)
-            return
-
-        default.Script.onStateChanged(self, event)
+        obj = event.source
+        if obj.getRole() == pyatspi.ROLE_DOCUMENT_FRAME and not event.detail1:
+            self._messageLoaded = True
+            if self.inDocumentContent():
+                self._presentMessage(obj)
 
     def onStateFocused(self, event):
         """Called whenever an object's state changes focus.
diff --git a/src/orca/scripts/default.py b/src/orca/scripts/default.py
index 8e4e47f..524fd96 100644
--- a/src/orca/scripts/default.py
+++ b/src/orca/scripts/default.py
@@ -529,6 +529,8 @@ class Script(script.Script):
             self.onChildrenChanged
         listeners["object:state-changed:active"]            = \
             self.onStateChanged
+        listeners["object:state-changed:busy"]              = \
+            self.onBusyChanged
         listeners["object:state-changed:focused"]           = \
             self.onStateChanged
         listeners["object:state-changed:showing"]           = \
@@ -2261,6 +2263,10 @@ class Script(script.Script):
                 [orca_state.locusOfFocus.parent,
                  orca_state.locusOfFocus.getIndexInParent()]
 
+    def onBusyChanged(self, event):
+        """Callback for object:state-changed:busy accessibility events."""
+        pass
+
     def onChildrenChanged(self, event):
         """Called when a child node has changed.
 
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 231d420..996113c 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -447,8 +447,6 @@ class Script(default.Script):
             self.onStateChanged
         listeners["object:state-changed:indeterminate"]     = \
             self.onStateChanged
-        listeners["object:state-changed:busy"]              = \
-            self.onStateChanged
         listeners["object:children-changed"]                = \
             self.onChildrenChanged
         listeners["object:text-changed:insert"]             = \
@@ -1170,6 +1168,80 @@ class Script(default.Script):
 
         default.Script.onSelectionChanged(self, event)
 
+    def onBusyChanged(self, event):
+        """Callback for object:state-changed:busy accessibility events."""
+
+        try:
+            obj = event.source
+            role = obj.getRole()
+            name = obj.name
+        except:
+            return
+        if role != pyatspi.ROLE_DOCUMENT_FRAME:
+             return
+
+        # The event is for the changing contents of the help frame as the user
+        # navigates from topic to topic in the list on the left. Ignore this.
+        if orca_state.locusOfFocus \
+           and orca_state.locusOfFocus.getRole() == pyatspi.ROLE_LIST_ITEM \
+           and not self.inDocumentContent(orca_state.locusOfFocus):
+            return
+ 
+        finishedLoading = False
+        if event.detail1:
+            self._loadingDocumentContent = True
+            message = messages.PAGE_LOADING_START
+        elif name:
+            message = messages.PAGE_LOADING_END_NAMED % name
+            finishedLoading = True
+        else:
+            message = messages.PAGE_LOADING_END
+            finishedLoading = True
+ 
+        if not _settingsManager.getSetting('onlySpeakDisplayedText'):
+            self.presentMessage(message)
+ 
+        if not finishedLoading:
+            return
+
+        # Store the document frame otherwise the first time it gains focus (e.g.
+        # the first time the user arrows off of a link into non-focusable text),
+        # onFocused will start chatting unnecessarily.
+        self._currentFrame = obj
+ 
+        # First try to figure out where the caret is on the newly loaded page.
+        # If it is on an editable object (e.g., a text entry), then present just
+        # that object. Otherwise, force the caret to the top of the page and
+        # start a SayAll from that position.
+        [obj, characterOffset] = self.getCaretContext()
+        atTop = False
+        if not obj:
+            self.clearCaretContext()
+            [obj, characterOffset] = self.getCaretContext()
+            atTop = True
+        if not obj:
+             return
+        if not atTop and not obj.getState().contains(pyatspi.STATE_FOCUSABLE):
+            self.clearCaretContext()
+            [obj, characterOffset] = self.getCaretContext()
+            if not obj:
+                return
+ 
+        # For braille, we just show the current line containing the caret. For
+        # speech, however, we will start a Say All operation if the caret is in
+        # an unfocusable area (e.g., it's not in a text entry area such as
+        # Google's search text entry or a link that we just returned to by
+        # pressing the back button). Otherwise, we'll just speak the line that
+        # the caret is on.
+        self.updateBraille(obj)
+        if obj.getState().contains(pyatspi.STATE_FOCUSABLE):
+            speech.speak(self.speechGenerator.generateSpeech(obj))
+        elif not script_settings.sayAllOnLoad:
+            self.speakContents(
+                self.getLineContentsAtOffset(obj, characterOffset))
+        elif _settingsManager.getSetting('enableSpeech'):
+            self.sayAll(None)
+
     def onChildrenChanged(self, event):
         """Called when a child node has changed.  In particular, we are looking
         for addition events often associated with Javascipt insertion.  One such
@@ -1411,95 +1483,6 @@ class Script(default.Script):
                         speech.speak(self.speechGenerator.getLocalizedRoleName(\
                                 event.source, pyatspi.ROLE_AUTOCOMPLETE))
 
-        # We care when the document frame changes it's busy state.  That
-        # means it has started/stopped loading content.
-        #
-        if event.type.startswith("object:state-changed:busy"):
-            if event.source \
-                and (event.source.getRole() == pyatspi.ROLE_DOCUMENT_FRAME):
-
-                finishedLoading = False
-                if orca_state.locusOfFocus \
-                    and (orca_state.locusOfFocus.getRole() \
-                         == pyatspi.ROLE_LIST_ITEM) \
-                   and not self.inDocumentContent(orca_state.locusOfFocus):
-                    # The event is for the changing contents of the help
-                    # frame as the user navigates from topic to topic in
-                    # the list on the left.  Ignore this.
-                    #
-                    return
-
-                elif event.detail1:
-                    self._loadingDocumentContent = True
-                    message = messages.PAGE_LOADING_START
-
-                elif event.source.name:
-                    message = messages.PAGE_LOADING_END_NAMED % event.source.name
-                    finishedLoading = True
-
-                else:
-                    message = messages.PAGE_LOADING_END
-                    finishedLoading = True
-
-                if not _settingsManager.getSetting('onlySpeakDisplayedText'):
-                    self.presentMessage(message)
-
-                if finishedLoading:
-                    # Store the document frame otherwise the first time it
-                    # gains focus (e.g. the first time the user arrows off
-                    # of a link into non-focusable text), onStateFocused
-                    # will start chatting unnecessarily.
-                    #
-                    self._currentFrame = event.source
-
-                    # We first try to figure out where the caret is on
-                    # the newly loaded page.  If it is on an editable
-                    # object (e.g., a text entry), then we present just
-                    # that object.  Otherwise, we force the caret to the
-                    # top of the page and start a SayAll from that position.
-                    #
-                    [obj, characterOffset] = self.getCaretContext()
-                    atTop = False
-                    if not obj:
-                        self.clearCaretContext()
-                        [obj, characterOffset] = self.getCaretContext()
-                        atTop = True
-
-                    # If we found nothing, then don't do anything.  Otherwise
-                    # determine if we should do a SayAll or not.
-                    #
-                    if not obj:
-                        return
-                    elif not atTop \
-                        and not obj.getState().contains(\
-                            pyatspi.STATE_FOCUSABLE):
-                        self.clearCaretContext()
-                        [obj, characterOffset] = self.getCaretContext()
-                        if not obj:
-                            return
-
-                    # For braille, we just show the current line
-                    # containing the caret.  For speech, however, we
-                    # will start a Say All operation if the caret is
-                    # in an unfocusable area (e.g., it's not in a text
-                    # entry area such as Google's search text entry
-                    # or a link that we just returned to by pressing
-                    # the back button). Otherwise, we'll just speak the
-                    # line that the caret is on.
-                    #
-                    self.updateBraille(obj)
-
-                    if obj.getState().contains(pyatspi.STATE_FOCUSABLE):
-                        speech.speak(self.speechGenerator.generateSpeech(obj))
-                    elif not script_settings.sayAllOnLoad:
-                        self.speakContents(\
-                            self.getLineContentsAtOffset(obj,
-                                                         characterOffset))
-                    elif _settingsManager.getSetting('enableSpeech'):
-                        self.sayAll(None)
-
-            return
-
         default.Script.onStateChanged(self, event)
 
     def onStateFocused(self, event):
diff --git a/src/orca/scripts/toolkits/WebKitGtk/script.py b/src/orca/scripts/toolkits/WebKitGtk/script.py
index 6fe0a22..e8838fc 100644
--- a/src/orca/scripts/toolkits/WebKitGtk/script.py
+++ b/src/orca/scripts/toolkits/WebKitGtk/script.py
@@ -85,8 +85,6 @@ class Script(default.Script):
             self.onDocumentLoadComplete
         listeners["document:load-stopped"]                  = \
             self.onDocumentLoadStopped
-        listeners["object:state-changed:busy"]              = \
-            self.onStateChanged
 
         return listeners
 
@@ -294,27 +292,23 @@ class Script(default.Script):
 
         default.Script.onFocus(self, event)
 
-    def onStateChanged(self, event):
-        """Called whenever an object's state changes.
+    def onBusyChanged(self, event):
+        """Callback for object:state-changed:busy accessibility events."""
 
-        Arguments:
-        - event: the Event
-        """
-
-        if not event.type.startswith("object:state-changed:busy"):
-            default.Script.onStateChanged(self, event)
+        obj = event.source
+        try:
+            role = obj.getRole()
+            name = obj.name
+        except:
             return
 
-        if not event.source \
-           or event.source.getRole() != pyatspi.ROLE_DOCUMENT_FRAME \
-           or not self._isBrowser:
+        if role != pyatspi.ROLE_DOCUMENT_FRAME or not self._isBrowser:
             return
 
         if event.detail1:
             self.presentMessage(messages.PAGE_LOADING_START)
-        elif event.source.name:
-            self.presentMessage(
-                messages.PAGE_LOADING_END_NAMED % event.source.name)
+        elif name:
+            self.presentMessage(messages.PAGE_LOADING_END_NAMED % name)
         else:
             self.presentMessage(messages.PAGE_LOADING_END)
 
@@ -599,11 +593,11 @@ class Script(default.Script):
 
         document = utils.findAncestor(
             obj, lambda x: x.getRole() == pyatspi.ROLE_DOCUMENT_FRAME)
-        if not document:
+        if not document or document.getState().contains(pyatspi.STATE_BUSY):
             return
 
         allTextObjs = utils.findAllDescendants(
-            document, lambda x: 'Text' in utils.listInterfaces(x))
+            document, lambda x: x and 'Text' in utils.listInterfaces(x))
         allTextObjs = allTextObjs[allTextObjs.index(obj):len(allTextObjs)]
         textObjs = [x for x in allTextObjs if x.parent not in allTextObjs]
         if not textObjs:


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