Add new bar.binding_mode_button configuration.
Patch status: needinfo
Patch by syl20bnr
Long description:
This patch adds a new configuration for i3bar called 'binding_mode_button' which acts like the workspace_buttons configiration but for the binding mode button (i.e the default resize mode button). This way it is possible to configure i3bar to hide the workspace buttons and keep showing the binding mode button. This should make the hide workspace buttons configuration more convenient for those who are heavily using binding modes.
To apply this patch, use:
curl http://cr.i3wm.org/patch/203/raw.patch | git am
b/docs/ipc
33 |
@@ -494,6 +494,8 @@ font (string):: |
34 |
The font to use for text on the bar. |
35 |
workspace_buttons (boolean):: |
36 |
Display workspace buttons or not? Defaults to true. |
37 |
+binding_mode_button (boolean):: |
38 |
+ Display the mode button or not? Defaults to true. |
39 |
verbose (boolean):: |
40 |
Should the bar enable verbose output for debugging? Defaults to false. |
41 |
colors (map):: |
42 |
@@ -539,6 +541,7 @@ urgent_workspace_text/urgent_workspace_bar:: |
43 |
"status_command": "i3status", |
44 |
"font": "-misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1", |
45 |
"workspace_buttons": true, |
46 |
+ "binding_mode_button": true, |
47 |
"verbose": false, |
48 |
"colors": { |
49 |
"background": "#c0c0c0", |
b/docs/userguide
54 |
@@ -1186,6 +1186,28 @@ bar { |
55 |
} |
56 |
-------------------- |
57 |
|
58 |
+=== Binding Mode button |
59 |
+ |
60 |
+Specifies whether the current binding mode button should be shown or not. |
61 |
+This is useful if you want to hide the workspace buttons but still be able |
62 |
+to see the current binding mode button. |
63 |
+For an example of a +mode+ definition, please refer to the resize mode |
64 |
+section. |
65 |
+ |
66 |
+The default is to show the mode button. |
67 |
+ |
68 |
+*Syntax*: |
69 |
+-------------------------- |
70 |
+binding_mode_button <yes|no> |
71 |
+-------------------------- |
72 |
+ |
73 |
+*Example*: |
74 |
+-------------------- |
75 |
+bar { |
76 |
+ binding_mode_button no |
77 |
+} |
78 |
+-------------------- |
79 |
+ |
80 |
=== Colors |
81 |
|
82 |
As with i3, colors are in HTML hex format (#rrggbb). The following colors can |
b/i3bar/include/config.h
87 |
@@ -23,6 +23,7 @@ typedef struct config_t { |
88 |
position_t position; |
89 |
int verbose; |
90 |
struct xcb_color_strings_t colors; |
91 |
+ int disable_binding_mode; |
92 |
int disable_ws; |
93 |
char *bar_id; |
94 |
char *command; |
b/i3bar/src/config.c
99 |
@@ -193,6 +193,12 @@ static int config_string_cb(void *params_, const unsigned char *val, unsigned in |
100 |
* |
101 |
*/ |
102 |
static int config_boolean_cb(void *params_, int val) { |
103 |
+ if (!strcmp(cur_key, "binding_mode_button")) { |
104 |
+ DLOG("binding_mode_button = %d\n", val); |
105 |
+ config.disable_binding_mode = !val; |
106 |
+ return 1; |
107 |
+ } |
108 |
+ |
109 |
if (!strcmp(cur_key, "workspace_buttons")) { |
110 |
DLOG("workspace_buttons = %d\n", val); |
111 |
config.disable_ws = !val; |
b/i3bar/src/xcb.c
116 |
@@ -1666,72 +1666,72 @@ void draw_bars(bool unhide) { |
117 |
MIN(outputs_walk->rect.w - traypx - 4, statusline_width), font.height + 2); |
118 |
} |
119 |
|
120 |
- if (config.disable_ws) { |
121 |
- continue; |
122 |
- } |
123 |
- |
124 |
- i3_ws *ws_walk; |
125 |
- |
126 |
- TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { |
127 |
- DLOG("Drawing Button for WS %s at x = %d, len = %d\n", i3string_as_utf8(ws_walk->name), i, ws_walk->name_width); |
128 |
- uint32_t fg_color = colors.inactive_ws_fg; |
129 |
- uint32_t bg_color = colors.inactive_ws_bg; |
130 |
- uint32_t border_color = colors.inactive_ws_border; |
131 |
- if (ws_walk->visible) { |
132 |
- if (!ws_walk->focused) { |
133 |
- fg_color = colors.active_ws_fg; |
134 |
- bg_color = colors.active_ws_bg; |
135 |
- border_color = colors.active_ws_border; |
136 |
- } else { |
137 |
- fg_color = colors.focus_ws_fg; |
138 |
- bg_color = colors.focus_ws_bg; |
139 |
- border_color = colors.focus_ws_border; |
140 |
- if (last_urgent_ws && strcmp(i3string_as_utf8(ws_walk->name), last_urgent_ws) == 0) |
141 |
- walks_away = false; |
142 |
+ if (!config.disable_ws) { |
143 |
+ i3_ws *ws_walk; |
144 |
+ TAILQ_FOREACH(ws_walk, outputs_walk->workspaces, tailq) { |
145 |
+ DLOG("Drawing Button for WS %s at x = %d, len = %d\n", |
146 |
+ i3string_as_utf8(ws_walk->name), i, ws_walk->name_width); |
147 |
+ uint32_t fg_color = colors.inactive_ws_fg; |
148 |
+ uint32_t bg_color = colors.inactive_ws_bg; |
149 |
+ uint32_t border_color = colors.inactive_ws_border; |
150 |
+ if (ws_walk->visible) { |
151 |
+ if (!ws_walk->focused) { |
152 |
+ fg_color = colors.active_ws_fg; |
153 |
+ bg_color = colors.active_ws_bg; |
154 |
+ border_color = colors.active_ws_border; |
155 |
+ } else { |
156 |
+ fg_color = colors.focus_ws_fg; |
157 |
+ bg_color = colors.focus_ws_bg; |
158 |
+ border_color = colors.focus_ws_border; |
159 |
+ if (last_urgent_ws && strcmp(i3string_as_utf8(ws_walk->name), |
160 |
+ last_urgent_ws) == 0) |
161 |
+ walks_away = false; |
162 |
+ } |
163 |
} |
164 |
- } |
165 |
- if (ws_walk->urgent) { |
166 |
- DLOG("WS %s is urgent!\n", i3string_as_utf8(ws_walk->name)); |
167 |
- fg_color = colors.urgent_ws_fg; |
168 |
- bg_color = colors.urgent_ws_bg; |
169 |
- border_color = colors.urgent_ws_border; |
170 |
- unhide = true; |
171 |
- if (!ws_walk->focused) { |
172 |
- FREE(last_urgent_ws); |
173 |
- last_urgent_ws = sstrdup(i3string_as_utf8(ws_walk->name)); |
174 |
+ if (ws_walk->urgent) { |
175 |
+ DLOG("WS %s is urgent!\n", i3string_as_utf8(ws_walk->name)); |
176 |
+ fg_color = colors.urgent_ws_fg; |
177 |
+ bg_color = colors.urgent_ws_bg; |
178 |
+ border_color = colors.urgent_ws_border; |
179 |
+ unhide = true; |
180 |
+ if (!ws_walk->focused) { |
181 |
+ FREE(last_urgent_ws); |
182 |
+ last_urgent_ws = sstrdup(i3string_as_utf8(ws_walk->name)); |
183 |
+ } |
184 |
} |
185 |
- } |
186 |
- uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; |
187 |
- uint32_t vals_border[] = { border_color, border_color }; |
188 |
- xcb_change_gc(xcb_connection, |
189 |
- outputs_walk->bargc, |
190 |
- mask, |
191 |
- vals_border); |
192 |
- xcb_rectangle_t rect_border = { i, 1, ws_walk->name_width + 10, font.height + 4 }; |
193 |
- xcb_poly_fill_rectangle(xcb_connection, |
194 |
- outputs_walk->buffer, |
195 |
- outputs_walk->bargc, |
196 |
- 1, |
197 |
- &rect_border); |
198 |
- uint32_t vals[] = { bg_color, bg_color }; |
199 |
- xcb_change_gc(xcb_connection, |
200 |
- outputs_walk->bargc, |
201 |
- mask, |
202 |
- vals); |
203 |
- xcb_rectangle_t rect = { i + 1, 2, ws_walk->name_width + 8, font.height + 2 }; |
204 |
- xcb_poly_fill_rectangle(xcb_connection, |
205 |
- outputs_walk->buffer, |
206 |
- outputs_walk->bargc, |
207 |
- 1, |
208 |
- &rect); |
209 |
- set_font_colors(outputs_walk->bargc, fg_color, bg_color); |
210 |
- draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc, i + 5, 3, ws_walk->name_width); |
211 |
- i += 10 + ws_walk->name_width + 1; |
212 |
+ uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; |
213 |
+ uint32_t vals_border[] = { border_color, border_color }; |
214 |
+ xcb_change_gc(xcb_connection, |
215 |
+ outputs_walk->bargc, |
216 |
+ mask, |
217 |
+ vals_border); |
218 |
+ xcb_rectangle_t rect_border = { i, 1, ws_walk->name_width + 10, font.height + 4 }; |
219 |
+ xcb_poly_fill_rectangle(xcb_connection, |
220 |
+ outputs_walk->buffer, |
221 |
+ outputs_walk->bargc, |
222 |
+ 1, |
223 |
+ &rect_border); |
224 |
+ uint32_t vals[] = { bg_color, bg_color }; |
225 |
+ xcb_change_gc(xcb_connection, |
226 |
+ outputs_walk->bargc, |
227 |
+ mask, |
228 |
+ vals); |
229 |
+ xcb_rectangle_t rect = { i + 1, 2, ws_walk->name_width + 8, font.height + 2 }; |
230 |
+ xcb_poly_fill_rectangle(xcb_connection, |
231 |
+ outputs_walk->buffer, |
232 |
+ outputs_walk->bargc, |
233 |
+ 1, |
234 |
+ &rect); |
235 |
+ set_font_colors(outputs_walk->bargc, fg_color, bg_color); |
236 |
+ draw_text(ws_walk->name, outputs_walk->buffer, outputs_walk->bargc, |
237 |
+ i + 5, 3, ws_walk->name_width); |
238 |
+ i += 10 + ws_walk->name_width + 1; |
239 |
|
240 |
+ } |
241 |
} |
242 |
|
243 |
- if (binding.name) { |
244 |
|
245 |
+ if (binding.name && !config.disable_binding_mode) { |
246 |
uint32_t fg_color = colors.urgent_ws_fg; |
247 |
uint32_t bg_color = colors.urgent_ws_bg; |
248 |
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; |
249 |
@@ -1766,6 +1766,7 @@ void draw_bars(bool unhide) { |
250 |
unhide = true; |
251 |
} |
252 |
|
253 |
+ |
254 |
i = 0; |
255 |
} |
256 |
|
b/include/config.h
261 |
@@ -267,6 +267,10 @@ struct Barconfig { |
262 |
* zero. */ |
263 |
bool hide_workspace_buttons; |
264 |
|
265 |
+ /** Hide mode button? Configuration option is 'binding_mode_button no' |
266 |
+ * but we invert the bool for the same reason as hide_workspace_buttons.*/ |
267 |
+ bool hide_binding_mode_button; |
268 |
+ |
269 |
/** Enable verbose mode? Useful for debugging purposes. */ |
270 |
bool verbose; |
271 |
|
b/include/config_directives.h
276 |
@@ -74,6 +74,7 @@ CFGFUN(bar_socket_path, const char *socket_path); |
277 |
CFGFUN(bar_tray_output, const char *output); |
278 |
CFGFUN(bar_color_single, const char *colorclass, const char *color); |
279 |
CFGFUN(bar_status_command, const char *command); |
280 |
+CFGFUN(bar_binding_mode_button, const char *value); |
281 |
CFGFUN(bar_workspace_buttons, const char *value); |
282 |
CFGFUN(bar_finish); |
283 |
|
b/parser-specs/config.spec
288 |
@@ -345,20 +345,21 @@ state BAR: |
289 |
error -> |
290 |
'#' -> BAR_IGNORE_LINE |
291 |
'set' -> BAR_IGNORE_LINE |
292 |
- 'i3bar_command' -> BAR_BAR_COMMAND |
293 |
- 'status_command' -> BAR_STATUS_COMMAND |
294 |
- 'socket_path' -> BAR_SOCKET_PATH |
295 |
- 'mode' -> BAR_MODE |
296 |
- 'hidden_state' -> BAR_HIDDEN_STATE |
297 |
- 'id' -> BAR_ID |
298 |
- 'modifier' -> BAR_MODIFIER |
299 |
- 'position' -> BAR_POSITION |
300 |
- 'output' -> BAR_OUTPUT |
301 |
- 'tray_output' -> BAR_TRAY_OUTPUT |
302 |
- 'font' -> BAR_FONT |
303 |
- 'workspace_buttons' -> BAR_WORKSPACE_BUTTONS |
304 |
- 'verbose' -> BAR_VERBOSE |
305 |
- 'colors' -> BAR_COLORS_BRACE |
306 |
+ 'i3bar_command' -> BAR_BAR_COMMAND |
307 |
+ 'status_command' -> BAR_STATUS_COMMAND |
308 |
+ 'socket_path' -> BAR_SOCKET_PATH |
309 |
+ 'mode' -> BAR_MODE |
310 |
+ 'hidden_state' -> BAR_HIDDEN_STATE |
311 |
+ 'id' -> BAR_ID |
312 |
+ 'modifier' -> BAR_MODIFIER |
313 |
+ 'position' -> BAR_POSITION |
314 |
+ 'output' -> BAR_OUTPUT |
315 |
+ 'tray_output' -> BAR_TRAY_OUTPUT |
316 |
+ 'font' -> BAR_FONT |
317 |
+ 'binding_mode_button' -> BAR_BINDING_MODE_BUTTON |
318 |
+ 'workspace_buttons' -> BAR_WORKSPACE_BUTTONS |
319 |
+ 'verbose' -> BAR_VERBOSE |
320 |
+ 'colors' -> BAR_COLORS_BRACE |
321 |
'}' |
322 |
-> call cfg_bar_finish(); INITIAL |
323 |
|
324 |
@@ -411,6 +412,10 @@ state BAR_FONT: |
325 |
font = string |
326 |
-> call cfg_bar_font($font); BAR |
327 |
|
328 |
+state BAR_BINDING_MODE_BUTTON: |
329 |
+ value = word |
330 |
+ -> call cfg_bar_binding_mode_button($value); BAR |
331 |
+ |
332 |
state BAR_WORKSPACE_BUTTONS: |
333 |
value = word |
334 |
-> call cfg_bar_workspace_buttons($value); BAR |
b/src/config_directives.c
339 |
@@ -550,6 +550,10 @@ CFGFUN(bar_status_command, const char *command) { |
340 |
current_bar.status_command = sstrdup(command); |
341 |
} |
342 |
|
343 |
+CFGFUN(bar_binding_mode_button, const char *value) { |
344 |
+ current_bar.hide_binding_mode_button = !eval_boolstr(value); |
345 |
+} |
346 |
+ |
347 |
CFGFUN(bar_workspace_buttons, const char *value) { |
348 |
current_bar.hide_workspace_buttons = !eval_boolstr(value); |
349 |
} |
b/src/ipc.c
354 |
@@ -686,6 +686,9 @@ IPC_HANDLER(get_bar_config) { |
355 |
ystr("workspace_buttons"); |
356 |
y(bool, !config->hide_workspace_buttons); |
357 |
|
358 |
+ ystr("binding_mode_button"); |
359 |
+ y(bool, !config->hide_binding_mode_button); |
360 |
+ |
361 |
ystr("verbose"); |
362 |
y(bool, config->verbose); |
363 |
|
b/testcases/t/177-bar-config.t
368 |
@@ -63,6 +63,7 @@ my $bar_config = $i3->get_bar_config($bar_id)->recv; |
369 |
is($bar_config->{status_command}, 'i3status --foo', 'status_command correct'); |
370 |
ok(!$bar_config->{verbose}, 'verbose off by default'); |
371 |
ok($bar_config->{workspace_buttons}, 'workspace buttons enabled per default'); |
372 |
+ok($bar_config->{binding_mode_button}, 'mode button enabled per default'); |
373 |
is($bar_config->{mode}, 'dock', 'dock mode by default'); |
374 |
is($bar_config->{position}, 'bottom', 'position bottom by default'); |
375 |
|
376 |
@@ -85,7 +86,8 @@ $config = <<EOT; |
377 |
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 |
378 |
|
379 |
bar { |
380 |
- # Start a default instance of i3bar which provides workspace buttons. |
381 |
+ # Start a default instance of i3bar which does not provide |
382 |
+ # workspace buttons. |
383 |
# Additionally, i3status will provide a statusline. |
384 |
status_command i3status --bar |
385 |
|
386 |
@@ -98,6 +100,7 @@ bar { |
387 |
mode dock |
388 |
font Terminus |
389 |
workspace_buttons no |
390 |
+ binding_mode_button no |
391 |
verbose yes |
392 |
socket_path /tmp/foobar |
393 |
|
394 |
@@ -125,6 +128,7 @@ $bar_config = $i3->get_bar_config($bar_id)->recv; |
395 |
is($bar_config->{status_command}, 'i3status --bar', 'status_command correct'); |
396 |
ok($bar_config->{verbose}, 'verbose on'); |
397 |
ok(!$bar_config->{workspace_buttons}, 'workspace buttons disabled'); |
398 |
+ok(!$bar_config->{binding_mode_button}, 'mode button disabled'); |
399 |
is($bar_config->{mode}, 'dock', 'dock mode'); |
400 |
is($bar_config->{position}, 'top', 'position top'); |
401 |
is_deeply($bar_config->{outputs}, [ 'HDMI1', 'HDMI2' ], 'outputs ok'); |
402 |
@@ -230,7 +234,8 @@ $config = <<EOT; |
403 |
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 |
404 |
|
405 |
bar { |
406 |
- # Start a default instance of i3bar which provides workspace buttons. |
407 |
+ # Start a default instance of i3bar which does not provide |
408 |
+ # workspace buttons. |
409 |
# Additionally, i3status will provide a statusline. |
410 |
status_command i3status --bar |
411 |
|
412 |
@@ -243,6 +248,7 @@ bar { |
413 |
mode dock |
414 |
font Terminus |
415 |
workspace_buttons no |
416 |
+ binding_mode_button yes |
417 |
verbose yes |
418 |
socket_path /tmp/foobar |
419 |
|
420 |
@@ -271,6 +277,7 @@ $bar_config = $i3->get_bar_config($bar_id)->recv; |
421 |
is($bar_config->{status_command}, 'i3status --bar', 'status_command correct'); |
422 |
ok($bar_config->{verbose}, 'verbose on'); |
423 |
ok(!$bar_config->{workspace_buttons}, 'workspace buttons disabled'); |
424 |
+ok($bar_config->{binding_mode_button}, 'mode button enabled'); |
425 |
is($bar_config->{mode}, 'dock', 'dock mode'); |
426 |
is($bar_config->{position}, 'top', 'position top'); |
427 |
is_deeply($bar_config->{outputs}, [ 'HDMI1', 'HDMI2' ], 'outputs ok'); |
b/testcases/t/201-config-parser.t
432 |
@@ -627,7 +627,7 @@ EOT |
433 |
|
434 |
$expected = <<'EOT'; |
435 |
cfg_bar_output(LVDS-1) |
436 |
-ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'position', 'output', 'tray_output', 'font', 'workspace_buttons', 'verbose', 'colors', '}' |
437 |
+ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'position', 'output', 'tray_output', 'font', 'binding_mode_button', 'workspace_buttons', 'verbose', 'colors', '}' |
438 |
ERROR: CONFIG: (in file <stdin>) |
439 |
ERROR: CONFIG: Line 1: bar { |
440 |
ERROR: CONFIG: Line 2: output LVDS-1 |