-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
Related to
- Parent issue: Alert/Dialog system (
DisplayAlert,DisplayActionSheet,DisplayPromptAsync) needs a public extensibility point #34104 (internal APIs blocking custom platform backends)
Problem
Custom platform backends need to fire gesture events when native gestures are recognized. MAUI provides public controller interfaces for some gesture types but not others:
| Gesture | Public Interface | Status |
|---|---|---|
| Swipe | ISwipeGestureController |
✅ Public — SendSwipe() + DetectSwipe() |
| Pinch | IPinchGestureController |
✅ Public — SendPinch() etc. |
| Pan | IPanGestureController |
✅ Public — SendPan() etc. |
| Tap | ❌ None | SendTapped() is internal |
| Pointer | ❌ None | SendPointerEntered/Exited/Moved/Pressed/Released() are all internal |
TapGestureRecognizer
TapGestureRecognizer.SendTapped(View) is internal. A custom backend must use reflection:
var sendTapped = typeof(TapGestureRecognizer).GetMethod(
"SendTapped", BindingFlags.Instance | BindingFlags.NonPublic);
sendTapped.Invoke(gesture, new object[] { parentView });An ITapGestureController with a public SendTapped() method (matching the pattern of ISwipeGestureController) would solve this.
PointerGestureRecognizer
SendPointerEntered(View, Func<IElement?, Point?>, PlatformPointerEventArgs, ButtonsMask) and the other SendPointer* methods are all internal. Custom backends must reflect:
var sendEntered = typeof(PointerGestureRecognizer).GetMethod(
"SendPointerEntered", BindingFlags.Instance | BindingFlags.NonPublic);
sendEntered.Invoke(gesture, new object[] { view, getPositionFunc, null, ButtonsMask.Primary });An IPointerGestureController interface (or making the existing SendPointer* methods public) would allow backends to properly implement pointer tracking without reflection.
Impact
Without these public APIs, custom platform backends (macOS/AppKit, Linux/GTK, etc.) are:
- Forced to use reflection, which is fragile across MAUI versions
- Subject to trimming/AOT failures since the internal methods aren't preserved
- Unable to properly validate parameter signatures at compile time (we shipped a bug where we passed 2 args to a 4-param method, silently failing)
Proposed Solution
Add public controller interfaces matching the existing pattern:
public interface ITapGestureController
{
void SendTapped(View sender);
}
public interface IPointerGestureController
{
void SendPointerEntered(View sender, Func<IElement?, Point?>? getPosition);
void SendPointerExited(View sender, Func<IElement?, Point?>? getPosition);
void SendPointerMoved(View sender, Func<IElement?, Point?>? getPosition);
void SendPointerPressed(View sender, Func<IElement?, Point?>? getPosition);
void SendPointerReleased(View sender, Func<IElement?, Point?>? getPosition);
}Or alternatively, make the existing internal methods public.