Skip to content

Commit

Permalink
Merge 4721d55 into bdd3153
Browse files Browse the repository at this point in the history
  • Loading branch information
cary-rowen authored Dec 11, 2024
2 parents bdd3153 + 4721d55 commit 8a5bed9
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 4,918 deletions.
6 changes: 5 additions & 1 deletion source/NVDAObjects/behaviors.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import globalVars
from typing import List, Union
import diffHandler
from config.configFlags import TypingEcho


class ProgressBar(NVDAObject):
Expand Down Expand Up @@ -571,7 +572,10 @@ def event_typedCharacter(self, ch):
else:
self._hasTab = False
if (
(config.conf["keyboard"]["speakTypedCharacters"] or config.conf["keyboard"]["speakTypedWords"])
(
config.conf["keyboard"]["speakTypedCharacters"] > TypingEcho.OFF.value
or config.conf["keyboard"]["speakTypedWords"] > TypingEcho.OFF.value
)
and not config.conf["terminals"]["speakPasswords"]
and self._supportsTextChange
):
Expand Down
6 changes: 5 additions & 1 deletion source/NVDAObjects/inputComposition.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import eventHandler
import queueHandler
import controlTypes
from config.configFlags import TypingEcho
import characterProcessing
import speech
import config
Expand Down Expand Up @@ -73,7 +74,10 @@ def findOverlayClasses(self, clsList):
return clsList

def reportNewText(self, oldString, newString):
if config.conf["keyboard"]["speakTypedCharacters"] or config.conf["keyboard"]["speakTypedWords"]:
if (
config.conf["keyboard"]["speakTypedCharacters"] > TypingEcho.OFF.value
or config.conf["keyboard"]["speakTypedWords"] > TypingEcho.OFF.value
):
newText = calculateInsertedChars(oldString.strip("\u3000"), newString.strip("\u3000"))
if newText:
queueHandler.queueFunction(
Expand Down
24 changes: 24 additions & 0 deletions source/config/configFlags.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,30 @@ def _displayStringLabels(self):
}


@unique
class TypingEcho(DisplayStringIntEnum):
"""Enumeration containing the possible config values for typing echo (characters and words).
Use TypingEcho.MEMBER.value to compare with the config;
use TypingEcho.MEMBER.displayString in the UI for a translatable description of this member.
"""

OFF = 0
ON = 1
EDIT_CONTROLS = 2

@property
def _displayStringLabels(self):
return {
# Translators: One of the choices for typing echo in keyboard settings
TypingEcho.OFF: _("Off"),
# Translators: One of the choices for typing echo in keyboard settings
TypingEcho.ON: _("On"),
# Translators: One of the choices for typing echo in keyboard settings
TypingEcho.EDIT_CONTROLS: _("Only in edit controls"),
}


@unique
class ShowMessages(DisplayStringIntEnum):
"""Enumeration containing the possible config values for "Show messages" option in braille settings.
Expand Down
6 changes: 4 additions & 2 deletions source/config/configSpec.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,10 @@
# Default = 6: NumpadInsert + ExtendedInsert
NVDAModifierKeys = integer(1, 7, default=6)
keyboardLayout = string(default="desktop")
speakTypedCharacters = boolean(default=true)
speakTypedWords = boolean(default=false)
# 0: Off, 1: on, 2: Only in edit controls
speakTypedCharacters = integer(default=1,min=0,max=2)
# 0: Off, 1: on, 2: Only in edit controls
speakTypedWords = integer(default=1,min=0,max=2)
beepForLowercaseWithCapslock = boolean(default=true)
speakCommandKeys = boolean(default=false)
speechInterruptForCharacters = boolean(default=true)
Expand Down
31 changes: 13 additions & 18 deletions source/globalCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
ShowMessages,
BrailleMode,
OutputMode,
TypingEcho,
)
from config.featureFlag import FeatureFlag
from config.featureFlagEnums import BoolFlag
Expand Down Expand Up @@ -542,15 +543,12 @@ def script_previousSynthSetting(self, gesture):
gesture="kb:NVDA+2",
)
def script_toggleSpeakTypedCharacters(self, gesture):
if config.conf["keyboard"]["speakTypedCharacters"]:
# Translators: The message announced when toggling the speak typed characters keyboard setting.
state = _("speak typed characters off")
config.conf["keyboard"]["speakTypedCharacters"] = False
else:
# Translators: The message announced when toggling the speak typed characters keyboard setting.
state = _("speak typed characters on")
config.conf["keyboard"]["speakTypedCharacters"] = True
ui.message(state)
numVals = len(TypingEcho)
state = TypingEcho((config.conf["keyboard"]["speakTypedCharacters"] + 1) % numVals)
config.conf["keyboard"]["speakTypedCharacters"] = state.value
# Translators: Reported when the user cycles through speak typed characters modes.
# {mode} will be replaced with the mode; e.g. Off, On, Only in edit controls.
ui.message(_("Speak typed characters {mode}").format(mode=state.displayString))

@script(
# Translators: Input help mode message for toggle speak typed words command.
Expand All @@ -559,15 +557,12 @@ def script_toggleSpeakTypedCharacters(self, gesture):
gesture="kb:NVDA+3",
)
def script_toggleSpeakTypedWords(self, gesture):
if config.conf["keyboard"]["speakTypedWords"]:
# Translators: The message announced when toggling the speak typed words keyboard setting.
state = _("speak typed words off")
config.conf["keyboard"]["speakTypedWords"] = False
else:
# Translators: The message announced when toggling the speak typed words keyboard setting.
state = _("speak typed words on")
config.conf["keyboard"]["speakTypedWords"] = True
ui.message(state)
numVals = len(TypingEcho)
state = TypingEcho((config.conf["keyboard"]["speakTypedWords"] + 1) % numVals)
config.conf["keyboard"]["speakTypedWords"] = state.value
# Translators: Reported when the user cycles through speak typed words modes.
# {mode} will be replaced with the mode; e.g. Off, On, Only in edit controls.
ui.message(_("Speak typed words {mode}").format(mode=state.displayString))

@script(
# Translators: Input help mode message for toggle speak command keys command.
Expand Down
40 changes: 22 additions & 18 deletions source/gui/settingsDialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
ReportTableHeaders,
ReportCellBorders,
OutputMode,
TypingEcho,
)
import languageHandler
import speech
Expand Down Expand Up @@ -1981,24 +1982,27 @@ def makeSettings(self, settingsSizer):
checkedItems.append(n)
self.modifierList.CheckedItems = checkedItems
self.modifierList.Select(0)

self.bindHelpEvent("KeyboardSettingsModifiers", self.modifierList)
# Translators: This is the label for a checkbox in the
# keyboard settings panel.
charsText = _("Speak typed &characters")
self.charsCheckBox = sHelper.addItem(wx.CheckBox(self, label=charsText))
self.bindHelpEvent(
"KeyboardSettingsSpeakTypedCharacters",
self.charsCheckBox,
)
self.charsCheckBox.SetValue(config.conf["keyboard"]["speakTypedCharacters"])

# Translators: This is the label for a checkbox in the
# keyboard settings panel.
speakTypedWordsText = _("Speak typed &words")
self.wordsCheckBox = sHelper.addItem(wx.CheckBox(self, label=speakTypedWordsText))
self.bindHelpEvent("KeyboardSettingsSpeakTypedWords", self.wordsCheckBox)
self.wordsCheckBox.SetValue(config.conf["keyboard"]["speakTypedWords"])
# Translators: This is the label for a combobox in the keyboard settings panel.
charsLabelText = _("Speak typed &characters:")
charsChoices = [mode.displayString for mode in TypingEcho]
self.charsList = sHelper.addLabeledControl(charsLabelText, wx.Choice, choices=charsChoices)
self.bindHelpEvent("KeyboardSettingsSpeakTypedCharacters", self.charsList)
try:
self.charsList.SetSelection(config.conf["keyboard"]["speakTypedCharacters"])
except:
log.debugWarning("Could not set characters echo list to current setting", exc_info=True)

# Translators: This is the label for a combobox in the keyboard settings panel.
wordsLabelText = _("Speak typed &words:")
wordsChoices = [mode.displayString for mode in TypingEcho]
self.wordsList = sHelper.addLabeledControl(wordsLabelText, wx.Choice, choices=wordsChoices)
self.bindHelpEvent("KeyboardSettingsSpeakTypedWords", self.wordsList)
try:
self.wordsList.SetSelection(config.conf["keyboard"]["speakTypedWords"])
except:
log.debugWarning("Could not set words echo list to current setting", exc_info=True)

# Translators: This is the label for a checkbox in the
# keyboard settings panel.
Expand Down Expand Up @@ -2098,8 +2102,8 @@ def onSave(self):
config.conf["keyboard"]["NVDAModifierKeys"] = sum(
key.value for (n, key) in enumerate(NVDAKey) if self.modifierList.IsChecked(n)
)
config.conf["keyboard"]["speakTypedCharacters"] = self.charsCheckBox.IsChecked()
config.conf["keyboard"]["speakTypedWords"] = self.wordsCheckBox.IsChecked()
config.conf["keyboard"]["speakTypedCharacters"] = self.charsList.GetSelection()
config.conf["keyboard"]["speakTypedWords"] = self.wordsList.GetSelection()
config.conf["keyboard"]["speechInterruptForCharacters"] = (
self.speechInterruptForCharsCheckBox.IsChecked()
)
Expand Down
34 changes: 28 additions & 6 deletions source/speech/speech.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
ReportTableHeaders,
ReportCellBorders,
OutputMode,
TypingEcho,
)
import aria
from .priorities import Spri
Expand Down Expand Up @@ -780,8 +781,8 @@ def _getPlaceholderSpeechIfTextEmpty(
reason: OutputReason,
) -> Tuple[bool, SpeechSequence]:
"""Attempt to get speech for placeholder attribute if text for 'obj' is empty. Don't report the placeholder
value unless the text is empty, because it is confusing to hear the current value (presumably typed by the
user) *and* the placeholder. The placeholder should "disappear" once the user types a value.
value unless the text is empty, because it is confusing to hear the current value (presumably typed by the
user) *and* the placeholder. The placeholder should "disappear" once the user types a value.
@return: (True, SpeechSequence) if text for obj was considered empty and we attempted to get speech for the
placeholder value. (False, []) if text for obj was not considered empty.
"""
Expand Down Expand Up @@ -1355,6 +1356,14 @@ def _suppressSpeakTypedCharacters(number: int):
FIRST_NONCONTROL_CHAR = " "


def is_editableControl() -> bool:
obj = api.getFocusObject()
controls = {controlTypes.ROLE_EDITABLETEXT, controlTypes.ROLE_DOCUMENT, controlTypes.ROLE_TERMINAL}
return (
obj.role in controls or controlTypes.STATE_EDITABLE in obj.states
) and controlTypes.STATE_READONLY not in obj.states


def speakTypedCharacters(ch: str):
typingIsProtected = api.isTypingProtected()
if typingIsProtected:
Expand All @@ -1374,8 +1383,14 @@ def speakTypedCharacters(ch: str):
clearTypedWordBuffer()
if log.isEnabledFor(log.IO):
log.io("typed word: %s" % typedWord)
if config.conf["keyboard"]["speakTypedWords"] and not typingIsProtected:
speakText(typedWord)
typingEchoMode = config.conf["keyboard"]["speakTypedWords"]
if typingEchoMode > TypingEcho.OFF.value and not typingIsProtected:
if (
typingEchoMode == TypingEcho.EDIT_CONTROLS.value
and is_editableControl()
or typingEchoMode == TypingEcho.ON.value
):
speakText(typedWord)
if _speechState._suppressSpeakTypedCharactersNumber > 0:
# We primarily suppress based on character count and still have characters to suppress.
# However, we time out after a short while just in case.
Expand All @@ -1387,8 +1402,15 @@ def speakTypedCharacters(ch: str):
_speechState._suppressSpeakTypedCharactersTime = None
else:
suppress = False
if not suppress and config.conf["keyboard"]["speakTypedCharacters"] and ch >= FIRST_NONCONTROL_CHAR:
speakSpelling(realChar)

typingEchoMode = config.conf["keyboard"]["speakTypedCharacters"]
if not suppress and typingEchoMode > TypingEcho.OFF.value and ch >= FIRST_NONCONTROL_CHAR:
if (
typingEchoMode == TypingEcho.EDIT_CONTROLS.value
and is_editableControl()
or typingEchoMode == TypingEcho.ON.value
):
speakSpelling(realChar)


class SpeakTextInfoState(object):
Expand Down
Loading

0 comments on commit 8a5bed9

Please sign in to comment.