diff --git a/README.md b/README.md index 8fa652b7..401075ff 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,8 @@ 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 +quick-save Quicksave the current resize layout dimensions +quick-load Load the last quicksaved resize layout dimensions query Query the current window manager state log Tail komorebi.exe's process logs (cancel with Ctrl-C) focus Change focus to the window in the specified direction @@ -272,6 +274,7 @@ used [is available here](komorebi.sample.with.lib.ahk). - [x] Mouse follows focused container - [x] Resize window container in direction - [ ] Resize child window containers by split ratio +- [x] Quicksave and quickload layouts with resize dimensions - [x] Mouse drag to swap window container position - [x] Mouse drag to resize window container - [x] Configurable workspace and container gaps diff --git a/komorebi-core/src/lib.rs b/komorebi-core/src/lib.rs index f34dbeca..dbe001df 100644 --- a/komorebi-core/src/lib.rs +++ b/komorebi-core/src/lib.rs @@ -52,6 +52,8 @@ pub enum SocketMessage { Stop, TogglePause, Retile, + QuickSave, + QuickLoad, FocusMonitorNumber(usize), FocusWorkspaceNumber(usize), ContainerPadding(usize, usize, i32), diff --git a/komorebi.sample.with.lib.ahk b/komorebi.sample.with.lib.ahk index d580d117..89c39350 100644 --- a/komorebi.sample.with.lib.ahk +++ b/komorebi.sample.with.lib.ahk @@ -40,16 +40,24 @@ FloatRule("exe", "Wally.exe") FloatRule("exe", "wincompose.exe") FloatRule("exe", "1Password.exe") FloatRule("exe", "Wox.exe") +FloatRule("exe", "ddm.exe") +FloatRule("class", "Chrome_RenderWidgetHostHWND") ; GOG Electron invisible overlay +FloatRule("class", "CEFCLIENT") ; Identify Minimize-to-Tray Applications IdentifyTrayApplication("exe", "Discord.exe") IdentifyTrayApplication("exe", "Spotify.exe") +IdentifyTrayApplication("exe", "GalaxyClient.exe") ; Identify Electron applications with overflowing borders IdentifyBorderOverflow("exe", "Discord.exe") IdentifyBorderOverflow("exe", "Spotify.exe") +IdentifyBorderOverflow("exe", "GalaxyClient.exe") IdentifyBorderOverflow("class", "ZPFTEWndClass") +; Identify applications to be forcibly managed +ManageRule("exe", "GalaxyClient.exe") + ; Change the focused window, Alt + Vim direction keys !h:: Focus("left") diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index 9e34704a..6f1f4ad6 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -1,3 +1,5 @@ +use std::fs::File; +use std::fs::OpenOptions; use std::io::BufRead; use std::io::BufReader; use std::io::Write; @@ -12,6 +14,7 @@ use parking_lot::Mutex; use uds_windows::UnixStream; use komorebi_core::FocusFollowsMouseImplementation; +use komorebi_core::Rect; use komorebi_core::SocketMessage; use komorebi_core::StateQuery; @@ -326,6 +329,39 @@ impl WindowManager { self.invisible_borders = rect; self.retile_all()?; } + SocketMessage::QuickSave => { + let workspace = self.focused_workspace()?; + let resize = workspace.resize_dimensions(); + + let mut quicksave_json = std::env::temp_dir(); + quicksave_json.push("komorebi.quicksave.json"); + + let file = OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(quicksave_json)?; + + serde_json::to_writer_pretty(&file, &resize)?; + } + SocketMessage::QuickLoad => { + let workspace = self.focused_workspace_mut()?; + + let mut quicksave_json = std::env::temp_dir(); + quicksave_json.push("komorebi.quicksave.json"); + + let file = File::open(&quicksave_json).map_err(|_| { + anyhow!( + "no quicksave found at {}", + quicksave_json.display().to_string() + ) + })?; + + let resize: Vec> = serde_json::from_reader(file)?; + + workspace.set_resize_dimensions(resize); + self.update_focused_workspace(false)?; + } }; tracing::info!("processed"); diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index c91b4820..f4c6a2f1 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -48,7 +48,7 @@ pub struct Workspace { #[serde(skip_serializing)] #[getset(get = "pub", set = "pub")] latest_layout: Vec, - #[getset(get = "pub", get_mut = "pub")] + #[getset(get = "pub", get_mut = "pub", set = "pub")] resize_dimensions: Vec>, #[getset(get = "pub", set = "pub")] tile: bool, diff --git a/komorebic.lib.sample.ahk b/komorebic.lib.sample.ahk index 55f9dab5..f7f0ea42 100644 --- a/komorebic.lib.sample.ahk +++ b/komorebic.lib.sample.ahk @@ -12,6 +12,14 @@ State() { Run, komorebic.exe state, , Hide } +QuickSave() { + Run, komorebic.exe quick-save, , Hide +} + +QuickLoad() { + Run, komorebic.exe quick-load, , Hide +} + Query(state_query) { Run, komorebic.exe query %state_query%, , Hide } diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index 365c32d1..658270c6 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -283,6 +283,10 @@ enum SubCommand { Stop, /// Show a JSON representation of the current window manager state State, + /// Quicksave the current resize layout dimensions + QuickSave, + /// Load the last quicksaved resize layout dimensions + QuickLoad, /// Query the current window manager state #[clap(setting = AppSettings::ArgRequiredElseHelp)] Query(Query), @@ -767,6 +771,12 @@ fn main() -> Result<()> { SubCommand::Unmanage => { send_message(&*SocketMessage::UnmanageFocusedWindow.as_bytes()?)?; } + SubCommand::QuickSave => { + send_message(&*SocketMessage::QuickSave.as_bytes()?)?; + } + SubCommand::QuickLoad => { + send_message(&*SocketMessage::QuickLoad.as_bytes()?)?; + } } Ok(())