Skip to content

fix(input): pierce shadow DOM in onTouchMove over-canvas detection#7321

Open
pauliojanpera wants to merge 1 commit into
phaserjs:masterfrom
pauliojanpera:fix/input-shadow-dom-touchmove
Open

fix(input): pierce shadow DOM in onTouchMove over-canvas detection#7321
pauliojanpera wants to merge 1 commit into
phaserjs:masterfrom
pauliojanpera:fix/input-shadow-dom-touchmove

Conversation

@pauliojanpera

Copy link
Copy Markdown

This PR

  • Fixes a bug

Describe the changes below:

InputManager.onTouchMove used document.elementFromPoint() to decide whether a touch is over the canvas. When Phaser runs inside a shadow root, that call resolves to the shadow host rather than the canvas, so overCanvas is always false, isOver latches false, and every touchmove inside the shadow root is silently dropped — pointer.x/y never update on touch devices.

Use the canvas's root node (canvas.getRootNode(), a ShadowRoot when inside shadow DOM, otherwise the Document) which exposes elementFromPoint and resolves the topmost element across the shadow boundary. Falls back to document when the root node has no elementFromPoint.

Reproduction

A self-contained, single-file repro that demonstrates the bug:

It mounts a Phaser game whose canvas is created inside an open shadow root and logs two independent event streams: a raw DOM touchmove listener on the canvas, and Phaser's own pointermove. Open the live link and drag inside the dark area on a touch device (or with DevTools touch emulation: Ctrl/Cmd+Shift+M).

  • Before this fix (pinned phaser@3.90.0): the raw touchmove events fire, but Phaser pointermove never fires for touch, and the status bar turns red — "BUG REPRODUCED". A mouse drag still logs pointermove, since the mouse path never calls elementFromPoint — so only the touch path is broken.
  • After this fix (swap the <script src> for a build containing the patched InputManager.js): touchmove and pointermove fire together and the status bar turns green.

InputManager.onTouchMove used document.elementFromPoint() to decide whether a
touch is over the canvas. When Phaser runs inside a shadow root, that call
resolves to the shadow host rather than the canvas, so `overCanvas` is always
false, `isOver` latches false, and every touchmove inside the shadow root is
silently dropped — pointer.x/y never update on touch devices.

Use the canvas's root node (canvas.getRootNode(), a ShadowRoot when inside
shadow DOM, otherwise the Document) which exposes elementFromPoint and resolves
the topmost element across the shadow boundary. Falls back to document when the
root node has no elementFromPoint.
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