Skip to content

Commit 63d6cf2

Browse files
Ahmad-S792Ahmad Saleem
authored andcommitted
layerX/layerY return incorrect values with CSS transforms
https://bugs.webkit.org/show_bug.cgi?id=306314 rdar://168968832 Reviewed by Lily Spiniolas and Abrar Rahman Protyasha. This patch aligns WebKit with Gecko / Firefox and Blink / Chromium. The layerX and layerY properties were computed by walking up the layer tree and subtracting each layer's location(). This approach fails with CSS transforms because layer locations are in local coordinate space and don't account for transforms applied to parent layers. It doesn't make sense not to include transforms when subtracting the layer offset, because before this subtraction the mouse position value already includes transforms (via absoluteLocation which applies the documentToAbsoluteScaleFactor). Fix by computing the layer's position in absolute coordinates using localToAbsolute() with UseTransforms, matching Chromium's approach. This ensures both the mouse position and layer position are in the same coordinate system before computing their relative offset. See: https://github.com/w3c/uievents/issues/398 * Source/WebCore/dom/MouseRelatedEvent.cpp: (WebCore::MouseRelatedEvent::computeRelativePosition): * LayoutTests/imported/w3c/web-platform-tests/uievents/mouse/layer-coords-transform-expected.txt: Progression * LayoutTests/fast/events/mouse-relative-position-expected.txt: * LayoutTests/fast/events/mouse-relative-position.html: Canonical link: https://commits.webkit.org/306300@main
1 parent 61e4fab commit 63d6cf2

File tree

4 files changed

+29
-11
lines changed

4 files changed

+29
-11
lines changed
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
span
22

33
PASS simulateElementClick(testElement, [100, 100, 200, 200]); is '100, 100, 200, 200'
4-
PASS simulateElementClick(spanElement, [16, 10, 16, 10]); is '16, 10, 16, 10'
5-
PASS simulateElementClick(inputElement, [40, 10, 40, 10]); is '40, 10, 40, 10'
4+
PASS simulateElementClick(spanElement, [16, 10, 112, 110]); is '16, 10, 112, 110'
5+
PASS simulateElementClick(inputElement, [39, 9, 95, 10]); is '39, 9, 95, 10'
6+
PASS successfullyParsed is true
7+
8+
TEST COMPLETE
69

LayoutTests/fast/events/mouse-relative-position.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<html>
22
<head>
3-
<script src="../../resources/js-test-pre.js"></script>
3+
<script src="../../resources/js-test.js"></script>
44
<style>
55
html, body {
66
margin: 0;
@@ -97,7 +97,7 @@
9797
var inputElement = testElement2.getElementsByTagName('input')[0];
9898

9999
shouldBe("simulateElementClick(testElement, [100, 100, 200, 200]);", "'100, 100, 200, 200'");
100-
shouldBe("simulateElementClick(spanElement, [16, 10, 16, 10]);", "'16, 10, 16, 10'");
101-
shouldBe("simulateElementClick(inputElement, [40, 10, 40, 10]);", "'40, 10, 40, 10'");
100+
shouldBe("simulateElementClick(spanElement, [16, 10, 112, 110]);", "'16, 10, 112, 110'");
101+
shouldBe("simulateElementClick(inputElement, [39, 9, 95, 10]);", "'39, 9, 95, 10'");
102102
</script>
103103
</html>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
FAIL layer-coords-transform assert_equals: layerX expected 200 but got 210
2+
PASS layer-coords-transform
33
PASS layer-coords-transform 1
44

Source/WebCore/dom/MouseRelatedEvent.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,31 @@ void MouseRelatedEvent::computeRelativePosition()
252252
while (node && !node->renderer())
253253
node = node->parentNode();
254254

255-
CheckedPtr<RenderLayer> layer;
256-
if (node && (layer = node->renderer()->enclosingLayer())) {
257-
for (; layer; layer = layer->parent()) {
258-
m_layerLocation -= toLayoutSize(layer->location());
255+
if (node) {
256+
CheckedPtr layer = node->renderer()->enclosingLayer();
257+
while (layer && !layer->isSelfPaintingLayer())
258+
layer = layer->parent();
259+
260+
if (layer) {
261+
// Start with absoluteLocation which is already in absolute coordinates
262+
// (has zoom factor applied via documentToAbsoluteScaleFactor).
263+
auto layerLocationInAbsoluteCoords = absoluteLocation();
264+
265+
// Convert layer position to absolute coordinates accounting for transforms.
266+
auto layerAbsolutePosition = layer->renderer().localToAbsolute(FloatPoint(), UseTransforms);
267+
268+
// Subtract the layer's absolute position from the mouse absolute position.
269+
layerLocationInAbsoluteCoords.moveBy(-layerAbsolutePosition);
270+
271+
// Scale back to page coordinates (remove zoom factor).
272+
auto inverseScaleFactor = 1 / documentToAbsoluteScaleFactor();
273+
m_layerLocation = LayoutPoint(layerLocationInAbsoluteCoords.scaled(inverseScaleFactor));
259274
}
260275
}
261276

262277
m_hasCachedRelativePosition = true;
263278
}
264-
279+
265280
DoublePoint MouseRelatedEvent::locationInRootViewCoordinates() const
266281
{
267282
if (RefPtr frameView = frameViewFromWindowProxy(view()))

0 commit comments

Comments
 (0)