Skip to content

[Windows] Fix SearchHandler does not focus when ShowSoftInputAsync is called#35079

Open
praveenkumarkarunanithi wants to merge 6 commits intodotnet:mainfrom
praveenkumarkarunanithi:fix-22151
Open

[Windows] Fix SearchHandler does not focus when ShowSoftInputAsync is called#35079
praveenkumarkarunanithi wants to merge 6 commits intodotnet:mainfrom
praveenkumarkarunanithi:fix-22151

Conversation

@praveenkumarkarunanithi
Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue.
Thank you!

Root Cause

PR #29600 added ShowSoftInputRequested and HideSoftInputRequested event handling for Android and iOS via their respective SearchHandlerAppearanceTracker implementations.

However, Windows uses ShellItemHandler.Windows.cs, which was not updated to handle these events. As a result, although the events are raised by SearchHandler.ShowSoftInputAsync(), there are no subscribers on Windows, leading to no action.

Description of Change

Extended support for ShowSoftInputAsync() / HideSoftInputAsync() to Windows by wiring the corresponding events in ShellItemHandler.Windows.cs.

Event subscriptions are handled in UpdateSearchHandler when a handler is assigned, and are properly cleaned up when the handler is replaced or during DisconnectHandler.

Since Windows does not use an on-screen keyboard, the implementation focuses on focus management. Focus is applied using autoSuggestBox.Focus(FocusState.Programmatic), aligning with standard WinUI behavior. Unfocus is handled using the existing IsEnabled toggle pattern (consistent with ViewExtensions.UnfocusControl), with proper preservation of IsTabStop.

A safety guard is included to ensure that disabled controls are not unintentionally re-enabled during the unfocus process.

Issues Fixed

Fixes #34930

Tested the behaviour in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

Screenshots

Before Issue Fix After Issue Fix
withoutfix withfix

@github-actions
Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35079

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35079"

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Apr 22, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review April 22, 2026 10:37
Copilot AI review requested due to automatic review settings April 22, 2026 10:37
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds Windows support for SearchHandler.ShowSoftInputAsync() / HideSoftInputAsync() by wiring the corresponding internal events in the Windows ShellItemHandler, and introduces a UI test + HostApp repro page to validate focus behavior.

Changes:

  • Subscribe/unsubscribe to ShowSoftInputRequested / HideSoftInputRequested in ShellItemHandler.Windows.cs and implement focus/unfocus behavior via the AutoSuggestBox.
  • Add HostApp issue page Issue34930 with buttons and labels to exercise/observe focus behavior.
  • Add Appium/NUnit UI test Issue34930 to validate focus occurs after invoking ShowSoftInputAsync().

Reviewed changes

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

File Description
src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs Wires ShowSoftInputRequested/HideSoftInputRequested to focus/unfocus the underlying AutoSuggestBox on Windows.
src/Controls/tests/TestCases.HostApp/Issues/Issue34930.cs Adds a HostApp repro page that triggers Show/Hide soft-input requests and displays focus state.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34930.cs Adds a UI test which taps the button and asserts focus state/event indicators.

Comment on lines +25 to +26
var focusedEvent = App.WaitForElement("focusedEventLabel").GetText();
Assert.That(focusedEvent, Is.EqualTo("FocusedEvent: True"));
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

Same timing issue as above: focusedEventLabel exists from the start, so WaitForElement doesn't wait for its text to change. Consider waiting for the label text to become FocusedEvent: True before asserting to avoid race conditions.

Copilot uses AI. Check for mistakes.
}

[Test]
[Category(UITestCategories.SearchBar)]
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

This test is exercising the ShowSoftInputAsync/HideSoftInputAsync behavior; UITestCategories.SoftInput (or Shell) looks like a better fit than SearchBar and is already used for other soft-input tests. Using the more specific category helps CI categorization and targeted runs.

Suggested change
[Category(UITestCategories.SearchBar)]
[Category(UITestCategories.SoftInput)]

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +21
public void SearchHandlerShowSoftInputShouldFocusSearchHandlerOnWindows()
{
App.WaitForElement("ShowKeyboardButton");
App.Tap("ShowKeyboardButton");

Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

The PR wires up both Show/Hide soft-input requests on Windows, but this test only validates the "show" path. To prevent regressions in the new HideSoftInputRequested wiring, consider extending the test to tap the hide button and assert focus is cleared (e.g., IsFocused: False and/or an unfocused indicator).

Copilot uses AI. Check for mistakes.
Comment on lines +69 to +73
showKeyboardButton.Clicked += async (s, e) =>
{
searchHandler.ShowSoftInputAsync();
await Task.Delay(200);
isFocusedLabel.Text = $"IsFocused: {searchHandler.IsFocused}";
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

The Task.Delay(200) here is a fixed timing guess to wait for focus to propagate, which can be flaky across devices/CI load. Prefer updating isFocusedLabel in response to searchHandler.Focused/Unfocused (or another deterministic signal) so the UI and the UITest can wait on state instead of time.

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +52
AutomationId = "isFocusedLabel"
};

var focusedEventLabel = new Label
{
Text = "FocusedEvent: False",
AutomationId = "focusedEventLabel"
};

var searchHandler = new SearchHandler
{
AutomationId = "searchHandler",
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

AutomationId values in this file are mostly PascalCase (e.g., ShowKeyboardButton), but isFocusedLabel is lower camelCase. Consider using a consistent naming style for AutomationIds to make tests easier to read and maintain.

Suggested change
AutomationId = "isFocusedLabel"
};
var focusedEventLabel = new Label
{
Text = "FocusedEvent: False",
AutomationId = "focusedEventLabel"
};
var searchHandler = new SearchHandler
{
AutomationId = "searchHandler",
AutomationId = "IsFocusedLabel"
};
var focusedEventLabel = new Label
{
Text = "FocusedEvent: False",
AutomationId = "FocusedEventLabel"
};
var searchHandler = new SearchHandler
{
AutomationId = "SearchHandler",

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +52
AutomationId = "isFocusedLabel"
};

var focusedEventLabel = new Label
{
Text = "FocusedEvent: False",
AutomationId = "focusedEventLabel"
};

var searchHandler = new SearchHandler
{
AutomationId = "searchHandler",
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

AutomationId is lower camelCase here (focusedEventLabel) while other IDs in the page use PascalCase (e.g., ShowKeyboardButton). Aligning on one style for AutomationIds improves consistency across HostApp issue pages and UI tests.

Suggested change
AutomationId = "isFocusedLabel"
};
var focusedEventLabel = new Label
{
Text = "FocusedEvent: False",
AutomationId = "focusedEventLabel"
};
var searchHandler = new SearchHandler
{
AutomationId = "searchHandler",
AutomationId = "IsFocusedLabel"
};
var focusedEventLabel = new Label
{
Text = "FocusedEvent: False",
AutomationId = "FocusedEventLabel"
};
var searchHandler = new SearchHandler
{
AutomationId = "SearchHandler",

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +52
AutomationId = "isFocusedLabel"
};

var focusedEventLabel = new Label
{
Text = "FocusedEvent: False",
AutomationId = "focusedEventLabel"
};

var searchHandler = new SearchHandler
{
AutomationId = "searchHandler",
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

AutomationId = "searchHandler" is lower camelCase while other AutomationIds in the page use PascalCase. Consider renaming for consistency (and update the corresponding UITest IDs if it becomes referenced there).

Suggested change
AutomationId = "isFocusedLabel"
};
var focusedEventLabel = new Label
{
Text = "FocusedEvent: False",
AutomationId = "focusedEventLabel"
};
var searchHandler = new SearchHandler
{
AutomationId = "searchHandler",
AutomationId = "IsFocusedLabel"
};
var focusedEventLabel = new Label
{
Text = "FocusedEvent: False",
AutomationId = "FocusedEventLabel"
};
var searchHandler = new SearchHandler
{
AutomationId = "SearchHandler",

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +24

var isFocused = App.WaitForElement("isFocusedLabel").GetText();
Assert.That(isFocused, Is.EqualTo("IsFocused: True"));

Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

The test reads isFocusedLabel text immediately after tapping the button. Since the label exists before the tap, WaitForElement doesn't guarantee the text has updated yet, which can make this assertion flaky. Prefer waiting for the expected text (e.g., via WaitForTextToBePresentInElement) before asserting.

Suggested change
var isFocused = App.WaitForElement("isFocusedLabel").GetText();
Assert.That(isFocused, Is.EqualTo("IsFocused: True"));
App.WaitForTextToBePresentInElement("isFocusedLabel", "IsFocused: True");
var isFocused = App.WaitForElement("isFocusedLabel").GetText();
Assert.That(isFocused, Is.EqualTo("IsFocused: True"));
App.WaitForTextToBePresentInElement("focusedEventLabel", "FocusedEvent: True");

Copilot uses AI. Check for mistakes.
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Apr 22, 2026
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Could you please review the ai's summary and verify the failing tests?

Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Could you please check the ai's summary?

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented May 2, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

partner/syncfusion Issues / PR's with Syncfusion collaboration platform/windows s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) shell-search-handler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Windows] SearchHandler.ShowSoftInputAsync() does not focus the SearchHandler

5 participants