diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 57e80c97b02a..ffddf62a43cb 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -12,21 +12,21 @@
https://github.com/xamarin/xamarin-android
caf6f3cd02fef236dbe7bd5a1dae5d073a3e40c5
-
+
https://github.com/xamarin/xamarin-macios
- 0e53b999d279ef18eb8c27fc72f596d002882365
+ 3198941d450cfc98491cc71c322b1c86b3d6a5fa
-
+
https://github.com/xamarin/xamarin-macios
- 0e53b999d279ef18eb8c27fc72f596d002882365
+ 3198941d450cfc98491cc71c322b1c86b3d6a5fa
-
+
https://github.com/xamarin/xamarin-macios
- 0e53b999d279ef18eb8c27fc72f596d002882365
+ 3198941d450cfc98491cc71c322b1c86b3d6a5fa
-
+
https://github.com/xamarin/xamarin-macios
- 0e53b999d279ef18eb8c27fc72f596d002882365
+ 3198941d450cfc98491cc71c322b1c86b3d6a5fa
https://github.com/dotnet/emsdk
diff --git a/eng/Versions.props b/eng/Versions.props
index a92f11443a2c..44bc292d7236 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -13,10 +13,10 @@
33.0.0-rc.1.125
- 15.4.1006-rc.1
- 15.4.1006-rc.1
- 12.3.1006-rc.1
- 15.4.1006-rc.1
+ 15.4.1009-rc.1
+ 15.4.1009-rc.1
+ 12.3.1009-rc.1
+ 15.4.1009-rc.1
7.0.100-rc.1.22
diff --git a/src/Compatibility/ControlGallery/src/Issues.Shared/Bugzilla38978.cs b/src/Compatibility/ControlGallery/src/Issues.Shared/Bugzilla38978.cs
index cb9d3bf4e7c0..d0c1f472c427 100644
--- a/src/Compatibility/ControlGallery/src/Issues.Shared/Bugzilla38978.cs
+++ b/src/Compatibility/ControlGallery/src/Issues.Shared/Bugzilla38978.cs
@@ -30,7 +30,7 @@ public MyViewCell()
Label label = new Label { Text = "Click the image to resize", VerticalOptions = LayoutOptions.Center };
var tapGestureRecognizer = new TapGestureRecognizer();
- tapGestureRecognizer.Tapped += (object sender, EventArgs e) =>
+ tapGestureRecognizer.Tapped += (sender, e) =>
{
if (_image.HeightRequest < 250)
{
diff --git a/src/Controls/samples/Controls.Sample/Pages/Core/TapGestureGalleryPage.cs b/src/Controls/samples/Controls.Sample/Pages/Core/TapGestureGalleryPage.cs
index b6d16c75993c..56354fad1688 100644
--- a/src/Controls/samples/Controls.Sample/Pages/Core/TapGestureGalleryPage.cs
+++ b/src/Controls/samples/Controls.Sample/Pages/Core/TapGestureGalleryPage.cs
@@ -8,10 +8,15 @@ public class TapGestureGalleryPage : BasePage
{
Command TapCommand;
Label changeColorBoxView;
+ Label windowPosition = new Label();
+ Label relativeToToggleButtonPosition = new Label();
+ Label relativeToContainerPosition = new Label();
+ Button toggleButton;
public TapGestureGalleryPage()
{
TapCommand = new Command(HandleTapCommand);
+
var vertical = new VerticalStackLayout
{
VerticalOptions = LayoutOptions.Center,
@@ -19,6 +24,10 @@ public TapGestureGalleryPage()
Spacing = 40
};
+ vertical.Add(windowPosition);
+ vertical.Add(relativeToToggleButtonPosition);
+ vertical.Add(relativeToContainerPosition);
+
var horizontal = new HorizontalStackLayout
{
Spacing = 20,
@@ -38,6 +47,7 @@ public TapGestureGalleryPage()
CommandParameter = Colors.PaleGreen,
NumberOfTapsRequired = 1,
};
+ singleTapGesture.Tapped += OnTapped;
singleTapLabel.GestureRecognizers.Add(singleTapGesture);
horizontal.Add(singleTapLabel);
@@ -52,6 +62,7 @@ public TapGestureGalleryPage()
CommandParameter = Colors.Aqua,
NumberOfTapsRequired = 2,
};
+ doubleTapGesture.Tapped += OnTapped;
doubleTapLabel.GestureRecognizers.Add(doubleTapGesture);
horizontal.Add(doubleTapLabel);
@@ -65,8 +76,7 @@ public TapGestureGalleryPage()
};
vertical.Add(changeColorBoxView);
-
- vertical.Add(new Button()
+ toggleButton = new Button()
{
Text = "Toggle Single Tap Gesture",
Command = new Command(() =>
@@ -76,15 +86,77 @@ public TapGestureGalleryPage()
else
singleTapLabel.GestureRecognizers.Add(singleTapGesture);
})
- });
+ };
+
+ vertical.Add(toggleButton);
+
+ var tripleClicklabel = new Label
+ {
+ Text = "Triple click me!!!",
+ BackgroundColor = Colors.Olive
+ };
+ var tripleClickGesture = new TapGestureRecognizer
+ {
+ Command = TapCommand,
+ CommandParameter = Colors.Olive,
+ NumberOfTapsRequired = 3,
+ Buttons = ButtonsMask.Primary
+ };
+ tripleClickGesture.Tapped += OnTapped;
+ tripleClicklabel.GestureRecognizers.Add(tripleClickGesture);
+ horizontal.Children.Add(tripleClicklabel);
+
+ var rightClickLabel = new Label
+ {
+ Text = "Right click me¡",
+ BackgroundColor = Colors.Coral
+ };
+ var rigthClickGesture = new TapGestureRecognizer
+ {
+ Command = TapCommand,
+ CommandParameter = Colors.Coral,
+ NumberOfTapsRequired = 1,
+ Buttons = ButtonsMask.Secondary
+ };
+ rigthClickGesture.Tapped += OnTapped;
+ rightClickLabel.GestureRecognizers.Add(rigthClickGesture);
+ horizontal.Children.Add(rightClickLabel);
+
+
+ var rightorLeftClickLabel = new Label
+ {
+ Text = "Right or Left click me¡",
+ BackgroundColor = Colors.Green
+ };
+ var rigthOrLeftClickGesture = new TapGestureRecognizer
+ {
+ Command = TapCommand,
+ CommandParameter = Colors.Green,
+ NumberOfTapsRequired = 1,
+ Buttons = ButtonsMask.Secondary | ButtonsMask.Primary
+ };
+
+ rigthOrLeftClickGesture.Tapped += OnTapped;
+ rightorLeftClickLabel.GestureRecognizers.Add(rigthOrLeftClickGesture);
+ horizontal.Children.Add(rightorLeftClickLabel);
+
Content = vertical;
}
- async void HandleTapCommand(Color backgroundColor)
+ void OnTapped(object sender, System.EventArgs e)
+ {
+ var args = (TappedEventArgs)e;
+ var view = (View)sender;
+
+ windowPosition.Text = $"Position inside window: {args.GetPosition(null)}";
+ relativeToToggleButtonPosition.Text = $"Position relative to toggle button: {args.GetPosition(toggleButton)}";
+ relativeToContainerPosition.Text = $"Position inside my view: {args.GetPosition(view)}";
+ }
+
+ void HandleTapCommand(Color backgroundColor)
{
changeColorBoxView.BackgroundColor = backgroundColor;
- await DisplayAlert("Tapped", "Tap Command Fired", "Close");
}
}
}
diff --git a/src/Controls/samples/Controls.Sample/ViewModels/GesturesViewModel.cs b/src/Controls/samples/Controls.Sample/ViewModels/GesturesViewModel.cs
index 44062c3c03dc..27bcf8810835 100644
--- a/src/Controls/samples/Controls.Sample/ViewModels/GesturesViewModel.cs
+++ b/src/Controls/samples/Controls.Sample/ViewModels/GesturesViewModel.cs
@@ -17,8 +17,8 @@ protected override IEnumerable CreateItems() => new[]
"Pan Gesture."),
new SectionModel(typeof(SwipeGestureGalleryPage), "Swipe Gesture",
"Swipe Gesture."),
- new SectionModel(typeof(TapGestureGalleryPage), "Click Gesture",
- "Click Gesture."),
+ new SectionModel(typeof(TapGestureGalleryPage), "Tap Gesture",
+ "Tap Gesture."),
};
}
}
diff --git a/src/Controls/src/Core/ButtonsMask.cs b/src/Controls/src/Core/ButtonsMask.cs
new file mode 100644
index 000000000000..93ed553bdcb7
--- /dev/null
+++ b/src/Controls/src/Core/ButtonsMask.cs
@@ -0,0 +1,16 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Input;
+
+namespace Microsoft.Maui.Controls
+{
+ ///
+ [Flags]
+ public enum ButtonsMask
+ {
+ ///
+ Primary = 1 << 0,
+ ///
+ Secondary = 1 << 1
+ }
+}
diff --git a/src/Controls/src/Core/ClickGestureRecognizer.cs b/src/Controls/src/Core/ClickGestureRecognizer.cs
index 58609900e7c6..e287695a689e 100644
--- a/src/Controls/src/Core/ClickGestureRecognizer.cs
+++ b/src/Controls/src/Core/ClickGestureRecognizer.cs
@@ -4,16 +4,6 @@
namespace Microsoft.Maui.Controls
{
- ///
- [Flags]
- public enum ButtonsMask
- {
- ///
- Primary = 1 << 0,
- ///
- Secondary = 1 << 1
- }
-
///
public sealed class ClickGestureRecognizer : GestureRecognizer
{
diff --git a/src/Controls/src/Core/Platform/Android/InnerGestureListener.cs b/src/Controls/src/Core/Platform/Android/InnerGestureListener.cs
index ae02d6f6d7fb..048b1cf87248 100644
--- a/src/Controls/src/Core/Platform/Android/InnerGestureListener.cs
+++ b/src/Controls/src/Core/Platform/Android/InnerGestureListener.cs
@@ -24,7 +24,7 @@ internal class InnerGestureListener : Object, GestureDetector.IOnGestureListener
Func _scrollCompleteDelegate;
Func _scrollDelegate;
Func _scrollStartedDelegate;
- Func _tapDelegate;
+ Func _tapDelegate;
Func> _tapGestureRecognizers;
public InnerGestureListener(
@@ -74,7 +74,7 @@ bool GestureDetector.IOnDoubleTapListener.OnDoubleTap(MotionEvent e)
if (HasDoubleTapHandler())
{
- return _tapDelegate(2, new Point(e.GetX(), e.GetY()));
+ return _tapDelegate(2, e);
}
if (HasSingleTapHandler())
@@ -82,7 +82,7 @@ bool GestureDetector.IOnDoubleTapListener.OnDoubleTap(MotionEvent e)
// If we're registering double taps and we don't actually have a double-tap handler,
// but we _do_ have a single-tap handler, then we're really just seeing two singles in a row
// Fire off the delegate for the second single-tap (OnSingleTapUp already did the first one)
- return _tapDelegate(1, new Point(e.GetX(), e.GetY()));
+ return _tapDelegate(1, e);
}
return false;
@@ -149,7 +149,7 @@ bool GestureDetector.IOnGestureListener.OnSingleTapUp(MotionEvent e)
// A single tap has occurred and there's no handler for double tap to worry about,
// so we can go ahead and run the delegate
- return _tapDelegate(1, new Point(e.GetX(), e.GetY()));
+ return _tapDelegate(1, e);
}
bool GestureDetector.IOnDoubleTapListener.OnSingleTapConfirmed(MotionEvent e)
@@ -166,7 +166,7 @@ bool GestureDetector.IOnDoubleTapListener.OnSingleTapConfirmed(MotionEvent e)
// Since there was a double-tap handler, we had to wait for OnSingleTapConfirmed;
// Now that we're sure it's a single tap, we can run the delegate
- return _tapDelegate(1, new Point(e.GetX(), e.GetY()));
+ return _tapDelegate(1, e);
}
protected override void Dispose(bool disposing)
diff --git a/src/Controls/src/Core/Platform/Android/PanGestureHandler.cs b/src/Controls/src/Core/Platform/Android/PanGestureHandler.cs
index d0ffddfc177f..8d6cb61e4eea 100644
--- a/src/Controls/src/Core/Platform/Android/PanGestureHandler.cs
+++ b/src/Controls/src/Core/Platform/Android/PanGestureHandler.cs
@@ -6,11 +6,23 @@ namespace Microsoft.Maui.Controls.Platform
{
internal class PanGestureHandler
{
- readonly Func _pixelTranslation;
+ Func PixelTranslation
+ {
+ get
+ {
+ return (input) =>
+ {
+ var context = GetView()?.Handler?.MauiContext?.Context;
+ if (context == null)
+ return 0;
+
+ return context.FromPixels(input);
+ };
+ }
+ }
- public PanGestureHandler(Func getView, Func pixelTranslation)
+ public PanGestureHandler(Func getView)
{
- _pixelTranslation = pixelTranslation;
GetView = getView;
}
@@ -27,7 +39,7 @@ public bool OnPan(float x, float y, int pointerCount)
foreach (PanGestureRecognizer panGesture in
view.GestureRecognizers.GetGesturesFor(g => g.TouchPoints == pointerCount))
{
- ((IPanGestureController)panGesture).SendPan(view, _pixelTranslation(x), _pixelTranslation(y), PanGestureRecognizer.CurrentId.Value);
+ ((IPanGestureController)panGesture).SendPan(view, PixelTranslation(x), PixelTranslation(y), PanGestureRecognizer.CurrentId.Value);
result = true;
}
diff --git a/src/Controls/src/Core/Platform/Android/SwipeGestureHandler.cs b/src/Controls/src/Core/Platform/Android/SwipeGestureHandler.cs
index 389d0b85d1fa..09fa9ccaf451 100644
--- a/src/Controls/src/Core/Platform/Android/SwipeGestureHandler.cs
+++ b/src/Controls/src/Core/Platform/Android/SwipeGestureHandler.cs
@@ -6,11 +6,23 @@ namespace Microsoft.Maui.Controls.Platform
{
internal class SwipeGestureHandler
{
- readonly Func _pixelTranslation;
+ Func PixelTranslation
+ {
+ get
+ {
+ return (input) =>
+ {
+ var context = GetView()?.Handler?.MauiContext?.Context;
+ if (context == null)
+ return 0;
+
+ return context.FromPixels(input);
+ };
+ }
+ }
- public SwipeGestureHandler(Func getView, Func pixelTranslation)
+ public SwipeGestureHandler(Func getView)
{
- _pixelTranslation = pixelTranslation;
GetView = getView;
}
@@ -27,7 +39,7 @@ public bool OnSwipe(float x, float y)
foreach (SwipeGestureRecognizer swipeGesture in
view.GestureRecognizers.GetGesturesFor())
{
- ((ISwipeGestureController)swipeGesture).SendSwipe(view, _pixelTranslation(x), _pixelTranslation(y));
+ ((ISwipeGestureController)swipeGesture).SendSwipe(view, PixelTranslation(x), PixelTranslation(y));
result = true;
}
diff --git a/src/Controls/src/Core/Platform/Android/TapGestureHandler.cs b/src/Controls/src/Core/Platform/Android/TapGestureHandler.cs
index 1317bdd9fec3..8dbe5eefa8ea 100644
--- a/src/Controls/src/Core/Platform/Android/TapGestureHandler.cs
+++ b/src/Controls/src/Core/Platform/Android/TapGestureHandler.cs
@@ -1,21 +1,26 @@
+#nullable enable
+
using System;
using System.Collections.Generic;
using System.Linq;
+using Android.Views;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Graphics;
+using Microsoft.Maui.Platform;
+using AView = Android.Views.View;
namespace Microsoft.Maui.Controls.Platform
{
internal class TapGestureHandler
{
- public TapGestureHandler(Func getView, Func> getChildElements)
+ public TapGestureHandler(Func getView, Func> getChildElements)
{
GetView = getView;
GetChildElements = getChildElements;
}
Func> GetChildElements { get; }
- Func GetView { get; }
+ Func GetView { get; }
public void OnSingleClick()
{
@@ -23,12 +28,19 @@ public void OnSingleClick()
if (TapGestureRecognizers(2).Any())
return;
- OnTap(1, new Point(-1, -1));
+ OnTap(1, null);
}
- public bool OnTap(int count, Point point)
+ public bool OnTap(int count, MotionEvent? e)
{
- View view = GetView();
+ Point point;
+
+ if (e == null)
+ point = new Point(-1, -1);
+ else
+ point = new Point(e.GetX(), e.GetY());
+
+ var view = GetView();
if (view == null)
return false;
@@ -38,11 +50,16 @@ public bool OnTap(int count, Point point)
var children = view.GetChildElements(point);
if (children != null)
+ {
foreach (var recognizer in children.GetChildGesturesFor(recognizer => recognizer.NumberOfTapsRequired == count))
{
- recognizer.SendTapped(view);
+ if (!CheckButtonMask(recognizer, e))
+ continue;
+
+ recognizer.SendTapped(view, CalculatePosition);
captured = true;
}
+ }
if (captured)
return captured;
@@ -50,11 +67,61 @@ public bool OnTap(int count, Point point)
IEnumerable gestureRecognizers = TapGestureRecognizers(count);
foreach (var gestureRecognizer in gestureRecognizers)
{
- gestureRecognizer.SendTapped(view);
+ if (!CheckButtonMask(gestureRecognizer, e))
+ continue;
+
+ gestureRecognizer.SendTapped(view, CalculatePosition);
captured = true;
}
return captured;
+
+ bool CheckButtonMask(TapGestureRecognizer tapGestureRecognizer, MotionEvent? motionEvent)
+ {
+ if (tapGestureRecognizer.Buttons == ButtonsMask.Secondary)
+ {
+ var buttonState = motionEvent?.ButtonState ?? MotionEventButtonState.Primary;
+
+ return
+ buttonState == MotionEventButtonState.Secondary ||
+ buttonState == MotionEventButtonState.StylusSecondary;
+ }
+
+ return (tapGestureRecognizer.Buttons & ButtonsMask.Primary) == ButtonsMask.Primary;
+ }
+
+ Point? CalculatePosition(IElement? element)
+ {
+ var context = GetView()?.Handler?.MauiContext?.Context;
+
+ if (context == null)
+ return null;
+
+ if (e == null)
+ return null;
+
+ if (element == null)
+ {
+ return new Point(context.FromPixels(e.RawX), context.FromPixels(e.RawY));
+ }
+
+ if (element == GetView())
+ {
+ return new Point(context.FromPixels(e.GetX()), context.FromPixels(e.GetY()));
+ }
+
+ if (element?.Handler?.PlatformView is AView aView)
+ {
+ var location = aView.GetLocationOnScreenPx();
+
+ var x = e.RawX - location.X;
+ var y = e.RawY - location.Y;
+
+ return new Point(context.FromPixels(x), context.FromPixels(y));
+ }
+
+ return null;
+ }
}
public bool HasAnyGestures()
@@ -66,7 +133,7 @@ public bool HasAnyGestures()
public IEnumerable TapGestureRecognizers(int count)
{
- View view = GetView();
+ var view = GetView();
if (view == null)
return Enumerable.Empty();
diff --git a/src/Controls/src/Core/Platform/GestureManager/GestureManager.Android.cs b/src/Controls/src/Core/Platform/GestureManager/GestureManager.Android.cs
index ee428c472405..9daa4ee6015a 100644
--- a/src/Controls/src/Core/Platform/GestureManager/GestureManager.Android.cs
+++ b/src/Controls/src/Core/Platform/GestureManager/GestureManager.Android.cs
@@ -119,8 +119,8 @@ TapAndPanGestureDetector InitializeTapAndPanAndSwipeDetector()
return new List();
}),
- new PanGestureHandler(() => View, context.FromPixels),
- new SwipeGestureHandler(() => View, context.FromPixels),
+ new PanGestureHandler(() => View),
+ new SwipeGestureHandler(() => View),
InitializeDragAndDropHandler()
);
@@ -172,6 +172,20 @@ void SetupGestures()
{
platformView.Touch += OnPlatformViewTouched;
}
+
+ if (View is not Microsoft.Maui.IButton)
+ {
+ platformView.KeyPress += PlatformView_KeyPress;
+ platformView.Click += PlatformView_Click;
+ }
+ }
+
+ private void PlatformView_Click(object? sender, EventArgs e)
+ {
+ }
+
+ private void PlatformView_KeyPress(object? sender, AView.KeyEventArgs e)
+ {
}
void OnPlatformViewTouched(object? sender, AView.TouchEventArgs e)
diff --git a/src/Controls/src/Core/Platform/GestureManager/GestureManager.Windows.cs b/src/Controls/src/Core/Platform/GestureManager/GestureManager.Windows.cs
index da2ebf530530..0decac4e58a1 100644
--- a/src/Controls/src/Core/Platform/GestureManager/GestureManager.Windows.cs
+++ b/src/Controls/src/Core/Platform/GestureManager/GestureManager.Windows.cs
@@ -120,17 +120,15 @@ void SendEventArgs(Action func)
return;
var view = Element as View;
- var gestures =
- view?
- .GestureRecognizers?
- .OfType();
+ var gestures = view?.GestureRecognizers;
if (gestures == null)
return;
foreach (var gesture in gestures)
{
- func(gesture);
+ if (gesture is TRecognizer recognizer)
+ func(recognizer);
}
}
@@ -313,7 +311,6 @@ void ClearContainerEventHandlers()
_container.DragOver -= HandleDragOver;
_container.Drop -= HandleDrop;
_container.Tapped -= OnTap;
- _container.DoubleTapped -= OnDoubleTap;
_container.ManipulationDelta -= OnManipulationDelta;
_container.ManipulationStarted -= OnManipulationStarted;
_container.ManipulationCompleted -= OnManipulationCompleted;
@@ -421,33 +418,6 @@ void ModelGestureRecognizersOnCollectionChanged(object? sender, NotifyCollection
UpdatingGestureRecognizers();
}
- void OnDoubleTap(object sender, DoubleTappedRoutedEventArgs e)
- {
- var view = Element as View;
- if (view == null)
- return;
-
- var tapPosition = e.GetPosition(Control);
- var children = (view as IGestureController)?.GetChildElements(new Point(tapPosition.X, tapPosition.Y));
-
- if (children != null)
- foreach (var recognizer in children.GetChildGesturesFor(g => g.NumberOfTapsRequired == 1 || g.NumberOfTapsRequired == 2))
- {
- recognizer.SendTapped(view);
- e.Handled = true;
- }
-
- if (e.Handled)
- return;
-
- IEnumerable doubleTapGestures = view.GestureRecognizers.GetGesturesFor(g => g.NumberOfTapsRequired == 1 || g.NumberOfTapsRequired == 2);
- foreach (TapGestureRecognizer recognizer in doubleTapGestures)
- {
- recognizer.SendTapped(view);
- e.Handled = true;
- }
- }
-
void OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
SwipeComplete(true);
@@ -511,30 +481,67 @@ void OnPointerReleased(object sender, PointerRoutedEventArgs e)
PanComplete(true);
}
- void OnTap(object sender, TappedRoutedEventArgs e)
+ void OnTap(object sender, RoutedEventArgs e)
{
var view = Element as View;
if (view == null)
return;
+
+ var tapPosition = e.GetPositionRelativeToPlatformElement(Control);
+
+ if (tapPosition == null)
+ return;
- var tapPosition = e.GetPosition(Control);
- var children = (view as IGestureController)?.GetChildElements(new Point(tapPosition.X, tapPosition.Y));
+ var children =
+ (view as IGestureController)?.GetChildElements(new Point(tapPosition.Value.X, tapPosition.Value.Y))?.
+ GetChildGesturesFor(ValidateGesture);
- if (children != null)
- foreach (var recognizer in children.GetChildGesturesFor(g => g.NumberOfTapsRequired == 1))
+ if (ProcessGestureRecognizers(children))
+ return;
+
+ IEnumerable tapGestures = view.GestureRecognizers.GetGesturesFor(ValidateGesture);
+ ProcessGestureRecognizers(tapGestures);
+
+ bool ProcessGestureRecognizers(IEnumerable? tapGestures)
+ {
+ bool handled = false;
+ if (tapGestures == null)
+ return handled;
+
+ foreach (var recognizer in tapGestures)
{
- recognizer.SendTapped(view);
- e.Handled = true;
+ recognizer.SendTapped(view, (relativeTo) =>
+ {
+ var result = e.GetPositionRelativeToElement(relativeTo);
+ if (result == null)
+ return null;
+
+ return new Point(result.Value.X, result.Value.Y);
+ });
+
+ e.SetHandled(true);
+ handled = true;
}
- if (e.Handled)
- return;
+ return handled;
+ }
- IEnumerable tapGestures = view.GestureRecognizers.GetGesturesFor(g => g.NumberOfTapsRequired == 1);
- foreach (var recognizer in tapGestures)
+ bool ValidateGesture(TapGestureRecognizer g)
{
- recognizer.SendTapped(view);
- e.Handled = true;
+ if (e is RightTappedRoutedEventArgs &&
+ (g.Buttons & ButtonsMask.Secondary) == ButtonsMask.Secondary)
+ {
+ // Currently we only support single right clicks on WinUI
+ return g.NumberOfTapsRequired == 1;
+ }
+
+ if ((g.Buttons & ButtonsMask.Primary) != ButtonsMask.Primary)
+ return false;
+
+ if (e is DoubleTappedRoutedEventArgs)
+ return g.NumberOfTapsRequired == 1 || g.NumberOfTapsRequired == 2;
+
+ return g.NumberOfTapsRequired == 1;
}
}
@@ -649,6 +656,7 @@ void UpdatingGestureRecognizers()
|| children?.GetChildGesturesFor(g => g.NumberOfTapsRequired == 1).Any() == true)
{
_container.Tapped += OnTap;
+ _container.RightTapped += OnTap;
}
else
{
@@ -661,7 +669,7 @@ void UpdatingGestureRecognizers()
if (gestures.GetGesturesFor(g => g.NumberOfTapsRequired == 1 || g.NumberOfTapsRequired == 2).Any()
|| children?.GetChildGesturesFor(g => g.NumberOfTapsRequired == 1 || g.NumberOfTapsRequired == 2).Any() == true)
{
- _container.DoubleTapped += OnDoubleTap;
+ _container.DoubleTapped += OnTap;
}
else
{
@@ -709,6 +717,5 @@ void HandleDoubleTapped(object sender, DoubleTappedRoutedEventArgs doubleTappedR
{
doubleTappedRoutedEventArgs.Handled = true;
}
-
}
}
diff --git a/src/Controls/src/Core/Platform/GestureManager/GestureManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GestureManager.iOS.cs
index e76e32c59418..71ec5bae4244 100644
--- a/src/Controls/src/Core/Platform/GestureManager/GestureManager.iOS.cs
+++ b/src/Controls/src/Core/Platform/GestureManager/GestureManager.iOS.cs
@@ -4,13 +4,15 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
+using System.Reflection;
+using System.Runtime.Versioning;
+using CoreGraphics;
+using Foundation;
using Microsoft.Maui.Controls.Internals;
using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;
using Microsoft.Maui.Graphics;
using ObjCRuntime;
using UIKit;
-using NativeGestureRecognizer = UIKit.UIGestureRecognizer;
-using NativeGestureRecognizerState = UIKit.UIGestureRecognizerState;
using PlatformView = UIKit.UIView;
namespace Microsoft.Maui.Controls.Platform
@@ -19,8 +21,8 @@ class GestureManager : IDisposable
{
readonly NotifyCollectionChangedEventHandler _collectionChangedHandler;
- readonly Dictionary _gestureRecognizers = new Dictionary();
-
+ readonly Dictionary _gestureRecognizers = new Dictionary();
+ readonly List _interactions = new List();
readonly IPlatformViewHandler _handler;
bool _disposed;
@@ -79,12 +81,25 @@ public void Dispose()
foreach (var kvp in _gestureRecognizers)
{
+ if (TryGetTapGestureRecognizer(kvp.Key, out TapGestureRecognizer? tapGestureRecognizer) &&
+ tapGestureRecognizer != null)
+ {
+ tapGestureRecognizer.PropertyChanged -= OnTapGestureRecognizerPropertyChanged;
+ }
+
if (_platformView != null)
_platformView.RemoveGestureRecognizer(kvp.Value);
kvp.Value.ShouldReceiveTouch = null;
kvp.Value.Dispose();
}
+ if (_platformView != null && OperatingSystem.IsIOSVersionAtLeast(11))
+ {
+ foreach (IUIInteraction interaction in _interactions)
+ {
+ _platformView.RemoveInteraction(interaction);
+ }
+ }
_gestureRecognizers.Clear();
Disconnect();
@@ -93,7 +108,7 @@ public void Dispose()
}
static IList? GetChildGestures(
- NativeGestureRecognizer sender,
+ CGPoint originPoint,
WeakReference weakEventTracker, WeakReference weakRecognizer, GestureManager? eventTracker, View? view)
{
if (!weakRecognizer.IsAlive)
@@ -102,50 +117,104 @@ public void Dispose()
if (eventTracker == null || eventTracker._disposed || view == null)
return null;
- var originPoint = sender.LocationInView(eventTracker._handler.PlatformView);
var childGestures = view.GetChildElements(new Point(originPoint.X, originPoint.Y));
return childGestures;
}
- Action CreateRecognizerHandler(WeakReference weakEventTracker, WeakReference weakRecognizer, TapGestureRecognizer clickRecognizer)
+ static void ProcessRecognizerHandlerTap(
+ WeakReference weakEventTracker,
+ WeakReference weakRecognizer,
+ CGPoint originPoint,
+ int uiTapGestureRecognizerNumberOfTapsRequired,
+ UITapGestureRecognizer? uITapGestureRecognizer = null)
{
- return new Action((sender) =>
+ var recognizer = weakRecognizer.Target as IGestureRecognizer;
+ var eventTracker = weakEventTracker.Target as GestureManager;
+ var view = eventTracker?._handler?.VirtualView as View;
+
+ WeakReference? weakPlatformRecognizer = null;
+ if (uITapGestureRecognizer != null)
+ weakPlatformRecognizer = new WeakReference(uITapGestureRecognizer);
+
+ if (recognizer is TapGestureRecognizer tapGestureRecognizer)
{
- var eventTracker = weakEventTracker.Target as GestureManager;
- var view = eventTracker?._handler?.VirtualView as View;
+ var childGestures = GetChildGestures(originPoint, weakEventTracker, weakRecognizer, eventTracker, view);
+
+ if (childGestures?.HasChildGesturesFor(x => x.NumberOfTapsRequired == uiTapGestureRecognizerNumberOfTapsRequired) == true)
+ return;
+
+ if (view != null)
+ tapGestureRecognizer.SendTapped(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakPlatformRecognizer, weakEventTracker));
+ }
+ else if (recognizer is ChildGestureRecognizer childGestureRecognizer)
+ {
+ var childGestures = GetChildGestures(originPoint, weakEventTracker, weakRecognizer, eventTracker, view);
- var childGestures = GetChildGestures(sender, weakEventTracker, weakRecognizer, eventTracker, view);
+ var recognizers = childGestures?.GetChildGesturesFor(x => x.NumberOfTapsRequired == uiTapGestureRecognizerNumberOfTapsRequired);
- if (childGestures?.HasChildGesturesFor(x => x.NumberOfTapsRequired == (int)sender.NumberOfTapsRequired) == true)
+ if (recognizers == null || weakRecognizer.Target == null)
return;
- if (weakRecognizer.Target is TapGestureRecognizer tapGestureRecognizer && view != null)
- tapGestureRecognizer.SendTapped(view);
- });
+ var childTapGestureRecognizer = childGestureRecognizer.GestureRecognizer as TapGestureRecognizer;
+ foreach (var item in recognizers)
+ if (item == childTapGestureRecognizer && view != null)
+ childTapGestureRecognizer.SendTapped(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakPlatformRecognizer, weakEventTracker));
+ }
}
- Action CreateChildRecognizerHandler(WeakReference weakEventTracker, WeakReference weakRecognizer)
+
+ static Point? CalculatePosition(IElement? element, CGPoint originPoint, WeakReference? weakPlatformRecognizer, WeakReference weakEventTracker)
{
- return new Action((sender) =>
+ var eventTracker = weakEventTracker.Target as GestureManager;
+ var virtualView = eventTracker?._handler?.VirtualView as View;
+ var platformRecognizer = weakPlatformRecognizer?.Target as UIGestureRecognizer;
+
+ if (virtualView == null)
+ return null;
+
+ if (platformRecognizer == null)
{
- var eventTracker = weakEventTracker.Target as GestureManager;
- var view = eventTracker?._handler?.VirtualView as View;
+ if (virtualView == element)
+ return new Point((int)originPoint.X, (int)originPoint.Y);
- var childGestures = GetChildGestures(sender, weakEventTracker, weakRecognizer, eventTracker, view);
+ var targetViewScreenLocation = virtualView.GetLocationOnScreen();
- var recognizers = childGestures?.GetChildGesturesFor(x => x.NumberOfTapsRequired == (int)sender.NumberOfTapsRequired);
+ if (!targetViewScreenLocation.HasValue)
+ return null;
- if (recognizers == null || weakRecognizer.Target == null)
- return;
+ var windowX = targetViewScreenLocation.Value.X + originPoint.X;
+ var windowY = targetViewScreenLocation.Value.Y + originPoint.Y;
+
+ if (element == null)
+ return new Point(windowX, windowY);
+
+ if (element?.Handler?.PlatformView is UIView uiView)
+ {
+ var location = uiView.GetLocationOnScreen();
+
+ var x = windowX - location.X;
+ var y = windowY - location.Y;
+
+ return new Point(x, y);
+ }
+
+ return null;
+ }
+
+ CGPoint? result = null;
+ if (element == null)
+ result = platformRecognizer.LocationInView(null);
+ else if (element.Handler?.PlatformView is UIView view)
+ result = platformRecognizer.LocationInView(view);
+
+ if (result == null)
+ return null;
+
+ return new Point((int)result.Value.X, (int)result.Value.Y);
- var tapGestureRecognizer = ((ChildGestureRecognizer)weakRecognizer.Target).GestureRecognizer as TapGestureRecognizer;
- foreach (var item in recognizers)
- if (item == tapGestureRecognizer && view != null)
- tapGestureRecognizer.SendTapped(view);
- });
}
- protected virtual NativeGestureRecognizer? GetPlatformRecognizer(IGestureRecognizer recognizer)
+ protected virtual UIGestureRecognizer? GetPlatformRecognizer(IGestureRecognizer recognizer)
{
if (recognizer == null)
return null;
@@ -153,14 +222,12 @@ Action CreateChildRecognizerHandler(WeakReference weakEv
var weakRecognizer = new WeakReference(recognizer);
var weakEventTracker = new WeakReference(this);
- var tapRecognizer = recognizer as TapGestureRecognizer;
- if (tapRecognizer != null)
- {
- var returnAction = CreateRecognizerHandler(weakEventTracker, weakRecognizer, tapRecognizer);
+ var tapGestureRecognizer = CreateTapRecognizer(weakEventTracker, weakRecognizer);
- var uiRecognizer = CreateTapRecognizer(tapRecognizer.NumberOfTapsRequired, returnAction);
- return uiRecognizer;
+ if (tapGestureRecognizer != null)
+ {
+ return tapGestureRecognizer;
}
var swipeRecognizer = recognizer as SwipeGestureRecognizer;
@@ -179,16 +246,6 @@ Action CreateChildRecognizerHandler(WeakReference weakEv
return uiRecognizer;
}
- if (recognizer is ChildGestureRecognizer childRecognizer)
- {
- if (childRecognizer.GestureRecognizer is TapGestureRecognizer tapChildRecognizer)
- {
- var returnAction = CreateChildRecognizerHandler(weakEventTracker, weakRecognizer);
- var uiRecognizer = CreateTapRecognizer(tapChildRecognizer.NumberOfTapsRequired, returnAction);
- return uiRecognizer;
- }
- }
-
var pinchRecognizer = recognizer as IPinchGestureController;
if (pinchRecognizer != null)
{
@@ -208,17 +265,17 @@ weakEventTracker.Target is GestureManager eventTracker &&
switch (r.State)
{
- case NativeGestureRecognizerState.Began:
+ case UIGestureRecognizerState.Began:
if (r.NumberOfTouches < 2)
return;
pinchGestureRecognizer.SendPinchStarted(view, scaledPoint);
startingScale = view.Scale;
break;
- case NativeGestureRecognizerState.Changed:
+ case UIGestureRecognizerState.Changed:
if (r.NumberOfTouches < 2 && pinchGestureRecognizer.IsPinching)
{
- r.State = NativeGestureRecognizerState.Ended;
+ r.State = UIGestureRecognizerState.Ended;
pinchGestureRecognizer.SendPinchEnded(view);
return;
}
@@ -233,12 +290,12 @@ weakEventTracker.Target is GestureManager eventTracker &&
pinchGestureRecognizer.SendPinch(view, delta, scaledPoint);
eventTracker._previousScale = scale;
break;
- case NativeGestureRecognizerState.Cancelled:
- case NativeGestureRecognizerState.Failed:
+ case UIGestureRecognizerState.Cancelled:
+ case UIGestureRecognizerState.Failed:
if (pinchGestureRecognizer.IsPinching)
pinchGestureRecognizer.SendPinchCanceled(view);
break;
- case NativeGestureRecognizerState.Ended:
+ case UIGestureRecognizerState.Ended:
if (pinchGestureRecognizer.IsPinching)
pinchGestureRecognizer.SendPinchEnded(view);
eventTracker._previousScale = 1;
@@ -262,15 +319,15 @@ weakEventTracker.Target is GestureManager eventTracker &&
{
switch (r.State)
{
- case NativeGestureRecognizerState.Began:
+ case UIGestureRecognizerState.Began:
if (r.NumberOfTouches != panRecognizer.TouchPoints)
return;
panGestureRecognizer.SendPanStarted(view, PanGestureRecognizer.CurrentId.Value);
break;
- case NativeGestureRecognizerState.Changed:
+ case UIGestureRecognizerState.Changed:
if (r.NumberOfTouches != panRecognizer.TouchPoints)
{
- r.State = NativeGestureRecognizerState.Ended;
+ r.State = UIGestureRecognizerState.Ended;
panGestureRecognizer.SendPanCompleted(view, PanGestureRecognizer.CurrentId.Value);
PanGestureRecognizer.CurrentId.Increment();
return;
@@ -278,12 +335,12 @@ weakEventTracker.Target is GestureManager eventTracker &&
var translationInView = r.TranslationInView(_platformView);
panGestureRecognizer.SendPan(view, translationInView.X, translationInView.Y, PanGestureRecognizer.CurrentId.Value);
break;
- case NativeGestureRecognizerState.Cancelled:
- case NativeGestureRecognizerState.Failed:
+ case UIGestureRecognizerState.Cancelled:
+ case UIGestureRecognizerState.Failed:
panGestureRecognizer.SendPanCanceled(view, PanGestureRecognizer.CurrentId.Value);
PanGestureRecognizer.CurrentId.Increment();
break;
- case NativeGestureRecognizerState.Ended:
+ case UIGestureRecognizerState.Ended:
if (r.NumberOfTouches != panRecognizer.TouchPoints)
{
panGestureRecognizer.SendPanCompleted(view, PanGestureRecognizer.CurrentId.Value);
@@ -325,22 +382,53 @@ UISwipeGestureRecognizer CreateSwipeRecognizer(SwipeDirection direction, Action<
return result;
}
- UITapGestureRecognizer CreateTapRecognizer(int numTaps, Action action, int numFingers = 1)
+ UITapGestureRecognizer? CreateTapRecognizer(
+ WeakReference weakEventTracker,
+ WeakReference weakRecognizer)
{
+ if (!TryGetTapGestureRecognizer(weakRecognizer.Target as IGestureRecognizer, out TapGestureRecognizer? tapGesture))
+ return null;
+
+ if (tapGesture == null)
+ return null;
+
+ Action action = new Action((sender) =>
+ {
+ var eventTracker = weakEventTracker.Target as GestureManager;
+ var originPoint = sender.LocationInView(eventTracker?._handler?.PlatformView);
+ ProcessRecognizerHandlerTap(weakEventTracker, weakRecognizer, originPoint, (int)sender.NumberOfTapsRequired, sender);
+ });
+
var result = new UITapGestureRecognizer(action)
{
- NumberOfTouchesRequired = (uint)numFingers,
- NumberOfTapsRequired = (uint)numTaps,
+ NumberOfTapsRequired = (uint)tapGesture.NumberOfTapsRequired,
ShouldRecognizeSimultaneously = ShouldRecognizeTapsTogether
};
+ // For whatever reason the secondary mask doesn't work on catalyst
+ // it only works when you have a mouse connected to an iPad
+ // so we just ignore setting the mask if the user is running catalyst
+ // right click is handled by adding a UIContextMenu interaction
+ if (OperatingSystem.IsIOSVersionAtLeast(13, 4) && !OperatingSystem.IsMacCatalyst())
+ {
+ UIEventButtonMask uIEventButtonMask = (UIEventButtonMask)0;
+
+ if ((tapGesture.Buttons & ButtonsMask.Primary) == ButtonsMask.Primary)
+ uIEventButtonMask |= UIEventButtonMask.Primary;
+
+ if ((tapGesture.Buttons & ButtonsMask.Secondary) == ButtonsMask.Secondary)
+ uIEventButtonMask |= UIEventButtonMask.Secondary;
+
+ result.ButtonMaskRequired = uIEventButtonMask;
+ }
+
return result;
}
- static bool ShouldRecognizeTapsTogether(NativeGestureRecognizer gesture, NativeGestureRecognizer other)
+ static bool ShouldRecognizeTapsTogether(UIGestureRecognizer gesture, UIGestureRecognizer other)
{
// If multiple tap gestures are potentially firing (because multiple tap gesture recognizers have been
- // added to the XF Element), we want to allow them to fire simultaneously if they have the same number
+ // added to the MAUI Element), we want to allow them to fire simultaneously if they have the same number
// of taps and touches
var tap = gesture as UITapGestureRecognizer;
@@ -373,6 +461,15 @@ static bool ShouldRecognizeTapsTogether(NativeGestureRecognizer gesture, NativeG
return true;
}
+ bool TryGetTapGestureRecognizer(IGestureRecognizer? recognizer, out TapGestureRecognizer? tapGestureRecognizer)
+ {
+ tapGestureRecognizer =
+ recognizer as TapGestureRecognizer ??
+ (recognizer as ChildGestureRecognizer)?.GestureRecognizer as TapGestureRecognizer;
+
+ return tapGestureRecognizer != null;
+ }
+
void LoadRecognizers()
{
if (ElementGestureRecognizers == null)
@@ -412,6 +509,7 @@ _handler.VirtualView is View v &&
{
_platformView.AccessibilityTraits |= UIAccessibilityTrait.Button;
_addedFlags |= UIAccessibilityTrait.Button;
+
if (OperatingSystem.IsIOSVersionAtLeast(13) || OperatingSystem.IsTvOSVersionAtLeast(13))
{
_defaultAccessibilityRespondsToUserInteraction = _platformView.AccessibilityRespondsToUserInteraction;
@@ -419,6 +517,8 @@ _handler.VirtualView is View v &&
}
}
+ _interactions.Clear();
+
for (int i = 0; i < ElementGestureRecognizers.Count; i++)
{
IGestureRecognizer recognizer = ElementGestureRecognizers[i];
@@ -426,6 +526,22 @@ _handler.VirtualView is View v &&
if (_gestureRecognizers.ContainsKey(recognizer))
continue;
+ if (TryGetTapGestureRecognizer(recognizer, out TapGestureRecognizer? tapGestureRecognizer) &&
+ tapGestureRecognizer != null)
+ {
+ tapGestureRecognizer.PropertyChanged += OnTapGestureRecognizerPropertyChanged;
+ }
+
+ // AddFakeRightClickForMacCatalyst returns the button mask for the processed tap gesture
+ // If a fake gesture wasn't added then it just returns 0
+ // If a fake gesture was added then we return the button mask fromm the tap gesture
+ // If the user only cares about right click then we'll just exit now
+ // so that an additional tap gesture doesn't get added
+ if (AddFakeRightClickForMacCatalyst(recognizer) == ButtonsMask.Secondary)
+ {
+ continue;
+ }
+
var nativeRecognizer = GetPlatformRecognizer(recognizer);
if (nativeRecognizer != null && _platformView != null)
@@ -485,8 +601,32 @@ _handler.VirtualView is View v &&
if (_platformView != null)
_platformView.RemoveGestureRecognizer(uiRecognizer);
+ if (TryGetTapGestureRecognizer(gestureRecognizer, out TapGestureRecognizer? tapGestureRecognizer) &&
+ tapGestureRecognizer != null)
+ {
+ gestureRecognizer.PropertyChanged -= OnTapGestureRecognizerPropertyChanged;
+ }
+
uiRecognizer.Dispose();
}
+
+ if (_platformView != null && OperatingSystem.IsIOSVersionAtLeast(11))
+ {
+ for (int i = _platformView.Interactions.Length - 1; i >= 0; i--)
+ {
+ var interaction = (IUIInteraction)_platformView.Interactions[i];
+ if (interaction is FakeRightClickContextMenuInteraction && !_interactions.Contains(interaction))
+ {
+ _platformView.RemoveInteraction(interaction);
+ }
+ }
+ }
+ }
+
+ void OnTapGestureRecognizerPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ if (e.Is(TapGestureRecognizer.ButtonsProperty))
+ LoadRecognizers();
}
bool ShouldReceiveTouch(UIGestureRecognizer recognizer, UITouch touch)
@@ -563,5 +703,77 @@ void OnElementChanged(object sender, VisualElementChangedEventArgs e)
}
}
}
+
+ ButtonsMask AddFakeRightClickForMacCatalyst(IGestureRecognizer recognizer)
+ {
+ if (OperatingSystem.IsIOSVersionAtLeast(13, 4) && OperatingSystem.IsMacCatalyst())
+ {
+ TryGetTapGestureRecognizer(recognizer, out TapGestureRecognizer? tapRecognizer);
+
+ if (tapRecognizer == null || (tapRecognizer.Buttons & ButtonsMask.Secondary) != ButtonsMask.Secondary)
+ {
+ return (ButtonsMask)0;
+ }
+
+ if (_platformView != null)
+ {
+ foreach (var interaction in _platformView.Interactions)
+ {
+ // check if this gesture was already added
+ if (interaction is FakeRightClickContextMenuInteraction faker &&
+ faker.TapGestureRecognizer == tapRecognizer)
+ {
+ _interactions.Add(faker);
+ return tapRecognizer.Buttons;
+ }
+ }
+ }
+
+ var fakeInteraction = new FakeRightClickContextMenuInteraction(tapRecognizer, this);
+ _interactions.Add(fakeInteraction);
+
+ _platformView?.AddInteraction(fakeInteraction);
+
+ return tapRecognizer.Buttons;
+ }
+
+ return (ButtonsMask)0;
+ }
+
+ [SupportedOSPlatform("ios13.0")]
+ [SupportedOSPlatform("maccatalyst13.0.0")]
+ [UnsupportedOSPlatform("tvos")]
+ internal class FakeRightClickContextMenuInteraction : UIContextMenuInteraction
+ {
+ // Store a reference to the platform delegate so that it is not garbage collected
+ FakeRightClickDelegate? _dontCollectMePlease;
+
+ public FakeRightClickContextMenuInteraction(TapGestureRecognizer tapGestureRecognizer, GestureManager gestureManager)
+ : base(new FakeRightClickDelegate(tapGestureRecognizer, gestureManager))
+ {
+ _dontCollectMePlease = Delegate as FakeRightClickDelegate;
+ }
+
+ public TapGestureRecognizer? TapGestureRecognizer => _dontCollectMePlease?.TapGestureRecognizer;
+
+ class FakeRightClickDelegate : UIContextMenuInteractionDelegate
+ {
+ WeakReference _recognizer;
+ WeakReference _gestureManager;
+
+ public TapGestureRecognizer? TapGestureRecognizer => _recognizer.Target as TapGestureRecognizer;
+ public FakeRightClickDelegate(TapGestureRecognizer tapGestureRecognizer, GestureManager gestureManager)
+ {
+ _recognizer = new WeakReference(tapGestureRecognizer);
+ _gestureManager = new WeakReference(gestureManager);
+ }
+
+ public override UIContextMenuConfiguration? GetConfigurationForMenu(UIContextMenuInteraction interaction, CGPoint location)
+ {
+ ProcessRecognizerHandlerTap(_gestureManager, _recognizer, location, 1);
+ return null;
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/Controls/src/Core/Platform/SemanticExtensions.cs b/src/Controls/src/Core/Platform/SemanticExtensions.cs
index 819a42217eb6..9d4a107a6a36 100644
--- a/src/Controls/src/Core/Platform/SemanticExtensions.cs
+++ b/src/Controls/src/Core/Platform/SemanticExtensions.cs
@@ -15,7 +15,7 @@ internal static bool TapGestureRecognizerNeedsDelegate(this View virtualView)
//Accessibility can't handle Tap Recognizers with > 1 tap
if (gesture is TapGestureRecognizer tgr && tgr.NumberOfTapsRequired == 1)
{
- return true;
+ return (tgr.Buttons & ButtonsMask.Primary) == ButtonsMask.Primary;
}
}
return false;
diff --git a/src/Controls/src/Core/Platform/Windows/VisualElementTracker.cs b/src/Controls/src/Core/Platform/Windows/VisualElementTracker.cs
index d13c5dc20a43..1c7bedd52321 100644
--- a/src/Controls/src/Core/Platform/Windows/VisualElementTracker.cs
+++ b/src/Controls/src/Core/Platform/Windows/VisualElementTracker.cs
@@ -25,7 +25,7 @@
namespace Microsoft.Maui.Controls.Platform
{
- // TODO MAUI: can we convert this over to using IView
+ [Obsolete("VisualElementTracker is obsolete as of .NET 7. This behavior has been built into ViewHandler and is included by default on anything that inherits from `Microsoft.Maui.Controls.View`. If something is missing for you please log an issue. In the mean time, you can try using Microsoft.Maui.Controls.Compatibility.Platform.UWP.VisualElementTracker")]
public class VisualElementTracker : IDisposable where TElement : VisualElement where TPlatformElement : FrameworkElement
{
readonly NotifyCollectionChangedEventHandler _collectionChangedHandler;
diff --git a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Shipped.txt b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Shipped.txt
index c4b270568482..2abe7d32f1d2 100644
--- a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Shipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Shipped.txt
@@ -2702,7 +2702,7 @@ Microsoft.Maui.Controls.TapGestureRecognizer
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.get -> int
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.set -> void
Microsoft.Maui.Controls.TapGestureRecognizer.TapGestureRecognizer() -> void
-Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
Microsoft.Maui.Controls.TappedEventArgs
Microsoft.Maui.Controls.TargetIdiom
Microsoft.Maui.Controls.TargetIdiom.Desktop = 3 -> Microsoft.Maui.Controls.TargetIdiom
@@ -5215,12 +5215,12 @@ virtual Microsoft.Maui.Controls.Window.OnStopped() -> void
~Microsoft.Maui.Controls.TableView.Root.get -> Microsoft.Maui.Controls.TableRoot
~Microsoft.Maui.Controls.TableView.Root.set -> void
~Microsoft.Maui.Controls.TableView.TableView(Microsoft.Maui.Controls.TableRoot root) -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
-~Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object
-~Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object parameter) -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand?
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object?
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
+Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object?
+Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object? parameter) -> void
~Microsoft.Maui.Controls.TemplateBinding.Converter.get -> Microsoft.Maui.Controls.IValueConverter
~Microsoft.Maui.Controls.TemplateBinding.Converter.set -> void
~Microsoft.Maui.Controls.TemplateBinding.ConverterParameter.get -> object
@@ -7570,9 +7570,9 @@ static readonly Microsoft.Maui.Controls.AdaptiveTrigger.MinWindowWidthProperty -
~static readonly Microsoft.Maui.Controls.TableSectionBase.TitleProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.HasUnevenRowsProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.RowHeightProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty!
~static readonly Microsoft.Maui.Controls.TemplatedPage.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TemplatedView.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TextCell.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
diff --git a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt
index 1127aa3bb1a9..88dc6cd3403a 100644
--- a/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt
@@ -9,6 +9,10 @@ Microsoft.Maui.Controls.MenuFlyout.IsReadOnly.get -> bool
Microsoft.Maui.Controls.MenuFlyout.RemoveAt(int index) -> void
Microsoft.Maui.Controls.MenuFlyoutSeparator
Microsoft.Maui.Controls.MenuFlyoutSeparator.MenuFlyoutSeparator() -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
+Microsoft.Maui.Controls.TappedEventArgs.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
Microsoft.Maui.Controls.ToolTipProperties
Microsoft.Maui.Controls.ToolTipProperties.ToolTipProperties() -> void
override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
@@ -22,6 +26,7 @@ override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConst
static Microsoft.Maui.Controls.ToolTipProperties.GetText(Microsoft.Maui.Controls.BindableObject! bindable) -> object!
static Microsoft.Maui.Controls.ToolTipProperties.SetText(Microsoft.Maui.Controls.BindableObject! bindable, object! value) -> void
static readonly Microsoft.Maui.Controls.ToolTipProperties.TextProperty -> Microsoft.Maui.Controls.BindableProperty!
+virtual Microsoft.Maui.Controls.TappedEventArgs.GetPosition(Microsoft.Maui.Controls.Element? relativeTo) -> Microsoft.Maui.Graphics.Point?
~Microsoft.Maui.Controls.MenuFlyout.Add(Microsoft.Maui.IMenuElement item) -> void
~Microsoft.Maui.Controls.MenuFlyout.Contains(Microsoft.Maui.IMenuElement item) -> bool
~Microsoft.Maui.Controls.MenuFlyout.CopyTo(Microsoft.Maui.IMenuElement[] array, int arrayIndex) -> void
@@ -42,3 +47,5 @@ static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsof
~static Microsoft.Maui.Controls.FlyoutBase.GetContextFlyout(Microsoft.Maui.Controls.BindableObject b) -> Microsoft.Maui.Controls.FlyoutBase
~static Microsoft.Maui.Controls.FlyoutBase.SetContextFlyout(Microsoft.Maui.Controls.BindableObject b, Microsoft.Maui.Controls.FlyoutBase value) -> void
~static readonly Microsoft.Maui.Controls.FlyoutBase.ContextFlyoutProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.ButtonsProperty -> Microsoft.Maui.Controls.BindableProperty!
+*REMOVED*Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
\ No newline at end of file
diff --git a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Shipped.txt b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Shipped.txt
index 7dd8e712d03e..7d9ba51c0e41 100644
--- a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Shipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Shipped.txt
@@ -2699,7 +2699,7 @@ Microsoft.Maui.Controls.TapGestureRecognizer
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.get -> int
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.set -> void
Microsoft.Maui.Controls.TapGestureRecognizer.TapGestureRecognizer() -> void
-Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
Microsoft.Maui.Controls.TappedEventArgs
Microsoft.Maui.Controls.TargetIdiom
Microsoft.Maui.Controls.TargetIdiom.Desktop = 3 -> Microsoft.Maui.Controls.TargetIdiom
@@ -5169,12 +5169,12 @@ virtual Microsoft.Maui.Controls.Window.OnStopped() -> void
~Microsoft.Maui.Controls.TableView.Root.get -> Microsoft.Maui.Controls.TableRoot
~Microsoft.Maui.Controls.TableView.Root.set -> void
~Microsoft.Maui.Controls.TableView.TableView(Microsoft.Maui.Controls.TableRoot root) -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
-~Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object
-~Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object parameter) -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand?
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object?
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
+Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object?
+Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object? parameter) -> void
~Microsoft.Maui.Controls.TemplateBinding.Converter.get -> Microsoft.Maui.Controls.IValueConverter
~Microsoft.Maui.Controls.TemplateBinding.Converter.set -> void
~Microsoft.Maui.Controls.TemplateBinding.ConverterParameter.get -> object
@@ -7606,9 +7606,9 @@ static readonly Microsoft.Maui.Controls.AdaptiveTrigger.MinWindowWidthProperty -
~static readonly Microsoft.Maui.Controls.TableSectionBase.TitleProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.HasUnevenRowsProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.RowHeightProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty!
~static readonly Microsoft.Maui.Controls.TemplatedPage.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TemplatedView.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TextCell.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
diff --git a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt
index e7b40843b15f..6f24828745f0 100644
--- a/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt
@@ -9,6 +9,10 @@ Microsoft.Maui.Controls.MenuFlyout.IsReadOnly.get -> bool
Microsoft.Maui.Controls.MenuFlyout.RemoveAt(int index) -> void
Microsoft.Maui.Controls.MenuFlyoutSeparator
Microsoft.Maui.Controls.MenuFlyoutSeparator.MenuFlyoutSeparator() -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
+Microsoft.Maui.Controls.TappedEventArgs.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
Microsoft.Maui.Controls.ToolTipProperties
Microsoft.Maui.Controls.ToolTipProperties.ToolTipProperties() -> void
override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
@@ -27,6 +31,7 @@ static Microsoft.Maui.Controls.ToolTipProperties.GetText(Microsoft.Maui.Controls
static Microsoft.Maui.Controls.ToolTipProperties.SetText(Microsoft.Maui.Controls.BindableObject! bindable, object! value) -> void
static readonly Microsoft.Maui.Controls.ToolTipProperties.TextProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsoft.Maui.Controls.BindableProperty!
+virtual Microsoft.Maui.Controls.TappedEventArgs.GetPosition(Microsoft.Maui.Controls.Element? relativeTo) -> Microsoft.Maui.Graphics.Point?
~Microsoft.Maui.Controls.MenuFlyout.Add(Microsoft.Maui.IMenuElement item) -> void
~Microsoft.Maui.Controls.MenuFlyout.Contains(Microsoft.Maui.IMenuElement item) -> bool
~Microsoft.Maui.Controls.MenuFlyout.CopyTo(Microsoft.Maui.IMenuElement[] array, int arrayIndex) -> void
@@ -39,3 +44,5 @@ static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsof
~static Microsoft.Maui.Controls.FlyoutBase.GetContextFlyout(Microsoft.Maui.Controls.BindableObject b) -> Microsoft.Maui.Controls.FlyoutBase
~static Microsoft.Maui.Controls.FlyoutBase.SetContextFlyout(Microsoft.Maui.Controls.BindableObject b, Microsoft.Maui.Controls.FlyoutBase value) -> void
~static readonly Microsoft.Maui.Controls.FlyoutBase.ContextFlyoutProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.ButtonsProperty -> Microsoft.Maui.Controls.BindableProperty!
+*REMOVED*Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
\ No newline at end of file
diff --git a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Shipped.txt b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Shipped.txt
index 7dd8e712d03e..7d9ba51c0e41 100644
--- a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Shipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Shipped.txt
@@ -2699,7 +2699,7 @@ Microsoft.Maui.Controls.TapGestureRecognizer
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.get -> int
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.set -> void
Microsoft.Maui.Controls.TapGestureRecognizer.TapGestureRecognizer() -> void
-Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
Microsoft.Maui.Controls.TappedEventArgs
Microsoft.Maui.Controls.TargetIdiom
Microsoft.Maui.Controls.TargetIdiom.Desktop = 3 -> Microsoft.Maui.Controls.TargetIdiom
@@ -5169,12 +5169,12 @@ virtual Microsoft.Maui.Controls.Window.OnStopped() -> void
~Microsoft.Maui.Controls.TableView.Root.get -> Microsoft.Maui.Controls.TableRoot
~Microsoft.Maui.Controls.TableView.Root.set -> void
~Microsoft.Maui.Controls.TableView.TableView(Microsoft.Maui.Controls.TableRoot root) -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
-~Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object
-~Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object parameter) -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand?
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object?
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
+Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object?
+Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object? parameter) -> void
~Microsoft.Maui.Controls.TemplateBinding.Converter.get -> Microsoft.Maui.Controls.IValueConverter
~Microsoft.Maui.Controls.TemplateBinding.Converter.set -> void
~Microsoft.Maui.Controls.TemplateBinding.ConverterParameter.get -> object
@@ -7606,9 +7606,9 @@ static readonly Microsoft.Maui.Controls.AdaptiveTrigger.MinWindowWidthProperty -
~static readonly Microsoft.Maui.Controls.TableSectionBase.TitleProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.HasUnevenRowsProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.RowHeightProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty!
~static readonly Microsoft.Maui.Controls.TemplatedPage.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TemplatedView.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TextCell.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
diff --git a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
index e7b40843b15f..6f24828745f0 100644
--- a/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
@@ -9,6 +9,10 @@ Microsoft.Maui.Controls.MenuFlyout.IsReadOnly.get -> bool
Microsoft.Maui.Controls.MenuFlyout.RemoveAt(int index) -> void
Microsoft.Maui.Controls.MenuFlyoutSeparator
Microsoft.Maui.Controls.MenuFlyoutSeparator.MenuFlyoutSeparator() -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
+Microsoft.Maui.Controls.TappedEventArgs.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
Microsoft.Maui.Controls.ToolTipProperties
Microsoft.Maui.Controls.ToolTipProperties.ToolTipProperties() -> void
override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
@@ -27,6 +31,7 @@ static Microsoft.Maui.Controls.ToolTipProperties.GetText(Microsoft.Maui.Controls
static Microsoft.Maui.Controls.ToolTipProperties.SetText(Microsoft.Maui.Controls.BindableObject! bindable, object! value) -> void
static readonly Microsoft.Maui.Controls.ToolTipProperties.TextProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsoft.Maui.Controls.BindableProperty!
+virtual Microsoft.Maui.Controls.TappedEventArgs.GetPosition(Microsoft.Maui.Controls.Element? relativeTo) -> Microsoft.Maui.Graphics.Point?
~Microsoft.Maui.Controls.MenuFlyout.Add(Microsoft.Maui.IMenuElement item) -> void
~Microsoft.Maui.Controls.MenuFlyout.Contains(Microsoft.Maui.IMenuElement item) -> bool
~Microsoft.Maui.Controls.MenuFlyout.CopyTo(Microsoft.Maui.IMenuElement[] array, int arrayIndex) -> void
@@ -39,3 +44,5 @@ static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsof
~static Microsoft.Maui.Controls.FlyoutBase.GetContextFlyout(Microsoft.Maui.Controls.BindableObject b) -> Microsoft.Maui.Controls.FlyoutBase
~static Microsoft.Maui.Controls.FlyoutBase.SetContextFlyout(Microsoft.Maui.Controls.BindableObject b, Microsoft.Maui.Controls.FlyoutBase value) -> void
~static readonly Microsoft.Maui.Controls.FlyoutBase.ContextFlyoutProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.ButtonsProperty -> Microsoft.Maui.Controls.BindableProperty!
+*REMOVED*Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
\ No newline at end of file
diff --git a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Shipped.txt b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Shipped.txt
index 795ba378551a..8cb5dff5b9bb 100644
--- a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Shipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Shipped.txt
@@ -4901,12 +4901,12 @@ virtual Microsoft.Maui.Controls.Window.OnStopped() -> void
~Microsoft.Maui.Controls.TableView.Root.get -> Microsoft.Maui.Controls.TableRoot
~Microsoft.Maui.Controls.TableView.Root.set -> void
~Microsoft.Maui.Controls.TableView.TableView(Microsoft.Maui.Controls.TableRoot root) -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
-~Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object
-~Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object parameter) -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand?
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object?
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
+Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object?
+Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object? parameter) -> void
~Microsoft.Maui.Controls.TemplateBinding.Converter.get -> Microsoft.Maui.Controls.IValueConverter
~Microsoft.Maui.Controls.TemplateBinding.Converter.set -> void
~Microsoft.Maui.Controls.TemplateBinding.ConverterParameter.get -> object
@@ -7194,9 +7194,9 @@ static readonly Microsoft.Maui.Controls.AdaptiveTrigger.MinWindowWidthProperty -
~static readonly Microsoft.Maui.Controls.TableSectionBase.TitleProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.HasUnevenRowsProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.RowHeightProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty!
~static readonly Microsoft.Maui.Controls.TemplatedPage.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TemplatedView.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TextCell.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
diff --git a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
index bf213f85eacb..c84813d38e49 100644
--- a/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
@@ -9,6 +9,10 @@ Microsoft.Maui.Controls.MenuFlyout.IsReadOnly.get -> bool
Microsoft.Maui.Controls.MenuFlyout.RemoveAt(int index) -> void
Microsoft.Maui.Controls.MenuFlyoutSeparator
Microsoft.Maui.Controls.MenuFlyoutSeparator.MenuFlyoutSeparator() -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
+Microsoft.Maui.Controls.TappedEventArgs.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
Microsoft.Maui.Controls.ToolTipProperties
Microsoft.Maui.Controls.ToolTipProperties.ToolTipProperties() -> void
override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
@@ -26,6 +30,7 @@ static Microsoft.Maui.Controls.ToolTipProperties.GetText(Microsoft.Maui.Controls
static Microsoft.Maui.Controls.ToolTipProperties.SetText(Microsoft.Maui.Controls.BindableObject! bindable, object! value) -> void
static readonly Microsoft.Maui.Controls.ToolTipProperties.TextProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsoft.Maui.Controls.BindableProperty!
+virtual Microsoft.Maui.Controls.TappedEventArgs.GetPosition(Microsoft.Maui.Controls.Element? relativeTo) -> Microsoft.Maui.Graphics.Point?
~Microsoft.Maui.Controls.MenuFlyout.Add(Microsoft.Maui.IMenuElement item) -> void
~Microsoft.Maui.Controls.MenuFlyout.Contains(Microsoft.Maui.IMenuElement item) -> bool
~Microsoft.Maui.Controls.MenuFlyout.CopyTo(Microsoft.Maui.IMenuElement[] array, int arrayIndex) -> void
@@ -38,3 +43,5 @@ static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsof
~static Microsoft.Maui.Controls.FlyoutBase.GetContextFlyout(Microsoft.Maui.Controls.BindableObject b) -> Microsoft.Maui.Controls.FlyoutBase
~static Microsoft.Maui.Controls.FlyoutBase.SetContextFlyout(Microsoft.Maui.Controls.BindableObject b, Microsoft.Maui.Controls.FlyoutBase value) -> void
~static readonly Microsoft.Maui.Controls.FlyoutBase.ContextFlyoutProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.ButtonsProperty -> Microsoft.Maui.Controls.BindableProperty!
+*REMOVED*Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler
\ No newline at end of file
diff --git a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Shipped.txt b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Shipped.txt
index c27d428577df..9980c5ecfed8 100644
--- a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Shipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Shipped.txt
@@ -2631,7 +2631,7 @@ Microsoft.Maui.Controls.TapGestureRecognizer
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.get -> int
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.set -> void
Microsoft.Maui.Controls.TapGestureRecognizer.TapGestureRecognizer() -> void
-Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
Microsoft.Maui.Controls.TappedEventArgs
Microsoft.Maui.Controls.TargetIdiom
Microsoft.Maui.Controls.TargetIdiom.Desktop = 3 -> Microsoft.Maui.Controls.TargetIdiom
@@ -4894,12 +4894,12 @@ virtual Microsoft.Maui.Controls.Window.OnStopped() -> void
~Microsoft.Maui.Controls.TableView.Root.get -> Microsoft.Maui.Controls.TableRoot
~Microsoft.Maui.Controls.TableView.Root.set -> void
~Microsoft.Maui.Controls.TableView.TableView(Microsoft.Maui.Controls.TableRoot root) -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
-~Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object
-~Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object parameter) -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand?
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object?
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
+Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object?
+Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object? parameter) -> void
~Microsoft.Maui.Controls.TemplateBinding.Converter.get -> Microsoft.Maui.Controls.IValueConverter
~Microsoft.Maui.Controls.TemplateBinding.Converter.set -> void
~Microsoft.Maui.Controls.TemplateBinding.ConverterParameter.get -> object
@@ -7238,9 +7238,9 @@ static readonly Microsoft.Maui.Controls.AdaptiveTrigger.MinWindowWidthProperty -
~static readonly Microsoft.Maui.Controls.TableSectionBase.TitleProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.HasUnevenRowsProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.RowHeightProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty!
~static readonly Microsoft.Maui.Controls.TemplatedPage.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TemplatedView.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TextCell.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
diff --git a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt
index f30d626778e8..59b356ab477e 100644
--- a/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt
@@ -12,6 +12,10 @@ Microsoft.Maui.Controls.Platform.ShellNavigationViewItem.ShellNavigationViewItem
Microsoft.Maui.Controls.Platform.ShellNavigationViewItemAutomationPeer
Microsoft.Maui.Controls.MenuFlyoutSeparator
Microsoft.Maui.Controls.MenuFlyoutSeparator.MenuFlyoutSeparator() -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
+Microsoft.Maui.Controls.TappedEventArgs.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
Microsoft.Maui.Controls.ToolTipProperties
Microsoft.Maui.Controls.ToolTipProperties.ToolTipProperties() -> void
override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
@@ -26,6 +30,7 @@ override Microsoft.Maui.Controls.TemplatedView.MeasureOverride(double widthConst
*REMOVED*override Microsoft.Maui.Controls.RadioButton.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
*REMOVED*override Microsoft.Maui.Controls.FlexLayout.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
*REMOVED*override Microsoft.Maui.Controls.Platform.ShellFlyoutItemView.OnContentChanged(object oldContent, object newContent) -> void
+virtual Microsoft.Maui.Controls.TappedEventArgs.GetPosition(Microsoft.Maui.Controls.Element? relativeTo) -> Microsoft.Maui.Graphics.Point?
~Microsoft.Maui.Controls.Platform.ShellNavigationViewItemAutomationPeer.ShellNavigationViewItemAutomationPeer(Microsoft.Maui.Controls.Platform.ShellNavigationViewItem owner) -> void
~override Microsoft.Maui.Controls.Platform.ShellNavigationViewItem.OnCreateAutomationPeer() -> Microsoft.UI.Xaml.Automation.Peers.AutomationPeer
~override Microsoft.Maui.Controls.Platform.ShellNavigationViewItemAutomationPeer.GetChildrenCore() -> System.Collections.Generic.IList
@@ -46,3 +51,5 @@ static readonly Microsoft.Maui.Controls.ToolTipProperties.TextProperty -> Micros
~static Microsoft.Maui.Controls.FlyoutBase.GetContextFlyout(Microsoft.Maui.Controls.BindableObject b) -> Microsoft.Maui.Controls.FlyoutBase
~static Microsoft.Maui.Controls.FlyoutBase.SetContextFlyout(Microsoft.Maui.Controls.BindableObject b, Microsoft.Maui.Controls.FlyoutBase value) -> void
~static readonly Microsoft.Maui.Controls.FlyoutBase.ContextFlyoutProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.ButtonsProperty -> Microsoft.Maui.Controls.BindableProperty!
+*REMOVED*Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
\ No newline at end of file
diff --git a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Shipped.txt b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Shipped.txt
index 25ecdc557649..2d3d3299a78b 100644
--- a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Shipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Shipped.txt
@@ -2474,7 +2474,7 @@ Microsoft.Maui.Controls.TapGestureRecognizer
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.get -> int
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.set -> void
Microsoft.Maui.Controls.TapGestureRecognizer.TapGestureRecognizer() -> void
-Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
Microsoft.Maui.Controls.TappedEventArgs
Microsoft.Maui.Controls.TargetIdiom
Microsoft.Maui.Controls.TargetIdiom.Desktop = 3 -> Microsoft.Maui.Controls.TargetIdiom
@@ -4574,12 +4574,12 @@ virtual Microsoft.Maui.Controls.Window.OnStopped() -> void
~Microsoft.Maui.Controls.TableView.Root.get -> Microsoft.Maui.Controls.TableRoot
~Microsoft.Maui.Controls.TableView.Root.set -> void
~Microsoft.Maui.Controls.TableView.TableView(Microsoft.Maui.Controls.TableRoot root) -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
-~Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object
-~Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object parameter) -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand?
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object?
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
+Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object?
+Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object? parameter) -> void
~Microsoft.Maui.Controls.TemplateBinding.Converter.get -> Microsoft.Maui.Controls.IValueConverter
~Microsoft.Maui.Controls.TemplateBinding.Converter.set -> void
~Microsoft.Maui.Controls.TemplateBinding.ConverterParameter.get -> object
@@ -6806,9 +6806,9 @@ static readonly Microsoft.Maui.Controls.AdaptiveTrigger.MinWindowWidthProperty -
~static readonly Microsoft.Maui.Controls.TableSectionBase.TitleProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.HasUnevenRowsProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.RowHeightProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty!
~static readonly Microsoft.Maui.Controls.TemplatedPage.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TemplatedView.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TextCell.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
diff --git a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt
index bf213f85eacb..518183110f44 100644
--- a/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt
@@ -9,6 +9,10 @@ Microsoft.Maui.Controls.MenuFlyout.IsReadOnly.get -> bool
Microsoft.Maui.Controls.MenuFlyout.RemoveAt(int index) -> void
Microsoft.Maui.Controls.MenuFlyoutSeparator
Microsoft.Maui.Controls.MenuFlyoutSeparator.MenuFlyoutSeparator() -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
+Microsoft.Maui.Controls.TappedEventArgs.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
Microsoft.Maui.Controls.ToolTipProperties
Microsoft.Maui.Controls.ToolTipProperties.ToolTipProperties() -> void
override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
@@ -26,6 +30,7 @@ static Microsoft.Maui.Controls.ToolTipProperties.GetText(Microsoft.Maui.Controls
static Microsoft.Maui.Controls.ToolTipProperties.SetText(Microsoft.Maui.Controls.BindableObject! bindable, object! value) -> void
static readonly Microsoft.Maui.Controls.ToolTipProperties.TextProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsoft.Maui.Controls.BindableProperty!
+virtual Microsoft.Maui.Controls.TappedEventArgs.GetPosition(Microsoft.Maui.Controls.Element? relativeTo) -> Microsoft.Maui.Graphics.Point?
~Microsoft.Maui.Controls.MenuFlyout.Add(Microsoft.Maui.IMenuElement item) -> void
~Microsoft.Maui.Controls.MenuFlyout.Contains(Microsoft.Maui.IMenuElement item) -> bool
~Microsoft.Maui.Controls.MenuFlyout.CopyTo(Microsoft.Maui.IMenuElement[] array, int arrayIndex) -> void
@@ -38,3 +43,5 @@ static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsof
~static Microsoft.Maui.Controls.FlyoutBase.GetContextFlyout(Microsoft.Maui.Controls.BindableObject b) -> Microsoft.Maui.Controls.FlyoutBase
~static Microsoft.Maui.Controls.FlyoutBase.SetContextFlyout(Microsoft.Maui.Controls.BindableObject b, Microsoft.Maui.Controls.FlyoutBase value) -> void
~static readonly Microsoft.Maui.Controls.FlyoutBase.ContextFlyoutProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.ButtonsProperty -> Microsoft.Maui.Controls.BindableProperty!
+*REMOVED*Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
\ No newline at end of file
diff --git a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Shipped.txt b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Shipped.txt
index 25ecdc557649..2d3d3299a78b 100644
--- a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Shipped.txt
+++ b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Shipped.txt
@@ -2474,7 +2474,7 @@ Microsoft.Maui.Controls.TapGestureRecognizer
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.get -> int
Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequired.set -> void
Microsoft.Maui.Controls.TapGestureRecognizer.TapGestureRecognizer() -> void
-Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
Microsoft.Maui.Controls.TappedEventArgs
Microsoft.Maui.Controls.TargetIdiom
Microsoft.Maui.Controls.TargetIdiom.Desktop = 3 -> Microsoft.Maui.Controls.TargetIdiom
@@ -4574,12 +4574,12 @@ virtual Microsoft.Maui.Controls.Window.OnStopped() -> void
~Microsoft.Maui.Controls.TableView.Root.get -> Microsoft.Maui.Controls.TableRoot
~Microsoft.Maui.Controls.TableView.Root.set -> void
~Microsoft.Maui.Controls.TableView.TableView(Microsoft.Maui.Controls.TableRoot root) -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand
-~Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object
-~Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
-~Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object
-~Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object parameter) -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.get -> System.Windows.Input.ICommand?
+Microsoft.Maui.Controls.TapGestureRecognizer.Command.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.get -> object?
+Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameter.set -> void
+Microsoft.Maui.Controls.TappedEventArgs.Parameter.get -> object?
+Microsoft.Maui.Controls.TappedEventArgs.TappedEventArgs(object? parameter) -> void
~Microsoft.Maui.Controls.TemplateBinding.Converter.get -> Microsoft.Maui.Controls.IValueConverter
~Microsoft.Maui.Controls.TemplateBinding.Converter.set -> void
~Microsoft.Maui.Controls.TemplateBinding.ConverterParameter.get -> object
@@ -6806,9 +6806,9 @@ static readonly Microsoft.Maui.Controls.AdaptiveTrigger.MinWindowWidthProperty -
~static readonly Microsoft.Maui.Controls.TableSectionBase.TitleProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.HasUnevenRowsProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TableView.RowHeightProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty
-~static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.CommandProperty -> Microsoft.Maui.Controls.BindableProperty!
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.NumberOfTapsRequiredProperty -> Microsoft.Maui.Controls.BindableProperty!
~static readonly Microsoft.Maui.Controls.TemplatedPage.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TemplatedView.ControlTemplateProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.TextCell.CommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
diff --git a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt
index bf213f85eacb..518183110f44 100644
--- a/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt
+++ b/src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt
@@ -9,6 +9,10 @@ Microsoft.Maui.Controls.MenuFlyout.IsReadOnly.get -> bool
Microsoft.Maui.Controls.MenuFlyout.RemoveAt(int index) -> void
Microsoft.Maui.Controls.MenuFlyoutSeparator
Microsoft.Maui.Controls.MenuFlyoutSeparator.MenuFlyoutSeparator() -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
+Microsoft.Maui.Controls.TapGestureRecognizer.Buttons.set -> void
+Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
+Microsoft.Maui.Controls.TappedEventArgs.Buttons.get -> Microsoft.Maui.Controls.ButtonsMask
Microsoft.Maui.Controls.ToolTipProperties
Microsoft.Maui.Controls.ToolTipProperties.ToolTipProperties() -> void
override Microsoft.Maui.Controls.ContentPresenter.ArrangeOverride(Microsoft.Maui.Graphics.Rect bounds) -> Microsoft.Maui.Graphics.Size
@@ -26,6 +30,7 @@ static Microsoft.Maui.Controls.ToolTipProperties.GetText(Microsoft.Maui.Controls
static Microsoft.Maui.Controls.ToolTipProperties.SetText(Microsoft.Maui.Controls.BindableObject! bindable, object! value) -> void
static readonly Microsoft.Maui.Controls.ToolTipProperties.TextProperty -> Microsoft.Maui.Controls.BindableProperty!
static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsoft.Maui.Controls.BindableProperty!
+virtual Microsoft.Maui.Controls.TappedEventArgs.GetPosition(Microsoft.Maui.Controls.Element? relativeTo) -> Microsoft.Maui.Graphics.Point?
~Microsoft.Maui.Controls.MenuFlyout.Add(Microsoft.Maui.IMenuElement item) -> void
~Microsoft.Maui.Controls.MenuFlyout.Contains(Microsoft.Maui.IMenuElement item) -> bool
~Microsoft.Maui.Controls.MenuFlyout.CopyTo(Microsoft.Maui.IMenuElement[] array, int arrayIndex) -> void
@@ -38,3 +43,5 @@ static readonly Microsoft.Maui.Controls.VisualElement.ZIndexProperty -> Microsof
~static Microsoft.Maui.Controls.FlyoutBase.GetContextFlyout(Microsoft.Maui.Controls.BindableObject b) -> Microsoft.Maui.Controls.FlyoutBase
~static Microsoft.Maui.Controls.FlyoutBase.SetContextFlyout(Microsoft.Maui.Controls.BindableObject b, Microsoft.Maui.Controls.FlyoutBase value) -> void
~static readonly Microsoft.Maui.Controls.FlyoutBase.ContextFlyoutProperty -> Microsoft.Maui.Controls.BindableProperty
+static readonly Microsoft.Maui.Controls.TapGestureRecognizer.ButtonsProperty -> Microsoft.Maui.Controls.BindableProperty!
+*REMOVED*Microsoft.Maui.Controls.TapGestureRecognizer.Tapped -> System.EventHandler?
\ No newline at end of file
diff --git a/src/Controls/src/Core/Span.cs b/src/Controls/src/Core/Span.cs
index 423cc531cc76..0058ec9ad973 100644
--- a/src/Controls/src/Core/Span.cs
+++ b/src/Controls/src/Core/Span.cs
@@ -183,7 +183,6 @@ internal override void ValidateGesture(IGestureRecognizer gesture)
{
switch (gesture)
{
- case ClickGestureRecognizer click:
case TapGestureRecognizer tap:
case null:
break;
diff --git a/src/Controls/src/Core/TapGestureRecognizer.cs b/src/Controls/src/Core/TapGestureRecognizer.cs
index cf737e29ea8d..84a37b21b3dd 100644
--- a/src/Controls/src/Core/TapGestureRecognizer.cs
+++ b/src/Controls/src/Core/TapGestureRecognizer.cs
@@ -1,6 +1,8 @@
+#nullable enable
+
using System;
-using System.ComponentModel;
using System.Windows.Input;
+using Microsoft.Maui.Graphics;
namespace Microsoft.Maui.Controls
{
@@ -11,25 +13,27 @@ public sealed class TapGestureRecognizer : GestureRecognizer
public static readonly BindableProperty CommandProperty = BindableProperty.Create("Command", typeof(ICommand), typeof(TapGestureRecognizer), null);
///
- public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create("CommandParameter", typeof(object), typeof(TapGestureRecognizer), null);
+ public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(TapGestureRecognizer), null);
///
public static readonly BindableProperty NumberOfTapsRequiredProperty = BindableProperty.Create("NumberOfTapsRequired", typeof(int), typeof(TapGestureRecognizer), 1);
+ public static readonly BindableProperty ButtonsProperty = BindableProperty.Create(nameof(Buttons), typeof(ButtonsMask), typeof(TapGestureRecognizer), ButtonsMask.Primary);
+
///
public TapGestureRecognizer()
{
}
///
- public ICommand Command
+ public ICommand? Command
{
- get { return (ICommand)GetValue(CommandProperty); }
+ get { return (ICommand?)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
///
- public object CommandParameter
+ public object? CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
@@ -42,17 +46,22 @@ public int NumberOfTapsRequired
set { SetValue(NumberOfTapsRequiredProperty, value); }
}
- public event EventHandler Tapped;
+ public ButtonsMask Buttons
+ {
+ get { return (ButtonsMask)GetValue(ButtonsProperty); }
+ set { SetValue(ButtonsProperty, value); }
+ }
+
+ public event EventHandler? Tapped;
- internal void SendTapped(View sender)
+ internal void SendTapped(View sender, Func? getPosition = null)
{
- ICommand cmd = Command;
+ var cmd = Command;
if (cmd != null && cmd.CanExecute(CommandParameter))
cmd.Execute(CommandParameter);
- EventHandler handler = Tapped;
- if (handler != null)
- handler(sender, new TappedEventArgs(CommandParameter));
+ Tapped?.Invoke(sender, new TappedEventArgs(CommandParameter, getPosition));
}
+
}
}
\ No newline at end of file
diff --git a/src/Controls/src/Core/TappedEventArgs.cs b/src/Controls/src/Core/TappedEventArgs.cs
index 9db19e8f7168..33ca22a48c05 100644
--- a/src/Controls/src/Core/TappedEventArgs.cs
+++ b/src/Controls/src/Core/TappedEventArgs.cs
@@ -1,17 +1,32 @@
+#nullable enable
+
using System;
+using Microsoft.Maui.Graphics;
namespace Microsoft.Maui.Controls
{
///
public class TappedEventArgs : EventArgs
{
+ Func? _getPosition;
+
///
- public TappedEventArgs(object parameter)
+ public TappedEventArgs(object? parameter)
{
Parameter = parameter;
}
+ internal TappedEventArgs(object? parameter, Func? getPosition) : this(parameter)
+ {
+ _getPosition = getPosition;
+ }
+
///
- public object Parameter { get; private set; }
+ public object? Parameter { get; private set; }
+
+ public ButtonsMask Buttons { get; private set; }
+
+ public virtual Point? GetPosition(Element? relativeTo) =>
+ _getPosition?.Invoke(relativeTo);
}
}
\ No newline at end of file
diff --git a/src/Controls/tests/DeviceTests/GestureTests.iOS.cs b/src/Controls/tests/DeviceTests/GestureTests.iOS.cs
index bf581e129d46..c7c5190a5783 100644
--- a/src/Controls/tests/DeviceTests/GestureTests.iOS.cs
+++ b/src/Controls/tests/DeviceTests/GestureTests.iOS.cs
@@ -3,6 +3,7 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Maui.Controls;
+using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Dispatching;
using Microsoft.Maui.Handlers;
@@ -27,5 +28,59 @@ await InvokeOnMainThreadAsync(() =>
Assert.True(handler.PlatformView.UserInteractionEnabled);
});
}
+
+#if MACCATALYST
+ [Fact]
+ public async Task InteractionsAreRemovedWhenGestureIsRemoved()
+ {
+ var label = new Label();
+ label.GestureRecognizers.Add(new TapGestureRecognizer() { Buttons = ButtonsMask.Secondary });
+
+ await InvokeOnMainThreadAsync(() =>
+ {
+ var handler = CreateHandler(label);
+
+ var interactions =
+ handler.PlatformView.Interactions.OfType()
+ .ToList();
+
+ Assert.Single(interactions);
+
+ label.GestureRecognizers.RemoveAt(0);
+
+ interactions =
+ handler.PlatformView.Interactions.OfType()
+ .ToList();
+
+ Assert.Empty(interactions);
+ });
+ }
+
+ [Fact]
+ public async Task InteractionsAreRemovedWhenGestureButtonMaskChanged()
+ {
+ var label = new Label();
+ label.GestureRecognizers.Add(new TapGestureRecognizer() { Buttons = ButtonsMask.Secondary });
+
+ await InvokeOnMainThreadAsync(() =>
+ {
+ var handler = CreateHandler(label);
+
+ var interactions =
+ handler.PlatformView.Interactions.OfType()
+ .ToList();
+
+ Assert.Single(interactions);
+
+ (label.GestureRecognizers[0] as TapGestureRecognizer).Buttons = ButtonsMask.Primary;
+
+ interactions =
+ handler.PlatformView.Interactions.OfType()
+ .ToList();
+
+ Assert.Empty(interactions);
+ });
+ }
+#endif
}
}
diff --git a/src/Core/src/Handlers/View/ViewHandler.iOS.cs b/src/Core/src/Handlers/View/ViewHandler.iOS.cs
index 81dea8e249a7..78233060a780 100644
--- a/src/Core/src/Handlers/View/ViewHandler.iOS.cs
+++ b/src/Core/src/Handlers/View/ViewHandler.iOS.cs
@@ -55,7 +55,14 @@ internal static void MapContextFlyout(IElementHandler handler, IContextFlyoutEle
static partial void MappingFrame(IViewHandler handler, IView view)
{
UpdateTransformation(handler, view);
- handler.ToPlatform().UpdateBackgroundLayerFrame();
+
+ var platformView = handler.ToPlatform();
+
+ if (platformView != null)
+ {
+ platformView.UpdateBackgroundLayerFrame();
+ platformView.UpdateShadowLayerFrame();
+ }
}
public static void MapTranslationX(IViewHandler handler, IView view)
diff --git a/src/Core/src/Layouts/HorizontalStackLayoutManager.cs b/src/Core/src/Layouts/HorizontalStackLayoutManager.cs
index 89cc5063da2b..459a3964e4b6 100644
--- a/src/Core/src/Layouts/HorizontalStackLayoutManager.cs
+++ b/src/Core/src/Layouts/HorizontalStackLayoutManager.cs
@@ -16,6 +16,7 @@ public override Size Measure(double widthConstraint, double heightConstraint)
double measuredWidth = 0;
double measuredHeight = 0;
+ int spacingCount = 0;
for (int n = 0; n < Stack.Count; n++)
{
@@ -26,12 +27,13 @@ public override Size Measure(double widthConstraint, double heightConstraint)
continue;
}
+ spacingCount += 1;
var measure = child.Measure(double.PositiveInfinity, heightConstraint - padding.VerticalThickness);
measuredWidth += measure.Width;
measuredHeight = Math.Max(measuredHeight, measure.Height);
}
- measuredWidth += MeasureSpacing(Stack.Spacing, Stack.Count);
+ measuredWidth += MeasureSpacing(Stack.Spacing, spacingCount);
measuredWidth += padding.HorizontalThickness;
measuredHeight += padding.VerticalThickness;
diff --git a/src/Core/src/Layouts/VerticalStackLayoutManager.cs b/src/Core/src/Layouts/VerticalStackLayoutManager.cs
index 3de65b1bb4ba..465b3b00e973 100644
--- a/src/Core/src/Layouts/VerticalStackLayoutManager.cs
+++ b/src/Core/src/Layouts/VerticalStackLayoutManager.cs
@@ -16,6 +16,7 @@ public override Size Measure(double widthConstraint, double heightConstraint)
double measuredHeight = 0;
double measuredWidth = 0;
double childWidthConstraint = widthConstraint - padding.HorizontalThickness;
+ int spacingCount = 0;
for (int n = 0; n < Stack.Count; n++)
{
@@ -26,12 +27,13 @@ public override Size Measure(double widthConstraint, double heightConstraint)
continue;
}
+ spacingCount += 1;
var measure = child.Measure(childWidthConstraint, double.PositiveInfinity);
measuredHeight += measure.Height;
measuredWidth = Math.Max(measuredWidth, measure.Width);
}
- measuredHeight += MeasureSpacing(Stack.Spacing, Stack.Count);
+ measuredHeight += MeasureSpacing(Stack.Spacing, spacingCount);
measuredHeight += padding.VerticalThickness;
measuredWidth += padding.HorizontalThickness;
diff --git a/src/Core/src/Platform/Windows/RoutedEventArgsExtensions.cs b/src/Core/src/Platform/Windows/RoutedEventArgsExtensions.cs
new file mode 100644
index 000000000000..eec449bf0b5d
--- /dev/null
+++ b/src/Core/src/Platform/Windows/RoutedEventArgsExtensions.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.UI.Xaml.Input;
+using Microsoft.UI.Xaml;
+using WPoint = Windows.Foundation.Point;
+namespace Microsoft.Maui.Platform
+{
+ internal static class RoutedEventArgsExtensions
+ {
+ public static void SetHandled(this RoutedEventArgs e, bool value)
+ {
+ if (e is RightTappedRoutedEventArgs rt)
+ rt.Handled = value;
+ else if (e is TappedRoutedEventArgs t)
+ t.Handled = value;
+ else if (e is DoubleTappedRoutedEventArgs dt)
+ dt.Handled = value;
+ }
+
+ public static WPoint? GetPositionRelativeToElement(this RoutedEventArgs e, IElement? relativeTo)
+ {
+ if (relativeTo == null)
+ return GetPositionRelativeToPlatformElement(e, null);
+
+ if (relativeTo?.Handler?.PlatformView is UIElement element)
+ return GetPositionRelativeToPlatformElement(e, element);
+
+ return null;
+ }
+
+ public static WPoint? GetPositionRelativeToPlatformElement(this RoutedEventArgs e, UIElement? relativeTo)
+ {
+ if (e is RightTappedRoutedEventArgs rt)
+ return rt.GetPosition(relativeTo);
+ else if (e is TappedRoutedEventArgs t)
+ return t.GetPosition(relativeTo);
+ else if (e is DoubleTappedRoutedEventArgs dt)
+ return dt.GetPosition(relativeTo);
+
+ return null;
+ }
+ }
+}
diff --git a/src/Core/src/Platform/iOS/ViewExtensions.cs b/src/Core/src/Platform/iOS/ViewExtensions.cs
index a7b69e983608..c9f7a8af22a0 100644
--- a/src/Core/src/Platform/iOS/ViewExtensions.cs
+++ b/src/Core/src/Platform/iOS/ViewExtensions.cs
@@ -59,9 +59,9 @@ public static void UpdateVisibility(this UIView platformView, Visibility visibil
public static void UpdateBackground(this ContentView platformView, IBorderStroke border)
{
- bool hasBorder = border.Shape != null && border.Stroke != null;
+ bool hasShape = border.Shape != null;
- if (hasBorder)
+ if (hasShape)
{
platformView.UpdateMauiCALayer(border);
}
@@ -213,6 +213,27 @@ public static void UpdateBackgroundLayerFrame(this UIView view)
}
}
+ // TODO: NET7 make this public for net7.0
+ internal static void UpdateShadowLayerFrame(this UIView view)
+ {
+ if (view == null || view.Frame.IsEmpty)
+ return;
+
+ var layer = view.Layer;
+
+ if (layer == null || layer.Sublayers == null || layer.Sublayers.Length == 0)
+ return;
+
+ foreach (var sublayer in layer.Sublayers)
+ {
+ if (sublayer.Opacity > 0) // If the layer has shadow, invalidate the Size
+ {
+ sublayer.Frame = view.Bounds;
+ break;
+ }
+ }
+ }
+
public static void InvalidateMeasure(this UIView platformView, IView view)
{
platformView.SetNeedsLayout();
diff --git a/src/Core/tests/UnitTests/Layouts/GridLayoutManagerTests.cs b/src/Core/tests/UnitTests/Layouts/GridLayoutManagerTests.cs
index 010e1d9b8843..681ab715ad36 100644
--- a/src/Core/tests/UnitTests/Layouts/GridLayoutManagerTests.cs
+++ b/src/Core/tests/UnitTests/Layouts/GridLayoutManagerTests.cs
@@ -372,6 +372,30 @@ public void RowSpacingForEmptyRows()
Assert.Equal(100 + 100 + 10, measure.Height);
}
+ [Category(GridSpacing, GridAutoSizing)]
+ [Fact(DisplayName = "Auto rows with collapsed views should not incur additional row spacing")]
+ public void RowSpacingForAutoRowsWithCollapsedViews()
+ {
+ var grid = CreateGridLayout(rows: "100, auto, 100", rowSpacing: 10);
+ var view0 = CreateTestView(new Size(100, 100));
+ var view1 = CreateTestView(new Size(100, 100));
+ var view2 = CreateTestView(new Size(100, 100));
+
+ SubstituteChildren(grid, view0, view2);
+ SetLocation(grid, view0);
+ SetLocation(grid, view1, row: 1);
+ SetLocation(grid, view2, row: 2);
+
+ view1.Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new GridLayoutManager(grid);
+ var measure = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ // Because the auto row has no content, we expect it to have height zero
+ // and we expect that it won't add more row spacing
+ Assert.Equal(100 + 100 + 10, measure.Height);
+ }
+
[Category(GridSpacing)]
[Fact(DisplayName = "Column spacing shouldn't affect a single-column grid")]
public void SingleColumnIgnoresColumnSpacing()
@@ -462,6 +486,30 @@ public void ColumnSpacingForEmptyColumns()
Assert.Equal(100 + 100 + 10, measure.Width);
}
+ [Category(GridSpacing, GridAutoSizing)]
+ [Fact(DisplayName = "Auto columns with collapsed views should not incur additional column spacing")]
+ public void AutoColumnsWithCollapsedViews()
+ {
+ var grid = CreateGridLayout(columns: "100, auto, 100", colSpacing: 10);
+ var view0 = CreateTestView(new Size(100, 100));
+ var view1 = CreateTestView(new Size(100, 100));
+ var view2 = CreateTestView(new Size(100, 100));
+
+ SubstituteChildren(grid, view0, view2);
+ SetLocation(grid, view0);
+ SetLocation(grid, view1, col: 1);
+ SetLocation(grid, view2, col: 2);
+
+ view1.Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new GridLayoutManager(grid);
+ var measure = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ // Because the auto column has no content, we expect it to have width zero
+ // and we expect that it won't add more column spacing
+ Assert.Equal(100 + 100 + 10, measure.Width);
+ }
+
[Category(GridSpan)]
[Fact(DisplayName = "Simple row spanning")]
public void ViewSpansRows()
diff --git a/src/Core/tests/UnitTests/Layouts/HorizontalStackLayoutManagerTests.cs b/src/Core/tests/UnitTests/Layouts/HorizontalStackLayoutManagerTests.cs
index b32f0abd65af..3d47be7bfba9 100644
--- a/src/Core/tests/UnitTests/Layouts/HorizontalStackLayoutManagerTests.cs
+++ b/src/Core/tests/UnitTests/Layouts/HorizontalStackLayoutManagerTests.cs
@@ -427,5 +427,87 @@ public void ChildMeasureAccountsForPadding(Size viewSize, Thickness padding, Siz
view.Received().Measure(Arg.Is(expectedMeasureConstraint.Width), Arg.Is(expectedMeasureConstraint.Height));
}
+
+ [Fact]
+ public void CollapsedItemsDoNotIncurSpacingInMiddle()
+ {
+ var viewWidth = 5;
+ var viewHeight = 7;
+ var spacing = 10;
+
+ var stack = SetUpVisibilityTestStack(viewWidth, viewHeight, spacing);
+ stack.Spacing.Returns(spacing);
+
+ stack[1].Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new HorizontalStackLayoutManager(stack);
+ var measuredSize = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ var expectedWidth = viewWidth + spacing + viewWidth;
+
+ Assert.Equal(expectedWidth, measuredSize.Width);
+ }
+
+ [Fact]
+ public void CollapsedItemsDoNotIncurSpacingAtEnd()
+ {
+ var viewWidth = 5;
+ var viewHeight = 7;
+ var spacing = 10;
+
+ var stack = SetUpVisibilityTestStack(viewWidth, viewHeight, spacing);
+ stack.Spacing.Returns(spacing);
+
+ stack[2].Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new HorizontalStackLayoutManager(stack);
+ var measuredSize = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ var expectedWidth = viewWidth + spacing + viewWidth;
+
+ Assert.Equal(expectedWidth, measuredSize.Width);
+ }
+
+ [Fact]
+ public void CollapsedItemsDoNotIncurSpacingAtStart()
+ {
+ var viewWidth = 5;
+ var viewHeight = 7;
+ var spacing = 10;
+
+ var stack = SetUpVisibilityTestStack(viewWidth, viewHeight, spacing);
+ stack.Spacing.Returns(spacing);
+
+ stack[0].Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new HorizontalStackLayoutManager(stack);
+ var measuredSize = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ var expectedWidth = viewWidth + spacing + viewWidth;
+
+ Assert.Equal(expectedWidth, measuredSize.Width);
+ }
+
+ [Fact]
+ public void LayoutWithAllCollapsedItemsHasNoSpacing()
+ {
+ var viewWidth = 5;
+ var viewHeight = 7;
+ var spacing = 10;
+
+ var stack = SetUpVisibilityTestStack(viewWidth, viewHeight, spacing);
+ stack.Spacing.Returns(spacing);
+
+ stack[0].Visibility.Returns(Visibility.Collapsed);
+ stack[1].Visibility.Returns(Visibility.Collapsed);
+ stack[2].Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new HorizontalStackLayoutManager(stack);
+ var measuredSize = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ var expectedWidth = 0;
+
+ Assert.Equal(expectedWidth, measuredSize.Width);
+ }
}
}
diff --git a/src/Core/tests/UnitTests/Layouts/StackLayoutManagerTests.cs b/src/Core/tests/UnitTests/Layouts/StackLayoutManagerTests.cs
index 91297e3b3862..a9e44341fd65 100644
--- a/src/Core/tests/UnitTests/Layouts/StackLayoutManagerTests.cs
+++ b/src/Core/tests/UnitTests/Layouts/StackLayoutManagerTests.cs
@@ -68,5 +68,17 @@ protected IStackLayout BuildStack(int viewCount, double viewWidth, double viewHe
return stack;
}
+
+ protected IStackLayout SetUpVisibilityTestStack(double viewWidth, double viewHeight, double spacing)
+ {
+ var startView = CreateTestView(new Size(viewWidth, viewHeight));
+ var middleView = CreateTestView(new Size(viewWidth, viewHeight));
+ var endView = CreateTestView(new Size(viewWidth, viewHeight));
+
+ var stack = CreateTestLayout(new List { startView, middleView, endView });
+ stack.Spacing.Returns(spacing);
+
+ return stack;
+ }
}
}
diff --git a/src/Core/tests/UnitTests/Layouts/VerticalStackLayoutManagerTests.cs b/src/Core/tests/UnitTests/Layouts/VerticalStackLayoutManagerTests.cs
index 299eb41b0d7a..ac7c0c0c6b35 100644
--- a/src/Core/tests/UnitTests/Layouts/VerticalStackLayoutManagerTests.cs
+++ b/src/Core/tests/UnitTests/Layouts/VerticalStackLayoutManagerTests.cs
@@ -361,5 +361,87 @@ public void ChildMeasureAccountsForPadding(Size viewSize, Thickness padding, Siz
view.Received().Measure(Arg.Is(expectedMeasureConstraint.Width), Arg.Is(expectedMeasureConstraint.Height));
}
+
+ [Fact]
+ public void CollapsedItemsDoNotIncurSpacingInMiddle()
+ {
+ var viewWidth = 7;
+ var viewHeight = 5;
+ var spacing = 10;
+
+ var stack = SetUpVisibilityTestStack(viewWidth, viewHeight, spacing);
+ stack.Spacing.Returns(spacing);
+
+ stack[1].Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new VerticalStackLayoutManager(stack);
+ var measuredSize = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ var expectedHeight = viewHeight + spacing + viewHeight;
+
+ Assert.Equal(expectedHeight, measuredSize.Height);
+ }
+
+ [Fact]
+ public void CollapsedItemsDoNotIncurSpacingAtEnd()
+ {
+ var viewWidth = 7;
+ var viewHeight = 5;
+ var spacing = 10;
+
+ var stack = SetUpVisibilityTestStack(viewWidth, viewHeight, spacing);
+ stack.Spacing.Returns(spacing);
+
+ stack[2].Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new VerticalStackLayoutManager(stack);
+ var measuredSize = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ var expectedHeight = viewHeight + spacing + viewHeight;
+
+ Assert.Equal(expectedHeight, measuredSize.Height);
+ }
+
+ [Fact]
+ public void CollapsedItemsDoNotIncurSpacingAtStart()
+ {
+ var viewWidth = 7;
+ var viewHeight = 5;
+ var spacing = 10;
+
+ var stack = SetUpVisibilityTestStack(viewWidth, viewHeight, spacing);
+ stack.Spacing.Returns(spacing);
+
+ stack[0].Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new VerticalStackLayoutManager(stack);
+ var measuredSize = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ var expectedHeight = viewHeight + spacing + viewHeight;
+
+ Assert.Equal(expectedHeight, measuredSize.Height);
+ }
+
+ [Fact]
+ public void LayoutWithAllCollapsedItemsHasNoSpacing()
+ {
+ var viewWidth = 7;
+ var viewHeight = 5;
+ var spacing = 10;
+
+ var stack = SetUpVisibilityTestStack(viewWidth, viewHeight, spacing);
+ stack.Spacing.Returns(spacing);
+
+ stack[0].Visibility.Returns(Visibility.Collapsed);
+ stack[1].Visibility.Returns(Visibility.Collapsed);
+ stack[2].Visibility.Returns(Visibility.Collapsed);
+
+ var manager = new VerticalStackLayoutManager(stack);
+ var measuredSize = manager.Measure(double.PositiveInfinity, double.PositiveInfinity);
+
+ var expectedHeight = 0;
+
+ Assert.Equal(expectedHeight, measuredSize.Height);
+ }
}
}
diff --git a/src/Essentials/samples/Samples/Platforms/Android/MainActivity.cs b/src/Essentials/samples/Samples/Platforms/Android/MainActivity.cs
index 2b12a3e04236..c2140a85ae5b 100644
--- a/src/Essentials/samples/Samples/Platforms/Android/MainActivity.cs
+++ b/src/Essentials/samples/Samples/Platforms/Android/MainActivity.cs
@@ -8,7 +8,7 @@
namespace Samples.Droid
{
- [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
+ [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, ScreenOrientation = ScreenOrientation.FullSensor)]
[IntentFilter(
new[] { Microsoft.Maui.ApplicationModel.Platform.Intent.ActionAppAction },
Categories = new[] { Intent.CategoryDefault })]
diff --git a/src/Essentials/samples/Samples/View/DeviceInfoPage.xaml b/src/Essentials/samples/Samples/View/DeviceInfoPage.xaml
index 969b03dcaa5b..d82cf3423259 100644
--- a/src/Essentials/samples/Samples/View/DeviceInfoPage.xaml
+++ b/src/Essentials/samples/Samples/View/DeviceInfoPage.xaml
@@ -8,10 +8,10 @@
-
+
-
+
@@ -30,8 +30,11 @@
+
+
+
-
+
\ No newline at end of file
diff --git a/src/Essentials/samples/Samples/ViewModel/DeviceInfoViewModel.cs b/src/Essentials/samples/Samples/ViewModel/DeviceInfoViewModel.cs
index f0f4fd65ff81..b46d746f701b 100644
--- a/src/Essentials/samples/Samples/ViewModel/DeviceInfoViewModel.cs
+++ b/src/Essentials/samples/Samples/ViewModel/DeviceInfoViewModel.cs
@@ -21,11 +21,21 @@ public class DeviceInfoViewModel : BaseViewModel
public DeviceIdiom Idiom => DeviceInfo.Idiom;
public DeviceType DeviceType => DeviceInfo.DeviceType;
+
+ public double Rotation =>
+ ScreenMetrics.Rotation switch
+ {
+ DisplayRotation.Rotation0 => 0,
+ DisplayRotation.Rotation90 => -90,
+ DisplayRotation.Rotation180 => -180,
+ DisplayRotation.Rotation270 => -270,
+ _ => 0
+ };
public DisplayInfo ScreenMetrics
{
get => screenMetrics;
- set => SetProperty(ref screenMetrics, value);
+ set => SetProperty(ref screenMetrics, value, onChanged: () => OnPropertyChanged(nameof(Rotation)));
}
public override void OnAppearing()
diff --git a/src/Essentials/src/DeviceDisplay/DeviceDisplay.uwp.cs b/src/Essentials/src/DeviceDisplay/DeviceDisplay.uwp.cs
index 9161e1a872dd..6bdd06d9adcf 100644
--- a/src/Essentials/src/DeviceDisplay/DeviceDisplay.uwp.cs
+++ b/src/Essentials/src/DeviceDisplay/DeviceDisplay.uwp.cs
@@ -44,61 +44,22 @@ protected override void SetKeepScreenOn(bool keepScreenOn)
}
}
- static DisplayRotation CalculateRotation(DisplayOrientations native, DisplayOrientations current)
- {
- if (native == DisplayOrientations.Portrait)
- {
- switch (current)
- {
- case DisplayOrientations.Landscape:
- return DisplayRotation.Rotation90;
- case DisplayOrientations.Portrait:
- return DisplayRotation.Rotation0;
- case DisplayOrientations.LandscapeFlipped:
- return DisplayRotation.Rotation270;
- case DisplayOrientations.PortraitFlipped:
- return DisplayRotation.Rotation180;
- }
- }
- else if (native == DisplayOrientations.Landscape)
- {
- switch (current)
- {
- case DisplayOrientations.Landscape:
- return DisplayRotation.Rotation0;
- case DisplayOrientations.Portrait:
- return DisplayRotation.Rotation270;
- case DisplayOrientations.LandscapeFlipped:
- return DisplayRotation.Rotation180;
- case DisplayOrientations.PortraitFlipped:
- return DisplayRotation.Rotation90;
- }
- }
-
- return DisplayRotation.Unknown;
- }
-
AppWindow? _currentAppWindowListeningTo;
protected override DisplayInfo GetMainDisplayInfo()
{
if (WindowStateManager.Default.GetActiveAppWindow(false) is not AppWindow appWindow)
- return new DisplayInfo();
+ return default;
var windowHandle = UI.Win32Interop.GetWindowFromWindowId(appWindow.Id);
var mi = GetDisplay(windowHandle);
if (mi == null)
- return new DisplayInfo();
+ return default;
- DEVMODE vDevMode = new DEVMODE();
+ var vDevMode = new DEVMODE();
EnumDisplaySettings(mi.Value.DeviceNameToLPTStr(), -1, ref vDevMode);
- var rotation = CalculateRotation(vDevMode, appWindow);
- var perpendicular =
- rotation == DisplayRotation.Rotation90 ||
- rotation == DisplayRotation.Rotation270;
-
var w = vDevMode.dmPelsWidth;
var h = vDevMode.dmPelsHeight;
@@ -108,13 +69,16 @@ protected override DisplayInfo GetMainDisplayInfo()
else
dpi = 1.0;
- var orientation = GetWindowOrientationWin32(appWindow) == DisplayOrientations.Landscape
+ var displayOrientation = GetDisplayOrientation(vDevMode);
+ var rotation = CalculateRotation(displayOrientation);
+
+ var orientation = displayOrientation == DisplayOrientations.Landscape || displayOrientation == DisplayOrientations.LandscapeFlipped
? DisplayOrientation.Landscape
: DisplayOrientation.Portrait;
return new DisplayInfo(
- width: perpendicular ? h : w,
- height: perpendicular ? w : h,
+ width: w,
+ height: h,
density: dpi,
orientation: orientation,
rotation: rotation,
@@ -179,56 +143,39 @@ void OnWindowDisplayChanged(object? sender, EventArgs e) =>
void OnAppWindowChanged(AppWindow sender, AppWindowChangedEventArgs args) =>
OnMainDisplayInfoChanged();
- static DisplayRotation CalculateRotation(DEVMODE devMode, AppWindow appWindow)
- {
- DisplayOrientations native = DisplayOrientations.Portrait;
- switch (devMode.dmDisplayOrientation)
+ static DisplayRotation CalculateRotation(DisplayOrientations orientation) =>
+ orientation switch
{
- case 0:
- native = DisplayOrientations.Landscape;
- break;
- case 1:
- native = DisplayOrientations.Portrait;
- break;
- case 2:
- native = DisplayOrientations.LandscapeFlipped;
- break;
- case 3:
- native = DisplayOrientations.PortraitFlipped;
- break;
- }
-
- var current = GetWindowOrientationWin32(appWindow);
- return CalculateRotation(native, current);
- }
-
- // https://github.com/marb2000/DesktopWindow/blob/abb21b797767bb24da09c066514117d5f1aabd75/WindowExtensions/DesktopWindow.cs#L407
- static DisplayOrientations GetWindowOrientationWin32(AppWindow appWindow)
- {
- DisplayOrientations orientationEnum;
- int theScreenWidth = appWindow.Size.Width;
- int theScreenHeight = appWindow.Size.Height;
- if (theScreenWidth > theScreenHeight)
- orientationEnum = DisplayOrientations.Landscape;
- else
- orientationEnum = DisplayOrientations.Portrait;
-
- return orientationEnum;
- }
+ DisplayOrientations.Landscape => DisplayRotation.Rotation0,
+ DisplayOrientations.Portrait => DisplayRotation.Rotation270,
+ DisplayOrientations.LandscapeFlipped => DisplayRotation.Rotation180,
+ DisplayOrientations.PortraitFlipped => DisplayRotation.Rotation90,
+ _ => DisplayRotation.Rotation0,
+ };
+
+ static DisplayOrientations GetDisplayOrientation(DEVMODE devMode) =>
+ devMode.dmDisplayOrientation switch
+ {
+ 0 => DisplayOrientations.Landscape,
+ 1 => DisplayOrientations.Portrait,
+ 2 => DisplayOrientations.LandscapeFlipped,
+ 3 => DisplayOrientations.PortraitFlipped,
+ _ => DisplayOrientations.Landscape,
+ };
- [DllImport("User32", CharSet = CharSet.Unicode)]
+ [DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern int GetDpiForWindow(IntPtr hwnd);
- [DllImport("User32", CharSet = CharSet.Unicode, SetLastError = true)]
+ [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern IntPtr MonitorFromRect(ref RECT lprc, MonitorOptions dwFlags);
- [DllImport("User32", CharSet = CharSet.Unicode, SetLastError = true)]
+ [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
- [DllImport("User32.dll")]
+ [DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
- static extern Boolean EnumDisplaySettings(
+ static extern bool EnumDisplaySettings(
byte[] lpszDeviceName,
[param: MarshalAs(UnmanagedType.U4)] int iModeNum,
[In, Out] ref DEVMODE lpDevMode);
@@ -236,20 +183,6 @@ static extern Boolean EnumDisplaySettings(
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
- [DllImport("user32.dll")]
- static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, EnumMonitorsDelegate lpfnEnum, IntPtr dwData);
- delegate bool EnumMonitorsDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData);
-
- static bool MonitorEnumProc(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData)
- {
- MONITORINFOEX mi = new MONITORINFOEX();
- mi.Size = Marshal.SizeOf(typeof(MONITORINFOEX));
- if (GetMonitorInfo(hMonitor, ref mi))
- Console.WriteLine(mi.DeviceName);
-
- return true;
- }
-
enum MonitorOptions : uint
{
MONITOR_DEFAULTTONULL,
@@ -292,9 +225,10 @@ public byte[] DeviceNameToLPTStr()
struct DEVMODE
{
- private const int CCHDEVICENAME = 0x20;
- private const int CCHFORMNAME = 0x20;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
+ const int CCHDEVICENAME = 0x20;
+ const int CCHFORMNAME = 0x20;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
@@ -310,7 +244,7 @@ struct DEVMODE
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;