refactor(wm): improve data consistency + scoping

Just a little bit of clean up to make sure that the float rule data
structures match the same emerging pattern as the data structures for
other kinds of rules.

Also some refactoring of Window.should_manage to ensure stricter scoping
where locks are gained on global static variables.
This commit is contained in:
LGUG2Z
2021-08-19 17:18:22 -07:00
parent 6f7e87799b
commit 2e86b607b2
7 changed files with 59 additions and 107 deletions
+1 -3
View File
@@ -57,10 +57,8 @@ pub enum SocketMessage {
// Configuration // Configuration
ReloadConfiguration, ReloadConfiguration,
WatchConfiguration(bool), WatchConfiguration(bool),
FloatClass(String),
FloatExe(String),
FloatTitle(String),
WorkspaceRule(ApplicationIdentifier, String, usize, usize), WorkspaceRule(ApplicationIdentifier, String, usize, usize),
FloatRule(ApplicationIdentifier, String),
ManageRule(ApplicationIdentifier, String), ManageRule(ApplicationIdentifier, String),
IdentifyTrayApplication(ApplicationIdentifier, String), IdentifyTrayApplication(ApplicationIdentifier, String),
State, State,
+1 -3
View File
@@ -48,9 +48,6 @@ mod winevent_listener;
mod workspace; mod workspace;
lazy_static! { lazy_static! {
static ref FLOAT_CLASSES: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
static ref FLOAT_EXES: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
static ref FLOAT_TITLES: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
static ref HIDDEN_HWNDS: Arc<Mutex<Vec<isize>>> = Arc::new(Mutex::new(vec![])); static ref HIDDEN_HWNDS: Arc<Mutex<Vec<isize>>> = Arc::new(Mutex::new(vec![]));
static ref LAYERED_EXE_WHITELIST: Arc<Mutex<Vec<String>>> = static ref LAYERED_EXE_WHITELIST: Arc<Mutex<Vec<String>>> =
Arc::new(Mutex::new(vec!["steam.exe".to_string()])); Arc::new(Mutex::new(vec!["steam.exe".to_string()]));
@@ -71,6 +68,7 @@ lazy_static! {
static ref WORKSPACE_RULES: Arc<Mutex<HashMap<String, (usize, usize)>>> = static ref WORKSPACE_RULES: Arc<Mutex<HashMap<String, (usize, usize)>>> =
Arc::new(Mutex::new(HashMap::new())); Arc::new(Mutex::new(HashMap::new()));
static ref MANAGE_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![])); static ref MANAGE_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
static ref FLOAT_IDENTIFIERS: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(vec![]));
} }
fn setup() -> Result<(WorkerGuard, WorkerGuard)> { fn setup() -> Result<(WorkerGuard, WorkerGuard)> {
+11 -40
View File
@@ -16,9 +16,7 @@ use komorebi_core::SocketMessage;
use crate::window_manager; use crate::window_manager;
use crate::window_manager::WindowManager; use crate::window_manager::WindowManager;
use crate::windows_api::WindowsApi; use crate::windows_api::WindowsApi;
use crate::FLOAT_CLASSES; use crate::FLOAT_IDENTIFIERS;
use crate::FLOAT_EXES;
use crate::FLOAT_TITLES;
use crate::MANAGE_IDENTIFIERS; use crate::MANAGE_IDENTIFIERS;
use crate::TRAY_AND_MULTI_WINDOW_CLASSES; use crate::TRAY_AND_MULTI_WINDOW_CLASSES;
use crate::TRAY_AND_MULTI_WINDOW_EXES; use crate::TRAY_AND_MULTI_WINDOW_EXES;
@@ -52,18 +50,7 @@ pub fn listen_for_commands(wm: Arc<Mutex<WindowManager>>) {
impl WindowManager { impl WindowManager {
#[tracing::instrument(skip(self))] #[tracing::instrument(skip(self))]
pub fn process_command(&mut self, message: SocketMessage) -> Result<()> { pub fn process_command(&mut self, message: SocketMessage) -> Result<()> {
let virtual_desktop_id = winvd::helpers::get_current_desktop_number().ok(); self.validate_virtual_desktop_id();
if let (Some(id), Some(virtual_desktop_id)) = (virtual_desktop_id, self.virtual_desktop_id)
{
if id != virtual_desktop_id {
tracing::warn!(
"ignoring events while not on virtual desktop {:?}",
virtual_desktop_id
);
return Ok(());
}
}
match message { match message {
SocketMessage::Promote => self.promote_container_to_front()?, SocketMessage::Promote => self.promote_container_to_front()?,
@@ -87,24 +74,6 @@ impl WindowManager {
SocketMessage::WorkspacePadding(monitor_idx, workspace_idx, size) => { SocketMessage::WorkspacePadding(monitor_idx, workspace_idx, size) => {
self.set_workspace_padding(monitor_idx, workspace_idx, size)?; self.set_workspace_padding(monitor_idx, workspace_idx, size)?;
} }
SocketMessage::FloatClass(target) => {
let mut float_classes = FLOAT_CLASSES.lock();
if !float_classes.contains(&target) {
float_classes.push(target);
}
}
SocketMessage::FloatExe(target) => {
let mut float_exes = FLOAT_EXES.lock();
if !float_exes.contains(&target) {
float_exes.push(target);
}
}
SocketMessage::FloatTitle(target) => {
let mut float_titles = FLOAT_TITLES.lock();
if !float_titles.contains(&target) {
float_titles.push(target);
}
}
SocketMessage::WorkspaceRule(identifier, id, monitor_idx, workspace_idx) => { SocketMessage::WorkspaceRule(identifier, id, monitor_idx, workspace_idx) => {
match identifier { match identifier {
ApplicationIdentifier::Exe | ApplicationIdentifier::Class => { ApplicationIdentifier::Exe | ApplicationIdentifier::Class => {
@@ -120,17 +89,19 @@ impl WindowManager {
} }
SocketMessage::ManageRule(identifier, id) => match identifier { SocketMessage::ManageRule(identifier, id) => match identifier {
ApplicationIdentifier::Exe | ApplicationIdentifier::Class => { ApplicationIdentifier::Exe | ApplicationIdentifier::Class => {
{ let mut manage_identifiers = MANAGE_IDENTIFIERS.lock();
let mut manage_identifiers = MANAGE_IDENTIFIERS.lock(); if !manage_identifiers.contains(&id) {
if !manage_identifiers.contains(&id) { manage_identifiers.push(id);
manage_identifiers.push(id);
}
} }
self.update_focused_workspace(false)?;
} }
ApplicationIdentifier::Title => {} ApplicationIdentifier::Title => {}
}, },
SocketMessage::FloatRule(_, id) => {
let mut float_identifiers = FLOAT_IDENTIFIERS.lock();
if !float_identifiers.contains(&id) {
float_identifiers.push(id);
}
}
SocketMessage::AdjustContainerPadding(sizing, adjustment) => { SocketMessage::AdjustContainerPadding(sizing, adjustment) => {
self.adjust_container_padding(sizing, adjustment)?; self.adjust_container_padding(sizing, adjustment)?;
} }
+1 -12
View File
@@ -48,18 +48,7 @@ impl WindowManager {
return Ok(()); return Ok(());
} }
let virtual_desktop_id = winvd::helpers::get_current_desktop_number().ok(); self.validate_virtual_desktop_id();
if let (Some(id), Some(virtual_desktop_id)) = (virtual_desktop_id, self.virtual_desktop_id)
{
if id != virtual_desktop_id {
tracing::warn!(
"ignoring events while not on virtual desktop {:?}",
virtual_desktop_id
);
return Ok(());
}
}
// Make sure we have the most recently focused monitor from any event // Make sure we have the most recently focused monitor from any event
match event { match event {
+22 -29
View File
@@ -15,9 +15,7 @@ use crate::styles::GwlExStyle;
use crate::styles::GwlStyle; use crate::styles::GwlStyle;
use crate::window_manager_event::WindowManagerEvent; use crate::window_manager_event::WindowManagerEvent;
use crate::windows_api::WindowsApi; use crate::windows_api::WindowsApi;
use crate::FLOAT_CLASSES; use crate::FLOAT_IDENTIFIERS;
use crate::FLOAT_EXES;
use crate::FLOAT_TITLES;
use crate::HIDDEN_HWNDS; use crate::HIDDEN_HWNDS;
use crate::LAYERED_EXE_WHITELIST; use crate::LAYERED_EXE_WHITELIST;
use crate::MANAGE_IDENTIFIERS; use crate::MANAGE_IDENTIFIERS;
@@ -220,10 +218,6 @@ impl Window {
#[tracing::instrument(fields(exe, title))] #[tracing::instrument(fields(exe, title))]
pub fn should_manage(self, event: Option<WindowManagerEvent>) -> Result<bool> { pub fn should_manage(self, event: Option<WindowManagerEvent>) -> Result<bool> {
let float_classes = FLOAT_CLASSES.lock();
let float_exes = FLOAT_EXES.lock();
let float_titles = FLOAT_TITLES.lock();
if self.title().is_err() { if self.title().is_err() {
return Ok(false); return Ok(false);
} }
@@ -241,21 +235,24 @@ impl Window {
// If not allowing cloaked windows, we need to ensure the window is not cloaked // If not allowing cloaked windows, we need to ensure the window is not cloaked
(false, false) => { (false, false) => {
if let (Ok(title), Ok(exe_name), Ok(class)) = (self.title(), self.exe(), self.class()) { if let (Ok(title), Ok(exe_name), Ok(class)) = (self.title(), self.exe(), self.class()) {
if float_titles.contains(&title) { {
return Ok(false); let float_identifiers = FLOAT_IDENTIFIERS.lock();
} if float_identifiers.contains(&title)
|| float_identifiers.contains(&exe_name)
if float_exes.contains(&exe_name) { || float_identifiers.contains(&class) {
return Ok(false);
}
if let Ok(class) = self.class() {
if float_classes.contains(&class) {
return Ok(false); return Ok(false);
} }
} }
let allow_layered = LAYERED_EXE_WHITELIST.lock().contains(&exe_name); let managed_override = {
let manage_identifiers = MANAGE_IDENTIFIERS.lock();
manage_identifiers.contains(&exe_name) || manage_identifiers.contains(&class)
};
let allow_layered = {
let layered_exe_whitelist = LAYERED_EXE_WHITELIST.lock();
layered_exe_whitelist.contains(&exe_name)
};
let style = self.style()?; let style = self.style()?;
let ex_style = self.ex_style()?; let ex_style = self.ex_style()?;
@@ -268,21 +265,17 @@ impl Window {
// allowing a specific layered window on the whitelist (like Steam), it should // allowing a specific layered window on the whitelist (like Steam), it should
// pass this check // pass this check
&& (allow_layered || !ex_style.contains(GwlExStyle::LAYERED)) && (allow_layered || !ex_style.contains(GwlExStyle::LAYERED))
|| MANAGE_IDENTIFIERS.lock().contains(&exe_name) || MANAGE_IDENTIFIERS.lock().contains(&class) || managed_override
{ {
Ok(true) return Ok(true)
} else { } else if event.is_some() {
if event.is_some() { tracing::debug!("ignoring (exe: {}, title: {})", exe_name, title);
tracing::debug!("ignoring (exe: {}, title: {})", exe_name, title);
}
Ok(false)
} }
} else {
Ok(false)
} }
} }
_ => Ok(false), _ => {}
} }
Ok(false)
} }
} }
+20 -9
View File
@@ -30,10 +30,9 @@ use crate::window_manager_event::WindowManagerEvent;
use crate::windows_api::WindowsApi; use crate::windows_api::WindowsApi;
use crate::winevent_listener::WINEVENT_CALLBACK_CHANNEL; use crate::winevent_listener::WINEVENT_CALLBACK_CHANNEL;
use crate::workspace::Workspace; use crate::workspace::Workspace;
use crate::FLOAT_CLASSES; use crate::FLOAT_IDENTIFIERS;
use crate::FLOAT_EXES;
use crate::FLOAT_TITLES;
use crate::LAYERED_EXE_WHITELIST; use crate::LAYERED_EXE_WHITELIST;
use crate::MANAGE_IDENTIFIERS;
use crate::TRAY_AND_MULTI_WINDOW_CLASSES; use crate::TRAY_AND_MULTI_WINDOW_CLASSES;
use crate::TRAY_AND_MULTI_WINDOW_EXES; use crate::TRAY_AND_MULTI_WINDOW_EXES;
use crate::WORKSPACE_RULES; use crate::WORKSPACE_RULES;
@@ -52,9 +51,8 @@ pub struct WindowManager {
pub struct State { pub struct State {
pub monitors: Ring<Monitor>, pub monitors: Ring<Monitor>,
pub is_paused: bool, pub is_paused: bool,
pub float_classes: Vec<String>, pub float_identifiers: Vec<String>,
pub float_exes: Vec<String>, pub manage_identifiers: Vec<String>,
pub float_titles: Vec<String>,
pub layered_exe_whitelist: Vec<String>, pub layered_exe_whitelist: Vec<String>,
pub tray_and_multi_window_exes: Vec<String>, pub tray_and_multi_window_exes: Vec<String>,
pub tray_and_multi_window_classes: Vec<String>, pub tray_and_multi_window_classes: Vec<String>,
@@ -66,9 +64,8 @@ impl From<&mut WindowManager> for State {
Self { Self {
monitors: wm.monitors.clone(), monitors: wm.monitors.clone(),
is_paused: wm.is_paused, is_paused: wm.is_paused,
float_classes: FLOAT_CLASSES.lock().clone(), float_identifiers: FLOAT_IDENTIFIERS.lock().clone(),
float_exes: FLOAT_EXES.lock().clone(), manage_identifiers: MANAGE_IDENTIFIERS.lock().clone(),
float_titles: FLOAT_TITLES.lock().clone(),
layered_exe_whitelist: LAYERED_EXE_WHITELIST.lock().clone(), layered_exe_whitelist: LAYERED_EXE_WHITELIST.lock().clone(),
tray_and_multi_window_exes: TRAY_AND_MULTI_WINDOW_EXES.lock().clone(), tray_and_multi_window_exes: TRAY_AND_MULTI_WINDOW_EXES.lock().clone(),
tray_and_multi_window_classes: TRAY_AND_MULTI_WINDOW_CLASSES.lock().clone(), tray_and_multi_window_classes: TRAY_AND_MULTI_WINDOW_CLASSES.lock().clone(),
@@ -334,6 +331,20 @@ impl WindowManager {
Ok(()) Ok(())
} }
#[tracing::instrument(skip(self))]
pub fn validate_virtual_desktop_id(&self) {
let virtual_desktop_id = winvd::helpers::get_current_desktop_number().ok();
if let (Some(id), Some(virtual_desktop_id)) = (virtual_desktop_id, self.virtual_desktop_id)
{
if id != virtual_desktop_id {
tracing::warn!(
"ignoring events while not on virtual desktop {}",
virtual_desktop_id
);
}
}
}
#[tracing::instrument(skip(self))] #[tracing::instrument(skip(self))]
pub fn manage_focused_window(&mut self) -> Result<()> { pub fn manage_focused_window(&mut self) -> Result<()> {
let hwnd = WindowsApi::foreground_window()?; let hwnd = WindowsApi::foreground_window()?;
+3 -11
View File
@@ -424,17 +424,9 @@ fn main() -> Result<()> {
SubCommand::Stop => { SubCommand::Stop => {
send_message(&*SocketMessage::Stop.as_bytes()?)?; send_message(&*SocketMessage::Stop.as_bytes()?)?;
} }
SubCommand::FloatRule(arg) => match arg.identifier { SubCommand::FloatRule(arg) => {
ApplicationIdentifier::Exe => { send_message(&*SocketMessage::FloatRule(arg.identifier, arg.id).as_bytes()?)?;
send_message(&*SocketMessage::FloatExe(arg.id).as_bytes()?)?; }
}
ApplicationIdentifier::Class => {
send_message(&*SocketMessage::FloatClass(arg.id).as_bytes()?)?;
}
ApplicationIdentifier::Title => {
send_message(&*SocketMessage::FloatTitle(arg.id).as_bytes()?)?;
}
},
SubCommand::ManageRule(arg) => { SubCommand::ManageRule(arg) => {
send_message(&*SocketMessage::ManageRule(arg.identifier, arg.id).as_bytes()?)?; send_message(&*SocketMessage::ManageRule(arg.identifier, arg.id).as_bytes()?)?;
} }