diff --git a/CHANGELOG.md b/CHANGELOG.md index a293c721..e76f985b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ ## Unreleased ### Added +* TODO * `toplevel-tag` option (and `--toplevel-tag` command line options to `foot` and `footclient`), allowing you to set a custom toplevel tag. The compositor must implement the new `xdg-toplevel-tag-v1` diff --git a/config.c b/config.c index 515b088c..6c2d355d 100644 --- a/config.c +++ b/config.c @@ -25,6 +25,7 @@ #include "input.h" #include "key-binding.h" #include "macros.h" +#include "srgb.h" #include "tokenize.h" #include "util.h" #include "xmalloc.h" @@ -3185,6 +3186,16 @@ parse_config_file(FILE *f, struct config *conf, const char *path, bool errors_ar errno = 0; } + struct color_theme *color_themes[] = {&conf->colors, &conf->colors2}; + for (int i = 0; i < ALEN(color_themes); i++) { + struct color_theme *color_theme = color_themes[i]; + if (color_theme->dim_blend_towards != DIM_BLEND_TOWARDS_INVALID) + continue; + color_theme->dim_blend_towards = + is_dark_theme(color_theme->fg, color_theme->bg) + ? DIM_BLEND_TOWARDS_BLACK : DIM_BLEND_TOWARDS_WHITE; + } + if (errno != 0) { LOG_AND_NOTIFY_ERRNO("failed to read from configuration"); if (errors_are_fatal) @@ -3442,7 +3453,7 @@ config_load(struct config *conf, const char *conf_path, .flash_alpha = 0x7fff, .alpha = 0xffff, .alpha_mode = ALPHA_MODE_DEFAULT, - .dim_blend_towards = DIM_BLEND_TOWARDS_BLACK, + .dim_blend_towards = DIM_BLEND_TOWARDS_INVALID, .selection_fg = 0x80000000, /* Use default bg */ .selection_bg = 0x80000000, /* Use default fg */ .cursor = { @@ -3538,7 +3549,6 @@ 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)); - conf->colors2.dim_blend_towards = DIM_BLEND_TOWARDS_WHITE; parse_modifiers(XKB_MOD_NAME_SHIFT, 5, &conf->mouse.selection_override_modifiers); @@ -4096,6 +4106,30 @@ check_if_font_is_monospaced(const char *pattern, return is_monospaced; } +pixman_color_t +color_hex_to_pixman_srgb(uint32_t color, uint16_t alpha) +{ + return (pixman_color_t){ + .alpha = alpha, /* Consider alpha linear already? */ + .red = srgb_decode_8_to_16((color >> 16) & 0xff), + .green = srgb_decode_8_to_16((color >> 8) & 0xff), + .blue = srgb_decode_8_to_16((color >> 0) & 0xff), + }; +} + +// See https://en.wikipedia.org/wiki/Relative_luminance +static float relative_luminance(uint32_t rgb) +{ + pixman_color_t srgb = + color_hex_to_pixman_srgb(rgb, /*alpha=*/UINT16_MAX); + return 0.2126 * srgb.red + 0.7152 * srgb.green + 0.0722 * srgb.blue; +} + +bool is_dark_theme(uint32_t fg, uint32_t bg) +{ + return relative_luminance(bg) < relative_luminance(fg); +} + #if 0 xkb_mod_mask_t conf_modifiers_to_mask(const struct seat *seat, diff --git a/config.h b/config.h index fc5e290e..a4a01fac 100644 --- a/config.h +++ b/config.h @@ -148,6 +148,7 @@ struct color_theme { enum { DIM_BLEND_TOWARDS_BLACK, DIM_BLEND_TOWARDS_WHITE, + DIM_BLEND_TOWARDS_INVALID, } dim_blend_towards; enum { @@ -473,3 +474,7 @@ conf_modifiers_to_mask( #endif bool check_if_font_is_monospaced( const char *pattern, user_notifications_t *notifications); + +pixman_color_t +color_hex_to_pixman_srgb(uint32_t color, uint16_t alpha); +bool is_dark_theme(uint32_t fg, uint32_t bg); diff --git a/doc/foot-ctlseqs.7.scd b/doc/foot-ctlseqs.7.scd index 40906ebf..86f36492 100644 --- a/doc/foot-ctlseqs.7.scd +++ b/doc/foot-ctlseqs.7.scd @@ -664,9 +664,7 @@ manipulation sequences. The generic format is: : 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. + 997 ; 1|2 n*, where *1* means dark and *2* light. # OSC diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index c9782895..20721056 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -1138,17 +1138,12 @@ dark theme (since the default theme is dark). # 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, except -for *dim-blend-towards*, which defaults to *white* instead. +keys and default values as the *colors* section. 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 diff --git a/foot.ini b/foot.ini index 2d170489..09950b64 100644 --- a/foot.ini +++ b/foot.ini @@ -132,7 +132,7 @@ # bright7=ffffff # bright white ## dimmed colors (see foot.ini(5) man page) -# dim-blend-towards=black +# dim-blend-towards= # dim0= # ... # dim7= @@ -171,8 +171,7 @@ [colors2] # Alternative color theme, see man page foot.ini(5) -# Same builtin defaults as [color], except for: -# dim-blend-towards=white +# Same builtin defaults as [color] [csd] # preferred=server diff --git a/render.c b/render.c index 1d0f08af..6e079016 100644 --- a/render.c +++ b/render.c @@ -40,7 +40,6 @@ #include "selection.h" #include "shm.h" #include "sixel.h" -#include "srgb.h" #include "url-mode.h" #include "util.h" #include "xmalloc.h" @@ -229,17 +228,6 @@ attrs_to_font(const struct terminal *term, const struct attributes *attrs) return term->fonts[idx]; } -static pixman_color_t -color_hex_to_pixman_srgb(uint32_t color, uint16_t alpha) -{ - return (pixman_color_t){ - .alpha = alpha, /* Consider alpha linear already? */ - .red = srgb_decode_8_to_16((color >> 16) & 0xff), - .green = srgb_decode_8_to_16((color >> 8) & 0xff), - .blue = srgb_decode_8_to_16((color >> 0) & 0xff), - }; -} - static inline pixman_color_t color_hex_to_pixman_with_alpha(uint32_t color, uint16_t alpha, bool srgb) { diff --git a/subprojects/.wraplock b/subprojects/.wraplock new file mode 100644 index 00000000..e69de29b diff --git a/terminal.c b/terminal.c index 3ef53daa..d24e03ca 100644 --- a/terminal.c +++ b/terminal.c @@ -1,4 +1,6 @@ #include "terminal.h" +#include "pixman.h" +#include #if defined(__GLIBC__) #include @@ -4785,10 +4787,6 @@ term_theme_toggle(struct terminal *term) /* * 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. */ void term_send_color_theme_mode(struct terminal* term) { @@ -4796,6 +4794,6 @@ void term_send_color_theme_mode(struct terminal* term) "\033[?997;2n", "\033[?997;1n", }; - const bool is_dark = term->colors.active_theme == COLOR_THEME1; + const bool is_dark = is_dark_theme(term->colors.fg, term->colors.bg); term_to_slave(term, reply[is_dark], 9); } diff --git a/tests/meson.build b/tests/meson.build index 9baa064c..3d126973 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,6 +1,7 @@ config_test = executable( 'test-config', 'test-config.c', + srgb_funcs, wl_proto_headers, link_with: [common, tokenize], dependencies: [pixman, xkb, fontconfig, wayland_client, fcft, tllist])