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 15 matching lines...) Expand all Loading... |
26 | 26 |
27 #include "core/editing/InputMethodController.h" | 27 #include "core/editing/InputMethodController.h" |
28 | 28 |
29 #include "core/InputModeNames.h" | 29 #include "core/InputModeNames.h" |
30 #include "core/InputTypeNames.h" | 30 #include "core/InputTypeNames.h" |
31 #include "core/dom/Document.h" | 31 #include "core/dom/Document.h" |
32 #include "core/dom/Element.h" | 32 #include "core/dom/Element.h" |
33 #include "core/dom/Text.h" | 33 #include "core/dom/Text.h" |
34 #include "core/editing/EditingUtilities.h" | 34 #include "core/editing/EditingUtilities.h" |
35 #include "core/editing/Editor.h" | 35 #include "core/editing/Editor.h" |
| 36 #include "core/editing/TextSuggestionController.h" |
36 #include "core/editing/commands/TypingCommand.h" | 37 #include "core/editing/commands/TypingCommand.h" |
37 #include "core/editing/markers/DocumentMarkerController.h" | 38 #include "core/editing/markers/DocumentMarkerController.h" |
38 #include "core/editing/state_machines/BackwardCodePointStateMachine.h" | 39 #include "core/editing/state_machines/BackwardCodePointStateMachine.h" |
39 #include "core/editing/state_machines/ForwardCodePointStateMachine.h" | 40 #include "core/editing/state_machines/ForwardCodePointStateMachine.h" |
40 #include "core/events/CompositionEvent.h" | 41 #include "core/events/CompositionEvent.h" |
41 #include "core/frame/LocalFrame.h" | 42 #include "core/frame/LocalFrame.h" |
42 #include "core/html/HTMLInputElement.h" | 43 #include "core/html/HTMLInputElement.h" |
43 #include "core/html/HTMLTextAreaElement.h" | 44 #include "core/html/HTMLTextAreaElement.h" |
44 #include "core/input/EventHandler.h" | 45 #include "core/input/EventHandler.h" |
45 #include "core/layout/LayoutObject.h" | 46 #include "core/layout/LayoutObject.h" |
(...skipping 18 matching lines...) Expand all Loading... |
64 Element* target = frame.document()->focusedElement(); | 65 Element* target = frame.document()->focusedElement(); |
65 if (!target) | 66 if (!target) |
66 return; | 67 return; |
67 | 68 |
68 CompositionEvent* event = CompositionEvent::create( | 69 CompositionEvent* event = CompositionEvent::create( |
69 EventTypeNames::compositionend, frame.domWindow(), text); | 70 EventTypeNames::compositionend, frame.domWindow(), text); |
70 target->dispatchEvent(event); | 71 target->dispatchEvent(event); |
71 } | 72 } |
72 | 73 |
73 bool needsIncrementalInsertion(const LocalFrame& frame, const String& newText) { | 74 bool needsIncrementalInsertion(const LocalFrame& frame, const String& newText) { |
74 // No need to apply incremental insertion if it doesn't support formated text. | |
75 if (!frame.editor().canEditRichly()) | |
76 return false; | |
77 | |
78 // No need to apply incremental insertion if the old text (text to be | 75 // No need to apply incremental insertion if the old text (text to be |
79 // replaced) or the new text (text to be inserted) is empty. | 76 // replaced) or the new text (text to be inserted) is empty. |
80 if (frame.selectedText().isEmpty() || newText.isEmpty()) | 77 if (frame.selectedText().isEmpty() || newText.isEmpty()) |
81 return false; | 78 return false; |
82 | 79 |
83 return true; | 80 return true; |
84 } | 81 } |
85 | 82 |
86 void dispatchBeforeInputFromComposition(EventTarget* target, | 83 void dispatchBeforeInputFromComposition(EventTarget* target, |
87 InputEvent::InputType inputType, | 84 InputEvent::InputType inputType, |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 unsigned offsetInPlainChars) { | 433 unsigned offsetInPlainChars) { |
437 for (const auto& underline : underlines) { | 434 for (const auto& underline : underlines) { |
438 unsigned underlineStart = offsetInPlainChars + underline.startOffset(); | 435 unsigned underlineStart = offsetInPlainChars + underline.startOffset(); |
439 unsigned underlineEnd = offsetInPlainChars + underline.endOffset(); | 436 unsigned underlineEnd = offsetInPlainChars + underline.endOffset(); |
440 | 437 |
441 EphemeralRange ephemeralLineRange = | 438 EphemeralRange ephemeralLineRange = |
442 PlainTextRange(underlineStart, underlineEnd).createRange(*baseElement); | 439 PlainTextRange(underlineStart, underlineEnd).createRange(*baseElement); |
443 if (ephemeralLineRange.isNull()) | 440 if (ephemeralLineRange.isNull()) |
444 continue; | 441 continue; |
445 | 442 |
446 document().markers().addCompositionMarker( | 443 if (underline.suggestions().isEmpty()) { |
447 ephemeralLineRange, underline.color(), underline.thick(), | 444 document().markers().addCompositionMarker( |
448 underline.backgroundColor()); | 445 ephemeralLineRange, underline.color(), underline.thick(), |
| 446 underline.backgroundColor()); |
| 447 } else { |
| 448 document().markers().addSuggestionMarker( |
| 449 ephemeralLineRange, |
| 450 underline.color(), underline.thick(), underline.backgroundColor(), |
| 451 underline.suggestions()); |
| 452 } |
449 } | 453 } |
450 } | 454 } |
451 | 455 |
452 bool InputMethodController::replaceCompositionAndMoveCaret( | 456 bool InputMethodController::replaceCompositionAndMoveCaret( |
453 const String& text, | 457 const String& text, |
454 int relativeCaretPosition, | 458 int relativeCaretPosition, |
455 const Vector<CompositionUnderline>& underlines) { | 459 const Vector<CompositionUnderline>& underlines) { |
456 Element* rootEditableElement = | 460 Element* rootEditableElement = |
457 frame() | 461 frame() |
458 .selection() | 462 .selection() |
459 .computeVisibleSelectionInDOMTreeDeprecated() | 463 .computeVisibleSelectionInDOMTreeDeprecated() |
460 .rootEditableElement(); | 464 .rootEditableElement(); |
461 if (!rootEditableElement) | 465 if (!rootEditableElement) |
462 return false; | 466 return false; |
463 DCHECK(hasComposition()); | 467 DCHECK(hasComposition()); |
464 PlainTextRange compositionRange = | 468 PlainTextRange compositionRange = |
465 PlainTextRange::create(*rootEditableElement, *m_compositionRange); | 469 PlainTextRange::create(*rootEditableElement, *m_compositionRange); |
466 if (compositionRange.isNull()) | 470 if (compositionRange.isNull()) |
467 return false; | 471 return false; |
| 472 |
468 int textStart = compositionRange.start(); | 473 int textStart = compositionRange.start(); |
469 | 474 |
470 if (!replaceComposition(text)) | 475 if (!replaceComposition(text)) |
471 return false; | 476 return false; |
472 | 477 |
473 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 478 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
474 // needs to be audited. see http://crbug.com/590369 for more details. | 479 // needs to be audited. see http://crbug.com/590369 for more details. |
475 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 480 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
476 | 481 |
477 addCompositionUnderlines(underlines, rootEditableElement, textStart); | 482 addCompositionUnderlines(underlines, rootEditableElement, textStart); |
(...skipping 11 matching lines...) Expand all Loading... |
489 return true; | 494 return true; |
490 } | 495 } |
491 | 496 |
492 bool InputMethodController::insertTextAndMoveCaret( | 497 bool InputMethodController::insertTextAndMoveCaret( |
493 const String& text, | 498 const String& text, |
494 int relativeCaretPosition, | 499 int relativeCaretPosition, |
495 const Vector<CompositionUnderline>& underlines) { | 500 const Vector<CompositionUnderline>& underlines) { |
496 PlainTextRange selectionRange = getSelectionOffsets(); | 501 PlainTextRange selectionRange = getSelectionOffsets(); |
497 if (selectionRange.isNull()) | 502 if (selectionRange.isNull()) |
498 return false; | 503 return false; |
| 504 |
499 int textStart = selectionRange.start(); | 505 int textStart = selectionRange.start(); |
500 | 506 |
501 if (text.length()) { | 507 if (text.length()) { |
502 if (!insertText(text)) | 508 if (!insertText(text)) |
503 return false; | 509 return false; |
504 | 510 |
505 Element* rootEditableElement = | 511 Element* rootEditableElement = |
506 frame() | 512 frame() |
507 .selection() | 513 .selection() |
508 .computeVisibleSelectionInDOMTreeDeprecated() | 514 .computeVisibleSelectionInDOMTreeDeprecated() |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 baseNode->layoutObject()->setShouldDoFullPaintInvalidation(); | 689 baseNode->layoutObject()->setShouldDoFullPaintInvalidation(); |
684 | 690 |
685 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 691 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
686 // needs to be audited. see http://crbug.com/590369 for more details. | 692 // needs to be audited. see http://crbug.com/590369 for more details. |
687 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 693 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
688 | 694 |
689 // We shouldn't close typing in the middle of setComposition. | 695 // We shouldn't close typing in the middle of setComposition. |
690 setEditableSelectionOffsets(selectedRange, NotUserTriggered); | 696 setEditableSelectionOffsets(selectedRange, NotUserTriggered); |
691 | 697 |
692 if (underlines.isEmpty()) { | 698 if (underlines.isEmpty()) { |
| 699 // Don't add black underline when suggestion menu is open, the suggestion |
| 700 // range already gets an underline |
| 701 if (frame().textSuggestionController().suggestionMenuIsOpen()) |
| 702 return; |
| 703 |
693 document().markers().addCompositionMarker( | 704 document().markers().addCompositionMarker( |
694 EphemeralRange(m_compositionRange), Color::black, false, | 705 EphemeralRange(m_compositionRange), Color::black, false, |
695 LayoutTheme::theme().platformDefaultCompositionBackgroundColor()); | 706 LayoutTheme::theme().platformDefaultCompositionBackgroundColor()); |
696 return; | 707 return; |
697 } | 708 } |
698 | 709 |
699 const PlainTextRange compositionPlainTextRange = | 710 const PlainTextRange compositionPlainTextRange = |
700 PlainTextRange::create(*baseNode->parentNode(), *m_compositionRange); | 711 PlainTextRange::create(*baseNode->parentNode(), *m_compositionRange); |
701 addCompositionUnderlines(underlines, baseNode->parentNode(), | 712 addCompositionUnderlines(underlines, baseNode->parentNode(), |
702 compositionPlainTextRange.start()); | 713 compositionPlainTextRange.start()); |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 finishComposingText(KeepSelection); | 1252 finishComposingText(KeepSelection); |
1242 } | 1253 } |
1243 | 1254 |
1244 DEFINE_TRACE(InputMethodController) { | 1255 DEFINE_TRACE(InputMethodController) { |
1245 visitor->trace(m_frame); | 1256 visitor->trace(m_frame); |
1246 visitor->trace(m_compositionRange); | 1257 visitor->trace(m_compositionRange); |
1247 SynchronousMutationObserver::trace(visitor); | 1258 SynchronousMutationObserver::trace(visitor); |
1248 } | 1259 } |
1249 | 1260 |
1250 } // namespace blink | 1261 } // namespace blink |
OLD | NEW |