Make window icons follow title alignment
Fixes #4464. Inspired by changes from #4453 but I didn't end up using the original code. For ALIGN_LEFT and ALIGN_CENTER icon offset is calculated first and then title offset is based on that. For ALIGN_RIGHT title offset is calculated first but we make sure that the icon fits in the window. Additionally, icons will now hide if there is not enough space to render them + their padding. Realistically, this won't happen in normal usecases. Effectively, icons have higher precedence over text: draw_util_text will hide text when it exceeds the max width and the code takes this into consideration. Icons will only hide when they can't fit at all, not in order to assure that the text can be displayed fully.
This commit is contained in:
parent
3bdea50548
commit
cc44d9a999
81
src/x.c
81
src/x.c
@ -614,33 +614,11 @@ void x_draw_decoration(Con *con) {
|
||||
|
||||
/* 6: draw the icon and title */
|
||||
int text_offset_y = (con->deco_rect.height - config.font.height) / 2;
|
||||
int text_offset_x = 0;
|
||||
|
||||
struct Window *win = con->window;
|
||||
|
||||
const int title_padding = logical_px(2);
|
||||
const int deco_width = (int)con->deco_rect.width;
|
||||
|
||||
/* Draw the icon */
|
||||
if (con->window_icon_padding > -1 && win && win->icon) {
|
||||
/* icon_padding is applied horizontally only,
|
||||
* the icon will always use all available vertical space. */
|
||||
const int icon_padding = logical_px(1 + con->window_icon_padding);
|
||||
|
||||
const uint16_t icon_size = con->deco_rect.height - 2 * logical_px(1);
|
||||
|
||||
const int icon_offset_y = logical_px(1);
|
||||
|
||||
text_offset_x += icon_size + 2 * icon_padding;
|
||||
|
||||
draw_util_image(
|
||||
win->icon,
|
||||
&(parent->frame_buffer),
|
||||
con->deco_rect.x + icon_padding,
|
||||
con->deco_rect.y + icon_offset_y,
|
||||
icon_size,
|
||||
icon_size);
|
||||
}
|
||||
const int title_padding = logical_px(2);
|
||||
|
||||
int mark_width = 0;
|
||||
if (config.show_marks && !TAILQ_EMPTY(&(con->marks_head))) {
|
||||
@ -699,33 +677,62 @@ void x_draw_decoration(Con *con) {
|
||||
goto copy_pixmaps;
|
||||
}
|
||||
|
||||
/* icon_padding is applied horizontally only, the icon will always use all
|
||||
* available vertical space. */
|
||||
int icon_size = max(0, con->deco_rect.height - logical_px(2));
|
||||
int icon_padding = logical_px(max(1, con->window_icon_padding));
|
||||
int total_icon_space = icon_size + 2 * icon_padding;
|
||||
const bool has_icon = (con->window_icon_padding > -1) && win && win->icon && (total_icon_space < deco_width);
|
||||
if (!has_icon) {
|
||||
icon_size = icon_padding = total_icon_space = 0;
|
||||
}
|
||||
/* Determine x offsets according to title alignment */
|
||||
int icon_offset_x;
|
||||
int title_offset_x;
|
||||
switch (config.title_align) {
|
||||
case ALIGN_LEFT:
|
||||
/* (pad)[text ](pad)[mark + its pad) */
|
||||
title_offset_x = title_padding;
|
||||
/* (pad)[(pad)(icon)(pad)][text ](pad)[mark + its pad)
|
||||
* ^ ^--- title_offset_x
|
||||
* ^--- icon_offset_x */
|
||||
icon_offset_x = icon_padding;
|
||||
title_offset_x = title_padding + total_icon_space;
|
||||
break;
|
||||
case ALIGN_CENTER:
|
||||
/* (pad)[ text ](pad)[mark + its pad)
|
||||
* To center the text inside its allocated space, the surface
|
||||
* between the brackets, we use the formula
|
||||
* (surface_width - predict_text_width) / 2
|
||||
* where surface_width = deco_width - 2 * pad - mark_width
|
||||
* so, offset = pad + (surface_width - predict_text_width) / 2 =
|
||||
* = … = (deco_width - mark_width - predict_text_width) / 2 */
|
||||
title_offset_x = max(title_padding, (deco_width - mark_width - predict_text_width(title)) / 2);
|
||||
/* (pad)[ ][(pad)(icon)(pad)][text ](pad)[mark + its pad)
|
||||
* ^ ^--- title_offset_x
|
||||
* ^--- icon_offset_x
|
||||
* Text should come right after the icon (+padding). We calculate
|
||||
* the offset for the icon (white space in the title) by dividing
|
||||
* by two the total available area. That's the decoration width
|
||||
* minus the elements that come after icon_offset_x (icon, its
|
||||
* padding, text, marks). */
|
||||
icon_offset_x = max(icon_padding, (deco_width - icon_padding - icon_size - predict_text_width(title) - title_padding - mark_width) / 2);
|
||||
title_offset_x = max(title_padding, icon_offset_x + icon_padding + icon_size);
|
||||
break;
|
||||
case ALIGN_RIGHT:
|
||||
/* [mark + its pad](pad)[ text](pad) */
|
||||
title_offset_x = max(title_padding + mark_width, deco_width - title_padding - predict_text_width(title));
|
||||
/* [mark + its pad](pad)[ text][(pad)(icon)(pad)](pad)
|
||||
* ^ ^--- icon_offset_x
|
||||
* ^--- title_offset_x */
|
||||
title_offset_x = max(title_padding + mark_width, deco_width - title_padding - predict_text_width(title) - total_icon_space);
|
||||
/* Make sure the icon does not escape title boundaries */
|
||||
icon_offset_x = min(deco_width - icon_size - icon_padding - title_padding, title_offset_x + predict_text_width(title) + icon_padding);
|
||||
break;
|
||||
}
|
||||
|
||||
draw_util_text(title, &(parent->frame_buffer),
|
||||
p->color->text, p->color->background,
|
||||
con->deco_rect.x + text_offset_x + title_offset_x,
|
||||
con->deco_rect.x + title_offset_x,
|
||||
con->deco_rect.y + text_offset_y,
|
||||
deco_width - text_offset_x - mark_width - 2 * title_padding);
|
||||
deco_width - mark_width - 2 * title_padding - total_icon_space);
|
||||
if (has_icon) {
|
||||
draw_util_image(
|
||||
win->icon,
|
||||
&(parent->frame_buffer),
|
||||
con->deco_rect.x + icon_offset_x,
|
||||
con->deco_rect.y + logical_px(1),
|
||||
icon_size,
|
||||
icon_size);
|
||||
}
|
||||
|
||||
if (win == NULL || con->title_format != NULL) {
|
||||
I3STRING_FREE(title);
|
||||
|
Loading…
x
Reference in New Issue
Block a user