Make calculation of OS Window background opacity centralised

This commit is contained in:
Kovid Goyal 2025-08-22 11:57:29 +05:30
parent 3483f99d09
commit 110b13dc98
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
5 changed files with 29 additions and 23 deletions

View file

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

View file

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

View file

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

View file

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

View file

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