diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs index 0c5b1b1d42..5ac1be7152 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -178,7 +178,6 @@ namespace Avalonia.Input.GestureRecognizers _inertia = default; _delta = default; _scrolling = false; - _velocityTracker?.Dispose(); _velocityTracker = null; Target!.RaiseEvent(new ScrollGestureEndedEventArgs(_gestureId)); _gestureId = 0; diff --git a/src/Avalonia.Base/Input/GestureRecognizers/VelocityTracker.cs b/src/Avalonia.Base/Input/GestureRecognizers/VelocityTracker.cs index 34a7122f4f..e7871fde6b 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/VelocityTracker.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/VelocityTracker.cs @@ -3,7 +3,6 @@ using System; using System.Diagnostics; -using Avalonia.Utilities; namespace Avalonia.Input.GestureRecognizers { @@ -59,7 +58,7 @@ namespace Avalonia.Input.GestureRecognizers /// /// The quality of the velocity estimation will be better if more data points /// have been received. - internal class VelocityTracker : IDisposable + internal class VelocityTracker { private const int AssumePointerMoveStoppedMilliseconds = 40; private const int HistorySize = 20; @@ -202,11 +201,6 @@ namespace Avalonia.Input.GestureRecognizers { return GetVelocity().ClampMagnitude(MinFlingVelocity, MaxFlingVelocity); } - - public void Dispose() - { - _sinceLastSample.Stop(); - } } /// An nth degree polynomial fit to a dataset. diff --git a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs index c56a6b8ee4..395c24824f 100644 --- a/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs @@ -621,7 +621,7 @@ namespace Avalonia.Controls.Presenters e.Handled = !IsScrollChainingEnabled || offsetChanged; - if(!e.Handled) + if(!e.Handled && !IsScrollChainingEnabled) { // Gesture may cause an overscroll so we mark the event as handled if it did. e.Handled = canXScroll || canYScroll; diff --git a/src/Avalonia.Controls/Primitives/TextSelectionCanvas.cs b/src/Avalonia.Controls/Primitives/TextSelectionCanvas.cs index 5fc73a74f4..3ac1f119f0 100644 --- a/src/Avalonia.Controls/Primitives/TextSelectionCanvas.cs +++ b/src/Avalonia.Controls/Primitives/TextSelectionCanvas.cs @@ -5,7 +5,6 @@ using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives.PopupPositioning; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Layout; using Avalonia.Media.TextFormatting; using Avalonia.Threading; using Avalonia.VisualTree; @@ -386,7 +385,7 @@ namespace Avalonia.Controls.Primitives if (!_handle1.IsDragging) { var pos = _handle1.SelectionHandleType == SelectionHandleType.Start ? startPoint : endPoint; - if(pos.isRtl != _handle1.IsRtl) + if (pos.isRtl != _handle1.IsRtl) _handle1.NeedsIndicatorUpdate = true; _handle1.IsRtl = pos.isRtl; _handle1.SetTopLeft(ToLayer(pos.position)); @@ -580,7 +579,7 @@ namespace Avalonia.Controls.Primitives ShowHandles = false; CloseFlyout(); } - else if(e.Property == TextBox.SelectionStartProperty || e.Property == TextBox.SelectionEndProperty + else if (e.Property == TextBox.SelectionStartProperty || e.Property == TextBox.SelectionEndProperty || e.Property == TextBox.CaretIndexProperty) { MoveHandlesToSelection(); @@ -596,42 +595,18 @@ namespace Avalonia.Controls.Primitives // Listener to layout changes for presenter. private class PresenterVisualListener { - private List _attachedVisuals = new List(); private TextPresenter? _presenter; - private object _lock = new object(); public event EventHandler? Invalidated; public void Attach(TextPresenter presenter) { - lock (_lock) - { - if (_presenter != null) - throw new InvalidOperationException("Listener is already attached to a TextPresenter"); - - _presenter = presenter; - presenter.SizeChanged += Presenter_SizeChanged; - presenter.EffectiveViewportChanged += Visual_EffectiveViewportChanged; - - - void AttachViewportHandler(Visual visual) - { - if (visual is Layoutable layoutable) - { - layoutable.EffectiveViewportChanged += Visual_EffectiveViewportChanged; - } - - _attachedVisuals.Add(visual); - } + if (_presenter != null) + throw new InvalidOperationException("Listener is already attached to a TextPresenter"); - var visualParent = presenter.VisualParent; - while (visualParent != null) - { - AttachViewportHandler(visualParent); - - visualParent = visualParent.VisualParent; - } - } + _presenter = presenter; + presenter.SizeChanged += Presenter_SizeChanged; + presenter.EffectiveViewportChanged += Visual_EffectiveViewportChanged; } private void Visual_EffectiveViewportChanged(object? sender, Layout.EffectiveViewportChangedEventArgs e) @@ -646,25 +621,13 @@ namespace Avalonia.Controls.Primitives public void Detach() { - lock (_lock) + if (_presenter is { } presenter) { - if (_presenter is { } presenter) - { - presenter.SizeChanged -= Presenter_SizeChanged; - presenter.EffectiveViewportChanged -= Visual_EffectiveViewportChanged; - } - - foreach (var visual in _attachedVisuals) - { - if (visual is Layoutable layoutable) - { - layoutable.EffectiveViewportChanged -= Visual_EffectiveViewportChanged; - } - } - - _presenter = null; - _attachedVisuals.Clear(); + presenter.SizeChanged -= Presenter_SizeChanged; + presenter.EffectiveViewportChanged -= Visual_EffectiveViewportChanged; } + + _presenter = null; } private void OnInvalidated() diff --git a/src/Avalonia.Controls/Primitives/TextSelectionHandle.cs b/src/Avalonia.Controls/Primitives/TextSelectionHandle.cs index 99798b2a39..b155c3f5ce 100644 --- a/src/Avalonia.Controls/Primitives/TextSelectionHandle.cs +++ b/src/Avalonia.Controls/Primitives/TextSelectionHandle.cs @@ -1,9 +1,7 @@ using System; -using System.Drawing; using Avalonia.Controls.Metadata; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Media; namespace Avalonia.Controls.Primitives { @@ -252,17 +250,17 @@ namespace Avalonia.Controls.Primitives private void UpdateHandleClasses() { - Classes.Remove("caret"); - Classes.Remove("start"); - Classes.Remove("end"); + PseudoClasses.Remove(":caret"); + PseudoClasses.Remove(":start"); + PseudoClasses.Remove(":end"); - Classes.Add(SelectionHandleType switch + PseudoClasses.Add(":" + (SelectionHandleType switch { SelectionHandleType.Caret => "caret", SelectionHandleType.Start => IsRtl ? "end" : "start", SelectionHandleType.End => IsRtl ? "start" : "end", _ => throw new NotImplementedException(), - }); + })); InvalidateVisual(); } } diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 898c3037d5..7da2b6cb0b 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -35,7 +35,7 @@ namespace Avalonia.Controls /// /// The radius for touch input. Used to determine if selection should change from moving a touch pointer. /// - private readonly static int s_touchRadius = (int)((AvaloniaLocator.Current?.GetService()?.GetTapSize(PointerType.Touch).Height ?? 10) / 2) + 5; + private readonly Lazy _touchRadius = new(() => (int)((AvaloniaLocator.Current?.GetService()?.GetTapSize(PointerType.Touch).Height ?? 10) / 2) + 5); /// /// Gets a platform-specific for the Cut action @@ -1735,7 +1735,7 @@ namespace Avalonia.Controls { base.OnTapped(e); - if(e.Pointer.Type != PointerType.Mouse) + if (e.Pointer.Type != PointerType.Mouse) { _presenter?.EnsureTextSelectionLayer(); _presenter?.TextSelectionHandleCanvas?.Show(); @@ -1815,18 +1815,13 @@ namespace Avalonia.Controls if (_isDoubleTapped) { - var oldCaret = _presenter.CaretIndex; _presenter.MoveCaretToPoint(_lastPoint); var caretIndex = _presenter.CaretIndex; - if(Math.Abs(oldCaret - caretIndex) > 3) - { - return; - } var selectionStart = SelectionStart; var selectionEnd = SelectionEnd; - SelectWord(text, caretIndex, caretIndex, caretIndex); + SelectWord(text, caretIndex, selectionStart, selectionEnd); _presenter?.EnsureTextSelectionLayer(); _presenter?.TextSelectionHandleCanvas?.Show(); } @@ -1957,7 +1952,7 @@ namespace Avalonia.Controls if (!_isInTouchCaretMode) { - var touchRect = new Rect(_lastPoint.X, _lastPoint.Y, 0, 0).Inflate(s_touchRadius); + var touchRect = new Rect(_lastPoint.X, _lastPoint.Y, 0, 0).Inflate(_touchRadius.Value); var isInRect = touchRect.X < point.X && touchRect.Y < point.Y && touchRect.Right > point.X && diff --git a/src/Avalonia.Themes.Fluent/Controls/TextSelectionHandle.xaml b/src/Avalonia.Themes.Fluent/Controls/TextSelectionHandle.xaml index c0ee242776..42020b14f7 100644 --- a/src/Avalonia.Themes.Fluent/Controls/TextSelectionHandle.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/TextSelectionHandle.xaml @@ -97,21 +97,21 @@ - - - - - diff --git a/src/Avalonia.Themes.Simple/Controls/TextSelectionHandle.xaml b/src/Avalonia.Themes.Simple/Controls/TextSelectionHandle.xaml index eb38e30d67..4d8c4b0d90 100644 --- a/src/Avalonia.Themes.Simple/Controls/TextSelectionHandle.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TextSelectionHandle.xaml @@ -85,21 +85,21 @@ - - - - -