diff --git a/README.md b/README.md index e06b3e72..2b93ab56 100644 --- a/README.md +++ b/README.md @@ -282,73 +282,74 @@ keybindings with. You can run `komorebic.exe --help` to get a full exp each command. ``` -start Start komorebi.exe as a background process -stop Stop the komorebi.exe process and restore all hidden windows -state Show a JSON representation of the current window manager state -query Query the current window manager state -subscribe Subscribe to komorebi events -unsubscribe Unsubscribe from komorebi events -log Tail komorebi.exe's process logs (cancel with Ctrl-C) -quick-save-resize Quicksave the current resize layout dimensions -quick-load-resize Load the last quicksaved resize layout dimensions -save-resize Save the current resize layout dimensions to a file -load-resize Load the resize layout dimensions from a file -focus Change focus to the window in the specified direction -move Move the focused window in the specified direction -cycle-focus Change focus to the window in the specified cycle direction -cycle-move Move the focused window in the specified cycle direction -stack Stack the focused window in the specified direction -resize-edge Resize the focused window in the specified direction -resize-axis Resize the focused window or primary column along the specified axis -unstack Unstack the focused window -cycle-stack Cycle the focused stack in the specified cycle direction -move-to-monitor Move the focused window to the specified monitor -move-to-workspace Move the focused window to the specified workspace -send-to-monitor Send the focused window to the specified monitor -send-to-workspace Send the focused window to the specified workspace -focus-monitor Focus the specified monitor -focus-workspace Focus the specified workspace on the focused monitor -cycle-monitor Focus the monitor in the given cycle direction -cycle-workspace Focus the workspace in the given cycle direction -new-workspace Create and append a new workspace on the focused monitor -resize-delta Set the resize delta (used by resize-edge and resize-axis) -invisible-borders Set the invisible border dimensions around each window -work-area-offset Set offsets to exclude parts of the work area from tiling -adjust-container-padding Adjust container padding on the focused workspace -adjust-workspace-padding Adjust workspace padding on the focused workspace -change-layout Set the layout on the focused workspace -load-custom-layout Load a custom layout from file for the focused workspace -flip-layout Flip the layout on the focused workspace (BSP only) -promote Promote the focused window to the top of the tree -retile Force the retiling of all managed windows -ensure-workspaces Create at least this many workspaces for the specified monitor -container-padding Set the container padding for the specified workspace -workspace-padding Set the workspace padding for the specified workspace -workspace-layout Set the 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-name Set the workspace name for the specified workspace -toggle-pause Toggle the window manager on and off across all monitors -toggle-tiling Toggle window tiling on the focused workspace -toggle-float Toggle floating mode for the focused window -toggle-monocle Toggle monocle mode for the focused container -toggle-maximize Toggle native maximization for the focused window -restore-windows Restore all hidden windows (debugging command) -manage Force komorebi to manage the focused window -unmanage Unmanage a window that was forcibly managed -reload-configuration Reload ~/komorebi.ahk (if it exists) -watch-configuration Enable or disable watching of ~/komorebi.ahk (if it exists) -float-rule Add a rule to always float the specified application -manage-rule Add a rule to always manage the specified application -workspace-rule Add a rule to associate an application with a workspace -identify-tray-application Identify an application that closes to the system tray -identify-border-overflow Identify an application that has overflowing borders -focus-follows-mouse Enable or disable focus follows mouse for the operating system -toggle-focus-follows-mouse Toggle focus follows mouse for the operating system -mouse-follows-focus Enable or disable mouse follows focus on all workspaces -toggle-mouse-follows-focus Toggle mouse follows focus on all workspaces -ahk-library Generate a library of AutoHotKey helper functions -help Print this message or the help of the given subcommand(s) +start Start komorebi.exe as a background process +stop Stop the komorebi.exe process and restore all hidden windows +state Show a JSON representation of the current window manager state +query Query the current window manager state +subscribe Subscribe to komorebi events +unsubscribe Unsubscribe from komorebi events +log Tail komorebi.exe's process logs (cancel with Ctrl-C) +quick-save-resize Quicksave the current resize layout dimensions +quick-load-resize Load the last quicksaved resize layout dimensions +save-resize Save the current resize layout dimensions to a file +load-resize Load the resize layout dimensions from a file +focus Change focus to the window in the specified direction +move Move the focused window in the specified direction +cycle-focus Change focus to the window in the specified cycle direction +cycle-move Move the focused window in the specified cycle direction +stack Stack the focused window in the specified direction +resize-edge Resize the focused window in the specified direction +resize-axis Resize the focused window or primary column along the specified axis +unstack Unstack the focused window +cycle-stack Cycle the focused stack in the specified cycle direction +move-to-monitor Move the focused window to the specified monitor +move-to-workspace Move the focused window to the specified workspace +send-to-monitor Send the focused window to the specified monitor +send-to-workspace Send the focused window to the specified workspace +focus-monitor Focus the specified monitor +focus-workspace Focus the specified workspace on the focused monitor +cycle-monitor Focus the monitor in the given cycle direction +cycle-workspace Focus the workspace in the given cycle direction +new-workspace Create and append a new workspace on the focused monitor +resize-delta Set the resize delta (used by resize-edge and resize-axis) +invisible-borders Set the invisible border dimensions around each window +work-area-offset Set offsets to exclude parts of the work area from tiling +adjust-container-padding Adjust container padding on the focused workspace +adjust-workspace-padding Adjust workspace padding on the focused workspace +change-layout Set the layout on the focused workspace +load-custom-layout Load a custom layout from file for the focused workspace +flip-layout Flip the layout on the focused workspace (BSP only) +promote Promote the focused window to the top of the tree +retile Force the retiling of all managed windows +ensure-workspaces Create at least this many workspaces for the specified monitor +container-padding Set the container padding for the specified workspace +workspace-padding Set the workspace padding for the specified workspace +workspace-layout Set the 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-name Set the workspace name for the specified workspace +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-float Toggle floating mode for the focused window +toggle-monocle Toggle monocle mode for the focused container +toggle-maximize Toggle native maximization for the focused window +restore-windows Restore all hidden windows (debugging command) +manage Force komorebi to manage the focused window +unmanage Unmanage a window that was forcibly managed +reload-configuration Reload ~/komorebi.ahk (if it exists) +watch-configuration Enable or disable watching of ~/komorebi.ahk (if it exists) +float-rule Add a rule to always float the specified application +manage-rule Add a rule to always manage the specified application +workspace-rule Add a rule to associate an application with a workspace +identify-tray-application Identify an application that closes to the system tray +identify-border-overflow Identify an application that has overflowing borders +focus-follows-mouse Enable or disable focus follows mouse for the operating system +toggle-focus-follows-mouse Toggle focus follows mouse for the operating system +mouse-follows-focus Enable or disable mouse follows focus on all workspaces +toggle-mouse-follows-focus Toggle mouse follows focus on all workspaces +ahk-library Generate a library of AutoHotKey helper functions +help Print this message or the help of the given subcommand(s) ``` ### AutoHotKey Helper Library for `komorebic` diff --git a/komorebi-core/src/lib.rs b/komorebi-core/src/lib.rs index 225fd990..26c6a3dc 100644 --- a/komorebi-core/src/lib.rs +++ b/komorebi-core/src/lib.rs @@ -51,6 +51,7 @@ pub enum SocketMessage { ToggleFloat, ToggleMonocle, ToggleMaximize, + ToggleNewWindowBehaviour, // Current Workspace Commands ManageFocusedWindow, UnmanageFocusedWindow, @@ -139,6 +140,13 @@ pub enum FocusFollowsMouseImplementation { 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)] #[strum(serialize_all = "snake_case")] pub enum Sizing { diff --git a/komorebi/src/container.rs b/komorebi/src/container.rs index dd772cb0..2a2578cd 100644 --- a/komorebi/src/container.rs +++ b/komorebi/src/container.rs @@ -78,18 +78,18 @@ impl Container { } pub fn remove_window_by_idx(&mut self, idx: usize) -> Option { - 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 { let focused_idx = self.focused_window_idx(); - let window = self.remove_window_by_idx(focused_idx); - - if focused_idx != 0 { - self.focus_window(focused_idx - 1); - } - - window + self.remove_window_by_idx(focused_idx) } pub fn add_window(&mut self, window: Window) { diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index 8616f4ab..70571b42 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -18,6 +18,7 @@ use uds_windows::UnixStream; use komorebi_core::Axis; use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::Layout; +use komorebi_core::NewWindowBehaviour; use komorebi_core::OperationDirection; use komorebi_core::Rect; use komorebi_core::Sizing; @@ -547,6 +548,14 @@ impl WindowManager { SocketMessage::ResizeDelta(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"); diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index cfe391a4..2f3d625d 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -7,6 +7,7 @@ use color_eyre::Result; use crossbeam_channel::select; use parking_lot::Mutex; +use komorebi_core::NewWindowBehaviour; use komorebi_core::OperationDirection; use komorebi_core::Rect; use komorebi_core::Sizing; @@ -201,11 +202,23 @@ impl WindowManager { } } + let behaviour = self.new_window_behaviour; let workspace = self.focused_workspace_mut()?; if !workspace.contains_window(window.hwnd) { - workspace.new_container_for_window(*window); - self.update_focused_workspace(false)?; + match behaviour { + NewWindowBehaviour::CreateNewContainer => { + workspace.new_container_for_window(*window); + 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(_, _) => { diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 51bc36ba..2583de50 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -21,6 +21,7 @@ use komorebi_core::CycleDirection; use komorebi_core::DefaultLayout; use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::Layout; +use komorebi_core::NewWindowBehaviour; use komorebi_core::OperationDirection; use komorebi_core::Rect; use komorebi_core::Sizing; @@ -50,6 +51,7 @@ pub struct WindowManager { pub invisible_borders: Rect, pub work_area_offset: Option, pub resize_delta: i32, + pub new_window_behaviour: NewWindowBehaviour, pub focus_follows_mouse: Option, pub mouse_follows_focus: bool, pub hotwatch: Hotwatch, @@ -64,6 +66,7 @@ pub struct State { pub is_paused: bool, pub invisible_borders: Rect, pub resize_delta: i32, + pub new_window_behaviour: NewWindowBehaviour, pub work_area_offset: Option, pub focus_follows_mouse: Option, pub mouse_follows_focus: bool, @@ -83,6 +86,7 @@ impl From<&WindowManager> for State { invisible_borders: wm.invisible_borders, work_area_offset: wm.work_area_offset, resize_delta: wm.resize_delta, + new_window_behaviour: wm.new_window_behaviour, focus_follows_mouse: wm.focus_follows_mouse.clone(), mouse_follows_focus: wm.mouse_follows_focus, has_pending_raise_op: wm.has_pending_raise_op, @@ -156,6 +160,7 @@ impl WindowManager { bottom: 7, }, work_area_offset: None, + new_window_behaviour: NewWindowBehaviour::CreateNewContainer, resize_delta: 50, focus_follows_mouse: None, mouse_follows_focus: true, diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index a52adb02..7be4aecc 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -456,9 +456,11 @@ impl Workspace { if self.resize_dimensions().get(container_idx).is_some() { self.resize_dimensions_mut().remove(container_idx); } - } - self.focus_previous_container(); + self.focus_previous_container(); + } else { + container.load_focused_window(); + } Ok(()) } diff --git a/komorebic.lib.sample.ahk b/komorebic.lib.sample.ahk index d8ba170c..bd0b98a1 100644 --- a/komorebic.lib.sample.ahk +++ b/komorebic.lib.sample.ahk @@ -184,6 +184,10 @@ WorkspaceName(monitor, workspace, value) { Run, komorebic.exe workspace-name %monitor% %workspace% %value%, , Hide } +ToggleNewWindowBehaviour() { + Run, komorebic.exe toggle-new-window-behaviour, , Hide +} + TogglePause() { Run, komorebic.exe toggle-pause, , Hide } diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index dac39b7a..5745d398 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -483,7 +483,9 @@ enum SubCommand { /// Set the workspace name for the specified workspace #[clap(setting = AppSettings::ArgRequiredElseHelp)] 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, /// Toggle window tiling on the focused workspace ToggleTiling, @@ -958,6 +960,9 @@ fn main() -> Result<()> { SubCommand::ResizeDelta(arg) => { send_message(&*SocketMessage::ResizeDelta(arg.pixels).as_bytes()?)?; } + SubCommand::ToggleNewWindowBehaviour => { + send_message(&*SocketMessage::ToggleNewWindowBehaviour.as_bytes()?)?; + } } Ok(())