Skip to content

Map event coordinates through CSS transforms - #664

Open
nicoburns wants to merge 1 commit into
mainfrom
devin/1786291686-transform-event-coords
Open

Map event coordinates through CSS transforms#664
nicoburns wants to merge 1 commit into
mainfrom
devin/1786291686-transform-event-coords

Conversation

@nicoburns

@nicoburns nicoburns commented Aug 9, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #663: a CSS transform on an element (or an ancestor) shifted the element coordinates of pointer/wheel events, and shifted the page/client coordinates forwarded to sub-documents and custom widgets.

Both paths derived coordinates from absolute_position(), which is a plain offset sum and ignores transforms:

  • EventDriver::adjust_element_coords: element = client - get_client_bounding_rect(target)
  • sub-document/widget forwarding in handle_dom_event: coords -= node.absolute_position(0,0)

The fix maps the event's page point into the target's local border-box space using the same math hit-testing already uses (per node along the layout chain: - location + scroll_offset, then inverse transform, then the inline-root content-box offset):

  • new Node::page_point_to_local(x, y, scale) — walks the layout-parent chain top-down mirroring hit_inner
  • new BaseDocument::page_point_to_element_space(node_id, x, y) — wraps it, handling non-atomic inline elements (no layout box) by mapping into the inline root and offsetting by their fragment-rect origin
  • adjust_element_coords and the sub-document/custom-widget forwarding now use these; forwarding also sets the forwarded event's element point and now adjusts Wheel coords (previously forwarded unadjusted)

Hoisted (z-index) children work because their accumulated HoistedPaintChild::position equals the sum of intermediate layout locations minus scrolls, and intermediates between a stacking-context root and a hoisted child can't carry transforms (a transform is itself an SC root).

Regression tests in tests/blitz-tests/tests/transformed_event_coords.rs cover ancestor translation, the transformed element itself, hidpi scale, rotation, and the untransformed baseline.

Link to Devin session: https://dioxus.staging.devinenterprise.com/sessions/f1ed0334be0c4f08a5b6b2aaa7194463
Requested by: @nicoburns

WPT results

No changes in test results compared to main.

Generated by the WPT workflow.

Element coordinates of pointer/wheel events, and the coordinates
forwarded to sub-documents and custom widgets, were computed from the
untransformed layout position, so a transform on the element (or an
ancestor) shifted them. Map the event point through the same inverse
transforms and scroll offsets that hit-testing applies instead.

Fixes #663
@nicoburns nicoburns self-assigned this Aug 9, 2026
@staging-devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

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.

Transform incorrectly affects elements coordinates

1 participant