diff --git a/src/backend/render/mod.rs b/src/backend/render/mod.rs index 2674a938..0792fc8c 100644 --- a/src/backend/render/mod.rs +++ b/src/backend/render/mod.rs @@ -545,7 +545,7 @@ where let overview = shell.overview_mode(); let (resize_mode, resize_indicator) = shell.resize_mode(); let resize_indicator = resize_indicator.map(|indicator| (resize_mode, indicator)); - let swap_tree = if let OverviewMode::Started(Trigger::KeyboardSwap(_, desc), _) = &overview.0 { + let swap_tree = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.active_trigger() { if current.0 != desc.handle { shell .workspaces @@ -657,6 +657,7 @@ where * 0.4 + 0.6 } + OverviewMode::Active(_) => 0.6, OverviewMode::None => 1.0, }; diff --git a/src/input/mod.rs b/src/input/mod.rs index c71bed8f..bc4f4b46 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -16,8 +16,7 @@ use crate::{ floating::ResizeGrabMarker, tiling::{SwapWindowGrab, TilingLayout}, }, - FocusResult, InvalidWorkspaceIndex, MoveResult, OverviewMode, ResizeMode, SeatExt, Trigger, - WorkspaceDelta, + FocusResult, InvalidWorkspaceIndex, MoveResult, SeatExt, Trigger, WorkspaceDelta, }, utils::prelude::*, wayland::{ @@ -229,8 +228,8 @@ impl State { time, |data, modifiers, handle| { // Leave move overview mode, if any modifier was released - if let OverviewMode::Started(Trigger::KeyboardMove(action_modifiers), _) = - shell.overview_mode().0 + if let Some(Trigger::KeyboardMove(action_modifiers)) = + shell.overview_mode().0.active_trigger() { if (action_modifiers.ctrl && !modifiers.ctrl) || (action_modifiers.alt && !modifiers.alt) @@ -241,8 +240,8 @@ impl State { } } // Leave swap overview mode, if any key was released - if let OverviewMode::Started(Trigger::KeyboardSwap(action_pattern, old_descriptor), _) = - shell.overview_mode().0 + if let Some(Trigger::KeyboardSwap(action_pattern, old_descriptor)) = + shell.overview_mode().0.active_trigger() { if (action_pattern.modifiers.ctrl && !modifiers.ctrl) || (action_pattern.modifiers.alt && !modifiers.alt) @@ -290,7 +289,7 @@ impl State { if let Some(old_workspace) = old_w.get_mut(0) { if let Some(new_workspace) = other_w.iter_mut().find(|w| w.handle == new_workspace) { if new_workspace.tiling_layer.windows().next().is_none() { - if let Some(focus) = TilingLayout::move_tree(&mut old_workspace.tiling_layer, &mut new_workspace.tiling_layer, &new_workspace.handle, &seat, new_workspace.focus_stack.get(&seat).iter(), old_descriptor) { + if let Some(focus) = TilingLayout::move_tree(&mut old_workspace.tiling_layer, &mut new_workspace.tiling_layer, &new_workspace.handle, &seat, new_workspace.focus_stack.get(&seat).iter(), old_descriptor.clone()) { let seat = seat.clone(); data.common.event_loop_handle.insert_idle(move |state| { Shell::set_focus(state, Some(&focus), &seat, None); @@ -306,8 +305,8 @@ impl State { } // Leave or update resize mode, if modifiers changed or initial key was released - if let (ResizeMode::Started(action_pattern, _, _), _) = - shell.resize_mode() + if let Some(action_pattern) = + shell.resize_mode().0.active_binding() { if action_pattern.key.is_some() && state == KeyState::Released && handle.raw_syms().contains(&action_pattern.key.unwrap()) @@ -336,8 +335,8 @@ impl State { } // Special case resizing with regards to arrow keys - if let (ResizeMode::Started(_, _, direction), _) = - shell.resize_mode() + if let Some(direction) = + shell.resize_mode().0.active_direction() { let resize_edge = match handle.modified_sym() { Keysym::Left | Keysym::h | Keysym::H => Some(ResizeEdge::LEFT), @@ -913,10 +912,10 @@ impl State { std::mem::drop(shell); } } else { - if let OverviewMode::Started(Trigger::Pointer(action_button), _) = - shell.overview_mode().0 + if let Some(Trigger::Pointer(action_button)) = + shell.overview_mode().0.active_trigger() { - if action_button == button { + if *action_button == button { shell .set_overview_mode(None, self.common.event_loop_handle.clone()); } @@ -1341,8 +1340,8 @@ impl State { } InputEvent::TouchUp { event, .. } => { let mut shell = self.common.shell.write().unwrap(); - if let OverviewMode::Started(Trigger::Touch(slot), _) = shell.overview_mode().0 { - if slot == event.slot() { + if let Some(Trigger::Touch(slot)) = shell.overview_mode().0.active_trigger() { + if *slot == event.slot() { shell.set_overview_mode(None, self.common.event_loop_handle.clone()); } } diff --git a/src/shell/layout/tiling/grabs/swap.rs b/src/shell/layout/tiling/grabs/swap.rs index 9805a07b..a0004eef 100644 --- a/src/shell/layout/tiling/grabs/swap.rs +++ b/src/shell/layout/tiling/grabs/swap.rs @@ -14,7 +14,7 @@ use xkbcommon::xkb::Keysym; use crate::{ config::key_bindings::cosmic_modifiers_from_smithay, - shell::{layout::tiling::NodeDesc, OverviewMode, Trigger}, + shell::{layout::tiling::NodeDesc, Trigger}, state::State, }; @@ -40,7 +40,7 @@ impl KeyboardGrab for SwapWindowGrab { serial: Serial, time: u32, ) { - if !matches!(&data.common.shell.read().unwrap().overview_mode, OverviewMode::Started(Trigger::KeyboardSwap(_, d), _) if d == &self.desc) + if !matches!(&data.common.shell.read().unwrap().overview_mode.active_trigger(), Some(Trigger::KeyboardSwap(_, d)) if d == &self.desc) { handle.unset_grab(self, data, serial, false); return; diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 83084b3f..3d143089 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -3137,7 +3137,10 @@ impl TilingLayout { } } - if !matches!(overview, OverviewMode::Started(_, _)) { + if !matches!( + overview, + OverviewMode::Started(_, _) | OverviewMode::Active(_) + ) { last_overview_hover.take(); } @@ -3249,8 +3252,8 @@ impl TilingLayout { _ => None, } } else if matches!( - overview, - OverviewMode::Started(Trigger::Pointer(_) | Trigger::Touch(_), _) + overview.active_trigger(), + Some(Trigger::Pointer(_) | Trigger::Touch(_)) ) { let non_exclusive_zone = layer_map_for_output(&self.output) .non_exclusive_zone() @@ -3889,12 +3892,12 @@ impl TilingLayout { let mut popup_elements = Vec::new(); let is_overview = !matches!(overview.0, OverviewMode::None); - let is_mouse_tiling = (matches!(overview.0, OverviewMode::Started(Trigger::Pointer(_), _))) + let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) .then(|| self.last_overview_hover.as_ref().map(|x| &x.1)); - let swap_desc = match &overview.0 { - OverviewMode::Started(Trigger::KeyboardSwap(_, desc), _) - | OverviewMode::Ended(Some(Trigger::KeyboardSwap(_, desc)), _) => Some(desc.clone()), - _ => None, + let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() { + Some(desc.clone()) + } else { + None }; // all gone windows and fade them out diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 6e7cddbe..47c42660 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -116,6 +116,7 @@ pub enum Trigger { pub enum OverviewMode { None, Started(Trigger, Instant), + Active(Trigger), Ended(Option, Instant), } @@ -127,6 +128,7 @@ impl OverviewMode { / ANIMATION_DURATION.as_millis() as f32; Some(ease(EaseInOutCubic, 0.0, 1.0, percentage)) } + OverviewMode::Active(_) => Some(1.0), OverviewMode::Ended(_, end) => { let percentage = Instant::now().duration_since(*end).as_millis() as f32 / ANIMATION_DURATION.as_millis() as f32; @@ -139,12 +141,31 @@ impl OverviewMode { OverviewMode::None => None, } } + + pub fn active_trigger(&self) -> Option<&Trigger> { + if let OverviewMode::Started(trigger, _) | OverviewMode::Active(trigger) = self { + Some(trigger) + } else { + None + } + } + + pub fn trigger(&self) -> Option<&Trigger> { + self.active_trigger().or_else(|| { + if let OverviewMode::Ended(trigger, _) = self { + trigger.as_ref() + } else { + None + } + }) + } } #[derive(Debug, Clone)] pub enum ResizeMode { None, Started(shortcuts::Binding, Instant, ResizeDirection), + Active(shortcuts::Binding, ResizeDirection), Ended(Instant, ResizeDirection), } @@ -156,6 +177,7 @@ impl ResizeMode { / ANIMATION_DURATION.as_millis() as f32; Some(ease(EaseInOutCubic, 0.0, 1.0, percentage)) } + ResizeMode::Active(_, _) => Some(1.0), ResizeMode::Ended(end, _) => { let percentage = Instant::now().duration_since(*end).as_millis() as f32 / ANIMATION_DURATION.as_millis() as f32; @@ -168,6 +190,22 @@ impl ResizeMode { ResizeMode::None => None, } } + + pub fn active_binding(&self) -> Option<&shortcuts::Binding> { + if let ResizeMode::Started(binding, _, _) | ResizeMode::Active(binding, _) = self { + Some(binding) + } else { + None + } + } + + pub fn active_direction(&self) -> Option { + if let ResizeMode::Started(_, _, direction) | ResizeMode::Active(_, direction) = self { + Some(*direction) + } else { + None + } + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -1190,8 +1228,8 @@ impl Shell { WorkspaceMode::OutputBound => { if let Some(set) = self.workspaces.sets.get_mut(output) { if matches!( - self.overview_mode, - OverviewMode::Started(Trigger::Pointer(_) | Trigger::Touch(_), _) + self.overview_mode.active_trigger(), + Some(Trigger::Pointer(_) | Trigger::Touch(_)) ) { set.workspaces[set.active].tiling_layer.cleanup_drag(); } @@ -1240,8 +1278,8 @@ impl Shell { WorkspaceMode::OutputBound => { if let Some(set) = self.workspaces.sets.get_mut(output) { if matches!( - self.overview_mode, - OverviewMode::Started(Trigger::Pointer(_) | Trigger::Touch(_), _) + self.overview_mode.active_trigger(), + Some(Trigger::Pointer(_) | Trigger::Touch(_)) ) { set.workspaces[set.active].tiling_layer.cleanup_drag(); } @@ -1526,12 +1564,16 @@ impl Shell { .as_ref() .is_some_and(|(_, delta)| delta.is_animating()) || set.sticky_layer.animations_going() - }) || !matches!(self.overview_mode, OverviewMode::None) - || !matches!(self.resize_mode, ResizeMode::None) - || self - .workspaces - .spaces() - .any(|workspace| workspace.animations_going()) + }) || !matches!( + self.overview_mode, + OverviewMode::None | OverviewMode::Active(_) + ) || !matches!( + self.resize_mode, + ResizeMode::None | ResizeMode::Active(_, _) + ) || self + .workspaces + .spaces() + .any(|workspace| workspace.animations_going()) } pub fn update_animations(&mut self) -> HashMap { @@ -1551,14 +1593,20 @@ impl Shell { evlh: LoopHandle<'static, crate::state::State>, ) { if let Some(trigger) = enabled { - if !matches!(self.overview_mode, OverviewMode::Started(_, _)) { + if !matches!( + self.overview_mode, + OverviewMode::Started(_, _) | OverviewMode::Active(_) + ) { if matches!(trigger, Trigger::KeyboardSwap(_, _)) { self.swap_indicator = Some(swap_indicator(evlh, self.theme.clone())); } self.overview_mode = OverviewMode::Started(trigger, Instant::now()); } } else { - if matches!(self.overview_mode, OverviewMode::Started(_, _)) { + if matches!( + self.overview_mode, + OverviewMode::Started(_, _) | OverviewMode::Active(_) + ) { let (reverse_duration, trigger) = if let OverviewMode::Started(trigger, start) = self.overview_mode.clone() { ( @@ -1567,7 +1615,7 @@ impl Shell { Some(trigger), ) } else { - (Duration::ZERO, None) + (Duration::ZERO, self.overview_mode.active_trigger().cloned()) }; self.overview_mode = OverviewMode::Ended(trigger, Instant::now() - reverse_duration); @@ -1576,8 +1624,16 @@ impl Shell { } pub fn overview_mode(&self) -> (OverviewMode, Option) { - if let OverviewMode::Ended(_, timestamp) = self.overview_mode { - if Instant::now().duration_since(timestamp) > ANIMATION_DURATION { + if let OverviewMode::Started(trigger, timestamp) = &self.overview_mode { + if Instant::now().duration_since(*timestamp) > ANIMATION_DURATION { + return ( + OverviewMode::Active(trigger.clone()), + self.swap_indicator.clone(), + ); + } + } + if let OverviewMode::Ended(_, timestamp) = &self.overview_mode { + if Instant::now().duration_since(*timestamp) > ANIMATION_DURATION { return (OverviewMode::None, None); } } @@ -1605,8 +1661,8 @@ impl Shell { self.theme.clone(), )); } else { - if let ResizeMode::Started(_, _, direction) = &self.resize_mode { - self.resize_mode = ResizeMode::Ended(Instant::now(), *direction); + if let Some(direction) = self.resize_mode.active_direction() { + self.resize_mode = ResizeMode::Ended(Instant::now(), direction); if let Some((_, direction, edge, _, _, _)) = self.resize_state.as_ref() { self.finish_resize(*direction, *edge); } @@ -1615,6 +1671,14 @@ impl Shell { } pub fn resize_mode(&self) -> (ResizeMode, Option) { + if let ResizeMode::Started(binding, timestamp, direction) = &self.resize_mode { + if Instant::now().duration_since(*timestamp) > ANIMATION_DURATION { + return ( + ResizeMode::Active(binding.clone(), *direction), + self.resize_indicator.clone(), + ); + } + } if let ResizeMode::Ended(timestamp, _) = self.resize_mode { if Instant::now().duration_since(timestamp) > ANIMATION_DURATION { return (ResizeMode::None, None); @@ -1648,17 +1712,34 @@ impl Shell { xdg_activation_state: &XdgActivationState, workspace_state: &mut WorkspaceUpdateGuard<'_, State>, ) { - if let OverviewMode::Ended(_, timestamp) = self.overview_mode { - if Instant::now().duration_since(timestamp) > ANIMATION_DURATION { + match &self.overview_mode { + OverviewMode::Started(trigger, timestamp) + if Instant::now().duration_since(*timestamp) > ANIMATION_DURATION => + { + self.overview_mode = OverviewMode::Active(trigger.clone()); + } + OverviewMode::Ended(_, timestamp) + if Instant::now().duration_since(*timestamp) > ANIMATION_DURATION => + { self.overview_mode = OverviewMode::None; self.swap_indicator = None; } + _ => {} } - if let ResizeMode::Ended(timestamp, _) = self.resize_mode { - if Instant::now().duration_since(timestamp) > ANIMATION_DURATION { + + match &self.resize_mode { + ResizeMode::Started(binding, timestamp, direction) + if Instant::now().duration_since(*timestamp) > ANIMATION_DURATION => + { + self.resize_mode = ResizeMode::Active(binding.clone(), *direction); + } + ResizeMode::Ended(timestamp, _) + if Instant::now().duration_since(*timestamp) > ANIMATION_DURATION => + { self.resize_mode = ResizeMode::None; self.resize_indicator = None; } + _ => {} } self.workspaces @@ -2559,8 +2640,8 @@ impl Shell { .find(|e| *e == &elem), KeyboardFocusTarget::Group { .. } => { let focus_stack = workspace.focus_stack.get(seat); - let swap_desc = match overview { - OverviewMode::Started(Trigger::KeyboardSwap(_, desc), _) => Some(desc), + let swap_desc = match overview.active_trigger() { + Some(Trigger::KeyboardSwap(_, desc)) => Some(desc.clone()), _ => None, }; @@ -2583,8 +2664,8 @@ impl Shell { if workspace.is_tiled(&focused) { let focus_stack = workspace.focus_stack.get(seat); - let swap_desc = match overview { - OverviewMode::Started(Trigger::KeyboardSwap(_, desc), _) => Some(desc), + let swap_desc = match overview.active_trigger() { + Some(Trigger::KeyboardSwap(_, desc)) => Some(desc.clone()), _ => None, }; diff --git a/src/shell/workspace.rs b/src/shell/workspace.rs index c161886d..804a29df 100644 --- a/src/shell/workspace.rs +++ b/src/shell/workspace.rs @@ -1146,6 +1146,7 @@ impl Workspace { * 0.4 + 0.6 } + OverviewMode::Active(_) => 0.6, OverviewMode::None => 1.0, }; @@ -1165,11 +1166,12 @@ impl Workspace { (Instant::now().duration_since(*start).as_millis() as f64 / 100.0).min(1.0) as f32, ), + OverviewMode::Active(_) => Some(1.0), OverviewMode::Ended(_, ended) => Some( 1.0 - (Instant::now().duration_since(*ended).as_millis() as f64 / 100.0) .min(1.0) as f32, ), - _ => None, + OverviewMode::None => None, }; //tiling surfaces