void InputMethodController::selectComposition() const { const EphemeralRange range = compositionEphemeralRange(); if (range.isNull()) return; // The composition can start inside a composed character sequence, so we have to override checks. // See <http://bugs.webkit.org/show_bug.cgi?id=15781> VisibleSelection selection; selection.setWithoutValidation(range.startPosition(), range.endPosition()); frame().selection().setSelection(selection, 0); }
bool InputMethodController::finishComposition(const String& text, FinishCompositionMode mode) { if (!hasComposition()) return false; ASSERT(mode == ConfirmComposition || mode == CancelComposition); Editor::RevealSelectionScope revealSelectionScope(&editor()); bool dirty = m_isDirty || plainText(compositionEphemeralRange()) != text; if (mode == CancelComposition) { ASSERT(text == emptyString()); } else if (dirty) { selectComposition(); } if (frame().selection().isNone()) return false; // Dispatch a compositionend event to the focused node. // We should send this event before sending a TextEvent as written in Section 6.2.2 and 6.2.3 of // the DOM Event specification. if (Element* target = frame().document()->focusedElement()) { RefPtrWillBeRawPtr<CompositionEvent> event = CompositionEvent::create(EventTypeNames::compositionend, frame().domWindow(), text); target->dispatchEvent(event); } // If text is empty, then delete the old composition here. If text is non-empty, InsertTextCommand::input // will delete the old composition with an optimized replace operation. if (text.isEmpty() && mode != CancelComposition && dirty) { ASSERT(frame().document()); TypingCommand::deleteSelection(*frame().document(), 0); } clear(); if (dirty) insertTextForConfirmedComposition(text); if (mode == CancelComposition) { // An open typing command that disagrees about current selection would cause issues with typing later on. TypingCommand::closeTyping(m_frame); } return true; }
bool InputMethodController::confirmComposition(const String& text) { if (!hasComposition()) return false; Editor::RevealSelectionScope revealSelectionScope(&editor()); // If the composition was set from existing text and didn't change, then // there's nothing to do here (and we should avoid doing anything as that // may clobber multi-node styled text). if (!m_isDirty && plainText(compositionEphemeralRange()) == text) { clear(); return true; } // Select the text that will be deleted or replaced. selectComposition(); if (frame().selection().isNone()) return false; dispatchCompositionEndEvent(frame(), text); if (!frame().document()) return false; // If text is empty, then delete the old composition here. If text is // non-empty, InsertTextCommand::input will delete the old composition with // an optimized replace operation. if (text.isEmpty()) TypingCommand::deleteSelection(*frame().document(), 0); clear(); insertTextForConfirmedComposition(text); return true; }
bool InputMethodController::confirmComposition() { return confirmComposition(plainText(compositionEphemeralRange())); }
String InputMethodController::composingText() const { return plainText(compositionEphemeralRange(), TextIteratorEmitsOriginalText); }