Chromium Code Reviews| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 // replaced) or the new text (text to be inserted) is empty. | 77 // replaced) or the new text (text to be inserted) is empty. |
| 78 if (frame.selectedText().isEmpty() || newText.isEmpty()) | 78 if (frame.selectedText().isEmpty() || newText.isEmpty()) |
| 79 return false; | 79 return false; |
| 80 | 80 |
| 81 return true; | 81 return true; |
| 82 } | 82 } |
| 83 | 83 |
| 84 // Used to insert/replace text during composition update and confirm | 84 // Used to insert/replace text during composition update and confirm |
| 85 // composition. | 85 // composition. |
| 86 // Procedure: | 86 // Procedure: |
| 87 // 1. Fire 'beforeinput' event for (TODO(chongz): deleted composed text) and | 87 // 1. Fire 'compositionupdate' event |
|
Xiaocheng
2016/12/21 02:56:39
Please revise the comments here.
chongz
2016/12/21 23:59:24
Reverted comments since there is no behavior chang
| |
| 88 // inserted text | 88 // 2. Use TextEvent or TypingCommand to modify DOM, which will fire |
| 89 // 2. Fire 'compositionupdate' event | 89 // 'beforeinput' and 'input' |
| 90 // 3. Fire TextEvent and modify DOM | |
| 91 // TODO(chongz): 4. Fire 'input' event | |
| 92 void insertTextDuringCompositionWithEvents( | 90 void insertTextDuringCompositionWithEvents( |
| 93 LocalFrame& frame, | 91 LocalFrame& frame, |
| 94 const String& text, | 92 const String& text, |
| 95 TypingCommand::Options options, | 93 TypingCommand::Options options, |
| 96 TypingCommand::TextCompositionType compositionType) { | 94 TypingCommand::TextCompositionType compositionType) { |
| 97 DCHECK(compositionType == | 95 DCHECK(compositionType == |
| 98 TypingCommand::TextCompositionType::TextCompositionUpdate || | 96 TypingCommand::TextCompositionType::TextCompositionUpdate || |
| 99 compositionType == | 97 compositionType == |
| 100 TypingCommand::TextCompositionType::TextCompositionConfirm || | 98 TypingCommand::TextCompositionType::TextCompositionConfirm || |
| 101 compositionType == | 99 compositionType == |
| 102 TypingCommand::TextCompositionType::TextCompositionCancel) | 100 TypingCommand::TextCompositionType::TextCompositionCancel) |
| 103 << "compositionType should be TextCompositionUpdate or " | 101 << "compositionType should be TextCompositionUpdate or " |
| 104 "TextCompositionConfirm or TextCompositionCancel, but got " | 102 "TextCompositionConfirm or TextCompositionCancel, but got " |
| 105 << static_cast<int>(compositionType); | 103 << static_cast<int>(compositionType); |
| 106 if (!frame.document()) | 104 if (!frame.document()) |
| 107 return; | 105 return; |
| 108 | 106 |
| 109 Element* target = frame.document()->focusedElement(); | 107 // TODO(chongz): Remove the following code after we have ensured it's OK to |
| 110 if (!target) | 108 // fire 'beforeinput' after 'compositionupdate'. |
| 111 return; | 109 // https://crbug.com/675820 |
| 112 | 110 if (compositionType == TypingCommand::TextCompositionUpdate || |
| 113 // TODO(chongz): Fire 'beforeinput' for the composed text being | 111 compositionType == TypingCommand::TextCompositionConfirm) { |
| 114 // replaced/deleted. | 112 Element* target = frame.document()->focusedElement(); |
| 115 | 113 if (!target) |
| 116 // Only the last confirmed text is cancelable. | 114 return; |
| 117 InputEvent::EventCancelable beforeInputCancelable = | 115 // Only the last confirmed text is cancelable. |
| 118 (compositionType == | 116 const InputEvent::EventCancelable beforeInputCancelable = |
| 119 TypingCommand::TextCompositionType::TextCompositionUpdate) | 117 (compositionType == TypingCommand::TextCompositionUpdate) |
| 120 ? InputEvent::EventCancelable::NotCancelable | 118 ? InputEvent::EventCancelable::NotCancelable |
| 121 : InputEvent::EventCancelable::IsCancelable; | 119 : InputEvent::EventCancelable::IsCancelable; |
| 122 DispatchEventResult result = dispatchBeforeInputFromComposition( | 120 RangeVector* targetRanges = nullptr; |
|
chongz
2016/12/20 23:27:52
Kept, still fire 'beforeinput' before 'composition
| |
| 123 target, InputEvent::InputType::InsertText, text, beforeInputCancelable); | 121 if (frame.editor().canEditRichly()) |
| 124 | 122 targetRanges = new RangeVector(1, frame.selection().firstRange()); |
| 125 if (beforeInputCancelable == InputEvent::EventCancelable::IsCancelable && | 123 const bool isCanceled = !dispatchBeforeInputEvent( |
| 126 result != DispatchEventResult::NotCanceled) | 124 EditCommandSource::kMenuOrKeyBinding, &frame, target, |
| 127 return; | 125 InputEvent::InputType::InsertText, text, nullptr, beforeInputCancelable, |
| 128 | 126 InputEvent::IsComposing, targetRanges); |
| 129 // 'beforeinput' event handler may destroy document. | 127 if (isCanceled) |
| 130 if (!frame.document()) | 128 return; |
| 131 return; | 129 } |
| 132 | 130 |
| 133 dispatchCompositionUpdateEvent(frame, text); | 131 dispatchCompositionUpdateEvent(frame, text); |
| 134 // 'compositionupdate' event handler may destroy document. | 132 // 'compositionupdate' event handler may destroy document. |
| 135 if (!frame.document()) | 133 if (!frame.document() || frame.document()->frame() != &frame) |
|
Xiaocheng
2016/12/21 02:56:38
This seems irrelevant to beforeinput.
If it's a b
chongz
2016/12/21 23:59:24
Reverted, will put in another patch.
| |
| 136 return; | 134 return; |
| 137 | 135 |
| 138 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 136 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 139 // needs to be audited. see http://crbug.com/590369 for more details. | 137 // needs to be audited. see http://crbug.com/590369 for more details. |
| 140 frame.document()->updateStyleAndLayoutIgnorePendingStylesheets(); | 138 frame.document()->updateStyleAndLayoutIgnorePendingStylesheets(); |
| 141 | 139 |
| 142 const bool isIncrementalInsertion = needsIncrementalInsertion(frame, text); | 140 const bool isIncrementalInsertion = needsIncrementalInsertion(frame, text); |
| 143 | 141 |
| 144 switch (compositionType) { | 142 switch (compositionType) { |
| 145 case TypingCommand::TextCompositionType::TextCompositionUpdate: | 143 case TypingCommand::TextCompositionType::TextCompositionUpdate: |
| 146 case TypingCommand::TextCompositionType::TextCompositionConfirm: | 144 case TypingCommand::TextCompositionType::TextCompositionConfirm: |
| 147 TypingCommand::insertText( | 145 TypingCommand::insertText( |
| 148 *frame.document(), EditCommandSource::kMenuOrKeyBinding, text, | 146 *frame.document(), EditCommandSource::kMenuOrKeyBinding, text, |
| 149 options, compositionType, isIncrementalInsertion); | 147 options, compositionType, isIncrementalInsertion); |
| 150 break; | 148 break; |
| 151 case TypingCommand::TextCompositionType::TextCompositionCancel: | 149 case TypingCommand::TextCompositionType::TextCompositionCancel: |
| 152 // TODO(chongz): Use TypingCommand::insertText after TextEvent was | 150 // TODO(chongz): Use TypingCommand::insertText after TextEvent was |
| 153 // removed. (Removed from spec since 2012) | 151 // removed. (Removed from spec since 2012) |
| 154 // See TextEvent.idl. | 152 // See TextEvent.idl. |
| 155 frame.eventHandler().handleTextInputEvent(text, 0, | 153 frame.eventHandler().handleTextInputEvent(text, 0, |
| 156 TextEventInputComposition); | 154 TextEventInputComposition); |
| 157 break; | 155 break; |
| 158 default: | 156 default: |
| 159 NOTREACHED(); | 157 NOTREACHED(); |
| 160 } | 158 } |
| 161 // TODO(chongz): Fire 'input' event. | |
|
Xiaocheng
2016/12/21 02:56:39
Is it a drive-by removal of a stale TODO?
If so,
chongz
2016/12/21 23:59:24
Yes, will isolate into another patch.
| |
| 162 } | 159 } |
| 163 | 160 |
| 164 AtomicString getInputModeAttribute(Element* element) { | 161 AtomicString getInputModeAttribute(Element* element) { |
| 165 if (!element) | 162 if (!element) |
| 166 return AtomicString(); | 163 return AtomicString(); |
| 167 | 164 |
| 168 bool queryAttribute = false; | 165 bool queryAttribute = false; |
| 169 if (isHTMLInputElement(*element)) { | 166 if (isHTMLInputElement(*element)) { |
| 170 queryAttribute = toHTMLInputElement(*element).supportsInputModeAttribute(); | 167 queryAttribute = toHTMLInputElement(*element).supportsInputModeAttribute(); |
| 171 } else if (isHTMLTextAreaElement(*element)) { | 168 } else if (isHTMLTextAreaElement(*element)) { |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 if (!moveCaret(absoluteCaretPosition)) | 342 if (!moveCaret(absoluteCaretPosition)) |
| 346 return false; | 343 return false; |
| 347 | 344 |
| 348 // No DOM update after 'compositionend'. | 345 // No DOM update after 'compositionend'. |
| 349 dispatchCompositionEndEvent(frame(), text); | 346 dispatchCompositionEndEvent(frame(), text); |
| 350 | 347 |
| 351 return true; | 348 return true; |
| 352 } | 349 } |
| 353 | 350 |
| 354 bool InputMethodController::insertText(const String& text) { | 351 bool InputMethodController::insertText(const String& text) { |
| 355 if (dispatchBeforeInputInsertText(document().focusedElement(), text) != | |
|
chongz
2016/12/20 23:27:52
Removed, inserting text was covered by |TypingComm
| |
| 356 DispatchEventResult::NotCanceled) | |
| 357 return false; | |
| 358 editor().insertText(text, 0); | 352 editor().insertText(text, 0); |
| 359 return true; | 353 return true; |
| 360 } | 354 } |
| 361 | 355 |
| 362 bool InputMethodController::insertTextAndMoveCaret(const String& text, | 356 bool InputMethodController::insertTextAndMoveCaret(const String& text, |
| 363 int relativeCaretPosition) { | 357 int relativeCaretPosition) { |
| 364 PlainTextRange selectionRange = getSelectionOffsets(); | 358 PlainTextRange selectionRange = getSelectionOffsets(); |
| 365 if (selectionRange.isNull()) | 359 if (selectionRange.isNull()) |
| 366 return false; | 360 return false; |
| 367 int textStart = selectionRange.start(); | 361 int textStart = selectionRange.start(); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 380 if (!hasComposition()) | 374 if (!hasComposition()) |
| 381 return; | 375 return; |
| 382 | 376 |
| 383 Editor::RevealSelectionScope revealSelectionScope(&editor()); | 377 Editor::RevealSelectionScope revealSelectionScope(&editor()); |
| 384 | 378 |
| 385 if (frame().selection().isNone()) | 379 if (frame().selection().isNone()) |
| 386 return; | 380 return; |
| 387 | 381 |
| 388 clear(); | 382 clear(); |
| 389 | 383 |
| 390 // TODO(chongz): Figure out which InputType should we use here. | |
| 391 dispatchBeforeInputFromComposition( | |
|
chongz
2016/12/20 23:27:52
Removed. This is a dummy 'beforeinput' with no act
| |
| 392 document().focusedElement(), | |
| 393 InputEvent::InputType::DeleteComposedCharacterBackward, nullAtom, | |
| 394 InputEvent::EventCancelable::NotCancelable); | |
| 395 dispatchCompositionUpdateEvent(frame(), emptyString()); | 384 dispatchCompositionUpdateEvent(frame(), emptyString()); |
| 396 insertTextDuringCompositionWithEvents( | 385 insertTextDuringCompositionWithEvents( |
| 397 frame(), emptyString(), 0, | 386 frame(), emptyString(), 0, |
| 398 TypingCommand::TextCompositionType::TextCompositionCancel); | 387 TypingCommand::TextCompositionType::TextCompositionCancel); |
| 399 // Event handler might destroy document. | 388 // Event handler might destroy document. |
| 400 if (!isAvailable()) | 389 if (!isAvailable()) |
| 401 return; | 390 return; |
| 402 | 391 |
| 403 // An open typing command that disagrees about current selection would cause | 392 // An open typing command that disagrees about current selection would cause |
| 404 // issues with typing later on. | 393 // issues with typing later on. |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 769 do { | 758 do { |
| 770 if (!setSelectionOffsets(PlainTextRange( | 759 if (!setSelectionOffsets(PlainTextRange( |
| 771 std::max(static_cast<int>(selectionOffsets.start()) - before, 0), | 760 std::max(static_cast<int>(selectionOffsets.start()) - before, 0), |
| 772 selectionOffsets.end() + after))) | 761 selectionOffsets.end() + after))) |
| 773 return; | 762 return; |
| 774 if (before == 0) | 763 if (before == 0) |
| 775 break; | 764 break; |
| 776 ++before; | 765 ++before; |
| 777 } while (frame().selection().start() == frame().selection().end() && | 766 } while (frame().selection().start() == frame().selection().end() && |
| 778 before <= static_cast<int>(selectionOffsets.start())); | 767 before <= static_cast<int>(selectionOffsets.start())); |
| 779 // TODO(chongz): Find a way to distinguish Forward and Backward. | |
| 780 dispatchBeforeInputEditorCommand( | |
|
chongz
2016/12/20 23:27:52
Removed, deleting text was covered by |TypingComma
| |
| 781 document().focusedElement(), InputEvent::InputType::DeleteContentBackward, | |
| 782 new RangeVector(1, m_frame->selection().firstRange())); | |
| 783 TypingCommand::deleteSelection(document(), | 768 TypingCommand::deleteSelection(document(), |
| 784 EditCommandSource::kMenuOrKeyBinding); | 769 EditCommandSource::kMenuOrKeyBinding); |
| 785 } | 770 } |
| 786 | 771 |
| 787 // TODO(yabinh): We should reduce the number of selectionchange events. | 772 // TODO(yabinh): We should reduce the number of selectionchange events. |
| 788 void InputMethodController::deleteSurroundingText(int before, int after) { | 773 void InputMethodController::deleteSurroundingText(int before, int after) { |
| 789 if (!editor().canEdit()) | 774 if (!editor().canEdit()) |
| 790 return; | 775 return; |
| 791 const PlainTextRange selectionOffsets(getSelectionOffsets()); | 776 const PlainTextRange selectionOffsets(getSelectionOffsets()); |
| 792 if (selectionOffsets.isNull()) | 777 if (selectionOffsets.isNull()) |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1063 frame().chromeClient().resetInputMethod(); | 1048 frame().chromeClient().resetInputMethod(); |
| 1064 } | 1049 } |
| 1065 | 1050 |
| 1066 DEFINE_TRACE(InputMethodController) { | 1051 DEFINE_TRACE(InputMethodController) { |
| 1067 visitor->trace(m_frame); | 1052 visitor->trace(m_frame); |
| 1068 visitor->trace(m_compositionRange); | 1053 visitor->trace(m_compositionRange); |
| 1069 SynchronousMutationObserver::trace(visitor); | 1054 SynchronousMutationObserver::trace(visitor); |
| 1070 } | 1055 } |
| 1071 | 1056 |
| 1072 } // namespace blink | 1057 } // namespace blink |
| OLD | NEW |