summaryrefslogtreecommitdiffstats
path: root/swaylock
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-05-19 08:47:47 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-05-20 22:54:09 +1000
commit9d99e5c2e72a464554b034c014437a495bb7b409 (patch)
tree06005cdf1ed6d50cbabc1f2a3d46348c206ad432 /swaylock
parentMerge pull request #2006 from kupospelov/fix-title-pixel-bar (diff)
downloadsway-9d99e5c2e72a464554b034c014437a495bb7b409.tar.gz
sway-9d99e5c2e72a464554b034c014437a495bb7b409.tar.zst
sway-9d99e5c2e72a464554b034c014437a495bb7b409.zip
Swaylock: Allow per-output images
Diffstat (limited to 'swaylock')
-rw-r--r--swaylock/main.c138
-rw-r--r--swaylock/render.c2
2 files changed, 119 insertions, 21 deletions
diff --git a/swaylock/main.c b/swaylock/main.c
index 200c1b5f..91c28bd2 100644
--- a/swaylock/main.c
+++ b/swaylock/main.c
@@ -13,6 +13,7 @@
13#include <time.h> 13#include <time.h>
14#include <unistd.h> 14#include <unistd.h>
15#include <wayland-client.h> 15#include <wayland-client.h>
16#include <wordexp.h>
16#include <wlr/util/log.h> 17#include <wlr/util/log.h>
17#include "swaylock/seat.h" 18#include "swaylock/seat.h"
18#include "swaylock/swaylock.h" 19#include "swaylock/swaylock.h"
@@ -20,9 +21,11 @@
20#include "pool-buffer.h" 21#include "pool-buffer.h"
21#include "cairo.h" 22#include "cairo.h"
22#include "log.h" 23#include "log.h"
24#include "stringop.h"
23#include "util.h" 25#include "util.h"
24#include "wlr-input-inhibitor-unstable-v1-client-protocol.h" 26#include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
25#include "wlr-layer-shell-unstable-v1-client-protocol.h" 27#include "wlr-layer-shell-unstable-v1-client-protocol.h"
28#include "xdg-output-unstable-v1-client-protocol.h"
26 29
27void sway_terminate(int exit_code) { 30void sway_terminate(int exit_code) {
28 exit(exit_code); 31 exit(exit_code);
@@ -84,22 +87,23 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
84 .closed = layer_surface_closed, 87 .closed = layer_surface_closed,
85}; 88};
86 89
87static void output_geometry(void *data, struct wl_output *output, int32_t x, 90static void handle_wl_output_geometry(void *data, struct wl_output *output, int32_t x,
88 int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, 91 int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel,
89 const char *make, const char *model, int32_t transform) { 92 const char *make, const char *model, int32_t transform) {
90 // Who cares 93 // Who cares
91} 94}
92 95
93static void output_mode(void *data, struct wl_output *output, uint32_t flags, 96static void handle_wl_output_mode(void *data, struct wl_output *output, uint32_t flags,
94 int32_t width, int32_t height, int32_t refresh) { 97 int32_t width, int32_t height, int32_t refresh) {
95 // Who cares 98 // Who cares
96} 99}
97 100
98static void output_done(void *data, struct wl_output *output) { 101static void handle_wl_output_done(void *data, struct wl_output *output) {
99 // Who cares 102 // Who cares
100} 103}
101 104
102static void output_scale(void *data, struct wl_output *output, int32_t factor) { 105static void handle_wl_output_scale(void *data, struct wl_output *output,
106 int32_t factor) {
103 struct swaylock_surface *surface = data; 107 struct swaylock_surface *surface = data;
104 surface->scale = factor; 108 surface->scale = factor;
105 if (surface->state->run_display) { 109 if (surface->state->run_display) {
@@ -107,11 +111,46 @@ static void output_scale(void *data, struct wl_output *output, int32_t factor) {
107 } 111 }
108} 112}
109 113
110struct wl_output_listener output_listener = { 114struct wl_output_listener _wl_output_listener = {
111 .geometry = output_geometry, 115 .geometry = handle_wl_output_geometry,
112 .mode = output_mode, 116 .mode = handle_wl_output_mode,
113 .done = output_done, 117 .done = handle_wl_output_done,
114 .scale = output_scale, 118 .scale = handle_wl_output_scale,
119};
120
121static void handle_xdg_output_logical_size(void *data, struct zxdg_output_v1 *output,
122 int width, int height) {
123 // Who cares
124}
125
126static void handle_xdg_output_logical_position(void *data,
127 struct zxdg_output_v1 *output, int x, int y) {
128 // Who cares
129}
130
131static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output,
132 const char *name) {
133 wlr_log(L_DEBUG, "output name is %s", name);
134 struct swaylock_surface *surface = data;
135 surface->xdg_output = output;
136 surface->output_name = strdup(name);
137}
138
139static void handle_xdg_output_description(void *data, struct zxdg_output_v1 *output,
140 const char *description) {
141 // Who cares
142}
143
144static void handle_xdg_output_done(void *data, struct zxdg_output_v1 *output) {
145 // Who cares
146}
147
148struct zxdg_output_v1_listener _xdg_output_listener = {
149 .logical_position = handle_xdg_output_logical_position,
150 .logical_size = handle_xdg_output_logical_size,
151 .done = handle_xdg_output_done,
152 .name = handle_xdg_output_name,
153 .description = handle_xdg_output_description,
115}; 154};
116 155
117static void handle_global(void *data, struct wl_registry *registry, 156static void handle_global(void *data, struct wl_registry *registry,
@@ -133,13 +172,16 @@ static void handle_global(void *data, struct wl_registry *registry,
133 } else if (strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name) == 0) { 172 } else if (strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name) == 0) {
134 state->input_inhibit_manager = wl_registry_bind( 173 state->input_inhibit_manager = wl_registry_bind(
135 registry, name, &zwlr_input_inhibit_manager_v1_interface, 1); 174 registry, name, &zwlr_input_inhibit_manager_v1_interface, 1);
175 } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
176 state->zxdg_output_manager = wl_registry_bind(
177 registry, name, &zxdg_output_manager_v1_interface, 2);
136 } else if (strcmp(interface, wl_output_interface.name) == 0) { 178 } else if (strcmp(interface, wl_output_interface.name) == 0) {
137 struct swaylock_surface *surface = 179 struct swaylock_surface *surface =
138 calloc(1, sizeof(struct swaylock_surface)); 180 calloc(1, sizeof(struct swaylock_surface));
139 surface->state = state; 181 surface->state = state;
140 surface->output = wl_registry_bind(registry, name, 182 surface->output = wl_registry_bind(registry, name,
141 &wl_output_interface, 3); 183 &wl_output_interface, 3);
142 wl_output_add_listener(surface->output, &output_listener, surface); 184 wl_output_add_listener(surface->output, &_wl_output_listener, surface);
143 wl_list_insert(&state->surfaces, &surface->link); 185 wl_list_insert(&state->surfaces, &surface->link);
144 } 186 }
145} 187}
@@ -154,6 +196,53 @@ static const struct wl_registry_listener registry_listener = {
154 .global_remove = handle_global_remove, 196 .global_remove = handle_global_remove,
155}; 197};
156 198
199static cairo_surface_t *select_image(struct swaylock_state *state,
200 struct swaylock_surface *surface) {
201 struct swaylock_image *image;
202 cairo_surface_t *default_image = NULL;
203 wl_list_for_each(image, &state->images, link) {
204 if (lenient_strcmp(image->output_name, surface->output_name) == 0) {
205 return image->cairo_surface;
206 } else if (!image->output_name) {
207 default_image = image->cairo_surface;
208 }
209 }
210 return default_image;
211}
212
213static void load_image(char *arg, struct swaylock_state *state) {
214 // [<output>:]<path>
215 struct swaylock_image *image = malloc(sizeof(struct swaylock_image));
216 char *separator = strchr(arg, ':');
217 if (separator) {
218 *separator = '\0';
219 image->output_name = strdup(arg);
220 image->path = strdup(separator + 1);
221 } else {
222 image->output_name = NULL;
223 image->path = strdup(arg);
224 }
225
226 // Bash doesn't replace the ~ with $HOME if the output name is supplied
227 wordexp_t p;
228 if (wordexp(image->path, &p, 0) == 0) {
229 free(image->path);
230 image->path = strdup(p.we_wordv[0]);
231 wordfree(&p);
232 }
233
234 // Load the actual image
235 image->cairo_surface = load_background_image(image->path);
236 if (!image->cairo_surface) {
237 free(image);
238 return;
239 }
240 wl_list_insert(&state->images, &image->link);
241 state->args.mode = BACKGROUND_MODE_FILL;
242 wlr_log(L_DEBUG, "Loaded image %s for output %s",
243 image->path, image->output_name ? image->output_name : "*");
244}
245
157static struct swaylock_state state; 246static struct swaylock_state state;
158 247
159int main(int argc, char **argv) { 248int main(int argc, char **argv) {
@@ -180,16 +269,15 @@ int main(int argc, char **argv) {
180 " -v, --version Show the version number and quit.\n" 269 " -v, --version Show the version number and quit.\n"
181 " -i, --image [<output>:]<path> Display the given image.\n" 270 " -i, --image [<output>:]<path> Display the given image.\n"
182 " -u, --no-unlock-indicator Disable the unlock indicator.\n" 271 " -u, --no-unlock-indicator Disable the unlock indicator.\n"
183 " -f, --daemonize Detach from the controlling terminal.\n" 272 " -f, --daemonize Detach from the controlling terminal.\n";
184 " --socket <socket> Use the specified socket.\n";
185 273
186 struct swaylock_args args = { 274 struct swaylock_args args = {
187 .mode = BACKGROUND_MODE_SOLID_COLOR, 275 .mode = BACKGROUND_MODE_SOLID_COLOR,
188 .color = 0xFFFFFFFF, 276 .color = 0xFFFFFFFF,
189 .show_indicator = true, 277 .show_indicator = true,
190 }; 278 };
191 cairo_surface_t *background_image = NULL;
192 state.args = args; 279 state.args = args;
280 wl_list_init(&state.images);
193 wlr_log_init(L_DEBUG, NULL); 281 wlr_log_init(L_DEBUG, NULL);
194 282
195 int c; 283 int c;
@@ -206,12 +294,7 @@ int main(int argc, char **argv) {
206 break; 294 break;
207 } 295 }
208 case 'i': 296 case 'i':
209 // TODO: Multiple background images (bleh) 297 load_image(optarg, &state);
210 background_image = load_background_image(optarg);
211 if (!background_image) {
212 return 1;
213 }
214 state.args.mode = BACKGROUND_MODE_FILL;
215 break; 298 break;
216 case 's': 299 case 's':
217 state.args.mode = parse_background_mode(optarg); 300 state.args.mode = parse_background_mode(optarg);
@@ -261,6 +344,7 @@ int main(int argc, char **argv) {
261 if (!state.input_inhibit_manager) { 344 if (!state.input_inhibit_manager) {
262 wlr_log(L_ERROR, "Compositor does not support the input inhibitor " 345 wlr_log(L_ERROR, "Compositor does not support the input inhibitor "
263 "protocol, refusing to run insecurely"); 346 "protocol, refusing to run insecurely");
347 return 1;
264 } 348 }
265 349
266 if (wl_list_empty(&state.surfaces)) { 350 if (wl_list_empty(&state.surfaces)) {
@@ -268,9 +352,23 @@ int main(int argc, char **argv) {
268 return 0; 352 return 0;
269 } 353 }
270 354
355 if (state.zxdg_output_manager) {
356 struct swaylock_surface *surface;
357 wl_list_for_each(surface, &state.surfaces, link) {
358 surface->xdg_output = zxdg_output_manager_v1_get_xdg_output(
359 state.zxdg_output_manager, surface->output);
360 zxdg_output_v1_add_listener(
361 surface->xdg_output, &_xdg_output_listener, surface);
362 }
363 wl_display_roundtrip(state.display);
364 } else {
365 wlr_log(L_INFO, "Compositor does not support zxdg output manager, "
366 "images assigned to named outputs will not work");
367 }
368
271 struct swaylock_surface *surface; 369 struct swaylock_surface *surface;
272 wl_list_for_each(surface, &state.surfaces, link) { 370 wl_list_for_each(surface, &state.surfaces, link) {
273 surface->image = background_image; 371 surface->image = select_image(&state, surface);
274 372
275 surface->surface = wl_compositor_create_surface(state.compositor); 373 surface->surface = wl_compositor_create_surface(state.compositor);
276 assert(surface->surface); 374 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) {
23 cairo_t *cairo = surface->current_buffer->cairo; 23 cairo_t *cairo = surface->current_buffer->cairo;
24 cairo_identity_matrix(cairo); 24 cairo_identity_matrix(cairo);
25 25
26 if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { 26 if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR || !surface->image) {
27 cairo_set_source_u32(cairo, state->args.color); 27 cairo_set_source_u32(cairo, state->args.color);
28 cairo_paint(cairo); 28 cairo_paint(cairo);
29 } else { 29 } else {