From e4dbafe4d84c8666a2f658fd195a47d13ae42378 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 18 May 2018 19:13:08 +0100 Subject: [PATCH 1/4] Fix swaylock crashing when unplugging output --- include/swaylock/swaylock.h | 1 + swaylock/main.c | 30 +++++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index 07b908d7..a82d6b86 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -48,6 +48,7 @@ struct swaylock_surface { cairo_surface_t *image; struct swaylock_state *state; struct wl_output *output; + uint32_t output_global_name; struct wl_surface *surface; struct zwlr_layer_surface_v1 *layer_surface; struct pool_buffer buffers[2]; diff --git a/swaylock/main.c b/swaylock/main.c index 200c1b5f..08a8691e 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -61,6 +61,20 @@ static void daemonize() { } } +static void destroy_surface(struct swaylock_surface *surface) { + wl_list_remove(&surface->link); + if (surface->layer_surface != NULL) { + zwlr_layer_surface_v1_destroy(surface->layer_surface); + } + if (surface->surface != NULL) { + wl_surface_destroy(surface->surface); + } + destroy_buffer(&surface->buffers[0]); + destroy_buffer(&surface->buffers[1]); + wl_output_destroy(surface->output); + free(surface); +} + static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *layer_surface, uint32_t serial, uint32_t width, uint32_t height) { @@ -74,9 +88,7 @@ static void layer_surface_configure(void *data, static void layer_surface_closed(void *data, struct zwlr_layer_surface_v1 *layer_surface) { struct swaylock_surface *surface = data; - zwlr_layer_surface_v1_destroy(surface->layer_surface); - wl_surface_destroy(surface->surface); - surface->state->run_display = false; + destroy_surface(surface); } static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { @@ -139,6 +151,7 @@ static void handle_global(void *data, struct wl_registry *registry, surface->state = state; surface->output = wl_registry_bind(registry, name, &wl_output_interface, 3); + surface->output_global_name = name; wl_output_add_listener(surface->output, &output_listener, surface); wl_list_insert(&state->surfaces, &surface->link); } @@ -146,7 +159,14 @@ static void handle_global(void *data, struct wl_registry *registry, static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { - // who cares + struct swaylock_state *state = data; + struct swaylock_surface *surface; + wl_list_for_each(surface, &state->surfaces, link) { + if (surface->output_global_name == name) { + destroy_surface(surface); + break; + } + } } static const struct wl_registry_listener registry_listener = { @@ -180,7 +200,7 @@ int main(int argc, char **argv) { " -v, --version Show the version number and quit.\n" " -i, --image [:] Display the given image.\n" " -u, --no-unlock-indicator Disable the unlock indicator.\n" - " -f, --daemonize Detach from the controlling terminal.\n" + " -f, --daemonize Detach from the controlling terminal.\n" " --socket Use the specified socket.\n"; struct swaylock_args args = { From b7ab7c0e66433aacaaccce08d6e40304e6f6593c Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 18 May 2018 21:57:58 +0100 Subject: [PATCH 2/4] Fix output hotplugging --- include/swaylock/swaylock.h | 1 + swaylock/main.c | 73 +++++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index a82d6b86..56ec0afb 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -38,6 +38,7 @@ struct swaylock_state { struct wl_shm *shm; struct wl_list surfaces; struct swaylock_args args; + cairo_surface_t *background_image; struct swaylock_password password; struct swaylock_xkb xkb; enum auth_state auth_state; diff --git a/swaylock/main.c b/swaylock/main.c index 08a8691e..9da99f97 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -75,6 +75,33 @@ static void destroy_surface(struct swaylock_surface *surface) { free(surface); } +static const struct zwlr_layer_surface_v1_listener layer_surface_listener; + +static void create_layer_surface(struct swaylock_surface *surface) { + struct swaylock_state *state = surface->state; + + surface->surface = wl_compositor_create_surface(state->compositor); + assert(surface->surface); + + surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + state->layer_shell, surface->surface, surface->output, + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "lockscreen"); + assert(surface->layer_surface); + + zwlr_layer_surface_v1_set_size(surface->layer_surface, 0, 0); + zwlr_layer_surface_v1_set_anchor(surface->layer_surface, + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); + zwlr_layer_surface_v1_set_exclusive_zone(surface->layer_surface, -1); + zwlr_layer_surface_v1_set_keyboard_interactivity( + surface->layer_surface, true); + zwlr_layer_surface_v1_add_listener(surface->layer_surface, + &layer_surface_listener, surface); + wl_surface_commit(surface->surface); +} + static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *layer_surface, uint32_t serial, uint32_t width, uint32_t height) { @@ -152,8 +179,14 @@ static void handle_global(void *data, struct wl_registry *registry, surface->output = wl_registry_bind(registry, name, &wl_output_interface, 3); surface->output_global_name = name; + surface->image = state->background_image; wl_output_add_listener(surface->output, &output_listener, surface); wl_list_insert(&state->surfaces, &surface->link); + + if (state->run_display) { + create_layer_surface(surface); + wl_display_roundtrip(state->display); + } } } @@ -190,7 +223,7 @@ int main(int argc, char **argv) { {0, 0, 0, 0} }; - const char *usage = + const char usage[] = "Usage: swaylock [options...]\n" "\n" " -h, --help Show help message and quit.\n" @@ -203,13 +236,12 @@ int main(int argc, char **argv) { " -f, --daemonize Detach from the controlling terminal.\n" " --socket Use the specified socket.\n"; - struct swaylock_args args = { + state.args = (struct swaylock_args){ .mode = BACKGROUND_MODE_SOLID_COLOR, .color = 0xFFFFFFFF, .show_indicator = true, }; - cairo_surface_t *background_image = NULL; - state.args = args; + wlr_log_init(L_DEBUG, NULL); int c; @@ -227,8 +259,8 @@ int main(int argc, char **argv) { } case 'i': // TODO: Multiple background images (bleh) - background_image = load_background_image(optarg); - if (!background_image) { + state.background_image = load_background_image(optarg); + if (!state.background_image) { return 1; } state.args.mode = BACKGROUND_MODE_FILL; @@ -288,34 +320,13 @@ int main(int argc, char **argv) { return 0; } + zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); + struct swaylock_surface *surface; wl_list_for_each(surface, &state.surfaces, link) { - surface->image = background_image; - - surface->surface = wl_compositor_create_surface(state.compositor); - assert(surface->surface); - - surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface( - state.layer_shell, surface->surface, surface->output, - ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "lockscreen"); - assert(surface->layer_surface); - - zwlr_layer_surface_v1_set_size(surface->layer_surface, 0, 0); - zwlr_layer_surface_v1_set_anchor(surface->layer_surface, - ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | - ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | - ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | - ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); - zwlr_layer_surface_v1_set_exclusive_zone(surface->layer_surface, -1); - zwlr_layer_surface_v1_set_keyboard_interactivity( - surface->layer_surface, true); - zwlr_layer_surface_v1_add_listener(surface->layer_surface, - &layer_surface_listener, surface); - wl_surface_commit(surface->surface); - wl_display_roundtrip(state.display); + create_layer_surface(surface); } - - zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); + wl_display_roundtrip(state.display); state.run_display = true; while (wl_display_dispatch(state.display) != -1 && state.run_display) { From 32f8ade7ab6228835144b519d927fd1eeaa2333a Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 23 May 2018 22:55:57 +0100 Subject: [PATCH 3/4] swaylock: don't try to render unconfigured surfaces --- swaylock/render.c | 3 +++ 1 file changed, 3 insertions(+) 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) { int buffer_width = surface->width * surface->scale; int buffer_height = surface->height * surface->scale; + if (buffer_width == 0 || buffer_height == 0) { + return; // not yet configured + } surface->current_buffer = get_next_buffer(state->shm, surface->buffers, buffer_width, buffer_height); From df61bfbb57ac9f7054dd6fe1c1e9398f0545d76b Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 23 May 2018 22:58:39 +0100 Subject: [PATCH 4/4] swaylock: remove unused field --- include/swaylock/swaylock.h | 1 - swaylock/main.c | 1 - 2 files changed, 2 deletions(-) diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index 27db67cd..dae823b8 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -39,7 +39,6 @@ struct swaylock_state { struct wl_list surfaces; struct wl_list images; struct swaylock_args args; - cairo_surface_t *background_image; struct swaylock_password password; struct swaylock_xkb xkb; enum auth_state auth_state; diff --git a/swaylock/main.c b/swaylock/main.c index 79c06285..f89f2849 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -226,7 +226,6 @@ static void handle_global(void *data, struct wl_registry *registry, surface->output = wl_registry_bind(registry, name, &wl_output_interface, 3); surface->output_global_name = name; - surface->image = state->background_image; wl_output_add_listener(surface->output, &_wl_output_listener, surface); wl_list_insert(&state->surfaces, &surface->link);