mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 01:00:29 +08:00
Issue #947: Improved layout handling and Unicode -> X11 keysyms translation
This commit is contained in:
parent
22db176ef0
commit
26238e241e
1
PKGBUILD
1
PKGBUILD
@ -62,6 +62,7 @@ depends=(
|
|||||||
python-pam
|
python-pam
|
||||||
"python-pillow>=8.3.1-1"
|
"python-pillow>=8.3.1-1"
|
||||||
python-xlib
|
python-xlib
|
||||||
|
libxkbcommon
|
||||||
python-hidapi
|
python-hidapi
|
||||||
python-six
|
python-six
|
||||||
python-pyrad
|
python-pyrad
|
||||||
|
|||||||
@ -41,15 +41,19 @@ class SymmapModifiers:
|
|||||||
CTRL: int = 0x4
|
CTRL: int = 0x4
|
||||||
|
|
||||||
|
|
||||||
def build_symmap(path: str) -> dict[int, dict[int, str]]:
|
def build_symmap(path: str) -> dict[int, dict[int, str]]: # x11 keysym -> [(modifiers, webkey), ...]
|
||||||
# https://github.com/qemu/qemu/blob/95a9457fd44ad97c518858a4e1586a5498f9773c/ui/keymaps.c
|
# https://github.com/qemu/qemu/blob/95a9457fd44ad97c518858a4e1586a5498f9773c/ui/keymaps.c
|
||||||
logger = get_logger()
|
logger = get_logger()
|
||||||
|
|
||||||
symmap: dict[int, dict[int, str]] = {}
|
symmap: dict[int, dict[int, str]] = {}
|
||||||
for (src, items) in [
|
for (src, items) in [
|
||||||
("<builtin>", list(X11_TO_AT1.items())),
|
|
||||||
(path, list(_read_keyboard_layout(path).items())),
|
(path, list(_read_keyboard_layout(path).items())),
|
||||||
|
("<builtin>", list(X11_TO_AT1.items())),
|
||||||
]:
|
]:
|
||||||
|
# Пока лучшая логика - самые первые записи в файле раскладки
|
||||||
|
# должны иметь приоритет над следующими, а дефолтный маппинг
|
||||||
|
# только дополняет отсутствующие значения.
|
||||||
|
|
||||||
for (code, keys) in items:
|
for (code, keys) in items:
|
||||||
for key in keys:
|
for key in keys:
|
||||||
web_name = AT1_TO_WEB.get(key.code)
|
web_name = AT1_TO_WEB.get(key.code)
|
||||||
@ -62,14 +66,15 @@ def build_symmap(path: str) -> dict[int, dict[int, str]]:
|
|||||||
logger.error("Invalid modifier key at mapping %s: %s / %s", src, web_name, key)
|
logger.error("Invalid modifier key at mapping %s: %s / %s", src, web_name, key)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if code not in symmap:
|
modifiers = (
|
||||||
symmap[code] = {}
|
|
||||||
symmap[code][
|
|
||||||
0
|
0
|
||||||
| (SymmapModifiers.SHIFT if key.shift else 0)
|
| (SymmapModifiers.SHIFT if key.shift else 0)
|
||||||
| (SymmapModifiers.ALTGR if key.altgr else 0)
|
| (SymmapModifiers.ALTGR if key.altgr else 0)
|
||||||
| (SymmapModifiers.CTRL if key.ctrl else 0)
|
| (SymmapModifiers.CTRL if key.ctrl else 0)
|
||||||
] = web_name
|
)
|
||||||
|
if code not in symmap:
|
||||||
|
symmap[code] = {}
|
||||||
|
symmap[code].setdefault(modifiers, web_name)
|
||||||
return symmap
|
return symmap
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -20,22 +20,50 @@
|
|||||||
# ========================================================================== #
|
# ========================================================================== #
|
||||||
|
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
import ctypes.util
|
||||||
|
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
|
||||||
from .keysym import SymmapModifiers
|
from .keysym import SymmapModifiers
|
||||||
from .mappings import WebModifiers
|
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
|
def text_to_web_keys( # pylint: disable=too-many-branches
|
||||||
text: str,
|
text: str,
|
||||||
symmap: dict[int, dict[int, str]],
|
symmap: dict[int, dict[int, str]],
|
||||||
shift_key: str=WebModifiers.SHIFT_LEFT,
|
|
||||||
) -> Generator[tuple[str, bool], None, None]:
|
) -> Generator[tuple[str, bool], None, None]:
|
||||||
|
|
||||||
assert shift_key in WebModifiers.SHIFTS
|
shift = False
|
||||||
|
altgr = False
|
||||||
|
|
||||||
shifted = False
|
|
||||||
for ch in text:
|
for ch in text:
|
||||||
# https://stackoverflow.com/questions/12343987/convert-ascii-character-to-x11-keycode
|
# https://stackoverflow.com/questions/12343987/convert-ascii-character-to-x11-keycode
|
||||||
# https://www.ascii-code.com
|
# https://www.ascii-code.com
|
||||||
@ -57,25 +85,34 @@ def text_to_web_keys( # pylint: disable=too-many-branches
|
|||||||
if not ch.isprintable():
|
if not ch.isprintable():
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
keys = symmap[ord(ch)]
|
keys = symmap[_ch_to_keysym(ch)]
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for (modifiers, key) in reversed(keys.items()):
|
for (modifiers, key) in keys.items():
|
||||||
if (modifiers & SymmapModifiers.ALTGR) or (modifiers & SymmapModifiers.CTRL):
|
if modifiers & SymmapModifiers.CTRL:
|
||||||
# Not supported yet
|
# Not supported yet
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if modifiers & SymmapModifiers.SHIFT and not shifted:
|
if modifiers & SymmapModifiers.SHIFT and not shift:
|
||||||
yield (shift_key, True)
|
yield (WebModifiers.SHIFT_LEFT, True)
|
||||||
shifted = True
|
shift = True
|
||||||
elif not (modifiers & SymmapModifiers.SHIFT) and shifted:
|
elif not (modifiers & SymmapModifiers.SHIFT) and shift:
|
||||||
yield (shift_key, False)
|
yield (WebModifiers.SHIFT_LEFT, False)
|
||||||
shifted = 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, True)
|
||||||
yield (key, False)
|
yield (key, False)
|
||||||
break
|
break
|
||||||
|
|
||||||
if shifted:
|
if shift:
|
||||||
yield (shift_key, False)
|
yield (WebModifiers.SHIFT_LEFT, False)
|
||||||
|
if altgr:
|
||||||
|
yield (WebModifiers.ALT_RIGHT, False)
|
||||||
|
|||||||
@ -56,6 +56,7 @@ RUN pacman --noconfirm --ask=4 -Syy \
|
|||||||
python-pam \
|
python-pam \
|
||||||
python-pillow \
|
python-pillow \
|
||||||
python-xlib \
|
python-xlib \
|
||||||
|
libxkbcommon \
|
||||||
python-hidapi \
|
python-hidapi \
|
||||||
python-zstandard \
|
python-zstandard \
|
||||||
freetype2 \
|
freetype2 \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user