view: Add simple window animations

This commit is contained in:
Andri Yngvason 2025-06-09 22:35:38 +00:00
parent 97ce4131bb
commit 21e93e480a
3 changed files with 93 additions and 0 deletions

View file

@ -201,6 +201,9 @@ struct view {
struct wlr_scene_tree *scene_tree; struct wlr_scene_tree *scene_tree;
struct wlr_scene_tree *content_tree; struct wlr_scene_tree *content_tree;
struct wlr_scene_buffer *animation;
uint64_t animation_start_time;
bool mapped; bool mapped;
bool been_mapped; bool been_mapped;
bool ssd_enabled; bool ssd_enabled;
@ -278,6 +281,7 @@ struct view {
struct wl_listener request_maximize; struct wl_listener request_maximize;
struct wl_listener request_fullscreen; struct wl_listener request_fullscreen;
struct wl_listener set_title; struct wl_listener set_title;
struct wl_listener output_commit;
struct foreign_toplevel *foreign_toplevel; struct foreign_toplevel *foreign_toplevel;

View file

@ -2,11 +2,92 @@
/* view-impl-common.c: common code for shell view->impl functions */ /* view-impl-common.c: common code for shell view->impl functions */
#include <stdio.h> #include <stdio.h>
#include <strings.h> #include <strings.h>
#include <math.h>
#include <assert.h>
#include <wlr/types/wlr_output.h>
#include "foreign-toplevel.h" #include "foreign-toplevel.h"
#include "labwc.h" #include "labwc.h"
#include "view.h" #include "view.h"
#include "view-impl-common.h" #include "view-impl-common.h"
#include "window-rules.h" #include "window-rules.h"
#include "workspaces.h"
static inline uint64_t
timespec_to_us(const struct timespec *ts)
{
return (uint64_t)ts->tv_sec * UINT64_C(1000000) +
(uint64_t)ts->tv_nsec / UINT64_C(1000);
}
static inline uint64_t
gettime_us(void)
{
struct timespec ts = { 0 };
clock_gettime(CLOCK_MONOTONIC, &ts);
return timespec_to_us(&ts);
}
static void
adjust_scaled_position(struct view *view, double scale)
{
int x = view->current.x;
int y = view->current.y;
double width = view->current.width;
double height = view->current.height;
int x_pos = x + round(width * (1.0 - scale) / 2.0);
int y_pos = y + round(height * (1.0 - scale) / 2.0);
wlr_scene_node_set_position(&view->scene_tree->node, x_pos, y_pos);
}
static void
view_run_animation(struct view *view, uint64_t now)
{
uint64_t elapsed_us = now - view->animation_start_time;
double t = (double)elapsed_us * 1e-6;
double duration = 0.2; // s
double scale = fmax(t / duration, 0.01);
if (scale < 1.0) {
wlr_scene_node_set_scale(&view->scene_tree->node, scale);
adjust_scaled_position(view, scale);
} else {
int x = view->current.x;
int y = view->current.y;
wlr_scene_node_set_position(&view->scene_tree->node, x, y);
wlr_scene_node_set_scale(&view->scene_tree->node, 1.0);
wl_list_remove(&view->output_commit.link);
wl_list_init(&view->output_commit.link);
view->animation_start_time = 0;
}
}
static void
handle_output_commit(struct wl_listener *listener, void *data)
{
struct wlr_output_event_commit *event = data;
struct view *view = wl_container_of(listener, view, output_commit);
if (!(event->state->committed & WLR_OUTPUT_STATE_BUFFER)) {
return;
}
view_run_animation(view, gettime_us());
wlr_output_update_needs_frame(event->output);
}
static void
view_start_animation(struct view *view)
{
view->output_commit.notify = handle_output_commit;
wl_signal_add(&view->output->wlr_output->events.commit, &view->output_commit);
uint64_t now = gettime_us();
view->animation_start_time = now;
view_run_animation(view, now);
}
void void
view_impl_map(struct view *view) view_impl_map(struct view *view)
@ -16,6 +97,7 @@ view_impl_map(struct view *view)
view_update_app_id(view); view_update_app_id(view);
if (!view->been_mapped) { if (!view->been_mapped) {
window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP); window_rules_apply(view, LAB_WINDOW_RULE_EVENT_ON_FIRST_MAP);
view_start_animation(view);
} }
/* /*
@ -104,4 +186,8 @@ view_impl_apply_geometry(struct view *view, int w, int h)
if (!wlr_box_equal(current, &old)) { if (!wlr_box_equal(current, &old)) {
view_moved(view); view_moved(view);
} }
if (view->animation_start_time) {
adjust_scaled_position(view, view->scene_tree->node.scale);
}
} }

View file

@ -2558,6 +2558,9 @@ view_destroy(struct view *view)
wl_list_remove(&view->set_title.link); wl_list_remove(&view->set_title.link);
wl_list_remove(&view->destroy.link); wl_list_remove(&view->destroy.link);
wl_list_remove(&view->output_commit.link);
wl_list_init(&view->output_commit.link);
if (view->foreign_toplevel) { if (view->foreign_toplevel) {
foreign_toplevel_destroy(view->foreign_toplevel); foreign_toplevel_destroy(view->foreign_toplevel);
view->foreign_toplevel = NULL; view->foreign_toplevel = NULL;