Merge pull request #2003 from emersion/fix-swaylock-hotplugging

Fix swaylock crashing when plugging/unplugging output
This commit is contained in:
Drew DeVault 2018-05-23 18:11:24 -04:00 committed by GitHub
commit 50d1b80d50
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 39 deletions

View file

@ -10,13 +10,13 @@
#include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h"
enum auth_state { enum auth_state {
AUTH_STATE_IDLE, AUTH_STATE_IDLE,
AUTH_STATE_CLEAR, AUTH_STATE_CLEAR,
AUTH_STATE_INPUT, AUTH_STATE_INPUT,
AUTH_STATE_INPUT_NOP, AUTH_STATE_INPUT_NOP,
AUTH_STATE_BACKSPACE, AUTH_STATE_BACKSPACE,
AUTH_STATE_VALIDATING, AUTH_STATE_VALIDATING,
AUTH_STATE_INVALID, AUTH_STATE_INVALID,
}; };
struct swaylock_args { struct swaylock_args {
@ -50,6 +50,7 @@ struct swaylock_surface {
cairo_surface_t *image; cairo_surface_t *image;
struct swaylock_state *state; struct swaylock_state *state;
struct wl_output *output; struct wl_output *output;
uint32_t output_global_name;
struct zxdg_output_v1 *xdg_output; struct zxdg_output_v1 *xdg_output;
struct wl_surface *surface; struct wl_surface *surface;
struct zwlr_layer_surface_v1 *layer_surface; struct zwlr_layer_surface_v1 *layer_surface;

View file

@ -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, static void layer_surface_configure(void *data,
struct zwlr_layer_surface_v1 *layer_surface, struct zwlr_layer_surface_v1 *layer_surface,
uint32_t serial, uint32_t width, uint32_t height) { 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, static void layer_surface_closed(void *data,
struct zwlr_layer_surface_v1 *layer_surface) { struct zwlr_layer_surface_v1 *layer_surface) {
struct swaylock_surface *surface = data; struct swaylock_surface *surface = data;
zwlr_layer_surface_v1_destroy(surface->layer_surface); destroy_surface(surface);
wl_surface_destroy(surface->surface);
surface->state->run_display = false;
} }
static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { 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->state = state;
surface->output = wl_registry_bind(registry, name, surface->output = wl_registry_bind(registry, name,
&wl_output_interface, 3); &wl_output_interface, 3);
surface->output_global_name = name;
wl_output_add_listener(surface->output, &_wl_output_listener, surface); wl_output_add_listener(surface->output, &_wl_output_listener, surface);
wl_list_insert(&state->surfaces, &surface->link); 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, static void handle_global_remove(void *data, struct wl_registry *registry,
uint32_t name) { 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 = { static const struct wl_registry_listener registry_listener = {
@ -276,7 +333,7 @@ int main(int argc, char **argv) {
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
const char *usage = const char usage[] =
"Usage: swaylock [options...]\n" "Usage: swaylock [options...]\n"
"\n" "\n"
" -h, --help Show help message and quit.\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" " -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";
struct swaylock_args args = { state.args = (struct swaylock_args){
.mode = BACKGROUND_MODE_SOLID_COLOR, .mode = BACKGROUND_MODE_SOLID_COLOR,
.color = 0xFFFFFFFF, .color = 0xFFFFFFFF,
.show_indicator = true, .show_indicator = true,
}; };
state.args = args;
wl_list_init(&state.images); wl_list_init(&state.images);
wlr_log_init(L_DEBUG, NULL); wlr_log_init(L_DEBUG, NULL);
int c; int c;
@ -369,6 +426,8 @@ int main(int argc, char **argv) {
return 0; return 0;
} }
zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager);
if (state.zxdg_output_manager) { if (state.zxdg_output_manager) {
struct swaylock_surface *surface; struct swaylock_surface *surface;
wl_list_for_each(surface, &state.surfaces, link) { wl_list_for_each(surface, &state.surfaces, link) {
@ -385,33 +444,9 @@ int main(int argc, char **argv) {
struct swaylock_surface *surface; struct swaylock_surface *surface;
wl_list_for_each(surface, &state.surfaces, link) { wl_list_for_each(surface, &state.surfaces, link) {
surface->image = select_image(&state, surface); create_layer_surface(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);
} }
zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager);
state.run_display = true; state.run_display = true;
while (wl_display_dispatch(state.display) != -1 && state.run_display) { while (wl_display_dispatch(state.display) != -1 && state.run_display) {
// This space intentionally left blank // This space intentionally left blank

View file

@ -17,6 +17,9 @@ void render_frame(struct swaylock_surface *surface) {
int buffer_width = surface->width * surface->scale; int buffer_width = surface->width * surface->scale;
int buffer_height = surface->height * 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->current_buffer = get_next_buffer(state->shm,
surface->buffers, buffer_width, buffer_height); surface->buffers, buffer_width, buffer_height);