diff --git a/docs/userguide b/docs/userguide index 804877d5..e752ec82 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1104,6 +1104,27 @@ bar { Available modifiers are Mod1-Mod5, Shift, Control (see +xmodmap(1)+). +=== Mouse button commands + +Specifies a command to run when a button was pressed on i3bar to override the +default behavior. Currently only the mouse wheel buttons are supported. This is +useful for disabling the scroll wheel action or running scripts that implement +custom behavior for these buttons. + +*Syntax*: +--------------------- +wheel_up_cmd +wheel_down_cmd +--------------------- + +*Example*: +--------------------- +bar { + wheel_up_cmd nop + wheel_down_cmd exec ~/.i3/scripts/custom_wheel_down +} +--------------------- + === Bar ID Specifies the bar ID for the configured bar instance. If this option is missing, diff --git a/i3bar/include/config.h b/i3bar/include/config.h index 730d3ef0..2c399305 100644 --- a/i3bar/include/config.h +++ b/i3bar/include/config.h @@ -24,6 +24,8 @@ typedef enum { M_DOCK = 0, typedef struct config_t { int modifier; + char *wheel_up_cmd; + char *wheel_down_cmd; position_t position; int verbose; struct xcb_color_strings_t colors; diff --git a/i3bar/src/config.c b/i3bar/src/config.c index 6f1a8b8e..bb322619 100644 --- a/i3bar/src/config.c +++ b/i3bar/src/config.c @@ -112,6 +112,20 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len return 1; } + if (!strcmp(cur_key, "wheel_up_cmd")) { + DLOG("wheel_up_cmd = %.*s\n", len, val); + FREE(config.wheel_up_cmd); + sasprintf(&config.wheel_up_cmd, "%.*s", len, val); + return 1; + } + + if (!strcmp(cur_key, "wheel_down_cmd")) { + DLOG("wheel_down_cmd = %.*s\n", len, val); + FREE(config.wheel_down_cmd); + sasprintf(&config.wheel_down_cmd, "%.*s", len, val); + return 1; + } + if (!strcmp(cur_key, "position")) { DLOG("position = %.*s\n", len, val); config.position = (len == 3 && !strncmp((const char *)val, "top", strlen("top")) ? POS_TOP : POS_BOT); diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index 37a13347..5bbec13e 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -370,6 +370,14 @@ void handle_button(xcb_button_press_event_t *event) { * If there is no more workspace, don’t even send the workspace * command, otherwise (with workspace auto_back_and_forth) we’d end * up on the wrong workspace. */ + + /* If `wheel_up_cmd [COMMAND]` was specified, it should override + * the default behavior */ + if (config.wheel_up_cmd) { + i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, config.wheel_up_cmd); + return; + } + if (cur_ws == TAILQ_FIRST(walk->workspaces)) return; @@ -380,6 +388,14 @@ void handle_button(xcb_button_press_event_t *event) { * If there is no more workspace, don’t even send the workspace * command, otherwise (with workspace auto_back_and_forth) we’d end * up on the wrong workspace. */ + + /* if `wheel_down_cmd [COMMAND]` was specified, it should override + * the default behavior */ + if (config.wheel_down_cmd) { + i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, config.wheel_down_cmd); + return; + } + if (cur_ws == TAILQ_LAST(walk->workspaces, ws_head)) return; diff --git a/include/config.h b/include/config.h index 22110eba..b0f22417 100644 --- a/include/config.h +++ b/include/config.h @@ -261,6 +261,14 @@ struct Barconfig { M_MOD5 = 7 } modifier; + /** Command that should be run when mouse wheel up button is pressed over + * i3bar to override the default behavior. */ + char *wheel_up_cmd; + + /** Command that should be run when mouse wheel down button is pressed over + * i3bar to override the default behavior. */ + char *wheel_down_cmd; + /** Bar position (bottom by default). */ enum { P_BOTTOM = 0, P_TOP = 1 } position; diff --git a/include/config_directives.h b/include/config_directives.h index 7fdca8c8..af7b9a90 100644 --- a/include/config_directives.h +++ b/include/config_directives.h @@ -73,6 +73,8 @@ CFGFUN(bar_id, const char *bar_id); CFGFUN(bar_output, const char *output); CFGFUN(bar_verbose, const char *verbose); CFGFUN(bar_modifier, const char *modifier); +CFGFUN(bar_wheel_up_cmd, const char *command); +CFGFUN(bar_wheel_down_cmd, const char *command); CFGFUN(bar_position, const char *position); CFGFUN(bar_i3bar_command, const char *i3bar_command); CFGFUN(bar_color, const char *colorclass, const char *border, const char *background, const char *text); diff --git a/parser-specs/config.spec b/parser-specs/config.spec index f1021b26..bdd03565 100644 --- a/parser-specs/config.spec +++ b/parser-specs/config.spec @@ -358,6 +358,8 @@ state BAR: 'hidden_state' -> BAR_HIDDEN_STATE 'id' -> BAR_ID 'modifier' -> BAR_MODIFIER + 'wheel_up_cmd' -> BAR_WHEEL_UP_CMD + 'wheel_down_cmd' -> BAR_WHEEL_DOWN_CMD 'position' -> BAR_POSITION 'output' -> BAR_OUTPUT 'tray_output' -> BAR_TRAY_OUTPUT @@ -403,6 +405,14 @@ state BAR_MODIFIER: modifier = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Control', 'Ctrl', 'Shift' -> call cfg_bar_modifier($modifier); BAR +state BAR_WHEEL_UP_CMD: + command = string + -> call cfg_bar_wheel_up_cmd($command); BAR + +state BAR_WHEEL_DOWN_CMD: + command = string + -> call cfg_bar_wheel_down_cmd($command); BAR + state BAR_POSITION: position = 'top', 'bottom' -> call cfg_bar_position($position); BAR diff --git a/src/config_directives.c b/src/config_directives.c index 6dfd369d..b5e4a32a 100644 --- a/src/config_directives.c +++ b/src/config_directives.c @@ -459,6 +459,16 @@ CFGFUN(bar_modifier, const char *modifier) { current_bar.modifier = M_SHIFT; } +CFGFUN(bar_wheel_up_cmd, const char *command) { + FREE(current_bar.wheel_up_cmd); + current_bar.wheel_up_cmd = sstrdup(command); +} + +CFGFUN(bar_wheel_down_cmd, const char *command) { + FREE(current_bar.wheel_down_cmd); + current_bar.wheel_down_cmd = sstrdup(command); +} + CFGFUN(bar_position, const char *position) { current_bar.position = (strcmp(position, "top") == 0 ? P_TOP : P_BOTTOM); } diff --git a/src/ipc.c b/src/ipc.c index 8413d0a6..d6bb34a4 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -512,6 +512,16 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) { break; } + if (config->wheel_up_cmd) { + ystr("wheel_up_cmd"); + ystr(config->wheel_up_cmd); + } + + if (config->wheel_down_cmd) { + ystr("wheel_down_cmd"); + ystr(config->wheel_down_cmd); + } + ystr("position"); if (config->position == P_BOTTOM) ystr("bottom"); diff --git a/testcases/t/201-config-parser.t b/testcases/t/201-config-parser.t index 874a25ec..1153423b 100644 --- a/testcases/t/201-config-parser.t +++ b/testcases/t/201-config-parser.t @@ -645,7 +645,7 @@ EOT $expected = <<'EOT'; cfg_bar_output(LVDS-1) -ERROR: CONFIG: Expected one of these tokens: , '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'position', 'output', 'tray_output', 'font', 'binding_mode_indicator', 'workspace_buttons', 'strip_workspace_numbers', 'verbose', 'colors', '}' +ERROR: CONFIG: Expected one of these tokens: , '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'wheel_up_cmd', 'wheel_down_cmd', 'position', 'output', 'tray_output', 'font', 'binding_mode_indicator', 'workspace_buttons', 'strip_workspace_numbers', 'verbose', 'colors', '}' ERROR: CONFIG: (in file ) ERROR: CONFIG: Line 1: bar { ERROR: CONFIG: Line 2: output LVDS-1