AtlatestRepositorysigil-wm
1
/* SPDX-License-Identifier: BSD-3-Clause2
* Output-management proposals are copied requests, never native WM policy. */3
struct output_configuration_request {4
struct wl_list link;5
struct server *server;6
struct wlr_output_configuration_v1 *configuration;7
uint64_t token,deadline,revision;8
bool apply;9
};10
static void publish_output_management(struct server *s) {11
inventory_schedule(s);12
foreign_refresh(s);13
if(!s->output_manager || s->stopping) return;14
struct wlr_output_configuration_v1 *configuration=output_configuration(s,true);15
if(configuration) wlr_output_manager_v1_set_configuration(s->output_manager,configuration);16
else atomic_fetch_add(&bridge.overflow,1);17
}18
static void output_request_remove(struct output_configuration_request *request) {19
wl_list_remove(&request->link);20
request->server->output_request_count--;21
atomic_fetch_sub(&bridge.objects,1);22
free(request);23
}24
static void output_configuration_requested(struct server *s,struct wlr_output_configuration_v1 *configuration,bool apply) {25
size_t count=wl_list_length(&configuration->heads);26
if(count>64 || s->output_request_count>=64 || s->stopping) {27
wlr_output_configuration_v1_send_failed(configuration);28
wlr_output_configuration_v1_destroy(configuration);29
return;30
}31
struct output_configuration_request *request=calloc(1,sizeof(*request));32
if(!request) {33
wlr_output_configuration_v1_send_failed(configuration);34
wlr_output_configuration_v1_destroy(configuration);35
return;36
}37
request->server=s; request->configuration=configuration; request->apply=apply;38
request->token=++s->next_token; request->deadline=now_ms()+bridge.request_deadline;39
request->revision=s->output_revision;40
wl_list_insert(&s->output_requests,&request->link);41
s->output_request_count++;42
atomic_fetch_add(&bridge.objects,1);43
EVENT(100,request->token,apply,count,request->revision);44
struct wlr_output_configuration_head_v1 *head;45
wl_list_for_each(head,&configuration->heads,link) {46
struct output *output=head->state.output->data;47
int mode_index=-1,index=0;48
struct wlr_output_mode *mode;49
wl_list_for_each(mode,&head->state.output->modes,link) {50
if(mode==head->state.mode) mode_index=index;51
index++;52
}53
int width=head->state.mode ? head->state.mode->width : head->state.custom_mode.width;54
int height=head->state.mode ? head->state.mode->height : head->state.custom_mode.height;55
int refresh=head->state.mode ? head->state.mode->refresh : head->state.custom_mode.refresh;56
EVENT(101,request->token,output ? output->id : 0,head->state.enabled,57
head->state.x,head->state.y,(int64_t)(head->state.scale*1000),head->state.transform,58
mode_index,width,height,refresh,head->state.adaptive_sync_enabled);59
}60
EVENT(102,request->token);61
}62
static void output_manager_apply(struct wl_listener *listener,void *data) {63
struct server *s=wl_container_of(listener,s,output_apply);64
output_configuration_requested(s,data,true);65
}66
static void output_manager_test(struct wl_listener *listener,void *data) {67
struct server *s=wl_container_of(listener,s,output_test);68
output_configuration_requested(s,data,false);69
}70
static void output_configuration_reply(struct server *s,uint64_t operation,const int64_t *words,size_t count) {71
bool success=false,apply=false,found=false;72
int rollback=0;73
uint64_t token=count ? words[0] : 0;74
if(count>=3 && words[0]>0 && (words[1]==0 || words[1]==1)) {75
struct output_configuration_request *request;76
wl_list_for_each(request,&s->output_requests,link) {77
if(request->token!=token) continue;78
found=true; apply=request->apply;79
struct wlr_output_configuration_v1 *configuration=request->configuration;80
bool current=request->revision==s->output_revision;81
output_request_remove(request);82
uint64_t selected[64];83
bool enabled[64];84
size_t selected_count=0;85
if(words[1] && current &&86
output_configuration_settings(s,configuration,words+2,count-2,selected,enabled,&selected_count) &&87
selected_count==(size_t)wl_list_length(&s->outputs) &&88
selected_count==(size_t)wl_list_length(&configuration->heads))89
success=output_configuration_commit(s,configuration,selected,enabled,selected_count,apply,&rollback);90
if(success) wlr_output_configuration_v1_send_succeeded(configuration);91
else wlr_output_configuration_v1_send_failed(configuration);92
wlr_output_configuration_v1_destroy(configuration);93
if(success && apply) s->output_revision++;94
publish_output_management(s);95
break;96
}97
}98
EVENT(104,token,success,apply,rollback,found);99
EVENT(24,operation,11,found);100
}101
static void output_requests_expire(struct server *s) {102
struct output_configuration_request *request,*next;103
wl_list_for_each_safe(request,next,&s->output_requests,link) {104
if(now_ms()<request->deadline && request->revision==s->output_revision) continue;105
uint64_t token=request->token;106
wlr_output_configuration_v1_send_failed(request->configuration);107
wlr_output_configuration_v1_destroy(request->configuration);108
output_request_remove(request);109
EVENT(72,token);110
}111
}112
static bool output_management_init(struct server *s) {113
s->output_manager=wlr_output_manager_v1_create(s->display);114
if(!s->output_manager) return false;115
listen(&s->output_manager->events.apply,&s->output_apply,output_manager_apply);116
listen(&s->output_manager->events.test,&s->output_test,output_manager_test);117
return true;118
}119
static void output_management_finish(struct server *s) {120
if(s->output_apply.notify) wl_list_remove(&s->output_apply.link);121
if(s->output_test.notify) wl_list_remove(&s->output_test.link);122
struct output_configuration_request *request,*next;123
wl_list_for_each_safe(request,next,&s->output_requests,link) {124
wlr_output_configuration_v1_destroy(request->configuration);125
output_request_remove(request);126
}127
}