diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-02-07 11:32:02 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-02-07 13:16:54 +0400 |
| commit | f9085db5648bc6bad7fb0abf45e2a11f2e03d1af (patch) | |
| tree | 56b32abe55f9857649f0296a0e36c30cd20c38e5 /niri-visual-tests/src | |
| parent | 49ce791d13031ba5396b2ee8dbbffe128d64ff0f (diff) | |
| download | niri-f9085db5648bc6bad7fb0abf45e2a11f2e03d1af.tar.gz niri-f9085db5648bc6bad7fb0abf45e2a11f2e03d1af.tar.bz2 niri-f9085db5648bc6bad7fb0abf45e2a11f2e03d1af.zip | |
Implement window open animations
Diffstat (limited to 'niri-visual-tests/src')
| -rw-r--r-- | niri-visual-tests/src/cases/layout.rs | 228 | ||||
| -rw-r--r-- | niri-visual-tests/src/cases/mod.rs | 1 | ||||
| -rw-r--r-- | niri-visual-tests/src/cases/tile.rs | 25 | ||||
| -rw-r--r-- | niri-visual-tests/src/main.rs | 22 | ||||
| -rw-r--r-- | niri-visual-tests/src/test_window.rs | 4 |
5 files changed, 279 insertions, 1 deletions
diff --git a/niri-visual-tests/src/cases/layout.rs b/niri-visual-tests/src/cases/layout.rs new file mode 100644 index 00000000..b12b6745 --- /dev/null +++ b/niri-visual-tests/src/cases/layout.rs @@ -0,0 +1,228 @@ +use std::collections::HashMap; +use std::time::Duration; + +use niri::layout::workspace::ColumnWidth; +use niri::layout::Options; +use niri::utils::get_monotonic_time; +use niri_config::Color; +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 super::TestCase; +use crate::test_window::TestWindow; + +type DynStepFn = Box<dyn FnOnce(&mut Layout)>; + +pub struct Layout { + output: Output, + windows: Vec<TestWindow>, + layout: niri::layout::Layout<TestWindow>, + start_time: Duration, + steps: HashMap<Duration, DynStepFn>, +} + +impl Layout { + pub fn new(size: Size<i32, Logical>) -> Self { + let output = Output::new( + String::new(), + PhysicalProperties { + size: Size::from((size.w, size.h)), + subpixel: Subpixel::Unknown, + make: String::new(), + model: String::new(), + }, + ); + let mode = Some(Mode { + size: size.to_physical(1), + refresh: 60000, + }); + output.change_current_state(mode, None, None, None); + + let options = Options { + focus_ring: niri_config::FocusRing { + off: true, + ..Default::default() + }, + border: niri_config::FocusRing { + off: false, + width: 4, + active_color: Color::new(255, 163, 72, 255), + inactive_color: Color::new(50, 50, 50, 255), + }, + ..Default::default() + }; + let mut layout = niri::layout::Layout::with_options(options); + layout.add_output(output.clone()); + + Self { + output, + windows: Vec::new(), + layout, + start_time: get_monotonic_time(), + steps: HashMap::new(), + } + } + + pub fn open_in_between(size: Size<i32, Logical>) -> Self { + let mut rv = Self::new(size); + + rv.add_window(TestWindow::freeform(0), Some(ColumnWidth::Proportion(0.3))); + rv.add_window(TestWindow::freeform(1), Some(ColumnWidth::Proportion(0.3))); + rv.layout.activate_window(&rv.windows[0]); + + rv.add_step(500, |l| { + let win = TestWindow::freeform(2); + l.add_window(win.clone(), Some(ColumnWidth::Proportion(0.3))); + l.layout.start_open_animation_for_window(&win); + }); + + rv + } + + pub fn open_multiple_quickly(size: Size<i32, Logical>) -> Self { + let mut rv = Self::new(size); + + for delay in [100, 200, 300] { + rv.add_step(delay, move |l| { + let win = TestWindow::freeform(delay as usize); + l.add_window(win.clone(), Some(ColumnWidth::Proportion(0.3))); + l.layout.start_open_animation_for_window(&win); + }); + } + + rv + } + + pub fn open_multiple_quickly_big(size: Size<i32, Logical>) -> Self { + let mut rv = Self::new(size); + + for delay in [100, 200, 300] { + rv.add_step(delay, move |l| { + let win = TestWindow::freeform(delay as usize); + l.add_window(win.clone(), Some(ColumnWidth::Proportion(0.5))); + l.layout.start_open_animation_for_window(&win); + }); + } + + rv + } + + pub fn open_to_the_left(size: Size<i32, Logical>) -> Self { + let mut rv = Self::new(size); + + rv.add_window(TestWindow::freeform(0), Some(ColumnWidth::Proportion(0.3))); + rv.add_window(TestWindow::freeform(1), Some(ColumnWidth::Proportion(0.3))); + + rv.add_step(500, |l| { + let win = TestWindow::freeform(2); + let right_of = l.windows[0].clone(); + l.add_window_right_of(&right_of, win.clone(), Some(ColumnWidth::Proportion(0.3))); + l.layout.start_open_animation_for_window(&win); + }); + + rv + } + + pub fn open_to_the_left_big(size: Size<i32, Logical>) -> Self { + let mut rv = Self::new(size); + + rv.add_window(TestWindow::freeform(0), Some(ColumnWidth::Proportion(0.3))); + rv.add_window(TestWindow::freeform(1), Some(ColumnWidth::Proportion(0.8))); + + rv.add_step(500, |l| { + let win = TestWindow::freeform(2); + let right_of = l.windows[0].clone(); + l.add_window_right_of(&right_of, win.clone(), Some(ColumnWidth::Proportion(0.5))); + l.layout.start_open_animation_for_window(&win); + }); + + rv + } + + fn add_window(&mut self, window: TestWindow, width: Option<ColumnWidth>) { + self.layout.add_window(window.clone(), width, false); + if window.communicate() { + self.layout.update_window(&window); + } + self.windows.push(window); + } + + fn add_window_right_of( + &mut self, + right_of: &TestWindow, + window: TestWindow, + width: Option<ColumnWidth>, + ) { + self.layout + .add_window_right_of(right_of, window.clone(), width, false); + if window.communicate() { + self.layout.update_window(&window); + } + self.windows.push(window); + } + + fn add_step(&mut self, delay_ms: u64, f: impl FnOnce(&mut Self) + 'static) { + self.steps + .insert(Duration::from_millis(delay_ms), Box::new(f) as _); + } +} + +impl TestCase for Layout { + fn resize(&mut self, width: i32, height: i32) { + let mode = Some(Mode { + size: Size::from((width, height)), + refresh: 60000, + }); + self.output.change_current_state(mode, None, None, None); + layer_map_for_output(&self.output).arrange(); + self.layout.update_output_size(&self.output); + for win in &self.windows { + if win.communicate() { + self.layout.update_window(win); + } + } + } + + fn are_animations_ongoing(&self) -> bool { + self.layout + .monitor_for_output(&self.output) + .unwrap() + .are_animations_ongoing() + || !self.steps.is_empty() + } + + fn advance_animations(&mut self, mut 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(); + f(self); + } + if !run.is_empty() { + current_time = get_monotonic_time(); + } + + self.layout.advance_animations(current_time); + } + + fn render( + &mut self, + renderer: &mut GlesRenderer, + _size: Size<i32, Physical>, + ) -> Vec<Box<dyn RenderElement<GlesRenderer>>> { + self.layout + .monitor_for_output(&self.output) + .unwrap() + .render_elements(renderer) + .into_iter() + .map(|elem| Box::new(elem) as _) + .collect() + } +} diff --git a/niri-visual-tests/src/cases/mod.rs b/niri-visual-tests/src/cases/mod.rs index b7d71cd0..6f732f6f 100644 --- a/niri-visual-tests/src/cases/mod.rs +++ b/niri-visual-tests/src/cases/mod.rs @@ -4,6 +4,7 @@ use smithay::backend::renderer::element::RenderElement; use smithay::backend::renderer::gles::GlesRenderer; use smithay::utils::{Physical, Size}; +pub mod layout; pub mod tile; pub mod window; diff --git a/niri-visual-tests/src/cases/tile.rs b/niri-visual-tests/src/cases/tile.rs index 824661bb..e3fa8fb1 100644 --- a/niri-visual-tests/src/cases/tile.rs +++ b/niri-visual-tests/src/cases/tile.rs @@ -41,6 +41,27 @@ impl Tile { rv } + pub fn freeform_open(size: Size<i32, Logical>) -> Self { + let mut rv = Self::freeform(size); + 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); + 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); + rv.window.set_color([0.1, 0.1, 0.1, 1.]); + rv.tile.start_open_animation(); + rv + } + pub fn with_window(window: TestWindow) -> Self { let options = Options { focus_ring: niri_config::FocusRing { @@ -66,6 +87,10 @@ impl TestCase for Tile { self.window.communicate(); } + fn are_animations_ongoing(&self) -> bool { + self.tile.are_animations_ongoing() + } + fn advance_animations(&mut self, current_time: Duration) { self.tile.advance_animations(current_time, true); } diff --git a/niri-visual-tests/src/main.rs b/niri-visual-tests/src/main.rs index ad208b19..32911b55 100644 --- a/niri-visual-tests/src/main.rs +++ b/niri-visual-tests/src/main.rs @@ -16,6 +16,7 @@ use smithay::utils::{Logical, Size}; use smithay_view::SmithayView; use tracing_subscriber::EnvFilter; +use crate::cases::layout::Layout; use crate::cases::TestCase; mod cases; @@ -85,6 +86,27 @@ fn build_ui(app: &adw::Application) { Tile::fixed_size_with_csd_shadow, "Fixed Size Tile - CSD Shadow", ); + s.add(Tile::freeform_open, "Freeform Tile - Open"); + s.add(Tile::fixed_size_open, "Fixed Size Tile - Open"); + s.add( + Tile::fixed_size_with_csd_shadow_open, + "Fixed Size Tile - CSD Shadow - Open", + ); + + s.add(Layout::open_in_between, "Layout - Open In-Between"); + s.add( + Layout::open_multiple_quickly, + "Layout - Open Multiple Quickly", + ); + s.add( + Layout::open_multiple_quickly_big, + "Layout - Open Multiple Quickly - Big", + ); + s.add(Layout::open_to_the_left, "Layout - Open To The Left"); + s.add( + Layout::open_to_the_left_big, + "Layout - Open To The Left - Big", + ); let content_headerbar = adw::HeaderBar::new(); diff --git a/niri-visual-tests/src/test_window.rs b/niri-visual-tests/src/test_window.rs index 291a391d..7e50023a 100644 --- a/niri-visual-tests/src/test_window.rs +++ b/niri-visual-tests/src/test_window.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use niri::layout::{LayoutElement, LayoutElementRenderElement}; use niri::render_helpers::renderer::NiriRenderer; use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; -use smithay::backend::renderer::element::Kind; +use smithay::backend::renderer::element::{Id, Kind}; use smithay::output::Output; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; use smithay::utils::{Logical, Point, Scale, Size, Transform}; @@ -196,6 +196,8 @@ impl LayoutElement for TestWindow { fn output_leave(&self, _output: &Output) {} + fn set_offscreen_element_id(&self, _id: Option<Id>) {} + fn is_fullscreen(&self) -> bool { false } |
