diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-05-10 16:58:53 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-05-10 20:23:08 +0400 |
| commit | 9dfa121b8e31082314d1c9347a60ef2e596494cb (patch) | |
| tree | 6e9b90f2f1d54213444fb89b4739e0c8948ed1e9 /src/layout/mod.rs | |
| parent | c4ebb9f58e7ea1d2e688d3ee9483a7a1b3dd52b4 (diff) | |
| download | niri-9dfa121b8e31082314d1c9347a60ef2e596494cb.tar.gz niri-9dfa121b8e31082314d1c9347a60ef2e596494cb.tar.bz2 niri-9dfa121b8e31082314d1c9347a60ef2e596494cb.zip | |
Implement interactive mouse resizing
Diffstat (limited to 'src/layout/mod.rs')
| -rw-r--r-- | src/layout/mod.rs | 161 |
1 files changed, 154 insertions, 7 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs index b93dfb4d..ad241d94 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -43,7 +43,7 @@ use smithay::backend::renderer::element::Id; use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture}; use smithay::output::Output; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; -use smithay::utils::{Logical, Point, Scale, Size, Transform}; +use smithay::utils::{Logical, Point, Scale, Serial, Size, Transform}; use self::monitor::Monitor; pub use self::monitor::MonitorRenderElement; @@ -52,7 +52,7 @@ use crate::niri_render_elements; use crate::render_helpers::renderer::NiriRenderer; use crate::render_helpers::snapshot::RenderSnapshot; use crate::render_helpers::{BakedBuffer, RenderTarget, SplitElements}; -use crate::utils::output_size; +use crate::utils::{output_size, ResizeEdge}; use crate::window::ResolvedWindowRules; pub mod closing_window; @@ -74,9 +74,16 @@ niri_render_elements! { pub type LayoutElementRenderSnapshot = RenderSnapshot<BakedBuffer<TextureBuffer<GlesTexture>>, BakedBuffer<SolidColorBuffer>>; +#[derive(Debug, Clone, Copy)] +pub struct InteractiveResizeData { + pub edges: ResizeEdge, + pub original_view_offset: i32, + pub original_column_width: i32, +} + pub trait LayoutElement { /// Type that can be used as a unique ID of this element. - type Id: PartialEq; + type Id: PartialEq + std::fmt::Debug; /// Unique ID of this element. fn id(&self) -> &Self::Id; @@ -166,6 +173,10 @@ pub trait LayoutElement { fn animation_snapshot(&self) -> Option<&LayoutElementRenderSnapshot>; fn take_animation_snapshot(&mut self) -> Option<LayoutElementRenderSnapshot>; + + fn set_interactive_resize(&mut self, data: Option<InteractiveResizeData>); + fn cancel_interactive_resize(&mut self); + fn interactive_resize_data(&mut self, serial: Serial) -> Option<InteractiveResizeData>; } #[derive(Debug)] @@ -669,13 +680,13 @@ impl<W: LayoutElement> Layout<W> { rv } - pub fn update_window(&mut self, window: &W::Id) { + pub fn update_window(&mut self, window: &W::Id, serial: Option<Serial>) { match &mut self.monitor_set { MonitorSet::Normal { monitors, .. } => { for mon in monitors { for ws in &mut mon.workspaces { if ws.has_window(window) { - ws.update_window(window); + ws.update_window(window, serial); return; } } @@ -684,7 +695,7 @@ impl<W: LayoutElement> Layout<W> { MonitorSet::NoOutputs { workspaces, .. } => { for ws in workspaces { if ws.has_window(window) { - ws.update_window(window); + ws.update_window(window, serial); return; } } @@ -1225,6 +1236,19 @@ impl<W: LayoutElement> Layout<W> { mon.window_under(pos_within_output) } + pub fn resize_edges_under( + &self, + output: &Output, + pos_within_output: Point<f64, Logical>, + ) -> Option<ResizeEdge> { + let MonitorSet::Normal { monitors, .. } = &self.monitor_set else { + return None; + }; + + let mon = monitors.iter().find(|mon| &mon.output == output)?; + mon.resize_edges_under(pos_within_output) + } + #[cfg(test)] fn verify_invariants(&self) { use std::collections::HashSet; @@ -1760,6 +1784,79 @@ impl<W: LayoutElement> Layout<W> { None } + pub fn interactive_resize_begin(&mut self, window: W::Id, edges: ResizeEdge) -> bool { + match &mut self.monitor_set { + MonitorSet::Normal { monitors, .. } => { + for mon in monitors { + for ws in &mut mon.workspaces { + if ws.has_window(&window) { + return ws.interactive_resize_begin(window, edges); + } + } + } + } + MonitorSet::NoOutputs { workspaces, .. } => { + for ws in workspaces { + if ws.has_window(&window) { + return ws.interactive_resize_begin(window, edges); + } + } + } + } + + false + } + + pub fn interactive_resize_update( + &mut self, + window: &W::Id, + delta: Point<f64, Logical>, + ) -> bool { + match &mut self.monitor_set { + MonitorSet::Normal { monitors, .. } => { + for mon in monitors { + for ws in &mut mon.workspaces { + if ws.has_window(window) { + return ws.interactive_resize_update(window, delta); + } + } + } + } + MonitorSet::NoOutputs { workspaces, .. } => { + for ws in workspaces { + if ws.has_window(window) { + return ws.interactive_resize_update(window, delta); + } + } + } + } + + false + } + + pub fn interactive_resize_end(&mut self, window: &W::Id) { + match &mut self.monitor_set { + MonitorSet::Normal { monitors, .. } => { + for mon in monitors { + for ws in &mut mon.workspaces { + if ws.has_window(window) { + ws.interactive_resize_end(Some(window)); + return; + } + } + } + } + MonitorSet::NoOutputs { workspaces, .. } => { + for ws in workspaces { + if ws.has_window(window) { + ws.interactive_resize_end(Some(window)); + return; + } + } + } + } + } + pub fn move_workspace_down(&mut self) { let Some(monitor) = self.active_monitor() else { return; @@ -2107,6 +2204,14 @@ mod tests { fn take_animation_snapshot(&mut self) -> Option<LayoutElementRenderSnapshot> { None } + + fn set_interactive_resize(&mut self, _data: Option<InteractiveResizeData>) {} + + fn cancel_interactive_resize(&mut self) {} + + fn interactive_resize_data(&mut self, _serial: Serial) -> Option<InteractiveResizeData> { + None + } } fn arbitrary_bbox() -> impl Strategy<Value = Rectangle<i32, Logical>> { @@ -2148,6 +2253,20 @@ mod tests { prop_oneof![(-10f64..10f64), (-50000f64..50000f64),] } + fn arbitrary_resize_edge() -> impl Strategy<Value = ResizeEdge> { + prop_oneof![ + Just(ResizeEdge::RIGHT), + Just(ResizeEdge::BOTTOM), + Just(ResizeEdge::LEFT), + Just(ResizeEdge::TOP), + Just(ResizeEdge::BOTTOM_RIGHT), + Just(ResizeEdge::BOTTOM_LEFT), + Just(ResizeEdge::TOP_RIGHT), + Just(ResizeEdge::TOP_LEFT), + Just(ResizeEdge::empty()), + ] + } + #[derive(Debug, Clone, Copy, Arbitrary)] enum Op { AddOutput(#[proptest(strategy = "1..=5usize")] usize), @@ -2237,6 +2356,24 @@ mod tests { WorkspaceSwitchGestureEnd { cancelled: bool, }, + InteractiveResizeBegin { + #[proptest(strategy = "1..=5usize")] + window: usize, + #[proptest(strategy = "arbitrary_resize_edge()")] + edges: ResizeEdge, + }, + InteractiveResizeUpdate { + #[proptest(strategy = "1..=5usize")] + window: usize, + #[proptest(strategy = "-20000f64..20000f64")] + dx: f64, + #[proptest(strategy = "-20000f64..20000f64")] + dy: f64, + }, + InteractiveResizeEnd { + #[proptest(strategy = "1..=5usize")] + window: usize, + }, } impl Op { @@ -2455,7 +2592,8 @@ mod tests { } if update { - layout.update_window(&id); + // FIXME: serial. + layout.update_window(&id, None); } } Op::MoveWorkspaceToOutput(id) => { @@ -2495,6 +2633,15 @@ mod tests { Op::WorkspaceSwitchGestureEnd { cancelled } => { layout.workspace_switch_gesture_end(cancelled); } + Op::InteractiveResizeBegin { window, edges } => { + layout.interactive_resize_begin(window, edges); + } + Op::InteractiveResizeUpdate { window, dx, dy } => { + layout.interactive_resize_update(&window, Point::from((dx, dy))); + } + Op::InteractiveResizeEnd { window } => { + layout.interactive_resize_end(&window); + } } } } |
