From 110b13dc98151b3a0af47eebb12d3c965e323821 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 22 Aug 2025 11:57:29 +0530 Subject: [PATCH] Make calculation of OS Window background opacity centralised --- kitty/child-monitor.c | 2 +- kitty/glfw.c | 14 +++++++------- kitty/shaders.c | 19 ++++++++++--------- kitty/state.c | 8 ++++---- kitty/state.h | 9 +++++++-- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index f99d6a52f..df9b375f4 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -710,7 +710,7 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int * bool needs_render = os_window->needs_render; os_window->needs_render = false; os_window->needs_layers = ( - !global_state.supports_framebuffer_srgb || os_window->is_semi_transparent || + !global_state.supports_framebuffer_srgb || effective_os_window_alpha(os_window) < 1.f || os_window->live_resize.in_progress || (os_window->bgimage && os_window->bgimage->texture_id > 0) ); if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) { diff --git a/kitty/glfw.c b/kitty/glfw.c index c4102056d..d34ba1606 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -178,7 +178,7 @@ static void get_window_content_scale(GLFWwindow *w, float *xscale, float *yscale static bool set_layer_shell_config_for(OSWindow *w, GLFWLayerShellConfig *lsc) { if (lsc) { - lsc->related.background_opacity = w->background_opacity; + lsc->related.background_opacity = effective_os_window_alpha(w); lsc->related.background_blur = OPT(background_blur); lsc->related.color_space = OPT(macos_colorspace); w->hide_on_focus_loss = lsc->hide_on_focus_loss; @@ -1121,9 +1121,9 @@ intercept_cocoa_fullscreen(GLFWwindow *w) { #endif static void -init_window_chrome_state(WindowChromeState *s, color_type active_window_bg, bool is_semi_transparent, float background_opacity) { +init_window_chrome_state(WindowChromeState *s, color_type active_window_bg, float background_opacity) { zero_at_ptr(s); - const bool should_blur = background_opacity < 1.f && OPT(background_blur) > 0 && is_semi_transparent; + const bool should_blur = background_opacity < 1.f && OPT(background_blur) > 0; #define SET_TCOL(val) \ s->use_system_color = false; \ switch (val & 0xff) { \ @@ -1191,7 +1191,7 @@ set_os_window_chrome(OSWindow *w) { } WindowChromeState new_state; - init_window_chrome_state(&new_state, bg, w->is_semi_transparent, w->background_opacity); + init_window_chrome_state(&new_state, bg, effective_os_window_alpha(w)); if (memcmp(&new_state, &w->last_window_chrome, sizeof(WindowChromeState)) != 0) { int width, height; glfwGetWindowSize(w->handle, &width, &height); @@ -1533,15 +1533,15 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { w->last_mouse_activity_at = now; w->mouse_activate_deadline = -1; w->mouse_show_threshold = 0; - w->is_semi_transparent = is_semi_transparent; - if (want_semi_transparent && !w->is_semi_transparent) { + w->background_opacity.supports_transparency = is_semi_transparent; + if (want_semi_transparent && !w->background_opacity.supports_transparency) { static bool warned = false; if (!warned) { log_error("Failed to enable transparency. This happens when your desktop environment does not support compositing."); warned = true; } } - init_window_chrome_state(&w->last_window_chrome, OPT(background), w->is_semi_transparent, w->background_opacity); + init_window_chrome_state(&w->last_window_chrome, OPT(background), effective_os_window_alpha(w)); if (w->is_layer_shell) { if (global_state.is_apple) set_layer_shell_config_for(w, lsc); } else apply_window_chrome_state( diff --git a/kitty/shaders.c b/kitty/shaders.c index cb9b991df..452481c82 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -32,7 +32,7 @@ typedef struct UIRenderData { Window *window; Screen *screen; OSWindow *os_window; GraphicsRenderData grd; WindowLogoRenderData *window_logo; - float inactive_text_alpha; + float bg_alpha, inactive_text_alpha; bool has_background_image; color_type background_color; // RGB only } UIRenderData; @@ -434,7 +434,7 @@ has_bgimage(OSWindow *w) { } static color_type -cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, CursorRenderInfo *cursor, OSWindow *os_window, float inactive_text_alpha) { +cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, CursorRenderInfo *cursor, OSWindow *os_window, float inactive_text_alpha, float bg_alpha) { struct GPUCellRenderData { GLfloat use_cell_bg_for_selection_fg, use_cell_fg_for_selection_color, use_cell_for_selection_bg; @@ -457,7 +457,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, C rd->default_fg = COLOR(default_fg); 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; + rd->bg_opacities0 = bg_alpha; #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); @@ -805,7 +805,7 @@ render_a_bar(const UIRenderData *ui, WindowBarData *bar, PyObject *title, bool a const unsigned sh = ui->full_framebuffer_height; // first blank the area to be drawn to background enable_scissor_using_top_left_origin(border_rect, sh); - blank_canvas(ui->os_window->is_semi_transparent ? ui->os_window->background_opacity : 1.f, bg, false); + blank_canvas(ui->bg_alpha, bg, false); disable_scissor(); // then draw the rendered text save_viewport_using_top_left_origin( @@ -1034,9 +1034,10 @@ draw_cells(const WindowRenderData *srd, OSWindow *os_window, bool is_active_wind // - There's only a single window and the os window is not focused // - There are multiple windows and the current window is not active float current_inactive_text_alpha = is_tab_bar || (!is_single_window && is_active_window) || (is_single_window && screen->cursor_render_info.is_focused) ? 1.0f : (float)OPT(inactive_text_alpha); + float bg_alpha = effective_os_window_alpha(os_window); color_type default_bg = cell_update_uniform_block( - srd->vao_idx, screen, uniform_buffer, &screen->cursor_render_info, os_window, current_inactive_text_alpha); + srd->vao_idx, screen, uniform_buffer, &screen->cursor_render_info, os_window, current_inactive_text_alpha, bg_alpha); set_cell_uniforms(screen->reload_all_gpu_data); WindowLogoRenderData *wl; if (window && (wl = &window->window_logo) && wl->id && (wl->instance = find_window_logo(global_state.all_window_logos, wl->id)) && wl->instance->load_from_disk_ok) { @@ -1054,7 +1055,7 @@ draw_cells(const WindowRenderData *srd, OSWindow *os_window, bool is_active_wind .full_framebuffer_width = os_window->viewport_width, .full_framebuffer_height = os_window->viewport_height, .window = window, .screen = screen, .os_window = os_window, .grd = grman_render_data(grman), .window_logo = wl, .inactive_text_alpha = current_inactive_text_alpha, .has_background_image = has_bgimage(os_window), - .background_color = default_bg, + .background_color = default_bg, .bg_alpha=effective_os_window_alpha(os_window), }; screen->reload_all_gpu_data = false; save_viewport_using_top_left_origin( @@ -1094,7 +1095,7 @@ create_border_vao(void) { void draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_buf, bool rect_data_is_dirty, color_type active_window_bg, unsigned int num_visible_windows, bool all_windows_have_same_bg, OSWindow *w) { - float background_opacity = w->is_semi_transparent ? w->background_opacity: 1.0f; + float background_opacity = effective_os_window_alpha(w); if (!num_border_rects) return; bind_program(BORDERS_PROGRAM); bind_vertex_array(vao_idx); const bool has_background_image = has_bgimage(w); @@ -1153,7 +1154,7 @@ draw_bg_image(OSWindow *os_window) { BackgroundImageRenderSettings s = { .os_window.width = os_window->viewport_width, .os_window.height = os_window->viewport_height, .instance_id = os_window->bgimage->id, .layout=OPT(background_image_layout), - .linear=OPT(background_image_linear), .bgcolor=OPT(background), .opacity=os_window->background_opacity, + .linear=OPT(background_image_linear), .bgcolor=OPT(background), .opacity=effective_os_window_alpha(os_window), }; bind_program(BGIMAGE_PROGRAM); GLfloat iwidth = os_window->bgimage->width, iheight = os_window->bgimage->height; @@ -1242,7 +1243,7 @@ blank_os_window(OSWindow *osw) { } } } - blank_canvas(osw->is_semi_transparent ? osw->background_opacity : 1.0f, color, true); + blank_canvas(effective_os_window_alpha(osw), color, true); } static void diff --git a/kitty/state.c b/kitty/state.c index fa5951649..059b4c50c 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -216,7 +216,7 @@ add_os_window(void) { zero_at_ptr(ans); ans->id = ++global_state.os_window_id_counter; ans->tab_bar_render_data.vao_idx = create_cell_vao(); - ans->background_opacity = OPT(background_opacity); + ans->background_opacity.alpha = OPT(background_opacity); ans->created_at = monotonic(); bool wants_bg = OPT(background_image) && OPT(background_image)[0] != 0; @@ -958,7 +958,7 @@ PYWRAP1(change_background_opacity) { float opacity; PA("Kf", &os_window_id, &opacity); WITH_OS_WINDOW(os_window_id) - os_window->background_opacity = opacity; + os_window->background_opacity.alpha = opacity; if (!os_window->redraw_count) os_window->redraw_count++; set_os_window_chrome(os_window); // on macOS titlebar opacity can depend on background_opacity Py_RETURN_TRUE; @@ -970,7 +970,7 @@ PYWRAP1(background_opacity_of) { id_type os_window_id = PyLong_AsUnsignedLongLong(args); if (PyErr_Occurred()) return NULL; WITH_OS_WINDOW(os_window_id) - return PyFloat_FromDouble((double)os_window->background_opacity); + return PyFloat_FromDouble((double)effective_os_window_alpha(os_window)); END_WITH_OS_WINDOW Py_RETURN_NONE; } @@ -1169,7 +1169,7 @@ PYWRAP0(apply_options_update) { for (size_t o = 0; o < global_state.num_os_windows; o++) { OSWindow *os_window = global_state.os_windows + o; get_platform_dependent_config_values(os_window->handle); - os_window->background_opacity = OPT(background_opacity); + os_window->background_opacity.alpha = OPT(background_opacity); if (!os_window->redraw_count) os_window->redraw_count++; for (size_t t = 0; t < os_window->num_tabs; t++) { Tab *tab = os_window->tabs + t; diff --git a/kitty/state.h b/kitty/state.h index e0d06e72c..0f6391950 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -313,10 +313,10 @@ typedef struct OSWindow { bool viewport_size_dirty, viewport_updated_at_least_once; monotonic_t viewport_resized_at; LiveResizeInfo live_resize; - bool has_pending_resizes, is_semi_transparent, shown_once, ignore_resize_events; + bool has_pending_resizes, shown_once, ignore_resize_events; unsigned int redraw_count; WindowChromeState last_window_chrome; - float background_opacity; + struct { float alpha; bool os_forces_opaque, supports_transparency; } background_opacity; FONTS_DATA_HANDLE fonts_data; id_type temp_font_group_id; enum RENDER_STATE render_state; @@ -327,6 +327,11 @@ typedef struct OSWindow { bool is_layer_shell, hide_on_focus_loss; } OSWindow; +static inline float +effective_os_window_alpha(OSWindow *w) { + return (!w->background_opacity.supports_transparency || w->background_opacity.os_forces_opaque) ? + 1.f : w->background_opacity.alpha; +} typedef struct GlobalState { Options opts;