You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ORPA-pyOpenRPA/Resources/WPy64-3720/python-3.7.2.amd64/Lib/site-packages/keyboard/_xlibkeyboard.py

120 lines
3.6 KiB

from collections import defaultdict
from Xlib import X, XK, display
from Xlib.ext import record
from Xlib.protocol import rq
from ._keyboard_event import KeyboardEvent, KEY_DOWN, KEY_UP, normalize_name
# from ._nixkeyboard import init
def cleanup_key(name):
if name.startswith('XK_'):
name = name[3:]
if name.startswith('KP_'):
is_keypad = True
name = name[3:]
else:
is_keypad = False
if name.endswith('_R'):
name = 'right ' + name[:-2]
if name.endswith('_L'):
name = 'left ' + name[:-2]
return normalize_name(name), is_keypad
keysym_to_keys = defaultdict(list)
name_to_keysyms = defaultdict(list)
for raw_name in dir(XK):
if not raw_name.startswith('XK_'): continue
keysym = getattr(XK, raw_name)
name, is_keypad = cleanup_key(raw_name)
keysym_to_keys[keysym].append((name, is_keypad))
name_to_keysyms[name].append(keysym)
local_dpy = None
record_dpy = None
ctx = None
def init():
# Adapted from https://github.com/python-xlib/python-xlib/blob/master/examples/record_demo.py
global local_dpy
global record_dpy
local_dpy = display.Display()
record_dpy = display.Display()
if not record_dpy.has_extension("RECORD"):
raise ImportError("RECORD extension not found")
r = record_dpy.record_get_version(0, 0)
# print("RECORD extension version %d.%d" % (r.major_version, r.minor_version))
# Create a recording context; we only want key and mouse events
global ctx
ctx = record_dpy.record_create_context(
0,
[record.AllClients],
[
{
'core_requests': (0, 0),
'core_replies': (0, 0),
'ext_requests': (0, 0, 0, 0),
'ext_replies': (0, 0, 0, 0),
'delivered_events': (0, 0),
'device_events': (X.KeyPress, X.KeyPress),
'errors': (0, 0),
'client_started': False,
'client_died': False,
}
]
)
def listen(callback):
def handler(reply):
if reply.category != record.FromServer:
return
if reply.client_swapped:
print("* received swapped protocol data, cowardly ignored")
return
if not len(reply.data) or reply.data[0] < 2:
# not an event
return
data = reply.data
while len(data):
raw_event, data = rq.EventField(None).parse_binary_value(data, record_dpy.display, None, None)
event_type = {X.KeyPress: KEY_DOWN, X.KeyRelease: KEY_UP}.get(raw_event.type)
if event_type:
keysym = local_dpy.keycode_to_keysym(raw_event.detail, 0)
# TODO: scan code is not correct.
if not keysym:
event = KeyboardEvent(event_type=event_type, scan_code=raw_event.detail)
else:
try:
name, is_keypad = keysym_to_keys[keysym][0]
except IndexError:
name, is_keypad = None, None
event = KeyboardEvent(event_type=event_type, scan_code=keysym, name=name, is_keypad=is_keypad)
callback(event)
try:
# Enable the context; this only returns after a call to record_disable_context,
# while calling the callback function in the meantime
record_dpy.record_enable_context(ctx, handler)
finally:
# Finally free the context
record_dpy.record_free_context(ctx)
def map_name(name):
for keysym in name_to_keysyms[name]:
yield keysym, ()