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 |