Issue #947: Improved layout handling and Unicode -> X11 keysyms translation

This commit is contained in:
Maxim Devaev
2023-03-23 11:50:22 +02:00
parent 22db176ef0
commit 26238e241e
4 changed files with 64 additions and 20 deletions

View File

@@ -20,22 +20,50 @@
# ========================================================================== #
import ctypes
import ctypes.util
from typing import Generator
from .keysym import SymmapModifiers
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)