aboutsummaryrefslogtreecommitdiff
path: root/src/layout/mod.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-05-10 16:58:53 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-05-10 20:23:08 +0400
commit9dfa121b8e31082314d1c9347a60ef2e596494cb (patch)
tree6e9b90f2f1d54213444fb89b4739e0c8948ed1e9 /src/layout/mod.rs
parentc4ebb9f58e7ea1d2e688d3ee9483a7a1b3dd52b4 (diff)
downloadniri-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.rs161
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);
+ }
}
}
}