From 2bceff4edcfdb71f042373076e3906f518cee9e2 Mon Sep 17 00:00:00 2001 From: eythaann Date: Wed, 28 Feb 2024 06:25:51 -0500 Subject: [PATCH] feat(wm): add path variant to application identifiers This commit add a new way to match applications through its paths, allowing to match a bunch of applications that share a parent folder. --- komorebi-core/src/config_generation.rs | 2 +- komorebi-core/src/lib.rs | 2 ++ komorebi/src/process_command.rs | 5 +++ komorebi/src/process_event.rs | 2 ++ komorebi/src/window.rs | 49 ++++++++++++++++++++++++-- komorebi/src/window_manager_event.rs | 2 ++ schema.asc.json | 3 +- schema.json | 7 ++++ 8 files changed, 68 insertions(+), 4 deletions(-) diff --git a/komorebi-core/src/config_generation.rs b/komorebi-core/src/config_generation.rs index 13a6870a..0525c44d 100644 --- a/komorebi-core/src/config_generation.rs +++ b/komorebi-core/src/config_generation.rs @@ -102,7 +102,7 @@ impl ApplicationConfiguration { pub fn populate_default_matching_strategies(&mut self) { if self.identifier.matching_strategy.is_none() { match self.identifier.kind { - ApplicationIdentifier::Exe => { + ApplicationIdentifier::Exe | ApplicationIdentifier::Path => { self.identifier.matching_strategy = Option::from(MatchingStrategy::Equals); } ApplicationIdentifier::Class | ApplicationIdentifier::Title => {} diff --git a/komorebi-core/src/lib.rs b/komorebi-core/src/lib.rs index bdacce9f..3e6112b4 100644 --- a/komorebi-core/src/lib.rs +++ b/komorebi-core/src/lib.rs @@ -223,6 +223,8 @@ pub enum ApplicationIdentifier { Class, #[serde(alias = "title")] Title, + #[serde(alias = "path")] + Path, } #[derive( diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index 172f1e41..09f85696 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -315,6 +315,11 @@ impl WindowManager { { for window in container.windows() { match identifier { + ApplicationIdentifier::Path => { + if window.path()? == *id { + hwnds_to_purge.push((i, window.hwnd)); + } + } ApplicationIdentifier::Exe => { if window.exe()? == *id { hwnds_to_purge.push((i, window.hwnd)); diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index 776e057a..a5cb6f96 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -185,6 +185,7 @@ impl WindowManager { let title = &window.title()?; let exe_name = &window.exe()?; let class = &window.class()?; + let path = &window.path()?; // We don't want to purge windows that have been deliberately hidden by us, eg. when // they are not on the top of a container stack. @@ -193,6 +194,7 @@ impl WindowManager { title, exe_name, class, + path, &tray_and_multi_window_identifiers, ®ex_identifiers, ); diff --git a/komorebi/src/window.rs b/komorebi/src/window.rs index e0b61036..6f4d3809 100644 --- a/komorebi/src/window.rs +++ b/komorebi/src/window.rs @@ -377,6 +377,14 @@ impl Window { WindowsApi::window_text_w(self.hwnd()) } + pub fn path(self) -> Result { + let (process_id, _) = WindowsApi::window_thread_process_id(self.hwnd()); + let handle = WindowsApi::process_handle(process_id)?; + let path = WindowsApi::exe_path(handle); + WindowsApi::close_process(handle)?; + path + } + pub fn exe(self) -> Result { let (process_id, _) = WindowsApi::window_thread_process_id(self.hwnd()); let handle = WindowsApi::process_handle(process_id)?; @@ -440,8 +448,8 @@ impl Window { (true, _) | // 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()) { - return Ok(window_is_eligible(&title, &exe_name, &class, &self.style()?, &self.ex_style()?, event)); + if let (Ok(title), Ok(exe_name), Ok(class), Ok(path)) = (self.title(), self.exe(), self.class(), self.path()) { + return Ok(window_is_eligible(&title, &exe_name, &class, &path, &self.style()?, &self.ex_style()?, event)); } } _ => {} @@ -455,6 +463,7 @@ fn window_is_eligible( title: &String, exe_name: &String, class: &String, + path: &String, style: &WindowStyle, ex_style: &ExtendedWindowStyle, event: Option, @@ -473,6 +482,7 @@ fn window_is_eligible( title, exe_name, class, + path, &float_identifiers, ®ex_identifiers, ); @@ -482,6 +492,7 @@ fn window_is_eligible( title, exe_name, class, + path, &manage_identifiers, ®ex_identifiers, ); @@ -495,6 +506,7 @@ fn window_is_eligible( title, exe_name, class, + path, &layered_whitelist, ®ex_identifiers, ); @@ -534,6 +546,7 @@ pub fn should_act( title: &str, exe_name: &str, class: &str, + path: &str, identifiers: &[IdWithIdentifier], regex_identifiers: &HashMap, ) -> bool { @@ -559,6 +572,11 @@ pub fn should_act( should_act = true; } } + ApplicationIdentifier::Path => { + if path.eq(&identifier.id) { + should_act = true; + } + } }, Some(MatchingStrategy::Equals) => match identifier.kind { ApplicationIdentifier::Title => { @@ -576,6 +594,11 @@ pub fn should_act( should_act = true; } } + ApplicationIdentifier::Path => { + if path.eq(&identifier.id) { + should_act = true; + } + } }, Some(MatchingStrategy::StartsWith) => match identifier.kind { ApplicationIdentifier::Title => { @@ -593,6 +616,11 @@ pub fn should_act( should_act = true; } } + ApplicationIdentifier::Path => { + if path.starts_with(&identifier.id) { + should_act = true; + } + } }, Some(MatchingStrategy::EndsWith) => match identifier.kind { ApplicationIdentifier::Title => { @@ -610,6 +638,11 @@ pub fn should_act( should_act = true; } } + ApplicationIdentifier::Path => { + if path.ends_with(&identifier.id) { + should_act = true; + } + } }, Some(MatchingStrategy::Contains) => match identifier.kind { ApplicationIdentifier::Title => { @@ -627,6 +660,11 @@ pub fn should_act( should_act = true; } } + ApplicationIdentifier::Path => { + if path.contains(&identifier.id) { + should_act = true; + } + } }, Some(MatchingStrategy::Regex) => match identifier.kind { ApplicationIdentifier::Title => { @@ -650,6 +688,13 @@ pub fn should_act( } } } + ApplicationIdentifier::Path => { + if let Some(re) = regex_identifiers.get(&identifier.id) { + if re.is_match(path) { + should_act = true; + } + } + } }, } } diff --git a/komorebi/src/window_manager_event.rs b/komorebi/src/window_manager_event.rs index 215ff3d8..13da588d 100644 --- a/komorebi/src/window_manager_event.rs +++ b/komorebi/src/window_manager_event.rs @@ -139,11 +139,13 @@ impl WindowManagerEvent { let title = &window.title().ok()?; let exe_name = &window.exe().ok()?; let class = &window.class().ok()?; + let path = &window.path().ok()?; let should_trigger = should_act( title, exe_name, class, + path, &object_name_change_on_launch, ®ex_identifiers, ); diff --git a/schema.asc.json b/schema.asc.json index f3bf75f0..8a2e4fa2 100644 --- a/schema.asc.json +++ b/schema.asc.json @@ -44,7 +44,8 @@ "enum": [ "Exe", "Class", - "Title" + "Title", + "Path" ] }, "ApplicationOptions": { diff --git a/schema.json b/schema.json index 3884b552..54b492e5 100644 --- a/schema.json +++ b/schema.json @@ -163,6 +163,7 @@ "kind": { "type": "string", "enum": [ + "Path", "Exe", "Class", "Title" @@ -234,6 +235,7 @@ "kind": { "type": "string", "enum": [ + "Path", "Exe", "Class", "Title" @@ -352,6 +354,7 @@ "kind": { "type": "string", "enum": [ + "Path", "Exe", "Class", "Title" @@ -387,6 +390,7 @@ "kind": { "type": "string", "enum": [ + "Path", "Exe", "Class", "Title" @@ -523,6 +527,7 @@ "kind": { "type": "string", "enum": [ + "Path", "Exe", "Class", "Title" @@ -594,6 +599,7 @@ "kind": { "type": "string", "enum": [ + "Path", "Exe", "Class", "Title" @@ -639,6 +645,7 @@ "kind": { "type": "string", "enum": [ + "Path", "Exe", "Class", "Title"