Skip to content

mobile: synthesised tap uses localFocalPoint, not focalPoint (follow-up to #163)#168

Open
mushogenshin wants to merge 1 commit into
nmfisher:developfrom
mushogenshin:fix/mobile-tap-localfocalpoint-followup
Open

mobile: synthesised tap uses localFocalPoint, not focalPoint (follow-up to #163)#168
mushogenshin wants to merge 1 commit into
nmfisher:developfrom
mushogenshin:fix/mobile-tap-localfocalpoint-followup

Conversation

@mushogenshin
Copy link
Copy Markdown
Contributor

Follow-up to #163

`#163` introduced the eager-scale gesture recognizer that synthesises tap and double-tap from the scale callbacks. The synthesis captured `event.focalPoint` from `ScaleStartDetails` and dispatched it as `TouchEvent.localPosition`. Flutter documents `focalPoint` as global (screen) coordinates; `TouchEvent.localPosition` consumers — most importantly `View.pick(x, y, …)` — expect coordinates relative to the viewport.

The result: in any layout where the Thermion widget isn't anchored at the screen origin (anything inside an AppBar / inside a list / inside padding), picks land outside the rendered viewport and Filament returns the background entity. Reproduced reliably on Android — the spike author's downstream app couldn't get region-tap to work in any non-trivial composition.

Fix

Capture `event.localFocalPoint` (widget-relative) into `_scaleStartFocal`, and use `event.localFocalPoint` in the onUpdate movement-distance comparison so the tap-vs-drag threshold is also computed in widget-local space.

The other places that pass `event.focalPoint` to `inputHandler.handle(ScaleStart/UpdateEvent(localFocalPoint: …))` keep using `event.focalPoint` (global) — that's the existing upstream convention for those events, and they're consumed by orbit-camera code that uses deltas, not absolute positions, so the global/local distinction doesn't affect them.

Why it didn't surface earlier

Initial testing happened in layouts where the viewer sat near the screen origin (top-left, full-width column). Global ≈ local in that case, picks landed on the right entity by coincidence. Moving the viewer into a real composition (e.g., a stress-test ListView on Android) immediately exposed the bug.

Verification

  • Spike app on Android emulator: region picking now resolves correctly inside a 220-px-tall ListView item with surrounding padding.
  • Single-viewer behaviour unchanged in flush-to-origin layouts (where global == local).
  • Orbit / pinch / double-tap all unchanged (they don't depend on absolute position).

Fixes a bug introduced by this same patch: the synthesised tap was
dispatched with `event.focalPoint`, which Flutter documents as
*global* coordinates (relative to the screen / Flutter window).
`TouchEvent.localPosition` consumers — most importantly
`View.pick(x, y, …)` — expect coordinates relative to the
rendered viewport, not the entire screen. Whenever the
ThermionWidget wasn't anchored at (0, 0) on screen (i.e. every
realistic layout: anything inside a Scaffold body, a ListView, a
Padding, etc.), picks landed outside the viewport and the result
handler always returned the background entity.

Symptom on Android: region clicks did nothing in any layout that
nested the viewer below an AppBar / inside a list. iOS / macOS
hadn't been hit yet because the spike author's iOS test layout
happened to have the viewer near the screen origin.

Fix: capture `event.localFocalPoint` (widget-relative) into
`_scaleStartFocal`, and compare with `event.localFocalPoint` in
onUpdate so the tap-vs-drag movement threshold is also computed
in widget-local space. The `inputHandler.handle(ScaleStart/Update
Event(localFocalPoint: …))` calls keep passing
`event.focalPoint` (global) since that matches the upstream
convention used elsewhere in this file for those events — and
those events are consumed by orbit-camera code that uses deltas,
not absolute positions, so the global/local distinction doesn't
affect them.

Doesn't change behaviour for any caller that doesn't use the
synthesised tap (orbit, pinch-zoom, double-tap detection's
duration-based half is already correct).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant