diff --git a/docs/evidence/cursor-poc-20261103/01-remote-cursor-cursor-region.png b/docs/evidence/cursor-poc-20261103/01-remote-cursor-cursor-region.png new file mode 100644 index 0000000..4f5ed07 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/01-remote-cursor-cursor-region.png differ diff --git a/docs/evidence/cursor-poc-20261103/01-remote-cursor.png b/docs/evidence/cursor-poc-20261103/01-remote-cursor.png new file mode 100644 index 0000000..7eb2368 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/01-remote-cursor.png differ diff --git a/docs/evidence/cursor-poc-20261103/02-video-cursor-disabled-cursor-region.png b/docs/evidence/cursor-poc-20261103/02-video-cursor-disabled-cursor-region.png new file mode 100644 index 0000000..61dc82b Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/02-video-cursor-disabled-cursor-region.png differ diff --git a/docs/evidence/cursor-poc-20261103/02-video-cursor-disabled.png b/docs/evidence/cursor-poc-20261103/02-video-cursor-disabled.png new file mode 100644 index 0000000..4736c97 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/02-video-cursor-disabled.png differ diff --git a/docs/evidence/cursor-poc-20261103/03-local-mode-video-only-cursor-region.png b/docs/evidence/cursor-poc-20261103/03-local-mode-video-only-cursor-region.png new file mode 100644 index 0000000..e260fbb Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/03-local-mode-video-only-cursor-region.png differ diff --git a/docs/evidence/cursor-poc-20261103/03-local-mode-video-only.png b/docs/evidence/cursor-poc-20261103/03-local-mode-video-only.png new file mode 100644 index 0000000..fe48f11 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/03-local-mode-video-only.png differ diff --git a/docs/evidence/cursor-poc-20261103/04-remote-cursor-restored-cursor-region.png b/docs/evidence/cursor-poc-20261103/04-remote-cursor-restored-cursor-region.png new file mode 100644 index 0000000..8759d38 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/04-remote-cursor-restored-cursor-region.png differ diff --git a/docs/evidence/cursor-poc-20261103/04-remote-cursor-restored.png b/docs/evidence/cursor-poc-20261103/04-remote-cursor-restored.png new file mode 100644 index 0000000..bc97f3f Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/04-remote-cursor-restored.png differ diff --git a/docs/evidence/cursor-poc-20261103/__hidden.json b/docs/evidence/cursor-poc-20261103/__hidden.json new file mode 100644 index 0000000..36fc3f9 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/__hidden.json @@ -0,0 +1 @@ +{"width": 1, "height": 1, "hotX": 0, "hotY": 0, "x": 320, "y": 1250, "argb": [0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/arrow.json b/docs/evidence/cursor-poc-20261103/arrow.json new file mode 100644 index 0000000..310c861 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/arrow.json @@ -0,0 +1 @@ +{"width": 32, "height": 32, "hotX": 0, "hotY": 0, "x": 320, "y": 500, "argb": [4278255885, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294507003, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4293980403, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4292993507, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294243575, 4294967295, 4294967295, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294243575, 4278255630, 4289967292, 4294967295, 4278387726, 4278782222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294243575, 4278255630, 4278848013, 4278321678, 4294967295, 4292993507, 4278321678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294243575, 4278255630, 4278848013, 0, 4278453264, 4290953929, 4294967295, 4278453264, 4278782222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278387726, 4278255630, 4278848013, 0, 0, 4278848013, 4278321678, 4294967295, 4292269784, 4278321678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278453264, 4292269784, 4294967295, 4278387214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979085, 4278321678, 4278519056, 4278913294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/before.png b/docs/evidence/cursor-poc-20261103/before.png new file mode 100644 index 0000000..eea05fb Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/before.png differ diff --git a/docs/evidence/cursor-poc-20261103/click-verification.json b/docs/evidence/cursor-poc-20261103/click-verification.json new file mode 100644 index 0000000..9b67a91 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/click-verification.json @@ -0,0 +1,5 @@ +{ + "clicks": 32, + "correct_regions_and_shapes": 32, + "max_coordinate_quantization_px": 1 +} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/cursor-poc-evidence-first.tar.gz b/docs/evidence/cursor-poc-20261103/cursor-poc-evidence-first.tar.gz new file mode 100644 index 0000000..8e47f5a Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/cursor-poc-evidence-first.tar.gz differ diff --git a/docs/evidence/cursor-poc-20261103/cursor-poc-evidence-v3.tar.gz b/docs/evidence/cursor-poc-20261103/cursor-poc-evidence-v3.tar.gz new file mode 100644 index 0000000..03fda58 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/cursor-poc-evidence-v3.tar.gz differ diff --git a/docs/evidence/cursor-poc-20261103/final-display.txt b/docs/evidence/cursor-poc-20261103/final-display.txt new file mode 100644 index 0000000..946d168 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/final-display.txt @@ -0,0 +1,3 @@ +{"action":"Query","device":"\\\\.\\DISPLAY3","hz":60,"width":2560,"bpp":32,"height":1440} +task_result=0 + diff --git a/docs/evidence/cursor-poc-20261103/final-host.txt b/docs/evidence/cursor-poc-20261103/final-host.txt new file mode 100644 index 0000000..11d3dd2 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/final-host.txt @@ -0,0 +1,10 @@ +{"Name":"NVIDIA GeForce GTX 965M","ConfigManagerErrorCode":0} +NVIDIA GeForce GTX 965M, 582.78, 11 % +cursor_probe_task_present=False + +[2026-11-03 14:29:49.548]: Info: Found H.264 encoder: h264_nvenc [nvenc] +[2026-11-03 14:29:50.970]: Info: Creating encoder [h264_nvenc] +[2026-11-03 14:34:22.851]: Info: Creating encoder [h264_nvenc] + + + diff --git a/docs/evidence/cursor-poc-20261103/final-local-cursor.txt b/docs/evidence/cursor-poc-20261103/final-local-cursor.txt new file mode 100644 index 0000000..d69451d --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/final-local-cursor.txt @@ -0,0 +1,2 @@ +{'width': 1, 'height': 1, 'hotX': 0, 'hotY': 0, 'x': 100, 'y': 100} +visible_local_pixels 0 diff --git a/docs/evidence/cursor-poc-20261103/final-normal-desktop.png b/docs/evidence/cursor-poc-20261103/final-normal-desktop.png new file mode 100644 index 0000000..ea49f84 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/final-normal-desktop.png differ diff --git a/docs/evidence/cursor-poc-20261103/first-01-remote-cursor.png b/docs/evidence/cursor-poc-20261103/first-01-remote-cursor.png new file mode 100644 index 0000000..de53099 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/first-01-remote-cursor.png differ diff --git a/docs/evidence/cursor-poc-20261103/first-02-video-cursor-disabled.png b/docs/evidence/cursor-poc-20261103/first-02-video-cursor-disabled.png new file mode 100644 index 0000000..039db11 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/first-02-video-cursor-disabled.png differ diff --git a/docs/evidence/cursor-poc-20261103/first-03-local-mode-video-only-small.png b/docs/evidence/cursor-poc-20261103/first-03-local-mode-video-only-small.png new file mode 100644 index 0000000..7b35c42 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/first-03-local-mode-video-only-small.png differ diff --git a/docs/evidence/cursor-poc-20261103/first-03-local-mode-video-only.png b/docs/evidence/cursor-poc-20261103/first-03-local-mode-video-only.png new file mode 100644 index 0000000..42d3252 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/first-03-local-mode-video-only.png differ diff --git a/docs/evidence/cursor-poc-20261103/first-04-remote-cursor-restored-small.png b/docs/evidence/cursor-poc-20261103/first-04-remote-cursor-restored-small.png new file mode 100644 index 0000000..8f3c5e4 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/first-04-remote-cursor-restored-small.png differ diff --git a/docs/evidence/cursor-poc-20261103/first-04-remote-cursor-restored.png b/docs/evidence/cursor-poc-20261103/first-04-remote-cursor-restored.png new file mode 100644 index 0000000..20f2509 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/first-04-remote-cursor-restored.png differ diff --git a/docs/evidence/cursor-poc-20261103/first-__hidden.json b/docs/evidence/cursor-poc-20261103/first-__hidden.json new file mode 100644 index 0000000..36fc3f9 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/first-__hidden.json @@ -0,0 +1 @@ +{"width": 1, "height": 1, "hotX": 0, "hotY": 0, "x": 320, "y": 1250, "argb": [0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/first-arrow.json b/docs/evidence/cursor-poc-20261103/first-arrow.json new file mode 100644 index 0000000..310c861 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/first-arrow.json @@ -0,0 +1 @@ +{"width": 32, "height": 32, "hotX": 0, "hotY": 0, "x": 320, "y": 500, "argb": [4278255885, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294507003, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4293980403, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4292993507, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294967295, 4294243575, 4294967295, 4294967295, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294967295, 4294243575, 4278255630, 4289967292, 4294967295, 4278387726, 4278782222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294967295, 4294243575, 4278255630, 4278848013, 4278321678, 4294967295, 4292993507, 4278321678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278255885, 4294243575, 4278255630, 4278848013, 0, 4278453264, 4290953929, 4294967295, 4278453264, 4278782222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278387726, 4278255630, 4278848013, 0, 0, 4278848013, 4278321678, 4294967295, 4292269784, 4278321678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278453264, 4292269784, 4294967295, 4278387214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979085, 4278321678, 4278519056, 4278913294, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/first-ibeam.json b/docs/evidence/cursor-poc-20261103/first-ibeam.json new file mode 100644 index 0000000..dea5010 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/first-ibeam.json @@ -0,0 +1 @@ +{"width": 32, "height": 32, "hotX": 8, "hotY": 9, "x": 960, "y": 500, "argb": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 4294112499, 4294112499, 0, 4294112499, 4294112499, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 4294112499, 4294112499, 0, 4294112499, 4294112499, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/first-lease.json b/docs/evidence/cursor-poc-20261103/first-lease.json new file mode 100644 index 0000000..53a9d87 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/first-lease.json @@ -0,0 +1 @@ +{"version": 1, "shape": "arrow", "visible": true, "expires": 1793689477.871138} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/first-results.json b/docs/evidence/cursor-poc-20261103/first-results.json new file mode 100644 index 0000000..7765025 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/first-results.json @@ -0,0 +1,44 @@ +[ + { + "shape": "arrow", + "x": 320, + "y": 500, + "visible": true + }, + { + "shape": "ibeam", + "x": 960, + "y": 500, + "visible": true + }, + { + "shape": "sizewe", + "x": 1600, + "y": 500, + "visible": true + }, + { + "shape": "wait", + "x": 2240, + "y": 500, + "visible": true + }, + { + "shape": "__hidden", + "x": 320, + "y": 1250, + "visible": false + }, + { + "test": "client-paused-local-motion", + "before": [ + 320, + 500 + ], + "after": [ + 500, + 650 + ], + "passed": true + } +] \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/first-sizewe.json b/docs/evidence/cursor-poc-20261103/first-sizewe.json new file mode 100644 index 0000000..a331d6d --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/first-sizewe.json @@ -0,0 +1 @@ +{"width": 32, "height": 32, "hotX": 11, "hotY": 4, "x": 1600, "y": 500, "argb": [0, 0, 0, 4278848013, 4278387726, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278387726, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4278190093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190093, 4293980403, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4294967295, 4278190093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190093, 4294967295, 4293717230, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4294967295, 4294967295, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4294967295, 4294967295, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278387726, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4293454058, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4294967295, 4294967295, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4294967295, 4294967295, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4294967295, 4278190093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190093, 4294967295, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4278190093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190093, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278387726, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/first-wait.json b/docs/evidence/cursor-poc-20261103/first-wait.json new file mode 100644 index 0000000..90f78a2 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/first-wait.json @@ -0,0 +1 @@ +{"width": 32, "height": 32, "hotX": 16, "hotY": 16, "x": 2240, "y": 500, "argb": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4278979083, 4278979083, 4278979083, 4278979083, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979339, 4278979083, 4279580242, 4280048014, 4280448185, 4280448185, 4280448185, 4280448185, 4280048014, 4279580242, 4278979083, 4278979339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279446596, 4280714710, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280714710, 4279446596, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980159, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279980159, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280119199, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279980159, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979339, 4279784819, 4280667391, 4280793339, 4280982260, 4280981491, 4280981491, 4280848101, 4280181404, 4279980160, 4279980160, 4280181404, 4280848101, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279446596, 4278979339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280664570, 4280667391, 4280667391, 4280730109, 4280982260, 4280380330, 4279046681, 4278979083, 4278979083, 4278979083, 4278979083, 4279046681, 4280380330, 4280981491, 4280981491, 4280981491, 4280981491, 4280714710, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4279786110, 4280667391, 4280667391, 4280667391, 4280667391, 4280461279, 4278979083, 0, 0, 0, 0, 0, 0, 4278979083, 4280380330, 4280981491, 4280981491, 4280981491, 4280981491, 4279580242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280392398, 4280667391, 4280667391, 4280667391, 4280600829, 4279115303, 0, 0, 0, 0, 0, 0, 0, 0, 4279046681, 4280848101, 4280981491, 4280981491, 4280981491, 4280048014, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280595950, 4280667391, 4280667391, 4280667391, 4280525786, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280181404, 4280981491, 4280981491, 4280981491, 4280448185, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280597749, 4280667391, 4280667391, 4280667391, 4280323776, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980160, 4280981491, 4280981491, 4280981491, 4280448185, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280597749, 4280667391, 4280667391, 4280667391, 4280323776, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980160, 4280981491, 4280981491, 4280981491, 4280448185, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280595950, 4280667391, 4280667391, 4280667391, 4280462048, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280181404, 4280981491, 4280981491, 4280981491, 4280448185, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280392398, 4280667391, 4280731134, 4280792314, 4280850923, 4279046681, 0, 0, 0, 0, 0, 0, 0, 0, 4279046681, 4280848101, 4280981491, 4280981491, 4280981491, 4280048014, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4279718259, 4280854519, 4280981491, 4280981491, 4280981491, 4280380330, 4278979083, 0, 0, 0, 0, 0, 0, 4278979083, 4280380330, 4280981491, 4280981491, 4280981491, 4280981491, 4279580242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280714710, 4280981491, 4280981491, 4280981491, 4280981491, 4280380330, 4279046681, 4278979083, 4278979083, 4278979083, 4278979083, 4279046681, 4280380330, 4280981491, 4280981491, 4280981491, 4280981491, 4280714710, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979339, 4279446596, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280848101, 4280181404, 4279980160, 4279980160, 4280181404, 4280848101, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279446596, 4278979339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980159, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279980159, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980159, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279980159, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279446596, 4280714710, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280714710, 4279446596, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979339, 4278979083, 4279580242, 4280048014, 4280448185, 4280448185, 4280448185, 4280448185, 4280048014, 4279580242, 4278979083, 4278979339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4278979083, 4278979083, 4278979083, 4278979083, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/host-final-probe.txt b/docs/evidence/cursor-poc-20261103/host-final-probe.txt new file mode 100644 index 0000000..83f58f0 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/host-final-probe.txt @@ -0,0 +1,74 @@ +{"version":1,"shape":"wait","visible":true,"x":2240,"y":741,"utc":"2026-11-03T07:12:30.9503413Z"} +utc,x,y,shape +2026-11-03T07:11:23.6728439Z,320,600,arrow +2026-11-03T07:11:23.9853459Z,959,600,ibeam +2026-11-03T07:11:24.2703418Z,1600,600,sizewe +2026-11-03T07:11:24.5743423Z,2240,600,wait +2026-11-03T07:11:24.8668434Z,320,620,arrow +2026-11-03T07:11:25.1643408Z,959,620,ibeam +2026-11-03T07:11:25.4458407Z,1600,620,sizewe +2026-11-03T07:11:25.7348467Z,2240,620,wait +2026-11-03T07:11:26.0408467Z,320,639,arrow +2026-11-03T07:11:26.3293390Z,959,639,ibeam +2026-11-03T07:11:26.6163416Z,1600,639,sizewe +2026-11-03T07:11:26.9133420Z,2240,639,wait +2026-11-03T07:11:27.1828416Z,320,659,arrow +2026-11-03T07:11:27.4833409Z,959,659,ibeam +2026-11-03T07:11:27.7798422Z,1600,659,sizewe +2026-11-03T07:11:28.0623467Z,2240,659,wait +2026-11-03T07:11:28.3813431Z,320,679,arrow +2026-11-03T07:11:28.6843441Z,959,679,ibeam +2026-11-03T07:11:28.9513522Z,1600,679,sizewe +2026-11-03T07:11:29.2338429Z,2240,679,wait +2026-11-03T07:11:29.5318423Z,320,699,arrow +2026-11-03T07:11:29.8163521Z,959,699,ibeam +2026-11-03T07:11:30.1223411Z,1600,699,sizewe +2026-11-03T07:11:30.4248457Z,2240,699,wait +2026-11-03T07:11:30.6963403Z,320,720,arrow +2026-11-03T07:11:30.9818405Z,959,720,ibeam +2026-11-03T07:11:31.2808460Z,1600,720,sizewe +2026-11-03T07:11:31.5703482Z,2240,720,wait +2026-11-03T07:11:31.8683454Z,320,740,arrow +2026-11-03T07:11:32.1633457Z,959,740,ibeam +2026-11-03T07:11:32.4473379Z,1600,740,sizewe +2026-11-03T07:11:32.7883589Z,2240,740,wait +utc,shape,flags,x,y +2026-11-03T07:11:06.8498407Z,wait,1,2559,0 +2026-11-03T07:11:16.6898849Z,arrow,1,320,499 +2026-11-03T07:11:19.9603457Z,ibeam,1,959,499 +2026-11-03T07:11:20.6268581Z,sizewe,1,1600,499 +2026-11-03T07:11:21.2778534Z,wait,1,2240,499 +2026-11-03T07:11:21.9288721Z,unknown,0,320,1250 +2026-11-03T07:11:22.4868707Z,arrow,1,320,499 +2026-11-03T07:11:23.8973466Z,ibeam,1,959,600 +2026-11-03T07:11:24.2383472Z,sizewe,1,1600,600 +2026-11-03T07:11:24.5638838Z,wait,1,2240,600 +2026-11-03T07:11:24.8898404Z,arrow,1,320,620 +2026-11-03T07:11:25.1063443Z,ibeam,1,959,620 +2026-11-03T07:11:25.4318717Z,sizewe,1,1600,620 +2026-11-03T07:11:25.7573475Z,wait,1,2240,620 +2026-11-03T07:11:25.9898858Z,arrow,1,320,639 +2026-11-03T07:11:26.3153463Z,ibeam,1,959,639 +2026-11-03T07:11:26.6408719Z,sizewe,1,1600,639 +2026-11-03T07:11:26.8578756Z,wait,1,2240,639 +2026-11-03T07:11:27.1958524Z,arrow,1,320,659 +2026-11-03T07:11:27.5088735Z,ibeam,1,959,659 +2026-11-03T07:11:27.7258762Z,sizewe,1,1600,659 +2026-11-03T07:11:28.0758556Z,wait,1,2240,659 +2026-11-03T07:11:28.3948537Z,arrow,1,320,679 +2026-11-03T07:11:28.6093549Z,ibeam,1,959,679 +2026-11-03T07:11:28.9348850Z,sizewe,1,1600,679 +2026-11-03T07:11:29.1518438Z,wait,1,2240,679 +2026-11-03T07:11:29.4773532Z,arrow,1,320,699 +2026-11-03T07:11:29.8318419Z,ibeam,1,959,699 +2026-11-03T07:11:30.1438730Z,sizewe,1,1600,699 +2026-11-03T07:11:30.3608443Z,wait,1,2240,699 +2026-11-03T07:11:30.6863784Z,arrow,1,320,720 +2026-11-03T07:11:30.9033588Z,ibeam,1,959,720 +2026-11-03T07:11:31.2288704Z,sizewe,1,1600,720 +2026-11-03T07:11:31.5543568Z,wait,1,2240,720 +2026-11-03T07:11:31.8998470Z,arrow,1,320,740 +2026-11-03T07:11:32.1123740Z,ibeam,1,959,740 +2026-11-03T07:11:32.4378716Z,sizewe,1,1600,740 +2026-11-03T07:11:32.7633726Z,wait,1,2240,740 + diff --git a/docs/evidence/cursor-poc-20261103/host-first.txt b/docs/evidence/cursor-poc-20261103/host-first.txt new file mode 100644 index 0000000..aa9b4fe --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/host-first.txt @@ -0,0 +1,74 @@ +{"version":1,"shape":"wait","visible":true,"x":2308,"y":758,"utc":"2026-11-03T07:07:02.9393420Z"} +utc,x,y,shape +2026-11-03T07:04:27.5718439Z,320,600,arrow +2026-11-03T07:04:27.8688460Z,959,600,ibeam +2026-11-03T07:04:28.1413412Z,1600,600,sizewe +2026-11-03T07:04:28.4368405Z,2240,600,wait +2026-11-03T07:04:28.7398485Z,320,620,arrow +2026-11-03T07:04:29.0323472Z,959,620,ibeam +2026-11-03T07:04:29.3253400Z,1600,620,sizewe +2026-11-03T07:04:29.6178424Z,2240,620,wait +2026-11-03T07:04:29.9088496Z,320,639,arrow +2026-11-03T07:04:30.2033461Z,959,639,ibeam +2026-11-03T07:04:30.4853411Z,1600,639,sizewe +2026-11-03T07:04:30.7708577Z,2240,639,wait +2026-11-03T07:04:31.0543463Z,320,659,arrow +2026-11-03T07:04:31.3768397Z,959,659,ibeam +2026-11-03T07:04:31.6688468Z,1600,659,sizewe +2026-11-03T07:04:31.9598392Z,2240,659,wait +2026-11-03T07:04:32.2533467Z,320,679,arrow +2026-11-03T07:04:32.5598422Z,959,679,ibeam +2026-11-03T07:04:32.8513466Z,1600,679,sizewe +2026-11-03T07:04:33.1398470Z,2240,679,wait +2026-11-03T07:04:33.4373390Z,320,699,arrow +2026-11-03T07:04:33.7618453Z,959,699,ibeam +2026-11-03T07:04:34.0528411Z,1600,699,sizewe +2026-11-03T07:04:34.3553395Z,2240,699,wait +2026-11-03T07:04:34.6193461Z,320,720,arrow +2026-11-03T07:04:34.9018406Z,959,720,ibeam +2026-11-03T07:04:35.1888416Z,1600,720,sizewe +2026-11-03T07:04:35.4698436Z,2240,720,wait +2026-11-03T07:04:35.7783469Z,320,740,arrow +2026-11-03T07:04:36.0693463Z,959,740,ibeam +2026-11-03T07:04:36.3558408Z,1600,740,sizewe +2026-11-03T07:04:36.6408493Z,2240,740,wait +utc,shape,flags,x,y +2026-11-03T07:04:11.1088554Z,wait,1,2426,267 +2026-11-03T07:04:20.5148709Z,arrow,1,320,499 +2026-11-03T07:04:23.8008747Z,ibeam,1,959,499 +2026-11-03T07:04:24.4518732Z,sizewe,1,1600,499 +2026-11-03T07:04:25.1028711Z,wait,1,2240,499 +2026-11-03T07:04:25.7693710Z,unknown,0,320,1250 +2026-11-03T07:04:26.4203719Z,arrow,1,320,499 +2026-11-03T07:04:27.8463737Z,ibeam,1,959,600 +2026-11-03T07:04:28.1718717Z,sizewe,1,1600,600 +2026-11-03T07:04:28.3888745Z,wait,1,2240,600 +2026-11-03T07:04:28.7143746Z,arrow,1,320,620 +2026-11-03T07:04:29.0463438Z,ibeam,1,959,620 +2026-11-03T07:04:29.2568716Z,sizewe,1,1600,620 +2026-11-03T07:04:29.5978717Z,wait,1,2240,620 +2026-11-03T07:04:29.9258382Z,arrow,1,320,639 +2026-11-03T07:04:30.1403684Z,ibeam,1,959,639 +2026-11-03T07:04:30.4658710Z,sizewe,1,1600,639 +2026-11-03T07:04:30.7918446Z,wait,1,2240,639 +2026-11-03T07:04:31.0083608Z,arrow,1,320,659 +2026-11-03T07:04:31.3493702Z,ibeam,1,959,659 +2026-11-03T07:04:31.6833398Z,sizewe,1,1600,659 +2026-11-03T07:04:31.8918706Z,wait,1,2240,659 +2026-11-03T07:04:32.2173716Z,arrow,1,320,679 +2026-11-03T07:04:32.5428703Z,ibeam,1,959,679 +2026-11-03T07:04:32.8683855Z,sizewe,1,1600,679 +2026-11-03T07:04:33.0853744Z,wait,1,2240,679 +2026-11-03T07:04:33.4263715Z,arrow,1,320,699 +2026-11-03T07:04:33.7518751Z,ibeam,1,959,699 +2026-11-03T07:04:34.0773750Z,sizewe,1,1600,699 +2026-11-03T07:04:34.2943515Z,wait,1,2240,699 +2026-11-03T07:04:34.6348401Z,arrow,1,320,720 +2026-11-03T07:04:34.8368725Z,ibeam,1,959,720 +2026-11-03T07:04:35.1778728Z,sizewe,1,1600,720 +2026-11-03T07:04:35.3933486Z,wait,1,2240,720 +2026-11-03T07:04:35.7203735Z,arrow,1,320,740 +2026-11-03T07:04:36.0458710Z,ibeam,1,959,740 +2026-11-03T07:04:36.3713767Z,sizewe,1,1600,740 +2026-11-03T07:04:36.5883715Z,wait,1,2240,740 + diff --git a/docs/evidence/cursor-poc-20261103/ibeam.json b/docs/evidence/cursor-poc-20261103/ibeam.json new file mode 100644 index 0000000..dea5010 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/ibeam.json @@ -0,0 +1 @@ +{"width": 32, "height": 32, "hotX": 8, "hotY": 9, "x": 960, "y": 500, "argb": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 4294112499, 4294112499, 0, 4294112499, 4294112499, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4294112499, 4294112499, 4294112499, 0, 4294112499, 4294112499, 4294112499, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/lease.json b/docs/evidence/cursor-poc-20261103/lease.json new file mode 100644 index 0000000..f21d264 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/lease.json @@ -0,0 +1 @@ +{"version": 1, "shape": "arrow", "visible": true, "expires": 1793689894.0310185} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/remote-before-crop.png b/docs/evidence/cursor-poc-20261103/remote-before-crop.png new file mode 100644 index 0000000..1034a28 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/remote-before-crop.png differ diff --git a/docs/evidence/cursor-poc-20261103/remote-hidden-crop.png b/docs/evidence/cursor-poc-20261103/remote-hidden-crop.png new file mode 100644 index 0000000..1034a28 Binary files /dev/null and b/docs/evidence/cursor-poc-20261103/remote-hidden-crop.png differ diff --git a/docs/evidence/cursor-poc-20261103/results.json b/docs/evidence/cursor-poc-20261103/results.json new file mode 100644 index 0000000..2c7e804 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/results.json @@ -0,0 +1,48 @@ +[ + { + "shape": "arrow", + "x": 320, + "y": 500, + "visible": true + }, + { + "shape": "ibeam", + "x": 960, + "y": 500, + "visible": true + }, + { + "shape": "sizewe", + "x": 1600, + "y": 500, + "visible": true + }, + { + "shape": "wait", + "x": 2240, + "y": 500, + "visible": true + }, + { + "shape": "__hidden", + "x": 320, + "y": 1250, + "visible": false + }, + { + "test": "client-paused-local-motion", + "before": [ + 320, + 500 + ], + "after": [ + 500, + 650 + ], + "passed": true + }, + { + "test": "helper-lease-expiry", + "passed": true + } +] \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/sizewe.json b/docs/evidence/cursor-poc-20261103/sizewe.json new file mode 100644 index 0000000..a331d6d --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/sizewe.json @@ -0,0 +1 @@ +{"width": 32, "height": 32, "hotX": 11, "hotY": 4, "x": 1600, "y": 500, "argb": [0, 0, 0, 4278848013, 4278387726, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278387726, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4278190093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190093, 4293980403, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4294967295, 4278190093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190093, 4294967295, 4293717230, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4294967295, 4294967295, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4294967295, 4294967295, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278387726, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4293454058, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4294967295, 4294967295, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4278387726, 4294967295, 4294967295, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4294967295, 4278190093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190093, 4294967295, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4294967295, 4278190093, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278190093, 4293454058, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278848013, 4278387726, 4278387726, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278387726, 4278387726, 4278848013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/video-cursor-regions.json b/docs/evidence/cursor-poc-20261103/video-cursor-regions.json new file mode 100644 index 0000000..327788e --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/video-cursor-regions.json @@ -0,0 +1,42 @@ +{ + "01-remote-cursor": { + "bright_pixels": 77, + "bbox": [ + 295, + 474, + 380, + 559 + ], + "pixels_above_background_threshold": 77 + }, + "02-video-cursor-disabled": { + "bright_pixels": 0, + "bbox": [ + 296, + 474, + 381, + 559 + ], + "pixels_above_background_threshold": 0 + }, + "03-local-mode-video-only": { + "bright_pixels": 0, + "bbox": [ + 2215, + 715, + 2300, + 800 + ], + "pixels_above_background_threshold": 0 + }, + "04-remote-cursor-restored": { + "bright_pixels": 0, + "bbox": [ + 2215, + 716, + 2300, + 801 + ], + "pixels_above_background_threshold": 226 + } +} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/wait.json b/docs/evidence/cursor-poc-20261103/wait.json new file mode 100644 index 0000000..90f78a2 --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/wait.json @@ -0,0 +1 @@ +{"width": 32, "height": 32, "hotX": 16, "hotY": 16, "x": 2240, "y": 500, "argb": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4278979083, 4278979083, 4278979083, 4278979083, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979339, 4278979083, 4279580242, 4280048014, 4280448185, 4280448185, 4280448185, 4280448185, 4280048014, 4279580242, 4278979083, 4278979339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279446596, 4280714710, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280714710, 4279446596, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980159, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279980159, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280119199, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279980159, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979339, 4279784819, 4280667391, 4280793339, 4280982260, 4280981491, 4280981491, 4280848101, 4280181404, 4279980160, 4279980160, 4280181404, 4280848101, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279446596, 4278979339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280664570, 4280667391, 4280667391, 4280730109, 4280982260, 4280380330, 4279046681, 4278979083, 4278979083, 4278979083, 4278979083, 4279046681, 4280380330, 4280981491, 4280981491, 4280981491, 4280981491, 4280714710, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4279786110, 4280667391, 4280667391, 4280667391, 4280667391, 4280461279, 4278979083, 0, 0, 0, 0, 0, 0, 4278979083, 4280380330, 4280981491, 4280981491, 4280981491, 4280981491, 4279580242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280392398, 4280667391, 4280667391, 4280667391, 4280600829, 4279115303, 0, 0, 0, 0, 0, 0, 0, 0, 4279046681, 4280848101, 4280981491, 4280981491, 4280981491, 4280048014, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280595950, 4280667391, 4280667391, 4280667391, 4280525786, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280181404, 4280981491, 4280981491, 4280981491, 4280448185, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280597749, 4280667391, 4280667391, 4280667391, 4280323776, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980160, 4280981491, 4280981491, 4280981491, 4280448185, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280597749, 4280667391, 4280667391, 4280667391, 4280323776, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980160, 4280981491, 4280981491, 4280981491, 4280448185, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280595950, 4280667391, 4280667391, 4280667391, 4280462048, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280181404, 4280981491, 4280981491, 4280981491, 4280448185, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280392398, 4280667391, 4280731134, 4280792314, 4280850923, 4279046681, 0, 0, 0, 0, 0, 0, 0, 0, 4279046681, 4280848101, 4280981491, 4280981491, 4280981491, 4280048014, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4279718259, 4280854519, 4280981491, 4280981491, 4280981491, 4280380330, 4278979083, 0, 0, 0, 0, 0, 0, 4278979083, 4280380330, 4280981491, 4280981491, 4280981491, 4280981491, 4279580242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4280714710, 4280981491, 4280981491, 4280981491, 4280981491, 4280380330, 4279046681, 4278979083, 4278979083, 4278979083, 4278979083, 4279046681, 4280380330, 4280981491, 4280981491, 4280981491, 4280981491, 4280714710, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979339, 4279446596, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280848101, 4280181404, 4279980160, 4279980160, 4280181404, 4280848101, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279446596, 4278979339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980159, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279980159, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279980159, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4279980159, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4279446596, 4280714710, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280981491, 4280714710, 4279446596, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979339, 4278979083, 4279580242, 4280048014, 4280448185, 4280448185, 4280448185, 4280448185, 4280048014, 4279580242, 4278979083, 4278979339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4278979083, 4278979083, 4278979083, 4278979083, 4278979083, 4278979083, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} \ No newline at end of file diff --git a/docs/evidence/cursor-poc-20261103/windows-shapes.json b/docs/evidence/cursor-poc-20261103/windows-shapes.json new file mode 100644 index 0000000..167fb5c --- /dev/null +++ b/docs/evidence/cursor-poc-20261103/windows-shapes.json @@ -0,0 +1 @@ +{"version":1,"shapes":[{"name":"arrow","width":32,"height":32,"hotX":0,"hotY":0,"invertedPixels":0,"monochrome":false,"argb":[4278255885,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294967295,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294967295,4294967295,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294967295,4294967295,4294967295,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294507003,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4293980403,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4293454058,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4292993507,4278387726,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294967295,4294243575,4294967295,4294967295,4278387726,4278387726,4278387726,4278387726,4278387726,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294967295,4294243575,4278255630,4289967292,4294967295,4278387726,4278782222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294967295,4294243575,4278255630,4278848013,4278321678,4294967295,4292993507,4278321678,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278255885,4294243575,4278255630,4278848013,0,4278453264,4290953929,4294967295,4278453264,4278782222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278387726,4278255630,4278848013,0,0,4278848013,4278321678,4294967295,4292269784,4278321678,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278453264,4292269784,4294967295,4278387214,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979085,4278321678,4278519056,4278913294,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},{"name":"ibeam","width":32,"height":32,"hotX":8,"hotY":9,"invertedPixels":0,"monochrome":true,"argb":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,4294112499,4294112499,0,4294112499,4294112499,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4294112499,4294112499,4294112499,0,4294112499,4294112499,4294112499,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},{"name":"sizewe","width":32,"height":32,"hotX":11,"hotY":4,"invertedPixels":0,"monochrome":false,"argb":[0,0,0,4278848013,4278387726,4278387726,0,0,0,0,0,0,0,0,0,0,0,4278387726,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278848013,4278387726,4294967295,4278190093,0,0,0,0,0,0,0,0,0,0,0,4278190093,4293980403,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,4278848013,4278387726,4294967295,4294967295,4278190093,0,0,0,0,0,0,0,0,0,0,0,4278190093,4294967295,4293717230,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,4278848013,4278387726,4294967295,4294967295,4294967295,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4294967295,4294967295,4293454058,4278387726,4278848013,0,0,0,0,0,0,0,0,0,4278387726,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295,4293454058,4278387726,0,0,0,0,0,0,0,0,0,4278848013,4278387726,4294967295,4294967295,4294967295,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4278387726,4294967295,4294967295,4293454058,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,4278848013,4278387726,4294967295,4294967295,4278190093,0,0,0,0,0,0,0,0,0,0,0,4278190093,4294967295,4293454058,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,4278848013,4278387726,4294967295,4278190093,0,0,0,0,0,0,0,0,0,0,0,4278190093,4293454058,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278848013,4278387726,4278387726,0,0,0,0,0,0,0,0,0,0,0,4278387726,4278387726,4278848013,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},{"name":"wait","width":32,"height":32,"hotX":16,"hotY":16,"invertedPixels":0,"monochrome":false,"argb":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4278979083,4278979083,4278979083,4278979083,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979339,4278979083,4279580242,4280048014,4280448185,4280448185,4280448185,4280448185,4280048014,4279580242,4278979083,4278979339,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4279446596,4280714710,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280714710,4279446596,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4279980159,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4279980159,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4280119199,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4279980159,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979339,4279784819,4280667391,4280793339,4280982260,4280981491,4280981491,4280848101,4280181404,4279980160,4279980160,4280181404,4280848101,4280981491,4280981491,4280981491,4280981491,4280981491,4279446596,4278979339,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4280664570,4280667391,4280667391,4280730109,4280982260,4280380330,4279046681,4278979083,4278979083,4278979083,4278979083,4279046681,4280380330,4280981491,4280981491,4280981491,4280981491,4280714710,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,4279786110,4280667391,4280667391,4280667391,4280667391,4280461279,4278979083,0,0,0,0,0,0,4278979083,4280380330,4280981491,4280981491,4280981491,4280981491,4279580242,0,0,0,0,0,0,0,0,0,0,0,4278979083,4280392398,4280667391,4280667391,4280667391,4280600829,4279115303,0,0,0,0,0,0,0,0,4279046681,4280848101,4280981491,4280981491,4280981491,4280048014,4278979083,0,0,0,0,0,0,0,0,0,0,4278979083,4280595950,4280667391,4280667391,4280667391,4280525786,4278979083,0,0,0,0,0,0,0,0,4278979083,4280181404,4280981491,4280981491,4280981491,4280448185,4278979083,0,0,0,0,0,0,0,0,0,0,4278979083,4280597749,4280667391,4280667391,4280667391,4280323776,4278979083,0,0,0,0,0,0,0,0,4278979083,4279980160,4280981491,4280981491,4280981491,4280448185,4278979083,0,0,0,0,0,0,0,0,0,0,4278979083,4280597749,4280667391,4280667391,4280667391,4280323776,4278979083,0,0,0,0,0,0,0,0,4278979083,4279980160,4280981491,4280981491,4280981491,4280448185,4278979083,0,0,0,0,0,0,0,0,0,0,4278979083,4280595950,4280667391,4280667391,4280667391,4280462048,4278979083,0,0,0,0,0,0,0,0,4278979083,4280181404,4280981491,4280981491,4280981491,4280448185,4278979083,0,0,0,0,0,0,0,0,0,0,4278979083,4280392398,4280667391,4280731134,4280792314,4280850923,4279046681,0,0,0,0,0,0,0,0,4279046681,4280848101,4280981491,4280981491,4280981491,4280048014,4278979083,0,0,0,0,0,0,0,0,0,0,0,4279718259,4280854519,4280981491,4280981491,4280981491,4280380330,4278979083,0,0,0,0,0,0,4278979083,4280380330,4280981491,4280981491,4280981491,4280981491,4279580242,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4280714710,4280981491,4280981491,4280981491,4280981491,4280380330,4279046681,4278979083,4278979083,4278979083,4278979083,4279046681,4280380330,4280981491,4280981491,4280981491,4280981491,4280714710,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,4278979339,4279446596,4280981491,4280981491,4280981491,4280981491,4280981491,4280848101,4280181404,4279980160,4279980160,4280181404,4280848101,4280981491,4280981491,4280981491,4280981491,4280981491,4279446596,4278979339,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4279980159,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4279980159,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4279980159,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4279980159,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4279446596,4280714710,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280981491,4280714710,4279446596,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979339,4278979083,4279580242,4280048014,4280448185,4280448185,4280448185,4280448185,4280048014,4279580242,4278979083,4278979339,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4278979083,4278979083,4278979083,4278979083,4278979083,4278979083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}]} \ No newline at end of file diff --git a/docs/independent-cursor-design-20261103.md b/docs/independent-cursor-design-20261103.md index 533c0f5..59f4b36 100644 --- a/docs/independent-cursor-design-20261103.md +++ b/docs/independent-cursor-design-20261103.md @@ -1,6 +1,6 @@ # 独立光标二次开发设计与接入条件 -状态:源码核实完成,尚未实现 Sunshine/Moonlight 的独立光标通道,不应标记为已部署。当前保留单个 Windows 远程白色光标。 +状态:已通过受控的 Windows 光标导出 + 盒子 X11 本地指针原型验证;尚未实现 Sunshine/Moonlight 的自动独立光标通道,不应标记为生产功能已部署。测试已结束,当前恢复单个 Windows 远程白色光标。实测结果见 [独立光标可行性验证](independent-cursor-feasibility-20261103.md)。 ## 已核实的实际路径 diff --git a/docs/independent-cursor-feasibility-20261103.md b/docs/independent-cursor-feasibility-20261103.md new file mode 100644 index 0000000..fb41b36 --- /dev/null +++ b/docs/independent-cursor-feasibility-20261103.md @@ -0,0 +1,53 @@ +# 独立光标原型可行性实测(2026-11-03) + +## 结论和当前现场 + +本地独立移动和 Windows 光标静态形状显示可行,值得继续开发 Sunshine + Moonlight 的正式同步协议。本轮完成了真实盒子和 VM100 的受控原型,不是仅做源码调研。但是自动形状同步、视频帧交接、断线回退尚未成为产品功能,不能默认启用,也不能称鼠标或窗口零延迟。 + +测试已结束,Windows 临时任务 VDICursorPOC 已停止并删除。正常 Moonlight PID31694、2560×1440/45FPS、RKMPP/EGL 和原二进制 SHA256 `35de7b1a4ade583823b23b5f2e012307f6d0a3848c8eb97bd6d4de9660afa00f` 保留。VDD读回 DISPLAY3、2560×1440@60。最后确认本地指针为全透明1×1,屏幕里只有正常Windows远程白色光标;没有遗留测试辅助进程。GTX965M错误码0,编码占用11%,Sunshine该正常会话创建了h264_nvenc。没有重启机器、修改GPU固件/直通、Windows鼠标主题或正式客户端配置。 + +## 原型做了什么 + +Windows已登录用户会话运行临时测试窗口,用 GetCursorInfo 读取实际光标状态;GetIconInfo/DrawIconEx 导出默认箭头、文字、左右缩放、忙碌四种真实Windows形状,均为32×32,热点分别为(0,0)、(8,9)、(11,4)、(16,16)。导出仅复制资源并释放 GetIconInfo 返回的位图,没有替换系统主题。通过黑白背景双次绘制重建alpha,检测到依赖背景反色的像素就拒绝;这四个样本未检测到此类像素,不代表全部自定义光标都支持。 + +管理工作站通过已有的认证PVE guest-agent通道读取导出文件,再经SSH传给盒子。没有新增网络监听端口,盒子没有直接使用PVE凭据。盒子辅助程序在现有Moonlight的X11窗口上创建本地指针,形状由测试脚本按已知测试区域顺序切换。**这是脚本控制的形状回放;没有将GetCursorInfo状态自动、实时同步到客户端。** Windows另存状态变化记录,供交叉核对。 + +测试临时使用Sunshine的Ctrl+Alt+Shift+N隐藏视频光标,最后成对恢复。它只是原型手段,没有会话确认/租约,不能作为正式交接协议。正常Moonlight二进制未重编或替换;本轮验证的是底层X11本地指针可用性。正式功能应进入Moonlight的SDL主线程,并适配后续Weston/Wayland,不能把这份X11辅助程序当最终架构。 + +## 实测结果 + +| 验证项 | 结果与边界 | +| --- | --- | +| 四种形状及热点 | XFixes读取本地指针,尺寸/热点均与Windows导出一致;忙碌只验证一帧,未实现动画 | +| 光标显隐 | 本地隐藏状态为全透明1×1;Windows记录也捕获到隐藏flags=0 | +| 移动独立于视频 | 仅将当前Moonlight进程短暂停住,小于0.5秒,并保证SIGCONT恢复;本地指针仍从(320,500)移动到(500,650),图像保持一致。这证明依赖关系解除,没有测得物理输入到屏幕毫秒数 | +| 单光标受控稳态 | 原始XWD截图在禁用后不再包含远程指针,XFixes另行确认本地指针存在。XWD不包含本地硬件指针,不能将原始截图无指针误报为本地显示失败;未用合成图冒充屏幕截图 | +| 点击正确性 | 最后完整一轮32次跨四区点击,Windows记录32/32区域及形状正确;绝对坐标归一化差值最大1像素,不宣称零偏差 | +| 辅助状态超时 | 0.8秒测试租约过期,辅助程序退出并通过SDL恢复其拥有的隐藏指针;测试控制器随后恢复远程视频光标。没有证明真实控制断网时服务器能自动回退 | +| 输入数据边界 | 10项测试通过,覆盖尺寸、热点、像素长度/范围、重复形状、XOR拒绝、格式、未知形状、过期/异常租约及文件大小 | + +最后完整轮次为 `cursor-poc-evidence-v3`。最初两轮已验证形状、移动和点击,但辅助程序退出后当前XFixes图像暂不可用,不能算完整通过;修正后才通过完整流程。没有把前两轮的失败隐藏成成功。 + +## 暴露的两个实际问题 + +1. **静止画面的旧光标会留在旧视频帧里。** 第一轮切换快捷键后立即截图,原位置的远程箭头仍在;之后画面更新才消失。最后一轮加入测试窗口时钟更新并等待新帧,禁用后的光标区域变为空背景,恢复后的区域重新出现Windows忙碌光标。正式实现必须用双方确认的视频帧边界切换,不能只延时几百毫秒后直接显示本地箭头。 +2. **X11指针资源有连接所有权。** 辅助程序在自己连接上复制一个隐藏指针,再关闭连接,并不足以可靠恢复SDL原先的资源。原型现在在XFixes临时隐藏保护下,使用Moonlight本地光标快捷键成对切换,让SDL重新设置它自己拥有的隐藏指针,再释放辅助资源。此清理依赖同一前台绝对鼠标会话,不能代替正式客户端内部的资源生命周期管理。代码失焦时明确报错,不声称任意退出路径都能可靠恢复。 + +## 下一阶段执行顺序 + +1. 固定现场Sunshine版本对应提交,在独立目录准备Windows可复现构建;当前未准备好该服务端C++构建环境。先验证未经修改的构建,再备份/部署测试实例,避免直接替换正常服务。 +2. 在现有已认证、加密的控制通道添加能力协商、形状/热点、显隐、状态序号与显示配置代数。Moonlight将有界状态投递SDL主线程,缓存形状,本地移动直接跟随物理输入;旧服务端保持远程模式。 +3. Sunshine提供有明确目标状态、帧边界确认和会话租约的光标交接,代替全局toggle;未捕获到可分离光标或形状不支持时回退。锁屏/UAC、远程主动warp、动画、缩放、多会话也须覆盖。 +4. 验收断网/重连/失焦、文字选择、拖窗、右键/双击及100%/125%/150%缩放,再用高速摄像分别测指针移动、点击反馈、窗口内容的P50/P95。通过后再开放可关闭的试用开关。 + +独立光标可以绕开捕获、编码、网络、解码对“指针位置显示”的等待;窗口本身和点击后的页面仍需视频返回。它不会直接解决当前盒子2K60只实渲染约46FPS的问题,视频呈现优化仍按此前对照结论推进。 + +## 文件与复核 + +- `tools/cursor-poc-host.ps1`、`tools/run-cursor-poc-host.py`:临时Windows交互任务的start/status/export/stop。不自动触发、不修改Sunshine。 +- `tools/cursor-poc-x11.py`:有界资产/状态解析、静态alpha形状、本地租约、SDL所有权归还;必须显式选择同一个前台Moonlight绝对鼠标窗口。仅用于受控实验。 +- `tools/verify-cursor-poc-box.py`:受控演示、32点击、短暂停客户端及恢复;**仅可在上述Windows测试窗口位于前台时运行,不能向用户普通桌面盲目注入点击。** 输出目录拒绝覆盖,复跑须使用新目录名。 +- `tools/test-cursor-poc.py`:Linux边界测试,不更改指针。 +- `docs/evidence/cursor-poc-20261103/`:Windows资产和状态/点击记录、XFixes形状、原始截图转换、首轮失败证据、最终成功结果、超时日志、GPU/显示/本地指针收尾查询。压缩包保留原始XWD。 + +实现依据:[Microsoft GetCursorInfo](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcursorinfo)、[GetIconInfo](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-geticoninfo)、[Desktop Duplication光标元数据](https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/desktop-dup-api)。正式协议及验收要求继续见 [双方二次开发设计](independent-cursor-design-20261103.md)。 diff --git a/tools/cursor-poc-host.ps1 b/tools/cursor-poc-host.ps1 new file mode 100644 index 0000000..535c717 --- /dev/null +++ b/tools/cursor-poc-host.ps1 @@ -0,0 +1,122 @@ +# Scoped interactive cursor probe. No theme, driver, display or Sunshine changes. +$ErrorActionPreference='Stop' +$folder='C:\ProgramData\VDI\cursor-poc-20261103' +Set-Content "$folder\pid.txt" $PID +try { +Add-Type -ReferencedAssemblies System.Windows.Forms,System.Drawing -TypeDefinition @' +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows.Forms; +public class VDICursorShape { + public string name; public int width,height,hotX,hotY,invertedPixels; + public bool monochrome; public uint[] argb; +} +public class VDICursorProbe : Form { + [StructLayout(LayoutKind.Sequential)] struct POINT { public int x,y; } + [StructLayout(LayoutKind.Sequential)] struct CI { public int size,flags; public IntPtr cursor; public POINT point; } + [StructLayout(LayoutKind.Sequential)] struct II { public bool icon; public int x,y; public IntPtr mask,color; } + [DllImport("user32.dll")] static extern bool GetCursorInfo(ref CI ci); + [DllImport("user32.dll")] static extern bool GetIconInfo(IntPtr h,out II info); + [DllImport("user32.dll")] static extern bool DrawIconEx(IntPtr dc,int x,int y,IntPtr icon,int w,int h,int step,IntPtr brush,int flags); + [DllImport("gdi32.dll")] static extern bool DeleteObject(IntPtr h); + [DllImport("user32.dll")] public static extern bool SetProcessDPIAware(); + public static readonly string[] Names={"arrow","ibeam","sizewe","wait"}; + static readonly Cursor[] Shapes={Cursors.Default,Cursors.IBeam,Cursors.SizeWE,Cursors.WaitCursor}; + static Bitmap Draw(IntPtr handle,int w,int h,Color background) { + Bitmap result=new Bitmap(w,h,System.Drawing.Imaging.PixelFormat.Format32bppArgb); + using(Graphics g=Graphics.FromImage(result)) { + g.Clear(background); IntPtr dc=g.GetHdc(); + try { if(!DrawIconEx(dc,0,0,handle,w,h,0,IntPtr.Zero,3)) throw new Exception("DrawIconEx failed"); } + finally { g.ReleaseHdc(dc); } + } + return result; + } + public static VDICursorShape Export(string name,IntPtr handle) { + II info; if(!GetIconInfo(handle,out info)) throw new Exception("GetIconInfo failed"); + try { + int w,h; + using(Bitmap mask=Bitmap.FromHbitmap(info.mask)) { w=mask.Width; h=mask.Height/(info.color==IntPtr.Zero?2:1); } + if(w<1 || h<1 || w>128 || h>128) throw new Exception("Unsupported cursor dimensions"); + VDICursorShape s=new VDICursorShape {name=name,width=w,height=h,hotX=info.x,hotY=info.y,monochrome=info.color==IntPtr.Zero,argb=new uint[w*h]}; + using(Bitmap black=Draw(handle,w,h,Color.Black)) + using(Bitmap white=Draw(handle,w,h,Color.White)) { + for(int y=0;y2 || Math.Abs(dr-db)>2) { ++s.invertedPixels; continue; } + int a=255-dr; + if(a==0) continue; + uint r=(uint)Math.Min(255,(b.R*255+a/2)/a),g=(uint)Math.Min(255,(b.G*255+a/2)/a),bl=(uint)Math.Min(255,(b.B*255+a/2)/a); + s.argb[y*w+x]=((uint)a<<24)|(r<<16)|(g<<8)|bl; + } + } + return s; + } finally { if(info.mask!=IntPtr.Zero) DeleteObject(info.mask); if(info.color!=IntPtr.Zero) DeleteObject(info.color); } + } + public static VDICursorShape[] ExportAll() { + List result=new List(); + for(int i=0;i8) { Close(); return; } + CI ci=new CI(); ci.size=Marshal.SizeOf(typeof(CI)); + if(!GetCursorInfo(ref ci)) return; + string observed="unknown"; + for(int i=0;iHeight*3/4; + if(nextHidden!=hidden) { if(nextHidden) Cursor.Hide(); else Cursor.Show(); hidden=nextHidden; } + int index=Math.Min(3,e.X*4/Math.Max(1,Width)); shape=Names[index]; Cursor=Shapes[index]; + } + protected override void OnMouseDown(MouseEventArgs e) { + base.OnMouseDown(e); ++clicks; + File.AppendAllText(Path.Combine(folder,"clicks.csv"),DateTime.UtcNow.ToString("o")+","+e.X+","+e.Y+","+shape+"\n"); Invalidate(); + } + protected override void OnPaint(PaintEventArgs e) { + e.Graphics.Clear(Color.FromArgb(24,32,44)); + using(Font f=new Font("Consolas",23)) for(int i=0;i<4;i++) { + e.Graphics.DrawRectangle(Pens.SlateGray,i*Width/4,150,Width/4-2,Height*3/4-150); + e.Graphics.DrawString(Names[i],f,Brushes.White,i*Width/4+40,200); + } + using(Font f=new Font("Consolas",24)) { + e.Graphics.DrawString("Independent cursor probe | clicks: "+clicks+" | "+DateTime.UtcNow.ToString("HH:mm:ss.fff"),f,Brushes.White,40,40); + e.Graphics.DrawString("BOTTOM AREA: cursor hidden",f,Brushes.Gold,40,Height*3/4+60); + } + } + protected override void OnFormClosed(FormClosedEventArgs e) { + timer.Stop(); timer.Dispose(); if(hidden) { Cursor.Show(); hidden=false; } base.OnFormClosed(e); + } +} +'@ +[VDICursorProbe]::SetProcessDPIAware() | Out-Null +@{version=1; shapes=[VDICursorProbe]::ExportAll()} | ConvertTo-Json -Depth 6 -Compress | Set-Content -Encoding utf8 "$folder\shapes.json" +[System.Windows.Forms.Application]::Run((New-Object VDICursorProbe($folder))) +} catch { $_ | Out-String | Set-Content "$folder\error.txt"; throw } diff --git a/tools/cursor-poc-x11.py b/tools/cursor-poc-x11.py new file mode 100644 index 0000000..2e2a9d6 --- /dev/null +++ b/tools/cursor-poc-x11.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python3 +"""Temporary X11 local-cursor proof, NOT a production Moonlight cursor protocol. + +Requires an already authenticated Moonlight session. Never changes Sunshine. +The caller owns remote-video-cursor handoff and must restore it in finally. +Only supports exported alpha cursors without destination-dependent XOR pixels. +""" +import argparse +import ctypes as C +import fcntl +import json +import math +import os +from pathlib import Path +import signal +import subprocess +import time + + +class XcursorImage(C.Structure): + _fields_ = [("version", C.c_uint32), ("size", C.c_uint32), + ("width", C.c_uint32), ("height", C.c_uint32), + ("xhot", C.c_uint32), ("yhot", C.c_uint32), + ("delay", C.c_uint32), ("pixels", C.POINTER(C.c_uint32))] + + +class XfixesImage(C.Structure): + _fields_ = [("x", C.c_short), ("y", C.c_short), + ("width", C.c_ushort), ("height", C.c_ushort), + ("xhot", C.c_ushort), ("yhot", C.c_ushort), + ("serial", C.c_ulong), ("pixels", C.POINTER(C.c_ulong)), + ("atom", C.c_ulong), ("name", C.c_char_p)] + + +def validate_assets(data): + if not isinstance(data, dict) or type(data.get("version")) is not int or data.get("version") != 1 or not isinstance(data.get("shapes"), list) or not 1 <= len(data["shapes"]) <= 32: + raise ValueError("Invalid asset version/count") + result = {} + for s in data["shapes"]: + if not isinstance(s, dict): + raise ValueError("Invalid shape") + name = s.get("name") + if not isinstance(name, str) or not name.isascii() or not name.isalnum() or len(name) > 32 or name in result: + raise ValueError("Invalid/duplicate shape name") + for key in ("width", "height", "hotX", "hotY", "invertedPixels"): + if type(s.get(key)) is not int: + raise ValueError("Noninteger cursor metadata") + w, h = s["width"], s["height"] + if not 1 <= w <= 128 or not 1 <= h <= 128 or not 0 <= s["hotX"] < w or not 0 <= s["hotY"] < h: + raise ValueError("Invalid size/hotspot") + if s["invertedPixels"] != 0: + raise ValueError("Destination-dependent XOR cursor requires fallback") + pixels = s.get("argb") + if not isinstance(pixels, list) or len(pixels) != w*h or any(type(p) is not int or not 0 <= p <= 0xffffffff for p in pixels): + raise ValueError("Invalid ARGB pixels") + result[name] = s + return result + + +def validate_state(state, shapes): + if not isinstance(state, dict) or type(state.get("version")) is not int or state.get("version") != 1 or type(state.get("visible")) is not bool or not isinstance(state.get("shape"), str) or state.get("shape") not in shapes: + raise ValueError("Invalid state/unknown shape") + # A bounded wall-clock lease prevents stale local pointers after the bridge dies. + expires = state.get("expires") + if type(expires) not in (int, float) or not math.isfinite(expires) or not time.time() < expires <= time.time()+5: + raise ValueError("Expired/invalid state lease") + return state["shape"] if state["visible"] else "__hidden" + + +def read_json(path, limit): + with open(path, "rb") as f: + raw = f.read(limit+1) + if len(raw) > limit: + raise ValueError("Oversize JSON") + return json.loads(raw) + + +class LocalCursor: + def __init__(self, window): + self.x = C.CDLL("libX11.so.6") + self.c = C.CDLL("libXcursor.so.1") + self.f = C.CDLL("libXfixes.so.3") + self.x.XOpenDisplay.argtypes = [C.c_char_p]; self.x.XOpenDisplay.restype = C.c_void_p + self.x.XDefineCursor.argtypes = [C.c_void_p, C.c_ulong, C.c_ulong] + self.x.XSync.argtypes = [C.c_void_p, C.c_int] + self.x.XFree.argtypes = [C.c_void_p] + self.x.XFreeCursor.argtypes = [C.c_void_p, C.c_ulong] + self.x.XCloseDisplay.argtypes = [C.c_void_p] + self.f.XFixesGetCursorImage.argtypes = [C.c_void_p]; self.f.XFixesGetCursorImage.restype = C.POINTER(XfixesImage) + self.f.XFixesHideCursor.argtypes = [C.c_void_p, C.c_ulong] + self.f.XFixesShowCursor.argtypes = [C.c_void_p, C.c_ulong] + self.c.XcursorImageCreate.argtypes = [C.c_int, C.c_int]; self.c.XcursorImageCreate.restype = C.POINTER(XcursorImage) + self.c.XcursorImageDestroy.argtypes = [C.POINTER(XcursorImage)] + self.c.XcursorImageLoadCursor.argtypes = [C.c_void_p, C.POINTER(XcursorImage)]; self.c.XcursorImageLoadCursor.restype = C.c_ulong + self.d = self.x.XOpenDisplay(None) + if not self.d: + raise RuntimeError("Cannot open X display") + self.window = window + self.cursors = {} + self.original = self.create(self.snapshot(), premultiplied=True) + + def snapshot(self): + image = self.f.XFixesGetCursorImage(self.d) + if not image: + raise RuntimeError("No XFixes cursor image") + try: + i = image.contents + if not 1 <= i.width <= 128 or not 1 <= i.height <= 128: + raise RuntimeError("Unsupported X cursor dimensions") + return dict(width=i.width, height=i.height, hotX=i.xhot, hotY=i.yhot, + x=i.x, y=i.y, argb=[int(i.pixels[p]) & 0xffffffff for p in range(i.width*i.height)]) + finally: + self.x.XFree(image) + + def create(self, s, premultiplied=False): + image = self.c.XcursorImageCreate(s["width"], s["height"]) + if not image: + raise RuntimeError("Xcursor allocation failed") + try: + image.contents.xhot, image.contents.yhot = s["hotX"], s["hotY"] + for j, p in enumerate(s["argb"]): + if premultiplied: + image.contents.pixels[j] = p + continue + # XRender/Xcursor uses premultiplied alpha; Windows export is straight ARGB. + a = p >> 24 + r, g, b = ((p >> shift) & 255 for shift in (16, 8, 0)) + image.contents.pixels[j] = (a << 24) | ((r*a+127)//255 << 16) | ((g*a+127)//255 << 8) | ((b*a+127)//255) + cursor = self.c.XcursorImageLoadCursor(self.d, image) + if not cursor: + raise RuntimeError("Xcursor creation failed") + return cursor + finally: + self.c.XcursorImageDestroy(image) + + def apply(self, cursor): + self.x.XDefineCursor(self.d, self.window, cursor) + self.x.XSync(self.d, 0) + + def close(self, sdl_pid=None): + self.apply(self.original) + try: + if sdl_pid is not None: + # X11 cursor resources owned by this connection disappear when + # it closes. Have SDL restore its own hidden cursor first. The + # temporary XFixes hide prevents the first toggle flashing the + # default local arrow. This POC requires the same focused stream. + active = subprocess.check_output(["xdotool", "getwindowfocus", "getwindowpid"],text=True).strip() + if active != str(sdl_pid): + raise RuntimeError("Cannot return cursor ownership: stream lost focus; reconnect normal client") + self.f.XFixesHideCursor(self.d,self.window); self.x.XSync(self.d,0) + try: + for unused in range(2): + subprocess.run(["xdotool","key","ctrl+alt+shift+c"],check=True) + time.sleep(.08) + finally: + self.f.XFixesShowCursor(self.d,self.window); self.x.XSync(self.d,0) + finally: + for cursor in [self.original, *self.cursors.values()]: + self.x.XFreeCursor(self.d, cursor) + self.x.XCloseDisplay(self.d) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--window", type=int, required=True) + parser.add_argument("--pid", type=int, required=True) + parser.add_argument("--assets", type=Path, required=True) + parser.add_argument("--state", type=Path, required=True) + parser.add_argument("--seconds", type=int, default=120) + parser.add_argument("--snapshot", type=Path) + args = parser.parse_args() + if not 1 <= args.seconds <= 180 or args.window <= 0 or args.pid <= 1: + parser.error("Invalid window/pid/duration") + command = Path(f"/proc/{args.pid}/cmdline").read_bytes().replace(b"\0", b" ") + if b"/moonlight " not in command or b" stream " not in command or b" --absolute-mouse " not in command: + parser.error("Target must be the absolute-mode Moonlight stream") + actual_pid = subprocess.check_output(["xdotool", "getwindowpid", str(args.window)], text=True).strip() + focused_window = subprocess.check_output(["xdotool", "getwindowfocus"], text=True).strip() + if actual_pid != str(args.pid) or focused_window != str(args.window): + parser.error("Target must be the same focused Moonlight window") + # Keep the experiment exclusive, with owner-only local files. + lock = open(args.state.with_suffix(".lock"), "w") + os.chmod(lock.name, 0o600) + fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB) + shapes = validate_assets(read_json(args.assets, 4*1024*1024)) + cursor = LocalCursor(args.window) + if any(cursor.snapshot()["argb"]): + cursor.x.XFreeCursor(cursor.d, cursor.original) + cursor.x.XCloseDisplay(cursor.d) + parser.error("POC requires the original local cursor to be hidden") + stop = False + def stopped(*unused): + nonlocal stop + stop = True + signal.signal(signal.SIGTERM, stopped); signal.signal(signal.SIGINT, stopped) + try: + cursor.cursors = {name: cursor.create(s) for name, s in shapes.items()} + cursor.cursors["__hidden"] = cursor.create(dict(width=1, height=1, hotX=0, hotY=0, argb=[0])) + current = None + end = time.monotonic()+args.seconds + while not stop and time.monotonic() < end: + if not Path(f"/proc/{args.pid}").exists(): + break + try: + desired = validate_state(read_json(args.state, 1024), shapes) + except (ValueError, OSError) as e: + print(json.dumps(dict(event="lease-ended", reason=str(e))), flush=True) + break + if desired != current: + cursor.apply(cursor.cursors[desired]); current = desired + s = cursor.snapshot() + if args.snapshot: + args.snapshot.write_text(json.dumps(s)) + print(json.dumps(dict(event="applied", shape=current, x=s["x"], y=s["y"], width=s["width"], height=s["height"], hotX=s["hotX"], hotY=s["hotY"])), flush=True) + time.sleep(.01) + finally: + cursor.close(sdl_pid=args.pid) + print('{"event":"sdl-hidden-cursor-restored"}', flush=True) + + +if __name__ == "__main__": + main() diff --git a/tools/run-cursor-poc-host.py b/tools/run-cursor-poc-host.py new file mode 100644 index 0000000..4658995 --- /dev/null +++ b/tools/run-cursor-poc-host.py @@ -0,0 +1,73 @@ +"""Scoped VM100 interactive cursor exporter. No new network listener or system cursor theme.""" +import argparse +import base64 +import json +from pathlib import Path +import runpy +import sys + +sys.stdout.reconfigure(encoding="utf-8", errors="replace") +parser = argparse.ArgumentParser(description=__doc__) +parser.add_argument("action", choices=["start", "status", "export", "stop"]) +parser.add_argument("--output", type=Path) +args = parser.parse_args() +root = Path(__file__).resolve().parent +t = runpy.run_path(str(root / "pve_term_exec.py")) +v = runpy.run_path(str(root / "pve_vm.py")) +ticket, csrf = t["login"]() +if v["api"]("/api2/json/nodes/starhe/qemu/100/status/current", ticket=ticket).get("status") != "running": + sys.exit("VM100 is not running") +command = r"$ErrorActionPreference='Stop'; $folder='C:\ProgramData\VDI\cursor-poc-20261103'; $task='VDICursorPOC'; " +if args.action == "start": + payload = base64.b64encode((root / "cursor-poc-host.ps1").read_bytes()).decode() + command += r""" +if(Get-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue) { throw 'Probe already exists' } +$user=(Get-CimInstance Win32_ComputerSystem).UserName +if(-not $user) { throw 'No interactive user' } +New-Item -ItemType Directory -Force $folder | Out-Null +$acl=Get-Acl $folder +$acl.SetAccessRule((New-Object Security.AccessControl.FileSystemAccessRule($user,'Modify','ContainerInherit,ObjectInherit','None','Allow'))) +Set-Acl $folder $acl +Remove-Item "$folder\error.txt","$folder\state.json","$folder\shapes.json" -ErrorAction SilentlyContinue +[IO.File]::WriteAllBytes("$folder\probe.ps1",[Convert]::FromBase64String('__PAYLOAD__')) +$a=New-ScheduledTaskAction -Execute powershell.exe -Argument "-NoProfile -STA -ExecutionPolicy Bypass -WindowStyle Hidden -File $folder\probe.ps1" +$p=New-ScheduledTaskPrincipal -UserId $user -LogonType Interactive -RunLevel Limited +$s=New-ScheduledTaskSettingsSet -ExecutionTimeLimit (New-TimeSpan -Minutes 9) +Register-ScheduledTask -TaskName $task -Action $a -Principal $p -Settings $s | Out-Null +Start-ScheduledTask -TaskName $task +Start-Sleep -Seconds 3 +if(Test-Path "$folder\error.txt") { throw (Get-Content "$folder\error.txt" -Raw) } +if(-not(Test-Path "$folder\shapes.json")) { throw 'No fresh cursor export' } +'Cursor probe started' +""".replace("__PAYLOAD__", payload) +elif args.action == "export": + command += 'Get-Content "$folder\\shapes.json" -Raw' +elif args.action == "status": + command += r""" +Get-Content "$folder\state.json" -Raw +Get-Content "$folder\clicks.csv" +Get-Content "$folder\states.csv" +Get-Content "$folder\error.txt" -ErrorAction SilentlyContinue +""" +else: + command += r""" +Stop-ScheduledTask -TaskName $task -ErrorAction SilentlyContinue +Unregister-ScheduledTask -TaskName $task -Confirm:$false -ErrorAction SilentlyContinue +if(Test-Path "$folder\pid.txt") { + $probePid=[int](Get-Content "$folder\pid.txt") + $process=Get-CimInstance Win32_Process -Filter "ProcessId=$probePid" + if($process.CommandLine -like '*cursor-poc-20261103*') { Stop-Process -Id $probePid -ErrorAction SilentlyContinue } +} +'Cursor probe stopped' +""" +out, error = v["agent"](ticket, csrf, ["powershell.exe", "-NoProfile", "-Command", command]) +if error or not out or out == "TIMEOUT": + sys.exit(error or out or "Empty guest-agent result") +if args.action == "export": + data = json.loads(out.lstrip("\ufeff")) + if args.output: + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(data, separators=(",", ":")), encoding="utf-8") + print(json.dumps([{k: s[k] for k in ("name", "width", "height", "hotX", "hotY", "monochrome", "invertedPixels")} for s in data["shapes"]])) +else: + print(out) diff --git a/tools/test-cursor-poc.py b/tools/test-cursor-poc.py new file mode 100644 index 0000000..833253c --- /dev/null +++ b/tools/test-cursor-poc.py @@ -0,0 +1,50 @@ +"""Cursor asset boundary/fallback tests; run on Linux (same fcntl environment as box).""" +import copy +import importlib.util +from pathlib import Path +import tempfile +import time +import unittest + +spec=importlib.util.spec_from_file_location("cursor_poc",Path(__file__).with_name("cursor-poc-x11.py")) +m=importlib.util.module_from_spec(spec); spec.loader.exec_module(m) + +class Boundaries(unittest.TestCase): + def setUp(self): + self.asset=dict(version=1,shapes=[dict(name="arrow",width=1,height=1,hotX=0,hotY=0,invertedPixels=0,argb=[0xffffffff])]) + def bad(self,key,value): + data=copy.deepcopy(self.asset); data["shapes"][0][key]=value + with self.assertRaises(ValueError): m.validate_assets(data) + def test_valid(self): self.assertIn("arrow",m.validate_assets(self.asset)) + def test_dimensions(self): + for v in (-1,0,129,True,"32"): self.bad("width",v) + def test_hotspot(self): + for v in (-1,1): self.bad("hotX",v) + def test_xor_requires_fallback(self): self.bad("invertedPixels",1) + def test_pixels(self): + for v in ([],[True],[-1],[0x100000000],[0,0]): self.bad("argb",v) + def test_duplicate_shapes(self): + self.asset["shapes"]*=2 + with self.assertRaises(ValueError): m.validate_assets(self.asset) + def test_envelopes(self): + for v in (None,[],{},dict(version=True,shapes=self.asset["shapes"])): + with self.assertRaises(ValueError): m.validate_assets(v) + def test_lease(self): + shapes=m.validate_assets(self.asset) + for expires in (time.time()-1,time.time()+60,float("nan"),float("inf"),True): + with self.assertRaises(ValueError): m.validate_state(dict(version=1,visible=True,shape="arrow",expires=expires),shapes) + def test_state(self): + shapes=m.validate_assets(self.asset) + state=dict(version=1,visible=True,shape="arrow",expires=time.time()+1) + self.assertEqual(m.validate_state(state,shapes),"arrow") + state["visible"]=False + self.assertEqual(m.validate_state(state,shapes),"__hidden") + for key,value in (("visible",1),("shape","missing"),("shape",[]),("version",True)): + bad=dict(state); bad[key]=value + with self.assertRaises(ValueError): m.validate_state(bad,shapes) + def test_oversize_file(self): + with tempfile.TemporaryDirectory() as d: + p=Path(d)/"data.json"; p.write_text(" "*1025) + with self.assertRaises(ValueError): m.read_json(p,1024) + +if __name__=="__main__": unittest.main() diff --git a/tools/verify-cursor-poc-box.py b/tools/verify-cursor-poc-box.py new file mode 100644 index 0000000..73fe9cb --- /dev/null +++ b/tools/verify-cursor-poc-box.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +"""Controlled existing-stream POC; always restores the remote-video cursor toggle. + +Only run with cursor-poc-host.ps1's disposable foreground window on Windows. +Shape selections here are scripted replay, NOT automatic host synchronization. +""" +import importlib.util +import json +import os +from pathlib import Path +import signal +import subprocess as S +import time + +ROOT = Path(__file__).resolve().parent +os.environ.update(DISPLAY=":0", XAUTHORITY="/home/armbian/.Xauthority") +spec = importlib.util.spec_from_file_location("cursor_poc", ROOT / "cursor-poc-x11.py") +m = importlib.util.module_from_spec(spec); spec.loader.exec_module(m) +OUT = ROOT / "cursor-poc-evidence-v3" +OUT.mkdir(exist_ok=False) # Never overwrite earlier evidence. + +def xd(*args): + return S.check_output(["xdotool", *map(str,args)], text=True).strip() + +pid = int(xd("getwindowfocus", "getwindowpid")) +window = int(xd("getwindowfocus")) +cmd = Path(f"/proc/{pid}/cmdline").read_bytes().replace(b"\0", b" ") +if b"/moonlight " not in cmd or b" stream 192.168.1.70 Desktop " not in cmd or b" --absolute-mouse " not in cmd: + raise RuntimeError("Unexpected foreground process") +assets = m.validate_assets(m.read_json(ROOT / "windows-shapes.json", 4*1024*1024)) +cursor = m.LocalCursor(window) +if any(cursor.snapshot()["argb"]): + cursor.close(); raise RuntimeError("Original local cursor is not hidden") +hidden_remote = False +paused = False +records = [] +def interrupted(signum, frame): + raise SystemExit(128+signum) +signal.signal(signal.SIGTERM, interrupted) +signal.signal(signal.SIGINT, interrupted) + +def focus(): + if int(xd("getwindowfocus", "getwindowpid")) != pid: + raise RuntimeError("Moonlight lost foreground; stop the POC") + +def capture(name): + with (OUT / (name+".xwd")).open("wb") as f: + S.run(["xwd", "-root", "-silent"], stdout=f, check=True) + +try: + cursor.cursors = {k: cursor.create(v) for k,v in assets.items()} + cursor.cursors["__hidden"] = cursor.create(dict(width=1,height=1,hotX=0,hotY=0,argb=[0])) + focus(); xd("mousemove", 320, 500); time.sleep(.8) + capture("01-remote-cursor") + focus(); xd("key", "ctrl+alt+shift+n"); hidden_remote=True + xd("mousemove",321,500); time.sleep(1.0) + capture("02-video-cursor-disabled") + for name,x in (("arrow",320),("ibeam",960),("sizewe",1600),("wait",2240),("__hidden",320)): + focus(); y=1250 if name=="__hidden" else 500 + xd("mousemove", x,y); time.sleep(.25) + cursor.apply(cursor.cursors[name]); time.sleep(.05) + snap=cursor.snapshot() + (OUT/(name+".json")).write_text(json.dumps(snap)) + if name=="__hidden": + assert not any(snap["argb"]), "Hidden cursor still has visible pixels" + else: + a=assets[name] + assert (snap["width"],snap["height"],snap["hotX"],snap["hotY"]) == (a["width"],a["height"],a["hotX"],a["hotY"]) + assert any(snap["argb"]), "Visible cursor has no pixels" + assert (snap["x"],snap["y"])==(x,y) + records.append(dict(shape=name,x=x,y=y,visible=any(snap["argb"]))) + time.sleep(.3) # Allow the host probe to observe the real shape/visibility. + focus(); xd("mousemove",320,500); cursor.apply(cursor.cursors["arrow"]); time.sleep(.4) + # Freeze only this client for < 0.5s; X11 cursor must move while its video/input + # event processing is stopped. SIGCONT is guaranteed before cursor restoration. + os.kill(pid,signal.SIGSTOP); paused=True + try: + first=cursor.snapshot() + xd("mousemove",500,650); time.sleep(.12) + second=cursor.snapshot() + assert (second["x"],second["y"])==(500,650) + assert first["argb"]==second["argb"] + records.append(dict(test="client-paused-local-motion",before=[first["x"],first["y"]],after=[second["x"],second["y"]],passed=True)) + finally: + os.kill(pid,signal.SIGCONT); paused=False + time.sleep(.5) + # Click only within the disposable Windows form. Scripted shape replay is + # deliberately distinct from the not-yet-implemented live cursor protocol. + for i in range(32): + focus(); n=i%4; x=320+640*n; y=600+(i//4)*20 + cursor.apply(cursor.cursors[("arrow","ibeam","sizewe","wait")[n]]) + xd("mousemove",x,y); time.sleep(.06); xd("click",1); time.sleep(.06) + capture("03-local-mode-video-only") + # Verify the actual helper's lease failure path while video cursor is hidden. + cursor.apply(cursor.original) + lease=OUT/"lease.json" + lease.write_text(json.dumps(dict(version=1,shape="arrow",visible=True,expires=time.time()+.8))) + result=S.run(["python3",str(ROOT/"cursor-poc-x11.py"),"--window",str(window),"--pid",str(pid), + "--assets",str(ROOT/"windows-shapes.json"),"--state",str(lease),"--seconds","3"], + capture_output=True,text=True,timeout=5) + (OUT/"lease-expiry.log").write_text(result.stdout+result.stderr) + assert result.returncode==0 and "lease-ended" in result.stdout and "sdl-hidden-cursor-restored" in result.stdout + # Xorg can briefly have no current cursor image after another connection's + # final cursor resource is released. Trigger pointer recomputation before + # checking the *post-exit* image; do not mistake this for an alpha image. + xd("mousemove",2240,741); time.sleep(.1) + assert not any(cursor.snapshot()["argb"]) + records.append(dict(test="helper-lease-expiry",passed=True)) +finally: + if paused: os.kill(pid,signal.SIGCONT) + try: + cursor.close(sdl_pid=pid) + finally: + # Remote restoration must still run when local cleanup raises an error. + if hidden_remote: + xd("windowactivate","--sync",window); focus() + xd("key","ctrl+alt+shift+n"); time.sleep(.8) + capture("04-remote-cursor-restored") + (OUT/"results.json").write_text(json.dumps(records,indent=2)) + print(json.dumps(dict(restored_remote_cursor=hidden_remote,records=records)),flush=True)