From 9013a810f17ff48036d103ab9b60f606d2c31728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 11 Aug 2021 17:36:42 +0200 Subject: [PATCH] render: whole-window transparency when unfocused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a new option, colors.unfocused-alpha. When set to a value < 1.0, the entire window (*everything* - all bg/fg colors, images etc) are made transparent while the window does not have keyboard focus. The way this is implemented (trying to keep the patch small), we need to do full-screen repaints while in this mode. That is, all screen updates result in full-screen repaints when: * The window does not have keyboard focus * The window *just* gained keyboard focus (i.e. last frame was rendered with transparency) As such, one can expect a fairly large performance impact when there’s large amount of output while the window is unfocused. Focused windows are unaffected, as are unfocused windows when colors.unfocused-alpha == 1.0. --- CHANGELOG.md | 1 + config.c | 13 +++++++++++++ config.h | 1 + doc/foot.ini.5.scd | 20 ++++++++++++++++++++ foot.ini | 1 + render.c | 20 ++++++++++++++++++++ terminal.h | 1 + 7 files changed, 57 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f40d8ba1..d115906f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -144,6 +144,7 @@ * Mouse buttons 6/7 (mouse wheel left/right). * `url.uri-characters` option to `foot.ini` (https://codeberg.org/dnkl/foot/issues/654). +* `colors.unfocused-alpha` to `foot.ini`. ### Changed diff --git a/config.c b/config.c index 8be36fea..5a1cb79d 100644 --- a/config.c +++ b/config.c @@ -1359,6 +1359,18 @@ parse_section_colors(const char *key, const char *value, struct config *conf, return true; } + else if (strcmp(key, "unfocused-alpha") == 0) { + double alpha; + if (!str_to_double(value, &alpha) || alpha < 0. || alpha > 1.) { + LOG_AND_NOTIFY_ERR("%s:%d: [colors]: unfocused-alpha: expected a value in the range 0.0-1.0", + path, lineno); + return false; + } + + conf->colors.unfocused_alpha = alpha * 65535.; + return true; + } + else { LOG_AND_NOTIFY_ERR("%s:%d: [colors]: %s: invalid key", path, lineno, key); return false; @@ -2940,6 +2952,7 @@ config_load(struct config *conf, const char *conf_path, .fg = default_foreground, .bg = default_background, .alpha = 0xffff, + .unfocused_alpha = 0xffff, .selection_fg = 0x80000000, /* Use default bg */ .selection_bg = 0x80000000, /* Use default fg */ .use_custom = { diff --git a/config.h b/config.h index db4bc275..11caa5b5 100644 --- a/config.h +++ b/config.h @@ -154,6 +154,7 @@ struct config { uint32_t bg; uint32_t table[256]; uint16_t alpha; + uint16_t unfocused_alpha; uint32_t selection_fg; uint32_t selection_bg; uint32_t url; diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index 7fc73123..5cb5b33f 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -509,6 +509,26 @@ _alpha_ option. Background translucency. A value in the range 0.0-1.0, where 0.0 means completely transparent, and 1.0 is opaque. Default: _1.0_. +*unfocused-alpha* + Window translucency applied when window does not have keyboard + focus. Unlike *alpha*, this option affects everything (all + background colors, foreground colors, images etc). + + Note that *alpha* is also applied. + + Be aware that there is a performance penalty of using this, as + damage tracking is disabled while the window is + unfocused. I.e. all screen updates will result in fullscreen + repaints. This is not an issue when the window content is static, + or updates at a slow pace (e.g. top), but can be noticeable with + high amounts of output. Performance is unaffected in focused + windows. + + Valid values are in the range 0.0-1.0, where 0.0 means completely + transparent, and 1.0 is opaque. + + Default: _1.0_ + *selection-foreground*, *selection-background* Foreground (text) and background color to use in selected text. Note that *both* options must be set, or the default will be diff --git a/foot.ini b/foot.ini index 131d970d..4e34d266 100644 --- a/foot.ini +++ b/foot.ini @@ -66,6 +66,7 @@ [colors] # alpha=1.0 +# unfocused-alpha=1.0 # foreground=dcdccc # background=111111 # regular0=222222 # black diff --git a/render.c b/render.c index ddeb72f4..1bac2ef4 100644 --- a/render.c +++ b/render.c @@ -2366,6 +2366,9 @@ grid_render(struct terminal *term) term->render.last_buf->height != buf->height || term->flash.active || term->render.was_flashing || term->is_searching != term->render.was_searching || + (term->conf->colors.unfocused_alpha < 0xffff && ( + !term->kbd_focus || + !term->render.was_focused)) || term->render.margins) { force_full_repaint(term, buf); @@ -2392,6 +2395,7 @@ grid_render(struct terminal *term) term->render.last_buf = buf; term->render.was_flashing = term->flash.active; term->render.was_searching = term->is_searching; + term->render.was_focused = term->kbd_focus; shm_addref(buf); buf->age = 0; @@ -2677,6 +2681,22 @@ grid_render(struct terminal *term) xassert(buf->width % term->scale == 0); xassert(buf->height % term->scale == 0); + if (!term->kbd_focus && term->conf->colors.unfocused_alpha < 0xffff) { + pixman_color_t unfocused_alpha = + {0, 0, 0, term->conf->colors.unfocused_alpha}; + pixman_image_t *transparent = + pixman_image_create_solid_fill(&unfocused_alpha); + + pixman_image_composite32( + PIXMAN_OP_IN_REVERSE, transparent, NULL, buf->pix[0], + 0, 0, 0, 0, 0, 0, buf->width, buf->height); + + pixman_image_unref(transparent); + + wl_surface_damage_buffer( + term->window->surface, 0, 0, buf->width, buf->height); + } + wl_surface_attach(term->window->surface, buf->wl_buf, 0, 0); wl_surface_commit(term->window->surface); } diff --git a/terminal.h b/terminal.h index 73988ba8..2645968e 100644 --- a/terminal.h +++ b/terminal.h @@ -554,6 +554,7 @@ struct terminal { struct buffer *last_buf; /* Buffer we rendered to last time */ bool was_flashing; /* Flash was active last time we rendered */ bool was_searching; + bool was_focused; size_t search_glyph_offset;