Merge branch 'master' into live-color-reload

This commit is contained in:
wreald 2025-05-31 15:41:21 +10:00
commit 9f5cf7abca
95 changed files with 1787 additions and 666 deletions

View file

@ -1,6 +1,10 @@
# Changelog
* [Unreleased](#unreleased)
* [1.22.3](#1-22-3)
* [1.22.2](#1-22-2)
* [1.22.1](#1-22-1)
* [1.22.0](#1-22-0)
* [1.21.0](#1-21-0)
* [1.20.2](#1-20-2)
* [1.20.1](#1-20-1)
@ -61,6 +65,164 @@
## Unreleased
### Added
* `colors2` config section. This section duplicates the `colors`
section, and lets you define an alternative color theme.
* `key-bindings.color-theme-switch-1`,
`key-bindings.color-theme-switch-2` and
`key-bindings.color-theme-toggle` key bindings. These can be used to
switch between the primary and alternative color themes. They are
not bound by default.
* Support for private mode 2031 - [_Dark and Light Mode
Detection_](https://contour-terminal.org/vt-extensions/color-palette-update-notifications/)
([#2025][2025])
* Added `initial-color-theme=1|2` config option. `1` uses colors from
the `[colors]` section, `2` uses `[colors2]`.
* Combined dark/light theme files for (dark variant is the default,
set `initial-color-theme=2` to use the light variant by default):
- gruvbox
- nvim
- paper-color
- selenized
- solarized
* `regex-copy`/`show-urls-copy` will copy and paste the selected text if the hint
is completed with an uppercase character ([#1975][1975]).
* `16-bit` to `tweak.surface-bit-depth`. Makes foot use 16-bit image
buffers. They provide the necessary color precision required by
`gamma-correct-blending=yes`.
* New cursor shapes, from `cursor-shape-v1` version 2.
* `center-when-fullscreen` and `center-when-maximized-and-fullscreen`
to the `pad` option. This allows you to configure when the grid is
centered in more detail ([#2111][2111]).
[2025]: https://codeberg.org/dnkl/foot/issues/2025
[1975]: https://codeberg.org/dnkl/foot/issues/1975
[2111]: https://codeberg.org/dnkl/foot/issues/2111
### Changed
* `cursor.color` moved to `colors.cursor`.
* OSC-11 without an alpha value will now restore the configured
(i.e. from `foot.ini`) alpha, rather than keeping whatever the
current alpha value is, unchanged.
* `gamma-correct-blending=yes` now defaults to `16-bit` image buffers,
instead of `10-bit`.
* Allow setting either selection background, or selection foreground,
only ([#1846][1846]).
* Drop required version of libxkbcommon from 1.8.0 back to 1.0.0
([#2103][2103]).
[1846]: https://codeberg.org/dnkl/foot/issues/1846
[2103]: https://codeberg.org/dnkl/foot/issues/2103
### Deprecated
* `cursor.color` config option; use `colors.cursor` instead.
### Removed
### Fixed
* `REP`: wrong width of repeated multi-codepoint graphemes.
* Incorrect surface commit after a configure event, under certain
conditions ([#2105][2105]).
[2105]: https://codeberg.org/dnkl/foot/issues/2105
### Security
### Contributors
## 1.22.3
### Added
* `auto` to the `tweak.surface-bit-depth` option.
### Changed
* `gamma-correct-blending` now defaults to `no` instead of `yes`.
* `tweak.surface-bit-depth` default value changed to `auto`; uses
10-bit surfaces when `gamma-correct-blending=yes`, and 8-bit
surfaces otherwise.
### Fixed
* Inaccurate colors when `gamma-correct-blending=yes` ([#2082][2082]).
[2082]: https://codeberg.org/dnkl/foot/issues/2082
## 1.22.2
### Changed
* `gamma-correct-blending=yes` now uses a pure gamma 2.2 transfer
function, instead of the piece-wise sRGB transfer function, to match
what compositors do.
### Fixed
* Wrong colors when `gamma-correct-blending=yes` (the default when
there is compositor support). Note that some colors will still be
off by a **very** small amount, due to loss of precision when
converting to a linear color space. ([#2035][2035]).
[2035]: https://codeberg.org/dnkl/foot/issues/2035
## 1.22.1
### Fixed
* `colors.alpha-mode=matching` not working as intended.
* Grapheme shaping was allowed to be "enabled" at runtime, even though
disabled at compile time. This caused mis-rendering of certain
codepoints ([#2039][2039]).
* Keyboard modifiers not being reset on keyboard leave events
([#2034][2034]).
* Fallback font (and possibly wrong color) being used when a character
was followed by a zero-width grapheme breaking codepoint (for
example, _LEFT-TO-RIGHT MARK_) ([#2049][2049]).
* Regression: alpha applied to inversed text/selections
([#2073][2073]).
[2039]: https://codeberg.org/dnkl/foot/issues/2039
[2034]: https://codeberg.org/dnkl/foot/issues/2034
[2049]: https://codeberg.org/dnkl/foot/issues/2049
[2073]: https://codeberg.org/dnkl/foot/issues/2073
### Contributors
* Jan Palus
* valoq
## 1.22.0
### Added
* Support for toplevel edge constraints. When the compositor indicates
the toplevel has edge constraints, foot will not allow the window to
be resized (via CSDs) in the constrained directions.
* Virtual modifiers (e.g. `Alt` instead of `Mod1`, `Super` instead of
`Mod4` etc) in key bindings are now recognized as being virtual, and
are automatically mapped to the corresponding real modifier. This
means you can use e.g. `Alt+b` instead of `Mod1+b`.
* `alpha-mode` option to `foot.ini`. Defaults to `default`. This
config changes how alpha is handled on background colours not set by
the terminal.(e.g. vim) ([#2026](2026))
[2026]: https://codeberg.org/dnkl/foot/issues/2026
### Changed
* UTF-8 error recovery now discards fewer bytes.
@ -75,17 +237,18 @@
kitty keyboard protocol.
- some of foot's default shortcuts not working (mainly those using
`Mod1`) out of the box.
* Virtual modifiers (e.g. `Alt` instead of `Mod1`, `Super` instead of
`Mod4` etc) in key bindings are now recognized as being virtual, and
are automatically mapped to the corresponding real modifier. This
means you can use e.g. `Alt+b` instead of `Mod1+b`.
* Default URL regex changed to a much more strict variant
([#2016][2016]). You can manually set the [old
one](https://codeberg.org/dnkl/foot/src/tag/1.21.0/foot.ini#L72), if
you prefer it over the new regex.
* A tiled window can now be resized in the corners (via CSDs), unless
the compositor has indicated the toplevel has edge constraints.
[2006]: https://codeberg.org/dnkl/foot/issues/2006
[2009]: https://codeberg.org/dnkl/foot/issues/2009
[2016]: https://codeberg.org/dnkl/foot/issues/2016
### Deprecated
### Removed
### Fixed
* Regression: assertion in `url-mode.c` when activating a second URL
@ -93,14 +256,24 @@
* Build failure (`srgb.h` not found) when doing a parallel build.
* Regression: reflowing (changing the window size) removing empty
lines ([#2011][2011]).
* `url/regex-copy` not handling double-width characters correctly
([#2027][2027]).
[2000]: https://codeberg.org/dnkl/foot/issues/2000
[2011]: https://codeberg.org/dnkl/foot/issues/2011
[2027]: https://codeberg.org/dnkl/foot/issues/2027
### Security
### Contributors
* Alex Xu (Hello71)
* datsudo
* Dominique Martinet
* Fazzi
* llyyr
* Łukasz Wojniłowicz
* Sam McCall
## 1.21.0
@ -179,9 +352,9 @@
enabled ([#1947][1947]).
* Reflow of the cursor (active + saved) when at the end of the line
with a pending wrap (LCF set) ([#1954][1954]).
* Zero-width characters that also are grapheme breaks (e.g. U+200B,
* ~~Zero-width characters that also are grapheme breaks (e.g. U+200B,
ZERO WIDTH SPACE) being ignored (discarded and never stored in the
grid) ([#1960][1960]).
grid) ([#1960][1960]).~~ (reverted)
* `--server=<FD>` not working on FreeBSD ([#1956][1956]).
* Crash when resetting the terminal and an application had previously
set a custom app ID ([#1963][1963])

View file

@ -689,8 +689,11 @@ Every now and then I post foot related updates on
# Sponsoring/donations
* Liberapay: https://liberapay.com/dnkl
* GitHub Sponsors: https://github.com/sponsors/dnkl
[![Donate using Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/dnkl/donate)
# License

271
config.c
View file

@ -142,6 +142,9 @@ static const char *const binding_action_map[] = {
[BIND_ACTION_QUIT] = "quit",
[BIND_ACTION_REGEX_LAUNCH] = "regex-launch",
[BIND_ACTION_REGEX_COPY] = "regex-copy",
[BIND_ACTION_THEME_SWITCH_1] = "color-theme-switch-1",
[BIND_ACTION_THEME_SWITCH_2] = "color-theme-switch-2",
[BIND_ACTION_THEME_TOGGLE] = "color-theme-toggle",
/* Mouse-specific actions */
[BIND_ACTION_SCROLLBACK_UP_MOUSE] = "scrollback-up-mouse",
@ -930,21 +933,34 @@ parse_section_main(struct context *ctx)
else if (streq(key, "pad")) {
unsigned x, y;
char mode[16] = {0};
char mode[64] = {0};
int ret = sscanf(value, "%ux%u %63s", &x, &y, mode);
int ret = sscanf(value, "%ux%u %15s", &x, &y, mode);
bool center = strcasecmp(mode, "center") == 0;
bool invalid_mode = !center && mode[0] != '\0';
enum center_when center = CENTER_NEVER;
if ((ret != 2 && ret != 3) || invalid_mode) {
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) {
LOG_CONTEXTUAL_ERR(
"invalid padding (must be in the form PAD_XxPAD_Y [center])");
"invalid padding (must be in the form PAD_XxPAD_Y "
"[center|"
"center-when-fullscreen|"
"center-when-maximized-and-fullscreen])");
return false;
}
conf->pad_x = x;
conf->pad_y = y;
conf->center = center;
conf->center_when = ret == 2 ? CENTER_NEVER : center;
return true;
}
@ -1083,16 +1099,16 @@ parse_section_main(struct context *ctx)
return true;
}
else if (streq(key, "gamma-correct-blending")) {
bool gamma_correct;
if (!value_to_bool(ctx, &gamma_correct))
return false;
else if (streq(key, "gamma-correct-blending"))
return value_to_bool(ctx, &conf->gamma_correct);
conf->gamma_correct =
gamma_correct
? GAMMA_CORRECT_ENABLED
: GAMMA_CORRECT_DISABLED;
return true;
else if (streq(key, "initial-color-theme")) {
_Static_assert(
sizeof(conf->initial_color_theme) == sizeof(int),
"enum is not 32-bit");
return value_to_enum(ctx, (const char*[]){"1", "2", NULL},
(int *)&conf->initial_color_theme);
}
else {
@ -1338,10 +1354,9 @@ parse_section_regex(struct context *ctx)
}
}
static bool
parse_section_colors(struct context *ctx)
static bool NOINLINE
parse_color_theme(struct context *ctx, struct color_theme *theme)
{
struct config *conf = ctx->conf;
const char *key = ctx->key;
size_t key_len = strlen(key);
@ -1350,28 +1365,26 @@ parse_section_colors(struct context *ctx)
if (isdigit(key[0])) {
unsigned long index;
if (!str_to_ulong(key, 0, &index) ||
index >= ALEN(conf->colors.table))
{
if (!str_to_ulong(key, 0, &index) || index >= ALEN(theme->table)) {
LOG_CONTEXTUAL_ERR(
"invalid color palette index: %s (not in range 0-%zu)",
key, ALEN(conf->colors.table));
key, ALEN(theme->table));
return false;
}
color = &conf->colors.table[index];
color = &theme->table[index];
}
else if (key_len == 8 && str_has_prefix(key, "regular") && last_digit < 8)
color = &conf->colors.table[last_digit];
color = &theme->table[last_digit];
else if (key_len == 7 && str_has_prefix(key, "bright") && last_digit < 8)
color = &conf->colors.table[8 + last_digit];
color = &theme->table[8 + last_digit];
else if (key_len == 4 && str_has_prefix(key, "dim") && last_digit < 8) {
if (!value_to_color(ctx, &conf->colors.dim[last_digit], false))
if (!value_to_color(ctx, &theme->dim[last_digit], false))
return false;
conf->colors.use_custom.dim |= 1 << last_digit;
theme->use_custom.dim |= 1 << last_digit;
return true;
}
@ -1380,76 +1393,90 @@ parse_section_colors(struct context *ctx)
(key_len == 7 && key[5] == '1' && last_digit < 6)))
{
size_t idx = key_len == 6 ? last_digit : 10 + last_digit;
return value_to_color(ctx, &conf->colors.sixel[idx], false);
return value_to_color(ctx, &theme->sixel[idx], false);
}
else if (streq(key, "flash")) color = &conf->colors.flash;
else if (streq(key, "foreground")) color = &conf->colors.fg;
else if (streq(key, "background")) color = &conf->colors.bg;
else if (streq(key, "selection-foreground")) color = &conf->colors.selection_fg;
else if (streq(key, "selection-background")) color = &conf->colors.selection_bg;
else if (streq(key, "flash")) color = &theme->flash;
else if (streq(key, "foreground")) color = &theme->fg;
else if (streq(key, "background")) color = &theme->bg;
else if (streq(key, "selection-foreground")) color = &theme->selection_fg;
else if (streq(key, "selection-background")) color = &theme->selection_bg;
else if (streq(key, "jump-labels")) {
if (!value_to_two_colors(
ctx,
&conf->colors.jump_label.fg,
&conf->colors.jump_label.bg,
&theme->jump_label.fg,
&theme->jump_label.bg,
false))
{
return false;
}
conf->colors.use_custom.jump_label = true;
theme->use_custom.jump_label = true;
return true;
}
else if (streq(key, "scrollback-indicator")) {
if (!value_to_two_colors(
ctx,
&conf->colors.scrollback_indicator.fg,
&conf->colors.scrollback_indicator.bg,
&theme->scrollback_indicator.fg,
&theme->scrollback_indicator.bg,
false))
{
return false;
}
conf->colors.use_custom.scrollback_indicator = true;
theme->use_custom.scrollback_indicator = true;
return true;
}
else if (streq(key, "search-box-no-match")) {
if (!value_to_two_colors(
ctx,
&conf->colors.search_box.no_match.fg,
&conf->colors.search_box.no_match.bg,
&theme->search_box.no_match.fg,
&theme->search_box.no_match.bg,
false))
{
return false;
}
conf->colors.use_custom.search_box_no_match = true;
theme->use_custom.search_box_no_match = true;
return true;
}
else if (streq(key, "search-box-match")) {
if (!value_to_two_colors(
ctx,
&conf->colors.search_box.match.fg,
&conf->colors.search_box.match.bg,
&theme->search_box.match.fg,
&theme->search_box.match.bg,
false))
{
return false;
}
conf->colors.use_custom.search_box_match = true;
theme->use_custom.search_box_match = true;
return true;
}
else if (streq(key, "cursor")) {
if (!value_to_two_colors(
ctx,
&theme->cursor.text,
&theme->cursor.cursor,
false))
{
return false;
}
theme->use_custom.cursor = true;
return true;
}
else if (streq(key, "urls")) {
if (!value_to_color(ctx, &conf->colors.url, false))
if (!value_to_color(ctx, &theme->url, false))
return false;
conf->colors.use_custom.url = true;
theme->use_custom.url = true;
return true;
}
@ -1463,7 +1490,7 @@ parse_section_colors(struct context *ctx)
return false;
}
conf->colors.alpha = alpha * 65535.;
theme->alpha = alpha * 65535.;
return true;
}
@ -1477,10 +1504,19 @@ parse_section_colors(struct context *ctx)
return false;
}
conf->colors.flash_alpha = alpha * 65535.;
theme->flash_alpha = alpha * 65535.;
return true;
}
else if (strcmp(key, "alpha-mode") == 0) {
_Static_assert(sizeof(theme->alpha_mode) == sizeof(int),
"enum is not 32-bit");
return value_to_enum(
ctx,
(const char *[]){"default", "matching", "all", NULL},
(int *)&theme->alpha_mode);
}
else {
LOG_CONTEXTUAL_ERR("not valid option");
@ -1495,6 +1531,18 @@ parse_section_colors(struct context *ctx)
return true;
}
static bool
parse_section_colors(struct context *ctx)
{
return parse_color_theme(ctx, &ctx->conf->colors);
}
static bool
parse_section_colors2(struct context *ctx)
{
return parse_color_theme(ctx, &ctx->conf->colors2);
}
static bool
parse_section_cursor(struct context *ctx)
{
@ -1528,17 +1576,24 @@ parse_section_cursor(struct context *ctx)
return value_to_uint32(ctx, 10, &conf->cursor.blink.rate_ms);
else if (streq(key, "color")) {
LOG_WARN("%s:%d: cursor.color: deprecated; use colors.cursor instead",
ctx->path, ctx->lineno);
user_notification_add(
&conf->notifications,
USER_NOTIFICATION_DEPRECATED,
xstrdup("cursor.color: use colors.cursor instead"));
if (!value_to_two_colors(
ctx,
&conf->cursor.color.text,
&conf->cursor.color.cursor,
false))
ctx,
&conf->colors.cursor.text,
&conf->colors.cursor.cursor,
false))
{
return false;
}
conf->cursor.color.text |= 1u << 31;
conf->cursor.color.cursor |= 1u << 31;
conf->colors.use_custom.cursor = true;
return true;
}
@ -2767,12 +2822,19 @@ parse_section_tweak(struct context *ctx)
else if (streq(key, "surface-bit-depth")) {
_Static_assert(sizeof(conf->tweak.surface_bit_depth) == sizeof(int),
"enum is not 32-bit");
"enum is not 32-bit");
#if defined(HAVE_PIXMAN_RGBA_16)
return value_to_enum(
ctx,
(const char *[]){"8-bit", "10-bit", NULL},
(const char *[]){"auto", "8-bit", "10-bit", "16-bit", NULL},
(int *)&conf->tweak.surface_bit_depth);
#else
return value_to_enum(
ctx,
(const char *[]){"auto", "8-bit", "10-bit", NULL},
(int *)&conf->tweak.surface_bit_depth);
#endif
}
else {
@ -2867,6 +2929,7 @@ enum section {
SECTION_URL,
SECTION_REGEX,
SECTION_COLORS,
SECTION_COLORS2,
SECTION_CURSOR,
SECTION_MOUSE,
SECTION_CSD,
@ -2897,6 +2960,7 @@ static const struct {
[SECTION_URL] = {&parse_section_url, "url"},
[SECTION_REGEX] = {&parse_section_regex, "regex", true},
[SECTION_COLORS] = {&parse_section_colors, "colors"},
[SECTION_COLORS2] = {&parse_section_colors2, "colors2"},
[SECTION_CURSOR] = {&parse_section_cursor, "cursor"},
[SECTION_MOUSE] = {&parse_section_mouse, "mouse"},
[SECTION_CSD] = {&parse_section_csd, "csd"},
@ -3289,6 +3353,7 @@ config_load(struct config *conf, const char *conf_path,
},
.pad_x = 0,
.pad_y = 0,
.center_when = CENTER_MAXIMIZED_AND_FULLSCREEN,
.resize_by_cells = true,
.resize_keep_grid = true,
.resize_delay_ms = 100,
@ -3310,7 +3375,7 @@ config_load(struct config *conf, const char *conf_path,
.underline_thickness = {.pt = 0., .px = -1},
.strikeout_thickness = {.pt = 0., .px = -1},
.dpi_aware = false,
.gamma_correct = GAMMA_CORRECT_AUTO,
.gamma_correct = false,
.security = {
.osc52 = OSC52_ENABLED,
},
@ -3345,16 +3410,20 @@ config_load(struct config *conf, const char *conf_path,
.flash = 0x7f7f00,
.flash_alpha = 0x7fff,
.alpha = 0xffff,
.alpha_mode = ALPHA_MODE_DEFAULT,
.selection_fg = 0x80000000, /* Use default bg */
.selection_bg = 0x80000000, /* Use default fg */
.cursor = {
.text = 0,
.cursor = 0,
},
.use_custom = {
.selection = false,
.jump_label = false,
.scrollback_indicator = false,
.url = false,
},
},
.initial_color_theme = COLOR_THEME1,
.cursor = {
.style = CURSOR_BLOCK,
.unfocused_style = CURSOR_UNFOCUSED_HOLLOW,
@ -3362,10 +3431,6 @@ config_load(struct config *conf, const char *conf_path,
.enabled = false,
.rate_ms = 500,
},
.color = {
.text = 0,
.cursor = 0,
},
.beam_thickness = {.pt = 1.5},
.underline_thickness = {.pt = 0., .px = -1},
},
@ -3419,7 +3484,7 @@ config_load(struct config *conf, const char *conf_path,
.box_drawing_solid_shades = true,
.font_monospace_warn = true,
.sixel = true,
.surface_bit_depth = 8,
.surface_bit_depth = SHM_BITS_AUTO,
},
.touch = {
@ -3438,6 +3503,7 @@ config_load(struct config *conf, const char *conf_path,
memcpy(conf->colors.table, default_color_table, sizeof(default_color_table));
memcpy(conf->colors.sixel, default_sixel_colors, sizeof(default_sixel_colors));
memcpy(&conf->colors2, &conf->colors, sizeof(conf->colors));
parse_modifiers(XKB_MOD_NAME_SHIFT, 5, &conf->mouse.selection_override_modifiers);
tokenize_cmdline(
@ -3447,39 +3513,46 @@ config_load(struct config *conf, const char *conf_path,
tokenize_cmdline("xdg-open ${url}", &conf->url.launch.argv.args);
{
/*
* Based on https://gist.github.com/gruber/249502, but modified:
* - Do not allow {} at all
* - Do allow matched []
*/
const char *url_regex_string =
const char *url_regex_string =
"("
"("
"("
"[a-z][[:alnum:]-]+:" // protocol
"("
"/{1,3}|[a-z0-9%]" // slashes (what's the OR part for?)
")"
"|"
"www[:digit:]{0,3}[.]"
//"|"
//"[a-z0-9.\\-]+[.][a-z]{2,4}/" /* "looks like domain name followed by a slash" - remove? */
")"
"("
"[^[:space:](){}<>]+"
"|"
"\\(([^[:space:](){}<>]+|(\\([^[:space:](){}<>]+\\)))*\\)"
"|"
"\\[([^]\\[[:space:](){}<>]+|(\\[[^]\\[[:space:](){}<>]+\\]))*\\]"
")+"
"("
"\\(([^[:space:](){}<>]+|(\\([^[:space:](){}<>]+\\)))*\\)"
"|"
"\\[([^]\\[[:space:](){}<>]+|(\\[[^]\\[[:space:](){}<>]+\\]))*\\]"
"|"
"[^]\\[[:space:]`!(){};:'\".,<>?«»“”‘’]"
")"
"(https?://|mailto:|ftp://|file:|ssh:|ssh://|git://|tel:|magnet:|ipfs://|ipns://|gemini://|gopher://|news:)"
"|"
"www\\."
")"
;
"("
/* Safe + reserved + some unsafe characters parenthesis and double quotes omitted (we only allow them when balanced) */
"[0-9a-zA-Z:/?#@!$&*+,;=.~_%^\\-]+"
"|"
/* Balanced "(...)". Content is same as above, plus all _other_ characters we require to be balanced */
"\\([]\\[\"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\\-]*\\)"
"|"
/* Balanced "[...]". Content is same as above, plus all _other_ characters we require to be balanced */
"\\[[\\(\\)\"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\\-]*\\]"
"|"
/* Balanced '"..."'. Content is same as above, plus all _other_ characters we require to be balanced */
"\"[]\\[\\(\\)0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\\-]*\""
"|"
/* Balanced "'...'". Content is same as above, plus all _other_ characters we require to be balanced */
"'[]\\[\\(\\)0-9a-zA-Z:/?#@!$&*+,;=.~_%^\\-]*'"
")+"
"("
/* Same as above, except :?!,;. are excluded */
"[0-9a-zA-Z/#@$&*+=~_%^\\-]"
"|"
/* Balanced "(...)". Content is same as above, plus all _other_ characters we require to be balanced */
"\\([]\\[\"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\\-]*\\)"
"|"
/* Balanced "[...]". Content is same as above, plus all _other_ characters we require to be balanced */
"\\[[\\(\\)\"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\\-]*\\]"
"|"
/* Balanced '"..."'. Content is same as above, plus all _other_ characters we require to be balanced */
"\"[]\\[\\(\\)0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\\-]*\""
"|"
/* Balanced "'...'". Content is same as above, plus all _other_ characters we require to be balanced */
"'[]\\[\\(\\)0-9a-zA-Z:/?#@!$&*+,;=.~_%^\\-]*'"
")"
")";
int r = regcomp(&conf->url.preg, url_regex_string, REG_EXTENDED);
xassert(r == 0);
@ -3536,10 +3609,6 @@ config_load(struct config *conf, const char *conf_path,
if (!config_override_apply(conf, overrides, errors_are_fatal))
ret = !errors_are_fatal;
conf->colors.use_custom.selection =
conf->colors.selection_fg >> 24 == 0 &&
conf->colors.selection_bg >> 24 == 0;
if (ret && conf->fonts[0].count == 0) {
struct config_font font;
if (!config_font_parse("monospace", &font)) {

139
config.h
View file

@ -131,6 +131,84 @@ struct custom_regex {
struct config_spawn_template launch;
};
struct color_theme {
uint32_t fg;
uint32_t bg;
uint32_t flash;
uint32_t flash_alpha;
uint32_t table[256];
uint16_t alpha;
uint32_t selection_fg;
uint32_t selection_bg;
uint32_t url;
uint32_t dim[8];
uint32_t sixel[16];
enum {
ALPHA_MODE_DEFAULT,
ALPHA_MODE_MATCHING,
ALPHA_MODE_ALL
} alpha_mode;
struct {
uint32_t text;
uint32_t cursor;
} cursor;
struct {
uint32_t fg;
uint32_t bg;
} jump_label;
struct {
uint32_t fg;
uint32_t bg;
} scrollback_indicator;
struct {
struct {
uint32_t fg;
uint32_t bg;
} no_match;
struct {
uint32_t fg;
uint32_t bg;
} match;
} search_box;
struct {
bool cursor:1;
bool jump_label:1;
bool scrollback_indicator:1;
bool url:1;
bool search_box_no_match:1;
bool search_box_match:1;
uint8_t dim;
} use_custom;
};
enum which_color_theme {
COLOR_THEME1,
COLOR_THEME2,
};
enum shm_bit_depth {
SHM_BITS_AUTO,
SHM_BITS_8,
SHM_BITS_10,
SHM_BITS_16,
};
enum center_when {
CENTER_INVALID,
CENTER_NEVER,
CENTER_FULLSCREEN,
CENTER_MAXIMIZED_AND_FULLSCREEN,
CENTER_ALWAYS,
};
struct config {
char *path;
char *term;
@ -149,7 +227,7 @@ struct config {
unsigned pad_x;
unsigned pad_y;
bool center;
enum center_when center_when;
bool resize_by_cells;
bool resize_keep_grid;
@ -169,9 +247,7 @@ struct config {
enum { STARTUP_WINDOWED, STARTUP_MAXIMIZED, STARTUP_FULLSCREEN } startup_mode;
bool dpi_aware;
enum {GAMMA_CORRECT_DISABLED,
GAMMA_CORRECT_ENABLED,
GAMMA_CORRECT_AUTO} gamma_correct;
bool gamma_correct;
struct config_font_list fonts[4];
struct font_size_adjustment font_size_adjustment;
@ -245,52 +321,9 @@ struct config {
tll(struct custom_regex) custom_regexes;
struct {
uint32_t fg;
uint32_t bg;
uint32_t flash;
uint32_t flash_alpha;
uint32_t table[256];
uint16_t alpha;
uint32_t selection_fg;
uint32_t selection_bg;
uint32_t url;
uint32_t dim[8];
uint32_t sixel[16];
struct {
uint32_t fg;
uint32_t bg;
} jump_label;
struct {
uint32_t fg;
uint32_t bg;
} scrollback_indicator;
struct {
struct {
uint32_t fg;
uint32_t bg;
} no_match;
struct {
uint32_t fg;
uint32_t bg;
} match;
} search_box;
struct {
bool selection:1;
bool jump_label:1;
bool scrollback_indicator:1;
bool url:1;
bool search_box_no_match:1;
bool search_box_match:1;
uint8_t dim;
} use_custom;
} colors;
struct color_theme colors;
struct color_theme colors2;
enum which_color_theme initial_color_theme;
struct {
enum cursor_style style;
@ -299,10 +332,6 @@ struct config {
bool enabled;
uint32_t rate_ms;
} blink;
struct {
uint32_t text;
uint32_t cursor;
} color;
struct pt_or_px beam_thickness;
struct pt_or_px underline_thickness;
} cursor;
@ -405,7 +434,7 @@ struct config {
bool box_drawing_solid_shades;
bool font_monospace_warn;
bool sixel;
enum { SHM_8_BIT, SHM_10_BIT } surface_bit_depth;
enum shm_bit_depth surface_bit_depth;
} tweak;
struct {

47
csi.c
View file

@ -558,7 +558,13 @@ decset_decrst(struct terminal *term, unsigned param, bool enable)
break;
case 2027:
#if defined(FOOT_GRAPHEME_CLUSTERING)
term->grapheme_shaping = enable;
#endif
break;
case 2031:
term->report_theme_changes = enable;
break;
case 2048:
@ -655,6 +661,7 @@ decrqm(const struct terminal *term, unsigned param)
case 2027: return term->conf->tweak.grapheme_width_method != GRAPHEME_WIDTH_DOUBLE
? DECRPM_PERMANENTLY_RESET
: decrpm(term->grapheme_shaping);
case 2031: return decrpm(term->report_theme_changes);
case 2048: return decrpm(term->size_notifications);
case 8452: return decrpm(term->sixel.cursor_right_of_graphics);
case 737769: return decrpm(term_ime_is_enabled(term));
@ -700,6 +707,7 @@ xtsave(struct terminal *term, unsigned param)
case 2004: term->xtsave.bracketed_paste = term->bracketed_paste; break;
case 2026: term->xtsave.app_sync_updates = term->render.app_sync_updates.enabled; break;
case 2027: term->xtsave.grapheme_shaping = term->grapheme_shaping; break;
case 2031: term->xtsave.report_theme_changes = term->report_theme_changes; break;
case 2048: term->xtsave.size_notifications = term->size_notifications; break;
case 8452: term->xtsave.sixel_cursor_right_of_graphics = term->sixel.cursor_right_of_graphics; break;
case 737769: term->xtsave.ime = term_ime_is_enabled(term); break;
@ -744,6 +752,7 @@ xtrestore(struct terminal *term, unsigned param)
case 2004: enable = term->xtsave.bracketed_paste; break;
case 2026: enable = term->xtsave.app_sync_updates; break;
case 2027: enable = term->xtsave.grapheme_shaping; break;
case 2031: enable = term->xtsave.report_theme_changes; break;
case 2048: enable = term->xtsave.size_notifications; break;
case 8452: enable = term->xtsave.sixel_cursor_right_of_graphics; break;
case 737769: enable = term->xtsave.ime; break;
@ -790,7 +799,17 @@ csi_dispatch(struct terminal *term, uint8_t final)
int count = vt_param_get(term, 0, 1);
LOG_DBG("REP: '%lc' %d times", (wint_t)term->vt.last_printed, count);
const int width = c32width(term->vt.last_printed);
int width;
if (term->vt.last_printed >= CELL_COMB_CHARS_LO) {
const struct composed *comp = composed_lookup(
term->composed, term->vt.last_printed - CELL_COMB_CHARS_LO);
xassert(comp != NULL);
width = comp->forced_width > 0 ? comp->forced_width : comp->width;
} else
width = c32width(term->vt.last_printed);
if (width > 0) {
for (int i = 0; i < count; i++)
term_print(term, term->vt.last_printed, width, false);
@ -1537,6 +1556,32 @@ csi_dispatch(struct terminal *term, uint8_t final)
break;
}
case 'n': {
const int param = vt_param_get(term, 0, 0);
switch (param) {
case 996: { /* Query current theme mode (see private mode 2031) */
/*
* 1 - dark mode
* 2 - light mode
*
* In foot, the themes aren't necessarily light/dark,
* but by convention, the primary theme is dark, and
* the alternative theme is light.
*/
char reply[16] = {0};
int chars = snprintf(
reply, sizeof(reply),
"\033[?997;%dn",
term->colors.active_theme == COLOR_THEME1 ? 1 : 2);
term_to_slave(term, reply, chars);
break;
}
}
break;
}
case 'p': {
/*
* Request status of ECMA-48/"ANSI" private mode (DECRQM

View file

@ -54,7 +54,7 @@ cursor_shape_to_server_shape(enum cursor_shape shape)
}
enum wp_cursor_shape_device_v1_shape
cursor_string_to_server_shape(const char *xcursor)
cursor_string_to_server_shape(const char *xcursor, int bound_version)
{
if (xcursor == NULL)
return 0;
@ -72,7 +72,7 @@ cursor_string_to_server_shape(const char *xcursor)
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_VERTICAL_TEXT] = {"vertical-text"},
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALIAS] = {"alias", "dnd-link"},
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COPY] = {"copy", "dnd-copy"},
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE] = {"move"}, /* dnd-move? */
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE] = {"move", "dnd-move"},
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NO_DROP] = {"no-drop", "dnd-no-drop"},
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NOT_ALLOWED] = {"not-allowed", "crossed_circle"},
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB] = {"grab", "hand1"},
@ -94,9 +94,29 @@ cursor_string_to_server_shape(const char *xcursor)
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_SCROLL] = {"all-scroll", "fleur"},
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_IN] = {"zoom-in"},
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ZOOM_OUT] = {"zoom-out"},
#if defined(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK_SINCE_VERSION) /* 1.42 */
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK] = {"dnd-ask"},
#endif
#if defined(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE_SINCE_VERSION) /* 1.42 */
[WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE] = {"all-resize"},
#endif
};
for (size_t i = 0; i < ALEN(table); i++) {
#if defined(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK_SINCE_VERSION)
if (i == WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK &&
bound_version < WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK_SINCE_VERSION)
{
continue;
}
#endif
#if defined(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE_SINCE_VERSION)
if (i == WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE &&
bound_version < WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ALL_RESIZE_SINCE_VERSION)
{
continue;
}
#endif
for (size_t j = 0; j < ALEN(table[i]); j++) {
if (table[i][j] != NULL && streq(xcursor, table[i][j])) {
return i;

View file

@ -26,4 +26,4 @@ const char *const *cursor_shape_to_string(enum cursor_shape shape);
enum wp_cursor_shape_device_v1_shape cursor_shape_to_server_shape(
enum cursor_shape shape);
enum wp_cursor_shape_device_v1_shape cursor_string_to_server_shape(
const char *xcursor);
const char *xcursor, int bound_version);

View file

@ -337,6 +337,9 @@ that corresponds to one of the following modes:
| 2027
: contour
: Grapheme cluster processing
| 2031
: contour
: Request color theme updates
| 2048
: TODO
: In-band window resize notifications
@ -657,6 +660,13 @@ manipulation sequences. The generic format is:
: xterm
: Report the current entry on the palette stack, and the number of
palettes stored on the stack.
| \\E[ ? 996 n
: Query the current (color) theme mode
: contour
: The current color theme mode (light or dark) is reported as *CSI ?
997 ; 1|2 n*, where *1* means dark and *2* light. By convention, the
primary theme in foot is considered dark, and the alternative theme
light.
# OSC

View file

@ -207,7 +207,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
Compared to the default (disabled), bright glyphs on a dark
background will appear thicker, and dark glyphs on a light
background will appear thinner.
FreeType can limit the effect of the latter, with a technique
called stem darkening. It is only available for CFF fonts
(OpenType, .otf) and disabled by default (in FreeType). You can
@ -220,12 +220,16 @@ empty string to be set, but it must be quoted: *KEY=""*)
than intended when rendered with gamma-correct blending, since the
font designer set the font weight based on incorrect rendering.
You may also want to enable 10-bit image buffers when
gamma-correct blending is enabled. Though probably only if you do
not use a transparent background (with 10-bit buffers, you only
get 2 bits alpha). See *tweak.surface-bit-depth*.
In order to represent colors faithfully, higher precision image
buffers are required. By default, foot will use either 16-bit, or
10-bit color channels, depending on availability, when
gamma-correct blending is enabled. However, the high precision
buffers are slow; if you want to use gamma-correct blending, but
prefer speed (throughput and input latency) over accurate colors,
you can force 8-bit color channels by setting
*tweak.surface-bit-depth=8-bit*.
Default: enabled when compositor support is available
Default: _no_.
*box-drawings-uses-font-glyphs*
Boolean. When disabled, foot generates box/line drawing characters
@ -249,6 +253,7 @@ empty string to be set, but it must be quoted: *KEY=""*)
- U+02500 - U+0259F
- U+02800 - U+028FF
- U+1CD00 - U+1CDE5
- U+1Fb00 - U+1FB9B
Default: _no_.
@ -284,18 +289,29 @@ empty string to be set, but it must be quoted: *KEY=""*)
*pad*
Padding between border and glyphs, in pixels (subject to output
scaling), in the form _XxY_.
scaling), in the form
```
_XxY_ [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. The grid content
will be anchored in the top left corner. I.e. if the window
manager forces an odd window size on foot, the additional pixels
will be added to the right and bottom sides.
sides, and Y pixels on the top and bottom sides.
To instead center the grid content, append *center* (e.g. *pad=5x5
center*).
When no centering is specified, the grid content is anchored to
the top left corner. I.e. if the window manager forces an odd
window size on foot, the additional pixels will be added to the
right and bottom sides.
Default: _0x0_.
If *center* is specified, the grid content is instead
centered. This may cause "jumpiness" when resizing the window.
With *center-when-fullscreen* and
*center-when-maximized-and-fullscreen*, the grid is anchored to
the top left corner, unless the window is maximized, or
fullscreened.
Default: _0x0_ center-when-maximized-and-fullscreen.
*resize-delay-ms*
@ -347,6 +363,18 @@ empty string to be set, but it must be quoted: *KEY=""*)
Default: _yes_
*initial-color-theme*
Selects which color theme to use, *1*, or *2*.
*1* uses the colors defined in the *colors* section, while *2*
uses the colors from the *colors2* section.
Use the *color-theme-switch-1*, *color-theme-switch-2* and
*color-theme-toggle* key bindings to switch between the two themes
at runtime.
Default: _1_
*initial-window-size-pixels*
Initial window width and height in _pixels_ (subject to output
scaling), in the form _WIDTHxHEIGHT_. The height _includes_ the
@ -419,6 +447,10 @@ empty string to be set, but it must be quoted: *KEY=""*)
multithreading. Default: the number of available logical CPUs
(including SMT). Note that this is not always the best value. In
some cases, the number of physical _cores_ is better.
In case you have a ridiculous amount of cores and/or threads,
consider limiting the number of *workers*, since foot cannot
parallelize more than the number of visible rows.
*utmp-helper*
Path to utmp logging helper binary.
@ -828,7 +860,7 @@ section.
whole regex match to be used as an URL, surround all of it with
parenthesis: *(regex-pattern)*.
Default: _(([a-z][[:alnum:]-]+:(/{1,3}|[a-z0-9%])|www[:digit:]{0,3}[.])([^[:space:](){}<>]+|\(([^[:space:](){}<>]+|(\([^[:space:](){}<>]+\)))\*\)|\[([^]\[[:space:](){}<>]+|(\[[^]\[[:space:](){}<>]+\]))\*\])+(\(([^[:space:](){}<>]+|(\([^[:space:](){}<>]+\)))\*\)|\[([^]\[[:space:](){}<>]+|(\[[^]\[[:space:](){}<>]+\]))\*\]|[^]\[[:space:]`!(){};:'".,<>?«»“”‘’]))_
Default: _(((https?://|mailto:|ftp://|file:|ssh:|ssh://|git://|tel:|magnet:|ipfs://|ipns://|gemini://|gopher://|news:)|www\.)([0-9a-zA-Z:/?#@!$&\*+,;=.~\_%^\-]+|\([]\["0-9a-zA-Z:/?#@!$&'\*+,;=.~\_%^\-]\*\)|\[[\(\)"0-9a-zA-Z:/?#@!$&'\*+,;=.~\_%^\-]\*\]|"[]\[\(\)0-9a-zA-Z:/?#@!$&'\*+,;=.~\_%^\-]\*"|'[]\[\(\)0-9a-zA-Z:/?#@!$&\*+,;=.~\_%^\-]\*')+([0-9a-zA-Z/#@$&\*+=~\_%^\-]|\([]\["0-9a-zA-Z:/?#@!$&'\*+,;=.~\_%^\-]\*\)|\[[\(\)"0-9a-zA-Z:/?#@!$&'\*+,;=.~\_%^\-]\*\]|"[]\[\(\)0-9a-zA-Z:/?#@!$&'\*+,;=.~\_%^\-]\*"|'[]\[\(\)0-9a-zA-Z:/?#@!$&\*+,;=.~\_%^\-]\*'))_
# SECTION: regex
@ -892,15 +924,6 @@ applications can change these at runtime.
enabled. Expressed in milliseconds between each blink. Default:
_500_.
*color*
Two space separated RRGGBB values (i.e. plain old 6-digit hex
values, without prefix) specifying the foreground (text) and
background (cursor) colors for the cursor.
Example: *ff0000 00ff00* (green cursor, red text)
Default: the regular foreground and background colors, reversed.
*beam-thickness*
Thickness (width) of the beam styled cursor. The value is in
points, and its exact value thus depends on the monitor's DPI. To
@ -961,6 +984,19 @@ The colors are in RRGGBB format (i.e. plain old 6-digit hex values,
without prefix). That is, they do *not* have an alpha component. You
can configure the background transparency with the _alpha_ option.
In the context of private mode 2031 (Dark and Light Mode detection),
the primary theme (i.e. the *colors* section) is considered to be the
dark theme (since the default theme is dark).
*cursor*
Two space separated RRGGBB values (i.e. plain old 6-digit hex
values, without prefix) specifying the foreground (text) and
background (cursor) colors for the cursor.
Example: *ff0000 00ff00* (green cursor, red text)
Default: the regular foreground and background colors, reversed.
*foreground*
Default foreground color. This is the color used when no ANSI
color is being used. Default: _839496_.
@ -1027,10 +1063,24 @@ can configure the background transparency with the _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_.
*alpha-mode*
Specifies when *alpha* is applied. One of *default*, *matching* or
*all*.
*default* applies *alpha* to cells with the default background
color, excluding cells with the same RGB value as the default
background color.
*matching* is the same as *default*, but also applies *alpha* to
cells with the same RGB value as the default background color.
*all* applies *alpha* to all cells, regardless of background color.
Default: _default_
*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
used. Default: _inverse foreground/background_.
text. Default: _inverse foreground/background_.
*jump-labels*
Two color values specifying the foreground (text) and background
@ -1063,6 +1113,19 @@ can configure the background transparency with the _alpha_ option.
Flash translucency. A value in the range 0.0-1.0, where 0.0 means
completely transparent, and 1.0 is opaque. Default: _0.5_.
# SECTION: colors2
This section defines an alternative color theme. It has the exact same
keys as the *colors* section. The default values are the same.
Note that values are not inherited. That is, if you set a value in
*colors*, but not in *colors2*, the value from *colors* is not
inherited by *colors2*.
In the context of private mode 2031 (Dark and Light Mode detection),
the alternative theme (i.e. the *colors2* section) is considered to be
the light theme (since the default, the primary theme, is dark).
# SECTION: csd
This section controls the look of the _CSDs_ (Client Side
@ -1171,17 +1234,18 @@ different approaches.
As an example, let's say you press ctrl+shift+c (assume plain us ASCII
layout). XKB will tell foot *Control+C* was pressed. Note the lack of
the shift modifier, and the upper case 'C'. Internally, this is called
the "translated" form, and is what foot tries to match first.
the "translated" form.
If no "translated" key bindings can be found, foot proceeds to
checking the "untranslated" variant. Using the same example as above,
this will match *Control+Shift+c* (shift modifier present, lower case
'c').
The "untranslated" form (*Control+Shift+c*) is derived from the
translated form, and is what foot tries to match first.
If no "untranslated" key bindings can be found, foot proceeds to
checking the "translated" variant.
This means you can use either form in your foot configuration, and
that *Control+C* (and similar) has higher priority than
*Control+Shift+c*. Also note that while foot normally detects when the
same combination is assigned to multiple actions, it will not detect
that *Control+Shift+c* (and similar) has higher priority than
*Control+C*. Also note that while foot normally detects when the same
combination is assigned to multiple actions, it will not detect
*Control+C* vs. *Control+Shift+c* collisions. Call it a known bug...
Finally, foot tries to match the raw key code. Here, the primary
@ -1305,7 +1369,8 @@ e.g. *search-start=none*.
*show-urls-copy*
Enter URL mode, where all currently visible URLs are tagged with a
jump label with a key sequence that will place the URL in the
clipboard. Default: _none_.
clipboard. If the hint is completed with an uppercase character,
the match will also be pasted. Default: _none_.
*regex-launch*
Enter regex mode. This works exactly the same as URL mode; all
@ -1328,8 +1393,10 @@ e.g. *search-start=none*.
Default: _none_.
*regex-copy*
Same as *regex-copy*, but the match is placed in the clipboard,
instead of "launched", upon activation. Default: _none_.
Same as *regex-launch*, but the match is placed in the clipboard,
instead of "launched", upon activation. If the hint is completed
with an uppercase character, the match will also be pasted.
Default: _none_.
*prompt-prev*
Jump to the previous, currently not visible, prompt (requires
@ -1365,6 +1432,22 @@ e.g. *search-start=none*.
Default: _Control+Shift+u_.
*color-theme-switch-1*, *color-theme-switch-2*, *color-theme-toggle*
Switch between the primary color theme (defined in the *colors*
section), and the alternative color theme (defined in the
*colors2* section).
*color-theme-switch-1* applies the primary color theme regardless
of which color theme is currently active.
*color-theme-switch-2* applies the alternative color theme regardless
of which color theme is currently active.
*color-theme-toggle* toggles between the primary and alternative
color themes.
Default: _none_
*quit*
Quit foot. Default: _none_.
@ -1951,23 +2034,27 @@ any of these options.
*surface-bit-depth*
Selects which RGB bit depth to use for image buffers. One of
*8-bit*, or *10-bit*.
*auto*, *8-bit*, *10-bit* or *16-bit*.
The default, *8-bit*, uses 8 bits for all channels, alpha
included. When *gamma-correct-blending* is disabled, this is the
best option.
*auto* chooses bit depth depending on other settings, and
availability.
When *gamma-correct-blending* is enabled, you may want to enable
10-bit surfaces, as that improves the color resolution. Be aware
however, that in this mode, the alpha channel is only 2 bits
instead of 8 bits. Thus, if you are using a transparent
background, you may want to use the default, *8-bit*, even if you
have gamma-correct blending enabled.
*8-bit*, uses 8 bits for each color channel, alpha included. This
is the default when *gamma-correct-blending=no*.
You should also note that 10-bit surface is slower. This will
increase input latency and decrease rendering throughput.
*10-bit* uses 10 bits for each RGB channel, and 2 bits for the
alpha channel. Thus, it provides higher precision color channels,
but a lower precision alpha channel.
Default: _8-bit_
*16-bit* 16 bits for each color channel, alpha included. If
available, this is the default when *gamma-correct-blending=yes*.
Note that both *10-bit* and *16-bit* are much slower than *8-bit*;
if you want to use gamma-correct blending, and if you prefer speed
(throughput and input latency) over accurate colors, you can set
*surface-bit-depth=8-bit* explicitly.
Default: _auto_
# LIVE RELOAD

View file

@ -22,11 +22,13 @@
# strikeout-thickness=<font strikeout thickness>
# box-drawings-uses-font-glyphs=no
# dpi-aware=no
# gamma-correct-blending=no
# initial-color-theme=1
# initial-window-size-pixels=700x500 # Or,
# initial-window-size-chars=<COLSxROWS>
# initial-window-mode=windowed
# pad=0x0 # optionally append 'center'
# pad=0x0 center-when-maximized-and-fullscreen
# resize-by-cells=yes
# resize-keep-grid=yes
# resize-delay-ms=100
@ -69,7 +71,7 @@
# launch=xdg-open ${url}
# label-letters=sadfjklewcmpgh
# osc8-underline=url-mode
# regex=(([a-z][[:alnum:]-]+:(/{1,3}|[a-z0-9%])|www[:digit:]{0,3}[.])([^[:space:](){}<>]+|\(([^[:space:](){}<>]+|(\([^[:space:](){}<>]+\)))*\)|\[([^]\[[:space:](){}<>]+|(\[[^]\[[:space:](){}<>]+\]))*\])+(\(([^[:space:](){}<>]+|(\([^[:space:](){}<>]+\)))*\)|\[([^]\[[:space:](){}<>]+|(\[[^]\[[:space:](){}<>]+\]))*\]|[^]\[[:space:]`!(){};:'".,<>?«»“”‘’]))
# regex=(((https?://|mailto:|ftp://|file:|ssh:|ssh://|git://|tel:|magnet:|ipfs://|ipns://|gemini://|gopher://|news:)|www\.)([0-9a-zA-Z:/?#@!$&*+,;=.~_%^\-]+|\([]\["0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\)|\[[\(\)"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\]|"[]\[\(\)0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*"|'[]\[\(\)0-9a-zA-Z:/?#@!$&*+,;=.~_%^\-]*')+([0-9a-zA-Z/#@$&*+=~_%^\-]|\([]\["0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\)|\[[\(\)"0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*\]|"[]\[\(\)0-9a-zA-Z:/?#@!$&'*+,;=.~_%^\-]*"|'[]\[\(\)0-9a-zA-Z:/?#@!$&*+,;=.~_%^\-]*'))
# You can define your own regex's, by adding a section called
# 'regex:<ID>' with a 'regex' and 'launch' key. These can then be tied
@ -85,7 +87,6 @@
[cursor]
# style=block
# color=<inverse foreground/background>
# blink=no
# blink-rate=500
# beam-thickness=1.5
@ -100,11 +101,14 @@
[colors]
# alpha=1.0
# alpha-mode=default # Can be `default`, `matching` or `all`
# background=242424
# foreground=ffffff
# flash=7f7f00
# flash-alpha=0.5
# cursor=<inverse foreground/background>
## Normal/regular colors (color palette 0-7)
# regular0=242424 # black
# regular1=f62b5a # red
@ -162,6 +166,9 @@
# search-box-match=<regular0> <regular3> # black-on-yellow
# urls=<regular3>
[colors2]
# Alternative color theme, see man page foot.ini(5)
[csd]
# preferred=server
# size=26
@ -207,6 +214,9 @@
# prompt-prev=Control+Shift+z
# prompt-next=Control+Shift+x
# unicode-input=Control+Shift+u
# color-theme-switch-1=none
# color-theme-switch-2=none
# color-theme-toggle=none
# noop=none
# quit=none

137
input.c
View file

@ -40,6 +40,7 @@
#include "url-mode.h"
#include "util.h"
#include "vt.h"
#include "xkbcommon-vmod.h"
#include "xmalloc.h"
#include "xsnprintf.h"
@ -484,6 +485,63 @@ execute_binding(struct seat *seat, struct terminal *term,
return true;
case BIND_ACTION_THEME_SWITCH_1:
if (term->colors.active_theme != COLOR_THEME1) {
term_theme_apply(term, &term->conf->colors);
term->colors.active_theme = COLOR_THEME1;
wayl_win_alpha_changed(term->window);
term_font_subpixel_changed(term);
if (term->report_theme_changes)
term_to_slave(term, "\033[?997;1n", 9);
term_damage_view(term);
term_damage_margins(term);
render_refresh(term);
}
return true;
case BIND_ACTION_THEME_SWITCH_2:
if (term->colors.active_theme != COLOR_THEME2) {
term_theme_apply(term, &term->conf->colors2);
term->colors.active_theme = COLOR_THEME2;
wayl_win_alpha_changed(term->window);
term_font_subpixel_changed(term);
if (term->report_theme_changes)
term_to_slave(term, "\033[?997;2n", 9);
term_damage_view(term);
term_damage_margins(term);
render_refresh(term);
}
return true;
case BIND_ACTION_THEME_TOGGLE:
if (term->colors.active_theme == COLOR_THEME1) {
term_theme_apply(term, &term->conf->colors2);
term->colors.active_theme = COLOR_THEME2;
if (term->report_theme_changes)
term_to_slave(term, "\033[?997;2n", 9);
} else {
term_theme_apply(term, &term->conf->colors);
term->colors.active_theme = COLOR_THEME1;
if (term->report_theme_changes)
term_to_slave(term, "\033[?997;1n", 9);
}
wayl_win_alpha_changed(term->window);
term_font_subpixel_changed(term);
term_damage_view(term);
term_damage_margins(term);
render_refresh(term);
return true;
case BIND_ACTION_SELECT_BEGIN:
selection_start(
term, seat->mouse.col, seat->mouse.row, SELECTION_CHAR_WISE, false);
@ -765,9 +823,17 @@ keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
seat->kbd.alt = false;
seat->kbd.ctrl = false;
seat->kbd.super = false;
if (seat->kbd.xkb_compose_state != NULL)
xkb_compose_state_reset(seat->kbd.xkb_compose_state);
if (seat->kbd.xkb_state != NULL && seat->kbd.xkb_keymap != NULL) {
const xkb_layout_index_t layout_count = xkb_keymap_num_layouts(seat->kbd.xkb_keymap);
for (xkb_layout_index_t i = 0; i < layout_count; i++)
xkb_state_update_mask(seat->kbd.xkb_state, 0, 0, 0, i, i, i);
}
if (old_focused != NULL) {
seat->pointer.hidden = false;
term_xcursor_update_for_seat(old_focused, seat);
@ -2280,7 +2346,7 @@ is_top_left(const struct terminal *term, int x, int y)
{
int csd_border_size = term->conf->csd.border_width;
return (
(!term->window->is_tiled_top && !term->window->is_tiled_left) &&
(!term->window->is_constrained_top && !term->window->is_constrained_left) &&
((term->active_surface == TERM_SURF_BORDER_LEFT && y < 10 * term->scale) ||
(term->active_surface == TERM_SURF_BORDER_TOP && x < (10 + csd_border_size) * term->scale)));
}
@ -2290,7 +2356,7 @@ is_top_right(const struct terminal *term, int x, int y)
{
int csd_border_size = term->conf->csd.border_width;
return (
(!term->window->is_tiled_top && !term->window->is_tiled_right) &&
(!term->window->is_constrained_top && !term->window->is_constrained_right) &&
((term->active_surface == TERM_SURF_BORDER_RIGHT && y < 10 * term->scale) ||
(term->active_surface == TERM_SURF_BORDER_TOP && x > term->width + 1 * csd_border_size * term->scale - 10 * term->scale)));
}
@ -2301,7 +2367,7 @@ is_bottom_left(const struct terminal *term, int x, int y)
int csd_title_size = term->conf->csd.title_height;
int csd_border_size = term->conf->csd.border_width;
return (
(!term->window->is_tiled_bottom && !term->window->is_tiled_left) &&
(!term->window->is_constrained_bottom && !term->window->is_constrained_left) &&
((term->active_surface == TERM_SURF_BORDER_LEFT && y > csd_title_size * term->scale + term->height) ||
(term->active_surface == TERM_SURF_BORDER_BOTTOM && x < (10 + csd_border_size) * term->scale)));
}
@ -2312,7 +2378,7 @@ is_bottom_right(const struct terminal *term, int x, int y)
int csd_title_size = term->conf->csd.title_height;
int csd_border_size = term->conf->csd.border_width;
return (
(!term->window->is_tiled_bottom && !term->window->is_tiled_right) &&
(!term->window->is_constrained_bottom && !term->window->is_constrained_right) &&
((term->active_surface == TERM_SURF_BORDER_RIGHT && y > csd_title_size * term->scale + term->height) ||
(term->active_surface == TERM_SURF_BORDER_BOTTOM && x > term->width + 1 * csd_border_size * term->scale - 10 * term->scale)));
}
@ -2324,10 +2390,23 @@ xcursor_for_csd_border(struct terminal *term, int x, int y)
else if (is_top_right(term, x, y)) return CURSOR_SHAPE_TOP_RIGHT_CORNER;
else if (is_bottom_left(term, x, y)) return CURSOR_SHAPE_BOTTOM_LEFT_CORNER;
else if (is_bottom_right(term, x, y)) return CURSOR_SHAPE_BOTTOM_RIGHT_CORNER;
else if (term->active_surface == TERM_SURF_BORDER_LEFT) return CURSOR_SHAPE_LEFT_SIDE;
else if (term->active_surface == TERM_SURF_BORDER_RIGHT) return CURSOR_SHAPE_RIGHT_SIDE;
else if (term->active_surface == TERM_SURF_BORDER_TOP) return CURSOR_SHAPE_TOP_SIDE;
else if (term->active_surface == TERM_SURF_BORDER_BOTTOM) return CURSOR_SHAPE_BOTTOM_SIDE;
else if (term->active_surface == TERM_SURF_BORDER_LEFT)
return !term->window->is_constrained_left
? CURSOR_SHAPE_LEFT_SIDE : CURSOR_SHAPE_LEFT_PTR;
else if (term->active_surface == TERM_SURF_BORDER_RIGHT)
return !term->window->is_constrained_right
? CURSOR_SHAPE_RIGHT_SIDE : CURSOR_SHAPE_LEFT_PTR;
else if (term->active_surface == TERM_SURF_BORDER_TOP)
return !term->window->is_constrained_top
? CURSOR_SHAPE_TOP_SIDE : CURSOR_SHAPE_LEFT_PTR;
else if (term->active_surface == TERM_SURF_BORDER_BOTTOM)
return !term->window->is_constrained_bottom
? CURSOR_SHAPE_BOTTOM_SIDE : CURSOR_SHAPE_LEFT_PTR;
else {
BUG("Unreachable");
return CURSOR_SHAPE_NONE;
@ -3095,15 +3174,8 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
case TERM_SURF_BORDER_RIGHT:
case TERM_SURF_BORDER_TOP:
case TERM_SURF_BORDER_BOTTOM: {
static const enum xdg_toplevel_resize_edge map[] = {
[TERM_SURF_BORDER_LEFT] = XDG_TOPLEVEL_RESIZE_EDGE_LEFT,
[TERM_SURF_BORDER_RIGHT] = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT,
[TERM_SURF_BORDER_TOP] = XDG_TOPLEVEL_RESIZE_EDGE_TOP,
[TERM_SURF_BORDER_BOTTOM] = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM,
};
if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED) {
enum xdg_toplevel_resize_edge resize_type;
enum xdg_toplevel_resize_edge resize_type = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
int x = seat->mouse.x;
int y = seat->mouse.y;
@ -3116,11 +3188,36 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
else if (is_bottom_right(term, x, y))
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
else
resize_type = map[term->active_surface];
else {
if (term->active_surface == TERM_SURF_BORDER_LEFT &&
!term->window->is_constrained_left)
{
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
}
xdg_toplevel_resize(
term->window->xdg_toplevel, seat->wl_seat, serial, resize_type);
else if (term->active_surface == TERM_SURF_BORDER_RIGHT &&
!term->window->is_constrained_right)
{
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
}
else if (term->active_surface == TERM_SURF_BORDER_TOP &&
!term->window->is_constrained_top)
{
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
}
else if (term->active_surface == TERM_SURF_BORDER_BOTTOM &&
!term->window->is_constrained_bottom)
{
resize_type = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
}
}
if (resize_type != XDG_TOPLEVEL_RESIZE_EDGE_NONE) {
xdg_toplevel_resize(
term->window->xdg_toplevel, seat->wl_seat, serial, resize_type);
}
}
return;
}

View file

@ -11,6 +11,7 @@
#include "terminal.h"
#include "util.h"
#include "wayland.h"
#include "xkbcommon-vmod.h"
#include "xmalloc.h"
struct vmod_map {

View file

@ -43,6 +43,9 @@ enum bind_action_normal {
BIND_ACTION_QUIT,
BIND_ACTION_REGEX_LAUNCH,
BIND_ACTION_REGEX_COPY,
BIND_ACTION_THEME_SWITCH_1,
BIND_ACTION_THEME_SWITCH_2,
BIND_ACTION_THEME_TOGGLE,
/* Mouse specific actions - i.e. they require a mouse coordinate */
BIND_ACTION_SCROLLBACK_UP_MOUSE,
@ -56,7 +59,7 @@ enum bind_action_normal {
BIND_ACTION_SELECT_QUOTE,
BIND_ACTION_SELECT_ROW,
BIND_ACTION_KEY_COUNT = BIND_ACTION_REGEX_COPY + 1,
BIND_ACTION_KEY_COUNT = BIND_ACTION_THEME_TOGGLE + 1,
BIND_ACTION_COUNT = BIND_ACTION_SELECT_ROW + 1,
};

View file

@ -1,5 +1,5 @@
project('foot', 'c',
version: '1.21.0',
version: '1.22.3',
license: 'MIT',
meson_version: '>=0.59.0',
default_options: [
@ -145,6 +145,10 @@ if utf8proc.found()
add_project_arguments('-DFOOT_GRAPHEME_CLUSTERING=1', language: 'c')
endif
if pixman.version().version_compare('>=0.46.0')
add_project_arguments('-DHAVE_PIXMAN_RGBA_16', language: 'c')
endif
tllist = dependency('tllist', version: '>=1.1.0', fallback: 'tllist')
fcft = dependency('fcft', version: ['>=3.3.1', '<4.0.0'], fallback: 'fcft')
@ -253,7 +257,7 @@ vtlib = static_library(
'osc.c', 'osc.h',
'sixel.c', 'sixel.h',
'vt.c', 'vt.h',
builtin_terminfo, emoji_variation_sequences, srgb_funcs,
builtin_terminfo, srgb_funcs,
wl_proto_src + wl_proto_headers,
version,
dependencies: [libepoll, pixman, fcft, tllist, wayland_client, xkb, utf8proc],
@ -268,6 +272,7 @@ pgolib = static_library(
'config.c', 'config.h',
'user-notification.c', 'user-notification.h',
'tokenize.c', 'tokenize.h',
emoji_variation_sequences,
wl_proto_src + wl_proto_headers,
dependencies: [libepoll, pixman, fcft, tllist, wayland_client, xkb, utf8proc],
link_with: vtlib,
@ -317,6 +322,7 @@ executable(
'url-mode.c', 'url-mode.h',
'user-notification.c', 'user-notification.h',
'wayland.c', 'wayland.h', 'shm-formats.h',
'xkbcommon-vmod.h',
srgb_funcs, wl_proto_src + wl_proto_headers, version,
dependencies: [math, threads, libepoll, pixman, wayland_client, wayland_cursor, xkb, fontconfig, utf8proc,
tllist, fcft],

35
osc.c
View file

@ -1455,15 +1455,20 @@ osc_dispatch(struct terminal *term)
case 11:
term->colors.bg = color;
if (have_alpha) {
const bool changed = term->colors.alpha != alpha;
term->colors.alpha = alpha;
if (changed) {
wayl_win_alpha_changed(term->window);
term_font_subpixel_changed(term);
}
if (!have_alpha) {
alpha = term->colors.active_theme == COLOR_THEME1
? term->conf->colors.alpha
: term->conf->colors2.alpha;
}
const bool changed = term->colors.alpha != alpha;
term->colors.alpha = alpha;
if (changed) {
wayl_win_alpha_changed(term->window);
term_font_subpixel_changed(term);
}
term_damage_color(term, COLOR_DEFAULT, 0);
term_damage_margins(term);
break;
@ -1475,12 +1480,10 @@ osc_dispatch(struct terminal *term)
case 17:
term->colors.selection_bg = color;
term->colors.use_custom_selection = true;
break;
case 19:
term->colors.selection_fg = color;
term->colors.use_custom_selection = true;
break;
}
@ -1570,21 +1573,25 @@ osc_dispatch(struct terminal *term)
case 112:
LOG_DBG("resetting cursor color");
term->colors.cursor_fg = term->conf->cursor.color.text;
term->colors.cursor_bg = term->conf->cursor.color.cursor;
term->colors.cursor_fg = term->conf->colors.cursor.text;
term->colors.cursor_bg = term->conf->colors.cursor.cursor;
if (term->conf->colors.use_custom.cursor) {
term->colors.cursor_fg |= 1u << 31;
term->colors.cursor_bg |= 1u << 31;
}
term_damage_cursor(term);
break;
case 117:
LOG_DBG("resetting selection background color");
term->colors.selection_bg = term->conf->colors.selection_bg;
term->colors.use_custom_selection = term->conf->colors.use_custom.selection;
break;
case 119:
LOG_DBG("resetting selection foreground color");
term->colors.selection_fg = term->conf->colors.selection_fg;
term->colors.use_custom_selection = term->conf->colors.use_custom.selection;
break;
case 133:

View file

@ -129,7 +129,7 @@ render_worker_thread(void *_ctx)
}
bool
render_do_linear_blending(const struct terminal *term)
wayl_do_linear_blending(const struct wayland *wayl, const struct config *conf)
{
return false;
}
@ -201,11 +201,12 @@ void urls_reset(struct terminal *term) {}
void shm_unref(struct buffer *buf) {}
void shm_chain_free(struct buffer_chain *chain) {}
enum shm_bit_depth shm_chain_bit_depth(const struct buffer_chain *chain) { return SHM_BITS_8; }
struct buffer_chain *
shm_chain_new(
struct wayland *wayl, bool scrollable, size_t pix_instances,
bool ten_bit_it_if_capable)
enum shm_bit_depth desired_bit_depth)
{
return NULL;
}

294
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 &&
@ -631,7 +626,7 @@ draw_cursor(const struct terminal *term, const struct cell *cell,
pixman_color_t cursor_color;
pixman_color_t text_color;
cursor_colors_for_cell(term, cell, fg, bg, &cursor_color, &text_color,
render_do_linear_blending(term));
wayl_do_linear_blending(term->wl, term->conf));
if (unlikely(!term->kbd_focus)) {
switch (term->conf->cursor.unfocused_style) {
@ -699,101 +694,140 @@ render_cell(struct terminal *term, pixman_image_t *pix,
const int x = term->margins.left + col * width;
const int y = term->margins.top + row_no * height;
bool is_selected = cell->attrs.selected;
uint32_t _fg = 0;
uint32_t _bg = 0;
uint16_t alpha = 0xffff;
const bool is_selected = cell->attrs.selected;
/* Use cell specific color, if set, otherwise the default colors (possible reversed) */
switch (cell->attrs.fg_src) {
case COLOR_RGB:
_fg = cell->attrs.fg;
break;
case COLOR_BASE16:
case COLOR_BASE256:
xassert(cell->attrs.fg < ALEN(term->colors.table));
_fg = term->colors.table[cell->attrs.fg];
break;
case COLOR_DEFAULT:
_fg = term->reverse ? term->colors.bg : term->colors.fg;
break;
}
switch (cell->attrs.bg_src) {
case COLOR_RGB:
_bg = cell->attrs.bg;
break;
case COLOR_BASE16:
case COLOR_BASE256:
xassert(cell->attrs.bg < ALEN(term->colors.table));
_bg = term->colors.table[cell->attrs.bg];
break;
case COLOR_DEFAULT:
_bg = term->reverse ? term->colors.fg : term->colors.bg;
break;
}
if (unlikely(is_selected)) {
const uint32_t cell_fg = _fg;
const uint32_t cell_bg = _bg;
const bool custom_fg = term->colors.selection_fg >> 24 == 0;
const bool custom_bg = term->colors.selection_bg >> 24 == 0;
const bool custom_both = custom_fg && custom_bg;
if (custom_both) {
_fg = term->colors.selection_fg;
_bg = term->colors.selection_bg;
} else if (custom_bg) {
_bg = term->colors.selection_bg;
_fg = cell->attrs.reverse ? cell_bg : cell_fg;
} else if (custom_fg) {
_fg = term->colors.selection_fg;
_bg = cell->attrs.reverse ? cell_fg : cell_bg;
} else {
_bg = cell_fg;
_fg = cell_bg;
}
if (unlikely(_fg == _bg)) {
/* Invert bg when selected/highlighted text has same fg/bg */
_bg = ~_bg;
alpha = 0xffff;
}
if (is_selected && term->colors.use_custom_selection) {
_fg = term->colors.selection_fg;
_bg = term->colors.selection_bg;
} else {
/* Use cell specific color, if set, otherwise the default colors (possible reversed) */
switch (cell->attrs.fg_src) {
case COLOR_RGB:
_fg = cell->attrs.fg;
break;
case COLOR_BASE16:
case COLOR_BASE256:
xassert(cell->attrs.fg < ALEN(term->colors.table));
_fg = term->colors.table[cell->attrs.fg];
break;
case COLOR_DEFAULT:
_fg = term->reverse ? term->colors.bg : term->colors.fg;
break;
}
switch (cell->attrs.bg_src) {
case COLOR_RGB:
_bg = cell->attrs.bg;
break;
case COLOR_BASE16:
case COLOR_BASE256:
xassert(cell->attrs.bg < ALEN(term->colors.table));
_bg = term->colors.table[cell->attrs.bg];
break;
case COLOR_DEFAULT:
_bg = term->reverse ? term->colors.fg : term->colors.bg;
break;
}
if (cell->attrs.reverse ^ is_selected) {
if (unlikely(cell->attrs.reverse)) {
uint32_t swap = _fg;
_fg = _bg;
_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;
else 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;
}
}
}
if (unlikely(is_selected && _fg == _bg)) {
/* Invert bg when selected/highlighted text has same fg/bg */
_bg = ~_bg;
alpha = 0xffff;
case ALPHA_MODE_MATCHING: {
if (cell->attrs.bg_src == COLOR_DEFAULT ||
((cell->attrs.bg_src == COLOR_BASE16 ||
cell->attrs.bg_src == COLOR_BASE256) &&
term->colors.table[cell->attrs.bg] == term->colors.bg) ||
(cell->attrs.bg_src == COLOR_RGB &&
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);
}
}
if (cell->attrs.dim)
@ -804,7 +838,7 @@ render_cell(struct terminal *term, pixman_image_t *pix,
if (cell->attrs.blink && term->blink.state == BLINK_OFF)
_fg = color_blend_towards(_fg, 0x00000000, term->conf->dim.amount);
const bool gamma_correct = render_do_linear_blending(term);
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
pixman_color_t fg = color_hex_to_pixman(_fg, gamma_correct);
pixman_color_t bg = color_hex_to_pixman_with_alpha(_bg, alpha, gamma_correct);
@ -991,8 +1025,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))
@ -1140,8 +1176,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;
@ -1160,7 +1198,8 @@ static void
render_urgency(struct terminal *term, struct buffer *buf)
{
uint32_t red = term->colors.table[1];
pixman_color_t bg = color_hex_to_pixman(red, render_do_linear_blending(term));
pixman_color_t bg = color_hex_to_pixman(
red, wayl_do_linear_blending(term->wl, term->conf));
int width = min(min(term->margins.left, term->margins.right),
min(term->margins.top, term->margins.bottom));
@ -1191,7 +1230,7 @@ render_margin(struct terminal *term, struct buffer *buf,
const int bmargin = term->height - term->margins.bottom;
const int line_count = end_line - start_line;
const bool gamma_correct = render_do_linear_blending(term);
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
const uint32_t _bg = !term->reverse ? term->colors.bg : term->colors.fg;
uint16_t alpha = term->colors.alpha;
@ -1679,7 +1718,7 @@ render_ime_preedit_for_seat(struct terminal *term, struct seat *seat,
if (unlikely(term->is_searching))
return;
const bool gamma_correct = render_do_linear_blending(term);
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
/* Adjust cursor position to viewport */
struct coord cursor;
@ -1950,7 +1989,8 @@ render_overlay(struct terminal *term)
case OVERLAY_FLASH:
color = color_hex_to_pixman_with_alpha(
term->conf->colors.flash,
term->conf->colors.flash_alpha, render_do_linear_blending(term));
term->conf->colors.flash_alpha,
wayl_do_linear_blending(term->wl, term->conf));
break;
case OVERLAY_NONE:
@ -2214,16 +2254,21 @@ get_csd_data(const struct terminal *term, enum csd_surface surf_idx)
const int button_width = title_visible
? roundf(term->conf->csd.button_width * scale) : 0;
const int button_close_width = term->width >= 1 * button_width
? button_width : 0;
int remaining_width = term->width;
const int button_maximize_width =
term->width >= 2 * button_width && term->window->wm_capabilities.maximize
? button_width : 0;
const int button_close_width = remaining_width >= button_width ? button_width : 0;
remaining_width -= button_close_width;
const int button_close_start = remaining_width;
const int button_minimize_width =
term->width >= 3 * button_width && term->window->wm_capabilities.minimize
? button_width : 0;
const int button_maximize_width = remaining_width >= button_width &&
term->window->wm_capabilities.maximize ? button_width : 0;
remaining_width -= button_maximize_width;
const int button_maximize_start = remaining_width;
const int button_minimize_width = remaining_width >= button_width &&
term->window->wm_capabilities.minimize ? button_width : 0;
remaining_width -= button_minimize_width;
const int button_minimize_start = remaining_width;
/*
* With fractional scaling, we must ensure the offset, when
@ -2248,9 +2293,9 @@ get_csd_data(const struct terminal *term, enum csd_surface surf_idx)
case CSD_SURF_BOTTOM: return (struct csd_data){-border_width, term->height, top_bottom_width, border_width};
/* Positioned relative to CSD_SURF_TITLE */
case CSD_SURF_MINIMIZE: return (struct csd_data){term->width - 3 * button_width, 0, button_minimize_width, title_height};
case CSD_SURF_MAXIMIZE: return (struct csd_data){term->width - 2 * button_width, 0, button_maximize_width, title_height};
case CSD_SURF_CLOSE: return (struct csd_data){term->width - 1 * button_width, 0, button_close_width, title_height};
case CSD_SURF_MINIMIZE: return (struct csd_data){button_minimize_start, 0, button_minimize_width, title_height};
case CSD_SURF_MAXIMIZE: return (struct csd_data){button_maximize_start, 0, button_maximize_width, title_height};
case CSD_SURF_CLOSE: return (struct csd_data){ button_close_start, 0, button_close_width, title_height};
case CSD_SURF_COUNT:
break;
@ -2292,7 +2337,7 @@ render_osd(struct terminal *term, const struct wayl_sub_surface *sub_surf,
pixman_image_set_clip_region32(buf->pix[0], &clip);
pixman_region32_fini(&clip);
const bool gamma_correct = render_do_linear_blending(term);
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
uint16_t alpha = _bg >> 24 | (_bg >> 24 << 8);
pixman_color_t bg = color_hex_to_pixman_with_alpha(_bg, alpha, gamma_correct);
pixman_image_fill_rectangles(
@ -2433,7 +2478,7 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx,
if (info->width == 0 || info->height == 0)
return;
const bool gamma_correct = render_do_linear_blending(term);
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
{
/* Fully transparent - no need to do a color space transform */
@ -2522,7 +2567,7 @@ get_csd_button_fg_color(const struct terminal *term)
}
return color_hex_to_pixman_with_alpha(
_color, alpha, render_do_linear_blending(term));
_color, alpha, wayl_do_linear_blending(term->wl, term->conf));
}
static void
@ -2799,7 +2844,7 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx,
if (!term->visual_focus)
_color = color_dim(term, _color);
const bool gamma_correct = render_do_linear_blending(term);
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
pixman_color_t color = color_hex_to_pixman_with_alpha(_color, alpha, gamma_correct);
render_csd_part(term, surf->surf, buf, info->width, info->height, &color);
@ -3658,7 +3703,7 @@ render_search_box(struct terminal *term)
: term->conf->colors.use_custom.search_box_no_match;
/* Background - yellow on empty/match, red on mismatch (default) */
const bool gamma_correct = render_do_linear_blending(term);
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
const pixman_color_t color = color_hex_to_pixman(
is_match
? (custom_colors
@ -4551,9 +4596,12 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts)
const int total_x_pad = term->width - grid_width;
const int total_y_pad = term->height - grid_height;
const bool centered_padding = term->conf->center
|| term->window->is_fullscreen
|| term->window->is_maximized;
const enum center_when center = term->conf->center_when;
const bool centered_padding =
center == CENTER_ALWAYS ||
(center == CENTER_MAXIMIZED_AND_FULLSCREEN &&
(term->window->is_fullscreen || term->window->is_maximized)) ||
(center == CENTER_FULLSCREEN && term->window->is_fullscreen);
if (centered_padding && !term->window->is_resizing) {
term->margins.left = total_x_pad / 2;
@ -4884,8 +4932,9 @@ render_xcursor_update(struct seat *seat)
const enum wp_cursor_shape_device_v1_shape custom_shape =
(shape == CURSOR_SHAPE_CUSTOM && xcursor != NULL
? cursor_string_to_server_shape(xcursor)
: 0);
? cursor_string_to_server_shape(
xcursor, seat->wayl->shape_manager_version)
: 0);
if (shape != CURSOR_SHAPE_CUSTOM || custom_shape != 0) {
xassert(custom_shape == 0 || shape == CURSOR_SHAPE_CUSTOM);
@ -5227,10 +5276,3 @@ render_xcursor_set(struct seat *seat, struct terminal *term,
seat->pointer.xcursor_pending = true;
return true;
}
bool
render_do_linear_blending(const struct terminal *term)
{
return term->conf->gamma_correct != GAMMA_CORRECT_DISABLED &&
term->wl->color_management.img_description != NULL;
}

View file

@ -47,5 +47,3 @@ struct csd_data {
};
struct csd_data get_csd_data(const struct terminal *term, enum csd_surface surf_idx);
bool render_do_linear_blending(const struct terminal *term);

View file

@ -5,21 +5,16 @@ import math
import sys
# Note: we use a pure gamma 2.2 function, rather than the piece-wise
# sRGB transfer function, since that is what all compositors do.
def srgb_to_linear(f: float) -> float:
assert(f >= 0 and f <= 1.0)
if f <= 0.04045:
return f / 12.92
return math.pow((f + 0.055) / 1.055, 2.4)
return math.pow(f, 2.2)
def linear_to_srgb(f: float) -> float:
if f < 0.0031308:
return f * 12.92
return 1.055 * math.pow(f, 1 / 2.4) - 0.055
return math.pow(f, 1 / 2.2)
def main():
@ -29,24 +24,10 @@ def main():
opts = parser.parse_args()
linear_table: list[int] = []
srgb_table: list[int] = []
for i in range(256):
linear_table.append(int(srgb_to_linear(float(i) / 255) * 65535 + 0.5))
for i in range(4096):
srgb_table.append(int(linear_to_srgb(float(i) / 4095) * 255 + 0.5))
for i in range(256):
while True:
linear = linear_table[i]
srgb = srgb_table[linear >> 4]
if i == srgb:
break
linear_table[i] += 1
opts.h_output.write("#pragma once\n")
opts.h_output.write("#include <stdint.h>\n")

58
shm.c
View file

@ -338,7 +338,10 @@ get_new_buffers(struct buffer_chain *chain, size_t count,
size_t total_size = 0;
for (size_t i = 0; i < count; i++) {
stride[i] = stride_for_format_and_width(
with_alpha ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8, widths[i]);
with_alpha
? chain->pixman_fmt_with_alpha
: chain->pixman_fmt_without_alpha,
widths[i]);
sizes[i] = stride[i] * heights[i];
total_size += sizes[i];
}
@ -972,7 +975,7 @@ shm_unref(struct buffer *_buf)
struct buffer_chain *
shm_chain_new(struct wayland *wayl, bool scrollable, size_t pix_instances,
bool ten_bit_if_capable)
enum shm_bit_depth desired_bit_depth)
{
pixman_format_code_t pixman_fmt_without_alpha = PIXMAN_x8r8g8b8;
enum wl_shm_format shm_fmt_without_alpha = WL_SHM_FORMAT_XRGB8888;
@ -981,9 +984,38 @@ shm_chain_new(struct wayland *wayl, bool scrollable, size_t pix_instances,
enum wl_shm_format shm_fmt_with_alpha = WL_SHM_FORMAT_ARGB8888;
static bool have_logged = false;
static bool have_logged_10_fallback = false;
#if defined(HAVE_PIXMAN_RGBA_16)
static bool have_logged_16_fallback = false;
if (ten_bit_if_capable) {
if (desired_bit_depth == SHM_BITS_16) {
if (wayl->shm_have_abgr161616 && wayl->shm_have_xbgr161616) {
pixman_fmt_without_alpha = PIXMAN_a16b16g16r16;
shm_fmt_without_alpha = WL_SHM_FORMAT_XBGR16161616;
pixman_fmt_without_alpha = PIXMAN_a16b16g16r16;
shm_fmt_with_alpha = WL_SHM_FORMAT_ABGR16161616;
if (!have_logged) {
have_logged = true;
LOG_INFO("using 16-bit BGR surfaces");
}
} else {
if (!have_logged_16_fallback) {
have_logged_16_fallback = true;
LOG_WARN(
"16-bit surfaces requested, but compositor does not "
"implement ABGR161616+XBGR161616");
}
}
}
#endif
if (desired_bit_depth >= SHM_BITS_10 &&
pixman_fmt_with_alpha == PIXMAN_a8r8g8b8)
{
if (wayl->shm_have_argb2101010 && wayl->shm_have_xrgb2101010) {
pixman_fmt_without_alpha = PIXMAN_x2r10g10b10;
shm_fmt_without_alpha = WL_SHM_FORMAT_XRGB2101010;
@ -1011,13 +1043,13 @@ shm_chain_new(struct wayland *wayl, bool scrollable, size_t pix_instances,
}
else {
if (!have_logged) {
have_logged = true;
if (!have_logged_10_fallback) {
have_logged_10_fallback = true;
LOG_WARN(
"10-bit surfaces requested, but compositor does not "
"implement ARGB2101010+XRGB2101010, or "
"ABGR2101010+XBGR2101010. Falling back to 8-bit surfaces");
"ABGR2101010+XBGR2101010");
}
}
} else {
@ -1058,3 +1090,17 @@ shm_chain_free(struct buffer_chain *chain)
free(chain);
}
enum shm_bit_depth
shm_chain_bit_depth(const struct buffer_chain *chain)
{
const pixman_format_code_t fmt = chain->pixman_fmt_with_alpha;
return fmt == PIXMAN_a8r8g8b8
? SHM_BITS_8
#if defined(HAVE_PIXMAN_RGBA_16)
: fmt == PIXMAN_a16b16g16r16
? SHM_BITS_16
#endif
: SHM_BITS_10;
}

5
shm.h
View file

@ -9,6 +9,7 @@
#include <tllist.h>
#include "config.h"
#include "wayland.h"
struct damage;
@ -46,9 +47,11 @@ void shm_set_max_pool_size(off_t max_pool_size);
struct buffer_chain;
struct buffer_chain *shm_chain_new(
struct wayland *wayl, bool scrollable, size_t pix_instances,
bool ten_bit_it_if_capable);
enum shm_bit_depth desired_bit_depth);
void shm_chain_free(struct buffer_chain *chain);
enum shm_bit_depth shm_chain_bit_depth(const struct buffer_chain *chain);
/*
* Returns a single buffer.
*

15
sixel.c
View file

@ -110,10 +110,21 @@ sixel_init(struct terminal *term, int p1, int p2, int p3)
term->sixel.image.height = 0;
term->sixel.image.alloc_height = 0;
term->sixel.image.bottom_pixel = 0;
term->sixel.linear_blending = render_do_linear_blending(term);
term->sixel.linear_blending = wayl_do_linear_blending(term->wl, term->conf);
term->sixel.pixman_fmt = PIXMAN_a8r8g8b8;
if (term->conf->tweak.surface_bit_depth == SHM_10_BIT) {
/*
* Use higher-precision sixel surfaces if we're using
* higher-precision window surfaces.
*
* This is to a) get more accurate colors when doing gamma-correct
* blending, and b) use the same pixman format as the main
* surfaces, for (hopefully) better performance.
*
* For now, don't support 16-bit surfaces (too much sixel logic
* that assumes 32-bit pixels).
*/
if (shm_chain_bit_depth(term->render.chains.grid) >= SHM_BITS_10) {
if (term->wl->shm_have_argb2101010 && term->wl->shm_have_xrgb2101010) {
term->sixel.use_10bit = true;
term->sixel.pixman_fmt = PIXMAN_a2r10g10b10;

View file

@ -1073,19 +1073,20 @@ reload_fonts(struct terminal *term, bool resize_grid)
options->scaling_filter = conf->tweak.fcft_filter;
options->color_glyphs.format = PIXMAN_a8r8g8b8;
options->color_glyphs.srgb_decode = render_do_linear_blending(term);
options->color_glyphs.srgb_decode =
wayl_do_linear_blending(term->wl, term->conf);
if (conf->tweak.surface_bit_depth == SHM_10_BIT) {
if ((term->wl->shm_have_argb2101010 && term->wl->shm_have_xrgb2101010) ||
(term->wl->shm_have_abgr2101010 && term->wl->shm_have_xbgr2101010))
{
/*
* Use a high-res buffer type for emojis. We don't want to
* use an a2r10g0b10 type of surface, since we need more
* than 2 bits for alpha.
*/
options->color_glyphs.format = PIXMAN_rgba_float;
}
if (shm_chain_bit_depth(term->render.chains.grid) >= SHM_BITS_10) {
/*
* Use a high-res buffer type for emojis. We don't want to use
* an a2r10g0b10 type of surface, since we need more than 2
* bits for alpha.
*/
#if defined(HAVE_PIXMAN_RGBA_16)
options->color_glyphs.format = PIXMAN_a16b16g16r16;
#else
options->color_glyphs.format = PIXMAN_rgba_float;
#endif
}
struct fcft_font *fonts[4];
@ -1260,7 +1261,16 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
goto err;
}
const bool ten_bit_surfaces = conf->tweak.surface_bit_depth == SHM_10_BIT;
const enum shm_bit_depth desired_bit_depth =
conf->tweak.surface_bit_depth == SHM_BITS_AUTO
? wayl_do_linear_blending(wayl, conf) ? SHM_BITS_16 : SHM_BITS_8
: conf->tweak.surface_bit_depth;
const struct color_theme *theme = NULL;
switch (conf->initial_color_theme) {
case COLOR_THEME1: theme = &conf->colors; break;
case COLOR_THEME2: theme = &conf->colors2; break;
}
/* Initialize configure-based terminal attributes */
*term = (struct terminal) {
@ -1279,7 +1289,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
},
.font_dpi = 0.,
.font_dpi_before_unmap = -1.,
.font_subpixel = (conf->colors.alpha == 0xffff /* Can't do subpixel rendering on transparent background */
.font_subpixel = (theme->alpha == 0xffff /* Can't do subpixel rendering on transparent background */
? FCFT_SUBPIXEL_DEFAULT
: FCFT_SUBPIXEL_NONE),
.cursor_keys_mode = CURSOR_KEYS_NORMAL,
@ -1295,14 +1305,14 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
.state = 0, /* STATE_GROUND */
},
.colors = {
.fg = conf->colors.fg,
.bg = conf->colors.bg,
.alpha = conf->colors.alpha,
.cursor_fg = conf->cursor.color.text,
.cursor_bg = conf->cursor.color.cursor,
.selection_fg = conf->colors.selection_fg,
.selection_bg = conf->colors.selection_bg,
.use_custom_selection = conf->colors.use_custom.selection,
.fg = theme->fg,
.bg = theme->bg,
.alpha = theme->alpha,
.cursor_fg = (theme->use_custom.cursor ? 1u << 31 : 0) | theme->cursor.text,
.cursor_bg = (theme->use_custom.cursor ? 1u << 31 : 0) | theme->cursor.cursor,
.selection_fg = theme->selection_fg,
.selection_bg = theme->selection_bg,
.active_theme = conf->initial_color_theme,
},
.color_stack = {
.stack = NULL,
@ -1346,13 +1356,13 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
.render = {
.chains = {
.grid = shm_chain_new(wayl, true, 1 + conf->render_worker_count,
ten_bit_surfaces),
.search = shm_chain_new(wayl, false, 1 ,ten_bit_surfaces),
.scrollback_indicator = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
.render_timer = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
.url = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
.csd = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
.overlay = shm_chain_new(wayl, false, 1, ten_bit_surfaces),
desired_bit_depth),
.search = shm_chain_new(wayl, false, 1 ,desired_bit_depth),
.scrollback_indicator = shm_chain_new(wayl, false, 1, desired_bit_depth),
.render_timer = shm_chain_new(wayl, false, 1, desired_bit_depth),
.url = shm_chain_new(wayl, false, 1, desired_bit_depth),
.csd = shm_chain_new(wayl, false, 1, desired_bit_depth),
.overlay = shm_chain_new(wayl, false, 1, desired_bit_depth),
},
.scrollback_lines = conf->scrollback.lines,
.app_sync_updates.timer_fd = app_sync_updates_fd,
@ -1433,7 +1443,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
xassert(tll_length(term->wl->monitors) > 0);
term->scale = tll_front(term->wl->monitors).scale;
memcpy(term->colors.table, term->conf->colors.table, sizeof(term->colors.table));
memcpy(term->colors.table, theme->table, sizeof(term->colors.table));
/* Initialize the Wayland window backend */
if ((term->window = wayl_win_init(term, token)) == NULL)
@ -1495,7 +1505,7 @@ term_window_configured(struct terminal *term)
xassert(term->window->is_configured);
fdm_add(term->fdm, term->ptmx, EPOLLIN, &fdm_ptmx, term);
const bool gamma_correct = render_do_linear_blending(term);
const bool gamma_correct = wayl_do_linear_blending(term->wl, term->conf);
LOG_INFO("gamma-correct blending: %s", gamma_correct ? "enabled" : "disabled");
}
}
@ -2147,19 +2157,18 @@ term_reset(struct terminal *term, bool hard)
if (!hard)
return;
const struct color_theme *theme = NULL;
switch (term->conf->initial_color_theme) {
case COLOR_THEME1: theme = &term->conf->colors; break;
case COLOR_THEME2: theme = &term->conf->colors2; break;
}
term->flash.active = false;
term->blink.state = BLINK_ON;
fdm_del(term->fdm, term->blink.fd); term->blink.fd = -1;
term->colors.fg = term->conf->colors.fg;
term->colors.bg = term->conf->colors.bg;
term->colors.alpha = term->conf->colors.alpha;
term->colors.cursor_fg = term->conf->cursor.color.text;
term->colors.cursor_bg = term->conf->cursor.color.cursor;
term->colors.selection_fg = term->conf->colors.selection_fg;
term->colors.selection_bg = term->conf->colors.selection_bg;
term->colors.use_custom_selection = term->conf->colors.use_custom.selection;
memcpy(term->colors.table, term->conf->colors.table,
sizeof(term->colors.table));
term_theme_apply(term, theme);
term->colors.active_theme = term->conf->initial_color_theme;
free(term->color_stack.stack);
term->color_stack.stack = NULL;
term->color_stack.size = 0;
@ -2760,13 +2769,11 @@ UNITTEST
},
.kind = SELECTION_NONE,
.auto_scroll = {
.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK),
.fd = -1,
},
},
};
xassert(term.selection.auto_scroll.fd >= 0);
#define populate_scrollback() do { \
for (int i = 0; i < scrollback_rows; i++) { \
if (term.normal.rows[i] == NULL) { \
@ -2856,7 +2863,7 @@ UNITTEST
/* Cleanup */
tll_free(term.normal.sixel_images);
close(term.selection.auto_scroll.fd);
xassert(term.selection.auto_scroll.fd == -1);
for (int i = 0; i < scrollback_rows; i++)
grid_row_free(term.normal.rows[i]);
free(term.normal.rows);
@ -3564,7 +3571,9 @@ term_xcursor_update_for_seat(struct terminal *term, struct seat *seat)
if (seat->pointer.hidden)
shape = CURSOR_SHAPE_HIDDEN;
else if (cursor_string_to_server_shape(term->mouse_user_cursor) != 0 ||
else if (cursor_string_to_server_shape(
term->mouse_user_cursor,
term->wl->shape_manager_version) != 0 ||
render_xcursor_is_valid(seat, term->mouse_user_cursor))
{
shape = CURSOR_SHAPE_CUSTOM;
@ -4188,7 +4197,7 @@ term_process_and_print_non_ascii(struct terminal *term, char32_t wc)
if (grapheme_clustering) {
/* Check if we're on a grapheme cluster break */
if (utf8proc_grapheme_break_stateful(
last, wc, &term->vt.grapheme_state) && width > 0)
last, wc, &term->vt.grapheme_state))
{
term_reset_grapheme_state(term);
goto out;
@ -4694,28 +4703,33 @@ term_send_size_notification(struct terminal *term)
term_to_slave(term, buf, n);
}
void
term_theme_apply(struct terminal *term, const struct color_theme *theme)
{
term->colors.fg = theme->fg;
term->colors.bg = theme->bg;
term->colors.alpha = theme->alpha;
term->colors.cursor_fg = (theme->use_custom.cursor ? 1u << 31 : 0) | theme->cursor.text;
term->colors.cursor_bg = (theme->use_custom.cursor ? 1u << 31 : 0) | theme->cursor.cursor;
term->colors.selection_fg = theme->selection_fg;
term->colors.selection_bg = theme->selection_bg;
memcpy(term->colors.table, theme->table, sizeof(term->colors.table));
}
/* Reload configured colors from disk. */
void
term_hard_reload_config_colors(struct terminal *term) {
term_reload_config_colors(struct terminal *term) {
config_reload_colors((struct config *)term->conf);
term_soft_reload_config_colors(term);
}
if (term->colors.active_theme == COLOR_THEME1) {
term_theme_apply(term, &term->conf->colors);
} else {
term_theme_apply(term, &term->conf->colors2);
}
/* Reset colors to the in-memory config values. Does not reload the config from
disk. */
void
term_soft_reload_config_colors(struct terminal *term) {
term->colors.fg = term->conf->colors.fg;
term->colors.bg = term->conf->colors.bg;
term->colors.alpha = term->conf->colors.alpha;
term->colors.cursor_fg = term->conf->cursor.color.text;
term->colors.cursor_bg = term->conf->cursor.color.cursor;
term->colors.selection_fg = term->conf->colors.selection_fg;
term->colors.selection_bg = term->conf->colors.selection_bg;
wayl_win_alpha_changed(term->window);
term_font_subpixel_changed(term);
memcpy(term->colors.table, term->conf->colors.table, sizeof(term->colors.table));
term_damage_all(term);
term_damage_view(term);
term_damage_margins(term);
render_refresh(term);
}

View file

@ -404,7 +404,7 @@ struct colors {
uint32_t cursor_bg; /* cursor color */
uint32_t selection_fg;
uint32_t selection_bg;
bool use_custom_selection;
enum which_color_theme active_theme;
};
struct terminal {
@ -517,6 +517,7 @@ struct terminal {
bool num_lock_modifier;
bool bell_action_enabled;
bool report_theme_changes;
/* Saved DECSET modes - we save the SET state */
struct {
@ -547,6 +548,7 @@ struct terminal {
bool ime:1;
bool app_sync_updates:1;
bool grapheme_shaping:1;
bool report_theme_changes:1;
bool size_notifications:1;
@ -982,8 +984,8 @@ void term_enable_size_notifications(struct terminal *term);
void term_disable_size_notifications(struct terminal *term);
void term_send_size_notification(struct terminal *term);
void term_hard_reload_config_colors(struct terminal *term);
void term_soft_reload_config_colors(struct terminal *term);
void term_theme_apply(struct terminal *term, const struct color_theme *theme);
void term_reload_config_colors(struct terminal *term);
static inline void term_reset_grapheme_state(struct terminal *term)
{

View file

@ -399,6 +399,16 @@ test_color(struct context *ctx, bool (*parse_fun)(struct context *ctx),
BUG("[%s].%s=%s: failed to parse",
ctx->section, ctx->key, ctx->value);
}
uint32_t color = input[i].color;
if (alpha_allowed && strlen(input[i].option_string) == 6)
color |= 0xff000000;
if (*ptr != color) {
BUG("[%s].%s=%s: expected 0x%08x, got 0x%08x",
ctx->section, ctx->key, ctx->value,
color, *ptr);
}
}
}
}
@ -445,6 +455,18 @@ test_two_colors(struct context *ctx, bool (*parse_fun)(struct context *ctx),
BUG("[%s].%s=%s: failed to parse",
ctx->section, ctx->key, ctx->value);
}
if (*ptr1 != input[i].color1) {
BUG("[%s].%s=%s: expected 0x%08x, got 0x%08x",
ctx->section, ctx->key, ctx->value,
input[i].color1, *ptr1);
}
if (*ptr2 != input[i].color2) {
BUG("[%s].%s=%s: expected 0x%08x, got 0x%08x",
ctx->section, ctx->key, ctx->value,
input[i].color2, *ptr2);
}
}
}
}
@ -468,6 +490,7 @@ test_section_main(void)
test_boolean(&ctx, &parse_section_main, "box-drawings-uses-font-glyphs", &conf.box_drawings_uses_font_glyphs);
test_boolean(&ctx, &parse_section_main, "locked-title", &conf.locked_title);
test_boolean(&ctx, &parse_section_main, "dpi-aware", &conf.dpi_aware);
test_boolean(&ctx, &parse_section_main, "gamma-correct-blending", &conf.gamma_correct);
test_pt_or_px(&ctx, &parse_section_main, "font-size-adjustment", &conf.font_size_adjustment.pt_or_px); /* TODO: test N% values too */
test_pt_or_px(&ctx, &parse_section_main, "line-height", &conf.line_height);
@ -720,6 +743,15 @@ test_section_colors(void)
&conf.colors.search_box.match.fg,
&conf.colors.search_box.match.bg);
test_two_colors(&ctx, &parse_section_colors, "cursor", false,
&conf.colors.cursor.text,
&conf.colors.cursor.cursor);
test_enum(&ctx, &parse_section_colors, "alpha-mode", 3,
(const char *[]){"default", "matching", "all"},
(int []){ALPHA_MODE_DEFAULT, ALPHA_MODE_MATCHING, ALPHA_MODE_ALL},
(int *)&conf.colors.alpha_mode);
for (size_t i = 0; i < 255; i++) {
char key_name[4];
sprintf(key_name, "%zu", i);

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Aero root theme
[cursor]
color=1a1a1a 9fd5f5
[colors]
cursor=1a1a1a 9fd5f5
foreground=dedeef
background=1a1a1a

57
themes/alacritty Normal file
View file

@ -0,0 +1,57 @@
# -*- conf -*-
# Alacritty
[colors]
cursor = 181818 56d8c9
background= 181818
foreground= d8d8d8
#black
regular0= 181818
#red
regular1= ac4242
#green
regular2= 90a959
#yellow
regular3= f4bf75
#blue
regular4= 6a9fb5
#magenta
regular5= aa759f
#cyan
regular6= 75b5aa
#white/grey
regular7= d8d8d8
#grey/black
bright0= 6b6b6b
#red
bright1= c55555
#green
bright2= aac474
#yellow
bright3= feca88
#blue
bright4= 82b8c8
#pink
bright5= c28cb8
#cyan
bright6= 93d3c3
#grey
bright7= f8f8f8

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# https://github.com/romainl/Apprentice
[cursor]
color=262626 6c6c6c
[colors]
cursor=262626 6c6c6c
foreground=bcbcbc
background=262626
regular0=1c1c1c

View file

@ -2,10 +2,8 @@
# theme: Ayu Mirage
# description: a theme based on Ayu Mirage for Sublime Text (original: https://github.com/dempfi/ayu)
[cursor]
color = ffcc66 665a44
[colors]
cursor = ffcc66 665a44
foreground = cccac2
background = 242936

View file

@ -23,6 +23,11 @@ bright5=f4b8e4
bright6=81c8be
bright7=a5adce
cursor=232634 f2d5cf
16=ef9f76
17=f2d5cf
selection-foreground=c6d0f5
selection-background=4f5369

View file

@ -23,6 +23,11 @@ bright5=ea76cb
bright6=179299
bright7=bcc0cc
cursor=eff1f5 dc8a78
16=fe640b
17=dc8a78
selection-foreground=4c4f69
selection-background=ccced7

View file

@ -23,6 +23,11 @@ bright5=f5bde6
bright6=8bd5ca
bright7=a5adcb
cursor=181926 f4dbd6
16=f5a97f
17=f4dbd6
selection-foreground=cad3f5
selection-background=454a5f

View file

@ -23,6 +23,11 @@ bright5=f5c2e7
bright6=94e2d5
bright7=a6adc8
cursor=11111b f5e0dc
16=fab387
17=f5e0dc
selection-foreground=cdd6f4
selection-background=414356

View file

@ -3,10 +3,8 @@
# author: ayushnix (https://sr.ht/~ayushnix)
# description: A dark theme with bright cyberpunk colors (WCAG AAA compliant)
[cursor]
color = 181818 cdcdcd
[colors]
cursor = 181818 cdcdcd
foreground = cdcdcd
background = 181818
regular0 = 181818

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Derp
[cursor]
color=000000 ffffff
[colors]
cursor=000000 ffffff
foreground=ffffff
background=000000
regular0=111111

View file

@ -2,10 +2,8 @@
# Deus
# Color palette based on: https://github.com/ajmwagar/vim-deus
[cursor]
color=2c323b eaeaea
[colors]
cursor=2c323b eaeaea
background=2c323b
foreground=eaeaea
regular0=242a32

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Dracula
[cursor]
color=282a36 f8f8f2
[colors]
cursor=282a36 f8f8f2
foreground=f8f8f2
background=282a36
regular0=000000 # black

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Dracula iTerm2 variant
[cursor]
color=ffffff bbbbbb
[colors]
cursor=ffffff bbbbbb
foreground=f8f8f2
background=1e1f29
regular0=000000 # black

View file

@ -5,10 +5,8 @@
# text and the white background.
# author: Eugen Rahaian <eugen@rah.ro>
[cursor]
color=ffffff 515151
[colors]
cursor=ffffff 515151
background= ffffff
foreground= 000000

42
themes/gruvbox Normal file
View file

@ -0,0 +1,42 @@
# -*- conf -*-
# Gruvbox
[colors]
background=282828
foreground=ebdbb2
regular0=282828
regular1=cc241d
regular2=98971a
regular3=d79921
regular4=458588
regular5=b16286
regular6=689d6a
regular7=a89984
bright0=928374
bright1=fb4934
bright2=b8bb26
bright3=fabd2f
bright4=83a598
bright5=d3869b
bright6=8ec07c
bright7=ebdbb2
[colors2]
background=fbf1c7
foreground=3c3836
regular0=fbf1c7
regular1=cc241d
regular2=98971a
regular3=d79921
regular4=458588
regular5=b16286
regular6=689d6a
regular7=7c6f64
bright0=928374
bright1=9d0006
bright2=79740e
bright3=b57614
bright4=076678
bright5=8f3f71
bright6=427b58
bright7=3c3836

View file

@ -1,8 +1,7 @@
# -*- conf -*-
[cursor]
color=141414 c9c9c9
[colors]
cursor=141414 c9c9c9
foreground=c9c9c9
background=141414
regular0=191918 # black

View file

@ -2,10 +2,8 @@
# JetBrains Darcula
# Palette based on the same theme from https://github.com/dexpota/kitty-themes
[cursor]
color=202020 ffffff
[colors]
cursor=202020 ffffff
background=202020
foreground=adadad
regular0=000000 # black

View file

@ -1,9 +1,7 @@
# -*- conf -*-
[cursor]
color=111111 cccccc
[colors]
cursor=111111 cccccc
foreground=dddddd
background=000000
regular0=000000 # black

View file

@ -2,10 +2,8 @@
# Material Amber
# Based on material.io guidelines with Amber 50 background
[cursor]
color=fff8e1 21201d
[colors]
cursor=fff8e1 21201d
foreground = 21201d
background = fff8e1

23
themes/molokai Normal file
View file

@ -0,0 +1,23 @@
# -*- conf -*-
# Molokai
# Based on zhou13's at https://github.com/zhou13/molokai-terminal/blob/master/xterm/Xresources
[colors]
background=1B1D1E
foreground=CCCCCC
regular0=1B1D1E
regular1=FF0044
regular2=82B414
regular3=FD971F
regular4=266C98
regular5=AC0CB1
regular6=AE81FF
regular7=CCCCCC
bright0=808080
bright1=F92672
bright2=A6E22E
bright3=E6DB74
bright4=7070F0
bright5=D63AE1
bright6=66D9EF
bright7=F8F8F2

View file

@ -2,10 +2,8 @@
# moonfly
# Based on https://github.com/bluz71/vim-moonfly-colors
[cursor]
color = 080808 9e9e9e
[colors]
cursor = 080808 9e9e9e
foreground = b2b2b2
background = 080808

28
themes/night-owl Normal file
View file

@ -0,0 +1,28 @@
# _*_ conf _*_
# Night Owl
[colors]
cursor=011627 80a4c2
foreground=d6deeb
background=011627
regular0=011627
regular1=ef5350
regular2=22da6e
regular3=addb67
regular4=82aaff
regular5=c792ea
regular6=21c7a8
regular7=ffffff
bright0=575656
bright1=ef5350
bright2=22da6e
bright3=ffeb95
bright4=82aaff
bright5=c792ea
bright6=7fdbca
bright7=ffffff
selection-background=5f7e97
selection-foreground=dfe5ee

View file

@ -2,10 +2,8 @@
# nightfly
# Based on https://github.com/bluz71/vim-nightfly-guicolors
[cursor]
color = 080808 9ca1aa
[colors]
cursor = 080808 9ca1aa
foreground = acb4c2
background = 011627

View file

@ -3,10 +3,8 @@
# https://github.com/n1ghtmare/noirblaze-kitty
[cursor]
color=121212 ff0088
[colors]
cursor=121212 ff0088
foreground=d5d5d5
background=121212

View file

@ -6,10 +6,8 @@
# this specific foot theme is based on nord-alacritty:
# https://github.com/arcticicestudio/nord-alacritty/blob/develop/src/nord.yml
[cursor]
color = 2e3440 d8dee9
[colors]
cursor = 2e3440 d8dee9
foreground = d8dee9
background = 2e3440

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Nordiq
[cursor]
color=eeeeee 9f515a
[colors]
cursor=eeeeee 9f515a
foreground=dbdee9
background=0e1420
regular0=5b6272

56
themes/nvim Normal file
View file

@ -0,0 +1,56 @@
# -*- conf -*-
# Neovim Dark theme
# Uses the dark color palette from the default Neovim color scheme
# See: https://github.com/neovim/neovim/blob/fb6c059dc55c8d594102937be4dd70f5ff51614a/src/nvim/highlight_group.c#L419
[colors]
cursor=14161b e0e2ea # NvimDarkGrey2 NvimLightGrey2
foreground=e0e2ea # NvimLightGrey2
background=14161b # NvimDarkGrey2
selection-foreground=e0e2ea # NvimLightGrey2
selection-background=4f5258 # NvimDarkGrey4
regular0=07080d # NvimDarkGrey1
regular1=ffc0b9 # NvimLightRed
regular2=b3f6c0 # NvimLightGreen
regular3=fce094 # NvimLightYellow
regular4=a6dbff # NvimLightBlue
regular5=ffcaff # NvimLightMagenta
regular6=8cf8f7 # NvimLightCyan
regular7=c4c6cd # NvimLightGrey3
bright0=2c2e33 # NvimDarkGrey3
bright1=ffc0b9 # NvimLightRed
bright2=b3f6c0 # NvimLightGreen
bright3=fce094 # NvimLightYellow
bright4=a6dbff # NvimLightBlue
bright5=ffcaff # NvimLightMagenta
bright6=8cf8f7 # NvimLightCyan
bright7=eef1f8 # NvimLightGrey1
[colors2]
cursor=e0e2ea 14161b # NvimLightGrey2 NvimDarkGrey2
foreground=14161b # NvimDarkGrey2
background=e0e2ea # NvimLightGrey2
selection-foreground=14161b # NvimDarkGrey2
selection-background=9b9ea4 # NvimLightGrey4
regular0=eef1f8 # NvimLightGrey1
regular1=590008 # NvimDarkRed
regular2=005523 # NvimDarkGreen
regular3=6b5300 # NvimDarkYellow
regular4=004c73 # NvimDarkBlue
regular5=470045 # NvimDarkMagenta
regular6=007373 # NvimDarkCyan
regular7=2c2e33 # NvimDarkGrey3
bright0=c4c6cd # NvimLightGrey3
bright1=590008 # NvimDarkRed
bright2=005523 # NvimDarkGreen
bright3=6b5300 # NvimDarkYellow
bright4=004c73 # NvimDarkBlue
bright5=470045 # NvimDarkMagenta
bright6=007373 # NvimDarkCyan
bright7=07080d # NvimDarkGrey1

View file

@ -3,10 +3,8 @@
# Uses the dark color palette from the default Neovim color scheme
# See: https://github.com/neovim/neovim/blob/fb6c059dc55c8d594102937be4dd70f5ff51614a/src/nvim/highlight_group.c#L419
[cursor]
color=14161b e0e2ea # NvimDarkGrey2 NvimLightGrey2
[colors]
cursor=14161b e0e2ea # NvimDarkGrey2 NvimLightGrey2
foreground=e0e2ea # NvimLightGrey2
background=14161b # NvimDarkGrey2

View file

@ -3,10 +3,8 @@
# Uses the light color palette from the default Neovim color scheme
# See: https://github.com/neovim/neovim/blob/fb6c059dc55c8d594102937be4dd70f5ff51614a/src/nvim/highlight_group.c#L334
[cursor]
color=e0e2ea 14161b # NvimLightGrey2 NvimDarkGrey2
[colors]
cursor=e0e2ea 14161b # NvimLightGrey2 NvimDarkGrey2
foreground=14161b # NvimDarkGrey2
background=e0e2ea # NvimLightGrey2

View file

@ -1,10 +1,8 @@
# OneDark
# Palette based on the same theme from https://github.com/dexpota/kitty-themes
[cursor]
color=111111 cccccc
[colors]
cursor=111111 cccccc
foreground=979eab
background=282c34
regular0=282c34 # black

View file

@ -7,10 +7,8 @@
# + cursor colors from:
# https://github.com/sonph/onehalf/blob/master/iterm/OneHalfDark.itermcolors
[cursor]
color=dcdfe4 a3b3cc
[colors]
cursor=dcdfe4 a3b3cc
foreground=dcdfe4
background=282c34
regular0=282c34 # black

49
themes/paper-color Normal file
View file

@ -0,0 +1,49 @@
# -*- conf -*-
# PaperColorDark
# Palette based on https://github.com/NLKNguyen/papercolor-theme
[colors]
cursor=1c1c1c eeeeee
background=1c1c1c
foreground=eeeeee
regular0=1c1c1c # black
regular1=af005f # red
regular2=5faf00 # green
regular3=d7af5f # yellow
regular4=5fafd7 # blue
regular5=808080 # magenta
regular6=d7875f # cyan
regular7=d0d0d0 # white
bright0=bcbcbc # bright black
bright1=5faf5f # bright red
bright2=afd700 # bright green
bright3=af87d7 # bright yellow
bright4=ffaf00 # bright blue
bright5=ff5faf # bright magenta
bright6=00afaf # bright cyan
bright7=5f8787 # bright white
# selection-foreground=1c1c1c
# selection-background=af87d7
[colors2]
cursor=eeeeee 444444
background=eeeeee
foreground=444444
regular0=eeeeee # black
regular1=af0000 # red
regular2=008700 # green
regular3=5f8700 # yellow
regular4=0087af # blue
regular5=878787 # magenta
regular6=005f87 # cyan
regular7=764e37 # white
bright0=bcbcbc # bright black
bright1=d70000 # bright red
bright2=d70087 # bright green
bright3=8700af # bright yellow
bright4=d75f00 # bright blue
bright5=d75f00 # bright magenta
bright6=4c7a5d # bright cyan
bright7=005faf # bright white
# selection-foreground=eeeeee
# selection-background=0087af

View file

@ -2,10 +2,8 @@
# PaperColorDark
# Palette based on https://github.com/NLKNguyen/papercolor-theme
[cursor]
color=1c1c1c eeeeee
[colors]
cursor=1c1c1c eeeeee
background=1c1c1c
foreground=eeeeee
regular0=1c1c1c # black

View file

@ -2,10 +2,8 @@
# PaperColor Light
# Palette based on https://github.com/NLKNguyen/papercolor-theme
[cursor]
color=eeeeee 444444
[colors]
cursor=eeeeee 444444
background=eeeeee
foreground=444444
regular0=eeeeee # black

View file

@ -1,10 +1,8 @@
# Based on Poimandres color theme for kitti terminal emulator
# https://github.com/ubmit/poimandres-kitty
[cursor]
color=1b1e28 ffffff
[colors]
cursor=1b1e28 ffffff
foreground=a6accd
background=1b1e28

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Rosé Pine
[cursor]
color=191724 e0def4
[colors]
cursor=191724 e0def4
background=191724
foreground=e0def4

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Rosé Pine Dawn
[cursor]
color=faf4ed 575279
[colors]
cursor=faf4ed 575279
background=faf4ed
foreground=575279

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Rosé Pine Moon
[cursor]
color=232136 e0def4
[colors]
cursor=232136 e0def4
background=232136
foreground=e0def4

48
themes/selenized Normal file
View file

@ -0,0 +1,48 @@
# -*- conf -*-
# Selenized dark
[colors]
cursor = 103c48 53d6c7
background= 103c48
foreground= adbcbc
regular0= 184956
regular1= fa5750
regular2= 75b938
regular3= dbb32d
regular4= 4695f7
regular5= f275be
regular6= 41c7b9
regular7= 72898f
bright0= 2d5b69
bright1= ff665c
bright2= 84c747
bright3= ebc13d
bright4= 58a3ff
bright5= ff84cd
bright6= 53d6c7
bright7= cad8d9
[colors2]
cursor=fbf3db 00978a
background= fbf3db
foreground= 53676d
regular0= ece3cc
regular1= d2212d
regular2= 489100
regular3= ad8900
regular4= 0072d4
regular5= ca4898
regular6= 009c8f
regular7= 909995
bright0= d5cdb6
bright1= cc1729
bright2= 428b00
bright3= a78300
bright4= 006dce
bright5= c44392
bright6= 00978a
bright7= 3a4d53

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Selenized black
[cursor]
color = 181818 56d8c9
[colors]
cursor = 181818 56d8c9
background= 181818
foreground= b9b9b9

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Selenized dark
[cursor]
color = 103c48 53d6c7
[colors]
cursor = 103c48 53d6c7
background= 103c48
foreground= adbcbc

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Selenized light
[cursor]
color=fbf3db 00978a
[colors]
cursor=fbf3db 00978a
background= fbf3db
foreground= 53676d

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Selenized white
[cursor]
color=ffffff 009a8a
[colors]
cursor=ffffff 009a8a
background= ffffff
foreground= 474747

47
themes/solarized Normal file
View file

@ -0,0 +1,47 @@
# -*- conf -*-
# Solarized dark+light
# Dark
[colors]
cursor= 002b36 93a1a1
background= 002b36
foreground= 839496
regular0= 073642
regular1= dc322f
regular2= 859900
regular3= b58900
regular4= 268bd2
regular5= d33682
regular6= 2aa198
regular7= eee8d5
bright0= 002b36
bright1= cb4b16
bright2= 586e75
bright3= 657b83
bright4= 839496
bright5= 6c71c4
bright6= 93a1a1
bright7= fdf6e3
# Light
[colors2]
cursor= fdf6e3 586e75
background= fdf6e3
foreground= 657b83
regular0= eee8d5
regular1= dc322f
regular2= 859900
regular3= b58900
regular4= 268bd2
regular5= d33682
regular6= 2aa198
regular7= 073642
bright0= cb4b16
bright1= fdf6e3
bright2= 93a1a1
bright3= 839496
bright4= 657b83
bright5= 6c71c4
bright6= 586e75
bright7= 002b36

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Solarized dark
[cursor]
color= 002b36 93a1a1
[colors]
cursor= 002b36 93a1a1
background= 002b36
foreground= 839496
regular0= 073642

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Solarized dark
[cursor]
color= 002b36 93a1a1
[colors]
cursor= 002b36 93a1a1
background= 002b36
foreground= 839496
regular0= 073642

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Solarized light
[cursor]
color=fdf6e3 586e75
[colors]
cursor= fdf6e3 586e75
background= fdf6e3
foreground= 657b83
regular0= eee8d5

View file

@ -0,0 +1,54 @@
# -*- conf -*-
# Solarized dark+light
#
# Bright colors are brighter versions of the regular colors, instead
# of the normal solarized palette.
#
# They were generated by taking the regular colors, decoding from sRGB
# to linear, multiplying the linear RGB values by 1.8, and then
# encoding to sRGB again.
# Dark
[colors]
cursor= 002b36 93a1a1
background= 002b36
foreground= 839496
regular0= 073642
regular1= dc322f
regular2= 859900
regular3= b58900
regular4= 268bd2
regular5= d33682
regular6= 2aa198
regular7= eee8d5
bright0= 0c4958
bright1= ff4440
bright2= aec700
bright3= ebb300
bright4= 34b5ff
bright5= ff49aa
bright6= 3ad2c6
bright7= ffffff
# Light
[colors2]
cursor= fdf6e3 586e75
background= fdf6e3
foreground= 657b83
regular0= eee8d5
regular1= dc322f
regular2= 859900
regular3= b58900
regular4= 268bd2
regular5= d33682
regular6= 2aa198
regular7= 073642
bright0= ffffff
bright1= ff4440
bright2= aec700
bright3= ebb300
bright4= 34b5ff
bright5= ff49aa
bright6= 3ad2c6
bright7= 0c4958

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# Tango
[cursor]
color=000000 babdb6
[colors]
cursor=000000 babdb6
foreground=babdb6
background=000000
regular0=2e3436

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Dark theme with a palette inspired by earthly colours (WCAG AA compliant)
#[cursor]
#color = 302420 a9a2a6
[colors]
#cursor = 302420 a9a2a6
foreground = a9a2a6
background = 302420
regular0 = 302420

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Dark theme with warm hues (WCAG AA compliant)
#[cursor]
#color = 232323 aeadaf
[colors]
#cursor = 232323 aeadaf
foreground = aeadaf
background = 232323
regular0 = 232323

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Light theme with a soft, slightly desaturated palette (WCAG AA compliant)
#[cursor]
#color = eff0f2 4a4b4e
[colors]
#cursor = eff0f2 4a4b4e
foreground = 4a4b4e
background = eff0f2
regular0 = 4a4b4e

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Light theme with warm colours (WCAG AA compliant)
#[cursor]
#color = f8f2e5 464340
[colors]
#cursor = f8f2e5 464340
foreground = 464340
background = f8f2e5
regular0 = 464340

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Dark theme with a deep blue-ish, slightly desaturated palette (WCAG AA compliant)
#[cursor]
#color = 1f252d a2a8ba
[colors]
#cursor = 1f252d a2a8ba
foreground = a2a8ba
background = 1f252d
regular0 = 1f252d

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Light, pleasant theme optimised for long writing/coding sessions (WCAG AA compliant)
#[cursor]
#color = fff5f3 4d595f
[colors]
#cursor = fff5f3 4d595f
foreground = 4d595f
background = fff5f3
regular0 = 4d595f

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Dark theme with colours inspired by concept art of outer space (WCAG AAA compliant)
#[cursor]
#color = 090a18 b4abac
[colors]
#cursor = 090a18 b4abac
foreground = b4abac
background = 090a18
regular0 = 090a18

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: High contrast dark theme with bright colours (WCAG AAA compliant)
#[cursor]
#color = 1a1a1a e0e0e0
[colors]
#cursor = 1a1a1a e0e0e0
foreground = e0e0e0
background = 1a1a1a
regular0 = 1a1a1a

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Light theme inspired by old vaporwave concept art (WCAG AA compliant)
#[cursor]
#color = f3f2f4 53545b
[colors]
#cursor = f3f2f4 53545b
foreground = 53545b
background = f3f2f4
regular0 = 53545b

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Dark theme with a subdued palette on the green side of the spectrum (WCAG AA compliant)
#[cursor]
#color = 162c22 bbbcbc
[colors]
#cursor = 162c22 bbbcbc
foreground = bbbcbc
background = 162c22
regular0 = 162c22

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Dark theme with a palette inspired by early spring colours (WCAG AA compliant)
#[cursor]
#color = 283a37 b5b8b7
[colors]
#cursor = 283a37 b5b8b7
foreground = b5b8b7
background = 283a37
regular0 = 283a37

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Dark theme with colours inspired by summer evenings by the sea (WCAG AA compliant)
#[cursor]
#color = 202c3d a0abae
[colors]
#cursor = 202c3d a0abae
foreground = a0abae
background = 202c3d
regular0 = 202c3d

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: A green-scale, subtle theme for late night hackers (WCAG AAA compliant)
#[cursor]
#color = 282b2b b6e0ca
[colors]
#cursor = 282b2b b6e0ca
foreground = b6e0ca
background = 282b2b
regular0 = 282b2b

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Light theme for prose or for coding in an open space (WCAG AAA compliant)
#[cursor]
#color = ffffff 4a484d
[colors]
#cursor = ffffff 4a484d
foreground = 4a484d
background = ffffff
regular0 = 4a484d

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Dark theme with a vibrant palette (WCAG AA compliant)
#[cursor]
#color = 001514 a29fa0
[colors]
#cursor = 001514 a29fa0
foreground = a29fa0
background = 001514
regular0 = 001514

View file

@ -3,10 +3,8 @@
# author: Protesilaos Stavrou (https://protesilaos.com)
# description: Dark theme with a palette inspired by winter nights at the city (WCAG AA compliant)
#[cursor]
#color = 202427 8da3b8
[colors]
#cursor = 202427 8da3b8
foreground = 8da3b8
background = 202427
regular0 = 202427

View file

@ -1,10 +1,8 @@
# -*- conf -*-
# VisiBone
[cursor]
color=010101 ffffff
[colors]
cursor=010101 ffffff
foreground=ffffff
background=010101
regular0=666666

View file

@ -131,7 +131,7 @@ spawn_url_launcher(struct seat *seat, struct terminal *term, const char *url,
static void
activate_url(struct seat *seat, struct terminal *term, const struct url *url,
uint32_t serial)
uint32_t serial, bool paste_url_to_self)
{
char *url_string = NULL;
@ -159,6 +159,15 @@ activate_url(struct seat *seat, struct terminal *term, const struct url *url,
switch (url->action) {
case URL_ACTION_COPY:
if (paste_url_to_self) {
if (term->bracketed_paste)
term_to_slave(term, "\033[200~", 6);
term_to_slave(term, url_string, strlen(url_string));
if (term->bracketed_paste)
term_to_slave(term, "\033[201~", 6);
}
if (text_to_clipboard(seat, term, url_string, seat->kbd.serial)) {
/* Now owned by our clipboard “manager” */
url_string = NULL;
@ -273,7 +282,8 @@ urls_input(struct seat *seat, struct terminal *term,
}
if (match) {
activate_url(seat, term, match, serial);
// If the last hint character was uppercase, copy and paste
activate_url(seat, term, match, serial, wc == toc32upper(wc));
switch (match->action) {
case URL_ACTION_COPY:
@ -347,6 +357,9 @@ regex_detected(const struct terminal *term, enum url_action action,
wc_count = composed->count;
}
else if (wc[0] >= CELL_SPACER)
continue;
/* Convert wide character to utf8 */
for (size_t i = 0; i < wc_count; i++) {
char buf[16];
@ -355,6 +368,7 @@ regex_detected(const struct terminal *term, enum url_action action,
if (char_len == (size_t)-1)
continue;
for (size_t j = 0; j < char_len; j++) {
const size_t requires_size = vline->len + char_len;
@ -411,9 +425,9 @@ regex_detected(const struct terminal *term, enum url_action action,
const size_t end = start + mlen;
LOG_DBG(
"regex match at row %d: %.*srow/col = %dx%d",
"regex match at row %d: %.*s (%zu bytes), row/col = %dx%d",
matches[1].rm_so, (int)mlen, &search_string[matches[1].rm_so],
v->map[start].row, v->map[start].col);
mlen, v->map[start].row, v->map[start].col);
tll_push_back(
*urls,

View file

@ -244,6 +244,8 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
case WL_SHM_FORMAT_ARGB2101010: wayl->shm_have_argb2101010 = true; break;
case WL_SHM_FORMAT_XBGR2101010: wayl->shm_have_xbgr2101010 = true; break;
case WL_SHM_FORMAT_ABGR2101010: wayl->shm_have_abgr2101010 = true; break;
case WL_SHM_FORMAT_XBGR16161616: wayl->shm_have_xbgr161616 = true; break;
case WL_SHM_FORMAT_ABGR16161616: wayl->shm_have_abgr161616 = true; break;
}
#if defined(_DEBUG)
@ -852,6 +854,10 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
bool is_tiled_bottom = false;
bool is_tiled_left = false;
bool is_tiled_right = false;
bool is_constrained_top = false;
bool is_constrained_bottom = false;
bool is_constrained_left = false;
bool is_constrained_right = false;
bool is_suspended UNUSED = false;
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
@ -869,6 +875,12 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
[XDG_TOPLEVEL_STATE_TILED_BOTTOM] = "tiled:bottom",
#if defined(XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION) /* wayland-protocols >= 1.32 */
[XDG_TOPLEVEL_STATE_SUSPENDED] = "suspended",
#endif
#if defined(XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION)
[XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT] = "constrained:left",
[XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT] = "constrained:right",
[XDG_TOPLEVEL_STATE_CONSTRAINED_TOP] = "constrained:top",
[XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM] = "constrained:bottom",
#endif
};
#endif
@ -887,6 +899,12 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
#if defined(XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION)
case XDG_TOPLEVEL_STATE_SUSPENDED: is_suspended = true; break;
#endif
#if defined(XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION)
case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT: is_constrained_left = true; break;
case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT: is_constrained_right = true; break;
case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP: is_constrained_top = true; break;
case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM: is_constrained_bottom = true; break;
#endif
}
@ -927,6 +945,10 @@ xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
win->configure.is_tiled_bottom = is_tiled_bottom;
win->configure.is_tiled_left = is_tiled_left;
win->configure.is_tiled_right = is_tiled_right;
win->configure.is_constrained_top = is_constrained_top;
win->configure.is_constrained_bottom = is_constrained_bottom;
win->configure.is_constrained_left = is_constrained_left;
win->configure.is_constrained_right = is_constrained_right;
win->configure.width = width;
win->configure.height = height;
}
@ -1050,14 +1072,22 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface,
win->is_maximized = win->configure.is_maximized;
win->is_fullscreen = win->configure.is_fullscreen;
win->is_resizing = win->configure.is_resizing;
win->is_tiled_top = win->configure.is_tiled_top;
win->is_tiled_bottom = win->configure.is_tiled_bottom;
win->is_tiled_left = win->configure.is_tiled_left;
win->is_tiled_right = win->configure.is_tiled_right;
win->is_constrained_top = win->configure.is_constrained_top;
win->is_constrained_bottom = win->configure.is_constrained_bottom;
win->is_constrained_left = win->configure.is_constrained_left;
win->is_constrained_right = win->configure.is_constrained_right;
win->is_tiled = (win->is_tiled_top ||
win->is_tiled_bottom ||
win->is_tiled_left ||
win->is_tiled_right);
win->csd_mode = win->configure.csd_mode;
bool enable_csd = win->csd_mode == CSD_YES && !win->is_fullscreen;
@ -1104,7 +1134,7 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface,
else
term_visual_focus_out(term);
if (!resized) {
if (!resized && !term->render.pending.grid) {
/*
* If we didn't resize, we won't be committing a new surface
* anytime soon. Some compositors require a commit in
@ -1233,13 +1263,23 @@ handle_global(void *data, struct wl_registry *registry,
return;
/*
* We *require* version 1, but _can_ use version 5. Version 2
* adds 'tiled' window states. We use that information to
* restore the window size when window is un-tiled. Version 5
* adds 'wm_capabilities'. We use that information to draw
* window decorations.
* We *require* version 1, but _can_ use version 2, 5 or 7, if
* available.
*
* Version 2 adds 'tiled' window states. We use this
* information to restore the window size when window is
* un-tiled.
*
* Version 5 adds 'wm_capabilities'. We use this information
* to draw window decorations.
*
* Version 7 adds 'constrained' window states. We use this
* information to determine whether to allow window resize
* (via CSDs) or not.
*/
#if defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
#if defined(XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION)
const uint32_t preferred = XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION;
#elif defined(XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION)
const uint32_t preferred = XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION;
#elif defined(XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION)
const uint32_t preferred = XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION;
@ -1440,8 +1480,16 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required))
return;
#if defined(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK_SINCE_VERSION) /* 1.42 */
const uint32_t preferred = WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DND_ASK_SINCE_VERSION;
#else
const uint32_t preferred = required;
#endif
wayl->shape_manager_version = min(required, preferred);
wayl->cursor_shape_manager = wl_registry_bind(
wayl->registry, name, &wp_cursor_shape_manager_v1_interface, required);
wayl->registry, name, &wp_cursor_shape_manager_v1_interface,
min(required, preferred));
}
else if (streq(interface, wp_single_pixel_buffer_manager_v1_interface.name)) {
@ -1454,13 +1502,13 @@ handle_global(void *data, struct wl_registry *registry,
&wp_single_pixel_buffer_manager_v1_interface, required);
}
else if (streq(interface, xdg_toplevel_icon_v1_interface.name)) {
else if (streq(interface, xdg_toplevel_icon_manager_v1_interface.name)) {
const uint32_t required = 1;
if (!verify_iface_version(interface, version, required))
return;
wayl->toplevel_icon_manager = wl_registry_bind(
wayl->registry, name, &xdg_toplevel_icon_v1_interface, required);
wayl->registry, name, &xdg_toplevel_icon_manager_v1_interface, required);
}
else if (streq(interface, xdg_system_bell_v1_interface.name)) {
@ -1612,6 +1660,8 @@ fdm_wayl(struct fdm *fdm, int fd, int events, void *data)
return false;
}
wl_display_dispatch_pending(wayl->display);
while (wl_display_prepare_read(wayl->display) != 0) {
if (wl_display_dispatch_pending(wayl->display) < 0) {
LOG_ERRNO("failed to dispatch pending Wayland events");
@ -1942,7 +1992,7 @@ wayl_win_init(struct terminal *term, const char *token)
xdg_toplevel_icon_v1_destroy(icon);
}
if (term->conf->gamma_correct != GAMMA_CORRECT_DISABLED) {
if (term->conf->gamma_correct) {
if (wayl->color_management.img_description != NULL) {
xassert(wayl->color_management.manager != NULL);
@ -1952,7 +2002,7 @@ wayl_win_init(struct terminal *term, const char *token)
wp_color_management_surface_v1_set_image_description(
win->surface.color_management, wayl->color_management.img_description,
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
} else if (term->conf->gamma_correct == GAMMA_CORRECT_ENABLED) {
} else {
if (wayl->color_management.manager == NULL) {
LOG_WARN(
"gamma-corrected-blending: disabling; "
@ -1967,8 +2017,6 @@ wayl_win_init(struct terminal *term, const char *token)
LOG_WARN(" - TF: ext_linear");
LOG_WARN(" - primaries: sRGB");
}
} else {
/* "auto" - don't warn */
}
}
@ -2209,7 +2257,14 @@ wayl_flush(struct wayland *wayl)
}
if (errno != EAGAIN) {
LOG_ERRNO("failed to flush wayland socket");
const int saved_errno = errno;
if (errno == EPIPE) {
wl_display_read_events(wayl->display);
wl_display_dispatch_pending(wayl->display);
}
LOG_ERRNO_P(saved_errno, "failed to flush wayland socket");
return;
}
@ -2604,3 +2659,10 @@ wayl_activate(struct wayland *wayl, struct wl_window *win, const char *token)
xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface.surf);
}
bool
wayl_do_linear_blending(const struct wayland *wayl, const struct config *conf)
{
return conf->gamma_correct &&
wayl->color_management.img_description != NULL;
}

View file

@ -26,6 +26,7 @@
#include <fcft/fcft.h>
#include <tllist.h>
#include "config.h"
#include "cursor-shape.h"
#include "fdm.h"
@ -402,6 +403,12 @@ struct wl_window {
bool is_tiled_left;
bool is_tiled_right;
bool is_tiled; /* At least one of is_tiled_{top,bottom,left,right} is true */
bool is_constrained_top;
bool is_constrained_bottom;
bool is_constrained_left;
bool is_constrained_right;
struct {
int width;
int height;
@ -409,10 +416,17 @@ struct wl_window {
bool is_fullscreen:1;
bool is_maximized:1;
bool is_resizing:1;
bool is_tiled_top:1;
bool is_tiled_bottom:1;
bool is_tiled_left:1;
bool is_tiled_right:1;
bool is_constrained_top:1;
bool is_constrained_bottom:1;
bool is_constrained_left:1;
bool is_constrained_right:1;
enum csd_mode csd_mode;
} configure;
@ -446,6 +460,7 @@ struct wayland {
struct wp_fractional_scale_manager_v1 *fractional_scale_manager;
struct wp_cursor_shape_manager_v1 *cursor_shape_manager;
int shape_manager_version;
struct wp_single_pixel_buffer_manager_v1 *single_pixel_manager;
@ -482,6 +497,8 @@ struct wayland {
bool shm_have_xrgb2101010:1;
bool shm_have_abgr2101010:1;
bool shm_have_xbgr2101010:1;
bool shm_have_abgr161616:1;
bool shm_have_xbgr161616:1;
};
struct wayland *wayl_init(
@ -526,3 +543,4 @@ bool wayl_get_activation_token(
struct wl_window *win, activation_token_cb_t cb, void *cb_data);
void wayl_activate(struct wayland *wayl, struct wl_window *win, const char *token);
bool wayl_do_linear_blending(const struct wayland *wayl, const struct config *conf);

18
xkbcommon-vmod.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include <xkbcommon/xkbcommon-names.h>
/* Added in libxkbcommon 1.8.0 */
#if !defined(XKB_VMOD_NAME_ALT)
/* Common *virtual* modifiers, encoded in xkeyboard-config in the compat and
* symbols files. They have been stable since the beginning of the project and
* are unlikely to ever change. */
#define XKB_VMOD_NAME_ALT "Alt"
#define XKB_VMOD_NAME_HYPER "Hyper"
#define XKB_VMOD_NAME_LEVEL3 "LevelThree"
#define XKB_VMOD_NAME_LEVEL5 "LevelFive"
#define XKB_VMOD_NAME_META "Meta"
#define XKB_VMOD_NAME_NUM "NumLock"
#define XKB_VMOD_NAME_SCROLL "ScrollLock"
#define XKB_VMOD_NAME_SUPER "Super"
#endif