From 4d3648f7326c0e6252a0e16899e67044ff367b5e Mon Sep 17 00:00:00 2001 From: redth Date: Thu, 13 Jun 2024 17:25:51 -0700 Subject: [PATCH 1/5] Don't receive touch when view is disabled --- .../GestureManager/GesturePlatformManager.iOS.cs | 5 +++++ .../Gestures/TapGestureRecognizerTests.cs | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs index 758342768947..128878f5e566 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs @@ -757,6 +757,11 @@ public bool ShouldReceiveTouch(UIGestureRecognizer recognizer, UITouch touch) return false; } + if (!virtualView.IsEnabled) + { + return false; + } + if (touch.View == platformView) { return true; diff --git a/src/Controls/tests/Core.UnitTests/Gestures/TapGestureRecognizerTests.cs b/src/Controls/tests/Core.UnitTests/Gestures/TapGestureRecognizerTests.cs index 6dd8ff80d085..c2dd12988f94 100644 --- a/src/Controls/tests/Core.UnitTests/Gestures/TapGestureRecognizerTests.cs +++ b/src/Controls/tests/Core.UnitTests/Gestures/TapGestureRecognizerTests.cs @@ -29,5 +29,21 @@ public void CallbackPassesParameter() tap.SendTapped(view); Assert.Equal(result, tap.CommandParameter); } + + [Fact] + public void NoCallbackWhenViewIsDisabled() + { + var view = new View + { + IsEnabled = false + }; + + var tap = new TapGestureRecognizer(); + object result = null; + tap.Command = new Command(o => result = o); + + tap.SendTapped(view); + Assert.Null(result); + } } } From 0f51eba524825b885bfd835d33d59d673fd02b39 Mon Sep 17 00:00:00 2001 From: redth Date: Mon, 17 Jun 2024 11:16:08 -0400 Subject: [PATCH 2/5] Add UITest for Single Tap enabled/disabled This removes the first pass unit test version which isn't really testing the scenario properly. --- .../Gestures/TapGestureRecognizerTests.cs | 16 ------ .../Tests/GestureRecognizerUITests.cs | 30 +++++++++++ .../Elements/GestureRecognizerGallery.cs | 1 + .../TestCases/Elements/TapGestureGallery.cs | 52 +++++++++++++++++++ 4 files changed, 83 insertions(+), 16 deletions(-) create mode 100644 src/Controls/tests/TestCases/Elements/TapGestureGallery.cs diff --git a/src/Controls/tests/Core.UnitTests/Gestures/TapGestureRecognizerTests.cs b/src/Controls/tests/Core.UnitTests/Gestures/TapGestureRecognizerTests.cs index c2dd12988f94..6dd8ff80d085 100644 --- a/src/Controls/tests/Core.UnitTests/Gestures/TapGestureRecognizerTests.cs +++ b/src/Controls/tests/Core.UnitTests/Gestures/TapGestureRecognizerTests.cs @@ -29,21 +29,5 @@ public void CallbackPassesParameter() tap.SendTapped(view); Assert.Equal(result, tap.CommandParameter); } - - [Fact] - public void NoCallbackWhenViewIsDisabled() - { - var view = new View - { - IsEnabled = false - }; - - var tap = new TapGestureRecognizer(); - object result = null; - tap.Command = new Command(o => result = o); - - tap.SendTapped(view); - Assert.Null(result); - } } } diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs index 5fd085c967df..1ee9a0ed7cea 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs @@ -52,5 +52,35 @@ public void DoubleTap() var result = App.FindElement("DoubleTapResults").GetText(); ClassicAssert.AreEqual("Success", result); } + + [Test] + [Category(UITestCategories.Gestures)] + public void SingleTap() + { + App.WaitForElement("TargetView"); + App.EnterText("TargetView", "SingleTapGallery"); + App.Tap("GoButton"); + + App.WaitForElement("SingleTapSurface"); + App.Tap("SingleTapSurface"); + + var result = App.FindElement("SingleTapResults").GetText(); + ClassicAssert.AreEqual("Success", result); + } + + [Test] + [Category(UITestCategories.Gestures)] + public void DisabledSingleTap() + { + App.WaitForElement("TargetView"); + App.EnterText("TargetView", "SingleTapGallery"); + App.Tap("GoButton"); + + App.WaitForElement("DisabledTapSurface"); + App.Tap("DisabledTapSurface"); + + var result = App.FindElement("DisabledTapResults").GetText(); + ClassicAssert.AreNotEqual("Success", result); + } } } \ No newline at end of file diff --git a/src/Controls/tests/TestCases/Elements/GestureRecognizerGallery.cs b/src/Controls/tests/TestCases/Elements/GestureRecognizerGallery.cs index cca7d286762e..a433ed2f3338 100644 --- a/src/Controls/tests/TestCases/Elements/GestureRecognizerGallery.cs +++ b/src/Controls/tests/TestCases/Elements/GestureRecognizerGallery.cs @@ -11,6 +11,7 @@ public GestureRecognizerGallery() { Add(new PointerGestureRecognizerEvents()); Add(new DoubleTapGallery()); + Add(new SingleTapGallery()); } } } diff --git a/src/Controls/tests/TestCases/Elements/TapGestureGallery.cs b/src/Controls/tests/TestCases/Elements/TapGestureGallery.cs new file mode 100644 index 000000000000..a0006434f794 --- /dev/null +++ b/src/Controls/tests/TestCases/Elements/TapGestureGallery.cs @@ -0,0 +1,52 @@ +using Microsoft.Maui.Controls; + +namespace Maui.Controls.Sample +{ + public class SingleTapGallery : Microsoft.Maui.Controls.ContentView + { + public SingleTapGallery() + { + AutomationId = nameof(SingleTapGallery); + + var layout = new VerticalStackLayout { Margin = 10, Spacing = 10 }; + + var singleTapResults = new Label { AutomationId = "SingleTapGestureResults", Text = "Should succeed."}; + var singleTapSurface = new Grid() + { + HeightRequest = 100, + WidthRequest = 200, + BackgroundColor = Microsoft.Maui.Graphics.Colors.AliceBlue, + Children = { new Label { Text = "SingleTapSurface", AutomationId = "SingleTapSurface" } } + }; + + var singleTapRecognizer = new TapGestureRecognizer(); + singleTapRecognizer.Tapped += (sender, args) => { singleTapResults.Text = "Success"; }; + singleTapSurface.GestureRecognizers.Add(singleTapRecognizer); + + layout.Add(singleTapSurface); + layout.Add(singleTapResults); + + + // Now add a tap surface that is disabled and a results label that should not change when the surface is tapped + var disabledTapResults = new Label { AutomationId = "DisabledTapGestureResults", Text = "Should not succeed" }; + var disabledTapSurface = new Grid() + { + IsEnabled = false, // Disabled + HeightRequest = 100, + WidthRequest = 200, + BackgroundColor = Microsoft.Maui.Graphics.Colors.Bisque, + Children = { new Label { Text = "DisabledTapSurface", AutomationId = "DisabledTapSurface" } } + }; + + // Wire up the tap gesture recognizer, it should never fire + var disabledTapRecognizer = new TapGestureRecognizer(); + disabledTapRecognizer.Tapped += (sender, args) => { disabledTapResults.Text = "Success"; }; + disabledTapSurface.GestureRecognizers.Add(disabledTapRecognizer); + + layout.Add(disabledTapSurface); + layout.Add(disabledTapResults); + + Content = layout; + } + } +} \ No newline at end of file From 2063ef87bea1e32954d0005a181cf58ccbbfc5f2 Mon Sep 17 00:00:00 2001 From: redth Date: Mon, 17 Jun 2024 15:04:36 -0400 Subject: [PATCH 3/5] Fix element automation id --- .../TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs index 1ee9a0ed7cea..b08b64549ddf 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs @@ -64,7 +64,7 @@ public void SingleTap() App.WaitForElement("SingleTapSurface"); App.Tap("SingleTapSurface"); - var result = App.FindElement("SingleTapResults").GetText(); + var result = App.FindElement("SingleTapGestureResults").GetText(); ClassicAssert.AreEqual("Success", result); } @@ -79,7 +79,7 @@ public void DisabledSingleTap() App.WaitForElement("DisabledTapSurface"); App.Tap("DisabledTapSurface"); - var result = App.FindElement("DisabledTapResults").GetText(); + var result = App.FindElement("DisabledTapGestureResults").GetText(); ClassicAssert.AreNotEqual("Success", result); } } From 4d93bafc8aea180c159a3b80845a71f22fe65017 Mon Sep 17 00:00:00 2001 From: redth Date: Mon, 17 Jun 2024 17:03:03 -0400 Subject: [PATCH 4/5] Don't fire tap for windows if control disabled --- .../GestureManager/GesturePlatformManager.Windows.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs index 75a511c14e25..ba6d8a98f69c 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs @@ -608,6 +608,11 @@ void OnTap(object sender, RoutedEventArgs e) if (view == null) return; + if (!view.IsEnabled) + { + return; + } + var tapPosition = e.GetPositionRelativeToPlatformElement(Control); if (tapPosition == null) From 0ffbcec12dcb291e589a86a0d527ea2405ce6e1a Mon Sep 17 00:00:00 2001 From: redth Date: Tue, 18 Jun 2024 10:34:42 -0400 Subject: [PATCH 5/5] Make failure case text less confusing --- .../TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs | 2 +- src/Controls/tests/TestCases/Elements/TapGestureGallery.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs index b08b64549ddf..d74956537c09 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/GestureRecognizerUITests.cs @@ -80,7 +80,7 @@ public void DisabledSingleTap() App.Tap("DisabledTapSurface"); var result = App.FindElement("DisabledTapGestureResults").GetText(); - ClassicAssert.AreNotEqual("Success", result); + ClassicAssert.AreNotEqual("Failed", result); } } } \ No newline at end of file diff --git a/src/Controls/tests/TestCases/Elements/TapGestureGallery.cs b/src/Controls/tests/TestCases/Elements/TapGestureGallery.cs index a0006434f794..1cc4028f0959 100644 --- a/src/Controls/tests/TestCases/Elements/TapGestureGallery.cs +++ b/src/Controls/tests/TestCases/Elements/TapGestureGallery.cs @@ -28,7 +28,7 @@ public SingleTapGallery() // Now add a tap surface that is disabled and a results label that should not change when the surface is tapped - var disabledTapResults = new Label { AutomationId = "DisabledTapGestureResults", Text = "Should not succeed" }; + var disabledTapResults = new Label { AutomationId = "DisabledTapGestureResults", Text = "Should not change when tapped" }; var disabledTapSurface = new Grid() { IsEnabled = false, // Disabled @@ -40,7 +40,7 @@ public SingleTapGallery() // Wire up the tap gesture recognizer, it should never fire var disabledTapRecognizer = new TapGestureRecognizer(); - disabledTapRecognizer.Tapped += (sender, args) => { disabledTapResults.Text = "Success"; }; + disabledTapRecognizer.Tapped += (sender, args) => { disabledTapResults.Text = "Failed"; }; disabledTapSurface.GestureRecognizers.Add(disabledTapRecognizer); layout.Add(disabledTapSurface);