diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index c6ec10fd..f486c992 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -184,7 +184,8 @@ pub struct MoveGrab { window: CosmicMapped, start_data: PointerGrabStartData, seat: Seat, - outputs: HashSet, + cursor_output: Output, + window_outputs: HashSet, tiling: bool, } @@ -196,6 +197,30 @@ impl PointerGrab for MoveGrab { _focus: Option<(PointerFocusTarget, Point)>, event: &MotionEvent, ) { + let Some(current_output) = state + .common + .shell + .outputs() + .find(|output| { + output + .geometry() + .contains(handle.current_location().to_i32_round()) + }) + .cloned() + else { + return; + }; + if self.cursor_output != current_output { + state + .common + .shell + .workspaces + .active_mut(&self.cursor_output) + .tiling_layer + .cleanup_drag(&self.cursor_output); + self.cursor_output = current_output.clone(); + } + let mut borrow = self .seat .user_data() @@ -204,9 +229,9 @@ impl PointerGrab for MoveGrab { if let Some(grab_state) = borrow.as_mut().and_then(|s| s.as_mut()) { let mut window_geo = self.window.geometry(); window_geo.loc += event.location.to_i32_round() + grab_state.window_offset; - for output in state.common.shell.outputs() { + for output in &state.common.shell.outputs { if let Some(overlap) = output.geometry().intersection(window_geo) { - if self.outputs.insert(output.clone()) { + if self.window_outputs.insert(output.clone()) { self.window.output_enter(output, overlap); if let Some(indicator) = grab_state.stacking_indicator.as_ref().map(|x| &x.0) @@ -214,7 +239,7 @@ impl PointerGrab for MoveGrab { indicator.output_enter(output, overlap); } } - } else if self.outputs.remove(&output) { + } else if self.window_outputs.remove(&output) { self.window.output_leave(output); if let Some(indicator) = grab_state.stacking_indicator.as_ref().map(|x| &x.0) { indicator.output_leave(output); @@ -222,19 +247,18 @@ impl PointerGrab for MoveGrab { } } - let output = state.common.last_active_seat().active_output(); if self.tiling { let indicator_location = state .common .shell - .active_space(&output) + .active_space(¤t_output) .tiling_layer .stacking_indicator(); if indicator_location.is_some() != grab_state.stacking_indicator.is_some() { grab_state.stacking_indicator = indicator_location.map(|geo| { let element = stack_hover(state.common.event_loop_handle.clone(), geo.size); - for output in &self.outputs { + for output in &self.window_outputs { element.output_enter(output, output.geometry()); } (element, geo.loc) @@ -327,7 +351,8 @@ impl MoveGrab { window, start_data, seat: seat.clone(), - outputs, + window_outputs: outputs, + cursor_output: output, tiling: was_tiled, } } @@ -358,7 +383,7 @@ impl MoveGrab { + grab_state.window_offset; let workspace_handle = state.common.shell.active_space(&output).handle; - for old_output in self.outputs.iter().filter(|o| *o != &output) { + for old_output in self.window_outputs.iter().filter(|o| *o != &output) { grab_state.window.output_leave(old_output); } for (window, _) in grab_state.window.windows() { diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 5743c0df..043d4f5b 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -1641,6 +1641,40 @@ impl TilingLayout { } } + pub fn cleanup_drag(&mut self, output: &Output) { + let mut queue = self.queues.get_mut(output); + let mut owned_tree = None; + let mut tree = if let Some(queue) = queue.as_mut() { + owned_tree = queue.trees.back().map(|x| x.0.copy_clone()); + owned_tree.as_mut() + } else { + self.standby_tree.as_mut() + } + .unwrap(); + + if let Some(root) = tree.root_node_id() { + for id in tree + .traverse_pre_order_ids(root) + .unwrap() + .collect::>() + .into_iter() + { + match tree.get_mut(&id).map(|node| node.data_mut()) { + Ok(Data::Placeholder { .. }) => TilingLayout::unmap_internal(&mut tree, &id), + Ok(Data::Group { pill_indicator, .. }) if pill_indicator.is_some() => { + pill_indicator.take(); + } + _ => {} + } + } + + if let Some(mut tree) = owned_tree { + let blocker = TilingLayout::update_positions(output, &mut tree, self.gaps); + queue.unwrap().push_tree(tree, ANIMATION_DURATION, blocker); + } + } + } + pub fn drop_window( &mut self, window: CosmicMapped, diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 8663c67a..2240c461 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -1003,6 +1003,12 @@ impl Shell { if match &mut self.workspaces { WorkspaceMode::OutputBound(sets, _) => { if let Some(set) = sets.get_mut(output) { + if matches!( + self.overview_mode, + OverviewMode::Started(Trigger::Pointer(_), _) + ) { + set.workspaces[set.active].tiling_layer.cleanup_drag(output); + } set.activate(idx, &mut self.workspace_state.update())? } else { false