diff options
author | Maxim Devaev <[email protected]> | 2023-03-23 11:50:22 +0200 |
---|---|---|
committer | Maxim Devaev <[email protected]> | 2023-03-23 11:50:22 +0200 |
commit | 26238e241e2d470ddda0798f95bb5e855bd11ecc (patch) | |
tree | 088811b1df8b434fc6c770232ccdbd5a709c2a34 /kvmd/keyboard/printer.py | |
parent | 22db176ef05df0b49a9e40e3c31c886dfcb710b5 (diff) |
Issue #947: Improved layout handling and Unicode -> X11 keysyms translation
Diffstat (limited to 'kvmd/keyboard/printer.py')
-rw-r--r-- | kvmd/keyboard/printer.py | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/kvmd/keyboard/printer.py b/kvmd/keyboard/printer.py index a2003a18..a29355b6 100644 --- a/kvmd/keyboard/printer.py +++ b/kvmd/keyboard/printer.py @@ -20,6 +20,9 @@ # ========================================================================== # +import ctypes +import ctypes.util + from typing import Generator from .keysym import SymmapModifiers @@ -27,15 +30,40 @@ from .mappings import WebModifiers # ===== +def _load_libxkbcommon() -> ctypes.CDLL: + path = ctypes.util.find_library("xkbcommon") + if not path: + raise RuntimeError("Where is libxkbcommon?") + assert path + lib = ctypes.CDLL(path) + for (name, restype, argtypes) in [ + ("xkb_utf32_to_keysym", ctypes.c_uint32, [ctypes.c_uint32]), + ]: + func = getattr(lib, name) + if not func: + raise RuntimeError(f"Where is libc.{name}?") + setattr(func, "restype", restype) + setattr(func, "argtypes", argtypes) + return lib + + +_libxkbcommon = _load_libxkbcommon() + + +def _ch_to_keysym(ch: str) -> int: + assert len(ch) == 1 + return _libxkbcommon.xkb_utf32_to_keysym(ord(ch)) + + +# ===== def text_to_web_keys( # pylint: disable=too-many-branches text: str, symmap: dict[int, dict[int, str]], - shift_key: str=WebModifiers.SHIFT_LEFT, ) -> Generator[tuple[str, bool], None, None]: - assert shift_key in WebModifiers.SHIFTS + shift = False + altgr = False - shifted = False for ch in text: # https://stackoverflow.com/questions/12343987/convert-ascii-character-to-x11-keycode # https://www.ascii-code.com @@ -57,25 +85,34 @@ def text_to_web_keys( # pylint: disable=too-many-branches if not ch.isprintable(): continue try: - keys = symmap[ord(ch)] + keys = symmap[_ch_to_keysym(ch)] except Exception: continue - for (modifiers, key) in reversed(keys.items()): - if (modifiers & SymmapModifiers.ALTGR) or (modifiers & SymmapModifiers.CTRL): + for (modifiers, key) in keys.items(): + if modifiers & SymmapModifiers.CTRL: # Not supported yet continue - if modifiers & SymmapModifiers.SHIFT and not shifted: - yield (shift_key, True) - shifted = True - elif not (modifiers & SymmapModifiers.SHIFT) and shifted: - yield (shift_key, False) - shifted = False + if modifiers & SymmapModifiers.SHIFT and not shift: + yield (WebModifiers.SHIFT_LEFT, True) + shift = True + elif not (modifiers & SymmapModifiers.SHIFT) and shift: + yield (WebModifiers.SHIFT_LEFT, False) + shift = False + + if modifiers & SymmapModifiers.ALTGR and not altgr: + yield (WebModifiers.ALT_RIGHT, True) + altgr = True + elif not (modifiers & SymmapModifiers.ALTGR) and altgr: + yield (WebModifiers.ALT_RIGHT, False) + altgr = False yield (key, True) yield (key, False) break - if shifted: - yield (shift_key, False) + if shift: + yield (WebModifiers.SHIFT_LEFT, False) + if altgr: + yield (WebModifiers.ALT_RIGHT, False) |