| Index: Source/core/page/DragController.cpp
|
| diff --git a/Source/core/page/DragController.cpp b/Source/core/page/DragController.cpp
|
| index 3dc03d21ba91ea2e7244b7eee0649b39065a37fd..8e0b8c7b3045e8595b62221de001df3998a1b596 100644
|
| --- a/Source/core/page/DragController.cpp
|
| +++ b/Source/core/page/DragController.cpp
|
| @@ -620,45 +620,77 @@ bool DragController::tryDHTMLDrag(DragData* dragData, DragOperation& operation)
|
| return true;
|
| }
|
|
|
| -Node* DragController::draggableNode(const Frame* src, Node* startNode, const IntPoint& dragOrigin, DragState& state) const
|
| +Node* DragController::draggableNode(const Frame* src, Node* startNode, const IntPoint& dragOrigin, SelectionDragPolicy selectionDragPolicy, DragSourceAction& dragType) const
|
| {
|
| - state.m_dragType = (src->selection().contains(dragOrigin)) ? DragSourceActionSelection : DragSourceActionNone;
|
| + if (src->selection().contains(dragOrigin)) {
|
| + dragType = DragSourceActionSelection;
|
| + if (selectionDragPolicy == ImmediateSelectionDragResolution)
|
| + return startNode;
|
| + } else {
|
| + dragType = DragSourceActionNone;
|
| + }
|
|
|
| + Node* node = 0;
|
| + DragSourceAction candidateDragType = DragSourceActionNone;
|
| for (const RenderObject* renderer = startNode->renderer(); renderer; renderer = renderer->parent()) {
|
| - Node* node = renderer->nonPseudoNode();
|
| - if (!node)
|
| + node = renderer->nonPseudoNode();
|
| + if (!node) {
|
| // Anonymous render blocks don't correspond to actual DOM nodes, so we skip over them
|
| // for the purposes of finding a draggable node.
|
| continue;
|
| - if (!(state.m_dragType & DragSourceActionSelection) && node->isTextNode() && node->canStartSelection())
|
| + }
|
| + if (dragType != DragSourceActionSelection && node->isTextNode() && node->canStartSelection()) {
|
| // 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
|
| // to try to drag.
|
| return 0;
|
| + }
|
| if (node->isElementNode()) {
|
| EUserDrag dragMode = renderer->style()->userDrag();
|
| if (dragMode == DRAG_NONE)
|
| continue;
|
| + // Even if the image is part of a selection, we always only drag the image in this case.
|
| if (renderer->isImage()
|
| && src->settings()
|
| && src->settings()->loadsImagesAutomatically()) {
|
| - state.m_dragType = static_cast<DragSourceAction>(state.m_dragType | DragSourceActionImage);
|
| + dragType = DragSourceActionImage;
|
| return node;
|
| }
|
| + // Other draggable elements are considered unselectable.
|
| if (isHTMLAnchorElement(node)
|
| && toHTMLAnchorElement(node)->isLiveLink()) {
|
| - state.m_dragType = static_cast<DragSourceAction>(state.m_dragType | DragSourceActionLink);
|
| - return node;
|
| + candidateDragType = DragSourceActionLink;
|
| + break;
|
| }
|
| if (dragMode == DRAG_ELEMENT) {
|
| - state.m_dragType = static_cast<DragSourceAction>(state.m_dragType | DragSourceActionDHTML);
|
| - return node;
|
| + candidateDragType = DragSourceActionDHTML;
|
| + break;
|
| }
|
| }
|
| }
|
|
|
| - // We either have nothing to drag or we have a selection and we're not over a draggable element.
|
| - return (state.m_dragType & DragSourceActionSelection) ? startNode : 0;
|
| + if (candidateDragType == DragSourceActionNone) {
|
| + // Either:
|
| + // 1) Nothing under the cursor is considered draggable, so we bail out.
|
| + // 2) There was a selection under the cursor but selectionDragPolicy is set to
|
| + // DelayedSelectionDragResolution and no other draggable element could be found, so bail
|
| + // out and allow text selection to start at the cursor instead.
|
| + return 0;
|
| + }
|
| +
|
| + ASSERT(node);
|
| + if (dragType == DragSourceActionSelection) {
|
| + // Dragging unselectable elements in a selection has special behavior if selectionDragPolicy
|
| + // is DelayedSelectionDragResolution and this drag was flagged as a potential selection
|
| + // drag. In that case, don't allow selection and just drag the entire selection instead.
|
| + ASSERT(selectionDragPolicy == DelayedSelectionDragResolution);
|
| + node = startNode;
|
| + } else {
|
| + // If the cursor isn't over a selection, then just drag the node we found earlier.
|
| + ASSERT(dragType == DragSourceActionNone);
|
| + dragType = candidateDragType;
|
| + }
|
| + return node;
|
| }
|
|
|
| static ImageResource* getImageResource(Element* element)
|
| @@ -699,7 +731,7 @@ bool DragController::populateDragClipboard(Frame* src, const DragState& state, c
|
| if (!src->view() || !src->contentRenderer())
|
| return false;
|
|
|
| - HitTestResult hitTestResult = src->eventHandler().hitTestResultAtPoint(dragOrigin, HitTestRequest::ReadOnly | HitTestRequest::Active);
|
| + HitTestResult hitTestResult = src->eventHandler().hitTestResultAtPoint(dragOrigin);
|
| // FIXME: Can this even happen? I guess it's possible, but should verify
|
| // with a layout test.
|
| if (!state.m_dragSrc->contains(hitTestResult.innerNode())) {
|
| @@ -820,11 +852,12 @@ bool DragController::startDrag(Frame* src, const DragState& state, const Platfor
|
| return false;
|
|
|
| HitTestResult hitTestResult = src->eventHandler().hitTestResultAtPoint(dragOrigin);
|
| - if (!state.m_dragSrc->contains(hitTestResult.innerNode()))
|
| + if (!state.m_dragSrc->contains(hitTestResult.innerNode())) {
|
| // The original node being dragged isn't under the drag origin anymore... maybe it was
|
| // hidden or moved out from under the cursor. Regardless, we don't want to start a drag on
|
| // something that's not actually under the drag origin.
|
| return false;
|
| + }
|
| const KURL& linkURL = hitTestResult.absoluteLinkURL();
|
| const KURL& imageURL = hitTestResult.absoluteImageURL();
|
|
|
|
|