Browse Source

Only allow focus change on pointer release for touch and pen input (#19753)

Emmanuel Hansen 1 tuần trước cách đây
mục cha
commit
98c7fde141

+ 20 - 5
src/Avalonia.Base/Input/FocusManager.cs

@@ -34,7 +34,11 @@ namespace Avalonia.Input
         {
             InputElement.PointerPressedEvent.AddClassHandler(
                 typeof(IInputElement),
-                new EventHandler<RoutedEventArgs>(OnPreviewPointerPressed),
+                new EventHandler<RoutedEventArgs>(OnPreviewPointerEventHandler),
+                RoutingStrategies.Tunnel);
+            InputElement.PointerReleasedEvent.AddClassHandler(
+                typeof(IInputElement),
+                new EventHandler<RoutedEventArgs>(OnPreviewPointerEventHandler),
                 RoutingStrategies.Tunnel);
         }
 
@@ -194,6 +198,17 @@ namespace Avalonia.Input
         /// <returns>True if the element can be focused.</returns>
         internal static bool CanFocus(IInputElement e) => e.Focusable && e.IsEffectivelyEnabled && IsVisible(e);
 
+        private static bool CanPointerFocus(IInputElement e, PointerEventArgs ev)
+        {
+            if (CanFocus(e))
+            {
+                if (ev.Pointer.Type == PointerType.Mouse || ev is PointerReleasedEventArgs)
+                    return true;
+            }
+
+            return false;
+        }
+
         /// <summary>
         /// Gets the focus scope of the specified control, traversing popups.
         /// </summary>
@@ -241,21 +256,21 @@ namespace Avalonia.Input
         /// </summary>
         /// <param name="sender">The event sender.</param>
         /// <param name="e">The event args.</param>
-        private static void OnPreviewPointerPressed(object? sender, RoutedEventArgs e)
+        private static void OnPreviewPointerEventHandler(object? sender, RoutedEventArgs e)
         {
             if (sender is null)
                 return;
 
-            var ev = (PointerPressedEventArgs)e;
+            var ev = (PointerEventArgs)e;
             var visual = (Visual)sender;
 
-            if (sender == e.Source && ev.GetCurrentPoint(visual).Properties.IsLeftButtonPressed)
+            if (sender == e.Source && (ev.GetCurrentPoint(visual).Properties.IsLeftButtonPressed || (e as PointerReleasedEventArgs)?.InitialPressMouseButton == MouseButton.Left))
             {
                 Visual? element = ev.Pointer?.Captured as Visual ?? e.Source as Visual;
 
                 while (element != null)
                 {
-                    if (element is IInputElement inputElement && CanFocus(inputElement))
+                    if (element is IInputElement inputElement && CanPointerFocus(inputElement, ev))
                     {
                         inputElement.Focus(NavigationMethod.Pointer, ev.KeyModifiers);
 

+ 4 - 9
src/Avalonia.Controls/Primitives/TextSelectionCanvas.cs

@@ -276,7 +276,6 @@ namespace Avalonia.Controls.Primitives
             {
                 _textBox.RemoveHandler(TextBox.TextChangingEvent, TextChanged);
                 _textBox.RemoveHandler(KeyDownEvent, TextBoxKeyDown);
-                _textBox.RemoveHandler(PointerReleasedEvent, TextBoxPointerReleased);
 
                 _textBox.PropertyChanged -= TextBoxPropertyChanged;
                 _textBox.EffectiveViewportChanged -= TextBoxEffectiveViewportChanged;
@@ -294,7 +293,6 @@ namespace Avalonia.Controls.Primitives
                 {
                     _textBox.AddHandler(TextBox.TextChangingEvent, TextChanged, handledEventsToo: true);
                     _textBox.AddHandler(KeyDownEvent, TextBoxKeyDown, handledEventsToo: true);
-                    _textBox.AddHandler(PointerReleasedEvent, TextBoxPointerReleased, handledEventsToo: true);
 
                     _textBox.PropertyChanged += TextBoxPropertyChanged;
                     _textBox.EffectiveViewportChanged += TextBoxEffectiveViewportChanged;
@@ -371,15 +369,12 @@ namespace Avalonia.Controls.Primitives
             return false;
         }
 
-        private void TextBoxPointerReleased(object? sender, PointerReleasedEventArgs e)
+        internal void Show()
         {
-            if (e.Pointer.Type != PointerType.Mouse)
-            {
-                ShowHandles = true;
+            ShowHandles = true;
 
-                MoveHandlesToSelection();
-                EnsureVisible();
-            }
+            MoveHandlesToSelection();
+            EnsureVisible();
         }
 
         private void TextBoxPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)

+ 0 - 5
src/Avalonia.Controls/Primitives/TextSelectionHandle.cs

@@ -151,11 +151,6 @@ namespace Avalonia.Controls.Primitives
             {
                 var vector = e.GetPosition(VisualRoot as Visual) - _lastPoint.Value;
 
-                var tapSize = TopLevel.GetTopLevel(this)?.PlatformSettings?.GetTapSize(PointerType.Touch) ?? new Size(10, 10);
-
-                if (Math.Abs(vector.X) < tapSize.Width && Math.Abs(vector.Y) < tapSize.Height)
-                    return;
-
                 ev = new VectorEventArgs
                 {
                     RoutedEvent = DragDeltaEvent,

+ 2 - 0
src/Avalonia.Controls/TextBox.cs

@@ -1868,6 +1868,8 @@ namespace Avalonia.Controls
                     SetCurrentValue(SelectionEndProperty, caretIndex);
                 }
 
+                _presenter.TextSelectionHandleCanvas?.Show();
+
                 if (SelectionStart != SelectionEnd)
                 {
                     _presenter.TextSelectionHandleCanvas?.ShowContextMenu();