mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #2003 from emersion/fix-swaylock-hotplugging
Fix swaylock crashing when plugging/unplugging output
This commit is contained in:
		
						commit
						50d1b80d50
					
				
					 3 changed files with 78 additions and 39 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue