Chromium Code Reviews| 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..2dae627e512c2ca6127e8af36622abc388ce5b9f 100644 |
| --- a/third_party/WebKit/Source/core/page/DragController.cpp |
| +++ b/third_party/WebKit/Source/core/page/DragController.cpp |
| @@ -92,6 +92,58 @@ |
| 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); |
|
yosin_UTC9
2016/08/31 01:20:34
nit: We don't need to have parenthesis.
Edit
chongz
2016/09/02 18:02:10
Done.
|
| + } |
| + |
| + // 'beforeinput' event handler may destroy frame. |
| + if (dragFrame != dragTarget->document().frame() || dropFrame != dropTarget->document().frame()) |
|
yosin_UTC9
2016/08/31 01:20:34
What is happened when |dropTarget| is removed?
chongz
2016/09/02 18:02:10
Added check for removed element. So if |dropTarget
|
| + 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); |
|
yosin_UTC9
2016/08/31 01:20:34
nit: We don't need to have parenthesis.
chongz
2016/09/02 18:02:10
Done.
|
| + |
| + // 'beforeinput' event handler may destroy frame. |
| + if (dragFrame != dragTarget->document().frame() || dropFrame != dropTarget->document().frame()) |
| + return DragDropBeforeInputResult::None; |
| + |
| + // 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 +176,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 +550,54 @@ 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 { |
| + DragDropBeforeInputResult beforeInputResult = dispatchDragDropBeforeInput(innerFrame->editor().findEventTargetFromSelection(), element, dragData, dragIsMove(innerFrame->selection(), dragData)); |
| + |
| + 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) { |