AtlatestRepositorysigil-wm

sigil-wm / tree / src / coutput-controls.h

1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copied output-control requests and native commit/lifetime mechanisms. */
3struct 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};
12static 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);
19static 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);
25static 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;
37static 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;
46static 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;
80static 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);
94static 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 latest
107 * 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);
128static 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 }
143static 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;
151static 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);