fix: replace Ghostty AppleScript with Core Graphics + Accessibility API#286
Conversation
Self Code ReviewSummarySolid fix that correctly replaces the broken System Events approach with Core Graphics API for window enumeration and Accessibility API for window manipulation. The implementation follows proven patterns from kild-peek-core and includes proper fallback strategies. FindingsStrengths
Issues Found & Fixed
Checklist
|
PR Review SummaryReviewed by 6 specialized agents: code-reviewer, silent-failure-hunter, type-design-analyzer, pr-test-analyzer, comment-analyzer, docs-impact-agent. Critical Issues (5 found)
Important Issues (5 found)
Suggestions (5 found)
Strengths
Documentation UpdatesNone required. CLAUDE.md architecture section remains accurate — Verdict: NEEDS FIXESThe code quality is high (code-reviewer passed with no issues), but the "No Silent Failures" principle from CLAUDE.md is violated in 3 critical locations. All three will produce "window not found" errors that hide the real problem. Recommended Actions
|
…PI (#269) Ghostty uses GPU rendering which bypasses the native widget tree that macOS System Events relies on, causing focus, hide, and is_window_open to always fail. This replaces the 6 AppleScript-based functions with Core Graphics API (via xcap) for window enumeration and the macOS Accessibility API for window manipulation. Changes: - Add terminal/native/ module with CG enumeration + AX manipulation - Replace focus_by_pid/title, hide_by_pid/title, check_window_by_pid/title with find_ghostty_native_window + native::focus_window/minimize_window - Add NativeWindowError variant to TerminalError - Add xcap, accessibility-sys, core-foundation as macOS-only deps Fixes #269
- Use i32::try_from instead of `as i32` for PID casts from xcap u32 - Guard against empty title_contains in find_window to prevent matching all windows when session ID is somehow empty
…sages - Add warn! logging for empty title guard, PID conversion failures - Add debug! logging for skipped windows in enumeration loops - Improve AX fallback messages to note degraded behavior (app-level activation instead of window-specific, hides all windows not just target) - Add actionable hints to AppleScript error messages (is app running? check automation permissions?) - Include window count in AX window-not-found error - Fix stale focus_by_pid comment reference - Upgrade PID parse failure to warn when output is non-empty - Add semantics comment for open=not-minimized logic - Add doc comments for NativeWindowError and NativeWindowInfo - Add tests: empty title guard, nonexistent app, PID overflow, NativeWindowError variant
6251993 to
8026784
Compare
After the Core Graphics migration (#286), `kild focus` could not restore a window previously minimized via `kild hide` because the AX API focus path only raised the window without unsetting kAXMinimizedAttribute. Changes: - Add UnminimizeAndRaise variant to WindowAction enum - Add ax_unminimize_and_raise_window function mirroring existing pattern - Check is_minimized in focus_window and unminimize before raising - Add test for new WindowAction variant Fixes #289
* Investigate issue #289: Ghostty focus/hide after CG migration Root cause: focus_window doesn't unminimize — AXRaised + activate_app don't undo kAXMinimizedAttribute set by kild hide. Need to add UnminimizeAndRaise action that sets kAXMinimized=false before raising. * fix: unminimize Ghostty window before raising on focus (#289) After the Core Graphics migration (#286), `kild focus` could not restore a window previously minimized via `kild hide` because the AX API focus path only raised the window without unsetting kAXMinimizedAttribute. Changes: - Add UnminimizeAndRaise variant to WindowAction enum - Add ax_unminimize_and_raise_window function mirroring existing pattern - Check is_minimized in focus_window and unminimize before raising - Add test for new WindowAction variant Fixes #289 * fix: add specific unminimize failure logging and exhaustive match test Add dedicated focus_unminimize_failed log event to distinguish unminimize failures from general AX raise failures — helps debug Ghostty AX quirks. Replace array length test with exhaustive match test for WindowAction variants, providing stronger compile-time guarantees.
Summary
focus,hide, andis_window_opento always fail (0 windows reported)terminal/native/module as a clean abstraction layer with fallback strategies when AX API is unavailableChanges
crates/kild-core/Cargo.tomlcrates/kild-core/src/terminal/native/types.rsNativeWindowInfostructcrates/kild-core/src/terminal/native/macos.rscrates/kild-core/src/terminal/native/mod.rscrates/kild-core/src/terminal/mod.rscrates/kild-core/src/terminal/errors.rsNativeWindowErrorvariantcrates/kild-core/src/terminal/backends/ghostty.rswith_ghostty_windowwithfind_ghostty_native_window+ native API callsTest plan
cargo fmt --checkpassescargo clippy --all -- -D warningspassescargo test --allpasses (all 120+ tests)cargo build --allsucceedskild focus <branch>brings Ghostty window to foregroundkild hide <branch>minimizes Ghostty windowkild listshows correct status detectionFixes #269