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

1 participant