win: track number of in progress animations with transition callbacks

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2024-03-21 18:01:02 +00:00
parent c1d2a8fa40
commit 4b3688ddec
No known key found for this signature in database
GPG Key ID: D3A4405BE6CC17F4
3 changed files with 25 additions and 14 deletions

View File

@ -502,9 +502,8 @@ static bool run_fade(session_t *ps, struct managed_win **_w, unsigned int steps)
steps);
if (w->state == WSTATE_MAPPED || w->state == WSTATE_UNMAPPED) {
// We are not fading
assert(!animatable_is_animating(&w->opacity));
assert(!animatable_is_animating(&w->blur_opacity));
log_trace("|- not fading");
assert(w->number_of_animations == 0);
log_trace("|- not animated");
return false;
}
@ -513,8 +512,7 @@ static bool run_fade(session_t *ps, struct managed_win **_w, unsigned int steps)
animatable_early_stop(&w->opacity);
animatable_early_stop(&w->blur_opacity);
}
if (!animatable_is_animating(&w->opacity) &&
!animatable_is_animating(&w->blur_opacity)) {
if (w->number_of_animations == 0) {
// 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
@ -951,7 +949,7 @@ static bool paint_preprocess(session_t *ps, bool *fade_running, bool *animation,
// 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)) {
if (was_painted && w->number_of_animations != 0) {
add_damage_from_win(ps, w);
}

View File

@ -892,6 +892,11 @@ static double win_calc_opacity_target(session_t *ps, const struct managed_win *w
return opacity;
}
static void win_transition_callback(enum transition_event event attr_unused, void *data) {
auto w = (struct managed_win *)data;
w->number_of_animations--;
}
/// Call `animatable_set_target` on the opacity of a window, with appropriate
/// target opacity and duration.
///
@ -903,8 +908,9 @@ static inline unsigned int win_start_fade(session_t *ps, struct managed_win *w)
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);
w->number_of_animations++;
animatable_set_target(&w->opacity, target_opacity, duration,
NULL, NULL);
win_transition_callback, w);
return duration;
}
@ -2413,7 +2419,8 @@ void unmap_win_start(session_t *ps, struct managed_win *w) {
w->a.map_state = XCB_MAP_STATE_UNMAPPED;
w->state = WSTATE_UNMAPPING;
auto duration = win_start_fade(ps, w);
animatable_set_target(&w->blur_opacity, 0, duration, NULL, NULL);
w->number_of_animations++;
animatable_set_target(&w->blur_opacity, 0, duration, win_transition_callback, w);
#ifdef CONFIG_DBUS
// Send D-Bus signal
@ -2439,10 +2446,10 @@ void unmap_win_start(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(!animatable_is_animating(&w->opacity));
assert(w->number_of_animations == 0);
return false;
}
if (!animatable_is_animating(&w->opacity)) {
if (w->number_of_animations == 0) {
switch (w->state) {
case WSTATE_UNMAPPING: unmap_win_finish(ps, w); return false;
case WSTATE_DESTROYING: destroy_win_finish(ps, &w->base); return true;
@ -2461,7 +2468,7 @@ bool win_maybe_finalize_fading(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(!animatable_is_animating(&w->opacity));
assert(w->number_of_animations == 0);
return false;
}
log_debug("Skipping fading process of window %#010x (%s)", w->base.id, w->name);
@ -2528,7 +2535,8 @@ void map_win_start(session_t *ps, struct managed_win *w) {
// iff `state` is MAPPED
w->state = WSTATE_MAPPING;
auto duration = win_start_fade(ps, w);
animatable_set_target(&w->blur_opacity, 1, duration, NULL, NULL);
w->number_of_animations++;
animatable_set_target(&w->blur_opacity, 1, duration, win_transition_callback, w);
log_debug("Window %#010x has opacity %f, opacity target is %f", w->base.id,
animatable_get(&w->opacity), w->opacity.target);
@ -2561,7 +2569,7 @@ void map_win_start(session_t *ps, struct managed_win *w) {
void win_update_opacity_target(session_t *ps, struct managed_win *w) {
auto duration = win_start_fade(ps, w);
if (!animatable_is_animating(&w->opacity)) {
if (w->number_of_animations == 0) {
return;
}
@ -2573,8 +2581,9 @@ void win_update_opacity_target(session_t *ps, struct managed_win *w) {
} else if (w->state == WSTATE_MAPPING) {
// Opacity target changed while fading in, keep the blur_opacity
// in lock step with the opacity
w->number_of_animations++;
animatable_set_target(&w->blur_opacity, w->blur_opacity.target, duration,
NULL, NULL);
win_transition_callback, w);
log_debug("Opacity changed while fading in");
} else if (w->state == WSTATE_FADING) {
// Opacity target changed while FADING.

View File

@ -282,6 +282,10 @@ struct managed_win {
struct c2_window_state c2_state;
// Animation related
/// Number of animations currently in progress
unsigned int number_of_animations;
#ifdef CONFIG_OPENGL
/// Textures and FBO background blur use.
glx_blur_cache_t glx_blur_cache;