mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-03-23 18:01:12 +01:00
refactor(wm): add window handling sync/async enum
This commit adds a dedicated WindowHandlingBehaviour enum with Sync and Async variants, and reverts a change to the render fn in window.rs to use move_window instead of position_window if the WindowHandlingBehaviour variant is Sync.
This commit is contained in:
@@ -529,6 +529,16 @@ impl Sizing {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Default, Serialize, Deserialize, Display, EnumString, ValueEnum, PartialEq,
|
||||
)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum WindowHandlingBehaviour {
|
||||
#[default]
|
||||
Sync,
|
||||
Async,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -63,6 +63,7 @@ use crate::core::config_generation::MatchingRule;
|
||||
use crate::core::config_generation::MatchingStrategy;
|
||||
use crate::core::config_generation::WorkspaceMatchingRule;
|
||||
use color_eyre::Result;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use os_info::Version;
|
||||
use parking_lot::Mutex;
|
||||
use parking_lot::RwLock;
|
||||
@@ -240,7 +241,8 @@ pub static REMOVE_TITLEBARS: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub static SLOW_APPLICATION_COMPENSATION_TIME: AtomicU64 = AtomicU64::new(20);
|
||||
|
||||
pub static ASYNC_WINDOW_HANDLING_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||
pub static WINDOW_HANDLING_BEHAVIOUR: AtomicCell<WindowHandlingBehaviour> =
|
||||
AtomicCell::new(WindowHandlingBehaviour::Sync);
|
||||
|
||||
shadow_rs::shadow!(build);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ use crate::FloatingLayerBehaviour;
|
||||
use crate::Placement;
|
||||
use crate::PredefinedAspectRatio;
|
||||
use crate::ResolvedPathBuf;
|
||||
use crate::ASYNC_WINDOW_HANDLING_ENABLED;
|
||||
use crate::WindowHandlingBehaviour;
|
||||
use crate::DATA_DIR;
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crate::DEFAULT_WORKSPACE_PADDING;
|
||||
@@ -84,6 +84,7 @@ use crate::SLOW_APPLICATION_IDENTIFIERS;
|
||||
use crate::TRANSPARENCY_BLACKLIST;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WINDOWS_11;
|
||||
use crate::WINDOW_HANDLING_BEHAVIOUR;
|
||||
use crate::WORKSPACE_MATCHING_RULES;
|
||||
use color_eyre::Result;
|
||||
use crossbeam_channel::Receiver;
|
||||
@@ -561,9 +562,9 @@ pub struct StaticConfig {
|
||||
/// Aspect ratio to resize with when toggling floating mode for a window
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub floating_window_aspect_ratio: Option<AspectRatio>,
|
||||
/// Use asynchronous window handling to avoid blocking the main thread when a window is not responding (default: false)
|
||||
/// Which Windows API behaviour to use when manipulating windows (default: Sync)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub async_window_handling: Option<bool>,
|
||||
pub window_handling_behaviour: Option<WindowHandlingBehaviour>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||
@@ -925,7 +926,7 @@ impl From<&WindowManager> for StaticConfig {
|
||||
bar_configurations: None,
|
||||
remove_titlebar_applications: Option::from(NO_TITLEBAR.lock().clone()),
|
||||
floating_window_aspect_ratio: Option::from(*FLOATING_WINDOW_TOGGLE_ASPECT_RATIO.lock()),
|
||||
async_window_handling: Option::from(false),
|
||||
window_handling_behaviour: Option::from(WINDOW_HANDLING_BEHAVIOUR.load()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1213,8 +1214,8 @@ impl StaticConfig {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(async_enabled) = self.async_window_handling {
|
||||
ASYNC_WINDOW_HANDLING_ENABLED.store(async_enabled, Ordering::SeqCst);
|
||||
if let Some(behaviour) = self.window_handling_behaviour {
|
||||
WINDOW_HANDLING_BEHAVIOUR.store(behaviour);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -27,6 +27,7 @@ use crate::window_manager_event::WindowManagerEvent;
|
||||
use crate::windows_api;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::AnimationStyle;
|
||||
use crate::WindowHandlingBehaviour;
|
||||
use crate::FLOATING_APPLICATIONS;
|
||||
use crate::FLOATING_WINDOW_TOGGLE_ASPECT_RATIO;
|
||||
use crate::HIDDEN_HWNDS;
|
||||
@@ -39,6 +40,7 @@ use crate::PERMAIGNORE_CLASSES;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::SLOW_APPLICATION_COMPENSATION_TIME;
|
||||
use crate::SLOW_APPLICATION_IDENTIFIERS;
|
||||
use crate::WINDOW_HANDLING_BEHAVIOUR;
|
||||
use crate::WSL2_UI_PROCESSES;
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::Result;
|
||||
@@ -203,8 +205,15 @@ impl RenderDispatcher for MovementRenderDispatcher {
|
||||
fn render(&self, progress: f64) -> Result<()> {
|
||||
let new_rect = self.start_rect.lerp(self.target_rect, progress, self.style);
|
||||
|
||||
// MoveWindow runs faster than SetWindowPos, but it doesn't support async window pos
|
||||
WindowsApi::position_window(self.hwnd, &new_rect, self.top, true)?;
|
||||
match WINDOW_HANDLING_BEHAVIOUR.load() {
|
||||
WindowHandlingBehaviour::Sync => {
|
||||
WindowsApi::move_window(self.hwnd, &new_rect, false)?;
|
||||
}
|
||||
WindowHandlingBehaviour::Async => {
|
||||
// MoveWindow runs faster than SetWindowPos, but it doesn't support async window pos
|
||||
WindowsApi::position_window(self.hwnd, &new_rect, self.top, true)?;
|
||||
}
|
||||
}
|
||||
WindowsApi::invalidate_rect(self.hwnd, None, false);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -8,7 +8,6 @@ use std::collections::VecDeque;
|
||||
use std::convert::TryFrom;
|
||||
use std::mem::size_of;
|
||||
use std::path::Path;
|
||||
use std::sync::atomic::Ordering;
|
||||
use windows::core::Result as WindowsCrateResult;
|
||||
use windows::core::PCWSTR;
|
||||
use windows::core::PWSTR;
|
||||
@@ -160,11 +159,12 @@ use crate::ring::Ring;
|
||||
use crate::set_window_position::SetWindowPosition;
|
||||
use crate::windows_callbacks;
|
||||
use crate::Window;
|
||||
use crate::WindowHandlingBehaviour;
|
||||
use crate::WindowManager;
|
||||
use crate::ASYNC_WINDOW_HANDLING_ENABLED;
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::DUPLICATE_MONITOR_SERIAL_IDS;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::WINDOW_HANDLING_BEHAVIOUR;
|
||||
|
||||
macro_rules! as_ptr {
|
||||
($value:expr) => {
|
||||
@@ -481,7 +481,7 @@ impl WindowsApi {
|
||||
hwnd: isize,
|
||||
layout: &Rect,
|
||||
top: bool,
|
||||
async_window_pos: bool,
|
||||
supports_async: bool,
|
||||
) -> Result<()> {
|
||||
let hwnd = HWND(as_ptr!(hwnd));
|
||||
|
||||
@@ -497,7 +497,12 @@ impl WindowsApi {
|
||||
// By default SetWindowPos waits for target window's WindowProc thread
|
||||
// to process the message, so we have to use ASYNC_WINDOW_POS to avoid
|
||||
// blocking our thread in case the target window is not responding.
|
||||
if async_window_pos && ASYNC_WINDOW_HANDLING_ENABLED.load(Ordering::SeqCst) {
|
||||
if supports_async
|
||||
&& matches!(
|
||||
WINDOW_HANDLING_BEHAVIOUR.load(),
|
||||
WindowHandlingBehaviour::Async
|
||||
)
|
||||
{
|
||||
flags |= SetWindowPosition::ASYNC_WINDOW_POS;
|
||||
}
|
||||
|
||||
@@ -540,7 +545,10 @@ impl WindowsApi {
|
||||
| SetWindowPosition::NO_ACTIVATE
|
||||
| SetWindowPosition::SHOW_WINDOW;
|
||||
|
||||
if ASYNC_WINDOW_HANDLING_ENABLED.load(Ordering::SeqCst) {
|
||||
if matches!(
|
||||
WINDOW_HANDLING_BEHAVIOUR.load(),
|
||||
WindowHandlingBehaviour::Async
|
||||
) {
|
||||
flags |= SetWindowPosition::ASYNC_WINDOW_POS;
|
||||
}
|
||||
|
||||
@@ -561,7 +569,10 @@ impl WindowsApi {
|
||||
| SetWindowPosition::NO_ACTIVATE
|
||||
| SetWindowPosition::SHOW_WINDOW;
|
||||
|
||||
if ASYNC_WINDOW_HANDLING_ENABLED.load(Ordering::SeqCst) {
|
||||
if matches!(
|
||||
WINDOW_HANDLING_BEHAVIOUR.load(),
|
||||
WindowHandlingBehaviour::Async
|
||||
) {
|
||||
flags |= SetWindowPosition::ASYNC_WINDOW_POS;
|
||||
}
|
||||
|
||||
@@ -580,7 +591,10 @@ impl WindowsApi {
|
||||
| SetWindowPosition::NO_REDRAW
|
||||
| SetWindowPosition::SHOW_WINDOW;
|
||||
|
||||
if ASYNC_WINDOW_HANDLING_ENABLED.load(Ordering::SeqCst) {
|
||||
if matches!(
|
||||
WINDOW_HANDLING_BEHAVIOUR.load(),
|
||||
WindowHandlingBehaviour::Async
|
||||
) {
|
||||
flags |= SetWindowPosition::ASYNC_WINDOW_POS;
|
||||
}
|
||||
|
||||
@@ -626,7 +640,10 @@ impl WindowsApi {
|
||||
// BOOL is returned but does not signify whether or not the operation was succesful
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
|
||||
// TODO: error handling
|
||||
if ASYNC_WINDOW_HANDLING_ENABLED.load(Ordering::SeqCst) {
|
||||
if matches!(
|
||||
WINDOW_HANDLING_BEHAVIOUR.load(),
|
||||
WindowHandlingBehaviour::Async
|
||||
) {
|
||||
unsafe {
|
||||
let _ = ShowWindowAsync(HWND(as_ptr!(hwnd)), command);
|
||||
};
|
||||
|
||||
12
schema.json
12
schema.json
@@ -217,10 +217,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"async_window_handling": {
|
||||
"description": "Use asynchronous window handling to avoid blocking the main thread when a window is not responding (default: false)",
|
||||
"type": "boolean"
|
||||
},
|
||||
"bar_configurations": {
|
||||
"description": "Komorebi status bar configuration files for multiple instances on different monitors",
|
||||
"type": "array",
|
||||
@@ -4619,6 +4615,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"window_handling_behaviour": {
|
||||
"description": "Which Windows API behaviour to use when manipulating windows (default: Sync)",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Sync",
|
||||
"Async"
|
||||
]
|
||||
},
|
||||
"window_hiding_behaviour": {
|
||||
"description": "Which Windows signal to use when hiding windows (default: Cloak)",
|
||||
"oneOf": [
|
||||
|
||||
Reference in New Issue
Block a user