[orca] Fix for bgo#576847 - Add ability to 'flash' braille messages



commit a7d9ec884bfb67c5fc074e0f0a880114fdf8803e
Author: Willie Walker <william walker sun com>
Date:   Fri Jul 31 17:07:02 2009 -0400

    Fix for bgo#576847 - Add ability to 'flash' braille messages

 src/orca/braille.py  |  108 ++++++++++++++++++++++++++++++++++++++++++++++---
 src/orca/default.py  |   10 ++++-
 src/orca/orca.py     |    3 +
 src/orca/settings.py |    4 ++
 4 files changed, 116 insertions(+), 9 deletions(-)
---
diff --git a/src/orca/braille.py b/src/orca/braille.py
index 77fb522..f069504 100644
--- a/src/orca/braille.py
+++ b/src/orca/braille.py
@@ -37,6 +37,9 @@ log = logging.getLogger("braille")
 import signal
 import os
 
+import gobject
+gobject.threads_init()
+
 try:
     import louis
 except ImportError:
@@ -44,8 +47,6 @@ except ImportError:
 
 try:
     import brlapi
-    import gobject
-    gobject.threads_init()
 
     _brlAPI = None
     _brlAPIAvailable = True
@@ -209,6 +210,14 @@ beginningIsShowing = False
 #
 cursorCell = 0
 
+# The event source of a timeout used for flashing a message.
+#
+_flashEventSourceId = 0
+
+# Line information saved prior to flashing any messages
+#
+_saved = None
+
 # Translators: These are the braille translation table names for different
 # languages. You could read about braille tables at:
 # http://en.wikipedia.org/wiki/Braille
@@ -1047,7 +1056,10 @@ def setFocus(region, panToFocus=True, getLinkMask=True):
 
     viewport[0] = max(0, offset)
 
-def refresh(panToCursor=True, targetCursorCell=0, getLinkMask=True):
+def refresh(panToCursor=True,
+            targetCursorCell=0,
+            getLinkMask=True,
+            stopFlash=True):
     """Repaints the Braille on the physical display.  This clips the entire
     logical structure by the viewport and also sets the cursor to the
     appropriate location.  [[[TODO: WDW - I'm not sure how BrlTTY handles
@@ -1068,6 +1080,7 @@ def refresh(panToCursor=True, targetCursorCell=0, getLinkMask=True):
       attributeMask for links. Reasons we might not want to include
       knowning that we will fail and/or it taking an unreasonable
       amount of time (AKA Gecko).
+    - stopFlash: if True, kill any flashed message that may be showing.
     """
 
     global endIsShowing
@@ -1075,6 +1088,9 @@ def refresh(panToCursor=True, targetCursorCell=0, getLinkMask=True):
     global cursorCell
     global _monitor
 
+    if stopFlash:
+        killFlash(restoreSaved=False)
+
     if len(_lines) == 0:
         if not _brlAPIRunning:
             init(_callback, settings.tty)
@@ -1200,7 +1216,67 @@ def refresh(panToCursor=True, targetCursorCell=0, getLinkMask=True):
     beginningIsShowing = startPos == 0
     endIsShowing = endPos >= len(string)
 
-def displayRegions(regionInfo):
+def _flashCallback():
+    global _lines
+    global _regionWithFocus
+    global viewport
+    global _flashEventSourceId
+
+    if _flashEventSourceId:
+        (_lines, _regionWithFocus, viewport, flashTime) = _saved
+        refresh(panToCursor=False, stopFlash=False)
+        _flashEventSourceId = 0
+
+    return False
+
+def killFlash(restoreSaved=True):
+    global _flashEventSourceId
+    global _lines
+    global _regionWithFocus
+    global viewport
+    if _flashEventSourceId:
+        if _flashEventSourceId > 0:
+            gobject.source_remove(_flashEventSourceId)
+        if restoreSaved:
+            (_lines, _regionWithFocus, viewport, flashTime) = _saved
+            refresh(panToCursor=False, stopFlash=False)
+        _flashEventSourceId = 0
+
+def resetFlashTimer():
+    global _flashEventSourceId
+    if _flashEventSourceId > 0:
+        gobject.source_remove(_flashEventSourceId)
+        flashTime = _saved[3]
+        _flashEventSourceId = gobject.timeout_add(flashTime, _flashCallback)
+
+def _initFlash(flashTime):
+    """Sets up the state needed to flash a message or clears any existing
+    flash if nothing is to be flashed.
+
+    Arguments:
+    - flashTime:  if non-0, the number of milliseconds to display the
+                  regions before reverting back to what was there before.
+                  A 0 means to not do any flashing.  A negative number
+                  means display the message until some other message
+                  comes along or the user presses a cursor routing key.
+    """
+
+    global _saved
+    global _flashEventSourceId
+
+    if _flashEventSourceId:
+        if _flashEventSourceId > 0:
+            gobject.source_remove(_flashEventSourceId)
+        _flashEventSourceId = 0
+    else:
+        _saved = (_lines, _regionWithFocus, viewport, flashTime)
+
+    if flashTime > 0:
+        _flashEventSourceId = gobject.timeout_add(flashTime, _flashCallback)
+    elif flashTime < 0:
+        _flashEventSourceId = -666
+
+def displayRegions(regionInfo, flashTime=0):
     """Displays a list of regions on a single line, setting focus to the
        specified region.  The regionInfo parameter is something that is
        typically returned by a call to braille_generator.generateBraille.
@@ -1209,8 +1285,14 @@ def displayRegions(regionInfo):
     - regionInfo: a list where the first element is a list of regions
                   to display and the second element is the region
                   with focus (must be in the list from element 0)
+    - flashTime:  if non-0, the number of milliseconds to display the
+                  regions before reverting back to what was there before.
+                  A 0 means to not do any flashing.  A negative number
+                  means display the message until some other message
+                  comes along or the user presses a cursor routing key.
     """
 
+    _initFlash(flashTime)
     regions = regionInfo[0]
     focusedRegion = regionInfo[1]
 
@@ -1220,22 +1302,28 @@ def displayRegions(regionInfo):
         line.addRegion(item)
     addLine(line)
     setFocus(focusedRegion)
-    refresh()
+    refresh(stopFlash=False)
 
-def displayMessage(message, cursor=-1):
+def displayMessage(message, cursor=-1, flashTime=0):
     """Displays a single line, setting the cursor to the given position,
     ensuring that the cursor is in view.
 
     Arguments:
     - message: the string to display
     - cursor: the 0-based cursor position, where -1 (default) means no cursor
+    - flashTime:  if non-0, the number of milliseconds to display the
+                  regions before reverting back to what was there before.
+                  A 0 means to not do any flashing.  A negative number
+                  means display the message until some other message
+                  comes along or the user presses a cursor routing key.
     """
 
+    _initFlash(flashTime)
     clear()
     region = Region(message, cursor)
     addLine(Line(region))
     setFocus(region)
-    refresh(True)
+    refresh(True, stopFlash=False)
 
 def panLeft(panAmount=0):
     """Pans the display to the left, limiting the pan to the beginning
@@ -1335,6 +1423,12 @@ def processRoutingKey(event):
     the dictionary form of the expanded BrlAPI event.
     """
 
+    # If a message is being flashed, we'll use a routing key to dismiss it.
+    #
+    if _flashEventSourceId:
+        killFlash()
+        return
+
     cell = event.event["argument"]
 
     if len(_lines) > 0:
diff --git a/src/orca/default.py b/src/orca/default.py
index c5ac2ce..a5903fb 100644
--- a/src/orca/default.py
+++ b/src/orca/default.py
@@ -5060,7 +5060,10 @@ class Script(script.Script):
                 self.reviewPreviousCharacter(inputEvent)
         else:
             braille.panLeft(panAmount)
-            braille.refresh(False)
+            # We might be panning through a flashed message.
+            #
+            braille.resetFlashTimer()
+            braille.refresh(False, stopFlash=False)
 
         return True
 
@@ -5118,7 +5121,10 @@ class Script(script.Script):
                 text.setCaretOffset(endOffset)
         else:
             braille.panRight(panAmount)
-            braille.refresh(False)
+            # We might be panning through a flashed message.
+            #
+            braille.resetFlashTimer()
+            braille.refresh(False, stopFlash=False)
 
         return True
 
diff --git a/src/orca/orca.py b/src/orca/orca.py
index 8324d1c..e8b299b 100644
--- a/src/orca/orca.py
+++ b/src/orca/orca.py
@@ -759,6 +759,9 @@ def _processKeyboardEvent(event):
 
     keyboardEvent = KeyboardEvent(event)
 
+    if keyboardEvent.type == pyatspi.KEY_PRESSED_EVENT:
+        braille.killFlash()
+
     # See if this is one of our special Orca modifier keys.
     #
     # Just looking at the keycode should suffice, but there is a
diff --git a/src/orca/settings.py b/src/orca/settings.py
index e9253d5..1672ee5 100644
--- a/src/orca/settings.py
+++ b/src/orca/settings.py
@@ -366,6 +366,10 @@ enableBrailleContext    = True
 #
 enableBrailleGrouping   = False
 
+# The timeout (in milliseconds) to use for messages flashed in braille.
+#
+brailleFlashTime        = 5000
+
 # If True, enable braille monitor.
 #
 enableBrailleMonitor    = False



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