From feee06318f604bd741ad167c85cfd03505b4ae98 Mon Sep 17 00:00:00 2001 From: Russell Greene Date: Fri, 13 Sep 2024 02:23:36 -0600 Subject: [PATCH 1/3] 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, From e6c766a2f58133d3190d983ed83b67a350fc86ff Mon Sep 17 00:00:00 2001 From: Russell Greene Date: Mon, 23 Sep 2024 21:55:12 -0600 Subject: [PATCH 2/3] review comments --- src/shell/layout/tiling/grabs/resize.rs | 207 ++++++++++-------------- src/shell/layout/tiling/mod.rs | 79 +++++---- src/shell/mod.rs | 25 +-- 3 files changed, 151 insertions(+), 160 deletions(-) diff --git a/src/shell/layout/tiling/grabs/resize.rs b/src/shell/layout/tiling/grabs/resize.rs index 4e0a9ddd..f62fcb8f 100644 --- a/src/shell/layout/tiling/grabs/resize.rs +++ b/src/shell/layout/tiling/grabs/resize.rs @@ -83,6 +83,10 @@ impl PointerTarget for ResizeForkTarget { data.common.event_loop_handle.insert_idle(move |state| { let pointer = seat.get_pointer().unwrap(); let location = pointer.current_location(); + let (left_node_idx, right_node_idx) = match orientation { + Orientation::Horizontal => (Some((node, left_up_idx)), None), + Orientation::Vertical => (None, Some((node, left_up_idx))), + }; pointer.set_grab( state, ResizeForkGrab::new( @@ -92,10 +96,8 @@ impl PointerTarget for ResizeForkTarget { location, }), location.as_global(), - node, - left_up_idx, - None, - orientation, + left_node_idx, + right_node_idx, output, ReleaseMode::NoMouseButtons, ), @@ -138,6 +140,10 @@ impl TouchTarget for ResizeForkTarget { let location = event.location; data.common.event_loop_handle.insert_idle(move |state| { let touch = seat.get_touch().unwrap(); + let (left_node_idx, right_node_idx) = match orientation { + Orientation::Horizontal => (Some((node, left_up_idx)), None), + Orientation::Vertical => (None, Some((node, left_up_idx))), + }; touch.set_grab( state, ResizeForkGrab::new( @@ -147,10 +153,8 @@ impl TouchTarget for ResizeForkTarget { location, }), location.as_global(), - node, - left_up_idx, - None, // only resizing in one dimension when dragging resize targets - orientation, + left_node_idx, + right_node_idx, output, ReleaseMode::NoMouseButtons, ), @@ -185,13 +189,11 @@ pub struct ResizeForkGrab { start_data: GrabStartData, last_loc: Point, old_tree: Option>, - accumulated_delta: f64, - accumulated_delta_parent: f64, - node: NodeId, + accumulated_delta_left: f64, + accumulated_delta_up: f64, + left_node_idx: Option<(NodeId, usize)>, + up_node_idx: Option<(NodeId, usize)>, output: WeakOutput, - left_up_idx: usize, - parent_left_up_idx: Option, - orientation: Orientation, release: ReleaseMode, } @@ -199,10 +201,8 @@ impl ResizeForkGrab { pub fn new( start_data: GrabStartData, pointer_loc: Point, - node: NodeId, - left_up_idx: usize, - parent_left_up_idx: Option, - orientation: Orientation, + left_node_idx: Option<(NodeId, usize)>, + up_node_idx: Option<(NodeId, usize)>, output: WeakOutput, release: ReleaseMode, ) -> ResizeForkGrab { @@ -210,14 +210,12 @@ impl ResizeForkGrab { start_data, last_loc: pointer_loc, old_tree: None, - accumulated_delta: 0.0, - accumulated_delta_parent: 0.0, - node, - output, - left_up_idx, - parent_left_up_idx, - orientation, + accumulated_delta_left: 0.0, + accumulated_delta_up: 0.0, + left_node_idx, + up_node_idx, release, + output, } } } @@ -260,8 +258,8 @@ impl ResizeForkGrab { if !equal { *old_tree = tree.copy_clone(); - self.accumulated_delta = 0.0; - self.accumulated_delta_parent = 0.0; + self.accumulated_delta_left = 0.0; + self.accumulated_delta_up = 0.0; } else { *tree = old_tree.copy_clone(); } @@ -270,73 +268,22 @@ impl ResizeForkGrab { *x = Some(tree.copy_clone()); } }; - if tree.get(&self.node).is_ok() { - 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(); - } - } - // check that we are still alive - let mut iter = tree - .children_ids(&self.node) - .unwrap() - .skip(self.left_up_idx); - let first_elem = iter.next(); - let second_elem = iter.next(); - if first_elem.is_none() || second_elem.is_none() { - return true; - }; - - 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 !perform_fork_grab_resize( - &mut sizes[..], - self.left_up_idx, - *orientation, - self.accumulated_delta, - ) { - return false; - } - - *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.accumulated_delta_left += delta.x.round(); + self.accumulated_delta_up += delta.y.round(); - self.last_loc = location.as_global(); - let blocker = TilingLayout::update_positions(&output, tree, gaps); - tiling_layer.pending_blockers.extend(blocker); - } else { - return true; + if let Some((left_node, left_idx)) = &self.left_node_idx { + perform_fork_grab_resize(tree, left_node, *left_idx, self.accumulated_delta_left); } + if let Some((up_node, up_idx)) = &self.up_node_idx { + perform_fork_grab_resize(tree, up_node, *up_idx, self.accumulated_delta_up); + } + + self.last_loc = location.as_global(); + let blocker = TilingLayout::update_positions(&output, tree, gaps); + tiling_layer.pending_blockers.extend(blocker); + } else { + return true; } false } @@ -574,36 +521,56 @@ impl TouchGrab for ResizeForkGrab { } fn perform_fork_grab_resize( - sizes: &mut [i32], + tree: &mut Tree, + node: &NodeId, 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 + if tree.get(&node).is_ok() { + // check that we are still alive + let mut iter = tree.children_ids(node).unwrap().skip(left_up_idx); + let first_elem = iter.next(); + let second_elem = iter.next(); + if first_elem.is_none() || second_elem.is_none() { + return true; + }; + + let node = tree.get_mut(node).unwrap(); + + match node.data_mut() { + Data::Group { + sizes, orientation, .. + } => { + 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; + } + _ => unreachable!(), + }; + } + + return true; } diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 159025af..f2793859 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -2463,51 +2463,74 @@ impl TilingLayout { edges } + // Returns (left_node_idx, up_node_idx) pub fn resize_request( &self, - mut node_id: NodeId, + window_node_id: NodeId, edge: ResizeEdge, - ) -> Option<(NodeId, usize, Option, Orientation)> { + ) -> (Option<(NodeId, usize)>, Option<(NodeId, usize)>) { let tree = self.tree(); + // need to find two NodeIds and associated index + // that indicate the groups and then the index that needs to be resized inside each one + // the one that's closer to the root is the "upper" one, and the one closer to the hovered window is the "lower" one - while let Some(group_id) = tree.get(&node_id).unwrap().parent().cloned() { - let orientation = tree.get(&group_id).unwrap().data().orientation(); - let node_idx = tree - .children_ids(&group_id) + let mut try_lower_node_id = window_node_id; + while let Some(try_lower_group_id) = tree.get(&try_lower_node_id).unwrap().parent().cloned() + { + let orientation = tree.get(&try_lower_group_id).unwrap().data().orientation(); + let lower_node_idx_in_group = tree + .children_ids(&try_lower_group_id) .unwrap() - .position(|id| id == &node_id) + .position(|id| id == &try_lower_node_id) .unwrap(); - let total = tree.children_ids(&group_id).unwrap().count(); + let lower_total = tree.children_ids(&try_lower_group_id).unwrap().count(); + if let Some(left_up_idx) = - resize_edge_to_left_up_idx(orientation, node_idx, total, edge) + resize_edge_to_left_up_idx(orientation, lower_node_idx_in_group, lower_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) + let lower_node_idx = Some((try_lower_group_id.clone(), left_up_idx)); // found a lower group id! + + // need to find closest parent that + // 1. is the opposite orientation as the lower group we found + // 2. can be resized in the direction we want + let mut try_upper_node_id = try_lower_group_id; + let mut parent_left_up_node_idx = None; + while let Some(try_upper_group_id) = + tree.get(&try_upper_node_id).unwrap().parent().cloned() + { + // ensure meets condition (1) + if tree.get(&try_upper_group_id).unwrap().data().orientation() != orientation { + let upper_node_idx_in_group = tree + .children_ids(&try_upper_group_id) .unwrap() - .position(|id| id == &group_id) + .position(|id| id == &try_upper_node_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, + let upper_total = tree.children_ids(&try_upper_group_id).unwrap().count(); + + // ensure meets condition (2) + if let Some(idx) = resize_edge_to_left_up_idx( + !orientation, + upper_node_idx_in_group, + upper_total, edge, - ) - } else { - None - }; + ) { + parent_left_up_node_idx = Some((try_upper_group_id.clone(), idx)); // found an upper group id! + break; + } + } + try_upper_node_id = try_upper_group_id; + } - return Some((group_id, left_up_idx, parent_left_up_idx, orientation)); + return match orientation { + Orientation::Horizontal => (parent_left_up_node_idx, lower_node_idx), + Orientation::Vertical => (lower_node_idx, parent_left_up_node_idx), + }; } - node_id = group_id; + try_lower_node_id = try_lower_group_id; } - None + (None, None) } pub fn resize( diff --git a/src/shell/mod.rs b/src/shell/mod.rs index b79786ba..67d7e558 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -3262,15 +3262,15 @@ 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, parent_left_up_idx, orientation) = - ws.tiling_layer.resize_request(node_id, edge)?; + let (left_node_idx, up_node_idx) = ws.tiling_layer.resize_request(node_id, edge); + if left_node_idx.is_none() && up_node_idx.is_none() { + return None; + } ResizeForkGrab::new( start_data, new_loc.to_f64(), - node, - left_up_idx, - parent_left_up_idx, - orientation, + left_node_idx, + up_node_idx, ws.output.downgrade(), ReleaseMode::Click, ) @@ -3466,15 +3466,16 @@ 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, parent_left_up_idx, orientation) = - ws.tiling_layer.resize_request(node_id, edges)?; + let (left_node_idx, up_node_idx) = + ws.tiling_layer.resize_request(node_id, edges); + if left_node_idx.is_none() && up_node_idx.is_none() { + return None; + } ResizeForkGrab::new( start_data, seat.get_pointer().unwrap().current_location().as_global(), - node, - left_up_idx, - parent_left_up_idx, - orientation, + left_node_idx, + up_node_idx, ws.output.downgrade(), ReleaseMode::NoMouseButtons, ) From 17b06f3bb0f7c82ad8fd6a81ad746aa886254df5 Mon Sep 17 00:00:00 2001 From: Russell Greene Date: Tue, 24 Sep 2024 16:10:17 -0600 Subject: [PATCH 3/3] more review comments --- src/shell/layout/tiling/grabs/resize.rs | 37 +++++++++----------- src/shell/layout/tiling/mod.rs | 46 ++++++++++++++++++++----- src/shell/mod.rs | 14 ++++---- 3 files changed, 60 insertions(+), 37 deletions(-) diff --git a/src/shell/layout/tiling/grabs/resize.rs b/src/shell/layout/tiling/grabs/resize.rs index f62fcb8f..dbf4f8c4 100644 --- a/src/shell/layout/tiling/grabs/resize.rs +++ b/src/shell/layout/tiling/grabs/resize.rs @@ -5,7 +5,7 @@ use crate::{ shell::{ focus::target::PointerFocusTarget, grabs::{GrabStartData, ReleaseMode}, - layout::Orientation, + layout::{tiling::ResizeTarget, Orientation}, }, utils::prelude::*, }; @@ -83,9 +83,10 @@ impl PointerTarget for ResizeForkTarget { data.common.event_loop_handle.insert_idle(move |state| { let pointer = seat.get_pointer().unwrap(); let location = pointer.current_location(); - let (left_node_idx, right_node_idx) = match orientation { - Orientation::Horizontal => (Some((node, left_up_idx)), None), - Orientation::Vertical => (None, Some((node, left_up_idx))), + let request = match orientation { + // NOTE: vertical split means we are resizing horizontially + Orientation::Horizontal => ResizeTarget::new_vertical(node, left_up_idx), + Orientation::Vertical => ResizeTarget::new_horizonital(node, left_up_idx), }; pointer.set_grab( state, @@ -96,8 +97,7 @@ impl PointerTarget for ResizeForkTarget { location, }), location.as_global(), - left_node_idx, - right_node_idx, + request, output, ReleaseMode::NoMouseButtons, ), @@ -140,9 +140,10 @@ impl TouchTarget for ResizeForkTarget { let location = event.location; data.common.event_loop_handle.insert_idle(move |state| { let touch = seat.get_touch().unwrap(); - let (left_node_idx, right_node_idx) = match orientation { - Orientation::Horizontal => (Some((node, left_up_idx)), None), - Orientation::Vertical => (None, Some((node, left_up_idx))), + let request = match orientation { + // NOTE: vertical split means we are resizing horizontially + Orientation::Horizontal => ResizeTarget::new_vertical(node, left_up_idx), + Orientation::Vertical => ResizeTarget::new_horizonital(node, left_up_idx), }; touch.set_grab( state, @@ -153,8 +154,7 @@ impl TouchTarget for ResizeForkTarget { location, }), location.as_global(), - left_node_idx, - right_node_idx, + request, output, ReleaseMode::NoMouseButtons, ), @@ -191,8 +191,7 @@ pub struct ResizeForkGrab { old_tree: Option>, accumulated_delta_left: f64, accumulated_delta_up: f64, - left_node_idx: Option<(NodeId, usize)>, - up_node_idx: Option<(NodeId, usize)>, + target: ResizeTarget, output: WeakOutput, release: ReleaseMode, } @@ -201,8 +200,7 @@ impl ResizeForkGrab { pub fn new( start_data: GrabStartData, pointer_loc: Point, - left_node_idx: Option<(NodeId, usize)>, - up_node_idx: Option<(NodeId, usize)>, + request: ResizeTarget, output: WeakOutput, release: ReleaseMode, ) -> ResizeForkGrab { @@ -212,8 +210,7 @@ impl ResizeForkGrab { old_tree: None, accumulated_delta_left: 0.0, accumulated_delta_up: 0.0, - left_node_idx, - up_node_idx, + target: request, release, output, } @@ -272,10 +269,10 @@ impl ResizeForkGrab { self.accumulated_delta_left += delta.x.round(); self.accumulated_delta_up += delta.y.round(); - if let Some((left_node, left_idx)) = &self.left_node_idx { + if let Some((left_node, left_idx)) = &self.target.left_node_idx { perform_fork_grab_resize(tree, left_node, *left_idx, self.accumulated_delta_left); } - if let Some((up_node, up_idx)) = &self.up_node_idx { + if let Some((up_node, up_idx)) = &self.target.up_node_idx { perform_fork_grab_resize(tree, up_node, *up_idx, self.accumulated_delta_up); } @@ -521,7 +518,7 @@ impl TouchGrab for ResizeForkGrab { } fn perform_fork_grab_resize( - tree: &mut Tree, + tree: &mut Tree, node: &NodeId, left_up_idx: usize, delta: f64, diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index f2793859..bba11eb6 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -341,6 +341,30 @@ pub struct MinimizedTilingState { pub sizes: Vec, } +#[derive(Default)] +pub struct ResizeTarget { + pub left_node_idx: Option<(NodeId, usize)>, // node ID of group, and the child inside index inside it to resize + pub up_node_idx: Option<(NodeId, usize)>, +} + +impl ResizeTarget { + pub fn new_horizonital(group: NodeId, child_idx: usize) -> Self { + Self { + left_node_idx: Some((group, child_idx)), + up_node_idx: None, + } + } + pub fn new_vertical(group: NodeId, child_idx: usize) -> Self { + Self { + left_node_idx: None, + up_node_idx: Some((group, child_idx)), + } + } + pub fn is_empty(&self) -> bool { + self.left_node_idx.is_none() && self.up_node_idx.is_none() + } +} + impl TilingLayout { pub fn new(theme: cosmic::Theme, output: &Output) -> TilingLayout { TilingLayout { @@ -2463,12 +2487,7 @@ impl TilingLayout { edges } - // Returns (left_node_idx, up_node_idx) - pub fn resize_request( - &self, - window_node_id: NodeId, - edge: ResizeEdge, - ) -> (Option<(NodeId, usize)>, Option<(NodeId, usize)>) { + pub fn resize_request(&self, window_node_id: NodeId, edge: ResizeEdge) -> ResizeTarget { let tree = self.tree(); // need to find two NodeIds and associated index // that indicate the groups and then the index that needs to be resized inside each one @@ -2522,15 +2541,24 @@ impl TilingLayout { } return match orientation { - Orientation::Horizontal => (parent_left_up_node_idx, lower_node_idx), - Orientation::Vertical => (lower_node_idx, parent_left_up_node_idx), + Orientation::Horizontal => ResizeTarget { + left_node_idx: parent_left_up_node_idx, + up_node_idx: lower_node_idx, + }, + Orientation::Vertical => ResizeTarget { + left_node_idx: lower_node_idx, + up_node_idx: parent_left_up_node_idx, + }, }; } try_lower_node_id = try_lower_group_id; } - (None, None) + ResizeTarget { + left_node_idx: None, + up_node_idx: None, + } } pub fn resize( diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 67d7e558..612fbd46 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -3262,15 +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 (left_node_idx, up_node_idx) = ws.tiling_layer.resize_request(node_id, edge); - if left_node_idx.is_none() && up_node_idx.is_none() { + let target = ws.tiling_layer.resize_request(node_id, edge); + if target.is_empty() { return None; } ResizeForkGrab::new( start_data, new_loc.to_f64(), - left_node_idx, - up_node_idx, + target, ws.output.downgrade(), ReleaseMode::Click, ) @@ -3466,16 +3465,15 @@ 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 (left_node_idx, up_node_idx) = + let target = ws.tiling_layer.resize_request(node_id, edges); - if left_node_idx.is_none() && up_node_idx.is_none() { + if target.is_empty() { return None; } ResizeForkGrab::new( start_data, seat.get_pointer().unwrap().current_location().as_global(), - left_node_idx, - up_node_idx, + target, ws.output.downgrade(), ReleaseMode::NoMouseButtons, )