Skip to content

Commit

Permalink
improve hold support in textbox
Browse files Browse the repository at this point in the history
  • Loading branch information
emmauss committed Sep 20, 2023
1 parent d41aad6 commit 047f5e5
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 15 deletions.
12 changes: 6 additions & 6 deletions src/Avalonia.Base/Input/Gestures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ public static class Gestures
/// Defines the IsHoldingEnabled attached property.
/// </summary>
public static readonly AttachedProperty<bool> IsHoldingEnabledProperty =
AvaloniaProperty.RegisterAttached<StyledElement, bool>("IsHoldingEnabled", typeof(Gestures), true, inherits: true);
AvaloniaProperty.RegisterAttached<StyledElement, bool>("IsHoldingEnabled", typeof(Gestures), true);

/// <summary>
/// Defines the IsHoldWithMouseEnabled attached property.
/// </summary>
public static readonly AttachedProperty<bool> IsHoldWithMouseEnabledProperty =
AvaloniaProperty.RegisterAttached<StyledElement, bool>("IsHoldWithMouseEnabled", typeof(Gestures), false, inherits: true);
AvaloniaProperty.RegisterAttached<StyledElement, bool>("IsHoldWithMouseEnabled", typeof(Gestures), false);

public static readonly RoutedEvent<TappedEventArgs> TappedEvent = RoutedEvent.Register<TappedEventArgs>(
"Tapped",
Expand Down Expand Up @@ -163,7 +163,7 @@ private static void PointerPressed(RoutedEventArgs ev)
{
if(s_isHolding && ev.Source is Interactive i)
{
i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Cancelled, s_lastPressPoint, s_lastPointer.Type));
i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Cancelled, s_lastPressPoint, s_lastPointer.Type, e));
}
s_holdCancellationToken?.Cancel();
s_holdCancellationToken?.Dispose();
Expand Down Expand Up @@ -191,7 +191,7 @@ private static void PointerPressed(RoutedEventArgs ev)
if (!token.IsCancellationRequested && e.Source is InputElement i && GetIsHoldingEnabled(i) && (e.Pointer.Type != PointerType.Mouse || GetIsHoldWithMouseEnabled(i)))
{
s_isHolding = true;
i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Started, s_lastPressPoint, s_lastPointer.Type));
i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Started, s_lastPressPoint, s_lastPointer.Type, e));
}
}, settings.HoldWaitDuration);
}
Expand Down Expand Up @@ -231,7 +231,7 @@ e.InitialPressMouseButton is MouseButton.Left or MouseButton.Right &&
if(s_isHolding)
{
s_isHolding = false;
i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Completed, s_lastPressPoint, s_lastPointer!.Type));
i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Completed, s_lastPressPoint, s_lastPointer!.Type, e));
}
else if (e.InitialPressMouseButton == MouseButton.Right)
{
Expand Down Expand Up @@ -275,7 +275,7 @@ private static void PointerMoved(RoutedEventArgs ev)

if (s_isHolding)
{
i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Cancelled, s_lastPressPoint, s_lastPointer!.Type));
i.RaiseEvent(new HoldingRoutedEventArgs(HoldingState.Cancelled, s_lastPressPoint, s_lastPointer!.Type, e));
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/Avalonia.Base/Input/HoldingRoutedEventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ public class HoldingRoutedEventArgs : RoutedEventArgs
/// </summary>
public PointerType PointerType { get; }

public PointerEventArgs? PointerEventArgs { get; }

/// <summary>
/// Initializes a new instance of the <see cref="HoldingRoutedEventArgs"/> class.
/// </summary>
Expand All @@ -29,6 +31,11 @@ public HoldingRoutedEventArgs(HoldingState holdingState, Point position, Pointer
Position = position;
PointerType = pointerType;
}

internal HoldingRoutedEventArgs(HoldingState holdingState, Point position, PointerType pointerType, PointerEventArgs pointerEventArgs) : this(holdingState, position, pointerType)
{
PointerEventArgs = pointerEventArgs;
}
}

public enum HoldingState
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Controls/Control.cs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ private void OnHoldEvent(object? sender, HoldingRoutedEventArgs e)
if (!e.Handled && e.HoldingState == HoldingState.Started)
{
// Trigger ContentRequest when hold has started
RaiseEvent(new ContextRequestedEventArgs());
RaiseEvent(e.PointerEventArgs is { } ev ? new ContextRequestedEventArgs(ev) : new ContextRequestedEventArgs());
}
}

Expand Down
62 changes: 54 additions & 8 deletions src/Avalonia.Controls/TextBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,13 @@ public UndoRedoState(string? text, int caretPosition)
private bool _canRedo;

private int _wordSelectionStart = -1;
private bool _touchDragStarted;
private bool _inTouchDrag;
private Point _touchDragStartPoint;
private int _selectedTextChangesMadeSinceLastUndoSnapshot;
private bool _hasDoneSnapshotOnce;
private static bool _isHolding;
private int _currentClickCount;
private const int _maxCharsBeforeUndoSnapshot = 7;

static TextBox()
Expand Down Expand Up @@ -848,10 +852,10 @@ private void OnHolding(object? sender, HoldingRoutedEventArgs e)
SetCurrentValue(SelectionEndProperty, end);
}

_isHolding = true;

e.Handled = true;
}

_isHolding = true;
}

protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
Expand Down Expand Up @@ -1489,8 +1493,21 @@ protected override void OnPointerPressed(PointerPressedEventArgs e)
if (text != null && clickInfo.Properties.IsLeftButtonPressed &&
!(clickInfo.Pointer?.Captured is Border))
{
var isTouch = e.Pointer.Type == PointerType.Touch;

_currentClickCount = e.ClickCount;
var point = e.GetPosition(_presenter);

if(isTouch && e.ClickCount == 1)
{
_wordSelectionStart = -1;
_touchDragStarted = true;
_touchDragStartPoint = point;
e.Pointer.Capture(_presenter);
e.Handled = true;
return;
}

_presenter.MoveCaretToPoint(point);

var caretIndex = _presenter.CaretIndex;
Expand Down Expand Up @@ -1571,6 +1588,16 @@ protected override void OnPointerMoved(PointerEventArgs e)
MathUtilities.Clamp(point.X, 0, Math.Max(_presenter.Bounds.Width - 1, 0)),
MathUtilities.Clamp(point.Y, 0, Math.Max(_presenter.Bounds.Height - 1, 0)));

if(_touchDragStarted)
{
_touchDragStarted = false;
_inTouchDrag = true;

_presenter.MoveCaretToPoint(_touchDragStartPoint);
_touchDragStartPoint = default;
SetCurrentValue(SelectionStartProperty, _presenter.CaretIndex);
}

_presenter.MoveCaretToPoint(point);

var caretIndex = _presenter.CaretIndex;
Expand Down Expand Up @@ -1625,6 +1652,12 @@ protected override void OnPointerReleased(PointerReleasedEventArgs e)
return;
}

_touchDragStarted = false;
_touchDragStartPoint = default;

var isInTouchDrag = _inTouchDrag;
_inTouchDrag = false;

if (e.Pointer.Captured != _presenter)
{
return;
Expand All @@ -1634,13 +1667,8 @@ protected override void OnPointerReleased(PointerReleasedEventArgs e)
if (_isHolding)
{
_isHolding = false;

RaiseEvent(new ContextRequestedEventArgs(e));

return;
}

if (e.InitialPressMouseButton == MouseButton.Right)
else if (e.InitialPressMouseButton == MouseButton.Right)
{
var point = e.GetPosition(_presenter);

Expand All @@ -1661,6 +1689,24 @@ protected override void OnPointerReleased(PointerReleasedEventArgs e)
SetCurrentValue(SelectionStartProperty, caretIndex);
}
}
else if (e.Pointer.Type == PointerType.Touch)
{
if (_currentClickCount == 1 && !isInTouchDrag)
{
var point = e.GetPosition(_presenter);

_presenter.MoveCaretToPoint(point);

var caretIndex = _presenter.CaretIndex;
SetCurrentValue(SelectionStartProperty, caretIndex);
SetCurrentValue(SelectionEndProperty, caretIndex);
}

if(SelectionStart != SelectionEnd)
{
RaiseEvent(new ContextRequestedEventArgs(e));
}
}

e.Pointer.Capture(null);
}
Expand Down

0 comments on commit 047f5e5

Please sign in to comment.