diff options
author | Devaev Maxim <[email protected]> | 2020-05-23 15:57:02 +0300 |
---|---|---|
committer | Devaev Maxim <[email protected]> | 2020-05-23 15:57:02 +0300 |
commit | e9d86c058d715af343be355b1ab3d58b7eed43b9 (patch) | |
tree | 6ae712152e4e9d7c274c5e369755f7030269677e /kvmd/keyboard | |
parent | a795fe5ed63b960cbf24c9130ed37f9f7f33280c (diff) |
major keymaps improvement
Diffstat (limited to 'kvmd/keyboard')
-rw-r--r-- | kvmd/keyboard/keysym.py | 38 | ||||
-rw-r--r-- | kvmd/keyboard/printer.py | 79 |
2 files changed, 46 insertions, 71 deletions
diff --git a/kvmd/keyboard/keysym.py b/kvmd/keyboard/keysym.py index fbfeb913..d12e2b84 100644 --- a/kvmd/keyboard/keysym.py +++ b/kvmd/keyboard/keysym.py @@ -20,6 +20,7 @@ # ========================================================================== # +import dataclasses import pkgutil import functools @@ -29,22 +30,34 @@ import Xlib.keysymdef from ..logging import get_logger +from .mappings import At1Key from .mappings import X11_TO_AT1 from .mappings import AT1_TO_WEB # ===== -def build_symmap(path: str) -> Dict[int, str]: [email protected](frozen=True) +class SymmapWebKey: + name: str + shift: bool + + +def build_symmap(path: str) -> Dict[int, SymmapWebKey]: # https://github.com/qemu/qemu/blob/95a9457fd44ad97c518858a4e1586a5498f9773c/ui/keymaps.c - symmap: Dict[int, str] = {} + symmap: Dict[int, SymmapWebKey] = {} for (x11_code, at1_key) in X11_TO_AT1.items(): - symmap[x11_code] = AT1_TO_WEB[at1_key.code] - - for (x11_code, at1_code) in _read_keyboard_layout(path).items(): - if (web_name := AT1_TO_WEB.get(at1_code)) is not None: - # mypy bug - symmap[x11_code] = web_name # type: ignore + symmap[x11_code] = SymmapWebKey( + name=AT1_TO_WEB[at1_key.code], + shift=False, + ) + + for (x11_code, at1_key) in _read_keyboard_layout(path).items(): + if (web_name := AT1_TO_WEB.get(at1_key.code)) is not None: + symmap[x11_code] = SymmapWebKey( + name=web_name, + shift=at1_key.shift, + ) return symmap @@ -76,14 +89,14 @@ def _resolve_keysym(name: str) -> int: return 0 -def _read_keyboard_layout(path: str) -> Dict[int, int]: # Keysym to evdev (at1) +def _read_keyboard_layout(path: str) -> Dict[int, At1Key]: # Keysym to evdev (at1) logger = get_logger(0) logger.info("Reading keyboard layout %s ...", path) with open(path) as layout_file: lines = list(map(str.strip, layout_file.read().split("\n"))) - layout: Dict[int, int] = {} + layout: Dict[int, At1Key] = {} for (number, line) in enumerate(lines): if len(line) == 0 or line.startswith(("#", "map ", "include ")): continue @@ -92,7 +105,10 @@ def _read_keyboard_layout(path: str) -> Dict[int, int]: # Keysym to evdev (at1) if len(parts) >= 2: if (code := _resolve_keysym(parts[0])) != 0: try: - layout[code] = int(parts[1], 16) + layout[code] = At1Key( + code=int(parts[1], 16), + shift=bool(len(parts) == 3 and parts[2] == "shift"), + ) except ValueError as err: logger.error("Can't parse layout line #%d: %s", number, str(err)) return layout diff --git a/kvmd/keyboard/printer.py b/kvmd/keyboard/printer.py index f8086be3..2e26c232 100644 --- a/kvmd/keyboard/printer.py +++ b/kvmd/keyboard/printer.py @@ -20,84 +20,43 @@ # ========================================================================== # -import string - from typing import Tuple +from typing import Dict from typing import Generator -from .mappings import KEYMAP +from .keysym import SymmapWebKey # ===== -_LOWER_CHARS = { - "\n": "Enter", - "\t": "Tab", - " ": "Space", - "`": "Backquote", - "\\": "Backslash", - "[": "BracketLeft", - "]": "BracketLeft", - ",": "Comma", - ".": "Period", - "-": "Minus", - "'": "Quote", - ";": "Semicolon", - "/": "Slash", - "=": "Equal", - **{str(number): f"Digit{number}" for number in range(0, 10)}, - **{ch: f"Key{ch.upper()}" for ch in string.ascii_lowercase}, -} -assert not set(_LOWER_CHARS.values()).difference(KEYMAP) - -_UPPER_CHARS = { - "~": "Backquote", - "|": "Backslash", - "{": "BracketLeft", - "}": "BracketRight", - "<": "Comma", - ">": "Period", - "!": "Digit1", - "@": "Digit2", - "#": "Digit3", - "$": "Digit4", - "%": "Digit5", - "^": "Digit6", - "&": "Digit7", - "*": "Digit8", - "(": "Digit9", - ")": "Digit0", - "_": "Minus", - "\"": "Quote", - ":": "Semicolon", - "?": "Slash", - "+": "Equal", - **{ch: f"Key{ch}" for ch in string.ascii_uppercase}, -} -assert not set(_UPPER_CHARS.values()).difference(KEYMAP) +def text_to_web_keys( + text: str, + symmap: Dict[int, SymmapWebKey], + shift_key: str="ShiftLeft", +) -> Generator[Tuple[str, bool], None, None]: - -# ===== -def text_to_web_keys(text: str, shift_key: str="ShiftLeft") -> Generator[Tuple[str, bool], None, None]: assert shift_key in ["ShiftLeft", "ShiftRight"] shifted = False for ch in text: - upper = False - key = _LOWER_CHARS.get(ch) - if key is None: - if (key := _UPPER_CHARS.get(ch)) is None: + try: + code = ord(ch) + if not (0x20 <= code <= 0x7E): + # https://stackoverflow.com/questions/12343987/convert-ascii-character-to-x11-keycode + # https://www.ascii-code.com continue - upper = True + key = symmap[code] + except Exception: + continue - if upper and not shifted: + if key.shift and not shifted: yield (shift_key, True) shifted = True - elif not upper and shifted: + elif not key.shift and shifted: yield (shift_key, False) shifted = False - yield (key, True) - yield (key, False) + yield (key.name, True) + yield (key.name, False) if shifted: yield (shift_key, False) |