diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-28 10:13:30 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-12-30 20:12:37 +0300 |
| commit | ad50dd21fea1912b9e21fb66a22fce517dac3aee (patch) | |
| tree | 20d7f1a1d6db2a843a33a551d5895bcc86cf0f38 | |
| parent | 8b0cb0bb57112bd15bc7ac04e6952d857dadcbca (diff) | |
| download | niri-ad50dd21fea1912b9e21fb66a22fce517dac3aee.tar.gz niri-ad50dd21fea1912b9e21fb66a22fce517dac3aee.tar.bz2 niri-ad50dd21fea1912b9e21fb66a22fce517dac3aee.zip | |
Add move-window-to-floating/tiling actions
| -rw-r--r-- | niri-config/src/lib.rs | 14 | ||||
| -rw-r--r-- | niri-ipc/src/lib.rs | 16 | ||||
| -rw-r--r-- | src/input/mod.rs | 28 | ||||
| -rw-r--r-- | src/layout/mod.rs | 35 | ||||
| -rw-r--r-- | src/layout/workspace.rs | 11 |
5 files changed, 104 insertions, 0 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index 069bb015..1807f06c 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -1271,6 +1271,12 @@ pub enum Action { ToggleWindowFloating, #[knuffel(skip)] ToggleWindowFloatingById(u64), + MoveWindowToFloating, + #[knuffel(skip)] + MoveWindowToFloatingById(u64), + MoveWindowToTiling, + #[knuffel(skip)] + MoveWindowToTilingById(u64), SwitchFocusBetweenFloatingAndTiling, } @@ -1413,6 +1419,14 @@ impl From<niri_ipc::Action> for Action { niri_ipc::Action::ToggleWindowFloating { id: Some(id) } => { Self::ToggleWindowFloatingById(id) } + niri_ipc::Action::MoveWindowToFloating { id: None } => Self::MoveWindowToFloating, + niri_ipc::Action::MoveWindowToFloating { id: Some(id) } => { + Self::MoveWindowToFloatingById(id) + } + niri_ipc::Action::MoveWindowToTiling { id: None } => Self::MoveWindowToTiling, + niri_ipc::Action::MoveWindowToTiling { id: Some(id) } => { + Self::MoveWindowToTilingById(id) + } niri_ipc::Action::SwitchFocusBetweenFloatingAndTiling {} => { Self::SwitchFocusBetweenFloatingAndTiling } diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs index bf66d3a8..c3878941 100644 --- a/niri-ipc/src/lib.rs +++ b/niri-ipc/src/lib.rs @@ -454,6 +454,22 @@ pub enum Action { #[cfg_attr(feature = "clap", arg(long))] id: Option<u64>, }, + /// Move the focused window to the floating layout. + MoveWindowToFloating { + /// Id of the window to move. + /// + /// If `None`, uses the focused window. + #[cfg_attr(feature = "clap", arg(long))] + id: Option<u64>, + }, + /// Move the focused window to the tiling layout. + MoveWindowToTiling { + /// Id of the window to move. + /// + /// If `None`, uses the focused window. + #[cfg_attr(feature = "clap", arg(long))] + id: Option<u64>, + }, /// Toggles the focus between the floating and the tiling layout. SwitchFocusBetweenFloatingAndTiling {}, } diff --git a/src/input/mod.rs b/src/input/mod.rs index 6e116d9e..c510a958 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1318,6 +1318,34 @@ impl State { self.niri.queue_redraw_all(); } } + Action::MoveWindowToFloating => { + self.niri.layout.set_window_floating(None, true); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::MoveWindowToFloatingById(id) => { + let window = self.niri.layout.windows().find(|(_, m)| m.id().get() == id); + let window = window.map(|(_, m)| m.window.clone()); + if let Some(window) = window { + self.niri.layout.set_window_floating(Some(&window), true); + // FIXME: granular + self.niri.queue_redraw_all(); + } + } + Action::MoveWindowToTiling => { + self.niri.layout.set_window_floating(None, false); + // FIXME: granular + self.niri.queue_redraw_all(); + } + Action::MoveWindowToTilingById(id) => { + let window = self.niri.layout.windows().find(|(_, m)| m.id().get() == id); + let window = window.map(|(_, m)| m.window.clone()); + if let Some(window) = window { + self.niri.layout.set_window_floating(Some(&window), false); + // FIXME: granular + self.niri.queue_redraw_all(); + } + } Action::SwitchFocusBetweenFloatingAndTiling => { self.niri.layout.switch_focus_floating_tiling(); // FIXME: granular diff --git a/src/layout/mod.rs b/src/layout/mod.rs index acdf1301..53c9ce6b 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -2703,6 +2703,32 @@ impl<W: LayoutElement> Layout<W> { workspace.toggle_window_floating(window); } + pub fn set_window_floating(&mut self, window: Option<&W::Id>, floating: bool) { + if let Some(InteractiveMoveState::Moving(move_)) = &mut self.interactive_move { + if window.is_none() || window == Some(move_.tile.window().id()) { + if move_.is_floating != floating { + self.toggle_window_floating(window); + } + return; + } + } + + let workspace = if let Some(window) = window { + Some( + self.workspaces_mut() + .find(|ws| ws.has_window(window)) + .unwrap(), + ) + } else { + self.active_workspace_mut() + }; + + let Some(workspace) = workspace else { + return; + }; + workspace.set_window_floating(window, floating); + } + pub fn switch_focus_floating_tiling(&mut self) { let Some(workspace) = self.active_workspace_mut() else { return; @@ -4362,6 +4388,11 @@ mod tests { #[proptest(strategy = "proptest::option::of(1..=5usize)")] id: Option<usize>, }, + SetWindowFloating { + #[proptest(strategy = "proptest::option::of(1..=5usize)")] + id: Option<usize>, + floating: bool, + }, SwitchFocusFloatingTiling, SetParent { #[proptest(strategy = "1..=5usize")] @@ -4874,6 +4905,10 @@ mod tests { let id = id.filter(|id| layout.has_window(id)); layout.toggle_window_floating(id.as_ref()); } + Op::SetWindowFloating { id, floating } => { + let id = id.filter(|id| layout.has_window(id)); + layout.set_window_floating(id.as_ref(), floating); + } Op::SwitchFocusFloatingTiling => { layout.switch_focus_floating_tiling(); } diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index cd1a6261..099b449c 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -1146,6 +1146,17 @@ impl<W: LayoutElement> Workspace<W> { tile.animate_move_from(render_pos - new_render_pos); } + pub fn set_window_floating(&mut self, id: Option<&W::Id>, floating: bool) { + if id.map_or(self.floating_is_active.get(), |id| { + self.floating.has_window(id) + }) == floating + { + return; + } + + self.toggle_window_floating(id); + } + pub fn switch_focus_floating_tiling(&mut self) { if self.floating.is_empty() { // If floating is empty, keep focus on scrolling. |
