Skip to content

Commit 4ca7f33

Browse files
authored
Merge d216153 into a73b481
2 parents a73b481 + d216153 commit 4ca7f33

6 files changed

Lines changed: 48 additions & 11 deletions

File tree

source/config/configSpec.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
allowSkimReadingInSayAll = boolean(default=False)
154154
alertForSpellingErrors = boolean(default=True)
155155
handleInjectedKeys= boolean(default=true)
156+
maxRepeatedKeyPressDelay = float(default=0.5, min=0.1, max=30.0)
156157
157158
[virtualBuffers]
158159
maxLineLength = integer(default=100)

source/gui/guiHelper.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,11 @@ def associateElements( firstElement, secondElement):
112112
""" Associates two GUI elements together. Handles choosing a layout and appropriate spacing. Abstracts away common
113113
pairings used in the NVDA GUI.
114114
Currently handles:
115-
wx.StaticText and (wx.Choice, wx.TextCtrl, wx.Slider or wx.Button) - Horizontal layout
116-
wx.StaticText and (wx.ListCtrl or wx.ListBox or wx.TreeCtrl ) - Vertical layout
117-
wx.Button and wx.CheckBox - Horizontal layout
118-
wx.TextCtrl and wx.Button - Horizontal layout
115+
wx.StaticText and (wx.Choice, wx.TextCtrl, wx.SpinCtrl, wx.SpinCtrlDouble, wx.Slider or wx.Button)
116+
-> Horizontal layout
117+
wx.StaticText and (wx.ListCtrl or wx.ListBox or wx.TreeCtrl ) -> Vertical layout
118+
wx.Button and wx.CheckBox -> Horizontal layout
119+
wx.TextCtrl and wx.Button -> Horizontal layout
119120
"""
120121
if isinstance(firstElement, ButtonHelper) or isinstance(secondElement, ButtonHelper):
121122
raise NotImplementedError("AssociateElements has no implementation for ButtonHelper elements")
@@ -125,7 +126,7 @@ def associateElements( firstElement, secondElement):
125126
# staticText and (choice, textCtrl or button)
126127
if isinstance(firstElement, wx.StaticText) and isinstance(secondElement, (
127128
wx.Choice, wx.TextCtrl,
128-
wx.SpinCtrl, wx.Button, wx.Slider
129+
wx.SpinCtrl, wx.SpinCtrlDouble, wx.Button, wx.Slider
129130
)):
130131
sizer = wx.BoxSizer(wx.HORIZONTAL)
131132
sizer.Add(firstElement, flag=wx.ALIGN_CENTER_VERTICAL)

source/gui/nvdaControls.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,22 +70,32 @@ def sendListItemFocusedEvent(self, index):
7070
evt.Index = index
7171
self.ProcessEvent(evt)
7272

73-
class SelectOnFocusSpinCtrl(wx.SpinCtrl):
73+
74+
class _SelectOnFocusControl(object):
7475
"""
75-
A spin control that automatically selects the value when the control gains focus.
76+
A control that automatically selects the value when the control gains focus.
7677
This makes editing the values quicker.
7778
"""
78-
def __init__(self, parent, id=wx.ID_ANY, value=wx.EmptyString, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.SP_ARROW_KEYS|wx.ALIGN_RIGHT, min=0, max=100, initial=0, name="labelStr"):
79+
def __init__(self, parent, **kwargs):
7980
""" initialiser - Takes the same parameters as a wx.SpinCtrl.
8081
"""
81-
wx.SpinCtrl.__init__(self, parent, id, value, pos, size, style, min, max, initial, name)
82+
super().__init__(parent, **kwargs)
8283
self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
8384

8485
def OnSetFocus(self, evt):
8586
numChars = len(str(self.GetValue()))
8687
self.SetSelection(0, numChars)
8788
evt.Skip()
8889

90+
91+
class SelectOnFocusSpinCtrl(_SelectOnFocusControl, wx.SpinCtrl):
92+
pass
93+
94+
95+
class SelectOnFocusSpinCtrlDouble(_SelectOnFocusControl, wx.SpinCtrlDouble):
96+
pass
97+
98+
8999
class AccPropertyOverride(accPropServer.IAccPropServer_Impl):
90100

91101
def __init__(self, control, propertyAnnotations):

source/gui/settingsDialogs.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,6 +1666,26 @@ def makeSettings(self, settingsSizer):
16661666
self.handleInjectedKeysCheckBox=sHelper.addItem(wx.CheckBox(self,label=handleInjectedKeysText))
16671667
self.bindHelpEvent("KeyboardSettingsHandleKeys", self.handleInjectedKeysCheckBox)
16681668
self.handleInjectedKeysCheckBox.SetValue(config.conf["keyboard"]["handleInjectedKeys"])
1669+
1670+
minDelay = float(config.conf.getConfigValidation(
1671+
("keyboard", "maxRepeatedKeyPressDelay")
1672+
).kwargs["min"])
1673+
maxDelay = float(config.conf.getConfigValidation(
1674+
("keyboard", "maxRepeatedKeyPressDelay")
1675+
).kwargs["max"])
1676+
# Translators: The label for a setting in keyboard settings to change maximum delay between two key press
1677+
# to be considered a double key press.
1678+
maxRepeatedDelayText = _("Maximum &delay between two key presses to be considered a repeated key press:")
1679+
self.maxRepeatedDelayEdit = sHelper.addLabeledControl(
1680+
maxRepeatedDelayText,
1681+
nvdaControls.SelectOnFocusSpinCtrlDouble,
1682+
min=minDelay,
1683+
max=maxDelay,
1684+
initial=config.conf["keyboard"]["maxRepeatedKeyPressDelay"],
1685+
inc=0.5,
1686+
)
1687+
self.maxRepeatedDelayEdit.SetDigits(1)
1688+
self.bindHelpEvent("MaxRepeatedKeyDelay", self.maxRepeatedDelayEdit)
16691689

16701690
def isValid(self):
16711691
# #2871: check whether at least one key is the nvda key.
@@ -1694,6 +1714,7 @@ def onSave(self):
16941714
config.conf["keyboard"]["speakCommandKeys"]=self.commandKeysCheckBox.IsChecked()
16951715
config.conf["keyboard"]["alertForSpellingErrors"]=self.alertForSpellingErrorsCheckBox.IsChecked()
16961716
config.conf["keyboard"]["handleInjectedKeys"]=self.handleInjectedKeysCheckBox.IsChecked()
1717+
config.conf["keyboard"]["maxRepeatedKeyPressDelay"] = self.maxRepeatedDelayEdit.GetValue()
16971718

16981719
class MouseSettingsPanel(SettingsPanel):
16991720
# Translators: This is the label for the mouse settings panel.

source/scriptHandler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ def executeScript(script,gesture):
199199
try:
200200
scriptTime=time.time()
201201
scriptRef=weakref.ref(scriptFunc)
202-
if (scriptTime-_lastScriptTime)<=0.5 and scriptFunc==lastScriptRef:
202+
if (scriptTime - _lastScriptTime) <= config.conf["keyboard"]["maxRepeatedKeyPressDelay"] and scriptFunc==lastScriptRef:
203203
_lastScriptCount+=1
204204
else:
205205
_lastScriptCount=0
@@ -219,7 +219,7 @@ def getLastScriptRepeatCount():
219219
@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.
220220
@rtype: integer
221221
"""
222-
if (time.time()-_lastScriptTime)>0.5:
222+
if (time.time() - _lastScriptTime) > config.conf["keyboard"]["maxRepeatedKeyPressDelay"]:
223223
return 0
224224
else:
225225
return _lastScriptCount

user_docs/en/userGuide.t2t

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,10 @@ This option is only available if reporting of spelling errors is enabled in NVDA
14941494
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.
14951495
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.
14961496

1497+
==== Maximum delay between two key presses to be considered a repeated key press ====[MaxRepeatedKeyDelay]
1498+
This option allows to control the maximum delay between two key presses to perform double or triple key presses.
1499+
Increasing this delay may be especially useful for people using sticky keys or having some physical disability.
1500+
14971501
+++ Mouse (NVDA+control+m) +++[MouseSettings]
14981502
The Mouse category in the NVDA Settings dialog allows NVDA to track the mouse, play mouse coordinate beeps and sets other mouse usage options.
14991503
This category contains the following options:

0 commit comments

Comments
 (0)