Implement handling of short_text field of i3 input protocol.

Matches i3bar behavior of setting all blocks to use the short_text if the full
text width does not fit.
This commit is contained in:
Dmitri Kourennyi 2019-03-22 17:18:21 -04:00 committed by Drew DeVault
parent 75e7bd24cc
commit 0553e75b53

View file

@ -144,16 +144,21 @@ static void i3bar_block_unref_callback(void *data) {
static uint32_t render_status_block(cairo_t *cairo, static uint32_t render_status_block(cairo_t *cairo,
struct swaybar_output *output, struct i3bar_block *block, double *x, struct swaybar_output *output, struct i3bar_block *block, double *x,
bool edge) { bool edge, bool use_short_text) {
if (!block->full_text || !*block->full_text) { if (!block->full_text || !*block->full_text) {
return 0; return 0;
} }
char* text = block->full_text;
if (use_short_text && block->short_text && *block->short_text) {
text = block->short_text;
}
struct swaybar_config *config = output->bar->config; struct swaybar_config *config = output->bar->config;
int text_width, text_height; int text_width, text_height;
get_text_size(cairo, config->font, &text_width, &text_height, NULL, get_text_size(cairo, config->font, &text_width, &text_height, NULL,
output->scale, block->markup, "%s", block->full_text); output->scale, block->markup, "%s", text);
int margin = 3 * output->scale; int margin = 3 * output->scale;
double ws_vertical_padding = config->status_padding * output->scale; double ws_vertical_padding = config->status_padding * output->scale;
@ -263,7 +268,7 @@ static uint32_t render_status_block(cairo_t *cairo,
color = block->urgent ? config->colors.urgent_workspace.text : color; color = block->urgent ? config->colors.urgent_workspace.text : color;
cairo_set_source_u32(cairo, color); cairo_set_source_u32(cairo, color);
pango_printf(cairo, config->font, output->scale, pango_printf(cairo, config->font, output->scale,
block->markup, "%s", block->full_text); block->markup, "%s", text);
x_pos += width; x_pos += width;
if (block->border && block->border_right > 0) { if (block->border && block->border_right > 0) {
@ -294,13 +299,174 @@ static uint32_t render_status_block(cairo_t *cairo,
return output->height; return output->height;
} }
static void predict_status_block_pos(cairo_t *cairo,
struct swaybar_output *output, struct i3bar_block *block, double *x,
bool edge) {
if (!block->full_text || !*block->full_text) {
return;
}
struct swaybar_config *config = output->bar->config;
int text_width, text_height;
get_text_size(cairo, config->font, &text_width, &text_height, NULL,
output->scale, block->markup, "%s", block->full_text);
int margin = 3 * output->scale;
double ws_vertical_padding = config->status_padding * output->scale;
int width = text_width;
if (block->min_width_str) {
int w;
get_text_size(cairo, config->font, &w, NULL, NULL,
output->scale, block->markup, "%s", block->min_width_str);
block->min_width = w;
}
if (width < block->min_width) {
width = block->min_width;
}
double block_width = width;
uint32_t ideal_height = text_height + ws_vertical_padding * 2;
uint32_t ideal_surface_height = ideal_height / output->scale;
if (!output->bar->config->height &&
output->height < ideal_surface_height) {
return;
}
*x -= width;
if ((block->border || block->urgent) && block->border_left > 0) {
*x -= (block->border_left * output->scale + margin);
block_width += block->border_left * output->scale + margin;
}
if ((block->border || block->urgent) && block->border_right > 0) {
*x -= (block->border_right * output->scale + margin);
block_width += block->border_right * output->scale + margin;
}
int sep_width, sep_height;
int sep_block_width = block->separator_block_width;
if (!edge) {
if (config->sep_symbol) {
get_text_size(cairo, config->font, &sep_width, &sep_height, NULL,
output->scale, false, "%s", config->sep_symbol);
uint32_t _ideal_height = sep_height + ws_vertical_padding * 2;
uint32_t _ideal_surface_height = _ideal_height / output->scale;
if (!output->bar->config->height &&
output->height < _ideal_surface_height) {
return;
}
if (sep_width > sep_block_width) {
sep_block_width = sep_width + margin * 2;
}
}
*x -= sep_block_width;
} else if (config->status_edge_padding) {
*x -= config->status_edge_padding * output->scale;
}
}
static double predict_status_line_pos(cairo_t *cairo,
struct swaybar_output *output, double x) {
bool edge = x == output->width * output->scale;
struct i3bar_block *block;
wl_list_for_each(block, &output->bar->status->blocks, link) {
predict_status_block_pos(cairo, output, block, &x, edge);
edge = false;
}
return x;
}
static uint32_t predict_workspace_button_length(cairo_t *cairo,
struct swaybar_output *output,
struct swaybar_workspace *ws) {
struct swaybar_config *config = output->bar->config;
int text_width, text_height;
get_text_size(cairo, config->font, &text_width, &text_height, NULL,
output->scale, config->pango_markup, "%s", ws->label);
int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale;
int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale;
int border_width = BORDER_WIDTH * output->scale;
uint32_t ideal_height = ws_vertical_padding * 2 + text_height
+ border_width * 2;
uint32_t ideal_surface_height = ideal_height / output->scale;
if (!output->bar->config->height &&
output->height < ideal_surface_height) {
return 0;
}
return ws_horizontal_padding * 2 + text_width + border_width * 2;
}
static uint32_t predict_workspace_buttons_length(cairo_t *cairo,
struct swaybar_output *output) {
uint32_t width = 0;
if (output->bar->config->workspace_buttons) {
struct swaybar_workspace *ws;
wl_list_for_each(ws, &output->workspaces, link) {
width += predict_workspace_button_length(cairo, output, ws);
}
}
return width;
}
static uint32_t predict_binding_mode_indicator_length(cairo_t *cairo,
struct swaybar_output *output) {
const char *mode = output->bar->mode;
if (!mode) {
return 0;
}
struct swaybar_config *config = output->bar->config;
if (!config->binding_mode_indicator) {
return 0;
}
int text_width, text_height;
get_text_size(cairo, config->font, &text_width, &text_height, NULL,
output->scale, output->bar->mode_pango_markup,
"%s", mode);
int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale;
int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale;
int border_width = BORDER_WIDTH * output->scale;
uint32_t ideal_height = text_height + ws_vertical_padding * 2
+ border_width * 2;
uint32_t ideal_surface_height = ideal_height / output->scale;
if (!output->bar->config->height &&
output->height < ideal_surface_height) {
return 0;
}
return text_width + ws_horizontal_padding * 2 + border_width * 2;
}
static uint32_t render_status_line_i3bar(cairo_t *cairo, static uint32_t render_status_line_i3bar(cairo_t *cairo,
struct swaybar_output *output, double *x) { struct swaybar_output *output, double *x) {
uint32_t max_height = 0; uint32_t max_height = 0;
bool edge = *x == output->width * output->scale; bool edge = *x == output->width * output->scale;
struct i3bar_block *block; struct i3bar_block *block;
bool use_short_text = false;
// TODO: Add margin here?
uint32_t reserved_width = predict_workspace_buttons_length(cairo, output) +
predict_binding_mode_indicator_length(cairo, output);
uint32_t predicted_full_pos =
predict_status_line_pos(cairo, output, *x);
if (predicted_full_pos < reserved_width) {
use_short_text = true;
}
wl_list_for_each(block, &output->bar->status->blocks, link) { wl_list_for_each(block, &output->bar->status->blocks, link) {
uint32_t h = render_status_block(cairo, output, block, x, edge); uint32_t h = render_status_block(cairo, output, block, x, edge,
use_short_text);
max_height = h > max_height ? h : max_height; max_height = h > max_height ? h : max_height;
edge = false; edge = false;
} }