Skip to content

Commit

Permalink
Merge pull request #18887 from ramezgerges/textbox_focus_in_popup_wasm
Browse files Browse the repository at this point in the history
fix(textbox): losing focus on PointerUp when inside a Popup on WASM
  • Loading branch information
ramezgerges authored Nov 28, 2024
2 parents f75fc1d + 9058d6d commit dabd0a6
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using Windows.UI.Input.Preview.Injection;
using Windows.Foundation;
using System.Collections.Generic;
using Uno.Extensions;


#if WINAPPSDK
Expand Down Expand Up @@ -1124,6 +1125,44 @@ static FrameworkElement GetSCP(TextBox tb)
}
#endif

#if HAS_UNO
[TestMethod]
[UnoWorkItem("https://github.com/unoplatform/uno/issues/18790")]
#if !HAS_INPUT_INJECTOR
[Ignore("InputInjector is not supported on this platform.")]
#endif
public async Task When_Clicked_In_Popup()
{
TextBox tb;
var btn = new Button
{
Flyout = new Flyout
{
Content = tb = new TextBox()
}
};

await UITestHelper.Load(btn);

var injector = InputInjector.TryCreate() ?? throw new InvalidOperationException("Failed to init the InputInjector");
using var mouse = injector.GetMouse();

mouse.Press(btn.GetAbsoluteBoundsRect().GetCenter());
await UITestHelper.WaitForIdle();
mouse.Release();
await UITestHelper.WaitForIdle();

Assert.IsTrue(btn.Flyout.IsOpen);

mouse.Press(tb.GetAbsoluteBoundsRect().GetCenter());
await UITestHelper.WaitForIdle();
mouse.Release();
await UITestHelper.WaitForIdle();

Assert.AreEqual(tb, FocusManager.GetFocusedElement(WindowHelper.XamlRoot));
}
#endif

private static async Task<TextBox> LoadZeroSizeTextBoxAsync(Style style)
{
var loaded = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ protected override void OnPointerReleased(PointerRoutedEventArgs args)

private static bool ScrollContentControl_SetFocusOnFlyoutLightDismissPopupByPointer(UIElement pScrollContentControl)
{
#if __WASM__
if ((pScrollContentControl as ScrollViewer)?.DisableSetFocusOnPopupByPointer ?? false)
{
return false;
}
#endif

PopupRoot? pPopupRoot = null;
Popup? pPopup = null;

Expand Down
9 changes: 9 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/ScrollViewer/ScrollViewer.wasm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ namespace Microsoft.UI.Xaml.Controls
{
partial class ScrollViewer
{
/// <summary>
/// This is specifically added for ScrollViewers inside TextBoxes and specifically for WASM
/// On WASM, a click on a TextBox inside a popup shifts focus to the Popup instead of the TextBox
/// as a result of ScrollContentControl_SetFocusOnFlyoutLightDismissPopupByPointer.
/// This is only a problem on WASM because we don't capture the pointer when pressing inside a TextBox
/// <seealso cref="TextBox.IsPointerCaptureRequired"/>.
/// </summary>
internal bool DisableSetFocusOnPopupByPointer { get; set; }

internal bool CancelNextNativeScroll { get; private set; }
internal Size ScrollBarSize => (_presenter as ScrollContentPresenter)?.ScrollBarSize ?? default;

Expand Down
12 changes: 11 additions & 1 deletion src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.Uno.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ public bool IsPointerCaptureRequired
new FrameworkPropertyMetadata(
// We should not capture the pointer on WASM by default because it would prevent the user from scrolling through text on selection.
// See https://github.com/unoplatform/uno/pull/16982, https://issues.chromium.org/issues/344491566
false));
false
#if __WASM__
, static (dO, args) =>
{
if (((TextBox)dO)._contentElement is ScrollViewer sv)
{
sv.DisableSetFocusOnPopupByPointer = !(bool)args.NewValue;
}
}
#endif
));
#endif
}
4 changes: 4 additions & 0 deletions src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ private protected override void OnLoaded()
scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled; // The template sets this to Hidden
scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto; // The template sets this to Hidden
}

#if __WASM__
scrollViewer.DisableSetFocusOnPopupByPointer = !IsPointerCaptureRequired;
#endif
#endif
}
}
Expand Down

0 comments on commit dabd0a6

Please sign in to comment.