Canvas gesture ownership — make the viewer, not the browser, the owner of
every touch gesture over the 3D canvas.
Without this, a two-finger pinch over the canvas is claimed by the browser as
PAGE zoom: the engine fires pointercancel, the orbit controls' pinch
handler never runs, and the whole UI ends up zoomed with no way back
(measured under iPhone emulation: camera distance unchanged,
visualViewport.scale 1 → 5). A double-tap zooms the page too, and a
long-press raises iOS's image callout sheet over the canvas.
Two layers, because the canvas has three owners:
The standalone page styles its own canvas in styles/base/layout.css
(touch-action: none there is the fast path, applied before any script
runs).
An npm-library embedder supplies the canvas (LuxarAppOptions.canvas),
so this function stamps the same declarations from JS — but only when
the computed touch-action is still the default auto, so an embedder
who chose e.g. pan-y on the canvas itself deliberately keeps their
choice (touch-action does not inherit from its wrapper).
A LuxarLayer host owns its renderer and canvas outright and is
documented as responsible for touch-action itself.
Safari additionally fires proprietary gesturestart / gesturechange /
gestureend events for a pinch, which touch-action does not silence in
every WebKit version; they are cancelled here, registered only on devices
that report touch points so a desktop Safari trackpad pinch (which also
emits them, and which the FOV handler consumes as a ctrl-wheel) is untouched.
All listeners and inline style changes register through the caller's
EventGroup, so a single dispose() removes them with everything
else the app owns.
Canvas gesture ownership — make the viewer, not the browser, the owner of every touch gesture over the 3D canvas.
Without this, a two-finger pinch over the canvas is claimed by the browser as PAGE zoom: the engine fires
pointercancel, the orbit controls' pinch handler never runs, and the whole UI ends up zoomed with no way back (measured under iPhone emulation: camera distance unchanged,visualViewport.scale1 → 5). A double-tap zooms the page too, and a long-press raises iOS's image callout sheet over the canvas.Two layers, because the canvas has three owners:
styles/base/layout.css(touch-action: nonethere is the fast path, applied before any script runs).LuxarAppOptions.canvas), so this function stamps the same declarations from JS — but only when the computedtouch-actionis still the defaultauto, so an embedder who chose e.g.pan-yon the canvas itself deliberately keeps their choice (touch-actiondoes not inherit from its wrapper).LuxarLayerhost owns its renderer and canvas outright and is documented as responsible fortouch-actionitself.Safari additionally fires proprietary
gesturestart/gesturechange/gestureendevents for a pinch, whichtouch-actiondoes not silence in every WebKit version; they are cancelled here, registered only on devices that report touch points so a desktop Safari trackpad pinch (which also emits them, and which the FOV handler consumes as a ctrl-wheel) is untouched.All listeners and inline style changes register through the caller's EventGroup, so a single
dispose()removes them with everything else the app owns.