diff --git a/src/animation/client.h b/src/animation/client.h index b151920..c098a7a 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -615,10 +615,15 @@ void fadeout_client_animation_next_tick(Client *c) { BufferData buffer_data; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + uint32_t passed_time = timespec_to_ms(&now) - c->animation.time_started; double animation_passed = - c->animation.total_frames - ? (double)c->animation.passed_frames / c->animation.total_frames + c->animation.duration + ? (double)passed_time / (double)c->animation.duration : 1.0; + int type = c->animation.action = c->animation.action; double factor = find_animation_curve_at(animation_passed, type); unsigned int width = @@ -662,20 +667,22 @@ void fadeout_client_animation_next_tick(Client *c) { &c->scene->node, snap_scene_buffer_apply_effect, &buffer_data); } - if (animation_passed == 1.0) { + if (animation_passed >= 1.0) { wl_list_remove(&c->fadeout_link); wlr_scene_node_destroy(&c->scene->node); free(c); c = NULL; - } else { - c->animation.passed_frames++; } } void client_animation_next_tick(Client *c) { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + uint32_t passed_time = timespec_to_ms(&now) - c->animation.time_started; double animation_passed = - c->animation.total_frames - ? (double)c->animation.passed_frames / c->animation.total_frames + c->animation.duration + ? (double)passed_time / (double)c->animation.duration : 1.0; int type = c->animation.action == NONE ? MOVE : c->animation.action; @@ -707,7 +714,7 @@ void client_animation_next_tick(Client *c) { c->is_pending_open_animation = false; - if (animation_passed == 1.0) { + if (animation_passed >= 1.0) { // clear the open action state // To prevent him from being mistaken that @@ -735,8 +742,6 @@ void client_animation_next_tick(Client *c) { // end flush in next frame, not the current frame c->need_output_flush = false; - } else { - c->animation.passed_frames++; } client_apply_clip(c, factor); @@ -820,9 +825,7 @@ void init_fadeout_client(Client *c) { fadeout_cient->geom.height * zoom_end_ratio; } - fadeout_cient->animation.passed_frames = 0; - fadeout_cient->animation.total_frames = - fadeout_cient->animation.duration / all_output_frame_duration_ms(); + fadeout_cient->animation.time_started = get_now_in_ms(); wlr_scene_node_set_enabled(&fadeout_cient->scene->node, true); wl_list_insert(&fadeout_clients, &fadeout_cient->fadeout_link); @@ -839,23 +842,11 @@ void client_commit(Client *c) { } c->animation.initial = c->animainit_geom; - // 设置动画速度 - c->animation.passed_frames = 0; - c->animation.total_frames = - c->animation.duration / all_output_frame_duration_ms(); + c->animation.time_started = get_now_in_ms(); // 标记动画开始 c->animation.running = true; c->animation.should_animate = false; - } else { - // 如果动画没有开始,且被判定为不应该动画, - // 则设置总帧数为1,不然其他地方一旦获取动画 - // 进度,总帧数作为分母会造成除零 - // 比如动画类型为none的时候 - if (!c->animation.running) { - c->animation.passed_frames = 1; - c->animation.total_frames = 1; - } } // 请求刷新屏幕 request_fresh_all_monitors(); @@ -1032,12 +1023,11 @@ bool client_draw_fadeout_frame(Client *c) { void client_set_focused_opacity_animation(Client *c) { float *border_color = get_border_color(c); + c->opacity_animation.duration = animation_duration_focus; memcpy(c->opacity_animation.target_border_color, border_color, sizeof(c->opacity_animation.target_border_color)); c->opacity_animation.target_opacity = c->focused_opacity; - c->opacity_animation.total_frames = - animation_duration_focus / all_output_frame_duration_ms(); - c->opacity_animation.passed_frames = 0; + c->opacity_animation.time_started = get_now_in_ms(); if (c->opacity_animation.running) { memcpy(c->opacity_animation.initial_border_color, c->opacity_animation.current_border_color, @@ -1058,13 +1048,12 @@ void client_set_focused_opacity_animation(Client *c) { void cleint_set_unfocused_opacity_animation(Client *c) { // Start border color animation to unfocused float *border_color = get_border_color(c); + c->opacity_animation.duration = animation_duration_focus; memcpy(c->opacity_animation.target_border_color, border_color, sizeof(c->opacity_animation.target_border_color)); // Start opacity animation to unfocused c->opacity_animation.target_opacity = c->unfocused_opacity; - c->opacity_animation.total_frames = - animation_duration_focus / all_output_frame_duration_ms(); - c->opacity_animation.passed_frames = 0; + c->opacity_animation.time_started = get_now_in_ms(); if (c->opacity_animation.running) { memcpy(c->opacity_animation.initial_border_color, @@ -1092,8 +1081,14 @@ bool client_apply_focus_opacity(Client *c) { client_set_opacity(c, 1); } else if (c->animation.running && c->animation.action == OPEN) { c->opacity_animation.running = false; - float linear_progress = - (float)c->animation.passed_frames / c->animation.total_frames; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + uint32_t passed_time = timespec_to_ms(&now) - c->animation.time_started; + double linear_progress = + c->animation.duration + ? (double)passed_time / (double)c->animation.duration + : 1.0; float percent = animation_fade_in && !c->nofadein ? linear_progress : 1.0; @@ -1107,8 +1102,17 @@ bool client_apply_focus_opacity(Client *c) { } client_set_opacity(c, target_opacity); } else if (animations && c->opacity_animation.running) { - float linear_progress = (float)c->opacity_animation.passed_frames / - c->opacity_animation.total_frames; + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + uint32_t passed_time = + timespec_to_ms(&now) - c->opacity_animation.time_started; + double linear_progress = + c->opacity_animation.duration + ? (double)passed_time / (double)c->opacity_animation.duration + : 1.0; + float eased_progress = find_animation_curve_at(linear_progress, FOCUS); c->opacity_animation.current_opacity = @@ -1130,7 +1134,6 @@ bool client_apply_focus_opacity(Client *c) { if (linear_progress == 1.0f) { c->opacity_animation.running = false; } else { - c->opacity_animation.passed_frames++; return true; } } else if (c == selmon->sel) { diff --git a/src/animation/common.h b/src/animation/common.h index edd39b0..06ffe1a 100644 --- a/src/animation/common.h +++ b/src/animation/common.h @@ -86,22 +86,6 @@ double find_animation_curve_at(double t, int type) { return baked_points[up].y; } -double all_output_frame_duration_ms() { - int32_t refresh_total = 0; - Monitor *m = NULL; - wl_list_for_each(m, &mons, link) { - if (!m->wlr_output->enabled) { - continue; - } - refresh_total += m->wlr_output->refresh; - } - return 1000000.0 / refresh_total; -} - -double output_frame_duration_ms(Monitor *m) { - return 1000000.0 / m->wlr_output->refresh; -} - static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly, struct wlr_scene_tree *snapshot_tree) { if (!node->enabled && node->type != WLR_SCENE_NODE_TREE) { diff --git a/src/animation/layer.h b/src/animation/layer.h index 2487a9c..48ceb21 100644 --- a/src/animation/layer.h +++ b/src/animation/layer.h @@ -234,10 +234,15 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) { if (!l) return; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + uint32_t passed_time = timespec_to_ms(&now) - l->animation.time_started; double animation_passed = - l->animation.total_frames - ? (double)l->animation.passed_frames / l->animation.total_frames + l->animation.duration + ? (double)passed_time / (double)l->animation.duration : 1.0; + int type = l->animation.action = l->animation.action; double factor = find_animation_curve_at(animation_passed, type); unsigned int width = @@ -280,13 +285,11 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) { wlr_scene_node_for_each_buffer(&l->scene->node, scene_buffer_apply_opacity, &opacity); - if (animation_passed == 1.0) { + if (animation_passed >= 1.0) { wl_list_remove(&l->fadeout_link); wlr_scene_node_destroy(&l->scene->node); free(l); l = NULL; - } else { - l->animation.passed_frames++; } } @@ -295,9 +298,13 @@ void layer_animation_next_tick(LayerSurface *l) { if (!l || !l->mapped) return; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + uint32_t passed_time = timespec_to_ms(&now) - l->animation.time_started; double animation_passed = - l->animation.total_frames - ? (double)l->animation.passed_frames / l->animation.total_frames + l->animation.duration + ? (double)passed_time / (double)l->animation.duration : 1.0; int type = l->animation.action == NONE ? MOVE : l->animation.action; @@ -349,12 +356,10 @@ void layer_animation_next_tick(LayerSurface *l) { .height = height, }; - if (animation_passed == 1.0) { + if (animation_passed >= 1.0) { l->animation.running = false; l->need_output_flush = false; l->animation.action = MOVE; - } else { - l->animation.passed_frames++; } } @@ -448,10 +453,8 @@ void init_fadeout_layers(LayerSurface *l) { fadeout_layer->current.height = 0; } - // 计算动画帧数 - fadeout_layer->animation.passed_frames = 0; - fadeout_layer->animation.total_frames = - fadeout_layer->animation.duration / all_output_frame_duration_ms(); + // 动画开始时间 + fadeout_layer->animation.time_started = get_now_in_ms(); // 将节点插入到关闭动画链表中,屏幕刷新哪里会检查链表中是否有节点可以应用于动画 wlr_scene_node_set_enabled(&fadeout_layer->scene->node, true); @@ -534,23 +537,11 @@ 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.running = true; l->animation.should_animate = false; - } else { - // 如果动画没有开始,且被判定为不应该动画, - // 则设置总帧数为1,不然其他地方一旦获取动画 - // 进度,总帧数作为分母会造成除零 - // 比如动画类型为none的时候 - if (!l->animation.running) { - l->animation.passed_frames = 1; - l->animation.total_frames = 1; - } } // 请求刷新屏幕 wlr_output_schedule_frame(l->mon->wlr_output); diff --git a/src/common/util.c b/src/common/util.c index 272340c..6eadbc6 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "util.h" @@ -80,3 +81,15 @@ int regex_match(const char *pattern, const char *str) { void wl_list_append(struct wl_list *list, struct wl_list *object) { wl_list_insert(list->prev, object); } + +unsigned int get_now_in_ms(void) { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + return timespec_to_ms(&now); +} + +unsigned int timespec_to_ms(struct timespec *ts) { + return (unsigned int)ts->tv_sec * 1000 + + (unsigned int)ts->tv_nsec / 1000000; +} diff --git a/src/common/util.h b/src/common/util.h index 2ebef43..3a0f6da 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -6,3 +6,5 @@ void *ecalloc(size_t nmemb, size_t size); int fd_set_nonblock(int fd); int regex_match(const char *pattern_mb, const char *str_mb); void wl_list_append(struct wl_list *list, struct wl_list *object); +unsigned int get_now_in_ms(void); +unsigned int timespec_to_ms(struct timespec *ts); \ No newline at end of file diff --git a/src/mango.c b/src/mango.c index 0779e9f..690775b 100644 --- a/src/mango.c +++ b/src/mango.c @@ -231,8 +231,7 @@ struct dwl_animation { bool tagouting; bool begin_fade_in; bool tag_from_rule; - unsigned int total_frames; - unsigned int passed_frames; + unsigned int time_started; unsigned int duration; struct wlr_box initial; struct wlr_box current; @@ -244,8 +243,8 @@ struct dwl_opacity_animation { float current_opacity; float target_opacity; float initial_opacity; - unsigned int total_frames; - unsigned int passed_frames; + unsigned int time_started; + unsigned int duration; float current_border_color[4]; float target_border_color[4]; float initial_border_color[4];