Commit 0eb6dc60 authored by dcheng@chromium.org's avatar dcheng@chromium.org

2011-05-13 Daniel Cheng <dcheng@chromium.org>

        Reviewed by Tony Chang.

        Improve drag start logic
        https://bugs.webkit.org/show_bug.cgi?id=59409

        Add a new test to test drag start edge cases on Mac (because of a non-zero text drag delay)
        as well as rebase an existing test.

        * fast/css/user-drag-none.html: Text nodes are no longer draggable.
        * platform/mac/editing/pasteboard/drag-selections-to-contenteditable-expected.txt: Added.
        * platform/mac/editing/pasteboard/drag-selections-to-contenteditable.html: Added.
2011-05-13  Daniel Cheng  <dcheng@chromium.org>

        Reviewed by Tony Chang.

        Improve drag start logic
        https://bugs.webkit.org/show_bug.cgi?id=59409

        Rewrite and simplify the dragging logic to better match IE, Firefox, and the behavior
        defined in the spec. Among other things:
        - draggableNode() no longer returns text nodes when dragging anchors.
        - When starting a drag over an image in a selection, prefer to drag the selection.
        - Several redundant hit tests have been removed.
        - Minor refactoring to make the logic easier to follow.

        Test: platform/mac/editing/pasteboard/drag-selections-to-contenteditable.html

        * WebCore.xcodeproj/project.pbxproj:
        * page/DragController.cpp:
        (WebCore::DragController::draggableNode):
        (WebCore::DragController::startDrag):
        * page/DragController.h:
        * page/DragState.h:
        (WebCore::DragState::shouldDispatchEvents):
        * page/EventHandler.cpp:
        (WebCore::EventHandler::EventHandler):
        (WebCore::EventHandler::eventMayStartDrag):
        (WebCore::EventHandler::updateDragSourceActionsAllowed):
        (WebCore::EventHandler::updateDragAndDrop):
        (WebCore::EventHandler::cancelDragAndDrop):
        (WebCore::EventHandler::dragHysteresisExceeded):
        (WebCore::EventHandler::dragSourceEndedAt):
        (WebCore::ExactlyOneBitSet):
        (WebCore::EventHandler::handleDrag):
        * page/EventHandler.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@86472 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 14c5dd6c
2011-05-13 Daniel Cheng <dcheng@chromium.org>
Reviewed by Tony Chang.
Improve drag start logic
https://bugs.webkit.org/show_bug.cgi?id=59409
Add a new test to test drag start edge cases on Mac (because of a non-zero text drag delay)
as well as rebase an existing test.
* fast/css/user-drag-none.html: Text nodes are no longer draggable.
* platform/mac/editing/pasteboard/drag-selections-to-contenteditable-expected.txt: Added.
* platform/mac/editing/pasteboard/drag-selections-to-contenteditable.html: Added.
2011-05-13 Anders Carlsson <andersca@apple.com> 2011-05-13 Anders Carlsson <andersca@apple.com>
Reviewed by Sam Weinig. Reviewed by Sam Weinig.
...@@ -19,11 +19,11 @@ ...@@ -19,11 +19,11 @@
<img class="drag-none" src="resources/greenbox.png"> <img class="drag-none" src="resources/greenbox.png">
</div> </div>
<div class="box" expect="IMG text text A nil"> <div class="box" expect="IMG A A A nil">
<a href="#"><img src="resources/greenbox.png">x<br><span>y</span></a> <a href="#"><img src="resources/greenbox.png">x<br><span>y</span></a>
</div> </div>
<div class="box" expect="IMG text text A nil"> <div class="box" expect="IMG A A A nil">
<a href="#" class="drag-element"><img src="resources/greenbox.png">x<br><span>y</span></a> <a href="#" class="drag-element"><img src="resources/greenbox.png">x<br><span>y</span></a>
</div> </div>
...@@ -31,11 +31,11 @@ ...@@ -31,11 +31,11 @@
<a href="#" class="drag-none"><img src="resources/greenbox.png">x<br><span>y</span></a> <a href="#" class="drag-none"><img src="resources/greenbox.png">x<br><span>y</span></a>
</div> </div>
<div class="box" expect="A text text A nil"> <div class="box" expect="A A A A nil">
<a href="#"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a> <a href="#"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a>
</div> </div>
<div class="box" expect="A text text A nil"> <div class="box" expect="A A A A nil">
<a href="#" class="drag-element"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a> <a href="#" class="drag-element"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a>
</div> </div>
...@@ -43,11 +43,11 @@ ...@@ -43,11 +43,11 @@
<a href="#" class="drag-none"><img src="resources/greenbox.png">x<br><span>y</span></a> <a href="#" class="drag-none"><img src="resources/greenbox.png">x<br><span>y</span></a>
</div> </div>
<div class="box drag-element" expect="A text text A DIV"> <div class="box drag-element" expect="A A A A DIV">
<a href="#"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a> <a href="#"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a>
</div> </div>
<div class="box drag-element" expect="A text text A DIV"> <div class="box drag-element" expect="A A A A DIV">
<a href="#" class="drag-element"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a> <a href="#" class="drag-element"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a>
</div> </div>
</div> </div>
......
  Link Random text.
Link Random text.
This test checks selection drag edge cases on Mac. To run the test manually:
Select everything above, start the drag over the image, and with no delay, drag it to the content editable area. Only the image should be dragged.
Select everything above, start the drag over the link, and with no delay, drag it to the content editable area. The entire selection should be dragged.
Select everything above, start the drag over the text, and with no delay, drag it to the content editable area. Nothing should be dragged, but a bunch of text should be selected instead.
Dumping info about contenteditable div:
Number of children: 4
Contents:
IMG
IMG
A
SPAN
Number of selected ranges: 1
<html>
<head>
<script>
function log(message) {
var console = document.getElementById("console");
var div = document.createElement("div");
var text = document.createTextNode(message);
console.appendChild(div);
div.appendChild(text);
}
function runTest() {
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
} else
return;
selectSelection();
dragElementToContentEditable(document.getElementById("dragimage"));
selectSelection();
dragElementToContentEditable(document.getElementById("draglink"));
selectSelection();
dragElementToContentEditable(document.getElementById("dragtext"));
var target = document.getElementById("target");
log("Dumping info about contenteditable div:");
log("Number of children: " + target.children.length);
log("Contents:");
log(target.children[0].tagName);
log(target.children[1].tagName);
log(target.children[2].tagName);
log(target.children[3].tagName);
log("Number of selected ranges: " + window.getSelection().rangeCount);
layoutTestController.notifyDone();
}
function selectSelection() {
window.getSelection().selectAllChildren(document.getElementById("selection"));
}
function dragElementToContentEditable(dragSource)
{
x = dragSource.offsetLeft + dragSource.offsetWidth / 2;
y = dragSource.offsetTop + dragSource.offsetHeight / 2;
eventSender.mouseMoveTo(x, y);
eventSender.mouseDown();
var dropTarget = document.getElementById("target");
x = dropTarget.offsetLeft + dropTarget.offsetWidth / 2;
y = dropTarget.offsetTop + dropTarget.offsetHeight / 2;
eventSender.mouseMoveTo(x, y);
eventSender.mouseUp();
}
</script>
</head>
<body style="padding:0; margin:0" onload="runTest();">
<div id="target" style="border: 1px solid black; width: 300px; height: 200px;" contenteditable="true"></div>
<div id="selection">
<img id="dragimage" src="../../../../editing/resources/abe.png">
<a href="#" id="draglink">Link</a>
<span id="dragtext">Random text.</span></div>
<p>This test checks selection drag edge cases on Mac. To run the test manually:
<ol>
<li>Select everything above, start the drag over the image, and with no delay, drag it to the content editable area. Only the image should be dragged.
<li>Select everything above, start the drag over the link, and with no delay, drag it to the content editable area. The entire selection should be dragged.
<li>Select everything above, start the drag over the text, and with no delay, drag it to the content editable area. Nothing should be dragged, but a bunch of text should be selected instead.
</ol>
</p>
<div id="console"></ul>
</body>
2011-05-13 Daniel Cheng <dcheng@chromium.org>
Reviewed by Tony Chang.
Improve drag start logic
https://bugs.webkit.org/show_bug.cgi?id=59409
Rewrite and simplify the dragging logic to better match IE, Firefox, and the behavior
defined in the spec. Among other things:
- draggableNode() no longer returns text nodes when dragging anchors.
- When starting a drag over an image in a selection, prefer to drag the selection.
- Several redundant hit tests have been removed.
- Minor refactoring to make the logic easier to follow.
Test: platform/mac/editing/pasteboard/drag-selections-to-contenteditable.html
* WebCore.xcodeproj/project.pbxproj:
* page/DragController.cpp:
(WebCore::DragController::draggableNode):
(WebCore::DragController::startDrag):
* page/DragController.h:
* page/DragState.h:
(WebCore::DragState::shouldDispatchEvents):
* page/EventHandler.cpp:
(WebCore::EventHandler::EventHandler):
(WebCore::EventHandler::eventMayStartDrag):
(WebCore::EventHandler::updateDragSourceActionsAllowed):
(WebCore::EventHandler::updateDragAndDrop):
(WebCore::EventHandler::cancelDragAndDrop):
(WebCore::EventHandler::dragHysteresisExceeded):
(WebCore::EventHandler::dragSourceEndedAt):
(WebCore::ExactlyOneBitSet):
(WebCore::EventHandler::handleDrag):
* page/EventHandler.h:
2011-05-13 Oliver Hunt <oliver@apple.com> 2011-05-13 Oliver Hunt <oliver@apple.com>
Reviewed by Geoffrey Garen. Reviewed by Geoffrey Garen.
...@@ -1675,7 +1675,7 @@ ...@@ -1675,7 +1675,7 @@
81BE209911F4AB8D00915DFA /* IDBCursorBackendInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 81BE209411F4AB8D00915DFA /* IDBCursorBackendInterface.h */; }; 81BE209911F4AB8D00915DFA /* IDBCursorBackendInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 81BE209411F4AB8D00915DFA /* IDBCursorBackendInterface.h */; };
81BE20D211F4BC3200915DFA /* JSIDBCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 81BE20A711F4B66F00915DFA /* JSIDBCursor.cpp */; }; 81BE20D211F4BC3200915DFA /* JSIDBCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 81BE20A711F4B66F00915DFA /* JSIDBCursor.cpp */; };
81BE20D311F4BC3200915DFA /* JSIDBCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 81BE20A811F4B66F00915DFA /* JSIDBCursor.h */; }; 81BE20D311F4BC3200915DFA /* JSIDBCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 81BE20A811F4B66F00915DFA /* JSIDBCursor.h */; };
81F65FF613788FAA00FF6F2D /* DragState.h in Headers */ = {isa = PBXBuildFile; fileRef = 81F65FF513788FAA00FF6F2D /* DragState.h */; }; 81F65FF613788FAA00FF6F2D /* DragState.h in Headers */ = {isa = PBXBuildFile; fileRef = 81F65FF513788FAA00FF6F2D /* DragState.h */; settings = {ATTRIBUTES = (Private, ); }; };
82AB1743124B99EC00C5069D /* InspectorCSSAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 82AB1741124B99EC00C5069D /* InspectorCSSAgent.cpp */; }; 82AB1743124B99EC00C5069D /* InspectorCSSAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 82AB1741124B99EC00C5069D /* InspectorCSSAgent.cpp */; };
82AB1744124B99EC00C5069D /* InspectorCSSAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 82AB1742124B99EC00C5069D /* InspectorCSSAgent.h */; }; 82AB1744124B99EC00C5069D /* InspectorCSSAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 82AB1742124B99EC00C5069D /* InspectorCSSAgent.h */; };
82AB1773125C826700C5069D /* InspectorStyleSheet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 82AB176F125C826700C5069D /* InspectorStyleSheet.cpp */; }; 82AB1773125C826700C5069D /* InspectorStyleSheet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 82AB176F125C826700C5069D /* InspectorStyleSheet.cpp */; };
...@@ -569,71 +569,46 @@ bool DragController::tryDHTMLDrag(DragData* dragData, DragOperation& operation) ...@@ -569,71 +569,46 @@ bool DragController::tryDHTMLDrag(DragData* dragData, DragOperation& operation)
return true; return true;
} }
Node* DragController::draggableNode(const Frame* src, Node* startNode, bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const Node* DragController::draggableNode(const Frame* src, Node* startNode, const IntPoint& dragOrigin, DragState& state) const
{ {
if (!dhtmlOK && !uaOK) state.m_dragType = (src->selection()->contains(dragOrigin)) ? DragSourceActionSelection : DragSourceActionNone;
return 0;
for (const RenderObject* renderer = startNode->renderer(); renderer; renderer = renderer->parent()) { for (const RenderObject* renderer = startNode->renderer(); renderer; renderer = renderer->parent()) {
Node* node = renderer->node(); Node* node = renderer->node();
if (node && node->nodeType() == Node::TEXT_NODE) { if (!node)
// Since there's no way for the author to address the -webkit-user-drag style for a text node, // Anonymous render blocks don't correspond to actual DOM nodes, so we skip over them
// we use our own judgement. // for the purposes of finding a draggable node.
if (uaOK && mayStartDragAtEventLocation(src, IntPoint(x, y), node)) { continue;
dhtmlWillDrag = false; if (!(state.m_dragType & DragSourceActionSelection) && node->isTextNode() && node->canStartSelection())
return node; // In this case we have a click in the unselected portion of text. If this text is
} // selectable, we want to start the selection process instead of looking for a parent
if (node->canStartSelection()) // to try to drag.
// In this case we have a click in the unselected portion of text. If this text is return 0;
// selectable, we want to start the selection process instead of looking for a parent if (node->isElementNode()) {
// to try to drag.
return 0;
} else {
EUserDrag dragMode = renderer->style()->userDrag(); EUserDrag dragMode = renderer->style()->userDrag();
if (dhtmlOK && dragMode == DRAG_ELEMENT) { if ((m_dragSourceAction & DragSourceActionDHTML) && dragMode == DRAG_ELEMENT) {
dhtmlWillDrag = true; state.m_dragType = static_cast<DragSourceAction>(state.m_dragType | DragSourceActionDHTML);
return node; return node;
} }
if (uaOK && dragMode == DRAG_AUTO && mayStartDragAtEventLocation(src, IntPoint(x, y), node)) { if (dragMode == DRAG_AUTO) {
dhtmlWillDrag = false; if ((m_dragSourceAction & DragSourceActionImage)
return node; && node->hasTagName(HTMLNames::imgTag)
&& src->settings()->loadsImagesAutomatically()) {
state.m_dragType = static_cast<DragSourceAction>(state.m_dragType | DragSourceActionImage);
return node;
}
if ((m_dragSourceAction & DragSourceActionLink)
&& node->hasTagName(HTMLNames::aTag)
&& static_cast<HTMLAnchorElement*>(node)->isLiveLink()) {
state.m_dragType = static_cast<DragSourceAction>(state.m_dragType | DragSourceActionLink);
return node;
}
} }
} }
} }
return 0;
}
bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPoint& framePos, Node* node) const
{
ASSERT(frame);
ASSERT(frame->settings());
if (!frame->view() || !frame->contentRenderer())
return false;
HitTestResult mouseDownTarget = HitTestResult(framePos);
mouseDownTarget = frame->eventHandler()->hitTestResultAtPoint(framePos, true); // We either have nothing to drag or we have a selection and we're not over a draggable element.
if (node) return (state.m_dragType & DragSourceActionSelection) ? startNode : 0;
mouseDownTarget.setInnerNonSharedNode(node);
if (mouseDownTarget.image()
&& !mouseDownTarget.absoluteImageURL().isEmpty()
&& frame->settings()->loadsImagesAutomatically()
&& m_dragSourceAction & DragSourceActionImage)
return true;
if (!mouseDownTarget.absoluteLinkURL().isEmpty()
&& m_dragSourceAction & DragSourceActionLink
&& mouseDownTarget.isLiveLink()
&& mouseDownTarget.URLElement()->renderer() && mouseDownTarget.URLElement()->renderer()->style()->userDrag() != DRAG_NONE)
return true;
if (mouseDownTarget.isSelected()
&& m_dragSourceAction & DragSourceActionSelection)
return true;
return false;
} }
static CachedImage* getCachedImage(Element* element) static CachedImage* getCachedImage(Element* element)
...@@ -695,19 +670,21 @@ static IntPoint dragLocForSelectionDrag(Frame* src) ...@@ -695,19 +670,21 @@ static IntPoint dragLocForSelectionDrag(Frame* src)
return IntPoint(xpos, ypos); return IntPoint(xpos, ypos);
} }
bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin, bool isDHTMLDrag) bool DragController::startDrag(Frame* src, const DragState& state, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin)
{ {
ASSERT(src); ASSERT(src);
ASSERT(clipboard);
if (!src->view() || !src->contentRenderer()) if (!src->view() || !src->contentRenderer())
return false; return false;
HitTestResult dragSource = HitTestResult(dragOrigin); HitTestResult hitTestResult = src->eventHandler()->hitTestResultAtPoint(dragOrigin, true);
dragSource = src->eventHandler()->hitTestResultAtPoint(dragOrigin, true); if (!state.m_dragSrc->contains(hitTestResult.innerNode()))
KURL linkURL = dragSource.absoluteLinkURL(); // The original node being dragged isn't under the drag origin anymore... maybe it was
KURL imageURL = dragSource.absoluteImageURL(); // hidden or moved out from under the cursor. Regardless, we don't want to start a drag on
bool isSelected = dragSource.isSelected(); // something that's not actually under the drag origin.
return false;
KURL linkURL = hitTestResult.absoluteLinkURL();
KURL imageURL = hitTestResult.absoluteImageURL();
IntPoint mouseDraggedPoint = src->view()->windowToContents(dragEvent.pos()); IntPoint mouseDraggedPoint = src->view()->windowToContents(dragEvent.pos());
...@@ -718,14 +695,14 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s ...@@ -718,14 +695,14 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s
IntPoint dragLoc(0, 0); IntPoint dragLoc(0, 0);
IntPoint dragImageOffset(0, 0); IntPoint dragImageOffset(0, 0);
if (isDHTMLDrag) Clipboard* clipboard = state.m_dragClipboard.get();
if (state.m_dragType == DragSourceActionDHTML)
dragImage = clipboard->createDragImage(dragImageOffset); dragImage = clipboard->createDragImage(dragImageOffset);
else { if (state.m_dragType == DragSourceActionSelection || !imageURL.isEmpty() || !linkURL.isEmpty())
// This drag operation is not a DHTML drag and may go outside the WebView. // Selection, image, and link drags receive a default set of allowed drag operations that
// We provide a default set of allowed drag operations that follows from: // follows from:
// http://trac.webkit.org/browser/trunk/WebKit/mac/WebView/WebHTMLView.mm?rev=48526#L3430 // http://trac.webkit.org/browser/trunk/WebKit/mac/WebView/WebHTMLView.mm?rev=48526#L3430
m_sourceDragOperation = (DragOperation)(DragOperationGeneric | DragOperationCopy); m_sourceDragOperation = static_cast<DragOperation>(m_sourceDragOperation | DragOperationGeneric | DragOperationCopy);
}
// We allow DHTML/JS to set the drag image, even if its a link, image or text we're dragging. // We allow DHTML/JS to set the drag image, even if its a link, image or text we're dragging.
// This is in the spirit of the IE API, which allows overriding of pasteboard data and DragOp. // This is in the spirit of the IE API, which allows overriding of pasteboard data and DragOp.
...@@ -736,26 +713,44 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s ...@@ -736,26 +713,44 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s
bool startedDrag = true; // optimism - we almost always manage to start the drag bool startedDrag = true; // optimism - we almost always manage to start the drag
Node* node = dragSource.innerNonSharedNode(); Node* node = state.m_dragSrc.get();
Image* image = getImage(static_cast<Element*>(node)); Image* image = getImage(static_cast<Element*>(node));
if (!imageURL.isEmpty() && node && node->isElementNode() && image if (state.m_dragType == DragSourceActionSelection) {
&& (m_dragSourceAction & DragSourceActionImage)) { if (!clipboard->hasData()) {
if (isNodeInTextFormControl(src->selection()->start().deprecatedNode()))
clipboard->writePlainText(src->editor()->selectedText());
else {
RefPtr<Range> selectionRange = src->selection()->toNormalizedRange();
ASSERT(selectionRange);
clipboard->writeRange(selectionRange.get(), src);
}
}
m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard);
if (!dragImage) {
dragImage = createDragImageForSelection(src);
dragLoc = dragLocForSelectionDrag(src);
m_dragOffset = IntPoint(dragOrigin.x() - dragLoc.x(), dragOrigin.y() - dragLoc.y());
}
doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
} else if (!imageURL.isEmpty() && node && node->isElementNode() && image
&& (m_dragSourceAction & DragSourceActionImage)) {
// We shouldn't be starting a drag for an image that can't provide an extension. // We shouldn't be starting a drag for an image that can't provide an extension.
// This is an early detection for problems encountered later upon drop. // This is an early detection for problems encountered later upon drop.
ASSERT(!image->filenameExtension().isEmpty()); ASSERT(!image->filenameExtension().isEmpty());
Element* element = static_cast<Element*>(node); Element* element = static_cast<Element*>(node);
if (!clipboard->hasData()) { if (!clipboard->hasData()) {
m_draggingImageURL = imageURL; m_draggingImageURL = imageURL;
prepareClipboardForImageDrag(src, clipboard, element, linkURL, imageURL, dragSource.altDisplayString()); prepareClipboardForImageDrag(src, clipboard, element, linkURL, imageURL, hitTestResult.altDisplayString());
} }
m_client->willPerformDragSourceAction(DragSourceActionImage, dragOrigin, clipboard); m_client->willPerformDragSourceAction(DragSourceActionImage, dragOrigin, clipboard);
if (!dragImage) { if (!dragImage) {
IntRect imageRect = dragSource.imageRect(); IntRect imageRect = hitTestResult.imageRect();
imageRect.setLocation(m_page->mainFrame()->view()->windowToContents(src->view()->contentsToWindow(imageRect.location()))); imageRect.setLocation(m_page->mainFrame()->view()->windowToContents(src->view()->contentsToWindow(imageRect.location())));
doImageDrag(element, dragOrigin, dragSource.imageRect(), clipboard, src, m_dragOffset); doImageDrag(element, dragOrigin, hitTestResult.imageRect(), clipboard, src, m_dragOffset);
} else } else
// DHTML defined drag image // DHTML defined drag image
doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false); doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
...@@ -764,7 +759,7 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s ...@@ -764,7 +759,7 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s
if (!clipboard->hasData()) if (!clipboard->hasData())
// Simplify whitespace so the title put on the clipboard resembles what the user sees // Simplify whitespace so the title put on the clipboard resembles what the user sees
// on the web page. This includes replacing newlines with spaces. // on the web page. This includes replacing newlines with spaces.
clipboard->writeURL(linkURL, dragSource.textContent().simplifyWhiteSpace(), src); clipboard->writeURL(linkURL, hitTestResult.textContent().simplifyWhiteSpace(), src);
if (src->selection()->isCaret() && src->selection()->isContentEditable()) { if (src->selection()->isCaret() && src->selection()->isContentEditable()) {
// a user can initiate a drag on a link without having any text // a user can initiate a drag on a link without having any text
...@@ -778,37 +773,19 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s ...@@ -778,37 +773,19 @@ bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation s
m_client->willPerformDragSourceAction(DragSourceActionLink, dragOrigin, clipboard); m_client->willPerformDragSourceAction(DragSourceActionLink, dragOrigin, clipboard);
if (!dragImage) { if (!dragImage) {
dragImage = createDragImageForLink(linkURL, dragSource.textContent(), src); dragImage = createDragImageForLink(linkURL, hitTestResult.textContent(), src);
IntSize size = dragImageSize(dragImage); IntSize size = dragImageSize(dragImage);
m_dragOffset = IntPoint(-size.width() / 2, -LinkDragBorderInset); m_dragOffset = IntPoint(-size.width() / 2, -LinkDragBorderInset);
dragLoc = IntPoint(mouseDraggedPoint.x() + m_dragOffset.x(), mouseDraggedPoint.y() + m_dragOffset.y()); dragLoc = IntPoint(mouseDraggedPoint.x() + m_dragOffset.x(), mouseDraggedPoint.y() + m_dragOffset.y());
} }
doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true); doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true);
} else if (isSelected && (m_dragSourceAction & DragSourceActionSelection)) { } else if (state.m_dragType == DragSourceActionDHTML) {
if (!clipboard->hasData()) {
if (isNodeInTextFormControl(src->selection()->start().deprecatedNode()))
clipboard->writePlainText(src->editor()->selectedText());
else {
RefPtr<Range> selectionRange = src->selection()->toNormalizedRange();
ASSERT(selectionRange);
clipboard->writeRange(selectionRange.get(), src);
}
}
m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard);
if (!dragImage) {
dragImage = createDragImageForSelection(src);
dragLoc = dragLocForSelectionDrag(src);
m_dragOffset = IntPoint((int)(dragOrigin.x() - dragLoc.x()), (int)(dragOrigin.y() - dragLoc.y()));
}
doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
} else if (isDHTMLDrag) {
ASSERT(m_dragSourceAction & DragSourceActionDHTML); ASSERT(m_dragSourceAction & DragSourceActionDHTML);
m_client->willPerformDragSourceAction(DragSourceActionDHTML, dragOrigin, clipboard); m_client->willPerformDragSourceAction(DragSourceActionDHTML, dragOrigin, clipboard);
doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false); doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
} else { } else {
// Only way I know to get here is if to get here is if the original element clicked on in the mousedown is no longer // draggableNode() determined an image or link node was draggable, but it turns out the
// under the mousedown point, so linkURL, imageURL and isSelected are all false/empty. // image or link had no URL, so there is nothing to drag.
startedDrag = false; startedDrag = false;
} }
......
...@@ -37,6 +37,7 @@ namespace WebCore { ...@@ -37,6 +37,7 @@ namespace WebCore {
class Document; class Document;
class DragClient; class DragClient;
class DragData; class DragData;
struct DragState;
class Element; class Element;
class Frame; class Frame;
class FrameSelection; class FrameSelection;
...@@ -75,13 +76,12 @@ namespace WebCore { ...@@ -75,13 +76,12 @@ namespace WebCore {
DragDestinationAction dragDestinationAction() const { return m_dragDestinationAction; } DragDestinationAction dragDestinationAction() const { return m_dragDestinationAction; }
DragSourceAction delegateDragSourceAction(const IntPoint& pagePoint); DragSourceAction delegateDragSourceAction(const IntPoint& pagePoint);
Node* draggableNode(const Frame*, Node*, bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const; Node* draggableNode(const Frame*, Node*, const IntPoint&, DragState&) const;
bool mayStartDragAtEventLocation(const Frame*, const IntPoint& framePos, Node*) const;
void dragEnded(); void dragEnded();
void placeDragCaret(const IntPoint&); void placeDragCaret(const IntPoint&);
bool startDrag(Frame* src, Clipboard*, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin, bool isDHTMLDrag); bool startDrag(Frame* src, const DragState&, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin);
static const IntSize& maxDragImageSize(); static const IntSize& maxDragImageSize();
static const int LinkDragBorderInset; static const int LinkDragBorderInset;
......
...@@ -26,23 +26,29 @@ ...@@ -26,23 +26,29 @@
#ifndef DragState_h #ifndef DragState_h
#define DragState_h #define DragState_h
#include "DragActions.h"
#include <wtf/Forward.h> #include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
#include <wtf/RefPtr.h> #include <wtf/RefPtr.h>
namespace WebCore { namespace WebCore {
class Clipboard;
class Node;
struct DragState { struct DragState {
WTF_MAKE_NONCOPYABLE(DragState); WTF_MAKE_NONCOPYABLE(DragState);
WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_FAST_ALLOCATED;
public: public:
enum EventDispatchPolicy {