mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-04-25 10:08:33 +02:00
feat(wm): allow ws moves of floating apps
WIP
This commit is contained in:
@@ -20,6 +20,7 @@ use crate::workspace::Workspace;
|
|||||||
use crate::DefaultLayout;
|
use crate::DefaultLayout;
|
||||||
use crate::Layout;
|
use crate::Layout;
|
||||||
use crate::OperationDirection;
|
use crate::OperationDirection;
|
||||||
|
use crate::WindowsApi;
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
@@ -178,66 +179,90 @@ impl Monitor {
|
|||||||
bail!("cannot move native maximized window to another monitor or workspace");
|
bail!("cannot move native maximized window to another monitor or workspace");
|
||||||
}
|
}
|
||||||
|
|
||||||
let container = workspace
|
let foreground_hwnd = WindowsApi::foreground_window()?;
|
||||||
.remove_focused_container()
|
let floating_window_index = workspace
|
||||||
.ok_or_else(|| anyhow!("there is no container"))?;
|
.floating_windows()
|
||||||
|
.iter()
|
||||||
|
.position(|w| w.hwnd == foreground_hwnd);
|
||||||
|
|
||||||
let workspaces = self.workspaces_mut();
|
if let Some(idx) = floating_window_index {
|
||||||
|
let window = workspace.floating_windows_mut().remove(idx);
|
||||||
|
|
||||||
#[allow(clippy::option_if_let_else)]
|
let workspaces = self.workspaces_mut();
|
||||||
let target_workspace = match workspaces.get_mut(target_workspace_idx) {
|
#[allow(clippy::option_if_let_else)]
|
||||||
None => {
|
let target_workspace = match workspaces.get_mut(target_workspace_idx) {
|
||||||
workspaces.resize(target_workspace_idx + 1, Workspace::default());
|
None => {
|
||||||
workspaces.get_mut(target_workspace_idx).unwrap()
|
workspaces.resize(target_workspace_idx + 1, Workspace::default());
|
||||||
}
|
workspaces.get_mut(target_workspace_idx).unwrap()
|
||||||
Some(workspace) => workspace,
|
|
||||||
};
|
|
||||||
|
|
||||||
match direction {
|
|
||||||
Some(OperationDirection::Left) => match target_workspace.layout() {
|
|
||||||
Layout::Default(layout) => match layout {
|
|
||||||
DefaultLayout::RightMainVerticalStack => {
|
|
||||||
target_workspace.add_container_to_front(container);
|
|
||||||
}
|
|
||||||
DefaultLayout::UltrawideVerticalStack => {
|
|
||||||
if target_workspace.containers().len() == 1 {
|
|
||||||
target_workspace.insert_container_at_idx(0, container);
|
|
||||||
} else {
|
|
||||||
target_workspace.add_container_to_back(container);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
target_workspace.add_container_to_back(container);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Layout::Custom(_) => {
|
|
||||||
target_workspace.add_container_to_back(container);
|
|
||||||
}
|
}
|
||||||
},
|
Some(workspace) => workspace,
|
||||||
Some(OperationDirection::Right) => match target_workspace.layout() {
|
};
|
||||||
Layout::Default(layout) => {
|
|
||||||
let target_index = layout.leftmost_index(target_workspace.containers().len());
|
|
||||||
|
|
||||||
match layout {
|
target_workspace.floating_windows_mut().push(window);
|
||||||
DefaultLayout::RightMainVerticalStack
|
} else {
|
||||||
| DefaultLayout::UltrawideVerticalStack => {
|
let container = workspace
|
||||||
|
.remove_focused_container()
|
||||||
|
.ok_or_else(|| anyhow!("there is no container"))?;
|
||||||
|
|
||||||
|
let workspaces = self.workspaces_mut();
|
||||||
|
|
||||||
|
#[allow(clippy::option_if_let_else)]
|
||||||
|
let target_workspace = match workspaces.get_mut(target_workspace_idx) {
|
||||||
|
None => {
|
||||||
|
workspaces.resize(target_workspace_idx + 1, Workspace::default());
|
||||||
|
workspaces.get_mut(target_workspace_idx).unwrap()
|
||||||
|
}
|
||||||
|
Some(workspace) => workspace,
|
||||||
|
};
|
||||||
|
|
||||||
|
match direction {
|
||||||
|
Some(OperationDirection::Left) => match target_workspace.layout() {
|
||||||
|
Layout::Default(layout) => match layout {
|
||||||
|
DefaultLayout::RightMainVerticalStack => {
|
||||||
|
target_workspace.add_container_to_front(container);
|
||||||
|
}
|
||||||
|
DefaultLayout::UltrawideVerticalStack => {
|
||||||
if target_workspace.containers().len() == 1 {
|
if target_workspace.containers().len() == 1 {
|
||||||
target_workspace.add_container_to_back(container);
|
target_workspace.insert_container_at_idx(0, container);
|
||||||
} else {
|
} else {
|
||||||
target_workspace.insert_container_at_idx(target_index, container);
|
target_workspace.add_container_to_back(container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
target_workspace.insert_container_at_idx(target_index, container);
|
target_workspace.add_container_to_back(container);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Layout::Custom(_) => {
|
||||||
|
target_workspace.add_container_to_back(container);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(OperationDirection::Right) => match target_workspace.layout() {
|
||||||
|
Layout::Default(layout) => {
|
||||||
|
let target_index =
|
||||||
|
layout.leftmost_index(target_workspace.containers().len());
|
||||||
|
|
||||||
|
match layout {
|
||||||
|
DefaultLayout::RightMainVerticalStack
|
||||||
|
| DefaultLayout::UltrawideVerticalStack => {
|
||||||
|
if target_workspace.containers().len() == 1 {
|
||||||
|
target_workspace.add_container_to_back(container);
|
||||||
|
} else {
|
||||||
|
target_workspace
|
||||||
|
.insert_container_at_idx(target_index, container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
target_workspace.insert_container_at_idx(target_index, container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Layout::Custom(_) => {
|
||||||
|
target_workspace.add_container_to_front(container);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
target_workspace.add_container_to_back(container);
|
||||||
}
|
}
|
||||||
Layout::Custom(_) => {
|
|
||||||
target_workspace.add_container_to_front(container);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
target_workspace.add_container_to_back(container);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,14 +150,6 @@ impl WindowManager {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
for monitor in self.monitors_mut() {
|
|
||||||
for workspace in monitor.workspaces_mut() {
|
|
||||||
if let WindowManagerEvent::FocusChange(_, window) = event {
|
|
||||||
let _ = workspace.focus_changed(window.hwnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.enforce_workspace_rules()?;
|
self.enforce_workspace_rules()?;
|
||||||
|
|
||||||
if matches!(event, WindowManagerEvent::MouseCapture(..)) {
|
if matches!(event, WindowManagerEvent::MouseCapture(..)) {
|
||||||
@@ -247,24 +239,31 @@ impl WindowManager {
|
|||||||
self.update_focused_workspace(self.mouse_follows_focus, false)?;
|
self.update_focused_workspace(self.mouse_follows_focus, false)?;
|
||||||
|
|
||||||
let workspace = self.focused_workspace_mut()?;
|
let workspace = self.focused_workspace_mut()?;
|
||||||
if !workspace
|
let floating_window_idx = workspace
|
||||||
.floating_windows()
|
.floating_windows()
|
||||||
.iter()
|
.iter()
|
||||||
.any(|w| w.hwnd == window.hwnd)
|
.position(|w| w.hwnd == window.hwnd);
|
||||||
{
|
|
||||||
if let Some(w) = workspace.maximized_window() {
|
match floating_window_idx {
|
||||||
if w.hwnd == window.hwnd {
|
None => {
|
||||||
return Ok(());
|
if let Some(w) = workspace.maximized_window() {
|
||||||
|
if w.hwnd == window.hwnd {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(monocle) = workspace.monocle_container() {
|
||||||
|
if let Some(window) = monocle.focused_window() {
|
||||||
|
window.focus(false)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
workspace.focus_container_by_window(window.hwnd)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(idx) => {
|
||||||
if let Some(monocle) = workspace.monocle_container() {
|
if let Some(window) = workspace.floating_windows().get(idx) {
|
||||||
if let Some(window) = monocle.focused_window() {
|
|
||||||
window.focus(false)?;
|
window.focus(false)?;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
self.focused_workspace_mut()?
|
|
||||||
.focus_container_by_window(window.hwnd)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,18 +221,19 @@ impl Workspace {
|
|||||||
container.restore();
|
container.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
for window in self.floating_windows() {
|
|
||||||
window.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(container) = self.focused_container_mut() {
|
if let Some(container) = self.focused_container_mut() {
|
||||||
container.focus_window(container.focused_window_idx());
|
container.focus_window(container.focused_window_idx());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for window in self.floating_windows() {
|
||||||
|
window.restore();
|
||||||
|
}
|
||||||
|
|
||||||
// Do this here to make sure that an error doesn't stop the restoration of other windows
|
// Do this here to make sure that an error doesn't stop the restoration of other windows
|
||||||
// Maximised windows should always be drawn at the top of the Z order
|
// Maximised windows and floating windows should always be drawn at the top of the Z order
|
||||||
|
// when switching to a workspace
|
||||||
if let Some(window) = to_focus {
|
if let Some(window) = to_focus {
|
||||||
if self.maximized_window().is_none() {
|
if self.maximized_window().is_none() && self.floating_windows().is_empty() {
|
||||||
window.focus(mouse_follows_focus)?;
|
window.focus(mouse_follows_focus)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,26 +394,6 @@ impl Workspace {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// focus_changed performs updates in response to the fact that a focus
|
|
||||||
// change event has occurred. The focus change is assumed to be valid, and
|
|
||||||
// should not result in a new focus change - the intent here is to update
|
|
||||||
// focus-reactive elements, such as the stackbar.
|
|
||||||
pub fn focus_changed(&mut self, hwnd: isize) -> Result<()> {
|
|
||||||
if !self.tile() {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let containers = self.containers_mut();
|
|
||||||
|
|
||||||
for container in containers.iter_mut() {
|
|
||||||
if let Some(idx) = container.idx_for_window(hwnd) {
|
|
||||||
container.focus_window(idx);
|
|
||||||
container.restore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn reap_orphans(&mut self) -> Result<(usize, usize)> {
|
pub fn reap_orphans(&mut self) -> Result<(usize, usize)> {
|
||||||
let mut hwnds = vec![];
|
let mut hwnds = vec![];
|
||||||
let mut floating_hwnds = vec![];
|
let mut floating_hwnds = vec![];
|
||||||
|
|||||||
Reference in New Issue
Block a user