[orca] Add initial, partial support for regoin-change events



commit a701740116c6b2bdff0f31ae1866313afd49b9e5
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Tue May 19 17:20:11 2020 -0400

    Add initial, partial support for regoin-change events
    
    Emit the new AT-SPI2 "region-changed" signal to allow other tools
    which work with Orca (e.g. screen magnifiers, highlighting tools,
    etc.) to know the object and optional text range Orca is presenting.
    
    This has so far been added for:
    * Focus tracking
    * Mouse Review
    * Say All
    * Caret navigation (all apps but web-based)
    
    Remaining:
    * Caret navigation (web-based)
    * Flat review (all apps)
    
    The above two tasks are slightly more complicated because a given
    line can be made up of multiple objects being presented at once.
    
    The current support also includes the mode/reason Orca's current
    region of interest has changed. We are waiting for additional
    API added to AT-SPI2 so that we can emit a signal to notify
    interested tools of this mode change/reason.

 src/orca/mouse_review.py                      |  6 +++++-
 src/orca/orca.py                              | 31 +++++++++++++++++++++++++++
 src/orca/orca_state.py                        |  3 +++
 src/orca/scripts/apps/Thunderbird/script.py   |  1 +
 src/orca/scripts/apps/gedit/script.py         |  1 +
 src/orca/scripts/apps/soffice/script.py       |  1 +
 src/orca/scripts/default.py                   | 19 +++++++++++++---
 src/orca/scripts/toolkits/WebKitGtk/script.py |  4 ++++
 src/orca/scripts/web/script.py                |  4 ++++
 9 files changed, 66 insertions(+), 4 deletions(-)
---
diff --git a/src/orca/mouse_review.py b/src/orca/mouse_review.py
index 4d1856633..c9c38b9ae 100644
--- a/src/orca/mouse_review.py
+++ b/src/orca/mouse_review.py
@@ -43,6 +43,7 @@ except:
 from . import debug
 from . import event_manager
 from . import messages
+from . import orca
 from . import orca_state
 from . import script_manager
 from . import settings_manager
@@ -66,7 +67,7 @@ class _StringContext:
         - script: The script associated with the accessible object
         """
 
-        self._obj = hash(obj)
+        self._obj = obj
         self._script = script
         self._string = string
         self._start = start
@@ -142,6 +143,8 @@ class _StringContext:
 
         voice = self._script.speechGenerator.voice(string=self._string)
         string = self._script.utilities.adjustForRepeats(self._string)
+
+        orca.emitRegionChanged(self._obj, self._start, self._end, orca.MOUSE_REVIEW)
         self._script.speakMessage(string, voice=voice, interrupt=False)
         self._script.displayBrailleMessage(self._string, -1)
         return True
@@ -291,6 +294,7 @@ class _ItemContext:
 
         if self._obj and self._obj != prior._obj:
             priorObj = prior._obj or self._getContainer()
+            orca.emitRegionChanged(self._obj, mode=orca.MOUSE_REVIEW)
             self._script.presentObject(self._obj, priorObj=priorObj, inMouseReview=True)
             if not self._script.utilities.isEditableTextArea(self._obj):
                 return True
diff --git a/src/orca/orca.py b/src/orca/orca.py
index fa41b2707..71d1279d7 100644
--- a/src/orca/orca.py
+++ b/src/orca/orca.py
@@ -121,6 +121,37 @@ _restoreOrcaKeys = False
 #                                                                      #
 ########################################################################
 
+CARET_TRACKING = "caret-tracking"
+FOCUS_TRACKING = "focus-tracking"
+FLAT_REVIEW = "flat-review"
+MOUSE_REVIEW = "mouse-review"
+SAY_ALL = "say-all"
+
+def emitRegionChanged(obj, startOffset=None, endOffset=None, mode=None):
+    """Notifies interested clients that the current region of interest has changed."""
+
+    if startOffset is None:
+        startOffset = 0
+    if endOffset is None:
+        endOffset = startOffset
+    if mode is None:
+        mode = FOCUS_TRACKING
+
+    # TODO - JD: Once the API has been defined in AT-SPI2, emit mode-change here.
+
+    if mode != orca_state.activeMode:
+        msg = "ORCA: Switching active mode from %s to %s" % (orca_state.activeMode, mode)
+        debug.println(debug.LEVEL_INFO, msg, True)
+        orca_state.activeMode = mode
+
+    try:
+        msg = "ORCA: Region of interest: %s (%i, %i)" % (obj, startOffset, endOffset)
+        debug.println(debug.LEVEL_INFO, msg, True)
+        obj.emit("region-changed", startOffset, endOffset)
+    except:
+        msg = "ORCA: Exception emitting region-changed notification"
+        debug.println(debug.LEVEL_INFO, msg, True)
+
 def setLocusOfFocus(event, obj, notifyScript=True, force=False):
     """Sets the locus of focus (i.e., the object with visual focus) and
     notifies the script of the change should the script wish to present
diff --git a/src/orca/orca_state.py b/src/orca/orca_state.py
index bb8bd49ab..8fa1e8865 100644
--- a/src/orca/orca_state.py
+++ b/src/orca/orca_state.py
@@ -44,6 +44,9 @@ activeWindow = None
 #
 activeScript = None
 
+# The currently active mode (focus, say all, flat review, etc.)
+activeMode = None
+
 # Used to capture keys to redefine key bindings by the user.
 #
 capturingKeys   = False
diff --git a/src/orca/scripts/apps/Thunderbird/script.py b/src/orca/scripts/apps/Thunderbird/script.py
index d1e9de49b..9da4a188e 100644
--- a/src/orca/scripts/apps/Thunderbird/script.py
+++ b/src/orca/scripts/apps/Thunderbird/script.py
@@ -124,6 +124,7 @@ class Script(Gecko.Script):
 
         if self.spellcheck.isSuggestionsItem(newFocus):
             includeLabel = not self.spellcheck.isSuggestionsItem(oldFocus)
+            orca.emitRegionChanged(newFocus)
             self.updateBraille(newFocus)
             self.spellcheck.presentSuggestionListItem(includeLabel=includeLabel)
             return
diff --git a/src/orca/scripts/apps/gedit/script.py b/src/orca/scripts/apps/gedit/script.py
index f83f29cf9..94237d6d4 100644
--- a/src/orca/scripts/apps/gedit/script.py
+++ b/src/orca/scripts/apps/gedit/script.py
@@ -67,6 +67,7 @@ class Script(gtk.Script):
 
         if self.spellcheck.isSuggestionsItem(newFocus):
             includeLabel = not self.spellcheck.isSuggestionsItem(oldFocus)
+            orca.emitRegionChanged(newFocus)
             self.updateBraille(newFocus)
             self.spellcheck.presentSuggestionListItem(includeLabel=includeLabel)
             return
diff --git a/src/orca/scripts/apps/soffice/script.py b/src/orca/scripts/apps/soffice/script.py
index c156d28fd..a2e4c607c 100644
--- a/src/orca/scripts/apps/soffice/script.py
+++ b/src/orca/scripts/apps/soffice/script.py
@@ -510,6 +510,7 @@ class Script(default.Script):
 
         if self.spellcheck.isSuggestionsItem(newLocusOfFocus) \
            and not self.spellcheck.isSuggestionsItem(oldLocusOfFocus):
+            orca.emitRegionChanged(newFocus)
             self.updateBraille(newLocusOfFocus)
             self.spellcheck.presentSuggestionListItem(includeLabel=True)
             return
diff --git a/src/orca/scripts/default.py b/src/orca/scripts/default.py
index e114f557e..196d47639 100644
--- a/src/orca/scripts/default.py
+++ b/src/orca/scripts/default.py
@@ -845,6 +845,7 @@ class Script(script.Script):
             priorObj=oldLocusOfFocus)
 
         speech.speak(utterances, interrupt=not shouldNotInterrupt)
+        orca.emitRegionChanged(newLocusOfFocus)
         self._saveFocusedObjectInfo(newLocusOfFocus)
 
     def activate(self):
@@ -3081,8 +3082,11 @@ class Script(script.Script):
             return
 
         if progressType == speechserver.SayAllContext.PROGRESS:
+            orca.emitRegionChanged(
+                context.obj, context.currentOffset, context.currentEndOffset, orca.SAY_ALL)
             return
-        elif progressType == speechserver.SayAllContext.INTERRUPTED:
+
+        if progressType == speechserver.SayAllContext.INTERRUPTED:
             if isinstance(orca_state.lastInputEvent, input_event.KeyboardEvent):
                 self._sayAllIsInterrupted = True
                 lastKey = orca_state.lastInputEvent.event_string
@@ -3093,9 +3097,11 @@ class Script(script.Script):
 
             self._inSayAll = False
             self._sayAllContexts = []
+            orca.emitRegionChanged(context.obj, context.currentOffset)
             text.setCaretOffset(context.currentOffset)
         elif progressType == speechserver.SayAllContext.COMPLETED:
             orca.setLocusOfFocus(None, context.obj, notifyScript=False)
+            orca.emitRegionChanged(context.obj, context.currentOffset, mode=orca.SAY_ALL)
             text.setCaretOffset(context.currentOffset)
 
         # If there is a selection, clear it. See bug #489504 for more details.
@@ -3286,8 +3292,9 @@ class Script(script.Script):
            and eventString in ["Right", "Down"]:
             offset -= 1
 
-        character, startOffset, endOffset = \
-            text.getTextAtOffset(offset, pyatspi.TEXT_BOUNDARY_CHAR)
+        character, startOffset, endOffset = text.getTextAtOffset(offset, pyatspi.TEXT_BOUNDARY_CHAR)
+        orca.emitRegionChanged(obj, startOffset, endOffset, orca.CARET_TRACKING)
+
         if not character or character == '\r':
             character = "\n"
 
@@ -3327,6 +3334,9 @@ class Script(script.Script):
             if result:
                 self.speakMessage(result)
 
+            endOffset = startOffset + len(line)
+            orca.emitRegionChanged(obj, startOffset, endOffset, orca.CARET_TRACKING)
+
             voice = self.speechGenerator.voice(string=line)
             line = self.utilities.adjustForLinks(obj, line, startOffset)
             line = self.utilities.adjustForRepeats(line)
@@ -3361,6 +3371,8 @@ class Script(script.Script):
             if result:
                 self.speakMessage(result)
 
+            orca.emitRegionChanged(obj, startOffset, endOffset, orca.CARET_TRACKING)
+
             voice = self.speechGenerator.voice(string=phrase)
             phrase = self.utilities.adjustForRepeats(phrase)
             if self.utilities.shouldVerbalizeAllPunctuation(obj):
@@ -3412,6 +3424,7 @@ class Script(script.Script):
             if lastChar == "\n" and lastWord != word:
                 self.speakCharacter("\n")
 
+        orca.emitRegionChanged(obj, startOffset, endOffset, orca.CARET_TRACKING)
 
         self.speakMisspelledIndicator(obj, startOffset)
         voice = self.speechGenerator.voice(string=word)
diff --git a/src/orca/scripts/toolkits/WebKitGtk/script.py b/src/orca/scripts/toolkits/WebKitGtk/script.py
index c91b3bf05..460e193a2 100644
--- a/src/orca/scripts/toolkits/WebKitGtk/script.py
+++ b/src/orca/scripts/toolkits/WebKitGtk/script.py
@@ -552,6 +552,8 @@ class Script(default.Script):
 
     def __sayAllProgressCallback(self, context, progressType):
         if progressType == speechserver.SayAllContext.PROGRESS:
+            orca.emitRegionChanged(
+                context.obj, context.currentOffset, context.currentEndOffset, orca.SAY_ALL)
             return
 
         obj = context.obj
@@ -573,6 +575,7 @@ class Script(default.Script):
             self._sayAllContexts = []
             if not self._lastCommandWasStructNav:
                 text.setCaretOffset(offset)
+            orca.emitRegionChanged(obj, offset)
             return
 
         # SayAllContext.COMPLETED doesn't necessarily mean done with SayAll;
@@ -589,6 +592,7 @@ class Script(default.Script):
             if [l for l in links if l.startIndex <= offset <= l.endIndex]:
                 return
 
+        orca.emitRegionChanged(obj, offset, mode=orca.SAY_ALL)
         text.setCaretOffset(offset)
 
     def getTextLineAtCaret(self, obj, offset=None, startOffset=None, endOffset=None):
diff --git a/src/orca/scripts/web/script.py b/src/orca/scripts/web/script.py
index 724d260b7..b53d3bbd1 100644
--- a/src/orca/scripts/web/script.py
+++ b/src/orca/scripts/web/script.py
@@ -752,6 +752,7 @@ class Script(default.Script):
                 elif lastKey == "Up" and self._rewindSayAll(context):
                     return
                 elif not self._lastCommandWasStructNav:
+                    orca.emitRegionChanged(obj, offset)
                     self.utilities.setCaretPosition(context.obj, context.currentOffset)
                     self.updateBraille(context.obj)
 
@@ -761,6 +762,8 @@ class Script(default.Script):
             return
 
         orca.setLocusOfFocus(None, context.obj, notifyScript=False)
+        orca.emitRegionChanged(
+            context.obj, context.currentOffset, context.currentEndOffset, orca.SAY_ALL)
         self.utilities.setCaretContext(context.obj, context.currentOffset)
 
     def inFocusMode(self):
@@ -1238,6 +1241,7 @@ class Script(default.Script):
 
         self.utilities.setCaretContext(newFocus, caretOffset)
         self.updateBraille(newFocus)
+        orca.emitRegionChanged(newFocus, caretOffset)
 
         if self.utilities.isContentEditableWithEmbeddedObjects(newFocus) \
            and not (newFocus.getRole() == pyatspi.ROLE_TABLE_CELL and newFocus.name):


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