TapGestureRecognizer and PointerGestureRecognizer lack public controller interfaces for custom backends
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 23.3k
- Forks
- 2k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 296
Description
Related to
- Parent issue: #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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating TapGestureRecognizer.SendTapped and the internal SendPointer* methods, then compare them with the existing ISwipeGestureController, IPinchGestureController, and IPanGestureController patterns. Decide whether to add public controller interfaces or expose the existing methods, and verify that custom backends can invoke the gesture events without reflection and with the documented parameter signatures.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- desktop-dev, frontend, mobile-dev
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100