diff --git a/src/input/actions.rs b/src/input/actions.rs index 4cecbe28a..45fcc2c75 100644 --- a/src/input/actions.rs +++ b/src/input/actions.rs @@ -893,6 +893,25 @@ impl State { } } + Action::TileWindow(zone) => { + use cosmic_settings_config::shortcuts::action::TilingZone; + use crate::shell::layout::floating::TiledCorners; + + let corner = match zone { + TilingZone::Top => TiledCorners::Top, + TilingZone::TopRight => TiledCorners::TopRight, + TilingZone::Right => TiledCorners::Right, + TilingZone::BottomRight => TiledCorners::BottomRight, + TilingZone::Bottom => TiledCorners::Bottom, + TilingZone::BottomLeft => TiledCorners::BottomLeft, + TilingZone::Left => TiledCorners::Left, + TilingZone::TopLeft => TiledCorners::TopLeft, + }; + + let mut shell = self.common.shell.write(); + shell.tile_window(corner, seat); + } + Action::Fullscreen => { let Some(focused_output) = seat.focused_output() else { return; diff --git a/src/shell/layout/floating/mod.rs b/src/shell/layout/floating/mod.rs index 1f3a7334e..2bc093f6c 100644 --- a/src/shell/layout/floating/mod.rs +++ b/src/shell/layout/floating/mod.rs @@ -1099,6 +1099,56 @@ impl FloatingLayout { self.toggle_stacking(&elem, focus_stack) } + pub fn tile_window( + &mut self, + window: &CosmicMapped, + corner: TiledCorners, + theme: &cosmic::Theme, + ) { + // Store previous geometry for animation + if let Some(geo) = self.space.element_geometry(window) { + let previous_geo = geo.as_local(); + + // Set the tiled corner state + *window.floating_tiled.lock().unwrap() = Some(corner); + + // Clear any maximized state + *window.maximized_state.lock().unwrap() = None; + + // Get output geometry for calculating new position + let output = self.space.outputs().next().unwrap().clone(); + let layers = layer_map_for_output(&output); + let output_geometry = layers.non_exclusive_zone(); + + // Calculate new geometry based on corner + let gaps = (theme.cosmic().gaps.0 as i32, theme.cosmic().gaps.1 as i32); + let new_geo = corner.relative_geometry(output_geometry, gaps); + + // Set window properties for tiled state + window.set_tiled(true); + window.set_maximized(false); + window.set_geometry(new_geo.to_global(&output)); + window.configure(); + + window.moved_since_mapped.store(true, Ordering::SeqCst); + + // Trigger animation + self.animations.insert( + window.clone(), + Animation::Tiled { + start: Instant::now(), + previous_geometry: previous_geo, + }, + ); + self.dirty.store(true, Ordering::SeqCst); + + // Update space mapping + self.space + .map_element(window.clone(), new_geo.loc.as_logical(), true); + self.space.refresh(); + } + } + pub fn move_element( &mut self, direction: Direction, diff --git a/src/shell/mod.rs b/src/shell/mod.rs index e28098619..a3814cc73 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -4124,6 +4124,26 @@ impl Shell { } } + pub fn tile_window(&mut self, corner: layout::floating::TiledCorners, seat: &Seat) { + let output = seat.active_output(); + let Some(workspace) = self.workspaces.active_mut(&output) else { + return; + }; + + let Some(KeyboardFocusTarget::Element(window)) = + seat.get_keyboard().and_then(|k| k.current_focus()) + else { + return; + }; + + // Only works on floating windows + if workspace.floating_layer.mapped().any(|w| w == &window) { + workspace + .floating_layer + .tile_window(&window, corner, &self.theme); + } + } + pub fn minimize_request(&mut self, surface: &S) where CosmicSurface: PartialEq,