Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 #include "core/editing/commands/MergeIdenticalElementsCommand.h" | 49 #include "core/editing/commands/MergeIdenticalElementsCommand.h" |
| 50 #include "core/editing/commands/RemoveCSSPropertyCommand.h" | 50 #include "core/editing/commands/RemoveCSSPropertyCommand.h" |
| 51 #include "core/editing/commands/RemoveNodeCommand.h" | 51 #include "core/editing/commands/RemoveNodeCommand.h" |
| 52 #include "core/editing/commands/RemoveNodePreservingChildrenCommand.h" | 52 #include "core/editing/commands/RemoveNodePreservingChildrenCommand.h" |
| 53 #include "core/editing/commands/ReplaceNodeWithSpanCommand.h" | 53 #include "core/editing/commands/ReplaceNodeWithSpanCommand.h" |
| 54 #include "core/editing/commands/ReplaceSelectionCommand.h" | 54 #include "core/editing/commands/ReplaceSelectionCommand.h" |
| 55 #include "core/editing/commands/SetNodeAttributeCommand.h" | 55 #include "core/editing/commands/SetNodeAttributeCommand.h" |
| 56 #include "core/editing/commands/SplitElementCommand.h" | 56 #include "core/editing/commands/SplitElementCommand.h" |
| 57 #include "core/editing/commands/SplitTextNodeCommand.h" | 57 #include "core/editing/commands/SplitTextNodeCommand.h" |
| 58 #include "core/editing/commands/SplitTextNodeContainingElementCommand.h" | 58 #include "core/editing/commands/SplitTextNodeContainingElementCommand.h" |
| 59 #include "core/editing/commands/TypingCommand.h" | |
| 59 #include "core/editing/commands/WrapContentsInDummySpanCommand.h" | 60 #include "core/editing/commands/WrapContentsInDummySpanCommand.h" |
| 60 #include "core/editing/iterators/TextIterator.h" | 61 #include "core/editing/iterators/TextIterator.h" |
| 61 #include "core/editing/markers/DocumentMarkerController.h" | 62 #include "core/editing/markers/DocumentMarkerController.h" |
| 62 #include "core/editing/serializers/Serialization.h" | 63 #include "core/editing/serializers/Serialization.h" |
| 63 #include "core/editing/spellcheck/SpellChecker.h" | 64 #include "core/editing/spellcheck/SpellChecker.h" |
| 64 #include "core/events/ScopedEventQueue.h" | 65 #include "core/events/ScopedEventQueue.h" |
| 65 #include "core/frame/LocalFrame.h" | 66 #include "core/frame/LocalFrame.h" |
| 66 #include "core/html/HTMLBRElement.h" | 67 #include "core/html/HTMLBRElement.h" |
| 67 #include "core/html/HTMLDivElement.h" | 68 #include "core/html/HTMLDivElement.h" |
| 68 #include "core/html/HTMLElement.h" | 69 #include "core/html/HTMLElement.h" |
| 69 #include "core/html/HTMLLIElement.h" | 70 #include "core/html/HTMLLIElement.h" |
| 70 #include "core/html/HTMLQuoteElement.h" | 71 #include "core/html/HTMLQuoteElement.h" |
| 71 #include "core/html/HTMLSpanElement.h" | 72 #include "core/html/HTMLSpanElement.h" |
| 72 #include "core/layout/LayoutBlock.h" | 73 #include "core/layout/LayoutBlock.h" |
| 73 #include "core/layout/LayoutListItem.h" | 74 #include "core/layout/LayoutListItem.h" |
| 74 #include "core/layout/LayoutText.h" | 75 #include "core/layout/LayoutText.h" |
| 75 #include "core/layout/line/InlineTextBox.h" | 76 #include "core/layout/line/InlineTextBox.h" |
| 76 #include <algorithm> | 77 #include <algorithm> |
| 77 | 78 |
| 78 namespace blink { | 79 namespace blink { |
| 79 | 80 |
| 80 using namespace HTMLNames; | 81 using namespace HTMLNames; |
| 81 | 82 |
| 82 EditCommandComposition* EditCommandComposition::create( | 83 EditCommandComposition* EditCommandComposition::create( |
| 83 Document* document, | 84 Document* document, |
| 84 const VisibleSelection& startingSelection, | 85 const VisibleSelection& startingSelection, |
| 85 const VisibleSelection& endingSelection, | 86 const VisibleSelection& endingSelection) { |
| 86 InputEvent::InputType inputType) { | |
| 87 return new EditCommandComposition(document, startingSelection, | 87 return new EditCommandComposition(document, startingSelection, |
| 88 endingSelection, inputType); | 88 endingSelection); |
| 89 } | 89 } |
| 90 | 90 |
| 91 EditCommandComposition::EditCommandComposition( | 91 EditCommandComposition::EditCommandComposition( |
| 92 Document* document, | 92 Document* document, |
| 93 const VisibleSelection& startingSelection, | 93 const VisibleSelection& startingSelection, |
| 94 const VisibleSelection& endingSelection, | 94 const VisibleSelection& endingSelection) |
| 95 InputEvent::InputType inputType) | |
| 96 : m_document(document), | 95 : m_document(document), |
| 97 m_startingSelection(startingSelection), | 96 m_startingSelection(startingSelection), |
| 98 m_endingSelection(endingSelection), | 97 m_endingSelection(endingSelection), |
| 99 m_startingRootEditableElement(startingSelection.rootEditableElement()), | 98 m_startingRootEditableElement(startingSelection.rootEditableElement()), |
| 100 m_endingRootEditableElement(endingSelection.rootEditableElement()), | 99 m_endingRootEditableElement(endingSelection.rootEditableElement()) {} |
| 101 m_inputType(inputType) {} | |
| 102 | 100 |
| 103 bool EditCommandComposition::belongsTo(const LocalFrame& frame) const { | 101 bool EditCommandComposition::belongsTo(const LocalFrame& frame) const { |
| 104 DCHECK(m_document); | 102 DCHECK(m_document); |
| 105 return m_document->frame() == &frame; | 103 return m_document->frame() == &frame; |
| 106 } | 104 } |
| 107 | 105 |
| 108 void EditCommandComposition::unapply(EditCommandSource source) { | 106 void EditCommandComposition::unapply(EditCommandSource source) { |
| 109 DCHECK(m_document); | 107 DCHECK(m_document); |
| 110 LocalFrame* frame = m_document->frame(); | 108 LocalFrame* frame = m_document->frame(); |
| 111 DCHECK(frame); | 109 DCHECK(frame); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 m_document->updateStyleAndLayoutIgnorePendingStylesheets(); | 143 m_document->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 146 | 144 |
| 147 { | 145 { |
| 148 for (const auto& command : m_commands) | 146 for (const auto& command : m_commands) |
| 149 command->doReapply(); | 147 command->doReapply(); |
| 150 } | 148 } |
| 151 | 149 |
| 152 frame->editor().reappliedEditing(this); | 150 frame->editor().reappliedEditing(this); |
| 153 } | 151 } |
| 154 | 152 |
| 155 bool EditCommandComposition::willUnapply(EditCommandSource) { | 153 bool EditCommandComposition::willUnapply(EditCommandSource source) { |
| 156 // TODO(chongz): Fire 'beforeinput' for 'historyUndo'. | 154 return dispatchBeforeInputEvent(source, m_document->frame(), m_document, |
| 157 return true; | 155 InputEvent::InputType::HistoryUndo, nullAtom, |
| 156 nullptr, InputEvent::IsCancelable, | |
| 157 InputEvent::NotComposing, nullptr); | |
| 158 } | 158 } |
| 159 | 159 |
| 160 bool EditCommandComposition::willReapply(EditCommandSource) { | 160 bool EditCommandComposition::willReapply(EditCommandSource source) { |
| 161 // TODO(chongz): Fire 'beforeinput' for 'historyRedo'. | 161 return dispatchBeforeInputEvent(source, m_document->frame(), m_document, |
| 162 return true; | 162 InputEvent::InputType::HistoryRedo, nullAtom, |
| 163 } | 163 nullptr, InputEvent::IsCancelable, |
| 164 | 164 InputEvent::NotComposing, nullptr); |
| 165 InputEvent::InputType EditCommandComposition::inputType() const { | |
| 166 return m_inputType; | |
| 167 } | 165 } |
| 168 | 166 |
| 169 void EditCommandComposition::append(SimpleEditCommand* command) { | 167 void EditCommandComposition::append(SimpleEditCommand* command) { |
| 170 m_commands.push_back(command); | 168 m_commands.push_back(command); |
| 171 } | 169 } |
| 172 | 170 |
| 173 void EditCommandComposition::append(EditCommandComposition* composition) { | 171 void EditCommandComposition::append(EditCommandComposition* composition) { |
| 174 m_commands.appendVector(composition->m_commands); | 172 m_commands.appendVector(composition->m_commands); |
| 175 } | 173 } |
| 176 | 174 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 case InputEvent::InputType::DeleteByDrag: | 223 case InputEvent::InputType::DeleteByDrag: |
| 226 case InputEvent::InputType::None: | 224 case InputEvent::InputType::None: |
| 227 break; | 225 break; |
| 228 default: | 226 default: |
| 229 NOTREACHED(); | 227 NOTREACHED(); |
| 230 return false; | 228 return false; |
| 231 } | 229 } |
| 232 } | 230 } |
| 233 ensureComposition(); | 231 ensureComposition(); |
| 234 | 232 |
| 233 // Covers the initial TypingCommand and other top-level commands. | |
| 234 // TypingCommand::willAddTypingToOpenCommand() also calls willApplyEditing(). | |
| 235 if (!willApplyEditing(source)) | |
|
Xiaocheng
2016/12/20 05:49:57
Yeah, this should be the right place to fire the e
| |
| 236 return false; | |
| 237 | |
| 235 // Changes to the document may have been made since the last editing operation | 238 // Changes to the document may have been made since the last editing operation |
| 236 // that require a layout, as in <rdar://problem/5658603>. Low level | 239 // that require a layout, as in <rdar://problem/5658603>. Low level |
| 237 // operations, like RemoveNodeCommand, don't require a layout because the high | 240 // operations, like RemoveNodeCommand, don't require a layout because the high |
| 238 // level operations that use them perform one if one is necessary (like for | 241 // level operations that use them perform one if one is necessary (like for |
| 239 // the creation of VisiblePositions). | 242 // the creation of VisiblePositions). |
| 240 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 243 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 241 | 244 |
| 242 if (!willApplyEditing(source)) | |
| 243 return false; | |
| 244 | |
| 245 LocalFrame* frame = document().frame(); | 245 LocalFrame* frame = document().frame(); |
| 246 DCHECK(frame); | 246 DCHECK(frame); |
| 247 EditingState editingState; | 247 EditingState editingState; |
| 248 { | 248 { |
| 249 EventQueueScope eventQueueScope; | 249 EventQueueScope eventQueueScope; |
| 250 doApply(&editingState); | 250 doApply(&editingState); |
| 251 } | 251 } |
| 252 | 252 |
| 253 // Only need to call appliedEditing for top-level commands, and TypingCommands | 253 // Only need to call appliedEditing for top-level commands, and TypingCommands |
| 254 // do it on their own (see TypingCommand::typingAddedToOpenCommand). | 254 // do it on their own (see TypingCommand::typingAddedToOpenCommand). |
| 255 if (!isTypingCommand()) | 255 if (!isTypingCommand()) |
| 256 frame->editor().appliedEditing(this); | 256 frame->editor().appliedEditing(this); |
| 257 setShouldRetainAutocorrectionIndicator(false); | 257 setShouldRetainAutocorrectionIndicator(false); |
| 258 return !editingState.isAborted(); | 258 return !editingState.isAborted(); |
| 259 } | 259 } |
| 260 | 260 |
| 261 EditCommandComposition* CompositeEditCommand::ensureComposition() { | 261 EditCommandComposition* CompositeEditCommand::ensureComposition() { |
| 262 CompositeEditCommand* command = this; | 262 CompositeEditCommand* command = this; |
| 263 while (command && command->parent()) | 263 while (command && command->parent()) |
| 264 command = command->parent(); | 264 command = command->parent(); |
| 265 if (!command->m_composition) | 265 if (!command->m_composition) { |
| 266 command->m_composition = EditCommandComposition::create( | 266 command->m_composition = EditCommandComposition::create( |
| 267 &document(), startingSelection(), endingSelection(), inputType()); | 267 &document(), startingSelection(), endingSelection()); |
| 268 } | |
| 268 return command->m_composition.get(); | 269 return command->m_composition.get(); |
| 269 } | 270 } |
| 270 | 271 |
| 271 bool CompositeEditCommand::willApplyEditing(EditCommandSource) { | 272 bool CompositeEditCommand::willApplyEditing(EditCommandSource source) { |
| 272 // TODO(chongz): Move all the 'beforeinput' dispatching logic here. | 273 // TODO(chongz): Remove the following code after we have ensured it's OK to |
| 273 return true; | 274 // fire 'beforeinput' after 'compositionupdate'. |
| 275 // https://crbug.com/675820 | |
| 276 if (isTypingCommand() && (toTypingCommand(this)->compositionType() == | |
| 277 TypingCommand::TextCompositionUpdate || | |
| 278 toTypingCommand(this)->compositionType() == | |
| 279 TypingCommand::TextCompositionConfirm)) | |
| 280 return true; | |
| 281 return dispatchBeforeInputEvent( | |
| 282 source, document().frame(), eventTargetNodeForDocument(&document()), | |
| 283 inputType(), textDataForInputEvent(), dataTransferForInputEvent(), | |
| 284 isCancelableFromCommand(this), isComposingFromCommand(this), | |
| 285 targetRangesForInputEvent()); | |
| 286 } | |
| 287 | |
| 288 InputEvent::InputType CompositeEditCommand::inputType() const { | |
| 289 return InputEvent::InputType::None; | |
| 290 } | |
| 291 | |
| 292 String CompositeEditCommand::textDataForInputEvent() const { | |
| 293 return nullAtom; | |
| 294 } | |
| 295 | |
| 296 DataTransfer* CompositeEditCommand::dataTransferForInputEvent() const { | |
| 297 return nullptr; | |
| 298 } | |
| 299 | |
| 300 RangeVector* CompositeEditCommand::targetRangesForInputEvent() const { | |
| 301 if (!document().frame()->editor().canEditRichly()) | |
| 302 return nullptr; | |
| 303 return new RangeVector(1, document().frame()->selection().firstRange()); | |
| 274 } | 304 } |
| 275 | 305 |
| 276 bool CompositeEditCommand::preservesTypingStyle() const { | 306 bool CompositeEditCommand::preservesTypingStyle() const { |
| 277 return false; | 307 return false; |
| 278 } | 308 } |
| 279 | 309 |
| 280 bool CompositeEditCommand::isTypingCommand() const { | 310 bool CompositeEditCommand::isTypingCommand() const { |
| 281 return false; | 311 return false; |
| 282 } | 312 } |
| 283 | 313 |
| (...skipping 1769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2053 return node; | 2083 return node; |
| 2054 } | 2084 } |
| 2055 | 2085 |
| 2056 DEFINE_TRACE(CompositeEditCommand) { | 2086 DEFINE_TRACE(CompositeEditCommand) { |
| 2057 visitor->trace(m_commands); | 2087 visitor->trace(m_commands); |
| 2058 visitor->trace(m_composition); | 2088 visitor->trace(m_composition); |
| 2059 EditCommand::trace(visitor); | 2089 EditCommand::trace(visitor); |
| 2060 } | 2090 } |
| 2061 | 2091 |
| 2062 } // namespace blink | 2092 } // namespace blink |
| OLD | NEW |