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
}