diff --git a/common/util.c b/common/util.c index f4588b57..abaca17f 100644 --- a/common/util.c +++ b/common/util.c @@ -1,4 +1,4 @@ -#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200809L #include #include #include @@ -23,7 +23,8 @@ int numlen(int n) { if (n == 0) { return 1; } - return log10(n) + 1; + // Account for the '-' in negative numbers. + return log10(abs(n)) + (n > 0 ? 1 : 2); } static struct modifier_key { diff --git a/include/sway/commands.h b/include/sway/commands.h index 6606775a..45f9addd 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -198,6 +198,7 @@ sway_cmd bar_cmd_separator_symbol; sway_cmd bar_cmd_status_command; sway_cmd bar_cmd_pango_markup; sway_cmd bar_cmd_strip_workspace_numbers; +sway_cmd bar_cmd_strip_workspace_name; sway_cmd bar_cmd_swaybar_command; sway_cmd bar_cmd_tray_output; sway_cmd bar_cmd_tray_padding; diff --git a/include/sway/config.h b/include/sway/config.h index 852d5576..5a355139 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -213,6 +213,7 @@ struct bar_config { bool wrap_scroll; char *separator_symbol; bool strip_workspace_numbers; + bool strip_workspace_name; bool binding_mode_indicator; bool verbose; pid_t pid; diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 95b20510..57c5114e 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -68,6 +68,7 @@ struct swaybar_workspace { struct wl_list link; // swaybar_output::workspaces int num; char *name; + char *label; bool focused; bool visible; bool urgent; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 5d40790a..700e6b60 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -34,6 +34,7 @@ struct swaybar_config { char *hidden_state; char *modifier; bool strip_workspace_numbers; + bool strip_workspace_name; bool binding_mode_indicator; bool wrap_scroll; bool workspace_buttons; diff --git a/sway/commands/bar.c b/sway/commands/bar.c index c808aef2..f9ed530e 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -25,6 +25,7 @@ static struct cmd_handler bar_handlers[] = { { "secondary_button", bar_cmd_secondary_button }, { "separator_symbol", bar_cmd_separator_symbol }, { "status_command", bar_cmd_status_command }, + { "strip_workspace_name", bar_cmd_strip_workspace_name }, { "strip_workspace_numbers", bar_cmd_strip_workspace_numbers }, { "tray_output", bar_cmd_tray_output }, { "tray_padding", bar_cmd_tray_padding }, diff --git a/sway/commands/bar/strip_workspace_name.c b/sway/commands/bar/strip_workspace_name.c new file mode 100644 index 00000000..79692f6e --- /dev/null +++ b/sway/commands/bar/strip_workspace_name.c @@ -0,0 +1,32 @@ +#include +#include +#include "sway/commands.h" +#include "log.h" +#include "util.h" + +struct cmd_results *bar_cmd_strip_workspace_name(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, + "strip_workspace_name", EXPECTED_EQUAL_TO, 1))) { + return error; + } + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, + "strip_workspace_name", "No bar defined."); + } + + config->current_bar->strip_workspace_name = + parse_boolean(argv[0], config->current_bar->strip_workspace_name); + + if (config->current_bar->strip_workspace_name) { + config->current_bar->strip_workspace_numbers = false; + + wlr_log(WLR_DEBUG, "Stripping workspace name on bar: %s", + config->current_bar->id); + } else { + wlr_log(WLR_DEBUG, "Enabling workspace name on bar: %s", + config->current_bar->id); + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/bar/strip_workspace_numbers.c b/sway/commands/bar/strip_workspace_numbers.c index 4e47d047..b33d01e5 100644 --- a/sway/commands/bar/strip_workspace_numbers.c +++ b/sway/commands/bar/strip_workspace_numbers.c @@ -2,6 +2,7 @@ #include #include "sway/commands.h" #include "log.h" +#include "util.h" struct cmd_results *bar_cmd_strip_workspace_numbers(int argc, char **argv) { struct cmd_results *error = NULL; @@ -13,17 +14,19 @@ struct cmd_results *bar_cmd_strip_workspace_numbers(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "strip_workspace_numbers", "No bar defined."); } - if (strcasecmp("yes", argv[0]) == 0) { - config->current_bar->strip_workspace_numbers = true; + + config->current_bar->strip_workspace_numbers = + parse_boolean(argv[0], config->current_bar->strip_workspace_numbers); + + if (config->current_bar->strip_workspace_numbers) { + config->current_bar->strip_workspace_name = false; + wlr_log(WLR_DEBUG, "Stripping workspace numbers on bar: %s", config->current_bar->id); - } else if (strcasecmp("no", argv[0]) == 0) { - config->current_bar->strip_workspace_numbers = false; + } else { wlr_log(WLR_DEBUG, "Enabling workspace numbers on bar: %s", config->current_bar->id); - } else { - return cmd_results_new(CMD_INVALID, - "strip_workspace_numbers", "Invalid value %s", argv[0]); } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/config/bar.c b/sway/config/bar.c index 8b88642e..94405a92 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -99,6 +99,7 @@ struct bar_config *default_bar_config(void) { bar->wrap_scroll = false; bar->separator_symbol = NULL; bar->strip_workspace_numbers = false; + bar->strip_workspace_name = false; bar->binding_mode_indicator = true; bar->verbose = false; bar->pid = 0; diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 4583558c..cf1b42a6 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -559,6 +559,8 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object_new_boolean(bar->workspace_buttons)); json_object_object_add(json, "strip_workspace_numbers", json_object_new_boolean(bar->strip_workspace_numbers)); + json_object_object_add(json, "strip_workspace_name", + json_object_new_boolean(bar->strip_workspace_name)); json_object_object_add(json, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); json_object_object_add(json, "verbose", diff --git a/sway/meson.build b/sway/meson.build index cde09a02..debd7a91 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -114,6 +114,7 @@ sway_sources = files( 'commands/bar/separator_symbol.c', 'commands/bar/status_command.c', 'commands/bar/strip_workspace_numbers.c', + 'commands/bar/strip_workspace_name.c', 'commands/bar/swaybar_command.c', 'commands/bar/tray_output.c', 'commands/bar/tray_padding.c', diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd index 873741c0..60ee9999 100644 --- a/sway/sway-bar.5.scd +++ b/sway/sway-bar.5.scd @@ -50,6 +50,10 @@ Sway allows configuring swaybar in the sway configuration file. *workspace\_buttons* yes|no Enables or disables workspace buttons on the bar. Default is _yes_. +*strip\_workspace\_name* yes|no + If set to _yes_, then workspace names will be omitted from the workspace + button and only the custom number will be shown. Default is _no_. + *strip\_workspace\_numbers* yes|no If set to _yes_, then workspace numbers will be omitted from the workspace button and only the custom name will be shown. Default is _no_. diff --git a/swaybar/bar.c b/swaybar/bar.c index 08c386a7..2178f542 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -31,6 +31,7 @@ void free_workspaces(struct wl_list *list) { wl_list_for_each_safe(ws, tmp, list, link) { wl_list_remove(&ws->link); free(ws->name); + free(ws->label); free(ws); } } diff --git a/swaybar/config.c b/swaybar/config.c index 1293cdae..98d94168 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -30,6 +30,7 @@ struct swaybar_config *init_config(void) { config->hidden_state = strdup("hide"); config->sep_symbol = NULL; config->strip_workspace_numbers = false; + config->strip_workspace_name = false; config->binding_mode_indicator = true; config->wrap_scroll = false; config->workspace_buttons = true; diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 706f968d..db4360c1 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -153,9 +153,10 @@ 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, *strip_workspace_numbers; - json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; - json_object *bindings; + json_object *font, *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; json_object_object_get_ex(bar_config, "mode", &mode); json_object_object_get_ex(bar_config, "hidden_state", &hidden_state); json_object_object_get_ex(bar_config, "position", &position); @@ -165,6 +166,7 @@ static bool ipc_parse_config( json_object_object_get_ex(bar_config, "wrap_scroll", &wrap_scroll); json_object_object_get_ex(bar_config, "workspace_buttons", &workspace_buttons); json_object_object_get_ex(bar_config, "strip_workspace_numbers", &strip_workspace_numbers); + json_object_object_get_ex(bar_config, "strip_workspace_name", &strip_workspace_name); json_object_object_get_ex(bar_config, "binding_mode_indicator", &binding_mode_indicator); json_object_object_get_ex(bar_config, "verbose", &verbose); json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol); @@ -190,6 +192,9 @@ static bool ipc_parse_config( if (strip_workspace_numbers) { config->strip_workspace_numbers = json_object_get_boolean(strip_workspace_numbers); } + if (strip_workspace_name) { + config->strip_workspace_name = json_object_get_boolean(strip_workspace_name); + } if (binding_mode_indicator) { config->binding_mode_indicator = json_object_get_boolean(binding_mode_indicator); } @@ -298,6 +303,24 @@ bool ipc_get_workspaces(struct swaybar *bar) { calloc(1, sizeof(struct swaybar_workspace)); ws->num = json_object_get_int(num); ws->name = strdup(json_object_get_string(name)); + ws->label = strdup(ws->name); + // ws->num will be -1 if workspace name doesn't begin with int. + if (ws->num != -1) { + size_t len_offset = numlen(ws->num); + if (bar->config->strip_workspace_name) { + free(ws->label); + ws->label = malloc(len_offset + 1 * sizeof(char)); + ws->label[len_offset] = '\0'; + strncpy(ws->label, ws->name, len_offset); + } else if (bar->config->strip_workspace_numbers) { + len_offset += ws->label[len_offset] == ':'; + if (strlen(ws->name) > len_offset) { + free(ws->label); + // Strip number prefix [1-?:] using len_offset. + ws->label = strdup(ws->name + len_offset); + } + } + } ws->visible = json_object_get_boolean(visible); ws->focused = json_object_get_boolean(focused); if (ws->focused) { diff --git a/swaybar/render.c b/swaybar/render.c index 4ebf922e..8269a840 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -342,19 +342,6 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, return output->height; } -static const char *strip_workspace_number(const char *ws_name) { - size_t len = strlen(ws_name); - for (size_t i = 0; i < len; ++i) { - if (ws_name[i] < '0' || ws_name[i] > '9') { - if (':' == ws_name[i] && i < len - 1 && i > 0) { - return ws_name + i + 1; - } - return ws_name; - } - } - return ws_name; -} - static enum hotspot_event_handling workspace_hotspot_callback(struct swaybar_output *output, int x, int y, enum x11_button button, void *data) { if (button != LEFT) { @@ -368,11 +355,6 @@ static uint32_t render_workspace_button(cairo_t *cairo, struct swaybar_output *output, struct swaybar_workspace *ws, double *x) { struct swaybar_config *config = output->bar->config; - const char *name = ws->name; - if (config->strip_workspace_numbers) { - name = strip_workspace_number(ws->name); - } - struct box_colors box_colors; if (ws->urgent) { box_colors = config->colors.urgent_workspace; @@ -388,7 +370,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, config->pango_markup, "%s", name); + output->scale, config->pango_markup, "%s", ws->label); int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; @@ -421,7 +403,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, cairo_set_source_u32(cairo, box_colors.text); cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); pango_printf(cairo, config->font, output->scale, config->pango_markup, - "%s", name); + "%s", ws->label); struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); hotspot->x = *x;