From 35b85155c58826992c888531a9a60e6dc5b5fef2 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Tue, 19 Mar 2024 16:44:02 +0000 Subject: [PATCH] win: use the new transition mechanism for fading Fading behavior is changed slightly when a window's opacity is changed while the window is already fading in/out. Signed-off-by: Yuxuan Shui --- src/backend/backend.c | 45 ++++++---------------- src/dbus.c | 8 +++- src/picom.c | 68 ++++++++++++++++----------------- src/render.c | 17 +++++---- src/win.c | 89 ++++++++++++++++++++----------------------- src/win.h | 29 ++++---------- 6 files changed, 110 insertions(+), 146 deletions(-) diff --git a/src/backend/backend.c b/src/backend/backend.c index 80b78a16..34e83e07 100644 --- a/src/backend/backend.c +++ b/src/backend/backend.c @@ -10,6 +10,7 @@ #include "config.h" #include "log.h" #include "region.h" +#include "transition.h" #include "types.h" #include "win.h" #include "x.h" @@ -253,45 +254,20 @@ bool paint_all_new(session_t *ps, struct managed_win *const t) { auto real_win_mode = w->mode; coord_t window_coord = {.x = w->g.x, .y = w->g.y}; + const double window_opacity = animatable_get(&w->opacity); if (w->blur_background && (ps->o.force_win_blend || real_win_mode == WMODE_TRANS || (ps->o.blur_background_frame && real_win_mode == WMODE_FRAME_TRANS))) { // Minimize the region we try to blur, if the window // itself is not opaque, only the frame is. - double blur_opacity = 1; - if (w->opacity < (1.0 / MAX_ALPHA)) { - // Hide blur for fully transparent windows. - blur_opacity = 0; - } else if (w->state == WSTATE_MAPPING) { - // Gradually increase the blur intensity during - // fading in. - assert(w->opacity <= w->opacity_target); - blur_opacity = w->opacity / w->opacity_target; - } else if (w->state == WSTATE_UNMAPPING || - w->state == WSTATE_DESTROYING) { - // Gradually decrease the blur intensity during - // fading out. - assert(w->opacity <= w->opacity_target_old); - blur_opacity = w->opacity / w->opacity_target_old; - } else if (w->state == WSTATE_FADING) { - if (w->opacity < w->opacity_target && - w->opacity_target_old < (1.0 / MAX_ALPHA)) { - // Gradually increase the blur intensity during - // fading in. - assert(w->opacity <= w->opacity_target); - blur_opacity = w->opacity / w->opacity_target; - } else if (w->opacity > w->opacity_target && - w->opacity_target < (1.0 / MAX_ALPHA)) { - // Gradually decrease the blur intensity during - // fading out. - assert(w->opacity <= w->opacity_target_old); - blur_opacity = w->opacity / w->opacity_target_old; - } - } + const double blur_opacity = animatable_get(&w->blur_opacity); assert(blur_opacity >= 0 && blur_opacity <= 1); - if (real_win_mode == WMODE_TRANS || ps->o.force_win_blend) { + if (blur_opacity * MAX_ALPHA < 1) { + // We don't need to blur if it would be completely + // transparent + } else if (real_win_mode == WMODE_TRANS || ps->o.force_win_blend) { // We need to blur the bounding shape of the window // (reg_paint_in_bound = reg_bound \cap reg_paint) ps->backend_data->ops->blur( @@ -404,7 +380,7 @@ bool paint_all_new(session_t *ps, struct managed_win *const t) { if (w->dim) { dim_opacity = ps->o.inactive_dim; if (!ps->o.inactive_dim_fixed) { - dim_opacity *= w->opacity; + dim_opacity *= window_opacity; } } @@ -418,7 +394,8 @@ bool paint_all_new(session_t *ps, struct managed_win *const t) { ps->backend_data, IMAGE_PROPERTY_DIM_LEVEL, w->win_image, &dim_opacity); ps->backend_data->ops->set_image_property( - ps->backend_data, IMAGE_PROPERTY_OPACITY, w->win_image, &w->opacity); + ps->backend_data, IMAGE_PROPERTY_OPACITY, w->win_image, + &window_opacity); ps->backend_data->ops->set_image_property( ps->backend_data, IMAGE_PROPERTY_CORNER_RADIUS, w->win_image, (double[]){w->corner_radius}); @@ -440,7 +417,7 @@ bool paint_all_new(session_t *ps, struct managed_win *const t) { w->fg_shader ? (void *)w->fg_shader->backend_shader : NULL); } - if (w->opacity * MAX_ALPHA < 1) { + if (window_opacity * MAX_ALPHA < 1) { // We don't need to paint the window body itself if it's // completely transparent. goto skip; diff --git a/src/dbus.c b/src/dbus.c index ca379fec..7dc83547 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -24,6 +24,7 @@ #include "list.h" #include "log.h" #include "string_utils.h" +#include "transition.h" #include "types.h" #include "uthash_extra.h" #include "utils.h" @@ -991,14 +992,17 @@ static bool cdbus_process_win_get(session_t *ps, DBusMessage *msg) { cdbus_m_win_get_do(class_general, cdbus_reply_string); cdbus_m_win_get_do(role, cdbus_reply_string); - cdbus_m_win_get_do(opacity, cdbus_reply_double); - cdbus_m_win_get_do(opacity_target, cdbus_reply_double); + cdbus_m_win_get_do(opacity.target, cdbus_reply_double); cdbus_m_win_get_do(has_opacity_prop, cdbus_reply_bool); cdbus_m_win_get_do(opacity_prop, cdbus_reply_uint32); cdbus_m_win_get_do(opacity_is_set, cdbus_reply_bool); cdbus_m_win_get_do(opacity_set, cdbus_reply_double); cdbus_m_win_get_do(frame_opacity, cdbus_reply_double); + if (strcmp(target, "opacity") == 0) { + cdbus_reply_double(ps, msg, animatable_get(&w->opacity)); + return true; + } if (!strcmp("left_width", target)) { cdbus_reply_int32(ps, msg, w->frame_extents.left); return true; diff --git a/src/picom.c b/src/picom.c index 1a9708fb..ee8b8d1d 100644 --- a/src/picom.c +++ b/src/picom.c @@ -48,6 +48,7 @@ #include "inspect.h" #include "kernel.h" #include "picom.h" +#include "transition.h" #include "win_defs.h" #ifdef CONFIG_OPENGL #include "opengl.h" @@ -495,22 +496,25 @@ static double fade_timeout(session_t *ps) { * @param steps steps of fading * @return whether we are still in fading mode */ -static bool run_fade(session_t *ps, struct managed_win **_w, long long steps) { +static bool run_fade(session_t *ps, struct managed_win **_w, unsigned int steps) { auto w = *_w; - log_trace("Process fading for window %s (%#010x), steps: %lld", w->name, - w->base.id, steps); + log_trace("Process fading for window %s (%#010x), steps: %u", w->name, w->base.id, + steps); if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { // We are not fading - assert(w->opacity_target == w->opacity); + assert(!animatable_is_animating(&w->opacity)); + assert(!animatable_is_animating(&w->blur_opacity)); log_trace("|- not fading"); return false; } if (!win_should_fade(ps, w)) { log_trace("|- in transition but doesn't need fading"); - w->opacity = w->opacity_target; + animatable_early_stop(&w->opacity); + animatable_early_stop(&w->blur_opacity); } - if (w->opacity == w->opacity_target) { + if (!animatable_is_animating(&w->opacity) && + !animatable_is_animating(&w->blur_opacity)) { // We have reached target opacity. // We don't call win_check_fade_finished here because that could destroy // the window, but we still need the damage info from this window @@ -518,20 +522,14 @@ static bool run_fade(session_t *ps, struct managed_win **_w, long long steps) { return false; } - log_trace("|- fading, opacity: %lf", w->opacity); - if (steps) { - if (w->opacity < w->opacity_target) { - w->opacity = clamp(w->opacity + ps->o.fade_in_step * (double)steps, - 0.0, w->opacity_target); - } else { - w->opacity = clamp(w->opacity - ps->o.fade_out_step * (double)steps, - w->opacity_target, 1); - } - log_trace("|- opacity updated: %lf", w->opacity); - } + log_trace("|- fading, opacity: %lf", animatable_get(&w->opacity)); + animatable_step(&w->opacity, steps); + animatable_step(&w->blur_opacity, steps); + log_trace("|- opacity updated: %lf (%u steps)", animatable_get(&w->opacity), steps); - // Note even if opacity == opacity_target here, we still want to run preprocess - // one last time to finish state transition. So return true in that case too. + // Note even if the animatable is not animating anymore at this point, we still + // want to run preprocess one last time to finish state transition. So return true + // in that case too. return true; } @@ -918,17 +916,19 @@ static bool paint_preprocess(session_t *ps, bool *fade_running, bool *animation, *out_bottom = NULL; // Fading step calculation - long long steps = 0L; + unsigned int steps = 0L; auto now = get_time_ms(); if (ps->fade_time) { assert(now >= ps->fade_time); - steps = (now - ps->fade_time) / ps->o.fade_delta; + auto raw_steps = (now - ps->fade_time) / ps->o.fade_delta; + assert(raw_steps <= UINT_MAX); + steps = (unsigned int)raw_steps; + ps->fade_time += raw_steps * ps->o.fade_delta; } else { // Reset fade_time if unset ps->fade_time = get_time_ms(); steps = 0L; } - ps->fade_time += steps * ps->o.fade_delta; // First, let's process fading, and animated shaders // TODO(yshui) check if a window is fully obscured, and if we don't need to @@ -936,7 +936,6 @@ static bool paint_preprocess(session_t *ps, bool *fade_running, bool *animation, win_stack_foreach_managed_safe(w, &ps->window_stack) { const winmode_t mode_old = w->mode; const bool was_painted = w->to_paint; - const double opacity_old = w->opacity; if (win_should_dim(ps, w) != w->dim) { w->dim = win_should_dim(ps, w); @@ -948,20 +947,20 @@ static bool paint_preprocess(session_t *ps, bool *fade_running, bool *animation, *animation = true; } + // Add window to damaged area if its opacity changes + // If was_painted == false, and to_paint is also false, we don't care + // If was_painted == false, but to_paint is true, damage will be added in + // the loop below + if (was_painted && animatable_is_animating(&w->opacity)) { + add_damage_from_win(ps, w); + } + // Run fading if (run_fade(ps, &w, steps)) { *fade_running = true; } - // Add window to damaged area if its opacity changes - // If was_painted == false, and to_paint is also false, we don't care - // If was_painted == false, but to_paint is true, damage will be added in - // the loop below - if (was_painted && w->opacity != opacity_old) { - add_damage_from_win(ps, w); - } - - if (win_check_fade_finished(ps, w)) { + if (win_maybe_finalize_fading(ps, w)) { // the window has been destroyed because fading finished continue; } @@ -994,6 +993,7 @@ static bool paint_preprocess(session_t *ps, bool *fade_running, bool *animation, bool to_paint = true; // w->to_paint remembers whether this window is painted last time const bool was_painted = w->to_paint; + const double window_opacity = animatable_get(&w->opacity); // Destroy reg_ignore if some window above us invalidated it if (!reg_ignore_valid) { @@ -1027,7 +1027,7 @@ static bool paint_preprocess(session_t *ps, bool *fade_running, bool *animation, w->g.x >= ps->root_width || w->g.y >= ps->root_height)) { log_trace("|- is positioned outside of the screen"); to_paint = false; - } else if (unlikely((double)w->opacity * MAX_ALPHA < 1 && !w->blur_background)) { + } else if (unlikely(window_opacity * MAX_ALPHA < 1 && !w->blur_background)) { /* TODO(yshui) for consistency, even a window has 0 opacity, we * still probably need to blur its background, so to_paint * shouldn't be false for them. */ @@ -1060,7 +1060,7 @@ static bool paint_preprocess(session_t *ps, bool *fade_running, bool *animation, log_verbose("Window %#010x (%s) will be painted", w->base.id, w->name); // Calculate shadow opacity - w->shadow_opacity = ps->o.shadow_opacity * w->opacity * ps->o.frame_opacity; + w->shadow_opacity = ps->o.shadow_opacity * window_opacity * ps->o.frame_opacity; // Generate ignore region for painting to reduce GPU load if (!w->reg_ignore) { diff --git a/src/render.c b/src/render.c index 31654433..b03a2102 100644 --- a/src/render.c +++ b/src/render.c @@ -12,6 +12,7 @@ #include "common.h" #include "options.h" +#include "transition.h" #ifdef CONFIG_OPENGL #include "backend/gl/glx.h" @@ -436,6 +437,7 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint) const int y = w->g.y; const uint16_t wid = to_u16_checked(w->widthb); const uint16_t hei = to_u16_checked(w->heightb); + const double window_opacity = animatable_get(&w->opacity); xcb_render_picture_t pict = w->paint.pict; @@ -472,7 +474,7 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint) } if (w->frame_opacity == 1) { - paint_region(ps, w, 0, 0, wid, hei, w->opacity, reg_paint, pict); + paint_region(ps, w, 0, 0, wid, hei, window_opacity, reg_paint, pict); } else { // Painting parameters const margin_t extents = win_calc_frame_extents(w); @@ -482,8 +484,8 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint) auto const r = extents.right; #define COMP_BDR(cx, cy, cwid, chei) \ - paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity * w->opacity, \ - reg_paint, pict) + paint_region(ps, w, (cx), (cy), (cwid), (chei), \ + w->frame_opacity *window_opacity, reg_paint, pict) // Sanitize the margins, in case some broken WM makes // top_width + bottom_width > height in some cases. @@ -542,7 +544,7 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint) // body paint_region(ps, w, cleft, ctop, body_width, body_height, - w->opacity, reg_paint, pict); + window_opacity, reg_paint, pict); } while (0); } @@ -557,7 +559,7 @@ void paint_one(session_t *ps, struct managed_win *w, const region_t *reg_paint) if (w->dim) { double dim_opacity = ps->o.inactive_dim; if (!ps->o.inactive_dim_fixed) { - dim_opacity *= w->opacity; + dim_opacity *= window_opacity; } switch (ps->o.backend) { @@ -899,12 +901,13 @@ win_blur_background(session_t *ps, struct managed_win *w, xcb_render_picture_t t auto const wid = to_u16_checked(w->widthb); auto const hei = to_u16_checked(w->heightb); const int cr = w ? w->corner_radius : 0; + const double window_opacity = animatable_get(&w->opacity); double factor_center = 1.0; // Adjust blur strength according to window opacity, to make it appear // better during fading if (!ps->o.blur_background_fixed) { - double pct = 1.0 - w->opacity * (1.0 - 1.0 / 9.0); + double pct = 1.0 - window_opacity * (1.0 - 1.0 / 9.0); factor_center = pct * 8.0 / (1.1 - pct); } @@ -1143,7 +1146,7 @@ void paint_all(session_t *ps, struct managed_win *t) { } // Only clip shadows above visible windows - if (w->opacity * MAX_ALPHA >= 1) { + if (animatable_get(&w->opacity) * MAX_ALPHA >= 1) { if (w->clip_shadow_above) { // Add window bounds to shadow-clip region pixman_region32_union(®_shadow_clip, ®_shadow_clip, diff --git a/src/win.c b/src/win.c index 78b5da84..8e96540f 100644 --- a/src/win.c +++ b/src/win.c @@ -27,6 +27,7 @@ #include "region.h" #include "render.h" #include "string_utils.h" +#include "transition.h" #include "types.h" #include "uthash_extra.h" #include "utils.h" @@ -799,7 +800,7 @@ bool win_client_has_alpha(const struct managed_win *w) { } winmode_t win_calc_mode(const struct managed_win *w) { - if (w->opacity < 1.0) { + if (animatable_get(&w->opacity) < 1.0) { return WMODE_TRANS; } @@ -846,7 +847,7 @@ winmode_t win_calc_mode(const struct managed_win *w) { * * @return target opacity */ -double win_calc_opacity_target(session_t *ps, const struct managed_win *w) { +static double win_calc_opacity_target(session_t *ps, const struct managed_win *w) { double opacity = 1; if (w->state == WSTATE_UNMAPPED) { @@ -882,6 +883,21 @@ double win_calc_opacity_target(session_t *ps, const struct managed_win *w) { return opacity; } +/// Call `animatable_set_target` on the opacity of a window, with appropriate +/// target opacity and duration. +/// +/// @return duration of the fade +static inline unsigned int win_start_fade(session_t *ps, struct managed_win *w) { + double current_opacity = animatable_get(&w->opacity), + target_opacity = win_calc_opacity_target(ps, w); + double step_size = + target_opacity > current_opacity ? ps->o.fade_in_step : ps->o.fade_out_step; + unsigned int duration = + (unsigned int)(fabs(target_opacity - current_opacity) / step_size); + animatable_set_target(&w->opacity, target_opacity, duration); + return duration; +} + /** * Determine whether a window is to be dimmed. */ @@ -1605,8 +1621,6 @@ struct win *attr_ret_nonnull maybe_allocate_managed_win(session_t *ps, struct wi .cache_leader = XCB_NONE, .window_type = WINTYPE_UNKNOWN, .focused = false, - .opacity = 0, - .opacity_target = 0, .has_opacity_prop = false, .opacity_prop = OPAQUE, .opacity_is_set = false, @@ -1685,6 +1699,8 @@ struct win *attr_ret_nonnull maybe_allocate_managed_win(session_t *ps, struct wi new->base = *w; new->base.managed = true; new->a = *a; + new->opacity = animatable_new(0, linear_interpolator, NULL); + new->blur_opacity = animatable_new(0, linear_interpolator, NULL); pixman_region32_init(&new->bounding_shape); free(a); @@ -2386,8 +2402,8 @@ void unmap_win_start(session_t *ps, struct managed_win *w) { w->a.map_state = XCB_MAP_STATE_UNMAPPED; w->state = WSTATE_UNMAPPING; - w->opacity_target_old = fmax(w->opacity_target, w->opacity_target_old); - w->opacity_target = win_calc_opacity_target(ps, w); + auto duration = win_start_fade(ps, w); + animatable_set_target(&w->blur_opacity, 0, duration); #ifdef CONFIG_DBUS // Send D-Bus signal @@ -2410,13 +2426,13 @@ void unmap_win_start(session_t *ps, struct managed_win *w) { * * @return whether the window is destroyed and freed */ -bool win_check_fade_finished(session_t *ps, struct managed_win *w) { +bool win_maybe_finalize_fading(session_t *ps, struct managed_win *w) { if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { // No fading in progress - assert(w->opacity_target == w->opacity); + assert(!animatable_is_animating(&w->opacity)); return false; } - if (w->opacity == w->opacity_target) { + if (!animatable_is_animating(&w->opacity)) { switch (w->state) { case WSTATE_UNMAPPING: unmap_win_finish(ps, w); return false; case WSTATE_DESTROYING: destroy_win_finish(ps, &w->base); return true; @@ -2435,12 +2451,13 @@ bool win_check_fade_finished(session_t *ps, struct managed_win *w) { /// @return whether the window is destroyed and freed bool win_skip_fading(session_t *ps, struct managed_win *w) { if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) { - assert(w->opacity_target == w->opacity); + assert(!animatable_is_animating(&w->opacity)); return false; } log_debug("Skipping fading process of window %#010x (%s)", w->base.id, w->name); - w->opacity = w->opacity_target; - return win_check_fade_finished(ps, w); + animatable_early_stop(&w->opacity); + animatable_early_stop(&w->blur_opacity); + return win_maybe_finalize_fading(ps, w); } // TODO(absolutelynothelix): rename to x_update_win_(randr_?)monitor and move to @@ -2514,11 +2531,11 @@ void map_win_start(session_t *ps, struct managed_win *w) { // XXX We need to make sure that win_data is available // iff `state` is MAPPED w->state = WSTATE_MAPPING; - w->opacity_target_old = 0; - w->opacity_target = win_calc_opacity_target(ps, w); + auto duration = win_start_fade(ps, w); + animatable_set_target(&w->blur_opacity, 1, duration); log_debug("Window %#010x has opacity %f, opacity target is %f", w->base.id, - w->opacity, w->opacity_target); + animatable_get(&w->opacity), w->opacity.target); // Cannot set w->ever_damaged = false here, since window mapping could be // delayed, so a damage event might have already arrived before this @@ -2546,49 +2563,25 @@ void map_win_start(session_t *ps, struct managed_win *w) { * Update target window opacity depending on the current state. */ void win_update_opacity_target(session_t *ps, struct managed_win *w) { - auto opacity_target_old = w->opacity_target; - w->opacity_target = win_calc_opacity_target(ps, w); + auto duration = win_start_fade(ps, w); - if (opacity_target_old == w->opacity_target) { + if (!animatable_is_animating(&w->opacity)) { return; } + log_debug("Window %#010x (%s) opacity %f, opacity target %f, start %f", w->base.id, + w->name, animatable_get(&w->opacity), w->opacity.target, w->opacity.start); if (w->state == WSTATE_MAPPED) { // Opacity target changed while MAPPED. Transition to FADING. - assert(w->opacity == opacity_target_old); - w->opacity_target_old = opacity_target_old; w->state = WSTATE_FADING; - log_debug("Window %#010x (%s) opacity %f, opacity target %f, set " - "old target %f", - w->base.id, w->name, w->opacity, w->opacity_target, - w->opacity_target_old); } else if (w->state == WSTATE_MAPPING) { - // Opacity target changed while fading in. - if (w->opacity >= w->opacity_target) { - // Already reached new target opacity. Transition to - // FADING. - map_win_finish(w); - w->opacity_target_old = fmax(opacity_target_old, w->opacity); - w->state = WSTATE_FADING; - log_debug("Window %#010x (%s) opacity %f already reached " - "new opacity target %f while mapping, set old " - "target %f", - w->base.id, w->name, w->opacity, w->opacity_target, - w->opacity_target_old); - } + // Opacity target changed while fading in, keep the blur_opacity + // in lock step with the opacity + animatable_set_target(&w->blur_opacity, w->blur_opacity.target, duration); + log_debug("Opacity changed while fading in"); } else if (w->state == WSTATE_FADING) { // Opacity target changed while FADING. - if ((w->opacity < opacity_target_old && w->opacity > w->opacity_target) || - (w->opacity > opacity_target_old && w->opacity < w->opacity_target)) { - // Changed while fading in and will fade out or while - // fading out and will fade in. - w->opacity_target_old = opacity_target_old; - log_debug("Window %#010x (%s) opacity %f already reached " - "new opacity target %f while fading, set " - "old target %f", - w->base.id, w->name, w->opacity, w->opacity_target, - w->opacity_target_old); - } + log_debug("Opacity changed while already fading"); } if (!ps->redirected) { diff --git a/src/win.h b/src/win.h index 7040669f..60310d9c 100644 --- a/src/win.h +++ b/src/win.h @@ -16,6 +16,7 @@ #include "list.h" #include "region.h" #include "render.h" +#include "transition.h" #include "types.h" #include "utils.h" #include "win_defs.h" @@ -204,12 +205,12 @@ struct managed_win { bool is_ewmh_focused; // Opacity-related members - /// Current window opacity. - double opacity; - /// Target window opacity. - double opacity_target; - /// Previous window opacity. - double opacity_target_old; + /// Window opacity + struct animatable opacity; + /// Opacity of the window's background blur + /// Used to gracefully fade in/out the window, otherwise the blur + /// would be at full/zero intensity immediately which will be jarring. + struct animatable blur_opacity; /// true if window (or client window, for broken window managers /// not transferring client window's _NET_WM_WINDOW_OPACITY value) has opacity /// prop @@ -326,20 +327,6 @@ bool attr_pure win_should_fade(session_t *ps, const struct managed_win *w); void win_on_factor_change(session_t *ps, struct managed_win *w); void win_unmark_client(session_t *ps, struct managed_win *w); -/** - * Calculate and return the opacity target of a window. - * - * The priority of opacity settings are: - * - * inactive_opacity_override (if set, and unfocused) > _NET_WM_WINDOW_OPACITY (if set) > - * opacity-rules (if matched) > window type default opacity > active/inactive opacity - * - * @param ps current session - * @param w struct _win object representing the window - * - * @return target opacity - */ -double attr_pure win_calc_opacity_target(session_t *ps, const struct managed_win *w); bool attr_pure win_should_dim(session_t *ps, const struct managed_win *w); void win_update_monitor(struct x_monitors *monitors, struct managed_win *mw); @@ -396,7 +383,7 @@ void restack_top(session_t *ps, struct win *w); /** * Execute fade callback of a window if fading finished. */ -bool must_use win_check_fade_finished(session_t *ps, struct managed_win *w); +bool must_use win_maybe_finalize_fading(session_t *ps, struct managed_win *w); // Stop receiving events (except ConfigureNotify, XXX why?) from a window void win_ev_stop(session_t *ps, const struct win *w);