feat(wm): add new float override option

This commit introduces a new option `float_override`, which makes it so
every every window opened, shown or uncloaked will be set to floating,
but it won't be ignored. It will be added to the floating_windows of the
workspace, meaning that the user can later tile that window with
toggle-float command.

This allows the users to have all windows open as floating and then
manually tile the ones they want.
This commit is contained in:
alex-ds13
2024-09-04 17:53:36 +01:00
parent 68e9365dda
commit 0e8dc85fb1
5 changed files with 66 additions and 26 deletions
+14 -1
View File
@@ -343,10 +343,23 @@ pub enum FocusFollowsMouseImplementation {
} }
#[derive( #[derive(
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema, Clone, Copy, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq,
)]
pub struct WindowManagementBehaviour {
/// The current WindowContainerBehaviour to be used
pub current_behaviour: WindowContainerBehaviour,
/// Override of `current_behaviour` to open new windows as floating windows
/// that can be later toggled to tiled, when false it will default to
/// `current_behaviour` again.
pub float_override: bool,
}
#[derive(
Clone, Copy, Debug, Default, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema, PartialEq
)] )]
pub enum WindowContainerBehaviour { pub enum WindowContainerBehaviour {
/// Create a new container for each new window /// Create a new container for each new window
#[default]
Create, Create,
/// Append new windows to the focused window container /// Append new windows to the focused window container
Append, Append,
+3 -3
View File
@@ -1346,12 +1346,12 @@ impl WindowManager {
self.resize_delta = delta; self.resize_delta = delta;
} }
SocketMessage::ToggleWindowContainerBehaviour => { SocketMessage::ToggleWindowContainerBehaviour => {
match self.window_container_behaviour { match self.window_management_behaviour.current_behaviour {
WindowContainerBehaviour::Create => { WindowContainerBehaviour::Create => {
self.window_container_behaviour = WindowContainerBehaviour::Append; self.window_management_behaviour.current_behaviour = WindowContainerBehaviour::Append;
} }
WindowContainerBehaviour::Append => { WindowContainerBehaviour::Append => {
self.window_container_behaviour = WindowContainerBehaviour::Create; self.window_management_behaviour.current_behaviour = WindowContainerBehaviour::Create;
} }
} }
} }
+13 -9
View File
@@ -333,8 +333,8 @@ impl WindowManager {
} }
if proceed { if proceed {
let behaviour = let mut behaviour =
self.window_container_behaviour(focused_monitor_idx, focused_workspace_idx); self.window_management_behaviour(focused_monitor_idx, focused_workspace_idx);
let workspace = self.focused_workspace_mut()?; let workspace = self.focused_workspace_mut()?;
let workspace_contains_window = workspace.contains_window(window.hwnd); let workspace_contains_window = workspace.contains_window(window.hwnd);
let monocle_container = workspace.monocle_container().clone(); let monocle_container = workspace.monocle_container().clone();
@@ -360,11 +360,13 @@ impl WindowManager {
} }
} }
if should_float && !matches!(event, WindowManagerEvent::Manage(_)) { behaviour.float_override = behaviour.float_override || (should_float && !matches!(event, WindowManagerEvent::Manage(_)));
if behaviour.float_override {
workspace.floating_windows_mut().push(window); workspace.floating_windows_mut().push(window);
self.update_focused_workspace(false, true)?; self.update_focused_workspace(false, false)?;
} else { } else {
match behaviour { match behaviour.current_behaviour {
WindowContainerBehaviour::Create => { WindowContainerBehaviour::Create => {
workspace.new_container_for_window(window); workspace.new_container_for_window(window);
self.update_focused_workspace(false, false)?; self.update_focused_workspace(false, false)?;
@@ -375,7 +377,6 @@ impl WindowManager {
.ok_or_else(|| anyhow!("there is no focused container"))? .ok_or_else(|| anyhow!("there is no focused container"))?
.add_window(window); .add_window(window);
self.update_focused_workspace(true, false)?; self.update_focused_workspace(true, false)?;
stackbar_manager::send_notification(); stackbar_manager::send_notification();
} }
} }
@@ -431,8 +432,8 @@ impl WindowManager {
let focused_monitor_idx = self.focused_monitor_idx(); let focused_monitor_idx = self.focused_monitor_idx();
let focused_workspace_idx = self.focused_workspace_idx().unwrap_or_default(); let focused_workspace_idx = self.focused_workspace_idx().unwrap_or_default();
let window_container_behaviour = let window_management_behaviour =
self.window_container_behaviour(focused_monitor_idx, focused_workspace_idx); self.window_management_behaviour(focused_monitor_idx, focused_workspace_idx);
let workspace = self.focused_workspace_mut()?; let workspace = self.focused_workspace_mut()?;
let focused_container_idx = workspace.focused_container_idx(); let focused_container_idx = workspace.focused_container_idx();
@@ -550,8 +551,11 @@ impl WindowManager {
} }
// Here we handle a simple move on the same monitor which is treated as // Here we handle a simple move on the same monitor which is treated as
// a container swap // a container swap
} else if window_management_behaviour.float_override {
workspace.floating_windows_mut().push(window);
self.update_focused_workspace(false, false)?;
} else { } else {
match window_container_behaviour { match window_management_behaviour.current_behaviour {
WindowContainerBehaviour::Create => { WindowContainerBehaviour::Create => {
match workspace.container_idx_from_current_point() { match workspace.container_idx_from_current_point() {
Some(target_idx) => { Some(target_idx) => {
+16 -5
View File
@@ -68,6 +68,7 @@ use crate::core::OperationBehaviour;
use crate::core::Rect; use crate::core::Rect;
use crate::core::SocketMessage; use crate::core::SocketMessage;
use crate::core::WindowContainerBehaviour; use crate::core::WindowContainerBehaviour;
use crate::core::WindowManagementBehaviour;
use color_eyre::Result; use color_eyre::Result;
use crossbeam_channel::Receiver; use crossbeam_channel::Receiver;
use hotwatch::EventKind; use hotwatch::EventKind;
@@ -235,6 +236,10 @@ pub struct StaticConfig {
/// Determine what happens when a new window is opened (default: Create) /// Determine what happens when a new window is opened (default: Create)
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub window_container_behaviour: Option<WindowContainerBehaviour>, pub window_container_behaviour: Option<WindowContainerBehaviour>,
/// Enable or disable float override, which makes it so every new window opens in floating mode
/// (default: false)
#[serde(skip_serializing_if = "Option::is_none")]
pub float_override: Option<bool>,
/// Determine what happens when a window is moved across a monitor boundary (default: Swap) /// Determine what happens when a window is moved across a monitor boundary (default: Swap)
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub cross_monitor_move_behaviour: Option<MoveBehaviour>, pub cross_monitor_move_behaviour: Option<MoveBehaviour>,
@@ -520,7 +525,8 @@ impl From<&WindowManager> for StaticConfig {
Self { Self {
invisible_borders: None, invisible_borders: None,
resize_delta: Option::from(value.resize_delta), resize_delta: Option::from(value.resize_delta),
window_container_behaviour: Option::from(value.window_container_behaviour), window_container_behaviour: Option::from(value.window_management_behaviour.current_behaviour),
float_override: Option::from(value.window_management_behaviour.float_override),
cross_monitor_move_behaviour: Option::from(value.cross_monitor_move_behaviour), cross_monitor_move_behaviour: Option::from(value.cross_monitor_move_behaviour),
cross_boundary_behaviour: Option::from(value.cross_boundary_behaviour), cross_boundary_behaviour: Option::from(value.cross_boundary_behaviour),
unmanaged_window_operation_behaviour: Option::from( unmanaged_window_operation_behaviour: Option::from(
@@ -1031,9 +1037,10 @@ impl StaticConfig {
is_paused: false, is_paused: false,
virtual_desktop_id: current_virtual_desktop(), virtual_desktop_id: current_virtual_desktop(),
work_area_offset: value.global_work_area_offset, work_area_offset: value.global_work_area_offset,
window_container_behaviour: value window_management_behaviour: WindowManagementBehaviour {
.window_container_behaviour current_behaviour: value.window_container_behaviour.unwrap_or(WindowContainerBehaviour::Create),
.unwrap_or(WindowContainerBehaviour::Create), float_override: value.float_override.unwrap_or_default(),
},
cross_monitor_move_behaviour: value cross_monitor_move_behaviour: value
.cross_monitor_move_behaviour .cross_monitor_move_behaviour
.unwrap_or(MoveBehaviour::Swap), .unwrap_or(MoveBehaviour::Swap),
@@ -1208,7 +1215,11 @@ impl StaticConfig {
} }
if let Some(val) = value.window_container_behaviour { if let Some(val) = value.window_container_behaviour {
wm.window_container_behaviour = val; wm.window_management_behaviour.current_behaviour = val;
}
if let Some(val) = value.float_override {
wm.window_management_behaviour.float_override = val;
} }
if let Some(val) = value.cross_monitor_move_behaviour { if let Some(val) = value.cross_monitor_move_behaviour {
+20 -8
View File
@@ -39,6 +39,7 @@ use crate::core::Rect;
use crate::core::Sizing; use crate::core::Sizing;
use crate::core::StackbarLabel; use crate::core::StackbarLabel;
use crate::core::WindowContainerBehaviour; use crate::core::WindowContainerBehaviour;
use crate::core::WindowManagementBehaviour;
use crate::border_manager; use crate::border_manager;
use crate::border_manager::STYLE; use crate::border_manager::STYLE;
@@ -92,7 +93,7 @@ pub struct WindowManager {
pub is_paused: bool, pub is_paused: bool,
pub work_area_offset: Option<Rect>, pub work_area_offset: Option<Rect>,
pub resize_delta: i32, pub resize_delta: i32,
pub window_container_behaviour: WindowContainerBehaviour, pub window_management_behaviour: WindowManagementBehaviour,
pub cross_monitor_move_behaviour: MoveBehaviour, pub cross_monitor_move_behaviour: MoveBehaviour,
pub cross_boundary_behaviour: CrossBoundaryBehaviour, pub cross_boundary_behaviour: CrossBoundaryBehaviour,
pub unmanaged_window_operation_behaviour: OperationBehaviour, pub unmanaged_window_operation_behaviour: OperationBehaviour,
@@ -112,6 +113,7 @@ pub struct State {
pub is_paused: bool, pub is_paused: bool,
pub resize_delta: i32, pub resize_delta: i32,
pub new_window_behaviour: WindowContainerBehaviour, pub new_window_behaviour: WindowContainerBehaviour,
pub float_override: bool,
pub cross_monitor_move_behaviour: MoveBehaviour, pub cross_monitor_move_behaviour: MoveBehaviour,
pub unmanaged_window_operation_behaviour: OperationBehaviour, pub unmanaged_window_operation_behaviour: OperationBehaviour,
pub work_area_offset: Option<Rect>, pub work_area_offset: Option<Rect>,
@@ -215,7 +217,8 @@ impl From<&WindowManager> for State {
is_paused: wm.is_paused, is_paused: wm.is_paused,
work_area_offset: wm.work_area_offset, work_area_offset: wm.work_area_offset,
resize_delta: wm.resize_delta, resize_delta: wm.resize_delta,
new_window_behaviour: wm.window_container_behaviour, new_window_behaviour: wm.window_management_behaviour.current_behaviour,
float_override: wm.window_management_behaviour.float_override,
cross_monitor_move_behaviour: wm.cross_monitor_move_behaviour, cross_monitor_move_behaviour: wm.cross_monitor_move_behaviour,
focus_follows_mouse: wm.focus_follows_mouse, focus_follows_mouse: wm.focus_follows_mouse,
mouse_follows_focus: wm.mouse_follows_focus, mouse_follows_focus: wm.mouse_follows_focus,
@@ -275,7 +278,7 @@ impl WindowManager {
is_paused: false, is_paused: false,
virtual_desktop_id: current_virtual_desktop(), virtual_desktop_id: current_virtual_desktop(),
work_area_offset: None, work_area_offset: None,
window_container_behaviour: WindowContainerBehaviour::Create, window_management_behaviour: WindowManagementBehaviour::default(),
cross_monitor_move_behaviour: MoveBehaviour::Swap, cross_monitor_move_behaviour: MoveBehaviour::Swap,
cross_boundary_behaviour: CrossBoundaryBehaviour::Workspace, cross_boundary_behaviour: CrossBoundaryBehaviour::Workspace,
unmanaged_window_operation_behaviour: OperationBehaviour::Op, unmanaged_window_operation_behaviour: OperationBehaviour::Op,
@@ -308,22 +311,31 @@ impl WindowManager {
StaticConfig::reload(pathbuf, self) StaticConfig::reload(pathbuf, self)
} }
pub fn window_container_behaviour( pub fn window_management_behaviour(
&self, &self,
monitor_idx: usize, monitor_idx: usize,
workspace_idx: usize, workspace_idx: usize,
) -> WindowContainerBehaviour { ) -> WindowManagementBehaviour {
if let Some(monitor) = self.monitors().get(monitor_idx) { if let Some(monitor) = self.monitors().get(monitor_idx) {
if let Some(workspace) = monitor.workspaces().get(workspace_idx) { if let Some(workspace) = monitor.workspaces().get(workspace_idx) {
return if workspace.containers().is_empty() { let current_behaviour = if workspace.containers().is_empty() && matches!(self.window_management_behaviour.current_behaviour, WindowContainerBehaviour::Append) {
// You can't append to an empty workspace
WindowContainerBehaviour::Create WindowContainerBehaviour::Create
} else { } else {
self.window_container_behaviour self.window_management_behaviour.current_behaviour
};
return WindowManagementBehaviour {
current_behaviour,
float_override: self.window_management_behaviour.float_override,
}; };
} }
} }
WindowContainerBehaviour::Create WindowManagementBehaviour {
current_behaviour: WindowContainerBehaviour::Create,
float_override: self.window_management_behaviour.float_override,
}
} }
#[tracing::instrument(skip(self))] #[tracing::instrument(skip(self))]