feat(wm): add option to either minimize or hide

This commit adds a command to let the user decide if they want windows
to be hidden with SW_HIDE or minimized with SW_MINIMIZE when workspaces
are changed or window container stacks are cycled.

After a modest amount of local testing, SW_MINIMIZE does not appear to
introduce any regressions, and given that alt-tabbing is a common
workflow on Windows, it makes sense to have minimizing be the default
setting to ease the onboarding experience for new users.

resolve #72
This commit is contained in:
LGUG2Z
2021-11-18 16:59:51 -08:00
parent 0519ebddbf
commit f9785bef55
10 changed files with 127 additions and 72 deletions

137
README.md
View File

@@ -282,74 +282,75 @@ keybindings with. You can run `komorebic.exe <COMMAND> --help` to get a full exp
each command. each command.
``` ```
start Start komorebi.exe as a background process start Start komorebi.exe as a background process
stop Stop the komorebi.exe process and restore all hidden windows stop Stop the komorebi.exe process and restore all hidden windows
state Show a JSON representation of the current window manager state state Show a JSON representation of the current window manager state
query Query the current window manager state query Query the current window manager state
subscribe Subscribe to komorebi events subscribe Subscribe to komorebi events
unsubscribe Unsubscribe from komorebi events unsubscribe Unsubscribe from komorebi events
log Tail komorebi.exe's process logs (cancel with Ctrl-C) log Tail komorebi.exe's process logs (cancel with Ctrl-C)
quick-save-resize Quicksave the current resize layout dimensions quick-save-resize Quicksave the current resize layout dimensions
quick-load-resize Load the last quicksaved resize layout dimensions quick-load-resize Load the last quicksaved resize layout dimensions
save-resize Save the current resize layout dimensions to a file save-resize Save the current resize layout dimensions to a file
load-resize Load the resize layout dimensions from a file load-resize Load the resize layout dimensions from a file
focus Change focus to the window in the specified direction focus Change focus to the window in the specified direction
move Move the focused 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-focus Change focus to the window in the specified cycle direction
cycle-move Move the focused 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 stack Stack the focused window in the specified direction
resize-edge Resize 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 resize-axis Resize the focused window or primary column along the specified axis
unstack Unstack the focused window unstack Unstack the focused window
cycle-stack Cycle the focused stack in the specified cycle direction cycle-stack Cycle the focused stack in the specified cycle direction
move-to-monitor Move the focused window to the specified monitor move-to-monitor Move the focused window to the specified monitor
move-to-workspace Move the focused window to the specified workspace move-to-workspace Move the focused window to the specified workspace
send-to-monitor Send the focused window to the specified monitor send-to-monitor Send the focused window to the specified monitor
send-to-workspace Send the focused window to the specified workspace send-to-workspace Send the focused window to the specified workspace
focus-monitor Focus the specified monitor focus-monitor Focus the specified monitor
focus-workspace Focus the specified workspace on the focused monitor focus-workspace Focus the specified workspace on the focused monitor
cycle-monitor Focus the monitor in the given cycle direction cycle-monitor Focus the monitor in the given cycle direction
cycle-workspace Focus the workspace 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 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) resize-delta Set the resize delta (used by resize-edge and resize-axis)
invisible-borders Set the invisible border dimensions around each window invisible-borders Set the invisible border dimensions around each window
work-area-offset Set offsets to exclude parts of the work area from tiling 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-container-padding Adjust container padding on the focused workspace
adjust-workspace-padding Adjust workspace padding on the focused workspace adjust-workspace-padding Adjust workspace padding on the focused workspace
change-layout Set the layout 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 load-custom-layout Load a custom layout from file for the focused workspace
flip-layout Flip the layout on the focused workspace (BSP only) flip-layout Flip the layout on the focused workspace (BSP only)
promote Promote the focused window to the top of the tree promote Promote the focused window to the top of the tree
retile Force the retiling of all managed windows retile Force the retiling of all managed windows
ensure-workspaces Create at least this many workspaces for the specified monitor ensure-workspaces Create at least this many workspaces for the specified monitor
container-padding Set the container padding for the specified workspace container-padding Set the container padding for the specified workspace
workspace-padding Set the workspace 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-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-new-window-behaviour Toggle the behaviour for new windows (stacking or dynamic tiling) toggle-window-container-behaviour Toggle the behaviour for new windows (stacking or dynamic tiling)
toggle-pause Toggle window tiling on the focused workspace 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
toggle-maximize Toggle native maximization for the focused window toggle-maximize Toggle native maximization for the focused window
restore-windows Restore all hidden windows (debugging command) restore-windows Restore all hidden windows (debugging command)
manage Force komorebi to manage the focused window manage Force komorebi to manage the focused window
unmanage Unmanage a window that was forcibly managed unmanage Unmanage a window that was forcibly managed
reload-configuration Reload ~/komorebi.ahk (if it exists) reload-configuration Reload ~/komorebi.ahk (if it exists)
watch-configuration Enable or disable watching of ~/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 window-hiding-behaviour Set the window behaviour when switching workspaces / cycling stacks
manage-rule Add a rule to always manage the specified application float-rule Add a rule to always float the specified application
workspace-rule Add a rule to associate an application with a workspace manage-rule Add a rule to always manage the specified application
identify-tray-application Identify an application that closes to the system tray workspace-rule Add a rule to associate an application with a workspace
identify-border-overflow Identify an application that has overflowing borders identify-tray-application Identify an application that closes to the system tray
focus-follows-mouse Enable or disable focus follows mouse for the operating system identify-border-overflow Identify an application that has overflowing borders
toggle-focus-follows-mouse Toggle focus follows mouse for the operating system focus-follows-mouse Enable or disable focus follows mouse for the operating system
mouse-follows-focus Enable or disable mouse follows focus on all workspaces toggle-focus-follows-mouse Toggle focus follows mouse for the operating system
toggle-mouse-follows-focus Toggle mouse follows focus on all workspaces mouse-follows-focus Enable or disable mouse follows focus on all workspaces
ahk-library Generate a library of AutoHotKey helper functions toggle-mouse-follows-focus Toggle mouse follows focus on all workspaces
help Print this message or the help of the given subcommand(s) 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` ### AutoHotKey Helper Library for `komorebic`

View File

@@ -52,6 +52,7 @@ pub enum SocketMessage {
ToggleMonocle, ToggleMonocle,
ToggleMaximize, ToggleMaximize,
ToggleWindowContainerBehaviour, ToggleWindowContainerBehaviour,
WindowHidingBehaviour(HidingBehaviour),
// Current Workspace Commands // Current Workspace Commands
ManageFocusedWindow, ManageFocusedWindow,
UnmanageFocusedWindow, UnmanageFocusedWindow,
@@ -147,6 +148,13 @@ pub enum WindowContainerBehaviour {
Append, Append,
} }
#[derive(Clone, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
#[strum(serialize_all = "snake_case")]
pub enum HidingBehaviour {
Hide,
Minimize,
}
#[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 {

View File

@@ -1,6 +1,9 @@
#SingleInstance Force #SingleInstance Force
#Include %A_ScriptDir%\komorebic.lib.ahk #Include %A_ScriptDir%\komorebic.lib.ahk
; Default to minimizing windows when switching workspaces
WindowHidingBehaviour("minimize")
; Enable hot reloading of changes to this file ; Enable hot reloading of changes to this file
WatchConfiguration("enable") WatchConfiguration("enable")

View File

@@ -29,6 +29,7 @@ use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
use which::which; use which::which;
use komorebi_core::HidingBehaviour;
use komorebi_core::SocketMessage; use komorebi_core::SocketMessage;
use crate::process_command::listen_for_commands; use crate::process_command::listen_for_commands;
@@ -92,6 +93,8 @@ lazy_static! {
])); ]));
static ref SUBSCRIPTION_PIPES: Arc<Mutex<HashMap<String, File>>> = static ref SUBSCRIPTION_PIPES: Arc<Mutex<HashMap<String, File>>> =
Arc::new(Mutex::new(HashMap::new())); Arc::new(Mutex::new(HashMap::new()));
static ref HIDING_BEHAVIOUR: Arc<Mutex<HidingBehaviour>> =
Arc::new(Mutex::new(HidingBehaviour::Minimize));
} }
pub static CUSTOM_FFM: AtomicBool = AtomicBool::new(false); pub static CUSTOM_FFM: AtomicBool = AtomicBool::new(false);

View File

@@ -34,6 +34,7 @@ use crate::NotificationEvent;
use crate::BORDER_OVERFLOW_IDENTIFIERS; use crate::BORDER_OVERFLOW_IDENTIFIERS;
use crate::CUSTOM_FFM; use crate::CUSTOM_FFM;
use crate::FLOAT_IDENTIFIERS; use crate::FLOAT_IDENTIFIERS;
use crate::HIDING_BEHAVIOUR;
use crate::MANAGE_IDENTIFIERS; use crate::MANAGE_IDENTIFIERS;
use crate::SUBSCRIPTION_PIPES; use crate::SUBSCRIPTION_PIPES;
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS; use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
@@ -559,6 +560,10 @@ impl WindowManager {
} }
} }
} }
SocketMessage::WindowHidingBehaviour(behaviour) => {
let mut hiding_behaviour = HIDING_BEHAVIOUR.lock();
*hiding_behaviour = behaviour;
}
}; };
tracing::info!("processed"); tracing::info!("processed");

View File

@@ -103,13 +103,25 @@ impl WindowManager {
window.raise()?; window.raise()?;
self.has_pending_raise_op = false; self.has_pending_raise_op = false;
} }
WindowManagerEvent::Minimize(_, window) WindowManagerEvent::Destroy(_, window) | WindowManagerEvent::Unmanage(window) => {
| WindowManagerEvent::Destroy(_, window)
| WindowManagerEvent::Unmanage(window) => {
self.focused_workspace_mut()?.remove_window(window.hwnd)?; self.focused_workspace_mut()?.remove_window(window.hwnd)?;
self.update_focused_workspace(false)?; self.update_focused_workspace(false)?;
} }
WindowManagerEvent::Minimize(_, window) => {
let mut hide = false;
{
let programmatically_hidden_hwnds = HIDDEN_HWNDS.lock();
if !programmatically_hidden_hwnds.contains(&window.hwnd) {
hide = true;
}
}
if hide {
self.focused_workspace_mut()?.remove_window(window.hwnd)?;
self.update_focused_workspace(false)?;
}
}
WindowManagerEvent::Hide(_, window) => { WindowManagerEvent::Hide(_, window) => {
let mut hide = false; let mut hide = false;
// Some major applications unfortunately send the HIDE signal when they are being // Some major applications unfortunately send the HIDE signal when they are being

View File

@@ -10,6 +10,7 @@ use serde::Serialize;
use serde::Serializer; use serde::Serializer;
use windows::Win32::Foundation::HWND; use windows::Win32::Foundation::HWND;
use komorebi_core::HidingBehaviour;
use komorebi_core::Rect; use komorebi_core::Rect;
use crate::styles::ExtendedWindowStyle; use crate::styles::ExtendedWindowStyle;
@@ -19,6 +20,7 @@ use crate::windows_api::WindowsApi;
use crate::BORDER_OVERFLOW_IDENTIFIERS; use crate::BORDER_OVERFLOW_IDENTIFIERS;
use crate::FLOAT_IDENTIFIERS; use crate::FLOAT_IDENTIFIERS;
use crate::HIDDEN_HWNDS; use crate::HIDDEN_HWNDS;
use crate::HIDING_BEHAVIOUR;
use crate::LAYERED_EXE_WHITELIST; use crate::LAYERED_EXE_WHITELIST;
use crate::MANAGE_IDENTIFIERS; use crate::MANAGE_IDENTIFIERS;
use crate::WSL2_UI_PROCESSES; use crate::WSL2_UI_PROCESSES;
@@ -139,7 +141,11 @@ impl Window {
programmatically_hidden_hwnds.push(self.hwnd); programmatically_hidden_hwnds.push(self.hwnd);
} }
WindowsApi::hide_window(self.hwnd()); let hiding_behaviour = HIDING_BEHAVIOUR.lock();
match *hiding_behaviour {
HidingBehaviour::Hide => WindowsApi::hide_window(self.hwnd()),
HidingBehaviour::Minimize => WindowsApi::minimize_window(self.hwnd()),
}
} }
pub fn restore(self) { pub fn restore(self) {

View File

@@ -74,6 +74,7 @@ use windows::Win32::UI::WindowsAndMessaging::SPI_GETACTIVEWINDOWTRACKING;
use windows::Win32::UI::WindowsAndMessaging::SPI_SETACTIVEWINDOWTRACKING; use windows::Win32::UI::WindowsAndMessaging::SPI_SETACTIVEWINDOWTRACKING;
use windows::Win32::UI::WindowsAndMessaging::SW_HIDE; use windows::Win32::UI::WindowsAndMessaging::SW_HIDE;
use windows::Win32::UI::WindowsAndMessaging::SW_MAXIMIZE; use windows::Win32::UI::WindowsAndMessaging::SW_MAXIMIZE;
use windows::Win32::UI::WindowsAndMessaging::SW_MINIMIZE;
use windows::Win32::UI::WindowsAndMessaging::SW_RESTORE; use windows::Win32::UI::WindowsAndMessaging::SW_RESTORE;
use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_ACTION; use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_ACTION;
use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS; use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS;
@@ -279,6 +280,10 @@ impl WindowsApi {
unsafe { ShowWindow(hwnd, command) }; unsafe { ShowWindow(hwnd, command) };
} }
pub fn minimize_window(hwnd: HWND) {
Self::show_window(hwnd, SW_MINIMIZE);
}
pub fn hide_window(hwnd: HWND) { pub fn hide_window(hwnd: HWND) {
Self::show_window(hwnd, SW_HIDE); Self::show_window(hwnd, SW_HIDE);
} }

View File

@@ -228,6 +228,10 @@ WatchConfiguration(boolean_state) {
Run, komorebic.exe watch-configuration %boolean_state%, , Hide Run, komorebic.exe watch-configuration %boolean_state%, , Hide
} }
WindowHidingBehaviour(hiding_behaviour) {
Run, komorebic.exe window-hiding-behaviour %hiding_behaviour%, , Hide
}
FloatRule(identifier, id) { FloatRule(identifier, id) {
Run, komorebic.exe float-rule %identifier% %id%, , Hide Run, komorebic.exe float-rule %identifier% %id%, , Hide
} }

View File

@@ -32,6 +32,7 @@ use komorebi_core::Axis;
use komorebi_core::CycleDirection; use komorebi_core::CycleDirection;
use komorebi_core::DefaultLayout; use komorebi_core::DefaultLayout;
use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::FocusFollowsMouseImplementation;
use komorebi_core::HidingBehaviour;
use komorebi_core::OperationDirection; use komorebi_core::OperationDirection;
use komorebi_core::Rect; use komorebi_core::Rect;
use komorebi_core::Sizing; use komorebi_core::Sizing;
@@ -90,6 +91,7 @@ gen_enum_subcommand_args! {
WatchConfiguration: BooleanState, WatchConfiguration: BooleanState,
MouseFollowsFocus: BooleanState, MouseFollowsFocus: BooleanState,
Query: StateQuery, Query: StateQuery,
WindowHidingBehaviour: HidingBehaviour,
} }
macro_rules! gen_target_subcommand_args { macro_rules! gen_target_subcommand_args {
@@ -506,6 +508,9 @@ enum SubCommand {
/// Enable or disable watching of ~/komorebi.ahk (if it exists) /// Enable or disable watching of ~/komorebi.ahk (if it exists)
#[clap(setting = AppSettings::ArgRequiredElseHelp)] #[clap(setting = AppSettings::ArgRequiredElseHelp)]
WatchConfiguration(WatchConfiguration), WatchConfiguration(WatchConfiguration),
/// Set the window behaviour when switching workspaces / cycling stacks
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
WindowHidingBehaviour(WindowHidingBehaviour),
/// Add a rule to always float the specified application /// Add a rule to always float the specified application
#[clap(setting = AppSettings::ArgRequiredElseHelp)] #[clap(setting = AppSettings::ArgRequiredElseHelp)]
FloatRule(FloatRule), FloatRule(FloatRule),
@@ -963,6 +968,9 @@ fn main() -> Result<()> {
SubCommand::ToggleWindowContainerBehaviour => { SubCommand::ToggleWindowContainerBehaviour => {
send_message(&*SocketMessage::ToggleWindowContainerBehaviour.as_bytes()?)?; send_message(&*SocketMessage::ToggleWindowContainerBehaviour.as_bytes()?)?;
} }
SubCommand::WindowHidingBehaviour(arg) => {
send_message(&*SocketMessage::WindowHidingBehaviour(arg.hiding_behaviour).as_bytes()?)?;
}
} }
Ok(()) Ok(())