EventHandler::handleGestureScrollUpdate() should invoke the user-generated scroll...
authortdanderson@chromium.org <tdanderson@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 2 Mar 2013 01:08:22 +0000 (01:08 +0000)
committertdanderson@chromium.org <tdanderson@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 2 Mar 2013 01:08:22 +0000 (01:08 +0000)
so its behavior matches other user-initiated scrolls
https://bugs.webkit.org/show_bug.cgi?id=109769

Reviewed by James Robinson.

Source/WebCore:

To ensure that the scrolling behavior of GestureScrollUpdate events are consistent with
the scrolling behavior of mousewheel events, use the existing user-generated scroll logic
instead of calling into RenderLayer::scrollByRecursively(). This patch fixes the bug
reported in https://bugs.webkit.org/show_bug.cgi?id=109316, where the example page can
be scrolled using touch but cannot be scrolled using mousewheels.

Note that this patch does not use any of the mousewheel event-handling code.

Tests: fast/events/touch/gesture/touch-gesture-noscroll-body-propagated.html
       fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden.html
       fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden.html
       fast/events/touch/gesture/touch-gesture-noscroll-body.html

* page/EventHandler.cpp:
(WebCore::EventHandler::clear):
(WebCore::EventHandler::handleGestureEvent):
(WebCore::EventHandler::handleGestureScrollBegin):
(WebCore::EventHandler::handleGestureScrollUpdate):
(WebCore::EventHandler::sendScrollEventToView):
    By calling this function at the start of handleGestureScrollUpdate() in the case
    where |m_scrollGestureHandlingNode| is null, we ensure that the scroll updates
    can still scroll the page itself, if possible.
(WebCore):
(WebCore::EventHandler::clearGestureScrollNodes):
* page/EventHandler.h:
(EventHandler):
* platform/PlatformWheelEvent.h:
(WebCore::PlatformWheelEvent::setHasPreciseScrollingDeltas):

Source/WebKit/chromium:

Clear the nodes corresponding to a fling scroll event when the event ends.

* src/WebViewImpl.cpp:
(WebKit::WebViewImpl::updateAnimations):

LayoutTests:

Four new layout tests have been added and touch-gesture-scroll-page.html has been
modified to demonstrate that this patch fixes two existing bugs. See the inline
comments below for details.

Because I am now using the existing user-generated scroll logic, the delta for a single
GestureScrollUpdate event will not be propagated to the parent of the targeted node
unless the targeted node has no remaining scrollable area. So the changes to the
existing layout tests have been made to ensure that the targeted node has been fully
scrolled before subsequent GestureScrollUpdate events will scroll the parent(s) of
the targeted node.

I have also removed the function recordScroll() from the existing layout tests
because this function already exists in the included file resources/gesture-helpers.js.

* fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt: Added.
* fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt: Added.
* fast/events/touch/gesture/touch-gesture-noscroll-body-propagated.html: Copied from LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page.html.
* fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt: Added.
* fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden.html: Copied from LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page.html.
* fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt: Added.
* fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden.html: Copied from LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page.html.
* fast/events/touch/gesture/touch-gesture-noscroll-body.html: Copied from LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page.html.
* fast/events/touch/gesture/touch-gesture-scroll-div-not-propagated.html:
* fast/events/touch/gesture/touch-gesture-scroll-div-propagated.html:
* fast/events/touch/gesture/touch-gesture-scroll-div-twice-propagated.html:
* fast/events/touch/gesture/touch-gesture-scroll-iframe-not-propagated.html:
* fast/events/touch/gesture/touch-gesture-scroll-iframe-propagated.html:
* fast/events/touch/gesture/touch-gesture-scroll-page-not-propagated.html:
* fast/events/touch/gesture/touch-gesture-scroll-page-propagated.html:
* fast/events/touch/gesture/touch-gesture-scroll-page.html:
      I modified this layout test in order to add test coverage for another bug
      which is fixed by this patch: if the hit test performed on a GestureScrollBegin
      does not target a specific node, the subsequent GestureScrollUpdate events should
      still attempt to scroll the page itself. This is consistent with how mousewheel
      events behave.
* platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt: Added.
* platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt: Added.
* platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt: Added.
* platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt: Added.
      These four new layout tests verify that a non-scrollable body will not scroll,
      as reported in https://bugs.webkit.org/show_bug.cgi?id=109316.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@144519 268f45cc-cd09-0410-ab3c-d52691b4dbfc

27 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated.html [new file with mode: 0644]
LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden.html [new file with mode: 0644]
LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden.html [new file with mode: 0644]
LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body.html [new file with mode: 0644]
LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-not-propagated.html
LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-propagated.html
LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-div-twice-propagated.html
LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-not-propagated.html
LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-iframe-propagated.html
LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-not-propagated.html
LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page-propagated.html
LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page.html
LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt [new file with mode: 0644]
LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/EventHandler.h
Source/WebCore/platform/PlatformWheelEvent.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/WebViewImpl.cpp

index fbd78a6..f26962a 100644 (file)
@@ -1,3 +1,53 @@
+2013-03-01  Terry Anderson  <tdanderson@chromium.org>
+
+        EventHandler::handleGestureScrollUpdate() should invoke the user-generated scroll routines 
+        so its behavior matches other user-initiated scrolls
+        https://bugs.webkit.org/show_bug.cgi?id=109769
+
+        Reviewed by James Robinson.
+
+        Four new layout tests have been added and touch-gesture-scroll-page.html has been
+        modified to demonstrate that this patch fixes two existing bugs. See the inline
+        comments below for details.
+
+        Because I am now using the existing user-generated scroll logic, the delta for a single
+        GestureScrollUpdate event will not be propagated to the parent of the targeted node
+        unless the targeted node has no remaining scrollable area. So the changes to the
+        existing layout tests have been made to ensure that the targeted node has been fully
+        scrolled before subsequent GestureScrollUpdate events will scroll the parent(s) of
+        the targeted node.
+
+        I have also removed the function recordScroll() from the existing layout tests
+        because this function already exists in the included file resources/gesture-helpers.js.
+
+        * fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt: Added.
+        * fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt: Added.
+        * fast/events/touch/gesture/touch-gesture-noscroll-body-propagated.html: Copied from LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page.html.
+        * fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt: Added.
+        * fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden.html: Copied from LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page.html.
+        * fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt: Added.
+        * fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden.html: Copied from LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page.html.
+        * fast/events/touch/gesture/touch-gesture-noscroll-body.html: Copied from LayoutTests/fast/events/touch/gesture/touch-gesture-scroll-page.html.
+        * fast/events/touch/gesture/touch-gesture-scroll-div-not-propagated.html:
+        * fast/events/touch/gesture/touch-gesture-scroll-div-propagated.html:
+        * fast/events/touch/gesture/touch-gesture-scroll-div-twice-propagated.html:
+        * fast/events/touch/gesture/touch-gesture-scroll-iframe-not-propagated.html:
+        * fast/events/touch/gesture/touch-gesture-scroll-iframe-propagated.html:
+        * fast/events/touch/gesture/touch-gesture-scroll-page-not-propagated.html:
+        * fast/events/touch/gesture/touch-gesture-scroll-page-propagated.html:
+        * fast/events/touch/gesture/touch-gesture-scroll-page.html:
+              I modified this layout test in order to add test coverage for another bug
+              which is fixed by this patch: if the hit test performed on a GestureScrollBegin
+              does not target a specific node, the subsequent GestureScrollUpdate events should
+              still attempt to scroll the page itself. This is consistent with how mousewheel
+              events behave.
+        * platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt: Added.
+        * platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt: Added.
+        * platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt: Added.
+        * platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt: Added.
+              These four new layout tests verify that a non-scrollable body will not scroll,
+              as reported in https://bugs.webkit.org/show_bug.cgi?id=109316.
+
 2013-03-01  Roger Fong  <roger_fong@apple.com>
 
                Unreviewed gardening of AppleWin port.
diff --git a/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt b/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt
new file mode 100644 (file)
index 0000000..0fbe3d2
--- /dev/null
@@ -0,0 +1,10 @@
+This tests that a page cannot be scrolled with touch if its body has style overflow:hidden.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+gesture events not implemented on this platform or gesture event scrolling of a document is broken
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt b/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt
new file mode 100644 (file)
index 0000000..ce87e48
--- /dev/null
@@ -0,0 +1,10 @@
+This tests that a page cannot be scrolled vertically with touch if its body has style overflow-y:hidden and the scroll event is propogated from a scrollable child div.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+gesture events not implemented on this platform or gesture event scrolling of a document is broken
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated.html b/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated.html
new file mode 100644 (file)
index 0000000..a8bbdee
--- /dev/null
@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../../../js/resources/js-test-style.css">
+<script src="../../../js/resources/js-test-pre.js"></script>
+<script src="resources/gesture-helpers.js"></script>
+<style type="text/css">
+#touchtarget {
+  width: 100px;
+  height: 100px;
+  background: white;
+  overflow:scroll;
+}
+
+::-webkit-scrollbar {
+    width: 0px;
+    height: 0px;
+}
+
+#greenbox {
+  width: 100px;
+  height: 100px;
+  background: green;
+  padding: 0px;
+  margin: 0px;
+}
+
+#redbox {
+  width: 100px;
+  height: 100px;
+  background: red;
+  padding: 0px;
+  margin: 0px;
+}
+
+td {
+  padding: 0px;
+}
+</style>
+</head>
+<body style="margin:0; overflow-y:hidden;" onload="runTest();">
+
+<div id="touchtarget">
+  <table border="0" cellspacing="0px" id="tablefoo">
+    <tr>
+      <td><div id="redbox"></div></td>
+      <td><div id="greenbox"></div></td>
+    </tr>
+    <tr>
+      <td><div id="greenbox"></div></td>
+      <td><div id="greenbox"></div></td>
+    </tr>
+  </table>
+</div>
+
+<table id="table_to_fill">
+    <tr><td><div id="greenbox"></div></td></tr>
+    <tr><td><div id="redbox"></div></td></tr>
+</table>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+
+var expectedGesturesTotal = 2;
+var gesturesOccurred = 0;
+var scrollAmountX = ['0', '0'];
+var scrollAmountY = ['0', '0'];
+var wheelEventsOccurred = 0;
+var expectedWheelEventsOccurred = ['0', '0'];
+var scrollEventsOccurred = 0;
+var expectedScrollEventsOccurred = '0';
+var scrolledElement = 'document.body'
+
+// Always construct a page larger than the vertical height of the window.
+function buildPage()
+{
+    var table = document.getElementById('table_to_fill');
+    var targetHeight = document.body.offsetHeight;
+    var cellPairHeight = table.offsetHeight;
+    var numberOfReps = targetHeight / cellPairHeight * 2;
+    var i;
+    for (i = 0; i < numberOfReps; i++) {
+        var p = document.createElement('tr');
+        p.innerHTML = '<td><div id="greenbox"></div></td>';
+        table.appendChild(p);
+        var p = document.createElement('tr');
+        p.innerHTML = '<td><div id="redbox"></div></td>';
+        table.appendChild(p);
+    }
+
+    window.addEventListener("scroll", recordScroll);
+    window.addEventListener("mousewheel", recordWheel);
+}
+
+function firstGestureScroll()
+{
+    debug("first gesture");
+    eventSender.gestureScrollBegin(95, 12);
+    eventSender.gestureScrollUpdate(0, -100);
+    eventSender.gestureScrollUpdate(0, -10);
+    eventSender.gestureScrollEnd(0, 0);
+
+    // Wait for layout.
+    checkScrollOffset();
+}
+
+function secondGestureScroll()
+{
+    debug("second gesture");
+    eventSender.gestureScrollBegin(12, 97);
+    eventSender.gestureScrollUpdate(0, -95);
+    eventSender.gestureScrollUpdate(0, -200);
+    eventSender.gestureScrollEnd(0, 0);
+
+    // Wait for layout.
+    checkScrollOffset();
+
+    // In this test we do not expect any scroll events to
+    // be received by the event listener, so we signal
+    // the end of the test by calling this function instead
+    // of relying on recordScroll() to do it.
+    finishTest();
+}
+
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+function runTest()
+{
+    buildPage();
+    if (window.eventSender) {
+        description('This tests that a page cannot be scrolled vertically with touch if its body has style overflow-y:hidden ' +
+                    'and the scroll event is propogated from a scrollable child div.');
+
+        if (checkTestDependencies())
+            firstGestureScroll();
+        else
+            exitIfNecessary();
+    } else {
+        debug("This test requires DumpRenderTree.  Touch scroll the red rect to log.");
+    }
+}
+
+function finishTest()
+{
+    if (window.eventSender) {
+        if (gesturesOccurred == expectedGesturesTotal) {
+            shouldBe('scrollEventsOccurred', expectedScrollEventsOccurred);
+            successfullyParsed = true;
+            isSuccessfullyParsed();
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+    }
+}
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt b/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt
new file mode 100644 (file)
index 0000000..5c9aa3b
--- /dev/null
@@ -0,0 +1,10 @@
+This tests that a page cannot be scrolled horizontally with touch (but can still be scrolled vertically) if its body has style overflow-x:hidden. The scroll events in this test have both an x and y component.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+gesture events not implemented on this platform or gesture event scrolling of a document is broken
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden.html b/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden.html
new file mode 100644 (file)
index 0000000..74bc84f
--- /dev/null
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../../../js/resources/js-test-style.css">
+<script src="../../../js/resources/js-test-pre.js"></script>
+<script src="resources/gesture-helpers.js"></script>
+<style type="text/css">
+#touchtarget {
+  width: 100px;
+  height: 100px;
+  background: white;
+  overflow:hidden;
+}
+
+::-webkit-scrollbar {
+    width: 0px;
+    height: 0px;
+}
+
+#greenbox {
+  width: 100px;
+  height: 100px;
+  background: green;
+  padding: 0px;
+  margin: 0px;
+}
+
+#redbox {
+  width: 100px;
+  height: 100px;
+  background: red;
+  padding: 0px;
+  margin: 0px;
+}
+
+td {
+  padding: 0px;
+}
+</style>
+</head>
+<body style="margin:0; overflow-x:hidden;" onload="runTest();">
+
+<table id="horizontal_table_to_fill">
+  <tr id="firstrow">
+    <td><div id="redbox"></div></td>
+    <td><div id="greenbox"></div></td>
+  </tr>
+</table>
+
+<table id="vertical_table_to_fill">
+    <tr><td><div id="greenbox"></div></td></tr>
+    <tr><td><div id="redbox"></div></td></tr>
+</table>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+
+var expectedGesturesTotal = 2;
+var gesturesOccurred = 0;
+var scrollAmountX = ['0', '0'];
+var scrollAmountY = ['110', '205'];
+var wheelEventsOccurred = 0;
+var expectedWheelEventsOccurred = ['0', '0'];
+var scrollEventsOccurred = 0;
+var expectedScrollEventsOccurred = '1';
+var scrolledElement = 'document.body'
+
+// Always construct a page larger than the vertical height of the window.
+function buildPage()
+{
+    // build vertical table
+    var table = document.getElementById('vertical_table_to_fill');
+    var targetHeight = document.body.offsetHeight;
+    var cellPairHeight = table.offsetHeight;
+    var numberOfReps = targetHeight / cellPairHeight * 2;
+    var i;
+    for (i = 0; i < numberOfReps; i++) {
+        var p = document.createElement('tr');
+        p.innerHTML = '<td><div id="greenbox"></div></td>';
+        table.appendChild(p);
+        var p = document.createElement('tr');
+        p.innerHTML = '<td><div id="redbox"></div></td>';
+        table.appendChild(p);
+    }
+
+    // build horizontal table
+    var horizontalTable = document.getElementById('horizontal_table_to_fill');
+    var tableRow = document.getElementById('firstrow');
+    var targetWidth = document.body.offsetWidth;
+    var cellPairWidth = horizontalTable.offsetWidth;
+    numberOfReps = targetWidth / cellPairWidth * 2;
+    for (i = 0; i < numberOfReps; i++) {
+        var p = document.createElement('td');
+        p.innerHTML = '<div id="redbox"></div>';
+        tableRow.appendChild(p);
+        var p = document.createElement('td');
+        p.innerHTML = '<div id="greenbox"></div>';
+        tableRow.appendChild(p);
+    }
+
+    window.addEventListener("scroll", recordScroll);
+    window.addEventListener("mousewheel", recordWheel);
+}
+
+function firstGestureScroll()
+{
+    debug("first gesture");
+    eventSender.gestureScrollBegin(95, 12);
+    eventSender.gestureScrollUpdate(-55, -110);
+    eventSender.gestureScrollEnd(0, 0);
+
+    // Wait for layout.
+    checkScrollOffset();
+}
+
+function secondGestureScroll()
+{
+    debug("second gesture");
+    eventSender.gestureScrollBegin(12, 97);
+    eventSender.gestureScrollUpdate(-42, -95);
+    eventSender.gestureScrollEnd(0, 0);
+
+    // Wait for layout.
+    checkScrollOffset();
+}
+
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+function runTest()
+{
+    buildPage();
+    if (window.eventSender) {
+        description('This tests that a page cannot be scrolled horizontally with touch ' +
+                    '(but can still be scrolled vertically) if its body has style overflow-x:hidden. ' +
+                    'The scroll events in this test have both an x and y component.');
+
+        if (checkTestDependencies())
+            firstGestureScroll();
+        else
+            exitIfNecessary();
+    } else {
+        debug("This test requires DumpRenderTree.  Touch scroll the red rect to log.");
+    }
+}
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt b/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt
new file mode 100644 (file)
index 0000000..79892ba
--- /dev/null
@@ -0,0 +1,10 @@
+This tests that a page cannot be scrolled vertically with touch (but can still be scrolled horizontally) if its body has style overflow-y:hidden. The scroll events in this test have both an x and y component.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+gesture events not implemented on this platform or gesture event scrolling of a document is broken
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden.html b/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden.html
new file mode 100644 (file)
index 0000000..fadc86a
--- /dev/null
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../../../js/resources/js-test-style.css">
+<script src="../../../js/resources/js-test-pre.js"></script>
+<script src="resources/gesture-helpers.js"></script>
+<style type="text/css">
+#touchtarget {
+  width: 100px;
+  height: 100px;
+  background: white;
+  overflow:hidden;
+}
+
+::-webkit-scrollbar {
+    width: 0px;
+    height: 0px;
+}
+
+#greenbox {
+  width: 100px;
+  height: 100px;
+  background: green;
+  padding: 0px;
+  margin: 0px;
+}
+
+#redbox {
+  width: 100px;
+  height: 100px;
+  background: red;
+  padding: 0px;
+  margin: 0px;
+}
+
+td {
+  padding: 0px;
+}
+</style>
+</head>
+<body style="margin:0; overflow-y:hidden;" onload="runTest();">
+
+<table id="horizontal_table_to_fill">
+  <tr id="firstrow">
+    <td><div id="redbox"></div></td>
+    <td><div id="greenbox"></div></td>
+  </tr>
+</table>
+
+<table id="vertical_table_to_fill">
+    <tr><td><div id="greenbox"></div></td></tr>
+    <tr><td><div id="redbox"></div></td></tr>
+</table>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+
+var expectedGesturesTotal = 2;
+var gesturesOccurred = 0;
+var scrollAmountX = ['55', '97'];
+var scrollAmountY = ['0', '0'];
+var wheelEventsOccurred = 0;
+var expectedWheelEventsOccurred = ['0', '0'];
+var scrollEventsOccurred = 0;
+var expectedScrollEventsOccurred = '1';
+var scrolledElement = 'document.body'
+
+// Always construct a page larger than the vertical height of the window.
+function buildPage()
+{
+    // build vertical table
+    var table = document.getElementById('vertical_table_to_fill');
+    var targetHeight = document.body.offsetHeight;
+    var cellPairHeight = table.offsetHeight;
+    var numberOfReps = targetHeight / cellPairHeight * 2;
+    var i;
+    for (i = 0; i < numberOfReps; i++) {
+        var p = document.createElement('tr');
+        p.innerHTML = '<td><div id="greenbox"></div></td>';
+        table.appendChild(p);
+        var p = document.createElement('tr');
+        p.innerHTML = '<td><div id="redbox"></div></td>';
+        table.appendChild(p);
+    }
+
+    // build horizontal table
+    var horizontalTable = document.getElementById('horizontal_table_to_fill');
+    var tableRow = document.getElementById('firstrow');
+    var targetWidth = document.body.offsetWidth;
+    var cellPairWidth = horizontalTable.offsetWidth;
+    numberOfReps = targetWidth / cellPairWidth * 2;
+    for (i = 0; i < numberOfReps; i++) {
+        var p = document.createElement('td');
+        p.innerHTML = '<div id="redbox"></div>';
+        tableRow.appendChild(p);
+        var p = document.createElement('td');
+        p.innerHTML = '<div id="greenbox"></div>';
+        tableRow.appendChild(p);
+    }
+
+    window.addEventListener("scroll", recordScroll);
+    window.addEventListener("mousewheel", recordWheel);
+}
+
+function firstGestureScroll()
+{
+    debug("first gesture");
+    eventSender.gestureScrollBegin(195, 12);
+    eventSender.gestureScrollUpdate(-55, -110);
+    eventSender.gestureScrollEnd(0, 0);
+
+    // Wait for layout.
+    checkScrollOffset();
+}
+
+function secondGestureScroll()
+{
+    debug("second gesture");
+    eventSender.gestureScrollBegin(120, 255);
+    eventSender.gestureScrollUpdate(-42, -95);
+    eventSender.gestureScrollEnd(0, 0);
+
+    // Wait for layout.
+    checkScrollOffset();
+}
+
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+function runTest()
+{
+    buildPage();
+    if (window.eventSender) {
+        description('This tests that a page cannot be scrolled vertically with touch ' +
+                    '(but can still be scrolled horizontally) if its body has style overflow-y:hidden. ' +
+                    'The scroll events in this test have both an x and y component.');
+
+        if (checkTestDependencies())
+            firstGestureScroll();
+        else
+            exitIfNecessary();
+    } else {
+        debug("This test requires DumpRenderTree.  Touch scroll the red rect to log.");
+    }
+}
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body.html b/LayoutTests/fast/events/touch/gesture/touch-gesture-noscroll-body.html
new file mode 100644 (file)
index 0000000..85b5e48
--- /dev/null
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../../../js/resources/js-test-style.css">
+<script src="../../../js/resources/js-test-pre.js"></script>
+<script src="resources/gesture-helpers.js"></script>
+<style type="text/css">
+#touchtarget {
+  width: 100px;
+  height: 100px;
+  background: white;
+  overflow:hidden;
+}
+
+::-webkit-scrollbar {
+    width: 0px;
+    height: 0px;
+}
+
+#greenbox {
+  width: 100px;
+  height: 100px;
+  background: green;
+  padding: 0px;
+  margin: 0px;
+}
+
+#redbox {
+  width: 100px;
+  height: 100px;
+  background: red;
+  padding: 0px;
+  margin: 0px;
+}
+
+td {
+  padding: 0px;
+}
+</style>
+</head>
+<body style="margin:0; overflow:hidden;" onload="runTest();">
+
+<table id="horizontal_table_to_fill">
+  <tr id="firstrow">
+    <td><div id="redbox"></div></td>
+    <td><div id="greenbox"></div></td>
+  </tr>
+</table>
+
+<table id="vertical_table_to_fill">
+    <tr><td><div id="greenbox"></div></td></tr>
+    <tr><td><div id="redbox"></div></td></tr>
+</table>
+
+<p id="description"></p>
+<div id="console"></div>
+<script type="text/javascript">
+
+var expectedGesturesTotal = 2;
+var gesturesOccurred = 0;
+var scrollAmountX = ['0', '0'];
+var scrollAmountY = ['0', '0'];
+var wheelEventsOccurred = 0;
+var expectedWheelEventsOccurred = ['0', '0'];
+var scrollEventsOccurred = 0;
+var expectedScrollEventsOccurred = '0';
+var scrolledElement = 'document.body'
+
+// Always construct a page larger than the vertical height of the window.
+function buildPage()
+{
+    // build vertical table
+    var table = document.getElementById('vertical_table_to_fill');
+    var targetHeight = document.body.offsetHeight;
+    var cellPairHeight = table.offsetHeight;
+    var numberOfReps = targetHeight / cellPairHeight * 2;
+    var i;
+    for (i = 0; i < numberOfReps; i++) {
+        var p = document.createElement('tr');
+        p.innerHTML = '<td><div id="greenbox"></div></td>';
+        table.appendChild(p);
+        var p = document.createElement('tr');
+        p.innerHTML = '<td><div id="redbox"></div></td>';
+        table.appendChild(p);
+    }
+
+    // build horizontal table
+    var horizontalTable = document.getElementById('horizontal_table_to_fill');
+    var tableRow = document.getElementById('firstrow');
+    var targetWidth = document.body.offsetWidth;
+    var cellPairWidth = horizontalTable.offsetWidth;
+    numberOfReps = targetWidth / cellPairWidth * 2;
+    for (i = 0; i < numberOfReps; i++) {
+        var p = document.createElement('td');
+        p.innerHTML = '<div id="redbox"></div>';
+        tableRow.appendChild(p);
+        var p = document.createElement('td');
+        p.innerHTML = '<div id="greenbox"></div>';
+        tableRow.appendChild(p);
+    }
+
+    window.addEventListener("scroll", recordScroll);
+    window.addEventListener("mousewheel", recordWheel);
+}
+
+function firstGestureScroll()
+{
+    debug("first gesture");
+    eventSender.gestureScrollBegin(95, 12);
+    eventSender.gestureScrollUpdate(-55, -110);
+    eventSender.gestureScrollEnd(0, 0);
+
+    // Wait for layout.
+    checkScrollOffset();
+}
+
+function secondGestureScroll()
+{
+    debug("second gesture");
+    eventSender.gestureScrollBegin(12, 97);
+    eventSender.gestureScrollUpdate(-42, -95);
+    eventSender.gestureScrollEnd(0, 0);
+
+    // Wait for layout.
+    checkScrollOffset();
+
+    // In this test we do not expect any scroll events to
+    // be received by the event listener, so we signal
+    // the end of the test by calling this function instead
+    // of relying on recordScroll() to do it.
+    finishTest();
+}
+
+if (window.testRunner)
+    testRunner.waitUntilDone();
+
+function runTest()
+{
+    buildPage();
+    if (window.eventSender) {
+        description('This tests that a page cannot be scrolled with touch if its body has style overflow:hidden.');
+
+        if (checkTestDependencies())
+            firstGestureScroll();
+        else
+            exitIfNecessary();
+    } else {
+        debug("This test requires DumpRenderTree.  Touch scroll the red rect to log.");
+    }
+}
+
+function finishTest()
+{
+    if (window.eventSender) {
+        if (gesturesOccurred == expectedGesturesTotal) {
+            shouldBe('scrollEventsOccurred', expectedScrollEventsOccurred);
+            successfullyParsed = true;
+            isSuccessfullyParsed();
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }
+    }
+}
+</script>
+</body>
+</html>
index 2801409..d0c5d50 100644 (file)
@@ -92,25 +92,6 @@ var scrolledElement = 'movedbox'
 var scrollEventsOccurred = 0;
 var expectedScrollEventsOccurred = '1';
 
-
-function recordScroll(event) {
-       debug('scroll event ' + scrollEventsOccurred + '+> ' + event.target);
-       scrollEventsOccurred++;
-
-       if (window.eventSender) {
-               // Because scroll events arrive asynchronously, only one will arrive.
-           if (gesturesOccurred == expectedGesturesTotal) {
-                       shouldBe('scrollEventsOccurred', expectedScrollEventsOccurred);
-               // If we've got here, we've passed.
-               successfullyParsed = true;
-               isSuccessfullyParsed();
-               if (window.testRunner)
-                   testRunner.notifyDone();
-               }
-    }
-}
-
-
 function firstGestureScroll()
 {
     debug("first gesture");
@@ -126,7 +107,8 @@ function secondGestureScroll()
 {
     debug("second gesture");
     eventSender.gestureScrollBegin(12, 40);
-    eventSender.gestureScrollUpdateWithoutPropagation(0, -60);
+    eventSender.gestureScrollUpdateWithoutPropagation(0, -50);
+    eventSender.gestureScrollUpdateWithoutPropagation(0, -10);
     eventSender.gestureScrollEnd(0, 0);
 
     // Wait for layout.
index 343e15f..9976985 100644 (file)
@@ -92,25 +92,6 @@ var scrolledElement = 'movedbox'
 var scrollEventsOccurred = 0;
 var expectedScrollEventsOccurred = '1';
 
-
-function recordScroll(event) {
-       debug('scroll event ' + scrollEventsOccurred + '+> ' + event.target);
-       scrollEventsOccurred++;
-
-       if (window.eventSender) {
-               // Because scroll events arrive asynchronously, only one will arrive.
-           if (gesturesOccurred == expectedGesturesTotal) {
-                       shouldBe('scrollEventsOccurred', expectedScrollEventsOccurred);
-               // If we've got here, we've passed.
-               successfullyParsed = true;
-               isSuccessfullyParsed();
-               if (window.testRunner)
-                   testRunner.notifyDone();
-               }
-    }
-}
-
-
 function firstGestureScroll()
 {
     debug("first gesture");
@@ -126,7 +107,8 @@ function secondGestureScroll()
 {
     debug("second gesture");
     eventSender.gestureScrollBegin(12, 40);
-    eventSender.gestureScrollUpdate(0, -60);
+    eventSender.gestureScrollUpdate(0, -50);
+    eventSender.gestureScrollUpdate(0, -10);
     eventSender.gestureScrollEnd(0, 0);
 
     // Wait for layout.
index 8f651d4..1b6e61e 100644 (file)
@@ -116,30 +116,12 @@ var scrolledElement = 'movedbox'
 var scrollEventsOccurred = 0;
 var expectedScrollEventsOccurred = '1';
 
-
-function recordScroll(event) {
-       debug('scroll event ' + scrollEventsOccurred + '+> ' + event.target);
-       scrollEventsOccurred++;
-
-       if (window.eventSender) {
-               // Because scroll events arrive asynchronously, only one will arrive.
-           if (gesturesOccurred == expectedGesturesTotal) {
-                       shouldBe('scrollEventsOccurred', expectedScrollEventsOccurred);
-               // If we've got here, we've passed.
-               successfullyParsed = true;
-               isSuccessfullyParsed();
-               if (window.testRunner)
-                   testRunner.notifyDone();
-               }
-    }
-}
-
-
 function firstGestureScroll()
 {
     debug("first gesture");
     eventSender.gestureScrollBegin(10, 72);
-    eventSender.gestureScrollUpdate(0, -230);
+    eventSender.gestureScrollUpdate(0, -200);
+    eventSender.gestureScrollUpdate(0, -30);
     eventSender.gestureScrollEnd(0, 0);
 
     // Wait for layout.
@@ -150,7 +132,8 @@ function secondGestureScroll()
 {
     debug("second gesture");
     eventSender.gestureScrollBegin(12, 40);
-    eventSender.gestureScrollUpdate(0, -45);
+    eventSender.gestureScrollUpdate(0, -20);
+    eventSender.gestureScrollUpdate(0, -25);
     eventSender.gestureScrollEnd(0, 0);
 
     // Wait for layout.
index a6d9f22..a99c265 100644 (file)
@@ -71,25 +71,6 @@ var scrolledElement = 'movedbox'
 var scrollEventsOccurred = 0;
 var expectedScrollEventsOccurred = '1';
 
-
-function recordScroll(event) {
-       debug('scroll event ' + scrollEventsOccurred + '+> ' + event.target);
-       scrollEventsOccurred++;
-
-       if (window.eventSender) {
-               // Because scroll events arrive asynchronously, only one will arrive.
-           if (gesturesOccurred == expectedGesturesTotal) {
-                       shouldBe('scrollEventsOccurred', expectedScrollEventsOccurred);
-               // If we've got here, we've passed.
-               successfullyParsed = true;
-               isSuccessfullyParsed();
-               if (window.testRunner)
-                   testRunner.notifyDone();
-               }
-    }
-}
-
-
 function firstGestureScroll()
 {
     debug("first gesture");
@@ -105,7 +86,8 @@ function secondGestureScroll()
 {
     debug("second gesture");
     eventSender.gestureScrollBegin(12, 40);
-    eventSender.gestureScrollUpdateWithoutPropagation(0, -100);
+    eventSender.gestureScrollUpdateWithoutPropagation(0, -10);
+    eventSender.gestureScrollUpdateWithoutPropagation(0, -50);
     eventSender.gestureScrollEnd(0, 0);
 
     // Wait for layout.
index 1a3b5ad..d3c0af4 100644 (file)
@@ -71,25 +71,6 @@ var scrolledElement = 'movedbox'
 var scrollEventsOccurred = 0;
 var expectedScrollEventsOccurred = '1';
 
-
-function recordScroll(event) {
-       debug('scroll event ' + scrollEventsOccurred + '+> ' + event.target);
-       scrollEventsOccurred++;
-
-       if (window.eventSender) {
-               // Because scroll events arrive asynchronously, only one will arrive.
-           if (gesturesOccurred == expectedGesturesTotal) {
-                       shouldBe('scrollEventsOccurred', expectedScrollEventsOccurred);
-               // If we've got here, we've passed.
-               successfullyParsed = true;
-               isSuccessfullyParsed();
-               if (window.testRunner)
-                   testRunner.notifyDone();
-               }
-    }
-}
-
-
 function firstGestureScroll()
 {
     debug("first gesture");
@@ -105,7 +86,8 @@ function secondGestureScroll()
 {
     debug("second gesture");
     eventSender.gestureScrollBegin(12, 40);
-    eventSender.gestureScrollUpdate(0, -100);
+    eventSender.gestureScrollUpdate(0, -10);
+    eventSender.gestureScrollUpdate(0, -50);
     eventSender.gestureScrollEnd(0, 0);
 
     // Wait for layout.
index b385245..46d836c 100644 (file)
@@ -86,23 +86,6 @@ var scrolledElement = 'document.body'
 var scrollEventsOccurred = 0;
 var expectedScrollEventsOccurred = '1';
 
-function recordScroll(event) {
-       debug('scroll event ' + scrollEventsOccurred + '+> ' + event.target);
-       scrollEventsOccurred++;
-
-       if (window.eventSender) {
-               // Because scroll events arrive asynchronously, only one will arrive.
-           if (gesturesOccurred == expectedGesturesTotal) {
-                       shouldBe('scrollEventsOccurred', expectedScrollEventsOccurred);
-               // If we've got here, we've passed.
-               successfullyParsed = true;
-               isSuccessfullyParsed();
-               if (window.testRunner)
-                   testRunner.notifyDone();
-               }
-    }
-}
-
 // Always construct a page larger than the vertical height of the window.
 function buildPage()
 {
@@ -136,7 +119,8 @@ function secondGestureScroll()
 {
     debug("second gesture");
     eventSender.gestureScrollBegin(12, 40);
-    eventSender.gestureScrollUpdateWithoutPropagation(0, -250);
+    eventSender.gestureScrollUpdateWithoutPropagation(0, -200);
+    eventSender.gestureScrollUpdateWithoutPropagation(0, -160);
     eventSender.gestureScrollEnd(0, 0);
 
     // Wait for layout.
index 093095c..daa4567 100644 (file)
@@ -86,23 +86,6 @@ var scrolledElement = 'document.body'
 var scrollEventsOccurred = 0;
 var expectedScrollEventsOccurred = '1';
 
-function recordScroll(event) {
-       debug('scroll event ' + scrollEventsOccurred + '+> ' + event.target);
-       scrollEventsOccurred++;
-
-       if (window.eventSender) {
-               // Because scroll events arrive asynchronously, only one will arrive.
-           if (gesturesOccurred == expectedGesturesTotal) {
-                       shouldBe('scrollEventsOccurred', expectedScrollEventsOccurred);
-               // If we've got here, we've passed.
-               successfullyParsed = true;
-               isSuccessfullyParsed();
-               if (window.testRunner)
-                   testRunner.notifyDone();
-               }
-    }
-}
-
 // Always construct a page larger than the vertical height of the window.
 function buildPage()
 {
@@ -136,7 +119,8 @@ function secondGestureScroll()
 {
     debug("second gesture");
     eventSender.gestureScrollBegin(12, 40);
-    eventSender.gestureScrollUpdate(0, -250);
+    eventSender.gestureScrollUpdate(0, -200);
+    eventSender.gestureScrollUpdate(0, -160);
     eventSender.gestureScrollEnd(0, 0);
 
     // Wait for layout.
index 4e60e5c..f935432 100644 (file)
@@ -1,4 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<!DOCTYPE html>
 <html>
 <head>
 <link rel="stylesheet" href="../../../js/resources/js-test-style.css">
@@ -105,7 +105,7 @@ function firstGestureScroll()
 function secondGestureScroll()
 {
     debug("second gesture");
-    eventSender.gestureScrollBegin(12, 40);
+    eventSender.gestureScrollBegin(800, 40);
     eventSender.gestureScrollUpdate(0, -30);
     eventSender.gestureScrollUpdate(0, -30);
     eventSender.gestureScrollEnd(0, 0);
diff --git a/LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt b/LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-expected.txt
new file mode 100644 (file)
index 0000000..54caf9a
--- /dev/null
@@ -0,0 +1,18 @@
+This tests that a page cannot be scrolled with touch if its body has style overflow:hidden.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+first gesture
+PASS document.body.scrollTop is 0
+PASS document.body.scrollLeft is 0
+PASS wheelEventsOccurred is 0
+second gesture
+PASS document.body.scrollTop is 0
+PASS document.body.scrollLeft is 0
+PASS wheelEventsOccurred is 0
+PASS scrollEventsOccurred is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt b/LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-propagated-expected.txt
new file mode 100644 (file)
index 0000000..df237a5
--- /dev/null
@@ -0,0 +1,18 @@
+This tests that a page cannot be scrolled vertically with touch if its body has style overflow-y:hidden and the scroll event is propogated from a scrollable child div.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+first gesture
+PASS document.body.scrollTop is 0
+PASS document.body.scrollLeft is 0
+PASS wheelEventsOccurred is 0
+second gesture
+PASS document.body.scrollTop is 0
+PASS document.body.scrollLeft is 0
+PASS wheelEventsOccurred is 0
+PASS scrollEventsOccurred is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt b/LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden-expected.txt
new file mode 100644 (file)
index 0000000..dc27762
--- /dev/null
@@ -0,0 +1,19 @@
+This tests that a page cannot be scrolled horizontally with touch (but can still be scrolled vertically) if its body has style overflow-x:hidden. The scroll events in this test have both an x and y component.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+first gesture
+PASS document.body.scrollTop is 110
+PASS document.body.scrollLeft is 0
+PASS wheelEventsOccurred is 0
+second gesture
+PASS document.body.scrollTop is 205
+PASS document.body.scrollLeft is 0
+PASS wheelEventsOccurred is 0
+scroll event 0+> [object HTMLDocument]
+PASS scrollEventsOccurred is 1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt b/LayoutTests/platform/chromium/fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden-expected.txt
new file mode 100644 (file)
index 0000000..689a1d7
--- /dev/null
@@ -0,0 +1,19 @@
+This tests that a page cannot be scrolled vertically with touch (but can still be scrolled horizontally) if its body has style overflow-y:hidden. The scroll events in this test have both an x and y component.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+first gesture
+PASS document.body.scrollTop is 0
+PASS document.body.scrollLeft is 55
+PASS wheelEventsOccurred is 0
+second gesture
+PASS document.body.scrollTop is 0
+PASS document.body.scrollLeft is 97
+PASS wheelEventsOccurred is 0
+scroll event 0+> [object HTMLDocument]
+PASS scrollEventsOccurred is 1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
index 8df43a6..14522cc 100644 (file)
@@ -1,3 +1,40 @@
+2013-03-01  Terry Anderson  <tdanderson@chromium.org>
+
+        EventHandler::handleGestureScrollUpdate() should invoke the user-generated scroll routines 
+        so its behavior matches other user-initiated scrolls
+        https://bugs.webkit.org/show_bug.cgi?id=109769
+
+        Reviewed by James Robinson.
+
+        To ensure that the scrolling behavior of GestureScrollUpdate events are consistent with
+        the scrolling behavior of mousewheel events, use the existing user-generated scroll logic
+        instead of calling into RenderLayer::scrollByRecursively(). This patch fixes the bug
+        reported in https://bugs.webkit.org/show_bug.cgi?id=109316, where the example page can
+        be scrolled using touch but cannot be scrolled using mousewheels.
+
+        Note that this patch does not use any of the mousewheel event-handling code.
+
+        Tests: fast/events/touch/gesture/touch-gesture-noscroll-body-propagated.html
+               fast/events/touch/gesture/touch-gesture-noscroll-body-xhidden.html
+               fast/events/touch/gesture/touch-gesture-noscroll-body-yhidden.html
+               fast/events/touch/gesture/touch-gesture-noscroll-body.html
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::clear):
+        (WebCore::EventHandler::handleGestureEvent):
+        (WebCore::EventHandler::handleGestureScrollBegin):
+        (WebCore::EventHandler::handleGestureScrollUpdate):
+        (WebCore::EventHandler::sendScrollEventToView):
+            By calling this function at the start of handleGestureScrollUpdate() in the case
+            where |m_scrollGestureHandlingNode| is null, we ensure that the scroll updates
+            can still scroll the page itself, if possible.
+        (WebCore):
+        (WebCore::EventHandler::clearGestureScrollNodes):
+        * page/EventHandler.h:
+        (EventHandler):
+        * platform/PlatformWheelEvent.h:
+        (WebCore::PlatformWheelEvent::setHasPreciseScrollingDeltas):
+
 2013-03-01  Alec Flett  <alecflett@chromium.org>
 
         IndexedDB: Avoid ScriptValue copies in IDBAny
index 6c15ac4..0ffcba8 100644 (file)
@@ -403,6 +403,7 @@ void EventHandler::clear()
 #if ENABLE(GESTURE_EVENTS)
     m_scrollGestureHandlingNode = 0;
     m_lastHitTestResultOverWidget = false;
+    m_previousGestureScrolledNode = 0;
     m_scrollbarHandlingScrollGesture = 0;
 #endif
     m_maxMouseMovedDuration = 0;
@@ -2476,6 +2477,9 @@ bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
     case PlatformEvent::GestureScrollUpdate:
     case PlatformEvent::GestureScrollUpdateWithoutPropagation:
         return handleGestureScrollUpdate(gestureEvent);
+    case PlatformEvent::GestureScrollEnd:
+        clearGestureScrollNodes(); 
+        return true;
     case PlatformEvent::GestureTap:
         return handleGestureTap(gestureEvent);
     case PlatformEvent::GestureTapDown:
@@ -2486,7 +2490,6 @@ bool EventHandler::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
         return handleGestureLongTap(gestureEvent);
     case PlatformEvent::GestureTwoFingerTap:
         return handleGestureTwoFingerTap(gestureEvent);
-    case PlatformEvent::GestureScrollEnd:
     case PlatformEvent::GestureDoubleTap:
     case PlatformEvent::GesturePinchBegin:
     case PlatformEvent::GesturePinchEnd:
@@ -2614,19 +2617,6 @@ bool EventHandler::passGestureEventToWidgetIfPossible(const PlatformGestureEvent
     return false;
 }
 
-static const Node* closestScrollableNodeCandidate(const Node* node)
-{
-    for (EventPathWalker walker(node); walker.node(); walker.moveToParent()) {
-        Node* scrollableNode = walker.node();
-        if (scrollableNode->isDocumentNode())
-            return scrollableNode;
-        RenderObject* renderer = scrollableNode->renderer();
-        if (renderer && renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea())
-            return scrollableNode;
-    }
-    return node;
-}
-
 bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureEvent)
 {
     Document* document = m_frame->document();
@@ -2645,6 +2635,7 @@ bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureE
 
     m_lastHitTestResultOverWidget = result.isOverWidget(); 
     m_scrollGestureHandlingNode = result.innerNode();
+    m_previousGestureScrolledNode = 0;
 
     Node* node = m_scrollGestureHandlingNode.get();
     if (node)
@@ -2655,48 +2646,79 @@ bool EventHandler::handleGestureScrollBegin(const PlatformGestureEvent& gestureE
 
 bool EventHandler::handleGestureScrollUpdate(const PlatformGestureEvent& gestureEvent)
 {
-    // Ignore this event if we don't already have a targeted node with a valid renderer.
-    const Node* node = m_scrollGestureHandlingNode.get();
-    if (!node)
+    FloatSize delta(gestureEvent.deltaX(), gestureEvent.deltaY());
+    if (delta.isZero())
         return false;
 
-    RenderObject* latchedRenderer = node->renderer();
-    if (!latchedRenderer)
-        return false;
+    const float scaleFactor = m_frame->pageZoomFactor() * m_frame->frameScaleFactor();
+    delta.scale(1 / scaleFactor, 1 / scaleFactor);
 
-    IntSize delta(-gestureEvent.deltaX(), -gestureEvent.deltaY());
-    if (delta.isZero())
+    Node* node = m_scrollGestureHandlingNode.get();
+    if (!node)
+        return sendScrollEventToView(gestureEvent, delta);
+
+    // Ignore this event if the targeted node does not have a valid renderer.
+    RenderObject* renderer = node->renderer();
+    if (!renderer)
         return false;
 
     RefPtr<FrameView> protector(m_frame->view());
 
     // Try to send the event to the correct view.
-    if (passGestureEventToWidgetIfPossible(gestureEvent, latchedRenderer))
+    if (passGestureEventToWidgetIfPossible(gestureEvent, renderer))
         return true;
 
-    // Otherwise if this is the correct view for the event, find the closest scrollable
-    // ancestor of the targeted node and scroll the layer that contains this node's renderer.
-    node = closestScrollableNodeCandidate(node);
-    if (!node)
-        return false;
+    Node* stopNode = 0;
+    bool scrollShouldNotPropagate = gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation;
+    if (scrollShouldNotPropagate)
+        stopNode = m_previousGestureScrolledNode.get();
 
-    latchedRenderer = node->renderer();
-    if (!latchedRenderer)
-        return false;
+    // First try to scroll the closest scrollable RenderBox ancestor of |node|.
+    ScrollGranularity granularity = ScrollByPixel; 
+    bool horizontalScroll = scrollNode(delta.width(), granularity, ScrollLeft, ScrollRight, node, &stopNode);
+    bool verticalScroll = scrollNode(delta.height(), granularity, ScrollUp, ScrollDown, node, &stopNode);
 
-    RenderLayer::ScrollPropagation shouldPropagate = RenderLayer::ShouldPropagateScroll;
-    if (gestureEvent.type() == PlatformEvent::GestureScrollUpdateWithoutPropagation)
-        shouldPropagate = RenderLayer::DontPropagateScroll;
+    if (scrollShouldNotPropagate)
+        m_previousGestureScrolledNode = stopNode;
 
-    const float scaleFactor = m_frame->pageZoomFactor() * m_frame->frameScaleFactor();
-    delta.scale(1 / scaleFactor, 1 / scaleFactor);
+    if (horizontalScroll || verticalScroll) {
+        setFrameWasScrolledByUser();
+        return true;
+    }
 
-    bool result = latchedRenderer->enclosingLayer()->scrollBy(delta, RenderLayer::ScrollOffsetClamped, shouldPropagate);
+    // Otherwise try to scroll the view.
+    return sendScrollEventToView(gestureEvent, delta);
+}
 
-    if (result)
+bool EventHandler::sendScrollEventToView(const PlatformGestureEvent& gestureEvent, const FloatSize& scaledDelta)
+{
+    FrameView* view = m_frame->view();
+    if (!view)
+        return false;
+
+    const float tickDivisor = static_cast<float>(WheelEvent::TickMultiplier);
+    IntPoint point(gestureEvent.position().x(), gestureEvent.position().y());
+    IntPoint globalPoint(gestureEvent.globalPosition().x(), gestureEvent.globalPosition().y());
+    PlatformWheelEvent syntheticWheelEvent(point, globalPoint,
+        scaledDelta.width(), scaledDelta.height(), 
+        scaledDelta.width() / tickDivisor, scaledDelta.height() / tickDivisor,
+        ScrollByPixelWheelEvent,
+        gestureEvent.shiftKey(), gestureEvent.ctrlKey(), gestureEvent.altKey(), gestureEvent.metaKey());
+#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
+    syntheticWheelEvent.setHasPreciseScrollingDeltas(true);
+#endif
+
+    bool scrolledFrame = view->wheelEvent(syntheticWheelEvent);
+    if (scrolledFrame)
         setFrameWasScrolledByUser();
 
-    return result;
+    return scrolledFrame;
+}
+
+void EventHandler::clearGestureScrollNodes()
+{
+    m_scrollGestureHandlingNode = 0;
+    m_previousGestureScrolledNode = 0;
 }
 
 bool EventHandler::isScrollbarHandlingGestures() const
index 3fc07f2..ee8daac 100644 (file)
@@ -181,6 +181,7 @@ public:
     bool handleGestureTwoFingerTap(const PlatformGestureEvent&);
     bool handleGestureScrollUpdate(const PlatformGestureEvent&);
     bool handleGestureScrollBegin(const PlatformGestureEvent&);
+    void clearGestureScrollNodes();
     bool isScrollbarHandlingGestures() const;
 #endif
 
@@ -378,6 +379,7 @@ private:
     bool handleGestureForTextSelectionOrContextMenu(const PlatformGestureEvent&);
     bool passGestureEventToWidget(const PlatformGestureEvent&, Widget*);
     bool passGestureEventToWidgetIfPossible(const PlatformGestureEvent&, RenderObject*);
+    bool sendScrollEventToView(const PlatformGestureEvent&, const FloatSize&);
 #endif
 
     void setLastKnownMousePosition(const PlatformMouseEvent&);
@@ -469,6 +471,7 @@ private:
 #if ENABLE(GESTURE_EVENTS)
     RefPtr<Node> m_scrollGestureHandlingNode;
     bool m_lastHitTestResultOverWidget;
+    RefPtr<Node> m_previousGestureScrolledNode;
     RefPtr<Scrollbar> m_scrollbarHandlingScrollGesture;
 #endif
 
index 8c0302c..5af2974 100644 (file)
@@ -157,6 +157,7 @@ namespace WebCore {
 
 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
         bool hasPreciseScrollingDeltas() const { return m_hasPreciseScrollingDeltas; }
+        void setHasPreciseScrollingDeltas(bool b) { m_hasPreciseScrollingDeltas = b; }
 #endif
 #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN))
         PlatformWheelEventPhase phase() const { return m_phase; }
index 71a902e..cc5c28d 100644 (file)
@@ -1,3 +1,16 @@
+2013-03-01  Terry Anderson  <tdanderson@chromium.org>
+
+        EventHandler::handleGestureScrollUpdate() should invoke the user-generated scroll routines 
+        so its behavior matches other user-initiated scrolls
+        https://bugs.webkit.org/show_bug.cgi?id=109769
+
+        Reviewed by James Robinson.
+
+        Clear the nodes corresponding to a fling scroll event when the event ends.
+
+        * src/WebViewImpl.cpp:
+        (WebKit::WebViewImpl::updateAnimations):
+
 2013-03-01  David Dorwin  <ddorwin@chromium.org>
 
         [chromium] Revert r143827 to restore WebHelperPluginImpl's call to frameDetached()
index 4e13a1e..6d227e9 100644 (file)
@@ -1846,6 +1846,8 @@ void WebViewImpl::updateAnimations(double monotonicFrameBeginTime)
             m_gestureAnimation.clear();
             if (m_layerTreeView)
                 m_layerTreeView->didStopFlinging();
+
+            mainFrameImpl()->frame()->eventHandler()->clearGestureScrollNodes();
         }
     }