AtlatestRepositorysigil-wm
1
/* SPDX-License-Identifier: BSD-3-Clause2
* Real Wayland loop/timers and existing expiry handlers. Protocol sends at the3
* lock/popup/configuration boundary are replaced by observation-only fixtures. */4
#define listen socket_listen5
#include <sys/socket.h>6
#undef listen7
#define wlr_session_lock_v1_send_locked fixture_lock_send8
#define wlr_xdg_popup_destroy fixture_popup_destroy9
#define wlr_output_configuration_v1_send_failed fixture_configuration_failed10
#define wlr_output_configuration_v1_destroy fixture_configuration_destroy11
#include "../src/c/host.c"12
#include <assert.h>13
static unsigned lock_acks,popup_expired,configuration_failed;14
static struct popup *fixture_popup;15
void fixture_lock_send(struct wlr_session_lock_v1 *lock) { (void)lock; lock_acks++; }16
void fixture_popup_destroy(struct wlr_xdg_popup *popup) {17
(void)popup; popup_expired++; wl_list_remove(&fixture_popup->link); free(fixture_popup); fixture_popup=NULL;18
}19
void fixture_configuration_failed(struct wlr_output_configuration_v1 *configuration) {20
(void)configuration; configuration_failed++;21
}22
void fixture_configuration_destroy(struct wlr_output_configuration_v1 *configuration) { (void)configuration; }23
static void initialize(struct server *s) {24
wl_list_init(&s->outputs); wl_list_init(&s->views); wl_list_init(&s->keyboards);25
wl_list_init(&s->devices); wl_list_init(&s->pixels); wl_list_init(&s->permissions);26
wl_list_init(&s->data_requests); wl_list_init(&s->output_controls);27
wl_list_init(&s->pending_outputs); wl_list_init(&s->output_requests);28
wl_list_init(&s->constraints); wl_list_init(&s->pointer_hints);29
wl_list_init(&s->decorations); wl_list_init(&s->legacy_decorations);30
wl_list_init(&s->inhibitors); wl_list_init(&s->popups);31
s->generation=1;32
}33
static void selection(void) {34
struct server s={0}; initialize(&s);35
uint64_t now=1000;36
assert(native_deadline(&s,now)==0);37
s.plan=(void *)1; s.plan_deadline=1030; assert(native_deadline(&s,now)==1030); s.plan=NULL;38
s.scene_update_deadline=1040; assert(native_deadline(&s,now)==1040); s.scene_update_deadline=0;39
s.lock_state=1; s.lock_deadline=1050; assert(native_deadline(&s,now)==1050); s.lock_state=0;40
s.has_pending_motion=true; s.motion_last=1000; s.motion_period=60;41
assert(native_deadline(&s,now)==1060); s.has_pending_motion=false;42
s.input_write=3;43
s.inputs[0]=(struct input){.kind=30,.deadline=UINT64_MAX};44
s.inputs[1]=(struct input){.kind=30,.native=true,.ready=true,.order_deadline=1007};45
s.inputs[2]=(struct input){.kind=30,.deadline=999}; /* blocked behind the bound head */46
assert(native_deadline(&s,now)==1007);47
s.inputs[1].completed=true; assert(native_deadline(&s,now)==0);48
s.inputs[2]=(struct input){.kind=32,.deadline=1003}; assert(native_deadline(&s,now)==1003);49
s.input_write=0;50
struct permission p={.deadline=1010}; wl_list_insert(&s.permissions,&p.link);51
assert(native_deadline(&s,now)==1010); wl_list_remove(&p.link);52
struct data_request d={.deadline=1011}; wl_list_insert(&s.data_requests,&d.link);53
assert(native_deadline(&s,now)==1011); wl_list_remove(&d.link);54
struct output o={.id=7}; wl_list_insert(&s.outputs,&o.link);55
o.scene_retry_at=1012; assert(native_deadline(&s,now)==1012); o.scene_retry_at=0;56
struct output_control_request c={.output=7,.deadline=1012}; wl_list_insert(&s.output_controls,&c.link);57
assert(native_deadline(&s,now)==1012); c.resolved=true;58
assert(native_deadline(&s,now)==0); wl_list_remove(&c.link); wl_list_remove(&o.link);59
struct output_configuration_request r={.deadline=1013}; wl_list_insert(&s.output_requests,&r.link);60
assert(native_deadline(&s,now)==1013); s.output_revision=1;61
assert(native_deadline(&s,now)==now); wl_list_remove(&r.link); s.output_revision=0;62
struct pointer_hint h={.deadline=1014,.generation=1}; wl_list_insert(&s.pointer_hints,&h.link);63
assert(native_deadline(&s,now)==1014); h.generation=0;64
assert(native_deadline(&s,now)==now); wl_list_remove(&h.link);65
struct popup popup={.deadline=1015}; wl_list_insert(&s.popups,&popup.link);66
assert(native_deadline(&s,now)==1015); wl_list_remove(&popup.link);67
atomic_store(&bridge.input_resync,true); assert(native_deadline(&s,now)==now);68
atomic_store(&bridge.input_resync,false);69
}70
static uint64_t deadline_start;71
static void wait_for_tick(struct server *s) {72
uint64_t ticks=atomic_load(&bridge.timer_wakes);73
deadline_start=now_ms();74
while(atomic_load(&bridge.timer_wakes)==ticks) {75
assert(now_ms()-deadline_start<500);76
assert(dispatch_native_once(s,100)==0);77
}78
assert(now_ms()-deadline_start>=15 && now_ms()-deadline_start<150);79
}80
struct repeating { struct wl_event_source *timer; unsigned count; };81
static int repeat_tick(void *data) {82
struct repeating *repeat=data;83
repeat->count++;84
if(repeat->count<4) wl_event_source_timer_update(repeat->timer,8);85
return 0;86
}87
static void idle_admit(void *data) { ((struct server *)data)->scene_update_deadline=now_ms()+25; }88
int main(void) {89
selection();90
struct server s={0}; initialize(&s);91
s.display=wl_display_create(); assert(s.display);92
s.cursor=wlr_cursor_create(); assert(s.cursor);93
s.scene=wlr_scene_create(); assert(s.scene);94
s.normal=wlr_scene_tree_create(&s.scene->tree); assert(s.normal);95
s.seat=wlr_seat_create(s.display,"deadline-test"); assert(s.seat);96
struct wl_event_loop *loop=wl_display_get_event_loop(s.display);97
s.timer=wl_event_loop_add_timer(loop,timer_tick,&s); assert(s.timer);98
bridge.event_fd=eventfd(0,EFD_NONBLOCK|EFD_CLOEXEC); assert(bridge.event_fd>=0);99
uint64_t start=now_ms();100
assert(dispatch_native_once(&s,60)==0);101
assert(now_ms()-start>=55 && atomic_load(&bridge.timer_wakes)==0 && s.timer_deadline==0);102
struct repeating repeat={0}; repeat.timer=wl_event_loop_add_timer(loop,repeat_tick,&repeat);103
wl_event_source_timer_update(repeat.timer,8);104
while(repeat.count<4) assert(dispatch_native_once(&s,100)==0);105
assert(atomic_load(&bridge.timer_wakes)==0); /* independent repeat timer survives */106
wl_event_source_remove(repeat.timer);107
wl_event_loop_add_idle(loop,idle_admit,&s);108
wait_for_tick(&s); assert(s.scene_update_deadline==0);109
s.scene_update_deadline=now_ms()+20; assert(rearm_deadline(&s,now_ms())==0);110
s.scene_update_deadline=0; assert(rearm_deadline(&s,now_ms())==0);111
uint64_t ticks=atomic_load(&bridge.timer_wakes);112
assert(dispatch_native_once(&s,50)==0 && atomic_load(&bridge.timer_wakes)==ticks);113
/* Bound decision expires once, then waits for its explicit reply. */114
s.inputs[0]=(struct input){.kind=30,.notified=true,.origin=1,.deadline=now_ms()+25}; s.input_write=1;115
wait_for_tick(&s); assert(s.inputs[0].deadline==UINT64_MAX && native_deadline(&s,now_ms())==0);116
s.input_read=s.input_write=0;117
/* Real permission resource is denied and destroyed at its deadline. */118
int sockets[2]; assert(socketpair(AF_UNIX,SOCK_STREAM,0,sockets)==0);119
struct wl_client *client=wl_client_create(s.display,sockets[0]); assert(client);120
struct wl_resource *resource=wl_resource_create(client,&wl_callback_interface,1,0); assert(resource);121
struct wlr_input_device device={.type=WLR_INPUT_DEVICE_KEYBOARD};122
bridge.request_deadline=25; permission_request(&s,resource,&device);123
wait_for_tick(&s); assert(wl_list_empty(&s.permissions));124
struct data_request *data=calloc(1,sizeof(*data)); assert(data);125
data->server=&s; data->token=100; data->generation=s.generation; data->deadline=now_ms()+25;126
wl_list_insert(&s.data_requests,&data->link); s.data_request_count++; atomic_fetch_add(&bridge.objects,1);127
wait_for_tick(&s); assert(wl_list_empty(&s.data_requests) && !s.data_request_count);128
struct pointer_hint *hint=calloc(1,sizeof(*hint)); assert(hint);129
hint->server=&s; hint->token=101; hint->generation=s.generation; hint->deadline=now_ms()+25;130
wl_list_init(&hint->destroy.link); wl_list_insert(&s.pointer_hints,&hint->link);131
s.pointer_hint_count++; atomic_fetch_add(&bridge.objects,1);132
wait_for_tick(&s); assert(wl_list_empty(&s.pointer_hints));133
struct output_configuration_request *request=calloc(1,sizeof(*request)); assert(request);134
request->server=&s; request->token=102; request->deadline=now_ms()+25;135
wl_list_insert(&s.output_requests,&request->link); s.output_request_count++; atomic_fetch_add(&bridge.objects,1);136
wait_for_tick(&s); assert(wl_list_empty(&s.output_requests) && configuration_failed==1);137
fixture_popup=calloc(1,sizeof(*fixture_popup)); assert(fixture_popup);138
fixture_popup->deadline=now_ms()+25; wl_list_insert(&s.popups,&fixture_popup->link);139
wait_for_tick(&s); assert(!fixture_popup && popup_expired==1);140
struct wlr_output native={.enabled=true};141
struct output output={.id=7,.native=&native,.lock_generation=1,.lock_presented=true};142
wl_list_insert(&s.outputs,&output.link);143
struct output_control_request *control=calloc(1,sizeof(*control)); assert(control);144
control->server=&s; control->token=103; control->kind=1; control->output=7; control->deadline=now_ms()+25;145
wl_list_insert(&s.output_controls,&control->link); s.output_control_count++; atomic_fetch_add(&bridge.objects,1);146
wait_for_tick(&s); assert(wl_list_empty(&s.output_controls));147
struct wlr_session_lock_v1 lock={0};148
s.lock_owner=&lock; s.lock_state=1; s.lock_generation=1; s.lock_deadline=now_ms()+25;149
lock_ack(&s); assert(s.lock_state==1 && lock_acks==0);150
wait_for_tick(&s); assert(s.lock_state==2 && lock_acks==1);151
s.lock_state=1; s.lock_deadline=now_ms()+25; output.lock_presented=false;152
wait_for_tick(&s); assert(s.lock_state==1 && lock_acks==1 && s.lock_deadline==0);153
assert(native_deadline(&s,now_ms())==0); /* presentation barrier never polls */154
output.lock_presented=true; lock_ack(&s); assert(s.lock_state==2 && lock_acks==2);155
s.lock_state=0; s.lock_owner=NULL; wl_list_remove(&output.link);156
s.plan=calloc(4,sizeof(int64_t)); assert(s.plan); s.plan[0]=1; s.plan_count=4; s.plan_deadline=now_ms()+25;157
wait_for_tick(&s); assert(!s.plan);158
wl_client_destroy(client); close(sockets[1]);159
wl_event_source_remove(s.timer); wlr_cursor_destroy(s.cursor);160
wlr_scene_node_destroy(&s.scene->tree.node); wl_display_destroy(s.display); close(bridge.event_fd);161
free_event_stream();162
puts("DEADLINES=PASS all-sources idle-zero repeat idle-admission cancellation bound-input permissions data output requests hints popups lock-presentation plan");163
}