| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 return; | 64 return; |
| 65 | 65 |
| 66 CompositionEvent* event = CompositionEvent::create( | 66 CompositionEvent* event = CompositionEvent::create( |
| 67 EventTypeNames::compositionend, frame.domWindow(), text); | 67 EventTypeNames::compositionend, frame.domWindow(), text); |
| 68 target->dispatchEvent(event); | 68 target->dispatchEvent(event); |
| 69 } | 69 } |
| 70 | 70 |
| 71 // Used to insert/replace text during composition update and confirm | 71 // Used to insert/replace text during composition update and confirm |
| 72 // composition. | 72 // composition. |
| 73 // Procedure: | 73 // Procedure: |
| 74 // 1. Fire 'beforeinput' event for (TODO(chongz): deleted composed text) and | 74 // 1. Fire 'compositionupdate' event |
| 75 // inserted text | 75 // 2. Use TextEvent or TypingCommand to modify DOM, which will fire |
| 76 // 2. Fire 'compositionupdate' event | 76 // 'beforeinput' and 'input' |
| 77 // 3. Fire TextEvent and modify DOM | |
| 78 // TODO(chongz): 4. Fire 'input' event | |
| 79 void insertTextDuringCompositionWithEvents( | 77 void insertTextDuringCompositionWithEvents( |
| 80 LocalFrame& frame, | 78 LocalFrame& frame, |
| 81 const String& text, | 79 const String& text, |
| 82 TypingCommand::Options options, | 80 TypingCommand::Options options, |
| 83 TypingCommand::TextCompositionType compositionType) { | 81 TypingCommand::TextCompositionType compositionType) { |
| 84 DCHECK(compositionType == | 82 DCHECK(compositionType == |
| 85 TypingCommand::TextCompositionType::TextCompositionUpdate || | 83 TypingCommand::TextCompositionType::TextCompositionUpdate || |
| 86 compositionType == | 84 compositionType == |
| 87 TypingCommand::TextCompositionType::TextCompositionConfirm || | 85 TypingCommand::TextCompositionType::TextCompositionConfirm || |
| 88 compositionType == | 86 compositionType == |
| 89 TypingCommand::TextCompositionType::TextCompositionCancel) | 87 TypingCommand::TextCompositionType::TextCompositionCancel) |
| 90 << "compositionType should be TextCompositionUpdate or " | 88 << "compositionType should be TextCompositionUpdate or " |
| 91 "TextCompositionConfirm or TextCompositionCancel, but got " | 89 "TextCompositionConfirm or TextCompositionCancel, but got " |
| 92 << static_cast<int>(compositionType); | 90 << static_cast<int>(compositionType); |
| 93 if (!frame.document()) | 91 if (!frame.document()) |
| 94 return; | 92 return; |
| 95 | 93 |
| 96 Element* target = frame.document()->focusedElement(); | |
| 97 if (!target) | |
| 98 return; | |
| 99 | |
| 100 // TODO(chongz): Fire 'beforeinput' for the composed text being | |
| 101 // replaced/deleted. | |
| 102 | |
| 103 // Only the last confirmed text is cancelable. | |
| 104 InputEvent::EventCancelable beforeInputCancelable = | |
| 105 (compositionType == | |
| 106 TypingCommand::TextCompositionType::TextCompositionUpdate) | |
| 107 ? InputEvent::EventCancelable::NotCancelable | |
| 108 : InputEvent::EventCancelable::IsCancelable; | |
| 109 DispatchEventResult result = dispatchBeforeInputFromComposition( | |
| 110 target, InputEvent::InputType::InsertText, text, beforeInputCancelable); | |
| 111 | |
| 112 if (beforeInputCancelable == InputEvent::EventCancelable::IsCancelable && | |
| 113 result != DispatchEventResult::NotCanceled) | |
| 114 return; | |
| 115 | |
| 116 // 'beforeinput' event handler may destroy document. | |
| 117 if (!frame.document()) | |
| 118 return; | |
| 119 | |
| 120 dispatchCompositionUpdateEvent(frame, text); | 94 dispatchCompositionUpdateEvent(frame, text); |
| 121 // 'compositionupdate' event handler may destroy document. | 95 // 'compositionupdate' event handler may destroy document. |
| 122 if (!frame.document()) | 96 if (!frame.document() || frame.document()->frame() != &frame) |
| 123 return; | 97 return; |
| 124 | 98 |
| 125 switch (compositionType) { | 99 switch (compositionType) { |
| 126 case TypingCommand::TextCompositionType::TextCompositionUpdate: | 100 case TypingCommand::TextCompositionType::TextCompositionUpdate: |
| 127 TypingCommand::insertText(*frame.document(), text, options, | 101 TypingCommand::insertText(*frame.document(), text, options, |
| 128 compositionType); | 102 compositionType); |
| 129 break; | 103 break; |
| 130 case TypingCommand::TextCompositionType::TextCompositionConfirm: | 104 case TypingCommand::TextCompositionType::TextCompositionConfirm: |
| 131 case TypingCommand::TextCompositionType::TextCompositionCancel: | 105 case TypingCommand::TextCompositionType::TextCompositionCancel: |
| 132 // TODO(chongz): Use TypingCommand::insertText after TextEvent was | 106 // TODO(chongz): Use TypingCommand::insertText after TextEvent was |
| 133 // removed. (Removed from spec since 2012) | 107 // removed. (Removed from spec since 2012) |
| 134 // See TextEvent.idl. | 108 // See TextEvent.idl. |
| 135 frame.eventHandler().handleTextInputEvent(text, 0, | 109 frame.eventHandler().handleTextInputEvent(text, 0, |
| 136 TextEventInputComposition); | 110 TextEventInputComposition); |
| 137 break; | 111 break; |
| 138 default: | 112 default: |
| 139 NOTREACHED(); | 113 NOTREACHED(); |
| 140 } | 114 } |
| 141 // TODO(chongz): Fire 'input' event. | |
| 142 } | 115 } |
| 143 | 116 |
| 144 AtomicString getInputModeAttribute(Element* element) { | 117 AtomicString getInputModeAttribute(Element* element) { |
| 145 if (!element) | 118 if (!element) |
| 146 return AtomicString(); | 119 return AtomicString(); |
| 147 | 120 |
| 148 bool queryAttribute = false; | 121 bool queryAttribute = false; |
| 149 if (isHTMLInputElement(*element)) { | 122 if (isHTMLInputElement(*element)) { |
| 150 queryAttribute = toHTMLInputElement(*element).supportsInputModeAttribute(); | 123 queryAttribute = toHTMLInputElement(*element).supportsInputModeAttribute(); |
| 151 } else if (isHTMLTextAreaElement(*element)) { | 124 } else if (isHTMLTextAreaElement(*element)) { |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 if (!moveCaret(absoluteCaretPosition)) | 305 if (!moveCaret(absoluteCaretPosition)) |
| 333 return false; | 306 return false; |
| 334 | 307 |
| 335 // No DOM update after 'compositionend'. | 308 // No DOM update after 'compositionend'. |
| 336 dispatchCompositionEndEvent(frame(), text); | 309 dispatchCompositionEndEvent(frame(), text); |
| 337 | 310 |
| 338 return true; | 311 return true; |
| 339 } | 312 } |
| 340 | 313 |
| 341 bool InputMethodController::insertText(const String& text) { | 314 bool InputMethodController::insertText(const String& text) { |
| 342 if (dispatchBeforeInputInsertText(document().focusedElement(), text) != | |
| 343 DispatchEventResult::NotCanceled) | |
| 344 return false; | |
| 345 editor().insertText(text, 0); | 315 editor().insertText(text, 0); |
| 346 return true; | 316 return true; |
| 347 } | 317 } |
| 348 | 318 |
| 349 bool InputMethodController::insertTextAndMoveCaret(const String& text, | 319 bool InputMethodController::insertTextAndMoveCaret(const String& text, |
| 350 int relativeCaretPosition) { | 320 int relativeCaretPosition) { |
| 351 PlainTextRange selectionRange = getSelectionOffsets(); | 321 PlainTextRange selectionRange = getSelectionOffsets(); |
| 352 if (selectionRange.isNull()) | 322 if (selectionRange.isNull()) |
| 353 return false; | 323 return false; |
| 354 int textStart = selectionRange.start(); | 324 int textStart = selectionRange.start(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 367 if (!hasComposition()) | 337 if (!hasComposition()) |
| 368 return; | 338 return; |
| 369 | 339 |
| 370 Editor::RevealSelectionScope revealSelectionScope(&editor()); | 340 Editor::RevealSelectionScope revealSelectionScope(&editor()); |
| 371 | 341 |
| 372 if (frame().selection().isNone()) | 342 if (frame().selection().isNone()) |
| 373 return; | 343 return; |
| 374 | 344 |
| 375 clear(); | 345 clear(); |
| 376 | 346 |
| 377 // TODO(chongz): Figure out which InputType should we use here. | |
| 378 dispatchBeforeInputFromComposition( | |
| 379 document().focusedElement(), | |
| 380 InputEvent::InputType::DeleteComposedCharacterBackward, nullAtom, | |
| 381 InputEvent::EventCancelable::NotCancelable); | |
| 382 dispatchCompositionUpdateEvent(frame(), emptyString()); | 347 dispatchCompositionUpdateEvent(frame(), emptyString()); |
| 383 insertTextDuringCompositionWithEvents( | 348 insertTextDuringCompositionWithEvents( |
| 384 frame(), emptyString(), 0, | 349 frame(), emptyString(), 0, |
| 385 TypingCommand::TextCompositionType::TextCompositionCancel); | 350 TypingCommand::TextCompositionType::TextCompositionCancel); |
| 386 // Event handler might destroy document. | 351 // Event handler might destroy document. |
| 387 if (!isAvailable()) | 352 if (!isAvailable()) |
| 388 return; | 353 return; |
| 389 | 354 |
| 390 // An open typing command that disagrees about current selection would cause | 355 // An open typing command that disagrees about current selection would cause |
| 391 // issues with typing later on. | 356 // issues with typing later on. |
| (...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 do { | 873 do { |
| 909 if (!setSelectionOffsets(PlainTextRange( | 874 if (!setSelectionOffsets(PlainTextRange( |
| 910 std::max(static_cast<int>(selectionOffsets.start()) - before, 0), | 875 std::max(static_cast<int>(selectionOffsets.start()) - before, 0), |
| 911 selectionOffsets.end() + after))) | 876 selectionOffsets.end() + after))) |
| 912 return; | 877 return; |
| 913 if (before == 0) | 878 if (before == 0) |
| 914 break; | 879 break; |
| 915 ++before; | 880 ++before; |
| 916 } while (frame().selection().start() == frame().selection().end() && | 881 } while (frame().selection().start() == frame().selection().end() && |
| 917 before <= static_cast<int>(selectionOffsets.start())); | 882 before <= static_cast<int>(selectionOffsets.start())); |
| 918 // TODO(chongz): Find a way to distinguish Forward and Backward. | |
| 919 dispatchBeforeInputEditorCommand( | |
| 920 document().focusedElement(), InputEvent::InputType::DeleteContentBackward, | |
| 921 new RangeVector(1, m_frame->selection().firstRange())); | |
| 922 TypingCommand::deleteSelection(document()); | 883 TypingCommand::deleteSelection(document()); |
| 923 } | 884 } |
| 924 | 885 |
| 925 // TODO(yabinh): We should reduce the number of selectionchange events. | 886 // TODO(yabinh): We should reduce the number of selectionchange events. |
| 926 void InputMethodController::deleteSurroundingText(int before, int after) { | 887 void InputMethodController::deleteSurroundingText(int before, int after) { |
| 927 if (!editor().canEdit()) | 888 if (!editor().canEdit()) |
| 928 return; | 889 return; |
| 929 const PlainTextRange selectionOffsets(getSelectionOffsets()); | 890 const PlainTextRange selectionOffsets(getSelectionOffsets()); |
| 930 if (selectionOffsets.isNull()) | 891 if (selectionOffsets.isNull()) |
| 931 return; | 892 return; |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 return WebTextInputTypeNone; | 1154 return WebTextInputTypeNone; |
| 1194 } | 1155 } |
| 1195 | 1156 |
| 1196 DEFINE_TRACE(InputMethodController) { | 1157 DEFINE_TRACE(InputMethodController) { |
| 1197 visitor->trace(m_frame); | 1158 visitor->trace(m_frame); |
| 1198 visitor->trace(m_compositionRange); | 1159 visitor->trace(m_compositionRange); |
| 1199 SynchronousMutationObserver::trace(visitor); | 1160 SynchronousMutationObserver::trace(visitor); |
| 1200 } | 1161 } |
| 1201 | 1162 |
| 1202 } // namespace blink | 1163 } // namespace blink |
| OLD | NEW |