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( InputElement.PointerPressedEvent.AddClassHandler(
typeof(IInputElement), typeof(IInputElement),
new EventHandler<RoutedEventArgs>(OnPreviewPointerPressed), new EventHandler<RoutedEventArgs>(OnPreviewPointerEventHandler),
RoutingStrategies.Tunnel);
InputElement.PointerReleasedEvent.AddClassHandler(
typeof(IInputElement),
new EventHandler<RoutedEventArgs>(OnPreviewPointerEventHandler),
RoutingStrategies.Tunnel); RoutingStrategies.Tunnel);
} }
@ -194,6 +198,17 @@ namespace Avalonia.Input
/// <returns>True if the element can be focused.</returns> /// <returns>True if the element can be focused.</returns>
internal static bool CanFocus(IInputElement e) => e.Focusable && e.IsEffectivelyEnabled && IsVisible(e); 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> /// <summary>
/// Gets the focus scope of the specified control, traversing popups. /// Gets the focus scope of the specified control, traversing popups.
/// </summary> /// </summary>
@ -241,21 +256,21 @@ namespace Avalonia.Input
/// </summary> /// </summary>
/// <param name="sender">The event sender.</param> /// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</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) if (sender is null)
return; return;
var ev = (PointerPressedEventArgs)e; var ev = (PointerEventArgs)e;
var visual = (Visual)sender; 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; Visual? element = ev.Pointer?.Captured as Visual ?? e.Source as Visual;
while (element != null) while (element != null)
{ {
if (element is IInputElement inputElement && CanFocus(inputElement)) if (element is IInputElement inputElement && CanPointerFocus(inputElement, ev))
{ {
inputElement.Focus(NavigationMethod.Pointer, ev.KeyModifiers); 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(TextBox.TextChangingEvent, TextChanged);
_textBox.RemoveHandler(KeyDownEvent, TextBoxKeyDown); _textBox.RemoveHandler(KeyDownEvent, TextBoxKeyDown);
_textBox.RemoveHandler(PointerReleasedEvent, TextBoxPointerReleased);
_textBox.PropertyChanged -= TextBoxPropertyChanged; _textBox.PropertyChanged -= TextBoxPropertyChanged;
_textBox.EffectiveViewportChanged -= TextBoxEffectiveViewportChanged; _textBox.EffectiveViewportChanged -= TextBoxEffectiveViewportChanged;
@ -294,7 +293,6 @@ namespace Avalonia.Controls.Primitives
{ {
_textBox.AddHandler(TextBox.TextChangingEvent, TextChanged, handledEventsToo: true); _textBox.AddHandler(TextBox.TextChangingEvent, TextChanged, handledEventsToo: true);
_textBox.AddHandler(KeyDownEvent, TextBoxKeyDown, handledEventsToo: true); _textBox.AddHandler(KeyDownEvent, TextBoxKeyDown, handledEventsToo: true);
_textBox.AddHandler(PointerReleasedEvent, TextBoxPointerReleased, handledEventsToo: true);
_textBox.PropertyChanged += TextBoxPropertyChanged; _textBox.PropertyChanged += TextBoxPropertyChanged;
_textBox.EffectiveViewportChanged += TextBoxEffectiveViewportChanged; _textBox.EffectiveViewportChanged += TextBoxEffectiveViewportChanged;
@ -371,15 +369,12 @@ namespace Avalonia.Controls.Primitives
return false; return false;
} }
private void TextBoxPointerReleased(object? sender, PointerReleasedEventArgs e) internal void Show()
{ {
if (e.Pointer.Type != PointerType.Mouse) ShowHandles = true;
{
ShowHandles = true;
MoveHandlesToSelection(); MoveHandlesToSelection();
EnsureVisible(); EnsureVisible();
}
} }
private void TextBoxPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) 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 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 ev = new VectorEventArgs
{ {
RoutedEvent = DragDeltaEvent, RoutedEvent = DragDeltaEvent,

2
src/Avalonia.Controls/TextBox.cs

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

Loading…
Cancel
Save