feat(wm): add quicksaving/loading of sizes/layouts

This commit adds two new komorebic commands to quicksave and quickload
BSP layouts with custom resize dimensions. The quicksave file is stored
at ${Env:TEMP}/komorebi.quicksave.json, and is a Vec<Option<Rect>>
serialized to JSON.

If a user tries to quickload without a quicksave file being present, an
error will be logged.

At this point there is only one quicksave file which will always be
overwritten whenever the quicksave command is called. Both commands will
only operate on the focused workspace of the focused monitor.

This means that you can quicksave a layout on one workspace, and then
quickload it onto multiple other workspaces (individually) on the same
or other monitors.

If the number of elements in the deserialized Vec is greater than the
number of containers on a workspace, the Vec will be truncated when
Workspace.update is run, and similarly if the number of elements is less
than the number of containers on a workspace, the Vec will be extended
by the difference using None values.

resolve #39
This commit is contained in:
LGUG2Z
2021-09-21 17:12:16 -07:00
parent e10e11d1de
commit 80bcb51f75
7 changed files with 68 additions and 1 deletions

View File

@@ -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

View File

@@ -52,6 +52,8 @@ pub enum SocketMessage {
Stop,
TogglePause,
Retile,
QuickSave,
QuickLoad,
FocusMonitorNumber(usize),
FocusWorkspaceNumber(usize),
ContainerPadding(usize, usize, i32),

View File

@@ -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")

View File

@@ -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<Option<Rect>> = serde_json::from_reader(file)?;
workspace.set_resize_dimensions(resize);
self.update_focused_workspace(false)?;
}
};
tracing::info!("processed");

View File

@@ -48,7 +48,7 @@ pub struct Workspace {
#[serde(skip_serializing)]
#[getset(get = "pub", set = "pub")]
latest_layout: Vec<Rect>,
#[getset(get = "pub", get_mut = "pub")]
#[getset(get = "pub", get_mut = "pub", set = "pub")]
resize_dimensions: Vec<Option<Rect>>,
#[getset(get = "pub", set = "pub")]
tile: bool,

View File

@@ -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
}

View File

@@ -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(())