feat(wm): allow stopping without restoring windows

This commit creates a new `SocketMessage` called `StopIgnoreRestore`
which makes komorebi stop without calling `window.restore()` on all
windows. This way every maximized window will stay maximized once you
start komorebi again and it is able to use the previous `State`.

If it fails to restore the previous state you might have to call
`komorebic restore-windows` in case you had hidden windows, for example
when when using the `window_hiding_behaviour` as `Hide`, or you can
simply unminimize them if you were using `Cloak` or `Minimize`.
This commit is contained in:
alex-ds13
2024-12-17 19:21:58 +00:00
committed by جاد
parent 5dbf0f1b89
commit f089d3e59b
5 changed files with 59 additions and 38 deletions

View File

@@ -105,6 +105,7 @@ pub enum SocketMessage {
NewWorkspace, NewWorkspace,
ToggleTiling, ToggleTiling,
Stop, Stop,
StopIgnoreRestore,
TogglePause, TogglePause,
Retile, Retile,
RetileWithResizeDimensions, RetileWithResizeDimensions,

View File

@@ -307,7 +307,7 @@ fn main() -> Result<()> {
ANIMATION_ENABLED_PER_ANIMATION.lock().clear(); ANIMATION_ENABLED_PER_ANIMATION.lock().clear();
ANIMATION_ENABLED_GLOBAL.store(false, Ordering::SeqCst); ANIMATION_ENABLED_GLOBAL.store(false, Ordering::SeqCst);
wm.lock().restore_all_windows()?; wm.lock().restore_all_windows(false)?;
AnimationEngine::wait_for_all_animations(); AnimationEngine::wait_for_all_animations();
if WindowsApi::focus_follows_mouse()? { if WindowsApi::focus_follows_mouse()? {

View File

@@ -1,11 +1,9 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::env::temp_dir;
use std::fs::File; use std::fs::File;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::BufRead; use std::io::BufRead;
use std::io::BufReader; use std::io::BufReader;
use std::io::Read; use std::io::Read;
use std::net::Shutdown;
use std::net::TcpListener; use std::net::TcpListener;
use std::net::TcpStream; use std::net::TcpStream;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
@@ -23,7 +21,6 @@ use schemars::gen::SchemaSettings;
use schemars::schema_for; use schemars::schema_for;
use uds_windows::UnixStream; use uds_windows::UnixStream;
use crate::animation::AnimationEngine;
use crate::animation::ANIMATION_DURATION_PER_ANIMATION; use crate::animation::ANIMATION_DURATION_PER_ANIMATION;
use crate::animation::ANIMATION_ENABLED_PER_ANIMATION; use crate::animation::ANIMATION_ENABLED_PER_ANIMATION;
use crate::animation::ANIMATION_STYLE_PER_ANIMATION; use crate::animation::ANIMATION_STYLE_PER_ANIMATION;
@@ -913,36 +910,10 @@ impl WindowManager {
} }
} }
SocketMessage::Stop => { SocketMessage::Stop => {
tracing::info!( self.stop(false)?;
"received stop command, restoring all hidden windows and terminating process" }
); SocketMessage::StopIgnoreRestore => {
self.stop(true)?;
let state = &window_manager::State::from(&*self);
std::fs::write(
temp_dir().join("komorebi.state.json"),
serde_json::to_string_pretty(&state)?,
)?;
ANIMATION_ENABLED_PER_ANIMATION.lock().clear();
ANIMATION_ENABLED_GLOBAL.store(false, Ordering::SeqCst);
self.restore_all_windows()?;
AnimationEngine::wait_for_all_animations();
if WindowsApi::focus_follows_mouse()? {
WindowsApi::disable_focus_follows_mouse()?;
}
let sockets = SUBSCRIPTION_SOCKETS.lock();
for path in (*sockets).values() {
if let Ok(stream) = UnixStream::connect(path) {
stream.shutdown(Shutdown::Both)?;
}
}
let socket = DATA_DIR.join("komorebi.sock");
let _ = std::fs::remove_file(socket);
std::process::exit(0)
} }
SocketMessage::MonitorIndexPreference(index_preference, left, top, right, bottom) => { SocketMessage::MonitorIndexPreference(index_preference, left, top, right, bottom) => {
let mut monitor_index_preferences = MONITOR_INDEX_PREFERENCES.lock(); let mut monitor_index_preferences = MONITOR_INDEX_PREFERENCES.lock();
@@ -1257,7 +1228,7 @@ impl WindowManager {
// Pause so that restored windows come to the foreground from all workspaces // Pause so that restored windows come to the foreground from all workspaces
self.is_paused = true; self.is_paused = true;
// Bring all windows to the foreground // Bring all windows to the foreground
self.restore_all_windows()?; self.restore_all_windows(false)?;
// Create a new wm from the config path // Create a new wm from the config path
let mut wm = StaticConfig::preload( let mut wm = StaticConfig::preload(

View File

@@ -3,6 +3,7 @@ use std::collections::HashSet;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::env::temp_dir; use std::env::temp_dir;
use std::io::ErrorKind; use std::io::ErrorKind;
use std::net::Shutdown;
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
@@ -21,7 +22,11 @@ use schemars::JsonSchema;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
use uds_windows::UnixListener; use uds_windows::UnixListener;
use uds_windows::UnixStream;
use crate::animation::AnimationEngine;
use crate::animation::ANIMATION_ENABLED_GLOBAL;
use crate::animation::ANIMATION_ENABLED_PER_ANIMATION;
use crate::core::config_generation::MatchingRule; use crate::core::config_generation::MatchingRule;
use crate::core::custom_layout::CustomLayout; use crate::core::custom_layout::CustomLayout;
use crate::core::Arrangement; use crate::core::Arrangement;
@@ -85,6 +90,7 @@ use crate::NO_TITLEBAR;
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH; use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
use crate::REGEX_IDENTIFIERS; use crate::REGEX_IDENTIFIERS;
use crate::REMOVE_TITLEBARS; use crate::REMOVE_TITLEBARS;
use crate::SUBSCRIPTION_SOCKETS;
use crate::TRANSPARENCY_BLACKLIST; use crate::TRANSPARENCY_BLACKLIST;
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS; use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
use crate::WORKSPACE_MATCHING_RULES; use crate::WORKSPACE_MATCHING_RULES;
@@ -1386,7 +1392,41 @@ impl WindowManager {
} }
#[tracing::instrument(skip(self))] #[tracing::instrument(skip(self))]
pub fn restore_all_windows(&mut self) -> Result<()> { pub fn stop(&mut self, ignore_restore: bool) -> Result<()> {
tracing::info!(
"received stop command, restoring all hidden windows and terminating process"
);
let state = &State::from(&*self);
std::fs::write(
temp_dir().join("komorebi.state.json"),
serde_json::to_string_pretty(&state)?,
)?;
ANIMATION_ENABLED_PER_ANIMATION.lock().clear();
ANIMATION_ENABLED_GLOBAL.store(false, Ordering::SeqCst);
self.restore_all_windows(ignore_restore)?;
AnimationEngine::wait_for_all_animations();
if WindowsApi::focus_follows_mouse()? {
WindowsApi::disable_focus_follows_mouse()?;
}
let sockets = SUBSCRIPTION_SOCKETS.lock();
for path in (*sockets).values() {
if let Ok(stream) = UnixStream::connect(path) {
stream.shutdown(Shutdown::Both)?;
}
}
let socket = DATA_DIR.join("komorebi.sock");
let _ = std::fs::remove_file(socket);
std::process::exit(0)
}
#[tracing::instrument(skip(self))]
pub fn restore_all_windows(&mut self, ignore_restore: bool) -> Result<()> {
tracing::info!("restoring all hidden windows"); tracing::info!("restoring all hidden windows");
let no_titlebar = NO_TITLEBAR.lock(); let no_titlebar = NO_TITLEBAR.lock();
@@ -1417,7 +1457,9 @@ impl WindowManager {
window.remove_accent()?; window.remove_accent()?;
} }
window.restore(); if !ignore_restore {
window.restore();
}
} }
} }
} }

View File

@@ -801,6 +801,9 @@ struct Stop {
/// Stop masir if it is running as a background process /// Stop masir if it is running as a background process
#[clap(long)] #[clap(long)]
masir: bool, masir: bool,
/// Do not restore windows after stopping komorebi
#[clap(long, hide = true)]
ignore_restore: bool,
} }
#[derive(Parser)] #[derive(Parser)]
@@ -2300,7 +2303,11 @@ if (Get-Command Get-CimInstance -ErrorAction SilentlyContinue) {
} }
} }
send_message(&SocketMessage::Stop)?; if arg.ignore_restore {
send_message(&SocketMessage::StopIgnoreRestore)?;
} else {
send_message(&SocketMessage::Stop)?;
}
let mut system = sysinfo::System::new_all(); let mut system = sysinfo::System::new_all();
system.refresh_processes(ProcessesToUpdate::All); system.refresh_processes(ProcessesToUpdate::All);