Skip to content

Commit e3c1c5a

Browse files
authored
Merge be23e08 into 816496f
2 parents 816496f + be23e08 commit e3c1c5a

9 files changed

Lines changed: 227 additions & 37 deletions

File tree

source/config/configFlags.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,30 @@
1313

1414
from enum import unique
1515
from utils.displayString import DisplayStringIntEnum, DisplayStringStrEnum
16+
from keyLabels import localizedKeyLabels
17+
18+
19+
@unique
20+
class NVDAKey(DisplayStringIntEnum):
21+
"""Enumeration containing the possible config values for "Select NVDA Modifier Keys" option in keyboard
22+
settings.
23+
24+
Use NVDAKey.MEMBER.value to compare with the config;
25+
the config stores a bitwise combination of one or more of these values.
26+
use NVDAKey.MEMBER.displayString in the UI for a translatable description of this member.
27+
"""
28+
29+
CAPS_LOCK = 1
30+
NUMPAD_INSERT = 2
31+
EXTENDED_INSERT = 4
32+
33+
@property
34+
def _displayStringLabels(self):
35+
return {
36+
NVDAKey.CAPS_LOCK: localizedKeyLabels['capslock'],
37+
NVDAKey.NUMPAD_INSERT: localizedKeyLabels['numpadinsert'],
38+
NVDAKey.EXTENDED_INSERT: localizedKeyLabels['insert'],
39+
}
1640

1741

1842
@unique

source/config/configSpec.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: UTF-8 -*-
22
# A part of NonVisual Desktop Access (NVDA)
3-
# Copyright (C) 2006-2022 NV Access Limited, Babbage B.V., Davy Kager, Bill Dengler, Julien Cochuyt,
3+
# Copyright (C) 2006-2023 NV Access Limited, Babbage B.V., Davy Kager, Bill Dengler, Julien Cochuyt,
44
# Joseph Lee, Dawid Pieper, mltony, Bram Duvigneau, Cyrille Bougot, Rob Meredith
55
# This file is covered by the GNU General Public License.
66
# See the file COPYING for more details.
@@ -12,7 +12,7 @@
1212
#: provide an upgrade step (@see profileUpgradeSteps.py). An upgrade step does not need to be added when
1313
#: just adding a new element to (or removing from) the schema, only when old versions of the config
1414
#: (conforming to old schema versions) will not work correctly with the new schema.
15-
latestSchemaVersion = 9
15+
latestSchemaVersion = 10
1616

1717
#: The configuration specification string
1818
#: @type: String
@@ -151,9 +151,12 @@
151151
152152
#Keyboard settings
153153
[keyboard]
154-
useCapsLockAsNVDAModifierKey = boolean(default=false)
155-
useNumpadInsertAsNVDAModifierKey = boolean(default=true)
156-
useExtendedInsertAsNVDAModifierKey = boolean(default=true)
154+
# NVDAModifierKeys: Integer value combining single-bit value:
155+
# 1: CapsLock
156+
# 2: NumpadInsert
157+
# 4: ExtendedInsert
158+
# Default = 6: NumpadInsert + ExtendedInsert
159+
NVDAModifierKeys = integer(1, 7, default=6)
157160
keyboardLayout = string(default="desktop")
158161
speakTypedCharacters = boolean(default=true)
159162
speakTypedWords = boolean(default=false)

source/config/profileUpgradeSteps.py

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: UTF-8 -*-
22
# A part of NonVisual Desktop Access (NVDA)
3-
# Copyright (C) 2016-2022 NV Access Limited, Bill Dengler, Cyrille Bougot, Łukasz Golonka
3+
# Copyright (C) 2016-2023 NV Access Limited, Bill Dengler, Cyrille Bougot, Łukasz Golonka
44
# This file is covered by the GNU General Public License.
55
# See the file COPYING for more details.
66

@@ -16,6 +16,7 @@
1616

1717
from logHandler import log
1818
from config.configFlags import (
19+
NVDAKey,
1920
ShowMessages,
2021
TetherTo,
2122
ReportLineIndentation,
@@ -300,3 +301,56 @@ def _upgradeConfigFrom_8_to_9_tetherTo(profile: ConfigObj) -> None:
300301
profile["braille"]["tetherTo"] = TetherTo.AUTO.value
301302
else:
302303
profile["braille"]["tetherTo"] = tetherToVal
304+
305+
306+
def upgradeConfigFrom_9_to_10(profile: ConfigObj) -> None:
307+
"""In NVDA config, use only one value to store NVDA keys rather than 3 distinct values.
308+
"""
309+
310+
anySettingInConfig = False
311+
try:
312+
capsLock: str = profile['keyboard']['useCapsLockAsNVDAModifierKey']
313+
del profile['keyboard']['useCapsLockAsNVDAModifierKey']
314+
anySettingInConfig = True
315+
except KeyError:
316+
capsLock = False
317+
try:
318+
numpadInsert: str = profile['keyboard']['useNumpadInsertAsNVDAModifierKey']
319+
del profile['keyboard']['useNumpadInsertAsNVDAModifierKey']
320+
anySettingInConfig = True
321+
except KeyError:
322+
numpadInsert = True
323+
try:
324+
extendedInsert: str = profile['keyboard']['useExtendedInsertAsNVDAModifierKey']
325+
del profile['keyboard']['useExtendedInsertAsNVDAModifierKey']
326+
anySettingInConfig = True
327+
except KeyError:
328+
extendedInsert = True
329+
if anySettingInConfig:
330+
val = 0
331+
if configobj.validate.is_boolean(capsLock):
332+
val |= NVDAKey.CAPS_LOCK.value
333+
if configobj.validate.is_boolean(numpadInsert):
334+
val |= NVDAKey.NUMPAD_INSERT.value
335+
if configobj.validate.is_boolean(extendedInsert):
336+
val |= NVDAKey.EXTENDED_INSERT.value
337+
if val == 0:
338+
# val may be 0 if:
339+
# 1: The default profile has caps lock enabled and the currently upgraded profile has ext insert and
340+
# numpad insert disabled. In the current profile's config this leads to:
341+
# - useNumpadInsertAsNVDAModifierKey = False
342+
# - useExtendedInsertAsNVDAModifierKey = False
343+
# - useCapsLockAsNVDAModifierKey not present (True inherited from default config)
344+
# (see issue #14527 for full description)
345+
# or
346+
# 2: Someone did disabled all 3 possible NVDA key in config manually, e.g. modifying nvda.ini or via the
347+
# Python console.
348+
# Thus we consider case 1 which is the only use case reachable by the user via NVDA's GUI.
349+
log.debug(
350+
"No True value for any of 'use*AsNVDAModifierKey',"
351+
" restore caps lock (only possible case via NVDA's GUI)."
352+
)
353+
val = NVDAKey.CAPS_LOCK.value
354+
profile['keyboard']['NVDAModifierKeys'] = val
355+
else:
356+
log.debug("['use*AsNVDAModifierKey'] values not present, no action taken.")

source/gui/settingsDialogs.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: UTF-8 -*-
22
# A part of NonVisual Desktop Access (NVDA)
3-
# Copyright (C) 2006-2022 NV Access Limited, Peter Vágner, Aleksey Sadovoy,
3+
# Copyright (C) 2006-2023 NV Access Limited, Peter Vágner, Aleksey Sadovoy,
44
# Rui Batista, Joseph Lee, Heiko Folkerts, Zahari Yurukov, Leonard de Ruijter,
55
# Derek Riemer, Babbage B.V., Davy Kager, Ethan Holliger, Bill Dengler, Thomas Stivers,
66
# Julien Cochuyt, Peter Vágner, Cyrille Bougot, Mesar Hameed, Łukasz Golonka, Aaron Cannon,
@@ -26,6 +26,7 @@
2626
from synthDriverHandler import changeVoice, getSynth, getSynthList, setSynth, SynthDriver
2727
import config
2828
from config.configFlags import (
29+
NVDAKey,
2930
ShowMessages,
3031
TetherTo,
3132
ReportLineIndentation,
@@ -1683,16 +1684,12 @@ def makeSettings(self, settingsSizer):
16831684
#Translators: This is the label for a list of checkboxes
16841685
# controlling which keys are NVDA modifier keys.
16851686
modifierBoxLabel = _("&Select NVDA Modifier Keys")
1686-
self.modifierChoices = [keyLabels.localizedKeyLabels[key] for key in keyboardHandler.SUPPORTED_NVDA_MODIFIER_KEYS]
1687+
self.modifierChoices = [key.displayString for key in NVDAKey]
16871688
self.modifierList=sHelper.addLabeledControl(modifierBoxLabel, nvdaControls.CustomCheckListBox, choices=self.modifierChoices)
16881689
checkedItems = []
1689-
if config.conf["keyboard"]["useNumpadInsertAsNVDAModifierKey"]:
1690-
checkedItems.append(keyboardHandler.SUPPORTED_NVDA_MODIFIER_KEYS.index("numpadinsert"))
1691-
1692-
if config.conf["keyboard"]["useExtendedInsertAsNVDAModifierKey"]:
1693-
checkedItems.append(keyboardHandler.SUPPORTED_NVDA_MODIFIER_KEYS.index("insert"))
1694-
if config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"]:
1695-
checkedItems.append(keyboardHandler.SUPPORTED_NVDA_MODIFIER_KEYS.index("capslock"))
1690+
for (n, key) in enumerate(NVDAKey):
1691+
if config.conf["keyboard"]["NVDAModifierKeys"] & key.value:
1692+
checkedItems.append(n)
16961693
self.modifierList.CheckedItems = checkedItems
16971694
self.modifierList.Select(0)
16981695

@@ -1781,9 +1778,9 @@ def isValid(self):
17811778
def onSave(self):
17821779
layout=self.kbdNames[self.kbdList.GetSelection()]
17831780
config.conf['keyboard']['keyboardLayout']=layout
1784-
config.conf["keyboard"]["useNumpadInsertAsNVDAModifierKey"]= self.modifierList.IsChecked(keyboardHandler.SUPPORTED_NVDA_MODIFIER_KEYS.index("numpadinsert"))
1785-
config.conf["keyboard"]["useExtendedInsertAsNVDAModifierKey"] = self.modifierList.IsChecked(keyboardHandler.SUPPORTED_NVDA_MODIFIER_KEYS.index("insert"))
1786-
config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"] = self.modifierList.IsChecked(keyboardHandler.SUPPORTED_NVDA_MODIFIER_KEYS.index("capslock"))
1781+
config.conf["keyboard"]["NVDAModifierKeys"] = sum([
1782+
key.value for (n, key) in enumerate(NVDAKey) if self.modifierList.IsChecked(n)
1783+
])
17871784
config.conf["keyboard"]["speakTypedCharacters"]=self.charsCheckBox.IsChecked()
17881785
config.conf["keyboard"]["speakTypedWords"]=self.wordsCheckBox.IsChecked()
17891786
config.conf["keyboard"]["speechInterruptForCharacters"]=self.speechInterruptForCharsCheckBox.IsChecked()

source/gui/startupDialogs.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: UTF-8 -*-
22
# A part of NonVisual Desktop Access (NVDA)
3-
# Copyright (C) 2006-2021 NV Access Limited, Łukasz Golonka
3+
# Copyright (C) 2006-2023 NV Access Limited, Łukasz Golonka, Cyrille Bougot
44
# This file may be used under the terms of the GNU General Public License, version 2 or later.
55
# For more details see: https://www.gnu.org/licenses/gpl-2.0.html
66

@@ -9,6 +9,7 @@
99
import wx
1010

1111
import config
12+
from config.configFlags import NVDAKey
1213
import core
1314
from documentationUtils import getDocFilePath
1415
import globalVars
@@ -76,7 +77,7 @@ def __init__(self, parent):
7677
# Translators: The label of a checkbox in the Welcome dialog.
7778
capsAsNVDAModifierText = _("&Use CapsLock as an NVDA modifier key")
7879
self.capsAsNVDAModifierCheckBox = sHelper.addItem(wx.CheckBox(optionsBox, label=capsAsNVDAModifierText))
79-
self.capsAsNVDAModifierCheckBox.SetValue(config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"])
80+
self.capsAsNVDAModifierCheckBox.SetValue(config.conf["keyboard"]["NVDAModifierKeys"] & NVDAKey.CAPS_LOCK)
8081
# Translators: The label of a checkbox in the Welcome dialog.
8182
startAfterLogonText = _("St&art NVDA after I sign in")
8283
self.startAfterLogonCheckBox = sHelper.addItem(wx.CheckBox(optionsBox, label=startAfterLogonText))
@@ -104,7 +105,11 @@ def __init__(self, parent):
104105
def onOk(self, evt):
105106
layout = self.kbdNames[self.kbdList.GetSelection()]
106107
config.conf["keyboard"]["keyboardLayout"] = layout
107-
config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"] = self.capsAsNVDAModifierCheckBox.IsChecked()
108+
config.conf["keyboard"]["NVDAModifierKeys"] = (
109+
(NVDAKey.CAPS_LOCK.value if self.capsAsNVDAModifierCheckBox.IsChecked() else 0)
110+
| (config.conf["keyboard"]["NVDAModifierKeys"] & NVDAKey.NUMPAD_INSERT.value)
111+
| (config.conf["keyboard"]["NVDAModifierKeys"] & NVDAKey.EXTENDED_INSERT.value)
112+
)
108113
if self.startAfterLogonCheckBox.Enabled:
109114
config.setStartAfterLogon(self.startAfterLogonCheckBox.Value)
110115
config.conf["general"]["showWelcomeDialogAtStartup"] = self.showWelcomeDialogAtStartupCheckBox.IsChecked()

source/keyboardHandler.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# -*- coding: UTF-8 -*-
2-
#keyboardHandler.py
3-
#A part of NonVisual Desktop Access (NVDA)
4-
#This file is covered by the GNU General Public License.
5-
#See the file COPYING for more details.
6-
#Copyright (C) 2006-2017 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Babbage B.V.
2+
# keyboardHandler.py
3+
# A part of NonVisual Desktop Access (NVDA)
4+
# This file is covered by the GNU General Public License.
5+
# See the file COPYING for more details.
6+
# Copyright (C) 2006-2023 NV Access Limited, Peter Vágner, Aleksey Sadovoy, Babbage B.V., Cyrille Bougot
77

88
"""Keyboard support"""
99

@@ -12,6 +12,7 @@
1212
import time
1313
import re
1414
import typing
15+
from typing import Any
1516

1617
import wx
1718
import winVersion
@@ -24,11 +25,13 @@
2425
from logHandler import log
2526
import queueHandler
2627
import config
28+
from config.configFlags import NVDAKey
2729
import api
2830
import winInputHook
2931
import inputCore
3032
import tones
3133
import core
34+
import NVDAState
3235
from contextlib import contextmanager
3336
import threading
3437

@@ -84,11 +87,22 @@ def passNextKeyThrough():
8487
passKeyThroughCount=0
8588

8689
def isNVDAModifierKey(vkCode,extended):
87-
if config.conf["keyboard"]["useNumpadInsertAsNVDAModifierKey"] and vkCode==winUser.VK_INSERT and not extended:
90+
if (
91+
(config.conf["keyboard"]["NVDAModifierKeys"] & NVDAKey.NUMPAD_INSERT)
92+
and vkCode == winUser.VK_INSERT
93+
and not extended
94+
):
8895
return True
89-
elif config.conf["keyboard"]["useExtendedInsertAsNVDAModifierKey"] and vkCode==winUser.VK_INSERT and extended:
96+
elif (
97+
(config.conf["keyboard"]["NVDAModifierKeys"] & NVDAKey.EXTENDED_INSERT)
98+
and vkCode == winUser.VK_INSERT
99+
and extended
100+
):
90101
return True
91-
elif config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"] and vkCode==winUser.VK_CAPITAL:
102+
elif (
103+
(config.conf["keyboard"]["NVDAModifierKeys"] & NVDAKey.CAPS_LOCK)
104+
and vkCode == winUser.VK_CAPITAL
105+
):
92106
return True
93107
else:
94108
return False
@@ -97,11 +111,11 @@ def isNVDAModifierKey(vkCode,extended):
97111

98112
def getNVDAModifierKeys():
99113
keys=[]
100-
if config.conf["keyboard"]["useExtendedInsertAsNVDAModifierKey"]:
114+
if config.conf["keyboard"]["NVDAModifierKeys"] & NVDAKey.EXTENDED_INSERT:
101115
keys.append(vkCodes.byName["insert"])
102-
if config.conf["keyboard"]["useNumpadInsertAsNVDAModifierKey"]:
116+
if config.conf["keyboard"]["NVDAModifierKeys"] & NVDAKey.NUMPAD_INSERT:
103117
keys.append(vkCodes.byName["numpadinsert"])
104-
if config.conf["keyboard"]["useCapsLockAsNVDAModifierKey"]:
118+
if config.conf["keyboard"]["NVDAModifierKeys"] & NVDAKey.CAPS_LOCK:
105119
keys.append(vkCodes.byName["capslock"])
106120
return keys
107121

source/nvda.pyw

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# -*- coding: UTF-8 -*-
22
# A part of NonVisual Desktop Access (NVDA)
3-
# Copyright (C) 2006-2022 NV Access Limited, Aleksey Sadovoy, Babbage B.V., Joseph Lee, Łukasz Golonka,
3+
# Copyright (C) 2006-2023 NV Access Limited, Aleksey Sadovoy, Babbage B.V., Joseph Lee, Łukasz Golonka,
44
# Cyrille Bougot
55
# This file is covered by the GNU General Public License.
66
# See the file COPYING for more details.
@@ -15,11 +15,13 @@ import os
1515

1616
import typing
1717

18+
import builtins
1819
import globalVars
1920
import ctypes
2021
from ctypes import wintypes
2122
import monkeyPatches
2223
import NVDAState
24+
from languageHandler import makePgettext
2325

2426

2527
monkeyPatches.applyMonkeyPatches()
@@ -63,13 +65,16 @@ import locale
6365
import gettext
6466

6567
try:
66-
gettext.translation(
68+
trans = gettext.translation(
6769
'nvda',
6870
localedir=os.path.join(globalVars.appDir, 'locale'),
6971
languages=[locale.getdefaultlocale()[0]]
70-
).install(True)
72+
)
73+
trans.install(True)
7174
except:
7275
gettext.install('nvda')
76+
# Install our pgettext function.
77+
builtins.pgettext = makePgettext(trans)
7378

7479
import time
7580
import argparse

tests/unit/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# A part of NonVisual Desktop Access (NVDA)
33
# This file is covered by the GNU General Public License.
44
# See the file COPYING for more details.
5-
# Copyright (C) 2017-2019 NV Access Limited, Babbage B.V.
5+
# Copyright (C) 2017-2023 NV Access Limited, Babbage B.V., Cyrille Bougot
66

77
"""NVDA unit testing.
88
All unit tests should reside within this package and should be
@@ -19,10 +19,12 @@
1919

2020
import locale
2121
import gettext
22+
import builtins
2223
#Localization settings
2324
locale.setlocale(locale.LC_ALL,'')
2425
translations = gettext.NullTranslations()
2526
translations.install()
27+
builtins.pgettext = lambda context, message: message
2628

2729
# The path to the unit tests.
2830
UNIT_DIR = os.path.dirname(os.path.abspath(__file__))

0 commit comments

Comments
 (0)