7373# KeyPress action gets the current keyboard group using XkbGetState from libX11.so using ctypes definitions
7474# under Wayland the keyboard group is None resulting in using the first keyboard group
7575# KeyPress action translates keysyms to keycodes using the GDK keymap
76- # KeyPress, MouseScroll, and MouseClick actions use XTest (under X11) or uinput.
76+ # KeyPress, MouseScroll, and MouseClick actions use uinput.
7777# For uinput to work the user must have write access for /dev/uinput.
78- # To get this access run sudo setfacl -m u:${user}:rw /dev/uinput
78+ # The Solaar udev rule should set this up
79+ # Otherwise run sudo setfacl -m u:${user}:rw /dev/uinput
7980#
8081# Rule GUI keyname determination uses a local file generated
8182# from http://cgit.freedesktop.org/xorg/proto/x11proto/plain/keysymdef.h
8586# Setting up is complex because there are several systems that each provide partial facilities:
8687# GDK - always available (when running with a window system) but only provides access to keymap
8788# X11 - provides access to active process and process with window under mouse and current modifier keys
88- # Xtest extension to X11 - provides input simulation, partly works under Wayland
89- # Wayland - provides input simulation
89+ # uinput and evdev - provides input simulation
9090
9191XK_KEYS : Dict [str , int ] = keysymdef .key_symbols
9292
111111 )
112112
113113try :
114- import Xlib
115-
116114 _x11 = None # X11 might be available
117115except Exception :
118116 _x11 = False # X11 is not available
119117
120118# Globals
121- xtest_available = True # Xtest might be available
122119xdisplay = None
123120
124121
@@ -170,7 +167,7 @@ class XkbStateRec(ctypes.Structure):
170167
171168
172169def x11_setup ():
173- global _x11 , xdisplay , modifier_keycodes , NET_ACTIVE_WINDOW , NET_WM_PID , WM_CLASS , xtest_available
170+ global _x11 , xdisplay , modifier_keycodes , NET_ACTIVE_WINDOW , NET_WM_PID , WM_CLASS
174171 if _x11 is not None :
175172 return _x11
176173 try :
@@ -187,7 +184,6 @@ def x11_setup():
187184 except Exception :
188185 logger .warning ("X11 not available - some rule capabilities inoperable" , exc_info = sys .exc_info ())
189186 _x11 = False
190- xtest_available = False
191187 return _x11
192188
193189
@@ -272,10 +268,6 @@ def setup_uinput():
272268 logger .warning ("cannot create uinput device: %s" , e )
273269
274270
275- if wayland : # Wayland can't use xtest so may as well set up uinput now
276- setup_uinput ()
277-
278-
279271def kbdgroup ():
280272 if xkb_setup ():
281273 state = XkbStateRec ()
@@ -324,31 +316,6 @@ def xy_direction(_x, _y):
324316 return "noop"
325317
326318
327- def simulate_xtest (code , event ):
328- global xtest_available
329- if x11_setup () and xtest_available :
330- try :
331- event = (
332- Xlib .X .KeyPress
333- if event == _KEY_PRESS
334- else Xlib .X .KeyRelease
335- if event == _KEY_RELEASE
336- else Xlib .X .ButtonPress
337- if event == _BUTTON_PRESS
338- else Xlib .X .ButtonRelease
339- if event == _BUTTON_RELEASE
340- else None
341- )
342- Xlib .ext .xtest .fake_input (xdisplay , event , code )
343- xdisplay .sync ()
344- if logger .isEnabledFor (logging .DEBUG ):
345- logger .debug ("xtest simulated input %s %s %s" , xdisplay , event , code )
346- return True
347- except Exception as e :
348- xtest_available = False
349- logger .warning ("xtest fake input failed: %s" , e )
350-
351-
352319def simulate_uinput (what , code , arg ):
353320 global udevice
354321 if setup_uinput ():
@@ -364,30 +331,11 @@ def simulate_uinput(what, code, arg):
364331
365332
366333def simulate_key (code , event ): # X11 keycode but Solaar event code
367- if not wayland and simulate_xtest (code , event ):
368- return True
369334 if evdev and simulate_uinput (evdev .ecodes .EV_KEY , code - 8 , event ):
370335 return True
371336 logger .warning ("no way to simulate key input" )
372337
373338
374- def click_xtest (button , count ):
375- if isinstance (count , int ):
376- for _ in range (count ):
377- if not simulate_xtest (button [0 ], _BUTTON_PRESS ):
378- return False
379- if not simulate_xtest (button [0 ], _BUTTON_RELEASE ):
380- return False
381- else :
382- if count != RELEASE :
383- if not simulate_xtest (button [0 ], _BUTTON_PRESS ):
384- return False
385- if count != DEPRESS :
386- if not simulate_xtest (button [0 ], _BUTTON_RELEASE ):
387- return False
388- return True
389-
390-
391339def click_uinput (button , count ):
392340 if isinstance (count , int ):
393341 for _ in range (count ):
@@ -406,23 +354,13 @@ def click_uinput(button, count):
406354
407355
408356def click (button , count ):
409- if not wayland and click_xtest (button , count ):
410- return True
411357 if click_uinput (button , count ):
412358 return True
413359 logger .warning ("no way to simulate mouse click" )
414360 return False
415361
416362
417363def simulate_scroll (dx , dy ):
418- if not wayland and xtest_available :
419- success = True
420- if dx :
421- success = click_xtest (buttons ["scroll_right" if dx > 0 else "scroll_left" ], count = abs (dx ))
422- if dy and success :
423- success = click_xtest (buttons ["scroll_up" if dy > 0 else "scroll_down" ], count = abs (dy ))
424- if success :
425- return True
426364 if setup_uinput ():
427365 success = True
428366 if dx :
0 commit comments