Add setting for minimal width of workspace buttons
This commit is contained in:
parent
ca82f95812
commit
94228fd902
|
@ -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
|
=== Strip workspace numbers/name
|
||||||
|
|
||||||
Specifies whether workspace numbers should be displayed within the workspace
|
Specifies whether workspace numbers should be displayed within the workspace
|
||||||
|
|
|
@ -52,6 +52,7 @@ typedef struct config_t {
|
||||||
struct xcb_color_strings_t colors;
|
struct xcb_color_strings_t colors;
|
||||||
bool disable_binding_mode_indicator;
|
bool disable_binding_mode_indicator;
|
||||||
bool disable_ws;
|
bool disable_ws;
|
||||||
|
int ws_min_width;
|
||||||
bool strip_ws_numbers;
|
bool strip_ws_numbers;
|
||||||
bool strip_ws_name;
|
bool strip_ws_name;
|
||||||
char *bar_id;
|
char *bar_id;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
/* Name of current binding mode and its render width */
|
/* Name of current binding mode and its render width */
|
||||||
struct mode {
|
struct mode {
|
||||||
i3String *name;
|
i3String *name;
|
||||||
int width;
|
int name_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct mode mode;
|
typedef struct mode mode;
|
||||||
|
|
|
@ -345,6 +345,12 @@ static int config_integer_cb(void *params_, long long val) {
|
||||||
return 1;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ static int mode_end_map_cb(void *params_) {
|
||||||
params->mode->name = i3string_from_utf8(params->name);
|
params->mode->name = i3string_from_utf8(params->name);
|
||||||
i3string_set_markup(params->mode->name, params->pango_markup);
|
i3string_set_markup(params->mode->name, params->pango_markup);
|
||||||
/* Save its rendered width */
|
/* 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));
|
DLOG("Got mode change: %s\n", i3string_as_utf8(params->mode->name));
|
||||||
FREE(params->cur_key);
|
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).
|
* 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-
|
* 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;
|
i3_ws *cur_ws = NULL, *clicked_ws = NULL, *ws_walk;
|
||||||
|
|
||||||
TAILQ_FOREACH(ws_walk, walk->workspaces, tailq) {
|
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)
|
if (x >= workspace_width && x <= workspace_width + w)
|
||||||
clicked_ws = ws_walk;
|
clicked_ws = ws_walk;
|
||||||
if (ws_walk->visible)
|
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
|
* Render the bars, with buttons and statusline
|
||||||
*
|
*
|
||||||
|
@ -1964,26 +1992,11 @@ void draw_bars(bool unhide) {
|
||||||
unhide = true;
|
unhide = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw the border of the button. */
|
int w = predict_button_width(ws_walk->name_width);
|
||||||
draw_util_rectangle(&(outputs_walk->buffer), border_color,
|
draw_button(&(outputs_walk->buffer), fg_color, bg_color, border_color,
|
||||||
workspace_width,
|
workspace_width, w, ws_walk->name_width, ws_walk->name);
|
||||||
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. */
|
workspace_width += w;
|
||||||
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;
|
|
||||||
if (TAILQ_NEXT(ws_walk, tailq) != NULL)
|
if (TAILQ_NEXT(ws_walk, tailq) != NULL)
|
||||||
workspace_width += logical_px(ws_spacing_px);
|
workspace_width += logical_px(ws_spacing_px);
|
||||||
}
|
}
|
||||||
|
@ -1992,28 +2005,12 @@ void draw_bars(bool unhide) {
|
||||||
if (binding.name && !config.disable_binding_mode_indicator) {
|
if (binding.name && !config.disable_binding_mode_indicator) {
|
||||||
workspace_width += logical_px(ws_spacing_px);
|
workspace_width += logical_px(ws_spacing_px);
|
||||||
|
|
||||||
color_t fg_color = colors.binding_mode_fg;
|
int w = predict_button_width(binding.name_width);
|
||||||
color_t bg_color = colors.binding_mode_bg;
|
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);
|
||||||
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);
|
|
||||||
|
|
||||||
unhide = true;
|
unhide = true;
|
||||||
workspace_width += 2 * logical_px(ws_hoff_px) + 2 * logical_px(1) + binding.width;
|
workspace_width += w;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TAILQ_EMPTY(&statusline_head)) {
|
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_status_command, const char *command);
|
||||||
CFGFUN(bar_binding_mode_indicator, const char *value);
|
CFGFUN(bar_binding_mode_indicator, const char *value);
|
||||||
CFGFUN(bar_workspace_buttons, 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_numbers, const char *value);
|
||||||
CFGFUN(bar_strip_workspace_name, const char *value);
|
CFGFUN(bar_strip_workspace_name, const char *value);
|
||||||
CFGFUN(bar_start);
|
CFGFUN(bar_start);
|
||||||
|
|
|
@ -325,6 +325,9 @@ struct Barconfig {
|
||||||
* zero. */
|
* zero. */
|
||||||
bool hide_workspace_buttons;
|
bool hide_workspace_buttons;
|
||||||
|
|
||||||
|
/** The minimal width for workspace buttons. */
|
||||||
|
int workspace_min_width;
|
||||||
|
|
||||||
/** Strip workspace numbers? Configuration option is
|
/** Strip workspace numbers? Configuration option is
|
||||||
* 'strip_workspace_numbers yes'. */
|
* 'strip_workspace_numbers yes'. */
|
||||||
bool strip_workspace_numbers;
|
bool strip_workspace_numbers;
|
||||||
|
|
|
@ -468,6 +468,7 @@ state BAR:
|
||||||
'separator_symbol' -> BAR_SEPARATOR_SYMBOL
|
'separator_symbol' -> BAR_SEPARATOR_SYMBOL
|
||||||
'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
|
'binding_mode_indicator' -> BAR_BINDING_MODE_INDICATOR
|
||||||
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS
|
'workspace_buttons' -> BAR_WORKSPACE_BUTTONS
|
||||||
|
'workspace_min_width' -> BAR_WORKSPACE_MIN_WIDTH
|
||||||
'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS
|
'strip_workspace_numbers' -> BAR_STRIP_WORKSPACE_NUMBERS
|
||||||
'strip_workspace_name' -> BAR_STRIP_WORKSPACE_NAME
|
'strip_workspace_name' -> BAR_STRIP_WORKSPACE_NAME
|
||||||
'verbose' -> BAR_VERBOSE
|
'verbose' -> BAR_VERBOSE
|
||||||
|
@ -572,6 +573,16 @@ state BAR_WORKSPACE_BUTTONS:
|
||||||
value = word
|
value = word
|
||||||
-> call cfg_bar_workspace_buttons($value); BAR
|
-> 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:
|
state BAR_STRIP_WORKSPACE_NUMBERS:
|
||||||
value = word
|
value = word
|
||||||
-> call cfg_bar_strip_workspace_numbers($value); BAR
|
-> 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);
|
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) {
|
CFGFUN(bar_strip_workspace_numbers, const char *value) {
|
||||||
current_bar->strip_workspace_numbers = eval_boolstr(value);
|
current_bar->strip_workspace_numbers = eval_boolstr(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -780,6 +780,9 @@ static void dump_bar_config(yajl_gen gen, Barconfig *config) {
|
||||||
ystr("workspace_buttons");
|
ystr("workspace_buttons");
|
||||||
y(bool, !config->hide_workspace_buttons);
|
y(bool, !config->hide_workspace_buttons);
|
||||||
|
|
||||||
|
ystr("workspace_min_width");
|
||||||
|
y(integer, config->workspace_min_width);
|
||||||
|
|
||||||
ystr("strip_workspace_numbers");
|
ystr("strip_workspace_numbers");
|
||||||
y(bool, config->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');
|
is($bar_config->{status_command}, 'i3status --foo', 'status_command correct');
|
||||||
ok(!$bar_config->{verbose}, 'verbose off by default');
|
ok(!$bar_config->{verbose}, 'verbose off by default');
|
||||||
ok($bar_config->{workspace_buttons}, 'workspace buttons enabled per 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');
|
ok($bar_config->{binding_mode_indicator}, 'mode indicator enabled per default');
|
||||||
is($bar_config->{mode}, 'dock', 'dock mode by default');
|
is($bar_config->{mode}, 'dock', 'dock mode by default');
|
||||||
is($bar_config->{position}, 'bottom', 'position bottom by default');
|
is($bar_config->{position}, 'bottom', 'position bottom by default');
|
||||||
|
@ -102,6 +103,7 @@ bar {
|
||||||
mode dock
|
mode dock
|
||||||
font Terminus
|
font Terminus
|
||||||
workspace_buttons no
|
workspace_buttons no
|
||||||
|
workspace_min_width 30
|
||||||
binding_mode_indicator no
|
binding_mode_indicator no
|
||||||
verbose yes
|
verbose yes
|
||||||
socket_path /tmp/foobar
|
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');
|
is($bar_config->{status_command}, 'i3status --bar', 'status_command correct');
|
||||||
ok($bar_config->{verbose}, 'verbose on');
|
ok($bar_config->{verbose}, 'verbose on');
|
||||||
ok(!$bar_config->{workspace_buttons}, 'workspace buttons disabled');
|
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');
|
ok(!$bar_config->{binding_mode_indicator}, 'mode indicator disabled');
|
||||||
is($bar_config->{mode}, 'dock', 'dock mode');
|
is($bar_config->{mode}, 'dock', 'dock mode');
|
||||||
is($bar_config->{position}, 'top', 'position top');
|
is($bar_config->{position}, 'top', 'position top');
|
||||||
|
|
|
@ -733,7 +733,7 @@ EOT
|
||||||
$expected = <<'EOT';
|
$expected = <<'EOT';
|
||||||
cfg_bar_start()
|
cfg_bar_start()
|
||||||
cfg_bar_output(LVDS-1)
|
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: (in file <stdin>)
|
||||||
ERROR: CONFIG: Line 1: bar {
|
ERROR: CONFIG: Line 1: bar {
|
||||||
ERROR: CONFIG: Line 2: output LVDS-1
|
ERROR: CONFIG: Line 2: output LVDS-1
|
||||||
|
|
Loading…
Reference in New Issue