diff options
author | Nuew <code@nuew.net> | 2016-03-24 18:02:34 -0400 |
---|---|---|
committer | Nuew <code@nuew.net> | 2016-03-24 18:02:34 -0400 |
commit | 0aa4383c9a1b3b693ee771e7829ed84582b4577c (patch) | |
tree | 4bc6746cabaedeae60ffeeb0f082c4c850487062 /swaylock/main.c | |
parent | Merge pull request #537 from mikkeloscar/exit-on-config-missing (diff) | |
download | sway-0aa4383c9a1b3b693ee771e7829ed84582b4577c.tar.gz sway-0aa4383c9a1b3b693ee771e7829ed84582b4577c.tar.zst sway-0aa4383c9a1b3b693ee771e7829ed84582b4577c.zip |
Add choice of display to --image.
Additionally
- Made background colors display when an image is enabled if
a --color is specified.
- Link CJson to swaylock.
- Add the --socket option to swaylock.
Diffstat (limited to 'swaylock/main.c')
-rw-r--r-- | swaylock/main.c | 155 |
1 files changed, 121 insertions, 34 deletions
diff --git a/swaylock/main.c b/swaylock/main.c index feb64975..7f4c424d 100644 --- a/swaylock/main.c +++ b/swaylock/main.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <xkbcommon/xkbcommon.h> | 2 | #include <xkbcommon/xkbcommon.h> |
3 | #include <xkbcommon/xkbcommon-names.h> | 3 | #include <xkbcommon/xkbcommon-names.h> |
4 | #include <security/pam_appl.h> | 4 | #include <security/pam_appl.h> |
5 | #include <json-c/json.h> | ||
5 | #include <stdio.h> | 6 | #include <stdio.h> |
6 | #include <stdlib.h> | 7 | #include <stdlib.h> |
7 | #include <string.h> | 8 | #include <string.h> |
@@ -11,6 +12,7 @@ | |||
11 | #include "client/window.h" | 12 | #include "client/window.h" |
12 | #include "client/registry.h" | 13 | #include "client/registry.h" |
13 | #include "client/cairo.h" | 14 | #include "client/cairo.h" |
15 | #include "ipc-client.h" | ||
14 | #include "log.h" | 16 | #include "log.h" |
15 | 17 | ||
16 | list_t *surfaces; | 18 | list_t *surfaces; |
@@ -134,7 +136,6 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod | |||
134 | void render_color(struct window *window, uint32_t color) { | 136 | void render_color(struct window *window, uint32_t color) { |
135 | cairo_set_source_u32(window->cairo, color); | 137 | cairo_set_source_u32(window->cairo, color); |
136 | cairo_paint(window->cairo); | 138 | cairo_paint(window->cairo); |
137 | window_render(window); | ||
138 | } | 139 | } |
139 | 140 | ||
140 | void render_image(struct window *window, cairo_surface_t *image, enum scaling_mode scaling_mode) { | 141 | void render_image(struct window *window, cairo_surface_t *image, enum scaling_mode scaling_mode) { |
@@ -203,14 +204,35 @@ void render_image(struct window *window, cairo_surface_t *image, enum scaling_mo | |||
203 | } | 204 | } |
204 | 205 | ||
205 | cairo_paint(window->cairo); | 206 | cairo_paint(window->cairo); |
207 | } | ||
208 | |||
209 | cairo_surface_t *load_image(char *image_path) { | ||
210 | cairo_surface_t *image = NULL; | ||
211 | |||
212 | #ifdef WITH_GDK_PIXBUF | ||
213 | GError *err = NULL; | ||
214 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); | ||
215 | if (!pixbuf) { | ||
216 | fprintf(stderr, "GDK Error: %s\n", err->message); | ||
217 | sway_abort("Failed to load background image."); | ||
218 | } | ||
219 | image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); | ||
220 | g_object_unref(pixbuf); | ||
221 | #else | ||
222 | image = cairo_image_surface_create_from_png(image_path); | ||
223 | #endif //WITH_GDK_PIXBUF | ||
224 | if (!image) { | ||
225 | sway_abort("Failed to read background image."); | ||
226 | } | ||
206 | 227 | ||
207 | window_render(window); | 228 | return image; |
208 | } | 229 | } |
209 | 230 | ||
210 | int main(int argc, char **argv) { | 231 | int main(int argc, char **argv) { |
211 | char *image_path = NULL; | 232 | char *scaling_mode_str = "fit", *socket_path = NULL; |
212 | char *scaling_mode_str = "fit"; | 233 | int i, num_images = 0, color_set = 0; |
213 | uint32_t color = 0xFFFFFFFF; | 234 | uint32_t color = 0xFFFFFFFF; |
235 | void *images; | ||
214 | 236 | ||
215 | init_log(L_INFO); | 237 | init_log(L_INFO); |
216 | 238 | ||
@@ -221,18 +243,22 @@ int main(int argc, char **argv) { | |||
221 | {"scaling", required_argument, NULL, 's'}, | 243 | {"scaling", required_argument, NULL, 's'}, |
222 | {"tiling", no_argument, NULL, 't'}, | 244 | {"tiling", no_argument, NULL, 't'}, |
223 | {"version", no_argument, NULL, 'v'}, | 245 | {"version", no_argument, NULL, 'v'}, |
246 | {"socket", required_argument, NULL, 'p'}, | ||
224 | {0, 0, 0, 0} | 247 | {0, 0, 0, 0} |
225 | }; | 248 | }; |
226 | 249 | ||
227 | const char *usage = | 250 | const char *usage = |
228 | "Usage: swaylock [options...]\n" | 251 | "Usage: swaylock [options...]\n" |
229 | "\n" | 252 | "\n" |
230 | " -h, --help Show help message and quit.\n" | 253 | " -h, --help Show help message and quit.\n" |
231 | " -c, --color <rrggbb[aa]> Turn the screen into the given color instead of white.\n" | 254 | " -c, --color <rrggbb[aa]> Turn the screen into the given color instead of white.\n" |
232 | " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" | 255 | " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" |
233 | " -t, --tiling Same as --scaling=tile.\n" | 256 | " -t, --tiling Same as --scaling=tile.\n" |
234 | " -v, --version Show the version number and quit.\n" | 257 | " -v, --version Show the version number and quit.\n" |
235 | " -i, --image <path> Display the given image.\n"; | 258 | " -i, --image [<display>:]<path> Display the given image.\n" |
259 | " --socket <socket> Use the specified socket.\n"; | ||
260 | |||
261 | registry = registry_poll(); | ||
236 | 262 | ||
237 | int c; | 263 | int c; |
238 | while (1) { | 264 | while (1) { |
@@ -250,6 +276,7 @@ int main(int argc, char **argv) { | |||
250 | exit(EXIT_FAILURE); | 276 | exit(EXIT_FAILURE); |
251 | } | 277 | } |
252 | color = strtol(optarg, NULL, 16); | 278 | color = strtol(optarg, NULL, 16); |
279 | color_set = 1; | ||
253 | 280 | ||
254 | if (colorlen == 6) { | 281 | if (colorlen == 6) { |
255 | color <<= 8; | 282 | color <<= 8; |
@@ -259,14 +286,39 @@ int main(int argc, char **argv) { | |||
259 | break; | 286 | break; |
260 | } | 287 | } |
261 | case 'i': | 288 | case 'i': |
262 | image_path = optarg; | 289 | { |
290 | char *image_path = strchr(optarg, ':'); | ||
291 | if (image_path == NULL) { | ||
292 | if (num_images == 0) { | ||
293 | images = load_image(optarg); | ||
294 | num_images = -1; | ||
295 | } else { | ||
296 | fprintf(stderr, "display must be defined for all --images or no --images.\n"); | ||
297 | exit(EXIT_FAILURE); | ||
298 | } | ||
299 | } else { | ||
300 | if (num_images == 0) { | ||
301 | images = calloc(registry->outputs->length, sizeof(char*) * 2); | ||
302 | } else if (num_images == -1) { | ||
303 | fprintf(stderr, "display must be defined for all --images or no --images.\n"); | ||
304 | exit(EXIT_FAILURE); | ||
305 | } | ||
306 | |||
307 | image_path[0] = '\0'; | ||
308 | ((char**) images)[num_images * 2] = optarg; | ||
309 | ((char**) images)[num_images++ * 2 + 1] = ++image_path; | ||
310 | } | ||
263 | break; | 311 | break; |
312 | } | ||
264 | case 's': | 313 | case 's': |
265 | scaling_mode_str = optarg; | 314 | scaling_mode_str = optarg; |
266 | break; | 315 | break; |
267 | case 't': | 316 | case 't': |
268 | scaling_mode_str = "tile"; | 317 | scaling_mode_str = "tile"; |
269 | break; | 318 | break; |
319 | case 'p': | ||
320 | socket_path = optarg; | ||
321 | break; | ||
270 | case 'v': | 322 | case 'v': |
271 | #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE | 323 | #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE |
272 | fprintf(stdout, "swaylock version %s (%s, branch \"%s\")\n", SWAY_GIT_VERSION, SWAY_VERSION_DATE, SWAY_GIT_BRANCH); | 324 | fprintf(stdout, "swaylock version %s (%s, branch \"%s\")\n", SWAY_GIT_VERSION, SWAY_VERSION_DATE, SWAY_GIT_BRANCH); |
@@ -300,7 +352,12 @@ int main(int argc, char **argv) { | |||
300 | password = malloc(password_size); | 352 | password = malloc(password_size); |
301 | password[0] = '\0'; | 353 | password[0] = '\0'; |
302 | surfaces = create_list(); | 354 | surfaces = create_list(); |
303 | registry = registry_poll(); | 355 | if (!socket_path) { |
356 | socket_path = get_socketpath(); | ||
357 | if (!socket_path) { | ||
358 | sway_abort("Unable to retrieve socket path"); | ||
359 | } | ||
360 | } | ||
304 | 361 | ||
305 | if (!registry) { | 362 | if (!registry) { |
306 | sway_abort("Unable to connect to wayland compositor"); | 363 | sway_abort("Unable to connect to wayland compositor"); |
@@ -316,7 +373,6 @@ int main(int argc, char **argv) { | |||
316 | registry->pointer = NULL; | 373 | registry->pointer = NULL; |
317 | } | 374 | } |
318 | 375 | ||
319 | int i; | ||
320 | for (i = 0; i < registry->outputs->length; ++i) { | 376 | for (i = 0; i < registry->outputs->length; ++i) { |
321 | struct output_state *output = registry->outputs->items[i]; | 377 | struct output_state *output = registry->outputs->items[i]; |
322 | struct window *window = window_setup(registry, output->width, output->height, true); | 378 | struct window *window = window_setup(registry, output->width, output->height, true); |
@@ -328,23 +384,38 @@ int main(int argc, char **argv) { | |||
328 | 384 | ||
329 | registry->input->notify = notify_key; | 385 | registry->input->notify = notify_key; |
330 | 386 | ||
331 | cairo_surface_t *image = NULL; | 387 | if (num_images >= 1) { |
332 | 388 | char **displays_paths = images; | |
333 | if (image_path) { | 389 | images = calloc(registry->outputs->length, sizeof(cairo_surface_t*)); |
334 | #ifdef WITH_GDK_PIXBUF | 390 | |
335 | GError *err = NULL; | 391 | int socketfd = ipc_open_socket(socket_path); |
336 | GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); | 392 | uint32_t len = 0; |
337 | if (!pixbuf) { | 393 | char *outputs = ipc_single_command(socketfd, IPC_GET_OUTPUTS, "", &len); |
338 | sway_abort("Failed to load background image."); | 394 | struct json_object *json_outputs = json_tokener_parse(outputs); |
339 | } | 395 | |
340 | image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); | 396 | for (i = 0; i < registry->outputs->length; ++i) { |
341 | g_object_unref(pixbuf); | 397 | if (displays_paths[i * 2] != NULL) { |
342 | #else | 398 | for (int j = 0;; ++j) { |
343 | cairo_surface_t *image = cairo_image_surface_create_from_png(argv[1]); | 399 | if (j >= json_object_array_length(json_outputs)) { |
344 | #endif //WITH_GDK_PIXBUF | 400 | fprintf(stderr, "%s is not an extant display\n", displays_paths[i * 2]); |
345 | if (!image) { | 401 | exit(EXIT_FAILURE); |
346 | sway_abort("Failed to read background image."); | 402 | } |
403 | |||
404 | struct json_object *dsp_name, *at_j = json_object_array_get_idx(json_outputs, j); | ||
405 | if (!json_object_object_get_ex(at_j, "name", &dsp_name)) { | ||
406 | sway_abort("display doesn't have a name field"); | ||
407 | } | ||
408 | if (!strcmp(displays_paths[i * 2], json_object_get_string(dsp_name))) { | ||
409 | ((cairo_surface_t**) images)[j] = load_image(displays_paths[i * 2 + 1]); | ||
410 | break; | ||
411 | } | ||
412 | } | ||
413 | } | ||
347 | } | 414 | } |
415 | |||
416 | json_object_put(json_outputs); | ||
417 | close(socketfd); | ||
418 | free(displays_paths); | ||
348 | } | 419 | } |
349 | 420 | ||
350 | for (i = 0; i < surfaces->length; ++i) { | 421 | for (i = 0; i < surfaces->length; ++i) { |
@@ -352,15 +423,31 @@ int main(int argc, char **argv) { | |||
352 | if (!window_prerender(window) || !window->cairo) { | 423 | if (!window_prerender(window) || !window->cairo) { |
353 | continue; | 424 | continue; |
354 | } | 425 | } |
355 | if (image) { | 426 | |
356 | render_image(window, image, scaling_mode); | 427 | if (num_images == 0 || color_set) { |
357 | } else { | ||
358 | render_color(window, color); | 428 | render_color(window, color); |
359 | } | 429 | } |
430 | |||
431 | if (num_images == -1) { | ||
432 | render_image(window, images, scaling_mode); | ||
433 | } else if (num_images >= 1) { | ||
434 | if (((cairo_surface_t**) images)[i] != NULL) { | ||
435 | render_image(window, ((cairo_surface_t**) images)[i], scaling_mode); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | window_render(window); | ||
360 | } | 440 | } |
361 | 441 | ||
362 | if (image) { | 442 | if (num_images == -1) { |
363 | cairo_surface_destroy(image); | 443 | cairo_surface_destroy((cairo_surface_t*) images); |
444 | } else if (num_images >= 1) { | ||
445 | for (i = 0; i < registry->outputs->length; ++i) { | ||
446 | if (((cairo_surface_t**) images)[i] != NULL) { | ||
447 | cairo_surface_destroy(((cairo_surface_t**) images)[i]); | ||
448 | } | ||
449 | } | ||
450 | free(images); | ||
364 | } | 451 | } |
365 | 452 | ||
366 | bool locked = false; | 453 | bool locked = false; |