fix: exclude the map's gesture detector from semantics - #2236
Open
wcjord wants to merge 1 commit into
Open
Conversation
This was referenced Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2176.
The mechanism
MapInteractiveViewerbuildsRawGestureDetector(gestures: _gestures, ...)and leavesexcludeFromSemanticsat its defaultfalse._gesturescontains aTapGestureRecognizerand aLongPressGestureRecognizer, so Flutter wraps the child in_GestureSemanticsand publishesSemanticsAction.tap/longPresson a semantics node covering the detector's whole hit area — i.e. the entire map.Two consequences once the semantics tree is enabled (
SemanticsBinding.instance.ensureSemantics(), or automatically when assistive technology is detected):1.
onTapreports the map centre (#2176). A semantics-driven activation doesn't carry a pointer position, so the framework synthesises one at the node's centre and the recognizer fires withkind: unknown. Since the node is the size of the map, that centre is the map centre — which is exactly the reported symptom, and whykindchanges frommousetounknown. Long-press is affected in principle for the same reason; drag recognizers publish no semantics action, which is why panning/zooming were unaffected and onlyonTaplooked broken.2. On web it blankets any
HtmlElementViewover the map. Flutter web gives a tappable semantics nodepointer-events: all. Platform views are not part of the semantics tree, so a map-sized tappable node sits above any<iframe>/<video>composited over the map and swallows its mouse events — the embed renders and plays but its own controls never respond (a YouTube embed never even shows its control bar, because it never receivesmousemove).I confirmed (2) in a Flutter web app by measuring
document.elementFromPointover a playing embed: the top element was the map'sflt-semanticsnode, viewport-sized,pointer-events: all, every ancestor correctlynone. Settingpointer-events: noneon that one node — changing nothing else — immediately restored the embed's full controls.The change
excludeFromSemantics: trueon thatRawGestureDetector. The map's gestures are pointer gestures, not semantic actions: a map-sized "tap" target isn't a meaningful screen-reader affordance, and its only current effect is to mis-report the tap position. Markers and other children keep their own semantics, so nothing meaningfully activatable loses a node.Testing
test/gestures/map_interactive_viewer_test.dart: with semantics enabled, a bareFlutterMappublishes notap/longPresssemantics action. It fails onmasterand passes with this change.Happy to adjust the approach — if you'd rather keep a semantic affordance on the map and fix the position synthesis instead, say so and I'll rework it.
AI disclosure
Per CONTRIBUTING: this was written with AI assistance (Claude). I've reviewed the diagnosis and the diff, ran the tests locally, and take responsibility for the change.