mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-01-29 00:51:53 +08:00
Issue #947: Improved layout handling and Unicode -> X11 keysyms translation
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user