11#!/usr/bin/python3
22# -*- coding: utf-8 -*-
33
4- from operator import le
5-
4+ # local modules
65from .base import DSIBase
76from .window import WindowBase
87from .image import Image
98
109# built-in modules
10+ import logging
1111import ctypes .util
1212from ctypes import (
1313 POINTER ,
3636
3737# Setup Xlib Structures
3838class Display (Structure ):
39- pass
39+ """
40+ https://tronche.com/gui/x/xlib/display/opening.html#Display\n
41+ /usr/include/X11/Xlib.h: 487
42+ """
4043
4144
4245class XImage (Structure ):
46+ """
47+ https://tronche.com/gui/x/xlib/graphics/images.html#XImage\n
48+ /usr/include/X11/Xlib.h: 360-394
49+ """
50+
4351 _fields_ = [
4452 ('width' , c_int ),
4553 ('height' , c_int ),
@@ -60,6 +68,11 @@ class XImage(Structure):
6068
6169
6270class XWindowAttributes (Structure ):
71+ """
72+ https://tronche.com/gui/x/xlib/window-information/XGetWindowAttributes.html\n
73+ /usr/include/X11/Xlib.h: 308-334
74+ """
75+
6376 _fields_ = [
6477 ("x" , c_int32 ),
6578 ("y" , c_int32 ),
@@ -88,6 +101,11 @@ class XWindowAttributes(Structure):
88101
89102
90103class XKeyEvent (Structure ):
104+ """
105+ https://tronche.com/gui/x/xlib/events/keyboard-pointer/keyboard-pointer.html#XKeyEvent\n
106+ /usr/include/X11/Xlib.h: 557-571
107+ """
108+
91109 _fields_ = [
92110 ('type' , c_int ),
93111 ('serial' , c_ulong ),
@@ -108,6 +126,11 @@ class XKeyEvent(Structure):
108126
109127
110128class XButtonEvent (ctypes .Structure ):
129+ """
130+ https://tronche.com/gui/x/xlib/events/keyboard-pointer/keyboard-pointer.html#XButtonEvent\n
131+ /usr/include/X11/Xlib.h: 575-589
132+ """
133+
111134 _fields_ = [
112135 ('type' , ctypes .c_int ),
113136 ('serial' , ctypes .c_ulong ),
@@ -128,17 +151,68 @@ class XButtonEvent(ctypes.Structure):
128151
129152
130153class XEvent (ctypes .Union ):
154+ """
155+ https://tronche.com/gui/x/xlib/events/structures.html#XEvent\n
156+ /usr/include/X11/Xlib.h: 973-1009
157+ """
131158 _fields_ = [
132159 ('type' , ctypes .c_int ),
133160 ('xkey' , XKeyEvent ),
134161 ('xbutton' , XButtonEvent ),
135162 ('pad' , ctypes .c_long * 24 ),
136163 ]
137164
165+
166+ class XErrorEvent (Structure ):
167+ """
168+ https://tronche.com/gui/x/xlib/event-handling/protocol-errors/default-handlers.html#XErrorEvent\n
169+ /usr/include/X11/Xlib.h: 924-932
170+ """
171+
172+ def __repr__ (self ) -> str :
173+ return f"XErrorEvent(type={ self .type } , serial={ self .serial } , error_code={ self .error_code } , request_code={ self .request_code } , minor_code={ self .minor_code } )"
174+
175+ _fields_ = [
176+ ("type" , c_int ),
177+ ("display" , POINTER (Display )),
178+ ("serial" , c_ulong ),
179+ ("error_code" , c_ubyte ),
180+ ("request_code" , c_ubyte ),
181+ ("minor_code" , c_ubyte ),
182+ ("resourceid" , c_void_p ),
183+ ]
184+
185+
186+ logger = logging .getLogger (__name__ )
187+ logger .setLevel (logging .CRITICAL )
188+
189+
190+ @ctypes .CFUNCTYPE (c_int , POINTER (Display ), POINTER (XErrorEvent ))
191+ def error_handler (_ , event ):
192+ logger .error ("%s" , event .contents )
193+ return 0
194+
195+
196+ xlib .XSetErrorHandler (error_handler )
197+
198+
199+ def get_logger () -> logging .Logger :
200+ """
201+ Returns a logger that is responsible for logging XErrorEvents.
202+ The logger is set to CRITICAL. So it will not log anything.
203+ To make it log something, set the log level at least to ERROR.
204+ You can archive this with "logger.setLevel(logging.ERROR)".
205+ """
206+ return logger
207+
138208# Setup Xlib Variables
139209
140210
141211class Masks (object ):
212+ """
213+ https://tronche.com/gui/x/xlib/events/mask.html\n
214+ /usr/include/X11/X.h: 150-175
215+ """
142216 NoEventMask = 0
143217 KeyPressMask = 1
144218 KeyReleaseMask = 2
@@ -168,6 +242,10 @@ class Masks(object):
168242
169243
170244class EventTypes (object ):
245+ """
246+ https://tronche.com/gui/x/xlib/events/types.html\n
247+ /usr/include/X11/X.h: 181-215
248+ """
171249 KeyPress = 2
172250 KeyRelease = 3
173251 ButtonPress = 4
@@ -206,6 +284,10 @@ class EventTypes(object):
206284
207285
208286class KeyMasks (object ):
287+ """
288+ https://tronche.com/gui/x/xlib/events/keyboard-pointer/keyboard-pointer.html\n
289+ /usr/include/X11/X.h: 221-228
290+ """
209291 ShiftMask = 1
210292 LockMask = 2
211293 ControlMask = 4
@@ -217,6 +299,10 @@ class KeyMasks(object):
217299
218300
219301class ButtonCodes (object ):
302+ """
303+ https://tronche.com/gui/x/xlib/events/keyboard-pointer/keyboard-pointer.html\n
304+ /usr/include/X11/X.h: 259-263
305+ """
220306 AnyButton = 0
221307 Button1 = 1
222308 Button2 = 2
@@ -265,13 +351,15 @@ class ButtonCodes(object):
265351
266352
267353def get_window_property (window_xid : int , property : str , type : _SimpleCData ):
354+ """
355+ https://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html
356+ """
268357 actual_type_return = c_ulong ()
269358 actual_format_return = c_int ()
270359 nitems_return = c_ulong ()
271360 bytes_after_return = c_ulong ()
272361 prop_return = POINTER (c_ubyte )()
273362
274- # https://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html
275363 xlib .XGetWindowProperty (
276364 display ,
277365 window_xid ,
@@ -451,6 +539,9 @@ def send_mouse_click(self, x: int, y: int, button: ButtonCodes = ButtonCodes.But
451539
452540
453541def get_active_window_xid () -> int :
542+ """
543+ Returns the XID of the active window.
544+ """
454545 return get_window_property (
455546 root_window ,
456547 "_NET_ACTIVE_WINDOW" ,
@@ -459,6 +550,10 @@ def get_active_window_xid() -> int:
459550
460551
461552def get_connected_xids (window ):
553+ """
554+ https://tronche.com/gui/x/xlib/window-information/XQueryTree.html\n
555+ Uses XQueryTree to get the XIDs of connected windows.
556+ """
462557 root_return = c_ulong ()
463558 parent_return = c_ulong ()
464559 children_return = POINTER (c_ulong )()
@@ -478,10 +573,16 @@ def get_connected_xids(window):
478573 for xid in range (nitems_return .value ):
479574 xids .append (children_return [xid ])
480575
576+ # don't forget to free the memory or you will be fucked
577+ xlib .XFree (children_return )
578+
481579 return xids
482580
483581
484582def get_all_windows () -> list :
583+ """
584+ Get all window XIDs. By recursively getting all connected windows.
585+ """
485586 final = get_connected_xids (root_window )
486587 next = final .copy ()
487588
0 commit comments