diff options
author | emersion <contact@emersion.fr> | 2018-05-23 22:54:52 +0100 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2018-05-23 22:54:52 +0100 |
commit | cd0fca2ebf81c252b3743c4474a5fdbcd3e2afad (patch) | |
tree | 595f1e80551b64de0d4e24f5721bae27acc195d9 /swaylock/main.c | |
parent | Fix output hotplugging (diff) | |
parent | Merge pull request #2022 from RedSoxFan/ipc-get-marks (diff) | |
download | sway-cd0fca2ebf81c252b3743c4474a5fdbcd3e2afad.tar.gz sway-cd0fca2ebf81c252b3743c4474a5fdbcd3e2afad.tar.zst sway-cd0fca2ebf81c252b3743c4474a5fdbcd3e2afad.zip |
Merge branch 'master' into fix-swaylock-hotplugging
Diffstat (limited to 'swaylock/main.c')
-rw-r--r-- | swaylock/main.c | 158 |
1 files changed, 139 insertions, 19 deletions
diff --git a/swaylock/main.c b/swaylock/main.c index 9da99f97..79c06285 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 | ||
27 | void sway_terminate(int exit_code) { | 30 | void sway_terminate(int exit_code) { |
28 | exit(exit_code); | 31 | exit(exit_code); |
@@ -77,9 +80,14 @@ static void destroy_surface(struct swaylock_surface *surface) { | |||
77 | 80 | ||
78 | static const struct zwlr_layer_surface_v1_listener layer_surface_listener; | 81 | static const struct zwlr_layer_surface_v1_listener layer_surface_listener; |
79 | 82 | ||
83 | static cairo_surface_t *select_image(struct swaylock_state *state, | ||
84 | struct swaylock_surface *surface); | ||
85 | |||
80 | static void create_layer_surface(struct swaylock_surface *surface) { | 86 | static void create_layer_surface(struct swaylock_surface *surface) { |
81 | struct swaylock_state *state = surface->state; | 87 | struct swaylock_state *state = surface->state; |
82 | 88 | ||
89 | surface->image = select_image(state, surface); | ||
90 | |||
83 | surface->surface = wl_compositor_create_surface(state->compositor); | 91 | surface->surface = wl_compositor_create_surface(state->compositor); |
84 | assert(surface->surface); | 92 | assert(surface->surface); |
85 | 93 | ||
@@ -123,22 +131,23 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { | |||
123 | .closed = layer_surface_closed, | 131 | .closed = layer_surface_closed, |
124 | }; | 132 | }; |
125 | 133 | ||
126 | static void output_geometry(void *data, struct wl_output *output, int32_t x, | 134 | static void handle_wl_output_geometry(void *data, struct wl_output *output, int32_t x, |
127 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, | 135 | int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, |
128 | const char *make, const char *model, int32_t transform) { | 136 | const char *make, const char *model, int32_t transform) { |
129 | // Who cares | 137 | // Who cares |
130 | } | 138 | } |
131 | 139 | ||
132 | static void output_mode(void *data, struct wl_output *output, uint32_t flags, | 140 | static void handle_wl_output_mode(void *data, struct wl_output *output, uint32_t flags, |
133 | int32_t width, int32_t height, int32_t refresh) { | 141 | int32_t width, int32_t height, int32_t refresh) { |
134 | // Who cares | 142 | // Who cares |
135 | } | 143 | } |
136 | 144 | ||
137 | static void output_done(void *data, struct wl_output *output) { | 145 | static void handle_wl_output_done(void *data, struct wl_output *output) { |
138 | // Who cares | 146 | // Who cares |
139 | } | 147 | } |
140 | 148 | ||
141 | static void output_scale(void *data, struct wl_output *output, int32_t factor) { | 149 | static void handle_wl_output_scale(void *data, struct wl_output *output, |
150 | int32_t factor) { | ||
142 | struct swaylock_surface *surface = data; | 151 | struct swaylock_surface *surface = data; |
143 | surface->scale = factor; | 152 | surface->scale = factor; |
144 | if (surface->state->run_display) { | 153 | if (surface->state->run_display) { |
@@ -146,11 +155,46 @@ static void output_scale(void *data, struct wl_output *output, int32_t factor) { | |||
146 | } | 155 | } |
147 | } | 156 | } |
148 | 157 | ||
149 | struct wl_output_listener output_listener = { | 158 | struct wl_output_listener _wl_output_listener = { |
150 | .geometry = output_geometry, | 159 | .geometry = handle_wl_output_geometry, |
151 | .mode = output_mode, | 160 | .mode = handle_wl_output_mode, |
152 | .done = output_done, | 161 | .done = handle_wl_output_done, |
153 | .scale = output_scale, | 162 | .scale = handle_wl_output_scale, |
163 | }; | ||
164 | |||
165 | static void handle_xdg_output_logical_size(void *data, struct zxdg_output_v1 *output, | ||
166 | int width, int height) { | ||
167 | // Who cares | ||
168 | } | ||
169 | |||
170 | static void handle_xdg_output_logical_position(void *data, | ||
171 | struct zxdg_output_v1 *output, int x, int y) { | ||
172 | // Who cares | ||
173 | } | ||
174 | |||
175 | static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output, | ||
176 | const char *name) { | ||
177 | wlr_log(L_DEBUG, "output name is %s", name); | ||
178 | struct swaylock_surface *surface = data; | ||
179 | surface->xdg_output = output; | ||
180 | surface->output_name = strdup(name); | ||
181 | } | ||
182 | |||
183 | static void handle_xdg_output_description(void *data, struct zxdg_output_v1 *output, | ||
184 | const char *description) { | ||
185 | // Who cares | ||
186 | } | ||
187 | |||
188 | static void handle_xdg_output_done(void *data, struct zxdg_output_v1 *output) { | ||
189 | // Who cares | ||
190 | } | ||
191 | |||
192 | struct zxdg_output_v1_listener _xdg_output_listener = { | ||
193 | .logical_position = handle_xdg_output_logical_position, | ||
194 | .logical_size = handle_xdg_output_logical_size, | ||
195 | .done = handle_xdg_output_done, | ||
196 | .name = handle_xdg_output_name, | ||
197 | .description = handle_xdg_output_description, | ||
154 | }; | 198 | }; |
155 | 199 | ||
156 | static void handle_global(void *data, struct wl_registry *registry, | 200 | static void handle_global(void *data, struct wl_registry *registry, |
@@ -172,6 +216,9 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
172 | } else if (strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name) == 0) { | 216 | } else if (strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name) == 0) { |
173 | state->input_inhibit_manager = wl_registry_bind( | 217 | state->input_inhibit_manager = wl_registry_bind( |
174 | registry, name, &zwlr_input_inhibit_manager_v1_interface, 1); | 218 | registry, name, &zwlr_input_inhibit_manager_v1_interface, 1); |
219 | } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { | ||
220 | state->zxdg_output_manager = wl_registry_bind( | ||
221 | registry, name, &zxdg_output_manager_v1_interface, 2); | ||
175 | } else if (strcmp(interface, wl_output_interface.name) == 0) { | 222 | } else if (strcmp(interface, wl_output_interface.name) == 0) { |
176 | struct swaylock_surface *surface = | 223 | struct swaylock_surface *surface = |
177 | calloc(1, sizeof(struct swaylock_surface)); | 224 | calloc(1, sizeof(struct swaylock_surface)); |
@@ -180,7 +227,7 @@ static void handle_global(void *data, struct wl_registry *registry, | |||
180 | &wl_output_interface, 3); | 227 | &wl_output_interface, 3); |
181 | surface->output_global_name = name; | 228 | surface->output_global_name = name; |
182 | surface->image = state->background_image; | 229 | surface->image = state->background_image; |
183 | wl_output_add_listener(surface->output, &output_listener, surface); | 230 | wl_output_add_listener(surface->output, &_wl_output_listener, surface); |
184 | wl_list_insert(&state->surfaces, &surface->link); | 231 | wl_list_insert(&state->surfaces, &surface->link); |
185 | 232 | ||
186 | if (state->run_display) { | 233 | if (state->run_display) { |
@@ -207,6 +254,70 @@ static const struct wl_registry_listener registry_listener = { | |||
207 | .global_remove = handle_global_remove, | 254 | .global_remove = handle_global_remove, |
208 | }; | 255 | }; |
209 | 256 | ||
257 | static cairo_surface_t *select_image(struct swaylock_state *state, | ||
258 | struct swaylock_surface *surface) { | ||
259 | struct swaylock_image *image; | ||
260 | cairo_surface_t *default_image = NULL; | ||
261 | wl_list_for_each(image, &state->images, link) { | ||
262 | if (lenient_strcmp(image->output_name, surface->output_name) == 0) { | ||
263 | return image->cairo_surface; | ||
264 | } else if (!image->output_name) { | ||
265 | default_image = image->cairo_surface; | ||
266 | } | ||
267 | } | ||
268 | return default_image; | ||
269 | } | ||
270 | |||
271 | static void load_image(char *arg, struct swaylock_state *state) { | ||
272 | // [<output>:]<path> | ||
273 | struct swaylock_image *image = calloc(1, sizeof(struct swaylock_image)); | ||
274 | char *separator = strchr(arg, ':'); | ||
275 | if (separator) { | ||
276 | *separator = '\0'; | ||
277 | image->output_name = strdup(arg); | ||
278 | image->path = strdup(separator + 1); | ||
279 | } else { | ||
280 | image->output_name = NULL; | ||
281 | image->path = strdup(arg); | ||
282 | } | ||
283 | |||
284 | bool exists = false; | ||
285 | struct swaylock_image *iter_image; | ||
286 | wl_list_for_each(iter_image, &state->images, link) { | ||
287 | if (lenient_strcmp(iter_image->output_name, image->output_name) == 0) { | ||
288 | exists = true; | ||
289 | break; | ||
290 | } | ||
291 | } | ||
292 | if (exists) { | ||
293 | if (image->output_name) { | ||
294 | wlr_log(L_ERROR, "Multiple images defined for output %s", | ||
295 | image->output_name); | ||
296 | } else { | ||
297 | wlr_log(L_ERROR, "Multiple default images defined"); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | // Bash doesn't replace the ~ with $HOME if the output name is supplied | ||
302 | wordexp_t p; | ||
303 | if (wordexp(image->path, &p, 0) == 0) { | ||
304 | free(image->path); | ||
305 | image->path = strdup(p.we_wordv[0]); | ||
306 | wordfree(&p); | ||
307 | } | ||
308 | |||
309 | // Load the actual image | ||
310 | image->cairo_surface = load_background_image(image->path); | ||
311 | if (!image->cairo_surface) { | ||
312 | free(image); | ||
313 | return; | ||
314 | } | ||
315 | wl_list_insert(&state->images, &image->link); | ||
316 | state->args.mode = BACKGROUND_MODE_FILL; | ||
317 | wlr_log(L_DEBUG, "Loaded image %s for output %s", | ||
318 | image->path, image->output_name ? image->output_name : "*"); | ||
319 | } | ||
320 | |||
210 | static struct swaylock_state state; | 321 | static struct swaylock_state state; |
211 | 322 | ||
212 | int main(int argc, char **argv) { | 323 | int main(int argc, char **argv) { |
@@ -233,14 +344,14 @@ int main(int argc, char **argv) { | |||
233 | " -v, --version Show the version number and quit.\n" | 344 | " -v, --version Show the version number and quit.\n" |
234 | " -i, --image [<output>:]<path> Display the given image.\n" | 345 | " -i, --image [<output>:]<path> Display the given image.\n" |
235 | " -u, --no-unlock-indicator Disable the unlock indicator.\n" | 346 | " -u, --no-unlock-indicator Disable the unlock indicator.\n" |
236 | " -f, --daemonize Detach from the controlling terminal.\n" | 347 | " -f, --daemonize Detach from the controlling terminal.\n"; |
237 | " --socket <socket> Use the specified socket.\n"; | ||
238 | 348 | ||
239 | state.args = (struct swaylock_args){ | 349 | state.args = (struct swaylock_args){ |
240 | .mode = BACKGROUND_MODE_SOLID_COLOR, | 350 | .mode = BACKGROUND_MODE_SOLID_COLOR, |
241 | .color = 0xFFFFFFFF, | 351 | .color = 0xFFFFFFFF, |
242 | .show_indicator = true, | 352 | .show_indicator = true, |
243 | }; | 353 | }; |
354 | wl_list_init(&state.images); | ||
244 | 355 | ||
245 | wlr_log_init(L_DEBUG, NULL); | 356 | wlr_log_init(L_DEBUG, NULL); |
246 | 357 | ||
@@ -258,12 +369,7 @@ int main(int argc, char **argv) { | |||
258 | break; | 369 | break; |
259 | } | 370 | } |
260 | case 'i': | 371 | case 'i': |
261 | // TODO: Multiple background images (bleh) | 372 | load_image(optarg, &state); |
262 | state.background_image = load_background_image(optarg); | ||
263 | if (!state.background_image) { | ||
264 | return 1; | ||
265 | } | ||
266 | state.args.mode = BACKGROUND_MODE_FILL; | ||
267 | break; | 373 | break; |
268 | case 's': | 374 | case 's': |
269 | state.args.mode = parse_background_mode(optarg); | 375 | state.args.mode = parse_background_mode(optarg); |
@@ -313,6 +419,7 @@ int main(int argc, char **argv) { | |||
313 | if (!state.input_inhibit_manager) { | 419 | if (!state.input_inhibit_manager) { |
314 | wlr_log(L_ERROR, "Compositor does not support the input inhibitor " | 420 | wlr_log(L_ERROR, "Compositor does not support the input inhibitor " |
315 | "protocol, refusing to run insecurely"); | 421 | "protocol, refusing to run insecurely"); |
422 | return 1; | ||
316 | } | 423 | } |
317 | 424 | ||
318 | if (wl_list_empty(&state.surfaces)) { | 425 | if (wl_list_empty(&state.surfaces)) { |
@@ -322,11 +429,24 @@ int main(int argc, char **argv) { | |||
322 | 429 | ||
323 | zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); | 430 | zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); |
324 | 431 | ||
432 | if (state.zxdg_output_manager) { | ||
433 | struct swaylock_surface *surface; | ||
434 | wl_list_for_each(surface, &state.surfaces, link) { | ||
435 | surface->xdg_output = zxdg_output_manager_v1_get_xdg_output( | ||
436 | state.zxdg_output_manager, surface->output); | ||
437 | zxdg_output_v1_add_listener( | ||
438 | surface->xdg_output, &_xdg_output_listener, surface); | ||
439 | } | ||
440 | wl_display_roundtrip(state.display); | ||
441 | } else { | ||
442 | wlr_log(L_INFO, "Compositor does not support zxdg output manager, " | ||
443 | "images assigned to named outputs will not work"); | ||
444 | } | ||
445 | |||
325 | struct swaylock_surface *surface; | 446 | struct swaylock_surface *surface; |
326 | wl_list_for_each(surface, &state.surfaces, link) { | 447 | wl_list_for_each(surface, &state.surfaces, link) { |
327 | create_layer_surface(surface); | 448 | create_layer_surface(surface); |
328 | } | 449 | } |
329 | wl_display_roundtrip(state.display); | ||
330 | 450 | ||
331 | state.run_display = true; | 451 | state.run_display = true; |
332 | while (wl_display_dispatch(state.display) != -1 && state.run_display) { | 452 | while (wl_display_dispatch(state.display) != -1 && state.run_display) { |