[orca] Work on bgo#575784 - accented characters are not echoed correctly
- From: William Walker <wwalker src gnome org>
- To: svn-commits-list gnome org
- Subject: [orca] Work on bgo#575784 - accented characters are not echoed correctly
- Date: Mon, 27 Jul 2009 15:11:44 +0000 (UTC)
commit 6be078c9ad7889b4710a1f120f149d3cb44f0153
Author: Willie Walker <william walker sun com>
Date: Mon Jul 27 11:08:11 2009 -0400
Work on bgo#575784 - accented characters are not echoed correctly
There is one remaining issue with this, which is that gnome-terminal
does not do key echo. Instead, it will always do character echo if
either key echo or character echo are enabled.
src/orca/default.py | 33 +++++++++++++
src/orca/keynames.py | 72 ++++++++++++++++++++++------
src/orca/orca-setup.ui | 56 ++++++++++++++++++++++
src/orca/orca.py | 77 +++++++++++++++++++++++++------
src/orca/orca_gui_prefs.py | 28 +++++++++++
src/orca/scripts/apps/gnome-terminal.py | 16 ++++++-
src/orca/settings.py | 12 +++++
7 files changed, 263 insertions(+), 31 deletions(-)
---
diff --git a/src/orca/default.py b/src/orca/default.py
index e48f23c..34f5a43 100644
--- a/src/orca/default.py
+++ b/src/orca/default.py
@@ -3643,6 +3643,30 @@ class Script(script.Script):
else:
speech.speak(character, voice, False)
+ def willEchoCharacter(self, event):
+ """Given a keyboard event containing an alphanumeric key,
+ determine if the script is likely to echo it as a character.
+ """
+
+ # The check here in English is something like this: "If this
+ # character echo is enabled, then character echo is likely to
+ # happen if the locus of focus is a focusable editable text
+ # area or terminal and neither of the Ctrl, Alt, or Orca
+ # modifiers are pressed. If that's the case, then character
+ # echo will kick in for us."
+ #
+ return settings.enableEchoByCharacter \
+ and orca_state.locusOfFocus \
+ and (self.isTextArea(orca_state.locusOfFocus)\
+ or orca_state.locusOfFocus.getRole() \
+ == pyatspi.ROLE_ENTRY) \
+ and (orca_state.locusOfFocus.getRole() \
+ == pyatspi.ROLE_TERMINAL \
+ or (not self.isReadOnlyTextArea(orca_state.locusOfFocus) \
+ and (orca_state.locusOfFocus.getState().contains( \
+ pyatspi.STATE_FOCUSABLE)))) \
+ and not (event.modifiers & settings.ORCA_CTRL_MODIFIER_MASK)
+
def onTextInserted(self, event):
"""Called whenever text is inserted into an object.
@@ -3720,6 +3744,15 @@ class Script(script.Script):
orca_state.lastInputEvent.button == "2":
speakThis = True
+ # We might need to echo this if it is a single character.
+ #
+ speakThis = speakThis \
+ or (settings.enableEchoByCharacter \
+ and text \
+ and event.source.getRole() \
+ != pyatspi.ROLE_PASSWORD_TEXT \
+ and len(text.decode("UTF-8")) == 1)
+
if speakThis:
if text.isupper():
speech.speak(text, self.voices[settings.UPPERCASE_VOICE])
diff --git a/src/orca/keynames.py b/src/orca/keynames.py
index 289cb55..c1351e6 100644
--- a/src/orca/keynames.py
+++ b/src/orca/keynames.py
@@ -144,67 +144,67 @@ __keynames["Return"] = _("return")
#
__keynames["KP_Enter"] = _("enter")
-# Translators: this is how someone would speak the name of the up arrow key
+# Translators: this is how someone would speak the name of the up arrow key
#
__keynames["Up"] = _("up")
-# Translators: this is how someone would speak the name of the up arrow key
+# Translators: this is how someone would speak the name of the up arrow key
#
__keynames["KP_Up"] = _("up")
-# Translators: this is how someone would speak the name of the down arrow key
+# Translators: this is how someone would speak the name of the down arrow key
#
__keynames["Down"] = _("down")
-# Translators: this is how someone would speak the name of the down arrow key
+# Translators: this is how someone would speak the name of the down arrow key
#
__keynames["KP_Down"] = _("down")
-# Translators: this is how someone would speak the name of the left arrow key
+# Translators: this is how someone would speak the name of the left arrow key
#
__keynames["Left"] = _("left")
-# Translators: this is how someone would speak the name of the left arrow key
+# Translators: this is how someone would speak the name of the left arrow key
#
__keynames["KP_Left"] = _("left")
-# Translators: this is how someone would speak the name of the right arrow key
+# Translators: this is how someone would speak the name of the right arrow key
#
__keynames["Right"] = _("right")
-# Translators: this is how someone would speak the name of the right arrow key
+# Translators: this is how someone would speak the name of the right arrow key
#
__keynames["KP_Right"] = _("right")
-# Translators: this is how someone would speak the name of the left super key
+# Translators: this is how someone would speak the name of the left super key
#
__keynames["Super_L"] = _("left super")
-# Translators: this is how someone would speak the name of the right super key
+# Translators: this is how someone would speak the name of the right super key
#
__keynames["Super_R"] = _("right super")
-# Translators: this is how someone would speak the name of the menu key
+# Translators: this is how someone would speak the name of the menu key
#
__keynames["Menu"] = _("menu")
-# Translators: this is how someone would speak the name of the ISO shift key
+# Translators: this is how someone would speak the name of the ISO shift key
#
__keynames["ISO_Level3_Shift"] = _("ISO level 3 shift")
-# Translators: this is how someone would speak the name of the help key
+# Translators: this is how someone would speak the name of the help key
#
__keynames["Help"] = _("help")
-# Translators: this is how someone would speak the name of the multi key
+# Translators: this is how someone would speak the name of the multi key
#
__keynames["Multi_key"] = _("multi")
-# Translators: this is how someone would speak the name of the mode switch key
+# Translators: this is how someone would speak the name of the mode switch key
#
__keynames["Mode_switch"] = _("mode switch")
-# Translators: this is how someone would speak the name of the escape key
+# Translators: this is how someone would speak the name of the escape key
#
__keynames["Escape"] = _("escape")
@@ -244,6 +244,46 @@ __keynames["KP_End"] = _("end")
#
__keynames["KP_Begin"] = _("begin")
+# Translators: this is how someone would speak the name of the
+# non-spacing diacritical key for the grave glyph
+#
+__keynames["dead_grave"] = _("grave")
+
+# Translators: this is how someone would speak the name of the
+# non-spacing diacritical key for the acute glyph
+#
+__keynames["dead_acute"] = _("acute")
+
+# Translators: this is how someone would speak the name of the
+# non-spacing diacritical key for the circumflex glyph
+#
+__keynames["dead_circumflex"] = _("circumflex")
+
+# Translators: this is how someone would speak the name of the
+# non-spacing diacritical key for the tilde glyph
+#
+__keynames["dead_tilde"] = _("tilde")
+
+# Translators: this is how someone would speak the name of the
+# non-spacing diacritical key for the diaeresis glyph
+#
+__keynames["dead_diaeresis"] = _("diaeresis")
+
+# Translators: this is how someone would speak the name of the
+# non-spacing diacritical key for the ring glyph
+#
+__keynames["dead_abovering"] = _("ring")
+
+# Translators: this is how someone would speak the name of the
+# non-spacing diacritical key for the cedilla glyph
+#
+__keynames["dead_cedilla"] = _("cedilla")
+
+# Translators: this is how someone would speak the name of the
+# non-spacing diacritical key for the stroke glyph
+#
+__keynames["dead_stroke"] = _("stroke")
+
def getKeyName(key):
"""Given a keyboard key, return its name as people might refer to it
in ordinary conversation.
diff --git a/src/orca/orca-setup.ui b/src/orca/orca-setup.ui
index 4345764..74a7986 100644
--- a/src/orca/orca-setup.ui
+++ b/src/orca/orca-setup.ui
@@ -2546,6 +2546,38 @@
</packing>
</child>
<child>
+ <object class="GtkAlignment" id="alignment59">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+ <child>
+ <object class="GtkCheckButton" id="diacriticalCheckbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Enable non-spacing _diacritical keys</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="diacriticalKeysChecked" last_modification_time="Tue, 30 Oct 2007 20:11:26 GMT" name="toggled"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkAlignment" id="alignment49">
<property name="visible">True</property>
<property name="xalign">0.5</property>
@@ -2557,6 +2589,30 @@
<property name="left_padding">0</property>
<property name="right_padding">0</property>
<child>
+ <object class="GtkCheckButton" id="echoByCharacterCheckbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Enable echo by cha_racter</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal handler="echoByCharacterChecked" last_modification_time="Thu, 20 Apr 2006 15:29:51 GMT" name="toggled"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkAlignment" id="alignment49">
+ <property name="visible">True</property>
+ <child>
<object class="GtkCheckButton" id="echoByWordCheckbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
diff --git a/src/orca/orca.py b/src/orca/orca.py
index 8106e5f..8324d1c 100644
--- a/src/orca/orca.py
+++ b/src/orca/orca.py
@@ -489,6 +489,22 @@ def isNavigationKey(event_string):
"orca.isNavigationKey: returning: %s" % reply)
return reply
+def isDiacriticalKey(event_string):
+ """Return an indication of whether this is a non-spacing diacritical key
+
+ Arguments:
+ - event: the event string
+ - modifiers: key modifiers state
+
+ Returns True if this is a non-spacing diacritical key
+ """
+
+ reply = event_string.startswith("dead_")
+
+ debug.println(debug.LEVEL_FINEST,
+ "orca.isDiacriticalKey: returning: %s" % reply)
+ return reply
+
class KeyEventType:
"""Definition of available key event types."""
@@ -516,6 +532,9 @@ class KeyEventType:
# A navigation key event.
NAVIGATION = 'NAVIGATION'
+ # A diacritical key event.
+ DIACRITICAL = 'DIACRITICAL'
+
def __init__(self):
pass
@@ -536,7 +555,7 @@ def keyEcho(event):
#
if orca_state.locusOfFocus \
and (orca_state.locusOfFocus.getRole() == pyatspi.ROLE_PASSWORD_TEXT):
- return
+ return False
event_string = event.event_string
debug.println(debug.LEVEL_FINEST,
@@ -550,22 +569,28 @@ def keyEcho(event):
if isModifierKey(event_string):
if not settings.enableModifierKeys:
- return
+ return False
eventType = KeyEventType.MODIFIER
elif isNavigationKey(event_string):
if not settings.enableNavigationKeys:
- return
+ return False
eventType = KeyEventType.NAVIGATION
+ elif isDiacriticalKey(event_string):
+ if not settings.enableDiacriticalKeys:
+ return False
+ eventType = KeyEventType.DIACRITICAL
+
elif isPrintableKey(event_string):
- if not settings.enablePrintableKeys:
- return
+ if not (settings.enablePrintableKeys \
+ or settings.enableEchoByCharacter):
+ return False
eventType = KeyEventType.PRINTABLE
elif isLockingKey(event_string):
if not settings.enableLockingKeys:
- return
+ return False
eventType = KeyEventType.LOCKING
modifiers = event.modifiers
@@ -590,28 +615,49 @@ def keyEcho(event):
elif isFunctionKey(event_string):
if not settings.enableFunctionKeys:
- return
+ return False
eventType = KeyEventType.FUNCTION
elif isActionKey(event_string):
if not settings.enableActionKeys:
- return
+ return False
eventType = KeyEventType.ACTION
else:
debug.println(debug.LEVEL_FINEST,
"orca.keyEcho: event string not handled: %s" % event_string)
- return
-
- debug.println(debug.LEVEL_FINEST,
- "orca.keyEcho: speaking: %s" % event_string)
+ return False
# We keep track of the time as means to let others know that
# we are probably echoing a key and should not be interrupted.
#
orca_state.lastKeyEchoTime = time.time()
- speech.speakKeyEvent(event_string, eventType)
+ # Before we echo printable keys, let's try to make sure the
+ # character echo isn't going to also echo something.
+ #
+ characterEcho = \
+ eventType == KeyEventType.PRINTABLE \
+ and not _orcaModifierPressed \
+ and orca_state.activeScript \
+ and orca_state.activeScript.willEchoCharacter(event)
+
+ # One last check for echoing -- a PRINTABLE key may have squeaked
+ # through due to the enableEchoByCharacter check above. We only
+ # want to echo PRINTABLE keys if enablePrintableKeys is True.
+ #
+ if not (characterEcho or
+ (eventType == KeyEventType.PRINTABLE \
+ and not settings.enablePrintableKeys)):
+ debug.println(debug.LEVEL_FINEST,
+ "orca.keyEcho: speaking: %s" % event_string)
+ speech.speakKeyEvent(event_string, eventType)
+ return True
+ elif characterEcho:
+ debug.println(debug.LEVEL_FINEST,
+ "orca.keyEcho: letting character echo handle: %s" \
+ % event_string)
+ return False
def _setClickCount(inputEvent):
"""Sets the count of the number of clicks a user has made to one
@@ -762,7 +808,10 @@ def _processKeyboardEvent(event):
#
if not settings.learnModeEnabled and \
orca_state.activeScript.echoKey(keyboardEvent):
- keyEcho(keyboardEvent)
+ try:
+ keyEcho(keyboardEvent)
+ except:
+ debug.printException(debug.LEVEL_SEVERE)
elif isOrcaModifier \
and (keyboardEvent.type == pyatspi.KEY_RELEASED_EVENT):
diff --git a/src/orca/orca_gui_prefs.py b/src/orca/orca_gui_prefs.py
index 40b53b1..3ca8f57 100644
--- a/src/orca/orca_gui_prefs.py
+++ b/src/orca/orca_gui_prefs.py
@@ -1626,6 +1626,10 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
prefs["enableActionKeys"])
self.get_widget("navigationCheckbutton").set_active( \
prefs["enableNavigationKeys"])
+ self.get_widget("diacriticalCheckbutton").set_active( \
+ prefs["enableDiacriticalKeys"])
+ self.get_widget("echoByCharacterCheckbutton").set_active( \
+ prefs["enableEchoByCharacter"])
self.get_widget("echoByWordCheckbutton").set_active( \
prefs["enableEchoByWord"])
self.get_widget("echoBySentenceCheckbutton").set_active( \
@@ -2073,6 +2077,7 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
self.get_widget("functionCheckbutton").set_sensitive(enable)
self.get_widget("actionCheckbutton").set_sensitive(enable)
self.get_widget("navigationCheckbutton").set_sensitive(enable)
+ self.get_widget("diacriticalCheckbutton").set_sensitive(enable)
def _say(self, text, stop=False):
"""If the text field is not None, speaks the given text, optionally
@@ -2701,6 +2706,29 @@ class OrcaSetupGUI(orca_gtkbuilder.GtkBuilderWrapper):
"""
self.prefsDict["enableNavigationKeys"] = widget.get_active()
+ def diacriticalKeysChecked(self, widget):
+ """Signal handler for the "toggled" signal for the
+ diacriticalCheckbutton GtkCheckButton widget. The user has
+ [un]checked the 'Enable diacritical keys' checkbox. Set the
+ 'enableDiacriticalKeys' preference to the new value.
+
+ Arguments:
+ - widget: the component that generated the signal.
+ """
+ self.prefsDict["enableDiacriticalKeys"] = widget.get_active()
+
+ def echoByCharacterChecked(self, widget):
+ """Signal handler for the "toggled" signal for the
+ echoByCharacterCheckbutton GtkCheckButton widget. The user has
+ [un]checked the 'Enable Echo by Character' checkbox. Set the
+ 'enableEchoByCharacter' preference to the new value.
+
+ Arguments:
+ - widget: the component that generated the signal.
+ """
+
+ self.prefsDict["enableEchoByCharacter"] = widget.get_active()
+
def echoByWordChecked(self, widget):
"""Signal handler for the "toggled" signal for the
echoByWordCheckbutton GtkCheckButton widget. The user has
diff --git a/src/orca/scripts/apps/gnome-terminal.py b/src/orca/scripts/apps/gnome-terminal.py
index 655641f..05d398c 100644
--- a/src/orca/scripts/apps/gnome-terminal.py
+++ b/src/orca/scripts/apps/gnome-terminal.py
@@ -256,7 +256,21 @@ class Script(default.Script):
speakThis = True
if matchFound:
- orca.keyEcho(orca_state.lastInputEvent)
+ echoed = orca.keyEcho(orca_state.lastInputEvent)
+ else:
+ echoed = False
+
+ if not echoed:
+ # We might need to echo this if it is a single character.
+ #
+ speakThis = speakThis \
+ or ((settings.enableEchoByCharacter \
+ or (settings.enableKeyEcho \
+ and settings.enablePrintableKeys)) \
+ and text \
+ and event.source.getRole() \
+ != pyatspi.ROLE_PASSWORD_TEXT \
+ and len(text.decode("UTF-8")) == 1)
if speakThis:
if text.isupper():
diff --git a/src/orca/settings.py b/src/orca/settings.py
index 8738228..83a05b7 100644
--- a/src/orca/settings.py
+++ b/src/orca/settings.py
@@ -95,6 +95,7 @@ userCustomizableSettings = [
"speechVerbosityLevel",
"readTableCellRow",
"enableSpeechIndentation",
+ "enableEchoByCharacter",
"enableEchoByWord",
"enableEchoBySentence",
"enableKeyEcho",
@@ -104,6 +105,7 @@ userCustomizableSettings = [
"enableFunctionKeys",
"enableActionKeys",
"enableNavigationKeys",
+ "enableDiacriticalKeys",
"enablePauseBreaks",
"enableTutorialMessages",
"enableMnemonicSpeaking",
@@ -532,6 +534,12 @@ magSourceDisplay = ''
#
magTargetDisplay = ''
+# if True, enable character echo.
+# Note that it is allowable for both enableEchoByCharacter and enableKeyEcho
+# to be True
+#
+enableEchoByCharacter = False
+
# if True, enable word echo.
# Note that it is allowable for both enableEchoByWord and enableKeyEcho
# to be True
@@ -574,6 +582,10 @@ enableActionKeys = True
#
enableNavigationKeys = False
+# If True and key echo is enabled, echo Diacritical keys.
+#
+enableDiacriticalKeys = False
+
# If True, tutorial strings defined will be spoken.
#
enableTutorialMessages = False
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]