diff --git a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems index df5919797d12..0890fa6560f4 100644 --- a/src/SamplesApp/UITests.Shared/UITests.Shared.projitems +++ b/src/SamplesApp/UITests.Shared/UITests.Shared.projitems @@ -3570,6 +3570,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -9150,6 +9154,9 @@ NavigationView_TopNavigation.xaml + + NavigationView_Tapped.xaml + ListView_DataContext_Propagation.xaml diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/NavigationViewTests/NavigationView_Tapped.xaml b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/NavigationViewTests/NavigationView_Tapped.xaml new file mode 100644 index 000000000000..51a1da3b66bd --- /dev/null +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/NavigationViewTests/NavigationView_Tapped.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + + + Manual test for https://github.com/unoplatform/uno/issues/18024 + + Test steps: + + 1. Press the hamburger menu on the left. A pane is supposed to open up (or expand). + + 2. Press the "Item 1" item in the pane. A new "Item 1.1" item should appear. + + 3. Press the "Item 1.1" item in the pane. The pane is supposed to collapse. (IMPORTANT) No popups or tooltips should be visible. + + + diff --git a/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/NavigationViewTests/NavigationView_Tapped.xaml.cs b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/NavigationViewTests/NavigationView_Tapped.xaml.cs new file mode 100644 index 000000000000..59216ef6cc8c --- /dev/null +++ b/src/SamplesApp/UITests.Shared/Windows_UI_Xaml_Controls/NavigationViewTests/NavigationView_Tapped.xaml.cs @@ -0,0 +1,14 @@ +using Uno.UI.Samples.Controls; +using Microsoft.UI.Xaml.Controls; + +namespace UITests.Shared.Windows_UI_Xaml_Controls.NavigationViewTests +{ + [SampleControlInfo("NavigationView", nameof(NavigationView_Tapped), IsManualTest = true)] + public sealed partial class NavigationView_Tapped : UserControl + { + public NavigationView_Tapped() + { + this.InitializeComponent(); + } + } +} diff --git a/src/Uno.UI/UI/Xaml/Input/PointerRoutedEventArgs.Android.cs b/src/Uno.UI/UI/Xaml/Input/PointerRoutedEventArgs.Android.cs index 044f130d36d9..08d86ad9a1ae 100644 --- a/src/Uno.UI/UI/Xaml/Input/PointerRoutedEventArgs.Android.cs +++ b/src/Uno.UI/UI/Xaml/Input/PointerRoutedEventArgs.Android.cs @@ -39,6 +39,12 @@ partial class PointerRoutedEventArgs private const int _pointerIdsCount = (int)MotionEventActions.PointerIndexMask >> (int)MotionEventActions.PointerIndexShift; // 0xff private const int _pointerIdsShift = 31 - (int)MotionEventActions.PointerIndexShift; // 23 + // _lastNativeEvent.lastArgs is not necessary equal to LastPointerEvent. _lastNativeEvent.lastArgs is + // the last PointerRoutedEventArgs that was created as part of the native bubbling of _lastNativeEvent.nativeEvent. + // In other words, if a PointerRoutedEventArgs was created in managed (using the parameterless constructor), + // then _lastNativeEvent.lastArgs and LastPointerEvent will diverge. + private static (MotionEvent nativeEvent, PointerRoutedEventArgs lastArgs)? _lastNativeEvent; + private readonly MotionEvent _nativeEvent; private readonly int _pointerIndex; private readonly UIElement _receiver; @@ -72,6 +78,18 @@ internal PointerRoutedEventArgs(MotionEvent nativeEvent, int pointerIndex, UIEle KeyModifiers = keys; OriginalSource = originalSource; + // On platforms with managed pointers, we reuse the same PointerRoutedEventArgs instance + // as we bubble up the event in the visual tree. On Android, the event bubbling is done + // natively and we create a corresponding (new) managed PointerRoutedEventArgs instance + // for each element up the tree. This means that parents won't see modifications in the + // PointerRoutedEventArgs instance that were done by the children. We have to detect + // this and copy the relevant fields ourselves. + if (_lastNativeEvent?.nativeEvent == nativeEvent) + { + GestureEventsAlreadyRaised = _lastNativeEvent.Value.lastArgs.GestureEventsAlreadyRaised; + } + _lastNativeEvent = (nativeEvent, this); + var inputManager = VisualTree.GetContentRootForElement(originalSource)?.InputManager; if (inputManager is not null) {