Skip to content
Permalink
Browse files

Merge pull request #3728 from cdlscpmv/next

Add setting for minimal width of workspace buttons
  • Loading branch information...
Airblader committed Oct 5, 2019
2 parents d22f034 + 94228fd commit ba0868e593033cfc407fb898311326a52e3578a5
@@ -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
@@ -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;
@@ -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;
@@ -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;
}

@@ -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);
@@ -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-
@@ -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)
@@ -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
*
@@ -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);
}
@@ -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)) {
@@ -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);
@@ -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;
@@ -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
@@ -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
@@ -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);
}
@@ -789,6 +789,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);

@@ -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');
@@ -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
@@ -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');
@@ -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

0 comments on commit ba0868e

Please sign in to comment.
You can’t perform that action at this time.