bool DragController::concludeEditDrag(DragData* dragData) { ASSERT(dragData); RefPtr<HTMLInputElement> fileInput = m_fileInputElementUnderMouse; if (m_fileInputElementUnderMouse) { m_fileInputElementUnderMouse->setCanReceiveDroppedFiles(false); m_fileInputElementUnderMouse = 0; } if (!m_documentUnderMouse) return false; IntPoint point = m_documentUnderMouse->view()->windowToContents(dragData->clientPosition()); Element* element = elementUnderMouse(m_documentUnderMouse.get(), point); if (!element) return false; Frame* innerFrame = element->ownerDocument()->frame(); ASSERT(innerFrame); if (m_page->dragCaretController()->hasCaret() && !dispatchTextInputEventFor(innerFrame, dragData)) return true; if (dragData->containsColor()) { Color color = dragData->asColor(); if (!color.isValid()) return false; RefPtr<Range> innerRange = innerFrame->selection()->toNormalizedRange(); RefPtr<StylePropertySet> style = StylePropertySet::create(); style->setProperty(CSSPropertyColor, color.serialized(), false); if (!innerFrame->editor()->shouldApplyStyle(style.get(), innerRange.get())) return false; m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); innerFrame->editor()->applyStyle(style.get(), EditActionSetColor); return true; } if (dragData->containsFiles() && fileInput) { // fileInput should be the element we hit tested for, unless it was made // display:none in a drop event handler. ASSERT(fileInput == element || !fileInput->renderer()); if (fileInput->disabled()) return false; Vector<String> filenames; dragData->asFilenames(filenames); if (filenames.isEmpty()) return false; fileInput->receiveDroppedFiles(filenames); m_client->willPerformDragDestinationAction(DragDestinationActionUpload, dragData); return true; } if (!m_page->dragController()->canProcessDrag(dragData)) { m_page->dragCaretController()->clear(); return false; } VisibleSelection dragCaret = m_page->dragCaretController()->caretPosition(); m_page->dragCaretController()->clear(); RefPtr<Range> range = dragCaret.toNormalizedRange(); RefPtr<Element> rootEditableElement = innerFrame->selection()->rootEditableElement(); // For range to be null a WebKit client must have done something bad while // manually controlling drag behaviour if (!range) return false; CachedResourceLoader* cachedResourceLoader = range->ownerDocument()->cachedResourceLoader(); ResourceCacheValidationSuppressor validationSuppressor(cachedResourceLoader); if (dragIsMove(innerFrame->selection(), dragData) || dragCaret.isContentRichlyEditable()) { bool chosePlainText = false; RefPtr<DocumentFragment> fragment = documentFragmentFromDragData(dragData, innerFrame, range, true, chosePlainText); if (!fragment || !innerFrame->editor()->shouldInsertFragment(fragment, range, EditorInsertActionDropped)) { return false; } m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); 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(); applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartInsert, smartDelete)); } else { if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) { ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::PreventNesting; if (dragData->canSmartReplace()) options |= ReplaceSelectionCommand::SmartReplace; if (chosePlainText) options |= ReplaceSelectionCommand::MatchStyle; applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse.get(), fragment, options)); } } } else { String text = dragData->asPlainText(innerFrame); if (text.isEmpty() || !innerFrame->editor()->shouldInsertText(text, range.get(), EditorInsertActionDropped)) { return false; } m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse.get(), createFragmentFromText(range.get(), text), ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting)); } if (rootEditableElement) { if (Frame* frame = rootEditableElement->document()->frame()) frame->eventHandler()->updateDragStateAfterEditDragIfNeeded(rootEditableElement.get()); } return true; }