mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-03-28 20:21:57 +01: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::Layout;
|
||||
use crate::OperationDirection;
|
||||
use crate::WindowsApi;
|
||||
|
||||
#[derive(
|
||||
Debug,
|
||||
@@ -178,66 +179,90 @@ impl Monitor {
|
||||
bail!("cannot move native maximized window to another monitor or workspace");
|
||||
}
|
||||
|
||||
let container = workspace
|
||||
.remove_focused_container()
|
||||
.ok_or_else(|| anyhow!("there is no container"))?;
|
||||
let foreground_hwnd = WindowsApi::foreground_window()?;
|
||||
let floating_window_index = workspace
|
||||
.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 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 {
|
||||
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);
|
||||
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(OperationDirection::Right) => match target_workspace.layout() {
|
||||
Layout::Default(layout) => {
|
||||
let target_index = layout.leftmost_index(target_workspace.containers().len());
|
||||
Some(workspace) => workspace,
|
||||
};
|
||||
|
||||
match layout {
|
||||
DefaultLayout::RightMainVerticalStack
|
||||
| DefaultLayout::UltrawideVerticalStack => {
|
||||
target_workspace.floating_windows_mut().push(window);
|
||||
} else {
|
||||
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 {
|
||||
target_workspace.add_container_to_back(container);
|
||||
target_workspace.insert_container_at_idx(0, container);
|
||||
} 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()?;
|
||||
|
||||
if matches!(event, WindowManagerEvent::MouseCapture(..)) {
|
||||
@@ -247,24 +239,31 @@ impl WindowManager {
|
||||
self.update_focused_workspace(self.mouse_follows_focus, false)?;
|
||||
|
||||
let workspace = self.focused_workspace_mut()?;
|
||||
if !workspace
|
||||
let floating_window_idx = workspace
|
||||
.floating_windows()
|
||||
.iter()
|
||||
.any(|w| w.hwnd == window.hwnd)
|
||||
{
|
||||
if let Some(w) = workspace.maximized_window() {
|
||||
if w.hwnd == window.hwnd {
|
||||
return Ok(());
|
||||
.position(|w| w.hwnd == window.hwnd);
|
||||
|
||||
match floating_window_idx {
|
||||
None => {
|
||||
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)?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(monocle) = workspace.monocle_container() {
|
||||
if let Some(window) = monocle.focused_window() {
|
||||
Some(idx) => {
|
||||
if let Some(window) = workspace.floating_windows().get(idx) {
|
||||
window.focus(false)?;
|
||||
}
|
||||
} else {
|
||||
self.focused_workspace_mut()?
|
||||
.focus_container_by_window(window.hwnd)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,18 +221,19 @@ impl Workspace {
|
||||
container.restore();
|
||||
}
|
||||
|
||||
for window in self.floating_windows() {
|
||||
window.restore();
|
||||
}
|
||||
|
||||
if let Some(container) = self.focused_container_mut() {
|
||||
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
|
||||
// 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 self.maximized_window().is_none() {
|
||||
if self.maximized_window().is_none() && self.floating_windows().is_empty() {
|
||||
window.focus(mouse_follows_focus)?;
|
||||
}
|
||||
}
|
||||
@@ -393,26 +394,6 @@ impl Workspace {
|
||||
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)> {
|
||||
let mut hwnds = vec![];
|
||||
let mut floating_hwnds = vec![];
|
||||
|
||||
Reference in New Issue
Block a user