aboutsummaryrefslogtreecommitdiff
path: root/niri-visual-tests/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-02-07 11:32:02 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-02-07 13:16:54 +0400
commitf9085db5648bc6bad7fb0abf45e2a11f2e03d1af (patch)
tree56b32abe55f9857649f0296a0e36c30cd20c38e5 /niri-visual-tests/src
parent49ce791d13031ba5396b2ee8dbbffe128d64ff0f (diff)
downloadniri-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.rs228
-rw-r--r--niri-visual-tests/src/cases/mod.rs1
-rw-r--r--niri-visual-tests/src/cases/tile.rs25
-rw-r--r--niri-visual-tests/src/main.rs22
-rw-r--r--niri-visual-tests/src/test_window.rs4
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
}