feat: Calculate animation curve by time points rather than passed frames
This commit is contained in:
@@ -615,10 +615,15 @@ void fadeout_client_animation_next_tick(Client *c) {
|
|||||||
|
|
||||||
BufferData buffer_data;
|
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 =
|
double animation_passed =
|
||||||
c->animation.total_frames
|
c->animation.duration
|
||||||
? (double)c->animation.passed_frames / c->animation.total_frames
|
? (double)passed_time / (double)c->animation.duration
|
||||||
: 1.0;
|
: 1.0;
|
||||||
|
|
||||||
int type = c->animation.action = c->animation.action;
|
int type = c->animation.action = c->animation.action;
|
||||||
double factor = find_animation_curve_at(animation_passed, type);
|
double factor = find_animation_curve_at(animation_passed, type);
|
||||||
unsigned int width =
|
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);
|
&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);
|
wl_list_remove(&c->fadeout_link);
|
||||||
wlr_scene_node_destroy(&c->scene->node);
|
wlr_scene_node_destroy(&c->scene->node);
|
||||||
free(c);
|
free(c);
|
||||||
c = NULL;
|
c = NULL;
|
||||||
} else {
|
|
||||||
c->animation.passed_frames++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_animation_next_tick(Client *c) {
|
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 =
|
double animation_passed =
|
||||||
c->animation.total_frames
|
c->animation.duration
|
||||||
? (double)c->animation.passed_frames / c->animation.total_frames
|
? (double)passed_time / (double)c->animation.duration
|
||||||
: 1.0;
|
: 1.0;
|
||||||
|
|
||||||
int type = c->animation.action == NONE ? MOVE : c->animation.action;
|
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;
|
c->is_pending_open_animation = false;
|
||||||
|
|
||||||
if (animation_passed == 1.0) {
|
if (animation_passed >= 1.0) {
|
||||||
|
|
||||||
// clear the open action state
|
// clear the open action state
|
||||||
// To prevent him from being mistaken that
|
// 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
|
// end flush in next frame, not the current frame
|
||||||
c->need_output_flush = false;
|
c->need_output_flush = false;
|
||||||
} else {
|
|
||||||
c->animation.passed_frames++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client_apply_clip(c, factor);
|
client_apply_clip(c, factor);
|
||||||
@@ -820,9 +825,7 @@ void init_fadeout_client(Client *c) {
|
|||||||
fadeout_cient->geom.height * zoom_end_ratio;
|
fadeout_cient->geom.height * zoom_end_ratio;
|
||||||
}
|
}
|
||||||
|
|
||||||
fadeout_cient->animation.passed_frames = 0;
|
fadeout_cient->animation.time_started = get_now_in_ms();
|
||||||
fadeout_cient->animation.total_frames =
|
|
||||||
fadeout_cient->animation.duration / all_output_frame_duration_ms();
|
|
||||||
wlr_scene_node_set_enabled(&fadeout_cient->scene->node, true);
|
wlr_scene_node_set_enabled(&fadeout_cient->scene->node, true);
|
||||||
wl_list_insert(&fadeout_clients, &fadeout_cient->fadeout_link);
|
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.initial = c->animainit_geom;
|
||||||
// 设置动画速度
|
c->animation.time_started = get_now_in_ms();
|
||||||
c->animation.passed_frames = 0;
|
|
||||||
c->animation.total_frames =
|
|
||||||
c->animation.duration / all_output_frame_duration_ms();
|
|
||||||
|
|
||||||
// 标记动画开始
|
// 标记动画开始
|
||||||
c->animation.running = true;
|
c->animation.running = true;
|
||||||
c->animation.should_animate = false;
|
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();
|
request_fresh_all_monitors();
|
||||||
@@ -1032,12 +1023,11 @@ bool client_draw_fadeout_frame(Client *c) {
|
|||||||
|
|
||||||
void client_set_focused_opacity_animation(Client *c) {
|
void client_set_focused_opacity_animation(Client *c) {
|
||||||
float *border_color = get_border_color(c);
|
float *border_color = get_border_color(c);
|
||||||
|
c->opacity_animation.duration = animation_duration_focus;
|
||||||
memcpy(c->opacity_animation.target_border_color, border_color,
|
memcpy(c->opacity_animation.target_border_color, border_color,
|
||||||
sizeof(c->opacity_animation.target_border_color));
|
sizeof(c->opacity_animation.target_border_color));
|
||||||
c->opacity_animation.target_opacity = c->focused_opacity;
|
c->opacity_animation.target_opacity = c->focused_opacity;
|
||||||
c->opacity_animation.total_frames =
|
c->opacity_animation.time_started = get_now_in_ms();
|
||||||
animation_duration_focus / all_output_frame_duration_ms();
|
|
||||||
c->opacity_animation.passed_frames = 0;
|
|
||||||
if (c->opacity_animation.running) {
|
if (c->opacity_animation.running) {
|
||||||
memcpy(c->opacity_animation.initial_border_color,
|
memcpy(c->opacity_animation.initial_border_color,
|
||||||
c->opacity_animation.current_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) {
|
void cleint_set_unfocused_opacity_animation(Client *c) {
|
||||||
// Start border color animation to unfocused
|
// Start border color animation to unfocused
|
||||||
float *border_color = get_border_color(c);
|
float *border_color = get_border_color(c);
|
||||||
|
c->opacity_animation.duration = animation_duration_focus;
|
||||||
memcpy(c->opacity_animation.target_border_color, border_color,
|
memcpy(c->opacity_animation.target_border_color, border_color,
|
||||||
sizeof(c->opacity_animation.target_border_color));
|
sizeof(c->opacity_animation.target_border_color));
|
||||||
// Start opacity animation to unfocused
|
// Start opacity animation to unfocused
|
||||||
c->opacity_animation.target_opacity = c->unfocused_opacity;
|
c->opacity_animation.target_opacity = c->unfocused_opacity;
|
||||||
c->opacity_animation.total_frames =
|
c->opacity_animation.time_started = get_now_in_ms();
|
||||||
animation_duration_focus / all_output_frame_duration_ms();
|
|
||||||
c->opacity_animation.passed_frames = 0;
|
|
||||||
|
|
||||||
if (c->opacity_animation.running) {
|
if (c->opacity_animation.running) {
|
||||||
memcpy(c->opacity_animation.initial_border_color,
|
memcpy(c->opacity_animation.initial_border_color,
|
||||||
@@ -1092,8 +1081,14 @@ bool client_apply_focus_opacity(Client *c) {
|
|||||||
client_set_opacity(c, 1);
|
client_set_opacity(c, 1);
|
||||||
} else if (c->animation.running && c->animation.action == OPEN) {
|
} else if (c->animation.running && c->animation.action == OPEN) {
|
||||||
c->opacity_animation.running = false;
|
c->opacity_animation.running = false;
|
||||||
float linear_progress =
|
struct timespec now;
|
||||||
(float)c->animation.passed_frames / c->animation.total_frames;
|
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 =
|
float percent =
|
||||||
animation_fade_in && !c->nofadein ? linear_progress : 1.0;
|
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);
|
client_set_opacity(c, target_opacity);
|
||||||
} else if (animations && c->opacity_animation.running) {
|
} 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);
|
float eased_progress = find_animation_curve_at(linear_progress, FOCUS);
|
||||||
|
|
||||||
c->opacity_animation.current_opacity =
|
c->opacity_animation.current_opacity =
|
||||||
@@ -1130,7 +1134,6 @@ bool client_apply_focus_opacity(Client *c) {
|
|||||||
if (linear_progress == 1.0f) {
|
if (linear_progress == 1.0f) {
|
||||||
c->opacity_animation.running = false;
|
c->opacity_animation.running = false;
|
||||||
} else {
|
} else {
|
||||||
c->opacity_animation.passed_frames++;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (c == selmon->sel) {
|
} else if (c == selmon->sel) {
|
||||||
|
|||||||
@@ -86,22 +86,6 @@ double find_animation_curve_at(double t, int type) {
|
|||||||
return baked_points[up].y;
|
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,
|
static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly,
|
||||||
struct wlr_scene_tree *snapshot_tree) {
|
struct wlr_scene_tree *snapshot_tree) {
|
||||||
if (!node->enabled && node->type != WLR_SCENE_NODE_TREE) {
|
if (!node->enabled && node->type != WLR_SCENE_NODE_TREE) {
|
||||||
|
|||||||
@@ -234,10 +234,15 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) {
|
|||||||
if (!l)
|
if (!l)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
|
uint32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
||||||
double animation_passed =
|
double animation_passed =
|
||||||
l->animation.total_frames
|
l->animation.duration
|
||||||
? (double)l->animation.passed_frames / l->animation.total_frames
|
? (double)passed_time / (double)l->animation.duration
|
||||||
: 1.0;
|
: 1.0;
|
||||||
|
|
||||||
int type = l->animation.action = l->animation.action;
|
int type = l->animation.action = l->animation.action;
|
||||||
double factor = find_animation_curve_at(animation_passed, type);
|
double factor = find_animation_curve_at(animation_passed, type);
|
||||||
unsigned int width =
|
unsigned int width =
|
||||||
@@ -280,13 +285,11 @@ void fadeout_layer_animation_next_tick(LayerSurface *l) {
|
|||||||
wlr_scene_node_for_each_buffer(&l->scene->node,
|
wlr_scene_node_for_each_buffer(&l->scene->node,
|
||||||
scene_buffer_apply_opacity, &opacity);
|
scene_buffer_apply_opacity, &opacity);
|
||||||
|
|
||||||
if (animation_passed == 1.0) {
|
if (animation_passed >= 1.0) {
|
||||||
wl_list_remove(&l->fadeout_link);
|
wl_list_remove(&l->fadeout_link);
|
||||||
wlr_scene_node_destroy(&l->scene->node);
|
wlr_scene_node_destroy(&l->scene->node);
|
||||||
free(l);
|
free(l);
|
||||||
l = NULL;
|
l = NULL;
|
||||||
} else {
|
|
||||||
l->animation.passed_frames++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,9 +298,13 @@ void layer_animation_next_tick(LayerSurface *l) {
|
|||||||
if (!l || !l->mapped)
|
if (!l || !l->mapped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
|
||||||
|
uint32_t passed_time = timespec_to_ms(&now) - l->animation.time_started;
|
||||||
double animation_passed =
|
double animation_passed =
|
||||||
l->animation.total_frames
|
l->animation.duration
|
||||||
? (double)l->animation.passed_frames / l->animation.total_frames
|
? (double)passed_time / (double)l->animation.duration
|
||||||
: 1.0;
|
: 1.0;
|
||||||
|
|
||||||
int type = l->animation.action == NONE ? MOVE : l->animation.action;
|
int type = l->animation.action == NONE ? MOVE : l->animation.action;
|
||||||
@@ -349,12 +356,10 @@ void layer_animation_next_tick(LayerSurface *l) {
|
|||||||
.height = height,
|
.height = height,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (animation_passed == 1.0) {
|
if (animation_passed >= 1.0) {
|
||||||
l->animation.running = false;
|
l->animation.running = false;
|
||||||
l->need_output_flush = false;
|
l->need_output_flush = false;
|
||||||
l->animation.action = MOVE;
|
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->current.height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算动画帧数
|
// 动画开始时间
|
||||||
fadeout_layer->animation.passed_frames = 0;
|
fadeout_layer->animation.time_started = get_now_in_ms();
|
||||||
fadeout_layer->animation.total_frames =
|
|
||||||
fadeout_layer->animation.duration / all_output_frame_duration_ms();
|
|
||||||
|
|
||||||
// 将节点插入到关闭动画链表中,屏幕刷新哪里会检查链表中是否有节点可以应用于动画
|
// 将节点插入到关闭动画链表中,屏幕刷新哪里会检查链表中是否有节点可以应用于动画
|
||||||
wlr_scene_node_set_enabled(&fadeout_layer->scene->node, true);
|
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.initial = l->animainit_geom;
|
||||||
// 设置动画速度
|
l->animation.time_started = get_now_in_ms();
|
||||||
l->animation.passed_frames = 0;
|
|
||||||
l->animation.total_frames =
|
|
||||||
l->animation.duration / output_frame_duration_ms(l->mon);
|
|
||||||
|
|
||||||
// 标记动画开始
|
// 标记动画开始
|
||||||
l->animation.running = true;
|
l->animation.running = true;
|
||||||
l->animation.should_animate = false;
|
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);
|
wlr_output_schedule_frame(l->mon->wlr_output);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "util.h"
|
#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) {
|
void wl_list_append(struct wl_list *list, struct wl_list *object) {
|
||||||
wl_list_insert(list->prev, 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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,3 +6,5 @@ void *ecalloc(size_t nmemb, size_t size);
|
|||||||
int fd_set_nonblock(int fd);
|
int fd_set_nonblock(int fd);
|
||||||
int regex_match(const char *pattern_mb, const char *str_mb);
|
int regex_match(const char *pattern_mb, const char *str_mb);
|
||||||
void wl_list_append(struct wl_list *list, struct wl_list *object);
|
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);
|
||||||
@@ -231,8 +231,7 @@ struct dwl_animation {
|
|||||||
bool tagouting;
|
bool tagouting;
|
||||||
bool begin_fade_in;
|
bool begin_fade_in;
|
||||||
bool tag_from_rule;
|
bool tag_from_rule;
|
||||||
unsigned int total_frames;
|
unsigned int time_started;
|
||||||
unsigned int passed_frames;
|
|
||||||
unsigned int duration;
|
unsigned int duration;
|
||||||
struct wlr_box initial;
|
struct wlr_box initial;
|
||||||
struct wlr_box current;
|
struct wlr_box current;
|
||||||
@@ -244,8 +243,8 @@ struct dwl_opacity_animation {
|
|||||||
float current_opacity;
|
float current_opacity;
|
||||||
float target_opacity;
|
float target_opacity;
|
||||||
float initial_opacity;
|
float initial_opacity;
|
||||||
unsigned int total_frames;
|
unsigned int time_started;
|
||||||
unsigned int passed_frames;
|
unsigned int duration;
|
||||||
float current_border_color[4];
|
float current_border_color[4];
|
||||||
float target_border_color[4];
|
float target_border_color[4];
|
||||||
float initial_border_color[4];
|
float initial_border_color[4];
|
||||||
|
|||||||
Reference in New Issue
Block a user