diff options
author | 2018-05-23 18:11:24 -0400 | |
---|---|---|
committer | 2018-05-23 18:11:24 -0400 | |
commit | 50d1b80d507096ad55e9e2fbb56b31b09b6671dc (patch) | |
tree | 3dc61f6ba02d754e71df1499c406f8586b853f76 /swaylock | |
parent | Merge pull request #2022 from RedSoxFan/ipc-get-marks (diff) | |
parent | swaylock: remove unused field (diff) | |
download | sway-50d1b80d507096ad55e9e2fbb56b31b09b6671dc.tar.gz sway-50d1b80d507096ad55e9e2fbb56b31b09b6671dc.tar.zst sway-50d1b80d507096ad55e9e2fbb56b31b09b6671dc.zip |
Merge pull request #2003 from emersion/fix-swaylock-hotplugging
Fix swaylock crashing when plugging/unplugging output
Diffstat (limited to 'swaylock')
-rw-r--r-- | swaylock/main.c | 99 | ||||
-rw-r--r-- | swaylock/render.c | 3 |
2 files changed, 70 insertions, 32 deletions
diff --git a/swaylock/main.c b/swaylock/main.c index 11b5e8c8..f89f2849 100644 --- a/swaylock/main.c +++ b/swaylock/main.c | |||
@@ -64,6 +64,52 @@ static void daemonize() { | |||
64 | } | 64 | } |
65 | } | 65 | } |
66 | 66 | ||
67 | static void destroy_surface(struct swaylock_surface *surface) { | ||
68 | wl_list_remove(&surface->link); | ||
69 | if (surface->layer_surface != NULL) { | ||
70 | zwlr_layer_surface_v1_destroy(surface->layer_surface); | ||
71 | } | ||
72 | if (surface->surface != NULL) { | ||
73 | wl_surface_destroy(surface->surface); | ||
74 | } | ||
75 | destroy_buffer(&surface->buffers[0]); | ||
76 | destroy_buffer(&surface->buffers[1]); | ||
77 | wl_output_destroy(surface->output); | ||
78 | free(surface); | ||
79 | } | ||
80 | |||
81 | static const struct zwlr_layer_surface_v1_listener layer_surface_listener; | ||
82 | |||
83 | static cairo_surface_t *select_image(struct swaylock_state *state, | ||
84 | struct swaylock_surface *surface); | ||
85 | |||
86 | static void create_layer_surface(struct swaylock_surface *surface) { | ||
87 | struct swaylock_state *state = surface->state; | ||
88 | |||
89 | surface->image = select_image(state, surface); | ||
90 | |||
91 | surface->surface = wl_compositor_create_surface(state->compositor); | ||
92 | assert(surface->surface); | ||
93 | |||
94 | surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface( | ||
95 | state->layer_shell, surface->surface, surface->output, | ||
96 | ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "lockscreen"); | ||
97 | assert(surface->layer_surface); | ||
98 | |||
99 | zwlr_layer_surface_v1_set_size(surface->layer_surface, 0, 0); | ||
100 | zwlr_layer_surface_v1_set_anchor(surface->layer_surface, | ||
101 | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | | ||
102 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | | ||
103 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | | ||
104 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); | ||
105 | zwlr_layer_surface_v1_set_exclusive_zone(surface->layer_surface, -1); | ||
106 | zwlr_layer_surface_v1_set_keyboard_interactivity( | ||
107 | surface->layer_surface, true); | ||
108 | zwlr_layer_surface_v1_add_listener(surface->layer_surface, | ||
109 | &layer_surface_listener, surface); | ||
110 | wl_surface_commit(surface->surface); | ||
111 | } | ||
112 | |||
67 | static void layer_surface_configure(void *data, | 113 | static void layer_surface_configure(void *data, |
68 | struct zwlr_layer_surface_v1 *layer_surface, | 114 | struct zwlr_layer_surface_v1 *layer_surface, |
69 | uint32_t serial, uint32_t width, uint32_t height) { | 115 | uint32_t serial, uint32_t width, uint32_t height) { |
@@ -77,9 +123,7 @@ static void layer_surface_configure(void *data, | |||
77 | static void layer_surface_closed(void *data, | 123 | static void layer_surface_closed(void *data, |
78 | struct zwlr_layer_surface_v1 *layer_surface) { | 124 | struct zwlr_layer_surface_v1 *layer_surface) { |
79 | struct swaylock_surface *surface = data; | 125 | struct swaylock_surface *surface = data; |
80 | zwlr_layer_surface_v1_destroy(surface->layer_surface); | 126 | destroy_surface(surface); |
81 | wl_surface_destroy(surface->surface); | ||
82 | surface->state->run_display = false; | ||
83 | } | 127 | } |
84 | 128 | ||
85 | static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { | 129 | static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { |
@@ -181,14 +225,27 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
181 | surface->state = state; | 225 | surface->state = state; |
182 | surface->output = wl_registry_bind(registry, name, | 226 | surface->output = wl_registry_bind(registry, name, |
183 | &wl_output_interface, 3); | 227 | &wl_output_interface, 3); |
228 | surface->output_global_name = name; | ||
184 | wl_output_add_listener(surface->output, &_wl_output_listener, surface); | 229 | wl_output_add_listener(surface->output, &_wl_output_listener, surface); |
185 | wl_list_insert(&state->surfaces, &surface->link); | 230 | wl_list_insert(&state->surfaces, &surface->link); |
231 | |||
232 | if (state->run_display) { | ||
233 | create_layer_surface(surface); | ||
234 | wl_display_roundtrip(state->display); | ||
235 | } | ||
186 | } | 236 | } |
187 | } | 237 | } |
188 | 238 | ||
189 | static void handle_global_remove(void *data, struct wl_registry *registry, | 239 | static void handle_global_remove(void *data, struct wl_registry *registry, |
190 | uint32_t name) { | 240 | uint32_t name) { |
191 | // who cares | 241 | struct swaylock_state *state = data; |
242 | struct swaylock_surface *surface; | ||
243 | wl_list_for_each(surface, &state->surfaces, link) { | ||
244 | if (surface->output_global_name == name) { | ||
245 | destroy_surface(surface); | ||
246 | break; | ||
247 | } | ||
248 | } | ||
192 | } | 249 | } |
193 | 250 | ||
194 | static const struct wl_registry_listener registry_listener = { | 251 | static const struct wl_registry_listener registry_listener = { |
@@ -276,7 +333,7 @@ int main(int argc, char **argv) { | |||
276 | {0, 0, 0, 0} | 333 | {0, 0, 0, 0} |
277 | }; | 334 | }; |
278 | 335 | ||
279 | const char *usage = | 336 | const char usage[] = |
280 | "Usage: swaylock [options...]\n" | 337 | "Usage: swaylock [options...]\n" |
281 | "\n" | 338 | "\n" |
282 | " -h, --help Show help message and quit.\n" | 339 | " -h, --help Show help message and quit.\n" |
@@ -288,13 +345,13 @@ int main(int argc, char **argv) { | |||
288 | " -u, --no-unlock-indicator Disable the unlock indicator.\n" | 345 | " -u, --no-unlock-indicator Disable the unlock indicator.\n" |
289 | " -f, --daemonize Detach from the controlling terminal.\n"; | 346 | " -f, --daemonize Detach from the controlling terminal.\n"; |
290 | 347 | ||
291 | struct swaylock_args args = { | 348 | state.args = (struct swaylock_args){ |
292 | .mode = BACKGROUND_MODE_SOLID_COLOR, | 349 | .mode = BACKGROUND_MODE_SOLID_COLOR, |
293 | .color = 0xFFFFFFFF, | 350 | .color = 0xFFFFFFFF, |
294 | .show_indicator = true, | 351 | .show_indicator = true, |
295 | }; | 352 | }; |
296 | state.args = args; | ||
297 | wl_list_init(&state.images); | 353 | wl_list_init(&state.images); |
354 | |||
298 | wlr_log_init(L_DEBUG, NULL); | 355 | wlr_log_init(L_DEBUG, NULL); |
299 | 356 | ||
300 | int c; | 357 | int c; |
@@ -369,6 +426,8 @@ int main(int argc, char **argv) { | |||
369 | return 0; | 426 | return 0; |
370 | } | 427 | } |
371 | 428 | ||
429 | zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); | ||
430 | |||
372 | if (state.zxdg_output_manager) { | 431 | if (state.zxdg_output_manager) { |
373 | struct swaylock_surface *surface; | 432 | struct swaylock_surface *surface; |
374 | wl_list_for_each(surface, &state.surfaces, link) { | 433 | wl_list_for_each(surface, &state.surfaces, link) { |
@@ -385,33 +444,9 @@ int main(int argc, char **argv) { | |||
385 | 444 | ||
386 | struct swaylock_surface *surface; | 445 | struct swaylock_surface *surface; |
387 | wl_list_for_each(surface, &state.surfaces, link) { | 446 | wl_list_for_each(surface, &state.surfaces, link) { |
388 | surface->image = select_image(&state, surface); | 447 | create_layer_surface(surface); |
389 | |||
390 | surface->surface = wl_compositor_create_surface(state.compositor); | ||
391 | assert(surface->surface); | ||
392 | |||
393 | surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface( | ||
394 | state.layer_shell, surface->surface, surface->output, | ||
395 | ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "lockscreen"); | ||
396 | assert(surface->layer_surface); | ||
397 | |||
398 | zwlr_layer_surface_v1_set_size(surface->layer_surface, 0, 0); | ||
399 | zwlr_layer_surface_v1_set_anchor(surface->layer_surface, | ||
400 | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | | ||
401 | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | | ||
402 | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | | ||
403 | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); | ||
404 | zwlr_layer_surface_v1_set_exclusive_zone(surface->layer_surface, -1); | ||
405 | zwlr_layer_surface_v1_set_keyboard_interactivity( | ||
406 | surface->layer_surface, true); | ||
407 | zwlr_layer_surface_v1_add_listener(surface->layer_surface, | ||
408 | &layer_surface_listener, surface); | ||
409 | wl_surface_commit(surface->surface); | ||
410 | wl_display_roundtrip(state.display); | ||
411 | } | 448 | } |
412 | 449 | ||
413 | zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); | ||
414 | |||
415 | state.run_display = true; | 450 | state.run_display = true; |
416 | while (wl_display_dispatch(state.display) != -1 && state.run_display) { | 451 | while (wl_display_dispatch(state.display) != -1 && state.run_display) { |
417 | // This space intentionally left blank | 452 | // This space intentionally left blank |
diff --git a/swaylock/render.c b/swaylock/render.c index cc40f4e9..05236dea 100644 --- a/swaylock/render.c +++ b/swaylock/render.c | |||
@@ -17,6 +17,9 @@ void render_frame(struct swaylock_surface *surface) { | |||
17 | 17 | ||
18 | int buffer_width = surface->width * surface->scale; | 18 | int buffer_width = surface->width * surface->scale; |
19 | int buffer_height = surface->height * surface->scale; | 19 | int buffer_height = surface->height * surface->scale; |
20 | if (buffer_width == 0 || buffer_height == 0) { | ||
21 | return; // not yet configured | ||
22 | } | ||
20 | 23 | ||
21 | surface->current_buffer = get_next_buffer(state->shm, | 24 | surface->current_buffer = get_next_buffer(state->shm, |
22 | surface->buffers, buffer_width, buffer_height); | 25 | surface->buffers, buffer_width, buffer_height); |