Browse Source

Improve pen secondary button handling on list box (#18766)

* Only start ScrollGesture when left click pressed, also `GetCurrentPoint(null)` behaves the same as root visual

* Allow right-click pen to select items on press

* Add context menus to even items on ListBox page for testing

* Avoid global static in UpdateSelectionFromPointerEvent

* Revert "Avoid global static in UpdateSelectionFromPointerEvent"

This reverts commit 2562d73e83.

* Add comment to UpdateSelectionFromPointerEvent

* Use fully mocked rendering for list box test

* Add pen selection tests

* TouchTestHelper should use correct inputs
pull/18892/head
Maxwell Katz 1 year ago
committed by GitHub
parent
commit
338a5ea0a2
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 7
      samples/ControlCatalog/Pages/ListBoxPage.xaml
  2. 12
      src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs
  3. 1
      src/Avalonia.Controls/ListBox.cs
  4. 6
      src/Avalonia.Controls/ListBoxItem.cs
  5. 28
      tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
  6. 192
      tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs
  7. 4
      tests/Avalonia.UnitTests/MouseTestHelper.cs
  8. 9
      tests/Avalonia.UnitTests/TouchTestHelper.cs

7
samples/ControlCatalog/Pages/ListBoxPage.xaml

@ -5,6 +5,13 @@
x:DataType="viewModels:ListBoxPageViewModel"> x:DataType="viewModels:ListBoxPageViewModel">
<DockPanel> <DockPanel>
<DockPanel.Styles> <DockPanel.Styles>
<Style Selector="ListBox ListBoxItem:nth-child(even)">
<Setter Property="ContextFlyout">
<MenuFlyout>
<MenuItem Header="Hello there" />
</MenuFlyout>
</Setter>
</Style>
<Style Selector="ListBox ListBoxItem:nth-child(5n+3)"> <Style Selector="ListBox ListBoxItem:nth-child(5n+3)">
<Setter Property="Foreground" Value="Red" /> <Setter Property="Foreground" Value="Red" />
<Setter Property="FontWeight" Value="Bold" /> <Setter Property="FontWeight" Value="Bold" />

12
src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs

@ -23,7 +23,6 @@ namespace Avalonia.Input.GestureRecognizers
private int _gestureId; private int _gestureId;
private Point _pointerPressedPoint; private Point _pointerPressedPoint;
private VelocityTracker? _velocityTracker; private VelocityTracker? _velocityTracker;
private Visual? _rootTarget;
// Movement per second // Movement per second
private Vector _inertia; private Vector _inertia;
@ -96,13 +95,15 @@ namespace Avalonia.Input.GestureRecognizers
protected override void PointerPressed(PointerPressedEventArgs e) protected override void PointerPressed(PointerPressedEventArgs e)
{ {
if (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen) var point = e.GetCurrentPoint(null);
if (e.Pointer.Type is PointerType.Touch or PointerType.Pen
&& point.Properties.IsLeftButtonPressed)
{ {
EndGesture(); EndGesture();
_tracking = e.Pointer; _tracking = e.Pointer;
_gestureId = ScrollGestureEventArgs.GetNextFreeId(); _gestureId = ScrollGestureEventArgs.GetNextFreeId();
_rootTarget = (Visual?)(Target as Visual)?.VisualRoot; _trackedRootPoint = _pointerPressedPoint = point.Position;
_trackedRootPoint = _pointerPressedPoint = e.GetPosition(_rootTarget);
_velocityTracker = new VelocityTracker(); _velocityTracker = new VelocityTracker();
_velocityTracker?.AddPosition(TimeSpan.FromMilliseconds(e.Timestamp), default); _velocityTracker?.AddPosition(TimeSpan.FromMilliseconds(e.Timestamp), default);
} }
@ -112,7 +113,7 @@ namespace Avalonia.Input.GestureRecognizers
{ {
if (e.Pointer == _tracking) if (e.Pointer == _tracking)
{ {
var rootPoint = e.GetPosition(_rootTarget); var rootPoint = e.GetPosition(null);
if (!_scrolling) if (!_scrolling)
{ {
if (CanHorizontallyScroll && Math.Abs(_trackedRootPoint.X - rootPoint.X) > ScrollStartDistance) if (CanHorizontallyScroll && Math.Abs(_trackedRootPoint.X - rootPoint.X) > ScrollStartDistance)
@ -159,7 +160,6 @@ namespace Avalonia.Input.GestureRecognizers
Target!.RaiseEvent(new ScrollGestureEndedEventArgs(_gestureId)); Target!.RaiseEvent(new ScrollGestureEndedEventArgs(_gestureId));
_gestureId = 0; _gestureId = 0;
_lastMoveTimestamp = null; _lastMoveTimestamp = null;
_rootTarget = null;
} }
} }

1
src/Avalonia.Controls/ListBox.cs

@ -166,6 +166,7 @@ namespace Avalonia.Controls
internal bool UpdateSelectionFromPointerEvent(Control source, PointerEventArgs e) internal bool UpdateSelectionFromPointerEvent(Control source, PointerEventArgs e)
{ {
// TODO: use TopLevel.PlatformSettings here, but first need to update our tests to use TopLevels.
var hotkeys = Application.Current!.PlatformSettings?.HotkeyConfiguration; var hotkeys = Application.Current!.PlatformSettings?.HotkeyConfiguration;
var toggle = hotkeys is not null && e.KeyModifiers.HasAllFlags(hotkeys.CommandModifiers); var toggle = hotkeys is not null && e.KeyModifiers.HasAllFlags(hotkeys.CommandModifiers);

6
src/Avalonia.Controls/ListBoxItem.cs

@ -64,9 +64,11 @@ namespace Avalonia.Controls
if (p.Properties.PointerUpdateKind is PointerUpdateKind.LeftButtonPressed or if (p.Properties.PointerUpdateKind is PointerUpdateKind.LeftButtonPressed or
PointerUpdateKind.RightButtonPressed) PointerUpdateKind.RightButtonPressed)
{ {
if (p.Pointer.Type == PointerType.Mouse) if (p.Pointer.Type == PointerType.Mouse
|| (p.Pointer.Type == PointerType.Pen && p.Properties.IsRightButtonPressed))
{ {
// If the pressed point comes from a mouse, perform the selection immediately. // If the pressed point comes from a mouse or right-click pen, perform the selection immediately.
// In case of pen, only right-click is accepted, as left click (a tip touch) is used for scrolling.
e.Handled = owner.UpdateSelectionFromPointerEvent(this, e); e.Handled = owner.UpdateSelectionFromPointerEvent(this, e);
} }
else else

28
tests/Avalonia.Controls.UnitTests/ListBoxTests.cs

@ -611,17 +611,6 @@ namespace Avalonia.Controls.UnitTests
}.RegisterInNameScope(scope)); }.RegisterInNameScope(scope));
} }
private static FuncControlTemplate ListBoxItemTemplate()
{
return new FuncControlTemplate<ListBoxItem>((parent, scope) =>
new ContentPresenter
{
Name = "PART_ContentPresenter",
[!ContentPresenter.ContentProperty] = parent[!ListBoxItem.ContentProperty],
[!ContentPresenter.ContentTemplateProperty] = parent[!ListBoxItem.ContentTemplateProperty],
}.RegisterInNameScope(scope));
}
private static FuncControlTemplate ScrollViewerTemplate() private static FuncControlTemplate ScrollViewerTemplate()
{ {
return new FuncControlTemplate<ScrollViewer>((parent, scope) => return new FuncControlTemplate<ScrollViewer>((parent, scope) =>
@ -645,21 +634,7 @@ namespace Avalonia.Controls.UnitTests
private static void Prepare(ListBox target) private static void Prepare(ListBox target)
{ {
target.Width = target.Height = 100; target.Width = target.Height = 100;
var root = new TestRoot(target);
var root = new TestRoot(target)
{
Resources =
{
{
typeof(ListBoxItem),
new ControlTheme(typeof(ListBoxItem))
{
Setters = { new Setter(ListBoxItem.TemplateProperty, ListBoxItemTemplate()) }
}
}
}
};
root.LayoutManager.ExecuteInitialLayoutPass(); root.LayoutManager.ExecuteInitialLayoutPass();
} }
@ -1263,7 +1238,6 @@ namespace Avalonia.Controls.UnitTests
{ {
new ListBoxItem() new ListBoxItem()
{ {
Template = ListBoxItemTemplate(),
Content = target, Content = target,
} }
} }

192
tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs

@ -6,6 +6,7 @@ using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.GestureRecognizers;
using Avalonia.Input.Platform; using Avalonia.Input.Platform;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Avalonia.Styling; using Avalonia.Styling;
@ -19,30 +20,34 @@ namespace Avalonia.Controls.UnitTests
public class ListBoxTests_Single : ScopedTestBase public class ListBoxTests_Single : ScopedTestBase
{ {
MouseTestHelper _mouse = new MouseTestHelper(); MouseTestHelper _mouse = new MouseTestHelper();
MouseTestHelper _pen = new MouseTestHelper(PointerType.Pen);
[Fact] [Fact]
public void Focusing_Item_With_Tab_Should_Not_Select_It() public void Focusing_Item_With_Tab_Should_Not_Select_It()
{ {
var target = new ListBox using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Template = new FuncControlTemplate(CreateListBoxTemplate), var target = new ListBox
ItemsSource = new[] { "Foo", "Bar", "Baz " }, {
}; Template = new FuncControlTemplate(CreateListBoxTemplate),
ItemsSource = new[] { "Foo", "Bar", "Baz " },
};
ApplyTemplate(target); Prepare(target);
target.Presenter.Panel.Children[0].RaiseEvent(new GotFocusEventArgs target.Presenter.Panel.Children[0].RaiseEvent(new GotFocusEventArgs
{ {
NavigationMethod = NavigationMethod.Tab, NavigationMethod = NavigationMethod.Tab,
}); });
Assert.Equal(-1, target.SelectedIndex); Assert.Equal(-1, target.SelectedIndex);
}
} }
[Fact] [Fact]
public void Pressing_Space_On_Focused_Item_With_Ctrl_Pressed_Should_Select_It() public void Pressing_Space_On_Focused_Item_With_Ctrl_Pressed_Should_Select_It()
{ {
using (UnitTestApplication.Start()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var target = new ListBox var target = new ListBox
{ {
@ -50,7 +55,7 @@ namespace Avalonia.Controls.UnitTests
ItemsSource = new[] { "Foo", "Bar", "Baz " }, ItemsSource = new[] { "Foo", "Bar", "Baz " },
}; };
AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration()); AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration());
ApplyTemplate(target); Prepare(target);
target.Presenter.Panel.Children[0].RaiseEvent(new GotFocusEventArgs target.Presenter.Panel.Children[0].RaiseEvent(new GotFocusEventArgs
{ {
@ -72,7 +77,7 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void Clicking_Item_Should_Select_It() public void Clicking_Item_Should_Select_It()
{ {
using (UnitTestApplication.Start()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var target = new ListBox var target = new ListBox
{ {
@ -80,17 +85,88 @@ namespace Avalonia.Controls.UnitTests
ItemsSource = new[] { "Foo", "Bar", "Baz " }, ItemsSource = new[] { "Foo", "Bar", "Baz " },
}; };
AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration()); AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration());
ApplyTemplate(target); Prepare(target);
_mouse.Click(target.Presenter.Panel.Children[0]); _mouse.Click(target.Presenter.Panel.Children[0]);
Assert.Equal(0, target.SelectedIndex); Assert.Equal(0, target.SelectedIndex);
} }
} }
[Fact]
public void Pen_Right_Press_Item_Should_Select_It()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var target = new ListBox
{
Template = new FuncControlTemplate(CreateListBoxTemplate),
ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
ItemsSource = new[] { "Foo", "Bar", "Baz " }
};
Prepare(target);
_pen.Down(target.Presenter.Panel.Children[0], MouseButton.Right);
Assert.Equal(0, target.SelectedIndex);
}
}
[Fact]
public void Pen_Left_Press_Item_Should_Not_Select_It()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var target = new ListBox
{
Template = new FuncControlTemplate(CreateListBoxTemplate),
ItemTemplate = new FuncDataTemplate<string>((x, _) => new TextBlock { Width = 20, Height = 10 }),
ItemsSource = new[] { "Foo", "Bar", "Baz " }
};
Prepare(target);
_pen.Down(target.Presenter.Panel.Children[0]);
Assert.Equal(-1, target.SelectedIndex);
}
}
[Theory]
[InlineData(PointerType.Mouse)]
[InlineData(PointerType.Pen)]
public void Pointer_Right_Click_Should_Select_Item_And_Open_Context(PointerType type)
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var target = new ListBox
{
Template = new FuncControlTemplate(CreateListBoxTemplate),
ItemsSource = new[] { "Foo", "Bar", "Baz " },
ItemTemplate = new FuncDataTemplate<string>((x, _) => new Border { Height = 10 })
};
target.GestureRecognizers.Add(new ScrollGestureRecognizer()
{
CanVerticallyScroll = true, ScrollStartDistance = 50
});
Prepare(target);
var contextRaised = false;
target.AddHandler(Control.ContextRequestedEvent, (sender, args) =>
{
contextRaised = true;
args.Handled = true;
});
var pointer = type == PointerType.Mouse ? _mouse : _pen;
pointer.Click(target.Presenter.Panel.Children[0], MouseButton.Right, position: new Point(5, 5));
Assert.True(contextRaised);
Assert.Equal(0, target.SelectedIndex);
}
}
[Fact] [Fact]
public void Clicking_Selected_Item_Should_Not_Deselect_It() public void Clicking_Selected_Item_Should_Not_Deselect_It()
{ {
using (UnitTestApplication.Start()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var target = new ListBox var target = new ListBox
{ {
@ -98,7 +174,7 @@ namespace Avalonia.Controls.UnitTests
ItemsSource = new[] { "Foo", "Bar", "Baz " }, ItemsSource = new[] { "Foo", "Bar", "Baz " },
}; };
AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration()); AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration());
ApplyTemplate(target); Prepare(target);
target.SelectedIndex = 0; target.SelectedIndex = 0;
_mouse.Click(target.Presenter.Panel.Children[0]); _mouse.Click(target.Presenter.Panel.Children[0]);
@ -110,7 +186,7 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void Clicking_Item_Should_Select_It_When_SelectionMode_Toggle() public void Clicking_Item_Should_Select_It_When_SelectionMode_Toggle()
{ {
using (UnitTestApplication.Start()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var target = new ListBox var target = new ListBox
{ {
@ -119,7 +195,7 @@ namespace Avalonia.Controls.UnitTests
SelectionMode = SelectionMode.Single | SelectionMode.Toggle, SelectionMode = SelectionMode.Single | SelectionMode.Toggle,
}; };
AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration()); AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration());
ApplyTemplate(target); Prepare(target);
_mouse.Click(target.Presenter.Panel.Children[0]); _mouse.Click(target.Presenter.Panel.Children[0]);
@ -130,7 +206,7 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void Clicking_Selected_Item_Should_Deselect_It_When_SelectionMode_Toggle() public void Clicking_Selected_Item_Should_Deselect_It_When_SelectionMode_Toggle()
{ {
using (UnitTestApplication.Start()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var target = new ListBox var target = new ListBox
{ {
@ -140,7 +216,7 @@ namespace Avalonia.Controls.UnitTests
}; };
AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration()); AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration());
ApplyTemplate(target); Prepare(target);
target.SelectedIndex = 0; target.SelectedIndex = 0;
_mouse.Click(target.Presenter.Panel.Children[0]); _mouse.Click(target.Presenter.Panel.Children[0]);
@ -152,7 +228,7 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void Clicking_Selected_Item_Should_Not_Deselect_It_When_SelectionMode_ToggleAlwaysSelected() public void Clicking_Selected_Item_Should_Not_Deselect_It_When_SelectionMode_ToggleAlwaysSelected()
{ {
using (UnitTestApplication.Start()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var target = new ListBox var target = new ListBox
{ {
@ -161,7 +237,7 @@ namespace Avalonia.Controls.UnitTests
SelectionMode = SelectionMode.Toggle | SelectionMode.AlwaysSelected, SelectionMode = SelectionMode.Toggle | SelectionMode.AlwaysSelected,
}; };
AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration()); AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration());
ApplyTemplate(target); Prepare(target);
target.SelectedIndex = 0; target.SelectedIndex = 0;
_mouse.Click(target.Presenter.Panel.Children[0]); _mouse.Click(target.Presenter.Panel.Children[0]);
@ -173,7 +249,7 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void Clicking_Another_Item_Should_Select_It_When_SelectionMode_Toggle() public void Clicking_Another_Item_Should_Select_It_When_SelectionMode_Toggle()
{ {
using (UnitTestApplication.Start()) using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
var target = new ListBox var target = new ListBox
{ {
@ -182,7 +258,7 @@ namespace Avalonia.Controls.UnitTests
SelectionMode = SelectionMode.Single | SelectionMode.Toggle, SelectionMode = SelectionMode.Single | SelectionMode.Toggle,
}; };
AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration()); AvaloniaLocator.CurrentMutable.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration());
ApplyTemplate(target); Prepare(target);
target.SelectedIndex = 1; target.SelectedIndex = 1;
_mouse.Click(target.Presenter.Panel.Children[0]); _mouse.Click(target.Presenter.Panel.Children[0]);
@ -194,45 +270,48 @@ namespace Avalonia.Controls.UnitTests
[Fact] [Fact]
public void Setting_Item_IsSelected_Sets_ListBox_Selection() public void Setting_Item_IsSelected_Sets_ListBox_Selection()
{ {
var target = new ListBox using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Template = new FuncControlTemplate(CreateListBoxTemplate), var target = new ListBox
ItemsSource = new[] { "Foo", "Bar", "Baz " }, {
}; Template = new FuncControlTemplate(CreateListBoxTemplate),
ItemsSource = new[] { "Foo", "Bar", "Baz " },
};
ApplyTemplate(target); Prepare(target);
((ListBoxItem)target.GetLogicalChildren().ElementAt(1)).IsSelected = true; ((ListBoxItem)target.GetLogicalChildren().ElementAt(1)).IsSelected = true;
Assert.Equal("Bar", target.SelectedItem); Assert.Equal("Bar", target.SelectedItem);
Assert.Equal(1, target.SelectedIndex); Assert.Equal(1, target.SelectedIndex);
}
} }
[Fact] [Fact]
public void SelectedItem_Should_Not_Cause_StackOverflow() public void SelectedItem_Should_Not_Cause_StackOverflow()
{ {
var viewModel = new TestStackOverflowViewModel() using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{ {
Items = new List<string> { "foo", "bar", "baz" } var viewModel = new TestStackOverflowViewModel() { Items = new List<string> { "foo", "bar", "baz" } };
};
var target = new ListBox var target = new ListBox
{ {
Template = new FuncControlTemplate(CreateListBoxTemplate), Template = new FuncControlTemplate(CreateListBoxTemplate),
DataContext = viewModel, DataContext = viewModel,
ItemsSource = viewModel.Items ItemsSource = viewModel.Items
}; };
target.Bind(ListBox.SelectedItemProperty, target.Bind(ListBox.SelectedItemProperty,
new Binding("SelectedItem") { Mode = BindingMode.TwoWay }); new Binding("SelectedItem") { Mode = BindingMode.TwoWay });
Assert.Equal(0, viewModel.SetterInvokedCount); Assert.Equal(0, viewModel.SetterInvokedCount);
// In Issue #855, a Stackoverflow occurred here. // In Issue #855, a Stackoverflow occurred here.
target.SelectedItem = viewModel.Items[2]; target.SelectedItem = viewModel.Items[2];
Assert.Equal(viewModel.Items[1], target.SelectedItem); Assert.Equal(viewModel.Items[1], target.SelectedItem);
Assert.Equal(1, viewModel.SetterInvokedCount); Assert.Equal(1, viewModel.SetterInvokedCount);
}
} }
private class TestStackOverflowViewModel : INotifyPropertyChanged private class TestStackOverflowViewModel : INotifyPropertyChanged
@ -295,20 +374,11 @@ namespace Avalonia.Controls.UnitTests
}.RegisterInNameScope(scope); }.RegisterInNameScope(scope);
} }
private static void ApplyTemplate(ListBox target) private static void Prepare(ListBox target)
{ {
// Apply the template to the ListBox itself. target.Width = target.Height = 100;
target.ApplyTemplate(); var root = new TestRoot(target);
root.LayoutManager.ExecuteInitialLayoutPass();
// Then to its inner ScrollViewer.
var scrollViewer = (ScrollViewer)target.GetVisualChildren().Single();
scrollViewer.ApplyTemplate();
// Then make the ScrollViewer create its child.
scrollViewer.Presenter.UpdateChild();
// Now the ItemsPresenter should be registered, so apply its template.
target.Presenter.ApplyTemplate();
} }
} }
} }

4
tests/Avalonia.UnitTests/MouseTestHelper.cs

@ -4,9 +4,9 @@ using Avalonia.VisualTree;
namespace Avalonia.UnitTests namespace Avalonia.UnitTests
{ {
public class MouseTestHelper public class MouseTestHelper(PointerType pointerType = PointerType.Mouse)
{ {
private readonly Pointer _pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); private readonly Pointer _pointer = new Pointer(Pointer.GetNextFreeId(), pointerType, true);
private ulong _nextStamp = 1; private ulong _nextStamp = 1;
private ulong Timestamp() => _nextStamp++; private ulong Timestamp() => _nextStamp++;

9
tests/Avalonia.UnitTests/TouchTestHelper.cs

@ -19,7 +19,8 @@ namespace Avalonia.UnitTests
public void Down(Interactive target, Interactive source, Point position = default, KeyModifiers modifiers = default) public void Down(Interactive target, Interactive source, Point position = default, KeyModifiers modifiers = default)
{ {
_pointer.Capture((IInputElement)target); _pointer.Capture((IInputElement)target);
source.RaiseEvent(new PointerPressedEventArgs(source, _pointer, (Visual)source, position, Timestamp(), PointerPointProperties.None, source.RaiseEvent(new PointerPressedEventArgs(source, _pointer, (Visual)source, position, Timestamp(),
new(RawInputModifiers.LeftMouseButton, PointerUpdateKind.LeftButtonPressed),
modifiers)); modifiers));
} }
@ -28,7 +29,7 @@ namespace Avalonia.UnitTests
public void Move(Interactive target, Interactive source, in Point position, KeyModifiers modifiers = default) public void Move(Interactive target, Interactive source, in Point position, KeyModifiers modifiers = default)
{ {
var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)target, position, var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, (Visual)target, position,
Timestamp(), PointerPointProperties.None, modifiers); Timestamp(), new(RawInputModifiers.LeftMouseButton, PointerUpdateKind.Other), modifiers);
if (_pointer.CapturedGestureRecognizer != null) if (_pointer.CapturedGestureRecognizer != null)
_pointer.CapturedGestureRecognizer.PointerMovedInternal(e); _pointer.CapturedGestureRecognizer.PointerMovedInternal(e);
else else
@ -41,8 +42,8 @@ namespace Avalonia.UnitTests
public void Up(Interactive target, Interactive source, Point position = default, KeyModifiers modifiers = default) public void Up(Interactive target, Interactive source, Point position = default, KeyModifiers modifiers = default)
{ {
var e = new PointerReleasedEventArgs(source, _pointer, (Visual)target, position, Timestamp(), PointerPointProperties.None, var e = new PointerReleasedEventArgs(source, _pointer, (Visual)target, position, Timestamp(),
modifiers, MouseButton.None); new(RawInputModifiers.None, PointerUpdateKind.LeftButtonReleased), modifiers, MouseButton.Left);
if (_pointer.CapturedGestureRecognizer != null) if (_pointer.CapturedGestureRecognizer != null)
_pointer.CapturedGestureRecognizer.PointerReleasedInternal(e); _pointer.CapturedGestureRecognizer.PointerReleasedInternal(e);

Loading…
Cancel
Save