diff options
-rw-r--r-- | include/sway/commands.h | 1 | ||||
-rw-r--r-- | include/sway/config.h | 1 | ||||
-rw-r--r-- | include/swaybar/config.h | 6 | ||||
-rw-r--r-- | sway/commands/bar.c | 1 | ||||
-rw-r--r-- | sway/commands/bar/gaps.c | 60 | ||||
-rw-r--r-- | sway/ipc-json.c | 12 | ||||
-rw-r--r-- | sway/ipc-server.c | 13 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/sway-bar.5.scd | 7 | ||||
-rw-r--r-- | swaybar/config.c | 6 | ||||
-rw-r--r-- | swaybar/ipc.c | 42 | ||||
-rw-r--r-- | swaybar/render.c | 5 | ||||
-rw-r--r-- | swaymsg/main.c | 70 | ||||
-rw-r--r-- | swaymsg/swaymsg.1.scd | 11 |
14 files changed, 217 insertions, 19 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h index c3913c79..1f2376d0 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -188,6 +188,7 @@ sway_cmd bar_cmd_bindsym; sway_cmd bar_cmd_colors; sway_cmd bar_cmd_context_button; sway_cmd bar_cmd_font; +sway_cmd bar_cmd_gaps; sway_cmd bar_cmd_mode; sway_cmd bar_cmd_modifier; sway_cmd bar_cmd_output; diff --git a/include/sway/config.h b/include/sway/config.h index d02b0d63..58b7010e 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -227,6 +227,7 @@ struct bar_config { bool strip_workspace_name; bool binding_mode_indicator; bool verbose; + struct side_gaps gaps; pid_t pid; struct { char *background; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 700e6b60..fd7c6ec4 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -42,6 +42,12 @@ struct swaybar_config { struct wl_list outputs; // config_output::link bool all_outputs; int height; + struct { + int top; + int right; + int bottom; + int left; + } gaps; struct { uint32_t background; diff --git a/sway/commands/bar.c b/sway/commands/bar.c index f9ed530e..0cf94907 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -14,6 +14,7 @@ static struct cmd_handler bar_handlers[] = { { "colors", bar_cmd_colors }, { "context_button", bar_cmd_context_button }, { "font", bar_cmd_font }, + { "gaps", bar_cmd_gaps }, { "height", bar_cmd_height }, { "hidden_state", bar_cmd_hidden_state }, { "icon_theme", bar_cmd_icon_theme }, diff --git a/sway/commands/bar/gaps.c b/sway/commands/bar/gaps.c new file mode 100644 index 00000000..f78f3742 --- /dev/null +++ b/sway/commands/bar/gaps.c @@ -0,0 +1,60 @@ +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include "sway/commands.h" +#include "sway/ipc-server.h" +#include "log.h" + +struct cmd_results *bar_cmd_gaps(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1))) { + return error; + } + if ((error = checkarg(argc, "gaps", EXPECTED_AT_MOST, 4))) { + return error; + } + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "bar gaps", "No bar defined."); + } + + int top = 0, right = 0, bottom = 0, left = 0; + + for (int i = 0; i < argc; i++) { + char *end; + int amount = strtol(argv[i], &end, 10); + if (strlen(end) && strcasecmp(end, "px") != 0) { + return cmd_results_new(CMD_INVALID, "bar gaps", + "Expected 'bar [<bar-id>] gaps <all> | <horizonal> " + "<vertical> | <top> <right> <bottom> <left>'"); + } + + if (i == 0) { + top = amount; + } + if (i == 0 || i == 1) { + right = amount; + } + if (i == 0 || i == 2) { + bottom = amount; + } + if (i == 0 || i == 1 || i == 3) { + left = amount; + } + } + + config->current_bar->gaps.top = top; + config->current_bar->gaps.right = right; + config->current_bar->gaps.bottom = bottom; + config->current_bar->gaps.left = left; + + wlr_log(WLR_DEBUG, "Setting bar gaps to %d %d %d %d on bar: %s", + config->current_bar->gaps.top, config->current_bar->gaps.right, + config->current_bar->gaps.bottom, config->current_bar->gaps.left, + config->current_bar->id); + + if (!config->reading) { + ipc_event_barconfig_update(config->current_bar); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 40fbd3e7..fc631373 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -638,6 +638,18 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object_new_string(bar->status_command) : NULL); json_object_object_add(json, "font", json_object_new_string((bar->font) ? bar->font : config->font)); + + json_object *gaps = json_object_new_object(); + json_object_object_add(gaps, "top", + json_object_new_int(bar->gaps.top)); + json_object_object_add(gaps, "right", + json_object_new_int(bar->gaps.right)); + json_object_object_add(gaps, "bottom", + json_object_new_int(bar->gaps.bottom)); + json_object_object_add(gaps, "left", + json_object_new_int(bar->gaps.left)); + json_object_object_add(json, "gaps", gaps); + if (bar->separator_symbol) { json_object_object_add(json, "separator_symbol", json_object_new_string(bar->separator_symbol)); diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 95433d97..e3d73522 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -668,7 +668,8 @@ void ipc_client_handle_command(struct ipc_client *client) { // TODO: Check if they're permitted to use these events struct json_object *request = json_tokener_parse(buf); if (request == NULL) { - client_valid = ipc_send_reply(client, "{\"success\": false}", 18); + const char msg[] = "[{\"success\": false}]"; + client_valid = ipc_send_reply(client, msg, strlen(msg)); wlr_log(WLR_INFO, "Failed to parse subscribe request"); goto exit_cleanup; } @@ -695,8 +696,8 @@ void ipc_client_handle_command(struct ipc_client *client) { client->subscribed_events |= event_mask(IPC_EVENT_TICK); is_tick = true; } else { - client_valid = - ipc_send_reply(client, "{\"success\": false}", 18); + const char msg[] = "[{\"success\": false}]"; + client_valid = ipc_send_reply(client, msg, strlen(msg)); json_object_put(request); wlr_log(WLR_INFO, "Unsupported event type in subscribe request"); goto exit_cleanup; @@ -704,10 +705,12 @@ void ipc_client_handle_command(struct ipc_client *client) { } json_object_put(request); - client_valid = ipc_send_reply(client, "{\"success\": true}", 17); + const char msg[] = "[{\"success\": true}]"; + client_valid = ipc_send_reply(client, msg, strlen(msg)); if (is_tick) { client->current_command = IPC_EVENT_TICK; - ipc_send_reply(client, "{\"first\": true, \"payload\": \"\"}", 30); + const char tickmsg[] = "{\"first\": true, \"payload\": \"\"}"; + ipc_send_reply(client, tickmsg, strlen(tickmsg)); } goto exit_cleanup; } diff --git a/sway/meson.build b/sway/meson.build index 75131891..51b40020 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -104,6 +104,7 @@ sway_sources = files( 'commands/bar/colors.c', 'commands/bar/context_button.c', 'commands/bar/font.c', + 'commands/bar/gaps.c', 'commands/bar/height.c', 'commands/bar/hidden_state.c', 'commands/bar/icon_theme.c', diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd index 60ee9999..a3c6af2e 100644 --- a/sway/sway-bar.5.scd +++ b/sway/sway-bar.5.scd @@ -61,6 +61,13 @@ Sway allows configuring swaybar in the sway configuration file. *binding\_mode\_indicator* yes|no Enable or disable binding mode indicator. Default is _yes_. +*gaps* <all> | <horizontal> <vertical> | <top> <right> <bottom> <left> + Sets the gaps from the edge of the screen for the bar. Gaps can either be + set all at once, per direction, or per side. Note that only sides that + touch an edge of the screen can have gaps. For the side that does not + touch an edge of the screen, per-side outer gaps for workspaces may be of + use. + *height* <height> Sets the height of the bar. Default height will match the font size. diff --git a/swaybar/config.c b/swaybar/config.c index 16febb2e..10c78c8a 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -40,6 +40,12 @@ struct swaybar_config *init_config(void) { /* height */ config->height = 0; + /* gaps */ + config->gaps.top = 0; + config->gaps.right = 0; + config->gaps.bottom = 0; + config->gaps.left = 0; + /* colors */ config->colors.background = 0x000000FF; config->colors.focused_background = 0x000000FF; diff --git a/swaybar/ipc.c b/swaybar/ipc.c index db4360c1..2b930786 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -153,7 +153,7 @@ static bool ipc_parse_config( return false; } json_object *markup, *mode, *hidden_state, *position, *status_command; - json_object *font, *bar_height, *wrap_scroll, *workspace_buttons; + json_object *font, *gaps, *bar_height, *wrap_scroll, *workspace_buttons; json_object *strip_workspace_numbers, *strip_workspace_name; json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol; json_object *outputs, *bindings; @@ -162,6 +162,7 @@ static bool ipc_parse_config( json_object_object_get_ex(bar_config, "position", &position); json_object_object_get_ex(bar_config, "status_command", &status_command); json_object_object_get_ex(bar_config, "font", &font); + json_object_object_get_ex(bar_config, "gaps", &gaps); json_object_object_get_ex(bar_config, "bar_height", &bar_height); json_object_object_get_ex(bar_config, "wrap_scroll", &wrap_scroll); json_object_object_get_ex(bar_config, "workspace_buttons", &workspace_buttons); @@ -207,6 +208,24 @@ static bool ipc_parse_config( if (bar_height) { config->height = json_object_get_int(bar_height); } + if (gaps) { + json_object *top = json_object_object_get(gaps, "top"); + if (top) { + config->gaps.top = json_object_get_int(top); + } + json_object *right = json_object_object_get(gaps, "right"); + if (right) { + config->gaps.right = json_object_get_int(right); + } + json_object *bottom = json_object_object_get(gaps, "bottom"); + if (bottom) { + config->gaps.bottom = json_object_get_int(bottom); + } + json_object *left = json_object_object_get(gaps, "left"); + if (left) { + config->gaps.left = json_object_get_int(left); + } + } if (markup) { config->pango_markup = json_object_get_boolean(markup); } @@ -446,6 +465,27 @@ static bool handle_barconfig_update(struct swaybar *bar, config->mode = strdup(json_object_get_string(json_mode)); wlr_log(WLR_DEBUG, "Changing bar mode to %s", config->mode); + json_object *gaps; + json_object_object_get_ex(json_config, "gaps", &gaps); + if (gaps) { + json_object *top = json_object_object_get(gaps, "top"); + if (top) { + config->gaps.top = json_object_get_int(top); + } + json_object *right = json_object_object_get(gaps, "right"); + if (right) { + config->gaps.right = json_object_get_int(right); + } + json_object *bottom = json_object_object_get(gaps, "bottom"); + if (bottom) { + config->gaps.bottom = json_object_get_int(bottom); + } + json_object *left = json_object_object_get(gaps, "left"); + if (left) { + config->gaps.left = json_object_get_int(left); + } + } + return determine_bar_visibility(bar, true); } diff --git a/swaybar/render.c b/swaybar/render.c index 8269a840..77cfecbf 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -506,6 +506,11 @@ void render_frame(struct swaybar_output *output) { if (height != output->height || output->width == 0) { // Reconfigure surface zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); + zwlr_layer_surface_v1_set_margin(output->layer_surface, + output->bar->config->gaps.top, + output->bar->config->gaps.right, + output->bar->config->gaps.bottom, + output->bar->config->gaps.left); if (strcmp(output->bar->config->mode, "dock") == 0) { zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); } diff --git a/swaymsg/main.c b/swaymsg/main.c index e640cadf..3e61b94a 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -305,8 +305,9 @@ static void pretty_print(int type, json_object *resp) { } int main(int argc, char **argv) { - static int quiet = 0; - static int raw = 0; + static bool quiet = false; + static bool raw = false; + static bool monitor = false; char *socket_path = NULL; char *cmdtype = NULL; @@ -314,6 +315,7 @@ int main(int argc, char **argv) { static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, + {"monitor", no_argument, NULL, 'm'}, {"quiet", no_argument, NULL, 'q'}, {"raw", no_argument, NULL, 'r'}, {"socket", required_argument, NULL, 's'}, @@ -326,6 +328,7 @@ int main(int argc, char **argv) { "Usage: swaymsg [options] [message]\n" "\n" " -h, --help Show help message and quit.\n" + " -m, --monitor Monitor until killed (-t SUBSCRIBE only)\n" " -q, --quiet Be quiet.\n" " -r, --raw Use raw output even if using a tty\n" " -s, --socket <socket> Use the specified socket.\n" @@ -337,16 +340,19 @@ int main(int argc, char **argv) { int c; while (1) { int option_index = 0; - c = getopt_long(argc, argv, "hqrs:t:v", long_options, &option_index); + c = getopt_long(argc, argv, "hmqrs:t:v", long_options, &option_index); if (c == -1) { break; } switch (c) { + case 'm': // Monitor + monitor = true; + break; case 'q': // Quiet - quiet = 1; + quiet = true; break; case 'r': // Raw - raw = 1; + raw = true; break; case 's': // Socket socket_path = strdup(optarg); @@ -400,12 +406,20 @@ int main(int argc, char **argv) { type = IPC_GET_CONFIG; } else if (strcasecmp(cmdtype, "send_tick") == 0) { type = IPC_SEND_TICK; + } else if (strcasecmp(cmdtype, "subscribe") == 0) { + type = IPC_SUBSCRIBE; } else { sway_abort("Unknown message type %s", cmdtype); } free(cmdtype); + if (monitor && type != IPC_SUBSCRIBE) { + wlr_log(WLR_ERROR, "Monitor can only be used with -t SUBSCRIBE"); + free(socket_path); + return 1; + } + char *command = NULL; if (optind < argc) { command = join_args(argv + optind, argc - optind); @@ -422,26 +436,56 @@ int main(int argc, char **argv) { json_object *obj = json_tokener_parse(resp); if (obj == NULL) { - fprintf(stderr, "ERROR: Could not parse json response from ipc. This is a bug in sway."); + fprintf(stderr, "ERROR: Could not parse json response from ipc. " + "This is a bug in sway."); printf("%s\n", resp); ret = 1; } else { if (!success(obj, true)) { ret = 1; } - if (raw) { - printf("%s\n", json_object_to_json_string_ext(obj, - JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); - } else { - pretty_print(type, obj); + if (type != IPC_SUBSCRIBE || ret != 0) { + if (raw) { + printf("%s\n", json_object_to_json_string_ext(obj, + JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); + } else { + pretty_print(type, obj); + } } json_object_put(obj); } } - close(socketfd); - free(command); free(resp); + + if (type == IPC_SUBSCRIBE && ret == 0) { + do { + struct ipc_response *reply = ipc_recv_response(socketfd); + if (!reply) { + break; + } + + json_object *obj = json_tokener_parse(reply->payload); + if (obj == NULL) { + fprintf(stderr, "ERROR: Could not parse json response from ipc" + ". This is a bug in sway."); + ret = 1; + break; + } else { + if (raw) { + printf("%s\n", json_object_to_json_string(obj)); + } else { + printf("%s\n", json_object_to_json_string_ext(obj, + JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); + } + json_object_put(obj); + } + + free_ipc_response(reply); + } while (monitor); + } + + close(socketfd); free(socket_path); return ret; } diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index eaac8105..f55f86a9 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd @@ -13,6 +13,12 @@ _swaymsg_ [options...] [message] *-h, --help* Show help message and quit. +*-m, --monitor* + Monitor for responses until killed instead of exiting after the first + response. This can only be used with the IPC message type _subscribe_. If + there is a malformed response or an invalid event type was requested, + swaymsg will stop monitoring and exit. + *-q, --quiet* Sends the IPC message but does not print the response from sway. @@ -71,3 +77,8 @@ _swaymsg_ [options...] [message] *send\_tick* Sends a tick event to all subscribed clients. + +*subscribe* + Subscribe to a list of event types. The argument for this type should be + provided in the form of a valid JSON array. If any of the types are invalid + or if an valid JSON array is not provided, this will result in an failure. |