[orca] Add a "sticky" browse mode and keybinding



commit d0e7c3893f95e1d64982e8ac09e09df443032b6f
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Sat Aug 6 13:45:29 2016 -0400

    Add a "sticky" browse mode and keybinding
    
    * Default binding is Orca+A triple-clicked
    * Primary purpose is to override incorrect automatic mode toggling
      triggered by something unique to a particular site's content
    * Secondary purpose is to allow navigation of ROLE_EMBEDDED content
      when authors use ARIA role application incorrectly.

 help/C/commands_reading.page             |    6 +++++
 src/orca/cmdnames.py                     |   11 ++++++++++
 src/orca/messages.py                     |   11 ++++++++++
 src/orca/scripts/web/script.py           |   32 ++++++++++++++++++++++++++++++
 src/orca/scripts/web/script_utilities.py |   12 ++++++++--
 5 files changed, 69 insertions(+), 3 deletions(-)
---
diff --git a/help/C/commands_reading.page b/help/C/commands_reading.page
index e3a1dbd..b36e927 100644
--- a/help/C/commands_reading.page
+++ b/help/C/commands_reading.page
@@ -260,6 +260,12 @@
           <keyseq><key>Orca Modifier</key><key>A</key></keyseq> (double-clicked)
         </p>
       </item>
+      <item>
+        <p>
+          Enable "sticky" browse mode:
+          <keyseq><key>Orca Modifier</key><key>A</key></keyseq> (triple-clicked)
+        </p>
+      </item>
     </list>
   </section>
 </page>
diff --git a/src/orca/cmdnames.py b/src/orca/cmdnames.py
index 45d0be3..5e61d1a 100644
--- a/src/orca/cmdnames.py
+++ b/src/orca/cmdnames.py
@@ -1020,6 +1020,17 @@ TOGGLE_PRESENTATION_MODE = _("Switches between browse mode and focus mode.")
 # This string is associated with the Orca command to enable sticky focus mode.
 SET_FOCUS_MODE_STICKY = _("Enables sticky focus mode.")
 
+# Translators: (Please see the previous, detailed translator notes about
+# Focus mode and Browse mode.) In order to minimize the amount of work Orca
+# users need to do to switch between focus mode and browse mode, Orca attempts
+# to automatically switch to the mode which is appropriate to the current
+# web element. Sometimes, however, this automatic mode switching is not what
+# the user wants. A good example being web apps which have their own keyboard
+# navigation and use interaction model. As a result, Orca has a command which
+# enables setting a "sticky" browse mode which disables all automatic toggling.
+# This string is associated with the Orca command to enable sticky browse mode.
+SET_BROWSE_MODE_STICKY = _("Enables sticky browse mode.")
+
 # Translators: this is for navigating among unvisited links in a document.
 UNVISITED_LINK_PREV = _("Goes to previous unvisited link.")
 
diff --git a/src/orca/messages.py b/src/orca/messages.py
index 2e9cf80..b375c7b 100644
--- a/src/orca/messages.py
+++ b/src/orca/messages.py
@@ -1316,6 +1316,17 @@ MODE_FOCUS_TUTORIAL = _("To enable focus mode press %s.")
 # This string is the message presented when Orca switches to sticky focus mode.
 MODE_FOCUS_IS_STICKY = _("Focus mode is sticky.")
 
+# Translators: (Please see the previous, detailed translator notes about
+# Focus mode and Browse mode.) In order to minimize the amount of work Orca
+# users need to do to switch between focus mode and browse mode, Orca attempts
+# to automatically switch to the mode which is appropriate to the current
+# web element. Sometimes, however, this automatic mode switching is not what
+# the user wants. A good example being web apps which have their own keyboard
+# navigation and use interaction model. As a result, Orca has a command which
+# enables setting a "sticky" browse mode which disables all automatic toggling.
+# This string is the message presented when Orca switches to sticky browse mode.
+MODE_BROWSE_IS_STICKY = _("Browse mode is sticky.")
+
 # Translators: Hovering the mouse over certain objects on a web page causes a 
 # new object to appear such as a pop-up menu. Orca has a command will move the
 # user to the object which just appeared as a result of the user hovering the
diff --git a/src/orca/scripts/web/script.py b/src/orca/scripts/web/script.py
index 439b423..266c877 100644
--- a/src/orca/scripts/web/script.py
+++ b/src/orca/scripts/web/script.py
@@ -79,6 +79,7 @@ class Script(default.Script):
         self._inMouseOverObject = False
         self._inFocusMode = False
         self._focusModeIsSticky = False
+        self._browseModeIsSticky = False
 
         if _settingsManager.getSetting('caretNavigationEnabled') is None:
             _settingsManager.setSetting('caretNavigationEnabled', True)
@@ -152,6 +153,14 @@ class Script(default.Script):
                 self.inputEventHandlers.get("enableStickyFocusModeHandler"),
                 2))
 
+        keyBindings.add(
+            keybindings.KeyBinding(
+                "a",
+                keybindings.defaultModifierMask,
+                keybindings.ORCA_MODIFIER_MASK,
+                self.inputEventHandlers.get("enableStickyBrowseModeHandler"),
+                3))
+
         layout = _settingsManager.getSetting('keyboardLayout')
         if layout == settings.GENERAL_KEYBOARD_LAYOUT_DESKTOP:
             key = "KP_Multiply"
@@ -212,6 +221,10 @@ class Script(default.Script):
                 Script.enableStickyFocusMode,
                 cmdnames.SET_FOCUS_MODE_STICKY)
 
+        self.inputEventHandlers["enableStickyBrowseModeHandler"] = \
+            input_event.InputEventHandler(
+                Script.enableStickyBrowseMode,
+                cmdnames.SET_BROWSE_MODE_STICKY)
 
     def getBookmarks(self):
         """Returns the "bookmarks" class for this script."""
@@ -682,12 +695,20 @@ class Script(default.Script):
 
         return self._focusModeIsSticky
 
+    def browseModeIsSticky(self):
+        """Returns True if we're in 'sticky' browse mode."""
+
+        return self._browseModeIsSticky
+
     def useFocusMode(self, obj):
         """Returns True if we should use focus mode in obj."""
 
         if self._focusModeIsSticky:
             return True
 
+        if self._browseModeIsSticky:
+            return False
+
         if not _settingsManager.getSetting('structNavTriggersFocusMode') \
            and self._lastCommandWasStructNav:
             return False
@@ -954,12 +975,21 @@ class Script(default.Script):
         self._inMouseOverObject = False
         self._lastMouseOverObject = None
 
+    def enableStickyBrowseMode(self, inputEvent, forceMessage=False):
+        if not self._browseModeIsSticky or forceMessage:
+            self.presentMessage(messages.MODE_BROWSE_IS_STICKY)
+
+        self._inFocusMode = False
+        self._focusModeIsSticky = False
+        self._browseModeIsSticky = True
+
     def enableStickyFocusMode(self, inputEvent, forceMessage=False):
         if not self._focusModeIsSticky or forceMessage:
             self.presentMessage(messages.MODE_FOCUS_IS_STICKY)
 
         self._inFocusMode = True
         self._focusModeIsSticky = True
+        self._browseModeIsSticky = False
 
     def togglePresentationMode(self, inputEvent):
         [obj, characterOffset] = self.utilities.getCaretContext()
@@ -984,6 +1014,7 @@ class Script(default.Script):
             self.presentMessage(messages.MODE_FOCUS)
         self._inFocusMode = not self._inFocusMode
         self._focusModeIsSticky = False
+        self._browseModeIsSticky = False
 
     def locusOfFocusChanged(self, event, oldFocus, newFocus):
         """Handles changes of focus of interest to the script."""
@@ -1052,6 +1083,7 @@ class Script(default.Script):
             return True
 
         if not self._focusModeIsSticky \
+           and not self._browseModeIsSticky \
            and self.useFocusMode(newFocus) != self._inFocusMode:
             self.togglePresentationMode(None)
 
diff --git a/src/orca/scripts/web/script_utilities.py b/src/orca/scripts/web/script_utilities.py
index 75072cd..602656d 100644
--- a/src/orca/scripts/web/script_utilities.py
+++ b/src/orca/scripts/web/script_utilities.py
@@ -761,9 +761,12 @@ class Utilities(script_utilities.Utilities):
                 rv = None
 
         if not self.isLiveRegion(obj):
-            doNotQuery = [pyatspi.ROLE_EMBEDDED,
-                          pyatspi.ROLE_TABLE_ROW,
+            doNotQuery = [pyatspi.ROLE_TABLE_ROW,
                           pyatspi.ROLE_TOOL_BAR]
+
+            if not self._script.browseModeIsSticky():
+                doNotQuery.append(pyatspi.ROLE_EMBEDDED)
+
             role = obj.getRole()
             if rv and role in doNotQuery:
                 rv = None
@@ -2784,7 +2787,6 @@ class Utilities(script_utilities.Utilities):
             return False
 
         doNotDescend = [pyatspi.ROLE_COMBO_BOX,
-                        pyatspi.ROLE_EMBEDDED,
                         pyatspi.ROLE_LIST_BOX,
                         pyatspi.ROLE_MENU_BAR,
                         pyatspi.ROLE_MENU,
@@ -2795,6 +2797,10 @@ class Utilities(script_utilities.Utilities):
                         pyatspi.ROLE_TOOL_TIP,
                         pyatspi.ROLE_TREE,
                         pyatspi.ROLE_TREE_TABLE]
+
+        if not self._script.browseModeIsSticky():
+            doNotDescend.append(pyatspi.ROLE_EMBEDDED)
+
         return role in doNotDescend
 
     def _searchForCaretContext(self, obj):


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