Skip to content
This repository has been archived by the owner on Apr 18, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Add setting for minimal width of workspace buttons
  • Loading branch information
cdlscpmv committed Jun 25, 2019
1 parent ca82f95 commit 94228fd
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 44 deletions.
29 changes: 29 additions & 0 deletions docs/userguide
Expand Up @@ -1625,6 +1625,35 @@ bar {
}
------------------------

=== Minimal width for workspace buttons

By default, the width a workspace button is determined by the width of the text
showing the workspace name. If the name is too short (say, one letter), then the
workspace button may look too small.

This option specifies the minimum width for workspace buttons. If the name of
a workspace is too short to cover the button, an additional padding is added on
both sides of the button so that the text is centered.

The default value of zero means that no additional padding is added.

The setting also applies to the current binding mode indicator.

Note that the specified pixels refer to logical pixels, which may translate
into more pixels on HiDPI displays.

*Syntax*:
------------------------
workspace_min_width <px> [px]
------------------------

*Example*:
------------------------
bar {
workspace_min_width 40
}
------------------------

=== Strip workspace numbers/name

Specifies whether workspace numbers should be displayed within the workspace
Expand Down
1 change: 1 addition & 0 deletions i3bar/include/configuration.h
Expand Up @@ -52,6 +52,7 @@ typedef struct config_t {
struct xcb_color_strings_t colors;
bool disable_binding_mode_indicator;
bool disable_ws;
int ws_min_width;
bool strip_ws_numbers;
bool strip_ws_name;
char *bar_id;
Expand Down
2 changes: 1 addition & 1 deletion i3bar/include/mode.h
Expand Up @@ -18,7 +18,7 @@
/* Name of current binding mode and its render width */
struct mode {
i3String *name;
int width;
int name_width;
};

typedef struct mode mode;
Expand Down
6 changes: 6 additions & 0 deletions i3bar/src/config.c
Expand Up @@ -345,6 +345,12 @@ static int config_integer_cb(void *params_, long long val) {
return 1;
}

if (!strcmp(cur_key, "workspace_min_width")) {
DLOG("workspace_min_width = %lld\n", val);
config.ws_min_width = val;
return 1;
}

return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion i3bar/src/mode.c
Expand Up @@ -81,7 +81,7 @@ static int mode_end_map_cb(void *params_) {
params->mode->name = i3string_from_utf8(params->name);
i3string_set_markup(params->mode->name, params->pango_markup);
/* Save its rendered width */
params->mode->width = predict_text_width(params->mode->name);
params->mode->name_width = predict_text_width(params->mode->name);

DLOG("Got mode change: %s\n", i3string_as_utf8(params->mode->name));
FREE(params->cur_key);
Expand Down
79 changes: 38 additions & 41 deletions i3bar/src/xcb.c
Expand Up @@ -499,6 +499,15 @@ static void child_handle_button(xcb_button_press_event_t *event, i3_output *outp
}
}

/*
* Predict the width of a workspace button or the current binding mode indicator.
*
*/
static int predict_button_width(int name_width) {
return MAX(name_width + 2 * logical_px(ws_hoff_px) + 2 * logical_px(1),
logical_px(config.ws_min_width));
}

/*
* Handle a button press event (i.e. a mouse click on one of our bars).
* We determine, whether the click occurred on a workspace button or if the scroll-
Expand Down Expand Up @@ -530,7 +539,7 @@ static void handle_button(xcb_button_press_event_t *event) {
i3_ws *cur_ws = NULL, *clicked_ws = NULL, *ws_walk;

TAILQ_FOREACH(ws_walk, walk->workspaces, tailq) {
int w = 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + ws_walk->name_width;
int w = predict_button_width(ws_walk->name_width);
if (x >= workspace_width && x <= workspace_width + w)
clicked_ws = ws_walk;
if (ws_walk->visible)
Expand Down Expand Up @@ -1909,6 +1918,25 @@ void reconfig_windows(bool redraw_bars) {
}
}

/*
* Draw the button for a workspace or the current binding mode indicator.
*
*/
static void draw_button(surface_t *surface, color_t fg_color, color_t bg_color, color_t border_color,
int x, int width, int text_width, i3String *text) {
int height = font.height + 2 * logical_px(ws_voff_px) - 2 * logical_px(1);

/* Draw the border of the button. */
draw_util_rectangle(surface, border_color, x, logical_px(1), width, height);

/* Draw the inside of the button. */
draw_util_rectangle(surface, bg_color, x + logical_px(1), 2 * logical_px(1),
width - 2 * logical_px(1), height - 2 * logical_px(1));

draw_util_text(text, surface, fg_color, bg_color, x + (width - text_width) / 2,
logical_px(ws_voff_px), text_width);
}

/*
* Render the bars, with buttons and statusline
*
Expand Down Expand Up @@ -1964,26 +1992,11 @@ void draw_bars(bool unhide) {
unhide = true;
}

/* Draw the border of the button. */
draw_util_rectangle(&(outputs_walk->buffer), border_color,
workspace_width,
logical_px(1),
ws_walk->name_width + 2 * logical_px(ws_hoff_px) + 2 * logical_px(1),
font.height + 2 * logical_px(ws_voff_px) - 2 * logical_px(1));

/* Draw the inside of the button. */
draw_util_rectangle(&(outputs_walk->buffer), bg_color,
workspace_width + logical_px(1),
2 * logical_px(1),
ws_walk->name_width + 2 * logical_px(ws_hoff_px),
font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1));

draw_util_text(ws_walk->name, &(outputs_walk->buffer), fg_color, bg_color,
workspace_width + logical_px(ws_hoff_px) + logical_px(1),
logical_px(ws_voff_px),
ws_walk->name_width);

workspace_width += 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + ws_walk->name_width;
int w = predict_button_width(ws_walk->name_width);
draw_button(&(outputs_walk->buffer), fg_color, bg_color, border_color,
workspace_width, w, ws_walk->name_width, ws_walk->name);

workspace_width += w;
if (TAILQ_NEXT(ws_walk, tailq) != NULL)
workspace_width += logical_px(ws_spacing_px);
}
Expand All @@ -1992,28 +2005,12 @@ void draw_bars(bool unhide) {
if (binding.name && !config.disable_binding_mode_indicator) {
workspace_width += logical_px(ws_spacing_px);

color_t fg_color = colors.binding_mode_fg;
color_t bg_color = colors.binding_mode_bg;

draw_util_rectangle(&(outputs_walk->buffer), colors.binding_mode_border,
workspace_width,
logical_px(1),
binding.width + 2 * logical_px(ws_hoff_px) + 2 * logical_px(1),
font.height + 2 * logical_px(ws_voff_px) - 2 * logical_px(1));

draw_util_rectangle(&(outputs_walk->buffer), bg_color,
workspace_width + logical_px(1),
2 * logical_px(1),
binding.width + 2 * logical_px(ws_hoff_px),
font.height + 2 * logical_px(ws_voff_px) - 4 * logical_px(1));

draw_util_text(binding.name, &(outputs_walk->buffer), fg_color, bg_color,
workspace_width + logical_px(ws_hoff_px) + logical_px(1),
logical_px(ws_voff_px),
binding.width);
int w = predict_button_width(binding.name_width);
draw_button(&(outputs_walk->buffer), colors.binding_mode_fg, colors.binding_mode_bg,
colors.binding_mode_border, workspace_width, w, binding.name_width, binding.name);

unhide = true;
workspace_width += 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + binding.width;
workspace_width += w;
}

if (!TAILQ_EMPTY(&statusline_head)) {
Expand Down
1 change: 1 addition & 0 deletions include/config_directives.h
Expand Up @@ -97,6 +97,7 @@ CFGFUN(bar_color_single, const char *colorclass, const char *color);
CFGFUN(bar_status_command, const char *command);
CFGFUN(bar_binding_mode_indicator, const char *value);
CFGFUN(bar_workspace_buttons, const char *value);
CFGFUN(bar_workspace_min_width, const long width);
CFGFUN(bar_strip_workspace_numbers, const char *value);
CFGFUN(bar_strip_workspace_name, const char *value);
CFGFUN(bar_start);
Expand Down
3 changes: 3 additions & 0 deletions include/configuration.h
Expand Up @@ -325,6 +325,9 @@ struct Barconfig {
* zero. */
bool hide_workspace_buttons;

/** The minimal width for workspace buttons. */
int workspace_min_width;

/** Strip workspace numbers? Configuration option is
* 'strip_workspace_numbers yes'. */
bool strip_workspace_numbers;
Expand Down
11 changes: 11 additions & 0 deletions parser-specs/config.spec
Expand Up @@ -468,6 +468,7 @@ state BAR:
'separator_symbol' -> BAR_SEPARATOR_SYMBOL
'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS
'workspace_min_width' -> BAR_WORKSPACE_MIN_WIDTH
'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS
'strip_workspace_name' -> BAR_STRIP_WORKSPACE_NAME
'verbose' -> BAR_VERBOSE
Expand Down Expand Up @@ -572,6 +573,16 @@ state BAR_WORKSPACE_BUTTONS:
value = word
-> call cfg_bar_workspace_buttons($value); BAR

state BAR_WORKSPACE_MIN_WIDTH:
width = number
-> BAR_WORKSPACE_MIN_WIDTH_PX

state BAR_WORKSPACE_MIN_WIDTH_PX:
'px'
->
end
-> call cfg_bar_workspace_min_width(&width); BAR

state BAR_STRIP_WORKSPACE_NUMBERS:
value = word
-> call cfg_bar_strip_workspace_numbers($value); BAR
Expand Down
4 changes: 4 additions & 0 deletions src/config_directives.c
Expand Up @@ -646,6 +646,10 @@ CFGFUN(bar_workspace_buttons, const char *value) {
current_bar->hide_workspace_buttons = !eval_boolstr(value);
}

CFGFUN(bar_workspace_min_width, const long width) {
current_bar->workspace_min_width = width;
}

CFGFUN(bar_strip_workspace_numbers, const char *value) {
current_bar->strip_workspace_numbers = eval_boolstr(value);
}
Expand Down
3 changes: 3 additions & 0 deletions src/ipc.c
Expand Up @@ -780,6 +780,9 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
ystr("workspace_buttons");
y(bool, !config->hide_workspace_buttons);

ystr("workspace_min_width");
y(integer, config->workspace_min_width);

ystr("strip_workspace_numbers");
y(bool, config->strip_workspace_numbers);

Expand Down
3 changes: 3 additions & 0 deletions testcases/t/177-bar-config.t
Expand Up @@ -63,6 +63,7 @@ my $bar_config = $i3->get_bar_config($bar_id)->recv;
is($bar_config->{status_command}, 'i3status --foo', 'status_command correct');
ok(!$bar_config->{verbose}, 'verbose off by default');
ok($bar_config->{workspace_buttons}, 'workspace buttons enabled per default');
is($bar_config->{workspace_min_width}, 0, 'workspace_min_width ok');
ok($bar_config->{binding_mode_indicator}, 'mode indicator enabled per default');
is($bar_config->{mode}, 'dock', 'dock mode by default');
is($bar_config->{position}, 'bottom', 'position bottom by default');
Expand Down Expand Up @@ -102,6 +103,7 @@ bar {
mode dock
font Terminus
workspace_buttons no
workspace_min_width 30
binding_mode_indicator no
verbose yes
socket_path /tmp/foobar
Expand Down Expand Up @@ -134,6 +136,7 @@ $bar_config = $i3->get_bar_config($bar_id)->recv;
is($bar_config->{status_command}, 'i3status --bar', 'status_command correct');
ok($bar_config->{verbose}, 'verbose on');
ok(!$bar_config->{workspace_buttons}, 'workspace buttons disabled');
is($bar_config->{workspace_min_width}, 30, 'workspace_min_width ok');
ok(!$bar_config->{binding_mode_indicator}, 'mode indicator disabled');
is($bar_config->{mode}, 'dock', 'dock mode');
is($bar_config->{position}, 'top', 'position top');
Expand Down
2 changes: 1 addition & 1 deletion testcases/t/201-config-parser.t
Expand Up @@ -733,7 +733,7 @@ EOT
$expected = <<'EOT';
cfg_bar_start()
cfg_bar_output(LVDS-1)
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'wheel_up_cmd', 'wheel_down_cmd', 'bindsym', 'position', 'output', 'tray_output', 'tray_padding', 'font', 'separator_symbol', 'binding_mode_indicator', 'workspace_buttons', 'strip_workspace_numbers', 'strip_workspace_name', 'verbose', 'colors', '}'
ERROR: CONFIG: Expected one of these tokens: <end>, '#', 'set', 'i3bar_command', 'status_command', 'socket_path', 'mode', 'hidden_state', 'id', 'modifier', 'wheel_up_cmd', 'wheel_down_cmd', 'bindsym', 'position', 'output', 'tray_output', 'tray_padding', 'font', 'separator_symbol', 'binding_mode_indicator', 'workspace_buttons', 'workspace_min_width', 'strip_workspace_numbers', 'strip_workspace_name', 'verbose', 'colors', '}'
ERROR: CONFIG: (in file <stdin>)
ERROR: CONFIG: Line 1: bar {
ERROR: CONFIG: Line 2: output LVDS-1
Expand Down

0 comments on commit 94228fd

Please sign in to comment.