Repository navigation
Fix get-focused ownership for Sandbox controls without a process ID - #880
Conversation
Verify native ancestor process and explicit root window ownership, preserve query errors, and cover missing/foreign/stale identity cases. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The Sandbox-specific native ownership path still needs live candidate validation and latest-head CI.
Pull request overview
Fixes Sandbox get-focused ownership detection when controls omit process IDs.
Changes:
- Verifies ownership through bounded native-ancestor traversal.
- Propagates query failures and adds regression coverage.
- Documents process- and window-scoped behavior.
File summaries
| File | Description |
|---|---|
| src/winapp-CLI/WinApp.UIAutomation/Services/UiAutomationService.cs | Adds native ownership verification. |
| src/winapp-CLI/WinApp.UIAutomation.Tests/RealUiAutomationTests.Coverage.cs | Verifies query failures propagate. |
| src/winapp-CLI/WinApp.UIAutomation.Tests/FocusedElementTests.cs | Covers ownership and traversal scenarios. |
| src/winapp-CLI/WinApp.Cli.Tests/UiCommandTests.SimpleVerbs.cs | Tests command-level JSON errors. |
| docs/ui-automation.md | Documents updated get-focused behavior. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Build Metrics ReportValidation passed. All required build and validation jobs succeeded. Binary Sizes
.NET Test Results (TRX reports)Other suites are reflected in the overall validation status above. ✅ 7711 passed, 37 skipped out of 7748 tests in 1155.5s (+30 tests, -211.2s vs. baseline) Test Coverage✅ 85.7% line coverage, 80.1% branch coverage · ✅ no change vs. baseline CLI Startup Time64ms median (x64, Try This BuildInstalls the MSIX for your architecture, replacing any previously installed build. Needs the GitHub CLI — the command offers to install it and sign you in if it is missing. & ([scriptblock]::Create((irm https://raw.githubusercontent.com/microsoft/winappCli/main/scripts/winapp-pr.ps1))) 880Switching between builds often?Put the tool on your PATH once: & ([scriptblock]::Create((irm https://raw.githubusercontent.com/microsoft/winappCli/main/scripts/winapp-pr.ps1))) -AddToPathThen this build is just: winapp-pr 880Run Updated 2026-09-22 00:22:36 UTC · commit |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
State: agent-preparing |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> # Conflicts: # plugins/winapp/skills/winapp-ui-automation/SKILL.md
Add CLI help regression and regenerate schema/npm help surfaces. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Description
Fix
ui get-focusedreporting no focus when a Sandbox control omits its process ID. The exact CsWin32 CUIAutomation8 query returned Daylight's focused title control with PID 0, while native ancestor windows independently identified the app.The command now verifies missing ownership through a bounded, cancellable ancestor search. It rejects foreign process identities and requires the exact top-level window for
-w, excluding owned popups. Actual query failures return an error rather than a successful no-focus result. The positive-own-PID process-target path is preserved. Command help, generated CLI schema and npm help explain the window scope.Usage Example
Observed with the focused
TaskTitleInput: installed prerelease.52 returned{"hasFocus":false}in six trials; the candidate returnedhasFocus:truewith that control in all six, by both PID and main HWND. Explicit owned-popup and foreign-window targets returned false as expected. Use fresh IDs fromui list-windows.Related Issue
Fixes #876. Focus activation (#877), empty-value transport (#875), input guards and sandbox lifecycle are outside this change. Main's independently merged empty-value fix is preserved.
Type of Change
Checklist
scripts\build-cli.ps1 -SkipTestsand generated-doc/plugin validation passed with the help fix; subsequent CLI build-OnlyDocspassed. Published ARM64ui get-focused --helpchecked.e66235f8: all four test shards, UI E2E, docs, 14 samples and required aggregate. TRX: 7,711 passed, 37 intentional skips.Screenshots / Demo
Textual CLI output above demonstrates this nonvisual query correction. No screenshots required.
Additional Notes
Live ARM64 candidate evidence belongs to build head
e63e39921b37d95b58adfba9012c9130580a3814, SHA256DF19FC7248FBF33FD3D2FB818E4C40970881707AD899D57BB2F43EFC2F077942: five focus operations and one guarded click, with keyboard-focus property confirmation and side-by-side baseline queries. The blank editor was canceled without entering or saving text; only this issue's staged artifacts were cleaned. The prior local app installation's exact revision was not verified.Current
mainwas merged without rewriting branch history; overlapping focus and empty-value guidance were both preserved. The focus ownership algorithm is unchanged from the live-tested implementation. Prior live evidence is not a claim that a newly built merge-head binary was live-tested. No host UI or new Sandbox interaction was performed for this update. Local builds skipped full shared-host UI tests; targeted non-UI tests and full repository CI provide integration coverage.The native checks validate ownership of a provider-supplied HWND; they do not authenticate a malicious UIA provider's claimed relationship to that window. This read-only query is not an input-authorization boundary, and input safety guards are unchanged.