feat(wm): floating over monocle

This commit allows for floating windows on the floating workspace layer
to be toggled on and off when monocle mode is enabled on a workspace.
This commit is contained in:
alex-ds13
2025-05-13 20:01:37 +01:00
committed by LGUG2Z
parent 5a1af5b133
commit 50c850cb02
3 changed files with 161 additions and 89 deletions

View File

@@ -6,6 +6,7 @@ use crate::core::BorderStyle;
use crate::core::WindowKind;
use crate::ring::Ring;
use crate::windows_api;
use crate::workspace::Workspace;
use crate::workspace::WorkspaceLayer;
use crate::WindowManager;
use crate::WindowsApi;
@@ -212,6 +213,8 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
[focused_workspace_idx]
.layer();
let foreground_window = WindowsApi::foreground_window().unwrap_or_default();
let layer_changed = previous_layer != workspace_layer;
let forced_update = matches!(notification, Notification::ForceUpdate);
drop(state);
@@ -234,6 +237,17 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
.unwrap_or_default()
.set_accent(window_kind_colour(window_kind))?;
if ws.layer() == &WorkspaceLayer::Floating {
for window in ws.floating_windows() {
let mut window_kind = WindowKind::Unfocused;
if foreground_window == window.hwnd {
window_kind = WindowKind::Floating;
}
window.set_accent(window_kind_colour(window_kind))?;
}
}
continue 'monitors;
}
@@ -448,6 +462,32 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
windows_borders.insert(focused_window_hwnd, id);
let border_hwnd = border.hwnd;
if ws.layer() == &WorkspaceLayer::Floating {
handle_floating_borders(
&mut borders,
&mut windows_borders,
ws,
monitor_idx,
foreground_window,
layer_changed,
forced_update,
)?;
// Remove all borders on this monitor except monocle and floating borders
remove_borders(
&mut borders,
&mut windows_borders,
monitor_idx,
|_, b| {
border_hwnd != b.hwnd
&& !ws
.floating_windows()
.iter()
.any(|w| w.hwnd == b.tracking_hwnd)
},
)?;
} else {
// Remove all borders on this monitor except monocle
remove_borders(
&mut borders,
@@ -455,7 +495,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
monitor_idx,
|_, b| border_hwnd != b.hwnd,
)?;
}
continue 'monitors;
}
@@ -569,9 +609,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
};
border.window_rect = rect;
let layer_changed = previous_layer != workspace_layer;
let forced_update = matches!(notification, Notification::ForceUpdate);
let should_invalidate = new_border
|| (last_focus_state != new_focus_state)
|| layer_changed
@@ -591,22 +628,52 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
windows_borders.insert(focused_window_hwnd, id);
}
{
handle_floating_borders(
&mut borders,
&mut windows_borders,
ws,
monitor_idx,
foreground_window,
layer_changed,
forced_update,
)?;
}
}
}
}
previous_snapshot = monitors;
previous_pending_move_op = pending_move_op;
previous_is_paused = is_paused;
previous_notification = Some(notification);
previous_layer = workspace_layer;
}
Ok(())
}
fn handle_floating_borders(
borders: &mut HashMap<String, Box<Border>>,
windows_borders: &mut HashMap<isize, String>,
ws: &Workspace,
monitor_idx: usize,
foreground_window: isize,
layer_changed: bool,
forced_update: bool,
) -> color_eyre::Result<()> {
for window in ws.floating_windows() {
let mut new_border = false;
let id = window.hwnd.to_string();
let border = match borders.entry(id.clone()) {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => {
if let Ok(border) = Border::create(
&window.hwnd.to_string(),
window.hwnd,
monitor_idx,
) {
if let Ok(border) =
Border::create(&window.hwnd.to_string(), window.hwnd, monitor_idx)
{
new_border = true;
entry.insert(border)
} else {
continue 'monitors;
return Ok(());
}
}
};
@@ -627,14 +694,8 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
let rect = WindowsApi::window_rect(window.hwnd)?;
border.window_rect = rect;
let layer_changed = previous_layer != workspace_layer;
let forced_update =
matches!(notification, Notification::ForceUpdate);
let should_invalidate = new_border
|| (last_focus_state != new_focus_state)
|| layer_changed
|| forced_update;
let should_invalidate =
new_border || (last_focus_state != new_focus_state) || layer_changed || forced_update;
if should_invalidate {
if forced_update && !new_border {
@@ -649,18 +710,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
windows_borders.insert(window.hwnd, id);
}
}
}
}
}
}
previous_snapshot = monitors;
previous_pending_move_op = pending_move_op;
previous_is_paused = is_paused;
previous_notification = Some(notification);
previous_layer = workspace_layer;
}
Ok(())
}

View File

@@ -1281,6 +1281,7 @@ impl WindowManager {
if i == focused_idx {
to_focus = Some(*window);
} else {
window.restore();
window.raise()?;
}
}
@@ -1288,6 +1289,7 @@ impl WindowManager {
if let Some(focused_window) = &to_focus {
// The focused window should be the last one raised to make sure it is
// on top
focused_window.restore();
focused_window.raise()?;
}
@@ -1296,12 +1298,28 @@ impl WindowManager {
window.lower()?;
}
}
if let Some(monocle) = workspace.monocle_container() {
if let Some(window) = monocle.focused_window() {
window.lower()?;
}
}
}
WorkspaceLayer::Floating => {
workspace.set_layer(WorkspaceLayer::Tiling);
if let Some(monocle) = workspace.monocle_container() {
if let Some(window) = monocle.focused_window() {
to_focus = Some(*window);
window.raise()?;
}
for window in workspace.floating_windows() {
window.hide();
}
} else {
let focused_container_idx = workspace.focused_container_idx();
for (i, container) in workspace.containers_mut().iter_mut().enumerate() {
for (i, container) in workspace.containers_mut().iter_mut().enumerate()
{
if let Some(window) = container.focused_window() {
if i == focused_container_idx {
to_focus = Some(*window);
@@ -1326,6 +1344,7 @@ impl WindowManager {
window.lower()?;
}
}
}
};
if let Some(window) = to_focus {
window.focus(mouse_follows_focus)?;

View File

@@ -500,7 +500,11 @@ impl WindowManager {
}
}
if !monocle_window_event && monocle_container.is_some() {
let workspace = self.focused_workspace()?;
if !(monocle_window_event
|| workspace.layer() != &WorkspaceLayer::Tiling)
&& monocle_container.is_some()
{
window.hide();
}
}