diff --git a/src/animation/client.h b/src/animation/client.h index d6a1682..6c73531 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -666,7 +666,7 @@ int fadeout_client_animation_next_tick(void *data) { } if (animation_passed >= 1.0) { - destroy_animation_timer(c); + client_destroy_animation_timer(c); wl_list_remove(&c->fadeout_link); wlr_scene_node_destroy(&c->scene->node); free(c); @@ -717,7 +717,7 @@ int client_animation_next_tick(void *data) { c->is_pending_open_animation = false; if (animation_passed >= 1.0) { - + client_destroy_animation_timer(c); // clear the open action state // To prevent him from being mistaken that // it's still in the opening animation in resize @@ -744,7 +744,6 @@ int client_animation_next_tick(void *data) { // end flush in next frame, not the current frame c->need_output_flush = false; - destroy_animation_timer(c); } else { wl_event_source_timer_update(c->animation.timer, c->animation.frame_duration); } diff --git a/src/animation/common.h b/src/animation/common.h index 33c3d55..665a717 100644 --- a/src/animation/common.h +++ b/src/animation/common.h @@ -277,9 +277,16 @@ void request_fresh_all_monitors(void) { } } -void destroy_animation_timer(Client *c) { +void client_destroy_animation_timer(Client *c) { if(c->animation.timer) { wl_event_source_remove(c->animation.timer); c->animation.timer = NULL; } +} + +void layer_destroy_animation_timer(LayerSurface *l) { + if(l->animation.timer) { + wl_event_source_remove(l->animation.timer); + l->animation.timer = NULL; + } } \ No newline at end of file diff --git a/src/animation/layer.h b/src/animation/layer.h index 2487a9c..666c6c2 100644 --- a/src/animation/layer.h +++ b/src/animation/layer.h @@ -290,15 +290,15 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) { } } -void layer_animation_next_tick(LayerSurface *l) { +int layer_animation_next_tick(void *data) { - if (!l || !l->mapped) - return; + LayerSurface *l = (LayerSurface *)data; - double animation_passed = - l->animation.total_frames - ? (double)l->animation.passed_frames / l->animation.total_frames - : 1.0; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + uint32_t passed_time = timespec_to_ms(&now) - l->animation.time_started; + double animation_passed = (double)passed_time / (double)l->animation.duration; int type = l->animation.action == NONE ? MOVE : l->animation.action; double factor = find_animation_curve_at(animation_passed, type); @@ -350,12 +350,23 @@ void layer_animation_next_tick(LayerSurface *l) { }; if (animation_passed == 1.0) { + layer_destroy_animation_timer(l); l->animation.running = false; l->need_output_flush = false; l->animation.action = MOVE; } else { - l->animation.passed_frames++; + wl_event_source_timer_update(l->animation.timer, l->animation.frame_duration); } + + layer_draw_shadow(l); + + if(l->animation.running) { + wlr_output_schedule_frame(l->mon->wlr_output); + return 1; + } else { + return 0; + } + } void init_fadeout_layers(LayerSurface *l) { @@ -535,9 +546,13 @@ void layer_commit(LayerSurface *l) { l->animation.initial = l->animainit_geom; // 设置动画速度 - l->animation.passed_frames = 0; - l->animation.total_frames = - l->animation.duration / output_frame_duration_ms(l->mon); + l->animation.time_started = get_now_in_ms(); + l->animation.frame_duration = get_fastest_output_refresh_ms(); + if(!l->animation.running) + l->animation.timer = + wl_event_loop_add_timer(wl_display_get_event_loop(dpy), layer_animation_next_tick, l); + wl_event_source_timer_update(l->animation.timer, l->animation.frame_duration); + // 标记动画开始 l->animation.running = true; @@ -570,8 +585,10 @@ bool layer_draw_frame(LayerSurface *l) { } if (animations && layer_animations && l->animation.running && !l->noanim) { - layer_animation_next_tick(l); - layer_draw_shadow(l); + if(!l->animation.nofirstframe) { + layer_animation_next_tick(l); + l->animation.nofirstframe = true; + } } else { layer_draw_shadow(l); l->need_output_flush = false; diff --git a/src/mango.c b/src/mango.c index f18793e..3565e5c 100644 --- a/src/mango.c +++ b/src/mango.c @@ -710,7 +710,7 @@ static void init_client_properties(Client *c); static float *get_border_color(Client *c); static void request_fresh_all_monitors(void); static int get_fastest_output_refresh_ms(void); -static void destroy_animation_timer(Client *c); +static void client_destroy_animation_timer(Client *c); #include "data/static_keymap.h" #include "dispatch/bind_declare.h" @@ -5168,6 +5168,8 @@ void unmaplayersurfacenotify(struct wl_listener *listener, void *data) { l->mapped = 0; + layer_destroy_animation_timer(l); + init_fadeout_layers(l); wlr_scene_node_set_enabled(&l->scene->node, false); @@ -5187,7 +5189,7 @@ void unmapnotify(struct wl_listener *listener, void *data) { Monitor *m = NULL; c->iskilling = 1; - destroy_animation_timer(c); + client_destroy_animation_timer(c); if (animations && !c->is_clip_to_hide && !c->isminied && (!c->mon || VISIBLEON(c, c->mon)))