diff --git a/docs/dev/macos-handcheck.md b/docs/dev/macos-handcheck.md index 9a7e35bd..79edbcbe 100644 --- a/docs/dev/macos-handcheck.md +++ b/docs/dev/macos-handcheck.md @@ -100,6 +100,7 @@ timeout. Until then H5 documents the hang. | deep dedup 1: `refactor(mac): the daemon uses the shared Container API with the hide spot` (see `jj log -r wip-u-mac-deep`) | `ContainerExt` (`add_window_at`, `load_focused_window_at`, `hide_on`, `restore_focused_window`) is gone: every call is the shared `Container::{add_window, load_focused_window, hide, restore}` with `workspace.hide_spot()`. `monocle_on` and `cycle_monocle` took the corner from the monitor (`monitor.extra`) and now take it from the workspace (`workspace.state`), which the monitor writes with the globals; `restore()` now skips the Accessibility call under `cfg!(test)`. | `cargo test`; then H1 (hide spot) and: toggle monocle on a workspace with two containers on a monitor with `window_hiding_position: BottomRight` (every other container parks in that corner), cycle the monocle container, stack with `komorebic stack`/`stack-all`, `cycle-stack`, `add-window-to-container`, switch workspaces. Change the monitor's `window_hiding_position` in the config, reload, and toggle monocle at once: the corner must be the new one. | | deep dedup 2: `refactor(mac): five router arms are methods with the KDE names` | `ToggleWorkspaceLayer`, `ResizeWindowAxis`, `SessionFloatRule`, `IgnoreRule` and `ReplaceConfiguration` call `toggle_workspace_layer`, `resize_window_axis`, `add_session_float_rule`, `add_ignore_rule(identifier, id: &str)` and `replace_configuration(&PathBuf)`, with the bodies the arms had (a pure move; the router arms are now the KDE text). `id` of the ignore rule is a `&str`, compared with `==`. | `cargo test`; by hand: `komorebic toggle-workspace-layer` twice (tiling to floating and back: a window of the layer is focused, the others hide at the corner and come back), `resize-axis horizontal|vertical increase|decrease`, `komorebic session-float-rule` on a window, `komorebic ignore-rule exe ` and `ignore-rule title/class` (the matching windows leave the workspaces), `komorebic replace-configuration ` (the daemon restarts its windows under the new config; with a broken file it is left alone). | | wm2 1: `refactor(mac): ignore and manage rules go through the shared push_simple_rule` | `ignore-rule` and `manage-rule` add a rule unless a simple rule of the same kind and id exists. The macOS code checked only the id, so `ignore-rule class foo` after `ignore-rule exe foo` was silently dropped; it is added now (this is the KDE behaviour, which a KDE test pins). | `komorebic ignore-rule exe Notes`, then `ignore-rule title Notes`: both rules are in `komorebic state` ... `ignore_identifiers` (before, the second was not). Running the same command twice adds one rule. `manage-rule` the same. | +| wm2 2: `refactor(mac): Minimize, Close and DebugWindow are methods` | The arms call `minimize_foreground_window`, `close_foreground_window` and `debug_window(window_id, reply)` with the bodies they had. | `komorebic minimize` and `komorebic close` on the focused window of another app (the window minimizes / closes; with no foreground window an error is logged), `komorebic debug-window ` for a real window id (the rule debug JSON is printed) and for an id that does not exist (nothing printed, no error). | Revisions in section B change no behaviour on purpose (rename, move, route); they still need the sections C walk-through, because a mechanical mistake would show there. diff --git a/komorebi-for-mac/komorebi/src/process_command.rs b/komorebi-for-mac/komorebi/src/process_command.rs index e775bb44..65bcade6 100644 --- a/komorebi-for-mac/komorebi/src/process_command.rs +++ b/komorebi-for-mac/komorebi/src/process_command.rs @@ -524,16 +524,8 @@ impl WindowManager { let _suspended_animations = animation::suspend(); self.focus_container_window(idx)?; } - SocketMessage::Minimize => { - let foreground_window = - MacosApi::foreground_window().ok_or_eyre("there is no foreground window")?; - AdhocWindow::minimize(&foreground_window)?; - } - SocketMessage::Close => { - let foreground_window = - MacosApi::foreground_window().ok_or_eyre("there is no foreground window")?; - AdhocWindow::close(&foreground_window)?; - } + SocketMessage::Minimize => self.minimize_foreground_window()?, + SocketMessage::Close => self.close_foreground_window()?, SocketMessage::ManageFocusedWindow => { self.manage_focused_window()?; } @@ -1217,28 +1209,7 @@ impl WindowManager { workspace.resize_dimensions = resize; self.update_focused_workspace(false, false)?; } - SocketMessage::DebugWindow(window_id) => { - if let Some(window_list_info) = CoreGraphicsApi::window_list_info() { - for raw_window_info in cf_array_as::(&window_list_info) { - let raw_info = WindowInfo::new(raw_window_info); - let application = Application::new(raw_info.owner_pid)?; - if let Some(elements) = application.window_elements() { - for element in elements { - if let Ok(wid) = crate::ax_registry::identify(&element) - && i64::from(wid) == window_id - && let Ok(window) = Window::new(element, application.clone()) - { - let mut rule_debug = RuleDebug::default(); - let _ = window.should_manage(None, &mut rule_debug); - let schema = serde_json::to_string_pretty(&rule_debug)?; - - reply.write_all(schema.as_bytes())?; - } - } - } - } - } - } + SocketMessage::DebugWindow(window_id) => self.debug_window(window_id, &mut reply)?, SocketMessage::DisplayIndexPreference(index_preference, ref display) => { crate::settings::settings().update(|settings| { settings @@ -1663,6 +1634,53 @@ impl WindowManager { } } +impl WindowManager { + /// Minimizes the window that has the focus + pub fn minimize_foreground_window(&mut self) -> eyre::Result<()> { + let foreground_window = + MacosApi::foreground_window().ok_or_eyre("there is no foreground window")?; + AdhocWindow::minimize(&foreground_window)?; + Ok(()) + } + + /// Closes the window that has the focus + pub fn close_foreground_window(&mut self) -> eyre::Result<()> { + let foreground_window = + MacosApi::foreground_window().ok_or_eyre("there is no foreground window")?; + AdhocWindow::close(&foreground_window)?; + Ok(()) + } + + /// Answers with why the window of this id is, or is not, managed + pub fn debug_window( + &self, + window_id: i64, + reply: &mut impl std::io::Write, + ) -> eyre::Result<()> { + if let Some(window_list_info) = CoreGraphicsApi::window_list_info() { + for raw_window_info in cf_array_as::(&window_list_info) { + let raw_info = WindowInfo::new(raw_window_info); + let application = Application::new(raw_info.owner_pid)?; + if let Some(elements) = application.window_elements() { + for element in elements { + if let Ok(wid) = crate::ax_registry::identify(&element) + && i64::from(wid) == window_id + && let Ok(window) = Window::new(element, application.clone()) + { + let mut rule_debug = RuleDebug::default(); + let _ = window.should_manage(None, &mut rule_debug); + let schema = serde_json::to_string_pretty(&rule_debug)?; + + reply.write_all(schema.as_bytes())?; + } + } + } + } + } + Ok(()) + } +} + /// The window manager as the shared commands of `komorebi_core::command` see it impl komorebi_core::CommandHost for WindowManager { type P = crate::workspace::MacosPlatform;