mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Change hit testing to walk over the render tree instead of the RenderLayer tree. This is a step in the direction of removing the RenderLayer tree entirely. For now, there's a few calls back into RenderLayer that will be removed in a followup patch. This patch also breaks hit testing on transformed inlines. I'll be removing the ability to transform inlines in a followup patch anyways, so it's ok for hit testing to give the wrong result temporarily here. Almost all of this patch is just moving code from RenderLayer to RenderBox. The primary substantive change is in RenderBox::hitTestLayer. Instead of having hitTestChildren calls, we call collectSelfPaintingLayers, reverse sort by z-index (so we start at the top), and then iterate over the result. The test-case also exposes that we don't correctly hit transformed elements inside inline-blocks. I went back as far as 4153b8a515d54275934d4244aaf2d5a7a8fe3333 and the bug still happened. R=abarth@chromium.org Review URL: https://codereview.chromium.org/945693002
76 lines
2.6 KiB
Plaintext
76 lines
2.6 KiB
Plaintext
<sky>
|
|
<style>
|
|
foo, parent { width: 100px; height: 100px; background: blue; }
|
|
bar { width: 100px; height: 100px; background: purple; }
|
|
parent { display: paragraph; }
|
|
child { background: salmon; }
|
|
canvas { height: 50px; background-color: pink; }
|
|
inline-block { display: inline-block; width: 50px; height: 50px; background: green; }
|
|
grand-child { width: 50px; height: 50px; transform: translate3d(100px, 0, 0); background: papayawhip; }
|
|
</style>
|
|
<foo /><bar />
|
|
<parent>
|
|
<child>Foo bar</child>
|
|
<inline-block>
|
|
<grand-child />
|
|
</inline-block>
|
|
</parent>
|
|
<canvas />
|
|
<script>
|
|
import "../resources/third_party/unittest/unittest.dart";
|
|
import "../resources/unit.dart";
|
|
|
|
import "dart:sky";
|
|
|
|
void main() {
|
|
initUnit();
|
|
|
|
test("should hit test", () {
|
|
// FIXME: We should have much better hit-testing coverage, at least:
|
|
// inline content (both sections of a wrapped run)
|
|
// text node
|
|
// flex box
|
|
// display: paragraph
|
|
// position: absolute
|
|
// position: relative
|
|
// z-order (missing, zero, positive and negative)
|
|
expect(document.elementFromPoint(50, 50).tagName, equals('foo'));
|
|
expect(document.elementFromPoint(50, 150).tagName, equals('bar'));
|
|
expect(document.elementFromPoint(150, 50).tagName, equals('sky'));
|
|
});
|
|
|
|
void hitTestWithChildren() {
|
|
expect(document.elementFromPoint(50, 210).tagName, equals('child'));
|
|
// Right of the <child> inline.
|
|
expect(document.elementFromPoint(95, 210).tagName, equals('parent'));
|
|
// Below the <child> inline.
|
|
expect(document.elementFromPoint(50, 275).tagName, equals('parent'));
|
|
}
|
|
|
|
test("should hit test child and parent", () {
|
|
hitTestWithChildren();
|
|
});
|
|
|
|
test("should hit test child with layered parent", () {
|
|
document.querySelector('parent').style["transform"] = "translate3d(0, 0, 0)";
|
|
hitTestWithChildren();
|
|
});
|
|
|
|
test("should hit test transformed child", () {
|
|
document.querySelector('parent').style["display"] = "block";
|
|
document.querySelector('child').style["transform"] = "translate3d(100px, 0, 0)";
|
|
expect(document.elementFromPoint(50, 210).tagName, equals('parent'));
|
|
expect(document.elementFromPoint(150, 210).tagName, equals('child'));
|
|
expect(document.elementFromPoint(25, 240).tagName, equals('inline-block'));
|
|
// TODO(ojan): This is incorrect. It should hit grand-child.
|
|
// This broke sometime before 4153b8a515d54275934d4244aaf2d5a7a8fe3333.
|
|
expect(document.elementFromPoint(150, 240).tagName, equals('sky'));
|
|
});
|
|
|
|
test("should hit test canvas", () {
|
|
expect(document.elementFromPoint(50, 310).tagName, equals('canvas'));
|
|
});
|
|
}
|
|
</script>
|
|
</sky>
|