diff --git a/src/Avalonia.Input/Gestures.cs b/src/Avalonia.Input/Gestures.cs index 65195394ab..02dda45e99 100644 --- a/src/Avalonia.Input/Gestures.cs +++ b/src/Avalonia.Input/Gestures.cs @@ -18,6 +18,11 @@ namespace Avalonia.Input RoutingStrategies.Bubble, typeof(Gestures)); + public static readonly RoutedEvent RightTappedEvent = RoutedEvent.Register( + "RightTapped", + RoutingStrategies.Bubble, + typeof(Gestures)); + public static readonly RoutedEvent ScrollGestureEvent = RoutedEvent.Register( "ScrollGesture", RoutingStrategies.Bubble, typeof(Gestures)); @@ -46,7 +51,7 @@ namespace Avalonia.Input } else if (s_lastPress?.IsAlive == true && e.ClickCount == 2 && s_lastPress.Target == e.Source) { - if (!ev.Handled) + if (e.MouseButton != MouseButton.Right) { e.Source.RaiseEvent(new RoutedEventArgs(DoubleTappedEvent)); } @@ -62,10 +67,8 @@ namespace Avalonia.Input if (s_lastPress?.IsAlive == true && s_lastPress.Target == e.Source) { - if (!ev.Handled) - { - ((IInteractive)s_lastPress.Target).RaiseEvent(new RoutedEventArgs(TappedEvent)); - } + var et = e.MouseButton != MouseButton.Right ? TappedEvent : RightTappedEvent; + ((IInteractive)s_lastPress.Target).RaiseEvent(new RoutedEventArgs(et)); } } } diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs index 2a61ff1566..27ddd95d20 100644 --- a/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs +++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests_Single.cs @@ -9,8 +9,8 @@ using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Input; using Avalonia.LogicalTree; -using Avalonia.Markup.Data; using Avalonia.Styling; +using Avalonia.UnitTests; using Avalonia.VisualTree; using Xunit; diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs index 4bcfeb6d03..be0f4272a5 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs @@ -13,7 +13,7 @@ using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Markup.Data; +using Avalonia.UnitTests; using Xunit; namespace Avalonia.Controls.UnitTests.Primitives diff --git a/tests/Avalonia.Input.UnitTests/GesturesTests.cs b/tests/Avalonia.Input.UnitTests/GesturesTests.cs new file mode 100644 index 0000000000..39c219a773 --- /dev/null +++ b/tests/Avalonia.Input.UnitTests/GesturesTests.cs @@ -0,0 +1,208 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System.Collections.Generic; +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.UnitTests; +using Xunit; + +namespace Avalonia.Interactivity.UnitTests +{ + public class GesturesTests + { + private MouseTestHelper _mouse = new MouseTestHelper(); + + [Fact] + public void Tapped_Should_Follow_Pointer_Pressed_Released() + { + Border border = new Border(); + var decorator = new Decorator + { + Child = border + }; + var result = new List(); + + AddHandlers(decorator, border, result, false); + + _mouse.Click(border); + + Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt" }, result); + } + + [Fact] + public void Tapped_Should_Be_Raised_Even_When_Pressed_Released_Handled() + { + Border border = new Border(); + var decorator = new Decorator + { + Child = border + }; + var result = new List(); + + AddHandlers(decorator, border, result, true); + + _mouse.Click(border); + + Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt" }, result); + } + + [Fact] + public void Tapped_Should_Be_Raised_For_Middle_Button() + { + Border border = new Border(); + var decorator = new Decorator + { + Child = border + }; + var raised = false; + + decorator.AddHandler(Gestures.TappedEvent, (s, e) => raised = true); + + _mouse.Click(border, MouseButton.Middle); + + Assert.True(raised); + } + + [Fact] + public void Tapped_Should_Not_Be_Raised_For_Right_Button() + { + Border border = new Border(); + var decorator = new Decorator + { + Child = border + }; + var raised = false; + + decorator.AddHandler(Gestures.TappedEvent, (s, e) => raised = true); + + _mouse.Click(border, MouseButton.Right); + + Assert.False(raised); + } + + [Fact] + public void RightTapped_Should_Be_Raised_For_Right_Button() + { + Border border = new Border(); + var decorator = new Decorator + { + Child = border + }; + var raised = false; + + decorator.AddHandler(Gestures.RightTappedEvent, (s, e) => raised = true); + + _mouse.Click(border, MouseButton.Right); + + Assert.True(raised); + } + + [Fact] + public void DoubleTapped_Should_Follow_Pointer_Pressed_Released_Pressed() + { + Border border = new Border(); + var decorator = new Decorator + { + Child = border + }; + var result = new List(); + + AddHandlers(decorator, border, result, false); + + _mouse.Click(border); + _mouse.Down(border, clickCount: 2); + + Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt", "bp", "dp", "bdt", "ddt" }, result); + } + + [Fact] + public void DoubleTapped_Should_Be_Raised_Even_When_Pressed_Released_Handled() + { + Border border = new Border(); + var decorator = new Decorator + { + Child = border + }; + var result = new List(); + + AddHandlers(decorator, border, result, true); + + _mouse.Click(border); + _mouse.Down(border, clickCount: 2); + + Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt", "bp", "dp", "bdt", "ddt" }, result); + } + + [Fact] + public void DoubleTapped_Should_Be_Raised_For_Middle_Button() + { + Border border = new Border(); + var decorator = new Decorator + { + Child = border + }; + var raised = false; + + decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => raised = true); + + _mouse.Click(border, MouseButton.Middle); + _mouse.Down(border, MouseButton.Middle, clickCount: 2); + + Assert.True(raised); + } + + [Fact] + public void DoubleTapped_Should_Not_Be_Raised_For_Right_Button() + { + Border border = new Border(); + var decorator = new Decorator + { + Child = border + }; + var raised = false; + + decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => raised = true); + + _mouse.Click(border, MouseButton.Right); + _mouse.Down(border, MouseButton.Right, clickCount: 2); + + Assert.False(raised); + } + + private void AddHandlers( + Decorator decorator, + Border border, + IList result, + bool markHandled) + { + decorator.AddHandler(Border.PointerPressedEvent, (s, e) => + { + result.Add("dp"); + + if (markHandled) + { + e.Handled = true; + } + }); + + decorator.AddHandler(Border.PointerReleasedEvent, (s, e) => + { + result.Add("dr"); + + if (markHandled) + { + e.Handled = true; + } + }); + + border.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("bp")); + border.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("br")); + + decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt")); + decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("ddt")); + border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt")); + border.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("bdt")); + } + } +} diff --git a/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj b/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj index 7316b1de3d..2bde78ad63 100644 --- a/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj +++ b/tests/Avalonia.Interactivity.UnitTests/Avalonia.Interactivity.UnitTests.csproj @@ -20,7 +20,7 @@ - + diff --git a/tests/Avalonia.Interactivity.UnitTests/GestureTests.cs b/tests/Avalonia.Interactivity.UnitTests/GestureTests.cs deleted file mode 100644 index 69bdf58f9d..0000000000 --- a/tests/Avalonia.Interactivity.UnitTests/GestureTests.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) The Avalonia Project. All rights reserved. -// Licensed under the MIT license. See licence.md file in the project root for full license information. - -using System.Collections.Generic; -using Avalonia.Controls; -using Avalonia.Controls.UnitTests; -using Avalonia.Input; -using Xunit; - -namespace Avalonia.Interactivity.UnitTests -{ - public class GestureTests - { - private MouseTestHelper _mouse = new MouseTestHelper(); - - [Fact] - public void Tapped_Should_Follow_Pointer_Pressed_Released() - { - Border border = new Border(); - var decorator = new Decorator - { - Child = border - }; - var result = new List(); - - decorator.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("dp")); - decorator.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("dr")); - decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt")); - border.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("bp")); - border.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("br")); - border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt")); - - _mouse.Click(border); - - Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt" }, result); - } - - [Fact] - public void Tapped_Should_Be_Raised_Even_When_PointerPressed_Handled() - { - Border border = new Border(); - var decorator = new Decorator - { - Child = border - }; - var result = new List(); - - border.AddHandler(Border.PointerPressedEvent, (s, e) => e.Handled = true); - decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt")); - border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt")); - - _mouse.Click(border); - - Assert.Equal(new[] { "bt", "dt" }, result); - } - - [Fact] - public void DoubleTapped_Should_Follow_Pointer_Pressed_Released_Pressed() - { - Border border = new Border(); - var decorator = new Decorator - { - Child = border - }; - var result = new List(); - - decorator.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("dp")); - decorator.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("dr")); - decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt")); - decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("ddt")); - border.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("bp")); - border.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("br")); - border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt")); - border.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("bdt")); - - _mouse.Click(border); - _mouse.Down(border, clickCount: 2); - - Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt", "bp", "dp", "bdt", "ddt" }, result); - } - - [Fact] - public void DoubleTapped_Should_Not_Be_Rasied_if_Pressed_is_Handled() - { - Border border = new Border(); - var decorator = new Decorator - { - Child = border - }; - var result = new List(); - - decorator.AddHandler(Border.PointerPressedEvent, (s, e) => - { - result.Add("dp"); - e.Handled = true; - }); - - decorator.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("dr")); - decorator.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("dt")); - decorator.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("ddt")); - border.AddHandler(Border.PointerPressedEvent, (s, e) => result.Add("bp")); - border.AddHandler(Border.PointerReleasedEvent, (s, e) => result.Add("br")); - border.AddHandler(Gestures.TappedEvent, (s, e) => result.Add("bt")); - border.AddHandler(Gestures.DoubleTappedEvent, (s, e) => result.Add("bdt")); - - _mouse.Click(border); - _mouse.Down(border, clickCount: 2); - - Assert.Equal(new[] { "bp", "dp", "br", "dr", "bt", "dt", "bp", "dp" }, result); - } - } -} diff --git a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj index f065fcb63d..ae901ca2f2 100644 --- a/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj +++ b/tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj @@ -1,6 +1,7 @@  netstandard2.0 + latest false Library false diff --git a/tests/Avalonia.Controls.UnitTests/MouseTestHelper.cs b/tests/Avalonia.UnitTests/MouseTestHelper.cs similarity index 98% rename from tests/Avalonia.Controls.UnitTests/MouseTestHelper.cs rename to tests/Avalonia.UnitTests/MouseTestHelper.cs index 373bbaed75..00ad850cf8 100644 --- a/tests/Avalonia.Controls.UnitTests/MouseTestHelper.cs +++ b/tests/Avalonia.UnitTests/MouseTestHelper.cs @@ -1,9 +1,8 @@ -using System.Reactive; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.VisualTree; -namespace Avalonia.Controls.UnitTests +namespace Avalonia.UnitTests { public class MouseTestHelper {