inputlistener.py (screenkey-1.4) | : | inputlistener.py (screenkey-1.5) | ||
---|---|---|---|---|
skipping to change at line 160 | skipping to change at line 160 | |||
self.btn = btn | self.btn = btn | |||
self.pressed = pressed == xlib.ButtonPress | self.pressed = pressed == xlib.ButtonPress | |||
class InputType: | class InputType: | |||
keyboard = 0b001 | keyboard = 0b001 | |||
button = 0b010 | button = 0b010 | |||
movement = 0b100 | movement = 0b100 | |||
all = 0b111 | all = 0b111 | |||
class InputListener(threading.Thread): | class InputListener(threading.Thread): | |||
def __init__(self, kbd_callback, btn_callback, input_types=InputType.all, | def __init__(self, event_callback, input_types=InputType.all, | |||
kbd_compose=True, kbd_translate=True): | kbd_compose=True, kbd_translate=True): | |||
super().__init__() | super().__init__() | |||
self.kbd_callback = kbd_callback | self.event_callback = event_callback | |||
self.btn_callback = btn_callback | ||||
self.input_types = input_types | self.input_types = input_types | |||
self.kbd_compose = kbd_compose | self.kbd_compose = kbd_compose | |||
self.kbd_translate = kbd_translate | self.kbd_translate = kbd_translate | |||
self.lock = threading.Lock() | self.lock = threading.Lock() | |||
self.stopped = True | self.stopped = True | |||
self.error = None | self.error = None | |||
def _event_received(self, ev): | def _event_received(self, ev): | |||
if xlib.KeyPress <= ev.type <= xlib.MotionNotify: | if xlib.KeyPress <= ev.type <= xlib.MotionNotify: | |||
xlib.XSendEvent(self.replay_dpy, self.replay_win, False, 0, ev) | xlib.XSendEvent(self.replay_dpy, self.replay_win, False, 0, ev) | |||
elif ev.type in [xlib.FocusIn, xlib.FocusOut]: | elif ev.type in [xlib.FocusIn, xlib.FocusOut]: | |||
# Forward the event as a custom message in the same queue instead | # Forward the event as a custom message in the same queue instead | |||
# of resetting the XIC directly, in order to preserve queued events | # of resetting the XIC directly, in order to preserve queued events | |||
fwd_ev = xlib.XEvent() | fwd_ev = xlib.XEvent() | |||
fwd_ev.type = xlib.ClientMessage | fwd_ev.type = xlib.ClientMessage | |||
fwd_ev.xclient.message_type = self.custom_atom | fwd_ev.xclient.message_type = self.custom_atom | |||
fwd_ev.xclient.format = 32 | fwd_ev.xclient.format = 32 | |||
fwd_ev.xclient.data[0] = ev.type | fwd_ev.xclient.data[0] = ev.type | |||
xlib.XSendEvent(self.replay_dpy, self.replay_win, False, 0, fwd_ev) | xlib.XSendEvent(self.replay_dpy, self.replay_win, False, 0, fwd_ev) | |||
def _kbd_event_callback(self, data): | def _event_callback(self, data): | |||
self.kbd_callback(data) | self.event_callback(data) | |||
return False | ||||
def _btn_event_callback(self, data): | ||||
self.btn_callback(data) | ||||
return False | return False | |||
def _event_processed(self, data): | def _event_processed(self, data): | |||
data.symbol = xlib.XKeysymToString(data.keysym) | data.symbol = xlib.XKeysymToString(data.keysym) | |||
if data.string is None: | if data.string is None: | |||
data.string = keysym_to_unicode(data.keysym) | data.string = keysym_to_unicode(data.keysym) | |||
glib.idle_add(self._kbd_event_callback, data) | glib.idle_add(self._event_callback, data) | |||
def _event_modifiers(self, kev, data): | def _event_modifiers(self, kev, data): | |||
data.modifiers = modifiers = {} | data.modifiers = modifiers = {} | |||
modifiers['shift'] = bool(kev.state & xlib.ShiftMask) | modifiers['shift'] = bool(kev.state & xlib.ShiftMask) | |||
modifiers['caps_lock'] = bool(kev.state & xlib.LockMask) | modifiers['caps_lock'] = bool(kev.state & xlib.LockMask) | |||
modifiers['ctrl'] = bool(kev.state & xlib.ControlMask) | modifiers['ctrl'] = bool(kev.state & xlib.ControlMask) | |||
modifiers['alt'] = bool(kev.state & xlib.Mod1Mask) | modifiers['alt'] = bool(kev.state & xlib.Mod1Mask) | |||
modifiers['num_lock'] = bool(kev.state & xlib.Mod2Mask) | modifiers['num_lock'] = bool(kev.state & xlib.Mod2Mask) | |||
modifiers['hyper'] = bool(kev.state & xlib.Mod3Mask) | modifiers['hyper'] = bool(kev.state & xlib.Mod3Mask) | |||
modifiers['super'] = bool(kev.state & xlib.Mod4Mask) | modifiers['super'] = bool(kev.state & xlib.Mod4Mask) | |||
skipping to change at line 308 | skipping to change at line 303 | |||
if not data.filtered and data.pressed and self.kbd_translate: | if not data.filtered and data.pressed and self.kbd_translate: | |||
self._event_keypress(ev.xkey, data) | self._event_keypress(ev.xkey, data) | |||
else: | else: | |||
self._event_lookup(ev.xkey, data) | self._event_lookup(ev.xkey, data) | |||
self._event_processed(data) | self._event_processed(data) | |||
self._kbd_last_ev = ev | self._kbd_last_ev = ev | |||
def _btn_process(self, ev): | def _btn_process(self, ev): | |||
if ev.type in [xlib.ButtonPress, xlib.ButtonRelease]: | if ev.type in [xlib.ButtonPress, xlib.ButtonRelease]: | |||
data = ButtonData(ev.xbutton.button, ev.type) | data = ButtonData(ev.xbutton.button, ev.type) | |||
glib.idle_add(self._btn_event_callback, data) | glib.idle_add(self._event_callback, data) | |||
def run(self): | def run(self): | |||
# control connection | # control connection | |||
self.control_dpy = xlib.XOpenDisplay(None) | self.control_dpy = xlib.XOpenDisplay(None) | |||
xlib.XSynchronize(self.control_dpy, True) | xlib.XSynchronize(self.control_dpy, True) | |||
# unmapped replay window | # unmapped replay window | |||
self.replay_dpy = xlib.XOpenDisplay(None) | self.replay_dpy = xlib.XOpenDisplay(None) | |||
self.custom_atom = xlib.XInternAtom(self.replay_dpy, b"SCREENKEY", False ) | self.custom_atom = xlib.XInternAtom(self.replay_dpy, b"SCREENKEY", False ) | |||
replay_fd = xlib.XConnectionNumber(self.replay_dpy) | replay_fd = xlib.XConnectionNumber(self.replay_dpy) | |||
skipping to change at line 332 | skipping to change at line 327 | |||
try: | try: | |||
if self.input_types & InputType.keyboard: | if self.input_types & InputType.keyboard: | |||
self._kbd_init() | self._kbd_init() | |||
except Exception as e: | except Exception as e: | |||
self.error = e | self.error = e | |||
xlib.XCloseDisplay(self.control_dpy) | xlib.XCloseDisplay(self.control_dpy) | |||
xlib.XDestroyWindow(self.replay_dpy, self.replay_win) | xlib.XDestroyWindow(self.replay_dpy, self.replay_win) | |||
xlib.XCloseDisplay(self.replay_dpy) | xlib.XCloseDisplay(self.replay_dpy) | |||
# cheap wakeup() equivalent for compatibility | # cheap wakeup() equivalent for compatibility | |||
glib.idle_add(self._kbd_event_callback, None) | glib.idle_add(self._event_callback, None) | |||
glib.idle_add(self._btn_event_callback, None) | ||||
self.stopped = True | self.stopped = True | |||
self.lock.release() | self.lock.release() | |||
return | return | |||
# initialize recording context | # initialize recording context | |||
ev_ranges = [] | ev_ranges = [] | |||
dev_ranges = [] | dev_ranges = [] | |||
if self.input_types & InputType.keyboard: | if self.input_types & InputType.keyboard: | |||
ev_ranges.append([xlib.FocusIn, xlib.FocusOut]) | ev_ranges.append([xlib.FocusIn, xlib.FocusOut]) | |||
skipping to change at line 410 | skipping to change at line 404 | |||
self.lock.release() | self.lock.release() | |||
if __name__ == '__main__': | if __name__ == '__main__': | |||
def callback(data): | def callback(data): | |||
values = {} | values = {} | |||
for k in dir(data): | for k in dir(data): | |||
if k[0] == '_': continue | if k[0] == '_': continue | |||
values[k] = getattr(data, k) | values[k] = getattr(data, k) | |||
print(values) | print(values) | |||
glib.threads_init() | ||||
kl = InputListener(callback) | kl = InputListener(callback) | |||
try: | try: | |||
# keep running only while the listener is alive | # keep running only while the listener is alive | |||
kl.start() | kl.start() | |||
while kl.is_alive(): | while kl.is_alive(): | |||
glib.main_context_default().iteration() | glib.main_context_default().iteration() | |||
except KeyboardInterrupt: | except KeyboardInterrupt: | |||
pass | pass | |||
# check if the thread terminated unexpectedly | # check if the thread terminated unexpectedly | |||
End of changes. 7 change blocks. | ||||
14 lines changed or deleted | 7 lines changed or added |