diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index e161ada9..dae823b8 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -10,13 +10,13 @@ #include "wlr-layer-shell-unstable-v1-client-protocol.h" enum auth_state { - AUTH_STATE_IDLE, - AUTH_STATE_CLEAR, - AUTH_STATE_INPUT, - AUTH_STATE_INPUT_NOP, - AUTH_STATE_BACKSPACE, - AUTH_STATE_VALIDATING, - AUTH_STATE_INVALID, + AUTH_STATE_IDLE, + AUTH_STATE_CLEAR, + AUTH_STATE_INPUT, + AUTH_STATE_INPUT_NOP, + AUTH_STATE_BACKSPACE, + AUTH_STATE_VALIDATING, + AUTH_STATE_INVALID, }; struct swaylock_args { @@ -50,6 +50,7 @@ struct swaylock_surface { cairo_surface_t *image; struct swaylock_state *state; struct wl_output *output; + uint32_t output_global_name; struct zxdg_output_v1 *xdg_output; struct wl_surface *surface; struct zwlr_layer_surface_v1 *layer_surface; 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() { } } +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 const struct zwlr_layer_surface_v1_listener layer_surface_listener; + +static cairo_surface_t *select_image(struct swaylock_state *state, + struct swaylock_surface *surface); + +static void create_layer_surface(struct swaylock_surface *surface) { + struct swaylock_state *state = surface->state; + + surface->image = select_image(state, surface); + + 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) { @@ -77,9 +123,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 = { @@ -181,14 +225,27 @@ 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, &_wl_output_listener, surface); wl_list_insert(&state->surfaces, &surface->link); + + if (state->run_display) { + create_layer_surface(surface); + wl_display_roundtrip(state->display); + } } } 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 = { @@ -276,7 +333,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" @@ -288,13 +345,13 @@ int main(int argc, char **argv) { " -u, --no-unlock-indicator Disable the unlock indicator.\n" " -f, --daemonize Detach from the controlling terminal.\n"; - struct swaylock_args args = { + state.args = (struct swaylock_args){ .mode = BACKGROUND_MODE_SOLID_COLOR, .color = 0xFFFFFFFF, .show_indicator = true, }; - state.args = args; wl_list_init(&state.images); + wlr_log_init(L_DEBUG, NULL); int c; @@ -369,6 +426,8 @@ int main(int argc, char **argv) { return 0; } + zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); + if (state.zxdg_output_manager) { struct swaylock_surface *surface; wl_list_for_each(surface, &state.surfaces, link) { @@ -385,33 +444,9 @@ int main(int argc, char **argv) { struct swaylock_surface *surface; wl_list_for_each(surface, &state.surfaces, link) { - surface->image = select_image(&state, surface); - - 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); - state.run_display = true; while (wl_display_dispatch(state.display) != -1 && state.run_display) { // 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) { 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);