mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 09:10:30 +08:00
more correct keymap handling
This commit is contained in:
parent
920f648d65
commit
f1910f7c8e
@ -42,7 +42,6 @@ from ....validators.kvm import valid_hid_mouse_move
|
|||||||
from ....validators.kvm import valid_hid_mouse_button
|
from ....validators.kvm import valid_hid_mouse_button
|
||||||
from ....validators.kvm import valid_hid_mouse_wheel
|
from ....validators.kvm import valid_hid_mouse_wheel
|
||||||
|
|
||||||
from ....keyboard.keysym import SymmapWebKey
|
|
||||||
from ....keyboard.keysym import build_symmap
|
from ....keyboard.keysym import build_symmap
|
||||||
from ....keyboard.printer import text_to_web_keys
|
from ....keyboard.printer import text_to_web_keys
|
||||||
|
|
||||||
@ -98,7 +97,7 @@ class HidApi:
|
|||||||
self.__hid.send_key_events(text_to_web_keys(text, symmap))
|
self.__hid.send_key_events(text_to_web_keys(text, symmap))
|
||||||
return make_json_response()
|
return make_json_response()
|
||||||
|
|
||||||
def __ensure_symmap(self, keymap_name: str) -> Dict[int, SymmapWebKey]:
|
def __ensure_symmap(self, keymap_name: str) -> Dict[int, Dict[int, str]]:
|
||||||
keymap_name = valid_printable_filename(keymap_name, "keymap")
|
keymap_name = valid_printable_filename(keymap_name, "keymap")
|
||||||
path = os.path.join(self.__keymaps_dir_path, keymap_name)
|
path = os.path.join(self.__keymaps_dir_path, keymap_name)
|
||||||
try:
|
try:
|
||||||
@ -110,7 +109,7 @@ class HidApi:
|
|||||||
return self.__inner_ensure_symmap(path, st.st_mtime)
|
return self.__inner_ensure_symmap(path, st.st_mtime)
|
||||||
|
|
||||||
@functools.lru_cache(maxsize=10)
|
@functools.lru_cache(maxsize=10)
|
||||||
def __inner_ensure_symmap(self, path: str, mtime: int) -> Dict[int, SymmapWebKey]:
|
def __inner_ensure_symmap(self, path: str, mtime: int) -> Dict[int, Dict[int, str]]:
|
||||||
_ = mtime # For LRU
|
_ = mtime # For LRU
|
||||||
return build_symmap(path)
|
return build_symmap(path)
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import aiohttp
|
|||||||
|
|
||||||
from ...logging import get_logger
|
from ...logging import get_logger
|
||||||
|
|
||||||
from ...keyboard.keysym import SymmapWebKey
|
from ...keyboard.keysym import switch_symmap_modifiers
|
||||||
from ...keyboard.keysym import build_symmap
|
from ...keyboard.keysym import build_symmap
|
||||||
|
|
||||||
from ...clients.kvmd import KvmdClientWs
|
from ...clients.kvmd import KvmdClientWs
|
||||||
@ -72,7 +72,7 @@ class _Client(RfbClient): # pylint: disable=too-many-instance-attributes
|
|||||||
|
|
||||||
desired_fps: int,
|
desired_fps: int,
|
||||||
keymap_name: str,
|
keymap_name: str,
|
||||||
symmap: Dict[int, SymmapWebKey],
|
symmap: Dict[int, Dict[int, str]],
|
||||||
|
|
||||||
kvmd: KvmdClient,
|
kvmd: KvmdClient,
|
||||||
streamer: StreamerClient,
|
streamer: StreamerClient,
|
||||||
@ -119,6 +119,8 @@ class _Client(RfbClient): # pylint: disable=too-many-instance-attributes
|
|||||||
|
|
||||||
self.__lock = asyncio.Lock()
|
self.__lock = asyncio.Lock()
|
||||||
|
|
||||||
|
self.__modifiers = 0
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
|
|
||||||
async def run(self) -> None:
|
async def run(self) -> None:
|
||||||
@ -238,10 +240,18 @@ class _Client(RfbClient): # pylint: disable=too-many-instance-attributes
|
|||||||
# =====
|
# =====
|
||||||
|
|
||||||
async def _on_key_event(self, code: int, state: bool) -> None:
|
async def _on_key_event(self, code: int, state: bool) -> None:
|
||||||
|
(is_modifier, self.__modifiers) = switch_symmap_modifiers(self.__modifiers, code, state)
|
||||||
if self.__kvmd_ws:
|
if self.__kvmd_ws:
|
||||||
web_key = self.__symmap.get(code)
|
web_keys = self.__symmap.get(code)
|
||||||
|
if web_keys:
|
||||||
|
if is_modifier:
|
||||||
|
web_key = web_keys.get(0)
|
||||||
|
else:
|
||||||
|
web_key = web_keys.get(self.__modifiers)
|
||||||
|
if web_key is None:
|
||||||
|
web_key = web_keys.get(0)
|
||||||
if web_key is not None:
|
if web_key is not None:
|
||||||
await self.__kvmd_ws.send_key_event(web_key.name, state)
|
await self.__kvmd_ws.send_key_event(web_key, state)
|
||||||
|
|
||||||
async def _on_pointer_event(self, buttons: Dict[str, bool], wheel: Dict[str, int], move: Dict[str, int]) -> None:
|
async def _on_pointer_event(self, buttons: Dict[str, bool], wheel: Dict[str, int], move: Dict[str, int]) -> None:
|
||||||
if self.__kvmd_ws:
|
if self.__kvmd_ws:
|
||||||
|
|||||||
@ -20,10 +20,11 @@
|
|||||||
# ========================================================================== #
|
# ========================================================================== #
|
||||||
|
|
||||||
|
|
||||||
import dataclasses
|
|
||||||
import pkgutil
|
import pkgutil
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
|
from typing import Tuple
|
||||||
|
from typing import List
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
|
||||||
import Xlib.keysymdef
|
import Xlib.keysymdef
|
||||||
@ -36,24 +37,40 @@ from .mappings import AT1_TO_WEB
|
|||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
@dataclasses.dataclass(frozen=True)
|
class SymmapModifiers:
|
||||||
class SymmapWebKey:
|
SHIFT: int = 0x1
|
||||||
name: str
|
ALTGR: int = 0x2
|
||||||
shift: bool
|
CTRL: int = 0x4
|
||||||
altgr: bool
|
|
||||||
ctrl: bool
|
|
||||||
|
|
||||||
|
|
||||||
def build_symmap(path: str) -> Dict[int, SymmapWebKey]:
|
def switch_symmap_modifiers(modifiers: int, code: int, state: bool) -> Tuple[bool, int]:
|
||||||
|
mod = 0
|
||||||
|
if code == 65505 or code == 65506: # XK_Shift_L, XK_Shift_R
|
||||||
|
mod = SymmapModifiers.SHIFT
|
||||||
|
elif code == 65027: # AltGR aka XK_ISO_Level3_Shift
|
||||||
|
mod = SymmapModifiers.ALTGR
|
||||||
|
elif code == 65507 or code == 65508: # XK_Control_L, XK_Control_R
|
||||||
|
mod = SymmapModifiers.CTRL
|
||||||
|
if mod == 0:
|
||||||
|
return (False, modifiers)
|
||||||
|
if state:
|
||||||
|
modifiers |= mod
|
||||||
|
else:
|
||||||
|
modifiers &= ~mod
|
||||||
|
return (True, modifiers)
|
||||||
|
|
||||||
|
|
||||||
|
def build_symmap(path: str) -> Dict[int, Dict[int, str]]:
|
||||||
# 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, SymmapWebKey] = {}
|
symmap: Dict[int, Dict[int, str]] = {}
|
||||||
for (src, items) in [
|
for (src, items) in [
|
||||||
("<builtin>", list(X11_TO_AT1.items())),
|
("<builtin>", list(X11_TO_AT1.items())),
|
||||||
(path, list(_read_keyboard_layout(path).items())),
|
(path, list(_read_keyboard_layout(path).items())),
|
||||||
]:
|
]:
|
||||||
for (code, key) in items:
|
for (code, keys) in items:
|
||||||
|
for key in keys:
|
||||||
web_name = AT1_TO_WEB.get(key.code)
|
web_name = AT1_TO_WEB.get(key.code)
|
||||||
if web_name is not None:
|
if web_name is not None:
|
||||||
if (
|
if (
|
||||||
@ -63,12 +80,15 @@ def build_symmap(path: str) -> Dict[int, SymmapWebKey]:
|
|||||||
):
|
):
|
||||||
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
|
||||||
symmap[code] = SymmapWebKey(
|
|
||||||
name=web_name,
|
if code not in symmap:
|
||||||
shift=key.shift,
|
symmap[code] = {}
|
||||||
altgr=key.altgr,
|
symmap[code][
|
||||||
ctrl=key.ctrl,
|
0
|
||||||
)
|
| (SymmapModifiers.SHIFT if key.shift else 0)
|
||||||
|
| (SymmapModifiers.ALTGR if key.altgr else 0)
|
||||||
|
| (SymmapModifiers.CTRL if key.ctrl else 0)
|
||||||
|
] = web_name
|
||||||
return symmap
|
return symmap
|
||||||
|
|
||||||
|
|
||||||
@ -100,14 +120,14 @@ def _resolve_keysym(name: str) -> int:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def _read_keyboard_layout(path: str) -> Dict[int, At1Key]: # Keysym to evdev (at1)
|
def _read_keyboard_layout(path: str) -> Dict[int, List[At1Key]]: # Keysym to evdev (at1)
|
||||||
logger = get_logger(0)
|
logger = get_logger(0)
|
||||||
logger.info("Reading keyboard layout %s ...", path)
|
logger.info("Reading keyboard layout %s ...", path)
|
||||||
|
|
||||||
with open(path) as layout_file:
|
with open(path) as layout_file:
|
||||||
lines = list(map(str.strip, layout_file.read().split("\n")))
|
lines = list(map(str.strip, layout_file.read().split("\n")))
|
||||||
|
|
||||||
layout: Dict[int, At1Key] = {}
|
layout: Dict[int, List[At1Key]] = {}
|
||||||
for (lineno, line) in enumerate(lines):
|
for (lineno, line) in enumerate(lines):
|
||||||
if len(line) == 0 or line.startswith(("#", "map ", "include ")):
|
if len(line) == 0 or line.startswith(("#", "map ", "include ")):
|
||||||
continue
|
continue
|
||||||
@ -115,7 +135,9 @@ def _read_keyboard_layout(path: str) -> Dict[int, At1Key]: # Keysym to evdev (a
|
|||||||
parts = line.split()
|
parts = line.split()
|
||||||
if len(parts) >= 2:
|
if len(parts) >= 2:
|
||||||
x11_code = _resolve_keysym(parts[0])
|
x11_code = _resolve_keysym(parts[0])
|
||||||
if x11_code != 0:
|
if x11_code == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
at1_code = int(parts[1], 16)
|
at1_code = int(parts[1], 16)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
@ -123,18 +145,22 @@ def _read_keyboard_layout(path: str) -> Dict[int, At1Key]: # Keysym to evdev (a
|
|||||||
continue
|
continue
|
||||||
rest = parts[2:]
|
rest = parts[2:]
|
||||||
|
|
||||||
layout[x11_code] = At1Key(
|
if x11_code not in layout:
|
||||||
|
layout[x11_code] = []
|
||||||
|
layout[x11_code].append(At1Key(
|
||||||
code=at1_code,
|
code=at1_code,
|
||||||
shift=("shift" in rest),
|
shift=("shift" in rest),
|
||||||
altgr=("altgr" in rest),
|
altgr=("altgr" in rest),
|
||||||
ctrl=("ctrl" in rest),
|
ctrl=("ctrl" in rest),
|
||||||
)
|
))
|
||||||
|
|
||||||
if "addupper" in rest:
|
if "addupper" in rest:
|
||||||
x11_code = _resolve_keysym(parts[0].upper())
|
x11_code = _resolve_keysym(parts[0].upper())
|
||||||
if x11_code != 0:
|
if x11_code != 0:
|
||||||
layout[x11_code] = At1Key(
|
if x11_code not in layout:
|
||||||
|
layout[x11_code] = []
|
||||||
|
layout[x11_code].append(At1Key(
|
||||||
code=at1_code,
|
code=at1_code,
|
||||||
shift=True,
|
shift=True,
|
||||||
)
|
))
|
||||||
return layout
|
return layout
|
||||||
|
|||||||
@ -163,161 +163,161 @@ class At1Key:
|
|||||||
|
|
||||||
|
|
||||||
X11_TO_AT1 = {
|
X11_TO_AT1 = {
|
||||||
65307: At1Key(code=1, shift=False), # XK_Escape
|
65307: [At1Key(code=1, shift=False)], # XK_Escape
|
||||||
33: At1Key(code=2, shift=True), # XK_exclam
|
33: [At1Key(code=2, shift=True)], # XK_exclam
|
||||||
49: At1Key(code=2, shift=False), # XK_1
|
49: [At1Key(code=2, shift=False)], # XK_1
|
||||||
50: At1Key(code=3, shift=False), # XK_2
|
50: [At1Key(code=3, shift=False)], # XK_2
|
||||||
64: At1Key(code=3, shift=True), # XK_at
|
64: [At1Key(code=3, shift=True)], # XK_at
|
||||||
35: At1Key(code=4, shift=True), # XK_numbersign
|
35: [At1Key(code=4, shift=True)], # XK_numbersign
|
||||||
51: At1Key(code=4, shift=False), # XK_3
|
51: [At1Key(code=4, shift=False)], # XK_3
|
||||||
36: At1Key(code=5, shift=True), # XK_dollar
|
36: [At1Key(code=5, shift=True)], # XK_dollar
|
||||||
52: At1Key(code=5, shift=False), # XK_4
|
52: [At1Key(code=5, shift=False)], # XK_4
|
||||||
37: At1Key(code=6, shift=True), # XK_percent
|
37: [At1Key(code=6, shift=True)], # XK_percent
|
||||||
53: At1Key(code=6, shift=False), # XK_5
|
53: [At1Key(code=6, shift=False)], # XK_5
|
||||||
54: At1Key(code=7, shift=False), # XK_6
|
54: [At1Key(code=7, shift=False)], # XK_6
|
||||||
94: At1Key(code=7, shift=True), # XK_asciicircum
|
94: [At1Key(code=7, shift=True)], # XK_asciicircum
|
||||||
38: At1Key(code=8, shift=True), # XK_ampersand
|
38: [At1Key(code=8, shift=True)], # XK_ampersand
|
||||||
55: At1Key(code=8, shift=False), # XK_7
|
55: [At1Key(code=8, shift=False)], # XK_7
|
||||||
42: At1Key(code=9, shift=True), # XK_asterisk
|
42: [At1Key(code=9, shift=True)], # XK_asterisk
|
||||||
56: At1Key(code=9, shift=False), # XK_8
|
56: [At1Key(code=9, shift=False)], # XK_8
|
||||||
40: At1Key(code=10, shift=True), # XK_parenleft
|
40: [At1Key(code=10, shift=True)], # XK_parenleft
|
||||||
57: At1Key(code=10, shift=False), # XK_9
|
57: [At1Key(code=10, shift=False)], # XK_9
|
||||||
41: At1Key(code=11, shift=True), # XK_parenright
|
41: [At1Key(code=11, shift=True)], # XK_parenright
|
||||||
48: At1Key(code=11, shift=False), # XK_0
|
48: [At1Key(code=11, shift=False)], # XK_0
|
||||||
45: At1Key(code=12, shift=False), # XK_minus
|
45: [At1Key(code=12, shift=False)], # XK_minus
|
||||||
95: At1Key(code=12, shift=True), # XK_underscore
|
95: [At1Key(code=12, shift=True)], # XK_underscore
|
||||||
43: At1Key(code=13, shift=True), # XK_plus
|
43: [At1Key(code=13, shift=True)], # XK_plus
|
||||||
61: At1Key(code=13, shift=False), # XK_equal
|
61: [At1Key(code=13, shift=False)], # XK_equal
|
||||||
65288: At1Key(code=14, shift=False), # XK_BackSpace
|
65288: [At1Key(code=14, shift=False)], # XK_BackSpace
|
||||||
65289: At1Key(code=15, shift=False), # XK_Tab
|
65289: [At1Key(code=15, shift=False)], # XK_Tab
|
||||||
81: At1Key(code=16, shift=True), # XK_Q
|
81: [At1Key(code=16, shift=True)], # XK_Q
|
||||||
113: At1Key(code=16, shift=False), # XK_q
|
113: [At1Key(code=16, shift=False)], # XK_q
|
||||||
87: At1Key(code=17, shift=True), # XK_W
|
87: [At1Key(code=17, shift=True)], # XK_W
|
||||||
119: At1Key(code=17, shift=False), # XK_w
|
119: [At1Key(code=17, shift=False)], # XK_w
|
||||||
69: At1Key(code=18, shift=True), # XK_E
|
69: [At1Key(code=18, shift=True)], # XK_E
|
||||||
101: At1Key(code=18, shift=False), # XK_e
|
101: [At1Key(code=18, shift=False)], # XK_e
|
||||||
82: At1Key(code=19, shift=True), # XK_R
|
82: [At1Key(code=19, shift=True)], # XK_R
|
||||||
114: At1Key(code=19, shift=False), # XK_r
|
114: [At1Key(code=19, shift=False)], # XK_r
|
||||||
84: At1Key(code=20, shift=True), # XK_T
|
84: [At1Key(code=20, shift=True)], # XK_T
|
||||||
116: At1Key(code=20, shift=False), # XK_t
|
116: [At1Key(code=20, shift=False)], # XK_t
|
||||||
89: At1Key(code=21, shift=True), # XK_Y
|
89: [At1Key(code=21, shift=True)], # XK_Y
|
||||||
121: At1Key(code=21, shift=False), # XK_y
|
121: [At1Key(code=21, shift=False)], # XK_y
|
||||||
85: At1Key(code=22, shift=True), # XK_U
|
85: [At1Key(code=22, shift=True)], # XK_U
|
||||||
117: At1Key(code=22, shift=False), # XK_u
|
117: [At1Key(code=22, shift=False)], # XK_u
|
||||||
73: At1Key(code=23, shift=True), # XK_I
|
73: [At1Key(code=23, shift=True)], # XK_I
|
||||||
105: At1Key(code=23, shift=False), # XK_i
|
105: [At1Key(code=23, shift=False)], # XK_i
|
||||||
79: At1Key(code=24, shift=True), # XK_O
|
79: [At1Key(code=24, shift=True)], # XK_O
|
||||||
111: At1Key(code=24, shift=False), # XK_o
|
111: [At1Key(code=24, shift=False)], # XK_o
|
||||||
80: At1Key(code=25, shift=True), # XK_P
|
80: [At1Key(code=25, shift=True)], # XK_P
|
||||||
112: At1Key(code=25, shift=False), # XK_p
|
112: [At1Key(code=25, shift=False)], # XK_p
|
||||||
91: At1Key(code=26, shift=False), # XK_bracketleft
|
91: [At1Key(code=26, shift=False)], # XK_bracketleft
|
||||||
123: At1Key(code=26, shift=True), # XK_braceleft
|
123: [At1Key(code=26, shift=True)], # XK_braceleft
|
||||||
93: At1Key(code=27, shift=False), # XK_bracketright
|
93: [At1Key(code=27, shift=False)], # XK_bracketright
|
||||||
125: At1Key(code=27, shift=True), # XK_braceright
|
125: [At1Key(code=27, shift=True)], # XK_braceright
|
||||||
65293: At1Key(code=28, shift=False), # XK_Return
|
65293: [At1Key(code=28, shift=False)], # XK_Return
|
||||||
65507: At1Key(code=29, shift=False), # XK_Control_L
|
65507: [At1Key(code=29, shift=False)], # XK_Control_L
|
||||||
65: At1Key(code=30, shift=True), # XK_A
|
65: [At1Key(code=30, shift=True)], # XK_A
|
||||||
97: At1Key(code=30, shift=False), # XK_a
|
97: [At1Key(code=30, shift=False)], # XK_a
|
||||||
83: At1Key(code=31, shift=True), # XK_S
|
83: [At1Key(code=31, shift=True)], # XK_S
|
||||||
115: At1Key(code=31, shift=False), # XK_s
|
115: [At1Key(code=31, shift=False)], # XK_s
|
||||||
68: At1Key(code=32, shift=True), # XK_D
|
68: [At1Key(code=32, shift=True)], # XK_D
|
||||||
100: At1Key(code=32, shift=False), # XK_d
|
100: [At1Key(code=32, shift=False)], # XK_d
|
||||||
70: At1Key(code=33, shift=True), # XK_F
|
70: [At1Key(code=33, shift=True)], # XK_F
|
||||||
102: At1Key(code=33, shift=False), # XK_f
|
102: [At1Key(code=33, shift=False)], # XK_f
|
||||||
71: At1Key(code=34, shift=True), # XK_G
|
71: [At1Key(code=34, shift=True)], # XK_G
|
||||||
103: At1Key(code=34, shift=False), # XK_g
|
103: [At1Key(code=34, shift=False)], # XK_g
|
||||||
72: At1Key(code=35, shift=True), # XK_H
|
72: [At1Key(code=35, shift=True)], # XK_H
|
||||||
104: At1Key(code=35, shift=False), # XK_h
|
104: [At1Key(code=35, shift=False)], # XK_h
|
||||||
74: At1Key(code=36, shift=True), # XK_J
|
74: [At1Key(code=36, shift=True)], # XK_J
|
||||||
106: At1Key(code=36, shift=False), # XK_j
|
106: [At1Key(code=36, shift=False)], # XK_j
|
||||||
75: At1Key(code=37, shift=True), # XK_K
|
75: [At1Key(code=37, shift=True)], # XK_K
|
||||||
107: At1Key(code=37, shift=False), # XK_k
|
107: [At1Key(code=37, shift=False)], # XK_k
|
||||||
76: At1Key(code=38, shift=True), # XK_L
|
76: [At1Key(code=38, shift=True)], # XK_L
|
||||||
108: At1Key(code=38, shift=False), # XK_l
|
108: [At1Key(code=38, shift=False)], # XK_l
|
||||||
58: At1Key(code=39, shift=True), # XK_colon
|
58: [At1Key(code=39, shift=True)], # XK_colon
|
||||||
59: At1Key(code=39, shift=False), # XK_semicolon
|
59: [At1Key(code=39, shift=False)], # XK_semicolon
|
||||||
34: At1Key(code=40, shift=True), # XK_quotedbl
|
34: [At1Key(code=40, shift=True)], # XK_quotedbl
|
||||||
39: At1Key(code=40, shift=False), # XK_apostrophe
|
39: [At1Key(code=40, shift=False)], # XK_apostrophe
|
||||||
96: At1Key(code=41, shift=False), # XK_grave
|
96: [At1Key(code=41, shift=False)], # XK_grave
|
||||||
126: At1Key(code=41, shift=True), # XK_asciitilde
|
126: [At1Key(code=41, shift=True)], # XK_asciitilde
|
||||||
65505: At1Key(code=42, shift=False), # XK_Shift_L
|
65505: [At1Key(code=42, shift=False)], # XK_Shift_L
|
||||||
92: At1Key(code=43, shift=False), # XK_backslash
|
92: [At1Key(code=43, shift=False)], # XK_backslash
|
||||||
124: At1Key(code=43, shift=True), # XK_bar
|
124: [At1Key(code=43, shift=True)], # XK_bar
|
||||||
90: At1Key(code=44, shift=True), # XK_Z
|
90: [At1Key(code=44, shift=True)], # XK_Z
|
||||||
122: At1Key(code=44, shift=False), # XK_z
|
122: [At1Key(code=44, shift=False)], # XK_z
|
||||||
88: At1Key(code=45, shift=True), # XK_X
|
88: [At1Key(code=45, shift=True)], # XK_X
|
||||||
120: At1Key(code=45, shift=False), # XK_x
|
120: [At1Key(code=45, shift=False)], # XK_x
|
||||||
67: At1Key(code=46, shift=True), # XK_C
|
67: [At1Key(code=46, shift=True)], # XK_C
|
||||||
99: At1Key(code=46, shift=False), # XK_c
|
99: [At1Key(code=46, shift=False)], # XK_c
|
||||||
86: At1Key(code=47, shift=True), # XK_V
|
86: [At1Key(code=47, shift=True)], # XK_V
|
||||||
118: At1Key(code=47, shift=False), # XK_v
|
118: [At1Key(code=47, shift=False)], # XK_v
|
||||||
66: At1Key(code=48, shift=True), # XK_B
|
66: [At1Key(code=48, shift=True)], # XK_B
|
||||||
98: At1Key(code=48, shift=False), # XK_b
|
98: [At1Key(code=48, shift=False)], # XK_b
|
||||||
78: At1Key(code=49, shift=True), # XK_N
|
78: [At1Key(code=49, shift=True)], # XK_N
|
||||||
110: At1Key(code=49, shift=False), # XK_n
|
110: [At1Key(code=49, shift=False)], # XK_n
|
||||||
77: At1Key(code=50, shift=True), # XK_M
|
77: [At1Key(code=50, shift=True)], # XK_M
|
||||||
109: At1Key(code=50, shift=False), # XK_m
|
109: [At1Key(code=50, shift=False)], # XK_m
|
||||||
44: At1Key(code=51, shift=False), # XK_comma
|
44: [At1Key(code=51, shift=False)], # XK_comma
|
||||||
60: At1Key(code=51, shift=True), # XK_less
|
60: [At1Key(code=51, shift=True)], # XK_less
|
||||||
46: At1Key(code=52, shift=False), # XK_period
|
46: [At1Key(code=52, shift=False)], # XK_period
|
||||||
62: At1Key(code=52, shift=True), # XK_greater
|
62: [At1Key(code=52, shift=True)], # XK_greater
|
||||||
47: At1Key(code=53, shift=False), # XK_slash
|
47: [At1Key(code=53, shift=False)], # XK_slash
|
||||||
63: At1Key(code=53, shift=True), # XK_question
|
63: [At1Key(code=53, shift=True)], # XK_question
|
||||||
65506: At1Key(code=54, shift=False), # XK_Shift_R
|
65506: [At1Key(code=54, shift=False)], # XK_Shift_R
|
||||||
215: At1Key(code=55, shift=False), # XK_multiply
|
215: [At1Key(code=55, shift=False)], # XK_multiply
|
||||||
65513: At1Key(code=56, shift=False), # XK_Alt_L
|
65513: [At1Key(code=56, shift=False)], # XK_Alt_L
|
||||||
32: At1Key(code=57, shift=False), # XK_space
|
32: [At1Key(code=57, shift=False)], # XK_space
|
||||||
65509: At1Key(code=58, shift=False), # XK_Caps_Lock
|
65509: [At1Key(code=58, shift=False)], # XK_Caps_Lock
|
||||||
65470: At1Key(code=59, shift=False), # XK_F1
|
65470: [At1Key(code=59, shift=False)], # XK_F1
|
||||||
65471: At1Key(code=60, shift=False), # XK_F2
|
65471: [At1Key(code=60, shift=False)], # XK_F2
|
||||||
65472: At1Key(code=61, shift=False), # XK_F3
|
65472: [At1Key(code=61, shift=False)], # XK_F3
|
||||||
65473: At1Key(code=62, shift=False), # XK_F4
|
65473: [At1Key(code=62, shift=False)], # XK_F4
|
||||||
65474: At1Key(code=63, shift=False), # XK_F5
|
65474: [At1Key(code=63, shift=False)], # XK_F5
|
||||||
65475: At1Key(code=64, shift=False), # XK_F6
|
65475: [At1Key(code=64, shift=False)], # XK_F6
|
||||||
65476: At1Key(code=65, shift=False), # XK_F7
|
65476: [At1Key(code=65, shift=False)], # XK_F7
|
||||||
65477: At1Key(code=66, shift=False), # XK_F8
|
65477: [At1Key(code=66, shift=False)], # XK_F8
|
||||||
65478: At1Key(code=67, shift=False), # XK_F9
|
65478: [At1Key(code=67, shift=False)], # XK_F9
|
||||||
65479: At1Key(code=68, shift=False), # XK_F10
|
65479: [At1Key(code=68, shift=False)], # XK_F10
|
||||||
65407: At1Key(code=69, shift=False), # XK_Num_Lock
|
65407: [At1Key(code=69, shift=False)], # XK_Num_Lock
|
||||||
65300: At1Key(code=70, shift=False), # XK_Scroll_Lock
|
65300: [At1Key(code=70, shift=False)], # XK_Scroll_Lock
|
||||||
65463: At1Key(code=71, shift=False), # XK_KP_7
|
65463: [At1Key(code=71, shift=False)], # XK_KP_7
|
||||||
65464: At1Key(code=72, shift=False), # XK_KP_8
|
65464: [At1Key(code=72, shift=False)], # XK_KP_8
|
||||||
65465: At1Key(code=73, shift=False), # XK_KP_9
|
65465: [At1Key(code=73, shift=False)], # XK_KP_9
|
||||||
65453: At1Key(code=74, shift=False), # XK_KP_Subtract
|
65453: [At1Key(code=74, shift=False)], # XK_KP_Subtract
|
||||||
65460: At1Key(code=75, shift=False), # XK_KP_4
|
65460: [At1Key(code=75, shift=False)], # XK_KP_4
|
||||||
65461: At1Key(code=76, shift=False), # XK_KP_5
|
65461: [At1Key(code=76, shift=False)], # XK_KP_5
|
||||||
65462: At1Key(code=77, shift=False), # XK_KP_6
|
65462: [At1Key(code=77, shift=False)], # XK_KP_6
|
||||||
65451: At1Key(code=78, shift=False), # XK_KP_Add
|
65451: [At1Key(code=78, shift=False)], # XK_KP_Add
|
||||||
65457: At1Key(code=79, shift=False), # XK_KP_1
|
65457: [At1Key(code=79, shift=False)], # XK_KP_1
|
||||||
65458: At1Key(code=80, shift=False), # XK_KP_2
|
65458: [At1Key(code=80, shift=False)], # XK_KP_2
|
||||||
65459: At1Key(code=81, shift=False), # XK_KP_3
|
65459: [At1Key(code=81, shift=False)], # XK_KP_3
|
||||||
65456: At1Key(code=82, shift=False), # XK_KP_0
|
65456: [At1Key(code=82, shift=False)], # XK_KP_0
|
||||||
65454: At1Key(code=83, shift=False), # XK_KP_Decimal
|
65454: [At1Key(code=83, shift=False)], # XK_KP_Decimal
|
||||||
65301: At1Key(code=84, shift=False), # XK_Sys_Req
|
65301: [At1Key(code=84, shift=False)], # XK_Sys_Req
|
||||||
65480: At1Key(code=87, shift=False), # XK_F11
|
65480: [At1Key(code=87, shift=False)], # XK_F11
|
||||||
65481: At1Key(code=88, shift=False), # XK_F12
|
65481: [At1Key(code=88, shift=False)], # XK_F12
|
||||||
65421: At1Key(code=57372, shift=False), # XK_KP_Enter
|
65421: [At1Key(code=57372, shift=False)], # XK_KP_Enter
|
||||||
65508: At1Key(code=57373, shift=False), # XK_Control_R
|
65508: [At1Key(code=57373, shift=False)], # XK_Control_R
|
||||||
65455: At1Key(code=57397, shift=False), # XK_KP_Divide
|
65455: [At1Key(code=57397, shift=False)], # XK_KP_Divide
|
||||||
65027: At1Key(code=57400, shift=False), # XK_ISO_Level3_Shift
|
65027: [At1Key(code=57400, shift=False)], # XK_ISO_Level3_Shift
|
||||||
65514: At1Key(code=57400, shift=False), # XK_Alt_R
|
65514: [At1Key(code=57400, shift=False)], # XK_Alt_R
|
||||||
65299: At1Key(code=57414, shift=False), # XK_Pause
|
65299: [At1Key(code=57414, shift=False)], # XK_Pause
|
||||||
65360: At1Key(code=57415, shift=False), # XK_Home
|
65360: [At1Key(code=57415, shift=False)], # XK_Home
|
||||||
65362: At1Key(code=57416, shift=False), # XK_Up
|
65362: [At1Key(code=57416, shift=False)], # XK_Up
|
||||||
65365: At1Key(code=57417, shift=False), # XK_Page_Up
|
65365: [At1Key(code=57417, shift=False)], # XK_Page_Up
|
||||||
65361: At1Key(code=57419, shift=False), # XK_Left
|
65361: [At1Key(code=57419, shift=False)], # XK_Left
|
||||||
65363: At1Key(code=57421, shift=False), # XK_Right
|
65363: [At1Key(code=57421, shift=False)], # XK_Right
|
||||||
65367: At1Key(code=57423, shift=False), # XK_End
|
65367: [At1Key(code=57423, shift=False)], # XK_End
|
||||||
65364: At1Key(code=57424, shift=False), # XK_Down
|
65364: [At1Key(code=57424, shift=False)], # XK_Down
|
||||||
65366: At1Key(code=57425, shift=False), # XK_Page_Down
|
65366: [At1Key(code=57425, shift=False)], # XK_Page_Down
|
||||||
65379: At1Key(code=57426, shift=False), # XK_Insert
|
65379: [At1Key(code=57426, shift=False)], # XK_Insert
|
||||||
65535: At1Key(code=57427, shift=False), # XK_Delete
|
65535: [At1Key(code=57427, shift=False)], # XK_Delete
|
||||||
65511: At1Key(code=57435, shift=False), # XK_Meta_L
|
65511: [At1Key(code=57435, shift=False)], # XK_Meta_L
|
||||||
65515: At1Key(code=57435, shift=False), # XK_Super_L
|
65515: [At1Key(code=57435, shift=False)], # XK_Super_L
|
||||||
65512: At1Key(code=57436, shift=False), # XK_Meta_R
|
65512: [At1Key(code=57436, shift=False)], # XK_Meta_R
|
||||||
65516: At1Key(code=57436, shift=False), # XK_Super_R
|
65516: [At1Key(code=57436, shift=False)], # XK_Super_R
|
||||||
65383: At1Key(code=57437, shift=False), # XK_Menu
|
65383: [At1Key(code=57437, shift=False)], # XK_Menu
|
||||||
269025071: At1Key(code=57438, shift=False), # XK_XF86_Sleep
|
269025071: [At1Key(code=57438, shift=False)], # XK_XF86_Sleep
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -62,7 +62,7 @@ class At1Key:
|
|||||||
X11_TO_AT1 = {
|
X11_TO_AT1 = {
|
||||||
% for km in sorted(keymap, key=operator.attrgetter("at1_code")):
|
% for km in sorted(keymap, key=operator.attrgetter("at1_code")):
|
||||||
% for x11_key in sorted(km.x11_keys, key=(lambda key: (key.code, key.shift))):
|
% for x11_key in sorted(km.x11_keys, key=(lambda key: (key.code, key.shift))):
|
||||||
${x11_key.code}: At1Key(code=${km.at1_code}, shift=${x11_key.shift}), # ${x11_key.name}
|
${x11_key.code}: [At1Key(code=${km.at1_code}, shift=${x11_key.shift})], # ${x11_key.name}
|
||||||
% endfor
|
% endfor
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,13 +24,13 @@ from typing import Tuple
|
|||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
|
||||||
from .keysym import SymmapWebKey
|
from .keysym import SymmapModifiers
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
def text_to_web_keys(
|
def text_to_web_keys(
|
||||||
text: str,
|
text: str,
|
||||||
symmap: Dict[int, SymmapWebKey],
|
symmap: Dict[int, Dict[int, str]],
|
||||||
shift_key: str="ShiftLeft",
|
shift_key: str="ShiftLeft",
|
||||||
) -> Generator[Tuple[str, bool], None, None]:
|
) -> Generator[Tuple[str, bool], None, None]:
|
||||||
|
|
||||||
@ -40,25 +40,32 @@ def text_to_web_keys(
|
|||||||
for ch in text:
|
for ch in text:
|
||||||
try:
|
try:
|
||||||
code = ord(ch)
|
code = ord(ch)
|
||||||
if not (0x20 <= code <= 0x7E):
|
if 0x20 <= code <= 0x7E:
|
||||||
# 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
|
||||||
|
keys = symmap[code]
|
||||||
|
elif code == 0x0A: # Enter:
|
||||||
|
keys = {0: "Enter"}
|
||||||
|
else:
|
||||||
continue
|
continue
|
||||||
key = symmap[code]
|
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
if key.altgr or key.ctrl:
|
|
||||||
continue # Not supported yet
|
|
||||||
|
|
||||||
if key.shift and not shifted:
|
for (modifiers, key) in reversed(keys.items()):
|
||||||
|
if (modifiers & SymmapModifiers.ALTGR) or (modifiers & SymmapModifiers.CTRL):
|
||||||
|
# Not supported yet
|
||||||
|
continue
|
||||||
|
|
||||||
|
if modifiers & SymmapModifiers.SHIFT and not shifted:
|
||||||
yield (shift_key, True)
|
yield (shift_key, True)
|
||||||
shifted = True
|
shifted = True
|
||||||
elif not key.shift and shifted:
|
elif not (modifiers & SymmapModifiers.SHIFT) and shifted:
|
||||||
yield (shift_key, False)
|
yield (shift_key, False)
|
||||||
shifted = False
|
shifted = False
|
||||||
|
|
||||||
yield (key.name, True)
|
yield (key, True)
|
||||||
yield (key.name, False)
|
yield (key, False)
|
||||||
|
break
|
||||||
|
|
||||||
if shifted:
|
if shifted:
|
||||||
yield (shift_key, False)
|
yield (shift_key, False)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user