added animation manager

This commit is contained in:
William McKinnon 2024-02-24 22:22:07 -05:00
parent d741e2415a
commit e5587312a8
5 changed files with 45 additions and 44 deletions

View file

@ -133,6 +133,9 @@ struct sway_server {
// Stores the nodes that have been marked as "dirty" and will be put into
// the pending transaction.
list_t *dirty_nodes;
list_t *animated_containers;
struct wl_event_source *animation_tick;
};
extern struct sway_server server;

View file

@ -125,8 +125,6 @@ struct sway_container {
float target_alpha;
float max_alpha;
struct wl_event_source *animation_present_timer;
int corner_radius;
float dim;

View file

@ -63,6 +63,39 @@ static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
}
}
static int animation_timer(void *data) {
struct sway_server *server = data;
float fastest_output_refresh_s = 1.0 / 60.0; // fallback to 60 Hz
for (int i = 0; i < server->animated_containers->length; i++) {
struct sway_container *con = server->animated_containers->items[i];
bool is_closing = con->alpha > con->target_alpha;
for (int i = 0; i < con->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i];
fastest_output_refresh_s = MIN(fastest_output_refresh_s, output->refresh_sec);
float alpha_step = config->animation_duration ?
(con->max_alpha * output->refresh_sec) / config->animation_duration : con->max_alpha;
con->alpha = is_closing ? MAX(con->alpha - alpha_step, con->target_alpha) :
MIN(con->alpha + alpha_step, con->target_alpha);
}
if (con->alpha == con->target_alpha) {
list_del(server->animated_containers, i);
if (is_closing) {
printf("done animation; clean up view\n");
view_remove_container(con->view);
continue;
}
}
container_damage_whole(con);
}
wl_event_source_timer_update(server->animation_tick, fastest_output_refresh_s * 1000);
return 1;
}
#define SWAY_XDG_SHELL_VERSION 2
bool server_init(struct sway_server *server) {
@ -264,6 +297,10 @@ bool server_init(struct sway_server *server) {
server->input = input_manager_create(server);
input_manager_get_default_seat(); // create seat0
server->animated_containers = create_list();
server->animation_tick = wl_event_loop_add_timer(server->wl_event_loop, animation_timer, server);
wl_event_source_timer_update(server->animation_tick, 1);
return true;
}
@ -275,6 +312,8 @@ void server_fini(struct sway_server *server) {
wl_display_destroy_clients(server->wl_display);
wl_display_destroy(server->wl_display);
list_free(server->dirty_nodes);
list_free(server->animated_containers);
wl_event_source_remove(server->animation_tick);
}
bool server_start(struct sway_server *server) {

View file

@ -30,36 +30,6 @@
#include "log.h"
#include "stringop.h"
// TODO signal instead of timer?
// TODO determine return val
// TODO no longer need output->refresh_sec?
// TODO better timing
static int animation_timer(void *data) {
struct sway_container *con = data;
float fastest_output_refresh_s = 0;
bool is_closing = con->alpha > con->target_alpha;
for (int i = 0; i < con->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i];
fastest_output_refresh_s = MAX(fastest_output_refresh_s, output->refresh_sec);
float alpha_step = config->animation_duration ?
(con->max_alpha * output->refresh_sec) / config->animation_duration : con->max_alpha;
con->alpha = is_closing ? MAX(con->alpha - alpha_step, con->target_alpha) :
MIN(con->alpha + alpha_step, con->target_alpha);
}
if (con->alpha != con->target_alpha) {
wl_event_source_timer_update(con->animation_present_timer, fastest_output_refresh_s * 1000);
} else if (is_closing) { // equal to target and closing
printf("done animation; clean up view\n");
view_remove_container(con->view);
return 1;
}
container_damage_whole(con);
return 1;
}
struct sway_container *container_create(struct sway_view *view) {
struct sway_container *c = calloc(1, sizeof(struct sway_container));
if (!c) {
@ -87,12 +57,8 @@ struct sway_container *container_create(struct sway_view *view) {
wl_signal_init(&c->events.destroy);
c->animation_present_timer = wl_event_loop_add_timer(server.wl_event_loop,
animation_timer, c);
// TODO: WON'T SPAWN IF LESS THAN 50, get optimal time (or use a signal?)
wl_event_source_timer_update(c->animation_present_timer, 200);
wl_signal_emit_mutable(&root->events.new_node, &c->node);
list_add(server.animated_containers, c);
return c;
}
@ -125,8 +91,6 @@ void container_destroy(struct sway_container *con) {
wlr_texture_destroy(con->marks_urgent);
wlr_texture_destroy(con->marks_focused_tab_title);
wl_event_source_remove(con->animation_present_timer);
if (con->view && con->view->container == con) {
con->view->container = NULL;
if (con->view->destroying) {

View file

@ -93,7 +93,6 @@ void view_remove_container(struct sway_view *view) {
arrange_workspace(ws);
workspace_detect_urgent(ws);
}
transaction_commit_dirty();
}
void view_begin_destroy(struct sway_view *view) {
@ -946,14 +945,12 @@ void view_unmap(struct sway_view *view) {
if (!config->animation_duration) {
view_remove_container(view);
transaction_commit_dirty();
} else {
// unfocus the view
// look at handle_seat_node_destroy
wl_signal_emit_mutable(&view->container->node.events.destroy, &view->container->node);
view_save_buffer(view);
view->container->target_alpha = 0;
wl_event_source_timer_update(view->container->animation_present_timer, 50);
list_add(server.animated_containers, view->container);
}
struct sway_seat *seat;