diff --git a/include/bar/config.h b/include/bar/config.h index c0e3d2a7..c957caa7 100644 --- a/include/bar/config.h +++ b/include/bar/config.h @@ -27,6 +27,7 @@ struct config { char *mode; bool strip_workspace_numbers; bool binding_mode_indicator; + bool wrap_scroll; bool workspace_buttons; bool all_outputs; list_t *outputs; diff --git a/include/config.h b/include/config.h index bf278ddb..87e23187 100644 --- a/include/config.h +++ b/include/config.h @@ -136,6 +136,7 @@ struct bar_config { int height; // -1 not defined int tray_padding; bool workspace_buttons; + bool wrap_scroll; char *separator_symbol; bool strip_workspace_numbers; bool binding_mode_indicator; diff --git a/sway/commands.c b/sway/commands.c index b9399dec..73f245c1 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -114,6 +114,7 @@ static sway_cmd bar_cmd_strip_workspace_numbers; static sway_cmd bar_cmd_swaybar_command; static sway_cmd bar_cmd_tray_output; static sway_cmd bar_cmd_tray_padding; +static sway_cmd bar_cmd_wrap_scroll; static sway_cmd bar_cmd_workspace_buttons; static sway_cmd bar_colors_cmd_active_workspace; @@ -3169,6 +3170,29 @@ static struct cmd_results *bar_cmd_tray_padding(int argc, char **argv) { return cmd_results_new(CMD_SUCCESS, NULL, NULL); } +static struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "wrap_scroll", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + if (!config->current_bar) { + return cmd_results_new(CMD_FAILURE, "wrap_scroll", "No bar defined."); + } + + if (strcasecmp("yes", argv[0]) == 0) { + config->current_bar->wrap_scroll = true; + sway_log(L_DEBUG, "Enabling wrap scroll on bar: %s", config->current_bar->id); + } else if (strcasecmp("no", argv[0]) == 0) { + config->current_bar->wrap_scroll = false; + sway_log(L_DEBUG, "Disabling wrap scroll on bar: %s", config->current_bar->id); + } else { + error = cmd_results_new(CMD_INVALID, "wrap_scroll", "Invalid value %s", argv[0]); + return error; + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} + static struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "workspace_buttons", EXPECTED_EQUAL_TO, 1))) { @@ -3211,6 +3235,7 @@ static struct cmd_handler bar_handlers[] = { { "swaybar_command", bar_cmd_swaybar_command }, { "tray_output", bar_cmd_tray_output }, { "tray_padding", bar_cmd_tray_padding }, + { "wrap_scroll", bar_cmd_wrap_scroll }, { "workspace_buttons", bar_cmd_workspace_buttons }, }; diff --git a/sway/ipc-json.c b/sway/ipc-json.c index e7ab988c..ca45557c 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -241,6 +241,7 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { json_object_object_add(json, "separator_symbol", json_object_new_string(bar->separator_symbol)); } json_object_object_add(json, "bar_height", json_object_new_int(bar->height)); + json_object_object_add(json, "wrap_scroll", json_object_new_boolean(bar->wrap_scroll)); json_object_object_add(json, "workspace_buttons", 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, "binding_mode_indicator", json_object_new_boolean(bar->binding_mode_indicator)); diff --git a/sway/sway-bar.5.txt b/sway/sway-bar.5.txt index dc4a673c..a404acd0 100644 --- a/sway/sway-bar.5.txt +++ b/sway/sway-bar.5.txt @@ -21,7 +21,7 @@ Commands **status_command** :: Executes the bar _status command_ with _sh -c_. Each line of text printed to stdout from this command will be displayed in the status area of the bar. You - can also use the i3bar JSON protocol: + may also use the i3bar JSON protocol: + https://i3wm.org/docs/i3bar-protocol.html @@ -48,9 +48,12 @@ Commands **separator_symbol** :: Specifies the separator symbol to separate blocks on the bar. +**wrap_scroll** :: + Enables or disables wrapping when scrolling through workspaces with the + scroll wheel. Default is no. + **workspace_buttons** :: - Enables or disables workspace buttons on the bar. Default is to enable - buttons. + Enables or disables workspace buttons on the bar. Default is yes. **strip_workspace_numbers** :: If set to _yes_, then workspace numbers will be omitted from the workspace diff --git a/swaybar/bar.c b/swaybar/bar.c index 9009e1ff..41538052 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -96,6 +96,37 @@ static void mouse_button_notify(struct window *window, int x, int y, static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) { sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down"); + if (!swaybar.config->wrap_scroll) { + // Find output this window lives on + int i; + struct output *output; + for (i = 0; i < swaybar.outputs->length; ++i) { + output = swaybar.outputs->items[i]; + if (output->window == window) { + break; + } + } + if (!sway_assert(i != swaybar.outputs->length, "Unknown window in scroll event")) { + return; + } + int focused = -1; + for (i = 0; i < output->workspaces->length; ++i) { + struct workspace *ws = output->workspaces->items[i]; + if (ws->focused) { + focused = i; + break; + } + } + if (!sway_assert(focused != -1, "Scroll wheel event received on inactive output")) { + return; + } + if ((focused == 0 && direction == SCROLL_UP) || + (focused == output->workspaces->length - 1 && direction == SCROLL_DOWN)) { + // Do not wrap + return; + } + } + const char *workspace_name = direction == SCROLL_UP ? "prev_on_output" : "next_on_output"; ipc_send_workspace_command(workspace_name); } diff --git a/swaybar/config.c b/swaybar/config.c index 7bd22c91..f3a3e716 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -53,6 +53,7 @@ struct config *init_config() { config->sep_symbol = NULL; config->strip_workspace_numbers = false; config->binding_mode_indicator = true; + config->wrap_scroll = false; config->workspace_buttons = true; config->all_outputs = false; config->outputs = create_list(); diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 15f40508..ad4f9ef8 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -19,7 +19,7 @@ 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_bar, *position, *status_command; - json_object *font, *bar_height, *workspace_buttons, *strip_workspace_numbers; + 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); @@ -29,6 +29,7 @@ static void ipc_parse_config(struct config *config, const char *payload) { 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, "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); json_object_object_get_ex(bar_config, "strip_workspace_numbers", &strip_workspace_numbers); json_object_object_get_ex(bar_config, "binding_mode_indicator", &binding_mode_indicator); @@ -65,6 +66,10 @@ static void ipc_parse_config(struct config *config, const char *payload) { config->binding_mode_indicator = json_object_get_boolean(binding_mode_indicator); } + if (wrap_scroll) { + config->wrap_scroll = json_object_get_boolean(wrap_scroll); + } + if (workspace_buttons) { config->workspace_buttons = json_object_get_boolean(workspace_buttons); }