Commit7e384acaRecorded29 Oct 2026Repositorysigil-wm
Add regressions for hidden plan readiness and output relocation
Changed
Makefile | 3 +++
scripts/test-plan-presentation | 10 ++++++++++
test/plan-presentation.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 100 insertions(+)Diff
Makefilemodified
@@ -247,3 +247,6 @@ build/security-context-v1-client-protocol.c:
247
248
build/security-context-client: test/security-context-client.c build/security-context-v1-client-protocol.h build/security-context-v1-client-protocol.c build/ext-foreign-toplevel-list-v1-client-protocol.h build/ext-foreign-toplevel-list-v1-client-protocol.c 249
$(CC) $(CFLAGS) -Ibuild $(shell pkg-config --cflags wayland-client) $< build/security-context-v1-client-protocol.c build/ext-foreign-toplevel-list-v1-client-protocol.c $(shell pkg-config --libs wayland-client) -Wl,-rpath,$(shell pkg-config --variable=libdir wayland-client) -o $@+250
+251
build/plan-presentation-test: test/plan-presentation.c src/c/host.c+252
$(CC) $(CFLAGS) $(CPPFLAGS) $< $(LDFLAGS) $(LDLIBS) -o $@scripts/test-plan-presentationadded
@@ -0,0 +1,10 @@
+1
#!/usr/bin/env bash+2
set -euo pipefail+3
cd -P "$(dirname "$0")/.."+4
make -j1 all build/plan-presentation-test+5
ulimit -c 0+6
result=0+7
for arm in readiness relocation; do+8
build/plan-presentation-test "$arm" || result=1+9
done+10
exit "$result"test/plan-presentation.cadded
@@ -0,0 +1,87 @@
+1
/* SPDX-License-Identifier: BSD-3-Clause+2
* Exercise native readiness and output placement with real scene/layout nodes.+3
* Observe scene commits without rendering a buffer. */+4
#define wlr_scene_output_commit fixture_scene_commit+5
#include "../src/c/host.c"+6
#include <assert.h>+7
static unsigned commits;+8
bool fixture_scene_commit(struct wlr_scene_output *output,+9
const struct wlr_scene_output_state_options *options) {+10
(void)output; (void)options; commits++; return true;+11
}+12
static void initialize(struct server *s) {+13
wl_list_init(&s->outputs); wl_list_init(&s->views); wl_list_init(&s->pixels);+14
wl_list_init(&s->constraints); wl_list_init(&s->keyboards);+15
s->display=wl_display_create(); assert(s->display);+16
s->scene=wlr_scene_create(); assert(s->scene);+17
s->normal=wlr_scene_tree_create(&s->scene->tree); assert(s->normal);+18
s->cursor=wlr_cursor_create(); assert(s->cursor);+19
s->layout=wlr_output_layout_create(s->display); assert(s->layout);+20
s->scene_layout=wlr_scene_attach_output_layout(s->scene,s->layout); assert(s->scene_layout);+21
bridge.event_fd=eventfd(0,EFD_NONBLOCK|EFD_CLOEXEC); assert(bridge.event_fd>=0);+22
}+23
static void finish(struct server *s) {+24
wlr_cursor_destroy(s->cursor);+25
wlr_scene_node_destroy(&s->scene->tree.node);+26
wl_display_destroy(s->display);+27
close(bridge.event_fd); free_event_stream();+28
}+29
static void readiness(void) {+30
struct server s={0}; initialize(&s);+31
struct wlr_xdg_surface surface={0};+32
struct wlr_xdg_toplevel toplevel={.base=&surface};+33
struct view view={.id=1,.server=&s,.mapped=true,.native=&toplevel,.serial=24};+34
view.tree=wlr_scene_tree_create(s.normal); assert(view.tree);+35
wl_list_insert(&s.views,&view.link);+36
wlr_scene_node_set_enabled(&view.tree->node,false);+37
int64_t words[]={1,1,0,200,1,10,10,300,200,0,0,0,0,0};+38
s.plan=malloc(sizeof(words)); assert(s.plan); memcpy(s.plan,words,sizeof(words));+39
s.plan_token=100; s.plan_deadline=now_ms()+200;+40
surface.current.configure_serial=21;+41
check_plan(&s);+42
assert(!s.plan && "HIDDEN_PLACEMENT_MUST_NOT_DELAY_PLAN");+43
struct wm_message event; assert(pop(&bridge.events,&event));+44
assert(event.word[0]==22 && event.word[2]==0);+45
words[9]=1;+46
s.plan=malloc(sizeof(words)); assert(s.plan); memcpy(s.plan,words,sizeof(words));+47
check_plan(&s);+48
assert(s.plan && "SHOWN_PLACEMENT_MUST_WAIT_FOR_CONFIGURE");+49
surface.current.configure_serial=24;+50
check_plan(&s);+51
assert(!s.plan && view.tree->node.enabled);+52
wl_list_remove(&view.link); finish(&s);+53
puts("PLAN_READINESS=PASS hidden-does-not-wait shown-waits-for-commit");+54
}+55
static void relocation(void) {+56
struct server s={0}; initialize(&s);+57
s.backend=wlr_headless_backend_create(wl_display_get_event_loop(s.display)); assert(s.backend);+58
struct wlr_output *native=wlr_headless_add_output(s.backend,320,240); assert(native);+59
assert(wlr_backend_start(s.backend));+60
struct wlr_output_state state; wlr_output_state_init(&state);+61
wlr_output_state_set_enabled(&state,true);+62
assert(wlr_output_commit_state(native,&state));+63
wlr_output_state_finish(&state);+64
struct output output={.server=&s,.id=1,.native=native,.configured_enabled=true};+65
output.scene=wlr_scene_output_create(s.scene,native); assert(output.scene);+66
wl_list_insert(&s.outputs,&output.link);+67
place_output_state(&s,&output,320,0);+68
/* Finish the initial scene, then move the survivor into the removed head's region. */+69
s.scene_update_deadline=0;+70
output_frame(&output.frame,NULL); unsigned before=commits;+71
place_output_state(&s,&output,0,0);+72
output_frame(&output.frame,NULL);+73
assert(commits==before && "RELOCATED_OUTPUT_MUST_WAIT_FOR_SCENE_PLAN");+74
int64_t words[]={1,0,0,200};+75
s.plan=malloc(sizeof(words)); assert(s.plan); memcpy(s.plan,words,sizeof(words));+76
check_plan(&s);+77
output_frame(&output.frame,NULL);+78
assert(commits==before+1 && "APPLIED_PLAN_MUST_RELEASE_PRESENTATION");+79
wl_list_remove(&output.link);+80
wlr_backend_destroy(s.backend); finish(&s);+81
puts("OUTPUT_RELOCATION=PASS presentation-held-until-plan");+82
}+83
int main(int argc,char **argv) {+84
assert(argc==2);+85
if(!strcmp(argv[1],"readiness")) readiness();+86
else { assert(!strcmp(argv[1],"relocation")); relocation(); }+87
}