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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 #include "core/inspector/ConsoleMessage.h" | 79 #include "core/inspector/ConsoleMessage.h" |
80 #include "core/layout/HitTestResult.h" | 80 #include "core/layout/HitTestResult.h" |
81 #include "core/layout/LayoutImage.h" | 81 #include "core/layout/LayoutImage.h" |
82 #include "core/loader/EmptyClients.h" | 82 #include "core/loader/EmptyClients.h" |
83 #include "core/page/DragData.h" | 83 #include "core/page/DragData.h" |
84 #include "core/page/EditorClient.h" | 84 #include "core/page/EditorClient.h" |
85 #include "core/page/FocusController.h" | 85 #include "core/page/FocusController.h" |
86 #include "core/page/Page.h" | 86 #include "core/page/Page.h" |
87 #include "core/svg/SVGImageElement.h" | 87 #include "core/svg/SVGImageElement.h" |
88 #include "platform/KillRing.h" | 88 #include "platform/KillRing.h" |
| 89 #include "platform/clipboard/ClipboardMimeTypes.h" |
89 #include "platform/weborigin/KURL.h" | 90 #include "platform/weborigin/KURL.h" |
90 #include "wtf/PtrUtil.h" | 91 #include "wtf/PtrUtil.h" |
91 #include "wtf/text/CharacterNames.h" | 92 #include "wtf/text/CharacterNames.h" |
92 | 93 |
93 namespace blink { | 94 namespace blink { |
94 | 95 |
95 using namespace HTMLNames; | 96 using namespace HTMLNames; |
96 using namespace WTF; | 97 using namespace WTF; |
97 using namespace Unicode; | 98 using namespace Unicode; |
98 | 99 |
99 namespace { | 100 namespace { |
100 | 101 |
| 102 DispatchEventResult dispatchBeforeInputEvent( |
| 103 Node* target, |
| 104 InputEvent::InputType inputType, |
| 105 const String& data, |
| 106 DataTransfer* dataTransfer, |
| 107 InputEvent::EventCancelable isCancelable, |
| 108 InputEvent::EventIsComposing isComposing, |
| 109 const RangeVector* ranges) { |
| 110 if (!RuntimeEnabledFeatures::inputEventEnabled()) |
| 111 return DispatchEventResult::NotCanceled; |
| 112 if (!target || !target->isConnected()) |
| 113 return DispatchEventResult::NotCanceled; |
| 114 |
| 115 if (!hasRichlyEditableStyle(*target)) { |
| 116 // Plain-text only elements (<input>, <textarea>, etc.) don't support |
| 117 // DataTransfer or Range. |
| 118 dataTransfer = nullptr; |
| 119 ranges = nullptr; |
| 120 } |
| 121 |
| 122 InputEvent* beforeInputEvent; |
| 123 |
| 124 if (dataTransfer) { |
| 125 beforeInputEvent = InputEvent::createBeforeInput( |
| 126 inputType, dataTransfer, isCancelable, isComposing, ranges); |
| 127 } else { |
| 128 beforeInputEvent = InputEvent::createBeforeInput( |
| 129 inputType, data, isCancelable, isComposing, ranges); |
| 130 } |
| 131 return target->dispatchEvent(beforeInputEvent); |
| 132 } |
| 133 |
101 void dispatchInputEvent(Element* target, | 134 void dispatchInputEvent(Element* target, |
102 InputEvent::InputType inputType, | 135 InputEvent::InputType inputType, |
103 const String& data, | 136 const String& data, |
104 InputEvent::EventIsComposing isComposing) { | 137 InputEvent::EventIsComposing isComposing) { |
105 if (!RuntimeEnabledFeatures::inputEventEnabled()) | 138 if (!RuntimeEnabledFeatures::inputEventEnabled()) |
106 return; | 139 return; |
107 if (!target) | 140 if (!target || !target->isConnected()) |
108 return; | 141 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 = | 142 InputEvent* inputEvent = |
112 InputEvent::createInput(inputType, data, isComposing, nullptr); | 143 InputEvent::createInput(inputType, data, isComposing); |
113 target->dispatchScopedEvent(inputEvent); | 144 target->dispatchScopedEvent(inputEvent); |
114 } | 145 } |
115 | 146 |
116 void dispatchInputEventEditableContentChanged( | 147 void dispatchInputEventEditableContentChanged( |
117 Element* startRoot, | 148 Element* startRoot, |
118 Element* endRoot, | 149 Element* endRoot, |
119 InputEvent::InputType inputType, | 150 InputEvent::InputType inputType, |
120 const String& data, | 151 const String& data, |
121 InputEvent::EventIsComposing isComposing) { | 152 InputEvent::EventIsComposing isComposing) { |
122 if (startRoot) | 153 if (startRoot) |
123 dispatchInputEvent(startRoot, inputType, data, isComposing); | 154 dispatchInputEvent(startRoot, inputType, data, isComposing); |
124 if (endRoot && endRoot != startRoot) | 155 if (endRoot && endRoot != startRoot) |
125 dispatchInputEvent(endRoot, inputType, data, isComposing); | 156 dispatchInputEvent(endRoot, inputType, data, isComposing); |
126 } | 157 } |
127 | 158 |
128 InputEvent::EventIsComposing isComposingFromCommand( | 159 InputEvent::EventIsComposing isComposingFromCommand( |
129 const CompositeEditCommand* command) { | 160 const CompositeEditCommand* command) { |
130 if (command->isTypingCommand() && | 161 if (command->isTypingCommand() && |
131 toTypingCommand(command)->compositionType() != | 162 toTypingCommand(command)->compositionType() != |
132 TypingCommand::TextCompositionNone) | 163 TypingCommand::TextCompositionNone) |
133 return InputEvent::EventIsComposing::IsComposing; | 164 return InputEvent::IsComposing; |
134 return InputEvent::EventIsComposing::NotComposing; | 165 return InputEvent::NotComposing; |
| 166 } |
| 167 |
| 168 InputEvent::EventCancelable isCancelableFromCommand( |
| 169 const CompositeEditCommand* command) { |
| 170 if (command->isTypingCommand() && |
| 171 toTypingCommand(command)->compositionType() == |
| 172 TypingCommand::TextCompositionUpdate) |
| 173 return InputEvent::NotCancelable; |
| 174 return InputEvent::IsCancelable; |
135 } | 175 } |
136 | 176 |
137 } // anonymous namespace | 177 } // anonymous namespace |
138 | 178 |
139 Editor::RevealSelectionScope::RevealSelectionScope(Editor* editor) | 179 Editor::RevealSelectionScope::RevealSelectionScope(Editor* editor) |
140 : m_editor(editor) { | 180 : m_editor(editor) { |
141 ++m_editor->m_preventRevealSelection; | 181 ++m_editor->m_preventRevealSelection; |
142 } | 182 } |
143 | 183 |
144 Editor::RevealSelectionScope::~RevealSelectionScope() { | 184 Editor::RevealSelectionScope::~RevealSelectionScope() { |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 if (insertMode == InsertMode::Smart) | 643 if (insertMode == InsertMode::Smart) |
604 options |= ReplaceSelectionCommand::SmartReplace; | 644 options |= ReplaceSelectionCommand::SmartReplace; |
605 if (dragSourceType == DragSourceType::PlainTextSource) | 645 if (dragSourceType == DragSourceType::PlainTextSource) |
606 options |= ReplaceSelectionCommand::MatchStyle; | 646 options |= ReplaceSelectionCommand::MatchStyle; |
607 DCHECK(frame().document()); | 647 DCHECK(frame().document()); |
608 ReplaceSelectionCommand::create(*frame().document(), fragment, options, | 648 ReplaceSelectionCommand::create(*frame().document(), fragment, options, |
609 InputEvent::InputType::InsertFromDrop) | 649 InputEvent::InputType::InsertFromDrop) |
610 ->apply(); | 650 ->apply(); |
611 } | 651 } |
612 | 652 |
613 bool Editor::deleteSelectionAfterDraggingWithEvents( | |
614 Element* dragSource, | |
615 DeleteMode deleteMode, | |
616 const Position& referenceMovePosition) { | |
617 if (!dragSource || !dragSource->isConnected()) | |
618 return true; | |
619 | |
620 // Dispatch 'beforeinput'. | |
621 const bool shouldDelete = dispatchBeforeInputEditorCommand( | |
622 dragSource, InputEvent::InputType::DeleteByDrag, | |
623 nullptr) == DispatchEventResult::NotCanceled; | |
624 | |
625 // 'beforeinput' event handler may destroy frame, return false to cancel | |
626 // remaining actions; | |
627 if (m_frame->document()->frame() != m_frame) | |
628 return false; | |
629 | |
630 if (shouldDelete && dragSource->isConnected()) { | |
631 deleteSelectionWithSmartDelete( | |
632 deleteMode, InputEvent::InputType::DeleteByDrag, referenceMovePosition); | |
633 } | |
634 | |
635 return true; | |
636 } | |
637 | |
638 bool Editor::replaceSelectionAfterDraggingWithEvents( | |
639 Element* dropTarget, | |
640 DragData* dragData, | |
641 DocumentFragment* fragment, | |
642 Range* dropCaretRange, | |
643 InsertMode insertMode, | |
644 DragSourceType dragSourceType) { | |
645 if (!dropTarget || !dropTarget->isConnected()) | |
646 return true; | |
647 | |
648 // Dispatch 'beforeinput'. | |
649 DataTransfer* dataTransfer = | |
650 DataTransfer::create(DataTransfer::DragAndDrop, DataTransferReadable, | |
651 dragData->platformData()); | |
652 dataTransfer->setSourceOperation(dragData->draggingSourceOperationMask()); | |
653 const bool shouldInsert = | |
654 dispatchBeforeInputDataTransfer( | |
655 dropTarget, InputEvent::InputType::InsertFromDrop, dataTransfer, | |
656 nullptr) == DispatchEventResult::NotCanceled; | |
657 | |
658 // 'beforeinput' event handler may destroy frame, return false to cancel | |
659 // remaining actions; | |
660 if (m_frame->document()->frame() != m_frame) | |
661 return false; | |
662 | |
663 if (shouldInsert && dropTarget->isConnected()) | |
664 replaceSelectionAfterDragging(fragment, insertMode, dragSourceType); | |
665 | |
666 return true; | |
667 } | |
668 | |
669 EphemeralRange Editor::selectedRange() { | 653 EphemeralRange Editor::selectedRange() { |
670 return frame().selection().selection().toNormalizedEphemeralRange(); | 654 return frame().selection().selection().toNormalizedEphemeralRange(); |
671 } | 655 } |
672 | 656 |
673 bool Editor::canDeleteRange(const EphemeralRange& range) const { | 657 bool Editor::canDeleteRange(const EphemeralRange& range) const { |
674 if (range.isCollapsed()) | 658 if (range.isCollapsed()) |
675 return false; | 659 return false; |
676 | 660 |
677 Node* startContainer = range.startPosition().computeContainerNode(); | 661 Node* startContainer = range.startPosition().computeContainerNode(); |
678 Node* endContainer = range.endPosition().computeContainerNode(); | 662 Node* endContainer = range.endPosition().computeContainerNode(); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 static void dispatchEditableContentChangedEvents(Element* startRoot, | 779 static void dispatchEditableContentChangedEvents(Element* startRoot, |
796 Element* endRoot) { | 780 Element* endRoot) { |
797 if (startRoot) | 781 if (startRoot) |
798 startRoot->dispatchEvent( | 782 startRoot->dispatchEvent( |
799 Event::create(EventTypeNames::webkitEditableContentChanged)); | 783 Event::create(EventTypeNames::webkitEditableContentChanged)); |
800 if (endRoot && endRoot != startRoot) | 784 if (endRoot && endRoot != startRoot) |
801 endRoot->dispatchEvent( | 785 endRoot->dispatchEvent( |
802 Event::create(EventTypeNames::webkitEditableContentChanged)); | 786 Event::create(EventTypeNames::webkitEditableContentChanged)); |
803 } | 787 } |
804 | 788 |
| 789 bool Editor::willApplyEditing(CompositeEditCommand* cmd) { |
| 790 // Don't fire 'beforeinput', return true to continue. |
| 791 if (m_executingCommandFromDOM || |
| 792 cmd->inputType() == InputEvent::InputType::None) |
| 793 return true; |
| 794 |
| 795 DispatchEventResult result = dispatchBeforeInputEvent( |
| 796 eventTargetNodeForDocument(m_frame->document()), cmd->inputType(), |
| 797 cmd->textDataForInputEvent(), cmd->dataTransferForInputEvent(), |
| 798 isCancelableFromCommand(cmd), isComposingFromCommand(cmd), |
| 799 cmd->targetRangesForInputEvent()); |
| 800 |
| 801 // 'beforeinput' event handler may destroy target frame. |
| 802 if (m_frame->document()->frame() != m_frame) |
| 803 return false; |
| 804 return result == DispatchEventResult::NotCanceled; |
| 805 } |
| 806 |
805 void Editor::appliedEditing(CompositeEditCommand* cmd) { | 807 void Editor::appliedEditing(CompositeEditCommand* cmd) { |
806 DCHECK(!cmd->isCommandGroupWrapper()); | 808 DCHECK(!cmd->isCommandGroupWrapper()); |
807 EventQueueScope scope; | 809 EventQueueScope scope; |
808 | 810 |
809 // Request spell checking before any further DOM change. | 811 // Request spell checking before any further DOM change. |
810 spellChecker().markMisspellingsAfterApplyingCommand(*cmd); | 812 spellChecker().markMisspellingsAfterApplyingCommand(*cmd); |
811 | 813 |
812 EditCommandComposition* composition = cmd->composition(); | 814 EditCommandComposition* composition = cmd->composition(); |
813 DCHECK(composition); | 815 DCHECK(composition); |
814 dispatchEditableContentChangedEvents( | 816 dispatchEditableContentChangedEvents( |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 : m_frame(&frame), | 928 : m_frame(&frame), |
927 m_undoStack(UndoStack::create()), | 929 m_undoStack(UndoStack::create()), |
928 m_preventRevealSelection(0), | 930 m_preventRevealSelection(0), |
929 m_shouldStartNewKillRingSequence(false), | 931 m_shouldStartNewKillRingSequence(false), |
930 // This is off by default, since most editors want this behavior (this | 932 // This is off by default, since most editors want this behavior (this |
931 // matches IE but not FF). | 933 // matches IE but not FF). |
932 m_shouldStyleWithCSS(false), | 934 m_shouldStyleWithCSS(false), |
933 m_killRing(wrapUnique(new KillRing)), | 935 m_killRing(wrapUnique(new KillRing)), |
934 m_areMarkedTextMatchesHighlighted(false), | 936 m_areMarkedTextMatchesHighlighted(false), |
935 m_defaultParagraphSeparator(EditorParagraphSeparatorIsDiv), | 937 m_defaultParagraphSeparator(EditorParagraphSeparatorIsDiv), |
936 m_overwriteModeEnabled(false) {} | 938 m_overwriteModeEnabled(false), |
| 939 m_executingCommandFromDOM(false) {} |
937 | 940 |
938 Editor::~Editor() {} | 941 Editor::~Editor() {} |
939 | 942 |
940 void Editor::clear() { | 943 void Editor::clear() { |
941 frame().inputMethodController().clear(); | 944 frame().inputMethodController().clear(); |
942 m_shouldStyleWithCSS = false; | 945 m_shouldStyleWithCSS = false; |
943 m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv; | 946 m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv; |
944 m_undoStack->clear(); | 947 m_undoStack->clear(); |
945 } | 948 } |
946 | 949 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 spellChecker().updateMarkersForWordsAffectedByEditing(true); | 1038 spellChecker().updateMarkersForWordsAffectedByEditing(true); |
1036 if (enclosingTextControl(frame().selection().start())) { | 1039 if (enclosingTextControl(frame().selection().start())) { |
1037 String plainText = frame().selectedTextForClipboard(); | 1040 String plainText = frame().selectedTextForClipboard(); |
1038 Pasteboard::generalPasteboard()->writePlainText( | 1041 Pasteboard::generalPasteboard()->writePlainText( |
1039 plainText, canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace | 1042 plainText, canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace |
1040 : Pasteboard::CannotSmartReplace); | 1043 : Pasteboard::CannotSmartReplace); |
1041 } else { | 1044 } else { |
1042 writeSelectionToPasteboard(); | 1045 writeSelectionToPasteboard(); |
1043 } | 1046 } |
1044 | 1047 |
1045 if (source == CommandFromMenuOrKeyBinding) { | |
1046 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), | |
1047 InputEvent::InputType::DeleteByCut, | |
1048 nullptr, nullptr) != | |
1049 DispatchEventResult::NotCanceled) | |
1050 return; | |
1051 // 'beforeinput' event handler may destroy target frame. | |
1052 if (m_frame->document()->frame() != m_frame) | |
1053 return; | |
1054 } | |
1055 deleteSelectionWithSmartDelete( | 1048 deleteSelectionWithSmartDelete( |
1056 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, | 1049 canSmartCopyOrDelete() ? DeleteMode::Smart : DeleteMode::Simple, |
1057 InputEvent::InputType::DeleteByCut); | 1050 InputEvent::InputType::DeleteByCut); |
1058 } | 1051 } |
1059 } | 1052 } |
1060 | 1053 |
1061 void Editor::copy() { | 1054 void Editor::copy() { |
1062 if (tryDHTMLCopy()) | 1055 if (tryDHTMLCopy()) |
1063 return; // DHTML did the whole operation | 1056 return; // DHTML did the whole operation |
1064 if (!canCopy()) | 1057 if (!canCopy()) |
(...skipping 28 matching lines...) Expand all Loading... |
1093 if (!canPaste()) | 1086 if (!canPaste()) |
1094 return; | 1087 return; |
1095 spellChecker().updateMarkersForWordsAffectedByEditing(false); | 1088 spellChecker().updateMarkersForWordsAffectedByEditing(false); |
1096 ResourceFetcher* loader = frame().document()->fetcher(); | 1089 ResourceFetcher* loader = frame().document()->fetcher(); |
1097 ResourceCacheValidationSuppressor validationSuppressor(loader); | 1090 ResourceCacheValidationSuppressor validationSuppressor(loader); |
1098 | 1091 |
1099 PasteMode pasteMode = frame().selection().isContentRichlyEditable() | 1092 PasteMode pasteMode = frame().selection().isContentRichlyEditable() |
1100 ? AllMimeTypes | 1093 ? AllMimeTypes |
1101 : PlainTextOnly; | 1094 : PlainTextOnly; |
1102 | 1095 |
1103 if (source == CommandFromMenuOrKeyBinding) { | |
1104 DataTransfer* dataTransfer = | |
1105 DataTransfer::create(DataTransfer::CopyAndPaste, DataTransferReadable, | |
1106 DataObject::createFromPasteboard(pasteMode)); | |
1107 | |
1108 if (dispatchBeforeInputDataTransfer(findEventTargetFromSelection(), | |
1109 InputEvent::InputType::InsertFromPaste, | |
1110 dataTransfer, nullptr) != | |
1111 DispatchEventResult::NotCanceled) | |
1112 return; | |
1113 // 'beforeinput' event handler may destroy target frame. | |
1114 if (m_frame->document()->frame() != m_frame) | |
1115 return; | |
1116 } | |
1117 | |
1118 if (pasteMode == AllMimeTypes) | 1096 if (pasteMode == AllMimeTypes) |
1119 pasteWithPasteboard(Pasteboard::generalPasteboard()); | 1097 pasteWithPasteboard(Pasteboard::generalPasteboard()); |
1120 else | 1098 else |
1121 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); | 1099 pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard()); |
1122 } | 1100 } |
1123 | 1101 |
1124 void Editor::pasteAsPlainText(EditorCommandSource source) { | 1102 void Editor::pasteAsPlainText(EditorCommandSource source) { |
1125 if (tryDHTMLPaste(PlainTextOnly)) | 1103 if (tryDHTMLPaste(PlainTextOnly)) |
1126 return; | 1104 return; |
1127 if (!canPaste()) | 1105 if (!canPaste()) |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), | 1202 writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), |
1225 result.innerNodeOrImageMapImage(), | 1203 result.innerNodeOrImageMapImage(), |
1226 result.altDisplayString()); | 1204 result.altDisplayString()); |
1227 } | 1205 } |
1228 | 1206 |
1229 bool Editor::canUndo() { | 1207 bool Editor::canUndo() { |
1230 return m_undoStack->canUndo(); | 1208 return m_undoStack->canUndo(); |
1231 } | 1209 } |
1232 | 1210 |
1233 void Editor::undo() { | 1211 void Editor::undo() { |
| 1212 if (!m_executingCommandFromDOM) { |
| 1213 if (dispatchBeforeInputEvent( |
| 1214 m_frame->document(), InputEvent::InputType::HistoryUndo, nullAtom, |
| 1215 nullptr, InputEvent::IsCancelable, InputEvent::NotComposing, |
| 1216 nullptr) != DispatchEventResult::NotCanceled) |
| 1217 return; |
| 1218 |
| 1219 // 'beforeinput' event handler may destroy target frame. |
| 1220 if (m_frame->document()->frame() != m_frame) |
| 1221 return; |
| 1222 } |
1234 m_undoStack->undo(); | 1223 m_undoStack->undo(); |
1235 } | 1224 } |
1236 | 1225 |
1237 bool Editor::canRedo() { | 1226 bool Editor::canRedo() { |
1238 return m_undoStack->canRedo(); | 1227 return m_undoStack->canRedo(); |
1239 } | 1228 } |
1240 | 1229 |
1241 void Editor::redo() { | 1230 void Editor::redo() { |
| 1231 if (!m_executingCommandFromDOM) { |
| 1232 if (dispatchBeforeInputEvent( |
| 1233 m_frame->document(), InputEvent::InputType::HistoryRedo, nullAtom, |
| 1234 nullptr, InputEvent::IsCancelable, InputEvent::NotComposing, |
| 1235 nullptr) != DispatchEventResult::NotCanceled) |
| 1236 return; |
| 1237 |
| 1238 // 'beforeinput' event handler may destroy target frame. |
| 1239 if (m_frame->document()->frame() != m_frame) |
| 1240 return; |
| 1241 } |
1242 m_undoStack->redo(); | 1242 m_undoStack->redo(); |
1243 } | 1243 } |
1244 | 1244 |
1245 void Editor::setBaseWritingDirection(WritingDirection direction) { | 1245 void Editor::setBaseWritingDirection(WritingDirection direction) { |
1246 Element* focusedElement = frame().document()->focusedElement(); | 1246 Element* focusedElement = frame().document()->focusedElement(); |
1247 if (isTextControlElement(focusedElement)) { | 1247 if (isTextControlElement(focusedElement)) { |
1248 if (direction == NaturalWritingDirection) | 1248 if (direction == NaturalWritingDirection) |
1249 return; | 1249 return; |
1250 focusedElement->setAttribute( | 1250 focusedElement->setAttribute( |
1251 dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl"); | 1251 dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl"); |
1252 focusedElement->dispatchInputEvent(); | 1252 focusedElement->dispatchInputEvent(); |
1253 return; | 1253 return; |
1254 } | 1254 } |
1255 | 1255 |
1256 MutableStylePropertySet* style = | 1256 MutableStylePropertySet* style = |
1257 MutableStylePropertySet::create(HTMLQuirksMode); | 1257 MutableStylePropertySet::create(HTMLQuirksMode); |
1258 style->setProperty( | 1258 style->setProperty( |
1259 CSSPropertyDirection, | 1259 CSSPropertyDirection, |
1260 direction == LeftToRightWritingDirection | 1260 direction == LeftToRightWritingDirection |
1261 ? "ltr" | 1261 ? "ltr" |
1262 : direction == RightToLeftWritingDirection ? "rtl" : "inherit", | 1262 : direction == RightToLeftWritingDirection ? "rtl" : "inherit", |
1263 false); | 1263 false); |
1264 applyParagraphStyleToSelection( | 1264 applyParagraphStyleToSelection( |
1265 style, InputEvent::InputType::FormatSetBlockTextDirection); | 1265 style, InputEvent::InputType::FormatSetBlockTextDirection); |
1266 } | 1266 } |
1267 | 1267 |
1268 void Editor::revealSelectionAfterEditingOperation( | 1268 void Editor::revealSelectionAfterEditingOperation( |
1269 const ScrollAlignment& alignment, | 1269 const ScrollAlignment& alignment, |
1270 RevealExtentOption revealExtentOption) { | 1270 RevealExtentOption revealExtentOption) { |
1271 if (m_preventRevealSelection) | 1271 if (m_preventRevealSelection || !m_frame->selection().isAvailable()) |
1272 return; | 1272 return; |
1273 frame().selection().revealSelection(alignment, revealExtentOption); | 1273 frame().selection().revealSelection(alignment, revealExtentOption); |
1274 } | 1274 } |
1275 | 1275 |
1276 void Editor::transpose() { | 1276 void Editor::transpose() { |
1277 if (!canEdit()) | 1277 if (!canEdit()) |
1278 return; | 1278 return; |
1279 | 1279 |
1280 VisibleSelection selection = frame().selection().selection(); | 1280 VisibleSelection selection = frame().selection().selection(); |
1281 if (!selection.isCaret()) | 1281 if (!selection.isCaret()) |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1660 } | 1660 } |
1661 | 1661 |
1662 DEFINE_TRACE(Editor) { | 1662 DEFINE_TRACE(Editor) { |
1663 visitor->trace(m_frame); | 1663 visitor->trace(m_frame); |
1664 visitor->trace(m_lastEditCommand); | 1664 visitor->trace(m_lastEditCommand); |
1665 visitor->trace(m_undoStack); | 1665 visitor->trace(m_undoStack); |
1666 visitor->trace(m_mark); | 1666 visitor->trace(m_mark); |
1667 } | 1667 } |
1668 | 1668 |
1669 } // namespace blink | 1669 } // namespace blink |
OLD | NEW |