From feee06318f604bd741ad167c85cfd03505b4ae98 Mon Sep 17 00:00:00 2001 From: Russell Greene Date: Fri, 13 Sep 2024 02:23:36 -0600 Subject: [PATCH] Allow resize in both direcitons on Meta+Right click Fixes #858 This is just an initial implementation, it seems to work alright but I'm unfamilar with this codebase so may have done something in a silly way. --- src/shell/layout/tiling/grabs/resize.rs | 118 +++++++++++++++++------- src/shell/layout/tiling/mod.rs | 65 ++++++++++--- src/shell/mod.rs | 7 +- 3 files changed, 139 insertions(+), 51 deletions(-) diff --git a/src/shell/layout/tiling/grabs/resize.rs b/src/shell/layout/tiling/grabs/resize.rs index 03a3cf62..4e0a9ddd 100644 --- a/src/shell/layout/tiling/grabs/resize.rs +++ b/src/shell/layout/tiling/grabs/resize.rs @@ -94,6 +94,7 @@ impl PointerTarget for ResizeForkTarget { location.as_global(), node, left_up_idx, + None, orientation, output, ReleaseMode::NoMouseButtons, @@ -148,6 +149,7 @@ impl TouchTarget for ResizeForkTarget { location.as_global(), node, left_up_idx, + None, // only resizing in one dimension when dragging resize targets orientation, output, ReleaseMode::NoMouseButtons, @@ -184,9 +186,11 @@ pub struct ResizeForkGrab { last_loc: Point, old_tree: Option>, accumulated_delta: f64, + accumulated_delta_parent: f64, node: NodeId, output: WeakOutput, left_up_idx: usize, + parent_left_up_idx: Option, orientation: Orientation, release: ReleaseMode, } @@ -196,7 +200,8 @@ impl ResizeForkGrab { start_data: GrabStartData, pointer_loc: Point, node: NodeId, - idx: usize, + left_up_idx: usize, + parent_left_up_idx: Option, orientation: Orientation, output: WeakOutput, release: ReleaseMode, @@ -206,9 +211,11 @@ impl ResizeForkGrab { last_loc: pointer_loc, old_tree: None, accumulated_delta: 0.0, + accumulated_delta_parent: 0.0, node, output, - left_up_idx: idx, + left_up_idx, + parent_left_up_idx, orientation, release, } @@ -254,6 +261,7 @@ impl ResizeForkGrab { if !equal { *old_tree = tree.copy_clone(); self.accumulated_delta = 0.0; + self.accumulated_delta_parent = 0.0; } else { *tree = old_tree.copy_clone(); } @@ -263,12 +271,16 @@ impl ResizeForkGrab { } }; if tree.get(&self.node).is_ok() { - let delta = match self.orientation { - Orientation::Vertical => delta.x, - Orientation::Horizontal => delta.y, + match self.orientation { + Orientation::Horizontal => { + self.accumulated_delta += delta.y.round(); + self.accumulated_delta_parent += delta.x.round(); + } + Orientation::Vertical => { + self.accumulated_delta += delta.x.round(); + self.accumulated_delta_parent += delta.y.round(); + } } - .round(); - self.accumulated_delta += delta; // check that we are still alive let mut iter = tree @@ -281,39 +293,42 @@ impl ResizeForkGrab { return true; }; - match tree.get_mut(&self.node).unwrap().data_mut() { + let node = tree.get_mut(&self.node).unwrap(); + let parent = node.parent().cloned(); + + let child_orientation = match node.data_mut() { Data::Group { sizes, orientation, .. } => { - if sizes[self.left_up_idx] + sizes[self.left_up_idx + 1] - < match orientation { - Orientation::Vertical => 720, - Orientation::Horizontal => 480, - } - { + if !perform_fork_grab_resize( + &mut sizes[..], + self.left_up_idx, + *orientation, + self.accumulated_delta, + ) { return false; - }; - - let old_size = sizes[self.left_up_idx]; - sizes[self.left_up_idx] = (old_size - + self.accumulated_delta.round() as i32) - .max(if self.orientation == Orientation::Vertical { - 360 - } else { - 240 - }); - let diff = old_size - sizes[self.left_up_idx]; - let next_size = sizes[self.left_up_idx + 1] + diff; - sizes[self.left_up_idx + 1] = - next_size.max(if self.orientation == Orientation::Vertical { - 360 - } else { - 240 - }); - let next_diff = next_size - sizes[self.left_up_idx + 1]; - sizes[self.left_up_idx] += next_diff; + } + + *orientation } _ => unreachable!(), + }; + + if let Some(parent_left_up_idx) = self.parent_left_up_idx { + if let Some(Data::Group { + orientation, sizes, .. + }) = parent.map(|p| tree.get_mut(&p).unwrap().data_mut()) + { + if *orientation == child_orientation { + return false; // definitely want it to be the other direction, strange situation if not... + } + perform_fork_grab_resize( + &mut sizes[..], + parent_left_up_idx, + *orientation, + self.accumulated_delta_parent, + ); + } } self.last_loc = location.as_global(); @@ -557,3 +572,38 @@ impl TouchGrab for ResizeForkGrab { fn unset(&mut self, _data: &mut State) {} } + +fn perform_fork_grab_resize( + sizes: &mut [i32], + left_up_idx: usize, + orientation: Orientation, + delta: f64, +) -> bool { + if sizes[left_up_idx] + sizes[left_up_idx + 1] + < match orientation { + Orientation::Vertical => 720, + Orientation::Horizontal => 480, + } + { + return false; + }; + + let old_size = sizes[left_up_idx]; + sizes[left_up_idx] = + (old_size + delta.round() as i32).max(if orientation == Orientation::Vertical { + 360 + } else { + 240 + }); + let diff = old_size - sizes[left_up_idx]; + let next_size = sizes[left_up_idx + 1] + diff; + sizes[left_up_idx + 1] = next_size.max(if orientation == Orientation::Vertical { + 360 + } else { + 240 + }); + let next_diff = next_size - sizes[left_up_idx + 1]; + sizes[left_up_idx] += next_diff; + + true +} diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index feeebcd8..159025af 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -2467,7 +2467,7 @@ impl TilingLayout { &self, mut node_id: NodeId, edge: ResizeEdge, - ) -> Option<(NodeId, usize, Orientation)> { + ) -> Option<(NodeId, usize, Option, Orientation)> { let tree = self.tree(); while let Some(group_id) = tree.get(&node_id).unwrap().parent().cloned() { @@ -2478,20 +2478,30 @@ impl TilingLayout { .position(|id| id == &node_id) .unwrap(); let total = tree.children_ids(&group_id).unwrap().count(); - if orientation == Orientation::Vertical { - if node_idx > 0 && edge.contains(ResizeEdge::LEFT) { - return Some((group_id, node_idx - 1, orientation)); - } - if node_idx < total - 1 && edge.contains(ResizeEdge::RIGHT) { - return Some((group_id, node_idx, orientation)); - } - } else { - if node_idx > 0 && edge.contains(ResizeEdge::TOP) { - return Some((group_id, node_idx - 1, orientation)); - } - if node_idx < total - 1 && edge.contains(ResizeEdge::BOTTOM) { - return Some((group_id, node_idx, orientation)); - } + if let Some(left_up_idx) = + resize_edge_to_left_up_idx(orientation, node_idx, total, edge) + { + let parent_left_up_idx = + if let Some(group_parent) = tree.get(&group_id).unwrap().parent() { + let group_idx = tree + .children_ids(&group_parent) + .unwrap() + .position(|id| id == &group_id) + .unwrap(); + let group_parent_orientation = + tree.get(&group_parent).unwrap().data().orientation(); + let group_parent_total = tree.children_ids(&group_parent).unwrap().count(); + resize_edge_to_left_up_idx( + group_parent_orientation, + group_idx, + group_parent_total, + edge, + ) + } else { + None + }; + + return Some((group_id, left_up_idx, parent_left_up_idx, orientation)); } node_id = group_id; @@ -5413,3 +5423,28 @@ fn scale_to_center( ) } } + +fn resize_edge_to_left_up_idx( + orientation: Orientation, + node_idx: usize, + total: usize, + edge: ResizeEdge, +) -> Option { + if orientation == Orientation::Vertical { + if node_idx > 0 && edge.contains(ResizeEdge::LEFT) { + return Some(node_idx - 1); + } + if node_idx < total - 1 && edge.contains(ResizeEdge::RIGHT) { + return Some(node_idx); + } + } else { + if node_idx > 0 && edge.contains(ResizeEdge::TOP) { + return Some(node_idx - 1); + } + if node_idx < total - 1 && edge.contains(ResizeEdge::BOTTOM) { + return Some(node_idx); + } + } + + None +} diff --git a/src/shell/mod.rs b/src/shell/mod.rs index c32f5cc5..b79786ba 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -3262,12 +3262,14 @@ impl Shell { grab.into() } else if let Some(ws) = self.space_for_mut(&mapped) { let node_id = mapped.tiling_node_id.lock().unwrap().clone()?; - let (node, left_up_idx, orientation) = ws.tiling_layer.resize_request(node_id, edge)?; + let (node, left_up_idx, parent_left_up_idx, orientation) = + ws.tiling_layer.resize_request(node_id, edge)?; ResizeForkGrab::new( start_data, new_loc.to_f64(), node, left_up_idx, + parent_left_up_idx, orientation, ws.output.downgrade(), ReleaseMode::Click, @@ -3464,13 +3466,14 @@ impl Shell { grab.into() } else if let Some(ws) = self.space_for_mut(&mapped) { let node_id = mapped.tiling_node_id.lock().unwrap().clone()?; - let (node, left_up_idx, orientation) = + let (node, left_up_idx, parent_left_up_idx, orientation) = ws.tiling_layer.resize_request(node_id, edges)?; ResizeForkGrab::new( start_data, seat.get_pointer().unwrap().current_location().as_global(), node, left_up_idx, + parent_left_up_idx, orientation, ws.output.downgrade(), ReleaseMode::NoMouseButtons,