how can i use python xlib to generate a single keypress?

  • Last Update :
  • Techknowledgy :

I'll use ctypes to show you how it could work, but porting it to python-xlib should be straightforward. So lets start with loading the library:

import ctypes
X11 = ctypes.CDLL("libX11.so")

and defining the structures needed:

class Display(ctypes.Structure):
   ""
" opaque struct "
""

class XKeyEvent(ctypes.Structure):
   _fields_ = [
      ('type', ctypes.c_int),
      ('serial', ctypes.c_ulong),
      ('send_event', ctypes.c_int),
      ('display', ctypes.POINTER(Display)),
      ('window', ctypes.c_ulong),
      ('root', ctypes.c_ulong),
      ('subwindow', ctypes.c_ulong),
      ('time', ctypes.c_ulong),
      ('x', ctypes.c_int),
      ('y', ctypes.c_int),
      ('x_root', ctypes.c_int),
      ('y_root', ctypes.c_int),
      ('state', ctypes.c_uint),
      ('keycode', ctypes.c_uint),
      ('same_screen', ctypes.c_int),
   ]

class XEvent(ctypes.Union):
   _fields_ = [
      ('type', ctypes.c_int),
      ('xkey', XKeyEvent),
      ('pad', ctypes.c_long * 24),
   ]

X11.XOpenDisplay.restype = ctypes.POINTER(Display)

Now we just need to send the event to the root window:

display = X11.XOpenDisplay(None)
key = XEvent(type = 2).xkey #KeyPress
key.keycode = X11.XKeysymToKeycode(display, 0xffcc) #F15
key.window = key.root = X11.XDefaultRootWindow(display)
X11.XSendEvent(display, key.window, True, 1, ctypes.byref(key))
X11.XCloseDisplay(display)

Suggestion : 2

Xlib.ext.record.AllClients()

def listen(self):
   self.grab()
while True:
   evt = self.disp.next_event()
if evt.type in [X.KeyPress, X.KeyRelease]:
   keycode = evt.detail
keysym = self.disp.keycode_to_keysym(keycode, 0)
char = XK.keysym_to_string(keysym)
self.disp.allow_events(X.ReplayKeyboard, X.CurrentTime)

self.mode(self, evt, char)

if evt.type == X.DestroyNotify:
   if evt.window.id == self.id:
   self.ungrab()
return
def normal_mode(self, event, char):
   events.append(event)

if event.type == X.KeyPress and char:
   pressed.add(event_to_string(self, event))
return

if event.type != X.KeyRelease:
   return

handled = False
if len(pressed) > 1:
   paste_style(self, pressed)
handled = True
elif len(pressed) == 1:
   # Get the only element in pressed
ev = next(iter(pressed))
handled = handle_single_key(self, ev)

# replay events to Inkscape
if we couldn 't handle them
if not handled:
   replay(self)

events.clear()
pressed.clear()
def __init__(self):
   threading.Thread.__init__(self)
self.finished = threading.Event()

# Give these some initial values
self.mouse_position_x = 0
self.mouse_position_y = 0
self.ison = {
   "shift": False,
   "caps": False
}

# Compile our regex statements.
self.isshift = re.compile('^Shift')
self.iscaps = re.compile('^Caps_Lock')
self.shiftablechar = re.compile('^[a-z0-9]$|^minus$|^equal$|^bracketleft$|^bracketright$|^semicolon$|^backslash$|^apostrophe$|^comma$|^period$|^slash$|^grave$')
self.logrelease = re.compile('.*')
self.isspace = re.compile('^space$')

# Assign
default
function actions(do nothing).
self.KeyDown = lambda x: True
self.KeyUp = lambda x: True
self.MouseAllButtonsDown = lambda x: True
self.MouseAllButtonsUp = lambda x: True

self.contextEventMask = [X.KeyPress, X.MotionNotify]

# Hook to our display.
self.local_dpy = display.Display()
self.record_dpy = display.Display()
def makekeyhookevent(self, keysym, event):
   storewm = self.xwindowinfo()
if event.type == X.KeyPress:
   MessageName = "key down"
elif event.type == X.KeyRelease:
   MessageName = "key up"
return pyxhookkeyevent(
   storewm["handle"],
   storewm["name"],
   storewm["class"],
   self.lookup_keysym(keysym),
   self.asciivalue(keysym),
   False,
   event.detail,
   MessageName
)
def __sendKeyPressEvent(self, keyCode, modifiers, theWindow = None):
   if theWindow is None:
   focus = self.localDisplay.get_input_focus().focus
else:
   focus = theWindow
keyEvent = event.KeyPress(
   detail = keyCode,
   time = X.CurrentTime,
   root = self.rootWindow,
   window = focus,
   child = X.NONE,
   root_x = 1,
   root_y = 1,
   event_x = 1,
   event_y = 1,
   state = modifiers,
   same_screen = 1
)
focus.send_event(keyEvent)
def run(self):
   # Create a recording context;
we only want key and mouse events
self.ctx = self.recordDisplay.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.ButtonPress),
      #X.KeyRelease,
      'errors': (0, 0),
      'client_started': False,
      'client_died': False,
   }])

# Enable the context;
this only returns after a call to record_disable_context,
#
while calling the callback
function in the meantime
logger.info("XRecord interface thread starting")
self.recordDisplay.record_enable_context(self.ctx, self.__processEvent)
# Finally free the context
self.recordDisplay.record_free_context(self.ctx)
self.recordDisplay.close()

Suggestion : 3

Last Updated : 28 Jun, 2022

Keylogger in Linux
pyxhook requires python-Xlib. Install it if you don’t have it already. 

sudo apt - get install python - xlib

Suggestion : 4

When a keyboard grab activates before generating any actual KeyPress event that activates the grab, G is the grab_window, and F is the current focus, the X server does the following: , When a keyboard grab deactivates after generating any actual KeyRelease event that deactivates the grab, G is the grab_window, and F is the current focus, the X server does the following: , Some of the terms used in this book are unique to X, and other terms that are common to other window systems have different meanings in X. You may find it helpful to refer to the glossary, which is located at the end of the book. , The ascent member is the logical extent of the font above the baseline that is used for determining line spacing. Specific characters may extend beyond this.

The encoding and interpretation of the display name are implementation-dependent. Strings in the Host Portable Character Encoding are supported; support for other characters is implementation-dependent. On POSIX-conformant systems, the display name or DISPLAY environment variable can be a string in the format:

protocol / hostname: number.screen_number

dual - headed: 0.1
AllPlanes

The XPixmapFormatValues structure provides an interface to the pixmap format information that is returned at the time of a connection setup. It contains:

typedef struct {
   int depth;
   int bits_per_pixel;
   int scanline_pad;
}
XPixmapFormatValues;

The following concepts may serve to make the explanation of visual types clearer. The screen can be color or grayscale, can have a colormap that is writable or read-only, and can also have a colormap whose indices are decomposed into separate RGB pieces, provided one is not on a grayscale screen. This leads to the following diagram:

                      Color Gray - Scale
                      R / O R / W R / O R / W
                         -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
                      Undecomposed Static Pseudo Static Gray
                      Colormap Color Color Gray Scale

                      Decomposed True Direct
                      Colormap Color Color
                      -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

/* Window attribute value mask bits */

/* Window attribute value mask bits */
#define CWBackPixmap(1 L << 0)
#define CWBackPixel(1 L << 1)
#define CWBorderPixmap(1 L << 2)
#define CWBorderPixel(1 L << 3)
#define CWBitGravity(1 L << 4)
#define CWWinGravity(1 L << 5)
#define CWBackingStore(1 L << 6)
#define CWBackingPlanes(1 L << 7)
#define CWBackingPixel(1 L << 8)
#define CWOverrideRedirect(1 L << 9)
#define CWSaveUnder(1 L << 10)
#define CWEventMask(1 L << 11)
#define CWDontPropagate(1 L << 12)
#define CWColormap(1 L << 13)
#define CWCursor(1 L << 14)

/* Values */

typedef struct {
   Pixmap background_pixmap; /* background, None, or ParentRelative */
   unsigned long background_pixel; /* background pixel */
   Pixmap border_pixmap; /* border of the window or CopyFromParent */
   unsigned long border_pixel; /* border pixel value */
   int bit_gravity; /* one of bit gravity values */
   int win_gravity; /* one of the window gravity values */
   int backing_store; /* NotUseful, WhenMapped, Always */
   unsigned long backing_planes; /* planes to be preserved if possible */
   unsigned long backing_pixel; /* value to use in restoring planes */
   Bool save_under; /* should bits under be saved? (popups) */
   long event_mask; /* set of events that should be saved */
   long do_not_propagate_mask; /* set of events that should not propagate */
   Bool override_redirect; /* boolean value for override_redirect */
   Colormap colormap; /* color map to be associated with window */
   Cursor cursor; /* cursor to be displayed (or None) */
}
XSetWindowAttributes;

/* Configure window value mask bits */
#define CWX(1 << 0)
#define CWY(1 << 1)
#define CWWidth(1 << 2)
#define CWHeight(1 << 3)
#define CWBorderWidth(1 << 4)
#define CWSibling(1 << 5)
#define CWStackMode(1 << 6)

/* Values */

typedef struct {
   int x, y;
   int width, height;
   int border_width;
   Window sibling;
   int stack_mode;
}
XWindowChanges;

Suggestion : 5

The pyautogui module can send virtual keypresses and mouse clicks to Windows, OS X, and Linux. Depending on which operating system you’re using, you may have to install some other modules (called dependencies) before you can install PyAutoGUI.,On Linux, run sudo pip3 install python3-xlib, sudo apt-get install scrot, sudo apt-get install python3-tk, and sudo apt-get install python3-dev. (Scrot is a screenshot program that PyAutoGUI uses.), On Linux, run sudo pip3 install python3-xlib, sudo apt-get install scrot, sudo apt-get install python3-tk, and sudo apt-get install python3-dev. (Scrot is a screenshot program that PyAutoGUI uses.) ,After these dependencies are installed, run pip install pyautogui (or pip3 on OS X and Linux) to install PyAutoGUI.

>>>
import pyautogui
   >>>
   pyautogui.PAUSE = 1 >>>
   pyautogui.FAILSAFE = True

>>>
import pyautogui
   >>>
   pyautogui.size()
   (1920, 1080) >>>
   width, height = pyautogui.size()

>>>
import pyautogui
   >>>
   for i in range(10):
   pyautogui.moveTo(100, 100, duration = 0.25)
pyautogui.moveTo(200, 100, duration = 0.25)
pyautogui.moveTo(200, 200, duration = 0.25)
pyautogui.moveTo(100, 200, duration = 0.25)

>>> pyautogui.position()
   (311, 622) >>>
   pyautogui.position()
   (377, 481) >>>
   pyautogui.position()
   (1536, 637)

#! python3

# mouseNow.py - Displays the mouse cursor 's current position.
import pyautogui
print('Press Ctrl-C to quit.')
#TODO: Get and print the mouse coordinates.

   #! python3

   # mouseNow.py - Displays the mouse cursor 's current position.
   import pyautogui
   print('Press Ctrl-C to quit.')
   try:
   while True:
      # TODO: Get and print the mouse coordinates.❶except KeyboardInterrupt: ❷print('\nDone.')

Suggestion : 6

The XChangeKeyboardControl() function changes control of a keyboard and operates on a XKeyboardControl structure: , To obtain the current control values for the keyboard, use XGetKeyboardControl(). , To turn on keyboard auto-repeat, use XAutoRepeatOn(). , A bell generator connected with the console but not directly on a keyboard is treated as if it were part of the keyboard. The order in which controls are verified and altered is server-dependent. If an error is generated, a subset of the controls may have been altered.

/* Mask bits for ChangeKeyboardControl */

#define KBKeyClickPercent(1 L << 0)
#define KBBellPercent(1 L << 1)
#define KBBellPitch(1 L << 2)
#define KBBellDuration(1 L << 3)
#define KBLed(1 L << 4)
#define KBLedMode(1 L << 5)
#define KBKey(1 L << 6)
#define KBAutoRepeatMode(1 L << 7)
/* Values */

typedef struct {
   int key_click_percent;
   int bell_percent;
   int bell_pitch;
   int bell_duration;
   int led;
   int led_mode; /* LedModeOn, LedModeOff */
   int key;
   int auto_repeat_mode;
   /* AutoRepeatModeOff, AutoRepeatModeOn, 
                            	AutoRepeatModeDefault */
}
XKeyboardControl;