Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008 Google Inc. | 3 * Copyright (C) 2008 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 #include "wtf/CurrentTime.h" | 85 #include "wtf/CurrentTime.h" |
| 86 #include "wtf/RefPtr.h" | 86 #include "wtf/RefPtr.h" |
| 87 #include <memory> | 87 #include <memory> |
| 88 | 88 |
| 89 #if OS(WIN) | 89 #if OS(WIN) |
| 90 #include <windows.h> | 90 #include <windows.h> |
| 91 #endif | 91 #endif |
| 92 | 92 |
| 93 namespace blink { | 93 namespace blink { |
| 94 | 94 |
| 95 namespace { | |
| 96 | |
| 97 DataTransfer* createDraggingDataTransfer(DataTransferAccessPolicy policy, DragDa ta* dragData) | |
| 98 { | |
| 99 return DataTransfer::create(DataTransfer::DragAndDrop, policy, dragData->pla tformData()); | |
| 100 } | |
| 101 | |
| 102 enum class DragDropBeforeInputResult { | |
| 103 None, | |
| 104 DeleteOnly, | |
| 105 InsertOnly, | |
| 106 DeleteAndInsert, | |
| 107 }; | |
| 108 | |
| 109 DragDropBeforeInputResult dispatchDragDropBeforeInput(Element* dragTarget, Eleme nt* dropTarget, DragData* dragData, bool dragIsMove) | |
| 110 { | |
| 111 LocalFrame* dragFrame = dragTarget->document().frame(); | |
| 112 LocalFrame* dropFrame = dropTarget->document().frame(); | |
| 113 | |
| 114 // Handle DeleteByDrag. | |
| 115 bool shouldDelete = dragIsMove; | |
| 116 if (shouldDelete) { | |
| 117 DispatchEventResult dragBeforeInputResult = dispatchBeforeInputEditorCom mand(dragTarget, InputEvent::InputType::DeleteByDrag, emptyString(), nullptr); | |
| 118 shouldDelete = dragBeforeInputResult == DispatchEventResult::NotCanceled ; | |
| 119 } | |
| 120 | |
| 121 // 'beforeinput' event handler may destroy frame. | |
| 122 if (dragFrame != dragTarget->document().frame() || dropFrame != dropTarget-> document().frame()) | |
| 123 return DragDropBeforeInputResult::None; | |
| 124 | |
| 125 // Handle InsertFromDrop. | |
| 126 DataTransfer* dataTransfer = createDraggingDataTransfer(DataTransferReadable , dragData); | |
| 127 dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask()); | |
| 128 DispatchEventResult dropBeforeInputResult = dispatchBeforeInputDataTransfer( dropTarget, InputEvent::InputType::InsertFromDrop, dataTransfer, nullptr); | |
| 129 bool shouldInsert = dropBeforeInputResult == DispatchEventResult::NotCancele d; | |
| 130 | |
| 131 // 'beforeinput' event handler may destroy frame. | |
| 132 if (dragFrame != dragTarget->document().frame() || dropFrame != dropTarget-> document().frame()) | |
| 133 return DragDropBeforeInputResult::None; | |
| 134 | |
| 135 // 'beforeinput' event handler may remove element from document, editing com mands won't modify disconnected elements. | |
| 136 shouldDelete = shouldDelete && dragTarget->isConnected(); | |
| 137 shouldInsert = shouldInsert && dropTarget->isConnected(); | |
| 138 | |
| 139 // Generate dispatch result. | |
| 140 if (shouldDelete && shouldInsert) | |
| 141 return DragDropBeforeInputResult::DeleteAndInsert; | |
| 142 if (shouldDelete) | |
| 143 return DragDropBeforeInputResult::DeleteOnly; | |
| 144 if (shouldInsert) | |
| 145 return DragDropBeforeInputResult::InsertOnly; | |
| 146 return DragDropBeforeInputResult::None; | |
| 147 } | |
| 148 | |
| 149 } // anonymous namespace | |
| 150 | |
| 95 const int DragController::DragIconRightInset = 7; | 151 const int DragController::DragIconRightInset = 7; |
| 96 const int DragController::DragIconBottomInset = 3; | 152 const int DragController::DragIconBottomInset = 3; |
| 97 | 153 |
| 98 static const int MaxOriginalImageArea = 1500 * 1500; | 154 static const int MaxOriginalImageArea = 1500 * 1500; |
| 99 static const int LinkDragBorderInset = 2; | 155 static const int LinkDragBorderInset = 2; |
| 100 static const float DragImageAlpha = 0.75f; | 156 static const float DragImageAlpha = 0.75f; |
| 101 | 157 |
| 102 #if ENABLE(ASSERT) | 158 #if ENABLE(ASSERT) |
| 103 static bool dragTypeIsValid(DragSourceAction action) | 159 static bool dragTypeIsValid(DragSourceAction action) |
| 104 { | 160 { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 117 #endif | 173 #endif |
| 118 | 174 |
| 119 static PlatformMouseEvent createMouseEvent(DragData* dragData) | 175 static PlatformMouseEvent createMouseEvent(DragData* dragData) |
| 120 { | 176 { |
| 121 return PlatformMouseEvent(dragData->clientPosition(), dragData->globalPositi on(), | 177 return PlatformMouseEvent(dragData->clientPosition(), dragData->globalPositi on(), |
| 122 WebPointerProperties::Button::Left, PlatformEvent::MouseMoved, 0, | 178 WebPointerProperties::Button::Left, PlatformEvent::MouseMoved, 0, |
| 123 static_cast<PlatformEvent::Modifiers>(dragData->modifiers()), | 179 static_cast<PlatformEvent::Modifiers>(dragData->modifiers()), |
| 124 PlatformMouseEvent::RealOrIndistinguishable, monotonicallyIncreasingTime ()); | 180 PlatformMouseEvent::RealOrIndistinguishable, monotonicallyIncreasingTime ()); |
| 125 } | 181 } |
| 126 | 182 |
| 127 static DataTransfer* createDraggingDataTransfer(DataTransferAccessPolicy policy, DragData* dragData) | |
| 128 { | |
| 129 return DataTransfer::create(DataTransfer::DragAndDrop, policy, dragData->pla tformData()); | |
| 130 } | |
| 131 | |
| 132 DragController::DragController(Page* page) | 183 DragController::DragController(Page* page) |
| 133 : m_page(page) | 184 : m_page(page) |
| 134 , m_documentUnderMouse(nullptr) | 185 , m_documentUnderMouse(nullptr) |
| 135 , m_dragInitiator(nullptr) | 186 , m_dragInitiator(nullptr) |
| 136 , m_fileInputElementUnderMouse(nullptr) | 187 , m_fileInputElementUnderMouse(nullptr) |
| 137 , m_documentIsHandlingDrag(false) | 188 , m_documentIsHandlingDrag(false) |
| 138 , m_dragDestinationAction(DragDestinationActionNone) | 189 , m_dragDestinationAction(DragDestinationActionNone) |
| 139 , m_didInitiateDrag(false) | 190 , m_didInitiateDrag(false) |
| 140 { | 191 { |
| 141 } | 192 } |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 return false; | 547 return false; |
| 497 } | 548 } |
| 498 Range* range = createRange(dragCaret.toNormalizedEphemeralRange()); | 549 Range* range = createRange(dragCaret.toNormalizedEphemeralRange()); |
| 499 Element* rootEditableElement = innerFrame->selection().rootEditableElement() ; | 550 Element* rootEditableElement = innerFrame->selection().rootEditableElement() ; |
| 500 | 551 |
| 501 // For range to be null a WebKit client must have done something bad while | 552 // For range to be null a WebKit client must have done something bad while |
| 502 // manually controlling drag behaviour | 553 // manually controlling drag behaviour |
| 503 if (!range) | 554 if (!range) |
| 504 return false; | 555 return false; |
| 505 ResourceFetcher* fetcher = range->ownerDocument().fetcher(); | 556 ResourceFetcher* fetcher = range->ownerDocument().fetcher(); |
| 506 ResourceCacheValidationSuppressor validationSuppressor(fetcher); | 557 ResourceCacheValidationSuppressor validationSuppressorr(fetcher); |
| 507 if (dragIsMove(innerFrame->selection(), dragData) || dragCaret.isContentRich lyEditable()) { | 558 |
| 559 DragDropBeforeInputResult beforeInputResult = dispatchDragDropBeforeInput(in nerFrame->editor().findEventTargetFromSelection(), element, dragData, dragIsMove (innerFrame->selection(), dragData)); | |
| 560 | |
| 561 switch (beforeInputResult) { | |
| 562 case DragDropBeforeInputResult::None: | |
| 563 default: | |
| 564 return true; | |
| 565 | |
| 566 case DragDropBeforeInputResult::DeleteOnly: | |
| 567 innerFrame->editor().deleteSelectionWithSmartDelete(innerFrame->editor() .smartInsertDeleteEnabled(), InputEvent::InputType::DeleteByDrag); | |
|
yosin_UTC9
2016/09/05 01:37:50
|innerFrame| can be destroyed due by "beforeInput"
chongz
2016/09/07 17:12:56
Added check for |innerFrame| and |m_documentUnderM
| |
| 568 break; | |
| 569 | |
| 570 case DragDropBeforeInputResult::InsertOnly: | |
| 571 if (dragCaret.isContentRichlyEditable()) { | |
| 572 bool chosePlainText = false; | |
| 573 DocumentFragment* fragment = documentFragmentFromDragData(dragData, innerFrame, range, true, chosePlainText); | |
| 574 if (!fragment) | |
| 575 return false; | |
| 576 if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) { | |
| 577 DCHECK(m_documentUnderMouse); | |
| 578 m_documentUnderMouse->frame()->editor().replaceSelectionAfterDra gging(fragment, dragData->canSmartReplace(), chosePlainText); | |
|
yosin_UTC9
2016/09/05 01:37:50
|m_documentUnderMouse->frame()| can be null due by
chongz
2016/09/07 17:12:56
See above.
| |
| 579 } | |
| 580 } else { | |
| 581 String text = dragData->asPlainText(); | |
| 582 if (text.isEmpty()) | |
| 583 return false; | |
| 584 | |
| 585 if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) { | |
| 586 const bool canSmartReplace = false; | |
| 587 const bool chosePlainText = true; | |
| 588 DCHECK(m_documentUnderMouse); | |
| 589 m_documentUnderMouse->frame()->editor().replaceSelectionAfterDra gging(createFragmentFromText(EphemeralRange(range), text), canSmartReplace, chos ePlainText); | |
| 590 } | |
| 591 } | |
| 592 break; | |
| 593 | |
| 594 case DragDropBeforeInputResult::DeleteAndInsert: | |
| 508 bool chosePlainText = false; | 595 bool chosePlainText = false; |
| 509 DocumentFragment* fragment = documentFragmentFromDragData(dragData, inne rFrame, range, true, chosePlainText); | 596 DocumentFragment* fragment = documentFragmentFromDragData(dragData, inne rFrame, range, true, chosePlainText); |
| 510 if (!fragment) | 597 if (!fragment) |
| 511 return false; | 598 return false; |
| 512 | 599 // NSTextView behavior is to always smart delete on moving a selection, |
| 513 if (dragIsMove(innerFrame->selection(), dragData)) { | 600 // but only to smart insert if the selection granularity is word granula rity. |
| 514 // NSTextView behavior is to always smart delete on moving a selecti on, | 601 bool smartDelete = innerFrame->editor().smartInsertDeleteEnabled(); |
| 515 // but only to smart insert if the selection granularity is word gra nularity. | 602 bool smartInsert = smartDelete && innerFrame->selection().granularity() == WordGranularity && dragData->canSmartReplace(); |
| 516 bool smartDelete = innerFrame->editor().smartInsertDeleteEnabled(); | 603 innerFrame->editor().moveSelectionAfterDragging(fragment, dragCaret.base (), smartInsert, smartDelete); |
| 517 bool smartInsert = smartDelete && innerFrame->selection().granularit y() == WordGranularity && dragData->canSmartReplace(); | 604 break; |
| 518 innerFrame->editor().moveSelectionAfterDragging(fragment, dragCaret. base(), smartInsert, smartDelete); | |
| 519 } else { | |
| 520 if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) { | |
| 521 ASSERT(m_documentUnderMouse); | |
| 522 m_documentUnderMouse->frame()->editor().replaceSelectionAfterDra gging(fragment, dragData->canSmartReplace(), chosePlainText); | |
| 523 } | |
| 524 } | |
| 525 } else { | |
| 526 String text = dragData->asPlainText(); | |
| 527 if (text.isEmpty()) | |
| 528 return false; | |
| 529 | |
| 530 if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) { | |
| 531 const bool canSmartReplace = false; | |
| 532 const bool chosePlainText = true; | |
| 533 ASSERT(m_documentUnderMouse); | |
| 534 m_documentUnderMouse->frame()->editor().replaceSelectionAfterDraggin g(createFragmentFromText(EphemeralRange(range), text), canSmartReplace, chosePla inText); | |
| 535 } | |
| 536 } | 605 } |
| 537 | 606 |
| 538 if (rootEditableElement) { | 607 if (rootEditableElement) { |
| 539 if (LocalFrame* frame = rootEditableElement->document().frame()) | 608 if (LocalFrame* frame = rootEditableElement->document().frame()) |
| 540 frame->eventHandler().updateDragStateAfterEditDragIfNeeded(rootEdita bleElement); | 609 frame->eventHandler().updateDragStateAfterEditDragIfNeeded(rootEdita bleElement); |
| 541 } | 610 } |
| 542 | 611 |
| 543 return true; | 612 return true; |
| 544 } | 613 } |
| 545 | 614 |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 997 | 1066 |
| 998 DEFINE_TRACE(DragController) | 1067 DEFINE_TRACE(DragController) |
| 999 { | 1068 { |
| 1000 visitor->trace(m_page); | 1069 visitor->trace(m_page); |
| 1001 visitor->trace(m_documentUnderMouse); | 1070 visitor->trace(m_documentUnderMouse); |
| 1002 visitor->trace(m_dragInitiator); | 1071 visitor->trace(m_dragInitiator); |
| 1003 visitor->trace(m_fileInputElementUnderMouse); | 1072 visitor->trace(m_fileInputElementUnderMouse); |
| 1004 } | 1073 } |
| 1005 | 1074 |
| 1006 } // namespace blink | 1075 } // namespace blink |
| OLD | NEW |