fix(wm): enforce strict manage override checks

This commit ensures that when a window has matched a float rule, the
managed override rule will only apply to that window if the override
identifier is of the same kind (exe, title, class) as the float rule
identifier.

This ensures that the wm isn't constantly trying to allow and disallow
certain windows such as Slack's hidden window, resulting in an infinite
show/hide and retile loop.
This commit is contained in:
LGUG2Z
2022-07-25 20:52:27 -07:00
parent 77ae5bc2f4
commit eec628f7f1

View File

@@ -12,6 +12,7 @@ use serde::Serialize;
use serde::Serializer;
use windows::Win32::Foundation::HWND;
use komorebi_core::ApplicationIdentifier;
use komorebi_core::HidingBehaviour;
use komorebi_core::Rect;
@@ -293,58 +294,7 @@ impl Window {
// If not allowing cloaked windows, we need to ensure the window is not cloaked
(false, false) => {
if let (Ok(title), Ok(exe_name), Ok(class)) = (self.title(), self.exe(), self.class()) {
let mut should_float = false;
{
let float_identifiers = FLOAT_IDENTIFIERS.lock();
for identifier in float_identifiers.iter() {
if title.starts_with(identifier) || title.ends_with(identifier) ||
class.starts_with(identifier) || class.ends_with(identifier) ||
identifier == &exe_name {
should_float = true;
}
}
}
let managed_override = {
let manage_identifiers = MANAGE_IDENTIFIERS.lock();
manage_identifiers.contains(&exe_name)
|| manage_identifiers.contains(&class)
|| manage_identifiers.contains(&title)
};
if should_float && !managed_override {
return Ok(false);
}
let allow_layered = {
let layered_whitelist = LAYERED_WHITELIST.lock();
layered_whitelist.contains(&exe_name)
|| layered_whitelist.contains(&class)
|| layered_whitelist.contains(&title)
};
let allow_wsl2_gui = {
let wsl2_ui_processes = WSL2_UI_PROCESSES.lock();
wsl2_ui_processes.contains(&exe_name)
};
let style = self.style()?;
let ex_style = self.ex_style()?;
if (allow_wsl2_gui || style.contains(WindowStyle::CAPTION) && ex_style.contains(ExtendedWindowStyle::WINDOWEDGE))
&& !ex_style.contains(ExtendedWindowStyle::DLGMODALFRAME)
// Get a lot of dupe events coming through that make the redrawing go crazy
// on FocusChange events if I don't filter out this one. But, if we are
// allowing a specific layered window on the whitelist (like Steam), it should
// pass this check
&& (allow_layered || !ex_style.contains(ExtendedWindowStyle::LAYERED))
|| managed_override
{
return Ok(true);
} else if event.is_some() {
tracing::debug!("ignoring (exe: {}, title: {})", exe_name, title);
}
return Ok(window_is_eligible(&title, &exe_name, &class, self.style()?, self.ex_style()?, event));
}
}
_ => {}
@@ -353,3 +303,83 @@ impl Window {
Ok(false)
}
}
fn window_is_eligible(
title: &String,
exe_name: &String,
class: &String,
style: WindowStyle,
ex_style: ExtendedWindowStyle,
event: Option<WindowManagerEvent>,
) -> bool {
let mut should_float = false;
let mut matched_identifier = None;
{
let float_identifiers = FLOAT_IDENTIFIERS.lock();
for identifier in float_identifiers.iter() {
if title.starts_with(identifier) || title.ends_with(identifier) {
should_float = true;
matched_identifier = Option::from(ApplicationIdentifier::Title);
}
if class.starts_with(identifier) || class.ends_with(identifier) {
should_float = true;
matched_identifier = Option::from(ApplicationIdentifier::Class);
}
if identifier == exe_name {
should_float = true;
matched_identifier = Option::from(ApplicationIdentifier::Exe);
}
}
};
let managed_override = {
let manage_identifiers = MANAGE_IDENTIFIERS.lock();
matched_identifier.map_or_else(
|| {
manage_identifiers.contains(exe_name)
|| manage_identifiers.contains(class)
|| manage_identifiers.contains(title)
},
|matched_identifier| match matched_identifier {
ApplicationIdentifier::Exe => manage_identifiers.contains(exe_name),
ApplicationIdentifier::Class => manage_identifiers.contains(class),
ApplicationIdentifier::Title => manage_identifiers.contains(title),
},
)
};
if should_float && !managed_override {
return false;
}
let allow_layered = {
let layered_whitelist = LAYERED_WHITELIST.lock();
layered_whitelist.contains(exe_name)
|| layered_whitelist.contains(class)
|| layered_whitelist.contains(title)
};
let allow_wsl2_gui = {
let wsl2_ui_processes = WSL2_UI_PROCESSES.lock();
wsl2_ui_processes.contains(exe_name)
};
if (allow_wsl2_gui || style.contains(WindowStyle::CAPTION) && ex_style.contains(ExtendedWindowStyle::WINDOWEDGE))
&& !ex_style.contains(ExtendedWindowStyle::DLGMODALFRAME)
// Get a lot of dupe events coming through that make the redrawing go crazy
// on FocusChange events if I don't filter out this one. But, if we are
// allowing a specific layered window on the whitelist (like Steam), it should
// pass this check
&& (allow_layered || !ex_style.contains(ExtendedWindowStyle::LAYERED))
|| managed_override
{
return true;
} else if event.is_some() {
tracing::debug!("ignoring (exe: {}, title: {})", exe_name, title);
}
false
}