| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
| 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 namespace { | 99 namespace { |
| 100 | 100 |
| 101 void dispatchInputEvent(Element* target, | 101 void dispatchInputEvent(Element* target, |
| 102 InputEvent::InputType inputType, | 102 InputEvent::InputType inputType, |
| 103 const String& data, | 103 const String& data, |
| 104 InputEvent::EventIsComposing isComposing) { | 104 InputEvent::EventIsComposing isComposing) { |
| 105 if (!RuntimeEnabledFeatures::inputEventEnabled()) | 105 if (!RuntimeEnabledFeatures::inputEventEnabled()) |
| 106 return; | 106 return; |
| 107 if (!target) | 107 if (!target) |
| 108 return; | 108 return; |
| 109 // TODO(chongz): Pass appreciate |ranges| after it's defined on spec. | |
| 110 // http://w3c.github.io/editing/input-events.html#dom-inputevent-inputtype | |
| 111 InputEvent* inputEvent = | 109 InputEvent* inputEvent = |
| 112 InputEvent::createInput(inputType, data, isComposing, nullptr); | 110 InputEvent::createInput(inputType, data, isComposing, nullptr); |
| 113 target->dispatchScopedEvent(inputEvent); | 111 target->dispatchScopedEvent(inputEvent); |
| 114 } | 112 } |
| 115 | 113 |
| 116 void dispatchInputEventEditableContentChanged( | 114 void dispatchInputEventEditableContentChanged( |
| 117 Element* startRoot, | 115 Element* startRoot, |
| 118 Element* endRoot, | 116 Element* endRoot, |
| 119 InputEvent::InputType inputType, | 117 InputEvent::InputType inputType, |
| 120 const String& data, | 118 const String& data, |
| 121 InputEvent::EventIsComposing isComposing) { | 119 InputEvent::EventIsComposing isComposing) { |
| 122 if (startRoot) | 120 if (startRoot) |
| 123 dispatchInputEvent(startRoot, inputType, data, isComposing); | 121 dispatchInputEvent(startRoot, inputType, data, isComposing); |
| 124 if (endRoot && endRoot != startRoot) | 122 if (endRoot && endRoot != startRoot) |
| 125 dispatchInputEvent(endRoot, inputType, data, isComposing); | 123 dispatchInputEvent(endRoot, inputType, data, isComposing); |
| 126 } | 124 } |
| 127 | 125 |
| 128 InputEvent::EventIsComposing isComposingFromCommand( | |
| 129 const CompositeEditCommand* command) { | |
| 130 if (command->isTypingCommand() && | |
| 131 toTypingCommand(command)->compositionType() != | |
| 132 TypingCommand::TextCompositionNone) | |
| 133 return InputEvent::EventIsComposing::IsComposing; | |
| 134 return InputEvent::EventIsComposing::NotComposing; | |
| 135 } | |
| 136 | |
| 137 } // anonymous namespace | 126 } // anonymous namespace |
| 138 | 127 |
| 139 Editor::RevealSelectionScope::RevealSelectionScope(Editor* editor) | 128 Editor::RevealSelectionScope::RevealSelectionScope(Editor* editor) |
| 140 : m_editor(editor) { | 129 : m_editor(editor) { |
| 141 ++m_editor->m_preventRevealSelection; | 130 ++m_editor->m_preventRevealSelection; |
| 142 } | 131 } |
| 143 | 132 |
| 144 Editor::RevealSelectionScope::~RevealSelectionScope() { | 133 Editor::RevealSelectionScope::~RevealSelectionScope() { |
| 145 DCHECK(m_editor->m_preventRevealSelection); | 134 DCHECK(m_editor->m_preventRevealSelection); |
| 146 --m_editor->m_preventRevealSelection; | 135 --m_editor->m_preventRevealSelection; |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 if (insertMode == InsertMode::Smart) | 605 if (insertMode == InsertMode::Smart) |
| 617 options |= ReplaceSelectionCommand::SmartReplace; | 606 options |= ReplaceSelectionCommand::SmartReplace; |
| 618 if (dragSourceType == DragSourceType::PlainTextSource) | 607 if (dragSourceType == DragSourceType::PlainTextSource) |
| 619 options |= ReplaceSelectionCommand::MatchStyle; | 608 options |= ReplaceSelectionCommand::MatchStyle; |
| 620 DCHECK(frame().document()); | 609 DCHECK(frame().document()); |
| 621 ReplaceSelectionCommand::create(*frame().document(), fragment, options, | 610 ReplaceSelectionCommand::create(*frame().document(), fragment, options, |
| 622 InputEvent::InputType::InsertFromDrop) | 611 InputEvent::InputType::InsertFromDrop) |
| 623 ->apply(EditCommandSource::kMenuOrKeyBinding); | 612 ->apply(EditCommandSource::kMenuOrKeyBinding); |
| 624 } | 613 } |
| 625 | 614 |
| 626 bool Editor::deleteSelectionAfterDraggingWithEvents( | |
| 627 Element* dragSource, | |
| 628 DeleteMode deleteMode, | |
| 629 const Position& referenceMovePosition) { | |
| 630 if (!dragSource || !dragSource->isConnected()) | |
| 631 return true; | |
| 632 | |
| 633 // Dispatch 'beforeinput'. | |
| 634 const bool shouldDelete = dispatchBeforeInputEditorCommand( | |
| 635 dragSource, InputEvent::InputType::DeleteByDrag, | |
| 636 nullptr) == DispatchEventResult::NotCanceled; | |
| 637 | |
| 638 // 'beforeinput' event handler may destroy frame, return false to cancel | |
| 639 // remaining actions; | |
| 640 if (m_frame->document()->frame() != m_frame) | |
| 641 return false; | |
| 642 | |
| 643 if (shouldDelete && dragSource->isConnected()) { | |
| 644 deleteSelectionWithSmartDelete( | |
| 645 EditCommandSource::kMenuOrKeyBinding, deleteMode, | |
| 646 InputEvent::InputType::DeleteByDrag, referenceMovePosition); | |
| 647 } | |
| 648 | |
| 649 return true; | |
| 650 } | |
| 651 | |
| 652 bool Editor::replaceSelectionAfterDraggingWithEvents( | |
| 653 Element* dropTarget, | |
| 654 DragData* dragData, | |
| 655 DocumentFragment* fragment, | |
| 656 Range* dropCaretRange, | |
| 657 InsertMode insertMode, | |
| 658 DragSourceType dragSourceType) { | |
| 659 if (!dropTarget || !dropTarget->isConnected()) | |
| 660 return true; | |
| 661 | |
| 662 // Dispatch 'beforeinput'. | |
| 663 DataTransfer* dataTransfer = | |
| 664 DataTransfer::create(DataTransfer::DragAndDrop, DataTransferReadable, | |
| 665 dragData->platformData()); | |
| 666 dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask()); | |
| 667 const bool shouldInsert = | |
| 668 dispatchBeforeInputDataTransfer( | |
| 669 dropTarget, InputEvent::InputType::InsertFromDrop, dataTransfer, | |
| 670 nullptr) == DispatchEventResult::NotCanceled; | |
| 671 | |
| 672 // 'beforeinput' event handler may destroy frame, return false to cancel | |
| 673 // remaining actions; | |
| 674 if (m_frame->document()->frame() != m_frame) | |
| 675 return false; | |
| 676 | |
| 677 if (shouldInsert && dropTarget->isConnected()) | |
| 678 replaceSelectionAfterDragging(fragment, insertMode, dragSourceType); | |
| 679 | |
| 680 return true; | |
| 681 } | |
| 682 | |
| 683 EphemeralRange Editor::selectedRange() { | 615 EphemeralRange Editor::selectedRange() { |
| 684 return frame().selection().selection().toNormalizedEphemeralRange(); | 616 return frame().selection().selection().toNormalizedEphemeralRange(); |
| 685 } | 617 } |
| 686 | 618 |
| 687 bool Editor::canDeleteRange(const EphemeralRange& range) const { | 619 bool Editor::canDeleteRange(const EphemeralRange& range) const { |
| 688 if (range.isCollapsed()) | 620 if (range.isCollapsed()) |
| 689 return false; | 621 return false; |
| 690 | 622 |
| 691 Node* startContainer = range.startPosition().computeContainerNode(); | 623 Node* startContainer = range.startPosition().computeContainerNode(); |
| 692 Node* endContainer = range.endPosition().computeContainerNode(); | 624 Node* endContainer = range.endPosition().computeContainerNode(); |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 spellChecker().updateMarkersForWordsAffectedByEditing(true); | 994 spellChecker().updateMarkersForWordsAffectedByEditing(true); |
| 1063 if (enclosingTextControl(frame().selection().start())) { | 995 if (enclosingTextControl(frame().selection().start())) { |
| 1064 String plainText = frame().selectedTextForClipboard(); | 996 String plainText = frame().selectedTextForClipboard(); |
| 1065 Pasteboard::generalPasteboard()->writePlainText( | 997 Pasteboard::generalPasteboard()->writePlainText( |
| 1066 plainText, canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace | 998 plainText, canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace |
| 1067 : Pasteboard::CannotSmartReplace); | 999 : Pasteboard::CannotSmartReplace); |
| 1068 } else { | 1000 } else { |
| 1069 writeSelectionToPasteboard(); | 1001 writeSelectionToPasteboard(); |
| 1070 } | 1002 } |
| 1071 | 1003 |
| 1072 if (source == EditCommandSource::kMenuOrKeyBinding) { | |
| 1073 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), | |
| 1074 InputEvent::InputType::DeleteByCut, | |
| 1075 nullptr, nullptr) != | |
| 1076 DispatchEventResult::NotCanceled) | |
| 1077 return; | |
| 1078 // 'beforeinput' event handler may destroy target frame. | |
| 1079 if (m_frame->document()->frame() != m_frame) | |
| 1080 return; | |
| 1081 } | |
| 1082 deleteSelectionWithSmartDelete( | 1004 deleteSelectionWithSmartDelete( |
| 1083 source, canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, | 1005 source, canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
| 1084 InputEvent::InputType::DeleteByCut); | 1006 InputEvent::InputType::DeleteByCut); |
| 1085 } | 1007 } |
| 1086 } | 1008 } |
| 1087 | 1009 |
| 1088 void Editor::copy() { | 1010 void Editor::copy() { |
| 1089 if (tryDHTMLCopy()) | 1011 if (tryDHTMLCopy()) |
| 1090 return; // DHTML did the whole operation | 1012 return; // DHTML did the whole operation |
| 1091 if (!canCopy()) | 1013 if (!canCopy()) |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1106 Document* document = frame().document(); | 1028 Document* document = frame().document(); |
| 1107 if (HTMLImageElement* imageElement = | 1029 if (HTMLImageElement* imageElement = |
| 1108 imageElementFromImageDocument(document)) | 1030 imageElementFromImageDocument(document)) |
| 1109 writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), imageElement, | 1031 writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), imageElement, |
| 1110 document->title()); | 1032 document->title()); |
| 1111 else | 1033 else |
| 1112 writeSelectionToPasteboard(); | 1034 writeSelectionToPasteboard(); |
| 1113 } | 1035 } |
| 1114 } | 1036 } |
| 1115 | 1037 |
| 1116 void Editor::paste(EditCommandSource source) { | 1038 // TODO(chongz): Pass |EditCommandSource| to |TextEvent| and don't fire |
| 1039 // 'beforeinput' for JS triggered paste. |
| 1040 void Editor::paste(EditCommandSource) { |
| 1117 DCHECK(frame().document()); | 1041 DCHECK(frame().document()); |
| 1118 if (tryDHTMLPaste(AllMimeTypes)) | 1042 if (tryDHTMLPaste(AllMimeTypes)) |
| 1119 return; // DHTML did the whole operation | 1043 return; // DHTML did the whole operation |
| 1120 if (!canPaste()) | 1044 if (!canPaste()) |
| 1121 return; | 1045 return; |
| 1122 spellChecker().updateMarkersForWordsAffectedByEditing(false); | 1046 spellChecker().updateMarkersForWordsAffectedByEditing(false); |
| 1123 ResourceFetcher* loader = frame().document()->fetcher(); | 1047 ResourceFetcher* loader = frame().document()->fetcher(); |
| 1124 ResourceCacheValidationSuppressor validationSuppressor(loader); | 1048 ResourceCacheValidationSuppressor validationSuppressor(loader); |
| 1125 | 1049 |
| 1126 PasteMode pasteMode = frame().selection().isContentRichlyEditable() | 1050 PasteMode pasteMode = frame().selection().isContentRichlyEditable() |
| 1127 ? AllMimeTypes | 1051 ? AllMimeTypes |
| 1128 : PlainTextOnly; | 1052 : PlainTextOnly; |
| 1129 | 1053 |
| 1130 if (source == EditCommandSource::kMenuOrKeyBinding) { | |
| 1131 DataTransfer* dataTransfer = | |
| 1132 DataTransfer::create(DataTransfer::CopyAndPaste, DataTransferReadable, | |
| 1133 DataObject::createFromPasteboard(pasteMode)); | |
| 1134 | |
| 1135 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), | |
| 1136 InputEvent::InputType::InsertFromPaste, | |
| 1137 dataTransfer, nullptr) != | |
| 1138 DispatchEventResult::NotCanceled) | |
| 1139 return; | |
| 1140 // 'beforeinput' event handler may destroy target frame. | |
| 1141 if (m_frame->document()->frame() != m_frame) | |
| 1142 return; | |
| 1143 } | |
| 1144 | |
| 1145 if (pasteMode == AllMimeTypes) | 1054 if (pasteMode == AllMimeTypes) |
| 1146 pasteWithPasteboard(Pasteboard::generalPasteboard()); | 1055 pasteWithPasteboard(Pasteboard::generalPasteboard()); |
| 1147 else | 1056 else |
| 1148 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); | 1057 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); |
| 1149 } | 1058 } |
| 1150 | 1059 |
| 1151 void Editor::pasteAsPlainText(EditCommandSource source) { | 1060 void Editor::pasteAsPlainText(EditCommandSource source) { |
| 1152 if (tryDHTMLPaste(PlainTextOnly)) | 1061 if (tryDHTMLPaste(PlainTextOnly)) |
| 1153 return; | 1062 return; |
| 1154 if (!canPaste()) | 1063 if (!canPaste()) |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1289 : direction == RightToLeftWritingDirection ? "rtl" : "inherit", | 1198 : direction == RightToLeftWritingDirection ? "rtl" : "inherit", |
| 1290 false); | 1199 false); |
| 1291 applyParagraphStyleToSelection( | 1200 applyParagraphStyleToSelection( |
| 1292 EditCommandSource::kMenuOrKeyBinding, style, | 1201 EditCommandSource::kMenuOrKeyBinding, style, |
| 1293 InputEvent::InputType::FormatSetBlockTextDirection); | 1202 InputEvent::InputType::FormatSetBlockTextDirection); |
| 1294 } | 1203 } |
| 1295 | 1204 |
| 1296 void Editor::revealSelectionAfterEditingOperation( | 1205 void Editor::revealSelectionAfterEditingOperation( |
| 1297 const ScrollAlignment& alignment, | 1206 const ScrollAlignment& alignment, |
| 1298 RevealExtentOption revealExtentOption) { | 1207 RevealExtentOption revealExtentOption) { |
| 1299 if (m_preventRevealSelection) | 1208 if (m_preventRevealSelection || !m_frame->selection().isAvailable()) |
| 1300 return; | 1209 return; |
| 1301 frame().selection().revealSelection(alignment, revealExtentOption); | 1210 frame().selection().revealSelection(alignment, revealExtentOption); |
| 1302 } | 1211 } |
| 1303 | 1212 |
| 1304 void Editor::transpose(EditCommandSource source) { | 1213 void Editor::transpose(EditCommandSource source) { |
| 1305 if (!canEdit()) | 1214 if (!canEdit()) |
| 1306 return; | 1215 return; |
| 1307 | 1216 |
| 1308 VisibleSelection selection = frame().selection().selection(); | 1217 VisibleSelection selection = frame().selection().selection(); |
| 1309 if (!selection.isCaret()) | 1218 if (!selection.isCaret()) |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1707 } | 1616 } |
| 1708 | 1617 |
| 1709 DEFINE_TRACE(Editor) { | 1618 DEFINE_TRACE(Editor) { |
| 1710 visitor->trace(m_frame); | 1619 visitor->trace(m_frame); |
| 1711 visitor->trace(m_lastEditCommand); | 1620 visitor->trace(m_lastEditCommand); |
| 1712 visitor->trace(m_undoStack); | 1621 visitor->trace(m_undoStack); |
| 1713 visitor->trace(m_mark); | 1622 visitor->trace(m_mark); |
| 1714 } | 1623 } |
| 1715 | 1624 |
| 1716 } // namespace blink | 1625 } // namespace blink |
| OLD | NEW |