Handle invalid keys coming from Qt
When pressing a key which doesn't exist as Qt.Key, we don't get Qt.Key_unknown like we'd expect, but we get 0x0 instead... Let's add that as a new "nil" key (to not conflict with None/unknown/zero/...) and handle it appropriately. This can be reproduced by doing: setxkbmap -layout us,gr -option grp:alt_shift_toggle and pressing Alt-Shift/Shift-Alt.
This commit is contained in:
parent
52c280ec12
commit
d1854eddaf
@ -145,7 +145,13 @@ class BaseKeyParser(QObject):
|
||||
self._count += txt
|
||||
return QKeySequence.ExactMatch
|
||||
|
||||
sequence = self._sequence.append_event(e)
|
||||
try:
|
||||
sequence = self._sequence.append_event(e)
|
||||
except keyutils.KeyParseError as e:
|
||||
self._debug_log("{} Aborting keychain.".format(e))
|
||||
self.clear_keystring()
|
||||
return QKeySequence.NoMatch
|
||||
|
||||
match, binding = self._match_key(sequence)
|
||||
if match == QKeySequence.NoMatch:
|
||||
mappings = config.val.bindings.key_mappings
|
||||
|
@ -39,7 +39,7 @@ _MODIFIER_MAP = {
|
||||
|
||||
|
||||
def is_printable(key):
|
||||
return key <= 0xff and key != Qt.Key_Space
|
||||
return key <= 0xff and key not in [Qt.Key_Space, 0x0]
|
||||
|
||||
|
||||
def is_modifier_key(key):
|
||||
@ -126,6 +126,7 @@ def _key_to_string(key):
|
||||
special_names[getattr(Qt, 'Key_' + k)] = v
|
||||
except AttributeError:
|
||||
pass
|
||||
special_names[0x0] = 'nil'
|
||||
|
||||
if key in special_names:
|
||||
return special_names[key]
|
||||
@ -231,7 +232,7 @@ class KeyInfo:
|
||||
modifiers &= ~_MODIFIER_MAP[self.key]
|
||||
elif is_printable(self.key):
|
||||
# "normal" binding
|
||||
if not key_string:
|
||||
if not key_string: # pragma: no cover
|
||||
raise ValueError("Got empty string for key 0x{:x}!"
|
||||
.format(self.key))
|
||||
|
||||
@ -371,6 +372,9 @@ class KeySequence:
|
||||
if info.key == Qt.Key_unknown:
|
||||
raise KeyParseError(keystr, "Got unknown key!")
|
||||
|
||||
for seq in self._sequences:
|
||||
assert seq
|
||||
|
||||
def matches(self, other):
|
||||
"""Check whether the given KeySequence matches with this one.
|
||||
|
||||
@ -428,6 +432,9 @@ class KeySequence:
|
||||
key = ev.key()
|
||||
modifiers = ev.modifiers()
|
||||
|
||||
if key == 0x0:
|
||||
raise KeyParseError(None, "Got nil key!")
|
||||
|
||||
if modifiers & Qt.ShiftModifier and key == Qt.Key_Backtab:
|
||||
key = Qt.Key_Tab
|
||||
|
||||
|
@ -48,7 +48,8 @@ class Key:
|
||||
qtest = attr.ib(True)
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
self.member = getattr(Qt, 'Key_' + self.attribute, None)
|
||||
if self.attribute:
|
||||
self.member = getattr(Qt, 'Key_' + self.attribute, None)
|
||||
if self.name is None:
|
||||
self.name = self.attribute
|
||||
|
||||
@ -585,4 +586,6 @@ KEYS = [
|
||||
Key('CameraFocus', 'Camera Focus', qtest=False),
|
||||
|
||||
Key('unknown', 'Unknown', qtest=False),
|
||||
# 0x0 is used by Qt for unknown keys...
|
||||
Key(attribute='', name='nil', member=0x0, qtest=False),
|
||||
]
|
||||
|
@ -182,6 +182,11 @@ class TestHandle:
|
||||
keyparser.handle(fake_keyevent(Qt.Key_1), dry_run=True)
|
||||
assert not keyparser._count
|
||||
|
||||
def test_invalid_key(self, fake_keyevent, keyparser):
|
||||
keyparser.handle(fake_keyevent(Qt.Key_B))
|
||||
keyparser.handle(fake_keyevent(0x0))
|
||||
assert not keyparser._sequence
|
||||
|
||||
def test_valid_keychain(self, handle_text, keyparser):
|
||||
# Press 'x' which is ignored because of no match
|
||||
handle_text(Qt.Key_X,
|
||||
|
@ -182,7 +182,8 @@ class TestKeySequence:
|
||||
with pytest.raises(keyutils.KeyParseError):
|
||||
keyutils.KeySequence(Qt.Key_unknown)
|
||||
|
||||
def test_init_invalid(self):
|
||||
@pytest.mark.parametrize('key', [0, -1])
|
||||
def test_init_invalid(self, key):
|
||||
with pytest.raises(AssertionError):
|
||||
keyutils.KeySequence(-1)
|
||||
|
||||
@ -343,6 +344,13 @@ class TestKeySequence:
|
||||
new = seq.append_event(event)
|
||||
assert new == keyutils.KeySequence.parse(expected)
|
||||
|
||||
@pytest.mark.parametrize('key', [Qt.Key_unknown, 0x0])
|
||||
def test_append_event_invalid(self, key):
|
||||
seq = keyutils.KeySequence()
|
||||
event = QKeyEvent(QKeyEvent.KeyPress, key, Qt.NoModifier, '')
|
||||
with pytest.raises(keyutils.KeyParseError):
|
||||
seq.append_event(event)
|
||||
|
||||
@pytest.mark.parametrize('keystr, expected', [
|
||||
('<Control-x>', keyutils.KeySequence(Qt.ControlModifier | Qt.Key_X)),
|
||||
('<Meta-x>', keyutils.KeySequence(Qt.MetaModifier | Qt.Key_X)),
|
||||
@ -405,6 +413,7 @@ def test_key_info_to_event():
|
||||
(Qt.Key_Enter, False),
|
||||
(Qt.Key_Space, False),
|
||||
(Qt.Key_X | Qt.ControlModifier, False), # Wrong usage
|
||||
(0x0, False), # Used by Qt for unknown keys
|
||||
|
||||
(Qt.Key_ydiaeresis, True),
|
||||
(Qt.Key_X, True),
|
||||
|
Loading…
Reference in New Issue
Block a user