diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index 68052826..d7ae34ca 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -293,33 +293,28 @@ impl PointerGrab for MoveGrab { } } - if self.previous == ManagedLayer::Tiling { - let indicator_location = state - .common - .shell - .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.as_logical(), - state.common.theme.clone(), + let indicator_location = state + .common + .shell + .stacking_indicator(¤t_output, self.previous); + 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.as_logical(), + state.common.theme.clone(), + ); + for output in &self.window_outputs { + element.output_enter( + output, + Rectangle::from_loc_and_size( + (0, 0), + output.geometry().size.as_logical(), + ), ); - for output in &self.window_outputs { - element.output_enter( - output, - Rectangle::from_loc_and_size( - (0, 0), - output.geometry().size.as_logical(), - ), - ); - } - (element, geo.loc.as_logical()) - }); - } + } + (element, geo.loc.as_logical()) + }); } } drop(borrow); @@ -566,13 +561,11 @@ impl Drop for MoveGrab { grab_state.window.geometry().size.as_global(), )); let workspace = state.common.shell.active_space_mut(&output); - workspace.floating_layer.map_internal( + let (window, location) = workspace.floating_layer.drop_window( grab_state.window, - Some(window_location.to_local(&workspace.output)), - None, + window_location.to_local(&workspace.output), ); - - Some((window.clone(), window_location)) + Some((window, location.to_global(&output))) } ManagedLayer::Sticky => { grab_state.window.set_geometry(Rectangle::from_loc_and_size( @@ -580,13 +573,11 @@ impl Drop for MoveGrab { grab_state.window.geometry().size.as_global(), )); let set = state.common.shell.workspaces.sets.get_mut(&output).unwrap(); - set.sticky_layer.map_internal( - grab_state.window, - Some(window_location.to_local(&output)), - None, - ); + let (window, location) = set + .sticky_layer + .drop_window(grab_state.window, window_location.to_local(&output)); - Some((window.clone(), window_location)) + Some((window, location.to_global(&output))) } } } else { diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index 41ed12af..886fb20e 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -27,11 +27,14 @@ use crate::{ shell::{ element::{ resize_indicator::ResizeIndicator, - stack::{CosmicStackRenderElement, MoveResult as StackMoveResult}, + stack::{CosmicStackRenderElement, MoveResult as StackMoveResult, TAB_HEIGHT}, window::CosmicWindowRenderElement, CosmicMapped, CosmicMappedRenderElement, CosmicWindow, }, - focus::{target::KeyboardFocusTarget, FocusStackMut}, + focus::{ + target::{KeyboardFocusTarget, PointerFocusTarget}, + FocusStackMut, + }, grabs::{ReleaseMode, ResizeEdge}, CosmicSurface, Direction, MoveResult, ResizeDirection, ResizeMode, }, @@ -50,6 +53,7 @@ pub struct FloatingLayout { pub(crate) space: Space, spawn_order: Vec, tiling_animations: HashMap)>, + hovered_stack: Option<(CosmicMapped, Rectangle)>, dirty: AtomicBool, pub theme: cosmic::Theme, } @@ -449,10 +453,53 @@ impl FloatingLayout { was_unmaped } + pub fn drop_window( + &mut self, + window: CosmicMapped, + position: Point, + ) -> (CosmicMapped, Point) { + if let Some((mapped, geo)) = self.hovered_stack.take() { + let stack = mapped.stack_ref().unwrap(); + for surface in window.windows().map(|s| s.0) { + stack.add_window(surface, None); + } + (mapped, geo.loc) + } else { + self.map_internal(window.clone(), Some(position), None); + (window, position) + } + } + pub fn element_geometry(&self, elem: &CosmicMapped) -> Option> { self.space.element_geometry(elem).map(RectExt::as_local) } + pub fn element_under( + &mut self, + location: Point, + ) -> Option<(PointerFocusTarget, Point)> { + let res = self + .space + .element_under(location.as_logical()) + .map(|(mapped, p)| (mapped.clone(), p.as_local())); + if let Some((mapped, _)) = res.as_ref() { + let geometry = self.space.element_geometry(mapped).unwrap(); + let offset = location.y.round() as i32 - geometry.loc.y; + if mapped.is_stack() && offset.is_positive() && offset <= TAB_HEIGHT { + self.hovered_stack = Some((mapped.clone(), geometry.as_local())); + } else { + self.hovered_stack.take(); + } + } else { + self.hovered_stack.take(); + } + res.map(|(m, p)| (m.into(), p)) + } + + pub fn stacking_indicator(&self) -> Option> { + self.hovered_stack.as_ref().map(|(_, geo)| geo.clone()) + } + pub fn resize_request( &mut self, mapped: &CosmicMapped, diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 4f2f26b7..8c0333f5 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -1510,6 +1510,25 @@ impl Shell { (self.resize_mode.clone(), self.resize_indicator.clone()) } + pub fn stacking_indicator( + &self, + output: &Output, + layer: ManagedLayer, + ) -> Option> { + match layer { + ManagedLayer::Sticky => self + .workspaces + .sets + .get(output) + .and_then(|set| set.sticky_layer.stacking_indicator()), + ManagedLayer::Floating => self + .active_space(output) + .floating_layer + .stacking_indicator(), + ManagedLayer::Tiling => self.active_space(output).tiling_layer.stacking_indicator(), + } + } + pub fn refresh(&mut self) { #[cfg(feature = "debug")] puffin::profile_function!(); diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index f30147d2..72ec94ed 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -424,9 +424,7 @@ impl Workspace { ) -> Option<(PointerFocusTarget, Point)> { let location = location.to_local(&self.output); self.floating_layer - .space - .element_under(location.as_logical()) - .map(|(mapped, p)| (mapped.clone().into(), p.as_local())) + .element_under(location) .or_else(|| self.tiling_layer.element_under(location, overview)) .map(|(m, p)| (m, p.to_global(&self.output))) }