AtlatestRepositorysigil-wm
1
/* SPDX-License-Identifier: BSD-3-Clause2
* Copied output-control requests and native commit/lifetime mechanisms. */3
struct output_control_request {4
struct wl_list link;5
struct server *server;6
uint64_t token,deadline,output,generation;7
int kind;8
bool on,resolved,accepted;9
struct wlr_gamma_control_v1 *gamma;10
struct wl_listener destroy;11
};12
static void output_control_remove(struct output_control_request *request) {13
if(request->destroy.notify) wl_list_remove(&request->destroy.link);14
wl_list_remove(&request->link);15
request->server->output_control_count--;16
atomic_fetch_sub(&bridge.objects,1);17
free(request);18
}19
static void output_control_destroyed(struct wl_listener *listener,void *data) {20
(void)data;21
struct output_control_request *request=wl_container_of(listener,request,destroy);22
EVENT(72,request->token);23
output_control_remove(request);24
}25
static struct output_control_request *output_control_new(struct server *s,struct output *output,int kind) {26
if(!output || s->output_control_count>=64 || s->stopping) return NULL;27
struct output_control_request *request=calloc(1,sizeof(*request));28
if(!request) return NULL;29
request->server=s; request->output=output->id; request->kind=kind;30
request->token=++s->next_token; request->deadline=now_ms()+bridge.request_deadline;31
request->generation=output->configuration_generation;32
wl_list_insert(&s->output_controls,&request->link);33
s->output_control_count++;34
atomic_fetch_add(&bridge.objects,1);35
return request;36
}37
static bool output_set_power(struct server *s,uint64_t id,bool on) {38
struct output *output=find_output(s,id);39
if(!output) return false;40
output->pending_power=true;41
output->pending_on=on;42
if(on && !output->wake_requested) output->wake_requested=now_ms();43
queue_output_flush(s);44
return true;45
}46
static bool output_control_reply(struct server *s,uint64_t token,bool accept) {47
struct output_control_request *request;48
wl_list_for_each(request,&s->output_controls,link) {49
if(request->token!=token) continue;50
struct output *output=find_output(s,request->output);51
int kind=request->kind;52
uint64_t id=request->output;53
struct wlr_gamma_control_v1 *gamma=request->gamma;54
bool valid=output && ((kind==0 && request->on) ||55
output->configuration_generation==request->generation);56
bool on=request->on;57
if(kind==0) {58
if(request->resolved) return true;59
request->resolved=true;60
request->accepted=accept && valid;61
if(request->accepted) output_set_power(s,id,on);62
queue_output_flush(s);63
return true;64
}65
output_control_remove(request);66
bool success=false;67
if(accept && valid &&68
wlr_gamma_control_manager_v1_get_control(s->gamma_manager,output->native)==gamma) {69
output->gamma_pending=true;70
wlr_output_schedule_frame(output->native);71
success=true;72
} else if(gamma) wlr_gamma_control_v1_send_failed_and_destroy(gamma);73
EVENT(92,token,kind,id,success);74
return true;75
}76
/* Native expiry may have completed a wake while policy was stalled.77
* A late disposition cannot undo that completed request. */78
return token && token<=s->next_token;79
}80
static void output_power_request(struct wl_listener *listener,void *data) {81
struct server *s=wl_container_of(listener,s,power_request);82
struct wlr_output_power_v1_set_mode_event *event=data;83
struct output *output=event->output->data;84
struct output_control_request *request=output_control_new(s,output,0);85
if(!request) {86
if(output && event->mode==ZWLR_OUTPUT_POWER_V1_MODE_ON)87
output_set_power(s,output->id,true);88
return;89
}90
request->on=event->mode==ZWLR_OUTPUT_POWER_V1_MODE_ON;91
if(request->on && !output->wake_requested) output->wake_requested=now_ms();92
EVENT(90,request->token,output->id,request->on,request->generation);93
}94
static void output_gamma_request(struct wl_listener *listener,void *data) {95
struct server *s=wl_container_of(listener,s,gamma_request);96
struct wlr_gamma_control_manager_v1_set_gamma_event *event=data;97
struct output *output=event->output->data;98
struct output_control_request *previous,*next;99
wl_list_for_each_safe(previous,next,&s->output_controls,link) {100
if(previous->kind==1 && output && previous->output==output->id) {101
EVENT(72,previous->token);102
output_control_remove(previous);103
}104
}105
if(!event->control) {106
/* A destroyed control cannot authorize a ramp. Restore the latest107
* base ramp without waiting for a policy reply from the dead client. */108
if(output && !s->stopping) {109
output->gamma_pending=true;110
wlr_output_schedule_frame(output->native);111
}112
return;113
}114
if(output) output->gamma_pending=false;115
struct output_control_request *request=output_control_new(s,output,1);116
if(!request) {117
if(event->control) wlr_gamma_control_v1_send_failed_and_destroy(event->control);118
return;119
}120
request->gamma=event->control;121
if(request->gamma) {122
wl_resource_add_destroy_listener(request->gamma->resource,&request->destroy);123
request->destroy.notify=output_control_destroyed;124
}125
EVENT(91,request->token,output->id,request->gamma ? request->gamma->ramp_size : 0,126
request->gamma==NULL,request->generation);127
}128
static void output_controls_expire(struct server *s) {129
struct output_control_request *request,*next;130
wl_list_for_each_safe(request,next,&s->output_controls,link) {131
if(!find_output(s,request->output)) {132
EVENT(72,request->token);133
output_control_remove(request);134
queue_output_flush(s);135
} else if(!request->resolved && now_ms()>=request->deadline) {136
bool wake=request->kind==0 && request->on;137
if(wake) wlr_log(WLR_INFO,"OUTPUT_WAKE_DEFAULT_ACCEPT output=%llu token=%llu",138
(unsigned long long)request->output,(unsigned long long)request->token);139
output_control_reply(s,request->token,wake);140
}141
}142
}143
static bool output_controls_init(struct server *s) {144
s->power_manager=wlr_output_power_manager_v1_create(s->display);145
s->gamma_manager=wlr_gamma_control_manager_v1_create(s->display);146
if(!s->power_manager || !s->gamma_manager) return false;147
listen(&s->power_manager->events.set_mode,&s->power_request,output_power_request);148
listen(&s->gamma_manager->events.set_gamma,&s->gamma_request,output_gamma_request);149
return true;150
}151
static void output_controls_finish(struct server *s) {152
if(s->power_request.notify) wl_list_remove(&s->power_request.link);153
if(s->gamma_request.notify) wl_list_remove(&s->gamma_request.link);154
struct output_control_request *request,*next;155
wl_list_for_each_safe(request,next,&s->output_controls,link) output_control_remove(request);156
}