feat(wm): add cmd to toggle new window behaviour

This commit introduces a new command, toggle-new-window-behaviour, which
can be used to toggle how new windows on the screen will be handled.

The default setting is to add a new window in a dedicated container, but
when toggled, new windows will be stacked on top of the currently
focused window container.

This can be useful if you only want to use a certain number of columns,
and when you have enough windows on the screen for them, you can toggle
the new window behaviour to start appending to the existing column
stacks.

This commit also fixes a bug where stacked windows being closed did
cause the next window underneath in the stack to be shown.

re #72
This commit is contained in:
LGUG2Z
2021-11-13 14:31:00 -08:00
parent 7f74640dbd
commit 676b643faf
9 changed files with 127 additions and 80 deletions
+2 -1
View File
@@ -328,7 +328,8 @@ workspace-layout Set the layout for the specified workspace
workspace-custom-layout Set a custom layout for the specified workspace workspace-custom-layout Set a custom layout for the specified workspace
workspace-tiling Enable or disable window tiling for the specified workspace workspace-tiling Enable or disable window tiling for the specified workspace
workspace-name Set the workspace name for the specified workspace workspace-name Set the workspace name for the specified workspace
toggle-pause Toggle the window manager on and off across all monitors toggle-new-window-behaviour Toggle the behaviour for new windows (stacking or dynamic tiling)
toggle-pause Toggle window tiling on the focused workspace
toggle-tiling Toggle window tiling on the focused workspace toggle-tiling Toggle window tiling on the focused workspace
toggle-float Toggle floating mode for the focused window toggle-float Toggle floating mode for the focused window
toggle-monocle Toggle monocle mode for the focused container toggle-monocle Toggle monocle mode for the focused container
+8
View File
@@ -51,6 +51,7 @@ pub enum SocketMessage {
ToggleFloat, ToggleFloat,
ToggleMonocle, ToggleMonocle,
ToggleMaximize, ToggleMaximize,
ToggleNewWindowBehaviour,
// Current Workspace Commands // Current Workspace Commands
ManageFocusedWindow, ManageFocusedWindow,
UnmanageFocusedWindow, UnmanageFocusedWindow,
@@ -139,6 +140,13 @@ pub enum FocusFollowsMouseImplementation {
Windows, Windows,
} }
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
#[strum(serialize_all = "snake_case")]
pub enum NewWindowBehaviour {
CreateNewContainer,
AppendToFocusedContainer,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)] #[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
#[strum(serialize_all = "snake_case")] #[strum(serialize_all = "snake_case")]
pub enum Sizing { pub enum Sizing {
+8 -8
View File
@@ -78,18 +78,18 @@ impl Container {
} }
pub fn remove_window_by_idx(&mut self, idx: usize) -> Option<Window> { pub fn remove_window_by_idx(&mut self, idx: usize) -> Option<Window> {
self.windows_mut().remove(idx) let window = self.windows_mut().remove(idx);
if idx != 0 {
self.focus_window(idx - 1);
};
window
} }
pub fn remove_focused_window(&mut self) -> Option<Window> { pub fn remove_focused_window(&mut self) -> Option<Window> {
let focused_idx = self.focused_window_idx(); let focused_idx = self.focused_window_idx();
let window = self.remove_window_by_idx(focused_idx); self.remove_window_by_idx(focused_idx)
if focused_idx != 0 {
self.focus_window(focused_idx - 1);
}
window
} }
pub fn add_window(&mut self, window: Window) { pub fn add_window(&mut self, window: Window) {
+9
View File
@@ -18,6 +18,7 @@ use uds_windows::UnixStream;
use komorebi_core::Axis; use komorebi_core::Axis;
use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::FocusFollowsMouseImplementation;
use komorebi_core::Layout; use komorebi_core::Layout;
use komorebi_core::NewWindowBehaviour;
use komorebi_core::OperationDirection; use komorebi_core::OperationDirection;
use komorebi_core::Rect; use komorebi_core::Rect;
use komorebi_core::Sizing; use komorebi_core::Sizing;
@@ -547,6 +548,14 @@ impl WindowManager {
SocketMessage::ResizeDelta(delta) => { SocketMessage::ResizeDelta(delta) => {
self.resize_delta = delta; self.resize_delta = delta;
} }
SocketMessage::ToggleNewWindowBehaviour => match self.new_window_behaviour {
NewWindowBehaviour::CreateNewContainer => {
self.new_window_behaviour = NewWindowBehaviour::AppendToFocusedContainer;
}
NewWindowBehaviour::AppendToFocusedContainer => {
self.new_window_behaviour = NewWindowBehaviour::CreateNewContainer;
}
},
}; };
tracing::info!("processed"); tracing::info!("processed");
+13
View File
@@ -7,6 +7,7 @@ use color_eyre::Result;
use crossbeam_channel::select; use crossbeam_channel::select;
use parking_lot::Mutex; use parking_lot::Mutex;
use komorebi_core::NewWindowBehaviour;
use komorebi_core::OperationDirection; use komorebi_core::OperationDirection;
use komorebi_core::Rect; use komorebi_core::Rect;
use komorebi_core::Sizing; use komorebi_core::Sizing;
@@ -201,12 +202,24 @@ impl WindowManager {
} }
} }
let behaviour = self.new_window_behaviour;
let workspace = self.focused_workspace_mut()?; let workspace = self.focused_workspace_mut()?;
if !workspace.contains_window(window.hwnd) { if !workspace.contains_window(window.hwnd) {
match behaviour {
NewWindowBehaviour::CreateNewContainer => {
workspace.new_container_for_window(*window); workspace.new_container_for_window(*window);
self.update_focused_workspace(false)?; self.update_focused_workspace(false)?;
} }
NewWindowBehaviour::AppendToFocusedContainer => {
workspace
.focused_container_mut()
.ok_or_else(|| anyhow!("there is no focused container"))?
.add_window(*window);
self.update_focused_workspace(true)?;
}
}
}
} }
WindowManagerEvent::MoveResizeStart(_, _) => { WindowManagerEvent::MoveResizeStart(_, _) => {
let monitor_idx = self.focused_monitor_idx(); let monitor_idx = self.focused_monitor_idx();
+5
View File
@@ -21,6 +21,7 @@ use komorebi_core::CycleDirection;
use komorebi_core::DefaultLayout; use komorebi_core::DefaultLayout;
use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::FocusFollowsMouseImplementation;
use komorebi_core::Layout; use komorebi_core::Layout;
use komorebi_core::NewWindowBehaviour;
use komorebi_core::OperationDirection; use komorebi_core::OperationDirection;
use komorebi_core::Rect; use komorebi_core::Rect;
use komorebi_core::Sizing; use komorebi_core::Sizing;
@@ -50,6 +51,7 @@ pub struct WindowManager {
pub invisible_borders: Rect, pub invisible_borders: Rect,
pub work_area_offset: Option<Rect>, pub work_area_offset: Option<Rect>,
pub resize_delta: i32, pub resize_delta: i32,
pub new_window_behaviour: NewWindowBehaviour,
pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>, pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>,
pub mouse_follows_focus: bool, pub mouse_follows_focus: bool,
pub hotwatch: Hotwatch, pub hotwatch: Hotwatch,
@@ -64,6 +66,7 @@ pub struct State {
pub is_paused: bool, pub is_paused: bool,
pub invisible_borders: Rect, pub invisible_borders: Rect,
pub resize_delta: i32, pub resize_delta: i32,
pub new_window_behaviour: NewWindowBehaviour,
pub work_area_offset: Option<Rect>, pub work_area_offset: Option<Rect>,
pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>, pub focus_follows_mouse: Option<FocusFollowsMouseImplementation>,
pub mouse_follows_focus: bool, pub mouse_follows_focus: bool,
@@ -83,6 +86,7 @@ impl From<&WindowManager> for State {
invisible_borders: wm.invisible_borders, invisible_borders: wm.invisible_borders,
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.new_window_behaviour,
focus_follows_mouse: wm.focus_follows_mouse.clone(), focus_follows_mouse: wm.focus_follows_mouse.clone(),
mouse_follows_focus: wm.mouse_follows_focus, mouse_follows_focus: wm.mouse_follows_focus,
has_pending_raise_op: wm.has_pending_raise_op, has_pending_raise_op: wm.has_pending_raise_op,
@@ -156,6 +160,7 @@ impl WindowManager {
bottom: 7, bottom: 7,
}, },
work_area_offset: None, work_area_offset: None,
new_window_behaviour: NewWindowBehaviour::CreateNewContainer,
resize_delta: 50, resize_delta: 50,
focus_follows_mouse: None, focus_follows_mouse: None,
mouse_follows_focus: true, mouse_follows_focus: true,
+3 -1
View File
@@ -456,9 +456,11 @@ impl Workspace {
if self.resize_dimensions().get(container_idx).is_some() { if self.resize_dimensions().get(container_idx).is_some() {
self.resize_dimensions_mut().remove(container_idx); self.resize_dimensions_mut().remove(container_idx);
} }
}
self.focus_previous_container(); self.focus_previous_container();
} else {
container.load_focused_window();
}
Ok(()) Ok(())
} }
+4
View File
@@ -184,6 +184,10 @@ WorkspaceName(monitor, workspace, value) {
Run, komorebic.exe workspace-name %monitor% %workspace% %value%, , Hide Run, komorebic.exe workspace-name %monitor% %workspace% %value%, , Hide
} }
ToggleNewWindowBehaviour() {
Run, komorebic.exe toggle-new-window-behaviour, , Hide
}
TogglePause() { TogglePause() {
Run, komorebic.exe toggle-pause, , Hide Run, komorebic.exe toggle-pause, , Hide
} }
+6 -1
View File
@@ -483,7 +483,9 @@ enum SubCommand {
/// Set the workspace name for the specified workspace /// Set the workspace name for the specified workspace
#[clap(setting = AppSettings::ArgRequiredElseHelp)] #[clap(setting = AppSettings::ArgRequiredElseHelp)]
WorkspaceName(WorkspaceName), WorkspaceName(WorkspaceName),
/// Toggle the window manager on and off across all monitors /// Toggle the behaviour for new windows (stacking or dynamic tiling)
ToggleNewWindowBehaviour,
/// Toggle window tiling on the focused workspace
TogglePause, TogglePause,
/// Toggle window tiling on the focused workspace /// Toggle window tiling on the focused workspace
ToggleTiling, ToggleTiling,
@@ -958,6 +960,9 @@ fn main() -> Result<()> {
SubCommand::ResizeDelta(arg) => { SubCommand::ResizeDelta(arg) => {
send_message(&*SocketMessage::ResizeDelta(arg.pixels).as_bytes()?)?; send_message(&*SocketMessage::ResizeDelta(arg.pixels).as_bytes()?)?;
} }
SubCommand::ToggleNewWindowBehaviour => {
send_message(&*SocketMessage::ToggleNewWindowBehaviour.as_bytes()?)?;
}
} }
Ok(()) Ok(())