WebKit Bugzilla
Attachment 358491 Details for
Bug 172917
: [Mac] Implement basic hit testing in the scrolling tree
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
0002-Bug-172917-Mac-Implement-basic-hit-testing.patch (text/plain), 36.65 KB, created by
Frédéric Wang (:fredw)
on 2019-01-07 03:32:50 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Frédéric Wang (:fredw)
Created:
2019-01-07 03:32:50 PST
Size:
36.65 KB
patch
obsolete
>From 724a0e31b16bcef905d006d324017ac5cb24b3f8 Mon Sep 17 00:00:00 2001 >From: Frederic Wang <fwang@igalia.com> >Date: Thu, 29 Nov 2018 10:25:17 +0100 >Subject: [PATCH xserver 2/3] Bug 172917 - [Mac] Implement basic hit testing > >--- > LayoutTests/ChangeLog | 24 ++++ > ...sting-axis-aligned-transforms-expected.txt | 15 +++ > ...e-hit-testing-axis-aligned-transforms.html | 121 ++++++++++++++++++ > .../scrolling/iframe-hit-testing-expected.txt | 15 +++ > .../iframe-hit-testing-overlap-expected.txt | 15 +++ > .../scrolling/iframe-hit-testing-overlap.html | 117 +++++++++++++++++ > .../fast/scrolling/iframe-hit-testing.html | 117 +++++++++++++++++ > ...frame-maximum-scroll-position-expected.txt | 15 +++ > .../iframe-maximum-scroll-position.html | 120 +++++++++++++++++ > ...roll-iframe-latched-mainframe-expected.txt | 13 ++ > .../fast-scroll-iframe-latched-mainframe.html | 102 +++++++++++++++ > LayoutTests/platform/ios/TestExpectations | 5 + > Source/WebCore/ChangeLog | 26 ++++ > .../WebCore/page/scrolling/ScrollingTree.cpp | 25 +++- > .../scrolling/ScrollingTreeScrollingNode.cpp | 26 ++++ > .../scrolling/ScrollingTreeScrollingNode.h | 3 + > 16 files changed, 757 insertions(+), 2 deletions(-) > create mode 100644 LayoutTests/fast/scrolling/iframe-hit-testing-axis-aligned-transforms-expected.txt > create mode 100644 LayoutTests/fast/scrolling/iframe-hit-testing-axis-aligned-transforms.html > create mode 100644 LayoutTests/fast/scrolling/iframe-hit-testing-expected.txt > create mode 100644 LayoutTests/fast/scrolling/iframe-hit-testing-overlap-expected.txt > create mode 100644 LayoutTests/fast/scrolling/iframe-hit-testing-overlap.html > create mode 100644 LayoutTests/fast/scrolling/iframe-hit-testing.html > create mode 100644 LayoutTests/fast/scrolling/iframe-maximum-scroll-position-expected.txt > create mode 100644 LayoutTests/fast/scrolling/iframe-maximum-scroll-position.html > create mode 100644 LayoutTests/fast/scrolling/latching/fast-scroll-iframe-latched-mainframe-expected.txt > create mode 100644 LayoutTests/fast/scrolling/latching/fast-scroll-iframe-latched-mainframe.html > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 893fd43ca84..32c318fc0e8 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,27 @@ >+2017-06-12 Frederic Wang <fwang@igalia.com> >+ >+ [Mac] Implement basic hit testing for frames >+ https://bugs.webkit.org/show_bug.cgi?id=172917 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add tests regarding basic hit testing of frames on mac when AsyncFrameScrollingEnabled=true: >+ - Find target frame for some mouse coordinates. >+ - Exclude frame that are scrolled to the maximum position. >+ - Verify node latching. >+ >+ * platform/ios/TestExpectations: Disable tests involving with mouse events. >+ * fast/scrolling/iframe-maximum-scroll-position-expected.txt: Added. >+ * fast/scrolling/iframe-maximum-scroll-position.html: Added. >+ * fast/scrolling/iframe-hit-testing-expected.txt: Added. >+ * fast/scrolling/iframe-hit-testing.html: Added. >+ * fast/scrolling/iframe-hit-testing-overlap-expected.txt: Added. >+ * fast/scrolling/iframe-hit-testing-overlap.html: Added. >+ * fast/scrolling/iframe-hit-testing-axis-aligned-transforms-expected.txt: Added. >+ * fast/scrolling/iframe-hit-testing-axis-aligned-transforms.html: Added. >+ * fast/scrolling/latching/fast-scroll-iframe-latched-mainframe-expected.txt: Added. >+ * fast/scrolling/latching/fast-scroll-iframe-latched-mainframe.html: Added. >+ > 2019-01-03 Zalan Bujtas <zalan@apple.com> > > REGRESSION: -webkit-appearance test case crashes >diff --git a/LayoutTests/fast/scrolling/iframe-hit-testing-axis-aligned-transforms-expected.txt b/LayoutTests/fast/scrolling/iframe-hit-testing-axis-aligned-transforms-expected.txt >new file mode 100644 >index 00000000000..43966153508 >--- /dev/null >+++ b/LayoutTests/fast/scrolling/iframe-hit-testing-axis-aligned-transforms-expected.txt >@@ -0,0 +1,15 @@ >+ >+Verifies hit testing for iframe scrolling when axis-aligned transforms are applied >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+PASS main frame did not receive wheel events. >+PASS IFrame 0 did not receive wheel events. >+PASS IFrame 1 did not receive wheel events. >+PASS IFrame 2 did not receive wheel events. >+PASS IFrame 3 consumed wheel events. >+ >diff --git a/LayoutTests/fast/scrolling/iframe-hit-testing-axis-aligned-transforms.html b/LayoutTests/fast/scrolling/iframe-hit-testing-axis-aligned-transforms.html >new file mode 100644 >index 00000000000..b81395de524 >--- /dev/null >+++ b/LayoutTests/fast/scrolling/iframe-hit-testing-axis-aligned-transforms.html >@@ -0,0 +1,121 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<style> >+ iframe { >+ border: 1px solid black; >+ position: absolute; >+ width: 200px; >+ height: 200px; >+ } >+ .transformed { >+ transform: translate(-75px) scale(1.5); >+ } >+</style> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script> >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+if (window.internals) >+ internals.settings.setAsyncFrameScrollingEnabled(true); >+if (window.eventSender) >+ eventSender.monitorWheelEvents(); >+ >+var pageScrollPositionBefore; >+var iFrameScrollPositionBefore = []; >+ >+function checkForInnerFrameScroll() { >+ var pageScrollPositionAfter = document.body.scrollTop; >+ var iFrameScrollPositionAfter = []; >+ for (var i = 0; i < window.frames.length; i++) >+ iFrameScrollPositionAfter[i] = window.frames[i].document.body.scrollTop; >+ >+ if (pageScrollPositionBefore != pageScrollPositionAfter) >+ testFailed("main frame consumed wheel events."); >+ else >+ testPassed("main frame did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[0] != iFrameScrollPositionAfter[0]) >+ testFailed("IFrame 0 consumed wheel events."); >+ else >+ testPassed("IFrame 0 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[1] != iFrameScrollPositionAfter[1]) >+ testFailed("IFrame 1 consumed wheel events."); >+ else >+ testPassed("IFrame 1 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[2] != iFrameScrollPositionAfter[2]) >+ testPassed("IFrame 2 consumed wheel events."); >+ else >+ testFailed("IFrame 2 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[3] != iFrameScrollPositionAfter[3]) >+ testPassed("IFrame 3 consumed wheel events."); >+ else >+ testFailed("IFrame 3 did not receive wheel events."); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+ >+function runTest() { >+ if (!window.eventSender) >+ return; >+ >+ // Determine initial scroll positions. >+ pageScrollPositionBefore = document.body.scrollTop; >+ for (var i = 0; i < window.frames.length; i++) >+ iFrameScrollPositionBefore[i] = window.frames[i].document.body.scrollTop; >+ >+ // Mouve the mouse on top of the target frame. >+ var targetFrame = document.getElementsByTagName("iframe")[2]; >+ var startPosX = targetFrame.offsetLeft + targetFrame.offsetWidth / 2; >+ var startPosY = targetFrame.offsetTop + targetFrame.offsetHeight / 2; >+ eventSender.mouseMoveTo(startPosX, startPosY); >+ >+ // Scroll the target frame. >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'began', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'begin'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end'); >+ eventSender.callAfterScrollingCompletes(checkForInnerFrameScroll); >+} >+ >+var frameToLoadCount = 4; >+function newFrameLoaded() { >+ frameToLoadCount--; >+ if (frameToLoadCount == 0) >+ runTest(); >+} >+</script> >+<div style="height: 5000px;"> >+ <iframe style="left: 100px; top: 100px; background: red; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 300px; top: 100px; background: green; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 100px; top: 300px; background: blue; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 300px; top: 300px; background: black; opacity: .5;" >+ class="transformed" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+</div> >+<div id="console"></div> >+<script> >+description("Verifies hit testing for iframe scrolling when axis-aligned transforms are applied"); >+</script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/fast/scrolling/iframe-hit-testing-expected.txt b/LayoutTests/fast/scrolling/iframe-hit-testing-expected.txt >new file mode 100644 >index 00000000000..cab7d36243a >--- /dev/null >+++ b/LayoutTests/fast/scrolling/iframe-hit-testing-expected.txt >@@ -0,0 +1,15 @@ >+ >+Verifies basic hit testing for iframe scrolling >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+PASS main frame did not receive wheel events. >+PASS IFrame 0 did not receive wheel events. >+PASS IFrame 1 did not receive wheel events. >+PASS IFrame 2 consumed wheel events. >+PASS IFrame 3 did not receive wheel events. >+ >diff --git a/LayoutTests/fast/scrolling/iframe-hit-testing-overlap-expected.txt b/LayoutTests/fast/scrolling/iframe-hit-testing-overlap-expected.txt >new file mode 100644 >index 00000000000..45b26faba50 >--- /dev/null >+++ b/LayoutTests/fast/scrolling/iframe-hit-testing-overlap-expected.txt >@@ -0,0 +1,15 @@ >+ >+Verifies basic hit testing for iframe scrolling (with overlap) >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+PASS main frame did not receive wheel events. >+PASS IFrame 0 did not receive wheel events. >+PASS IFrame 1 did not receive wheel events. >+PASS IFrame 2 consumed wheel events. >+PASS IFrame 3 did not receive wheel events. >+ >diff --git a/LayoutTests/fast/scrolling/iframe-hit-testing-overlap.html b/LayoutTests/fast/scrolling/iframe-hit-testing-overlap.html >new file mode 100644 >index 00000000000..f942b96bb4f >--- /dev/null >+++ b/LayoutTests/fast/scrolling/iframe-hit-testing-overlap.html >@@ -0,0 +1,117 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<style> >+ iframe { >+ border: 1px solid black; >+ position: absolute; >+ width: 200px; >+ height: 200px; >+ } >+</style> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script> >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+if (window.internals) >+ internals.settings.setAsyncFrameScrollingEnabled(true); >+if (window.eventSender) >+ eventSender.monitorWheelEvents(); >+ >+var pageScrollPositionBefore; >+var iFrameScrollPositionBefore = []; >+ >+function checkForInnerFrameScroll() { >+ var pageScrollPositionAfter = document.body.scrollTop; >+ var iFrameScrollPositionAfter = []; >+ for (var i = 0; i < window.frames.length; i++) >+ iFrameScrollPositionAfter[i] = window.frames[i].document.body.scrollTop; >+ >+ if (pageScrollPositionBefore != pageScrollPositionAfter) >+ testFailed("main frame consumed wheel events."); >+ else >+ testPassed("main frame did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[0] != iFrameScrollPositionAfter[0]) >+ testFailed("IFrame 0 consumed wheel events."); >+ else >+ testPassed("IFrame 0 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[1] != iFrameScrollPositionAfter[1]) >+ testFailed("IFrame 1 consumed wheel events."); >+ else >+ testPassed("IFrame 1 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[2] != iFrameScrollPositionAfter[2]) >+ testPassed("IFrame 2 consumed wheel events."); >+ else >+ testFailed("IFrame 2 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[3] != iFrameScrollPositionAfter[3]) >+ testFailed("IFrame 3 consumed wheel events."); >+ else >+ testPassed("IFrame 3 did not receive wheel events."); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+ >+function runTest() { >+ if (!window.eventSender) >+ return; >+ >+ // Determine initial scroll positions. >+ pageScrollPositionBefore = document.body.scrollTop; >+ for (var i = 0; i < window.frames.length; i++) >+ iFrameScrollPositionBefore[i] = window.frames[i].document.body.scrollTop; >+ >+ // Mouve the mouse on top of the target frame. >+ var targetFrame = document.getElementsByTagName("iframe")[2]; >+ var startPosX = targetFrame.offsetLeft + targetFrame.offsetWidth / 2; >+ var startPosY = targetFrame.offsetTop + targetFrame.offsetHeight / 2; >+ eventSender.mouseMoveTo(startPosX, startPosY); >+ >+ // Scroll the target frame. >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'began', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'begin'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end'); >+ eventSender.callAfterScrollingCompletes(checkForInnerFrameScroll); >+} >+ >+var frameToLoadCount = 4; >+function newFrameLoaded() { >+ frameToLoadCount--; >+ if (frameToLoadCount == 0) >+ runTest(); >+} >+</script> >+<div style="height: 5000px;"> >+ <iframe style="left: 50px; top: 250px; background: red; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 150px; top: 350px; background: green; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 100px; top: 300px; background: blue; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 225px; top: 300px; background: black; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+</div> >+<div id="console"></div> >+<script> >+description("Verifies basic hit testing for iframe scrolling (with overlap)"); >+</script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/fast/scrolling/iframe-hit-testing.html b/LayoutTests/fast/scrolling/iframe-hit-testing.html >new file mode 100644 >index 00000000000..a7e9f0a44ec >--- /dev/null >+++ b/LayoutTests/fast/scrolling/iframe-hit-testing.html >@@ -0,0 +1,117 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<style> >+ iframe { >+ border: 1px solid black; >+ position: absolute; >+ width: 200px; >+ height: 200px; >+ } >+</style> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script> >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+if (window.internals) >+ internals.settings.setAsyncFrameScrollingEnabled(true); >+if (window.eventSender) >+ eventSender.monitorWheelEvents(); >+ >+var pageScrollPositionBefore; >+var iFrameScrollPositionBefore = []; >+ >+function checkForInnerFrameScroll() { >+ var pageScrollPositionAfter = document.body.scrollTop; >+ var iFrameScrollPositionAfter = []; >+ for (var i = 0; i < window.frames.length; i++) >+ iFrameScrollPositionAfter[i] = window.frames[i].document.body.scrollTop; >+ >+ if (pageScrollPositionBefore != pageScrollPositionAfter) >+ testFailed("main frame consumed wheel events."); >+ else >+ testPassed("main frame did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[0] != iFrameScrollPositionAfter[0]) >+ testFailed("IFrame 0 consumed wheel events."); >+ else >+ testPassed("IFrame 0 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[1] != iFrameScrollPositionAfter[1]) >+ testFailed("IFrame 1 consumed wheel events."); >+ else >+ testPassed("IFrame 1 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[2] != iFrameScrollPositionAfter[2]) >+ testPassed("IFrame 2 consumed wheel events."); >+ else >+ testFailed("IFrame 2 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[3] != iFrameScrollPositionAfter[3]) >+ testFailed("IFrame 3 consumed wheel events."); >+ else >+ testPassed("IFrame 3 did not receive wheel events."); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+ >+function runTest() { >+ if (!window.eventSender) >+ return; >+ >+ // Determine initial scroll positions. >+ pageScrollPositionBefore = document.body.scrollTop; >+ for (var i = 0; i < window.frames.length; i++) >+ iFrameScrollPositionBefore[i] = window.frames[i].document.body.scrollTop; >+ >+ // Mouve the mouse on top of the target frame. >+ var targetFrame = document.getElementsByTagName("iframe")[2]; >+ var startPosX = targetFrame.offsetLeft + targetFrame.offsetWidth / 2; >+ var startPosY = targetFrame.offsetTop + targetFrame.offsetHeight / 2; >+ eventSender.mouseMoveTo(startPosX, startPosY); >+ >+ // Scroll the target frame. >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'began', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'begin'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end'); >+ eventSender.callAfterScrollingCompletes(checkForInnerFrameScroll); >+} >+ >+var frameToLoadCount = 4; >+function newFrameLoaded() { >+ frameToLoadCount--; >+ if (frameToLoadCount == 0) >+ runTest(); >+} >+</script> >+<div style="height: 5000px;"> >+ <iframe style="left: 100px; top: 100px; background: red; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 300px; top: 100px; background: green; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 100px; top: 300px; background: blue; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 300px; top: 300px; background: black; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+</div> >+<div id="console"></div> >+<script> >+description("Verifies basic hit testing for iframe scrolling"); >+</script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/fast/scrolling/iframe-maximum-scroll-position-expected.txt b/LayoutTests/fast/scrolling/iframe-maximum-scroll-position-expected.txt >new file mode 100644 >index 00000000000..f04f4ae6f41 >--- /dev/null >+++ b/LayoutTests/fast/scrolling/iframe-maximum-scroll-position-expected.txt >@@ -0,0 +1,15 @@ >+ >+Verifies basic that scrolling is passed to the parent when iframe is already scrolled to maximum >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+PASS main frame consumed wheel events. >+PASS IFrame 0 did not receive wheel events. >+PASS IFrame 1 did not receive wheel events. >+PASS IFrame 2 did not receive wheel events. >+PASS IFrame 3 did not receive wheel events. >+ >diff --git a/LayoutTests/fast/scrolling/iframe-maximum-scroll-position.html b/LayoutTests/fast/scrolling/iframe-maximum-scroll-position.html >new file mode 100644 >index 00000000000..671066e2f5b >--- /dev/null >+++ b/LayoutTests/fast/scrolling/iframe-maximum-scroll-position.html >@@ -0,0 +1,120 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<style> >+ iframe { >+ border: 1px solid black; >+ position: absolute; >+ width: 200px; >+ height: 200px; >+ } >+</style> >+<script src="../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script> >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+if (window.internals) >+ internals.settings.setScrollingTreeIncludesFrames(true); >+if (window.eventSender) >+ eventSender.monitorWheelEvents(); >+ >+var pageScrollPositionBefore; >+var iFrameScrollPositionBefore = []; >+ >+function checkForInnerFrameScroll() { >+ var pageScrollPositionAfter = document.body.scrollTop; >+ var iFrameScrollPositionAfter = []; >+ for (var i = 0; i < window.frames.length; i++) >+ iFrameScrollPositionAfter[i] = window.frames[i].document.body.scrollTop; >+ >+ if (pageScrollPositionBefore != pageScrollPositionAfter) >+ testPassed("main frame consumed wheel events."); >+ else >+ testFailed("main frame did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[0] != iFrameScrollPositionAfter[0]) >+ testFailed("IFrame 0 consumed wheel events."); >+ else >+ testPassed("IFrame 0 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[1] != iFrameScrollPositionAfter[1]) >+ testFailed("IFrame 1 consumed wheel events."); >+ else >+ testPassed("IFrame 1 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[2] != iFrameScrollPositionAfter[2]) >+ testFailed("IFrame 2 consumed wheel events."); >+ else >+ testPassed("IFrame 2 did not receive wheel events."); >+ >+ if (iFrameScrollPositionBefore[3] != iFrameScrollPositionAfter[3]) >+ testFailed("IFrame 3 consumed wheel events."); >+ else >+ testPassed("IFrame 3 did not receive wheel events."); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+ >+function runTest() { >+ // Scroll the target frame to the maximum vertical position. >+ window.frames[2].scrollTo(0, 500); >+ >+ if (!window.eventSender) >+ return; >+ >+ // Determine initial scroll positions. >+ pageScrollPositionBefore = document.body.scrollTop; >+ for (var i = 0; i < window.frames.length; i++) >+ iFrameScrollPositionBefore[i] = window.frames[i].document.body.scrollTop; >+ >+ // Mouve the mouse on top of the target frame. >+ var targetFrame = document.getElementsByTagName("iframe")[2]; >+ var startPosX = targetFrame.offsetLeft + targetFrame.offsetWidth / 2; >+ var startPosY = targetFrame.offsetTop + targetFrame.offsetHeight / 2; >+ eventSender.mouseMoveTo(startPosX, startPosY); >+ >+ // Scroll the target frame. >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'began', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'begin'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end'); >+ eventSender.callAfterScrollingCompletes(checkForInnerFrameScroll); >+} >+ >+var frameToLoadCount = 4; >+function newFrameLoaded() { >+ frameToLoadCount--; >+ if (frameToLoadCount == 0) >+ runTest(); >+} >+</script> >+<div style="height: 5000px;"> >+ <iframe style="left: 100px; top: 100px;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 300px; top: 100px;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 100px; top: 300px; background: blue; opacity: .5;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+ <iframe style="left: 300px; top: 300px;" >+ src="data:text/html,<div style='height: 300px;'></div>" >+ onload="newFrameLoaded()"> >+ </iframe> >+</div> >+<div id="console"></div> >+<script> >+description("Verifies basic that scrolling is passed to the parent when iframe is already scrolled to maximum"); >+</script> >+<script src="../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/fast/scrolling/latching/fast-scroll-iframe-latched-mainframe-expected.txt b/LayoutTests/fast/scrolling/latching/fast-scroll-iframe-latched-mainframe-expected.txt >new file mode 100644 >index 00000000000..19aa3b9b681 >--- /dev/null >+++ b/LayoutTests/fast/scrolling/latching/fast-scroll-iframe-latched-mainframe-expected.txt >@@ -0,0 +1,13 @@ >+Put mouse here and flick downwards >+ >+Tests that iframe doesn't consume wheel events when scroll >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+Mouse moved to (28, 66) >+PASS IFrame did not receive wheel events. >+ >diff --git a/LayoutTests/fast/scrolling/latching/fast-scroll-iframe-latched-mainframe.html b/LayoutTests/fast/scrolling/latching/fast-scroll-iframe-latched-mainframe.html >new file mode 100644 >index 00000000000..f1b7fd30b39 >--- /dev/null >+++ b/LayoutTests/fast/scrolling/latching/fast-scroll-iframe-latched-mainframe.html >@@ -0,0 +1,102 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<link rel="help" href="http://www.w3.org/TR/DOM-Level-3-Events/#events-WheelEvent"> >+<script src="../../../resources/js-test-pre.js"></script> >+</head> >+<body> >+<script> >+if (window.internals) >+ window.internals.settings.setAsyncFrameScrollingEnabled(true); >+ >+var iframeTarget; >+var pageScrollPositionBefore; >+var iFrameScrollPositionBefore; >+var continueCount = 2; >+ >+function checkForScroll() { >+ >+ // The IFrame should not have scrolled at all. >+ var pageScrollPositionAfter = document.body.scrollTop; >+ var iFrameScrollPositionAfter = window.frames['target'].document.body.scrollTop; >+ >+ //debug("Page before: " + pageScrollPositionBefore + ", IFrame before: " + iFrameScrollPositionBefore); >+ //debug("Page after: " + pageScrollPositionAfter + ", IFrame after: " + iFrameScrollPositionAfter); >+ >+ if (iFrameScrollPositionBefore != iFrameScrollPositionAfter) >+ testFailed("IFrame consumed wheel events."); >+ else >+ testPassed("IFrame did not receive wheel events."); >+ >+ testRunner.notifyDone(); >+} >+ >+function scrollTest() { >+ // See where our IFrame lives: >+ pageScrollPositionBefore = document.body.scrollTop; >+ iFrameScrollPositionBefore = window.frames['target'].document.body.scrollTop; >+ >+ iframeTarget = document.getElementById('target'); >+ >+ // Scroll the #source until we reach the #target. >+ var startPosX = iframeTarget.offsetLeft + 20; >+ var startPosY = iframeTarget.offsetTop - 42; // Slightly more than one wheel scroll away from the IFrame >+ eventSender.mouseMoveTo(startPosX, startPosY); // Make sure we are just outside the iFrame >+ debug("Mouse moved to (" + startPosX + ", " + startPosY + ")"); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'began', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'begin'); >+ for (i = 0; i < continueCount; i++) >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue'); >+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end'); >+ eventSender.callAfterScrollingCompletes(checkForScroll); >+} >+ >+function setupTopLevel() { >+ >+ if (window.eventSender) { >+ testRunner.waitUntilDone(); >+ eventSender.monitorWheelEvents(); >+ setTimeout(scrollTest, 1000); >+ } else { >+ var messageLocation = document.getElementById('parent'); >+ var message = document.createElement('div'); >+ message.innerHTML = "<p>This test is better run under DumpRenderTree. To manually test it, place the mouse pointer<br/>" >+ + "at the top of the page, and then use the mouse wheel or a two-finger swipe to scroll the<br/>" >+ + "down past the IFrame.<br/><br/>" >+ + "You should not see the row of END labels if this test is successful.</p>"; >+ messageLocation.appendChild(message); >+ } >+} >+ >+</script> >+<div id="parent" style="height: 2000px"> >+ <div id="source" style="height: 100px"> >+ Put mouse here and flick downwards >+ </div> >+ <iframe id="target" name="target" style="border:solid 1px green; height: 500px; width: 500px;" >+ src= "data:text/html, >+ <div id='notToBeScrolled' style='height: 1000px; width: 1000px;'> >+ TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP<br/><br/> >+ This should still be visible inside the frame after you scroll down >+ <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> >+ <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> >+ <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> >+ This should NOT be visible inside the frame after you scroll down<br/> >+ <br/> >+ END END END END END END END END END END END END END >+ </div> >+ " >+ onload="setupTopLevel();" >+ > >+ </iframe> >+</div> >+<div id="console"></div> >+<script> >+description("Tests that iframe doesn't consume wheel events when scroll "); >+</script> >+<script src="../../../resources/js-test-post.js"></script> >+</body> >+</html> >diff --git a/LayoutTests/platform/ios/TestExpectations b/LayoutTests/platform/ios/TestExpectations >index 4c38407ee7b..f9d28187c20 100644 >--- a/LayoutTests/platform/ios/TestExpectations >+++ b/LayoutTests/platform/ios/TestExpectations >@@ -678,6 +678,11 @@ fast/selectors/active-hover-strict.html [ Skip ] > fast/selectors/active-quirks.html [ Skip ] > fast/selectors/active-strict.html [ Skip ] > fast/selectors/hover-invalidation-descendant-dynamic.html [ Skip ] >+fast/scrolling/iframe-maximum-scroll-position.html [ Skip ] >+fast/scrolling/iframe-hit-testing.html [ Skip ] >+fast/scrolling/iframe-hit-testing-overlap.html [ Skip ] >+fast/scrolling/iframe-hit-testing-axis-aligned-transforms.html [ Skip ] >+fast/scrolling/latching/fast-scroll-iframe-latched-mainframe.html [ Skip ] > fast/selectors/hover-quirks.html [ Skip ] > fast/selectors/hover-strict.html [ Skip ] > fast/selectors/not-active-hover-quirks.html [ Skip ] >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index a3920592b9b..ea9594c49cd 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,29 @@ >+2017-06-12 Frederic Wang <fwang@igalia.com> >+ >+ [Mac] Implement basic hit testing for frames >+ https://bugs.webkit.org/show_bug.cgi?id=172917 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Introduce some basic hit testing for frames on mac when AsyncFrameScrollingEnabled=true. >+ For now, this does not take into account more advanced cases (e.g. transformations or >+ overlaps). >+ >+ Tests: fast/scrolling/iframe-maximum-scroll-position.html >+ fast/scrolling/iframe-simple-hit-testing.html >+ fast/scrolling/latching/fast-scroll-iframe-latched-mainframe.html >+ >+ * page/scrolling/ScrollingTree.cpp: >+ (WebCore::ScrollingTree::handleWheelEvent): Try to pass the wheel event to the latched node >+ or otherwise perform a hit testing. >+ * page/scrolling/ScrollingTreeScrollingNode.cpp: >+ (WebCore::ScrollingTreeScrollingNode::scrollLimitReached): Helper function to verify >+ whether a scrolling node can still be scrolled in the requested direction. >+ (WebCore::ScrollingTreeScrollingNode::scrollingTargetForWheelEvent): Add recursive hit >+ testing search for the current node. >+ * page/scrolling/ScrollingTreeScrollingNode.h: Declare scrollingTargetForWheelEvent and >+ scrollLimitReached. >+ > 2019-01-03 Zalan Bujtas <zalan@apple.com> > > REGRESSION: -webkit-appearance test case crashes >diff --git a/Source/WebCore/page/scrolling/ScrollingTree.cpp b/Source/WebCore/page/scrolling/ScrollingTree.cpp >index 524393dd16a..eda09f04f18 100644 >--- a/Source/WebCore/page/scrolling/ScrollingTree.cpp >+++ b/Source/WebCore/page/scrolling/ScrollingTree.cpp >@@ -85,8 +85,29 @@ void ScrollingTree::setOrClearLatchedNode(const PlatformWheelEvent& wheelEvent, > > void ScrollingTree::handleWheelEvent(const PlatformWheelEvent& wheelEvent) > { >- if (m_rootNode) >- downcast<ScrollingTreeScrollingNode>(*m_rootNode).handleWheelEvent(wheelEvent); >+ if (hasLatchedNode()) { >+ auto* node = nodeForID(latchedNode()); >+ if (is<ScrollingTreeScrollingNode>(node)) { >+ downcast<ScrollingTreeScrollingNode>(*node).handleWheelEvent(wheelEvent); >+ return; >+ } >+ } >+ if (m_rootNode) { >+ FloatPoint position = wheelEvent.position(); >+ auto& frameScrollingNode = downcast<ScrollingTreeFrameScrollingNode>(*m_rootNode); >+ position.move(frameScrollingNode.viewToContentsOffset(m_mainFrameScrollPosition)); >+ ScrollingTreeNode* node = &frameScrollingNode.scrollingNodeForPoint(LayoutPoint(position)); >+ while (node) { >+ // FIXME(https://webkit.org/b/176454): Implement CSS overscroll-behavior. >+ if (auto* scrollingNode = downcast<ScrollingTreeScrollingNode>(node)) { >+ if (!scrollingNode->scrollLimitReached(wheelEvent)) { >+ scrollingNode->handleWheelEvent(wheelEvent); >+ return; >+ } >+ } >+ node = node->parent(); >+ } >+ } > } > > void ScrollingTree::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const FloatRect& fixedPositionRect, double scale) >diff --git a/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp b/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp >index b41f7e1a529..f68c7e5e8fb 100644 >--- a/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp >+++ b/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp >@@ -167,6 +167,32 @@ void ScrollingTreeScrollingNode::dumpProperties(TextStream& ts, ScrollingStateTr > ts.dumpProperty("scrollable area parameters", m_scrollableAreaParameters); > } > >+bool ScrollingTreeScrollingNode::scrollLimitReached(const PlatformWheelEvent& wheelEvent) const >+{ >+ FloatPoint oldScrollPosition = scrollPosition(); >+ FloatPoint newScrollPosition = oldScrollPosition + FloatSize(wheelEvent.deltaX(), -wheelEvent.deltaY()); >+ newScrollPosition = newScrollPosition.constrainedBetween(minimumScrollPosition(), maximumScrollPosition()); >+ return newScrollPosition == oldScrollPosition; >+} >+ >+ScrollingTreeScrollingNode& ScrollingTreeScrollingNode::scrollingNodeForPoint(LayoutPoint position) >+{ >+ // Perform hit testing by browsing children recursively in reverse z-order (from top to bottom). >+ if (children()) { >+ LayoutPoint localPosition = position - toLayoutSize(parentRelativeScrollableRect().location()); >+ for (auto iterator = children()->rbegin(), end = children()->rend(); iterator != end; iterator++) { >+ if (is<ScrollingTreeScrollingNode>(**iterator)) { >+ auto& scrollingNode = downcast<ScrollingTreeScrollingNode>(**iterator); >+ if (scrollingNode.parentRelativeScrollableRect().contains(localPosition)) >+ return scrollingNode.scrollingNodeForPoint(localPosition); >+ } >+ } >+ } >+ >+ return *this; >+} >+ >+ > } // namespace WebCore > > #endif // ENABLE(ASYNC_SCROLLING) >diff --git a/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h b/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h >index f6de7830374..1e65306b825 100644 >--- a/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h >+++ b/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h >@@ -75,6 +75,9 @@ public: > void setCurrentVerticalSnapPointIndex(unsigned index) { m_currentVerticalSnapPointIndex = index; } > #endif > >+ ScrollingTreeScrollingNode& scrollingNodeForPoint(LayoutPoint); >+ bool scrollLimitReached(const PlatformWheelEvent&) const; >+ > protected: > ScrollingTreeScrollingNode(ScrollingTree&, ScrollingNodeType, ScrollingNodeID); > >-- >2.20.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 172917
:
312007
|
312321
|
320274
|
320548
|
320627
|
320631
|
320652
|
320752
|
320919
|
355486
|
355637
|
355639
|
355640
|
355641
|
355642
|
355986
|
356005
|
356149
|
356503
|
358490
|
358491
|
358703
|
360651
|
360657
|
360668
|
360677
|
360689
|
360691