diff options
author | emersion <contact@emersion.fr> | 2018-05-20 14:04:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-20 14:04:30 +0100 |
commit | cab0dd8281daecfb4ef2452fddc4b7aae9143fb7 (patch) | |
tree | 9ce53265d014560bf670d2bb9844e4f37e28e60b /swaylock | |
parent | 1afbfc94f4efb2ec6b021c224b6f432c625970e8 (diff) | |
parent | 836123329504af8b4fd735063eb44690a23e626e (diff) |
Merge pull request #1821 from RyanDwyer/swaylock-multiple-images
Swaylock: Allow per-output images
Diffstat (limited to 'swaylock')
-rw-r--r-- | swaylock/main.c | 155 | ||||
-rw-r--r-- | swaylock/render.c | 2 |
2 files changed, 136 insertions, 21 deletions
diff --git a/swaylock/main.c b/swaylock/main.c index 200c1b5f..11b5e8c8 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -13,6 +13,7 @@ #include <time.h> #include <unistd.h> #include <wayland-client.h> +#include <wordexp.h> #include <wlr/util/log.h> #include "swaylock/seat.h" #include "swaylock/swaylock.h" @@ -20,9 +21,11 @@ #include "pool-buffer.h" #include "cairo.h" #include "log.h" +#include "stringop.h" #include "util.h" #include "wlr-input-inhibitor-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" +#include "xdg-output-unstable-v1-client-protocol.h" void sway_terminate(int exit_code) { exit(exit_code); @@ -84,22 +87,23 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { .closed = layer_surface_closed, }; -static void output_geometry(void *data, struct wl_output *output, int32_t x, +static void handle_wl_output_geometry(void *data, struct wl_output *output, int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, const char *make, const char *model, int32_t transform) { // Who cares } -static void output_mode(void *data, struct wl_output *output, uint32_t flags, +static void handle_wl_output_mode(void *data, struct wl_output *output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { // Who cares } -static void output_done(void *data, struct wl_output *output) { +static void handle_wl_output_done(void *data, struct wl_output *output) { // Who cares } -static void output_scale(void *data, struct wl_output *output, int32_t factor) { +static void handle_wl_output_scale(void *data, struct wl_output *output, + int32_t factor) { struct swaylock_surface *surface = data; surface->scale = factor; if (surface->state->run_display) { @@ -107,11 +111,46 @@ static void output_scale(void *data, struct wl_output *output, int32_t factor) { } } -struct wl_output_listener output_listener = { - .geometry = output_geometry, - .mode = output_mode, - .done = output_done, - .scale = output_scale, +struct wl_output_listener _wl_output_listener = { + .geometry = handle_wl_output_geometry, + .mode = handle_wl_output_mode, + .done = handle_wl_output_done, + .scale = handle_wl_output_scale, +}; + +static void handle_xdg_output_logical_size(void *data, struct zxdg_output_v1 *output, + int width, int height) { + // Who cares +} + +static void handle_xdg_output_logical_position(void *data, + struct zxdg_output_v1 *output, int x, int y) { + // Who cares +} + +static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output, + const char *name) { + wlr_log(L_DEBUG, "output name is %s", name); + struct swaylock_surface *surface = data; + surface->xdg_output = output; + surface->output_name = strdup(name); +} + +static void handle_xdg_output_description(void *data, struct zxdg_output_v1 *output, + const char *description) { + // Who cares +} + +static void handle_xdg_output_done(void *data, struct zxdg_output_v1 *output) { + // Who cares +} + +struct zxdg_output_v1_listener _xdg_output_listener = { + .logical_position = handle_xdg_output_logical_position, + .logical_size = handle_xdg_output_logical_size, + .done = handle_xdg_output_done, + .name = handle_xdg_output_name, + .description = handle_xdg_output_description, }; static void handle_global(void *data, struct wl_registry *registry, @@ -133,13 +172,16 @@ static void handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name) == 0) { state->input_inhibit_manager = wl_registry_bind( registry, name, &zwlr_input_inhibit_manager_v1_interface, 1); + } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { + state->zxdg_output_manager = wl_registry_bind( + registry, name, &zxdg_output_manager_v1_interface, 2); } else if (strcmp(interface, wl_output_interface.name) == 0) { struct swaylock_surface *surface = calloc(1, sizeof(struct swaylock_surface)); surface->state = state; surface->output = wl_registry_bind(registry, name, &wl_output_interface, 3); - wl_output_add_listener(surface->output, &output_listener, surface); + wl_output_add_listener(surface->output, &_wl_output_listener, surface); wl_list_insert(&state->surfaces, &surface->link); } } @@ -154,6 +196,70 @@ static const struct wl_registry_listener registry_listener = { .global_remove = handle_global_remove, }; +static cairo_surface_t *select_image(struct swaylock_state *state, + struct swaylock_surface *surface) { + struct swaylock_image *image; + cairo_surface_t *default_image = NULL; + wl_list_for_each(image, &state->images, link) { + if (lenient_strcmp(image->output_name, surface->output_name) == 0) { + return image->cairo_surface; + } else if (!image->output_name) { + default_image = image->cairo_surface; + } + } + return default_image; +} + +static void load_image(char *arg, struct swaylock_state *state) { + // [<output>:]<path> + struct swaylock_image *image = calloc(1, sizeof(struct swaylock_image)); + char *separator = strchr(arg, ':'); + if (separator) { + *separator = '\0'; + image->output_name = strdup(arg); + image->path = strdup(separator + 1); + } else { + image->output_name = NULL; + image->path = strdup(arg); + } + + bool exists = false; + struct swaylock_image *iter_image; + wl_list_for_each(iter_image, &state->images, link) { + if (lenient_strcmp(iter_image->output_name, image->output_name) == 0) { + exists = true; + break; + } + } + if (exists) { + if (image->output_name) { + wlr_log(L_ERROR, "Multiple images defined for output %s", + image->output_name); + } else { + wlr_log(L_ERROR, "Multiple default images defined"); + } + } + + // Bash doesn't replace the ~ with $HOME if the output name is supplied + wordexp_t p; + if (wordexp(image->path, &p, 0) == 0) { + free(image->path); + image->path = strdup(p.we_wordv[0]); + wordfree(&p); + } + + // Load the actual image + image->cairo_surface = load_background_image(image->path); + if (!image->cairo_surface) { + free(image); + return; + } + wl_list_insert(&state->images, &image->link); + state->args.mode = BACKGROUND_MODE_FILL; + wlr_log(L_DEBUG, "Loaded image %s for output %s", + image->path, image->output_name ? image->output_name : "*"); +} + static struct swaylock_state state; int main(int argc, char **argv) { @@ -180,16 +286,15 @@ int main(int argc, char **argv) { " -v, --version Show the version number and quit.\n" " -i, --image [<output>:]<path> Display the given image.\n" " -u, --no-unlock-indicator Disable the unlock indicator.\n" - " -f, --daemonize Detach from the controlling terminal.\n" - " --socket <socket> Use the specified socket.\n"; + " -f, --daemonize Detach from the controlling terminal.\n"; struct swaylock_args args = { .mode = BACKGROUND_MODE_SOLID_COLOR, .color = 0xFFFFFFFF, .show_indicator = true, }; - cairo_surface_t *background_image = NULL; state.args = args; + wl_list_init(&state.images); wlr_log_init(L_DEBUG, NULL); int c; @@ -206,12 +311,7 @@ int main(int argc, char **argv) { break; } case 'i': - // TODO: Multiple background images (bleh) - background_image = load_background_image(optarg); - if (!background_image) { - return 1; - } - state.args.mode = BACKGROUND_MODE_FILL; + load_image(optarg, &state); break; case 's': state.args.mode = parse_background_mode(optarg); @@ -261,6 +361,7 @@ int main(int argc, char **argv) { if (!state.input_inhibit_manager) { wlr_log(L_ERROR, "Compositor does not support the input inhibitor " "protocol, refusing to run insecurely"); + return 1; } if (wl_list_empty(&state.surfaces)) { @@ -268,9 +369,23 @@ int main(int argc, char **argv) { return 0; } + if (state.zxdg_output_manager) { + struct swaylock_surface *surface; + wl_list_for_each(surface, &state.surfaces, link) { + surface->xdg_output = zxdg_output_manager_v1_get_xdg_output( + state.zxdg_output_manager, surface->output); + zxdg_output_v1_add_listener( + surface->xdg_output, &_xdg_output_listener, surface); + } + wl_display_roundtrip(state.display); + } else { + wlr_log(L_INFO, "Compositor does not support zxdg output manager, " + "images assigned to named outputs will not work"); + } + struct swaylock_surface *surface; wl_list_for_each(surface, &state.surfaces, link) { - surface->image = background_image; + surface->image = select_image(&state, surface); surface->surface = wl_compositor_create_surface(state.compositor); assert(surface->surface); diff --git a/swaylock/render.c b/swaylock/render.c index 7d9d25a5..cc40f4e9 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -23,7 +23,7 @@ void render_frame(struct swaylock_surface *surface) { cairo_t *cairo = surface->current_buffer->cairo; cairo_identity_matrix(cairo); - if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { + if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR || !surface->image) { cairo_set_source_u32(cairo, state->args.color); cairo_paint(cairo); } else { |