From 1d010afbf72355eae0fdffa249f2588cb801c302 Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Tue, 22 Mar 2016 11:27:36 +0100 Subject: [PATCH 1/9] Abort when receiving 0 bytes in IPC call When sway crashes a swaybar process is sometimes left behind running at 100% CPU. This was caused by the swaybar trying to retrieve an IPC response from the closed sway socket. This patch fixes the problem by aborting when the socket has been closed (recv return 0). Fix #528 --- common/ipc-client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/ipc-client.c b/common/ipc-client.c index 81348913..93f2963c 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -47,7 +47,7 @@ struct ipc_response *ipc_recv_response(int socketfd) { size_t total = 0; while (total < ipc_header_size) { ssize_t received = recv(socketfd, data + total, ipc_header_size - total, 0); - if (received < 0) { + if (received <= 0) { sway_abort("Unable to receive IPC response"); } total += received; From a8f989c6516e52ac6fe5380f39c94e470b7892e8 Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Wed, 23 Mar 2016 14:25:58 +0100 Subject: [PATCH 2/9] swaylock: Fix crash when unable to connect to wl Prevent swaylock from crashing when it can't connect to wayland for whatever reason. i.e. XDG_RUNTIME_DIR not set. Fix #534 --- swaylock/main.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/swaylock/main.c b/swaylock/main.c index f2015a05..3f0fc867 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -31,7 +31,9 @@ void sway_terminate(int exit_code) { window_teardown(window); } list_free(surfaces); - registry_teardown(registry); + if (registry) { + registry_teardown(registry); + } exit(exit_code); } @@ -292,6 +294,10 @@ int main(int argc, char **argv) { surfaces = create_list(); registry = registry_poll(); + if (!registry) { + sway_abort("Unable to connect to wayland compositor"); + } + if (!registry->swaylock) { sway_abort("swaylock requires the compositor to support the swaylock extension."); } From 5c85c018b4692e1bccedaf9d10be052b79e7dc63 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 24 Mar 2016 14:08:53 -0400 Subject: [PATCH 3/9] Update to new WLC API --- include/handlers.h | 3 ++- sway/handlers.c | 54 ++++++++++++++++------------------------------ sway/main.c | 3 ++- 3 files changed, 23 insertions(+), 37 deletions(-) diff --git a/include/handlers.h b/include/handlers.h index d7f6ffdd..956b98f4 100644 --- a/include/handlers.h +++ b/include/handlers.h @@ -4,7 +4,8 @@ #include #include -extern struct wlc_interface interface; +void register_wlc_handlers(); + extern uint32_t keys_pressed[32]; #endif diff --git a/sway/handlers.c b/sway/handlers.c index cec63192..7d4ea263 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -706,38 +706,22 @@ static void handle_wlc_ready(void) { } } -struct wlc_interface interface = { - .output = { - .created = handle_output_created, - .destroyed = handle_output_destroyed, - .resolution = handle_output_resolution_change, - .focus = handle_output_focused, - .render = { - .pre = handle_output_pre_render, - .post = handle_output_post_render - } - }, - .view = { - .created = handle_view_created, - .destroyed = handle_view_destroyed, - .focus = handle_view_focus, - .request = { - .geometry = handle_view_geometry_request, - .state = handle_view_state_request - } - }, - .keyboard = { - .key = handle_key - }, - .pointer = { - .motion = handle_pointer_motion, - .button = handle_pointer_button - }, - .compositor = { - .ready = handle_wlc_ready - }, - .input = { - .created = handle_input_created, - .destroyed = handle_input_destroyed - } -}; +void register_wlc_handlers() { + wlc_set_output_created_cb(handle_output_created); + wlc_set_output_destroyed_cb(handle_output_destroyed); + wlc_set_output_resolution_cb(handle_output_resolution_change); + wlc_set_output_focus_cb(handle_output_focused); + wlc_set_output_render_pre_cb(handle_output_pre_render); + wlc_set_output_render_post_cb(handle_output_post_render); + wlc_set_view_created_cb(handle_view_created); + wlc_set_view_destroyed_cb(handle_view_destroyed); + wlc_set_view_focus_cb(handle_view_focus); + wlc_set_view_request_geometry_cb(handle_view_geometry_request); + wlc_set_view_request_state_cb(handle_view_state_request); + wlc_set_keyboard_key_cb(handle_key); + wlc_set_pointer_motion_cb(handle_pointer_motion); + wlc_set_pointer_button_cb(handle_pointer_button); + wlc_set_compositor_ready_cb(handle_wlc_ready); + wlc_set_input_created_cb(handle_input_created); + wlc_set_input_destroyed_cb(handle_input_destroyed); +} diff --git a/sway/main.c b/sway/main.c index 7c712281..d4f18e9a 100644 --- a/sway/main.c +++ b/sway/main.c @@ -187,7 +187,8 @@ int main(int argc, char **argv) { /* Changing code earlier than this point requires detailed review */ /* (That code runs as root on systems without logind, and wlc_init drops to * another user.) */ - if (!wlc_init(&interface, argc, argv)) { + register_wlc_handlers(); + if (!wlc_init2()) { return 1; } register_extensions(); From fd061d4dc4691234c567157869eb9758a82c16e0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 24 Mar 2016 14:09:18 -0400 Subject: [PATCH 4/9] Don't set WLC_DIM on startup --- sway/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sway/main.c b/sway/main.c index d4f18e9a..810bd12c 100644 --- a/sway/main.c +++ b/sway/main.c @@ -178,7 +178,6 @@ int main(int argc, char **argv) { } else { init_log(L_ERROR); } - setenv("WLC_DIM", "0", 0); wlc_log_set_handler(wlc_log_handler); detect_proprietary(); From fb4fdf5336b32e7354110b3d526b8037fefbbf8e Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 24 Mar 2016 14:24:43 -0400 Subject: [PATCH 5/9] Update README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 63bff3a2..9de24bbb 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ irc.freenode.net). ![](https://sr.ht/NCx_.png) -## Rationale +## Release Signatures -I use i3 on xorg. Wayland is coming, and [i3way](http://i3way.org/) still has -zero lines of source code after two years. +Releases are signed with [B22DA89A](http://pgp.mit.edu/pks/lookup?search=B22DA89A&op=index) +and published [on GitHub](https://github.com/SirCmpwn/sway/releases). ## Status From 956ca66d2c9ea4408b9bf432d4103050856b1365 Mon Sep 17 00:00:00 2001 From: Julius Michaelis Date: Thu, 24 Mar 2016 19:31:48 +0100 Subject: [PATCH 6/9] swaylock: Interpret XKB_KEY_BackSpace as a deletion instead of a normal key. --- swaylock/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/swaylock/main.c b/swaylock/main.c index 3f0fc867..feb64975 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -108,6 +108,14 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod password = malloc(password_size); password[0] = '\0'; break; + case XKB_KEY_BackSpace: + { + int i = strlen(password); + if (i > 0) { + password[i - 1] = '\0'; + } + break; + } default: { int i = strlen(password); From 06107bb44eddec993354883436767b931f2aa4d7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 24 Mar 2016 16:48:42 -0400 Subject: [PATCH 7/9] Make the nvidia warning louder --- sway/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sway/main.c b/sway/main.c index 810bd12c..eef1ad19 100644 --- a/sway/main.c +++ b/sway/main.c @@ -53,6 +53,7 @@ void detect_proprietary() { char *line = read_line(f); if (strstr(line, "nvidia")) { fprintf(stderr, "\x1B[1;31mWarning: Proprietary nvidia drivers do NOT support Wayland. Use nouveau.\x1B[0m\n"); + fprintf(stderr, "\x1B[1;31mYes, they STILL don't work with the newly announced wayland \"support\".\x1B[0m\n"); free(line); break; } From 938ff29b7b14d9840a92acb1d1ee4192bfc8e89e Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Thu, 24 Mar 2016 22:13:42 +0100 Subject: [PATCH 8/9] Gracefully exit when config is not found This makes sure that sway will gracefully exit if the config is not found or sway is unable to read it. --- sway/config.c | 8 ++++++-- sway/main.c | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/sway/config.c b/sway/config.c index ebf7546d..a5fdf850 100644 --- a/sway/config.c +++ b/sway/config.c @@ -256,7 +256,7 @@ bool load_config(const char *file) { FILE *f = fopen(path, "r"); if (!f) { - fprintf(stderr, "Unable to open %s for reading", path); + sway_log(L_ERROR, "Unable to open %s for reading", path); free(path); return false; } @@ -272,7 +272,11 @@ bool load_config(const char *file) { update_active_bar_modifiers(); - return config_load_success; + if (!config_load_success) { + sway_log(L_ERROR, "Error(s) loading config!"); + } + + return true; } bool read_config(FILE *file, bool is_active) { diff --git a/sway/main.c b/sway/main.c index eef1ad19..c4a5d497 100644 --- a/sway/main.c +++ b/sway/main.c @@ -211,8 +211,9 @@ int main(int argc, char **argv) { } if (!load_config(config_path)) { - sway_log(L_ERROR, "Error(s) loading config!"); + sway_terminate(EXIT_FAILURE); } + if (config_path) { free(config_path); } From 0aa4383c9a1b3b693ee771e7829ed84582b4577c Mon Sep 17 00:00:00 2001 From: Nuew Date: Thu, 24 Mar 2016 18:02:34 -0400 Subject: [PATCH 9/9] 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. --- swaylock/CMakeLists.txt | 2 + swaylock/main.c | 153 +++++++++++++++++++++++++++++++--------- swaylock/swaylock.1.txt | 12 +++- 3 files changed, 131 insertions(+), 36 deletions(-) diff --git a/swaylock/CMakeLists.txt b/swaylock/CMakeLists.txt index 08c893ca..b290cd2f 100644 --- a/swaylock/CMakeLists.txt +++ b/swaylock/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories( ${CAIRO_INCLUDE_DIRS} ${PANGO_INCLUDE_DIRS} ${PAM_INCLUDE_DIRS} + ${JSONC_INCLUDE_DIRS} ) add_executable(swaylock @@ -18,6 +19,7 @@ target_link_libraries(swaylock ${CAIRO_LIBRARIES} ${PANGO_LIBRARIES} ${PAM_LIBRARIES} + ${JSONC_LIBRARIES} m ) 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 @@ #include #include #include +#include #include #include #include @@ -11,6 +12,7 @@ #include "client/window.h" #include "client/registry.h" #include "client/cairo.h" +#include "ipc-client.h" #include "log.h" list_t *surfaces; @@ -134,7 +136,6 @@ void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t cod void render_color(struct window *window, uint32_t color) { cairo_set_source_u32(window->cairo, color); cairo_paint(window->cairo); - window_render(window); } 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 } cairo_paint(window->cairo); +} - window_render(window); +cairo_surface_t *load_image(char *image_path) { + cairo_surface_t *image = NULL; + +#ifdef WITH_GDK_PIXBUF + GError *err = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); + if (!pixbuf) { + fprintf(stderr, "GDK Error: %s\n", err->message); + sway_abort("Failed to load background image."); + } + image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); + g_object_unref(pixbuf); +#else + image = cairo_image_surface_create_from_png(image_path); +#endif //WITH_GDK_PIXBUF + if (!image) { + sway_abort("Failed to read background image."); + } + + return image; } int main(int argc, char **argv) { - char *image_path = NULL; - char *scaling_mode_str = "fit"; + char *scaling_mode_str = "fit", *socket_path = NULL; + int i, num_images = 0, color_set = 0; uint32_t color = 0xFFFFFFFF; + void *images; init_log(L_INFO); @@ -221,18 +243,22 @@ int main(int argc, char **argv) { {"scaling", required_argument, NULL, 's'}, {"tiling", no_argument, NULL, 't'}, {"version", no_argument, NULL, 'v'}, + {"socket", required_argument, NULL, 'p'}, {0, 0, 0, 0} }; const char *usage = "Usage: swaylock [options...]\n" "\n" - " -h, --help Show help message and quit.\n" - " -c, --color Turn the screen into the given color instead of white.\n" - " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" - " -t, --tiling Same as --scaling=tile.\n" - " -v, --version Show the version number and quit.\n" - " -i, --image Display the given image.\n"; + " -h, --help Show help message and quit.\n" + " -c, --color Turn the screen into the given color instead of white.\n" + " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" + " -t, --tiling Same as --scaling=tile.\n" + " -v, --version Show the version number and quit.\n" + " -i, --image [:] Display the given image.\n" + " --socket Use the specified socket.\n"; + + registry = registry_poll(); int c; while (1) { @@ -250,6 +276,7 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } color = strtol(optarg, NULL, 16); + color_set = 1; if (colorlen == 6) { color <<= 8; @@ -259,14 +286,39 @@ int main(int argc, char **argv) { break; } case 'i': - image_path = optarg; + { + char *image_path = strchr(optarg, ':'); + if (image_path == NULL) { + if (num_images == 0) { + images = load_image(optarg); + num_images = -1; + } else { + fprintf(stderr, "display must be defined for all --images or no --images.\n"); + exit(EXIT_FAILURE); + } + } else { + if (num_images == 0) { + images = calloc(registry->outputs->length, sizeof(char*) * 2); + } else if (num_images == -1) { + fprintf(stderr, "display must be defined for all --images or no --images.\n"); + exit(EXIT_FAILURE); + } + + image_path[0] = '\0'; + ((char**) images)[num_images * 2] = optarg; + ((char**) images)[num_images++ * 2 + 1] = ++image_path; + } break; + } case 's': scaling_mode_str = optarg; break; case 't': scaling_mode_str = "tile"; break; + case 'p': + socket_path = optarg; + break; case 'v': #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE 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) { password = malloc(password_size); password[0] = '\0'; surfaces = create_list(); - registry = registry_poll(); + if (!socket_path) { + socket_path = get_socketpath(); + if (!socket_path) { + sway_abort("Unable to retrieve socket path"); + } + } if (!registry) { sway_abort("Unable to connect to wayland compositor"); @@ -316,7 +373,6 @@ int main(int argc, char **argv) { registry->pointer = NULL; } - int i; for (i = 0; i < registry->outputs->length; ++i) { struct output_state *output = registry->outputs->items[i]; struct window *window = window_setup(registry, output->width, output->height, true); @@ -328,23 +384,38 @@ int main(int argc, char **argv) { registry->input->notify = notify_key; - cairo_surface_t *image = NULL; + if (num_images >= 1) { + char **displays_paths = images; + images = calloc(registry->outputs->length, sizeof(cairo_surface_t*)); - if (image_path) { -#ifdef WITH_GDK_PIXBUF - GError *err = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); - if (!pixbuf) { - sway_abort("Failed to load background image."); - } - image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); - g_object_unref(pixbuf); -#else - cairo_surface_t *image = cairo_image_surface_create_from_png(argv[1]); -#endif //WITH_GDK_PIXBUF - if (!image) { - sway_abort("Failed to read background image."); + int socketfd = ipc_open_socket(socket_path); + uint32_t len = 0; + char *outputs = ipc_single_command(socketfd, IPC_GET_OUTPUTS, "", &len); + struct json_object *json_outputs = json_tokener_parse(outputs); + + for (i = 0; i < registry->outputs->length; ++i) { + if (displays_paths[i * 2] != NULL) { + for (int j = 0;; ++j) { + if (j >= json_object_array_length(json_outputs)) { + fprintf(stderr, "%s is not an extant display\n", displays_paths[i * 2]); + exit(EXIT_FAILURE); + } + + struct json_object *dsp_name, *at_j = json_object_array_get_idx(json_outputs, j); + if (!json_object_object_get_ex(at_j, "name", &dsp_name)) { + sway_abort("display doesn't have a name field"); + } + if (!strcmp(displays_paths[i * 2], json_object_get_string(dsp_name))) { + ((cairo_surface_t**) images)[j] = load_image(displays_paths[i * 2 + 1]); + break; + } + } + } } + + json_object_put(json_outputs); + close(socketfd); + free(displays_paths); } for (i = 0; i < surfaces->length; ++i) { @@ -352,15 +423,31 @@ int main(int argc, char **argv) { if (!window_prerender(window) || !window->cairo) { continue; } - if (image) { - render_image(window, image, scaling_mode); - } else { + + if (num_images == 0 || color_set) { render_color(window, color); } + + if (num_images == -1) { + render_image(window, images, scaling_mode); + } else if (num_images >= 1) { + if (((cairo_surface_t**) images)[i] != NULL) { + render_image(window, ((cairo_surface_t**) images)[i], scaling_mode); + } + } + + window_render(window); } - if (image) { - cairo_surface_destroy(image); + if (num_images == -1) { + cairo_surface_destroy((cairo_surface_t*) images); + } else if (num_images >= 1) { + for (i = 0; i < registry->outputs->length; ++i) { + if (((cairo_surface_t**) images)[i] != NULL) { + cairo_surface_destroy(((cairo_surface_t**) images)[i]); + } + } + free(images); } bool locked = false; diff --git a/swaylock/swaylock.1.txt b/swaylock/swaylock.1.txt index 04594fd0..724573ce 100644 --- a/swaylock/swaylock.1.txt +++ b/swaylock/swaylock.1.txt @@ -23,10 +23,11 @@ Options Show help message and quit. *-c, \--color* :: - Turn the screen into the given color instead of white. + Turn the screen into the given color instead of white. If an image is in use, + also enables color display. -*-i, \--image* :: - Display the given image. +*-i, \--image* [:]:: + Display the given image, optionally only on the given display. *-s, \--scaling*:: Scaling mode for images: stretch, fill, fit, center, or tile. @@ -37,6 +38,11 @@ Options *-v, \--version*:: Show the version number and quit. +*--socket *:: + Use the specified socket path. Otherwise, swaymsg will ask sway where the + socket is (which is the value of $SWAYSOCK, then of $I3SOCK). + + Authors -------