<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[173784] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/173784">173784</a></dd>
<dt>Author</dt> <dd>bfulgham@apple.com</dd>
<dt>Date</dt> <dd>2014-09-19 18:10:50 -0700 (Fri, 19 Sep 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Latching in iframes is not working as expected
https://bugs.webkit.org/show_bug.cgi?id=136729
<rdar://problem/18370549>
Reviewed by Simon Fraser.
Source/WebCore:
Test: platform/mac/fast/scrolling/scrolling-iframe-100pct.html
Correct latching behavior by moving the concept of latching from the event handler to the main frame.
The event handlers are per-document, and can improperly latch to the iframe element (rather than the
scrollable content of the iframe) resulting in incorrect behavior.
Also move the wheel event delta tracking to the main frame, as this is similarly "top-level" in nature.
* WebCore.vcxproj/WebCore.vcxproj: Add new LatchedState class.
* WebCore.vcxproj/WebCore.vcxproj.filters: Ditto.
* WebCore.xcodeproj/project.pbxproj: Ditto.
* page/EventHandler.cpp:
(WebCore::EventHandler::EventHandler): Update constructor after moving some members to the new
LatchedState object.
(WebCore::EventHandler::clear): Call 'clear' on the LatchedState class.
(WebCore::EventHandler::platformRecordWheelEvent): Update for new LatchedState class.
(WebCore::EventHandler::handleWheelEvent): Ditto.
(WebCore::EventHandler::clearLatchedState): Ditto.
(WebCore::EventHandler::defaultWheelEventHandler): Ditto.
* page/EventHandler.h:
* page/LatchedState.cpp: Added.
(WebCore::LatchedState::LatchedState):
(WebCore::LatchedState::~LatchedState):
(WebCore::LatchedState::clear):
(WebCore::LatchedState::setWheelEventElement):
(WebCore::LatchedState::setWidgetIsLatched):
(WebCore::LatchedState::setPreviousWheelScrolledElement):
(WebCore::LatchedState::setScrollableContainer):
* page/LatchedState.h: Added.
(WebCore::LatchedState::wheelEventElement):
(WebCore::LatchedState::frame):
(WebCore::LatchedState::setFrame):
(WebCore::LatchedState::widgetIsLatched):
(WebCore::LatchedState::previousWheelScrolledElement):
(WebCore::LatchedState::scrollableContainer):
(WebCore::LatchedState::startedGestureAtScrollLimit):
(WebCore::LatchedState::setStartedGestureAtScrollLimit):
* page/MainFrame.cpp:
(WebCore::MainFrame::MainFrame): Update for new members (LatchedState and WheelEventDeltaTracker)
* page/MainFrame.h:
* page/mac/EventHandlerMac.mm:
(WebCore::EventHandler::platformPrepareForWheelEvents): Use mainFrame-located latching information.
(WebCore::EventHandler::platformRecordWheelEvent): Use mainFrame-located wheel event delta tracking.
(WebCore::EventHandler::platformCompleteWheelEvent): Make sure to use the latched frame as well as
the latched element so that events get routed properly.
(WebCore::EventHandler::platformCompletePlatformWidgetWheelEvent): Update for new mainFrame
location for latched state information.
LayoutTests:
* platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug-expected.txt: Added.
* platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug.html: Added.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreCMakeListstxt">trunk/Source/WebCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorevcxprojWebCorevcxproj">trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj</a></li>
<li><a href="#trunkSourceWebCoreWebCorevcxprojWebCorevcxprojfilters">trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorepageEventHandlercpp">trunk/Source/WebCore/page/EventHandler.cpp</a></li>
<li><a href="#trunkSourceWebCorepageEventHandlerh">trunk/Source/WebCore/page/EventHandler.h</a></li>
<li><a href="#trunkSourceWebCorepageMainFramecpp">trunk/Source/WebCore/page/MainFrame.cpp</a></li>
<li><a href="#trunkSourceWebCorepageMainFrameh">trunk/Source/WebCore/page/MainFrame.h</a></li>
<li><a href="#trunkSourceWebCorepagemacEventHandlerMacmm">trunk/Source/WebCore/page/mac/EventHandlerMac.mm</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsplatformmacfastscrollingscrolliframewebkit1latchingbugexpectedtxt">trunk/LayoutTests/platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug-expected.txt</a></li>
<li><a href="#trunkLayoutTestsplatformmacfastscrollingscrolliframewebkit1latchingbughtml">trunk/LayoutTests/platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug.html</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollLatchingStatecpp">trunk/Source/WebCore/page/scrolling/ScrollLatchingState.cpp</a></li>
<li><a href="#trunkSourceWebCorepagescrollingScrollLatchingStateh">trunk/Source/WebCore/page/scrolling/ScrollLatchingState.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/LayoutTests/ChangeLog        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2014-09-19 Brent Fulgham <bfulgham@apple.com>
+
+ Latching in iframes is not working as expected
+ https://bugs.webkit.org/show_bug.cgi?id=136729
+ <rdar://problem/18370549>
+
+ Reviewed by Simon Fraser.
+
+ * platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug-expected.txt: Added.
+ * platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug.html: Added.
+
</ins><span class="cx"> 2014-09-19 Jer Noble <jer.noble@apple.com>
</span><span class="cx">
</span><span class="cx"> Videos with controls enabled never receive 'dragstart' events.
</span></span></pre></div>
<a id="trunkLayoutTestsplatformmacfastscrollingscrolliframewebkit1latchingbugexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug-expected.txt (0 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug-expected.txt         (rev 0)
+++ trunk/LayoutTests/platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug-expected.txt        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+
+Tests that iframe doesn't pass wheel events to main frame when scrolling at bottom
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+iframe display height = 150
+Mouse moved to (28, 116)
+PASS iframe received wheel events.
+
</ins></span></pre></div>
<a id="trunkLayoutTestsplatformmacfastscrollingscrolliframewebkit1latchingbughtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug.html (0 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug.html         (rev 0)
+++ trunk/LayoutTests/platform/mac/fast/scrolling/scroll-iframe-webkit1-latching-bug.html        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -0,0 +1,100 @@
</span><ins>+<!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 id="parent" style="height: 2000px">
+ <script>
+ var iframeTarget;
+ var pageScrollPositionBefore;
+ var iframeScrollPositionBefore;
+ var continueCount = 5;
+
+ function checkForScroll() {
+
+ // The iframe should have scrolled, but not the main page.
+ var pageScrollPositionAfter = document.body.scrollTop;
+ var iframeScrollPositionAfter = window.frames['target'].document.body.scrollTop;
+
+ if (iframeScrollPositionBefore != iframeScrollPositionAfter)
+ testPassed("iframe received wheel events.");
+ else
+ testFailed("iframe did not receive wheel events.");
+
+ testRunner.notifyDone();
+ }
+
+ function scrollTest() {
+ // See where our iframe lives:
+ pageScrollPositionBefore = document.body.scrollTop;
+
+ iframeTarget = document.getElementById('target');
+
+ var iframeBody = window.frames['target'].document.body;
+ iframeBody.scrollTop = iframeBody.scrollHeight - iframeTarget.clientHeight - 100;
+
+ iframeScrollPositionBefore = iframeBody.scrollTop;
+
+ // Scroll the #source until we reach the #target.
+ var startPosX = iframeTarget.offsetLeft + 20;
+ debug("iframe display height = " + iframeTarget.clientHeight);
+ var startPosY = iframeTarget.offsetTop + iframeTarget.clientHeight - 42; // One wheel turn before end.
+ eventSender.mouseMoveTo(startPosX, startPosY); // Make sure we are just outside the iframe
+ debug("Mouse moved to (" + startPosX + ", " + startPosY + ")");
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'began', 'none', true);
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none', true);
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'changed', 'none', true);
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'ended', 'none', true);
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'begin', true);
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue', true);
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue', true);
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue', true);
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue', true);
+ eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end', true);
+ setTimeout(checkForScroll, 100);
+ }
+
+ function setupTopLevel() {
+ if (window.eventSender) {
+ testRunner.waitUntilDone();
+
+ 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/>"
+ + "inside the iframe, then use the mouse wheel or a two-finger swipe to scroll the iframe to the bottom (and beyond).<br/>"
+ + "<br/><br/>"
+ + "The test passes if you scroll far enough to see the row of END labels but the main page does not scroll.</p>";
+ messageLocation.appendChild(message);
+ }
+ }
+ </script>
+ <iframe id="target" name="target" style="border:solid 1px green; height: 150px; width: 300px;"
+ src= "data:text/html,
+ <html style='height: 100%'>
+ <body style='height: 100%'>
+ <div style='height: 100px; width: 200px'>
+ <div style='overflow-y: auto; overflow-x: hidden;'>
+ 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>
+ </div>
+ </body>
+ </html>"
+ onload="setupTopLevel();">
+ </iframe>
+ <div id="console"></div>
+ <script>
+ description("Tests that iframe doesn't pass wheel events to main frame when scrolling at bottom");
+ </script>
+ <script src="../../../../resources/js-test-post.js"></script>
+ </body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceWebCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/CMakeLists.txt (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/CMakeLists.txt        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/CMakeLists.txt        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -1972,6 +1972,7 @@
</span><span class="cx"> page/animation/ImplicitAnimation.cpp
</span><span class="cx"> page/animation/KeyframeAnimation.cpp
</span><span class="cx">
</span><ins>+ page/scrolling/ScrollLatchingState.cpp
</ins><span class="cx"> page/scrolling/ScrollingConstraints.cpp
</span><span class="cx"> page/scrolling/ScrollingCoordinator.cpp
</span><span class="cx"> page/scrolling/ScrollingStateFixedNode.cpp
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/ChangeLog        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -1,3 +1,59 @@
</span><ins>+2014-09-19 Brent Fulgham <bfulgham@apple.com>
+
+ Latching in iframes is not working as expected
+ https://bugs.webkit.org/show_bug.cgi?id=136729
+ <rdar://problem/18370549>
+
+ Reviewed by Simon Fraser.
+
+ Test: platform/mac/fast/scrolling/scrolling-iframe-100pct.html
+
+ Correct latching behavior by moving the concept of latching from the event handler to the main frame.
+ The event handlers are per-document, and can improperly latch to the iframe element (rather than the
+ scrollable content of the iframe) resulting in incorrect behavior.
+
+ Also move the wheel event delta tracking to the main frame, as this is similarly "top-level" in nature.
+
+ * WebCore.vcxproj/WebCore.vcxproj: Add new LatchedState class.
+ * WebCore.vcxproj/WebCore.vcxproj.filters: Ditto.
+ * WebCore.xcodeproj/project.pbxproj: Ditto.
+ * page/EventHandler.cpp:
+ (WebCore::EventHandler::EventHandler): Update constructor after moving some members to the new
+ LatchedState object.
+ (WebCore::EventHandler::clear): Call 'clear' on the LatchedState class.
+ (WebCore::EventHandler::platformRecordWheelEvent): Update for new LatchedState class.
+ (WebCore::EventHandler::handleWheelEvent): Ditto.
+ (WebCore::EventHandler::clearLatchedState): Ditto.
+ (WebCore::EventHandler::defaultWheelEventHandler): Ditto.
+ * page/EventHandler.h:
+ * page/LatchedState.cpp: Added.
+ (WebCore::LatchedState::LatchedState):
+ (WebCore::LatchedState::~LatchedState):
+ (WebCore::LatchedState::clear):
+ (WebCore::LatchedState::setWheelEventElement):
+ (WebCore::LatchedState::setWidgetIsLatched):
+ (WebCore::LatchedState::setPreviousWheelScrolledElement):
+ (WebCore::LatchedState::setScrollableContainer):
+ * page/LatchedState.h: Added.
+ (WebCore::LatchedState::wheelEventElement):
+ (WebCore::LatchedState::frame):
+ (WebCore::LatchedState::setFrame):
+ (WebCore::LatchedState::widgetIsLatched):
+ (WebCore::LatchedState::previousWheelScrolledElement):
+ (WebCore::LatchedState::scrollableContainer):
+ (WebCore::LatchedState::startedGestureAtScrollLimit):
+ (WebCore::LatchedState::setStartedGestureAtScrollLimit):
+ * page/MainFrame.cpp:
+ (WebCore::MainFrame::MainFrame): Update for new members (LatchedState and WheelEventDeltaTracker)
+ * page/MainFrame.h:
+ * page/mac/EventHandlerMac.mm:
+ (WebCore::EventHandler::platformPrepareForWheelEvents): Use mainFrame-located latching information.
+ (WebCore::EventHandler::platformRecordWheelEvent): Use mainFrame-located wheel event delta tracking.
+ (WebCore::EventHandler::platformCompleteWheelEvent): Make sure to use the latched frame as well as
+ the latched element so that events get routed properly.
+ (WebCore::EventHandler::platformCompletePlatformWidgetWheelEvent): Update for new mainFrame
+ location for latched state information.
+
</ins><span class="cx"> 2014-09-19 Chris Dumez <cdumez@apple.com>
</span><span class="cx">
</span><span class="cx"> Minimize virtual function calls in MarkupAccumulator
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorevcxprojWebCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -7191,6 +7191,7 @@
</span><span class="cx"> <ClCompile Include="..\page\PerformanceTiming.cpp" />
</span><span class="cx"> <ClCompile Include="..\page\PrintContext.cpp" />
</span><span class="cx"> <ClCompile Include="..\page\Screen.cpp" />
</span><ins>+ <ClCompile Include="..\page\scrolling\ScrollLatchingState.cpp" />
</ins><span class="cx"> <ClCompile Include="..\page\scrolling\ScrollingConstraints.cpp" />
</span><span class="cx"> <ClCompile Include="..\page\scrolling\ScrollingCoordinator.cpp" />
</span><span class="cx"> <ClCompile Include="..\page\SecurityOrigin.cpp" />
</span><span class="lines">@@ -19173,6 +19174,7 @@
</span><span class="cx"> <ClInclude Include="..\page\PrintContext.h" />
</span><span class="cx"> <ClInclude Include="..\page\Screen.h" />
</span><span class="cx"> <ClInclude Include="..\page\scrolling\coordinatedgraphics\ScrollingCoordinatorCoordinatedGraphics.h" />
</span><ins>+ <ClInclude Include="..\page\scrolling\ScrollLatchingState.h" />
</ins><span class="cx"> <ClInclude Include="..\page\scrolling\ScrollingConstraints.h" />
</span><span class="cx"> <ClInclude Include="..\page\scrolling\ScrollingCoordinator.h" />
</span><span class="cx"> <ClInclude Include="..\page\scrolling\ScrollingStateFixedNode.h" />
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorevcxprojWebCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -789,6 +789,9 @@
</span><span class="cx"> <ClCompile Include="..\page\Screen.cpp">
</span><span class="cx"> <Filter>page</Filter>
</span><span class="cx"> </ClCompile>
</span><ins>+ <ClCompile Include="..\page\scrolling\ScrollLatchingState.cpp">
+ <Filter>page</Filter>
+ </ClCompile>
</ins><span class="cx"> <ClCompile Include="..\page\scrolling\ScrollingConstraints.cpp">
</span><span class="cx"> <Filter>page</Filter>
</span><span class="cx"> </ClCompile>
</span><span class="lines">@@ -7773,6 +7776,9 @@
</span><span class="cx"> <ClInclude Include="..\page\Screen.h">
</span><span class="cx"> <Filter>page</Filter>
</span><span class="cx"> </ClInclude>
</span><ins>+ <ClInclude Include="..\page\scrolling\ScrollLatchingState.h">
+ <Filter>page</Filter>
+ </ClInclude>
</ins><span class="cx"> <ClInclude Include="..\page\scrolling\ScrollingConstraints.h">
</span><span class="cx"> <Filter>page</Filter>
</span><span class="cx"> </ClInclude>
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -2364,6 +2364,8 @@
</span><span class="cx">                 7AA3A6A4194B5C22001CBD24 /* TileCoverageMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AA3A6A2194B5C22001CBD24 /* TileCoverageMap.h */; };
</span><span class="cx">                 7AABA25914BC613300AA9A11 /* DOMEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AABA25714BC613300AA9A11 /* DOMEditor.cpp */; };
</span><span class="cx">                 7AABA25A14BC613300AA9A11 /* DOMEditor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AABA25814BC613300AA9A11 /* DOMEditor.h */; };
</span><ins>+                7AAFE8CF19CB8672000F56D8 /* ScrollLatchingState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AAFE8CD19CB8672000F56D8 /* ScrollLatchingState.cpp */; };
+                7AAFE8D019CB8672000F56D8 /* ScrollLatchingState.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AAFE8CE19CB8672000F56D8 /* ScrollLatchingState.h */; };
</ins><span class="cx">                 7AB0B1C01211A62200A76940 /* InspectorDatabaseAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7AB0B1BE1211A62200A76940 /* InspectorDatabaseAgent.cpp */; };
</span><span class="cx">                 7AB0B1C11211A62200A76940 /* InspectorDatabaseAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 7AB0B1BF1211A62200A76940 /* InspectorDatabaseAgent.h */; };
</span><span class="cx">                 7ACD88D314C08BD60084EDD2 /* InspectorIndexedDBAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7ACD88D114C08BD60084EDD2 /* InspectorIndexedDBAgent.cpp */; };
</span><span class="lines">@@ -9498,6 +9500,8 @@
</span><span class="cx">                 7AA3A6A2194B5C22001CBD24 /* TileCoverageMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TileCoverageMap.h; path = ca/TileCoverageMap.h; sourceTree = "<group>"; };
</span><span class="cx">                 7AABA25714BC613300AA9A11 /* DOMEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMEditor.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 7AABA25814BC613300AA9A11 /* DOMEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMEditor.h; sourceTree = "<group>"; };
</span><ins>+                7AAFE8CD19CB8672000F56D8 /* ScrollLatchingState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollLatchingState.cpp; sourceTree = "<group>"; };
+                7AAFE8CE19CB8672000F56D8 /* ScrollLatchingState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollLatchingState.h; sourceTree = "<group>"; };
</ins><span class="cx">                 7AB0B1BE1211A62200A76940 /* InspectorDatabaseAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorDatabaseAgent.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 7AB0B1BF1211A62200A76940 /* InspectorDatabaseAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDatabaseAgent.h; sourceTree = "<group>"; };
</span><span class="cx">                 7ACD88D114C08BD60084EDD2 /* InspectorIndexedDBAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorIndexedDBAgent.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -15084,6 +15088,8 @@
</span><span class="cx">                                 1AF62EE214DA22A70041556C /* mac */,
</span><span class="cx">                                 0FFD4D5E18651FA300512F6E /* AsyncScrollingCoordinator.cpp */,
</span><span class="cx">                                 0FFD4D5F18651FA300512F6E /* AsyncScrollingCoordinator.h */,
</span><ins>+                                7AAFE8CD19CB8672000F56D8 /* ScrollLatchingState.cpp */,
+                                7AAFE8CE19CB8672000F56D8 /* ScrollLatchingState.h */,
</ins><span class="cx">                                 0F605AEA15F94848004DF0C0 /* ScrollingConstraints.cpp */,
</span><span class="cx">                                 0F605AEB15F94848004DF0C0 /* ScrollingConstraints.h */,
</span><span class="cx">                                 1AF62EE414DA22A70041556C /* ScrollingCoordinator.cpp */,
</span><span class="lines">@@ -24913,6 +24919,7 @@
</span><span class="cx">                                 BCEC01C30C274DDD009F4EC9 /* JSScreen.h in Headers */,
</span><span class="cx">                                 FDA15ECE12B03F61003A583A /* JSScriptProcessorNode.h in Headers */,
</span><span class="cx">                                 9FA37EFB1172FDA600C4CD55 /* JSScriptProfile.h in Headers */,
</span><ins>+                                7AAFE8D019CB8672000F56D8 /* ScrollLatchingState.h in Headers */,
</ins><span class="cx">                                 9FA37EFD1172FDA600C4CD55 /* JSScriptProfileNode.h in Headers */,
</span><span class="cx">                                 41D07A7F0FF935CA0095EDCE /* JSSharedWorker.h in Headers */,
</span><span class="cx">                                 41D1690610238B66009BC827 /* JSSharedWorkerGlobalScope.h in Headers */,
</span><span class="lines">@@ -28952,6 +28959,7 @@
</span><span class="cx">                                 B27535630B053814002CE64F /* PathCG.cpp in Sources */,
</span><span class="cx">                                 A88DD4890B4629B000C02990 /* PathTraversalState.cpp in Sources */,
</span><span class="cx">                                 A8FA6E5E0E4CFDED00D5CF49 /* Pattern.cpp in Sources */,
</span><ins>+                                7AAFE8CF19CB8672000F56D8 /* ScrollLatchingState.cpp in Sources */,
</ins><span class="cx">                                 A80A38FE0E50CC8200A25EBC /* PatternCG.cpp in Sources */,
</span><span class="cx">                                 B27535640B053814002CE64F /* PDFDocumentImage.cpp in Sources */,
</span><span class="cx">                                 2D6E468417D660F500ECF8BB /* PDFDocumentImageMac.mm in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCorepageEventHandlercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/EventHandler.cpp (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/EventHandler.cpp        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/page/EventHandler.cpp        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -83,6 +83,7 @@
</span><span class="cx"> #include "SVGNames.h"
</span><span class="cx"> #include "SVGUseElement.h"
</span><span class="cx"> #include "ScrollAnimator.h"
</span><ins>+#include "ScrollLatchingState.h"
</ins><span class="cx"> #include "Scrollbar.h"
</span><span class="cx"> #include "Settings.h"
</span><span class="cx"> #include "ShadowRoot.h"
</span><span class="lines">@@ -401,12 +402,9 @@
</span><span class="cx"> #endif
</span><span class="cx"> , m_mousePositionIsUnknown(true)
</span><span class="cx"> , m_mouseDownTimestamp(0)
</span><del>- , m_recentWheelEventDeltaTracker(std::make_unique<WheelEventDeltaTracker>())
- , m_widgetIsLatched(false)
</del><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx"> , m_mouseDownView(nil)
</span><span class="cx"> , m_sendingEventToSubview(false)
</span><del>- , m_startedGestureAtScrollLimit(false)
</del><span class="cx"> #if !PLATFORM(IOS)
</span><span class="cx"> , m_activationEventNumber(-1)
</span><span class="cx"> #endif // !PLATFORM(IOS)
</span><span class="lines">@@ -490,11 +488,9 @@
</span><span class="cx"> m_mousePressed = false;
</span><span class="cx"> m_capturesDragging = false;
</span><span class="cx"> m_capturingMouseEventsElement = nullptr;
</span><del>- m_latchedWheelEventElement = nullptr;
-#if PLATFORM(COCOA)
- m_latchedScrollableContainer = nullptr;
</del><ins>+#if PLATFORM(MAC)
+ m_frame.mainFrame().resetLatchingState();
</ins><span class="cx"> #endif
</span><del>- m_previousWheelScrolledElement = nullptr;
</del><span class="cx"> #if ENABLE(TOUCH_EVENTS) && !ENABLE(IOS_TOUCH_EVENTS)
</span><span class="cx"> m_originatingTouchPointTargets.clear();
</span><span class="cx"> m_originatingTouchPointDocument.clear();
</span><span class="lines">@@ -2644,7 +2640,7 @@
</span><span class="cx">
</span><span class="cx"> void EventHandler::platformRecordWheelEvent(const PlatformWheelEvent& event)
</span><span class="cx"> {
</span><del>- m_recentWheelEventDeltaTracker->recordWheelEventDelta(event);
</del><ins>+ m_frame.mainFrame().wheelEventDeltaTracker()->recordWheelEventDelta(event);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool EventHandler::platformCompleteWheelEvent(const PlatformWheelEvent& event, Element*, ContainerNode*, ScrollableArea*)
</span><span class="lines">@@ -2689,13 +2685,12 @@
</span><span class="cx"> bool isOverWidget = result.isOverWidget();
</span><span class="cx"> platformPrepareForWheelEvents(event, result, element, scrollableContainer, scrollableArea, isOverWidget);
</span><span class="cx">
</span><del>-#if PLATFORM(COCOA)
</del><ins>+#if PLATFORM(MAC)
</ins><span class="cx"> if (event.phase() == PlatformWheelEventPhaseNone && event.momentumPhase() == PlatformWheelEventPhaseNone)
</span><del>-#endif
</del><span class="cx"> {
</span><del>- m_latchedWheelEventElement = nullptr;
- m_previousWheelScrolledElement = nullptr;
</del><ins>+ m_frame.mainFrame().latchingState()->clear();
</ins><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx">
</span><span class="cx"> // FIXME: It should not be necessary to do this mutation here.
</span><span class="cx"> // Instead, the handlers should know convert vertical scrolls appropriately.
</span><span class="lines">@@ -2740,12 +2735,10 @@
</span><span class="cx">
</span><span class="cx"> void EventHandler::clearLatchedState()
</span><span class="cx"> {
</span><del>- m_latchedWheelEventElement = nullptr;
-#if PLATFORM(COCOA)
- m_latchedScrollableContainer = nullptr;
</del><ins>+#if PLATFORM(MAC)
+ m_frame.mainFrame().latchingState()->clear();
</ins><span class="cx"> #endif
</span><del>- m_widgetIsLatched = false;
- m_previousWheelScrolledElement = nullptr;
</del><ins>+ m_frame.mainFrame().wheelEventDeltaTracker()->endTrackingDeltas();
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void EventHandler::defaultWheelEventHandler(Node* startNode, WheelEvent* wheelEvent)
</span><span class="lines">@@ -2753,13 +2746,18 @@
</span><span class="cx"> if (!startNode || !wheelEvent)
</span><span class="cx"> return;
</span><span class="cx">
</span><del>- Element* stopElement = m_previousWheelScrolledElement.get();
</del><span class="cx"> DominantScrollGestureDirection dominantDirection = DominantScrollGestureDirection::None;
</span><span class="cx">
</span><ins>+#if PLATFORM(MAC)
+ ScrollLatchingState* latchedState = m_frame.mainFrame().latchingState();
+ ASSERT(latchedState);
+ Element* stopElement = latchedState->previousWheelScrolledElement();
+
</ins><span class="cx"> // Workaround for scrolling issues <rdar://problem/14758615>.
</span><del>-#if PLATFORM(COCOA)
- if (m_recentWheelEventDeltaTracker->isTrackingDeltas())
- dominantDirection = m_recentWheelEventDeltaTracker->dominantScrollGestureDirection();
</del><ins>+ if (m_frame.mainFrame().wheelEventDeltaTracker()->isTrackingDeltas())
+ dominantDirection = m_frame.mainFrame().wheelEventDeltaTracker()->dominantScrollGestureDirection();
+#else
+ Element* stopElement = nullptr;
</ins><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> // Break up into two scrolls if we need to. Diagonal movement on
</span><span class="lines">@@ -2770,8 +2768,10 @@
</span><span class="cx"> if (dominantDirection != DominantScrollGestureDirection::Horizontal && handleWheelEventInAppropriateEnclosingBoxForSingleAxis(startNode, wheelEvent, &stopElement, ScrollEventAxis::Vertical))
</span><span class="cx"> wheelEvent->setDefaultHandled();
</span><span class="cx">
</span><del>- if (!m_latchedWheelEventElement)
- m_previousWheelScrolledElement = stopElement;
</del><ins>+#if PLATFORM(MAC)
+ if (!latchedState->wheelEventElement())
+ latchedState->setPreviousWheelScrolledElement(stopElement);
+#endif
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> #if ENABLE(CONTEXT_MENUS)
</span></span></pre></div>
<a id="trunkSourceWebCorepageEventHandlerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/EventHandler.h (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/EventHandler.h        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/page/EventHandler.h        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -535,15 +535,8 @@
</span><span class="cx"> double m_mouseDownTimestamp;
</span><span class="cx"> PlatformMouseEvent m_mouseDown;
</span><span class="cx">
</span><del>- std::unique_ptr<WheelEventDeltaTracker> m_recentWheelEventDeltaTracker;
- RefPtr<Element> m_latchedWheelEventElement;
- bool m_widgetIsLatched;
-
- RefPtr<Element> m_previousWheelScrolledElement;
-
</del><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx"> NSView *m_mouseDownView;
</span><del>- RefPtr<ContainerNode> m_latchedScrollableContainer;
</del><span class="cx"> bool m_sendingEventToSubview;
</span><span class="cx"> bool m_startedGestureAtScrollLimit;
</span><span class="cx"> #if !PLATFORM(IOS)
</span></span></pre></div>
<a id="trunkSourceWebCorepageMainFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/MainFrame.cpp (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/MainFrame.cpp        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/page/MainFrame.cpp        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -1,40 +1,50 @@
</span><span class="cx"> /*
</span><ins>+ * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
</ins><span class="cx">
</span><del>-Copyright (C) 2013 Apple Inc. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*/
-
</del><span class="cx"> #include "config.h"
</span><span class="cx"> #include "MainFrame.h"
</span><span class="cx">
</span><ins>+#include "ScrollLatchingState.h"
+#include "WheelEventDeltaTracker.h"
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><span class="cx"> inline MainFrame::MainFrame(Page& page, FrameLoaderClient& client)
</span><span class="cx"> : Frame(page, nullptr, client)
</span><span class="cx"> , m_selfOnlyRefCount(0)
</span><ins>+#if PLATFORM(MAC)
+ , m_latchingState(std::make_unique<ScrollLatchingState>())
+#endif
+ , m_recentWheelEventDeltaTracker(std::make_unique<WheelEventDeltaTracker>())
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+MainFrame::~MainFrame()
+{
+}
+
</ins><span class="cx"> RefPtr<MainFrame> MainFrame::create(Page& page, FrameLoaderClient& client)
</span><span class="cx"> {
</span><span class="cx"> return adoptRef(new MainFrame(page, client));
</span><span class="lines">@@ -66,4 +76,14 @@
</span><span class="cx"> tree().removeChild(child);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+#if PLATFORM(MAC)
+void MainFrame::resetLatchingState()
+{
+ if (!m_latchingState)
+ return;
+
+ m_latchingState->clear();
</ins><span class="cx"> }
</span><ins>+#endif
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCorepageMainFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/MainFrame.h (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/MainFrame.h        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/page/MainFrame.h        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -1,29 +1,28 @@
</span><span class="cx"> /*
</span><ins>+ * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
</ins><span class="cx">
</span><del>-Copyright (C) 2013 Apple Inc. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*/
-
</del><span class="cx"> #ifndef MainFrame_h
</span><span class="cx"> #define MainFrame_h
</span><span class="cx">
</span><span class="lines">@@ -31,19 +30,36 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><ins>+class ScrollLatchingState;
+class WheelEventDeltaTracker;
+
</ins><span class="cx"> class MainFrame final : public Frame {
</span><span class="cx"> public:
</span><span class="cx"> static RefPtr<MainFrame> create(Page&, FrameLoaderClient&);
</span><span class="cx">
</span><ins>+ virtual ~MainFrame();
+
</ins><span class="cx"> void selfOnlyRef();
</span><span class="cx"> void selfOnlyDeref();
</span><span class="cx">
</span><ins>+ WheelEventDeltaTracker* wheelEventDeltaTracker() { return m_recentWheelEventDeltaTracker.get(); }
+
+#if PLATFORM(MAC)
+ ScrollLatchingState* latchingState() { return m_latchingState.get(); }
+ void resetLatchingState();
+#endif
+
</ins><span class="cx"> private:
</span><span class="cx"> MainFrame(Page&, FrameLoaderClient&);
</span><span class="cx">
</span><span class="cx"> void dropChildren();
</span><span class="cx">
</span><span class="cx"> unsigned m_selfOnlyRefCount;
</span><ins>+
+#if PLATFORM(MAC)
+ std::unique_ptr<ScrollLatchingState> m_latchingState;
+#endif
+ std::unique_ptr<WheelEventDeltaTracker> m_recentWheelEventDeltaTracker;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> inline bool Frame::isMainFrame() const
</span></span></pre></div>
<a id="trunkSourceWebCorepagemacEventHandlerMacmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/mac/EventHandlerMac.mm (173783 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/mac/EventHandlerMac.mm        2014-09-20 00:11:47 UTC (rev 173783)
+++ trunk/Source/WebCore/page/mac/EventHandlerMac.mm        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> #include "RenderListBox.h"
</span><span class="cx"> #include "RenderWidget.h"
</span><span class="cx"> #include "RuntimeApplicationChecks.h"
</span><ins>+#include "ScrollLatchingState.h"
</ins><span class="cx"> #include "ScrollableArea.h"
</span><span class="cx"> #include "Scrollbar.h"
</span><span class="cx"> #include "Settings.h"
</span><span class="lines">@@ -815,6 +816,18 @@
</span><span class="cx"> return widget->platformWidget();
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static bool latchingIsLockedToPlatformFrame(const Frame& frame)
+{
+ ScrollLatchingState* latchedState = frame.mainFrame().latchingState();
+ if (!latchedState)
+ return false;
+
+ if (frameHasPlatformWidget(frame) && &frame != latchedState->frame())
+ return true;
+
+ return false;
+}
+
</ins><span class="cx"> void EventHandler::platformPrepareForWheelEvents(const PlatformWheelEvent& wheelEvent, const HitTestResult& result, RefPtr<Element>& wheelEventTarget, RefPtr<ContainerNode>& scrollableContainer, ScrollableArea*& scrollableArea, bool& isOverWidget)
</span><span class="cx"> {
</span><span class="cx"> FrameView* view = m_frame.view();
</span><span class="lines">@@ -841,56 +854,73 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ ScrollLatchingState* latchingState = m_frame.mainFrame().latchingState();
+ ASSERT(latchingState);
</ins><span class="cx"> if (wheelEvent.shouldConsiderLatching()) {
</span><span class="cx"> if (scrollableArea && scrollableContainer)
</span><del>- m_startedGestureAtScrollLimit = scrolledToEdgeInDominantDirection(*scrollableContainer, *scrollableArea, wheelEvent.deltaX(), wheelEvent.deltaY());
</del><ins>+ latchingState->setStartedGestureAtScrollLimit(scrolledToEdgeInDominantDirection(*scrollableContainer, *scrollableArea, wheelEvent.deltaX(), wheelEvent.deltaY()));
</ins><span class="cx"> else
</span><del>- m_startedGestureAtScrollLimit = false;
- m_latchedWheelEventElement = wheelEventTarget;
</del><ins>+ latchingState->setStartedGestureAtScrollLimit(false);
+ latchingState->setWheelEventElement(wheelEventTarget);
+ latchingState->setFrame(&m_frame);
</ins><span class="cx"> // FIXME: What prevents us from deleting this scrollable container while still holding a pointer to it?
</span><del>- m_latchedScrollableContainer = scrollableContainer;
- m_widgetIsLatched = result.isOverWidget();
- isOverWidget = m_widgetIsLatched;
- m_recentWheelEventDeltaTracker->beginTrackingDeltas();
- } else if (wheelEvent.shouldResetLatching()) {
</del><ins>+ latchingState->setScrollableContainer(scrollableContainer);
+ latchingState->setWidgetIsLatched(result.isOverWidget());
+ isOverWidget = latchingState->widgetIsLatched();
+ m_frame.mainFrame().wheelEventDeltaTracker()->beginTrackingDeltas();
+ } else if (wheelEvent.shouldResetLatching())
</ins><span class="cx"> clearLatchedState();
</span><del>- m_recentWheelEventDeltaTracker->endTrackingDeltas();
</del><ins>+
+ if (!wheelEvent.shouldResetLatching() && latchingState->wheelEventElement()) {
+ if (latchingIsLockedToPlatformFrame(m_frame))
+ return;
+
+ wheelEventTarget = latchingState->wheelEventElement();
+ isOverWidget = latchingState->widgetIsLatched();
</ins><span class="cx"> }
</span><del>-
- if (!wheelEvent.shouldResetLatching() && m_latchedWheelEventElement) {
- wheelEventTarget = m_latchedWheelEventElement.get();
- isOverWidget = m_widgetIsLatched;
- }
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void EventHandler::platformRecordWheelEvent(const PlatformWheelEvent& wheelEvent)
</span><span class="cx"> {
</span><span class="cx"> switch (wheelEvent.phase()) {
</span><span class="cx"> case PlatformWheelEventPhaseBegan:
</span><del>- m_recentWheelEventDeltaTracker->beginTrackingDeltas();
</del><ins>+ m_frame.mainFrame().wheelEventDeltaTracker()->beginTrackingDeltas();
</ins><span class="cx"> break;
</span><span class="cx"> case PlatformWheelEventPhaseEnded:
</span><del>- m_recentWheelEventDeltaTracker->endTrackingDeltas();
</del><ins>+ m_frame.mainFrame().wheelEventDeltaTracker()->endTrackingDeltas();
</ins><span class="cx"> break;
</span><span class="cx"> default:
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- m_recentWheelEventDeltaTracker->recordWheelEventDelta(wheelEvent);
</del><ins>+ m_frame.mainFrame().wheelEventDeltaTracker()->recordWheelEventDelta(wheelEvent);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+static FrameView* frameViewForLatchingState(Frame& frame, ScrollLatchingState* latchingState)
+{
+ if (latchingIsLockedToPlatformFrame(frame))
+ return frame.view();
+
+ return latchingState->frame() ? latchingState->frame()->view() : frame.view();
+}
+
</ins><span class="cx"> bool EventHandler::platformCompleteWheelEvent(const PlatformWheelEvent& wheelEvent, Element* wheelEventTarget, ContainerNode* scrollableContainer, ScrollableArea* scrollableArea)
</span><span class="cx"> {
</span><span class="cx"> // We do another check on the frame view because the event handler can run JS which results in the frame getting destroyed.
</span><span class="cx"> FrameView* view = m_frame.view();
</span><span class="cx">
</span><del>- if (wheelEvent.useLatchedEventElement() && m_latchedScrollableContainer) {
</del><ins>+ ScrollLatchingState* latchingState = m_frame.mainFrame().latchingState();
+ ASSERT(latchingState);
+ if (wheelEvent.useLatchedEventElement() && latchingState->scrollableContainer()) {
+ view = frameViewForLatchingState(m_frame, latchingState);
</ins><span class="cx"> if (!view || !view->frame().isMainFrame()) {
</span><span class="cx"> bool didHandleWheelEvent = view && view->wheelEvent(wheelEvent);
</span><del>- if (!didHandleWheelEvent && scrollableContainer == m_latchedScrollableContainer) {
</del><ins>+ if (!didHandleWheelEvent && scrollableContainer == latchingState->scrollableContainer()) {
</ins><span class="cx"> // If we are just starting a scroll event, and have nowhere left to scroll, allow
</span><span class="cx"> // the enclosing frame to handle the scroll.
</span><del>- didHandleWheelEvent = !m_startedGestureAtScrollLimit;
</del><ins>+ didHandleWheelEvent = !latchingState->startedGestureAtScrollLimit();
+ if (!didHandleWheelEvent)
+ latchingState->setFrame(nullptr);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // If the platform widget is handling the event, we always want to return false
</span><span class="lines">@@ -901,11 +931,11 @@
</span><span class="cx"> return didHandleWheelEvent;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (scrollableArea && !m_startedGestureAtScrollLimit && scrollableContainer == m_latchedScrollableContainer) {
</del><ins>+ if (scrollableArea && !latchingState->startedGestureAtScrollLimit() && scrollableContainer == latchingState->scrollableContainer()) {
</ins><span class="cx"> m_isHandlingWheelEvent = false;
</span><span class="cx">
</span><span class="cx"> if (eventTargetIsPlatformWidget(wheelEventTarget))
</span><del>- return !m_startedGestureAtScrollLimit;
</del><ins>+ return !latchingState->startedGestureAtScrollLimit();
</ins><span class="cx">
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="lines">@@ -922,8 +952,10 @@
</span><span class="cx"> if (frameHasPlatformWidget(m_frame) && widget.isFrameView())
</span><span class="cx"> return true;
</span><span class="cx">
</span><del>- if (wheelEvent.useLatchedEventElement() && m_latchedScrollableContainer && scrollableContainer == m_latchedScrollableContainer)
- return !m_startedGestureAtScrollLimit;
</del><ins>+ ScrollLatchingState* latchingState = m_frame.mainFrame().latchingState();
+ ASSERT(latchingState);
+ if (wheelEvent.useLatchedEventElement() && latchingState->scrollableContainer() && scrollableContainer == latchingState->scrollableContainer())
+ return !latchingState->startedGestureAtScrollLimit();
</ins><span class="cx">
</span><span class="cx"> return false;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollLatchingStatecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/page/scrolling/ScrollLatchingState.cpp (0 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollLatchingState.cpp         (rev 0)
+++ trunk/Source/WebCore/page/scrolling/ScrollLatchingState.cpp        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScrollLatchingState.h"
+
+#include "Element.h"
+
+namespace WebCore {
+
+ScrollLatchingState::ScrollLatchingState()
+ : m_frame(nullptr)
+ , m_widgetIsLatched(false)
+ , m_startedGestureAtScrollLimit(false)
+{
+}
+
+ScrollLatchingState::~ScrollLatchingState()
+{
+}
+
+void ScrollLatchingState::clear()
+{
+ m_wheelEventElement = nullptr;
+ m_frame = nullptr;
+ m_scrollableContainer = nullptr;
+ m_widgetIsLatched = false;
+ m_previousWheelScrolledElement = nullptr;
+}
+
+void ScrollLatchingState::setWheelEventElement(PassRefPtr<Element> element)
+{
+ m_wheelEventElement = element;
+}
+
+void ScrollLatchingState::setWidgetIsLatched(bool isOverWidget)
+{
+ m_widgetIsLatched = isOverWidget;
+}
+
+void ScrollLatchingState::setPreviousWheelScrolledElement(PassRefPtr<Element> element)
+{
+ m_previousWheelScrolledElement = element;
+}
+
+void ScrollLatchingState::setScrollableContainer(PassRefPtr<ContainerNode> node)
+{
+ m_scrollableContainer = node;
+}
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebCorepagescrollingScrollLatchingStateh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/page/scrolling/ScrollLatchingState.h (0 => 173784)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/scrolling/ScrollLatchingState.h         (rev 0)
+++ trunk/Source/WebCore/page/scrolling/ScrollLatchingState.h        2014-09-20 01:10:50 UTC (rev 173784)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ScrollLatchingState_h
+#define ScrollLatchingState_h
+
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class ContainerNode;
+class Element;
+class Frame;
+
+class ScrollLatchingState {
+public:
+ ScrollLatchingState();
+ virtual ~ScrollLatchingState();
+
+ void clear();
+
+ Element* wheelEventElement() { return m_wheelEventElement.get(); }
+ void setWheelEventElement(PassRefPtr<Element>);
+ Frame* frame() { return m_frame; }
+ void setFrame(Frame* frame) { m_frame = frame; }
+
+ bool widgetIsLatched() const { return m_widgetIsLatched; }
+ void setWidgetIsLatched(bool isOverWidget);
+
+ Element* previousWheelScrolledElement() { return m_previousWheelScrolledElement.get(); }
+ void setPreviousWheelScrolledElement(PassRefPtr<Element>);
+
+ ContainerNode* scrollableContainer() { return m_scrollableContainer.get(); }
+ void setScrollableContainer(PassRefPtr<ContainerNode>);
+ bool startedGestureAtScrollLimit() const { return m_startedGestureAtScrollLimit; }
+ void setStartedGestureAtScrollLimit(bool startedAtLimit) { m_startedGestureAtScrollLimit = startedAtLimit; }
+
+private:
+ RefPtr<Element> m_wheelEventElement;
+ RefPtr<Element> m_previousWheelScrolledElement;
+ RefPtr<ContainerNode> m_scrollableContainer;
+
+ Frame* m_frame;
+
+ bool m_widgetIsLatched;
+ bool m_startedGestureAtScrollLimit;
+};
+
+}
+
+#endif
</ins></span></pre>
</div>
</div>
</body>
</html>