功能:接入Linux原生光标并完善设备接入工具
No files matched your search
@@ -0,0 +1,28 @@
|
||||
[
|
||||
{
|
||||
"host": "192.168.1.72",
|
||||
"normal": {
|
||||
"width": 24,
|
||||
"height": 24,
|
||||
"visible_pixels": 240
|
||||
},
|
||||
"adapter": {
|
||||
"width": 24,
|
||||
"height": 24,
|
||||
"visible_pixels": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"host": "192.168.1.71",
|
||||
"normal": {
|
||||
"width": 16,
|
||||
"height": 16,
|
||||
"visible_pixels": 0
|
||||
},
|
||||
"adapter": {
|
||||
"width": 16,
|
||||
"height": 16,
|
||||
"visible_pixels": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"ubuntu": {
|
||||
"measured_clicks": 28,
|
||||
"matched_source_events": 28,
|
||||
"max_coordinate_error_pixels": 0.9814453125,
|
||||
"p50_ms": 188.9504005,
|
||||
"p95_ms": 468.920931
|
||||
},
|
||||
"kylin": {
|
||||
"measured_clicks": 28,
|
||||
"matched_source_events": 28,
|
||||
"max_coordinate_error_pixels": 0.74267578125,
|
||||
"p50_ms": 127.61443249999999,
|
||||
"p95_ms": 168.630841
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
5d4330f703d7f8e053bc3795ca42bdaf231c9e9dd8ebb00a612013adbcccee03
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"192.168.1.71": {
|
||||
"host_py_sha256": "41f6a9a7dcbe3b916864eb3a4bb1b2cbaf669c779256f913fbeef4f53cf09b65",
|
||||
"client_sha256": "5d4330f703d7f8e053bc3795ca42bdaf231c9e9dd8ebb00a612013adbcccee03",
|
||||
"status": "600\nActiveState=inactive\n"
|
||||
},
|
||||
"192.168.1.72": {
|
||||
"host_py_sha256": "41f6a9a7dcbe3b916864eb3a4bb1b2cbaf669c779256f913fbeef4f53cf09b65",
|
||||
"client_sha256": "5d4330f703d7f8e053bc3795ca42bdaf231c9e9dd8ebb00a612013adbcccee03",
|
||||
"status": "600\nActiveState=active\n39181 /usr/bin/python3 /home/test2/vdi-terminal/native-cursor-v1/host.py stream\n"
|
||||
},
|
||||
"box_helper_sha256": "44b3e8a0ca591fbde42cf3372d343ab4cb603c089e7805bbccf6d261b2e173ac"
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
"""Run only with the controlled GTK acceptance window filling the stream."""
|
||||
import ctypes as C
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import signal
|
||||
import statistics
|
||||
import struct
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
os.environ.update(DISPLAY=':0', XAUTHORITY='/home/armbian/.Xauthority')
|
||||
x = C.CDLL('libX11.so.6')
|
||||
fix = C.CDLL('libXfixes.so.3')
|
||||
test = C.CDLL('libXtst.so.6')
|
||||
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.XDefaultRootWindow.argtypes = [C.c_void_p]
|
||||
x.XDefaultRootWindow.restype = C.c_ulong
|
||||
x.XFree.argtypes = [C.c_void_p]
|
||||
x.XSync.argtypes = [C.c_void_p, C.c_int]
|
||||
x.XWarpPointer.argtypes = [C.c_void_p, C.c_ulong, C.c_ulong, C.c_int,
|
||||
C.c_int, C.c_uint, C.c_uint, C.c_int, C.c_int]
|
||||
x.XGetImage.argtypes = [C.c_void_p, C.c_ulong, C.c_int, C.c_int,
|
||||
C.c_uint, C.c_uint, C.c_ulong, C.c_int]
|
||||
x.XGetImage.restype = C.c_void_p
|
||||
x.XGetPixel.argtypes = [C.c_void_p, C.c_int, C.c_int]
|
||||
x.XGetPixel.restype = C.c_ulong
|
||||
x.XDestroyImage.argtypes = [C.c_void_p]
|
||||
fix.XFixesGetCursorImage.argtypes = [C.c_void_p]
|
||||
fix.XFixesGetCursorImage.restype = C.POINTER(Cursor)
|
||||
test.XTestFakeButtonEvent.argtypes = [C.c_void_p, C.c_uint, C.c_int, C.c_ulong]
|
||||
d = x.XOpenDisplay(None)
|
||||
assert d
|
||||
root = x.XDefaultRootWindow(d)
|
||||
|
||||
|
||||
def native():
|
||||
p = fix.XFixesGetCursorImage(d)
|
||||
assert p
|
||||
try:
|
||||
c = p.contents
|
||||
return dict(x=c.x, y=c.y, w=c.w, h=c.h, hx=c.hx, hy=c.hy,
|
||||
pixels=[int(c.pixels[i]) & 0xffffffff for i in range(c.w*c.h)])
|
||||
finally:
|
||||
x.XFree(p)
|
||||
|
||||
|
||||
def warp(px, py):
|
||||
x.XWarpPointer(d, 0, root, 0, 0, 0, 0, px, py)
|
||||
x.XSync(d, 0)
|
||||
|
||||
|
||||
def decoded_sequence():
|
||||
im = x.XGetImage(d, root, 40, 1370, 640, 1, 0xffffffff, 2)
|
||||
assert im
|
||||
try:
|
||||
values = [x.XGetPixel(im, i*40+20, 0) & 0xffffff for i in range(16)]
|
||||
if any(0x202020 <= v <= 0xe0e0e0 for v in values):
|
||||
return -1
|
||||
return sum((1 << i) for i, v in enumerate(values) if v > 0xe0e0e0)
|
||||
finally:
|
||||
x.XDestroyImage(im)
|
||||
|
||||
|
||||
def flat_video_crop(px, py):
|
||||
im = x.XGetImage(d, root, px-40, py-40, 100, 100, 0xffffffff, 2)
|
||||
assert im
|
||||
try:
|
||||
pixels = [x.XGetPixel(im, a, b) & 0xffffff for b in range(100) for a in range(100)]
|
||||
# No baked-in pointer: uniform acceptance-window background at this point.
|
||||
ref = pixels[0]
|
||||
bad = sum(any(abs(((v >> s) & 255) - ((ref >> s) & 255)) > 8
|
||||
for s in (0, 8, 16)) for v in pixels)
|
||||
return dict(reference=ref, nonuniform_pixels=bad)
|
||||
finally:
|
||||
x.XDestroyImage(im)
|
||||
|
||||
|
||||
|
||||
start_sequence=decoded_sequence()
|
||||
results=[]
|
||||
for i in range(16):
|
||||
px,py=((300,800) if i%2==0 else (1500,900))
|
||||
warp(px,py);time.sleep(.18)
|
||||
start=time.monotonic_ns();test.XTestFakeButtonEvent(d,1,1,0);x.XSync(d,0)
|
||||
time.sleep(.04);test.XTestFakeButtonEvent(d,1,0,0);x.XSync(d,0)
|
||||
target=start_sequence+i+1
|
||||
while decoded_sequence()!=target and time.monotonic_ns()-start<2000000000:time.sleep(.002)
|
||||
seen=decoded_sequence();results.append(dict(seq=target,seen=seen,x=px,y=py));assert seen==target,results[-1]
|
||||
time.sleep(.08)
|
||||
# Two quick clicks before waiting for their combined numbered video update.
|
||||
start=decoded_sequence()
|
||||
for i in range(2):
|
||||
test.XTestFakeButtonEvent(d,1,1,0);x.XSync(d,0);time.sleep(.04);test.XTestFakeButtonEvent(d,1,0,0);x.XSync(d,0);time.sleep(.07)
|
||||
end=time.monotonic()+2
|
||||
while decoded_sequence()!=start+2 and time.monotonic()<end:time.sleep(.002)
|
||||
print(json.dumps(dict(clicks=results,double_click_start=start,double_click_end=decoded_sequence())))
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"192.168.1.71": {
|
||||
"status": "MainPID=194186\nExecStart={ path=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine ; argv[]=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine /home/test1/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 12:28:12 CST] ; stop_time=[n/a] ; pid=194186 ; code=(null) ; status=0/0 }\nId=vdi-sunshine.service\nActiveState=active\n\nMainPID=0\nExecStart={ path=/usr/bin/python3 ; argv[]=/usr/bin/python3 /home/test1/vdi-terminal/native-cursor-v1/host.py guard ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }\nId=vdi-native-cursor-guard.service\nActiveState=inactive\n\nMainPID=0\nId=vdi-native-cursor-source.service\nActiveState=inactive\nScreen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192\nVirtual-1 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 325mm x 203mm\n'Adwaita'\n24\n'default'\n1c3099bf924db3aee759b3d7c05e012569ef8650c400d1479144398795decc71 /opt/vdi-sunshine-0.21.0/usr/bin/sunshine\nno-runtime-dropin\n",
|
||||
"stderr": ""
|
||||
},
|
||||
"192.168.1.72": {
|
||||
"status": "MainPID=42901\nExecStart={ path=/home/test2/vdi-terminal/native-cursor-v1/sunshine ; argv[]=/home/test2/vdi-terminal/native-cursor-v1/sunshine /home/test2/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 12:29:41 CST] ; stop_time=[n/a] ; pid=42901 ; code=(null) ; status=0/0 }\nId=vdi-sunshine.service\nActiveState=active\n\nMainPID=42870\nExecStart={ path=/usr/bin/python3 ; argv[]=/usr/bin/python3 /home/test2/vdi-terminal/native-cursor-v1/host.py guard ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }\nId=vdi-native-cursor-guard.service\nActiveState=active\n\nMainPID=0\nId=vdi-native-cursor-source.service\nActiveState=inactive\nScreen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192\nVirtual-1 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 325mm x 203mm\n'Adwaita'\n24\n'default'\n61e1ecbc8db2df786b9760c652aa4b9885dff36c57d4af09616344314cb7c34c /usr/bin/sunshine\n/usr/bin/sunshine cap_sys_admin,cap_sys_nice=p\n",
|
||||
"stderr": ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"192.168.1.72": "MainPID=42703\nExecStart={ path=/usr/bin/sunshine ; argv[]=/usr/bin/sunshine /home/test2/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 12:25:39 CST] ; stop_time=[n/a] ; pid=42703 ; code=(null) ; status=0/0 }\nId=vdi-sunshine.service\nActiveState=active\n\nMainPID=0\nExecStart={ path=/usr/bin/python3 ; argv[]=/usr/bin/python3 /home/test2/vdi-terminal/native-cursor-v1/host.py guard ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }\nId=vdi-native-cursor-guard.service\nActiveState=inactive\n",
|
||||
"192.168.1.71": "MainPID=193092\nExecStart={ path=/home/test1/vdi-terminal/native-cursor-v1/sunshine ; argv[]=/home/test1/vdi-terminal/native-cursor-v1/sunshine /home/test1/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 12:26:14 CST] ; stop_time=[n/a] ; pid=193092 ; code=(null) ; status=0/0 }\nId=vdi-sunshine.service\nActiveState=active\n\nMainPID=193023\nExecStart={ path=/usr/bin/python3 ; argv[]=/usr/bin/python3 /home/test1/vdi-terminal/native-cursor-v1/host.py guard ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }\nId=vdi-native-cursor-guard.service\nActiveState=active\n"
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
"""Run only with the controlled GTK acceptance window filling the stream."""
|
||||
import ctypes as C
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import signal
|
||||
import statistics
|
||||
import struct
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
os.environ.update(DISPLAY=':0', XAUTHORITY='/home/armbian/.Xauthority')
|
||||
x = C.CDLL('libX11.so.6')
|
||||
fix = C.CDLL('libXfixes.so.3')
|
||||
test = C.CDLL('libXtst.so.6')
|
||||
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.XDefaultRootWindow.argtypes = [C.c_void_p]
|
||||
x.XDefaultRootWindow.restype = C.c_ulong
|
||||
x.XFree.argtypes = [C.c_void_p]
|
||||
x.XSync.argtypes = [C.c_void_p, C.c_int]
|
||||
x.XWarpPointer.argtypes = [C.c_void_p, C.c_ulong, C.c_ulong, C.c_int,
|
||||
C.c_int, C.c_uint, C.c_uint, C.c_int, C.c_int]
|
||||
x.XGetImage.argtypes = [C.c_void_p, C.c_ulong, C.c_int, C.c_int,
|
||||
C.c_uint, C.c_uint, C.c_ulong, C.c_int]
|
||||
x.XGetImage.restype = C.c_void_p
|
||||
x.XGetPixel.argtypes = [C.c_void_p, C.c_int, C.c_int]
|
||||
x.XGetPixel.restype = C.c_ulong
|
||||
x.XDestroyImage.argtypes = [C.c_void_p]
|
||||
fix.XFixesGetCursorImage.argtypes = [C.c_void_p]
|
||||
fix.XFixesGetCursorImage.restype = C.POINTER(Cursor)
|
||||
test.XTestFakeButtonEvent.argtypes = [C.c_void_p, C.c_uint, C.c_int, C.c_ulong]
|
||||
d = x.XOpenDisplay(None)
|
||||
assert d
|
||||
root = x.XDefaultRootWindow(d)
|
||||
|
||||
|
||||
def native():
|
||||
p = fix.XFixesGetCursorImage(d)
|
||||
assert p
|
||||
try:
|
||||
c = p.contents
|
||||
return dict(x=c.x, y=c.y, w=c.w, h=c.h, hx=c.hx, hy=c.hy,
|
||||
pixels=[int(c.pixels[i]) & 0xffffffff for i in range(c.w*c.h)])
|
||||
finally:
|
||||
x.XFree(p)
|
||||
|
||||
|
||||
def warp(px, py):
|
||||
x.XWarpPointer(d, 0, root, 0, 0, 0, 0, px, py)
|
||||
x.XSync(d, 0)
|
||||
|
||||
|
||||
def decoded_sequence():
|
||||
im = x.XGetImage(d, root, 40, 1370, 640, 1, 0xffffffff, 2)
|
||||
assert im
|
||||
try:
|
||||
values = [x.XGetPixel(im, i*40+20, 0) & 0xffffff for i in range(16)]
|
||||
if any(0x202020 <= v <= 0xe0e0e0 for v in values):
|
||||
return -1
|
||||
return sum((1 << i) for i, v in enumerate(values) if v > 0xe0e0e0)
|
||||
finally:
|
||||
x.XDestroyImage(im)
|
||||
|
||||
|
||||
def flat_video_crop(px, py):
|
||||
im = x.XGetImage(d, root, px-40, py-40, 100, 100, 0xffffffff, 2)
|
||||
assert im
|
||||
try:
|
||||
pixels = [x.XGetPixel(im, a, b) & 0xffffff for b in range(100) for a in range(100)]
|
||||
# No baked-in pointer: uniform acceptance-window background at this point.
|
||||
ref = pixels[0]
|
||||
bad = sum(any(abs(((v >> s) & 255) - ((ref >> s) & 255)) > 8
|
||||
for s in (0, 8, 16)) for v in pixels)
|
||||
return dict(reference=ref, nonuniform_pixels=bad)
|
||||
finally:
|
||||
x.XDestroyImage(im)
|
||||
|
||||
|
||||
|
||||
focus=C.c_ulong();revert=C.c_int()
|
||||
x.XGetInputFocus.argtypes=[C.c_void_p,C.POINTER(C.c_ulong),C.POINTER(C.c_int)]
|
||||
x.XSetInputFocus.argtypes=[C.c_void_p,C.c_ulong,C.c_int,C.c_ulong]
|
||||
x.XGetInputFocus(d,C.byref(focus),C.byref(revert))
|
||||
before=native()
|
||||
try:
|
||||
x.XSetInputFocus(d,0,1,0);x.XSync(d,0);time.sleep(.25);unfocused=native()
|
||||
finally:
|
||||
x.XSetInputFocus(d,focus.value,revert.value,0);x.XSync(d,0)
|
||||
time.sleep(.3);after=native()
|
||||
print(json.dumps(dict(original_focus=focus.value,unfocused_shape_changed=before['pixels']!=unfocused['pixels'],native_restored=before['pixels']==after['pixels'],position=[after['x'],after['y']])))
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"192.168.1.71": {
|
||||
"output": "MainPID=184769\nExecStart={ path=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine ; argv[]=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine /home/test1/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 11:33:00 CST] ; stop_time=[n/a] ; pid=184769 ; code=(null) ; status=0/0 }\nId=vdi-sunshine.service\nActiveState=active\n\nMainPID=0\nExecStart={ path=/usr/bin/python3 ; argv[]=/usr/bin/python3 /home/test1/vdi-terminal/native-cursor-v1/host.py guard ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }\nId=vdi-native-cursor-guard.service\nActiveState=inactive\n\nMainPID=0\nId=vdi-native-cursor-source.service\nActiveState=inactive\n",
|
||||
"stderr": "sha256sum: /usr/bin/sunshine: 没有那个文件或目录\n/usr/bin/sunshine (No such file or directory)\n"
|
||||
},
|
||||
"192.168.1.72": {
|
||||
"output": "MainPID=32278\nExecStart={ path=/usr/bin/sunshine ; argv[]=/usr/bin/sunshine /home/test2/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 11:43:42 CST] ; stop_time=[n/a] ; pid=32278 ; code=(null) ; status=0/0 }\nId=vdi-sunshine.service\nActiveState=active\n\nMainPID=0\nExecStart={ path=/usr/bin/python3 ; argv[]=/usr/bin/python3 /home/test2/vdi-terminal/native-cursor-v1/host.py guard ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }\nId=vdi-native-cursor-guard.service\nActiveState=inactive\n\nMainPID=0\nId=vdi-native-cursor-source.service\nActiveState=inactive\n61e1ecbc8db2df786b9760c652aa4b9885dff36c57d4af09616344314cb7c34c /usr/bin/sunshine\n/usr/bin/sunshine cap_sys_admin,cap_sys_nice=p\n",
|
||||
"stderr": ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"clicks": [{"seq": 29, "seen": 29, "x": 300, "y": 800}, {"seq": 30, "seen": 30, "x": 1500, "y": 900}, {"seq": 31, "seen": 31, "x": 300, "y": 800}, {"seq": 32, "seen": 32, "x": 1500, "y": 900}, {"seq": 33, "seen": 33, "x": 300, "y": 800}, {"seq": 34, "seen": 34, "x": 1500, "y": 900}, {"seq": 35, "seen": 35, "x": 300, "y": 800}, {"seq": 36, "seen": 36, "x": 1500, "y": 900}, {"seq": 37, "seen": 37, "x": 300, "y": 800}, {"seq": 38, "seen": 38, "x": 1500, "y": 900}, {"seq": 39, "seen": 39, "x": 300, "y": 800}, {"seq": 40, "seen": 40, "x": 1500, "y": 900}, {"seq": 41, "seen": 41, "x": 300, "y": 800}, {"seq": 42, "seen": 42, "x": 1500, "y": 900}, {"seq": 43, "seen": 43, "x": 300, "y": 800}, {"seq": 44, "seen": 44, "x": 1500, "y": 900}], "double_click_start": 44, "double_click_end": 46}
|
||||
@@ -0,0 +1 @@
|
||||
{"host": "192.168.1.71", "pid": 267646, "shapes": [{"name": "default", "source": {"w": 24, "h": 24, "hx": 4, "hy": 0, "x": 182, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 182, "y": 600, "w": 24, "h": 24, "hx": 4, "hy": 0}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 300, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "text", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 548, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 548, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 216, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "ew-resize", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 914, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 914, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 204, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "wait", "source": {"w": 24, "h": 24, "hx": 12, "hy": 12, "x": 1280, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 1280, "y": 600, "w": 24, "h": 24, "hx": 12, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 290, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "none", "source": {"w": 1, "h": 1, "hx": 0, "hy": 0, "x": 1645, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 1645, "y": 600, "w": 1, "h": 1, "hx": 0, "hy": 0}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 0, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "crosshair", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 2011, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 2011, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 252, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "custom", "source": {"w": 24, "h": 24, "hx": 7, "hy": 9, "x": 2377, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 2377, "y": 600, "w": 24, "h": 24, "hx": 7, "hy": 9}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 576, "video": {"reference": 15726074, "nonuniform_pixels": 0}}], "paused_client": {"position": [350, 700], "elapsed_ms": 249.580297, "same_shape": true, "steps": [{"target": [250, 650], "position": [250, 650], "query_ms": 2.364751}, {"target": [280, 670], "position": [280, 670], "query_ms": 2.234379}, {"target": [300, 690], "position": [300, 690], "query_ms": 2.128216}, {"target": [350, 700], "position": [350, 700], "query_ms": 2.286878}]}, "clicks": [{"seq": 1, "x": 182, "y": 750, "seen": 1, "decoded_ms": 108.930461}, {"seq": 2, "x": 548, "y": 850, "seen": 2, "decoded_ms": 98.691574}, {"seq": 3, "x": 914, "y": 750, "seen": 3, "decoded_ms": 152.320189}, {"seq": 4, "x": 1280, "y": 850, "seen": 4, "decoded_ms": 125.352183}, {"seq": 5, "x": 1645, "y": 750, "seen": 5, "decoded_ms": 135.816524}, {"seq": 6, "x": 2011, "y": 850, "seen": 6, "decoded_ms": 111.517755}, {"seq": 7, "x": 2377, "y": 750, "seen": 7, "decoded_ms": 108.898971}, {"seq": 8, "x": 182, "y": 850, "seen": 8, "decoded_ms": 119.075451}, {"seq": 9, "x": 548, "y": 750, "seen": 9, "decoded_ms": 134.943313}, {"seq": 10, "x": 914, "y": 850, "seen": 10, "decoded_ms": 146.081384}, {"seq": 11, "x": 1280, "y": 750, "seen": 11, "decoded_ms": 117.025403}, {"seq": 12, "x": 1645, "y": 850, "seen": 12, "decoded_ms": 152.719197}, {"seq": 13, "x": 2011, "y": 750, "seen": 13, "decoded_ms": 141.342555}, {"seq": 14, "x": 2377, "y": 850, "seen": 14, "decoded_ms": 130.95113}, {"seq": 15, "x": 182, "y": 750, "seen": 15, "decoded_ms": 143.698269}, {"seq": 16, "x": 548, "y": 850, "seen": 16, "decoded_ms": 114.9634}, {"seq": 17, "x": 914, "y": 750, "seen": 17, "decoded_ms": 159.173858}, {"seq": 18, "x": 1280, "y": 850, "seen": 18, "decoded_ms": 175.329882}, {"seq": 19, "x": 1645, "y": 750, "seen": 19, "decoded_ms": 119.051263}, {"seq": 20, "x": 2011, "y": 850, "seen": 20, "decoded_ms": 124.040341}, {"seq": 21, "x": 2377, "y": 750, "seen": 21, "decoded_ms": 121.588678}, {"seq": 22, "x": 182, "y": 850, "seen": 22, "decoded_ms": 129.876682}, {"seq": 23, "x": 548, "y": 750, "seen": 23, "decoded_ms": 124.467041}, {"seq": 24, "x": 914, "y": 850, "seen": 24, "decoded_ms": 153.052003}, {"seq": 25, "x": 1280, "y": 750, "seen": 25, "decoded_ms": 136.166846}, {"seq": 26, "x": 1645, "y": 850, "seen": 26, "decoded_ms": 168.630841}, {"seq": 27, "x": 2011, "y": 750, "seen": 27, "decoded_ms": 119.541845}, {"seq": 28, "x": 2377, "y": 850, "seen": 28, "decoded_ms": 110.41562}], "p50_ms": 127.61443249999999, "p95_ms": 168.630841, "method": "XTest click-down to unique decoded sequence; excludes USB and scanout"}
|
||||
|
After Width: | Height: | Size: 127 KiB |
@@ -0,0 +1 @@
|
||||
{"original_focus": 48234511, "unfocused_shape_changed": false, "native_restored": true, "position": [400, 600]}
|
||||
@@ -0,0 +1 @@
|
||||
{"pid": 297530, "args": "/home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream 192.168.1.71 Desktop --resolution 2560x1440 --fps 30 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --capture-system-keys always --keep-awake --no-vsync --no-frame-pacing --audio-on-host ", "sha256": "5d4330f703d7f8e053bc3795ca42bdaf231c9e9dd8ebb00a612013adbcccee03", "native": true, "shape": [24, 24, 4, 0]}
|
||||
|
After Width: | Height: | Size: 3.8 MiB |
@@ -0,0 +1 @@
|
||||
{"host": "192.168.1.71", "pid": 297530, "shapes": [{"name": "default", "source": {"w": 24, "h": 24, "hx": 4, "hy": 0, "x": 182, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 182, "y": 600, "w": 24, "h": 24, "hx": 4, "hy": 0}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 300, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "text", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 548, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 548, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 216, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "ew-resize", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 914, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 914, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 204, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "wait", "source": {"w": 24, "h": 24, "hx": 12, "hy": 12, "x": 1280, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 1280, "y": 600, "w": 24, "h": 24, "hx": 12, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 290, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "none", "source": {"w": 1, "h": 1, "hx": 0, "hy": 0, "x": 1645, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 1645, "y": 600, "w": 1, "h": 1, "hx": 0, "hy": 0}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 0, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "crosshair", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 2011, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 2011, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 252, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "custom", "source": {"w": 24, "h": 24, "hx": 7, "hy": 9, "x": 2377, "y": 600, "sw": 2560, "sh": 1440}, "local": {"x": 2377, "y": 600, "w": 24, "h": 24, "hx": 7, "hy": 9}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 576, "video": {"reference": 15726074, "nonuniform_pixels": 0}}], "paused_client": {"position": [350, 700], "elapsed_ms": 249.614056, "same_shape": true, "steps": [{"target": [250, 650], "position": [250, 650], "query_ms": 2.255936}, {"target": [280, 670], "position": [280, 670], "query_ms": 2.398262}, {"target": [300, 690], "position": [300, 690], "query_ms": 2.188272}, {"target": [350, 700], "position": [350, 700], "query_ms": 2.242227}]}, "clicks": [{"seq": 1, "x": 182, "y": 750, "seen": 1, "decoded_ms": 149.895203}, {"seq": 2, "x": 548, "y": 850, "seen": 2, "decoded_ms": 120.380242}, {"seq": 3, "x": 914, "y": 750, "seen": 3, "decoded_ms": 119.660739}, {"seq": 4, "x": 1280, "y": 850, "seen": 4, "decoded_ms": 147.265671}, {"seq": 5, "x": 1645, "y": 750, "seen": 5, "decoded_ms": 145.663335}, {"seq": 6, "x": 2011, "y": 850, "seen": 6, "decoded_ms": 129.562066}, {"seq": 7, "x": 2377, "y": 750, "seen": 7, "decoded_ms": 134.743571}, {"seq": 8, "x": 182, "y": 850, "seen": 8, "decoded_ms": 140.630877}, {"seq": 9, "x": 548, "y": 750, "seen": 9, "decoded_ms": 130.420116}, {"seq": 10, "x": 914, "y": 850, "seen": 10, "decoded_ms": 107.155271}, {"seq": 11, "x": 1280, "y": 750, "seen": 11, "decoded_ms": 117.124838}, {"seq": 12, "x": 1645, "y": 850, "seen": 12, "decoded_ms": 130.236678}, {"seq": 13, "x": 2011, "y": 750, "seen": 13, "decoded_ms": 111.917383}, {"seq": 14, "x": 2377, "y": 850, "seen": 14, "decoded_ms": 136.811123}, {"seq": 15, "x": 182, "y": 750, "seen": 15, "decoded_ms": 106.746093}, {"seq": 16, "x": 548, "y": 850, "seen": 16, "decoded_ms": 108.595469}, {"seq": 17, "x": 914, "y": 750, "seen": 17, "decoded_ms": 123.440014}, {"seq": 18, "x": 1280, "y": 850, "seen": 18, "decoded_ms": 150.429282}, {"seq": 19, "x": 1645, "y": 750, "seen": 19, "decoded_ms": 117.354684}, {"seq": 20, "x": 2011, "y": 850, "seen": 20, "decoded_ms": 147.688919}, {"seq": 21, "x": 2377, "y": 750, "seen": 21, "decoded_ms": 135.505122}, {"seq": 22, "x": 182, "y": 850, "seen": 22, "decoded_ms": 142.014237}, {"seq": 23, "x": 548, "y": 750, "seen": 23, "decoded_ms": 195.466041}, {"seq": 24, "x": 914, "y": 850, "seen": 24, "decoded_ms": 165.559673}, {"seq": 25, "x": 1280, "y": 750, "seen": 25, "decoded_ms": 142.88512}, {"seq": 26, "x": 1645, "y": 850, "seen": 26, "decoded_ms": 127.731718}, {"seq": 27, "x": 2011, "y": 750, "seen": 27, "decoded_ms": 146.832648}, {"seq": 28, "x": 2377, "y": 850, "seen": 28, "decoded_ms": 133.995845}], "p50_ms": 134.369708, "p95_ms": 165.559673, "method": "XTest click-down to unique decoded sequence; excludes USB and scanout"}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"recovered": true,
|
||||
"seconds": 3.555,
|
||||
"state": "ExecStart={ path=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine ; argv[]=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine /home/test1/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 11:33:00 CST] ; stop_time=[n/a] ; pid=184769 ; code=(null) ; status=0/0 }\nActiveState=active\nScreen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192\nVirtual-1 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 325mm x 203mm\n 1280x800 74.99 +\n 3840x2160 60.00 50.00 59.94 \n 1920x1440 60.00 \ninactive\n"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"host": "192.168.1.71",
|
||||
"target": [
|
||||
400,
|
||||
600
|
||||
],
|
||||
"readback": "X=400\nY=600\nSCREEN=0\nWINDOW=48234511\n",
|
||||
"passed": true
|
||||
}
|
||||
|
After Width: | Height: | Size: 54 KiB |
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"192.168.1.71": {
|
||||
"status": "MainPID=186038\nId=vdi-sunshine.service\nActiveState=active\n\nMainPID=185981\nId=vdi-native-cursor-guard.service\nActiveState=active\n\nMainPID=0\nId=vdi-native-cursor-source.service\nActiveState=inactive\nScreen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192\nVirtual-1 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 325mm x 203mm\n 1280x800 74.99 +\n 3840x2160 60.00 50.00 59.94 \n 1920x1440 60.00 \n'Adwaita'\n24\n'default'\ntrue\n1c3099bf924db3aee759b3d7c05e012569ef8650c400d1479144398795decc71 /opt/vdi-sunshine-0.21.0/usr/bin/sunshine\n",
|
||||
"stderr": "",
|
||||
"profile_client_sha": "1da552e4855d1562fdd8d6f04f1553382db4ccd364c66fe7486b1688cc584f15"
|
||||
},
|
||||
"192.168.1.72": {
|
||||
"status": "MainPID=32278\nId=vdi-sunshine.service\nActiveState=active\n\nMainPID=0\nId=vdi-native-cursor-guard.service\nActiveState=inactive\n\nMainPID=0\nId=vdi-native-cursor-source.service\nActiveState=inactive\nScreen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192\nVirtual-1 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 325mm x 203mm\n 1280x800 74.99 +\n 1920x1440 60.00 \n 2560x1080 50.00 \n'Adwaita'\n24\n'default'\nfalse\n61e1ecbc8db2df786b9760c652aa4b9885dff36c57d4af09616344314cb7c34c /usr/bin/sunshine\n/usr/bin/sunshine cap_sys_admin,cap_sys_nice=p\n",
|
||||
"stderr": "",
|
||||
"profile_client_sha": "1da552e4855d1562fdd8d6f04f1553382db4ccd364c66fe7486b1688cc584f15"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"baseline": "de2467e433821664cdd2224aad8c89a625be1ad9",
|
||||
"patches": [
|
||||
"0001-vdi-input-and-latest-frame.patch",
|
||||
"0003-vdi-input-priority.patch",
|
||||
"0004-vdi-power-key-policy.patch",
|
||||
"0005-vdi-native-linux-cursor.patch",
|
||||
"0002-vdi-absolute-click-barrier.patch"
|
||||
],
|
||||
"native_patch_sha256": "6a5879901ae0d2986271df7441a38d0f1813c0d7fb3f616af5e1212c75eaaa02",
|
||||
"returncode": 0,
|
||||
"stdout": "PATCHES_OK\n",
|
||||
"stderr": ""
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"patches_apply_cleanly": ["0001-vdi-input-and-latest-frame.patch", "0003-vdi-input-priority.patch", "0004-vdi-power-key-policy.patch", "0005-vdi-native-linux-cursor.patch", "0002-vdi-absolute-click-barrier.patch"], "baseline": "de2467e433821664cdd2224aad8c89a625be1ad9"}
|
||||
@@ -0,0 +1,188 @@
|
||||
"""Run only with the controlled GTK acceptance window filling the stream."""
|
||||
import ctypes as C
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import signal
|
||||
import statistics
|
||||
import struct
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
os.environ.update(DISPLAY=':0', XAUTHORITY='/home/armbian/.Xauthority')
|
||||
x = C.CDLL('libX11.so.6')
|
||||
fix = C.CDLL('libXfixes.so.3')
|
||||
test = C.CDLL('libXtst.so.6')
|
||||
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.XDefaultRootWindow.argtypes = [C.c_void_p]
|
||||
x.XDefaultRootWindow.restype = C.c_ulong
|
||||
x.XFree.argtypes = [C.c_void_p]
|
||||
x.XSync.argtypes = [C.c_void_p, C.c_int]
|
||||
x.XWarpPointer.argtypes = [C.c_void_p, C.c_ulong, C.c_ulong, C.c_int,
|
||||
C.c_int, C.c_uint, C.c_uint, C.c_int, C.c_int]
|
||||
x.XGetImage.argtypes = [C.c_void_p, C.c_ulong, C.c_int, C.c_int,
|
||||
C.c_uint, C.c_uint, C.c_ulong, C.c_int]
|
||||
x.XGetImage.restype = C.c_void_p
|
||||
x.XGetPixel.argtypes = [C.c_void_p, C.c_int, C.c_int]
|
||||
x.XGetPixel.restype = C.c_ulong
|
||||
x.XDestroyImage.argtypes = [C.c_void_p]
|
||||
fix.XFixesGetCursorImage.argtypes = [C.c_void_p]
|
||||
fix.XFixesGetCursorImage.restype = C.POINTER(Cursor)
|
||||
test.XTestFakeButtonEvent.argtypes = [C.c_void_p, C.c_uint, C.c_int, C.c_ulong]
|
||||
d = x.XOpenDisplay(None)
|
||||
assert d
|
||||
root = x.XDefaultRootWindow(d)
|
||||
|
||||
|
||||
def native():
|
||||
p = fix.XFixesGetCursorImage(d)
|
||||
assert p
|
||||
try:
|
||||
c = p.contents
|
||||
return dict(x=c.x, y=c.y, w=c.w, h=c.h, hx=c.hx, hy=c.hy,
|
||||
pixels=[int(c.pixels[i]) & 0xffffffff for i in range(c.w*c.h)])
|
||||
finally:
|
||||
x.XFree(p)
|
||||
|
||||
|
||||
def warp(px, py):
|
||||
x.XWarpPointer(d, 0, root, 0, 0, 0, 0, px, py)
|
||||
x.XSync(d, 0)
|
||||
|
||||
|
||||
def decoded_sequence():
|
||||
im = x.XGetImage(d, root, 40, 1370, 640, 1, 0xffffffff, 2)
|
||||
assert im
|
||||
try:
|
||||
values = [x.XGetPixel(im, i*40+20, 0) & 0xffffff for i in range(16)]
|
||||
if any(0x202020 <= v <= 0xe0e0e0 for v in values):
|
||||
return -1
|
||||
return sum((1 << i) for i, v in enumerate(values) if v > 0xe0e0e0)
|
||||
finally:
|
||||
x.XDestroyImage(im)
|
||||
|
||||
|
||||
def flat_video_crop(px, py):
|
||||
im = x.XGetImage(d, root, px-40, py-40, 100, 100, 0xffffffff, 2)
|
||||
assert im
|
||||
try:
|
||||
pixels = [x.XGetPixel(im, a, b) & 0xffffff for b in range(100) for a in range(100)]
|
||||
# No baked-in pointer: uniform acceptance-window background at this point.
|
||||
ref = pixels[0]
|
||||
bad = sum(any(abs(((v >> s) & 255) - ((ref >> s) & 255)) > 8
|
||||
for s in (0, 8, 16)) for v in pixels)
|
||||
return dict(reference=ref, nonuniform_pixels=bad)
|
||||
finally:
|
||||
x.XDestroyImage(im)
|
||||
|
||||
|
||||
host = os.sys.argv[1]
|
||||
prefix = '/home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream ' + host + ' '
|
||||
items = [l.split(None, 1) for l in subprocess.check_output(['ps','-eo','pid,args'], text=True).splitlines()[1:]
|
||||
if len(l.split(None, 1)) == 2 and l.split(None, 1)[1].startswith(prefix)]
|
||||
assert len(items) == 1, items
|
||||
pid = int(items[0][0])
|
||||
focus = subprocess.check_output(['xdotool','getwindowfocus','getwindowpid'], text=True).strip()
|
||||
assert focus == str(pid), (focus, pid)
|
||||
env = dict(item.split('=', 1) for item in Path('/proc/%d/environ' % pid).read_bytes().decode().split('\0') if '=' in item)
|
||||
statepath = Path(env['VDI_NATIVE_CURSOR_STATE'])
|
||||
initial_sequence = decoded_sequence()
|
||||
assert 0 <= initial_sequence < 60000, 'test window not ready'
|
||||
reference = flat_video_crop(180, 600)['reference']
|
||||
assert all(abs(((reference >> s) & 255)-v) < 10 for s,v in [(16,240),(8,245),(0,250)]), 'acceptance window not visible'
|
||||
shapes = []
|
||||
for i, name in enumerate(['default','text','ew-resize','wait','none','crosshair','custom']):
|
||||
px = int((i+.5)*2560/7)
|
||||
warp(px, 600)
|
||||
time.sleep(.6)
|
||||
state = statepath.read_bytes()
|
||||
header = struct.unpack('<8sQQQIIIIiiII', state[:64])
|
||||
local = native()
|
||||
source = dict(zip(['w','h','hx','hy','x','y','sw','sh'], header[4:]))
|
||||
# Convert expected straight RGBA to XRender premultiplied ARGB.
|
||||
expected = []
|
||||
for j in range(64, len(state)-8, 4):
|
||||
r,g,b,a = state[j:j+4]
|
||||
expected.append((a << 24) | ((r*a+127)//255 << 16) |
|
||||
((g*a+127)//255 << 8) | ((b*a+127)//255))
|
||||
same_geometry = all(local[k] == source[k] for k in ['w','h','hx','hy'])
|
||||
# Busy frames animate; these snapshots can legitimately be adjacent frames.
|
||||
diff = max((abs(((a >> s) & 255)-((b >> s) & 255))
|
||||
for a,b in zip(local['pixels'],expected) for s in [0,8,16,24]), default=0)
|
||||
shapes.append(dict(name=name, source=source,
|
||||
local={k:v for k,v in local.items() if k != 'pixels'},
|
||||
geometry_matches=same_geometry, max_pixel_difference=diff,
|
||||
visible_pixels=sum(p >> 24 != 0 for p in local['pixels']),
|
||||
video=flat_video_crop(px, 600)))
|
||||
|
||||
Path('/tmp/native-%s-shapes.json' % host).write_text(json.dumps(shapes))
|
||||
samples = []
|
||||
for i in range(28):
|
||||
px = int(((i % 7)+.5)*2560/7)
|
||||
py = 750 if i % 2 == 0 else 850
|
||||
warp(px, py)
|
||||
time.sleep(.25)
|
||||
start = time.monotonic_ns()
|
||||
test.XTestFakeButtonEvent(d, 1, 1, 0)
|
||||
x.XSync(d, 0)
|
||||
expected = initial_sequence+i+1
|
||||
seen = -1
|
||||
released = False
|
||||
try:
|
||||
while time.monotonic_ns()-start < 3000000000:
|
||||
if not released and time.monotonic_ns()-start >= 80000000:
|
||||
test.XTestFakeButtonEvent(d, 1, 0, 0)
|
||||
x.XSync(d, 0)
|
||||
released = True
|
||||
seen = decoded_sequence()
|
||||
if seen == expected:
|
||||
break
|
||||
if seen > expected:
|
||||
raise RuntimeError('unexpected duplicate click %d instead of %d' % (seen,expected))
|
||||
time.sleep(.002)
|
||||
finally:
|
||||
if not released:
|
||||
time.sleep(max(0, .08-(time.monotonic_ns()-start)/1e9))
|
||||
test.XTestFakeButtonEvent(d, 1, 0, 0)
|
||||
x.XSync(d, 0)
|
||||
samples.append(dict(seq=expected, x=px, y=py, seen=seen,
|
||||
decoded_ms=(time.monotonic_ns()-start)/1e6))
|
||||
if seen != expected:
|
||||
Path('/tmp/native-%s-failed-clicks.json' % host).write_text(json.dumps(samples))
|
||||
raise AssertionError(samples[-1])
|
||||
time.sleep(.1)
|
||||
times = sorted(s['decoded_ms'] for s in samples)
|
||||
# A stopped Moonlight cannot capture input, receive video, or draw frames.
|
||||
# X11's native pointer must still move and keep its shape while it is stopped.
|
||||
warp(200, 600)
|
||||
time.sleep(.3)
|
||||
before = native()
|
||||
try:
|
||||
os.kill(pid, signal.SIGSTOP)
|
||||
start = time.monotonic_ns()
|
||||
steps = []
|
||||
for px,py in [(250,650),(280,670),(300,690),(350,700)]:
|
||||
step_start = time.monotonic_ns()
|
||||
warp(px, py)
|
||||
after = native()
|
||||
steps.append(dict(target=[px,py],position=[after['x'],after['y']],
|
||||
query_ms=(time.monotonic_ns()-step_start)/1e6))
|
||||
time.sleep(.06)
|
||||
paused_ms = (time.monotonic_ns()-start)/1e6
|
||||
finally:
|
||||
os.kill(pid, signal.SIGCONT)
|
||||
pause = dict(position=[after['x'],after['y']], elapsed_ms=paused_ms,
|
||||
same_shape=before['pixels']==after['pixels'], steps=steps)
|
||||
assert all(s['target']==s['position'] for s in steps) and pause['same_shape']
|
||||
time.sleep(.4)
|
||||
|
||||
print(json.dumps(dict(host=host,pid=pid,shapes=shapes,paused_client=pause,
|
||||
clicks=samples,p50_ms=statistics.median(times),
|
||||
p95_ms=times[int(len(times)*.95)],
|
||||
method='XTest click-down to unique decoded sequence; excludes USB and scanout')))
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"client_sha256": "5d4330f703d7f8e053bc3795ca42bdaf231c9e9dd8ebb00a612013adbcccee03",
|
||||
"ubuntu": {
|
||||
"measured_clicks": 28,
|
||||
"matched_source_events": 28,
|
||||
"max_coordinate_error_pixels": 1.0546875,
|
||||
"p50_ms": 188.3848435,
|
||||
"p95_ms": 522.420223
|
||||
},
|
||||
"kylin": {
|
||||
"measured_clicks": 28,
|
||||
"matched_source_events": 28,
|
||||
"max_coordinate_error_pixels": 0.82855224609375,
|
||||
"p50_ms": 134.369708,
|
||||
"p95_ms": 165.559673
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
"""Observe actual deployed state/receiver; keep the test seat awake with motion.
|
||||
|
||||
Run on the box only while a controlled native-cursor session is active.
|
||||
No clicks, protocol injection, or changes to the state producer are made.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
duration = float(sys.argv[1])
|
||||
output = Path(sys.argv[2])
|
||||
pid = int(subprocess.check_output(['pgrep', '-x', 'moonlight']).strip())
|
||||
proc = Path('/proc') / str(pid)
|
||||
env = dict(x.split('=', 1) for x in (proc / 'environ').read_bytes().decode().split('\0') if '=' in x)
|
||||
state = Path(env['VDI_NATIVE_CURSOR_STATE'])
|
||||
start = time.monotonic()
|
||||
last_motion = 0
|
||||
result = dict(pid=pid, requested_seconds=duration, samples=0,
|
||||
timestamp_after_pre_read_clock=0, timestamp_after_post_read_clock=0,
|
||||
max_age_ms=0, survived=False)
|
||||
try:
|
||||
while time.monotonic() - start < duration:
|
||||
if not proc.exists() or (proc / 'comm').read_text().strip() != 'moonlight':
|
||||
raise RuntimeError('receiver exited')
|
||||
before = time.monotonic_ns()
|
||||
packet = state.read_bytes()
|
||||
after = time.monotonic_ns()
|
||||
stamp = struct.unpack_from('<Q', packet, 24)[0]
|
||||
result['samples'] += 1
|
||||
result['timestamp_after_pre_read_clock'] += stamp > before
|
||||
result['timestamp_after_post_read_clock'] += stamp > after
|
||||
result['max_age_ms'] = max(result['max_age_ms'], (after - stamp) / 1e6)
|
||||
result['last_sequence'] = struct.unpack_from('<Q', packet, 16)[0]
|
||||
if stamp > after or after - stamp > 2_000_000_000:
|
||||
raise RuntimeError('invalid post-read timestamp')
|
||||
now = time.monotonic()
|
||||
if now - last_motion > 10:
|
||||
px = 1800 + (int(now - start) // 10 % 2) * 50
|
||||
motion_env = dict(os.environ, DISPLAY=':0', XAUTHORITY='/home/armbian/.Xauthority')
|
||||
subprocess.run(['xdotool', 'mousemove', str(px), '1100'], env=motion_env, check=True)
|
||||
last_motion = now
|
||||
time.sleep(.004)
|
||||
result['survived'] = True
|
||||
except Exception as error:
|
||||
result['error'] = str(error)
|
||||
finally:
|
||||
result['elapsed_seconds'] = round(time.monotonic() - start, 3)
|
||||
output.write_text(json.dumps(result, indent=2) + '\n')
|
||||
print(json.dumps(result), flush=True)
|
||||
@@ -0,0 +1,92 @@
|
||||
"""Controlled GTK test window: real native cursors and unique click sequences."""
|
||||
import gi
|
||||
import json
|
||||
import time
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk, Gdk, GdkPixbuf, GLib
|
||||
|
||||
win = Gtk.Window(title='VDI native cursor acceptance')
|
||||
area = Gtk.DrawingArea()
|
||||
win.add(area)
|
||||
area.set_can_focus(True)
|
||||
area.set_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.BUTTON_PRESS_MASK |
|
||||
Gdk.EventMask.BUTTON_RELEASE_MASK)
|
||||
display = Gdk.Display.get_default()
|
||||
names = ['default', 'text', 'ew-resize', 'wait', 'none', 'crosshair', 'custom']
|
||||
cursors = {name: Gdk.Cursor.new_from_name(display, name) for name in names[:4] + ['crosshair']}
|
||||
cursors['none'] = Gdk.Cursor.new_for_display(display, Gdk.CursorType.BLANK_CURSOR)
|
||||
pix = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 24, 24)
|
||||
pix.fill(0xff5030ff)
|
||||
cursors['custom'] = Gdk.Cursor.new_from_pixbuf(display, pix, 7, 9)
|
||||
current = None
|
||||
sequence = 0
|
||||
|
||||
|
||||
def report(**kw):
|
||||
kw['t'] = time.monotonic()
|
||||
print(json.dumps(kw), flush=True)
|
||||
|
||||
|
||||
def motion(widget, event):
|
||||
global current
|
||||
index = min(6, int(event.x // (2560/7)))
|
||||
name = names[index]
|
||||
if name != current:
|
||||
area.get_window().set_cursor(cursors[name])
|
||||
current = name
|
||||
report(event='shape', name=name)
|
||||
return False
|
||||
|
||||
|
||||
def button(widget, event):
|
||||
global sequence
|
||||
if event.type in (Gdk.EventType.BUTTON_PRESS, Gdk.EventType.DOUBLE_BUTTON_PRESS,
|
||||
Gdk.EventType.TRIPLE_BUTTON_PRESS):
|
||||
# GTK emits an extra double/triple notification, not another input.
|
||||
if event.type == Gdk.EventType.BUTTON_PRESS:
|
||||
sequence += 1
|
||||
area.queue_draw_area(0, 1300, 1000, 140)
|
||||
report(event=event.type.value_nick, seq=sequence, x=event.x_root,
|
||||
y=event.y_root, button=event.button)
|
||||
return False
|
||||
|
||||
|
||||
def draw(widget, cr):
|
||||
cr.set_source_rgb(.94, .96, .98)
|
||||
cr.paint()
|
||||
cr.select_font_face('sans')
|
||||
cr.set_font_size(25)
|
||||
for i, name in enumerate(names):
|
||||
cr.set_source_rgb(.1, .15, .2)
|
||||
cr.move_to(40 + i*2560/7, 100)
|
||||
cr.show_text(name)
|
||||
cr.set_source_rgb(.65, .7, .8)
|
||||
cr.rectangle(i*2560/7, 120, 2, 1100)
|
||||
cr.fill()
|
||||
# Unique monotonic sequence, read from the actual decoded video.
|
||||
for bit in range(16):
|
||||
v = 1 if sequence & (1 << bit) else 0
|
||||
cr.set_source_rgb(v, v, v)
|
||||
cr.rectangle(40 + bit*40, 1340, 40, 60)
|
||||
cr.fill()
|
||||
return False
|
||||
|
||||
|
||||
def key(widget, event):
|
||||
if event.keyval == Gdk.KEY_Escape:
|
||||
Gtk.main_quit()
|
||||
return False
|
||||
|
||||
|
||||
win.connect('destroy', Gtk.main_quit)
|
||||
win.connect('key-press-event', key)
|
||||
area.connect('motion-notify-event', motion)
|
||||
area.connect('button-press-event', button)
|
||||
area.connect('button-release-event', button)
|
||||
area.connect('draw', draw)
|
||||
win.fullscreen()
|
||||
win.show_all()
|
||||
win.present()
|
||||
area.grab_focus()
|
||||
report(event='ready')
|
||||
Gtk.main()
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sunshine": "1c3099bf924db3aee759b3d7c05e012569ef8650c400d1479144398795decc71",
|
||||
"capture-no-cursor.so": "cff4b7532aee69f0f205fa42946f45a89c1330486adc6358b90d13d2ccf1a0ea"
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
{
|
||||
"host": "192.168.1.71",
|
||||
"ready": true,
|
||||
"samples": [
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 1
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 2
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 3
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 4
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 5
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 6
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 7
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 8
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 9
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 10
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 11
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 12
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 13
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 14
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 15
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 16
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 17
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 18
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 19
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 20
|
||||
},
|
||||
{
|
||||
"w": 16,
|
||||
"h": 16,
|
||||
"hx": 8,
|
||||
"hy": 8,
|
||||
"x": 1814,
|
||||
"y": 554,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 166,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 21
|
||||
}
|
||||
],
|
||||
"stderr": "",
|
||||
"exit": 0
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"host": "192.168.1.71",
|
||||
"ready": false,
|
||||
"samples": [],
|
||||
"stderr": "RuntimeError: Permission denied by kysec\n",
|
||||
"exit": 1
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"case": "agent-sigkill",
|
||||
"host": "192.168.1.71",
|
||||
"recovered": true,
|
||||
"recovery_seconds": 3.22,
|
||||
"state": "ExecStart={ path=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine ; argv[]=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine /home/test1/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 11:11:57 CST] ; stop_time=[n/a] ; pid=180535 ; code=(null) ; status=0/0 }\nActiveState=active\n"
|
||||
},
|
||||
{
|
||||
"case": "guard-sigkill",
|
||||
"host": "192.168.1.71",
|
||||
"recovered": true,
|
||||
"recovery_seconds": 0.893,
|
||||
"state": "ExecStart={ path=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine ; argv[]=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine /home/test1/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 11:12:00 CST] ; stop_time=[n/a] ; pid=180701 ; code=(null) ; status=0/0 }\nActiveState=active\n"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sunshine": "61e1ecbc8db2df786b9760c652aa4b9885dff36c57d4af09616344314cb7c34c",
|
||||
"capture-no-cursor.so": "cff4b7532aee69f0f205fa42946f45a89c1330486adc6358b90d13d2ccf1a0ea"
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
{
|
||||
"host": "192.168.1.72",
|
||||
"ready": true,
|
||||
"samples": [
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 1
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 2
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 3
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 4
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 5
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 6
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 7
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 8
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 9
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 10
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 11
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 12
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 13
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 14
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 15
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 16
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 17
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 18
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 19
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 20
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 21
|
||||
},
|
||||
{
|
||||
"w": 24,
|
||||
"h": 24,
|
||||
"hx": 3,
|
||||
"hy": 1,
|
||||
"x": 2548,
|
||||
"y": 1,
|
||||
"sw": 2560,
|
||||
"sh": 1440,
|
||||
"shape": 124,
|
||||
"type": "cursor",
|
||||
"version": 1,
|
||||
"seq": 22
|
||||
}
|
||||
],
|
||||
"stderr": "",
|
||||
"exit": 0
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"host": "192.168.1.72",
|
||||
"ready": false,
|
||||
"samples": [],
|
||||
"stderr": "Traceback (most recent call last):\n File \"/home/test2/vdi-terminal/native-cursor-v1/host.py\", line 211, in <module>\n main()\n File \"/home/test2/vdi-terminal/native-cursor-v1/host.py\", line 205, in main\n stream()\n File \"/home/test2/vdi-terminal/native-cursor-v1/host.py\", line 154, in stream\n raise RuntimeError('guard not ready')\nRuntimeError: guard not ready\n",
|
||||
"exit": 1
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
[
|
||||
{
|
||||
"case": "agent-sigkill",
|
||||
"host": "192.168.1.72",
|
||||
"recovered": true,
|
||||
"recovery_seconds": 2.724,
|
||||
"state": "ExecStart={ path=/usr/bin/sunshine ; argv[]=/usr/bin/sunshine /home/test2/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 11:11:56 CST] ; stop_time=[n/a] ; pid=24296 ; code=(null) ; status=0/0 }\nActiveState=active\n"
|
||||
},
|
||||
{
|
||||
"case": "guard-sigkill",
|
||||
"host": "192.168.1.72",
|
||||
"recovered": true,
|
||||
"recovery_seconds": 0.771,
|
||||
"state": "ExecStart={ path=/usr/bin/sunshine ; argv[]=/usr/bin/sunshine /home/test2/.config/sunshine/sunshine.conf ; ignore_errors=no ; start_time=[Thu 2026-11-05 11:12:14 CST] ; stop_time=[n/a] ; pid=24470 ; code=(null) ; status=0/0 }\nActiveState=active\n"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"pid": 285520,
|
||||
"requested_seconds": 360.0,
|
||||
"samples": 65658,
|
||||
"timestamp_after_pre_read_clock": 0,
|
||||
"timestamp_after_post_read_clock": 0,
|
||||
"max_age_ms": 308.103546,
|
||||
"survived": true,
|
||||
"last_sequence": 7956,
|
||||
"elapsed_seconds": 360.005
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
[{"file": "_usr_bin_sunshine.1000.crash", "ProblemType": "Crash", "Date": "Thu Nov 5 11:12:07 2026", "ExecutablePath": "/usr/bin/sunshine", "Package": "sunshine 2026.914.233613-1+ubuntu24.04 [origin: unknown]", "Signal": "5"}]
|
||||
@@ -0,0 +1 @@
|
||||
{"clicks": [{"seq": 29, "seen": 29, "x": 300, "y": 800}, {"seq": 30, "seen": 30, "x": 1500, "y": 900}, {"seq": 31, "seen": 31, "x": 300, "y": 800}, {"seq": 32, "seen": 32, "x": 1500, "y": 900}, {"seq": 33, "seen": 33, "x": 300, "y": 800}, {"seq": 34, "seen": 34, "x": 1500, "y": 900}, {"seq": 35, "seen": 35, "x": 300, "y": 800}, {"seq": 36, "seen": 36, "x": 1500, "y": 900}, {"seq": 37, "seen": 37, "x": 300, "y": 800}, {"seq": 38, "seen": 38, "x": 1500, "y": 900}, {"seq": 39, "seen": 39, "x": 300, "y": 800}, {"seq": 40, "seen": 40, "x": 1500, "y": 900}, {"seq": 41, "seen": 41, "x": 300, "y": 800}, {"seq": 42, "seen": 42, "x": 1500, "y": 900}, {"seq": 43, "seen": 43, "x": 300, "y": 800}, {"seq": 44, "seen": 44, "x": 1500, "y": 900}], "double_click_start": 44, "double_click_end": 46}
|
||||
@@ -0,0 +1 @@
|
||||
{"host": "192.168.1.72", "pid": 263384, "shapes": [{"name": "default", "source": {"w": 24, "h": 24, "hx": 3, "hy": 1, "x": 181, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 182, "y": 600, "w": 24, "h": 24, "hx": 3, "hy": 1}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 254, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "text", "source": {"w": 24, "h": 24, "hx": 11, "hy": 12, "x": 547, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 548, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 240, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "ew-resize", "source": {"w": 24, "h": 24, "hx": 12, "hy": 12, "x": 913, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 914, "y": 600, "w": 24, "h": 24, "hx": 12, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 301, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "wait", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 1280, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 1280, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 433, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "none", "source": {"w": 1, "h": 1, "hx": 0, "hy": 0, "x": 1645, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 1645, "y": 600, "w": 1, "h": 1, "hx": 0, "hy": 0}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 0, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "crosshair", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 2011, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 2011, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 281, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "custom", "source": {"w": 24, "h": 24, "hx": 7, "hy": 9, "x": 2377, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 2377, "y": 600, "w": 24, "h": 24, "hx": 7, "hy": 9}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 576, "video": {"reference": 15726074, "nonuniform_pixels": 0}}], "paused_client": {"position": [250, 650], "elapsed_ms": 2.232537, "same_shape": true}, "clicks": [{"seq": 1, "x": 182, "y": 750, "seen": 1, "decoded_ms": 183.136301}, {"seq": 2, "x": 548, "y": 850, "seen": 2, "decoded_ms": 150.601919}, {"seq": 3, "x": 914, "y": 750, "seen": 3, "decoded_ms": 162.979614}, {"seq": 4, "x": 1280, "y": 850, "seen": 4, "decoded_ms": 562.228218}, {"seq": 5, "x": 1645, "y": 750, "seen": 5, "decoded_ms": 149.661983}, {"seq": 6, "x": 2011, "y": 850, "seen": 6, "decoded_ms": 187.689807}, {"seq": 7, "x": 2377, "y": 750, "seen": 7, "decoded_ms": 186.617722}, {"seq": 8, "x": 182, "y": 850, "seen": 8, "decoded_ms": 167.201514}, {"seq": 9, "x": 548, "y": 750, "seen": 9, "decoded_ms": 143.805796}, {"seq": 10, "x": 914, "y": 850, "seen": 10, "decoded_ms": 145.803285}, {"seq": 11, "x": 1280, "y": 750, "seen": 11, "decoded_ms": 505.147227}, {"seq": 12, "x": 1645, "y": 850, "seen": 12, "decoded_ms": 156.874419}, {"seq": 13, "x": 2011, "y": 750, "seen": 13, "decoded_ms": 164.724633}, {"seq": 14, "x": 2377, "y": 850, "seen": 14, "decoded_ms": 172.592036}, {"seq": 15, "x": 182, "y": 750, "seen": 15, "decoded_ms": 195.775758}, {"seq": 16, "x": 548, "y": 850, "seen": 16, "decoded_ms": 151.145679}, {"seq": 17, "x": 914, "y": 750, "seen": 17, "decoded_ms": 173.941806}, {"seq": 18, "x": 1280, "y": 850, "seen": 18, "decoded_ms": 352.426864}, {"seq": 19, "x": 1645, "y": 750, "seen": 19, "decoded_ms": 156.050885}, {"seq": 20, "x": 2011, "y": 850, "seen": 20, "decoded_ms": 158.266234}, {"seq": 21, "x": 2377, "y": 750, "seen": 21, "decoded_ms": 126.999009}, {"seq": 22, "x": 182, "y": 850, "seen": 22, "decoded_ms": 194.209712}, {"seq": 23, "x": 548, "y": 750, "seen": 23, "decoded_ms": 183.157837}, {"seq": 24, "x": 914, "y": 850, "seen": 24, "decoded_ms": 186.545894}, {"seq": 25, "x": 1280, "y": 750, "seen": 25, "decoded_ms": 506.013562}, {"seq": 26, "x": 1645, "y": 850, "seen": 26, "decoded_ms": 164.698513}, {"seq": 27, "x": 2011, "y": 750, "seen": 27, "decoded_ms": 177.684307}, {"seq": 28, "x": 2377, "y": 850, "seen": 28, "decoded_ms": 174.644202}], "p50_ms": 173.26692100000002, "p95_ms": 506.013562, "method": "XTest click-down to unique decoded sequence; excludes USB and scanout"}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"pid": 293859,
|
||||
"requested_seconds": 360.0,
|
||||
"samples": 65960,
|
||||
"timestamp_after_pre_read_clock": 1,
|
||||
"timestamp_after_post_read_clock": 0,
|
||||
"max_age_ms": 1109.787402,
|
||||
"survived": true,
|
||||
"last_sequence": 6538,
|
||||
"elapsed_seconds": 360.003
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"pid": 293859, "worker": 293861, "pause_seconds": 2.6, "exited": true, "check_seconds": 2.9042484689998673}
|
||||
|
After Width: | Height: | Size: 804 KiB |
|
After Width: | Height: | Size: 2.0 MiB |
@@ -0,0 +1 @@
|
||||
{"pid": 299860, "ppid": 235482, "args": "/home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream 192.168.1.72 Desktop --resolution 2560x1440 --fps 30 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --capture-system-keys always --keep-awake --no-vsync --no-frame-pacing --audio-on-host ", "sha256": "5d4330f703d7f8e053bc3795ca42bdaf231c9e9dd8ebb00a612013adbcccee03", "native": true, "shape": [24, 24, 3, 1]}
|
||||
|
After Width: | Height: | Size: 2.0 MiB |
@@ -0,0 +1 @@
|
||||
{"host": "192.168.1.72", "pid": 256179, "shapes": [{"name": "default", "source": {"w": 24, "h": 24, "hx": 3, "hy": 1, "x": 181, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 182, "y": 600, "w": 24, "h": 24, "hx": 3, "hy": 1}, "geometry_matches": true, "max_pixel_difference": 162, "visible_pixels": 254, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "text", "source": {"w": 24, "h": 24, "hx": 11, "hy": 12, "x": 547, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 548, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 101, "visible_pixels": 240, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "ew-resize", "source": {"w": 24, "h": 24, "hx": 12, "hy": 12, "x": 913, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 914, "y": 600, "w": 24, "h": 24, "hx": 12, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 175, "visible_pixels": 301, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "wait", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 1280, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 1280, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 129, "visible_pixels": 433, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "none", "source": {"w": 1, "h": 1, "hx": 0, "hy": 0, "x": 1645, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 1645, "y": 600, "w": 1, "h": 1, "hx": 0, "hy": 0}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 0, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "crosshair", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 2011, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 2011, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 78, "visible_pixels": 281, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "custom", "source": {"w": 24, "h": 24, "hx": 7, "hy": 9, "x": 2377, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 2377, "y": 600, "w": 24, "h": 24, "hx": 7, "hy": 9}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 576, "video": {"reference": 15726074, "nonuniform_pixels": 0}}], "paused_client": {"position": [250, 650], "elapsed_ms": 2.727055, "same_shape": true}, "clicks": [{"seq": 3, "x": 182, "y": 750, "seen": 3, "decoded_ms": 177.207219}, {"seq": 4, "x": 548, "y": 850, "seen": 4, "decoded_ms": 177.766631}, {"seq": 5, "x": 914, "y": 750, "seen": 5, "decoded_ms": 199.373737}, {"seq": 6, "x": 1280, "y": 850, "seen": 6, "decoded_ms": 182.446665}, {"seq": 7, "x": 1645, "y": 750, "seen": 7, "decoded_ms": 174.159044}, {"seq": 8, "x": 2011, "y": 850, "seen": 8, "decoded_ms": 211.839356}, {"seq": 9, "x": 2377, "y": 750, "seen": 9, "decoded_ms": 172.112732}, {"seq": 10, "x": 182, "y": 850, "seen": 10, "decoded_ms": 218.076291}, {"seq": 11, "x": 548, "y": 750, "seen": 11, "decoded_ms": 158.319669}, {"seq": 12, "x": 914, "y": 850, "seen": 12, "decoded_ms": 190.78387}, {"seq": 13, "x": 1280, "y": 750, "seen": 13, "decoded_ms": 475.373962}, {"seq": 14, "x": 1645, "y": 850, "seen": 14, "decoded_ms": 183.265657}, {"seq": 15, "x": 2011, "y": 750, "seen": 15, "decoded_ms": 190.493082}, {"seq": 16, "x": 2377, "y": 850, "seen": 16, "decoded_ms": 174.658874}, {"seq": 17, "x": 182, "y": 750, "seen": 17, "decoded_ms": 202.290292}, {"seq": 18, "x": 548, "y": 850, "seen": 18, "decoded_ms": 201.035264}, {"seq": 19, "x": 914, "y": 750, "seen": 19, "decoded_ms": 169.113849}, {"seq": 20, "x": 1280, "y": 850, "seen": 20, "decoded_ms": 389.791156}, {"seq": 21, "x": 1645, "y": 750, "seen": 21, "decoded_ms": 145.709303}, {"seq": 22, "x": 2011, "y": 850, "seen": 22, "decoded_ms": 142.136716}, {"seq": 23, "x": 2377, "y": 750, "seen": 23, "decoded_ms": 150.834416}, {"seq": 24, "x": 182, "y": 850, "seen": 24, "decoded_ms": 218.919785}, {"seq": 25, "x": 548, "y": 750, "seen": 25, "decoded_ms": 145.115185}, {"seq": 26, "x": 914, "y": 850, "seen": 26, "decoded_ms": 174.238963}, {"seq": 27, "x": 1280, "y": 750, "seen": 27, "decoded_ms": 476.883703}, {"seq": 28, "x": 1645, "y": 850, "seen": 28, "decoded_ms": 165.254265}, {"seq": 29, "x": 2011, "y": 750, "seen": 29, "decoded_ms": 182.507335}, {"seq": 30, "x": 2377, "y": 850, "seen": 30, "decoded_ms": 168.10207}], "p50_ms": 180.106648, "p95_ms": 475.373962, "method": "XTest click-down to unique decoded sequence; excludes USB and scanout"}
|
||||
@@ -0,0 +1 @@
|
||||
{"host": "192.168.1.72", "pid": 293859, "shapes": [{"name": "default", "source": {"w": 24, "h": 24, "hx": 3, "hy": 1, "x": 181, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 182, "y": 600, "w": 24, "h": 24, "hx": 3, "hy": 1}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 254, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "text", "source": {"w": 24, "h": 24, "hx": 11, "hy": 12, "x": 547, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 548, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 240, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "ew-resize", "source": {"w": 24, "h": 24, "hx": 12, "hy": 12, "x": 913, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 914, "y": 600, "w": 24, "h": 24, "hx": 12, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 301, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "wait", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 1280, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 1280, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 433, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "none", "source": {"w": 1, "h": 1, "hx": 0, "hy": 0, "x": 1645, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 1645, "y": 600, "w": 1, "h": 1, "hx": 0, "hy": 0}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 0, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "crosshair", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 2011, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 2011, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 281, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "custom", "source": {"w": 24, "h": 24, "hx": 7, "hy": 9, "x": 2377, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 2377, "y": 600, "w": 24, "h": 24, "hx": 7, "hy": 9}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 576, "video": {"reference": 15726074, "nonuniform_pixels": 0}}], "paused_client": {"position": [350, 700], "elapsed_ms": 249.623897, "same_shape": true, "steps": [{"target": [250, 650], "position": [250, 650], "query_ms": 2.255624}, {"target": [280, 670], "position": [280, 670], "query_ms": 2.353619}, {"target": [300, 690], "position": [300, 690], "query_ms": 2.202252}, {"target": [350, 700], "position": [350, 700], "query_ms": 2.288873}]}, "clicks": [{"seq": 1, "x": 182, "y": 750, "seen": 1, "decoded_ms": 186.428878}, {"seq": 2, "x": 548, "y": 850, "seen": 2, "decoded_ms": 181.712898}, {"seq": 3, "x": 914, "y": 750, "seen": 3, "decoded_ms": 207.490698}, {"seq": 4, "x": 1280, "y": 850, "seen": 4, "decoded_ms": 533.830025}, {"seq": 5, "x": 1645, "y": 750, "seen": 5, "decoded_ms": 190.340809}, {"seq": 6, "x": 2011, "y": 850, "seen": 6, "decoded_ms": 204.401567}, {"seq": 7, "x": 2377, "y": 750, "seen": 7, "decoded_ms": 166.595545}, {"seq": 8, "x": 182, "y": 850, "seen": 8, "decoded_ms": 195.011611}, {"seq": 9, "x": 548, "y": 750, "seen": 9, "decoded_ms": 181.070161}, {"seq": 10, "x": 914, "y": 850, "seen": 10, "decoded_ms": 191.989545}, {"seq": 11, "x": 1280, "y": 750, "seen": 11, "decoded_ms": 450.587655}, {"seq": 12, "x": 1645, "y": 850, "seen": 12, "decoded_ms": 166.558247}, {"seq": 13, "x": 2011, "y": 750, "seen": 13, "decoded_ms": 174.993944}, {"seq": 14, "x": 2377, "y": 850, "seen": 14, "decoded_ms": 195.413266}, {"seq": 15, "x": 182, "y": 750, "seen": 15, "decoded_ms": 242.226344}, {"seq": 16, "x": 548, "y": 850, "seen": 16, "decoded_ms": 206.124429}, {"seq": 17, "x": 914, "y": 750, "seen": 17, "decoded_ms": 181.78767}, {"seq": 18, "x": 1280, "y": 850, "seen": 18, "decoded_ms": 463.825494}, {"seq": 19, "x": 1645, "y": 750, "seen": 19, "decoded_ms": 194.360157}, {"seq": 20, "x": 2011, "y": 850, "seen": 20, "decoded_ms": 177.975533}, {"seq": 21, "x": 2377, "y": 750, "seen": 21, "decoded_ms": 229.660945}, {"seq": 22, "x": 182, "y": 850, "seen": 22, "decoded_ms": 159.611781}, {"seq": 23, "x": 548, "y": 750, "seen": 23, "decoded_ms": 149.18704}, {"seq": 24, "x": 914, "y": 850, "seen": 24, "decoded_ms": 179.366438}, {"seq": 25, "x": 1280, "y": 750, "seen": 25, "decoded_ms": 522.420223}, {"seq": 26, "x": 1645, "y": 850, "seen": 26, "decoded_ms": 154.151825}, {"seq": 27, "x": 2011, "y": 750, "seen": 27, "decoded_ms": 154.669796}, {"seq": 28, "x": 2377, "y": 850, "seen": 28, "decoded_ms": 145.580813}], "p50_ms": 188.3848435, "p95_ms": 522.420223, "method": "XTest click-down to unique decoded sequence; excludes USB and scanout"}
|
||||
|
After Width: | Height: | Size: 129 KiB |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"agent": 39181,
|
||||
"client": 293859,
|
||||
"pause_seconds": 1.1,
|
||||
"local_pointer": "x:650 y:900 screen:0 window:48234511",
|
||||
"survived": true
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"bridge_frozen_seconds": 1.2,
|
||||
"checked_after_seconds": 3.289,
|
||||
"remaining_clients": []
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"host": "192.168.1.72", "pid": 272099, "shapes": [{"name": "default", "source": {"w": 24, "h": 24, "hx": 3, "hy": 1, "x": 181, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 182, "y": 600, "w": 24, "h": 24, "hx": 3, "hy": 1}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 254, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "text", "source": {"w": 24, "h": 24, "hx": 11, "hy": 12, "x": 547, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 548, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 240, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "ew-resize", "source": {"w": 24, "h": 24, "hx": 12, "hy": 12, "x": 913, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 914, "y": 600, "w": 24, "h": 24, "hx": 12, "hy": 12}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 301, "video": {"reference": 15726330, "nonuniform_pixels": 0}}, {"name": "wait", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 1280, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 1280, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 433, "video": {"reference": 15791866, "nonuniform_pixels": 0}}, {"name": "none", "source": {"w": 1, "h": 1, "hx": 0, "hy": 0, "x": 1645, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 1645, "y": 600, "w": 1, "h": 1, "hx": 0, "hy": 0}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 0, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "crosshair", "source": {"w": 24, "h": 24, "hx": 11, "hy": 11, "x": 2011, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 2011, "y": 600, "w": 24, "h": 24, "hx": 11, "hy": 11}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 281, "video": {"reference": 15726074, "nonuniform_pixels": 0}}, {"name": "custom", "source": {"w": 24, "h": 24, "hx": 7, "hy": 9, "x": 2377, "y": 599, "sw": 2560, "sh": 1440}, "local": {"x": 2377, "y": 600, "w": 24, "h": 24, "hx": 7, "hy": 9}, "geometry_matches": true, "max_pixel_difference": 0, "visible_pixels": 576, "video": {"reference": 15726074, "nonuniform_pixels": 0}}], "paused_client": {"position": [350, 700], "elapsed_ms": 263.611753, "same_shape": true, "steps": [{"target": [250, 650], "position": [250, 650], "query_ms": 16.220678}, {"target": [280, 670], "position": [280, 670], "query_ms": 2.214575}, {"target": [300, 690], "position": [300, 690], "query_ms": 2.215451}, {"target": [350, 700], "position": [350, 700], "query_ms": 2.380822}]}, "clicks": [{"seq": 2, "x": 182, "y": 750, "seen": 2, "decoded_ms": 192.980398}, {"seq": 3, "x": 548, "y": 850, "seen": 3, "decoded_ms": 249.189423}, {"seq": 4, "x": 914, "y": 750, "seen": 4, "decoded_ms": 193.088898}, {"seq": 5, "x": 1280, "y": 850, "seen": 5, "decoded_ms": 374.099277}, {"seq": 6, "x": 1645, "y": 750, "seen": 6, "decoded_ms": 166.521582}, {"seq": 7, "x": 2011, "y": 850, "seen": 7, "decoded_ms": 207.861192}, {"seq": 8, "x": 2377, "y": 750, "seen": 8, "decoded_ms": 246.000709}, {"seq": 9, "x": 182, "y": 850, "seen": 9, "decoded_ms": 181.998527}, {"seq": 10, "x": 548, "y": 750, "seen": 10, "decoded_ms": 181.410831}, {"seq": 11, "x": 914, "y": 850, "seen": 11, "decoded_ms": 221.952754}, {"seq": 12, "x": 1280, "y": 750, "seen": 12, "decoded_ms": 507.168335}, {"seq": 13, "x": 1645, "y": 850, "seen": 13, "decoded_ms": 182.568433}, {"seq": 14, "x": 2011, "y": 750, "seen": 14, "decoded_ms": 164.879833}, {"seq": 15, "x": 2377, "y": 850, "seen": 15, "decoded_ms": 212.375805}, {"seq": 16, "x": 182, "y": 750, "seen": 16, "decoded_ms": 188.116394}, {"seq": 17, "x": 548, "y": 850, "seen": 17, "decoded_ms": 203.54084}, {"seq": 18, "x": 914, "y": 750, "seen": 18, "decoded_ms": 183.044427}, {"seq": 19, "x": 1280, "y": 850, "seen": 19, "decoded_ms": 316.917585}, {"seq": 20, "x": 1645, "y": 750, "seen": 20, "decoded_ms": 161.788239}, {"seq": 21, "x": 2011, "y": 850, "seen": 21, "decoded_ms": 180.879436}, {"seq": 22, "x": 2377, "y": 750, "seen": 22, "decoded_ms": 172.71762}, {"seq": 23, "x": 182, "y": 850, "seen": 23, "decoded_ms": 175.79901}, {"seq": 24, "x": 548, "y": 750, "seen": 24, "decoded_ms": 185.907366}, {"seq": 25, "x": 914, "y": 850, "seen": 25, "decoded_ms": 207.759418}, {"seq": 26, "x": 1280, "y": 750, "seen": 26, "decoded_ms": 468.920931}, {"seq": 27, "x": 1645, "y": 850, "seen": 27, "decoded_ms": 189.784407}, {"seq": 28, "x": 2011, "y": 750, "seen": 28, "decoded_ms": 186.12174}, {"seq": 29, "x": 2377, "y": 850, "seen": 29, "decoded_ms": 182.798273}], "p50_ms": 188.9504005, "p95_ms": 468.920931, "method": "XTest click-down to unique decoded sequence; excludes USB and scanout"}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"host": "192.168.1.72",
|
||||
"target": [
|
||||
400,
|
||||
600
|
||||
],
|
||||
"readback": "X=400\nY=600\nSCREEN=0\nWINDOW=48234511\n",
|
||||
"passed": true
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"host": "192.168.1.72",
|
||||
"target": [
|
||||
400,
|
||||
600
|
||||
],
|
||||
"readback": "X=1500\nY=900\nSCREEN=0\nWINDOW=48234511\n"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"pid": 299142, "args": "/home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream 192.168.1.70 Desktop --resolution 2560x1440 --fps 45 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --capture-system-keys always --keep-awake --no-vsync --no-frame-pacing --audio-on-host ", "sha256": "5d4330f703d7f8e053bc3795ca42bdaf231c9e9dd8ebb00a612013adbcccee03", "native": false}
|
||||
|
After Width: | Height: | Size: 2.6 MiB |