AtlatestRepositorysigil-wm

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

1/* SPDX-License-Identifier: BSD-3-Clause
2 * Output-management proposals are copied requests, never native WM policy. */
3struct 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};
10static 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);
18static 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);
24static 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);
62static 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);
66static 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);
70static 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);
101static 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 }
112static 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;
119static 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 }