Refactor animations to take explicit current time

This commit is contained in:
Ivan Molodetskikh
2024-11-23 11:27:27 +03:00
parent 9c7e8d04d2
commit 93cee2994a
30 changed files with 426 additions and 187 deletions
@@ -7,9 +7,9 @@ use niri::render_helpers::border::BorderRenderElement;
use niri_config::{Color, CornerRadius, GradientInterpolation};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientAngle {
angle: f32,
@@ -17,7 +17,7 @@ pub struct GradientAngle {
}
impl GradientAngle {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
angle: 0.,
prev_time: Duration::ZERO,
+3 -3
View File
@@ -8,9 +8,9 @@ use niri::render_helpers::border::BorderRenderElement;
use niri_config::{Color, CornerRadius, FloatOrInt, GradientInterpolation};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Point, Rectangle, Size};
use smithay::utils::{Physical, Point, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientArea {
progress: f32,
@@ -19,7 +19,7 @@ pub struct GradientArea {
}
impl GradientArea {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
let border = FocusRing::new(niri_config::FocusRing {
off: false,
width: FloatOrInt(1.),
@@ -4,16 +4,16 @@ use niri_config::{
};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientOklab {
gradient_format: GradientInterpolation,
}
impl GradientOklab {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Oklab,
@@ -2,16 +2,16 @@ use niri::render_helpers::border::BorderRenderElement;
use niri_config::{Color, CornerRadius, GradientColorSpace, GradientInterpolation};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientOklabAlpha {
gradient_format: GradientInterpolation,
}
impl GradientOklabAlpha {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Oklab,
@@ -4,16 +4,16 @@ use niri_config::{
};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientOklchAlpha {
gradient_format: GradientInterpolation,
}
impl GradientOklchAlpha {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Oklch,
@@ -4,16 +4,16 @@ use niri_config::{
};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientOklchDecreasing {
gradient_format: GradientInterpolation,
}
impl GradientOklchDecreasing {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Oklch,
@@ -4,16 +4,16 @@ use niri_config::{
};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientOklchIncreasing {
gradient_format: GradientInterpolation,
}
impl GradientOklchIncreasing {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Oklch,
@@ -4,16 +4,16 @@ use niri_config::{
};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientOklchLonger {
gradient_format: GradientInterpolation,
}
impl GradientOklchLonger {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Oklch,
@@ -4,16 +4,16 @@ use niri_config::{
};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientOklchShorter {
gradient_format: GradientInterpolation,
}
impl GradientOklchShorter {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Oklch,
+3 -3
View File
@@ -4,16 +4,16 @@ use niri_config::{
};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientSrgb {
gradient_format: GradientInterpolation,
}
impl GradientSrgb {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Srgb,
@@ -2,16 +2,16 @@ use niri::render_helpers::border::BorderRenderElement;
use niri_config::{Color, CornerRadius, GradientColorSpace, GradientInterpolation};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientSrgbAlpha {
gradient_format: GradientInterpolation,
}
impl GradientSrgbAlpha {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::Srgb,
@@ -4,16 +4,16 @@ use niri_config::{
};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientSrgbLinear {
gradient_format: GradientInterpolation,
}
impl GradientSrgbLinear {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::SrgbLinear,
@@ -2,16 +2,16 @@ use niri::render_helpers::border::BorderRenderElement;
use niri_config::{Color, CornerRadius, GradientColorSpace, GradientInterpolation};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Rectangle, Size};
use smithay::utils::{Physical, Rectangle, Size};
use super::TestCase;
use super::{Args, TestCase};
pub struct GradientSrgbLinearAlpha {
gradient_format: GradientInterpolation,
}
impl GradientSrgbLinearAlpha {
pub fn new(_size: Size<i32, Logical>) -> Self {
pub fn new(_args: Args) -> Self {
Self {
gradient_format: GradientInterpolation {
color_space: GradientColorSpace::SrgbLinear,
+30 -22
View File
@@ -1,18 +1,18 @@
use std::collections::HashMap;
use std::time::Duration;
use niri::animation::Clock;
use niri::layout::workspace::ColumnWidth;
use niri::layout::{LayoutElement as _, Options};
use niri::render_helpers::RenderTarget;
use niri::utils::get_monotonic_time;
use niri_config::{Color, FloatOrInt, OutputName};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::desktop::layer_map_for_output;
use smithay::output::{Mode, Output, PhysicalProperties, Subpixel};
use smithay::utils::{Logical, Physical, Size};
use smithay::utils::{Physical, Size};
use super::TestCase;
use super::{Args, TestCase};
use crate::test_window::TestWindow;
type DynStepFn = Box<dyn FnOnce(&mut Layout)>;
@@ -20,13 +20,16 @@ type DynStepFn = Box<dyn FnOnce(&mut Layout)>;
pub struct Layout {
output: Output,
windows: Vec<TestWindow>,
clock: Clock,
layout: niri::layout::Layout<TestWindow>,
start_time: Duration,
steps: HashMap<Duration, DynStepFn>,
}
impl Layout {
pub fn new(size: Size<i32, Logical>) -> Self {
pub fn new(args: Args) -> Self {
let Args { size, clock } = args;
let output = Output::new(
String::new(),
PhysicalProperties {
@@ -63,20 +66,23 @@ impl Layout {
},
..Default::default()
};
let mut layout = niri::layout::Layout::with_options(options);
let mut layout = niri::layout::Layout::with_options(clock.clone(), options);
layout.add_output(output.clone());
let start_time = clock.now();
Self {
output,
windows: Vec::new(),
clock,
layout,
start_time: get_monotonic_time(),
start_time,
steps: HashMap::new(),
}
}
pub fn open_in_between(size: Size<i32, Logical>) -> Self {
let mut rv = Self::new(size);
pub fn open_in_between(args: Args) -> Self {
let mut rv = Self::new(args);
rv.add_window(TestWindow::freeform(0), Some(ColumnWidth::Proportion(0.3)));
rv.add_window(TestWindow::freeform(1), Some(ColumnWidth::Proportion(0.3)));
@@ -91,8 +97,8 @@ impl Layout {
rv
}
pub fn open_multiple_quickly(size: Size<i32, Logical>) -> Self {
let mut rv = Self::new(size);
pub fn open_multiple_quickly(args: Args) -> Self {
let mut rv = Self::new(args);
for delay in [100, 200, 300] {
rv.add_step(delay, move |l| {
@@ -105,8 +111,8 @@ impl Layout {
rv
}
pub fn open_multiple_quickly_big(size: Size<i32, Logical>) -> Self {
let mut rv = Self::new(size);
pub fn open_multiple_quickly_big(args: Args) -> Self {
let mut rv = Self::new(args);
for delay in [100, 200, 300] {
rv.add_step(delay, move |l| {
@@ -119,8 +125,8 @@ impl Layout {
rv
}
pub fn open_to_the_left(size: Size<i32, Logical>) -> Self {
let mut rv = Self::new(size);
pub fn open_to_the_left(args: Args) -> Self {
let mut rv = Self::new(args);
rv.add_window(TestWindow::freeform(0), Some(ColumnWidth::Proportion(0.3)));
rv.add_window(TestWindow::freeform(1), Some(ColumnWidth::Proportion(0.3)));
@@ -135,8 +141,8 @@ impl Layout {
rv
}
pub fn open_to_the_left_big(size: Size<i32, Logical>) -> Self {
let mut rv = Self::new(size);
pub fn open_to_the_left_big(args: Args) -> Self {
let mut rv = Self::new(args);
rv.add_window(TestWindow::freeform(0), Some(ColumnWidth::Proportion(0.3)));
rv.add_window(TestWindow::freeform(1), Some(ColumnWidth::Proportion(0.8)));
@@ -201,21 +207,23 @@ impl TestCase for Layout {
self.layout.are_animations_ongoing(Some(&self.output)) || !self.steps.is_empty()
}
fn advance_animations(&mut self, mut current_time: Duration) {
fn advance_animations(&mut self, current_time: Duration) {
let run = self
.steps
.keys()
.copied()
.filter(|delay| self.start_time + *delay <= current_time)
.collect::<Vec<_>>();
for key in &run {
let f = self.steps.remove(key).unwrap();
for delay in &run {
let now = self.start_time + *delay;
self.clock.set_time_override(Some(now));
self.layout.advance_animations(now);
let f = self.steps.remove(delay).unwrap();
f(self);
}
if !run.is_empty() {
current_time = get_monotonic_time();
}
self.clock.set_time_override(None);
self.layout.advance_animations(current_time);
}
+7 -1
View File
@@ -1,8 +1,9 @@
use std::time::Duration;
use niri::animation::Clock;
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Physical, Size};
use smithay::utils::{Logical, Physical, Size};
pub mod gradient_angle;
pub mod gradient_area;
@@ -21,6 +22,11 @@ pub mod layout;
pub mod tile;
pub mod window;
pub struct Args {
pub size: Size<i32, Logical>,
pub clock: Clock,
}
pub trait TestCase {
fn resize(&mut self, _width: i32, _height: i32) {}
fn are_animations_ongoing(&self) -> bool {
+22 -25
View File
@@ -6,9 +6,9 @@ use niri::render_helpers::RenderTarget;
use niri_config::{Color, FloatOrInt};
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Point, Rectangle, Scale, Size};
use smithay::utils::{Physical, Point, Rectangle, Scale, Size};
use super::TestCase;
use super::{Args, TestCase};
use crate::test_window::TestWindow;
pub struct Tile {
@@ -17,53 +17,44 @@ pub struct Tile {
}
impl Tile {
pub fn freeform(size: Size<i32, Logical>) -> Self {
pub fn freeform(args: Args) -> Self {
let window = TestWindow::freeform(0);
let mut rv = Self::with_window(window);
rv.tile.request_tile_size(size.to_f64(), false, None);
rv.window.communicate();
rv
Self::with_window(args, window)
}
pub fn fixed_size(size: Size<i32, Logical>) -> Self {
pub fn fixed_size(args: Args) -> Self {
let window = TestWindow::fixed_size(0);
let mut rv = Self::with_window(window);
rv.tile.request_tile_size(size.to_f64(), false, None);
rv.window.communicate();
rv
Self::with_window(args, window)
}
pub fn fixed_size_with_csd_shadow(size: Size<i32, Logical>) -> Self {
pub fn fixed_size_with_csd_shadow(args: Args) -> Self {
let window = TestWindow::fixed_size(0);
window.set_csd_shadow_width(64);
let mut rv = Self::with_window(window);
rv.tile.request_tile_size(size.to_f64(), false, None);
rv.window.communicate();
rv
Self::with_window(args, window)
}
pub fn freeform_open(size: Size<i32, Logical>) -> Self {
let mut rv = Self::freeform(size);
pub fn freeform_open(args: Args) -> Self {
let mut rv = Self::freeform(args);
rv.window.set_color([0.1, 0.1, 0.1, 1.]);
rv.tile.start_open_animation();
rv
}
pub fn fixed_size_open(size: Size<i32, Logical>) -> Self {
let mut rv = Self::fixed_size(size);
pub fn fixed_size_open(args: Args) -> Self {
let mut rv = Self::fixed_size(args);
rv.window.set_color([0.1, 0.1, 0.1, 1.]);
rv.tile.start_open_animation();
rv
}
pub fn fixed_size_with_csd_shadow_open(size: Size<i32, Logical>) -> Self {
let mut rv = Self::fixed_size_with_csd_shadow(size);
pub fn fixed_size_with_csd_shadow_open(args: Args) -> Self {
let mut rv = Self::fixed_size_with_csd_shadow(args);
rv.window.set_color([0.1, 0.1, 0.1, 1.]);
rv.tile.start_open_animation();
rv
}
pub fn with_window(window: TestWindow) -> Self {
pub fn with_window(args: Args, window: TestWindow) -> Self {
let options = Options {
focus_ring: niri_config::FocusRing {
off: true,
@@ -77,7 +68,13 @@ impl Tile {
},
..Default::default()
};
let tile = niri::layout::tile::Tile::new(window.clone(), 1., Rc::new(options));
let mut tile =
niri::layout::tile::Tile::new(window.clone(), 1., args.clock, Rc::new(options));
tile.request_tile_size(args.size.to_f64(), false, None);
window.communicate();
Self { window, tile }
}
}
+8 -8
View File
@@ -2,9 +2,9 @@ use niri::layout::LayoutElement;
use niri::render_helpers::RenderTarget;
use smithay::backend::renderer::element::RenderElement;
use smithay::backend::renderer::gles::GlesRenderer;
use smithay::utils::{Logical, Physical, Point, Scale, Size};
use smithay::utils::{Physical, Point, Scale, Size};
use super::TestCase;
use super::{Args, TestCase};
use crate::test_window::TestWindow;
pub struct Window {
@@ -12,24 +12,24 @@ pub struct Window {
}
impl Window {
pub fn freeform(size: Size<i32, Logical>) -> Self {
pub fn freeform(args: Args) -> Self {
let mut window = TestWindow::freeform(0);
window.request_size(size, false, None);
window.request_size(args.size, false, None);
window.communicate();
Self { window }
}
pub fn fixed_size(size: Size<i32, Logical>) -> Self {
pub fn fixed_size(args: Args) -> Self {
let mut window = TestWindow::fixed_size(0);
window.request_size(size, false, None);
window.request_size(args.size, false, None);
window.communicate();
Self { window }
}
pub fn fixed_size_with_csd_shadow(size: Size<i32, Logical>) -> Self {
pub fn fixed_size_with_csd_shadow(args: Args) -> Self {
let mut window = TestWindow::fixed_size(0);
window.set_csd_shadow_width(64);
window.request_size(size, false, None);
window.request_size(args.size, false, None);
window.communicate();
Self { window }
}
+2 -6
View File
@@ -5,12 +5,12 @@ use std::env;
use std::sync::atomic::Ordering;
use adw::prelude::{AdwApplicationWindowExt, NavigationPageExt};
use cases::Args;
use gtk::prelude::{
AdjustmentExt, ApplicationExt, ApplicationExtManual, BoxExt, GtkWindowExt, WidgetExt,
};
use gtk::{gdk, gio, glib};
use niri::animation::ANIMATION_SLOWDOWN;
use smithay::utils::{Logical, Size};
use smithay_view::SmithayView;
use tracing_subscriber::EnvFilter;
@@ -72,11 +72,7 @@ fn build_ui(app: &adw::Application) {
}
impl S {
fn add<T: TestCase + 'static>(
&self,
make: impl Fn(Size<i32, Logical>) -> T + 'static,
title: &str,
) {
fn add<T: TestCase + 'static>(&self, make: impl Fn(Args) -> T + 'static, title: &str) {
let view = SmithayView::new(make);
self.stack.add_titled(&view, None, title);
}
+12 -8
View File
@@ -1,8 +1,8 @@
use gtk::glib;
use gtk::subclass::prelude::*;
use smithay::utils::{Logical, Size};
use smithay::utils::Size;
use crate::cases::TestCase;
use crate::cases::{Args, TestCase};
mod imp {
use std::cell::{Cell, OnceCell, RefCell};
@@ -11,6 +11,7 @@ mod imp {
use anyhow::{ensure, Context};
use gtk::gdk;
use gtk::prelude::*;
use niri::animation::Clock;
use niri::render_helpers::{resources, shaders};
use niri::utils::get_monotonic_time;
use smithay::backend::egl::ffi::egl;
@@ -21,7 +22,7 @@ mod imp {
use super::*;
type DynMakeTestCase = Box<dyn Fn(Size<i32, Logical>) -> Box<dyn TestCase>>;
type DynMakeTestCase = Box<dyn Fn(Args) -> Box<dyn TestCase>>;
#[derive(Default)]
pub struct SmithayView {
@@ -30,6 +31,7 @@ mod imp {
renderer: RefCell<Option<Result<GlesRenderer, ()>>>,
pub make_test_case: OnceCell<DynMakeTestCase>,
test_case: RefCell<Option<Box<dyn TestCase>>>,
clock: RefCell<Clock>,
}
#[glib::object_subclass]
@@ -129,7 +131,11 @@ mod imp {
let mut case = self.test_case.borrow_mut();
let case = case.get_or_insert_with(|| {
let make = self.make_test_case.get().unwrap();
make(Size::from(size))
let args = Args {
size: Size::from(size),
clock: self.clock.borrow().clone(),
};
make(args)
});
case.advance_animations(get_monotonic_time());
@@ -232,12 +238,10 @@ glib::wrapper! {
}
impl SmithayView {
pub fn new<T: TestCase + 'static>(
make_test_case: impl Fn(Size<i32, Logical>) -> T + 'static,
) -> Self {
pub fn new<T: TestCase + 'static>(make_test_case: impl Fn(Args) -> T + 'static) -> Self {
let obj: Self = glib::Object::builder().build();
let make = move |size| Box::new(make_test_case(size)) as Box<dyn TestCase>;
let make = move |args| Box::new(make_test_case(args)) as Box<dyn TestCase>;
let make_test_case = Box::new(make) as _;
let _ = obj.imp().make_test_case.set(make_test_case);