From 39735013b4b48911f04aa8487c2a08fa24674aa4 Mon Sep 17 00:00:00 2001 From: Calvin Kosmatka Date: Wed, 12 Apr 2017 02:36:03 -0500 Subject: [PATCH] Adds hide mode functionality to swaybar --- include/sway/config.h | 12 ++++- include/swaybar/config.h | 1 + sway/commands.c | 1 + sway/commands/bar/mode.c | 20 ++++---- sway/commands/ipc.c | 1 + sway/config.c | 6 ++- sway/ipc-json.c | 7 ++- sway/ipc-server.c | 3 +- swaybar/config.c | 1 + swaybar/ipc.c | 66 ++++++++++++++---------- swaybar/render.c | 108 +++++++++++++++++++++------------------ 11 files changed, 133 insertions(+), 93 deletions(-) diff --git a/include/sway/config.h b/include/sway/config.h index 2de904344..408a21003 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -110,12 +110,19 @@ struct bar_config { * Always visible in dock mode. Visible only when modifier key is held in hide mode. * Never visible in invisible mode. */ - char *mode; + char *display_mode; /** * One of "show" or "hide". * * In "show" mode, it will always be shown on top of the active workspace. */ + char *mode; + /** + * Current keybinding mode + * + * Names should probably be reworked at some point, but I'm keeping it for now + * Don't think this does anything at the moment + */ char *hidden_state; /** * Id name used to identify the bar through IPC. @@ -225,9 +232,10 @@ enum ipc_feature { IPC_FEATURE_EVENT_WINDOW = 2048, IPC_FEATURE_EVENT_BINDING = 4096, IPC_FEATURE_EVENT_INPUT = 8192, + IPC_FEATURE_EVENT_MODIFIER = 16384, IPC_FEATURE_ALL_COMMANDS = 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, - IPC_FEATURE_ALL_EVENTS = 256 | 512 | 1024 | 2048 | 4096 | 8192, + IPC_FEATURE_ALL_EVENTS = 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384, IPC_FEATURE_ALL = IPC_FEATURE_ALL_COMMANDS | IPC_FEATURE_ALL_EVENTS, }; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 527361ed4..fd3e11cc2 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -26,6 +26,7 @@ struct config { char *font; char *sep_symbol; char *mode; + char *display_mode; char *hidden_state; bool strip_workspace_numbers; bool binding_mode_indicator; diff --git a/sway/commands.c b/sway/commands.c index 17c7d7176..02f6a6961 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -321,6 +321,7 @@ static struct cmd_handler ipc_event_handlers[] = { { "binding", cmd_ipc_event_cmd }, { "input", cmd_ipc_event_cmd }, { "mode", cmd_ipc_event_cmd }, + { "modifier", cmd_ipc_event_cmd }, { "output", cmd_ipc_event_cmd }, { "window", cmd_ipc_event_cmd }, { "workspace", cmd_ipc_event_cmd }, diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c index 36816b939..9ba9a1487 100644 --- a/sway/commands/bar/mode.c +++ b/sway/commands/bar/mode.c @@ -7,31 +7,31 @@ #include "log.h" static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode) { - char *old_mode = bar->mode; + char *old_mode = bar->display_mode; if (strcasecmp("toggle", mode) == 0 && !config->reading) { - if (strcasecmp("dock", bar->mode) == 0) { - bar->mode = strdup("hide"); - } else if (strcasecmp("hide", bar->mode) == 0) { - bar->mode = strdup("dock"); + if (strcasecmp("dock", bar->display_mode) == 0) { + bar->display_mode = strdup("hide"); + } else if (strcasecmp("hide", bar->display_mode) == 0) { + bar->display_mode = strdup("dock"); } } else if (strcasecmp("dock", mode) == 0) { - bar->mode = strdup("dock"); + bar->display_mode = strdup("dock"); } else if (strcasecmp("hide", mode) == 0) { - bar->mode = strdup("hide"); + bar->display_mode = strdup("hide"); } else if (strcasecmp("invisible", mode) == 0) { - bar->mode = strdup("invisible"); + bar->display_mode = strdup("invisible"); } else { return cmd_results_new(CMD_INVALID, "mode", "Invalid value %s", mode); } - if (strcmp(old_mode, bar->mode) != 0) { + if (strcmp(old_mode, bar->display_mode) != 0) { if (!config->reading) { ipc_event_barconfig_update(bar); // active bar modifiers might have changed. update_active_bar_modifiers(); } - sway_log(L_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id); + sway_log(L_DEBUG, "Setting mode: '%s' for bar: %s", bar->display_mode, bar->id); } // free old mode diff --git a/sway/commands/ipc.c b/sway/commands/ipc.c index 8a7b849f9..6dcee3658 100644 --- a/sway/commands/ipc.c +++ b/sway/commands/ipc.c @@ -130,6 +130,7 @@ struct cmd_results *cmd_ipc_event_cmd(int argc, char **argv) { { "window", IPC_FEATURE_EVENT_WINDOW }, { "binding", IPC_FEATURE_EVENT_BINDING }, { "input", IPC_FEATURE_EVENT_INPUT }, + { "modifier", IPC_FEATURE_EVENT_MODIFIER } }; uint32_t type = 0; diff --git a/sway/config.c b/sway/config.c index c8432a2a0..9744facd3 100644 --- a/sway/config.c +++ b/sway/config.c @@ -67,6 +67,7 @@ static void free_bar(struct bar_config *bar) { if (!bar) { return; } + free(bar->display_mode); free(bar->mode); free(bar->hidden_state); free(bar->status_command); @@ -408,7 +409,7 @@ void update_active_bar_modifiers() { int i; for (i = 0; i < config->bars->length; ++i) { bar = config->bars->items[i]; - if (strcmp(bar->mode, "hide") == 0 && strcmp(bar->hidden_state, "hide") == 0) { + if (strcmp(bar->display_mode, "hide") == 0 && strcmp(bar->hidden_state, "hide") == 0) { if (list_seq_find(config->active_bar_modifiers, compare_modifiers, &bar->modifier) < 0) { list_add(config->active_bar_modifiers, &bar->modifier); } @@ -1334,8 +1335,9 @@ struct bar_config *default_bar_config(void) { if (!bar) { return NULL; } - if (!(bar->mode = strdup("dock"))) goto cleanup; + if (!(bar->display_mode = strdup("dock"))) goto cleanup; if (!(bar->hidden_state = strdup("hide"))) goto cleanup; + bar->mode = NULL; bar->modifier = WLC_BIT_MOD_LOGO; bar->outputs = NULL; bar->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM; diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 6bd5204c7..20b82b784 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -288,7 +288,12 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object *json = json_object_new_object(); json_object_object_add(json, "id", json_object_new_string(bar->id)); json_object_object_add(json, "tray_output", NULL); - json_object_object_add(json, "mode", json_object_new_string(bar->mode)); + json_object_object_add(json, "mode", json_object_new_string(bar->display_mode)); + if (!bar->mode) { + json_object_object_add(json, "binding_mode", json_object_new_string("default")); + } else { + json_object_object_add(json, "binding_mode", json_object_new_string(bar->mode)); + } json_object_object_add(json, "hidden_state", json_object_new_string(bar->hidden_state)); json_object_object_add(json, "modifier", json_object_new_string(get_modifier_name_by_mask(bar->modifier))); switch (bar->position) { diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 6554098be..7b5b39e11 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -651,7 +651,8 @@ void ipc_send_event(const char *json_string, enum ipc_command_type event) { { IPC_EVENT_MODE, IPC_FEATURE_EVENT_MODE }, { IPC_EVENT_WINDOW, IPC_FEATURE_EVENT_WINDOW }, { IPC_EVENT_BINDING, IPC_FEATURE_EVENT_BINDING }, - { IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT } + { IPC_EVENT_INPUT, IPC_FEATURE_EVENT_INPUT }, + { IPC_EVENT_MODIFIER, IPC_FEATURE_EVENT_MODIFIER} }; uint32_t security_mask = 0; diff --git a/swaybar/config.c b/swaybar/config.c index 5b81c2e31..ee7486715 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -37,6 +37,7 @@ struct config *init_config() { config->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM; config->font = strdup("monospace 10"); config->mode = NULL; + config->display_mode = NULL; config->hidden_state = NULL; config->sep_symbol = NULL; config->strip_workspace_numbers = false; diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 0366a9f13..65b684a48 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -20,12 +20,14 @@ void ipc_send_workspace_command(const char *workspace_name) { static void ipc_parse_config(struct config *config, const char *payload) { json_object *bar_config = json_tokener_parse(payload); - json_object *tray_output, *mode, *hidden_state, *position, *status_command; + json_object *tray_output, *display_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 *markup; json_object_object_get_ex(bar_config, "tray_output", &tray_output); - json_object_object_get_ex(bar_config, "mode", &mode); + // "mode" as in the bar's display mode and "mode" as in binding mode + // should be distinguished more carefully + json_object_object_get_ex(bar_config, "mode", &display_mode); json_object_object_get_ex(bar_config, "hidden_state", &hidden_state); json_object_object_get_ex(bar_config, "position", &position); json_object_object_get_ex(bar_config, "status_command", &status_command); @@ -45,6 +47,16 @@ static void ipc_parse_config(struct config *config, const char *payload) { free(config->status_command); config->status_command = strdup(json_object_get_string(status_command)); } + + if (display_mode) { + free(config->display_mode); + config->display_mode = strdup(json_object_get_string(display_mode)); + } + + if (hidden_state) { + free(config->hidden_state); + config->hidden_state = strdup(json_object_get_string(hidden_state)); + } if (position) { config->position = parse_position(json_object_get_string(position)); @@ -323,10 +335,12 @@ void ipc_bar_init(struct bar *bar, const char *bar_id) { } free(res); json_object_put(outputs); - - const char *subscribe_json = strcmp(bar->config->mode, "hide") == 0 ? + // Will need to be redone for display mode toggling compatibility + // Will require setting bar->config->hidden_state to "show" as default + const char *subscribe_json = strcmp(bar->config->display_mode, "hide") == 0 ? "[ \"workspace\", \"mode\", \"modifier\" ]" : "[ \"workspace\", \"mode\" ]"; + sway_log(L_ERROR, subscribe_json); len = strlen(subscribe_json); res = ipc_single_command(bar->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); free(res); @@ -368,30 +382,28 @@ bool handle_ipc_event(struct bar *bar) { break; } case IPC_EVENT_MODIFIER: { - if (strcmp(bar->config->mode, "hide") == 0) { - json_object *result = json_tokener_parse(resp->payload); - if (!result) { - free_ipc_response(resp); - sway_log(L_ERROR, "failed to parse payload as json"); - return false; - } - json_object *json_change; - if (json_object_object_get_ex(result, "change", &json_change)) { - const char *change = json_object_get_string(json_change); - - if (strcmp(change, "pressed") == 0) { - bar->config->hidden_state = "show"; - } else { //must be "released" - bar->config->hidden_state = "hide"; - } - - } else { - sway_log(L_ERROR, "failed to parse response"); - } - - json_object_put(result); - break; + json_object *result = json_tokener_parse(resp->payload); + if (!result) { + free_ipc_response(resp); + sway_log(L_ERROR, "failed to parse payload as json"); + return false; } + json_object *json_change; + if (json_object_object_get_ex(result, "change", &json_change)) { + const char *change = json_object_get_string(json_change); + free(bar->config->hidden_state); + if (strcmp(change, "pressed") == 0) { + bar->config->hidden_state = strdup("show"); + } else { //must be "released" + bar->config->hidden_state = strdup("hide"); + } + + } else { + sway_log(L_ERROR, "failed to parse response"); + } + + json_object_put(result); + break; } default: free_ipc_response(resp); diff --git a/swaybar/render.c b/swaybar/render.c index 2eae997fc..f40fb9dce 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -286,59 +286,67 @@ void render(struct output *output, struct config *config, struct status_line *li cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_paint(cairo); cairo_restore(cairo); - - cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - - // Background - if (is_focused) { - cairo_set_source_u32(cairo, config->colors.focused_background); - } else { - cairo_set_source_u32(cairo, config->colors.background); - } - cairo_paint(cairo); - - // Command output - if (is_focused) { - cairo_set_source_u32(cairo, config->colors.focused_statusline); - } else { - cairo_set_source_u32(cairo, config->colors.statusline); - } - - int width, height; - - if (line->protocol == TEXT) { - get_text_size(window->cairo, window->font, &width, &height, - window->scale, config->pango_markup, "%s", line->text_line); - cairo_move_to(cairo, (window->width * window->scale) - - margin - width, margin); - pango_printf(window->cairo, window->font, window->scale, - config->pango_markup, "%s", line->text_line); - } else if (line->protocol == I3BAR && line->block_line) { - double pos = (window->width * window->scale) - 0.5; - bool edge = true; - for (i = line->block_line->length - 1; i >= 0; --i) { - struct status_block *block = line->block_line->items[i]; - if (block->full_text && block->full_text[0]) { - render_block(window, config, block, &pos, edge, is_focused); - edge = false; + // Could also be done by always rendering then conditionally clearing and drawing alpha + // That may be preferable down the line + if (!strcmp(config->display_mode, "hide") == 0 || strcmp(config->hidden_state, "show") == 0) { + + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + + // Background + if (is_focused) { + cairo_set_source_u32(cairo, config->colors.focused_background); + } else { + cairo_set_source_u32(cairo, config->colors.background); + } + cairo_paint(cairo); + + // Command output + if (is_focused) { + cairo_set_source_u32(cairo, config->colors.focused_statusline); + } else { + cairo_set_source_u32(cairo, config->colors.statusline); + } + + int width, height; + + if (line->protocol == TEXT) { + get_text_size(window->cairo, window->font, &width, &height, + window->scale, config->pango_markup, "%s", line->text_line); + cairo_move_to(cairo, (window->width * window->scale) + - margin - width, margin); + pango_printf(window->cairo, window->font, window->scale, + config->pango_markup, "%s", line->text_line); + } else if (line->protocol == I3BAR && line->block_line) { + double pos = (window->width * window->scale) - 0.5; + bool edge = true; + for (i = line->block_line->length - 1; i >= 0; --i) { + struct status_block *block = line->block_line->items[i]; + if (block->full_text && block->full_text[0]) { + render_block(window, config, block, &pos, edge, is_focused); + edge = false; + } } } - } - - cairo_set_line_width(cairo, 1.0); - double x = 0.5; - - // Workspaces - if (config->workspace_buttons) { - for (i = 0; i < output->workspaces->length; ++i) { - struct workspace *ws = output->workspaces->items[i]; - render_workspace_button(window, config, ws, &x); + + cairo_set_line_width(cairo, 1.0); + double x = 0.5; + + // Workspaces + if (config->workspace_buttons) { + for (i = 0; i < output->workspaces->length; ++i) { + struct workspace *ws = output->workspaces->items[i]; + render_workspace_button(window, config, ws, &x); + } } - } - - // binding mode indicator - if (config->mode && config->binding_mode_indicator) { - render_binding_mode_indicator(window, config, x); + + // binding mode indicator + if (config->mode && config->binding_mode_indicator) { + render_binding_mode_indicator(window, config, x); + } + } else { + cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); + cairo_set_source_u32(cairo, 0x00000000); + cairo_paint(cairo); } }