diff --git a/kitty/colors.c b/kitty/colors.c index e5c181a85..605df0d9d 100644 --- a/kitty/colors.c +++ b/kitty/colors.c @@ -80,9 +80,18 @@ set_configured_colors(ColorProfile *self, PyObject *opts) { n(default_fg, foreground); n(default_bg, background); n(cursor_color, cursor); n(cursor_text_color, cursor_text_color); n(highlight_fg, selection_foreground); n(highlight_bg, selection_background); - n(visual_bell_color, visual_bell_color); n(second_transparent_bg, second_transparent_bg); + n(visual_bell_color, visual_bell_color); #undef n - return true; + memset(self->configured_transparent_colors, 0, sizeof(self->configured_transparent_colors)); + RAII_PyObject(src, PyObject_GetAttrString(opts, "transparent_background_colors")); + if (!src) { PyErr_SetString(PyExc_TypeError, "No transparent_background_colors on opts object"); return false; } + for (Py_ssize_t i = 0; i < MIN(PyTuple_GET_SIZE(src), (Py_ssize_t)arraysz(self->configured_transparent_colors)); i++) { + PyObject *e = PyTuple_GET_ITEM(src, i); + self->configured_transparent_colors[i].color = ((Color*)(PyTuple_GET_ITEM(e, 0)))->color.val & 0xffffff; + self->configured_transparent_colors[i].opacity = (float)PyFloat_AsDouble(PyTuple_GET_ITEM(e, 1)); + self->configured_transparent_colors[i].is_set = true; + } + return PyErr_Occurred() ? false : true; } static bool @@ -162,6 +171,8 @@ copy_color_profile(ColorProfile *dest, ColorProfile *src) { memcpy(dest->orig_color_table, src->orig_color_table, sizeof(dest->color_table)); memcpy(&dest->configured, &src->configured, sizeof(dest->configured)); memcpy(&dest->overridden, &src->overridden, sizeof(dest->overridden)); + memcpy(dest->overriden_transparent_colors, src->overriden_transparent_colors, sizeof(dest->overriden_transparent_colors)); + memcpy(dest->configured_transparent_colors, src->configured_transparent_colors, sizeof(dest->configured_transparent_colors)); dest->dirty = true; } @@ -226,12 +237,28 @@ patch_color_profiles(PyObject *module UNUSED, PyObject *args) { S(foreground, default_fg); S(background, default_bg); S(cursor, cursor_color); S(selection_foreground, highlight_fg); S(selection_background, highlight_bg); S(cursor_text_color, cursor_text_color); S(visual_bell_color, visual_bell_color); - S(second_transparent_bg, second_transparent_bg); #undef SI #undef S + // TODO: Patch transparent_colors Py_RETURN_NONE; } +bool +colorprofile_to_transparent_color(const ColorProfile *self, unsigned index, color_type *color, float *opacity) { + *color = UINT32_MAX; *opacity = 1.0; + if (index < arraysz(self->configured_transparent_colors)) { + if (self->overriden_transparent_colors[index].is_set) { + *color = self->overriden_transparent_colors[index].color; *opacity = self->overriden_transparent_colors[index].opacity; + return true; + } + if (self->configured_transparent_colors[index].is_set) { + *color = self->configured_transparent_colors[index].color; *opacity = self->configured_transparent_colors[index].opacity; + return true; + } + } + return false; +} + DynamicColor colorprofile_to_color(const ColorProfile *self, DynamicColor entry, DynamicColor defval) { switch(entry.type) { @@ -295,9 +322,10 @@ as_dict(ColorProfile *self, PyObject *args UNUSED) { }} D(default_fg, foreground); D(default_bg, background); D(cursor_color, cursor); D(cursor_text_color, cursor_text); D(highlight_fg, selection_foreground); - D(highlight_bg, selection_background); D(visual_bell_color, visual_bell_color); D(second_transparent_bg, second_transparent_bg); + D(highlight_bg, selection_background); D(visual_bell_color, visual_bell_color); #undef D + // TODO: Add transparent_colors return ans; } @@ -373,6 +401,8 @@ copy_color_table_to_buffer(ColorProfile *self, color_type *buf, int offset, size static void push_onto_color_stack_at(ColorProfile *self, unsigned int i) { + self->color_stack[i].dynamic_colors = self->overridden; + memcpy(self->color_stack[i].transparent_colors, self->overriden_transparent_colors, sizeof(self->overriden_transparent_colors)); self->color_stack[i].dynamic_colors = self->overridden; memcpy(self->color_stack[i].color_table, self->color_table, sizeof(self->color_stack->color_table)); } @@ -381,6 +411,7 @@ static void copy_from_color_stack_at(ColorProfile *self, unsigned int i) { self->overridden = self->color_stack[i].dynamic_colors; memcpy(self->color_table, self->color_stack[i].color_table, sizeof(self->color_table)); + memcpy(self->overriden_transparent_colors, self->color_stack[i].transparent_colors, sizeof(self->overriden_transparent_colors)); } bool @@ -477,7 +508,6 @@ CGETSET(cursor_text_color, true) CGETSET(highlight_fg, true) CGETSET(highlight_bg, true) CGETSET(visual_bell_color, true) -CGETSET(second_transparent_bg, true) #undef CGETSET static PyGetSetDef cp_getsetters[] = { @@ -488,7 +518,6 @@ static PyGetSetDef cp_getsetters[] = { GETSET(highlight_fg) GETSET(highlight_bg) GETSET(visual_bell_color) - GETSET(second_transparent_bg) {NULL} /* Sentinel */ }; @@ -552,7 +581,7 @@ new_color(PyTypeObject *type UNUSED, PyObject *args, PyObject *kwds) { } static PyObject* -color_as_int(Color *self) { +Color_as_int(Color *self) { return PyLong_FromUnsignedLong(self->color.val); } @@ -566,7 +595,7 @@ color_truediv(Color *self, PyObject *divisor) { } static PyNumberMethods color_number_methods = { - .nb_int = (unaryfunc)color_as_int, + .nb_int = (unaryfunc)Color_as_int, .nb_true_divide = (binaryfunc)color_truediv, }; diff --git a/kitty/data-types.h b/kitty/data-types.h index a2db1f318..a2d348ff6 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -323,15 +323,21 @@ typedef union DynamicColor { } DynamicColor; typedef struct { - DynamicColor default_fg, default_bg, cursor_color, cursor_text_color, highlight_fg, highlight_bg, visual_bell_color, second_transparent_bg; + DynamicColor default_fg, default_bg, cursor_color, cursor_text_color, highlight_fg, highlight_bg, visual_bell_color; } DynamicColors; +typedef struct TransparentDynamicColor { + color_type color; float opacity; bool is_set; +} TransparentDynamicColor; + + typedef struct { PyObject_HEAD bool dirty; uint32_t color_table[256], orig_color_table[256]; - struct { DynamicColors dynamic_colors; uint32_t color_table[256]; } *color_stack; + TransparentDynamicColor configured_transparent_colors[8], overriden_transparent_colors[8]; + struct { DynamicColors dynamic_colors; uint32_t color_table[256]; TransparentDynamicColor transparent_colors[8]; } *color_stack; unsigned int color_stack_idx, color_stack_sz; DynamicColors configured, overridden; color_type mark_foregrounds[MARK_MASK+1], mark_backgrounds[MARK_MASK+1]; @@ -403,6 +409,7 @@ bool schedule_write_to_child_python(unsigned long id, const char *prefix, PyObje bool set_iutf8(int, bool); DynamicColor colorprofile_to_color(const ColorProfile *self, DynamicColor entry, DynamicColor defval); +bool colorprofile_to_transparent_color(const ColorProfile *self, unsigned index, color_type *color, float *opacity); color_type colorprofile_to_color_with_fallback(ColorProfile *self, DynamicColor entry, DynamicColor defval, DynamicColor fallback, DynamicColor falback_defval); void copy_color_table_to_buffer(ColorProfile *self, color_type *address, int offset, size_t stride); diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index ffdd00c9c..a31b647bf 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -809,11 +809,6 @@ class ColorProfile: @visual_bell_color.setter def visual_bell_color(self, val: Union[None|int|Color]) -> None: ... - @property - def second_transparent_bg(self) -> Optional[Color]: ... - @second_transparent_bg.setter - def second_transparent_bg(self, val: Union[None|int|Color]) -> None: ... - def __init__(self, opts: Optional[Options] = None): ... def as_dict(self) -> Dict[str, Optional[int]]: diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 6d33750e2..ca81206cb 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -1527,7 +1527,7 @@ opt('background_image_linear', 'no', long_text='When background image is scaled, whether linear interpolation should be used.' ) -opt('transparent_background_colors', '', option_type='transparent_background_colors', ctype='!transparent_background_colors', long_text=''' +opt('transparent_background_colors', '', option_type='transparent_background_colors', long_text=''' A space separated list of upto 7 colors, with opacity. When the background color of a cell matches one of these colors, it is rendered semi-transparent using the specified opacity. diff --git a/kitty/options/parse.py b/kitty/options/parse.py index 5a0c685b9..46813e8c5 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -1194,9 +1194,6 @@ class Parser: def scrollback_pager_history_size(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: ans['scrollback_pager_history_size'] = scrollback_pager_history_size(val) - def second_transparent_bg(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: - ans['second_transparent_bg'] = to_color_or_none(val) - def select_by_word_characters(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: ans['select_by_word_characters'] = str(val) diff --git a/kitty/options/to-c-generated.h b/kitty/options/to-c-generated.h index 1ba5235c5..949905b9c 100644 --- a/kitty/options/to-c-generated.h +++ b/kitty/options/to-c-generated.h @@ -850,19 +850,6 @@ convert_from_opts_background_image_linear(PyObject *py_opts, Options *opts) { Py_DECREF(ret); } -static void -convert_from_python_transparent_background_colors(PyObject *val, Options *opts) { - transparent_background_colors(val, opts); -} - -static void -convert_from_opts_transparent_background_colors(PyObject *py_opts, Options *opts) { - PyObject *ret = PyObject_GetAttrString(py_opts, "transparent_background_colors"); - if (ret == NULL) return; - convert_from_python_transparent_background_colors(ret, opts); - Py_DECREF(ret); -} - static void convert_from_python_dynamic_background_opacity(PyObject *val, Options *opts) { opts->dynamic_background_opacity = PyObject_IsTrue(val); @@ -1242,8 +1229,6 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) { if (PyErr_Occurred()) return false; convert_from_opts_background_image_linear(py_opts, opts); if (PyErr_Occurred()) return false; - convert_from_opts_transparent_background_colors(py_opts, opts); - if (PyErr_Occurred()) return false; convert_from_opts_dynamic_background_opacity(py_opts, opts); if (PyErr_Occurred()) return false; convert_from_opts_background_tint(py_opts, opts); diff --git a/kitty/options/to-c.h b/kitty/options/to-c.h index f2ccb236a..1240ba678 100644 --- a/kitty/options/to-c.h +++ b/kitty/options/to-c.h @@ -441,17 +441,6 @@ window_logo_scale(PyObject *src, Options *opts) { opts->window_logo_scale.height = PyFloat_AsFloat(PyTuple_GET_ITEM(src, 1)); } -static void -transparent_background_colors(PyObject *src, Options *opts) { - memset(opts->transparent_background_colors, 0, sizeof(opts->transparent_background_colors)); - for (Py_ssize_t i = 0; i < MIN(PyTuple_GET_SIZE(src), (Py_ssize_t)arraysz(opts->transparent_background_colors)); i++) { - PyObject *e = PyTuple_GET_ITEM(src, i); - opts->transparent_background_colors[i].color = color_as_int(PyTuple_GET_ITEM(e, 0)); - opts->transparent_background_colors[i].opacity = PyFloat_AsFloat(PyTuple_GET_ITEM(e, 1)); - opts->transparent_background_colors[i].is_set = true; - } -} - static inline void resize_debounce_time(PyObject *src, Options *opts) { opts->resize_debounce_time.on_end = s_double_to_monotonic_t(PyFloat_AsDouble(PyTuple_GET_ITEM(src, 0))); diff --git a/kitty/options/types.py b/kitty/options/types.py index 2ae6b4d2e..69a194097 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -409,7 +409,6 @@ option_names = ( # {{{ 'scrollback_lines', 'scrollback_pager', 'scrollback_pager_history_size', - 'second_transparent_bg', 'select_by_word_characters', 'select_by_word_characters_forward', 'selection_background', @@ -575,7 +574,6 @@ class Options: scrollback_lines: int = 2000 scrollback_pager: typing.List[str] = ['less', '--chop-long-lines', '--RAW-CONTROL-CHARS', '+INPUT_LINE_NUMBER'] scrollback_pager_history_size: int = 0 - second_transparent_bg: typing.Optional[kitty.fast_data_types.Color] = None select_by_word_characters: str = '@-./_~?&=%+#' select_by_word_characters_forward: str = '' selection_background: typing.Optional[kitty.fast_data_types.Color] = Color(255, 250, 205) @@ -1037,7 +1035,6 @@ nullable_colors = frozenset({ 'active_border_color' 'tab_bar_background' 'tab_bar_margin_color' - 'second_transparent_bg' 'selection_foreground' 'selection_background' }) \ No newline at end of file diff --git a/kitty/shaders.c b/kitty/shaders.c index c3af3907c..ce96576a8 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -313,10 +313,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c rd->highlight_fg = COLOR(highlight_fg); rd->highlight_bg = COLOR(highlight_bg); rd->bg_colors0 = COLOR(default_bg); rd->bg_opacities0 = os_window->is_semi_transparent ? os_window->background_opacity : 1.0f; -#define SETBG(which) if (OPT(transparent_background_colors)[which-1].is_set) { \ - rd->bg_colors##which = OPT(transparent_background_colors)[which-1].color; \ - rd->bg_opacities##which = OPT(transparent_background_colors)[which-1].opacity < 0 ? rd->bg_opacities0 : OPT(transparent_background_colors)[which-1].opacity; \ -} else { rd->bg_colors##which = UINT32_MAX; } +#define SETBG(which) colorprofile_to_transparent_color(cp, which - 1, &rd->bg_colors##which, &rd->bg_opacities##which) SETBG(1); SETBG(2); SETBG(3); SETBG(4); SETBG(5); SETBG(6); SETBG(7); #undef SETBG // selection diff --git a/kitty/state.h b/kitty/state.h index c87428907..efae4d909 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -119,7 +119,6 @@ typedef struct { } *entries; } font_features; struct { Animation *cursor, *visual_bell; } animation; - struct { color_type color; float opacity; bool is_set; } transparent_background_colors[8]; } Options; typedef struct WindowLogoRenderData { diff --git a/kitty/window.py b/kitty/window.py index 8bbc5cac7..3657d0077 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -453,11 +453,12 @@ def color_control(cp: ColorProfile, code: int, value: Union[str, bytes, memoryvi responses = {} for rec in value.split(';'): key, sep, val = rec.partition('=') + # TODO: Add transparent_colors attr = { 'foreground': 'default_fg', 'background': 'default_bg', 'selection_background': 'highlight_bg', 'selection_foreground': 'highlight_fg', 'cursor': 'cursor_color', 'cursor_text': 'cursor_text_color', - 'visual_bell': 'visual_bell_color', 'second_transparent_background': 'second_transparent_bg', + 'visual_bell': 'visual_bell_color', }.get(key, '') colnum = -1 with suppress(Exception): diff --git a/tools/cmd/at/set_colors.go b/tools/cmd/at/set_colors.go index ff2ba9c97..0dbe5ddc0 100644 --- a/tools/cmd/at/set_colors.go +++ b/tools/cmd/at/set_colors.go @@ -15,15 +15,14 @@ import ( var nullable_colors = map[string]bool{ // generated by gen-config.py do not edit // NULLABLE_COLORS_START - "active_border_color": true, - "cursor": true, - "cursor_text_color": true, - "second_transparent_bg": true, - "selection_background": true, - "selection_foreground": true, - "tab_bar_background": true, - "tab_bar_margin_color": true, - "visual_bell_color": true, + "active_border_color": true, + "cursor": true, + "cursor_text_color": true, + "selection_background": true, + "selection_foreground": true, + "tab_bar_background": true, + "tab_bar_margin_color": true, + "visual_bell_color": true, // NULLABLE_COLORS_END } diff --git a/tools/themes/collection.go b/tools/themes/collection.go index 6e6be02f6..587acd23e 100644 --- a/tools/themes/collection.go +++ b/tools/themes/collection.go @@ -309,7 +309,6 @@ var AllColorSettingNames = map[string]bool{ // {{{ "mark2_foreground": true, "mark3_background": true, "mark3_foreground": true, - "second_transparent_bg": true, "selection_background": true, "selection_foreground": true, "tab_bar_background": true,