Spaces:
Running
Running
File size: 4,550 Bytes
399b80c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | import os
import ctypes
import ctypes.util
import numpy as np
# A helper function to convert data from Xlib to byte array.
import struct, array
# Define ctypes version of XFixesCursorImage structure.
PIXEL_DATA_PTR = ctypes.POINTER(ctypes.c_ulong)
Atom = ctypes.c_ulong
class XFixesCursorImage(ctypes.Structure):
"""
See /usr/include/X11/extensions/Xfixes.h
typedef struct {
short x, y;
unsigned short width, height;
unsigned short xhot, yhot;
unsigned long cursor_serial;
unsigned long *pixels;
if XFIXES_MAJOR >= 2
Atom atom; /* Version >= 2 only */
const char *name; /* Version >= 2 only */
endif
} XFixesCursorImage;
"""
_fields_ = [('x', ctypes.c_short),
('y', ctypes.c_short),
('width', ctypes.c_ushort),
('height', ctypes.c_ushort),
('xhot', ctypes.c_ushort),
('yhot', ctypes.c_ushort),
('cursor_serial', ctypes.c_ulong),
('pixels', PIXEL_DATA_PTR),
('atom', Atom),
('name', ctypes.c_char_p)]
class Display(ctypes.Structure):
pass
class Xcursor:
display = None
def __init__(self, display=None):
if not display:
try:
display = os.environ["DISPLAY"].encode("utf-8")
except KeyError:
raise Exception("$DISPLAY not set.")
# XFixeslib = ctypes.CDLL('libXfixes.so')
XFixes = ctypes.util.find_library("Xfixes")
if not XFixes:
raise Exception("No XFixes library found.")
self.XFixeslib = ctypes.cdll.LoadLibrary(XFixes)
# xlib = ctypes.CDLL('libX11.so.6')
x11 = ctypes.util.find_library("X11")
if not x11:
raise Exception("No X11 library found.")
self.xlib = ctypes.cdll.LoadLibrary(x11)
# Define ctypes' version of XFixesGetCursorImage function
XFixesGetCursorImage = self.XFixeslib.XFixesGetCursorImage
XFixesGetCursorImage.restype = ctypes.POINTER(XFixesCursorImage)
XFixesGetCursorImage.argtypes = [ctypes.POINTER(Display)]
self.XFixesGetCursorImage = XFixesGetCursorImage
XOpenDisplay = self.xlib.XOpenDisplay
XOpenDisplay.restype = ctypes.POINTER(Display)
XOpenDisplay.argtypes = [ctypes.c_char_p]
if not self.display:
self.display = self.xlib.XOpenDisplay(display) # (display) or (None)
def argbdata_to_pixdata(self, data, len):
if data == None or len < 1: return None
# Create byte array
b = array.array('b', b'\x00' * 4 * len)
offset, i = 0, 0
while i < len:
argb = data[i] & 0xffffffff
rgba = (argb << 8) | (argb >> 24)
b1 = (rgba >> 24) & 0xff
b2 = (rgba >> 16) & 0xff
b3 = (rgba >> 8) & 0xff
b4 = rgba & 0xff
struct.pack_into("=BBBB", b, offset, b1, b2, b3, b4)
offset = offset + 4
i = i + 1
return b
def getCursorImageData(self):
# Call the function. Read data of cursor/mouse-pointer.
cursor_data = self.XFixesGetCursorImage(self.display)
if not (cursor_data and cursor_data[0]):
raise Exception("Cannot read XFixesGetCursorImage()")
# Note: cursor_data is a pointer, take cursor_data[0]
return cursor_data[0]
def getCursorImageArray(self):
data = self.getCursorImageData()
# x, y = data.x, data.y
height, width = data.height, data.width
bytearr = self.argbdata_to_pixdata(data.pixels, height * width)
imgarray = np.array(bytearr, dtype=np.uint8)
imgarray = imgarray.reshape(height, width, 4)
del bytearr
return imgarray
def getCursorImageArrayFast(self):
data = self.getCursorImageData()
# x, y = data.x, data.y
height, width = data.height, data.width
bytearr = ctypes.cast(data.pixels, ctypes.POINTER(ctypes.c_ulong * height * width))[0]
imgarray = np.array(bytearray(bytearr))
imgarray = imgarray.reshape(height, width, 8)[:, :, (0, 1, 2, 3)]
del bytearr
return imgarray
def saveImage(self, imgarray, text):
from PIL import Image
img = Image.fromarray(imgarray)
img.save(text)
if __name__ == "__main__":
cursor = Xcursor()
imgarray = cursor.getCursorImageArrayFast()
cursor.saveImage(imgarray, 'cursor_image.png')
|