Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(245)

Side by Side Diff: third_party/WebKit/Source/core/page/DragController.cpp

Issue 2374743002: [InputEvent] Support |deleteByDrag|, |insertFromDrop| and fire in sequential order (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 DocumentFragment* documentFragmentFromDragData(DragData* dragData, LocalFrame* f rame, Range* context, bool allowPlainText, bool& chosePlainText)
103 {
104 DCHECK(dragData);
105 chosePlainText = false;
106
107 Document& document = context->ownerDocument();
108 if (dragData->containsCompatibleContent()) {
109 if (DocumentFragment* fragment = dragData->asFragment(frame))
110 return fragment;
111
112 if (dragData->containsURL(DragData::DoNotConvertFilenames)) {
113 String title;
114 String url = dragData->asURL(DragData::DoNotConvertFilenames, &title );
115 if (!url.isEmpty()) {
116 HTMLAnchorElement* anchor = HTMLAnchorElement::create(document);
117 anchor->setHref(AtomicString(url));
118 if (title.isEmpty()) {
119 // Try the plain text first because the url might be normali zed or escaped.
120 if (dragData->containsPlainText())
121 title = dragData->asPlainText();
122 if (title.isEmpty())
123 title = url;
124 }
125 Node* anchorText = document.createTextNode(title);
126 anchor->appendChild(anchorText);
127 DocumentFragment* fragment = document.createDocumentFragment();
128 fragment->appendChild(anchor);
129 return fragment;
130 }
131 }
132 }
133 if (allowPlainText && dragData->containsPlainText()) {
134 chosePlainText = true;
135 return createFragmentFromText(EphemeralRange(context), dragData->asPlain Text());
136 }
137
138 return nullptr;
139 }
140
141 bool doDeleteByDragWithEvents(Element* dragTarget, bool smartDelete, const Posit ion& referenceMovePosition)
yosin_UTC9 2016/09/28 04:19:03 Please add comment about |bool| return value.
chongz 2016/09/29 02:36:22 Done.
142 {
yosin_UTC9 2016/09/28 04:19:03 This function should be in Editor class and avoid
chongz 2016/09/29 02:36:22 Done.
143 if (!dragTarget || !dragTarget->isConnected())
144 return true;
145
146 LocalFrame* dragFrame = dragTarget->document().frame();
147
148 // Dispatch 'beforeinput'.
149 const bool shouldDelete = dispatchBeforeInputEditorCommand(dragTarget, Input Event::InputType::DeleteByDrag, nullptr) == DispatchEventResult::NotCanceled;
yosin_UTC9 2016/09/28 04:19:03 I think we should dispatch event to drag source ra
chongz 2016/09/29 02:36:22 Sorry for the confusion, I've renamed it to |dragS
150
151 // 'beforeinput' event handler may destroy frame, return false to cancel rem aining actions;
152 if (dragFrame != dragTarget->document().frame())
153 return false;
154
155 if (shouldDelete && dragTarget->isConnected())
156 dragFrame->editor().deleteSelectionWithSmartDelete(smartDelete, InputEve nt::InputType::DeleteByDrag, referenceMovePosition);
157
158 return true;
159 }
160
161 bool doInsertFromDropWithEvents(Element* dropTarget, DragData* dragData, Documen tFragment* fragment, Range* dropCaretRange, bool smartInsert, bool chosePlainTex t)
yosin_UTC9 2016/09/28 04:19:03 Please add comment about |bool| return value.
chongz 2016/09/29 02:36:22 Done.
162 {
yosin_UTC9 2016/09/28 04:19:03 This function should be in Editor class and avoid
chongz 2016/09/29 02:36:22 Done.
163 if (!dropTarget || !dropTarget->isConnected())
164 return true;
165
166 LocalFrame* dropFrame = dropTarget->document().frame();
167
168 // Dispatch 'beforeinput'.
169 DataTransfer* dataTransfer = createDraggingDataTransfer(DataTransferReadable , dragData);
170 dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask());
171 const bool shouldInsert = dispatchBeforeInputDataTransfer(dropTarget, InputE vent::InputType::InsertFromDrop, dataTransfer, nullptr) == DispatchEventResult:: NotCanceled;
172
173 // 'beforeinput' event handler may destroy frame, return false to cancel rem aining actions;
174 if (dropFrame != dropTarget->document().frame())
175 return false;
176
177 if (shouldInsert && dropTarget->isConnected())
178 dropFrame->editor().replaceSelectionAfterDragging(fragment, smartInsert, chosePlainText);
179
180 return true;
181 }
182
183 } // anonymous namespace
184
95 const int DragController::DragIconRightInset = 7; 185 const int DragController::DragIconRightInset = 7;
96 const int DragController::DragIconBottomInset = 3; 186 const int DragController::DragIconBottomInset = 3;
97 187
98 static const int MaxOriginalImageArea = 1500 * 1500; 188 static const int MaxOriginalImageArea = 1500 * 1500;
99 static const int LinkDragBorderInset = 2; 189 static const int LinkDragBorderInset = 2;
100 static const float DragImageAlpha = 0.75f; 190 static const float DragImageAlpha = 0.75f;
101 191
102 #if ENABLE(ASSERT) 192 #if ENABLE(ASSERT)
103 static bool dragTypeIsValid(DragSourceAction action) 193 static bool dragTypeIsValid(DragSourceAction action)
104 { 194 {
(...skipping 12 matching lines...) Expand all
117 #endif 207 #endif
118 208
119 static PlatformMouseEvent createMouseEvent(DragData* dragData) 209 static PlatformMouseEvent createMouseEvent(DragData* dragData)
120 { 210 {
121 return PlatformMouseEvent(dragData->clientPosition(), dragData->globalPositi on(), 211 return PlatformMouseEvent(dragData->clientPosition(), dragData->globalPositi on(),
122 WebPointerProperties::Button::Left, PlatformEvent::MouseMoved, 0, 212 WebPointerProperties::Button::Left, PlatformEvent::MouseMoved, 0,
123 static_cast<PlatformEvent::Modifiers>(dragData->modifiers()), 213 static_cast<PlatformEvent::Modifiers>(dragData->modifiers()),
124 PlatformMouseEvent::RealOrIndistinguishable, monotonicallyIncreasingTime ()); 214 PlatformMouseEvent::RealOrIndistinguishable, monotonicallyIncreasingTime ());
125 } 215 }
126 216
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) 217 DragController::DragController(Page* page)
133 : m_page(page) 218 : m_page(page)
134 , m_documentUnderMouse(nullptr) 219 , m_documentUnderMouse(nullptr)
135 , m_dragInitiator(nullptr) 220 , m_dragInitiator(nullptr)
136 , m_fileInputElementUnderMouse(nullptr) 221 , m_fileInputElementUnderMouse(nullptr)
137 , m_documentIsHandlingDrag(false) 222 , m_documentIsHandlingDrag(false)
138 , m_dragDestinationAction(DragDestinationActionNone) 223 , m_dragDestinationAction(DragDestinationActionNone)
139 , m_didInitiateDrag(false) 224 , m_didInitiateDrag(false)
140 { 225 {
141 } 226 }
142 227
143 DragController* DragController::create(Page* page) 228 DragController* DragController::create(Page* page)
144 { 229 {
145 return new DragController(page); 230 return new DragController(page);
146 } 231 }
147 232
148 static DocumentFragment* documentFragmentFromDragData(DragData* dragData, LocalF rame* frame, Range* context, bool allowPlainText, bool& chosePlainText)
149 {
150 ASSERT(dragData);
151 chosePlainText = false;
152
153 Document& document = context->ownerDocument();
154 if (dragData->containsCompatibleContent()) {
155 if (DocumentFragment* fragment = dragData->asFragment(frame))
156 return fragment;
157
158 if (dragData->containsURL(DragData::DoNotConvertFilenames)) {
159 String title;
160 String url = dragData->asURL(DragData::DoNotConvertFilenames, &title );
161 if (!url.isEmpty()) {
162 HTMLAnchorElement* anchor = HTMLAnchorElement::create(document);
163 anchor->setHref(AtomicString(url));
164 if (title.isEmpty()) {
165 // Try the plain text first because the url might be normali zed or escaped.
166 if (dragData->containsPlainText())
167 title = dragData->asPlainText();
168 if (title.isEmpty())
169 title = url;
170 }
171 Node* anchorText = document.createTextNode(title);
172 anchor->appendChild(anchorText);
173 DocumentFragment* fragment = document.createDocumentFragment();
174 fragment->appendChild(anchor);
175 return fragment;
176 }
177 }
178 }
179 if (allowPlainText && dragData->containsPlainText()) {
180 chosePlainText = true;
181 return createFragmentFromText(EphemeralRange(context), dragData->asPlain Text());
182 }
183
184 return nullptr;
185 }
186
187 bool DragController::dragIsMove(FrameSelection& selection, DragData* dragData) 233 bool DragController::dragIsMove(FrameSelection& selection, DragData* dragData)
188 { 234 {
189 return m_documentUnderMouse == m_dragInitiator && selection.isContentEditabl e() && selection.isRange() && !isCopyKeyDown(dragData); 235 return m_documentUnderMouse == m_dragInitiator && selection.isContentEditabl e() && selection.isRange() && !isCopyKeyDown(dragData);
190 } 236 }
191 237
192 // FIXME: This method is poorly named. We're just clearing the selection from t he document this drag is exiting. 238 // FIXME: This method is poorly named. We're just clearing the selection from t he document this drag is exiting.
193 void DragController::cancelDrag() 239 void DragController::cancelDrag()
194 { 240 {
195 m_page->dragCaretController().clear(); 241 m_page->dragCaretController().clear();
196 } 242 }
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 ResourceCacheValidationSuppressor validationSuppressor(fetcher); 552 ResourceCacheValidationSuppressor validationSuppressor(fetcher);
507 if (dragIsMove(innerFrame->selection(), dragData) || dragCaret.isContentRich lyEditable()) { 553 if (dragIsMove(innerFrame->selection(), dragData) || dragCaret.isContentRich lyEditable()) {
508 bool chosePlainText = false; 554 bool chosePlainText = false;
509 DocumentFragment* fragment = documentFragmentFromDragData(dragData, inne rFrame, range, true, chosePlainText); 555 DocumentFragment* fragment = documentFragmentFromDragData(dragData, inne rFrame, range, true, chosePlainText);
510 if (!fragment) 556 if (!fragment)
511 return false; 557 return false;
512 558
513 if (dragIsMove(innerFrame->selection(), dragData)) { 559 if (dragIsMove(innerFrame->selection(), dragData)) {
514 // NSTextView behavior is to always smart delete on moving a selecti on, 560 // NSTextView behavior is to always smart delete on moving a selecti on,
515 // but only to smart insert if the selection granularity is word gra nularity. 561 // but only to smart insert if the selection granularity is word gra nularity.
516 bool smartDelete = innerFrame->editor().smartInsertDeleteEnabled(); 562 const bool smartDelete = innerFrame->editor().smartInsertDeleteEnabl ed();
517 bool smartInsert = smartDelete && innerFrame->selection().granularit y() == WordGranularity && dragData->canSmartReplace(); 563 const bool smartInsert = smartDelete && innerFrame->selection().gran ularity() == WordGranularity && dragData->canSmartReplace();
518 innerFrame->editor().moveSelectionAfterDragging(fragment, dragCaret. base(), smartInsert, smartDelete); 564
565 if (!doDeleteByDragWithEvents(innerFrame->editor().findEventTargetFr omSelection(), smartDelete, dragCaret.base()))
566 return false;
567
568 innerFrame->selection().setSelection(VisibleSelection(range->startPo sition(), range->endPosition()));
569 if (innerFrame->selection().isAvailable()) {
570 DCHECK(m_documentUnderMouse);
571 if (!doInsertFromDropWithEvents(element, dragData, fragment, ran ge, smartInsert, chosePlainText))
572 return false;
573 }
519 } else { 574 } else {
520 if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) { 575 if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) {
521 ASSERT(m_documentUnderMouse); 576 DCHECK(m_documentUnderMouse);
522 m_documentUnderMouse->frame()->editor().replaceSelectionAfterDra gging(fragment, dragData->canSmartReplace(), chosePlainText); 577 if (!doInsertFromDropWithEvents(element, dragData, fragment, ran ge, dragData->canSmartReplace(), chosePlainText))
578 return false;
523 } 579 }
524 } 580 }
525 } else { 581 } else {
526 String text = dragData->asPlainText(); 582 String text = dragData->asPlainText();
527 if (text.isEmpty()) 583 if (text.isEmpty())
528 return false; 584 return false;
529 585
530 if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) { 586 if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) {
531 const bool canSmartReplace = false; 587 const bool canSmartReplace = false;
532 const bool chosePlainText = true; 588 const bool chosePlainText = true;
533 ASSERT(m_documentUnderMouse); 589 DCHECK(m_documentUnderMouse);
534 m_documentUnderMouse->frame()->editor().replaceSelectionAfterDraggin g(createFragmentFromText(EphemeralRange(range), text), canSmartReplace, chosePla inText); 590 if (!doInsertFromDropWithEvents(element, dragData, createFragmentFro mText(EphemeralRange(range), text), range, canSmartReplace, chosePlainText))
591 return false;
535 } 592 }
536 } 593 }
537 594
538 if (rootEditableElement) { 595 if (rootEditableElement) {
539 if (LocalFrame* frame = rootEditableElement->document().frame()) 596 if (LocalFrame* frame = rootEditableElement->document().frame())
540 frame->eventHandler().updateDragStateAfterEditDragIfNeeded(rootEdita bleElement); 597 frame->eventHandler().updateDragStateAfterEditDragIfNeeded(rootEdita bleElement);
541 } 598 }
542 599
543 return true; 600 return true;
544 } 601 }
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
997 1054
998 DEFINE_TRACE(DragController) 1055 DEFINE_TRACE(DragController)
999 { 1056 {
1000 visitor->trace(m_page); 1057 visitor->trace(m_page);
1001 visitor->trace(m_documentUnderMouse); 1058 visitor->trace(m_documentUnderMouse);
1002 visitor->trace(m_dragInitiator); 1059 visitor->trace(m_dragInitiator);
1003 visitor->trace(m_fileInputElementUnderMouse); 1060 visitor->trace(m_fileInputElementUnderMouse);
1004 } 1061 }
1005 1062
1006 } // namespace blink 1063 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698