fix(core): use correct mjolnir requireFailure key for recognizers#10323
Open
charlieforward9 wants to merge 2 commits into
Open
fix(core): use correct mjolnir requireFailure key for recognizers#10323charlieforward9 wants to merge 2 commits into
charlieforward9 wants to merge 2 commits into
Conversation
chrisgervang
approved these changes
May 22, 2026
Collaborator
chrisgervang
left a comment
There was a problem hiding this comment.
I'm surprised this wasn't caught by typescript on the EventManager's recognizers param. Can that type need to be improved?
The EventManager's RecognizerTupleNormalized expects `requireFailure`,
but Deck was passing `requestFailure`. The key was silently dropped, so
every requireFailure relationship declared in RECOGNIZERS (pinch waiting
for multipan, single-finger pan waiting for multipan, click waiting for
dblclick) never took effect.
On mobile this caused pinch to fire on any 2-finger touch and beat the
multipan recognizer to the gesture: a 2-finger vertical drag would land
in pinch's `controllerState.zoom({pos, scale: ~1})` instead of
`_onMultiPan → rotate({pos})`, so the camera re-anchored its
longitude/latitude (looked like a pan) and picked up tiny bearing
changes from inter-finger rotation deltas — and pitch never engaged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
de24093 to
7501827
Compare
Collaborator
Author
|
Re: the TypeScript question — agreed, the type
Two tightening options, neither in scope here but I'm happy to follow up:
Want me to open a follow-up PR for either? |
Collaborator
|
I would like for some coverage in this PR so that the regression doesn't come back again. It could be a test if types can't cover it |
Collaborator
Author
|
Added in 725e724 — regression test asserts pinch/pan/click each have the right blocking recognizer in their mjolnir |
Construct a Deck and verify pinch, pan, and click each have the expected blocking recognizer in their requireFail array. Catches the `requestFailure` typo class of bug without depending on TypeScript flagging it through mjolnir's union type.
725e724 to
b8f30a0
Compare
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.
Problem
Deckwires its mjolnirEventManagerwith each recognizer descriptor under the keyrequestFailure, butEventManager(mjolnir.js/src/event-manager.ts:120) destructuresrequireFailure. The mismatched key was silently dropped, so everyrequireFailurerelationship declared inRECOGNIZERS(modules/core/src/lib/constants.ts) never took effect:In practice the missing wiring meant:
pinchnever waited formultipanto fail. With two fingers down,pinch.attrTest(|scale - 1| > 0) passes on the first frame from sub-pixel scale jitter, so pinch entersBegan,_onPinchStartrunszoomStart + rotateStart, and every subsequent move runszoomAround:"pointer"math. A 2-finger vertical drag — the gesture deck.gl ships for pitch onMapController/GlobeController(MULTI_PAN→controllerState.rotate({pos})) — never gets a turn. The user sees pan + small bearing wobble instead of pitch.pannever waited formultipanto fail (minor; pan needs 1 pointer and multipan needs 2, so practical impact is small).clicknever waited fordblclickto fail, so single-tap could fire eagerly.Fix
Rename the destructured tuple element and the returned property to
requireFailuresoEventManagercan read it.Verification
Hand-tested on iOS WKWebView with
GlobeController. Before: 2-finger vertical drag pans (zoomAround pointer math) with a tiny bearing nudge. After: 2-finger vertical drag pitches the camera as documented fortouchRotate: true.