[orca] Create a dedicated object:state-changed callback for "showing" events
- From: Joanmarie Diggs <joanied src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [orca] Create a dedicated object:state-changed callback for "showing" events
- Date: Mon, 4 Nov 2013 23:19:24 +0000 (UTC)
commit f07b55ba4b323fa4ca6268d59a5a43873d2557f1
Author: Joanmarie Diggs <jdiggs igalia com>
Date: Mon Nov 4 18:18:55 2013 -0500
Create a dedicated object:state-changed callback for "showing" events
src/orca/scripts/apps/evince/script.py | 17 ++--
src/orca/scripts/apps/evolution/script.py | 62 ++++++-------
src/orca/scripts/apps/gnome-panel/script.py | 36 ++------
src/orca/scripts/apps/gnome-search-tool/script.py | 101 ++++-----------------
src/orca/scripts/apps/metacity/script.py | 29 +++----
src/orca/scripts/default.py | 54 ++++-------
src/orca/scripts/toolkits/CALLY/script.py | 33 +++++++
src/orca/scripts/toolkits/Gecko/script.py | 62 ++++++--------
8 files changed, 152 insertions(+), 242 deletions(-)
---
diff --git a/src/orca/scripts/apps/evince/script.py b/src/orca/scripts/apps/evince/script.py
index 73148c9..4e953d3 100644
--- a/src/orca/scripts/apps/evince/script.py
+++ b/src/orca/scripts/apps/evince/script.py
@@ -114,14 +114,15 @@ class Script(default.Script):
return True
- def onStateChanged(self, event):
- """Called whenever an object's state changes."""
-
- if event.type.startswith("object:state-changed:showing") \
- and event.source.getRole() == pyatspi.ROLE_ALERT and event.detail1:
- labels = self.utilities.unrelatedLabels(event.source)
+ def onShowingChanged(self, event):
+ """Callback for object:state-changed:showing accessibility events."""
+
+ obj = event.source
+ if obj.getRole() == pyatspi.ROLE_ALERT and event.detail1:
+ labels = self.utilities.unrelatedLabels(obj)
message = " ".join(map(self.utilities.displayedText, labels))
self.presentMessage(
message, voice=self.voices.get(settings.DEFAULT_VOICE))
-
- return default.Script.onStateChanged(self, event)
+ return
+
+ default.Script.onShowingChanged(self, event)
diff --git a/src/orca/scripts/apps/evolution/script.py b/src/orca/scripts/apps/evolution/script.py
index 54cf2c4..cbb8991 100644
--- a/src/orca/scripts/apps/evolution/script.py
+++ b/src/orca/scripts/apps/evolution/script.py
@@ -112,48 +112,42 @@ class Script(WebKitGtk.Script):
default.Script.onNameChanged(self, event)
- def onStateChanged(self, event):
- """Called whenever an object's state changes.
-
- Arguments:
- - event: the Event
- """
-
+ def onShowingChanged(self, event):
+ """Callback for object:state-changed:showing accessibility events."""
+
if not event.detail1:
- default.Script.onStateChanged(self, event)
+ default.Script.onShowingChanged(self, event)
return
- # Present text in the Account Assistant
- if event.type.startswith("object:state-changed:showing"):
- try:
- role = event.source.getRole()
- relationSet = event.source.getRelationSet()
- except:
- return
+ obj = event.source
- if role != pyatspi.ROLE_LABEL or relationSet:
- default.Script.onStateChanged(self, event)
- return
+ # Present text in the Account Assistant
+ try:
+ role = obj.getRole()
+ relationSet = obj.getRelationSet()
+ except:
+ return
- window = self.utilities.topLevelObject(event.source)
- focusedObj = self.utilities.focusedObject(window)
- if self.utilities.spatialComparison(event.source, focusedObj) >= 0:
- return
+ if role != pyatspi.ROLE_LABEL or relationSet:
+ default.Script.onShowingChanged(self, event)
+ return
- # TODO - JD: The very last screen results in a crazy-huge number
- # of events, and they come in an order that is not good for this
- # approach. So we'll need to handle this particular case elsewhere.
- if focusedObj.getRole() == pyatspi.ROLE_CHECK_BOX:
- labels = self.utilities.unrelatedLabels(window)
- if len(labels) > 15:
- return
-
- voice = self.voices.get(settings.DEFAULT_VOICE)
- text = self.utilities.displayedText(event.source)
- self.presentMessage(text, voice=voice)
+ window = self.utilities.topLevelObject(obj)
+ focusedObj = self.utilities.focusedObject(window)
+ if self.utilities.spatialComparison(obj, focusedObj) >= 0:
return
+
+ # TODO - JD: The very last screen results in a crazy-huge number
+ # of events, and they come in an order that is not good for this
+ # approach. So we'll need to handle this particular case elsewhere.
+ if focusedObj.getRole() == pyatspi.ROLE_CHECK_BOX:
+ labels = self.utilities.unrelatedLabels(window)
+ if len(labels) > 15:
+ return
- default.Script.onStateChanged(self, event)
+ voice = self.voices.get(settings.DEFAULT_VOICE)
+ text = self.utilities.displayedText(obj)
+ self.presentMessage(text, voice=voice)
def skipObjectEvent(self, event):
# NOTE: This is here temporarily as part of the preparation for the
diff --git a/src/orca/scripts/apps/gnome-panel/script.py b/src/orca/scripts/apps/gnome-panel/script.py
index 3179141..983275e 100644
--- a/src/orca/scripts/apps/gnome-panel/script.py
+++ b/src/orca/scripts/apps/gnome-panel/script.py
@@ -26,11 +26,9 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
__license__ = "LGPL"
-import orca.scripts.default as default
-import orca.debug as debug
-import orca.speech as speech
import pyatspi
+import orca.scripts.default as default
from .speech_generator import SpeechGenerator
########################################################################
@@ -48,18 +46,8 @@ class Script(default.Script):
- app: the application to create a script for.
"""
- # Set the debug level for all the methods in this script.
- #
- self.debugLevel = debug.LEVEL_FINEST
-
- self._debug("__init__")
default.Script.__init__(self, app)
- def _debug(self, msg):
- """ Convenience method for printing debug messages
- """
- debug.println(self.debugLevel, "gnome-panel.py: "+msg)
-
def getSpeechGenerator(self):
"""Returns the speech generator for this script."""
@@ -71,19 +59,8 @@ class Script(default.Script):
Arguments:
- event: the Event
"""
- obj = event.source
-
- self._debug("onStateChanged: '%s' %s (%d, %d)" % \
- (obj.name, event.type, event.detail1, event.detail2))
- # Handle tooltip popups.
- #
- if obj.getRole() == pyatspi.ROLE_TOOL_TIP:
- if event.type.startswith("object:state-changed:showing") and \
- event.detail1 == 1:
- self.displayBrailleMessage(obj.name)
- utterances = self.speechGenerator.generateSpeech(obj)
- speech.speak(utterances)
+ obj = event.source
# If focus moves to something within a panel and focus was not
# already in the containing panel, the panel will issue its
@@ -92,11 +69,10 @@ class Script(default.Script):
# plus the extraneous event results in unnecessary chattiness
# and updates the braille display to "panel."
#
- elif obj.getRole() == pyatspi.ROLE_PANEL and \
+ if obj.getRole() == pyatspi.ROLE_PANEL and \
event.type.startswith("object:state-changed:focused") and \
- event.detail1 == 1 and not \
- event.source.getState().contains(pyatspi.STATE_FOCUSED):
+ event.detail1 == 1 \
+ and not obj.getState().contains(pyatspi.STATE_FOCUSED):
return
- else:
- default.Script.onStateChanged(self, event)
+ default.Script.onStateChanged(self, event)
diff --git a/src/orca/scripts/apps/gnome-search-tool/script.py
b/src/orca/scripts/apps/gnome-search-tool/script.py
index ef2ef9d..5e92b0e 100644
--- a/src/orca/scripts/apps/gnome-search-tool/script.py
+++ b/src/orca/scripts/apps/gnome-search-tool/script.py
@@ -25,16 +25,15 @@ __date__ = "$Date$"
__copyright__ = "Copyright (c) 2005-2008 Sun Microsystems Inc."
__license__ = "LGPL"
-import orca.debug as debug
+import pyatspi
+import time
+from gi.repository import GLib
+
import orca.messages as messages
import orca.scripts.default as default
from orca.orca_i18n import _
-import pyatspi
-import time
-from gi.repository import GLib
-
########################################################################
# #
# The gnome-search-tool script class. #
@@ -51,26 +50,9 @@ class Script(default.Script):
"""
default.Script.__init__(self, app)
-
- # Set the debug level for all the methods in this script.
- #
- self.debugLevel = debug.LEVEL_FINEST
-
- # The table of files found.
- #
self.fileTable = None
-
- # Set to true if we are doing a search.
- #
self.searching = False
-
- # Time value using by the interval timer.
- #
self.startTime = None
-
- # Interval in seconds, between utterances of "Searching" when a
- # search is in progress.
- #
self.searchInterval = 5.0
def _speakSearching(self):
@@ -89,83 +71,40 @@ class Script(default.Script):
return True
- def onStateChanged(self, event):
- """Called whenever an object's state changes.
+ def onShowingChanged(self, event):
+ """Callback for object:state-changed:showing accessibility events."""
- Arguments:
- - event: the Event
- """
+ obj = event.source
+ if obj.getRole() != pyatspi.ROLE_PUSH_BUTTON \
+ or not obj.getState().contains(pyatspi.STATE_VISIBLE):
+ return default.Script.onShowingChanged(self, event)
- details = debug.getAccessibleDetails(self.debugLevel, event.source)
- debug.printObjectEvent(self.debugLevel, event, details)
-
- rolesList = [pyatspi.ROLE_PUSH_BUTTON, \
- pyatspi.ROLE_FILLER, \
- pyatspi.ROLE_FILLER, \
- pyatspi.ROLE_FILLER, \
- pyatspi.ROLE_FRAME, \
- pyatspi.ROLE_APPLICATION]
- visible = event.source.getState().contains(pyatspi.STATE_VISIBLE)
-
- # Check to see if we have just had an "object:state-changed:showing"
- # event for the Stop button. If the name is "Stop", and one of its
- # states is VISIBLE, that means we have started a search. As the
- # search progresses, regularly inform the user of this by speaking
- # "Searching" (assuming the search tool has focus).
- #
# Translators: the "Stop" string must match what gnome-search-tool
# is using. We hate keying off stuff like this, but we're forced
# to do so in this case.
- #
- if self.utilities.hasMatchingHierarchy(event.source, rolesList) and \
- event.source.name == _("Stop") and visible:
- debug.println(self.debugLevel,
- "gnome-search-tool.onNameChanged - " \
- + "search started.")
-
+ if obj.name == _("Stop"):
self.searching = True
-
- # If we don't already have a handle to the table containing the
- # list of files found, then get it now.
- #
if not self.fileTable:
- frame = self.utilities.topLevelObject(event.source)
+ frame = self.utilities.topLevelObject(obj)
allTables = self.utilities.descendantsWithRole(
frame, pyatspi.ROLE_TABLE)
self.fileTable = allTables[0]
GLib.idle_add(self._speakSearching)
+ return
- # Check to see if we have just had an "object:state-changed:showing"
- # event for the Find button. If the name is "Find", and one of its
- # states is VISIBLE and we are currently searching, that means we
- # have just stopped a search. Inform the user that the search is
- # complete and tell them how many files were found.
- #
# Translators: the "Find" string must match what gnome-search-tool
# is using. We hate keying off stuff like this, but we're forced
# to do so in this case.
- #
- if self.utilities.hasMatchingHierarchy(event.source, rolesList) \
- and event.source.name == _("Find") and visible and self.searching:
- debug.println(self.debugLevel,
- "gnome-search-tool.onNameChanged - " \
- + "search completed.")
-
+ if obj.name == _("Find") and self.searching:
self.searching = False
self.presentMessage(messages.SEARCH_COMPLETE)
- sensitive = self.fileTable.getState().contains( \
- pyatspi.STATE_SENSITIVE)
- if sensitive:
+ if self.fileTable.getState().contains(pyatspi.STATE_SENSITIVE):
try:
fileCount = self.fileTable.queryTable().nRows
+ self.presentMessage(messages.filesFound(fileCount))
except NotImplementedError:
- fileCount = 0
- noFilesString = messages.filesFound(fileCount)
- self.presentMessage(noFilesString)
- else:
- self.presentMessage(messages.FILES_NOT_FOUND)
-
- # Pass the event onto the parent class to be handled in the default way.
- #
- default.Script.onStateChanged(self, event)
+ self.presentMessage(messages.FILES_NOT_FOUND)
+ return
+
+ default.Script.onShowingChanged(self, event)
diff --git a/src/orca/scripts/apps/metacity/script.py b/src/orca/scripts/apps/metacity/script.py
index 171213c..1b26b71 100644
--- a/src/orca/scripts/apps/metacity/script.py
+++ b/src/orca/scripts/apps/metacity/script.py
@@ -124,26 +124,19 @@ class Script(default.Script):
if event.source.getRole() != pyatspi.ROLE_STATUS_BAR:
default.Script.onNameChanged(self, event)
- def onStateChanged(self, event):
- """The status bar in metacity tells us what toplevel window
- will be activated when tab is released. We will key off the
- text inserted event to determine when to say something, as it
- seems to be the more reliable event.
+ def onShowingChanged(self, event):
+ """Callback for object:state-changed:showing accessibility events."""
- Arguments:
- - event: the object:state-changed: Event
- """
+ obj = event.source
+ role = obj.getRole()
- # Ignore changes on the status bar. We handle them in
- # onTextInserted. The only exception is if the status bar is
- # suddenly showing. Then, we want to present it because we
- # typically do not get onTextInserted events at that time.
- #
- if event.source.getRole() != pyatspi.ROLE_STATUS_BAR:
- default.Script.onStateChanged(self, event)
- elif (event.type.startswith("object:state-changed:showing")) \
- and event.detail1:
- self.presentStatusBar(event.source)
+ # If the status bar is suddenly showing, we need to handle it here
+ # because we typically do not get onTextInserted events at that time.
+ if role == pyatspi.ROLE_STATUS_BAR and event.detail1:
+ self.presentStatusBar(obj)
+ return
+
+ default.Script.onShowingChanged(self, event)
def onTextInserted(self, event):
"""Called whenever text is inserted into an object. This seems to
diff --git a/src/orca/scripts/default.py b/src/orca/scripts/default.py
index 35e24e0..7f097f2 100644
--- a/src/orca/scripts/default.py
+++ b/src/orca/scripts/default.py
@@ -534,7 +534,7 @@ class Script(script.Script):
listeners["object:state-changed:focused"] = \
self.onStateChanged
listeners["object:state-changed:showing"] = \
- self.onStateChanged
+ self.onShowingChanged
listeners["object:state-changed:checked"] = \
self.onCheckedChanged
listeners["object:state-changed:pressed"] = \
@@ -2613,40 +2613,34 @@ class Script(script.Script):
# orca.setLocusOfFocus(event, None)
return
- # Handle tooltip popups.
- #
- if event.source.getRole() == pyatspi.ROLE_TOOL_TIP:
- if not event.type.startswith("object:state-changed:showing"):
- return
+ def onShowingChanged(self, event):
+ """Callback for object:state-changed:showing accessibility events."""
+
+ obj = event.source
+ role = obj.getRole()
+ if role == pyatspi.ROLE_NOTIFICATION:
+ speech.speak(self.speechGenerator.generateSpeech(obj))
+ labels = self.utilities.unrelatedLabels(obj)
+ msg = ''.join(map(self.utilities.displayedText, labels))
+ self.displayBrailleMessage(msg, flashTime=settings.brailleFlashTime)
+ notification_messages.saveMessage(msg)
+ return
+ if role == pyatspi.ROLE_TOOL_TIP:
keyString, mods = self.utilities.lastKeyAndModifiers()
if keyString != "F1" \
- and not _settingsManager.getSetting('presentToolTips'):
+ and not _settingsManager.getSetting('presentToolTips'):
return
-
- if event.detail1 == 1:
- self.presentToolTip(event.source)
+ if event.detail1:
+ self.presentToolTip(obj)
return
-
+
if orca_state.locusOfFocus and keyString == "F1":
obj = orca_state.locusOfFocus
self.updateBraille(obj)
- utterances = self.speechGenerator.generateSpeech(obj)
- utterances.extend(
- self.tutorialGenerator.getTutorial(obj, False))
- speech.speak(utterances)
+ speech.speak(self.speechGenerator.generateSpeech(obj))
return
- if event.source.getRole() in state_change_notifiers:
- notifiers = state_change_notifiers[event.source.getRole()]
- found = False
- for state in notifiers:
- if state and event.type.endswith(state):
- found = True
- break
- if found:
- self.visualAppearanceChanged(event, event.source)
-
def onTextAttributesChanged(self, event):
"""Called when an object's text attributes change. Right now this
method is only to handle the presentation of spelling errors on
@@ -5099,13 +5093,3 @@ class Script(script.Script):
message = time.strftime(dateFormat, time.localtime())
self.presentMessage(message)
return True
-
-# Dictionary that defines the state changes we care about for various
-# objects. The key represents the role and the value represents a list
-# of states that we care about.
-#
-state_change_notifiers = {}
-
-state_change_notifiers[pyatspi.ROLE_PANEL] = ("showing", None)
-state_change_notifiers[pyatspi.ROLE_LABEL] = ("showing", None)
-state_change_notifiers[pyatspi.ROLE_NOTIFICATION] = ("showing", None)
diff --git a/src/orca/scripts/toolkits/CALLY/script.py b/src/orca/scripts/toolkits/CALLY/script.py
index b1f71b4..409b8ee 100644
--- a/src/orca/scripts/toolkits/CALLY/script.py
+++ b/src/orca/scripts/toolkits/CALLY/script.py
@@ -258,6 +258,39 @@ class Script(default.Script):
default.Script.onNameChanged(self, event)
+ def onShowingChanged(self, event):
+ """Callback for object:state-changed:showing accessibility events."""
+
+ try:
+ role = event.source.getRole()
+ name = event.source.name
+ except:
+ return
+
+ # When entering overview with many open windows, we get quite
+ # a few state-changed:showing events for nameless panels. The
+ # act of processing these by the default script causes us to
+ # present nothing, and introduces a significant delay before
+ # presenting the Top Bar button when Ctrl+Alt+Tab was pressed.
+ if role == pyatspi.ROLE_PANEL and not name:
+ return
+
+ # We cannot count on events or their order from dialog boxes.
+ # Therefore, the only way to reliably present a dialog is by
+ # ignoring the events of the dialog itself and keeping track
+ # of the current dialog.
+ activeDialog, timestamp = self._activeDialog
+ if not event.detail1 and event.source == activeDialog:
+ self._activeDialog = (None, 0)
+ self._activeDialogLabels = {}
+ return
+
+ if activeDialog and role == pyatspi.ROLE_LABEL and event.detail1:
+ if self.presentDialogLabel(event):
+ return
+
+ default.Script.onShowingChanged(self, event)
+
def onStateChanged(self, event):
"""Called whenever an object's state changes.
diff --git a/src/orca/scripts/toolkits/Gecko/script.py b/src/orca/scripts/toolkits/Gecko/script.py
index ee9d4b2..72aaa51 100644
--- a/src/orca/scripts/toolkits/Gecko/script.py
+++ b/src/orca/scripts/toolkits/Gecko/script.py
@@ -441,12 +441,6 @@ class Script(default.Script):
self.onDocumentLoadComplete
listeners["document:load-stopped"] = \
self.onDocumentLoadStopped
- listeners["object:state-changed:showing"] = \
- self.onStateChanged
- listeners["object:children-changed"] = \
- self.onChildrenChanged
- listeners["object:text-changed:insert"] = \
- self.onTextInserted
listeners["object:state-changed:focused"] = \
self.onStateFocused
@@ -1429,40 +1423,36 @@ class Script(default.Script):
default.Script.onFocus(self, event)
- def onStateChanged(self, event):
- """Called whenever an object's state changes.
-
- Arguments:
- - event: the Event
- """
+ def onShowingChanged(self, event):
+ """Callback for object:state-changed:showing accessibility events."""
+
+ try:
+ eventRole = event.source.getRole()
+ focusedRole = orca_state.locusOfFocus.getRole()
+ except:
+ default.Script.onShowingChanged(self, event)
+ return
# If an autocomplete appears beneath an entry, we don't want
# to prevent the user from being able to arrow into it.
- #
- if event.type.startswith("object:state-changed:showing") \
- and event.source \
- and (event.source.getRole() == pyatspi.ROLE_WINDOW) \
- and orca_state.locusOfFocus:
- if orca_state.locusOfFocus.getRole() in [pyatspi.ROLE_ENTRY,
- pyatspi.ROLE_LIST_ITEM]:
- self._autocompleteVisible = event.detail1
- # If the autocomplete has just appeared, we want to speak
- # its appearance if the user's verbosity level is verbose
- # or if the user forced it to appear with (Alt+)Down Arrow.
- #
- if self._autocompleteVisible:
- level = _settingsManager.getSetting('speechVerbosityLevel')
- speakIt = level == settings.VERBOSITY_LEVEL_VERBOSE
- if not speakIt \
- and isinstance(orca_state.lastInputEvent,
- input_event.KeyboardEvent):
- keyEvent = orca_state.lastNonModifierKeyEvent
- speakIt = (keyEvent.event_string == ("Down"))
- if speakIt:
- speech.speak(self.speechGenerator.getLocalizedRoleName(\
- event.source, pyatspi.ROLE_AUTOCOMPLETE))
+ if eventRole == pyatspi.ROLE_WINDOW \
+ and focusedRole in [pyatspi.ROLE_ENTRY, pyatspi.ROLE_LIST_ITEM]:
+ self._autocompleteVisible = event.detail1
+ # If the autocomplete has just appeared, we want to speak
+ # its appearance if the user's verbosity level is verbose
+ # or if the user forced it to appear with (Alt+)Down Arrow.
+ if self._autocompleteVisible:
+ level = _settingsManager.getSetting('speechVerbosityLevel')
+ speakIt = level == settings.VERBOSITY_LEVEL_VERBOSE
+ if not speakIt:
+ eventString, mods = self.utilities.lastKeyAndModifiers()
+ speakIt = eventString == "Down"
+ if speakIt:
+ speech.speak(self.speechGenerator.getLocalizedRoleName(
+ event.source, pyatspi.ROLE_AUTOCOMPLETE))
+ return
- default.Script.onStateChanged(self, event)
+ default.Script.onShowingChanged(self, event)
def onStateFocused(self, event):
default.Script.onStateChanged(self, event)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]