floating: Allow dragging windows into stacks

This commit is contained in:
Victoria Brekenfeld 2024-01-08 21:37:06 +00:00 committed by Victoria Brekenfeld
parent e9c5266509
commit 9ca5edc836
4 changed files with 97 additions and 42 deletions

View file

@ -293,33 +293,28 @@ impl PointerGrab<State> for MoveGrab {
}
}
if self.previous == ManagedLayer::Tiling {
let indicator_location = state
.common
.shell
.active_space(&current_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(&current_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 {

View file

@ -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<CosmicMapped>,
spawn_order: Vec<CosmicMapped>,
tiling_animations: HashMap<CosmicMapped, (Instant, Rectangle<i32, Local>)>,
hovered_stack: Option<(CosmicMapped, Rectangle<i32, Local>)>,
dirty: AtomicBool,
pub theme: cosmic::Theme,
}
@ -449,10 +453,53 @@ impl FloatingLayout {
was_unmaped
}
pub fn drop_window(
&mut self,
window: CosmicMapped,
position: Point<i32, Local>,
) -> (CosmicMapped, Point<i32, Local>) {
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<Rectangle<i32, Local>> {
self.space.element_geometry(elem).map(RectExt::as_local)
}
pub fn element_under(
&mut self,
location: Point<f64, Local>,
) -> Option<(PointerFocusTarget, Point<i32, Local>)> {
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<Rectangle<i32, Local>> {
self.hovered_stack.as_ref().map(|(_, geo)| geo.clone())
}
pub fn resize_request(
&mut self,
mapped: &CosmicMapped,

View file

@ -1510,6 +1510,25 @@ impl Shell {
(self.resize_mode.clone(), self.resize_indicator.clone())
}
pub fn stacking_indicator(
&self,
output: &Output,
layer: ManagedLayer,
) -> Option<Rectangle<i32, Local>> {
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!();

View file

@ -424,9 +424,7 @@ impl Workspace {
) -> Option<(PointerFocusTarget, Point<i32, Global>)> {
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)))
}