45 lines
2.3 KiB
Python
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)
|