Index: third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp |
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp |
index 68aee201cbbe8b3e2226b5d4b3e667d7bc59ff60..12f83d59bea955d18b47bfaf93edbca5bc1d0e62 100644 |
--- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp |
+++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp |
@@ -46,6 +46,59 @@ |
namespace blink { |
+namespace { |
+ |
+InputEvent::InputType inputTypeForTypingCommand( |
+ TypingCommand::ETypingCommand commandType, |
+ TextGranularity granularity, |
+ TypingCommand::TextCompositionType compositionType) { |
+ using InputType = InputEvent::InputType; |
+ |
+ switch (commandType) { |
+ case TypingCommand::DeleteSelection: |
+ return InputType::DeleteContent; |
+ case TypingCommand::DeleteKey: |
+ if (compositionType != TypingCommand::TextCompositionNone) |
+ return InputType::DeleteComposedCharacterBackward; |
+ return deletionInputTypeFromTextGranularity(DeleteDirection::Backward, |
+ granularity); |
+ case TypingCommand::ForwardDeleteKey: |
+ if (compositionType != TypingCommand::TextCompositionNone) |
+ return InputType::DeleteComposedCharacterForward; |
+ return deletionInputTypeFromTextGranularity(DeleteDirection::Forward, |
+ granularity); |
+ case TypingCommand::InsertText: |
+ return InputType::InsertText; |
+ case TypingCommand::InsertLineBreak: |
+ return InputType::InsertLineBreak; |
+ case TypingCommand::InsertParagraphSeparator: |
+ case TypingCommand::InsertParagraphSeparatorInQuotedContent: |
+ return InputType::InsertParagraph; |
+ default: |
+ return InputType::None; |
+ } |
+} |
+ |
+RangeVector* targetRangesFromCurrentSelectionOrExtendCaret( |
+ const LocalFrame& frame, |
+ SelectionDirection direction, |
+ TextGranularity granularity) { |
+ frame.document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
+ SelectionModifier selectionModifier(frame, frame.selection().selection()); |
+ if (selectionModifier.selection().isCaret()) { |
+ selectionModifier.modify(FrameSelection::AlterationExtend, direction, |
+ granularity); |
+ } |
+ RangeVector* ranges = new RangeVector; |
+ // We only supports single selections. |
+ if (selectionModifier.selection().isNone()) |
+ return ranges; |
+ ranges->append(firstRangeOf(selectionModifier.selection())); |
+ return ranges; |
+} |
+ |
+} // anonymous namespace |
+ |
using namespace HTMLNames; |
TypingCommand::TypingCommand(Document& document, |
@@ -67,6 +120,8 @@ TypingCommand::TypingCommand(Document& document, |
m_shouldRetainAutocorrectionIndicator(options & |
RetainAutocorrectionIndicator), |
m_shouldPreventSpellChecking(options & PreventSpellChecking) { |
+ m_inputType = inputTypeForTypingCommand(m_commandType, m_granularity, |
+ m_compositionType); |
updatePreservesTypingStyle(m_commandType); |
} |
@@ -83,6 +138,9 @@ void TypingCommand::deleteSelection(Document& document, Options options) { |
lastTypingCommand->setShouldPreventSpellChecking(options & |
PreventSpellChecking); |
+ if (!lastTypingCommand->willAddTypingToOpenCommand( |
+ InputEvent::InputType::DeleteContent)) |
+ return; |
// InputMethodController uses this function to delete composition |
// selection. It won't be aborted. |
lastTypingCommand->deleteSelection(options & SmartDelete, |
@@ -108,6 +166,9 @@ void TypingCommand::deleteKeyPressed(Document& document, |
frame); |
lastTypingCommand->setShouldPreventSpellChecking(options & |
PreventSpellChecking); |
+ if (!lastTypingCommand->willAddTypingToOpenCommand( |
+ InputEvent::InputType::DeleteContentBackward)) |
+ return; |
EditingState editingState; |
lastTypingCommand->deleteKeyPressed(granularity, options & KillRing, |
&editingState); |
@@ -132,6 +193,9 @@ void TypingCommand::forwardDeleteKeyPressed(Document& document, |
updateSelectionIfDifferentFromCurrentSelection(lastTypingCommand, frame); |
lastTypingCommand->setShouldPreventSpellChecking(options & |
PreventSpellChecking); |
+ if (!lastTypingCommand->willAddTypingToOpenCommand( |
+ InputEvent::InputType::DeleteContentForward)) |
+ return; |
lastTypingCommand->forwardDeleteKeyPressed( |
granularity, options & KillRing, editingState); |
return; |
@@ -143,9 +207,39 @@ void TypingCommand::forwardDeleteKeyPressed(Document& document, |
} |
String TypingCommand::textDataForInputEvent() const { |
- if (m_commands.isEmpty()) |
+ if (m_inputType == InputEvent::InputType::InsertText) |
return m_textToInsert; |
- return m_commands.back()->textDataForInputEvent(); |
+ return EditCommand::textDataForInputEvent(); |
+} |
+ |
+RangeVector* TypingCommand::targetRangesForInputEvent() const { |
+ LocalFrame* frame = document().frame(); |
+ DCHECK(frame); |
+ |
+ using InputType = InputEvent::InputType; |
+ |
+ switch (m_inputType) { |
+ case InputType::DeleteContentBackward: |
+ return targetRangesFromCurrentSelectionOrExtendCaret( |
+ *frame, DirectionBackward, CharacterGranularity); |
+ case InputType::DeleteContentForward: |
+ return targetRangesFromCurrentSelectionOrExtendCaret( |
+ *frame, DirectionForward, CharacterGranularity); |
+ case InputType::DeleteWordBackward: |
+ return targetRangesFromCurrentSelectionOrExtendCaret( |
+ *frame, DirectionBackward, WordGranularity); |
+ case InputType::DeleteWordForward: |
+ return targetRangesFromCurrentSelectionOrExtendCaret( |
+ *frame, DirectionForward, WordGranularity); |
+ case InputType::DeleteSoftLineBackward: |
+ return targetRangesFromCurrentSelectionOrExtendCaret( |
+ *frame, DirectionBackward, LineGranularity); |
+ case InputType::DeleteSoftLineForward: |
+ return targetRangesFromCurrentSelectionOrExtendCaret( |
+ *frame, DirectionForward, LineGranularity); |
+ default: |
+ return EditCommand::targetRangesForInputEvent(); |
+ } |
} |
void TypingCommand::updateSelectionIfDifferentFromCurrentSelection( |
@@ -226,6 +320,9 @@ void TypingCommand::insertText(Document& document, |
options & RetainAutocorrectionIndicator); |
lastTypingCommand->setShouldPreventSpellChecking(options & |
PreventSpellChecking); |
+ if (!lastTypingCommand->willAddTypingToOpenCommand( |
+ InputEvent::InputType::InsertText, text)) |
+ return; |
EditingState editingState; |
lastTypingCommand->insertText(newText, options & SelectInsertedText, |
&editingState); |
@@ -251,6 +348,9 @@ bool TypingCommand::insertLineBreak(Document& document) { |
if (TypingCommand* lastTypingCommand = |
lastTypingCommandIfStillOpenForTyping(document.frame())) { |
lastTypingCommand->setShouldRetainAutocorrectionIndicator(false); |
+ if (!lastTypingCommand->willAddTypingToOpenCommand( |
+ InputEvent::InputType::InsertLineBreak)) |
+ return false; |
EditingState editingState; |
lastTypingCommand->insertLineBreak(&editingState); |
return !editingState.isAborted(); |
@@ -263,6 +363,9 @@ bool TypingCommand::insertParagraphSeparatorInQuotedContent( |
Document& document) { |
if (TypingCommand* lastTypingCommand = |
lastTypingCommandIfStillOpenForTyping(document.frame())) { |
+ if (!lastTypingCommand->willAddTypingToOpenCommand( |
+ InputEvent::InputType::InsertParagraph)) |
+ return false; |
EditingState editingState; |
lastTypingCommand->insertParagraphSeparatorInQuotedContent(&editingState); |
return !editingState.isAborted(); |
@@ -277,6 +380,9 @@ bool TypingCommand::insertParagraphSeparator(Document& document) { |
if (TypingCommand* lastTypingCommand = |
lastTypingCommandIfStillOpenForTyping(document.frame())) { |
lastTypingCommand->setShouldRetainAutocorrectionIndicator(false); |
+ if (!lastTypingCommand->willAddTypingToOpenCommand( |
+ InputEvent::InputType::InsertParagraph)) |
+ return false; |
EditingState editingState; |
lastTypingCommand->insertParagraphSeparator(&editingState); |
return !editingState.isAborted(); |
@@ -341,33 +447,24 @@ void TypingCommand::doApply(EditingState* editingState) { |
} |
InputEvent::InputType TypingCommand::inputType() const { |
- using InputType = InputEvent::InputType; |
+ return m_inputType; |
+} |
- switch (m_commandType) { |
- // TODO(chongz): |DeleteSelection| is used by IME but we don't have |
- // direction info. |
- case DeleteSelection: |
- return InputType::DeleteContentBackward; |
- case DeleteKey: |
- if (m_compositionType != TextCompositionNone) |
- return InputType::DeleteComposedCharacterBackward; |
- return deletionInputTypeFromTextGranularity(DeleteDirection::Backward, |
- m_granularity); |
- case ForwardDeleteKey: |
- if (m_compositionType != TextCompositionNone) |
- return InputType::DeleteComposedCharacterForward; |
- return deletionInputTypeFromTextGranularity(DeleteDirection::Forward, |
- m_granularity); |
- case InsertText: |
- return InputType::InsertText; |
- case InsertLineBreak: |
- return InputType::InsertLineBreak; |
- case InsertParagraphSeparator: |
- case InsertParagraphSeparatorInQuotedContent: |
- return InputType::InsertParagraph; |
- default: |
- return InputType::None; |
- } |
+bool TypingCommand::willAddTypingToOpenCommand(InputEvent::InputType inputType, |
+ const String& text) { |
+ m_inputType = inputType; |
+ m_textToInsert = text; |
+ |
+ LocalFrame* frame = document().frame(); |
+ if (!frame) |
+ return false; |
+ bool result = frame->editor().willApplyEditing(this); |
+ |
+ // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
+ // needs to be audited. See http://crbug.com/590369 for more details. |
+ document().updateStyleAndLayoutIgnorePendingStylesheets(); |
+ |
+ return result; |
} |
void TypingCommand::typingAddedToOpenCommand( |