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

Commit

Permalink
Merge remote-tracking branch 'vanilla/next' into gaps-next
Browse files Browse the repository at this point in the history
  • Loading branch information
Airblader committed Oct 6, 2019
2 parents 474f57f + ba0868e commit b5a4373
Show file tree
Hide file tree
Showing 18 changed files with 142 additions and 49 deletions.
8 changes: 8 additions & 0 deletions docs/ipc
Expand Up @@ -357,6 +357,14 @@ focus (array of integer)::
order. Traversing the tree by following the first entry in this array
will result in eventually reaching the one node with +focused+ set to
true.
fullscreen_mode (integer)::
Whether this container is in fullscreen state or not.
Possible values are
+0+ (no fullscreen),
+1+ (fullscreened on output) or
+2+ (fullscreened globally).
Note that all workspaces are considered fullscreened on their respective output.

nodes (array of node)::
The tiling (i.e. non-floating) child containers of this node.
floating_nodes (array of node)::
Expand Down
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 @@ -53,6 +53,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 @@ -351,6 +351,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 @@ -1917,6 +1926,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 = bar_height - 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,
bar_height / 2 - font.height / 2, text_width);
}

/*
* Render the bars, with buttons and statusline
*
Expand Down Expand Up @@ -1972,26 +2000,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),
bar_height - 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),
bar_height - 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),
bar_height / 2 - font.height / 2,
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 @@ -2000,28 +2013,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),
bar_height - 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),
bar_height - 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),
bar_height / 2 - font.height / 2,
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 @@ -101,6 +101,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 @@ -334,6 +334,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 @@ -498,6 +498,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 @@ -603,6 +604,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 @@ -808,6 +808,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
1 change: 1 addition & 0 deletions src/floating.c
Expand Up @@ -371,6 +371,7 @@ void floating_enable(Con *con, bool automatic) {
if (nc->rect.x == 0 && nc->rect.y == 0) {
Con *leader;
if (con->window && con->window->leader != XCB_NONE &&
con->window->id != con->window->leader &&
(leader = con_by_window_id(con->window->leader)) != NULL) {
DLOG("Centering above leader\n");
floating_center(nc, leader->rect);
Expand Down
3 changes: 3 additions & 0 deletions src/ipc.c
Expand Up @@ -818,6 +818,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
15 changes: 12 additions & 3 deletions src/workspace.c
Expand Up @@ -213,18 +213,27 @@ void extract_workspace_names_from_bindings(void) {
while (*target == ' ' || *target == '\t')
target++;
/* We check if this is the workspace
* next/prev/next_on_output/prev_on_output/back_and_forth/number command.
* next/prev/next_on_output/prev_on_output/back_and_forth command.
* Beware: The workspace names "next", "prev", "next_on_output",
* "prev_on_output", "number", "back_and_forth" and "current" are OK,
* "prev_on_output", "back_and_forth" and "current" are OK,
* so we check before stripping the double quotes */
if (strncasecmp(target, "next", strlen("next")) == 0 ||
strncasecmp(target, "prev", strlen("prev")) == 0 ||
strncasecmp(target, "next_on_output", strlen("next_on_output")) == 0 ||
strncasecmp(target, "prev_on_output", strlen("prev_on_output")) == 0 ||
strncasecmp(target, "number", strlen("number")) == 0 ||
strncasecmp(target, "back_and_forth", strlen("back_and_forth")) == 0 ||
strncasecmp(target, "current", strlen("current")) == 0)
continue;
if (strncasecmp(target, "--no-auto-back-and-forth", strlen("--no-auto-back-and-forth")) == 0) {
target += strlen("--no-auto-back-and-forth");
while (*target == ' ' || *target == '\t')
target++;
}
if (strncasecmp(target, "number", strlen("number")) == 0) {
target += strlen("number");
while (*target == ' ' || *target == '\t')
target++;
}
char *target_name = parse_string(&target, false);
if (target_name == NULL)
continue;
Expand Down
18 changes: 18 additions & 0 deletions testcases/t/172-start-on-named-ws.t
Expand Up @@ -125,4 +125,22 @@ is_deeply(\@names, [ '3' ], 'i3 starts on workspace 3');

exit_gracefully($pid);

##############################################################
# 7: verify optional flags do not affect startup workspace
##############################################################

$config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
bindsym Mod1+1 workspace --no-auto-back-and-forth number 3:three
EOT

$pid = launch_with_config($config);

@names = @{get_workspace_names()};
is_deeply(\@names, [ '3:three' ], 'i3 starts on named workspace 3:three');

exit_gracefully($pid);

done_testing;
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 @@ -736,7 +736,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', 'height', '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', 'height', 'colors', '}'
ERROR: CONFIG: (in file <stdin>)
ERROR: CONFIG: Line 1: bar {
ERROR: CONFIG: Line 2: output LVDS-1
Expand Down
3 changes: 1 addition & 2 deletions testcases/t/270-config-no-newline-end.t
Expand Up @@ -19,10 +19,9 @@
use i3test i3_autostart => 0;

my $first_lines = <<'EOT';
set $workspace1 workspace number 1
set $workspace0 workspace eggs
bindsym Mod4+1 $workspace1
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
EOT

# Intentionally don't add a trailing newline for the last line since this is
Expand Down

0 comments on commit b5a4373

Please sign in to comment.