Dragging over an element with scrollbars should scroll the element when dragging...
authoryosin@chromium.org <yosin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 21 Jan 2013 01:29:07 +0000 (01:29 +0000)
committeryosin@chromium.org <yosin@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 21 Jan 2013 01:29:07 +0000 (01:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=39725

Reviewed by Hajime Morita.

Source/WebCore:

This patch introduces auto scrolling functionality during drag-and-drop
when drop source is near edge of scrollable element.

When drop source is inside 20px of scrollable element more than 200ms,
scrollable element is automatically scrolled every 50ms toward drop
source position, e.g. vertically scroll up when drop source is in top
edge.

Test: fast/events/drag-and-drop-autoscroll.html

* page/AutoscrollController.cpp:
(WebCore::AutoscrollController::AutoscrollController): Changed to initialize m_dragAndDropAutoscrollStartTime.
(WebCore::AutoscrollController::updateDragAndDrop): Added for start/stop autoscroll during drag-and-drop.
(WebCore::AutoscrollController::autoscrollTimerFired): Changed to add autoscroll for drag-and-drop, and to pass last know position to RenderBox::autoscroll().
* page/AutoscrollController.h:
(AutoscrollController): Changed to add updateDragAndDrop() and m_dragAndDropAutoscrollReferencePosition and m_dragAndDropAutoscrollStartTime.
* page/ChromeClient.h:
(WebCore::ChromeClient): Changed to add new function shouldAutoscrollForDragAndDrop().
* page/EventHandler.cpp:
(WebCore::EventHandler::updateDragAndDrop): Changed to call AutoscrollController::updateDragAndDrop().
(WebCore::EventHandler::clearDragState): Changed to call stopAutoscrollTimer().
* rendering/RenderBox.cpp:
(WebCore::RenderBox::autoscroll): Changed for new parameter position.
(WebCore::RenderBox::calculateAutoscrollDirection): Added for autoscroll.
* rendering/RenderBox.h:
(RenderBox):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::autoscroll):  Changed for new parameter position and move updateSelectionForMouseDrag() to AutoscrollController.
* rendering/RenderLayer.h:
(RenderLayer):
* rendering/RenderListBox.cpp:
(WebCore::RenderListBox::autoscroll):  Changed for new parameter position.
* rendering/RenderListBox.h:
(RenderListBox):
* rendering/RenderTextControlSingleLine.cpp:
(WebCore::RenderTextControlSingleLine::autoscroll):  Changed for new parameter position.
* rendering/RenderTextControlSingleLine.h:
(RenderTextControlSingleLine):

Source/WebKit/chromium:

This patch removes DragScrollTimer used for automatic scrolling of main
frame drag-and-drop which is now implemented in EventHandler.

Another patch will remove DragScrollTimer.{cpp,h} and update GYP files to
make patch size small.

No tests. Existing test covers this change.

* src/ChromeClientImpl.cpp:
(WebKit::ChromeClientImpl::shouldAutoscrollForDragAndDrop): Added.
* src/ChromeClientImpl.h:
(ChromeClientImpl): Changed to add shouldAutoscrollForDragAndDrop().
* src/WebViewImpl.cpp:
(WebKit::WebViewImpl::WebViewImpl): Changed to remove m_dragScrollTimer.
(WebKit::WebViewImpl::dragSourceEndedAt): ditto
(WebKit::WebViewImpl::dragSourceMovedTo): ditto
(WebKit::WebViewImpl::dragTargetDrop): ditto
(WebKit::WebViewImpl::dragTargetDragEnterOrOver): ditto
* src/WebViewImpl.h:
(WebKit): Chagned to remove DragScrollTimer.

Tools:

This patch introduces canceling drag-and-drop by escape key for testing
behavior after cancellation drag-and-drop.

* DumpRenderTree/chromium/TestRunner/src/EventSender.cpp:
(WebTestRunner):
(WebTestRunner::EventSender::doMouseUp):
(WebTestRunner::EventSender::finishDragAndDrop):
(WebTestRunner::EventSender::keyDown):
* DumpRenderTree/chromium/TestRunner/src/EventSender.h:
(EventSender):
* DumpRenderTree/chromium/TestRunner/src/KeyCodeMapping.h: Added VKEY_ESCAPE.

LayoutTests:

This patch adds new test for autoscroll during drag-and-drop.
This test is skipped other than Chromium ports.

* fast/events/drag-and-drop-autoscroll-expected.txt: Added.
* fast/events/drag-and-drop-autoscroll.html: Added.
* platform/efl/TestExpectations: Changed to skip fast/events/drag-and-drop-autoscroll.html
* platform/wincairo/TestExpectations: ditto.
* platform/mac/TestExpectations: ditto.
* platform/mac/TestExpectations: ditto.
* platform/qt/TestExpectations: ditto.
* platform/gtk/TestExpectations: ditto.
* platform/win/TestExpectations: ditto.
* platform/wk2/TestExpectations: ditto.

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

31 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/events/drag-and-drop-autoscroll-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/drag-and-drop-autoscroll.html [new file with mode: 0644]
LayoutTests/platform/efl/TestExpectations
LayoutTests/platform/gtk/TestExpectations
LayoutTests/platform/mac/TestExpectations
LayoutTests/platform/qt/TestExpectations
LayoutTests/platform/win/TestExpectations
LayoutTests/platform/wincairo/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/page/AutoscrollController.cpp
Source/WebCore/page/AutoscrollController.h
Source/WebCore/page/ChromeClient.h
Source/WebCore/page/EventHandler.cpp
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderBox.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderListBox.cpp
Source/WebCore/rendering/RenderListBox.h
Source/WebCore/rendering/RenderTextControlSingleLine.cpp
Source/WebCore/rendering/RenderTextControlSingleLine.h
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/ChromeClientImpl.cpp
Source/WebKit/chromium/src/ChromeClientImpl.h
Source/WebKit/chromium/src/WebViewImpl.cpp
Source/WebKit/chromium/src/WebViewImpl.h
Tools/ChangeLog
Tools/DumpRenderTree/chromium/TestRunner/src/EventSender.cpp
Tools/DumpRenderTree/chromium/TestRunner/src/EventSender.h
Tools/DumpRenderTree/chromium/TestRunner/src/KeyCodeMapping.h

index 5ccf36e..6bc9ca7 100644 (file)
@@ -1,3 +1,24 @@
+2013-01-20  Yoshifumi Inoue  <yosin@chromium.org>
+
+        Dragging over an element with scrollbars should scroll the element when dragging near edges
+        https://bugs.webkit.org/show_bug.cgi?id=39725
+
+        Reviewed by Hajime Morita.
+
+        This patch adds new test for autoscroll during drag-and-drop.
+        This test is skipped other than Chromium ports.
+
+        * fast/events/drag-and-drop-autoscroll-expected.txt: Added.
+        * fast/events/drag-and-drop-autoscroll.html: Added.
+        * platform/efl/TestExpectations: Changed to skip fast/events/drag-and-drop-autoscroll.html
+        * platform/wincairo/TestExpectations: ditto.
+        * platform/mac/TestExpectations: ditto.
+        * platform/mac/TestExpectations: ditto.
+        * platform/qt/TestExpectations: ditto.
+        * platform/gtk/TestExpectations: ditto.
+        * platform/win/TestExpectations: ditto.
+        * platform/wk2/TestExpectations: ditto.
+
 2013-01-20  Filip Pizlo  <fpizlo@apple.com>
 
         Add more JavaScript tests.
diff --git a/LayoutTests/fast/events/drag-and-drop-autoscroll-expected.txt b/LayoutTests/fast/events/drag-and-drop-autoscroll-expected.txt
new file mode 100644 (file)
index 0000000..e2e6148
--- /dev/null
@@ -0,0 +1,9 @@
+For manual testing, drag and drop "Drop Me" to "Scrollable" area.
+Check autoscroll by drag-and-drop
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS scrollable.scrollTop > 0
+PASS autoscroll stopped
+
diff --git a/LayoutTests/fast/events/drag-and-drop-autoscroll.html b/LayoutTests/fast/events/drag-and-drop-autoscroll.html
new file mode 100644 (file)
index 0000000..c1fe7e3
--- /dev/null
@@ -0,0 +1,127 @@
+<html>
+<head>
+<style type="text/css">
+#draggable {
+  padding: 5pt;
+  border: 3px solid #00cc00;
+  background: #00cccc;
+  width: 80px;
+  cursor: hand;
+}
+
+#scrollable {
+    height: 200px;
+    overflow: auto;
+    border: solid 3px #cc0000;
+    font-size: 80px;
+}
+</style>
+<script>
+function $(id) { return document.getElementById(id); }
+
+function finishTest() {
+    eventSender.mouseUp();
+    $('container').innerHTML = '';
+    window.testRunner.notifyDone();
+}
+
+function testIt() {
+    var draggable = $('draggable');
+    var scrollable = $('scrollable');
+
+    if (!window.eventSender)
+        return;
+
+    eventSender.dragMode = false;
+
+    // Grab draggable
+    eventSender.mouseMoveTo(draggable.offsetLeft + 5, draggable.offsetTop + 5);
+    eventSender.mouseDown();
+
+    // Move mouse to autoscroll border belt.
+    eventSender.mouseMoveTo(scrollable.offsetLeft + 5, scrollable.offsetTop + scrollable.offsetHeight - 10);
+
+    var retryCount = 0;
+    var lastScrollTop = 0;
+
+    function checkScrolled()
+    {
+        if (scrollable.scrollTop > 0) {
+            testPassed('scrollable.scrollTop > 0');
+            lastScrollTop = scrollable.scrollTop;
+            // Cancel drag and drop by ESC key.
+            eventSender.keyDown('\x1B');
+            retryCount = 0;
+            window.setTimeout(checkStopped, 50);
+            return;
+        }
+
+        ++retryCount;
+        if (retryCount > 10) {
+            testFailed('No autoscroll');
+            finishTest();
+            return;
+        }
+
+        // Autoscroll is occurred evey 0.05 sec.
+        window.setTimeout(checkScrolled, 50);
+    }
+
+    function checkStopped()
+    {
+        if (lastScrollTop == scrollable.scrollTop) {
+            testPassed('autoscroll stopped');
+            finishTest();
+            return;
+        }
+
+        ++retryCount;
+        if (retryCount > 10) {
+            testFailed('still autoscroll');
+            finishTest();
+            return;
+        }
+
+        lastScrollTop = scrollable.scrollTop;
+        window.setTimeout(checkStopped, 50);
+    }
+
+    checkScrolled();
+}
+
+function setUpTest()
+{
+    var scrollable = $('scrollable');
+    for (var i = 0; i < 100; ++i) {
+      var line = document.createElement('div');
+      line.innerHTML = "line " + i;
+      scrollable.appendChild(line);
+    }
+
+    if (!window.eventSender) {
+        console.log('Please run within DumpRenderTree');
+        return;
+    }
+
+    window.jsTestIsAsync = true;
+    window.setTimeout(testIt, 0);
+}
+</script>
+</head>
+<body>
+For manual testing, drag and drop "Drop Me" to "Scrollable" area.
+<div id="container">
+<div id="draggable" draggable="true">Drop Me</div>
+Scrollable
+<div id="scrollable">
+</div>
+</div>
+<div id="console"></div>
+<script src="../js/resources/js-test-pre.js"></script>
+<script>
+description('Check autoscroll by drag-and-drop');
+setUpTest();
+</script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
index 35fb8b4..fe94636 100644 (file)
@@ -1780,6 +1780,9 @@ webkit.org/b/105297 webaudio/audiobuffersource-playbackrate.html [ Failure ]
 webkit.org/b/105535 inspector-protocol/nmi-webaudio.html [ Failure ]
 webkit.org/b/105535 inspector-protocol/nmi-webaudio-leak-test.html [ Failure ]
 
+# Enable when support drag-and-drop autoscrolling
+webkit.org/b/39725 fast/events/drag-and-drop-autoscroll.html [ Skip ]
+
 # Leaking state into the next test.
 webkit.org/b/85522 http/tests/security/sandboxed-iframe-form-top.html [ Skip ]
 
index c26cd78..31461ec 100644 (file)
@@ -1340,6 +1340,9 @@ webkit.org/b/104686 http/tests/xmlhttprequest/redirect-cross-origin-tripmine.htm
 
 webkit.org/b/98146 accessibility/svg-bounds.html [ Failure ]
 
+# Enable when support drag-and-drop autoscrolling
+webkit.org/b/39725 fast/events/drag-and-drop-autoscroll.html [ Skip ]
+
 # Leaking state into the next test.
 webkit.org/b/85522 http/tests/security/sandboxed-iframe-form-top.html [ Skip ]
 
index 337c29c..bf0aa34 100644 (file)
@@ -1273,6 +1273,9 @@ webkit.org/b/106415 fast/workers/worker-close-more.html [ Pass Failure ]
 webkit.org/b/106415 fast/workers/worker-document-leak.html [ Pass Failure ]
 webkit.org/b/106415 fast/workers/worker-lifecycle.html [ Pass Failure ]
 
+# Enable when support drag-and-drop autoscrolling
+webkit.org/b/39725 fast/events/drag-and-drop-autoscroll.html [ Skip ]
+
 # Transient. Needs rebaseline.
 webkit.org/b/103955 fast/repaint/4774354.html [ ImageOnlyFailure ]
 webkit.org/b/103955 fast/repaint/4776765.html [ ImageOnlyFailure ]
index 9f2787b..3665c8c 100644 (file)
@@ -2515,6 +2515,9 @@ fast/workers/storage/interrupt-database.html
 # [Qt] New fast/js/dfg-create-inlined-arguments-in-closure-inline.html asserts on 32 bit
 webkit.org/b/106459 [ Debug ] fast/js/dfg-create-inlined-arguments-in-closure-inline.html
 
+# Enable when support drag-and-drop autoscrolling
+webkit.org/b/39725 fast/events/drag-and-drop-autoscroll.html [ Skip ]
+
 # New inspector/editor/text-editor-formatter.html introduced in r139617 fails on EFL, Mac, QT
 # https://bugs.webkit.org/show_bug.cgi?id=106883
 inspector/editor/text-editor-formatter.html
index 87c793d..6439474 100644 (file)
@@ -2506,6 +2506,9 @@ media/video-controls-captions-trackmenu-sorted.html
 media/video-controls-captions-trackmenu.html
 media/video-controls-visible-exiting-fullscreen.html
 
+# Enable when support drag-and-drop autoscrolling
+webkit.org/b/39725 fast/events/drag-and-drop-autoscroll.html [ Skip ]
+
 # Device Proximity is not enabled/implemented
 proximity/add-listener-from-callback.html
 proximity/basic-operation.html
index 6daea65..1b29a40 100644 (file)
@@ -2959,6 +2959,9 @@ webkit.org/b/100846 inspector-protocol/debugger-terminate-dedicated-worker-while
 # https://bugs.webkit.org/show_bug.cgi?id=100117
 fast/xmlhttprequest/xmlhttprequest-recursive-sync-event.html
 
+# Enable when support drag-and-drop autoscrolling
+webkit.org/b/39725 fast/events/drag-and-drop-autoscroll.html [ Skip ]
+
 # CSS3_TEXT is disabled on Windows
 fast/css3-text/css3-text-align-last/getComputedStyle/getComputedStyle-text-align-last-inherited.html
 fast/css3-text/css3-text-align-last/getComputedStyle/getComputedStyle-text-align-last.html
index c937f04..bc3dea8 100644 (file)
@@ -1,3 +1,49 @@
+2013-01-20  Yoshifumi Inoue  <yosin@chromium.org>
+
+        Dragging over an element with scrollbars should scroll the element when dragging near edges
+        https://bugs.webkit.org/show_bug.cgi?id=39725
+
+        Reviewed by Hajime Morita.
+
+        This patch introduces auto scrolling functionality during drag-and-drop
+        when drop source is near edge of scrollable element.
+
+        When drop source is inside 20px of scrollable element more than 200ms,
+        scrollable element is automatically scrolled every 50ms toward drop
+        source position, e.g. vertically scroll up when drop source is in top
+        edge.
+
+        Test: fast/events/drag-and-drop-autoscroll.html
+
+        * page/AutoscrollController.cpp:
+        (WebCore::AutoscrollController::AutoscrollController): Changed to initialize m_dragAndDropAutoscrollStartTime.
+        (WebCore::AutoscrollController::updateDragAndDrop): Added for start/stop autoscroll during drag-and-drop.
+        (WebCore::AutoscrollController::autoscrollTimerFired): Changed to add autoscroll for drag-and-drop, and to pass last know position to RenderBox::autoscroll().
+        * page/AutoscrollController.h:
+        (AutoscrollController): Changed to add updateDragAndDrop() and m_dragAndDropAutoscrollReferencePosition and m_dragAndDropAutoscrollStartTime.
+        * page/ChromeClient.h:
+        (WebCore::ChromeClient): Changed to add new function shouldAutoscrollForDragAndDrop().
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::updateDragAndDrop): Changed to call AutoscrollController::updateDragAndDrop().
+        (WebCore::EventHandler::clearDragState): Changed to call stopAutoscrollTimer().
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::autoscroll): Changed for new parameter position.
+        (WebCore::RenderBox::calculateAutoscrollDirection): Added for autoscroll.
+        * rendering/RenderBox.h:
+        (RenderBox):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::autoscroll):  Changed for new parameter position and move updateSelectionForMouseDrag() to AutoscrollController.
+        * rendering/RenderLayer.h:
+        (RenderLayer):
+        * rendering/RenderListBox.cpp:
+        (WebCore::RenderListBox::autoscroll):  Changed for new parameter position.
+        * rendering/RenderListBox.h:
+        (RenderListBox):
+        * rendering/RenderTextControlSingleLine.cpp:
+        (WebCore::RenderTextControlSingleLine::autoscroll):  Changed for new parameter position.
+        * rendering/RenderTextControlSingleLine.h:
+        (RenderTextControlSingleLine):
+
 2013-01-20  Laszlo Gombos  <l.gombos@samsung.com>
 
         Simplify a list of negative PLATFORM() tests
index 2aeb8c4..8f2d7ea 100644 (file)
@@ -28,6 +28,8 @@
 #include "config.h"
 #include "AutoscrollController.h"
 
+#include "Chrome.h"
+#include "ChromeClient.h"
 #include "EventHandler.h"
 #include "Frame.h"
 #include "FrameView.h"
 #include "Page.h"
 #include "RenderBox.h"
 #include "ScrollView.h"
+#include <wtf/CurrentTime.h>
 
 namespace WebCore {
 
+// Delay time in second for start autoscroll if pointer is in border edge of scrollable element.
+static double autoscrollDelay = 0.2;
+
 // When the autoscroll or the panScroll is triggered when do the scroll every 0.05s to make it smooth
 static const double autoscrollInterval = 0.05;
 
@@ -53,6 +59,7 @@ AutoscrollController::AutoscrollController()
     : m_autoscrollTimer(this, &AutoscrollController::autoscrollTimerFired)
     , m_autoscrollRenderer(0)
     , m_autoscrollType(NoAutoscroll)
+    , m_dragAndDropAutoscrollStartTime(0)
 {
 }
 
@@ -136,6 +143,50 @@ void AutoscrollController::updateAutoscrollRenderer()
     m_autoscrollRenderer = renderer && renderer->isBox() ? toRenderBox(renderer) : 0;
 }
 
+void AutoscrollController::updateDragAndDrop(Node* dropTargetNode, const IntPoint& eventPosition, double eventTime)
+{
+    if (!dropTargetNode) {
+        stopAutoscrollTimer();
+        return;
+    }
+
+    RenderBox* scrollable = RenderBox::findAutoscrollable(dropTargetNode->renderer());
+    if (!scrollable) {
+        stopAutoscrollTimer();
+        return;
+    }
+
+    Frame* frame = scrollable->frame();
+    if (!frame) {
+        stopAutoscrollTimer();
+        return;
+    }
+
+    Page* page = frame->page();
+    if (!page || !page->chrome()->client()->shouldAutoscrollForDragAndDrop(scrollable)) {
+        stopAutoscrollTimer();
+        return;
+    }
+
+    IntSize offset = scrollable->calculateAutoscrollDirection(eventPosition);
+    if (offset.isZero()) {
+        stopAutoscrollTimer();
+        return;
+    }
+
+    m_dragAndDropAutoscrollReferencePosition = eventPosition + offset;
+
+    if (m_autoscrollType == NoAutoscroll) {
+        m_autoscrollType = AutoscrollForDragAndDrop;
+        m_autoscrollRenderer = scrollable;
+        m_dragAndDropAutoscrollStartTime = eventTime;
+        startAutoscrollTimer();
+    } else if (m_autoscrollRenderer != scrollable) {
+        m_dragAndDropAutoscrollStartTime = eventTime;
+        m_autoscrollRenderer = scrollable;
+    }
+}
+
 #if ENABLE(PAN_SCROLLING)
 void AutoscrollController::didPanScrollStart()
 {
@@ -196,13 +247,20 @@ void AutoscrollController::autoscrollTimerFired(Timer<AutoscrollController>*)
 
     Frame* frame = m_autoscrollRenderer->frame();
     switch (m_autoscrollType) {
-    case AutoscrollForSelection:
-        if (!frame->eventHandler()->mousePressed()) {
+    case AutoscrollForDragAndDrop:
+        if (WTF::currentTime() - m_dragAndDropAutoscrollStartTime > autoscrollDelay)
+            m_autoscrollRenderer->autoscroll(m_dragAndDropAutoscrollReferencePosition);
+        break;
+    case AutoscrollForSelection: {
+        EventHandler* eventHandler = frame->eventHandler();
+        if (!eventHandler->mousePressed()) {
             stopAutoscrollTimer();
             return;
         }
-        m_autoscrollRenderer->autoscroll();
+        eventHandler->updateSelectionForMouseDrag();
+        m_autoscrollRenderer->autoscroll(eventHandler->lastKnownMousePosition());
         break;
+    }
     case NoAutoscroll:
         break;
 #if ENABLE(PAN_SCROLLING)
index 02e35e1..f5d4bf0 100644 (file)
@@ -34,12 +34,14 @@ namespace WebCore {
 class EventHandler;
 class Frame;
 class FrameView;
+class Node;
 class PlatformMouseEvent;
 class RenderBox;
 class RenderObject;
 
 enum AutoscrollType {
     NoAutoscroll,
+    AutoscrollForDragAndDrop,
     AutoscrollForSelection,
 #if ENABLE(PAN_SCROLLING)
     AutoscrollForPanCanStop,
@@ -57,6 +59,7 @@ public:
     void startAutoscrollForSelection(RenderObject*);
     void stopAutoscrollTimer(bool rendererIsBeingDestroyed = false);
     void updateAutoscrollRenderer();
+    void updateDragAndDrop(Node* targetNode, const IntPoint& eventPosition, double eventTime);
 #if ENABLE(PAN_SCROLLING)
     void didPanScrollStart();
     void didPanScrollStop();
@@ -75,6 +78,8 @@ private:
     Timer<AutoscrollController> m_autoscrollTimer;
     RenderBox* m_autoscrollRenderer;
     AutoscrollType m_autoscrollType;
+    IntPoint m_dragAndDropAutoscrollReferencePosition;
+    double m_dragAndDropAutoscrollStartTime;
 #if ENABLE(PAN_SCROLLING)
     IntPoint m_panScrollStartPos;
 #endif
index 839ae9f..32d2f8f 100644 (file)
@@ -375,6 +375,9 @@ public:
 
     virtual PassRefPtr<Image> plugInStartLabelImage(RenderSnapshottedPlugIn::LabelSize) const { return 0; }
 
+    // FIXME: Port should return true using heuristic based on scrollable(RenderBox).
+    virtual bool shouldAutoscrollForDragAndDrop(RenderBox*) const { return false; }
+
 protected:
     virtual ~ChromeClient() { }
 };
index bfc3eee..9606822 100644 (file)
@@ -1965,6 +1965,8 @@ bool EventHandler::updateDragAndDrop(const PlatformMouseEvent& event, Clipboard*
     if (newTarget && newTarget->isTextNode())
         newTarget = newTarget->parentNode();
 
+    m_autoscrollController->updateDragAndDrop(newTarget.get(), event.position(), event.timestamp());
+
     if (m_dragTarget != newTarget) {
         // FIXME: this ordering was explicitly chosen to match WinIE. However,
         // it is sometimes incorrect when dragging within subframes, as seen with
@@ -2048,6 +2050,7 @@ bool EventHandler::performDragAndDrop(const PlatformMouseEvent& event, Clipboard
 
 void EventHandler::clearDragState()
 {
+    stopAutoscrollTimer();
     m_dragTarget = 0;
     m_capturingMouseEventsNode = 0;
     m_shouldOnlyFireDragOverEvent = false;
index fe586c2..8400b34 100644 (file)
@@ -85,6 +85,11 @@ static OverrideSizeMap* gOverrideWidthMap = 0;
 static OverrideSizeMap* gOverrideContainingBlockLogicalHeightMap = 0;
 static OverrideSizeMap* gOverrideContainingBlockLogicalWidthMap = 0;
 
+
+// Size of border belt for autoscroll. When mouse pointer in border belt,
+// autoscroll is started.
+static const int autoscrollBeltSize = 20;
+
 bool RenderBox::s_hadOverflowClip = false;
 
 RenderBox::RenderBox(ContainerNode* node)
@@ -708,10 +713,10 @@ bool RenderBox::usesCompositedScrolling() const
     return hasOverflowClip() && hasLayer() && layer()->usesCompositedScrolling();
 }
 
-void RenderBox::autoscroll()
+void RenderBox::autoscroll(const IntPoint& position)
 {
     if (layer())
-        layer()->autoscroll();
+        layer()->autoscroll(position);
 }
 
 // There are two kinds of renderer that can autoscroll.
@@ -735,6 +740,33 @@ bool RenderBox::canAutoscroll() const
     return page && page->mainFrame() == frame;
 }
 
+// If specified point is in border belt, returned offset denotes direction of
+// scrolling.
+IntSize RenderBox::calculateAutoscrollDirection(const IntPoint& windowPoint) const
+{
+    if (!frame())
+        return IntSize();
+
+    FrameView* frameView = frame()->view();
+    if (!frameView)
+        return IntSize();
+
+    IntSize offset;
+    IntPoint point = frameView->windowToContents(windowPoint);
+    IntRect box(absoluteBoundingBoxRect());
+
+    if (point.x() < box.x() + autoscrollBeltSize)
+        point.move(-autoscrollBeltSize, 0);
+    else if (point.x() > box.maxX() - autoscrollBeltSize)
+        point.move(autoscrollBeltSize, 0);
+
+    if (point.y() < box.y() + autoscrollBeltSize)
+        point.move(0, -autoscrollBeltSize);
+    else if (point.y() > box.maxY() - autoscrollBeltSize)
+        point.move(0, autoscrollBeltSize);
+    return frameView->contentsToWindow(point) - windowPoint;
+}
+
 RenderBox* RenderBox::findAutoscrollable(RenderObject* renderer)
 {
     while (renderer && !(renderer->isBox() && toRenderBox(renderer)->canAutoscroll())) {
index ca749d2..272426c 100644 (file)
@@ -447,8 +447,9 @@ public:
     virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0);
     bool canBeScrolledAndHasScrollableArea() const;
     virtual bool canBeProgramaticallyScrolled() const;
-    virtual void autoscroll();
+    virtual void autoscroll(const IntPoint&);
     bool canAutoscroll() const;
+    IntSize calculateAutoscrollDirection(const IntPoint& windowPoint) const;
     static RenderBox* findAutoscrollable(RenderObject*);
     virtual void stopAutoscroll() { }
     virtual void panScroll(const IntPoint&);
index ea5d59f..06c3abb 100644 (file)
@@ -2301,7 +2301,7 @@ LayoutRect RenderLayer::getRectToExpose(const LayoutRect &visibleRect, const Lay
     return LayoutRect(LayoutPoint(x, y), visibleRect.size());
 }
 
-void RenderLayer::autoscroll()
+void RenderLayer::autoscroll(const IntPoint& position)
 {
     Frame* frame = renderer()->frame();
     if (!frame)
@@ -2311,11 +2311,7 @@ void RenderLayer::autoscroll()
     if (!frameView)
         return;
 
-#if ENABLE(DRAG_SUPPORT)
-    frame->eventHandler()->updateSelectionForMouseDrag();
-#endif
-
-    IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->lastKnownMousePosition());
+    IntPoint currentDocumentPosition = frameView->windowToContents(position);
     scrollRectToVisible(LayoutRect(currentDocumentPosition, LayoutSize(1, 1)), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
 }
 
index c2f2559..86e7421 100644 (file)
@@ -373,7 +373,7 @@ public:
     void updateScrollInfoAfterLayout();
 
     bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1);
-    void autoscroll();
+    void autoscroll(const IntPoint&);
 
     void resize(const PlatformMouseEvent&, const LayoutSize&);
     bool inResizeMode() const { return m_inResizeMode; }
index 31a1ed8..51f8e46 100644 (file)
@@ -557,7 +557,7 @@ int RenderListBox::scrollToward(const IntPoint& destination)
     return listIndexAtOffset(positionOffset);
 }
 
-void RenderListBox::autoscroll()
+void RenderListBox::autoscroll(const IntPoint&)
 {
     IntPoint pos = frame()->view()->windowToContents(frame()->eventHandler()->lastKnownMousePosition());
 
index ef0d60a..349293b 100644 (file)
@@ -85,7 +85,7 @@ private:
     virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&);
 
     virtual bool canBeProgramaticallyScrolled() const { return true; }
-    virtual void autoscroll();
+    virtual void autoscroll(const IntPoint&);
     virtual void stopAutoscroll();
 
     virtual bool shouldPanScroll() const { return true; }
index 1206f1d..2a001f7 100644 (file)
@@ -381,11 +381,11 @@ bool RenderTextControlSingleLine::textShouldBeTruncated() const
         && style()->textOverflow() == TextOverflowEllipsis;
 }
 
-void RenderTextControlSingleLine::autoscroll()
+void RenderTextControlSingleLine::autoscroll(const IntPoint& position)
 {
     RenderLayer* layer = innerTextElement()->renderBox()->layer();
     if (layer)
-        layer->autoscroll();
+        layer->autoscroll(position);
 }
 
 int RenderTextControlSingleLine::scrollWidth() const
index f4721c8..16f1c77 100644 (file)
@@ -58,7 +58,7 @@ private:
 
     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
 
-    virtual void autoscroll();
+    virtual void autoscroll(const IntPoint&);
 
     // Subclassed to forward to our inner div.
     virtual int scrollLeft() const;
index 990a44c..f515ec2 100644 (file)
@@ -1,3 +1,31 @@
+2013-01-20  Yoshifumi Inoue  <yosin@chromium.org>
+
+        Dragging over an element with scrollbars should scroll the element when dragging near edges
+        https://bugs.webkit.org/show_bug.cgi?id=39725
+
+        Reviewed by Hajime Morita.
+
+        This patch removes DragScrollTimer used for automatic scrolling of main
+        frame drag-and-drop which is now implemented in EventHandler.
+
+        Another patch will remove DragScrollTimer.{cpp,h} and update GYP files to
+        make patch size small.
+
+        No tests. Existing test covers this change.
+
+        * src/ChromeClientImpl.cpp:
+        (WebKit::ChromeClientImpl::shouldAutoscrollForDragAndDrop): Added.
+        * src/ChromeClientImpl.h:
+        (ChromeClientImpl): Changed to add shouldAutoscrollForDragAndDrop().
+        * src/WebViewImpl.cpp:
+        (WebKit::WebViewImpl::WebViewImpl): Changed to remove m_dragScrollTimer.
+        (WebKit::WebViewImpl::dragSourceEndedAt): ditto
+        (WebKit::WebViewImpl::dragSourceMovedTo): ditto
+        (WebKit::WebViewImpl::dragTargetDrop): ditto
+        (WebKit::WebViewImpl::dragTargetDragEnterOrOver): ditto
+        * src/WebViewImpl.h:
+        (WebKit): Chagned to remove DragScrollTimer.
+
 2013-01-18  Alec Flett  <alecflett@chromium.org>
 
         IndexedDB: Switch to new createTransaction call
index e5be371..8f7069c 100644 (file)
@@ -1131,6 +1131,12 @@ void ChromeClientImpl::numWheelEventHandlersChanged(unsigned numberOfWheelHandle
     m_webView->numberOfWheelEventHandlersChanged(numberOfWheelHandlers);
 }
 
+bool ChromeClientImpl::shouldAutoscrollForDragAndDrop(WebCore::RenderBox*) const
+{
+    return true;
+}
+
+
 #if ENABLE(TOUCH_EVENTS)
 void ChromeClientImpl::needTouchEvents(bool needsTouchEvents)
 {
index d2ad111..d5e9aff 100644 (file)
@@ -225,6 +225,8 @@ public:
     virtual bool shouldRubberBandInDirection(WebCore::ScrollDirection) const;
     virtual void numWheelEventHandlersChanged(unsigned);
 
+    virtual bool shouldAutoscrollForDragAndDrop(WebCore::RenderBox* scrollable) const OVERRIDE;
+
 #if ENABLE(POINTER_LOCK)
     virtual bool requestPointerLock();
     virtual void requestPointerUnlock();
index b41f600..fed4f8d 100644 (file)
@@ -53,7 +53,6 @@
 #include "DocumentLoader.h"
 #include "DragController.h"
 #include "DragData.h"
-#include "DragScrollTimer.h"
 #include "DragSession.h"
 #include "Editor.h"
 #include "EventHandler.h"
@@ -415,7 +414,6 @@ WebViewImpl::WebViewImpl(WebViewClient* client)
     , m_autofillPopup(0)
     , m_isTransparent(false)
     , m_tabsToLinks(false)
-    , m_dragScrollTimer(adoptPtr(new DragScrollTimer))
     , m_isCancelingFullScreen(false)
     , m_benchmarkSupport(this)
 #if USE(ACCELERATED_COMPOSITING)
@@ -3290,7 +3288,6 @@ void WebViewImpl::dragSourceEndedAt(
                            false, 0);
     m_page->mainFrame()->eventHandler()->dragSourceEndedAt(pme,
         static_cast<DragOperation>(operation));
-    m_dragScrollTimer->stop();
 }
 
 void WebViewImpl::dragSourceMovedTo(
@@ -3298,7 +3295,6 @@ void WebViewImpl::dragSourceMovedTo(
     const WebPoint& screenPoint,
     WebDragOperation operation)
 {
-    m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
 }
 
 void WebViewImpl::dragSourceSystemDragEnded()
@@ -3384,8 +3380,6 @@ void WebViewImpl::dragTargetDrop(const WebPoint& clientPoint,
 
     m_dragOperation = WebDragOperationNone;
     m_currentDragData = 0;
-
-    m_dragScrollTimer->stop();
 }
 
 WebDragOperation WebViewImpl::dragTargetDragEnterOrOver(const WebPoint& clientPoint, const WebPoint& screenPoint, DragAction dragAction, int keyModifiers)
@@ -3413,11 +3407,6 @@ WebDragOperation WebViewImpl::dragTargetDragEnterOrOver(const WebPoint& clientPo
 
      m_dragOperation = static_cast<WebDragOperation>(dropEffect);
 
-    if (dragAction == DragOver)
-        m_dragScrollTimer->triggerScroll(mainFrameImpl()->frameView(), clientPoint);
-    else
-        m_dragScrollTimer->stop();
-
     return m_dragOperation;
 }
 
index 3e8dcd4..40275d7 100644 (file)
@@ -92,7 +92,6 @@ class BatteryClientImpl;
 class ContextFeaturesClientImpl;
 class ContextMenuClientImpl;
 class DeviceOrientationClientProxy;
-class DragScrollTimer;
 class GeolocationClientProxy;
 class LinkHighlight;
 class NonCompositedContentHost;
@@ -821,7 +820,6 @@ private:
 
     typedef HashMap<WTF::String, WTF::String> SettingsMap;
     OwnPtr<SettingsMap> m_inspectorSettingsMap;
-    OwnPtr<DragScrollTimer> m_dragScrollTimer;
 
 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
     // The provider of desktop notifications;
index c861be2..a62f744 100644 (file)
@@ -1,3 +1,22 @@
+2013-01-20  Yoshifumi Inoue  <yosin@chromium.org>
+
+        Dragging over an element with scrollbars should scroll the element when dragging near edges
+        https://bugs.webkit.org/show_bug.cgi?id=39725
+
+        Reviewed by Hajime Morita.
+
+        This patch introduces canceling drag-and-drop by escape key for testing
+        behavior after cancellation drag-and-drop.
+
+        * DumpRenderTree/chromium/TestRunner/src/EventSender.cpp:
+        (WebTestRunner):
+        (WebTestRunner::EventSender::doMouseUp):
+        (WebTestRunner::EventSender::finishDragAndDrop):
+        (WebTestRunner::EventSender::keyDown):
+        * DumpRenderTree/chromium/TestRunner/src/EventSender.h:
+        (EventSender):
+        * DumpRenderTree/chromium/TestRunner/src/KeyCodeMapping.h: Added VKEY_ESCAPE.
+
 2013-01-20  Jochen Eisinger  <jochen@chromium.org>
 
         [chromium] move frame generation related methods to TestRunner
index 773a56b..c99af9a 100644 (file)
@@ -468,10 +468,17 @@ void EventSender::doMouseUp(const WebMouseEvent& e)
     // If we're in a drag operation, complete it.
     if (currentDragData.isNull())
         return;
+
     WebPoint clientPoint(e.x, e.y);
     WebPoint screenPoint(e.globalX, e.globalY);
+    finishDragAndDrop(e, webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0));
+}
 
-    currentDragEffect = webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0);
+void EventSender::finishDragAndDrop(const WebMouseEvent& e, WebKit::WebDragOperation dragEffect)
+{
+    WebPoint clientPoint(e.x, e.y);
+    WebPoint screenPoint(e.globalX, e.globalY);
+    currentDragEffect = dragEffect;
     if (currentDragEffect)
         webview()->dragTargetDrop(clientPoint, screenPoint, 0);
     else
@@ -648,6 +655,12 @@ void EventSender::keyDown(const CppArgumentList& arguments, CppVariant* result)
 
     webview()->handleInputEvent(eventDown);
 
+    if (code == VKEY_ESCAPE && !currentDragData.isNull()) {
+        WebMouseEvent event;
+        initMouseEvent(WebInputEvent::MouseDown, pressedButton, lastMousePos, &event, getCurrentEventTimeSec(m_delegate));
+        finishDragAndDrop(event, WebKit::WebDragOperationNone);
+    }
+
     m_delegate->clearEditCommand();
 
     if (generateChar) {
index b1da684..c2b3cd9 100644 (file)
@@ -158,6 +158,7 @@ private:
     // modifier to be passed into the generated event.
     bool needsShiftModifier(int);
 
+    void finishDragAndDrop(const WebKit::WebMouseEvent&, WebKit::WebDragOperation);
     void updateClickCountForButton(WebKit::WebMouseEvent::Button);
 
     // Compose a touch event from the current touch points and send it.
index 87469fa..023e595 100644 (file)
@@ -36,6 +36,7 @@ namespace WebTestRunner {
 // The keycodes match the values of the virtual keycodes found here http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
 enum {
     VKEY_RETURN   = 0x0D,
+    VKEY_ESCAPE   = 0x1B,
     VKEY_PRIOR    = 0x21,
     VKEY_NEXT     = 0x22,
     VKEY_END      = 0x23,