diff --git a/src/config/mod.rs b/src/config/mod.rs index c75dabe4..74d444f4 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -924,6 +924,17 @@ impl PartialEq for KeyModifiers { } } +impl Into for ModifiersState { + fn into(self) -> KeyModifiers { + KeyModifiers { + ctrl: self.ctrl, + alt: self.alt, + shift: self.shift, + logo: self.logo, + } + } +} + impl std::ops::AddAssign for KeyModifiers { fn add_assign(&mut self, rhs: KeyModifier) { match rhs { diff --git a/src/input/mod.rs b/src/input/mod.rs index 71804b70..91b67b8f 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -4,11 +4,12 @@ use crate::{ config::{Action, Config, KeyPattern, WorkspaceLayout}, shell::{ focus::{target::PointerFocusTarget, FocusDirection}, + grabs::ResizeEdge, layout::{ floating::SeatMoveGrabState, tiling::{Direction, FocusResult, MoveResult}, }, - OverviewMode, Workspace, + OverviewMode, ResizeMode, Workspace, }, // shell::grabs::SeatMoveGrabState state::Common, utils::prelude::*, @@ -229,6 +230,7 @@ impl State { serial, time, |data, modifiers, handle| { + // Leave overview mode, if any modifier was released if let OverviewMode::Started(action_modifiers, _) = data.common.shell.overview_mode() { @@ -241,12 +243,66 @@ impl State { } } + // Leave or update resize mode, if modifiers changed or initial key was released + if let ResizeMode::Started(action_pattern, _, _) = + data.common.shell.resize_mode() + { + if state == KeyState::Released + && handle.raw_syms().contains(&action_pattern.key) + { + data.common.shell.set_resize_mode(None); + return FilterResult::Intercept(None); + } else if action_pattern.modifiers != *modifiers { + let mut new_pattern = action_pattern.clone(); + new_pattern.modifiers = modifiers.clone().into(); + let enabled = data + .common + .config + .static_conf + .key_bindings + .iter() + .find_map(move |(binding, action)| { + if binding == &new_pattern + && matches!(action, Action::Resizing(_)) + { + let Action::Resizing(direction) = action else { unreachable!() }; + Some((new_pattern.clone(), *direction)) + } else { + None + } + }); + data.common.shell.set_resize_mode(enabled); + } + } + + // Special case resizing with regards to arrow keys + if let ResizeMode::Started(_, _, direction) = + data.common.shell.resize_mode() + { + if state == KeyState::Pressed { + let resize_edge = match handle.modified_sym() { + keysyms::KEY_Left | keysyms::KEY_H => Some(ResizeEdge::LEFT), + keysyms::KEY_Down | keysyms::KEY_J => Some(ResizeEdge::BOTTOM), + keysyms::KEY_Up | keysyms::KEY_K => Some(ResizeEdge::TOP), + keysyms::KEY_Right | keysyms::KEY_L => Some(ResizeEdge::RIGHT), + _ => None, + }; + + if let Some(edge) = resize_edge { + data.common.shell.resize_active_window(seat, direction, edge); + return FilterResult::Intercept(None); + } + } + } + + // Skip released events for initially surpressed keys if state == KeyState::Released && userdata.get::().unwrap().filter(&handle) { return FilterResult::Intercept(None); } + // Pass keys to debug interface, if it has focus #[cfg(feature = "debug")] { if data.common.seats().position(|x| x == seat).unwrap() == 0 @@ -267,6 +323,7 @@ impl State { } } + // Handle VT switches if state == KeyState::Pressed && (keysyms::KEY_XF86Switch_VT_1..=KEY_XF86Switch_VT_12) .contains(&handle.modified_sym()) @@ -282,7 +339,7 @@ impl State { return FilterResult::Intercept(None); } - // here we can handle global shortcuts and the like + // handle the rest of the global shortcuts if !shortcuts_inhibited { for (binding, action) in data.common.config.static_conf.key_bindings.iter() @@ -303,6 +360,7 @@ impl State { } } + // keys are passed through to apps FilterResult::Forward }, ) diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 5b34487c..ba23e863 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -1187,6 +1187,17 @@ impl Shell { self.resize_mode.clone() } + pub fn resize_active_window( + &mut self, + seat: &Seat, + direction: ResizeDirection, + edge: ResizeEdge, + ) { + self.workspaces + .active_mut(&seat.active_output()) + .resize(seat, direction, edge); + } + pub fn refresh(&mut self) { #[cfg(feature = "debug")] puffin::profile_function!(); diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index d23edefa..5e4601c8 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -48,9 +48,9 @@ use tracing::warn; use super::{ element::{stack::CosmicStackRenderElement, window::CosmicWindowRenderElement, CosmicMapped}, - focus::{FocusStack, FocusStackMut}, + focus::{target::KeyboardFocusTarget, FocusStack, FocusStackMut}, grabs::{ResizeEdge, ResizeGrab}, - CosmicMappedRenderElement, CosmicSurface, + CosmicMappedRenderElement, CosmicSurface, ResizeDirection, }; #[derive(Debug)] @@ -341,6 +341,18 @@ impl Workspace { } } + pub fn resize(&mut self, seat: &Seat, direction: ResizeDirection, edge: ResizeEdge) { + if let Some(KeyboardFocusTarget::Fullscreen(_)) = + seat.get_keyboard().unwrap().current_focus() + { + return; + } + + if !self.floating_layer.resize(seat, direction, edge) { + self.tiling_layer.resize(seat, direction, edge); + } + } + pub fn move_request( &mut self, window: &CosmicSurface,