diff options
author | Alessandro Vinciguerra <30745465+Arc676@users.noreply.github.com> | 2024-01-28 11:30:28 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-28 11:30:28 +0100 |
commit | ca510e5e0f9ef6e7075da5314e691cc8ab64b6a4 (patch) | |
tree | 8c5f9c6ed7853b2cab5ec900c298a13248e14ef2 | |
parent | f1696245608945eadc25105cf3fe41717551d968 (diff) | |
download | i3-ca510e5e0f9ef6e7075da5314e691cc8ab64b6a4.tar.gz i3-ca510e5e0f9ef6e7075da5314e691cc8ab64b6a4.zip |
Shrinking on a per-block basis (#5818)
Co-authored-by: Orestis Floros <orestisflo@gmail.com>
-rw-r--r-- | i3bar/include/common.h | 3 | ||||
-rw-r--r-- | i3bar/include/outputs.h | 2 | ||||
-rw-r--r-- | i3bar/src/child.c | 4 | ||||
-rw-r--r-- | i3bar/src/outputs.c | 1 | ||||
-rw-r--r-- | i3bar/src/xcb.c | 149 | ||||
-rw-r--r-- | release-notes/changes/4-shrink-i3bar-blocks | 1 |
6 files changed, 107 insertions, 53 deletions
diff --git a/i3bar/include/common.h b/i3bar/include/common.h index e0f2e7e4..9c13d02f 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -46,6 +46,9 @@ struct status_block { i3String *full_text; i3String *short_text; + bool use_short; + uint32_t render_length; + char *color; char *background; char *border; diff --git a/i3bar/include/outputs.h b/i3bar/include/outputs.h index 560abe53..dfe145fe 100644 --- a/i3bar/include/outputs.h +++ b/i3bar/include/outputs.h @@ -65,8 +65,6 @@ struct i3_output { surface_t statusline_buffer; /* How much of statusline_buffer's horizontal space was used on last statusline render. */ int statusline_width; - /* Whether statusline block short texts where used on last statusline render. */ - bool statusline_short_text; /* The actual window on which we draw. */ surface_t bar; diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 6dc19f9b..e4c97072 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -8,6 +8,7 @@ * */ #include "common.h" +#include "queue.h" #include "yajl_utils.h" #include <ctype.h> /* isspace */ @@ -21,6 +22,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <strings.h> #include <sys/wait.h> #include <unistd.h> @@ -354,11 +356,13 @@ static int stdin_end_map(void *context) { i3string_set_markup(new_block->full_text, new_block->pango_markup); + new_block->use_short = false; if (new_block->short_text != NULL) { i3string_set_markup(new_block->short_text, new_block->pango_markup); } TAILQ_INSERT_TAIL(&statusline_buffer, new_block, blocks); + return 1; } diff --git a/i3bar/src/outputs.c b/i3bar/src/outputs.c index 125663eb..279d4a78 100644 --- a/i3bar/src/outputs.c +++ b/i3bar/src/outputs.c @@ -147,7 +147,6 @@ static int outputs_start_map_cb(void *params_) { new_output->visible = false; new_output->ws = 0, new_output->statusline_width = 0; - new_output->statusline_short_text = false; memset(&new_output->rect, 0, sizeof(rect)); memset(&new_output->bar, 0, sizeof(surface_t)); memset(&new_output->buffer, 0, sizeof(surface_t)); diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c index afa03d74..7202825a 100644 --- a/i3bar/src/xcb.c +++ b/i3bar/src/xcb.c @@ -12,6 +12,7 @@ #include <err.h> #include <ev.h> #include <i3/ipc.h> +#include <stddef.h> #include <stdlib.h> #include <string.h> @@ -188,48 +189,59 @@ static void draw_separator(i3_output *output, uint32_t x, struct status_block *b } } -static uint32_t predict_statusline_length(bool use_short_text) { - uint32_t width = 0; - struct status_block *block; +static void predict_block_length(struct status_block *block) { + i3String *text = block->full_text; + struct status_block_render_desc *render = &block->full_render; + if (block->use_short && block->short_text != NULL) { + text = block->short_text; + render = &block->short_render; + } - TAILQ_FOREACH (block, &statusline_head, blocks) { - i3String *text = block->full_text; - struct status_block_render_desc *render = &block->full_render; - if (use_short_text && block->short_text != NULL) { - text = block->short_text; - render = &block->short_render; - } + if (i3string_get_num_bytes(text) == 0) { + block->render_length = 0; + return; + } - if (i3string_get_num_bytes(text) == 0) { - continue; - } + render->width = predict_text_width(text); + if (block->border) { + render->width += logical_px(block->border_left + block->border_right); + } - render->width = predict_text_width(text); - if (block->border) { - render->width += logical_px(block->border_left + block->border_right); + /* Compute offset and append for text alignment in min_width. */ + if (block->min_width <= render->width) { + render->x_offset = 0; + render->x_append = 0; + } else { + uint32_t padding_width = block->min_width - render->width; + switch (block->align) { + case ALIGN_LEFT: + render->x_append = padding_width; + break; + case ALIGN_RIGHT: + render->x_offset = padding_width; + break; + case ALIGN_CENTER: + render->x_offset = padding_width / 2; + render->x_append = padding_width / 2 + padding_width % 2; + break; } + } - /* Compute offset and append for text alignment in min_width. */ - if (block->min_width <= render->width) { - render->x_offset = 0; - render->x_append = 0; - } else { - uint32_t padding_width = block->min_width - render->width; - switch (block->align) { - case ALIGN_LEFT: - render->x_append = padding_width; - break; - case ALIGN_RIGHT: - render->x_offset = padding_width; - break; - case ALIGN_CENTER: - render->x_offset = padding_width / 2; - render->x_append = padding_width / 2 + padding_width % 2; - break; - } + block->render_length = render->width + render->x_offset + render->x_append; +} + +static uint32_t predict_statusline_length(void) { + uint32_t width = 0; + struct status_block *block; + + TAILQ_FOREACH (block, &statusline_head, blocks) { + predict_block_length(block); + uint32_t block_width = block->render_length; + if (block_width == 0) { + continue; } - width += render->width + render->x_offset + render->x_append; + width += block_width; /* If this is not the last block, add some pixels for a separator. */ if (TAILQ_NEXT(block, blocks) != NULL) { @@ -240,10 +252,49 @@ static uint32_t predict_statusline_length(bool use_short_text) { return width; } +static uint32_t switch_block_to_short(struct status_block *block) { + /* Skip blocks that have no short form or are already in short form */ + if (block->short_text == NULL || block->use_short) { + return 0; + } + uint32_t full = block->render_length; + block->use_short = true; + predict_block_length(block); + return full - block->render_length; +} + +static uint32_t adjust_statusline_length(uint32_t max_length) { + uint32_t width = predict_statusline_length(); + + /* Progressively switch the blocks to short mode */ + struct status_block *block; + TAILQ_FOREACH (block, &statusline_head, blocks) { + if (width < max_length) { + break; + } + width -= switch_block_to_short(block); + + /* Provide support for representing a single logical block using multiple + * JSON blocks: if one block is shortened, ensure that all other blocks + * with the same name are also shortened such that the entire logical block uses + * the short form text. */ + if (block->name) { + struct status_block *other; + TAILQ_FOREACH (other, &statusline_head, blocks) { + if (other->name && !strcmp(other->name, block->name)) { + width -= switch_block_to_short(other); + } + } + } + } + + return width; +} + /* * Redraws the statusline to the output's statusline_buffer */ -static void draw_statusline(i3_output *output, uint32_t clip_left, bool use_focus_colors, bool use_short_text) { +static void draw_statusline(i3_output *output, uint32_t clip_left, bool use_focus_colors) { struct status_block *block; color_t bar_color = (use_focus_colors ? colors.focus_bar_bg : colors.bar_bg); @@ -261,7 +312,7 @@ static void draw_statusline(i3_output *output, uint32_t clip_left, bool use_focu TAILQ_FOREACH (block, &statusline_head, blocks) { i3String *text = block->full_text; struct status_block_render_desc *render = &block->full_render; - if (use_short_text && block->short_text != NULL) { + if (block->use_short && block->short_text != NULL) { text = block->short_text; render = &block->short_render; } @@ -466,7 +517,7 @@ static void child_handle_button(xcb_button_press_event_t *event, i3_output *outp TAILQ_FOREACH (block, &statusline_head, blocks) { i3String *text; struct status_block_render_desc *render; - if (output->statusline_short_text && block->short_text != NULL) { + if (block->use_short && block->short_text != NULL) { text = block->short_text; render = &block->short_render; } else { @@ -2055,9 +2106,6 @@ static void draw_button(surface_t *surface, color_t fg_color, color_t bg_color, void draw_bars(bool unhide) { DLOG("Drawing bars...\n"); - uint32_t full_statusline_width = predict_statusline_length(false); - uint32_t short_statusline_width = predict_statusline_length(true); - i3_output *outputs_walk; SLIST_FOREACH (outputs_walk, outputs, slist) { int workspace_width = logical_px(config.padding.x); @@ -2132,27 +2180,28 @@ void draw_bars(bool unhide) { uint32_t hoff = logical_px(((workspace_width > 0) + (tray_width > 0)) * sb_hoff_px); uint32_t max_statusline_width = outputs_walk->rect.w - workspace_width - tray_width - hoff; uint32_t clip_left = 0; - uint32_t statusline_width = full_statusline_width; - bool use_short_text = false; + + /* Reset short mode between outputs */ + struct status_block *block; + TAILQ_FOREACH (block, &statusline_head, blocks) { + block->use_short = false; + } + + uint32_t statusline_width = adjust_statusline_length(max_statusline_width); if (statusline_width > max_statusline_width) { - statusline_width = short_statusline_width; - use_short_text = true; - if (statusline_width > max_statusline_width) { - clip_left = statusline_width - max_statusline_width; - } + clip_left = statusline_width - max_statusline_width; } int16_t visible_statusline_width = MIN(statusline_width, max_statusline_width); int x_dest = outputs_walk->rect.w - tray_width - logical_px((tray_width > 0) * sb_hoff_px) - visible_statusline_width; x_dest -= logical_px(config.padding.width); - draw_statusline(outputs_walk, clip_left, use_focus_colors, use_short_text); + draw_statusline(outputs_walk, clip_left, use_focus_colors); draw_util_copy_surface(&outputs_walk->statusline_buffer, &outputs_walk->buffer, 0, 0, x_dest, 0, visible_statusline_width, (int16_t)bar_height); outputs_walk->statusline_width = statusline_width; - outputs_walk->statusline_short_text = use_short_text; } } diff --git a/release-notes/changes/4-shrink-i3bar-blocks b/release-notes/changes/4-shrink-i3bar-blocks new file mode 100644 index 00000000..81a490c0 --- /dev/null +++ b/release-notes/changes/4-shrink-i3bar-blocks @@ -0,0 +1 @@ +i3bar: use short-form text on a per-block basis |