config+render: move alpha-mode to colors.alpha-mode, fix cursor handling

Move main.alpha-mode to colors.alpha-mode.

Fix (inverted) cursor handling, by always using the bg color without
alpha.

Do a minor optimization, where we don't even lock at colors.alpha-mode
if there's no transparency configured.
This commit is contained in:
Daniel Eklöf 2025-04-14 16:58:23 +02:00
parent bacfba135d
commit d2d4f53861
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 74 additions and 78 deletions

View file

@ -1095,15 +1095,6 @@ parse_section_main(struct context *ctx)
return true;
}
else if (strcmp(key, "alpha-mode") == 0) {
_Static_assert(sizeof(conf->alpha_mode) == sizeof(int),
"enum is not 32-bit");
return value_to_enum(
ctx,
(const char *[]){"default", "matching", "all", NULL},
(int *)&conf->alpha_mode);
}
else {
LOG_CONTEXTUAL_ERR("not a valid option: %s", key);
return false;
@ -1490,6 +1481,15 @@ parse_section_colors(struct context *ctx)
return true;
}
else if (strcmp(key, "alpha-mode") == 0) {
_Static_assert(sizeof(conf->colors.alpha_mode) == sizeof(int),
"enum is not 32-bit");
return value_to_enum(
ctx,
(const char *[]){"default", "matching", "all", NULL},
(int *)&conf->colors.alpha_mode);
}
else {
LOG_CONTEXTUAL_ERR("not valid option");
@ -3347,13 +3347,13 @@ config_load(struct config *conf, const char *conf_path,
},
.multiplier = 3.,
},
.alpha_mode = ALPHA_MODE_DEFAULT,
.colors = {
.fg = default_foreground,
.bg = default_background,
.flash = 0x7f7f00,
.flash_alpha = 0x7fff,
.alpha = 0xffff,
.alpha_mode = ALPHA_MODE_DEFAULT,
.selection_fg = 0x80000000, /* Use default bg */
.selection_bg = 0x80000000, /* Use default fg */
.use_custom = {

View file

@ -167,8 +167,6 @@ struct config {
enum { STARTUP_WINDOWED, STARTUP_MAXIMIZED, STARTUP_FULLSCREEN } startup_mode;
enum { ALPHA_MODE_DEFAULT, ALPHA_MODE_MATCHING, ALPHA_MODE_ALL } alpha_mode;
bool dpi_aware;
enum {GAMMA_CORRECT_DISABLED,
GAMMA_CORRECT_ENABLED,
@ -260,6 +258,12 @@ struct config {
uint32_t dim[8];
uint32_t sixel[16];
enum {
ALPHA_MODE_DEFAULT,
ALPHA_MODE_MATCHING,
ALPHA_MODE_ALL
} alpha_mode;
struct {
uint32_t fg;
uint32_t bg;

124
render.c
View file

@ -605,13 +605,8 @@ cursor_colors_for_cell(const struct terminal *term, const struct cell *cell,
if (term->colors.cursor_fg >> 31)
*text_color = color_hex_to_pixman(term->colors.cursor_fg, gamma_correct);
else {
xassert(bg->alpha == 0xffff);
*text_color = *bg;
if (unlikely(text_color->alpha != 0xffff)) {
/* The *only* color that can have transparency is the
* default background color */
*text_color = color_hex_to_pixman(term->colors.bg, gamma_correct);
}
}
if (text_color->red == cursor_color->red &&
@ -749,65 +744,58 @@ render_cell(struct terminal *term, pixman_image_t *pix,
_bg = swap;
}
else if (cell->attrs.bg_src == COLOR_DEFAULT) {
if (term->window->is_fullscreen) {
/*
* Note: disable transparency when fullscreened.
*
* This is because the wayland protocol mandates no
* screen content is shown behind the fullscreened
* window.
*
* The _intent_ of the specification is that a black
* (or other static color) should be used as
* background.
*
* There's a bit of gray area however, and some
* compositors have chosen to interpret the
* specification in a way that allows wallpapers to be
* seen through a fullscreen window.
*
* Given that a) the intent of the specification, and
* b) we don't know what the compositor will do, we
* simply disable transparency while in fullscreen.
*
* To see why, consider what happens if we keep our
* transparency. For example, if the background color
* is white, and alpha is 0.5, then the window will be
* drawn in a shade of gray while fullscreened.
*
* See
* https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/116
* for a discussion on whether transparent, fullscreen
* windows should be allowed in some way or not.
*
* NOTE: if changing this, also update render_margin()
*/
xassert(alpha == 0xffff);
} else {
alpha = term->colors.alpha;
}
}
if (!term->window->is_fullscreen) {
switch (term->conf->alpha_mode) {
case ALPHA_MODE_DEFAULT: {
if (cell->attrs.bg_src == COLOR_DEFAULT) {
alpha = term->colors.alpha;
}
break;
}
case ALPHA_MODE_MATCHING: {
if (cell->attrs.bg == term->colors.bg) {
alpha = term->colors.alpha;
}
break;
}
case ALPHA_MODE_ALL: {
if (!term->window->is_fullscreen && term->colors.alpha != 0xffff) {
switch (term->conf->colors.alpha_mode) {
case ALPHA_MODE_DEFAULT: {
if (cell->attrs.bg_src == COLOR_DEFAULT) {
alpha = term->colors.alpha;
break;
}
break;
}
case ALPHA_MODE_MATCHING: {
if (cell->attrs.bg == term->colors.bg)
alpha = term->colors.alpha;
break;
}
case ALPHA_MODE_ALL: {
alpha = term->colors.alpha;
break;
}
}
} else {
/*
* Note: disable transparency when fullscreened.
*
* This is because the wayland protocol mandates no screen
* content is shown behind the fullscreened window.
*
* The _intent_ of the specification is that a black (or
* other static color) should be used as background.
*
* There's a bit of gray area however, and some
* compositors have chosen to interpret the specification
* in a way that allows wallpapers to be seen through a
* fullscreen window.
*
* Given that a) the intent of the specification, and b)
* we don't know what the compositor will do, we simply
* disable transparency while in fullscreen.
*
* To see why, consider what happens if we keep our
* transparency. For example, if the background color is
* white, and alpha is 0.5, then the window will be drawn
* in a shade of gray while fullscreened.
*
* See
* https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/116
* for a discussion on whether transparent, fullscreen
* windows should be allowed in some way or not.
*
* NOTE: if changing this, also update render_margin()
*/
xassert(alpha == 0xffff);
}
}
@ -1012,8 +1000,10 @@ render_cell(struct terminal *term, pixman_image_t *pix,
mtx_unlock(&term->render.workers.lock);
}
if (unlikely(has_cursor && term->cursor_style == CURSOR_BLOCK && term->kbd_focus))
draw_cursor(term, cell, font, pix, &fg, &bg, x, y, cell_cols);
if (unlikely(has_cursor && term->cursor_style == CURSOR_BLOCK && term->kbd_focus)) {
const pixman_color_t bg_without_alpha = color_hex_to_pixman(_bg, gamma_correct);
draw_cursor(term, cell, font, pix, &fg, &bg_without_alpha, x, y, cell_cols);
}
if (cell->wc == 0 || cell->wc >= CELL_SPACER || cell->wc == U'\t' ||
(unlikely(cell->attrs.conceal) && !is_selected))
@ -1161,8 +1151,10 @@ render_cell(struct terminal *term, pixman_image_t *pix,
}
draw_cursor:
if (has_cursor && (term->cursor_style != CURSOR_BLOCK || !term->kbd_focus))
draw_cursor(term, cell, font, pix, &fg, &bg, x, y, cell_cols);
if (has_cursor && (term->cursor_style != CURSOR_BLOCK || !term->kbd_focus)) {
const pixman_color_t bg_without_alpha = color_hex_to_pixman(_bg, gamma_correct);
draw_cursor(term, cell, font, pix, &fg, &bg_without_alpha, x, y, cell_cols);
}
pixman_image_set_clip_region32(pix, NULL);
return cell_cols;