schcom: prove two clients and stacking order
The compositor already walked a surface table, but nothing had ever run
two clients at once, so "it composites" rested on a single rectangle.
schcom-test now starts two overlapping clients and checks the overlap
region from the host: the later surface has to win there. A compositor
that cannot order two surfaces cannot host a window manager, and that is
the property SchWM will be built on.
Two bugs in the test itself, both of which would have read as compositor
faults:
- it waited for the first "committed" line and screenshotted then, so
the second client had not drawn yet. It waits for both now.
- one probe point sat at 400,300 -- dead centre of an 800x600 screen,
which is exactly where the pointer is drawn. Moved clear of it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
bbb61c7405
commit
181c420f21
2 changed files with 31 additions and 7 deletions
|
|
@ -16,7 +16,9 @@ and Schcom exposes a protocol for it rather than implementing policy itself.
|
||||||
commits; the result is composited and presented. Verified end to end by
|
commits; the result is composited and presented. Verified end to end by
|
||||||
`make schcom-test`, which boots SchOS, runs the compositor and a client, then
|
`make schcom-test`, which boots SchOS, runs the compositor and a client, then
|
||||||
screendumps the framebuffer and asserts the pixels **from the host** — the
|
screendumps the framebuffer and asserts the pixels **from the host** — the
|
||||||
compositor's own report that it composited something proves nothing.
|
compositor's own report that it composited something proves nothing. It runs
|
||||||
|
two overlapping clients and checks that the newer one wins in the overlap: a
|
||||||
|
compositor that cannot order two surfaces cannot host a window manager.
|
||||||
|
|
||||||
What exists:
|
What exists:
|
||||||
|
|
||||||
|
|
@ -26,6 +28,7 @@ What exists:
|
||||||
- surface / attach / **commit** semantics: nothing is shown mid-draw
|
- surface / attach / **commit** semantics: nothing is shown mid-draw
|
||||||
- input from `/dev/input/eventN`, routed to the topmost surface
|
- input from `/dev/input/eventN`, routed to the topmost surface
|
||||||
- clients that die are cleaned up, including their shm segments
|
- clients that die are cleaned up, including their shm segments
|
||||||
|
- **multiple clients**, composited bottom-to-top in creation order
|
||||||
|
|
||||||
What does not exist yet: damage tracking beyond "repaint everything", multiple
|
What does not exist yet: damage tracking beyond "repaint everything", multiple
|
||||||
outputs, subsurfaces, and any focus model beyond "topmost". Those are additions
|
outputs, subsurfaces, and any focus model beyond "topmost". Those are additions
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,9 @@ EOF
|
||||||
|
|
||||||
(
|
(
|
||||||
sleep 26
|
sleep 26
|
||||||
printf 'schcom --frames 8 &\n'; sleep 6
|
printf 'schcom --frames 24 &\n'; sleep 6
|
||||||
printf 'schcom-demo --colour 0x00C04020 --at 100 80 --size 240 160 --wait 25\n'; sleep 14
|
printf 'schcom-demo --colour 0x00C04020 --at 100 80 --size 240 160 --wait 40 &\n'; sleep 10
|
||||||
|
printf 'schcom-demo --colour 0x002060C0 --at 260 180 --size 240 160 --wait 30 &\n'; sleep 12
|
||||||
printf '\n'
|
printf '\n'
|
||||||
sleep 40
|
sleep 40
|
||||||
) | timeout -k 5 120 qemu-system-x86_64 \
|
) | timeout -k 5 120 qemu-system-x86_64 \
|
||||||
|
|
@ -38,9 +39,11 @@ EOF
|
||||||
>/dev/null 2>&1 &
|
>/dev/null 2>&1 &
|
||||||
QPID=$!
|
QPID=$!
|
||||||
|
|
||||||
# Wait until the client says it committed, then photograph.
|
# Wait until *both* clients have committed, then photograph. Breaking on the
|
||||||
for i in $(seq 1 60); do
|
# first one screenshots a desktop the second client has not reached yet, which
|
||||||
grep -aq 'committed' "$LOG" 2>/dev/null && break
|
# looks exactly like a compositor that cannot handle two clients.
|
||||||
|
for i in $(seq 1 90); do
|
||||||
|
[ "$(grep -ac 'committed' "$LOG" 2>/dev/null)" -ge 2 ] && break
|
||||||
sleep 1
|
sleep 1
|
||||||
done
|
done
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
@ -106,12 +109,30 @@ if near(desktop, (0x20, 0x30, 0x40)):
|
||||||
else:
|
else:
|
||||||
print(f" FAIL: 20,20 is {desktop}, expected (32, 48, 64)"); fails += 1
|
print(f" FAIL: 20,20 is {desktop}, expected (32, 48, 64)"); fails += 1
|
||||||
|
|
||||||
border = at(100, 80) # top-left of the surface: white border
|
border = at(100, 80) # top-left of the first surface
|
||||||
if near(border, (0xFF, 0xFF, 0xFF)):
|
if near(border, (0xFF, 0xFF, 0xFF)):
|
||||||
print(f" [ok] border pixel at 100,80 is {border} -- surface landed exactly")
|
print(f" [ok] border pixel at 100,80 is {border} -- surface landed exactly")
|
||||||
else:
|
else:
|
||||||
print(f" FAIL: 100,80 is {border}, expected white border"); fails += 1
|
print(f" FAIL: 100,80 is {border}, expected white border"); fails += 1
|
||||||
|
|
||||||
|
# Second client, created later, so it is above the first where they overlap.
|
||||||
|
second = at(460, 320) # inside surface 2, clear of the pointer
|
||||||
|
if near(second, (0x20, 0x60, 0xC0)):
|
||||||
|
print(f" [ok] second surface at 460,320 is {second} -- two clients composited")
|
||||||
|
else:
|
||||||
|
print(f" FAIL: 460,320 is {second}, expected (32, 96, 192)"); fails += 1
|
||||||
|
|
||||||
|
# 260,180..340,240 is where the two overlap. The later surface must win: if
|
||||||
|
# stacking were ignored the first client's colour would show through here, and
|
||||||
|
# a compositor that cannot order two windows cannot host a window manager.
|
||||||
|
overlap = at(300, 220)
|
||||||
|
if near(overlap, (0x20, 0x60, 0xC0)):
|
||||||
|
print(f" [ok] overlap at 300,220 is {overlap} -- newer surface on top")
|
||||||
|
elif near(overlap, (0xC0, 0x40, 0x20)):
|
||||||
|
print(f" FAIL: overlap shows the older surface -- stacking order ignored"); fails += 1
|
||||||
|
else:
|
||||||
|
print(f" FAIL: overlap at 300,220 is {overlap}, expected the newer surface"); fails += 1
|
||||||
|
|
||||||
print("schcom end-to-end: PASSED" if not fails else f"schcom end-to-end: {fails} FAILED")
|
print("schcom end-to-end: PASSED" if not fails else f"schcom end-to-end: {fails} FAILED")
|
||||||
sys.exit(1 if fails else 0)
|
sys.exit(1 if fails else 0)
|
||||||
EOF
|
EOF
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue