[orca] Create a dedicated object:state-chagned callback for "checked" and "indeterminate" states



commit a89014f593b8080ff534c518bfc6598663455713
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Mon Nov 4 15:03:03 2013 -0500

    Create a dedicated object:state-chagned callback for "checked" and "indeterminate" states
    
    Also fix a bug in presenting ARIA tri-state checkbox state changes in Gecko

 src/orca/scripts/apps/soffice/script.py   |   25 +++++++++++++
 src/orca/scripts/default.py               |   54 ++++++++++++++++++++++------
 src/orca/scripts/toolkits/Gecko/script.py |   21 -----------
 3 files changed, 67 insertions(+), 33 deletions(-)
---
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index a765bb5..1a5f642 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -968,6 +968,31 @@ class Script(default.Script):
 
         default.Script.onCaretMoved(self, event)
 
+    def onCheckedChanged(self, event):
+        """Callback for object:state-changed:checked accessibility events."""
+
+        obj = event.source
+        role = obj.getRole()
+        if not role in [pyatspi.ROLE_TOGGLE_BUTTON, pyatspi.ROLE_PUSH_BUTTON]:
+            default.Script.onCheckedChanged(self, event)
+            return
+ 
+        # Announce when the toolbar buttons are toggled if we just toggled
+        # them; not if we navigated to some text.
+        weToggledIt = False
+        if isinstance(orca_state.lastInputEvent, input_event.MouseButtonEvent):
+            x = orca_state.lastInputEvent.x
+            y = orca_state.lastInputEvent.y
+            weToggledIt = obj.queryComponent().contains(x, y, 0)
+        else:
+            keyString, mods = self.utilities.lastKeyAndModifiers()
+            navKeys = ["Up", "Down", "Left", "Right", "Page_Up", "Page_Down",
+                       "Home", "End"]
+            wasCommand = mods & settings.COMMAND_MODIFIER_MASK
+            weToggledIt = wasCommand and keyString not in navKeys
+        if weToggledIt:
+            speech.speak(self.speechGenerator.generateSpeech(obj))
+
     def getTextLineAtCaret(self, obj, offset=None):
         """Gets the line of text where the caret is. Overridden here to
         handle combo boxes who have a text object with a caret offset
diff --git a/src/orca/scripts/default.py b/src/orca/scripts/default.py
index aec40b6..4ba5aac 100644
--- a/src/orca/scripts/default.py
+++ b/src/orca/scripts/default.py
@@ -536,11 +536,11 @@ class Script(script.Script):
         listeners["object:state-changed:showing"]           = \
             self.onStateChanged
         listeners["object:state-changed:checked"]           = \
-            self.onStateChanged
+            self.onCheckedChanged
         listeners["object:state-changed:pressed"]           = \
             self.onStateChanged
         listeners["object:state-changed:indeterminate"]     = \
-            self.onStateChanged
+            self.onIndeterminateChanged
         listeners["object:state-changed:expanded"]          = \
             self.onExpandedChanged
         listeners["object:state-changed:selected"]          = \
@@ -2267,6 +2267,28 @@ class Script(script.Script):
         """Callback for object:state-changed:busy accessibility events."""
         pass
 
+    def onCheckedChanged(self, event):
+        """Callback for object:state-changed:checked accessibility events."""
+
+        obj = event.source
+        if not self.utilities.isSameObject(obj, orca_state.locusOfFocus):
+            # Present changes of child widgets of GtkListBox items
+            isListBox = lambda x: x and x.getRole() == pyatspi.ROLE_LIST_BOX
+            if not pyatspi.findAncestor(obj, isListBox):
+                return
+ 
+        # Radio buttons normally change their state when you arrow to them,
+        # so we handle the announcement of their state changes in the focus
+        # handling code.  However, we do need to handle radio buttons where
+        # the user needs to press the space key to select them.
+        if obj.getRole() == pyatspi.ROLE_RADIO_BUTTON:
+            eventString, mods = self.utilities.lastKeyAndModifiers()
+            if not eventString in [" ", "space"]:
+                return
+ 
+        self.updateBraille(obj)
+        speech.speak(self.speechGenerator.generateSpeech(obj, alreadyFocused=True))
+
     def onChildrenChanged(self, event):
         """Called when a child node has changed.
 
@@ -2397,6 +2419,23 @@ class Script(script.Script):
 
         orca.setLocusOfFocus(event, newFocus)
 
+    def onIndeterminateChanged(self, event):
+        """Callback for object:state-changed:indeterminate accessibility events."""
+
+        # If this state is cleared, the new state will become checked or unchecked
+        # and we should get object:state-changed:checked events for those cases.
+        # Therefore, if the state is not now indeterminate/partially checked,
+        # ignore this event.
+        if not event.detail1:
+            return
+
+        obj = event.source
+        if not self.utilities.isSameObject(obj, orca_state.locusOfFocus):
+            return
+
+        self.updateBraille(obj)
+        speech.speak(self.speechGenerator.generateSpeech(obj, alreadyFocused=True))
+
     def onMouseButton(self, event):
         """Called whenever the user presses or releases a mouse button.
 
@@ -5058,16 +5097,7 @@ class Script(script.Script):
 #
 state_change_notifiers = {}
 
-state_change_notifiers[pyatspi.ROLE_CHECK_MENU_ITEM] = ("checked", None)
-state_change_notifiers[pyatspi.ROLE_CHECK_BOX]       = ("checked",
-                                                        "indeterminate",
-                                                        None)
 state_change_notifiers[pyatspi.ROLE_PANEL]           = ("showing", None)
 state_change_notifiers[pyatspi.ROLE_LABEL]           = ("showing", None)
 state_change_notifiers[pyatspi.ROLE_NOTIFICATION]    = ("showing", None)
-state_change_notifiers[pyatspi.ROLE_RADIO_BUTTON]    = ("checked", None)
-state_change_notifiers[pyatspi.ROLE_TOGGLE_BUTTON]   = ("checked",
-                                                        "pressed",
-                                                        None)
-state_change_notifiers[pyatspi.ROLE_TABLE_CELL]      = ("checked", None)
-
+state_change_notifiers[pyatspi.ROLE_TOGGLE_BUTTON]   = ("pressed", None)
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 996113c..ee9d4b2 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -443,10 +443,6 @@ class Script(default.Script):
             self.onDocumentLoadStopped
         listeners["object:state-changed:showing"]           = \
             self.onStateChanged
-        listeners["object:state-changed:checked"]           = \
-            self.onStateChanged
-        listeners["object:state-changed:indeterminate"]     = \
-            self.onStateChanged
         listeners["object:children-changed"]                = \
             self.onChildrenChanged
         listeners["object:text-changed:insert"]             = \
@@ -1440,23 +1436,6 @@ class Script(default.Script):
         - event: the Event
         """
 
-        # HTML radio buttons don't automatically become selected when
-        # they receive focus.  The user has to press the space bar on
-        # them much like checkboxes.  But if the user clicks on the
-        # radio button with the mouse, we'll wind up speaking the
-        # state twice because of the focus event.
-        #
-        if event.type.startswith("object:state-changed:checked") \
-           and event.source \
-           and (event.source.getRole() == pyatspi.ROLE_RADIO_BUTTON) \
-           and (event.detail1 == 1) \
-           and self.inDocumentContent(event.source) \
-           and not self.isAriaWidget(event.source) \
-           and not isinstance(orca_state.lastInputEvent,
-                              input_event.MouseButtonEvent):
-            self.visualAppearanceChanged(event, event.source)
-            return
-
         # If an autocomplete appears beneath an entry, we don't want
         # to prevent the user from being able to arrow into it.
         #


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