Merge branch 'master' into master

This commit is contained in:
jake-stewart 2026-03-16 12:09:15 +01:00
commit 5b0b1a2e64
22 changed files with 324 additions and 162 deletions

View file

@ -1,6 +1,8 @@
# Changelog
* [Unreleased](#unreleased)
* [1.26.1](#1-26-1)
* [1.26.0](#1-26-0)
* [1.25.0](#1-25-0)
* [1.24.0](#1-24-0)
* [1.23.1](#1-23-1)
@ -68,6 +70,36 @@
## Unreleased
### Added
### Changed
### Deprecated
### Removed
### Fixed
### Security
### Contributors
## 1.26.1
### Fixed
* Wrong documented default value for `initial-color-theme` in
`foot.ini(5)` ([#2292][2292]).
* Occasional crashes when closing a window and
`tweak.pre-apply-damage=yes` (the default) ([#2288][2288]).
[2292]: https://codeberg.org/dnkl/foot/issues/2292
[2288]: https://codeberg.org/dnkl/foot/issues/2288
### Contributors
* Roshless
* vlkrs
## 1.26.0
### Added
* `toplevel-tag` option (and `--toplevel-tag` command line options to
@ -78,9 +110,20 @@
* `[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]).
* `pad` option now supports 4-directional padding format:
`LEFTxTOPxRIGHTxBOTTOM` (e.g., `20x10x20x10`).
* `--config=PATH` option is now automatically passed to new
terminals spawned via `spawn-terminal` action ([#2259][2259]).
* 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
[2259]: https://codeberg.org/dnkl/foot/pulls/2259
### Changed
@ -135,9 +178,20 @@
[2263]: https://codeberg.org/dnkl/foot/issues/2263
### Security
### Contributors
* Andrei
* Barinderpreet Singh
* c4llv07e
* Johannes Altmanninger
* nariby
* pi66
* Ronan Pigott
* Stéphane Klein
* valoq
* Whyme Lyu
* Yaakov Selkowitz
## 1.25.0

View file

@ -65,7 +65,7 @@ The fast, lightweight and minimalistic Wayland terminal emulator.
* [Synchronized Updates](https://gitlab.freedesktop.org/terminal-wg/specifications/-/merge_requests/2) support
* [Sixel image support](https://en.wikipedia.org/wiki/Sixel)
![wow](doc/sixel-wow.png "Sixel screenshot")
![tux-with-foot](doc/sixel-tux-foot.png "Sixel screenshot")
# Installing

View file

@ -34,7 +34,7 @@ _Static_assert(
#if !defined(__STDC_UTF_32__) || !__STDC_UTF_32__
#error "char32_t does not use UTF-32"
#endif
#if (!defined(__STDC_ISO_10646__) || !__STDC_ISO_10646__) && !defined(__FreeBSD__)
#if (!defined(__STDC_ISO_10646__) || !__STDC_ISO_10646__) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
#error "wchar_t does not use UTF-32"
#endif

View file

@ -946,13 +946,12 @@ parse_section_main(struct context *ctx)
}
else if (streq(key, "pad")) {
unsigned x, y;
unsigned x, y, left, top, right, bottom;
char mode[64] = {0};
int ret = sscanf(value, "%ux%u %63s", &x, &y, mode);
int ret = sscanf(value, "%ux%ux%ux%u %63s", &left, &top, &right, &bottom, mode);
enum center_when center = CENTER_NEVER;
if (ret == 3) {
if (ret == 5) {
if (strcasecmp(mode, "center") == 0)
center = CENTER_ALWAYS;
else if (strcasecmp(mode, "center-when-fullscreen") == 0)
@ -961,20 +960,38 @@ parse_section_main(struct context *ctx)
center = CENTER_MAXIMIZED_AND_FULLSCREEN;
else
center = CENTER_INVALID;
} else if (ret < 4) {
ret = sscanf(value, "%ux%u %63s", &x, &y, mode);
if (ret >= 2) {
left = right = x;
top = bottom = y;
if (ret == 3) {
if (strcasecmp(mode, "center") == 0)
center = CENTER_ALWAYS;
else if (strcasecmp(mode, "center-when-fullscreen") == 0)
center = CENTER_FULLSCREEN;
else if (strcasecmp(mode, "center-when-maximized-and-fullscreen") == 0)
center = CENTER_MAXIMIZED_AND_FULLSCREEN;
else
center = CENTER_INVALID;
}
}
}
if ((ret != 2 && ret != 3) || center == CENTER_INVALID) {
if ((ret < 2 || ret > 5) || center == CENTER_INVALID) {
LOG_CONTEXTUAL_ERR(
"invalid padding (must be in the form PAD_XxPAD_Y "
"invalid padding (must be in the form RIGHTxTOPxLEFTxBOTTOM or XxY "
"[center|"
"center-when-fullscreen|"
"center-when-maximized-and-fullscreen])");
return false;
}
conf->pad_x = x;
conf->pad_y = y;
conf->center_when = ret == 2 ? CENTER_NEVER : center;
conf->pad_left = left;
conf->pad_top = top;
conf->pad_right = right;
conf->pad_bottom = bottom;
conf->center_when = (ret == 4 || ret == 2) ? CENTER_NEVER : center;
return true;
}
@ -1589,6 +1606,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;
@ -3533,6 +3553,7 @@ config_load(struct config *conf, const char *conf_path,
enum fcft_capabilities fcft_caps = fcft_capabilities();
*conf = (struct config) {
.conf_path = (conf_path ? xstrdup(conf_path) : NULL),
.term = xstrdup(FOOT_DEFAULT_TERM),
.shell = get_shell(),
.title = xstrdup("foot"),
@ -3544,8 +3565,10 @@ config_load(struct config *conf, const char *conf_path,
.width = 700,
.height = 500,
},
.pad_x = 0,
.pad_y = 0,
.pad_left = 0,
.pad_top = 0,
.pad_right = 0,
.pad_bottom = 0,
.center_when = CENTER_MAXIMIZED_AND_FULLSCREEN,
.resize_by_cells = true,
.resize_keep_grid = true,
@ -3617,6 +3640,7 @@ config_load(struct config *conf, const char *conf_path,
.scrollback_indicator = false,
.url = false,
},
.blur = false,
},
.initial_color_theme = COLOR_THEME_DARK,
.palette_generate = false,
@ -3999,6 +4023,7 @@ config_clone(const struct config *old)
struct config *conf = xmalloc(sizeof(*conf));
*conf = *old;
conf->conf_path = (old->conf_path ? xstrdup(old->conf_path) : NULL);
conf->term = xstrdup(old->term);
conf->shell = xstrdup(old->shell);
conf->title = xstrdup(old->title);
@ -4099,6 +4124,7 @@ UNITTEST
void
config_free(struct config *conf)
{
free(conf->conf_path);
free(conf->term);
free(conf->shell);
free(conf->title);

View file

@ -193,6 +193,8 @@ struct color_theme {
bool search_box_match:1;
uint8_t dim;
} use_custom;
bool blur;
};
enum which_color_theme {
@ -218,6 +220,7 @@ enum center_when {
};
struct config {
char *conf_path;
char *term;
char *shell;
char *title;
@ -233,8 +236,10 @@ struct config {
uint32_t height;
} size;
unsigned pad_x;
unsigned pad_y;
unsigned pad_left;
unsigned pad_top;
unsigned pad_right;
unsigned pad_bottom;
enum center_when center_when;
bool resize_by_cells;

View file

@ -27,6 +27,9 @@ the foot command line
*-c*,*--config*=_PATH_
Path to configuration file, see *foot.ini*(5) for details.
The configuration file is automatically passed to new terminals
spawned via *spawn-terminal* (see *foot.ini*(5)).
*-C*,*--check-config*
Verify configuration and then exit with 0 if ok, otherwise exit
with 230 (see *EXIT STATUS*).

View file

@ -29,7 +29,7 @@ Options are set using KEY=VALUE pairs:
*foreground=ffffff*
Empty values (*KEY=*) are not supported. String options do allow the
empty string to be set, but it must be quoted: *KEY=""*)
empty string to be set, but it must be quoted: *KEY=""*
# SECTION: main
@ -96,7 +96,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
*font-size-adjustment*
Amount, in _points_, _pixels_ or _percent_, to increment/decrement
the font size when zooming in our out.
the font size when zooming in or out.
Examples:
```
@ -129,7 +129,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
e.g. *line-height=12px*.
*Warning*: when changing the font size at runtime (i.e. zooming in
our out), foot will change the line height by the same
or out), foot will change the line height by the same
percentage. However, due to rounding, it is possible the line
height will be "too small" for some font sizes, causing
e.g. underscores to "disappear".
@ -161,7 +161,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
*underline-offset*
Use a custom offset for underlines. The offset is, by default, in
_points_ and relative the font's baseline. A positive value
_points_ and relative to the font's baseline. A positive value
positions the underline under the baseline, while a negative value
positions it above the baseline.
@ -240,7 +240,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
*box-drawings-uses-font-glyphs*
Boolean. When disabled, foot generates box/line drawing characters
itself. The are several advantages to doing this instead of using
itself. There are several advantages to doing this instead of using
font glyphs:
- No antialiasing effects where e.g. line endpoints appear
@ -281,7 +281,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
scaling factor *does* double the font size.
Note that this option typically does not work with bitmap fonts,
which only contains a pre-defined set of sizes, and cannot be
which only contain a pre-defined set of sizes, and cannot be
dynamically scaled. Whichever size (of the available ones) that
best matches the DPI or scaling factor, will be used.
@ -301,9 +301,20 @@ empty string to be set, but it must be quoted: *KEY=""*)
```
_XxY_ [center | center-when-fullscreen | center-when-maximized-and-fullscreen]
```
or
```
RIGHTxTOPxLEFTxBOTTOM [center | center-when-fullscreen | center-when-maximized-and-fullscreen]
```
This will add _at least_ X pixels on both the left and right
sides, and Y pixels on the top and bottom sides.
- `_XxY_` adds _at least_:
- X pixels on the left and right sides.
- Y pixels on the top and bottom sides.
- `LEFTxTOPxRIGHTxBOTTOM` adds **at least**:
- LEFT pixels to the left
- TOP pixels to the top
- RIGHT pixels to the right
- BOTTOM pixels to the bottom
When no centering is specified, the grid content is anchored to
the top left corner. I.e. if the window manager forces an odd
@ -337,7 +348,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
Emphasis is on _while_ here; as soon as the interactive resize
ends (i.e. when you let go of the window border), the final
dimensions is sent to the client, without any delays.
dimensions are sent to the client, without any delays.
Setting it to 0 disables the delay completely.
@ -352,7 +363,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
as necessary to accommodate window sizes that are not multiples of
the cell size.
This option only applies to floating windows. Sizes of maxmized, tiled
This option only applies to floating windows. Sizes of maximized, tiled
or fullscreen windows will not be constrained to multiples of the cell
size.
@ -381,7 +392,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
at runtime, or send SIGUSR1/SIGUSR2 to the foot process (see
*foot*(1) for details).
Default: _1_
Default: _dark_
*palette-generate*
Boolean. When enabled, the extended 256-color palette (colors
@ -417,7 +428,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
*initial-window-size-chars*
Initial window width and height in _characters_, in the form
_WIDTHxHEIGHT_. Mutually exclusive to
*initial-window-size-pixels*.'
*initial-window-size-pixels*.
Note that if you have a multi-monitor setup, with different
scaling factors, there is a possibility the window size will not
@ -606,7 +617,7 @@ Note: do not set *TERM* here; use the *term* option in the main
option, or preferably, by setting the *image-path* hint (with
e.g. notify-send's *--hint* option).
_${category}_ is replaced by the notification's catogory. Can
_${category}_ is replaced by the notification's category. Can
be used together with e.g. notify-send's *--category* option.
_${urgency}_ is replaced with the notifications urgency;
@ -718,7 +729,7 @@ xdgtoken=95ebdfe56e4f47ddb5bba9d7dc3a2c35
Foot recognizes this as:
- notification has the daemon assigned ID 17
- the user triggered the default action
- the notification send an XDG activation token
- the notification sent an XDG activation token
Example #2:
17++
@ -734,7 +745,7 @@ xdgtoken=95ebdfe56e4f47ddb5bba9d7dc3a2c35
Foot recognizes this as:
- notification has the daemon assigned ID 17
- the user triggered the first custom action, "1
- the user triggered the first custom action, "1"
Default: _notify-send++
--wait++
@ -778,7 +789,7 @@ xdgtoken=95ebdfe56e4f47ddb5bba9d7dc3a2c35
least one), *command-action-argument* will be expanded with the
action's name and label.
Then, _${action-argument}_ is expanded *command* to the full list
Then, _${action-argument}_ is expanded in *command* to the full list
of actions.
If *command-action-argument* is set to the empty string, no
@ -951,7 +962,7 @@ applications can change these at runtime.
by applications. Related option: *blink-rate*. Default: _no_.
*blink-rate*
The rate at which the cursor blink, when cursor blinking has been
The rate at which the cursor blinks, when cursor blinking has been
enabled. Expressed in milliseconds between each blink. Default:
_500_.
@ -1115,6 +1126,14 @@ The default theme used is *colors-dark*, unless
Default: _default_
*blur*
Boolean. When enabled, foot will blur the background (main window
only, not CSDs etc), 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
@ -1205,7 +1224,7 @@ Examples:
*hide-when-maximized*
Boolean. When enabled, the CSD titlebar is hidden when the window
is maximized. The completely disable the titlebar, set *size* to 0
is maximized. To completely disable the titlebar, set *size* to 0
instead. Default: _no_.
*double-click-to-maximize*
@ -1227,8 +1246,8 @@ Examples:
minimize/maximize/close buttons. Default: _26_.
*button-color*
Foreground color on the minimize/maximize/close buttons. Default:
use the default _background_ color.
Foreground color on the minimize/maximize/close buttons and the
titlebar text. Default: use the default _background_ color.
*button-minimize-color*
Minimize button's background color. Default: use the default
@ -1435,7 +1454,7 @@ e.g. *search-start=none*.
shell integration, see *foot*(1)). Default: _Control+Shift+z_.
*prompt-next*
Jump the next prompt (requires shell integration, see
Jump to the next prompt (requires shell integration, see
*foot*(1)). Default: _Control+Shift+x_.
*unicode-input*
@ -1464,7 +1483,7 @@ e.g. *search-start=none*.
Default: _Control+Shift+u_.
*color-theme-switch-dark*, *color-theme-switch-dark*, *color-theme-toggle*
*color-theme-switch-dark*, *color-theme-switch-light*, *color-theme-toggle*
Switch between the dark color theme (defined in the *colors-dark*
section), and the light color theme (defined in the *colors-light*
section).
@ -1835,7 +1854,7 @@ any of these options.
*scaling-filter*
Overrides the default scaling filter used when down-scaling bitmap
fonts (e.g. emoji fonts). Possible values are *none*, *nearest*,
*bilinear*, *impulse*, *box*, *linear*, *cubic* *gaussian*,
*bilinear*, *impulse*, *box*, *linear*, *cubic*, *gaussian*,
*lanczos2*, *lanczos3* or *lanczos3-stretched*.
Default: _lanczos3_.
@ -1904,8 +1923,8 @@ any of these options.
must be patched to use it.
Until this has happened, foot offers an interim workaround; an
attempt to mitigate the screen flicker *without* affecting neither
performance nor latency.
attempt to mitigate the screen flicker *without* affecting either
performance or latency.
It is based on the fact that the screen is updated at a fixed
interval (typically 60Hz). For us, this means it does not matter
@ -2147,7 +2166,7 @@ any of these options.
Thus, having this option enabled improves both performance
(copying the last two frames' changes is threaded), and improves
input latency (rending the next frame no longer has to first bring
input latency (rendering the next frame no longer has to first bring
over the changes between the last two frames).
Default: _yes_

BIN
doc/sixel-tux-foot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

BIN
doc/tux-foot-ok.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

View file

@ -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

View file

@ -1,5 +1,5 @@
project('foot', 'c',
version: '1.25.0',
version: '1.26.1',
license: 'MIT',
meson_version: '>=0.59.0',
default_options: [
@ -12,6 +12,11 @@ is_debug_build = get_option('buildtype').startswith('debug')
cc = meson.get_compiler('c')
# Newer clang versions warns when using __COUNTER__ without -std=c2y
if cc.has_argument('-Wc2y-extensions')
add_project_arguments('-Wno-c2y-extensions', language: 'c')
endif
if cc.has_function('memfd_create',
args: ['-D_GNU_SOURCE'],
prefix: '#include <sys/mman.h>')
@ -188,6 +193,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(

View file

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>org.codeberg.dnkl.foot</id>
<metadata_license>MIT</metadata_license>
<project_license>MIT</project_license>
<developer_name>dnkl</developer_name>
<name>foot</name>
<summary>The fast, lightweight and minimalistic Wayland terminal emulator.</summary>
<description>
<ul>
<li>Fast</li>
<li>Lightweight, in dependencies, on-disk and in-memory</li>
<li>Wayland native</li>
<li>DE agnostic</li>
<li>Server/daemon mode</li>
<li>User configurable font fallback</li>
<li>On-the-fly font resize</li>
<li>On-the-fly DPI font size adjustment</li>
<li>Scrollback search</li>
<li>Keyboard driven URL detection</li>
<li>Color emoji support</li>
<li>IME (via text-input-v3)</li>
<li>Multi-seat</li>
<li>True Color (24bpp)</li>
<li>Styled and colored underlines</li>
<li>Synchronized Updates support</li>
<li>Sixel image support</li>
</ul>
</description>
<screenshots>
<screenshot type="default">
<caption>Foot with sixel graphics</caption>
<image>https://codeberg.org/dnkl/foot/media/branch/master/doc/sixel-wow.png</image>
</screenshot>
</screenshots>
<releases>
<release version="1.18.1" date="2024-08-14"/>
<release version="1.18.0" date="2024-08-02"/>
<release version="1.17.2" date="2024-04-17"/>
<release version="1.17.1" date="2024-04-11"/>
<release version="1.17.0" date="2024-04-02"/>
<release version="1.16.2" date="2023-10-17"/>
<release version="1.16.1" date="2023-10-12"/>
<release version="1.16.0" date="2023-10-11"/>
<release version="1.15.3" date="2023-08-07"/>
<release version="1.15.2" date="2023-07-30"/>
<release version="1.15.1" date="2023-07-21"/>
<release version="1.15.0" date="2023-07-14"/>
<release version="1.14.0" date="2023-04-03"/>
<release version="1.13.1" date="2022-08-31"/>
<release version="1.13.0" date="2022-08-07"/>
</releases>
<launchable type="desktop-id">org.codeberg.dnkl.foot.desktop</launchable>
<url type="homepage">https://codeberg.org/dnkl/foot</url>
<url type="bugtracker">https://codeberg.org/dnkl/foot/issues</url>
<content_rating type="oars-1.1"/>
</component>

42
osc.c
View file

@ -1460,11 +1460,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;
@ -1517,10 +1514,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");
@ -1560,11 +1554,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;
@ -1572,11 +1562,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;
@ -1595,11 +1581,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;
@ -1615,11 +1597,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;
}
@ -1627,11 +1605,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;
}

View file

@ -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,
@ -4504,8 +4502,8 @@ set_size_from_grid(struct terminal *term, int *width, int *height, int cols, int
new_height = rows * term->cell_height;
/* Include any configured padding */
new_width += 2 * term->conf->pad_x * term->scale;
new_height += 2 * term->conf->pad_y * term->scale;
new_width += (term->conf->pad_left + term->conf->pad_right) * term->scale;
new_height += (term->conf->pad_top + term->conf->pad_bottom) * term->scale;
/* Round to multiples of scale */
new_width = round(term->scale * round(new_width / term->scale));
@ -4613,18 +4611,22 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts)
/* Padding */
const int max_pad_x = (width - min_width) / 2;
const int max_pad_y = (height - min_height) / 2;
const int pad_x = min(max_pad_x, scale * term->conf->pad_x);
const int pad_y = min(max_pad_y, scale * term->conf->pad_y);
const int pad_left = min(max_pad_x, scale * term->conf->pad_left);
const int pad_right = min(max_pad_x, scale * term->conf->pad_right);
const int pad_top = min(max_pad_y, scale * term->conf->pad_top);
const int pad_bottom= min(max_pad_y, scale * term->conf->pad_bottom);
if (is_floating &&
(opts & RESIZE_BY_CELLS) &&
term->conf->resize_by_cells)
{
/* If resizing in cell increments, restrict the width and height */
width = ((width - 2 * pad_x) / term->cell_width) * term->cell_width + 2 * pad_x;
width = ((width - (pad_left + pad_right)) / term->cell_width)
* term->cell_width + (pad_left + pad_right);
width = max(min_width, roundf(scale * roundf(width / scale)));
height = ((height - 2 * pad_y) / term->cell_height) * term->cell_height + 2 * pad_y;
height = ((height - (pad_top + pad_bottom)) / term->cell_height)
* term->cell_height + (pad_top + pad_bottom);
height = max(min_height, roundf(scale * roundf(height / scale)));
}
@ -4651,8 +4653,10 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts)
int old_rows = term->rows;
/* Screen rows/cols after resize */
const int new_cols = (term->width - 2 * pad_x) / term->cell_width;
const int new_rows = (term->height - 2 * pad_y) / term->cell_height;
const int new_cols =
(term->width - (pad_left + pad_right)) / term->cell_width;
const int new_rows =
(term->height - (pad_top + pad_bottom)) / term->cell_height;
/*
* Requirements for scrollback:
@ -4705,16 +4709,16 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts)
term->margins.left = total_x_pad / 2;
term->margins.top = total_y_pad / 2;
} else {
term->margins.left = pad_x;
term->margins.top = pad_y;
term->margins.left = pad_left;
term->margins.top = pad_top;
}
term->margins.right = total_x_pad - term->margins.left;
term->margins.bottom = total_y_pad - term->margins.top;
xassert(term->margins.left >= pad_x);
xassert(term->margins.right >= pad_x);
xassert(term->margins.top >= pad_y);
xassert(term->margins.bottom >= pad_y);
xassert(term->margins.left >= pad_left);
xassert(term->margins.right >= pad_right);
xassert(term->margins.top >= pad_top);
xassert(term->margins.bottom >= pad_bottom);
if (new_cols == old_cols && new_rows == old_rows) {
LOG_DBG("grid layout unaffected; skipping reflow");

View file

@ -3802,8 +3802,18 @@ term_bell(struct terminal *term)
bool
term_spawn_new(const struct terminal *term)
{
char *argv[4];
int argc = 0;
argv[argc++] = term->foot_exe;
if (term->conf->conf_path != NULL) {
argv[argc++] = "--config";
argv[argc++] = term->conf->conf_path;
}
argv[argc] = NULL;
return spawn(
term->reaper, term->cwd, (char *const []){term->foot_exe, NULL},
term->reaper, term->cwd, argv,
-1, -1, -1, NULL, NULL, NULL) >= 0;
}
@ -4809,3 +4819,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;
}

View file

@ -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)
{

View file

@ -774,6 +774,8 @@ test_section_colors_dark(void)
&conf.colors_dark.table[i]);
}
test_boolean(&ctx, &parse_section_colors_dark, "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_light, "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) */

View file

@ -2,7 +2,7 @@
# Alacritty
[colors-dark]
cursor = 181818 56d8c9
cursor = 181818 d8d8d8
background= 181818
foreground= d8d8d8

View file

@ -4,7 +4,7 @@
[main]
initial-color-theme=light
xs
[colors-light]
cursor=eeeeee 444444
background=eeeeee

101
wayland.c
View file

@ -1193,6 +1193,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)
{
@ -1555,6 +1576,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)) {
@ -1569,6 +1604,7 @@ handle_global(void *data, struct wl_registry *registry,
seat_add_text_input(&it->item);
}
#endif
}
static void
@ -1882,6 +1918,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);
@ -1986,8 +2026,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) {
@ -2000,6 +2038,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);
@ -2129,8 +2177,6 @@ wayl_win_destroy(struct wl_window *win)
struct terminal *term = win->term;
render_wait_for_preapply_damage(term);
if (win->csd.move_timeout_fd != -1)
close(win->csd.move_timeout_fd);
@ -2188,6 +2234,8 @@ wayl_win_destroy(struct wl_window *win)
tll_remove(win->urls, it);
}
render_wait_for_preapply_damage(term);
csd_destroy(win);
wayl_win_subsurface_destroy(&win->search);
wayl_win_subsurface_destroy(&win->scrollback_indicator);
@ -2206,7 +2254,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);
@ -2446,16 +2499,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);
@ -2464,6 +2517,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

View file

@ -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 {
@ -490,6 +497,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;