mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
Add support for background blur
This patch adds a new config option: colors{,2}.blur=no|yes. When
enabled, transparent background are also blurred.
Note that this requires the brand new ext-background-effect-v1
protocol, and specifically, that the compositor implements the blur
effect.
This commit is contained in:
parent
aa26676c43
commit
e63150305e
13 changed files with 154 additions and 43 deletions
|
|
@ -78,6 +78,12 @@
|
|||
* `[colors-light]` section to `foot.ini`. Replaces `[colors2]`.
|
||||
* `XTGETTCAP`: added `query-os-name`, returning the OS foot is
|
||||
compiled for (e.g. _'Linux'_) ([#2209][2209]).
|
||||
* Preliminary (untested) support for background blur via the new
|
||||
`ext-background-effect-v1` protocol. Enable by setting
|
||||
`colors-{dark,light}.blur=yes`. Foot needs to have been **built**
|
||||
against `wayland-protocols >= 1.45`, and the compositor **must**
|
||||
implement the `ext-background-effect-v1` protocol, **and** the
|
||||
`blur` effect.
|
||||
|
||||
[2212]: https://codeberg.org/dnkl/foot/issues/2212
|
||||
[2209]: https://codeberg.org/dnkl/foot/issues/2209
|
||||
|
|
|
|||
4
config.c
4
config.c
|
|
@ -1576,6 +1576,9 @@ parse_color_theme(struct context *ctx, struct color_theme *theme)
|
|||
(int *)&theme->dim_blend_towards);
|
||||
}
|
||||
|
||||
else if (streq(key, "blur"))
|
||||
return value_to_bool(ctx, &theme->blur);
|
||||
|
||||
else {
|
||||
LOG_CONTEXTUAL_ERR("not valid option");
|
||||
return false;
|
||||
|
|
@ -3526,6 +3529,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.scrollback_indicator = false,
|
||||
.url = false,
|
||||
},
|
||||
.blur = false,
|
||||
},
|
||||
.initial_color_theme = COLOR_THEME_DARK,
|
||||
.cursor = {
|
||||
|
|
|
|||
2
config.h
2
config.h
|
|
@ -192,6 +192,8 @@ struct color_theme {
|
|||
bool search_box_match:1;
|
||||
uint8_t dim;
|
||||
} use_custom;
|
||||
|
||||
bool blur;
|
||||
};
|
||||
|
||||
enum which_color_theme {
|
||||
|
|
|
|||
|
|
@ -1097,6 +1097,14 @@ The default theme used is *colors-dark*, unless
|
|||
|
||||
Default: _default_
|
||||
|
||||
*blur*
|
||||
Boolean. When enabled, foot will blur the background, when it is
|
||||
transparent. This feature requires the compositor to implement the
|
||||
_ext-background-effect-v1_ protocol (and specifically, the _blur_
|
||||
effect).
|
||||
|
||||
Default: _no_
|
||||
|
||||
*dim-blend-towards*
|
||||
Which color to blend towards when "auto" dimming a color (see
|
||||
*dim0*..*dim7* above). One of *black* or *white*. Blending towards
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@ const char version_and_features[] =
|
|||
" -toplevel-tag"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
" +blur"
|
||||
#else
|
||||
" -blur"
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
" +assertions"
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -188,6 +188,10 @@ if (wayland_protocols.version().version_compare('>=1.43'))
|
|||
wl_proto_xml += [wayland_protocols_datadir / 'staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml']
|
||||
add_project_arguments('-DHAVE_XDG_TOPLEVEL_TAG=1', language: 'c')
|
||||
endif
|
||||
if (wayland_protocols.version().version_compare('>=1.45'))
|
||||
wl_proto_xml += [wayland_protocols_datadir / 'staging/ext-background-effect/ext-background-effect-v1.xml']
|
||||
add_project_arguments('-DHAVE_EXT_BACKGROUND_EFFECT=1', language: 'c')
|
||||
endif
|
||||
|
||||
foreach prot : wl_proto_xml
|
||||
wl_proto_headers += custom_target(
|
||||
|
|
|
|||
42
osc.c
42
osc.c
|
|
@ -1458,11 +1458,8 @@ osc_dispatch(struct terminal *term)
|
|||
|
||||
case 11:
|
||||
term->colors.bg = color;
|
||||
if (!have_alpha) {
|
||||
alpha = term->colors.active_theme == COLOR_THEME_DARK
|
||||
? term->conf->colors_dark.alpha
|
||||
: term->conf->colors_light.alpha;
|
||||
}
|
||||
if (!have_alpha)
|
||||
alpha = term_theme_get(term)->alpha;
|
||||
|
||||
const bool changed = term->colors.alpha != alpha;
|
||||
term->colors.alpha = alpha;
|
||||
|
|
@ -1515,10 +1512,7 @@ osc_dispatch(struct terminal *term)
|
|||
case 104: {
|
||||
/* Reset Color Number 'c' (whole table if no parameter) */
|
||||
|
||||
const struct color_theme *theme =
|
||||
term->colors.active_theme == COLOR_THEME_DARK
|
||||
? &term->conf->colors_dark
|
||||
: &term->conf->colors_light;
|
||||
const struct color_theme *theme = term_theme_get(term);
|
||||
|
||||
if (string[0] == '\0') {
|
||||
LOG_DBG("resetting all colors");
|
||||
|
|
@ -1558,11 +1552,7 @@ osc_dispatch(struct terminal *term)
|
|||
case 110: /* Reset default text foreground color */
|
||||
LOG_DBG("resetting foreground color");
|
||||
|
||||
const struct color_theme *theme =
|
||||
term->colors.active_theme == COLOR_THEME_DARK
|
||||
? &term->conf->colors_dark
|
||||
: &term->conf->colors_light;
|
||||
|
||||
const struct color_theme *theme = term_theme_get(term);
|
||||
term->colors.fg = theme->fg;
|
||||
term_damage_color(term, COLOR_DEFAULT, 0);
|
||||
break;
|
||||
|
|
@ -1570,11 +1560,7 @@ osc_dispatch(struct terminal *term)
|
|||
case 111: { /* Reset default text background color */
|
||||
LOG_DBG("resetting background color");
|
||||
|
||||
const struct color_theme *theme =
|
||||
term->colors.active_theme == COLOR_THEME_DARK
|
||||
? &term->conf->colors_dark
|
||||
: &term->conf->colors_light;
|
||||
|
||||
const struct color_theme *theme = term_theme_get(term);
|
||||
bool alpha_changed = term->colors.alpha != theme->alpha;
|
||||
|
||||
term->colors.bg = theme->bg;
|
||||
|
|
@ -1593,11 +1579,7 @@ osc_dispatch(struct terminal *term)
|
|||
case 112: {
|
||||
LOG_DBG("resetting cursor color");
|
||||
|
||||
const struct color_theme *theme =
|
||||
term->colors.active_theme == COLOR_THEME_DARK
|
||||
? &term->conf->colors_dark
|
||||
: &term->conf->colors_light;
|
||||
|
||||
const struct color_theme *theme = term_theme_get(term);
|
||||
term->colors.cursor_fg = theme->cursor.text;
|
||||
term->colors.cursor_bg = theme->cursor.cursor;
|
||||
|
||||
|
|
@ -1613,11 +1595,7 @@ osc_dispatch(struct terminal *term)
|
|||
case 117: {
|
||||
LOG_DBG("resetting selection background color");
|
||||
|
||||
const struct color_theme *theme =
|
||||
term->colors.active_theme == COLOR_THEME_DARK
|
||||
? &term->conf->colors_dark
|
||||
: &term->conf->colors_light;
|
||||
|
||||
const struct color_theme *theme = term_theme_get(term);
|
||||
term->colors.selection_bg = theme->selection_bg;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1625,11 +1603,7 @@ osc_dispatch(struct terminal *term)
|
|||
case 119: {
|
||||
LOG_DBG("resetting selection foreground color");
|
||||
|
||||
const struct color_theme *theme =
|
||||
term->colors.active_theme == COLOR_THEME_DARK
|
||||
? &term->conf->colors_dark
|
||||
: &term->conf->colors_light;
|
||||
|
||||
const struct color_theme *theme = term_theme_get(term);
|
||||
term->colors.selection_fg = theme->selection_fg;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
4
render.c
4
render.c
|
|
@ -312,9 +312,7 @@ color_dim(const struct terminal *term, uint32_t color)
|
|||
}
|
||||
}
|
||||
|
||||
const struct color_theme *theme = term->colors.active_theme == COLOR_THEME_DARK
|
||||
? &conf->colors_dark
|
||||
: &conf->colors_light;
|
||||
const struct color_theme *theme = term_theme_get(term);
|
||||
|
||||
return color_blend_towards(
|
||||
color,
|
||||
|
|
|
|||
|
|
@ -4809,3 +4809,11 @@ term_theme_toggle(struct terminal *term)
|
|||
term_damage_margins(term);
|
||||
render_refresh(term);
|
||||
}
|
||||
|
||||
const struct color_theme *
|
||||
term_theme_get(const struct terminal *term)
|
||||
{
|
||||
return term->colors.active_theme == COLOR_THEME_DARK
|
||||
? &term->conf->colors_dark
|
||||
: &term->conf->colors_light;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -997,6 +997,7 @@ void term_send_size_notification(struct terminal *term);
|
|||
void term_theme_switch_to_dark(struct terminal *term);
|
||||
void term_theme_switch_to_light(struct terminal *term);
|
||||
void term_theme_toggle(struct terminal *term);
|
||||
const struct color_theme *term_theme_get(const struct terminal *term);
|
||||
|
||||
static inline void term_reset_grapheme_state(struct terminal *term)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -774,6 +774,8 @@ test_section_colors_dark(void)
|
|||
&conf.colors_dark.table[i]);
|
||||
}
|
||||
|
||||
test_boolean(&ctx, &parse_section_colors, "blur", &conf.colors_dark.blur);
|
||||
|
||||
test_invalid_key(&ctx, &parse_section_colors_dark, "256");
|
||||
|
||||
/* TODO: alpha (float in range 0-1, converted to uint16_t) */
|
||||
|
|
@ -853,6 +855,8 @@ test_section_colors_light(void)
|
|||
&conf.colors_light.table[i]);
|
||||
}
|
||||
|
||||
test_boolean(&ctx, &parse_section_colors, "blur", &conf.colors_light.blur);
|
||||
|
||||
test_invalid_key(&ctx, &parse_section_colors_light, "256");
|
||||
|
||||
/* TODO: alpha (float in range 0-1, converted to uint16_t) */
|
||||
|
|
|
|||
97
wayland.c
97
wayland.c
|
|
@ -1196,6 +1196,27 @@ static const struct zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration
|
|||
.configure = &xdg_toplevel_decoration_configure,
|
||||
};
|
||||
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
static void
|
||||
ext_background_capabilities(
|
||||
void *data,
|
||||
struct ext_background_effect_manager_v1 *ext_background_effect_manager_v1,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct wayland *wayl = data;
|
||||
|
||||
wayl->have_background_blur =
|
||||
!!(flags & EXT_BACKGROUND_EFFECT_MANAGER_V1_CAPABILITY_BLUR);
|
||||
|
||||
LOG_DBG("compositor supports background blur: %s",
|
||||
wayl->have_background_blur ? "yes" : "no");
|
||||
}
|
||||
|
||||
static const struct ext_background_effect_manager_v1_listener background_manager_listener = {
|
||||
.capabilities = &ext_background_capabilities,
|
||||
};
|
||||
#endif /* HAVE_EXT_BACKGROUND_EFFECT */
|
||||
|
||||
static bool
|
||||
fdm_repeat(struct fdm *fdm, int fd, int events, void *data)
|
||||
{
|
||||
|
|
@ -1558,6 +1579,20 @@ handle_global(void *data, struct wl_registry *registry,
|
|||
wayl->registry, name, &xdg_toplevel_tag_manager_v1_interface, required);
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
else if (streq(interface, ext_background_effect_manager_v1_interface.name)) {
|
||||
const uint32_t required = 1;
|
||||
if (!verify_iface_version(interface, version, required))
|
||||
return;
|
||||
|
||||
wayl->background_effect_manager = wl_registry_bind(
|
||||
wayl->registry, name,
|
||||
&ext_background_effect_manager_v1_interface, required);
|
||||
|
||||
ext_background_effect_manager_v1_add_listener(
|
||||
wayl->background_effect_manager, &background_manager_listener, wayl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
else if (streq(interface, zwp_text_input_manager_v3_interface.name)) {
|
||||
|
|
@ -1572,6 +1607,7 @@ handle_global(void *data, struct wl_registry *registry,
|
|||
seat_add_text_input(&it->item);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1885,6 +1921,10 @@ wayl_destroy(struct wayland *wayl)
|
|||
if (wayl->toplevel_tag_manager != NULL)
|
||||
xdg_toplevel_tag_manager_v1_destroy(wayl->toplevel_tag_manager);
|
||||
#endif
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
if (wayl->background_effect_manager != NULL)
|
||||
ext_background_effect_manager_v1_destroy(wayl->background_effect_manager);
|
||||
#endif
|
||||
|
||||
if (wayl->color_management.img_description != NULL)
|
||||
wp_image_description_v1_destroy(wayl->color_management.img_description);
|
||||
|
|
@ -1989,8 +2029,6 @@ wayl_win_init(struct terminal *term, const char *token)
|
|||
goto out;
|
||||
}
|
||||
|
||||
wayl_win_alpha_changed(win);
|
||||
|
||||
wl_surface_add_listener(win->surface.surf, &surface_listener, win);
|
||||
|
||||
if (wayl->fractional_scale_manager != NULL && wayl->viewporter != NULL) {
|
||||
|
|
@ -2003,6 +2041,16 @@ wayl_win_init(struct terminal *term, const char *token)
|
|||
win->fractional_scale, &fractional_scale_listener, win);
|
||||
}
|
||||
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
if (wayl->background_effect_manager != NULL) {
|
||||
win->surface.background_effect =
|
||||
ext_background_effect_manager_v1_get_background_effect(
|
||||
wayl->background_effect_manager, win->surface.surf);
|
||||
}
|
||||
#endif
|
||||
|
||||
wayl_win_alpha_changed(win);
|
||||
|
||||
win->xdg_surface = xdg_wm_base_get_xdg_surface(wayl->shell, win->surface.surf);
|
||||
xdg_surface_add_listener(win->xdg_surface, &xdg_surface_listener, win);
|
||||
|
||||
|
|
@ -2207,7 +2255,12 @@ wayl_win_destroy(struct wl_window *win)
|
|||
free(it->item);
|
||||
|
||||
tll_remove(win->xdg_tokens, it);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
if (win->surface.background_effect != NULL)
|
||||
ext_background_effect_surface_v1_destroy(win->surface.background_effect);
|
||||
#endif
|
||||
|
||||
if (win->surface.color_management != NULL)
|
||||
wp_color_management_surface_v1_destroy(win->surface.color_management);
|
||||
|
|
@ -2447,16 +2500,16 @@ void
|
|||
wayl_win_alpha_changed(struct wl_window *win)
|
||||
{
|
||||
struct terminal *term = win->term;
|
||||
struct wayland *wayl = term->wl;
|
||||
|
||||
/*
|
||||
* When fullscreened, transparency is disabled (see render.c).
|
||||
* Update the opaque region to match.
|
||||
*/
|
||||
bool is_opaque = term->colors.alpha == 0xffff || win->is_fullscreen;
|
||||
const bool is_opaque = term->colors.alpha == 0xffff || win->is_fullscreen;
|
||||
|
||||
if (is_opaque) {
|
||||
struct wl_region *region = wl_compositor_create_region(
|
||||
term->wl->compositor);
|
||||
struct wl_region *region = wl_compositor_create_region(wayl->compositor);
|
||||
|
||||
if (region != NULL) {
|
||||
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
|
||||
|
|
@ -2465,6 +2518,38 @@ wayl_win_alpha_changed(struct wl_window *win)
|
|||
}
|
||||
} else
|
||||
wl_surface_set_opaque_region(win->surface.surf, NULL);
|
||||
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
if (term_theme_get(term)->blur) {
|
||||
if (wayl->have_background_blur) {
|
||||
xassert(win->surface.background_effect != NULL);
|
||||
|
||||
if (is_opaque) {
|
||||
/* No transparency, disable blur */
|
||||
LOG_DBG("disabling background blur");
|
||||
ext_background_effect_surface_v1_set_blur_region(
|
||||
win->surface.background_effect, NULL);
|
||||
} else {
|
||||
/* We have transparency, enable blur if user has enabled it */
|
||||
struct wl_region *region = wl_compositor_create_region(wayl->compositor);
|
||||
if (region != NULL) {
|
||||
LOG_DBG("enabling background blur");
|
||||
|
||||
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
|
||||
ext_background_effect_surface_v1_set_blur_region(
|
||||
win->surface.background_effect, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
static bool have_warned = false;
|
||||
if (!have_warned) {
|
||||
LOG_WARN("background blur requested, but compositor does not support it");
|
||||
have_warned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_EXT_BACKGROUND_EFFECT */
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
11
wayland.h
11
wayland.h
|
|
@ -26,6 +26,9 @@
|
|||
#if defined(HAVE_XDG_TOPLEVEL_TAG)
|
||||
#include <xdg-toplevel-tag-v1.h>
|
||||
#endif
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
#include <ext-background-effect-v1.h>
|
||||
#endif
|
||||
|
||||
#include <fcft/fcft.h>
|
||||
#include <tllist.h>
|
||||
|
|
@ -62,6 +65,10 @@ struct wayl_surface {
|
|||
struct wl_surface *surf;
|
||||
struct wp_viewport *viewport;
|
||||
struct wp_color_management_surface_v1 *color_management;
|
||||
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
struct ext_background_effect_surface_v1 *background_effect;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct wayl_sub_surface {
|
||||
|
|
@ -488,6 +495,10 @@ struct wayland {
|
|||
#if defined(HAVE_XDG_TOPLEVEL_TAG)
|
||||
struct xdg_toplevel_tag_manager_v1 *toplevel_tag_manager;
|
||||
#endif
|
||||
#if defined(HAVE_EXT_BACKGROUND_EFFECT)
|
||||
struct ext_background_effect_manager_v1 *background_effect_manager;
|
||||
bool have_background_blur;
|
||||
#endif
|
||||
|
||||
#if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED
|
||||
struct zwp_text_input_manager_v3 *text_input_manager;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue