Browse Source

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

pull/19797/head
Emmanuel Hansen 12 months ago
committed by GitHub
parent
commit
98c7fde141
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 25
      src/Avalonia.Base/Input/FocusManager.cs
  2. 13
      src/Avalonia.Controls/Primitives/TextSelectionCanvas.cs
  3. 5
      src/Avalonia.Controls/Primitives/TextSelectionHandle.cs
  4. 2
      src/Avalonia.Controls/TextBox.cs

25
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);

13
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)

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
src/Avalonia.Controls/TextBox.cs

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

Loading…
Cancel
Save