mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
Add move-window-to-floating/tiling actions
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {},
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user