AtlatestRepositorysigil-wm

sigil-wm / tree / src / clock.h

1/* SPDX-License-Identifier: BSD-3-Clause
2 * Ported from Tessera's native lock isolation and presentation state machine.
3 * Normal scene isolation and authenticated unlock never depend on Sigil. */
4struct lock_surface {
5 struct server *server;
6 struct output *output;
7 struct wlr_session_lock_surface_v1 *native;
8 struct wlr_scene_tree *tree;
9 struct wl_listener map,unmap,destroy;
10 uint64_t id;
11};
12static void lock_damage(struct output *o) {
13 wlr_damage_ring_add_whole(&o->scene->damage_ring);
14 wlr_output_schedule_frame(o->native);
16static void lock_clear_input(struct server *s) {
17 constraints_end(s);
18 clear_held(s);
19 struct view *focused = find_view(s, s->focus);
20 if (focused && focused->x11)
21 wlr_xwayland_surface_activate(focused->x11, false);
22 s->focus=0;
23 foreign_refresh(s);
24 s->generation++;
25 wlr_seat_keyboard_end_grab(s->seat);
26 wlr_seat_pointer_end_grab(s->seat);
27 wlr_seat_keyboard_notify_clear_focus(s->seat);
28 wlr_seat_pointer_notify_clear_focus(s->seat);
29 wlr_cursor_unset_image(s->cursor);
30 EVENT(25,0,s->generation);
32static void lock_ack(struct server *s) {
33 if(s->lock_state!=1 || !s->lock_owner) return;
34 struct output *o;
35 wl_list_for_each(o,&s->outputs,link) {
36 if(o->native->enabled && (o->lock_generation!=s->lock_generation || !o->lock_presented)) return;
37 if(o->native->enabled && now_ms()<s->lock_deadline &&
38 (!o->lock_surface || !o->lock_surface->native->surface->mapped)) return;
39 }
40 wlr_session_lock_v1_send_locked(s->lock_owner);
41 s->lock_state=2;
42 EVENT(61,2,s->lock_generation);
44static void lock_present(struct wl_listener *listener,void *data) {
45 struct output *o=wl_container_of(listener,o,lock_present);
46 struct wlr_output_event_present *e=data;
47 uint64_t unset=0;
48 if(e->presented) atomic_compare_exchange_strong(&bridge.first_present_ms,&unset,now_ms());
49 if(trace_output_present(&o->trace,e->commit_seq,o->id,e->presented,&e->when)) wake(bridge.event_fd);
50 layer_output_present(o, e);
51 if(!o->server->lock_state || !e->presented || !o->lock_armed ||
52 o->lock_generation!=o->server->lock_generation ||
53 (int32_t)(e->commit_seq-o->lock_commit)<0) return;
54 o->lock_presented=true; o->lock_armed=false;
55 route_motion(o->server,now_ms(),false);
56 lock_ack(o->server);
58static void lock_arm(struct output *o) {
59 if(!o->server->lock_state || o->lock_presented || o->lock_armed) return;
60 o->lock_generation=o->server->lock_generation;
61 o->lock_commit=o->native->commit_seq+1;
62 o->lock_armed=true;
64static void lock_configure(struct output *o) {
65 struct server *s=o->server;
66 if(!s->lock_state) return;
67 int width,height;
68 wlr_output_effective_resolution(o->native,&width,&height);
69 struct wlr_box box;
70 wlr_output_layout_get_box(s->layout,o->native,&box);
71 /* Opaque blanking is the unconditional safe fallback. */
72 float color[4]={(s->lock_colour>>24)/255.0f,
73 ((s->lock_colour>>16)&255)/255.0f,((s->lock_colour>>8)&255)/255.0f,1};
74 if(!o->lock_fill) o->lock_fill=wlr_scene_rect_create(s->lock_scene,width,height,color);
75 if(o->lock_fill) {
76 wlr_scene_rect_set_color(o->lock_fill,color);
77 wlr_scene_rect_set_size(o->lock_fill,width,height);
78 wlr_scene_node_set_position(&o->lock_fill->node,box.x,box.y);
79 }
80 if(o->lock_surface) {
81 wlr_scene_node_set_position(&o->lock_surface->tree->node,box.x,box.y);
82 wlr_scene_node_raise_to_top(&o->lock_surface->tree->node);
83 wlr_session_lock_surface_v1_configure(o->lock_surface->native,width,height);
84 }
85 o->lock_generation=s->lock_generation;
86 o->lock_presented=false; o->lock_armed=false;
87 lock_damage(o);
89static struct wlr_surface *mapped_lock_surface(struct server *s) {
90 struct output *output;
91 wl_list_for_each(output,&s->outputs,link) {
92 if(output->lock_surface &&
93 output->lock_surface->native->surface->mapped)
94 return output->lock_surface->native->surface;
95 }
96 return NULL;
98static void lock_native_focus(struct server *s,struct wlr_surface *surface,
99 struct keyboard *keyboard) {
100 if(!s->lock_state || !s->lock_owner || !surface || !surface->mapped ||
101 !keyboard || keyboard->is_virtual) return;
102 wlr_seat_set_keyboard(s->seat,keyboard->native);
103 if(s->seat->keyboard_state.focused_surface!=surface) {
104 struct wlr_keyboard_modifiers mods={0};
105 wlr_seat_keyboard_notify_enter(s->seat,surface,NULL,0,&mods);
106 }
108static void lock_focus_available(struct server *s) {
109 struct wlr_surface *surface=mapped_lock_surface(s);
110 struct keyboard *keyboard;
111 wl_list_for_each(keyboard,&s->keyboards,link) {
112 if(!keyboard->is_virtual) {
113 lock_native_focus(s,surface,keyboard);
114 return;
115 }
116 }
118static void lock_keyboard_input(struct keyboard *keyboard,struct wlr_keyboard_key_event *event) {
119 struct server *s=keyboard->server;
120 if(keyboard->is_virtual || !s->lock_owner) return;
121 struct wlr_surface *focused=s->seat->keyboard_state.focused_surface;
122 bool eligible=false;
123 struct output *output;
124 wl_list_for_each(output,&s->outputs,link) {
125 if(output->lock_surface && output->lock_surface->native->surface==focused &&
126 focused->mapped) eligible=true;
127 }
128 if(!eligible) focused=mapped_lock_surface(s);
129 if(!focused) return;
130 lock_native_focus(s,focused,keyboard);
131 activity(s,1,0);
132 wlr_seat_keyboard_notify_key(s->seat,event->time_msec,event->keycode,event->state);
134static void lock_map(struct wl_listener *listener,void *data) {
135 (void)data;
136 struct lock_surface *surface=wl_container_of(listener,surface,map);
137 wlr_scene_node_set_enabled(&surface->tree->node,true);
138 if(surface->output) lock_configure(surface->output);
139 lock_focus_available(surface->server);
140 route_motion(surface->server,now_ms(),false);
141 EVENT(64,surface->id,surface->output ? surface->output->id : 0,surface->server->lock_generation,1);
143static void lock_unmap(struct wl_listener *listener,void *data) {
144 (void)data;
145 struct lock_surface *surface=wl_container_of(listener,surface,unmap);
146 wlr_scene_node_set_enabled(&surface->tree->node,false);
147 if(surface->server->seat->keyboard_state.focused_surface==surface->native->surface)
148 lock_clear_input(surface->server);
149 lock_focus_available(surface->server);
150 route_motion(surface->server,now_ms(),false);
151 EVENT(64,surface->id,surface->output ? surface->output->id : 0,surface->server->lock_generation,0);
153static void lock_surface_destroy(struct wl_listener *listener,void *data) {
154 (void)data;
155 struct lock_surface *surface=wl_container_of(listener,surface,destroy);
156 bool focused=surface->server->seat->keyboard_state.focused_surface==surface->native->surface;
157 if(focused)
158 lock_clear_input(surface->server);
159 if(surface->output) surface->output->lock_surface=NULL;
160 if(focused) lock_focus_available(surface->server);
161 wl_list_remove(&surface->map.link); wl_list_remove(&surface->unmap.link);
162 wl_list_remove(&surface->destroy.link);
163 surface->native->data=NULL;
164 wlr_scene_node_destroy(&surface->tree->node);
165 EVENT(65,surface->id);
166 free(surface);
168static void lock_new_surface(struct wl_listener *listener,void *data) {
169 struct server *s=wl_container_of(listener,s,lock_new_surface);
170 struct wlr_session_lock_surface_v1 *native=data;
171 struct output *o=native->output->data;
172 if(!o) return;
173 struct lock_surface *surface=calloc(1,sizeof(*surface));
174 if(!surface) { wl_client_post_no_memory(wl_resource_get_client(native->resource)); return; }
175 surface->server=s; surface->output=o; surface->native=native; surface->id=++s->next_id;
176 surface->tree=wlr_scene_tree_create(s->lock_scene);
177 if(!surface->tree || !wlr_scene_subsurface_tree_create(surface->tree,native->surface)) {
178 if(surface->tree) wlr_scene_node_destroy(&surface->tree->node);
179 free(surface); wl_client_post_no_memory(wl_resource_get_client(native->resource)); return;
180 }
181 native->data=surface; o->lock_surface=surface;
182 wlr_scene_node_set_enabled(&surface->tree->node,false);
183 listen(&native->surface->events.map,&surface->map,lock_map);
184 listen(&native->surface->events.unmap,&surface->unmap,lock_unmap);
185 listen(&native->events.destroy,&surface->destroy,lock_surface_destroy);
186 lock_configure(o);
187 EVENT(63,surface->id,o->id,s->lock_generation);
189static void lock_unlock(struct wl_listener *listener,void *data) {
190 (void)data;
191 struct server *s=wl_container_of(listener,s,lock_unlock);
192 if(!s->lock_owner || s->lock_state!=2) return;
193 lock_clear_input(s);
194 s->lock_state=0;
195 wlr_scene_node_set_enabled(&s->lock_scene->node,false);
196 wlr_scene_node_set_enabled(&s->normal->node,true);
197 wlr_scene_node_set_enabled(&s->drag_scene->node,true);
198 EVENT(61,0,s->lock_generation);
200static void lock_owner_destroy(struct wl_listener *listener,void *data) {
201 (void)data;
202 struct server *s=wl_container_of(listener,s,lock_destroy);
203 wl_list_remove(&s->lock_new_surface.link); wl_list_remove(&s->lock_unlock.link);
204 wl_list_remove(&s->lock_destroy.link);
205 s->lock_owner=NULL;
206 if(s->lock_state) {
207 lock_clear_input(s); s->lock_state=3;
208 EVENT(61,3,s->lock_generation);
209 }
211static void lock_new(struct wl_listener *listener,void *data) {
212 struct server *s=wl_container_of(listener,s,new_lock);
213 struct wlr_session_lock_v1 *owner=data;
214 if(s->lock_owner || s->stopping) { wlr_session_lock_v1_destroy(owner); return; }
215 scene_move_finish(s);
216 s->lock_owner=owner; s->lock_generation++; s->lock_state=1;
217 s->lock_deadline=now_ms()+bridge.request_deadline;
218 wlr_scene_node_set_enabled(&s->normal->node,false);
219 wlr_scene_node_set_enabled(&s->drag_scene->node,false);
220 wlr_scene_node_set_enabled(&s->lock_scene->node,true);
221 lock_clear_input(s);
222 listen(&owner->events.new_surface,&s->lock_new_surface,lock_new_surface);
223 listen(&owner->events.unlock,&s->lock_unlock,lock_unlock);
224 listen(&owner->events.destroy,&s->lock_destroy,lock_owner_destroy);
225 struct output *o;
226 wl_list_for_each(o,&s->outputs,link) lock_configure(o);
227 EVENT(61,1,s->lock_generation);
228 lock_ack(s);
230static bool lock_focus(struct server *s,uint64_t output_id,uint64_t device_id) {
231 struct output *o=find_output(s,output_id);
232 struct keyboard *k=find_keyboard(s,device_id);
233 if(!s->lock_state || !s->lock_owner || !o || !o->lock_surface ||
234 !o->lock_surface->native->surface->mapped || !k) return true;
235 if(k==&s->synthetic_owner || k->is_virtual) return false;
236 lock_native_focus(s,o->lock_surface->native->surface,k);
237 return true;