diff options
-rw-r--r-- | include/sway/input/seat.h | 4 | ||||
-rw-r--r-- | include/sway/server.h | 15 | ||||
-rw-r--r-- | sway/desktop/output.c | 19 | ||||
-rw-r--r-- | sway/desktop/render.c | 35 | ||||
-rw-r--r-- | sway/input/input-manager.c | 4 | ||||
-rw-r--r-- | sway/input/keyboard.c | 3 | ||||
-rw-r--r-- | sway/input/seat.c | 27 | ||||
-rw-r--r-- | sway/input/switch.c | 3 | ||||
-rw-r--r-- | sway/lock.c | 184 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/server.c | 2 |
11 files changed, 290 insertions, 7 deletions
diff --git a/include/sway/input/seat.h b/include/sway/input/seat.h index 50c4be9b..47726159 100644 --- a/include/sway/input/seat.h +++ b/include/sway/input/seat.h | |||
@@ -185,6 +185,10 @@ struct sway_workspace *seat_get_last_known_workspace(struct sway_seat *seat); | |||
185 | 185 | ||
186 | struct sway_container *seat_get_focused_container(struct sway_seat *seat); | 186 | struct sway_container *seat_get_focused_container(struct sway_seat *seat); |
187 | 187 | ||
188 | // Force focus to a particular surface that is not part of the workspace | ||
189 | // hierarchy (used for lockscreen) | ||
190 | void sway_force_focus(struct wlr_surface *surface); | ||
191 | |||
188 | /** | 192 | /** |
189 | * Return the last container to be focused for the seat (or the most recently | 193 | * Return the last container to be focused for the seat (or the most recently |
190 | * opened if no container has received focused) that is a child of the given | 194 | * opened if no container has received focused) that is a child of the given |
diff --git a/include/sway/server.h b/include/sway/server.h index 0bd860b2..d8ccd64f 100644 --- a/include/sway/server.h +++ b/include/sway/server.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <wlr/types/wlr_output_power_management_v1.h> | 16 | #include <wlr/types/wlr_output_power_management_v1.h> |
17 | #include <wlr/types/wlr_presentation_time.h> | 17 | #include <wlr/types/wlr_presentation_time.h> |
18 | #include <wlr/types/wlr_relative_pointer_v1.h> | 18 | #include <wlr/types/wlr_relative_pointer_v1.h> |
19 | #include <wlr/types/wlr_session_lock_v1.h> | ||
19 | #include <wlr/types/wlr_server_decoration.h> | 20 | #include <wlr/types/wlr_server_decoration.h> |
20 | #include <wlr/types/wlr_text_input_v3.h> | 21 | #include <wlr/types/wlr_text_input_v3.h> |
21 | #include <wlr/types/wlr_xdg_shell.h> | 22 | #include <wlr/types/wlr_xdg_shell.h> |
@@ -89,6 +90,19 @@ struct sway_server { | |||
89 | struct wl_listener output_manager_apply; | 90 | struct wl_listener output_manager_apply; |
90 | struct wl_listener output_manager_test; | 91 | struct wl_listener output_manager_test; |
91 | 92 | ||
93 | struct { | ||
94 | bool locked; | ||
95 | struct wlr_session_lock_manager_v1 *manager; | ||
96 | |||
97 | struct wlr_session_lock_v1 *lock; | ||
98 | struct wl_listener lock_new_surface; | ||
99 | struct wl_listener lock_unlock; | ||
100 | struct wl_listener lock_destroy; | ||
101 | |||
102 | struct wl_listener new_lock; | ||
103 | struct wl_listener manager_destroy; | ||
104 | } session_lock; | ||
105 | |||
92 | struct wlr_output_power_manager_v1 *output_power_manager_v1; | 106 | struct wlr_output_power_manager_v1 *output_power_manager_v1; |
93 | struct wl_listener output_power_manager_set_mode; | 107 | struct wl_listener output_power_manager_set_mode; |
94 | struct wlr_input_method_manager_v2 *input_method; | 108 | struct wlr_input_method_manager_v2 *input_method; |
@@ -148,6 +162,7 @@ void handle_new_output(struct wl_listener *listener, void *data); | |||
148 | 162 | ||
149 | void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data); | 163 | void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data); |
150 | void handle_layer_shell_surface(struct wl_listener *listener, void *data); | 164 | void handle_layer_shell_surface(struct wl_listener *listener, void *data); |
165 | void sway_session_lock_init(void); | ||
151 | void handle_xdg_shell_surface(struct wl_listener *listener, void *data); | 166 | void handle_xdg_shell_surface(struct wl_listener *listener, void *data); |
152 | #if HAVE_XWAYLAND | 167 | #if HAVE_XWAYLAND |
153 | void handle_xwayland_surface(struct wl_listener *listener, void *data); | 168 | void handle_xwayland_surface(struct wl_listener *listener, void *data); |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index dd2eaf08..18367a1c 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -275,6 +275,25 @@ static void for_each_surface_container_iterator(struct sway_container *con, | |||
275 | 275 | ||
276 | static void output_for_each_surface(struct sway_output *output, | 276 | static void output_for_each_surface(struct sway_output *output, |
277 | sway_surface_iterator_func_t iterator, void *user_data) { | 277 | sway_surface_iterator_func_t iterator, void *user_data) { |
278 | if (server.session_lock.locked) { | ||
279 | if (server.session_lock.lock == NULL) { | ||
280 | return; | ||
281 | } | ||
282 | struct wlr_session_lock_surface_v1 *lock_surface; | ||
283 | wl_list_for_each(lock_surface, &server.session_lock.lock->surfaces, link) { | ||
284 | if (lock_surface->output != output->wlr_output) { | ||
285 | continue; | ||
286 | } | ||
287 | if (!lock_surface->mapped) { | ||
288 | continue; | ||
289 | } | ||
290 | |||
291 | output_surface_for_each_surface(output, lock_surface->surface, | ||
292 | 0.0, 0.0, iterator, user_data); | ||
293 | } | ||
294 | return; | ||
295 | } | ||
296 | |||
278 | if (output_has_opaque_overlay_layer_surface(output)) { | 297 | if (output_has_opaque_overlay_layer_surface(output)) { |
279 | goto overlay; | 298 | goto overlay; |
280 | } | 299 | } |
diff --git a/sway/desktop/render.c b/sway/desktop/render.c index 02397c05..ed9ad490 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c | |||
@@ -1056,6 +1056,41 @@ void output_render(struct sway_output *output, struct timespec *when, | |||
1056 | wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); | 1056 | wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); |
1057 | } | 1057 | } |
1058 | 1058 | ||
1059 | if (server.session_lock.locked) { | ||
1060 | float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; | ||
1061 | if (server.session_lock.lock == NULL) { | ||
1062 | // abandoned lock -> red BG | ||
1063 | clear_color[0] = 1.f; | ||
1064 | } | ||
1065 | int nrects; | ||
1066 | pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); | ||
1067 | for (int i = 0; i < nrects; ++i) { | ||
1068 | scissor_output(wlr_output, &rects[i]); | ||
1069 | wlr_renderer_clear(renderer, clear_color); | ||
1070 | } | ||
1071 | |||
1072 | if (server.session_lock.lock != NULL) { | ||
1073 | struct render_data data = { | ||
1074 | .damage = damage, | ||
1075 | .alpha = 1.0f, | ||
1076 | }; | ||
1077 | |||
1078 | struct wlr_session_lock_surface_v1 *lock_surface; | ||
1079 | wl_list_for_each(lock_surface, &server.session_lock.lock->surfaces, link) { | ||
1080 | if (lock_surface->output != wlr_output) { | ||
1081 | continue; | ||
1082 | } | ||
1083 | if (!lock_surface->mapped) { | ||
1084 | continue; | ||
1085 | } | ||
1086 | |||
1087 | output_surface_for_each_surface(output, lock_surface->surface, | ||
1088 | 0.0, 0.0, render_surface_iterator, &data); | ||
1089 | } | ||
1090 | } | ||
1091 | goto renderer_end; | ||
1092 | } | ||
1093 | |||
1059 | if (output_has_opaque_overlay_layer_surface(output)) { | 1094 | if (output_has_opaque_overlay_layer_surface(output)) { |
1060 | goto render_overlay; | 1095 | goto render_overlay; |
1061 | } | 1096 | } |
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 8538d97c..4a0bce0e 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -289,6 +289,10 @@ static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) | |||
289 | struct sway_input_manager *input_manager = wl_container_of( | 289 | struct sway_input_manager *input_manager = wl_container_of( |
290 | listener, input_manager, inhibit_deactivate); | 290 | listener, input_manager, inhibit_deactivate); |
291 | struct sway_seat *seat; | 291 | struct sway_seat *seat; |
292 | if (server.session_lock.locked) { | ||
293 | // Don't deactivate the grab of a screenlocker | ||
294 | return; | ||
295 | } | ||
292 | wl_list_for_each(seat, &input_manager->seats, link) { | 296 | wl_list_for_each(seat, &input_manager->seats, link) { |
293 | seat_set_exclusive_client(seat, NULL); | 297 | seat_set_exclusive_client(seat, NULL); |
294 | struct sway_node *previous = seat_get_focus(seat); | 298 | struct sway_node *previous = seat_get_focus(seat); |
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 1aa30655..8f18b8ba 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c | |||
@@ -409,7 +409,8 @@ static void handle_key_event(struct sway_keyboard *keyboard, | |||
409 | char *device_identifier = input_device_get_identifier(wlr_device); | 409 | char *device_identifier = input_device_get_identifier(wlr_device); |
410 | bool exact_identifier = wlr_device->keyboard->group != NULL; | 410 | bool exact_identifier = wlr_device->keyboard->group != NULL; |
411 | seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD); | 411 | seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD); |
412 | bool input_inhibited = seat->exclusive_client != NULL; | 412 | bool input_inhibited = seat->exclusive_client != NULL || |
413 | server.session_lock.locked; | ||
413 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = | 414 | struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = |
414 | keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); | 415 | keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); |
415 | bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; | 416 | bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; |
diff --git a/sway/input/seat.c b/sway/input/seat.c index 85179dc7..fa83050b 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -212,6 +212,15 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) { | |||
212 | } | 212 | } |
213 | } | 213 | } |
214 | 214 | ||
215 | void sway_force_focus(struct wlr_surface *surface) { | ||
216 | struct sway_seat *seat; | ||
217 | wl_list_for_each(seat, &server.input->seats, link) { | ||
218 | seat_keyboard_notify_enter(seat, surface); | ||
219 | seat_tablet_pads_notify_enter(seat, surface); | ||
220 | sway_input_method_relay_set_focus(&seat->im_relay, surface); | ||
221 | } | ||
222 | } | ||
223 | |||
215 | void seat_for_each_node(struct sway_seat *seat, | 224 | void seat_for_each_node(struct sway_seat *seat, |
216 | void (*f)(struct sway_node *node, void *data), void *data) { | 225 | void (*f)(struct sway_node *node, void *data), void *data) { |
217 | struct sway_seat_node *current = NULL; | 226 | struct sway_seat_node *current = NULL; |
@@ -814,11 +823,13 @@ static void seat_configure_keyboard(struct sway_seat *seat, | |||
814 | sway_keyboard_configure(seat_device->keyboard); | 823 | sway_keyboard_configure(seat_device->keyboard); |
815 | wlr_seat_set_keyboard(seat->wlr_seat, | 824 | wlr_seat_set_keyboard(seat->wlr_seat, |
816 | seat_device->input_device->wlr_device->keyboard); | 825 | seat_device->input_device->wlr_device->keyboard); |
817 | struct sway_node *focus = seat_get_focus(seat); | 826 | |
818 | if (focus && node_is_view(focus)) { | 827 | // force notify reenter to pick up the new configuration. This reuses |
819 | // force notify reenter to pick up the new configuration | 828 | // the current focused surface to avoid breaking input grabs. |
829 | struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface; | ||
830 | if (surface) { | ||
820 | wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); | 831 | wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); |
821 | seat_keyboard_notify_enter(seat, focus->sway_container->view->surface); | 832 | seat_keyboard_notify_enter(seat, surface); |
822 | } | 833 | } |
823 | } | 834 | } |
824 | 835 | ||
@@ -1070,7 +1081,8 @@ void seat_configure_xcursor(struct sway_seat *seat) { | |||
1070 | bool seat_is_input_allowed(struct sway_seat *seat, | 1081 | bool seat_is_input_allowed(struct sway_seat *seat, |
1071 | struct wlr_surface *surface) { | 1082 | struct wlr_surface *surface) { |
1072 | struct wl_client *client = wl_resource_get_client(surface->resource); | 1083 | struct wl_client *client = wl_resource_get_client(surface->resource); |
1073 | return !seat->exclusive_client || seat->exclusive_client == client; | 1084 | return seat->exclusive_client == client || |
1085 | (seat->exclusive_client == NULL && !server.session_lock.locked); | ||
1074 | } | 1086 | } |
1075 | 1087 | ||
1076 | static void send_unfocus(struct sway_container *con, void *data) { | 1088 | static void send_unfocus(struct sway_container *con, void *data) { |
@@ -1171,6 +1183,11 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { | |||
1171 | return; | 1183 | return; |
1172 | } | 1184 | } |
1173 | 1185 | ||
1186 | // Deny setting focus when an input grab or lockscreen is active | ||
1187 | if (container && !seat_is_input_allowed(seat, container->view->surface)) { | ||
1188 | return; | ||
1189 | } | ||
1190 | |||
1174 | struct sway_output *new_output = | 1191 | struct sway_output *new_output = |
1175 | new_workspace ? new_workspace->output : NULL; | 1192 | new_workspace ? new_workspace->output : NULL; |
1176 | 1193 | ||
diff --git a/sway/input/switch.c b/sway/input/switch.c index af5a2385..ac4baece 100644 --- a/sway/input/switch.c +++ b/sway/input/switch.c | |||
@@ -34,7 +34,8 @@ static bool sway_switch_trigger_test(enum sway_switch_trigger trigger, | |||
34 | 34 | ||
35 | static void execute_binding(struct sway_switch *sway_switch) { | 35 | static void execute_binding(struct sway_switch *sway_switch) { |
36 | struct sway_seat* seat = sway_switch->seat_device->sway_seat; | 36 | struct sway_seat* seat = sway_switch->seat_device->sway_seat; |
37 | bool input_inhibited = seat->exclusive_client != NULL; | 37 | bool input_inhibited = seat->exclusive_client != NULL || |
38 | server.session_lock.locked; | ||
38 | 39 | ||
39 | list_t *bindings = config->current_mode->switch_bindings; | 40 | list_t *bindings = config->current_mode->switch_bindings; |
40 | struct sway_switch_binding *matched_binding = NULL; | 41 | struct sway_switch_binding *matched_binding = NULL; |
diff --git a/sway/lock.c b/sway/lock.c new file mode 100644 index 00000000..04f80079 --- /dev/null +++ b/sway/lock.c | |||
@@ -0,0 +1,184 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <assert.h> | ||
3 | #include "log.h" | ||
4 | #include "sway/input/keyboard.h" | ||
5 | #include "sway/input/seat.h" | ||
6 | #include "sway/output.h" | ||
7 | #include "sway/server.h" | ||
8 | |||
9 | struct sway_session_lock_surface { | ||
10 | struct wlr_session_lock_surface_v1 *lock_surface; | ||
11 | struct sway_output *output; | ||
12 | struct wlr_surface *surface; | ||
13 | struct wl_listener map; | ||
14 | struct wl_listener destroy; | ||
15 | struct wl_listener surface_commit; | ||
16 | struct wl_listener output_mode; | ||
17 | struct wl_listener output_commit; | ||
18 | }; | ||
19 | |||
20 | static void handle_surface_map(struct wl_listener *listener, void *data) { | ||
21 | struct sway_session_lock_surface *surf = wl_container_of(listener, surf, map); | ||
22 | sway_force_focus(surf->surface); | ||
23 | output_damage_whole(surf->output); | ||
24 | } | ||
25 | |||
26 | static void handle_surface_commit(struct wl_listener *listener, void *data) { | ||
27 | struct sway_session_lock_surface *surf = wl_container_of(listener, surf, surface_commit); | ||
28 | output_damage_surface(surf->output, 0, 0, surf->surface, false); | ||
29 | } | ||
30 | |||
31 | static void handle_output_mode(struct wl_listener *listener, void *data) { | ||
32 | struct sway_session_lock_surface *surf = wl_container_of(listener, surf, output_mode); | ||
33 | wlr_session_lock_surface_v1_configure(surf->lock_surface, | ||
34 | surf->output->width, surf->output->height); | ||
35 | } | ||
36 | |||
37 | static void handle_output_commit(struct wl_listener *listener, void *data) { | ||
38 | struct wlr_output_event_commit *event = data; | ||
39 | struct sway_session_lock_surface *surf = wl_container_of(listener, surf, output_commit); | ||
40 | if (event->committed & ( | ||
41 | WLR_OUTPUT_STATE_MODE | | ||
42 | WLR_OUTPUT_STATE_SCALE | | ||
43 | WLR_OUTPUT_STATE_TRANSFORM)) { | ||
44 | wlr_session_lock_surface_v1_configure(surf->lock_surface, | ||
45 | surf->output->width, surf->output->height); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | static void handle_surface_destroy(struct wl_listener *listener, void *data) { | ||
50 | struct sway_session_lock_surface *surf = wl_container_of(listener, surf, destroy); | ||
51 | wl_list_remove(&surf->map.link); | ||
52 | wl_list_remove(&surf->destroy.link); | ||
53 | wl_list_remove(&surf->surface_commit.link); | ||
54 | wl_list_remove(&surf->output_mode.link); | ||
55 | wl_list_remove(&surf->output_commit.link); | ||
56 | output_damage_whole(surf->output); | ||
57 | free(surf); | ||
58 | } | ||
59 | |||
60 | static void handle_new_surface(struct wl_listener *listener, void *data) { | ||
61 | struct wlr_session_lock_surface_v1 *lock_surface = data; | ||
62 | struct sway_session_lock_surface *surf = calloc(1, sizeof(*surf)); | ||
63 | if (surf == NULL) { | ||
64 | return; | ||
65 | } | ||
66 | |||
67 | sway_log(SWAY_DEBUG, "new lock layer surface"); | ||
68 | |||
69 | struct sway_output *output = lock_surface->output->data; | ||
70 | wlr_session_lock_surface_v1_configure(lock_surface, output->width, output->height); | ||
71 | |||
72 | surf->lock_surface = lock_surface; | ||
73 | surf->surface = lock_surface->surface; | ||
74 | surf->output = output; | ||
75 | surf->map.notify = handle_surface_map; | ||
76 | wl_signal_add(&lock_surface->events.map, &surf->map); | ||
77 | surf->destroy.notify = handle_surface_destroy; | ||
78 | wl_signal_add(&lock_surface->events.destroy, &surf->destroy); | ||
79 | surf->surface_commit.notify = handle_surface_commit; | ||
80 | wl_signal_add(&surf->surface->events.commit, &surf->surface_commit); | ||
81 | surf->output_mode.notify = handle_output_mode; | ||
82 | wl_signal_add(&output->wlr_output->events.mode, &surf->output_mode); | ||
83 | surf->output_commit.notify = handle_output_commit; | ||
84 | wl_signal_add(&output->wlr_output->events.commit, &surf->output_commit); | ||
85 | } | ||
86 | |||
87 | static void handle_unlock(struct wl_listener *listener, void *data) { | ||
88 | sway_log(SWAY_DEBUG, "session unlocked"); | ||
89 | server.session_lock.locked = false; | ||
90 | server.session_lock.lock = NULL; | ||
91 | |||
92 | wl_list_remove(&server.session_lock.lock_new_surface.link); | ||
93 | wl_list_remove(&server.session_lock.lock_unlock.link); | ||
94 | wl_list_remove(&server.session_lock.lock_destroy.link); | ||
95 | |||
96 | struct sway_seat *seat; | ||
97 | wl_list_for_each(seat, &server.input->seats, link) { | ||
98 | seat_set_exclusive_client(seat, NULL); | ||
99 | // copied from seat_set_focus_layer -- deduplicate? | ||
100 | struct sway_node *previous = seat_get_focus_inactive(seat, &root->node); | ||
101 | if (previous) { | ||
102 | // Hack to get seat to re-focus the return value of get_focus | ||
103 | seat_set_focus(seat, NULL); | ||
104 | seat_set_focus(seat, previous); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | // redraw everything | ||
109 | for (int i = 0; i < root->outputs->length; ++i) { | ||
110 | struct sway_output *output = root->outputs->items[i]; | ||
111 | output_damage_whole(output); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static void handle_abandon(struct wl_listener *listener, void *data) { | ||
116 | sway_log(SWAY_INFO, "session lock abandoned"); | ||
117 | server.session_lock.lock = NULL; | ||
118 | |||
119 | wl_list_remove(&server.session_lock.lock_new_surface.link); | ||
120 | wl_list_remove(&server.session_lock.lock_unlock.link); | ||
121 | wl_list_remove(&server.session_lock.lock_destroy.link); | ||
122 | |||
123 | struct sway_seat *seat; | ||
124 | wl_list_for_each(seat, &server.input->seats, link) { | ||
125 | seat->exclusive_client = NULL; | ||
126 | } | ||
127 | |||
128 | // redraw everything | ||
129 | for (int i = 0; i < root->outputs->length; ++i) { | ||
130 | struct sway_output *output = root->outputs->items[i]; | ||
131 | output_damage_whole(output); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void handle_session_lock(struct wl_listener *listener, void *data) { | ||
136 | struct wlr_session_lock_v1 *lock = data; | ||
137 | struct wl_client *client = wl_resource_get_client(lock->resource); | ||
138 | |||
139 | if (server.session_lock.lock) { | ||
140 | wlr_session_lock_v1_destroy(lock); | ||
141 | return; | ||
142 | } | ||
143 | |||
144 | sway_log(SWAY_DEBUG, "session locked"); | ||
145 | server.session_lock.locked = true; | ||
146 | server.session_lock.lock = lock; | ||
147 | |||
148 | struct sway_seat *seat; | ||
149 | wl_list_for_each(seat, &server.input->seats, link) { | ||
150 | seat_set_exclusive_client(seat, client); | ||
151 | } | ||
152 | |||
153 | wl_signal_add(&lock->events.new_surface, &server.session_lock.lock_new_surface); | ||
154 | wl_signal_add(&lock->events.unlock, &server.session_lock.lock_unlock); | ||
155 | wl_signal_add(&lock->events.destroy, &server.session_lock.lock_destroy); | ||
156 | |||
157 | wlr_session_lock_v1_send_locked(lock); | ||
158 | |||
159 | // redraw everything | ||
160 | for (int i = 0; i < root->outputs->length; ++i) { | ||
161 | struct sway_output *output = root->outputs->items[i]; | ||
162 | output_damage_whole(output); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static void handle_session_lock_destroy(struct wl_listener *listener, void *data) { | ||
167 | assert(server.session_lock.lock == NULL); | ||
168 | wl_list_remove(&server.session_lock.new_lock.link); | ||
169 | wl_list_remove(&server.session_lock.manager_destroy.link); | ||
170 | } | ||
171 | |||
172 | void sway_session_lock_init(void) { | ||
173 | server.session_lock.manager = wlr_session_lock_manager_v1_create(server.wl_display); | ||
174 | |||
175 | server.session_lock.lock_new_surface.notify = handle_new_surface; | ||
176 | server.session_lock.lock_unlock.notify = handle_unlock; | ||
177 | server.session_lock.lock_destroy.notify = handle_abandon; | ||
178 | server.session_lock.new_lock.notify = handle_session_lock; | ||
179 | server.session_lock.manager_destroy.notify = handle_session_lock_destroy; | ||
180 | wl_signal_add(&server.session_lock.manager->events.new_lock, | ||
181 | &server.session_lock.new_lock); | ||
182 | wl_signal_add(&server.session_lock.manager->events.destroy, | ||
183 | &server.session_lock.manager_destroy); | ||
184 | } | ||
diff --git a/sway/meson.build b/sway/meson.build index 4ccb2ba1..0ad783e3 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -5,6 +5,7 @@ sway_sources = files( | |||
5 | 'decoration.c', | 5 | 'decoration.c', |
6 | 'ipc-json.c', | 6 | 'ipc-json.c', |
7 | 'ipc-server.c', | 7 | 'ipc-server.c', |
8 | 'lock.c', | ||
8 | 'main.c', | 9 | 'main.c', |
9 | 'server.c', | 10 | 'server.c', |
10 | 'swaynag.c', | 11 | 'swaynag.c', |
diff --git a/sway/server.c b/sway/server.c index 9bfcffaf..0f0c76a8 100644 --- a/sway/server.c +++ b/sway/server.c | |||
@@ -183,6 +183,8 @@ bool server_init(struct sway_server *server) { | |||
183 | server->foreign_toplevel_manager = | 183 | server->foreign_toplevel_manager = |
184 | wlr_foreign_toplevel_manager_v1_create(server->wl_display); | 184 | wlr_foreign_toplevel_manager_v1_create(server->wl_display); |
185 | 185 | ||
186 | sway_session_lock_init(); | ||
187 | |||
186 | server->drm_lease_manager= | 188 | server->drm_lease_manager= |
187 | wlr_drm_lease_v1_manager_create(server->wl_display, server->backend); | 189 | wlr_drm_lease_v1_manager_create(server->wl_display, server->backend); |
188 | if (server->drm_lease_manager) { | 190 | if (server->drm_lease_manager) { |