Changeset 86472 in webkit
- Timestamp:
- May 13, 2011 4:31:49 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r86467 r86472 1 2011-05-13 Daniel Cheng <dcheng@chromium.org> 2 3 Reviewed by Tony Chang. 4 5 Improve drag start logic 6 https://bugs.webkit.org/show_bug.cgi?id=59409 7 8 Add a new test to test drag start edge cases on Mac (because of a non-zero text drag delay) 9 as well as rebase an existing test. 10 11 * fast/css/user-drag-none.html: Text nodes are no longer draggable. 12 * platform/mac/editing/pasteboard/drag-selections-to-contenteditable-expected.txt: Added. 13 * platform/mac/editing/pasteboard/drag-selections-to-contenteditable.html: Added. 14 1 15 2011-05-13 Anders Carlsson <andersca@apple.com> 2 16 -
trunk/LayoutTests/fast/css/user-drag-none.html
r55353 r86472 20 20 </div> 21 21 22 <div class="box" expect="IMG text textA nil">22 <div class="box" expect="IMG A A A nil"> 23 23 <a href="#"><img src="resources/greenbox.png">x<br><span>y</span></a> 24 24 </div> 25 25 26 <div class="box" expect="IMG text textA nil">26 <div class="box" expect="IMG A A A nil"> 27 27 <a href="#" class="drag-element"><img src="resources/greenbox.png">x<br><span>y</span></a> 28 28 </div> … … 32 32 </div> 33 33 34 <div class="box" expect="A text textA nil">34 <div class="box" expect="A A A A nil"> 35 35 <a href="#"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a> 36 36 </div> 37 37 38 <div class="box" expect="A text textA nil">38 <div class="box" expect="A A A A nil"> 39 39 <a href="#" class="drag-element"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a> 40 40 </div> … … 44 44 </div> 45 45 46 <div class="box drag-element" expect="A text textA DIV">46 <div class="box drag-element" expect="A A A A DIV"> 47 47 <a href="#"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a> 48 48 </div> 49 49 50 <div class="box drag-element" expect="A text textA DIV">50 <div class="box drag-element" expect="A A A A DIV"> 51 51 <a href="#" class="drag-element"><img class="drag-none" src="resources/greenbox.png">x<br><span>y</span></a> 52 52 </div> -
trunk/Source/WebCore/ChangeLog
r86469 r86472 1 2011-05-13 Daniel Cheng <dcheng@chromium.org> 2 3 Reviewed by Tony Chang. 4 5 Improve drag start logic 6 https://bugs.webkit.org/show_bug.cgi?id=59409 7 8 Rewrite and simplify the dragging logic to better match IE, Firefox, and the behavior 9 defined in the spec. Among other things: 10 - draggableNode() no longer returns text nodes when dragging anchors. 11 - When starting a drag over an image in a selection, prefer to drag the selection. 12 - Several redundant hit tests have been removed. 13 - Minor refactoring to make the logic easier to follow. 14 15 Test: platform/mac/editing/pasteboard/drag-selections-to-contenteditable.html 16 17 * WebCore.xcodeproj/project.pbxproj: 18 * page/DragController.cpp: 19 (WebCore::DragController::draggableNode): 20 (WebCore::DragController::startDrag): 21 * page/DragController.h: 22 * page/DragState.h: 23 (WebCore::DragState::shouldDispatchEvents): 24 * page/EventHandler.cpp: 25 (WebCore::EventHandler::EventHandler): 26 (WebCore::EventHandler::eventMayStartDrag): 27 (WebCore::EventHandler::updateDragSourceActionsAllowed): 28 (WebCore::EventHandler::updateDragAndDrop): 29 (WebCore::EventHandler::cancelDragAndDrop): 30 (WebCore::EventHandler::dragHysteresisExceeded): 31 (WebCore::EventHandler::dragSourceEndedAt): 32 (WebCore::ExactlyOneBitSet): 33 (WebCore::EventHandler::handleDrag): 34 * page/EventHandler.h: 35 1 36 2011-05-13 Oliver Hunt <oliver@apple.com> 2 37 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r86451 r86472 1676 1676 81BE20D211F4BC3200915DFA /* JSIDBCursor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 81BE20A711F4B66F00915DFA /* JSIDBCursor.cpp */; }; 1677 1677 81BE20D311F4BC3200915DFA /* JSIDBCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 81BE20A811F4B66F00915DFA /* JSIDBCursor.h */; }; 1678 81F65FF613788FAA00FF6F2D /* DragState.h in Headers */ = {isa = PBXBuildFile; fileRef = 81F65FF513788FAA00FF6F2D /* DragState.h */; };1678 81F65FF613788FAA00FF6F2D /* DragState.h in Headers */ = {isa = PBXBuildFile; fileRef = 81F65FF513788FAA00FF6F2D /* DragState.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1679 1679 82AB1743124B99EC00C5069D /* InspectorCSSAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 82AB1741124B99EC00C5069D /* InspectorCSSAgent.cpp */; }; 1680 1680 82AB1744124B99EC00C5069D /* InspectorCSSAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 82AB1742124B99EC00C5069D /* InspectorCSSAgent.h */; }; -
trunk/Source/WebCore/page/DragController.cpp
r86128 r86472 570 570 } 571 571 572 Node* DragController::draggableNode(const Frame* src, Node* startNode, bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const 573 { 574 if (!dhtmlOK && !uaOK) 575 return 0; 572 Node* DragController::draggableNode(const Frame* src, Node* startNode, const IntPoint& dragOrigin, DragState& state) const 573 { 574 state.m_dragType = (src->selection()->contains(dragOrigin)) ? DragSourceActionSelection : DragSourceActionNone; 576 575 577 576 for (const RenderObject* renderer = startNode->renderer(); renderer; renderer = renderer->parent()) { 578 577 Node* node = renderer->node(); 579 if (node && node->nodeType() == Node::TEXT_NODE) { 580 // Since there's no way for the author to address the -webkit-user-drag style for a text node, 581 // we use our own judgement. 582 if (uaOK && mayStartDragAtEventLocation(src, IntPoint(x, y), node)) { 583 dhtmlWillDrag = false; 578 if (!node) 579 // Anonymous render blocks don't correspond to actual DOM nodes, so we skip over them 580 // for the purposes of finding a draggable node. 581 continue; 582 if (!(state.m_dragType & DragSourceActionSelection) && node->isTextNode() && node->canStartSelection()) 583 // In this case we have a click in the unselected portion of text. If this text is 584 // selectable, we want to start the selection process instead of looking for a parent 585 // to try to drag. 586 return 0; 587 if (node->isElementNode()) { 588 EUserDrag dragMode = renderer->style()->userDrag(); 589 if ((m_dragSourceAction & DragSourceActionDHTML) && dragMode == DRAG_ELEMENT) { 590 state.m_dragType = static_cast<DragSourceAction>(state.m_dragType | DragSourceActionDHTML); 584 591 return node; 585 592 } 586 if (node->canStartSelection()) 587 // In this case we have a click in the unselected portion of text. If this text is 588 // selectable, we want to start the selection process instead of looking for a parent 589 // to try to drag. 590 return 0; 591 } else { 592 EUserDrag dragMode = renderer->style()->userDrag(); 593 if (dhtmlOK && dragMode == DRAG_ELEMENT) { 594 dhtmlWillDrag = true; 595 return node; 593 if (dragMode == DRAG_AUTO) { 594 if ((m_dragSourceAction & DragSourceActionImage) 595 && node->hasTagName(HTMLNames::imgTag) 596 && src->settings()->loadsImagesAutomatically()) { 597 state.m_dragType = static_cast<DragSourceAction>(state.m_dragType | DragSourceActionImage); 598 return node; 599 } 600 if ((m_dragSourceAction & DragSourceActionLink) 601 && node->hasTagName(HTMLNames::aTag) 602 && static_cast<HTMLAnchorElement*>(node)->isLiveLink()) { 603 state.m_dragType = static_cast<DragSourceAction>(state.m_dragType | DragSourceActionLink); 604 return node; 605 } 596 606 } 597 if (uaOK && dragMode == DRAG_AUTO && mayStartDragAtEventLocation(src, IntPoint(x, y), node)) { 598 dhtmlWillDrag = false; 599 return node; 600 } 601 } 602 } 603 return 0; 604 } 605 606 bool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPoint& framePos, Node* node) const 607 { 608 ASSERT(frame); 609 ASSERT(frame->settings()); 610 611 if (!frame->view() || !frame->contentRenderer()) 612 return false; 613 614 HitTestResult mouseDownTarget = HitTestResult(framePos); 615 616 mouseDownTarget = frame->eventHandler()->hitTestResultAtPoint(framePos, true); 617 if (node) 618 mouseDownTarget.setInnerNonSharedNode(node); 619 620 if (mouseDownTarget.image() 621 && !mouseDownTarget.absoluteImageURL().isEmpty() 622 && frame->settings()->loadsImagesAutomatically() 623 && m_dragSourceAction & DragSourceActionImage) 624 return true; 625 626 if (!mouseDownTarget.absoluteLinkURL().isEmpty() 627 && m_dragSourceAction & DragSourceActionLink 628 && mouseDownTarget.isLiveLink() 629 && mouseDownTarget.URLElement()->renderer() && mouseDownTarget.URLElement()->renderer()->style()->userDrag() != DRAG_NONE) 630 return true; 631 632 if (mouseDownTarget.isSelected() 633 && m_dragSourceAction & DragSourceActionSelection) 634 return true; 635 636 return false; 607 } 608 } 609 610 // We either have nothing to drag or we have a selection and we're not over a draggable element. 611 return (state.m_dragType & DragSourceActionSelection) ? startNode : 0; 637 612 } 638 613 … … 696 671 } 697 672 698 bool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin, bool isDHTMLDrag)673 bool DragController::startDrag(Frame* src, const DragState& state, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin) 699 674 { 700 675 ASSERT(src); 701 ASSERT(clipboard);702 676 703 677 if (!src->view() || !src->contentRenderer()) 704 678 return false; 705 679 706 HitTestResult dragSource = HitTestResult(dragOrigin); 707 dragSource = src->eventHandler()->hitTestResultAtPoint(dragOrigin, true); 708 KURL linkURL = dragSource.absoluteLinkURL(); 709 KURL imageURL = dragSource.absoluteImageURL(); 710 bool isSelected = dragSource.isSelected(); 680 HitTestResult hitTestResult = src->eventHandler()->hitTestResultAtPoint(dragOrigin, true); 681 if (!state.m_dragSrc->contains(hitTestResult.innerNode())) 682 // The original node being dragged isn't under the drag origin anymore... maybe it was 683 // hidden or moved out from under the cursor. Regardless, we don't want to start a drag on 684 // something that's not actually under the drag origin. 685 return false; 686 KURL linkURL = hitTestResult.absoluteLinkURL(); 687 KURL imageURL = hitTestResult.absoluteImageURL(); 711 688 712 689 IntPoint mouseDraggedPoint = src->view()->windowToContents(dragEvent.pos()); … … 719 696 IntPoint dragImageOffset(0, 0); 720 697 721 if (isDHTMLDrag) 698 Clipboard* clipboard = state.m_dragClipboard.get(); 699 if (state.m_dragType == DragSourceActionDHTML) 722 700 dragImage = clipboard->createDragImage(dragImageOffset); 723 else {724 // This drag operation is not a DHTML drag and may go outside the WebView.725 // We provide a default set of allowed drag operations thatfollows from:701 if (state.m_dragType == DragSourceActionSelection || !imageURL.isEmpty() || !linkURL.isEmpty()) 702 // Selection, image, and link drags receive a default set of allowed drag operations that 703 // follows from: 726 704 // http://trac.webkit.org/browser/trunk/WebKit/mac/WebView/WebHTMLView.mm?rev=48526#L3430 727 m_sourceDragOperation = (DragOperation)(DragOperationGeneric | DragOperationCopy); 728 } 705 m_sourceDragOperation = static_cast<DragOperation>(m_sourceDragOperation | DragOperationGeneric | DragOperationCopy); 729 706 730 707 // We allow DHTML/JS to set the drag image, even if its a link, image or text we're dragging. … … 737 714 bool startedDrag = true; // optimism - we almost always manage to start the drag 738 715 739 Node* node = dragSource.innerNonSharedNode();716 Node* node = state.m_dragSrc.get(); 740 717 741 718 Image* image = getImage(static_cast<Element*>(node)); 742 if (!imageURL.isEmpty() && node && node->isElementNode() && image 743 && (m_dragSourceAction & DragSourceActionImage)) { 719 if (state.m_dragType == DragSourceActionSelection) { 720 if (!clipboard->hasData()) { 721 if (isNodeInTextFormControl(src->selection()->start().deprecatedNode())) 722 clipboard->writePlainText(src->editor()->selectedText()); 723 else { 724 RefPtr<Range> selectionRange = src->selection()->toNormalizedRange(); 725 ASSERT(selectionRange); 726 727 clipboard->writeRange(selectionRange.get(), src); 728 } 729 } 730 m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard); 731 if (!dragImage) { 732 dragImage = createDragImageForSelection(src); 733 dragLoc = dragLocForSelectionDrag(src); 734 m_dragOffset = IntPoint(dragOrigin.x() - dragLoc.x(), dragOrigin.y() - dragLoc.y()); 735 } 736 doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false); 737 } else if (!imageURL.isEmpty() && node && node->isElementNode() && image 738 && (m_dragSourceAction & DragSourceActionImage)) { 744 739 // We shouldn't be starting a drag for an image that can't provide an extension. 745 740 // This is an early detection for problems encountered later upon drop. … … 748 743 if (!clipboard->hasData()) { 749 744 m_draggingImageURL = imageURL; 750 prepareClipboardForImageDrag(src, clipboard, element, linkURL, imageURL, dragSource.altDisplayString());745 prepareClipboardForImageDrag(src, clipboard, element, linkURL, imageURL, hitTestResult.altDisplayString()); 751 746 } 752 747 … … 754 749 755 750 if (!dragImage) { 756 IntRect imageRect = dragSource.imageRect();751 IntRect imageRect = hitTestResult.imageRect(); 757 752 imageRect.setLocation(m_page->mainFrame()->view()->windowToContents(src->view()->contentsToWindow(imageRect.location()))); 758 doImageDrag(element, dragOrigin, dragSource.imageRect(), clipboard, src, m_dragOffset);753 doImageDrag(element, dragOrigin, hitTestResult.imageRect(), clipboard, src, m_dragOffset); 759 754 } else 760 755 // DHTML defined drag image … … 765 760 // Simplify whitespace so the title put on the clipboard resembles what the user sees 766 761 // on the web page. This includes replacing newlines with spaces. 767 clipboard->writeURL(linkURL, dragSource.textContent().simplifyWhiteSpace(), src);762 clipboard->writeURL(linkURL, hitTestResult.textContent().simplifyWhiteSpace(), src); 768 763 769 764 if (src->selection()->isCaret() && src->selection()->isContentEditable()) { … … 779 774 m_client->willPerformDragSourceAction(DragSourceActionLink, dragOrigin, clipboard); 780 775 if (!dragImage) { 781 dragImage = createDragImageForLink(linkURL, dragSource.textContent(), src);776 dragImage = createDragImageForLink(linkURL, hitTestResult.textContent(), src); 782 777 IntSize size = dragImageSize(dragImage); 783 778 m_dragOffset = IntPoint(-size.width() / 2, -LinkDragBorderInset); … … 785 780 } 786 781 doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true); 787 } else if (isSelected && (m_dragSourceAction & DragSourceActionSelection)) { 788 if (!clipboard->hasData()) { 789 if (isNodeInTextFormControl(src->selection()->start().deprecatedNode())) 790 clipboard->writePlainText(src->editor()->selectedText()); 791 else { 792 RefPtr<Range> selectionRange = src->selection()->toNormalizedRange(); 793 ASSERT(selectionRange); 794 795 clipboard->writeRange(selectionRange.get(), src); 796 } 797 } 798 m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard); 799 if (!dragImage) { 800 dragImage = createDragImageForSelection(src); 801 dragLoc = dragLocForSelectionDrag(src); 802 m_dragOffset = IntPoint((int)(dragOrigin.x() - dragLoc.x()), (int)(dragOrigin.y() - dragLoc.y())); 803 } 804 doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false); 805 } else if (isDHTMLDrag) { 782 } else if (state.m_dragType == DragSourceActionDHTML) { 806 783 ASSERT(m_dragSourceAction & DragSourceActionDHTML); 807 784 m_client->willPerformDragSourceAction(DragSourceActionDHTML, dragOrigin, clipboard); 808 785 doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false); 809 786 } else { 810 // Only way I know to get here is if to get here is if the original element clicked on in the mousedown is no longer811 // under the mousedown point, so linkURL, imageURL and isSelected are all false/empty.787 // draggableNode() determined an image or link node was draggable, but it turns out the 788 // image or link had no URL, so there is nothing to drag. 812 789 startedDrag = false; 813 790 } -
trunk/Source/WebCore/page/DragController.h
r86128 r86472 38 38 class DragClient; 39 39 class DragData; 40 struct DragState; 40 41 class Element; 41 42 class Frame; … … 76 77 DragSourceAction delegateDragSourceAction(const IntPoint& pagePoint); 77 78 78 Node* draggableNode(const Frame*, Node*, bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const; 79 bool mayStartDragAtEventLocation(const Frame*, const IntPoint& framePos, Node*) const; 79 Node* draggableNode(const Frame*, Node*, const IntPoint&, DragState&) const; 80 80 void dragEnded(); 81 81 82 82 void placeDragCaret(const IntPoint&); 83 83 84 bool startDrag(Frame* src, Clipboard*, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin, bool isDHTMLDrag);84 bool startDrag(Frame* src, const DragState&, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin); 85 85 static const IntSize& maxDragImageSize(); 86 86 -
trunk/Source/WebCore/page/DragState.h
r86129 r86472 27 27 #define DragState_h 28 28 29 #include "DragActions.h" 29 30 #include <wtf/Forward.h> 31 #include <wtf/Noncopyable.h> 30 32 #include <wtf/RefPtr.h> 31 33 32 34 namespace WebCore { 35 36 class Clipboard; 37 class Node; 33 38 34 39 struct DragState { … … 36 41 WTF_MAKE_FAST_ALLOCATED; 37 42 public: 43 enum EventDispatchPolicy { 44 DoNotDispatchEvents, 45 DispatchEvents, 46 }; 38 47 DragState() { } 48 bool shouldDispatchEvents() const { return m_eventDispatchPolicy == DispatchEvents; } 39 49 RefPtr<Node> m_dragSrc; // element that may be a drag source, for the current mouse gesture 40 bool m_dragSrcIsLink; 41 bool m_dragSrcIsImage; 42 bool m_dragSrcInSelection; 43 bool m_dragSrcMayBeDHTML; 44 bool m_dragSrcMayBeUA; // Are DHTML and/or the UserAgent allowed to drag out? 45 bool m_dragSrcIsDHTML; 50 EventDispatchPolicy m_eventDispatchPolicy; 51 DragSourceAction m_dragType; 46 52 RefPtr<Clipboard> m_dragClipboard; // used on only the source side of dragging 47 53 }; -
trunk/Source/WebCore/page/EventHandler.cpp
r86461 r86472 80 80 #include "WheelEvent.h" 81 81 #include "WindowsKeyboardCodes.h" 82 #include <wtf/Assertions.h> 82 83 #include <wtf/CurrentTime.h> 83 84 #include <wtf/StdLibExtras.h> … … 179 180 #if ENABLE(DRAG_SUPPORT) 180 181 , m_mouseDownMayStartDrag(false) 182 , m_dragMayStartSelectionInstead(false) 181 183 #endif 182 184 , m_mouseDownWasSingleClickInSelection(false) … … 595 597 return false; 596 598 597 bool DHTMLFlag;598 bool UAFlag;599 allowDHTMLDrag(DHTMLFlag, UAFlag);600 if (!DHTMLFlag && !UAFlag)601 return false;602 603 599 FrameView* view = m_frame->view(); 604 600 if (!view) … … 609 605 return false; 610 606 607 updateDragSourceActionsAllowed(); 611 608 HitTestRequest request(HitTestRequest::ReadOnly); 612 609 HitTestResult result(view->windowToContents(event.pos())); 613 610 m_frame->contentRenderer()->layer()->hitTest(request, result); 614 bool srcIsDHTML;615 return result.innerNode() && page->dragController()->draggableNode(m_frame, result.innerNode(), DHTMLFlag, UAFlag, result.point().x(), result.point().y(), srcIsDHTML);611 DragState state; 612 return result.innerNode() && page->dragController()->draggableNode(m_frame, result.innerNode(), result.point(), state); 616 613 } 617 614 … … 900 897 901 898 #if ENABLE(DRAG_SUPPORT) 902 void EventHandler::allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const 903 { 904 flagDHTML = false; 905 flagUA = false; 906 899 DragSourceAction EventHandler::updateDragSourceActionsAllowed() const 900 { 907 901 if (!m_frame) 908 return ;902 return DragSourceActionNone; 909 903 910 904 Page* page = m_frame->page(); 911 905 if (!page) 912 return ;906 return DragSourceActionNone; 913 907 914 908 FrameView* view = m_frame->view(); 915 909 if (!view) 916 return; 917 918 unsigned mask = page->dragController()->delegateDragSourceAction(view->contentsToWindow(m_mouseDownPos)); 919 flagDHTML = (mask & DragSourceActionDHTML) != DragSourceActionNone; 920 flagUA = ((mask & DragSourceActionImage) || (mask & DragSourceActionLink) || (mask & DragSourceActionSelection)); 910 return DragSourceActionNone; 911 912 return page->dragController()->delegateDragSourceAction(view->contentsToWindow(m_mouseDownPos)); 921 913 } 922 914 #endif // ENABLE(DRAG_SUPPORT) … … 1810 1802 if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) { 1811 1803 // As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event. 1812 if (dragState().m_dragSrc && dragState(). m_dragSrcMayBeDHTML) {1804 if (dragState().m_dragSrc && dragState().shouldDispatchEvents()) { 1813 1805 // for now we don't care if event handler cancels default behavior, since there is none 1814 1806 dispatchDragSrcEvent(eventNames().dragEvent, event); … … 1828 1820 if (newTarget && canHandleDragAndDropForTarget(UpdateDragAndDrop, newTarget, event, clipboard, &accept)) { 1829 1821 // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier. 1830 if (!m_shouldOnlyFireDragOverEvent && dragState().m_dragSrc && dragState(). m_dragSrcMayBeDHTML) {1822 if (!m_shouldOnlyFireDragOverEvent && dragState().m_dragSrc && dragState().shouldDispatchEvents()) { 1831 1823 // for now we don't care if event handler cancels default behavior, since there is none 1832 1824 dispatchDragSrcEvent(eventNames().dragEvent, event); … … 1844 1836 { 1845 1837 if (m_dragTarget && canHandleDragAndDropForTarget(CancelDragAndDrop, m_dragTarget.get(), event, clipboard)) { 1846 if (dragState().m_dragSrc && dragState(). m_dragSrcMayBeDHTML)1838 if (dragState().m_dragSrc && dragState().shouldDispatchEvents()) 1847 1839 dispatchDragSrcEvent(eventNames().dragEvent, event); 1848 1840 dispatchDragEvent(eventNames().dragleaveEvent, m_dragTarget.get(), event, clipboard); … … 2637 2629 2638 2630 int threshold = GeneralDragHysteresis; 2639 if (dragState().m_dragSrcIsImage) 2631 switch (dragState().m_dragType) { 2632 case DragSourceActionSelection: 2633 threshold = TextDragHysteresis; 2634 break; 2635 case DragSourceActionImage: 2640 2636 threshold = ImageDragHysteresis; 2641 else if (dragState().m_dragSrcIsLink) 2637 break; 2638 case DragSourceActionLink: 2642 2639 threshold = LinkDragHysteresis; 2643 else if (dragState().m_dragSrcInSelection) 2644 threshold = TextDragHysteresis; 2640 break; 2641 case DragSourceActionDHTML: 2642 break; 2643 case DragSourceActionNone: 2644 case DragSourceActionAny: 2645 ASSERT_NOT_REACHED(); 2646 } 2645 2647 2646 2648 return abs(delta.width()) >= threshold || abs(delta.height()) >= threshold; … … 2655 2657 void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperation operation) 2656 2658 { 2657 if (dragState().m_dragSrc && dragState(). m_dragSrcMayBeDHTML) {2659 if (dragState().m_dragSrc && dragState().shouldDispatchEvents()) { 2658 2660 dragState().m_dragClipboard->setDestinationOperation(operation); 2659 2661 // for now we don't care if event handler cancels default behavior, since there is none … … 2673 2675 } 2674 2676 2677 static bool ExactlyOneBitSet(DragSourceAction n) 2678 { 2679 return n && !(n & (n - 1)); 2680 } 2681 2675 2682 bool EventHandler::handleDrag(const MouseEventWithHitTestResults& event) 2676 2683 { … … 2690 2697 2691 2698 if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) { 2692 allowDHTMLDrag(dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA); 2693 if (!dragState().m_dragSrcMayBeDHTML && !dragState().m_dragSrcMayBeUA) 2694 m_mouseDownMayStartDrag = false; // no element is draggable 2695 } 2696 2697 if (m_mouseDownMayStartDrag && !dragState().m_dragSrc) { 2699 dragState().m_eventDispatchPolicy = (updateDragSourceActionsAllowed() & DragSourceActionDHTML) ? DragState::DispatchEvents: DragState::DoNotDispatchEvents; 2700 2698 2701 // try to find an element that wants to be dragged 2699 2702 HitTestRequest request(HitTestRequest::ReadOnly); … … 2702 2705 Node* node = result.innerNode(); 2703 2706 if (node && m_frame->page()) 2704 dragState().m_dragSrc = m_frame->page()->dragController()->draggableNode(m_frame, node, dragState().m_dragSrcMayBeDHTML, dragState().m_dragSrcMayBeUA, 2705 m_mouseDownPos.x(), m_mouseDownPos.y(), dragState().m_dragSrcIsDHTML); 2707 dragState().m_dragSrc = m_frame->page()->dragController()->draggableNode(m_frame, node, m_mouseDownPos, dragState()); 2706 2708 else 2707 2709 dragState().m_dragSrc = 0; … … 2709 2711 if (!dragState().m_dragSrc) 2710 2712 m_mouseDownMayStartDrag = false; // no element is draggable 2711 else { 2712 // remember some facts about this source, while we have a HitTestResult handy 2713 node = result.URLElement(); 2714 dragState().m_dragSrcIsLink = node && node->isLink(); 2715 2716 node = result.innerNonSharedNode(); 2717 dragState().m_dragSrcIsImage = node && node->renderer() && node->renderer()->isImage(); 2718 2719 dragState().m_dragSrcInSelection = m_frame->selection()->contains(m_mouseDownPos); 2720 } 2713 else 2714 m_dragMayStartSelectionInstead = (dragState().m_dragType & DragSourceActionSelection); 2721 2715 } 2722 2716 2723 2717 // For drags starting in the selection, the user must wait between the mousedown and mousedrag, 2724 2718 // or else we bail on the dragging stuff and allow selection to occur 2725 if (m_mouseDownMayStartDrag && !dragState().m_dragSrcIsImage && dragState().m_dragSrcInSelection && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) { 2726 m_mouseDownMayStartDrag = false; 2727 dragState().m_dragSrc = 0; 2728 // ...but if this was the first click in the window, we don't even want to start selection 2729 if (eventActivatedView(event.event())) 2730 m_mouseDownMayStartSelect = false; 2719 if (m_mouseDownMayStartDrag && m_dragMayStartSelectionInstead && (dragState().m_dragType & DragSourceActionSelection) && event.event().timestamp() - m_mouseDownTimestamp < TextDragDelay) { 2720 ASSERT(event.event().eventType() == MouseEventMoved); 2721 if ((dragState().m_dragType & DragSourceActionImage)) { 2722 // ... unless the mouse is over an image, then we start dragging just the image 2723 dragState().m_dragType = DragSourceActionImage; 2724 } else if (!(dragState().m_dragType & (DragSourceActionDHTML | DragSourceActionLink))) { 2725 // ... but only bail if we're not over an unselectable element. 2726 m_mouseDownMayStartDrag = false; 2727 dragState().m_dragSrc = 0; 2728 // ... but if this was the first click in the window, we don't even want to start selection 2729 if (eventActivatedView(event.event())) 2730 m_mouseDownMayStartSelect = false; 2731 } else { 2732 // Prevent the following case from occuring: 2733 // 1. User starts a drag immediately after mouse down over an unselectable element. 2734 // 2. We enter this block and decided that since we're over an unselectable element, 2735 // don't cancel the drag. 2736 // 3. The drag gets resolved as a potential selection drag below /but/ we haven't 2737 // exceeded the drag hysteresis yet. 2738 // 4. We enter this block again, and since it's now marked as a selection drag, we 2739 // cancel the drag. 2740 m_dragMayStartSelectionInstead = false; 2741 } 2731 2742 } 2732 2743 … … 2734 2745 return !mouseDownMayStartSelect() && !m_mouseDownMayStartAutoscroll; 2735 2746 2747 if (!ExactlyOneBitSet(dragState().m_dragType)) { 2748 ASSERT((dragState().m_dragType & DragSourceActionSelection)); 2749 ASSERT((dragState().m_dragType & ~DragSourceActionSelection) == DragSourceActionDHTML 2750 || (dragState().m_dragType & ~DragSourceActionSelection) == DragSourceActionImage 2751 || (dragState().m_dragType & ~DragSourceActionSelection) == DragSourceActionLink); 2752 dragState().m_dragType = DragSourceActionSelection; 2753 } 2754 2736 2755 // We are starting a text/image/url drag, so the cursor should be an arrow 2737 2756 if (FrameView* view = m_frame->view()) { … … 2752 2771 dragState().m_dragClipboard = createDraggingClipboard(); 2753 2772 2754 if (dragState(). m_dragSrcMayBeDHTML) {2773 if (dragState().shouldDispatchEvents()) { 2755 2774 // Check to see if the is a DOM based drag, if it is get the DOM specified drag 2756 2775 // image and offset 2757 if (dragState().m_drag SrcIsDHTML) {2776 if (dragState().m_dragType == DragSourceActionDHTML) { 2758 2777 if (RenderObject* renderer = dragState().m_dragSrc->renderer()) { 2759 2778 // FIXME: This doesn't work correctly with transforms. … … 2791 2810 Page* page = m_frame->page(); 2792 2811 DragController* dragController = page ? page->dragController() : 0; 2793 bool startedDrag = dragController && dragController->startDrag(m_frame, dragState() .m_dragClipboard.get(), srcOp, event.event(), m_mouseDownPos, dragState().m_dragSrcIsDHTML);2794 if (!startedDrag && dragState(). m_dragSrcMayBeDHTML) {2812 bool startedDrag = dragController && dragController->startDrag(m_frame, dragState(), srcOp, event.event(), m_mouseDownPos); 2813 if (!startedDrag && dragState().shouldDispatchEvents()) { 2795 2814 // Drag was canned at the last minute - we owe m_dragSrc a DRAGEND event 2796 2815 dispatchDragSrcEvent(eventNames().dragendEvent, event.event()); -
trunk/Source/WebCore/page/EventHandler.h
r86461 r86472 28 28 29 29 #include "DragActions.h" 30 #include "DragState.h" 30 31 #include "FocusDirection.h" 31 32 #include "HitTestRequest.h" … … 50 51 class Clipboard; 51 52 class Cursor; 52 struct DragState;53 53 class Event; 54 54 class EventTarget; … … 324 324 325 325 #if ENABLE(DRAG_SUPPORT) 326 void allowDHTMLDrag(bool& flagDHTML, bool& flagUA) const;326 DragSourceAction updateDragSourceActionsAllowed() const; 327 327 #endif 328 328 … … 361 361 #if ENABLE(DRAG_SUPPORT) 362 362 bool m_mouseDownMayStartDrag; 363 bool m_dragMayStartSelectionInstead; 363 364 #endif 364 365 bool m_mouseDownWasSingleClickInSelection;
Note: See TracChangeset
for help on using the changeset viewer.