microsoft / microsoft/winappCli

[Bug]: ui focus should activate the target window and verify focus before reporting success

Open
#877 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C#
Stars
1.3k
Forks
80
Avg merge
3d 6h
Merged PRs (30d)
51

Description

### Describe the bug

`winapp ui focus ` can report success after focusing a control inside an inactive application, without bringing the application window to the foreground. The next guarded click or keyboard action can still fail because the app is not active.

The agreed user-facing behavior is: **activate the target window, focus the requested control, and verify the result before reporting success**. Activation should be attempted by default when needed, not require taking a screenshot or discovering a separate workaround.

This is an intentional correction to the current low-level UIA SetFocus-only contract, not a claim that the original implementation promised foreground activation. Windows restrictions, user interruption, target isolation, and existing input safety checks must remain in effect.

### To Reproduce

Observed with CLI `0.6.3-prerelease.52` in Windows Sandbox using the Daylight WinUI demo (https://github.com/nmetulev/daylight):

1. Start Daylight and discover its current app PID and main HWND. Establish that its main window is inactive.
2. Run `winapp ui click SearchTasksBox -a --on sandbox --json`.
3. Run `winapp ui focus SearchTasksBox -a --on sandbox --json`.
4. Read `HasKeyboardFocus` for the control and inspect which window is foreground. Do not use `get-focused` as the sole oracle because of #876.

Observed:
- The guarded click exited 1 with `foreground_not_target`.
- `focus SearchTasksBox` exited 0 and the control reported `HasKeyboardFocus=True`, but the main window remained inactive.
- `screenshot -w --focus --on sandbox` subsequently succeeded; an owned Daylight popup became foreground, and the following guarded click succeeded and activated the main window.

**Reproduction limitation:** Daylight was confirmed inactive, but this trial did not establish a stable unrelated foreground window. Add a controlled two-window regression case rather than treating the screenshot workaround as proof of the underlying activation failure.

Relevant current behavior:
- [UiFocusCommand](https://github.com/microsoft/winappCli/blob/2e307c7e8e648a1906205241148de20bcf12f7ab/src/winapp-CLI/WinApp.Cli/Commands/UiFocusCommand.cs) invokes UIA focus without an explicit foreground activation step.
- `UiClickCommand` already requests foreground activation and refuses if it is not obtained or retained. Do not remove that guard; simply adding another identical activation attempt is not sufficient evidence of a fix.
- Separately, installed help shows `focus []`, while `winapp ui focus -w 0 --on local --json` exits 1 with `missing_selector`. This help/validation mismatch is independently reproduced and should be corrected on the affected command.

### Expected behavior

For `winapp ui focus -a ` or `-w `:

1. Resolve and revalidate the intended app/window/control within the existing coordinated desktop operation.
2. If necessary, request activation of the correct target window using existing foreground helpers and safety rules.
3. Focus the requested control and verify both target foreground ownership and control keyboard focus before reporting success.
4. If Windows refuses activation, the user interrupts, focus moves elsewhere, or the target disappears, return an actionable nonzero failure rather than a success-shaped result.

"Activate by default" means **attempt activation when needed**, not forcibly bypass Windows focus restrictions or user-interruption safeguards.

Acceptance criteria:
- Cover an already active app, an eligible inactive app, refused activation, loss of foreground during focus, a stale/reused target, and relevant owned-popup cases.
- Never focus/type/click into an unrelated app or blindly treat every owned popup as the requested control's active window.
- Keep app/window targeting and local/sandbox isolation intact; do not add a local fallback.
- Preserve existing coordination and reuse existing helpers rather than creating a parallel activation subsystem.
- Add regression tests and a controlled live reproduction. Verify the observable outcome, not just that SetFocus or SetForegroundWindow was called.
- Update focus help, affected user documentation/skill guidance, and recovery messages to match the implemented behavior. Show the selector as required if it remains required; a new selector-less window-activation mode is not required for this issue.

Coordinate with #876 if focus verification needs shared ownership handling, but do not duplicate its focused-element discovery fix. #875 is a separate empty-value issue.

### Screenshots

N/A. Evidence consists of command exit codes and structured control-focus/foreground-window results.

### OS Version and details

CLI `0.6.3-prerelease.52`; native ARM64 Windows host and managed Windows Sandbox. Sandbox viewer connected and interactive during the reproduction. Source inspected at revision `2e307c7e8e648a1906205241148de20bcf12f7ab`.

No application code changes, saved edits, data resets, or input-guard bypasses were made during investigation.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/winapp-CLI/WinApp.Cli/Commands/UiFocusCommand.cs and compare its flow with UiClickCommand's existing foreground activation and safety checks. Add a controlled two-window regression covering activation, focus verification, refusal, stale targets, and owned popups, then update focus help, documentation or skill guidance, and recovery messages. Done means observable foreground ownership and control focus are verified before success without weakening isolation or input guards.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
cli, operating-systems, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.