[orca] Add optional start and end offset arguments for getTextLineAtCaret()



commit 4b76761b151e3b9e790e9e1574c09c678a5c8e19
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Mon Mar 2 11:21:46 2015 -0500

    Add optional start and end offset arguments for getTextLineAtCaret()
    
    In the case of web content, we've already figured out and provided to
    the generators the start offset, end offset, and string to be presented.
    But then braille.py turns around and asks the script to (re)calculate it
    and (re)provide it. This is 1000 different kinds of silly, and ultimately
    getTextLineAtCaret() needs to go away. In the meantime, since multiple
    scripts rely upon it (and for more than just braille), we might as well
    make it possible for scripts to turn around and immediately hand back what
    the braille code is asking for.

 src/orca/braille.py                                |    4 +-
 src/orca/braille_generator.py                      |    3 +-
 src/orca/debug.py                                  |    1 +
 src/orca/formatting.py                             |   15 +++++++--
 src/orca/scripts/apps/gnome-terminal/script.py     |   14 ++------
 src/orca/scripts/apps/soffice/script.py            |   18 ++--------
 src/orca/scripts/default.py                        |   16 +--------
 src/orca/scripts/toolkits/Gecko/script.py          |   35 ++++++++------------
 src/orca/scripts/toolkits/WebKitGtk/script.py      |   16 ++-------
 test/keystrokes/firefox/aria_menu.py               |    4 ++-
 .../firefox/html_role_list_item_where_am_i.py      |   10 +++---
 test/keystrokes/firefox/longdesc_4.py              |    2 +-
 test/keystrokes/firefox/longdesc_5.py              |    2 +-
 test/keystrokes/firefox/longdesc_6.py              |    2 +-
 test/keystrokes/firefox/longdesc_7.py              |    2 +-
 test/keystrokes/firefox/longdesc_8.py              |    2 +-
 test/keystrokes/firefox/longdesc_9.py              |    2 +-
 17 files changed, 56 insertions(+), 92 deletions(-)
---
diff --git a/src/orca/braille.py b/src/orca/braille.py
index f3db24a..34f2cbd 100644
--- a/src/orca/braille.py
+++ b/src/orca/braille.py
@@ -528,8 +528,8 @@ class Text(Region):
         self.accessible = accessible
         if orca_state.activeScript and self.accessible:
             [string, self.caretOffset, self.lineOffset] = \
-                 orca_state.activeScript.getTextLineAtCaret(self.accessible,
-                                                            startOffset)
+                 orca_state.activeScript.getTextLineAtCaret(
+                     self.accessible, startOffset=startOffset, endOffset=endOffset)
         else:
             string = ""
             self.caretOffset = 0
diff --git a/src/orca/braille_generator.py b/src/orca/braille_generator.py
index 4e1333c..f25fd94 100644
--- a/src/orca/braille_generator.py
+++ b/src/orca/braille_generator.py
@@ -136,7 +136,8 @@ class BrailleGenerator(generator.Generator):
 
         doNotPresent = [pyatspi.ROLE_UNKNOWN,
                         pyatspi.ROLE_FILLER,
-                        pyatspi.ROLE_EXTENDED]
+                        pyatspi.ROLE_EXTENDED,
+                        pyatspi.ROLE_LINK]
 
         # egg-list-box, e.g. privacy panel in gnome-control-center
         if obj.parent and obj.parent.getRole() == pyatspi.ROLE_LIST_BOX:
diff --git a/src/orca/debug.py b/src/orca/debug.py
index 2eaeda7..db1f9b5 100644
--- a/src/orca/debug.py
+++ b/src/orca/debug.py
@@ -205,6 +205,7 @@ def println(level, text = ""):
     """
 
     if level >= debugLevel:
+        text = text.replace("\ufffc", "[OBJ]")
         if debugFile:
             try:
                 debugFile.writelines([text, "\n"])
diff --git a/src/orca/formatting.py b/src/orca/formatting.py
index 8d1e701..111a734 100644
--- a/src/orca/formatting.py
+++ b/src/orca/formatting.py
@@ -399,7 +399,10 @@ formatting = {
             'unfocused': '[Component(obj,\
                                      asString(label + displayedText + value + roleName + required))]',
             },
-        #pyatspi.ROLE_ALERT: 'default'
+        pyatspi.ROLE_ALERT: {
+            'unfocused': '((substring and ' + BRAILLE_TEXT + ')\
+                          or ([Component(obj, asString(labelAndName + roleName))]))'
+            },
         pyatspi.ROLE_ANIMATION: {
             'unfocused': '[Component(obj,\
                                      asString(label + displayedText + roleName + (description and space(": 
") + description)))]',
@@ -451,6 +454,10 @@ formatting = {
         pyatspi.ROLE_ENTRY: {
             'unfocused': BRAILLE_TEXT
             },
+        pyatspi.ROLE_FORM: {
+            'unfocused': '((substring and ' + BRAILLE_TEXT + ')\
+                          or ([Component(obj, asString(labelAndName + roleName))]))'
+            },
         pyatspi.ROLE_FRAME: {
             'focused':   '[Component(obj,\
                                      asString(((label + displayedText) or name) + value + roleName + 
alertAndDialogCount))]',
@@ -458,7 +465,8 @@ formatting = {
                                      asString(((label + displayedText) or name) + value + roleName + 
alertAndDialogCount))]'
             },
         pyatspi.ROLE_HEADING: {
-            'unfocused': '[Text(obj)] + [Region(" " + asString(roleName))]'
+            'unfocused': '[Text(obj, asString(placeholderText), "", startOffset, endOffset)]\
+                          + [Region(" " + asString(roleName))]'
             },
         #pyatspi.ROLE_HTML_CONTAINER: 'default'
         pyatspi.ROLE_ICON: {
@@ -477,7 +485,8 @@ formatting = {
         pyatspi.ROLE_LINK: {
             'unfocused': '[Link(obj, asString(currentLineText)\
                                      or asString(displayedText)\
-                                     or asString(name))]',
+                                     or asString(name))] \
+                        + (roleName and [Region(" " + asString(roleName))])',
         },
         pyatspi.ROLE_LIST: {
             'unfocused': '[Component(obj,\
diff --git a/src/orca/scripts/apps/gnome-terminal/script.py b/src/orca/scripts/apps/gnome-terminal/script.py
index 1eeca09..43fdc36 100644
--- a/src/orca/scripts/apps/gnome-terminal/script.py
+++ b/src/orca/scripts/apps/gnome-terminal/script.py
@@ -83,19 +83,11 @@ class Script(gtk.Script):
         gtk.Script.locusOfFocusChanged(self, event,
                                            oldLocusOfFocus, newLocusOfFocus)
 
-    def getTextLineAtCaret(self, acc, offset=None):
-        """Gets the line of text where the caret is.
+    def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None):
+        """To-be-removed. Returns the string, caretOffset, startOffset."""
 
-        Argument:
-        - obj: an Accessible object that implements the AccessibleText
-          interface
-        - offset: an optional caret offset to use.
-
-        Returns the [string, caretOffset, startOffset] for the line of text
-        where the caret is.
-        """
         string, caretOffset, lineOffset = \
-                gtk.Script.getTextLineAtCaret(self, acc)
+            super().getTextLineAtCaret(obj, offset, startOffset, endOffset)
 
         # Sometimes, gnome-terminal will give us very odd values when
         # the user is editing using 'vi' and has positioned the caret
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index 731f4e7..52d3b7c 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -985,20 +985,8 @@ class Script(default.Script):
         # Useless signals are useless.
         pass
 
-    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
-        of -1 as a child.
-
-        Argument:
-        - obj: an Accessible object that implements the AccessibleText
-          interface
-        - offset: an optional caret offset to use. (Not used here at the
-          moment, but needed in the Gecko script)
-
-        Returns the [string, caretOffset, startOffset] for the line of text
-        where the caret is.
-        """
+    def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None):
+        """To-be-removed. Returns the string, caretOffset, startOffset."""
 
         if obj.parent.getRole() == pyatspi.ROLE_COMBO_BOX:
             try:
@@ -1017,7 +1005,7 @@ class Script(default.Script):
 
                 return [lineString, 0, startOffset]
 
-        textLine = default.Script.getTextLineAtCaret(self, obj, offset)
+        textLine = super().getTextLineAtCaret(obj, offset, startOffset, endOffset)
         if not obj.getState().contains(pyatspi.STATE_FOCUSED):
             textLine[0] = self.utilities.displayedText(obj)
 
diff --git a/src/orca/scripts/default.py b/src/orca/scripts/default.py
index ff627a7..8964121 100644
--- a/src/orca/scripts/default.py
+++ b/src/orca/scripts/default.py
@@ -3970,21 +3970,9 @@ class Script(script.Script):
         self._inSayAll = False
         self._sayAllContexts = []
 
-    def getTextLineAtCaret(self, obj, offset=None):
-        """Gets the line of text where the caret is.
+    def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None):
+        """To-be-removed. Returns the string, caretOffset, startOffset."""
 
-        Argument:
-        - obj: an Accessible object that implements the AccessibleText
-          interface
-        - offset: an optional caret offset to use. (Not used here at the
-          moment, but needed in the Gecko script)
-
-        Returns the [string, caretOffset, startOffset] for the line of text
-        where the caret is.
-        """
-
-        # Get the the AccessibleText interrface
-        #
         try:
             text = obj.queryText()
         except NotImplementedError:
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 5529775..fcc4086 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -1473,7 +1473,7 @@ class Script(default.Script):
         for i, content in enumerate(contents):
             [obj, startOffset, endOffset, string] = content
             [regions, fRegion] = self.brailleGenerator.generateBraille(
-                obj, startOffset=startOffset, endOffset=endOffset)
+                obj, startOffset=startOffset, endOffset=endOffset, string=string)
             if i == index:
                 focusedRegion = fRegion
 
@@ -2202,34 +2202,26 @@ class Script(default.Script):
         self._documentFrameCaretContext[hash(documentFrame)] = \
             [obj, characterOffset]
 
-    def getTextLineAtCaret(self, obj, offset=None):
-        """Gets the portion of the line of text where the caret (or optional
-        offset) is. This is an override to accomodate the intricities of our
-        caret navigation management and to deal with bogus line information
-        being returned by Gecko when using getTextAtOffset.
-
-        Argument:
-        - obj: an Accessible object that implements the AccessibleText
-          interface
-        - offset: an optional caret offset to use.
-
-        Returns the [string, caretOffset, startOffset] for the line of text
-        where the caret is.
-        """
+    def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None):
+        """To-be-removed. Returns the string, caretOffset, startOffset."""
 
         if self._inFocusMode or not self.inDocumentContent(obj) \
            or self.utilities.isEntry(obj) \
            or self.utilities.isPasswordText(obj):
-            return default.Script.getTextLineAtCaret(self, obj, offset)
+            return super().getTextLineAtCaret(obj, offset, startOffset, endOffset)
 
-        if offset == None:
+        text = self.utilities.queryNonEmptyText(obj)
+        if offset is None:
             try:
-                offset = max(0, obj.queryText().caretOffset)
+                offset = max(0, text.caretOffset)
             except:
                 offset = 0
 
+        if text and startOffset is not None and endOffset is not None:
+            return text.getText(startOffset, endOffset), offset, startOffset
+
         contextObj, contextOffset = self.getCaretContext()
-        if self.utilities.isSameObject(contextObj, obj):
+        if contextObj == obj:
             caretOffset = contextOffset
         else:
             caretOffset = offset
@@ -2243,7 +2235,7 @@ class Script(default.Script):
 
         if index > -1:
             candidate, startOffset, endOffset, string = contents[index]
-            if string.find(self.EMBEDDED_OBJECT_CHARACTER) == -1:
+            if not self.EMBEDDED_OBJECT_CHARACTER in string:
                 return string, caretOffset, startOffset
 
         return '', 0, 0
@@ -2369,7 +2361,8 @@ class Script(default.Script):
             else:
                 formatType = 'unfocused'
             utterance = self.speechGenerator.generateSpeech(
-                obj, startOffset=startOffset, endOffset=endOffset, formatType=formatType)
+                obj, startOffset=startOffset, endOffset=endOffset, string=string,
+                formatType=formatType)
             if eliminatePauses:
                 utterance = list(filter(lambda x: not isinstance(x, Pause), utterance))
             if utterance and utterance[0]:
diff --git a/src/orca/scripts/toolkits/WebKitGtk/script.py b/src/orca/scripts/toolkits/WebKitGtk/script.py
index e36fc45..89c01c4 100644
--- a/src/orca/scripts/toolkits/WebKitGtk/script.py
+++ b/src/orca/scripts/toolkits/WebKitGtk/script.py
@@ -611,20 +611,10 @@ class Script(default.Script):
 
         text.setCaretOffset(offset)
 
-    def getTextLineAtCaret(self, obj, offset=None):
-        """Gets the line of text where the caret is.
+    def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None):
+        """To-be-removed. Returns the string, caretOffset, startOffset."""
 
-        Argument:
-        - obj: an Accessible object that implements the AccessibleText
-          interface
-        - offset: an optional caret offset to use. (Not used here at the
-          moment, but needed in the Gecko script)
-
-        Returns the [string, caretOffset, startOffset] for the line of text
-        where the caret is.
-        """
-
-        textLine = default.Script.getTextLineAtCaret(self, obj, offset)
+        textLine = super().getTextLineAtCaret(obj, offset, startOffset, endOffset)
         string = textLine[0]
         if string and string.find(self.EMBEDDED_OBJECT_CHARACTER) == -1 \
            and obj.getState().contains(pyatspi.STATE_FOCUSED):
diff --git a/test/keystrokes/firefox/aria_menu.py b/test/keystrokes/firefox/aria_menu.py
index 6d4d958..8b0785a 100644
--- a/test/keystrokes/firefox/aria_menu.py
+++ b/test/keystrokes/firefox/aria_menu.py
@@ -11,7 +11,9 @@ sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("<Control><Alt>m"))
 sequence.append(utils.AssertPresentationAction(
     "1. Move to the menu",
-    ["BRAILLE LINE:  'Edit menu'",
+    ["BRAILLE LINE:  'Entry # column header'",
+     "     VISIBLE:  'Entry # column header', cursor=1",
+     "BRAILLE LINE:  'Edit menu'",
      "     VISIBLE:  'Edit menu', cursor=1",
      "BRAILLE LINE:  'Edit menu'",
      "     VISIBLE:  'Edit menu', cursor=1",
diff --git a/test/keystrokes/firefox/html_role_list_item_where_am_i.py 
b/test/keystrokes/firefox/html_role_list_item_where_am_i.py
index 1a89eee..e5820d5 100644
--- a/test/keystrokes/firefox/html_role_list_item_where_am_i.py
+++ b/test/keystrokes/firefox/html_role_list_item_where_am_i.py
@@ -21,7 +21,7 @@ sequence.append(KeyComboAction("KP_Enter"))
 sequence.append(utils.AssertPresentationAction(
     "2. Basic Where Am I next item",
     ["BRAILLE LINE:  '• In a paragraph'",
-     "     VISIBLE:  '• In a paragraph', cursor=1",
+     "     VISIBLE:  '• In a paragraph', cursor=3",
      "SPEECH OUTPUT: 'list item • In a paragraph'"]))
 
 sequence.append(KeyComboAction("Down"))
@@ -30,7 +30,7 @@ sequence.append(KeyComboAction("KP_Enter"))
 sequence.append(utils.AssertPresentationAction(
     "3. Basic Where Am I next item",
     ["BRAILLE LINE:  '• In a section'",
-     "     VISIBLE:  '• In a section', cursor=1",
+     "     VISIBLE:  '• In a section', cursor=3",
      "SPEECH OUTPUT: 'list item • In a section'"]))
 
 sequence.append(KeyComboAction("Down"))
@@ -48,7 +48,7 @@ sequence.append(KeyComboAction("KP_Enter"))
 sequence.append(utils.AssertPresentationAction(
     "5. Basic Where Am I next item",
     ["BRAILLE LINE:  '2. A nested list item, in a paragraph'",
-     "     VISIBLE:  '2. A nested list item, in a para', cursor=1",
+     "     VISIBLE:  '2. A nested list item, in a para', cursor=4",
      "SPEECH OUTPUT: 'list item 2. A nested list item, in a paragraph Nesting level 1'"]))
 
 sequence.append(KeyComboAction("Down"))
@@ -57,7 +57,7 @@ sequence.append(KeyComboAction("KP_Enter"))
 sequence.append(utils.AssertPresentationAction(
     "6. Basic Where Am I next item",
     ["BRAILLE LINE:  '3. A nested list item, in a section'",
-     "     VISIBLE:  '3. A nested list item, in a sect', cursor=1",
+     "     VISIBLE:  '3. A nested list item, in a sect', cursor=4",
      "SPEECH OUTPUT: 'list item 3. A nested list item, in a section Nesting level 1'"]))
 
 sequence.append(KeyComboAction("Down"))
@@ -66,7 +66,7 @@ sequence.append(KeyComboAction("KP_Enter"))
 sequence.append(utils.AssertPresentationAction(
     "7. Basic Where Am I next item",
     ["BRAILLE LINE:  '• In a paragraph that's in a section'",
-     "     VISIBLE:  '• In a paragraph that's in a sec', cursor=1",
+     "     VISIBLE:  '• In a paragraph that's in a sec', cursor=3",
      "SPEECH OUTPUT: 'list item • In a paragraph that's in a section'"]))
 
 sequence.append(utils.AssertionSummaryAction())
diff --git a/test/keystrokes/firefox/longdesc_4.py b/test/keystrokes/firefox/longdesc_4.py
index bb34700..e1f2326 100644
--- a/test/keystrokes/firefox/longdesc_4.py
+++ b/test/keystrokes/firefox/longdesc_4.py
@@ -11,7 +11,7 @@ sequence.append(utils.AssertPresentationAction(
     "1. Where Am I on image",
     ["KNOWN ISSUE: 'Empty images are exposed to us as text, without AtspiAction, and the Firefox right-click 
menu lacks View Description",
      "BRAILLE LINE:  'the image'",
-     "     VISIBLE:  'the image', cursor=0",
+     "     VISIBLE:  'the image', cursor=1",
      "SPEECH OUTPUT: 'the image'"]))
 
 #sequence.append(PauseAction(3000))
diff --git a/test/keystrokes/firefox/longdesc_5.py b/test/keystrokes/firefox/longdesc_5.py
index bb34700..e1f2326 100644
--- a/test/keystrokes/firefox/longdesc_5.py
+++ b/test/keystrokes/firefox/longdesc_5.py
@@ -11,7 +11,7 @@ sequence.append(utils.AssertPresentationAction(
     "1. Where Am I on image",
     ["KNOWN ISSUE: 'Empty images are exposed to us as text, without AtspiAction, and the Firefox right-click 
menu lacks View Description",
      "BRAILLE LINE:  'the image'",
-     "     VISIBLE:  'the image', cursor=0",
+     "     VISIBLE:  'the image', cursor=1",
      "SPEECH OUTPUT: 'the image'"]))
 
 #sequence.append(PauseAction(3000))
diff --git a/test/keystrokes/firefox/longdesc_6.py b/test/keystrokes/firefox/longdesc_6.py
index bb34700..e1f2326 100644
--- a/test/keystrokes/firefox/longdesc_6.py
+++ b/test/keystrokes/firefox/longdesc_6.py
@@ -11,7 +11,7 @@ sequence.append(utils.AssertPresentationAction(
     "1. Where Am I on image",
     ["KNOWN ISSUE: 'Empty images are exposed to us as text, without AtspiAction, and the Firefox right-click 
menu lacks View Description",
      "BRAILLE LINE:  'the image'",
-     "     VISIBLE:  'the image', cursor=0",
+     "     VISIBLE:  'the image', cursor=1",
      "SPEECH OUTPUT: 'the image'"]))
 
 #sequence.append(PauseAction(3000))
diff --git a/test/keystrokes/firefox/longdesc_7.py b/test/keystrokes/firefox/longdesc_7.py
index e7f041d..f668a93 100644
--- a/test/keystrokes/firefox/longdesc_7.py
+++ b/test/keystrokes/firefox/longdesc_7.py
@@ -26,7 +26,7 @@ sequence.append(utils.AssertPresentationAction(
     ["BRAILLE LINE:  'Pass h1'",
      "     VISIBLE:  'Pass h1', cursor=0",
      "BRAILLE LINE:  'Pass h1'",
-     "     VISIBLE:  'Pass h1', cursor=0",
+     "     VISIBLE:  'Pass h1', cursor=1",
      "SPEECH OUTPUT: 'heading level 1 Pass'"]))
 
 sequence.append(utils.AssertionSummaryAction())
diff --git a/test/keystrokes/firefox/longdesc_8.py b/test/keystrokes/firefox/longdesc_8.py
index e7f041d..f668a93 100644
--- a/test/keystrokes/firefox/longdesc_8.py
+++ b/test/keystrokes/firefox/longdesc_8.py
@@ -26,7 +26,7 @@ sequence.append(utils.AssertPresentationAction(
     ["BRAILLE LINE:  'Pass h1'",
      "     VISIBLE:  'Pass h1', cursor=0",
      "BRAILLE LINE:  'Pass h1'",
-     "     VISIBLE:  'Pass h1', cursor=0",
+     "     VISIBLE:  'Pass h1', cursor=1",
      "SPEECH OUTPUT: 'heading level 1 Pass'"]))
 
 sequence.append(utils.AssertionSummaryAction())
diff --git a/test/keystrokes/firefox/longdesc_9.py b/test/keystrokes/firefox/longdesc_9.py
index e7f041d..f668a93 100644
--- a/test/keystrokes/firefox/longdesc_9.py
+++ b/test/keystrokes/firefox/longdesc_9.py
@@ -26,7 +26,7 @@ sequence.append(utils.AssertPresentationAction(
     ["BRAILLE LINE:  'Pass h1'",
      "     VISIBLE:  'Pass h1', cursor=0",
      "BRAILLE LINE:  'Pass h1'",
-     "     VISIBLE:  'Pass h1', cursor=0",
+     "     VISIBLE:  'Pass h1', cursor=1",
      "SPEECH OUTPUT: 'heading level 1 Pass'"]))
 
 sequence.append(utils.AssertionSummaryAction())


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