Skip to content

Log frontmost macOS app name and bundle id for anchoring diagnostics#126

Merged
maraf merged 2 commits into
mainfrom
maraf/redesigned-journey
Apr 22, 2026
Merged

Log frontmost macOS app name and bundle id for anchoring diagnostics#126
maraf merged 2 commits into
mainfrom
maraf/redesigned-journey

Conversation

@maraf

@maraf maraf commented Apr 22, 2026

Copy link
Copy Markdown
Member

When the snippet window fails to anchor to the focused text field on macOS, diagnostics.log only recorded the frontmost application's PID. By the time I went to triage the log later, those PIDs were long gone, so it was impossible to tell which apps were breaking anchoring (the current log has five PIDs that always fail and a Chromium-ish PID that intermittently produces degenerate (0,982,1,1) caret bounds, but none of them are identifiable).

This PR threads the frontmost app's localized name and bundle identifier through the anchoring path so every related log line is attributable to a specific app.

Approach

  • MacOSApplication.GetFrontmostApplicationProcessId() becomes GetFrontmostApplication() and returns a new FrontmostApplication record (ProcessId, Name, BundleIdentifier). A single osascript call returns pid \t name \t bundle with try blocks around name/bundle identifier so processes that don't expose them still yield a usable PID.
  • Navigator stores the whole record (was just int?) and passes a frontmostAppLabel string into UpdateWindowPositionAnchor and on into MacOSTextAnchor.TryGetForFocusedElement.
  • MacOSTextAnchor appends Frontmost app: pid=..., name='...', bundle='...'. to every Info/Error line in the anchor pipeline: the initial attempt, each AXFocusedUIElement / AXFocusedWindow / AXBoundsForRange failure, the degenerate-bounds rejection, and the final centered-placement fallback. Empty labels produce no suffix, so behavior is unchanged when the PID capture fails.
  • ActivateProcess also accepts an optional name so the "Restoring focus to macOS process ..." line includes it.

Notes for reviewers

  • No functional behavior changes for positioning or focus restoration, only logging.
  • The AppleScript uses tab as a separator and empty strings for unavailable fields; confirmed on macOS the output is e.g. 94697\tgithub\tcom.copilot.tauri\n.
  • Existing SelectedTextBoundsPlausibilityTests still pass (110/110). MacOSTextAnchor.TryGetForFocusedElement gained an optional parameter with a default, so callers outside the Avalonia project are unaffected.

Capture the frontmost application's localized name and bundle identifier
alongside the PID via a single AppleScript call, and include that label
in snippet-window anchoring log messages. This makes it possible to
attribute anchoring failures (e.g. AXFocusedUIElement unavailable) to a
specific app when reviewing diagnostics.log.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves macOS anchoring diagnostics by threading the frontmost application’s identifying information (PID, localized name, bundle identifier) through the caret/focused-element anchoring flow so log lines can be attributed to a specific app during later triage.

Changes:

  • Replace PID-only capture with a FrontmostApplication record (pid/name/bundle) resolved via a single AppleScript call.
  • Pass a “frontmost app” label through Navigator into MacOSTextAnchor and append it to key Info/Error log lines.
  • Extend ActivateProcess to optionally include the app name in activation logging.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/Neptuo.Productivity.SnippetManager.Avalonia/Navigator.cs Captures/stores the full frontmost-app record, passes a derived label into anchoring, and logs app info when restoring focus.
src/Neptuo.Productivity.SnippetManager.Avalonia/MacOSTextAnchor.cs Adds an optional context suffix to anchoring pipeline log lines for better attribution.
src/Neptuo.Productivity.SnippetManager.Avalonia/MacOSApplication.cs Introduces FrontmostApplication, updates frontmost-app resolution to return pid/name/bundle, and extends activation logging.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Neptuo.Productivity.SnippetManager.Avalonia/MacOSApplication.cs
Comment thread src/Neptuo.Productivity.SnippetManager.Avalonia/Navigator.cs Outdated
Comment thread src/Neptuo.Productivity.SnippetManager.Avalonia/MacOSApplication.cs Outdated
Address review feedback on PR #126:

- Quote Name/BundleIdentifier with JSON-style escaping in
  FrontmostApplication.DescribeForLog so embedded quotes, tabs, or
  control characters cannot make log lines ambiguous. Missing values
  render as <unknown> (unquoted) to remain distinguishable from an
  empty string.
- Switch the AppleScript delimiter from tab to ASCII Unit Separator
  (character id 31 / 0x1F), which cannot appear in a macOS app name
  or bundle id, and defensively log when fewer than 3 fields are
  returned.
- Compute the 'Frontmost app: ...' suffix once in
  UpdateWindowPositionAnchor instead of duplicating it in each branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@maraf maraf merged commit 65245ea into main Apr 22, 2026
1 check passed
@maraf maraf deleted the maraf/redesigned-journey branch April 22, 2026 10:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants