From 1833b8c2dce9849953bd9cf63a1af791799a8f9f Mon Sep 17 00:00:00 2001 From: Asura Date: Thu, 23 Jun 2022 01:06:30 -0700 Subject: [PATCH 1/3] fix(pynput): Convert keysym to keycode according to the system input source --- pynput_service.py | 58 ++++++++++------------------------------------- 1 file changed, 12 insertions(+), 46 deletions(-) diff --git a/pynput_service.py b/pynput_service.py index d8df09e96..30bdd90f9 100644 --- a/pynput_service.py +++ b/pynput_service.py @@ -1,65 +1,32 @@ from pynput.keyboard import Key, Controller from pynput.keyboard._xorg import KeyCode from pynput._util.xorg import display_manager -import Xlib import os import sys import socket +from Xlib.ext.xtest import fake_input +from Xlib import X KeyCode._from_symbol("\0") # test + class MyController(Controller): def _handle(self, key, is_press): """Resolves a key identifier and sends a keyboard event. :param event: The *X* keyboard event. :param int keysym: The keysym to handle. """ - event = Xlib.display.event.KeyPress if is_press \ - else Xlib.display.event.KeyRelease + event = X.KeyPress if is_press \ + else X.KeyRelease + keysym = self._keysym(key) + # Get keycode according to system language + keycode = self._display.keysym_to_keycode(keysym) + print(keycode) - # Make sure to verify that the key was resolved - if keysym is None: - raise self.InvalidKeyException(key) + fake_input(self._display, event, keycode) + self._display.sync() - # If the key has a virtual key code, use that immediately with - # fake_input; fake input,being an X server extension, has access to - # more internal state that we do - if key.vk is not None: - with display_manager(self._display) as dm: - Xlib.ext.xtest.fake_input( - dm, - Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease, - dm.keysym_to_keycode(key.vk)) - - # Otherwise use XSendEvent; we need to use this in the general case to - # work around problems with keyboard layouts - else: - try: - keycode, shift_state = self.keyboard_mapping[keysym] - with self.modifiers as modifiers: - alt_gr = Key.alt_gr in modifiers - if alt_gr: - self._send_key(event, keycode, shift_state) - else: - with display_manager(self._display) as dm: - Xlib.ext.xtest.fake_input( - dm, - Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease, - keycode) - - except KeyError: - with self._borrow_lock: - keycode, index, count = self._borrows[keysym] - self._send_key( - event, - keycode, - index_to_shift(self._display, index)) - count += 1 if is_press else -1 - self._borrows[keysym] = (keycode, index, count) - - # Notify any running listeners - self._emit('_on_fake_event', key, is_press) keyboard = MyController() @@ -77,7 +44,7 @@ server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) server.bind(server_address) server.listen(1) clientsocket, address = server.accept() -os.system('chmod a+rw %s'%server_address) +os.system('chmod a+rw %s' % server_address) print("Got pynput connection") @@ -121,4 +88,3 @@ def loop(): loop() clientsocket.close() server.close() - From 8aeacf77b3faf3f54e66b205875d5ab618c97924 Mon Sep 17 00:00:00 2001 From: Asura <99897242+asur4s@users.noreply.github.com> Date: Thu, 23 Jun 2022 19:27:10 +0800 Subject: [PATCH 2/3] fix: remove print --- pynput_service.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pynput_service.py b/pynput_service.py index 30bdd90f9..382df9bed 100644 --- a/pynput_service.py +++ b/pynput_service.py @@ -22,7 +22,6 @@ class MyController(Controller): keysym = self._keysym(key) # Get keycode according to system language keycode = self._display.keysym_to_keycode(keysym) - print(keycode) fake_input(self._display, event, keycode) self._display.sync() From c842642c026a948257caf2a6e43a7f187ab6084e Mon Sep 17 00:00:00 2001 From: Asura <99897242+asur4s@users.noreply.github.com> Date: Fri, 24 Jun 2022 12:01:22 +0800 Subject: [PATCH 3/3] Replaced fake_input with display_manager's send_event --- pynput_service.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/pynput_service.py b/pynput_service.py index 382df9bed..24edcc1f9 100644 --- a/pynput_service.py +++ b/pynput_service.py @@ -6,6 +6,7 @@ import sys import socket from Xlib.ext.xtest import fake_input from Xlib import X +import Xlib KeyCode._from_symbol("\0") # test @@ -16,15 +17,31 @@ class MyController(Controller): :param event: The *X* keyboard event. :param int keysym: The keysym to handle. """ - event = X.KeyPress if is_press \ - else X.KeyRelease - keysym = self._keysym(key) - # Get keycode according to system language - keycode = self._display.keysym_to_keycode(keysym) + event = Xlib.display.event.KeyPress if is_press \ + else Xlib.display.event.KeyRelease + + origin_keysym = self._keysym(key) + keycode = self._display.keysym_to_keycode(origin_keysym) + + with display_manager(self._display) as dm, self.modifiers as modifiers: + # Under certain cimcumstances, such as when running under Xephyr, + # the value returned by dm.get_input_focus is an int + window = dm.get_input_focus().focus + send_event = getattr( + window, + 'send_event', + lambda event: dm.send_event(window, event)) + send_event(event( + detail=keycode, + state=self._shift_mask(modifiers), + time=0, + root=dm.screen().root, + window=window, + same_screen=0, + child=Xlib.X.NONE, + root_x=0, root_y=0, event_x=0, event_y=0)) - fake_input(self._display, event, keycode) - self._display.sync() keyboard = MyController()