diff options
Diffstat (limited to 'qutebrowser/keyinput/basekeyparser.py')
-rw-r--r-- | qutebrowser/keyinput/basekeyparser.py | 62 |
1 files changed, 34 insertions, 28 deletions
diff --git a/qutebrowser/keyinput/basekeyparser.py b/qutebrowser/keyinput/basekeyparser.py index 4db1d5d76..cdb3948b4 100644 --- a/qutebrowser/keyinput/basekeyparser.py +++ b/qutebrowser/keyinput/basekeyparser.py @@ -24,11 +24,11 @@ import types import dataclasses from typing import Mapping, MutableMapping, Optional, Sequence -from PyQt5.QtCore import pyqtSignal, QObject, Qt -from PyQt5.QtGui import QKeySequence, QKeyEvent +from qutebrowser.qt.core import QObject, pyqtSignal +from qutebrowser.qt.gui import QKeySequence, QKeyEvent from qutebrowser.config import config -from qutebrowser.utils import usertypes, log, utils +from qutebrowser.utils import log, usertypes, utils from qutebrowser.keyinput import keyutils @@ -42,7 +42,7 @@ class MatchResult: sequence: keyutils.KeySequence def __post_init__(self) -> None: - if self.match_type == QKeySequence.ExactMatch: + if self.match_type == QKeySequence.SequenceMatch.ExactMatch: assert self.command is not None else: assert self.command is None @@ -89,7 +89,7 @@ class BindingTrie: node.command = command def __contains__(self, sequence: keyutils.KeySequence) -> bool: - return self.matches(sequence).match_type == QKeySequence.ExactMatch + return self.matches(sequence).match_type == QKeySequence.SequenceMatch.ExactMatch def __repr__(self) -> str: return utils.get_repr(self, children=self.children, @@ -131,20 +131,20 @@ class BindingTrie: try: node = node.children[key] except KeyError: - return MatchResult(match_type=QKeySequence.NoMatch, + return MatchResult(match_type=QKeySequence.SequenceMatch.NoMatch, command=None, sequence=sequence) if node.command is not None: - return MatchResult(match_type=QKeySequence.ExactMatch, + return MatchResult(match_type=QKeySequence.SequenceMatch.ExactMatch, command=node.command, sequence=sequence) elif node.children: - return MatchResult(match_type=QKeySequence.PartialMatch, + return MatchResult(match_type=QKeySequence.SequenceMatch.PartialMatch, command=None, sequence=sequence) else: # This can only happen when there are no bindings at all. - return MatchResult(match_type=QKeySequence.NoMatch, + return MatchResult(match_type=QKeySequence.SequenceMatch.NoMatch, command=None, sequence=sequence) @@ -247,7 +247,7 @@ class BaseKeyParser(QObject): self._debug_log("Mapped {} -> {}".format( sequence, mapped)) return self._match_key(mapped) - return MatchResult(match_type=QKeySequence.NoMatch, + return MatchResult(match_type=QKeySequence.SequenceMatch.NoMatch, command=None, sequence=sequence) @@ -284,52 +284,60 @@ class BaseKeyParser(QObject): Return: A QKeySequence match. """ - key = Qt.Key(e.key()) - txt = str(keyutils.KeyInfo.from_event(e)) - self._debug_log("Got key: 0x{:x} / modifiers: 0x{:x} / text: '{}' / " - "dry_run {}".format(key, int(e.modifiers()), txt, - dry_run)) + try: + info = keyutils.KeyInfo.from_event(e) + except keyutils.InvalidKeyError as ex: + # See https://github.com/qutebrowser/qutebrowser/issues/7047 + log.keyboard.debug(f"Got invalid key: {ex}") + self.clear_keystring() + return QKeySequence.SequenceMatch.NoMatch + + self._debug_log(f"Got key: {info!r} (dry_run {dry_run})") - if keyutils.is_modifier_key(key): + if info.is_modifier_key(): self._debug_log("Ignoring, only modifier") - return QKeySequence.NoMatch + return QKeySequence.SequenceMatch.NoMatch try: sequence = self._sequence.append_event(e) except keyutils.KeyParseError as ex: self._debug_log("{} Aborting keychain.".format(ex)) self.clear_keystring() - return QKeySequence.NoMatch + return QKeySequence.SequenceMatch.NoMatch result = self._match_key(sequence) del sequence # Enforce code below to use the modified result.sequence - if result.match_type == QKeySequence.NoMatch: + if result.match_type == QKeySequence.SequenceMatch.NoMatch: result = self._match_without_modifiers(result.sequence) - if result.match_type == QKeySequence.NoMatch: + if result.match_type == QKeySequence.SequenceMatch.NoMatch: result = self._match_key_mapping(result.sequence) - if result.match_type == QKeySequence.NoMatch: + if result.match_type == QKeySequence.SequenceMatch.NoMatch: was_count = self._match_count(result.sequence, dry_run) if was_count: - return QKeySequence.ExactMatch + return QKeySequence.SequenceMatch.ExactMatch if dry_run: return result.match_type self._sequence = result.sequence + self._handle_result(info, result) + return result.match_type - if result.match_type == QKeySequence.ExactMatch: + def _handle_result(self, info: keyutils.KeyInfo, result: MatchResult) -> None: + """Handle a final MatchResult from handle().""" + if result.match_type == QKeySequence.SequenceMatch.ExactMatch: assert result.command is not None self._debug_log("Definitive match for '{}'.".format( result.sequence)) count = int(self._count) if self._count else None self.clear_keystring() self.execute(result.command, count) - elif result.match_type == QKeySequence.PartialMatch: + elif result.match_type == QKeySequence.SequenceMatch.PartialMatch: self._debug_log("No match for '{}' (added {})".format( - result.sequence, txt)) + result.sequence, info)) self.keystring_updated.emit(self._count + str(result.sequence)) - elif result.match_type == QKeySequence.NoMatch: + elif result.match_type == QKeySequence.SequenceMatch.NoMatch: self._debug_log("Giving up with '{}', no matches".format( result.sequence)) self.clear_keystring() @@ -337,8 +345,6 @@ class BaseKeyParser(QObject): raise utils.Unreachable("Invalid match value {!r}".format( result.match_type)) - return result.match_type - @config.change_filter('bindings') def _on_config_changed(self) -> None: self._read_config() |