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:
Nexoniarz 2026-08-10 04:19:09 +02:00
commit 181c420f21
2 changed files with 31 additions and 7 deletions

View file

@ -25,8 +25,9 @@ EOF
(
sleep 26
printf 'schcom --frames 8 &\n'; sleep 6
printf 'schcom-demo --colour 0x00C04020 --at 100 80 --size 240 160 --wait 25\n'; sleep 14
printf 'schcom --frames 24 &\n'; sleep 6
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'
sleep 40
) | timeout -k 5 120 qemu-system-x86_64 \
@ -38,9 +39,11 @@ EOF
>/dev/null 2>&1 &
QPID=$!
# Wait until the client says it committed, then photograph.
for i in $(seq 1 60); do
grep -aq 'committed' "$LOG" 2>/dev/null && break
# Wait until *both* clients have committed, then photograph. Breaking on the
# first one screenshots a desktop the second client has not reached yet, which
# 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
done
sleep 2
@ -106,12 +109,30 @@ if near(desktop, (0x20, 0x30, 0x40)):
else:
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)):
print(f" [ok] border pixel at 100,80 is {border} -- surface landed exactly")
else:
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")
sys.exit(1 if fails else 0)
EOF