vdi-cloud/docs/evidence/linux-gpu-20261111/double-cursor-check.py

45 lines
2.3 KiB
Python

"""Run on the box with a focused, live Ubuntu stream and clear wallpaper."""
import ctypes as C, json, subprocess, time, os
os.environ.update(DISPLAY=':0',XAUTHORITY='/home/armbian/.Xauthority')
import gi
gi.require_version('Gdk','3.0')
from gi.repository import Gdk
x=C.CDLL('libX11.so.6'); f=C.CDLL('libXfixes.so.3')
class Cursor(C.Structure):
_fields_=[('x',C.c_short),('y',C.c_short),('w',C.c_ushort),('h',C.c_ushort),
('hx',C.c_ushort),('hy',C.c_ushort),('serial',C.c_ulong),
('pixels',C.POINTER(C.c_ulong)),('atom',C.c_ulong),('name',C.c_char_p)]
x.XOpenDisplay.argtypes=[C.c_char_p]; x.XOpenDisplay.restype=C.c_void_p
x.XFree.argtypes=[C.c_void_p]; x.XCloseDisplay.argtypes=[C.c_void_p]
f.XFixesGetCursorImage.argtypes=[C.c_void_p];f.XFixesGetCursorImage.restype=C.POINTER(Cursor)
display=x.XOpenDisplay(None); assert display
pid=int(subprocess.check_output(['pgrep','-x','moonlight']).strip())
def focused():
assert int(subprocess.check_output(['xdotool','getwindowfocus','getwindowpid']).strip())==pid
def move(px,py):
subprocess.run(['xdotool','mousemove',str(px),str(py)],check=True)
time.sleep(.5)
def patch(px,py):
p=Gdk.pixbuf_get_from_window(Gdk.get_default_root_window(),px-8,py-8,64,64)
assert p and p.get_n_channels()==3
return bytes(p.get_pixels())
results=[]
try:
focused()
for px,py in [(900,900),(1300,900),(1800,900)]:
move(400,1100); before=patch(px,py)
move(px,py); after=patch(px,py)
diffs=[max(abs(a-b) for a,b in zip(before[i:i+3],after[i:i+3])) for i in range(0,len(before)-2,3)]
ptr=f.XFixesGetCursorImage(display); assert ptr
try:
c=ptr.contents
opaque=sum(((c.pixels[i]>>24)&255)>0 for i in range(c.w*c.h))
assert opaque>0 and (c.x,c.y)==(px,py)
results.append(dict(point=[px,py],video_pixels_changed_over_25=sum(v>25 for v in diffs),
max_video_channel_difference=max(diffs),local_shape=[c.w,c.h,c.hx,c.hy],
local_opaque_pixels=opaque))
finally:x.XFree(ptr)
focused()
print(json.dumps(dict(method='XGetImage-style root capture excludes local X11 cursor; compare clear wallpaper at identical coordinates',pid=pid,points=results)))
finally:x.XCloseDisplay(display)