| Index: third_party/WebKit/Source/core/page/DragController.cpp
|
| diff --git a/third_party/WebKit/Source/core/page/DragController.cpp b/third_party/WebKit/Source/core/page/DragController.cpp
|
| index c0a684f1d686859f59777949014ff1a06ba3a310..00a0bdab28d5abe61a88db14636e5f997feb49c2 100644
|
| --- a/third_party/WebKit/Source/core/page/DragController.cpp
|
| +++ b/third_party/WebKit/Source/core/page/DragController.cpp
|
| @@ -92,6 +92,62 @@
|
|
|
| namespace blink {
|
|
|
| +namespace {
|
| +
|
| +DataTransfer* createDraggingDataTransfer(DataTransferAccessPolicy policy, DragData* dragData)
|
| +{
|
| + return DataTransfer::create(DataTransfer::DragAndDrop, policy, dragData->platformData());
|
| +}
|
| +
|
| +enum class DragDropBeforeInputResult {
|
| + None,
|
| + DeleteOnly,
|
| + InsertOnly,
|
| + DeleteAndInsert,
|
| +};
|
| +
|
| +DragDropBeforeInputResult dispatchDragDropBeforeInput(Element* dragTarget, Element* dropTarget, DragData* dragData, bool dragIsMove)
|
| +{
|
| + LocalFrame* dragFrame = dragTarget->document().frame();
|
| + LocalFrame* dropFrame = dropTarget->document().frame();
|
| +
|
| + // Handle DeleteByDrag.
|
| + bool shouldDelete = dragIsMove;
|
| + if (shouldDelete) {
|
| + DispatchEventResult dragBeforeInputResult = dispatchBeforeInputEditorCommand(dragTarget, InputEvent::InputType::DeleteByDrag, emptyString(), nullptr);
|
| + shouldDelete = dragBeforeInputResult == DispatchEventResult::NotCanceled;
|
| + }
|
| +
|
| + // 'beforeinput' event handler may destroy frame.
|
| + if (dragFrame != dragTarget->document().frame() || dropFrame != dropTarget->document().frame())
|
| + return DragDropBeforeInputResult::None;
|
| +
|
| + // Handle InsertFromDrop.
|
| + DataTransfer* dataTransfer = createDraggingDataTransfer(DataTransferReadable, dragData);
|
| + dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask());
|
| + DispatchEventResult dropBeforeInputResult = dispatchBeforeInputDataTransfer(dropTarget, InputEvent::InputType::InsertFromDrop, dataTransfer, nullptr);
|
| + bool shouldInsert = dropBeforeInputResult == DispatchEventResult::NotCanceled;
|
| +
|
| + // 'beforeinput' event handler may destroy frame.
|
| + if (dragFrame != dragTarget->document().frame() || dropFrame != dropTarget->document().frame())
|
| + return DragDropBeforeInputResult::None;
|
| +
|
| + // 'beforeinput' event handler may remove element from document, editing commands won't modify disconnected elements.
|
| + shouldDelete = shouldDelete && dragTarget->isConnected();
|
| + shouldInsert = shouldInsert && dropTarget->isConnected();
|
| +
|
| + // Generate dispatch result.
|
| + if (shouldDelete && shouldInsert)
|
| + return DragDropBeforeInputResult::DeleteAndInsert;
|
| + if (shouldDelete)
|
| + return DragDropBeforeInputResult::DeleteOnly;
|
| + if (shouldInsert)
|
| + return DragDropBeforeInputResult::InsertOnly;
|
| + return DragDropBeforeInputResult::None;
|
| +}
|
| +
|
| +} // anonymous namespace
|
| +
|
| const int DragController::DragIconRightInset = 7;
|
| const int DragController::DragIconBottomInset = 3;
|
|
|
| @@ -124,11 +180,6 @@ static PlatformMouseEvent createMouseEvent(DragData* dragData)
|
| PlatformMouseEvent::RealOrIndistinguishable, monotonicallyIncreasingTime());
|
| }
|
|
|
| -static DataTransfer* createDraggingDataTransfer(DataTransferAccessPolicy policy, DragData* dragData)
|
| -{
|
| - return DataTransfer::create(DataTransfer::DragAndDrop, policy, dragData->platformData());
|
| -}
|
| -
|
| DragController::DragController(Page* page)
|
| : m_page(page)
|
| , m_documentUnderMouse(nullptr)
|
| @@ -503,36 +554,59 @@ bool DragController::concludeEditDrag(DragData* dragData)
|
| if (!range)
|
| return false;
|
| ResourceFetcher* fetcher = range->ownerDocument().fetcher();
|
| - ResourceCacheValidationSuppressor validationSuppressor(fetcher);
|
| - if (dragIsMove(innerFrame->selection(), dragData) || dragCaret.isContentRichlyEditable()) {
|
| - bool chosePlainText = false;
|
| - DocumentFragment* fragment = documentFragmentFromDragData(dragData, innerFrame, range, true, chosePlainText);
|
| - if (!fragment)
|
| - return false;
|
| + ResourceCacheValidationSuppressor validationSuppressorr(fetcher);
|
|
|
| - if (dragIsMove(innerFrame->selection(), dragData)) {
|
| - // NSTextView behavior is to always smart delete on moving a selection,
|
| - // but only to smart insert if the selection granularity is word granularity.
|
| - bool smartDelete = innerFrame->editor().smartInsertDeleteEnabled();
|
| - bool smartInsert = smartDelete && innerFrame->selection().granularity() == WordGranularity && dragData->canSmartReplace();
|
| - innerFrame->editor().moveSelectionAfterDragging(fragment, dragCaret.base(), smartInsert, smartDelete);
|
| - } else {
|
| + LocalFrame* frameUnderMouse = m_documentUnderMouse->frame();
|
| + DCHECK(frameUnderMouse);
|
| + DragDropBeforeInputResult beforeInputResult = dispatchDragDropBeforeInput(innerFrame->editor().findEventTargetFromSelection(), element, dragData, dragIsMove(innerFrame->selection(), dragData));
|
| + // 'beforeinput' handler may destroy frame.
|
| + if (innerFrame->document()->frame() != innerFrame || m_documentUnderMouse->frame() != frameUnderMouse)
|
| + return false;
|
| +
|
| + switch (beforeInputResult) {
|
| + case DragDropBeforeInputResult::None:
|
| + default:
|
| + return true;
|
| +
|
| + case DragDropBeforeInputResult::DeleteOnly:
|
| + innerFrame->editor().deleteSelectionWithSmartDelete(innerFrame->editor().smartInsertDeleteEnabled(), InputEvent::InputType::DeleteByDrag);
|
| + break;
|
| +
|
| + case DragDropBeforeInputResult::InsertOnly:
|
| + if (dragCaret.isContentRichlyEditable()) {
|
| + bool chosePlainText = false;
|
| + DocumentFragment* fragment = documentFragmentFromDragData(dragData, innerFrame, range, true, chosePlainText);
|
| + if (!fragment)
|
| + return false;
|
| if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) {
|
| - ASSERT(m_documentUnderMouse);
|
| + DCHECK(m_documentUnderMouse);
|
| m_documentUnderMouse->frame()->editor().replaceSelectionAfterDragging(fragment, dragData->canSmartReplace(), chosePlainText);
|
| }
|
| - }
|
| - } else {
|
| - String text = dragData->asPlainText();
|
| - if (text.isEmpty())
|
| - return false;
|
| + } else {
|
| + String text = dragData->asPlainText();
|
| + if (text.isEmpty())
|
| + return false;
|
|
|
| - if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) {
|
| - const bool canSmartReplace = false;
|
| - const bool chosePlainText = true;
|
| - ASSERT(m_documentUnderMouse);
|
| - m_documentUnderMouse->frame()->editor().replaceSelectionAfterDragging(createFragmentFromText(EphemeralRange(range), text), canSmartReplace, chosePlainText);
|
| + if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) {
|
| + const bool canSmartReplace = false;
|
| + const bool chosePlainText = true;
|
| + DCHECK(m_documentUnderMouse);
|
| + m_documentUnderMouse->frame()->editor().replaceSelectionAfterDragging(createFragmentFromText(EphemeralRange(range), text), canSmartReplace, chosePlainText);
|
| + }
|
| }
|
| + break;
|
| +
|
| + case DragDropBeforeInputResult::DeleteAndInsert:
|
| + bool chosePlainText = false;
|
| + DocumentFragment* fragment = documentFragmentFromDragData(dragData, innerFrame, range, true, chosePlainText);
|
| + if (!fragment)
|
| + return false;
|
| + // NSTextView behavior is to always smart delete on moving a selection,
|
| + // but only to smart insert if the selection granularity is word granularity.
|
| + bool smartDelete = innerFrame->editor().smartInsertDeleteEnabled();
|
| + bool smartInsert = smartDelete && innerFrame->selection().granularity() == WordGranularity && dragData->canSmartReplace();
|
| + innerFrame->editor().moveSelectionAfterDragging(fragment, dragCaret.base(), smartInsert, smartDelete);
|
| + break;
|
| }
|
|
|
| if (rootEditableElement) {
|
|
|