i3 - improved tiling WM


i3bar: implement custom mouse wheel commands

Patch status: needinfo

Patch by Tony Crisci

Long description:

Users can specify 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.

Example:

bar {
    wheel_up_cmd nop
    wheel_down_cmd exec ~/.i3/scripts/custom_wheel_down
}

fixes #1104

To apply this patch, use:
curl http://cr.i3wm.org/patch/609/raw.patch | git am

b/docs/userguide

34
@@ -1104,6 +1104,27 @@ bar {
35
 
36
 Available modifiers are Mod1-Mod5, Shift, Control (see +xmodmap(1)+).
37
 
38
+=== Mouse button commands
39
+
40
+Specifies a command to run when a button was pressed on i3bar to override the
41
+default behavior. Currently only the mouse wheel buttons are supported. This is
42
+useful for disabling the scroll wheel action or running scripts that implement
43
+custom behavior for these buttons.
44
+
45
+*Syntax*:
46
+---------------------
47
+wheel_up_cmd <command>
48
+wheel_down_cmd <command>
49
+---------------------
50
+
51
+*Example*:
52
+---------------------
53
+bar {
54
+    wheel_up_cmd nop
55
+    wheel_down_cmd exec ~/.i3/scripts/custom_wheel_down
56
+}
57
+---------------------
58
+
59
 === Bar ID
60
 
61
 Specifies the bar ID for the configured bar instance. If this option is missing,

b/i3bar/include/config.h

66
@@ -24,6 +24,8 @@ typedef enum { M_DOCK = 0,
67
 
68
 typedef struct config_t {
69
     int modifier;
70
+    char *wheel_up_cmd;
71
+    char *wheel_down_cmd;
72
     position_t position;
73
     int verbose;
74
     struct xcb_color_strings_t colors;

b/i3bar/src/config.c

79
@@ -112,6 +112,20 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len
80
         return 1;
81
     }
82
 
83
+    if (!strcmp(cur_key, "wheel_up_cmd")) {
84
+        DLOG("wheel_up_cmd = %.*s\n", len, val);
85
+        FREE(config.wheel_up_cmd);
86
+        sasprintf(&config.wheel_up_cmd, "%.*s", len, val);
87
+        return 1;
88
+    }
89
+
90
+    if (!strcmp(cur_key, "wheel_down_cmd")) {
91
+        DLOG("wheel_down_cmd = %.*s\n", len, val);
92
+        FREE(config.wheel_down_cmd);
93
+        sasprintf(&config.wheel_down_cmd, "%.*s", len, val);
94
+        return 1;
95
+    }
96
+
97
     if (!strcmp(cur_key, "position")) {
98
         DLOG("position = %.*s\n", len, val);
99
         config.position = (len == 3 && !strncmp((const char *)val, "top", strlen("top")) ? POS_TOP : POS_BOT);

b/i3bar/src/xcb.c

104
@@ -370,6 +370,14 @@ void handle_button(xcb_button_press_event_t *event) {
105
              * If there is no more workspace, don’t even send the workspace
106
              * command, otherwise (with workspace auto_back_and_forth) we’d end
107
              * up on the wrong workspace. */
108
+
109
+            /* If `wheel_up_cmd [COMMAND]` was specified, it should override
110
+             * the default behavior */
111
+            if (config.wheel_up_cmd) {
112
+                i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, config.wheel_up_cmd);
113
+                return;
114
+            }
115
+
116
             if (cur_ws == TAILQ_FIRST(walk->workspaces))
117
                 return;
118
 
119
@@ -380,6 +388,14 @@ void handle_button(xcb_button_press_event_t *event) {
120
              * If there is no more workspace, don’t even send the workspace
121
              * command, otherwise (with workspace auto_back_and_forth) we’d end
122
              * up on the wrong workspace. */
123
+
124
+            /* if `wheel_down_cmd [COMMAND]` was specified, it should override
125
+             * the default behavior */
126
+            if (config.wheel_down_cmd) {
127
+                i3_send_msg(I3_IPC_MESSAGE_TYPE_COMMAND, config.wheel_down_cmd);
128
+                return;
129
+            }
130
+
131
             if (cur_ws == TAILQ_LAST(walk->workspaces, ws_head))
132
                 return;
133
 

b/include/config.h

138
@@ -261,6 +261,14 @@ struct Barconfig {
139
         M_MOD5 = 7
140
     } modifier;
141
 
142
+    /** Command that should be run when mouse wheel up button is pressed over
143
+     * i3bar to override the default behavior. */
144
+    char *wheel_up_cmd;
145
+
146
+    /** Command that should be run when mouse wheel down button is pressed over
147
+     * i3bar to override the default behavior. */
148
+    char *wheel_down_cmd;
149
+
150
     /** Bar position (bottom by default). */
151
     enum { P_BOTTOM = 0,
152
            P_TOP = 1 } position;

b/include/config_directives.h

157
@@ -73,6 +73,8 @@ CFGFUN(bar_id, const char *bar_id);
158
 CFGFUN(bar_output, const char *output);
159
 CFGFUN(bar_verbose, const char *verbose);
160
 CFGFUN(bar_modifier, const char *modifier);
161
+CFGFUN(bar_wheel_up_cmd, const char *command);
162
+CFGFUN(bar_wheel_down_cmd, const char *command);
163
 CFGFUN(bar_position, const char *position);
164
 CFGFUN(bar_i3bar_command, const char *i3bar_command);
165
 CFGFUN(bar_color, const char *colorclass, const char *border, const char *background, const char *text);

b/parser-specs/config.spec

170
@@ -358,6 +358,8 @@ state BAR:
171
   'hidden_state'           -> BAR_HIDDEN_STATE
172
   'id'                     -> BAR_ID
173
   'modifier'               -> BAR_MODIFIER
174
+  'wheel_up_cmd'           -> BAR_WHEEL_UP_CMD
175
+  'wheel_down_cmd'         -> BAR_WHEEL_DOWN_CMD
176
   'position'               -> BAR_POSITION
177
   'output'                 -> BAR_OUTPUT
178
   'tray_output'            -> BAR_TRAY_OUTPUT
179
@@ -403,6 +405,14 @@ state BAR_MODIFIER:
180
   modifier = 'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5', 'Control', 'Ctrl', 'Shift'
181
       -> call cfg_bar_modifier($modifier); BAR
182
 
183
+state BAR_WHEEL_UP_CMD:
184
+  command = string
185
+      -> call cfg_bar_wheel_up_cmd($command); BAR
186
+
187
+state BAR_WHEEL_DOWN_CMD:
188
+  command = string
189
+      -> call cfg_bar_wheel_down_cmd($command); BAR
190
+
191
 state BAR_POSITION:
192
   position = 'top', 'bottom'
193
       -> call cfg_bar_position($position); BAR

b/src/config_directives.c

198
@@ -459,6 +459,16 @@ CFGFUN(bar_modifier, const char *modifier) {
199
         current_bar.modifier = M_SHIFT;
200
 }
201
 
202
+CFGFUN(bar_wheel_up_cmd, const char *command) {
203
+    FREE(current_bar.wheel_up_cmd);
204
+    current_bar.wheel_up_cmd = sstrdup(command);
205
+}
206
+
207
+CFGFUN(bar_wheel_down_cmd, const char *command) {
208
+    FREE(current_bar.wheel_down_cmd);
209
+    current_bar.wheel_down_cmd = sstrdup(command);
210
+}
211
+
212
 CFGFUN(bar_position, const char *position) {
213
     current_bar.position = (strcmp(position, "top") == 0 ? P_TOP : P_BOTTOM);
214
 }

b/src/ipc.c

219
@@ -512,6 +512,16 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
220
             break;
221
     }
222
 
223
+    if (config->wheel_up_cmd) {
224
+        ystr("wheel_up_cmd");
225
+        ystr(config->wheel_up_cmd);
226
+    }
227
+
228
+    if (config->wheel_down_cmd) {
229
+        ystr("wheel_down_cmd");
230
+        ystr(config->wheel_down_cmd);
231
+    }
232
+
233
     ystr("position");
234
     if (config->position == P_BOTTOM)
235
         ystr("bottom");