[orca] Implement ability to "rewind" and "fast forward" during SayAll



commit de7268eceaeb943d16a62e75eeb867be1378a09a
Author: Joanmarie Diggs <jdiggs igalia com>
Date:   Sun Jan 18 20:53:58 2015 -0500

    Implement ability to "rewind" and "fast forward" during SayAll
    
    Note: This feature is current disabled by default. To enable it,
    edit your orca-customizations.py file adding:
    
    import orca.settings
    orca.settings.rewindAndFastForwardInSayAll = True

 src/orca/scripts/default.py                   |   55 ++++++++++++++++++++++-
 src/orca/scripts/toolkits/Gecko/script.py     |   59 +++++++++++++++++++++++-
 src/orca/scripts/toolkits/WebKitGtk/script.py |   14 +++++-
 src/orca/settings.py                          |    4 ++
 4 files changed, 124 insertions(+), 8 deletions(-)
---
diff --git a/src/orca/scripts/default.py b/src/orca/scripts/default.py
index f51d741..e4cb0ff 100644
--- a/src/orca/scripts/default.py
+++ b/src/orca/scripts/default.py
@@ -139,6 +139,7 @@ class Script(script.Script):
         self._lastWordCheckedForSpelling = ""
 
         self._inSayAll = False
+        self._sayAllContexts = []
 
     def setupInputEventHandlers(self):
         """Defines InputEventHandler fields for this script that can be
@@ -3006,6 +3007,43 @@ class Script(script.Script):
             else:
                 self.sayCharacter(obj)
 
+    def _rewindSayAll(self, context, minCharCount=10):
+        if not _settingsManager.getSetting('rewindAndFastForwardInSayAll'):
+            return False
+
+        index = self._sayAllContexts.index(context)
+        self._sayAllContexts = self._sayAllContexts[0:index]
+        while self._sayAllContexts:
+            context = self._sayAllContexts.pop()
+            if context.endOffset - context.startOffset > minCharCount:
+                break
+
+        try:
+            text = context.obj.queryText()
+        except:
+            pass
+        else:
+            orca.setLocusOfFocus(None, context.obj, notifyScript=False)
+            text.setCaretOffset(context.startOffset)
+
+        self.sayAll(None, context.obj, context.startOffset)
+        return True
+
+    def _fastForwardSayAll(self, context):
+        if not _settingsManager.getSetting('rewindAndFastForwardInSayAll'):
+            return False
+
+        try:
+            text = context.obj.queryText()
+        except:
+            pass
+        else:
+            orca.setLocusOfFocus(None, context.obj, notifyScript=False)
+            text.setCaretOffset(context.endOffset)
+
+        self.sayAll(None, context.obj, context.endOffset)
+        return True
+
     def __sayAllProgressCallback(self, context, progressType):
         # [[[TODO: WDW - this needs work.  Need to be able to manage
         # the monitoring of progress and couple that with both updating
@@ -3026,7 +3064,15 @@ class Script(script.Script):
         if progressType == speechserver.SayAllContext.PROGRESS:
             return
         elif progressType == speechserver.SayAllContext.INTERRUPTED:
+            if isinstance(orca_state.lastInputEvent, input_event.KeyboardEvent):
+                lastKey = orca_state.lastInputEvent.event_string
+                if lastKey == "Down" and self._fastForwardSayAll(context):
+                    return
+                elif lastKey == "Up" and self._rewindSayAll(context):
+                    return
+
             self._inSayAll = False
+            self._sayAllContexts = []
             text.setCaretOffset(context.currentOffset)
         elif progressType == speechserver.SayAllContext.COMPLETED:
             orca.setLocusOfFocus(None, context.obj, notifyScript=False)
@@ -3819,6 +3865,7 @@ class Script(script.Script):
             text = obj.queryText()
         except:
             self._inSayAll = False
+            self._sayAllContexts = []
             return
 
         self._inSayAll = True
@@ -3887,9 +3934,10 @@ class Script(script.Script):
                 else:
                     voice = settings.voices[settings.DEFAULT_VOICE]
 
-                yield [speechserver.SayAllContext(obj, lineString,
-                                                  startOffset, endOffset),
-                       voice]
+                context = speechserver.SayAllContext(
+                    obj, lineString, startOffset, endOffset)
+                self._sayAllContexts.append(context)
+                yield [context, voice]
 
             moreLines = False
             relations = obj.getRelationSet()
@@ -3911,6 +3959,7 @@ class Script(script.Script):
                 done = True
 
         self._inSayAll = False
+        self._sayAllContexts = []
 
     def getTextLineAtCaret(self, obj, offset=None):
         """Gets the line of text where the caret is.
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index 43ec7c7..ed02c8d 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -236,6 +236,8 @@ class Script(default.Script):
         self._lastCommandWasStructNav = False
         self._lastCommandWasMouseButton = False
 
+        self._sayAllContents = []
+
         # See bug 665522 - comment 5
         app.setCacheMask(pyatspi.cache.DEFAULT ^ pyatspi.cache.CHILDREN)
 
@@ -735,6 +737,7 @@ class Script(default.Script):
                 contents = self.utilities.getSentenceContentsAtOffset(obj, characterOffset)
             else:
                 contents = self.getLineContentsAtOffset(obj, characterOffset)
+            self._sayAllContents = contents
             for content in contents:
                 obj, startOffset, endOffset, text = content
                 if self.utilities.isLabellingContents(content, contents) \
@@ -753,9 +756,10 @@ class Script(default.Script):
                     continue
 
                 for i, element in enumerate(elements):
-                    yield [speechserver.SayAllContext(obj, element,
-                                                      startOffset, endOffset),
-                           voices[i]]
+                    context = speechserver.SayAllContext(
+                        obj, element, startOffset, endOffset)
+                    self._sayAllContexts.append(context)
+                    yield [context, voices[i]]
 
             obj = contents[-1][0]
             characterOffset = contents[-1][2]
@@ -763,6 +767,8 @@ class Script(default.Script):
             done = (obj == None)
 
         self._inSayAll = False
+        self._sayAllContents = []
+        self._sayAllContexts = []
 
     def presentFindResults(self, obj, offset):
         """Updates the caret context to the match indicated by obj and
@@ -833,13 +839,52 @@ class Script(default.Script):
 
         return True
 
+    def _rewindSayAll(self, context, minCharCount=10):
+        if not self.inDocumentContent():
+            return default.Script._rewindSayAll(self, context, minCharCount)
+
+        if not _settingsManager.getSetting('rewindAndFastForwardInSayAll'):
+            return False
+
+        obj, start, end, string = self._sayAllContents[0]
+        orca.setLocusOfFocus(None, obj, notifyScript=False)
+        self.setCaretContext(obj, start)
+
+        prevObj, prevOffset = self.findPreviousCaretInOrder(obj, start)
+        self.sayAll(None, prevObj, prevOffset)
+        return True
+
+    def _fastForwardSayAll(self, context):
+        if not self.inDocumentContent():
+            return default.Script._fastForwardSayAll(self, context)
+
+        if not _settingsManager.getSetting('rewindAndFastForwardInSayAll'):
+            return False
+
+        obj, start, end, string = self._sayAllContents[-1]
+        orca.setLocusOfFocus(None, obj, notifyScript=False)
+        self.setCaretContext(obj, end)
+
+        nextObj, nextOffset = self.findNextCaretInOrder(obj, end)
+        self.sayAll(None, nextObj, nextOffset)
+        return True
+
     def __sayAllProgressCallback(self, context, progressType):
         if not self.inDocumentContent():
             default.Script.__sayAllProgressCallback(self, context, progressType)
             return
 
         if progressType == speechserver.SayAllContext.INTERRUPTED:
+            if isinstance(orca_state.lastInputEvent, input_event.KeyboardEvent):
+                lastKey = orca_state.lastInputEvent.event_string
+                if lastKey == "Down" and self._fastForwardSayAll(context):
+                    return
+                elif lastKey == "Up" and self._rewindSayAll(context):
+                    return
+
             self._inSayAll = False
+            self._sayAllContents = []
+            self._sayAllContexts = []
 
         orca.setLocusOfFocus(None, context.obj, notifyScript=False)
         self.setCaretContext(context.obj, context.currentOffset)
@@ -2555,6 +2600,10 @@ class Script(default.Script):
         Returns True if we actually moved.
         """
 
+        if self._inSayAll \
+           and _settingsManager.getSetting('rewindAndFastForwardInSayAll'):
+            return True
+
         [obj, characterOffset] = self.getCaretContext()
         thisLine = self.getLineContentsAtOffset(obj, characterOffset)
         if not (thisLine and thisLine[0]):
@@ -2585,6 +2634,10 @@ class Script(default.Script):
         Returns True if we actually moved.
         """
 
+        if self._inSayAll \
+           and _settingsManager.getSetting('rewindAndFastForwardInSayAll'):
+            return True
+
         [obj, characterOffset] = self.getCaretContext()
         thisLine = self.getLineContentsAtOffset(obj, characterOffset)
         if not (thisLine and thisLine[0]):
diff --git a/src/orca/scripts/toolkits/WebKitGtk/script.py b/src/orca/scripts/toolkits/WebKitGtk/script.py
index 31df702..4011933 100644
--- a/src/orca/scripts/toolkits/WebKitGtk/script.py
+++ b/src/orca/scripts/toolkits/WebKitGtk/script.py
@@ -600,12 +600,14 @@ class Script(default.Script):
                 textSegments.append([roleName, 0, -1, voice])
 
             for (string, start, end, voice) in textSegments:
-                yield [speechserver.SayAllContext(textObj, string, start, end),
-                       voice]
+                context = speechserver.SayAllContext(textObj, string, start, end)
+                self._sayAllContexts.append(context)
+                yield [context, voice]
 
             offset = 0
 
         self._inSayAll = False
+        self._sayAllContexts = []
 
     def __sayAllProgressCallback(self, context, progressType):
         if progressType == speechserver.SayAllContext.PROGRESS:
@@ -618,7 +620,15 @@ class Script(default.Script):
         text = obj.queryText()
 
         if progressType == speechserver.SayAllContext.INTERRUPTED:
+            if isinstance(orca_state.lastInputEvent, input_event.KeyboardEvent):
+                lastKey = orca_state.lastInputEvent.event_string
+                if lastKey == "Down" and self._fastForwardSayAll(context):
+                    return
+                elif lastKey == "Up" and self._rewindSayAll(context):
+                    return
+
             self._inSayAll = False
+            self._sayAllContexts = []
             text.setCaretOffset(offset)
             return
 
diff --git a/src/orca/settings.py b/src/orca/settings.py
index 33a0dc4..03f6015 100644
--- a/src/orca/settings.py
+++ b/src/orca/settings.py
@@ -364,3 +364,7 @@ structNavTriggersFocusMode = False
 caretNavTriggersFocusMode = False
 
 layoutMode = True
+
+# NOTE: The following are experimental and may be changed or removed at
+# any time
+rewindAndFastForwardInSayAll = False


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