[orca] Do not let caret navigation wander into offscreen labels



commit 6412bdcf8f3edfd77c0e9d0a2273a331eff1dfbb
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Tue Sep 9 23:51:47 2014 -0400

    Do not let caret navigation wander into offscreen labels

 src/orca/scripts/toolkits/Gecko/script.py          |   16 +++--
 .../scripts/toolkits/Gecko/script_utilities.py     |   17 +++++-
 test/html/hidden-label.html                        |   20 ++++++
 .../firefox/line_nav_hidden_label.params           |    1 +
 test/keystrokes/firefox/line_nav_hidden_label.py   |   65 ++++++++++++++++++++
 5 files changed, 112 insertions(+), 7 deletions(-)
---
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 9f1e50b..f3c0a55 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -1903,9 +1903,11 @@ class Script(default.Script):
                                              pyatspi.ROLE_TOOL_BAR]
 
         isHidden = self.utilities.isHidden(obj)
+        isOffScreenLabel = self.utilities.isOffScreenLabel(obj, startOffset)
+        skip = isHidden or isOffScreenLabel
 
         text = self.utilities.queryNonEmptyText(obj)
-        if text and not isHidden:
+        if text and not skip:
             unicodeText = self.utilities.unicodeText(obj)
 
             # Delete the final space character if we find it.  Otherwise,
@@ -1937,7 +1939,7 @@ class Script(default.Script):
         # to place the caret inside the list, but rather treat the list
         # as a single object.  Otherwise, if it has children, look there.
         #
-        elif obj.childCount and obj[0] and not doNotDescend and not isHidden:
+        elif obj.childCount and obj[0] and not doNotDescend and not skip:
             try:
                 return self.findNextCaretInOrder(obj[0],
                                                  -1,
@@ -1945,7 +1947,7 @@ class Script(default.Script):
             except:
                 pass
 
-        elif includeNonText and startOffset < 0 and not isHidden:
+        elif includeNonText and startOffset < 0 and not skip:
             extents = obj.queryComponent().getExtents(0)
             if (extents.width != 0) and (extents.height != 0):
                 return [obj, 0]
@@ -2019,9 +2021,11 @@ class Script(default.Script):
                                              pyatspi.ROLE_TOOL_BAR]
 
         isHidden = self.utilities.isHidden(obj)
+        isOffScreenLabel = self.utilities.isOffScreenLabel(obj, startOffset)
+        skip = isHidden or isOffScreenLabel
 
         text = self.utilities.queryNonEmptyText(obj)
-        if text and not isHidden:
+        if text and not skip:
             unicodeText = self.utilities.unicodeText(obj)
 
             # Delete the final space character if we find it.  Otherwise,
@@ -2054,7 +2058,7 @@ class Script(default.Script):
         # as a single object.  Otherwise, if it has children, look there.
         #
         elif obj.childCount and obj[obj.childCount - 1] and not doNotDescend \
-             and not isHidden:
+             and not skip:
             try:
                 return self.findPreviousCaretInOrder(
                     obj[obj.childCount - 1],
@@ -2063,7 +2067,7 @@ class Script(default.Script):
             except:
                 pass
 
-        elif includeNonText and startOffset < 0 and not isHidden:
+        elif includeNonText and startOffset < 0 and not skip:
             extents = obj.queryComponent().getExtents(0)
             if (extents.width != 0) and (extents.height != 0):
                 return [obj, 0]
diff --git a/src/orca/scripts/toolkits/Gecko/script_utilities.py 
b/src/orca/scripts/toolkits/Gecko/script_utilities.py
index 998dd80..f2a3ac9 100644
--- a/src/orca/scripts/toolkits/Gecko/script_utilities.py
+++ b/src/orca/scripts/toolkits/Gecko/script_utilities.py
@@ -801,7 +801,8 @@ class Utilities(script_utilities.Utilities):
                 return False
 
             if (self.isTextBlockElement(obj) and not string.strip()) \
-               or self._script.isLabellingContents(obj, contents):
+               or self._script.isLabellingContents(obj, contents) \
+               or self.isOffScreenLabel(obj, start):
                 return False
 
             return True
@@ -920,6 +921,20 @@ class Utilities(script_utilities.Utilities):
 
         return objects
 
+    def isOffScreenLabel(self, obj, offset=0):
+        if not obj:
+            return False
+
+        isLabelFor = lambda x: x.getRelationType() == pyatspi.RELATION_LABEL_FOR
+        relations = list(filter(isLabelFor, obj.getRelationSet()))
+        if relations:
+            offset = max(offset, 0)
+            x, y, width, height = self.getExtents(obj, offset, offset + 1)
+            if x < 0 or y < 0:
+                return True
+
+        return False
+
     def isClickableElement(self, obj):
         if not self._script.inDocumentContent(obj):
             return False
diff --git a/test/html/hidden-label.html b/test/html/hidden-label.html
new file mode 100644
index 0000000..4570504
--- /dev/null
+++ b/test/html/hidden-label.html
@@ -0,0 +1,20 @@
+<html><head>
+<meta http-equiv="content-type" content="text/html; charset=windows-1252">
+<style>
+.qOption {position:relative;}
+input.cb  {position:absolute;top:4px;left:4px;}
+label.cb_off img.selImg {vertical-align:top;width:20px;height:20px;position:relative;z-index:11;}
+div.hlbl, span.hlbl {position:absolute;left:0px;top:-5000px;width:1px;height:1px;overflow:hidden;}
+</style>
+</head>
+<body>
+<p>Start</p>
+<div class="qOption">
+<input class="cb" id="cb1" name="cb1" type="checkbox">
+<label for="cb1" id="lcb1" class="cb_off">
+<img src="" class="selImg" alt=""><span class="qLabel"><span class="hlbl">I am a hidden label! &nbsp; 
</span>Check me!</span></label>
+</div>
+<p>End</p>
+
+
+</body></html>
\ No newline at end of file
diff --git a/test/keystrokes/firefox/line_nav_hidden_label.params 
b/test/keystrokes/firefox/line_nav_hidden_label.params
new file mode 100644
index 0000000..9a88931
--- /dev/null
+++ b/test/keystrokes/firefox/line_nav_hidden_label.params
@@ -0,0 +1 @@
+PARAMS=$TEST_DIR/../../html/hidden-label.html
diff --git a/test/keystrokes/firefox/line_nav_hidden_label.py 
b/test/keystrokes/firefox/line_nav_hidden_label.py
new file mode 100644
index 0000000..707d614
--- /dev/null
+++ b/test/keystrokes/firefox/line_nav_hidden_label.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+"""Test of line navigation output of Firefox."""
+
+from macaroon.playback import *
+import utils
+
+sequence = MacroSequence()
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("<Control>Home"))
+sequence.append(utils.AssertPresentationAction(
+    "1. Top of file",
+    ["BRAILLE LINE:  'Start'",
+     "     VISIBLE:  'Start', cursor=1",
+     "SPEECH OUTPUT: 'Start'"]))
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("Down"))
+sequence.append(utils.AssertPresentationAction(
+    "2. Line Down",
+    ["KNOWN ISSUE: It would be nice to not present the junk image",
+     "BRAILLE LINE:  '< > I am a hidden label!   Check me! check box image'",
+     "     VISIBLE:  '< > I am a hidden label!   Check', cursor=0",
+     "SPEECH OUTPUT: 'I am a hidden label!   Check me!'",
+     "SPEECH OUTPUT: 'check box'",
+     "SPEECH OUTPUT: 'not checked'",
+     "SPEECH OUTPUT: 'image'"]))
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("Down"))
+sequence.append(utils.AssertPresentationAction(
+    "3. Line Down",
+    ["BRAILLE LINE:  ''",
+     "     VISIBLE:  '', cursor=0",
+     "SPEECH OUTPUT: 'blank'"]))
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("Down"))
+sequence.append(utils.AssertPresentationAction(
+    "4. Line Down",
+    ["BRAILLE LINE:  'End'",
+     "     VISIBLE:  'End', cursor=1",
+     "SPEECH OUTPUT: 'End'"]))
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("Up"))
+sequence.append(utils.AssertPresentationAction(
+    "5. Line Up",
+    ["BRAILLE LINE:  '< > I am a hidden label!   Check me! check box image'",
+     "     VISIBLE:  '< > I am a hidden label!   Check', cursor=0",
+     "SPEECH OUTPUT: 'I am a hidden label!   Check me!'",
+     "SPEECH OUTPUT: 'check box'",
+     "SPEECH OUTPUT: 'not checked'"]))
+
+sequence.append(utils.StartRecordingAction())
+sequence.append(KeyComboAction("Up"))
+sequence.append(utils.AssertPresentationAction(
+    "6. Line Up",
+    ["BRAILLE LINE:  'Start'",
+     "     VISIBLE:  'Start', cursor=1",
+     "SPEECH OUTPUT: 'Start'"]))
+
+sequence.append(utils.AssertionSummaryAction())
+sequence.start()


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