AtlatestRepositorysigil-wm
1
/* SPDX-License-Identifier: BSD-3-Clause2
* Ported from Tessera's native lock isolation and presentation state machine.3
* Normal scene isolation and authenticated unlock never depend on Sigil. */4
struct 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
};12
static void lock_damage(struct output *o) {13
wlr_damage_ring_add_whole(&o->scene->damage_ring);14
wlr_output_schedule_frame(o->native);15
}16
static 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);31
}32
static 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);43
}44
static 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);57
}58
static 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;63
}64
static 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);88
}89
static 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;97
}98
static 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
}107
}108
static 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
}117
}118
static 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);133
}134
static 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);142
}143
static 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);152
}153
static 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);167
}168
static 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);188
}189
static 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);199
}200
static 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
}210
}211
static 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);229
}230
static 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;238
}