From ba22e8dc5a3067df56ad8f69e16fc3723ad20a53 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Sat, 31 Oct 2026 10:10:53 -0700 Subject: [PATCH] refactor(mac): turn a system-handed element into a window id in one place Step 11(ii), fourth part. The seven sites that derive a CGWindowID from an element that the system handed over (event tap, observer callbacks, the focused window of an app, the tab check) call ax_registry::identify instead of AccessibilityApi::window_id: input_event_listener.rs, process_command.rs, process_event.rs (5), window_manager.rs. It is the same call; the point is that an element becomes an id only here, which is the key the registry is filled under. Not behaviour: nothing changes at runtime. Verified: macOS fake-CC type-check (tools/fast-check) PASS. Not verified: cannot run on Linux. --- komorebi-for-mac/komorebi/src/ax_registry.rs | 10 ++++++++++ komorebi-for-mac/komorebi/src/input_event_listener.rs | 3 +-- komorebi-for-mac/komorebi/src/process_command.rs | 3 +-- komorebi-for-mac/komorebi/src/process_event.rs | 9 ++++----- komorebi-for-mac/komorebi/src/window_manager.rs | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/komorebi-for-mac/komorebi/src/ax_registry.rs b/komorebi-for-mac/komorebi/src/ax_registry.rs index b72a13eb..a3159dac 100644 --- a/komorebi-for-mac/komorebi/src/ax_registry.rs +++ b/komorebi-for-mac/komorebi/src/ax_registry.rs @@ -102,3 +102,13 @@ pub fn windows() -> Vec { .filter_map(|(id, entry)| Some(Window::from_entry(id.to_u32()?, entry))) .collect() } + +/// The `CGWindowID` of the window that an Accessibility element is, as handed over by the system +/// (an observer callback, the event tap, the focused window of an application). This is the one +/// way to turn an element into the key of the table; a window is registered under what it +/// returns. +pub fn identify( + element: &objc2_application_services::AXUIElement, +) -> std::result::Result { + crate::accessibility::AccessibilityApi::window_id(element) +} diff --git a/komorebi-for-mac/komorebi/src/input_event_listener.rs b/komorebi-for-mac/komorebi/src/input_event_listener.rs index f6154849..f2031c64 100644 --- a/komorebi-for-mac/komorebi/src/input_event_listener.rs +++ b/komorebi-for-mac/komorebi/src/input_event_listener.rs @@ -1,4 +1,3 @@ -use crate::accessibility::AccessibilityApi; use crate::macos_api::MacosApi; use crate::reaper; use crate::reaper::ReaperNotification; @@ -93,7 +92,7 @@ extern "C-unwind" fn callback( } if pid != 0 { - let window_id = AccessibilityApi::window_id(&element).ok(); + let window_id = crate::ax_registry::identify(&element).ok(); // Send MoveEnd to handle pending drag-to-swap operations // macOS doesn't reliably fire AXWindowMoved after mouse release diff --git a/komorebi-for-mac/komorebi/src/process_command.rs b/komorebi-for-mac/komorebi/src/process_command.rs index 686be380..f32d3680 100644 --- a/komorebi-for-mac/komorebi/src/process_command.rs +++ b/komorebi-for-mac/komorebi/src/process_command.rs @@ -9,7 +9,6 @@ use crate::SESSION_FLOATING_APPLICATIONS; use crate::SUBSCRIPTION_SOCKET_OPTIONS; use crate::SUBSCRIPTION_SOCKETS; use crate::WORKSPACE_MATCHING_RULES; -use crate::accessibility::AccessibilityApi; use crate::animation; use crate::animation::ANIMATION_DURATION_GLOBAL; use crate::animation::ANIMATION_DURATION_PER_ANIMATION; @@ -1718,7 +1717,7 @@ impl WindowManager { let application = Application::new(raw_info.owner_pid)?; if let Some(elements) = application.window_elements() { for element in elements { - if let Ok(wid) = AccessibilityApi::window_id(&element) + if let Ok(wid) = crate::ax_registry::identify(&element) && i64::from(wid) == window_id && let Ok(window) = Window::new(element, application.clone()) { diff --git a/komorebi-for-mac/komorebi/src/process_event.rs b/komorebi-for-mac/komorebi/src/process_event.rs index 47f25fb4..0a03bcd5 100644 --- a/komorebi-for-mac/komorebi/src/process_event.rs +++ b/komorebi-for-mac/komorebi/src/process_event.rs @@ -6,7 +6,6 @@ use crate::REGEX_IDENTIFIERS; use crate::TABBED_APPLICATIONS; use crate::UNMANAGED_WINDOW_IDS; use crate::WORKSPACE_MATCHING_RULES; -use crate::accessibility::AccessibilityApi; use crate::accessibility::enhanced_ui; use crate::accessibility::error::AccessibilityApiError; use crate::accessibility::error::AccessibilityError; @@ -182,7 +181,7 @@ impl WindowManager { { let application = self.application(event.process_id())?; if let Some(element) = application.main_window() - && let Ok(wid) = AccessibilityApi::window_id(&element) + && let Ok(wid) = crate::ax_registry::identify(&element) { window_id = Some(wid); window_element = Some(AccessibilityUiElement(element.clone())); @@ -296,7 +295,7 @@ impl WindowManager { // Additional check: verify the stored element belongs to this container // This prevents treating separate windows as tabs when they have matching geometry if let Ok(stored_window_id) = - AccessibilityApi::window_id(&window.element.0) + crate::ax_registry::identify(&window.element.0) && stored_window_id == window.id { // All checks pass: stored element matches container ID = true tab change @@ -538,7 +537,7 @@ impl WindowManager { { let application = self.application(process_id)?; if let Some(element) = application.main_window() - && let Ok(wid) = AccessibilityApi::window_id(&element) + && let Ok(wid) = crate::ax_registry::identify(&element) { window_id = Some(wid); window_element = Some(element.clone()); @@ -552,7 +551,7 @@ impl WindowManager { let tabbed_applications = TABBED_APPLICATIONS.lock(); if tabbed_applications.contains(&application_name) { // Get the window_id for the new window - if let Ok(new_window_id) = AccessibilityApi::window_id(element) { + if let Ok(new_window_id) = crate::ax_registry::identify(element) { for window in workspace.visible_windows().iter().flatten() { if window.application.name().unwrap_or_default() == application_name { diff --git a/komorebi-for-mac/komorebi/src/window_manager.rs b/komorebi-for-mac/komorebi/src/window_manager.rs index 5c2e8b4b..e3c29fe8 100644 --- a/komorebi-for-mac/komorebi/src/window_manager.rs +++ b/komorebi-for-mac/komorebi/src/window_manager.rs @@ -1180,7 +1180,7 @@ impl WindowManager { let mut valid_window_ids = vec![]; if let Some(elements) = application.window_elements() { for element in elements { - if let Ok(window_id) = AccessibilityApi::window_id(&element) { + if let Ok(window_id) = crate::ax_registry::identify(&element) { valid_window_ids.push(window_id); } }