Skip to content
Merged
1 change: 1 addition & 0 deletions source/config/configSpec.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
allowSkimReadingInSayAll = boolean(default=False)
alertForSpellingErrors = boolean(default=True)
handleInjectedKeys= boolean(default=true)
multiPressTimeout = integer(default=500, min=100, max=20000)

[virtualBuffers]
maxLineLength = integer(default=100)
Expand Down
14 changes: 14 additions & 0 deletions source/gui/settingsDialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1977,6 +1977,19 @@ def makeSettings(self, settingsSizer):
self.bindHelpEvent("KeyboardSettingsHandleKeys", self.handleInjectedKeysCheckBox)
self.handleInjectedKeysCheckBox.SetValue(config.conf["keyboard"]["handleInjectedKeys"])

minTimeout = int(config.conf.getConfigValidation(("keyboard", "multiPressTimeout")).kwargs["min"])
maxTimeout = int(config.conf.getConfigValidation(("keyboard", "multiPressTimeout")).kwargs["max"])
# Translators: The label for a control in keyboard settings to modify the timeout for a multiple keypress.
multiPressTimeoutText = _("&Multiple key press timeout (ms):")
self.multiPressTimeoutEdit = sHelper.addLabeledControl(
multiPressTimeoutText,
nvdaControls.SelectOnFocusSpinCtrl,
min=minTimeout,
max=maxTimeout,
initial=config.conf["keyboard"]["multiPressTimeout"],
)
self.bindHelpEvent("MultiPressTimeout", self.multiPressTimeoutEdit)

def isValid(self) -> bool:
# #2871: check whether at least one key is the nvda key.
if not self.modifierList.CheckedItems:
Expand Down Expand Up @@ -2008,6 +2021,7 @@ def onSave(self):
config.conf["keyboard"]["speakCommandKeys"] = self.commandKeysCheckBox.IsChecked()
config.conf["keyboard"]["alertForSpellingErrors"] = self.alertForSpellingErrorsCheckBox.IsChecked()
config.conf["keyboard"]["handleInjectedKeys"] = self.handleInjectedKeysCheckBox.IsChecked()
config.conf["keyboard"]["multiPressTimeout"] = self.multiPressTimeoutEdit.GetValue()


class MouseSettingsPanel(SettingsPanel):
Expand Down
5 changes: 3 additions & 2 deletions source/scriptHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ def executeScript(script, gesture):
try:
scriptTime = time.time()
scriptRef = weakref.ref(scriptFunc)
if (scriptTime - _lastScriptTime) <= 0.5 and scriptFunc == lastScriptRef:
timeDiffMs = (scriptTime - _lastScriptTime) * 1000
if timeDiffMs <= config.conf["keyboard"]["multiPressTimeout"] and scriptFunc == lastScriptRef:
_lastScriptCount += 1
else:
_lastScriptCount = 0
Expand All @@ -311,7 +312,7 @@ def getLastScriptRepeatCount():
@returns: a value greater or equal to 0. If the script has not been repeated it is 0, if it has been repeated once its 1, and so forth.
@rtype: integer
"""
if (time.time() - _lastScriptTime) > 0.5:
if (time.time() - _lastScriptTime) * 1000 > config.conf["keyboard"]["multiPressTimeout"]:
return 0
else:
return _lastScriptCount
Expand Down
2 changes: 2 additions & 0 deletions user_docs/en/changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
The available options are:
* Liblouis (default): Uses formatting markers defined in the selected braille table.
* Tags: Uses start and end tags to denote where certain font attributes begin and end. (#16864)
* The timeout to perform a multiple keypress is now configurable; this may be especially useful for people with dexterity impairment. (#11929, @CyrilleB79)

### Bug Fixes

Expand Down Expand Up @@ -4999,3 +5000,4 @@ Major highlights of this release include support for 64 bit editions of Windows;
* NVDA now asks if it should save configuration and restart if the user has just changed the language in the User Interface Settings Dialog. NVDA must be restarted for the language change to fully take effect.
* If a synthesizer can not be loaded, when choosing it from the synthesizer dialog, a message box alerts the user to the fact.
* When loading a synthesizer for the first time, NVDA lets the synthesizer choose the most suitable voice, rate and pitch parameters, rather than forcing it to defaults it thinks are ok. This fixes a problem where Eloquence and Viavoice sapi4 synths start speaking way too fast for the first time.

10 changes: 10 additions & 0 deletions user_docs/en/userGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -2550,6 +2550,16 @@ This option is only available if reporting of spelling errors is enabled in NVDA
This option allows the user to control if key presses generated by applications such as on-screen keyboards and speech recognition software should be processed by NVDA.
This option is on by default, though certain users may wish to turn this off, such as those typing Vietnamese with the UniKey typing software as it will cause incorrect character input.

##### Multiple key press timeout {#MultiPressTimeout}

Some NVDA keyboard gestures perform different actions based upon how many times the same key is pressed in rapid succession.
An example of this is the "Report current character of navigator object" command.
This command reports the character if pressed once, a phonetic description of the character if pressed twice, and the numeric value of the character if pressed three times.
This option configures the timeout after which an additional press of the same key will start a new gesture, rather than being taken as a subsequent press of the first one.
For the example command, a too short timeout will cause two presses to report the current character twice, rather than the phonetic description.
The default timeout is 500 ms, i.e. half a second.
Increasing this timeout may be especially useful for people using sticky keys, or who have a physical disability.

#### Mouse {#MouseSettings}

<!-- KC:setting -->
Expand Down