13c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch/*
23c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
33c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
43c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *
53c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * Redistribution and use in source and binary forms, with or without
63c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * modification, are permitted provided that the following conditions
73c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * are met:
83c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * 1. Redistributions of source code must retain the above copyright
93c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *    notice, this list of conditions and the following disclaimer.
103c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * 2. Redistributions in binary form must reproduce the above copyright
113c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *    notice, this list of conditions and the following disclaimer in the
123c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *    documentation and/or other materials provided with the distribution.
133c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *
143c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
153c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
163c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
173c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
183c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
193c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
203c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
213c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
223c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
233c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
243c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
253c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch */
263c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
273c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "config.h"
283c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/editing/InputMethodController.h"
293c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
3006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/CompositionEvent.h"
313c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/dom/Document.h"
323c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/dom/Element.h"
333c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/dom/Range.h"
343c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/dom/Text.h"
353c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/editing/Editor.h"
363c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/editing/TypingCommand.h"
37d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/frame/LocalFrame.h"
38e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/html/HTMLTextAreaElement.h"
3951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "core/page/Chrome.h"
4051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "core/page/ChromeClient.h"
413c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/page/EventHandler.h"
423c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/rendering/RenderObject.h"
433c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
44c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
453c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
46e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)InputMethodController::SelectionOffsetsScope::SelectionOffsetsScope(InputMethodController* inputMethodController)
47e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    : m_inputMethodController(inputMethodController)
48e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    , m_offsets(inputMethodController->getSelectionOffsets())
49e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
50e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
51e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
52e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)InputMethodController::SelectionOffsetsScope::~SelectionOffsetsScope()
53e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
54e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    m_inputMethodController->setSelectionOffsets(m_offsets);
55e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
56e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
57e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)// ----------------------------
58e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciPassOwnPtrWillBeRawPtr<InputMethodController> InputMethodController::create(LocalFrame& frame)
603c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return adoptPtrWillBeNoop(new InputMethodController(frame));
623c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
633c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
64d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)InputMethodController::InputMethodController(LocalFrame& frame)
657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    : m_frame(&frame)
663c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    , m_compositionStart(0)
673c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    , m_compositionEnd(0)
683c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
693c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
703c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
713c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben MurdochInputMethodController::~InputMethodController()
723c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
733c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
743c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
75bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)bool InputMethodController::hasComposition() const
76bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
77bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return m_compositionNode && m_compositionNode->isContentEditable();
78bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
79bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
803c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochinline Editor& InputMethodController::editor() const
813c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return frame().editor();
833c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
843c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
853c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochvoid InputMethodController::clear()
863c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
87d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_compositionNode = nullptr;
883c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    m_customCompositionUnderlines.clear();
893c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
903c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
913c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochbool InputMethodController::insertTextForConfirmedComposition(const String& text)
923c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return frame().eventHandler().handleTextInputEvent(text, 0, TextEventInputComposition);
943c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
953c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
963c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochvoid InputMethodController::selectComposition() const
973c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
98a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    RefPtrWillBeRawPtr<Range> range = compositionRange();
993c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (!range)
1003c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
1013c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1023c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // The composition can start inside a composed character sequence, so we have to override checks.
1033c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // See <http://bugs.webkit.org/show_bug.cgi?id=15781>
1043c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    VisibleSelection selection;
1053c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    selection.setWithoutValidation(range->startPosition(), range->endPosition());
1067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    frame().selection().setSelection(selection, 0);
1073c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1083c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
109bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)bool InputMethodController::confirmComposition()
1103c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
111bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!hasComposition())
112bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return false;
113bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return finishComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), ConfirmComposition);
1143c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1153c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
116bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)bool InputMethodController::confirmComposition(const String& text)
1173c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
118bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return finishComposition(text, ConfirmComposition);
119bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
120bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
121bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)bool InputMethodController::confirmCompositionOrInsertText(const String& text, ConfirmCompositionBehavior confirmBehavior)
122bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
123bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!hasComposition()) {
124bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        if (!text.length())
125bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            return false;
126bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        editor().insertText(text, 0);
127bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return true;
128bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
129bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
130bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (text.length()) {
131bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        confirmComposition(text);
132bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return true;
133bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    }
134bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
135bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (confirmBehavior != KeepSelection)
136bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return confirmComposition();
137bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
138bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    SelectionOffsetsScope selectionOffsetsScope(this);
139bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return confirmComposition();
1403c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1413c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1423c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochvoid InputMethodController::confirmCompositionAndResetState()
1433c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
1443c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (!hasComposition())
1453c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
1463c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
14751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // ChromeClient::willSetInputMethodState() resets input method and the composition string is committed.
1487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    frame().chromeClient().willSetInputMethodState();
1493c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1503c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1513c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochvoid InputMethodController::cancelComposition()
1523c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
1533c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    finishComposition(emptyString(), CancelComposition);
1543c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1553c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1563c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochvoid InputMethodController::cancelCompositionIfSelectionIsInvalid()
1573c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
1583c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (!hasComposition() || editor().preventRevealSelection())
1593c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
1603c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1613c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // Check if selection start and selection end are valid.
1627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Position start = frame().selection().start();
1637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Position end = frame().selection().end();
1643c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (start.containerNode() == m_compositionNode
1653c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        && end.containerNode() == m_compositionNode
1668abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        && static_cast<unsigned>(start.computeOffsetInContainerNode()) >= m_compositionStart
1678abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        && static_cast<unsigned>(end.computeOffsetInContainerNode()) <= m_compositionEnd)
1683c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
1693c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1703c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    cancelComposition();
1717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    frame().chromeClient().didCancelCompositionOnSelectionChange();
1723c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1733c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
174bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)bool InputMethodController::finishComposition(const String& text, FinishCompositionMode mode)
1753c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
176bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!hasComposition())
177bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return false;
178bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
1793c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    ASSERT(mode == ConfirmComposition || mode == CancelComposition);
1803c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1813c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    Editor::RevealSelectionScope revealSelectionScope(&editor());
1823c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1833c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (mode == CancelComposition)
1843c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        ASSERT(text == emptyString());
1853c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    else
1863c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        selectComposition();
1873c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (frame().selection().isNone())
189bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return false;
1903c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1913c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // Dispatch a compositionend event to the focused node.
1923c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // We should send this event before sending a TextEvent as written in Section 6.2.2 and 6.2.3 of
1933c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // the DOM Event specification.
1947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (Element* target = frame().document()->focusedElement()) {
1957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        unsigned baseOffset = frame().selection().base().downstream().deprecatedEditingOffset();
19609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        Vector<CompositionUnderline> underlines;
19709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        for (size_t i = 0; i < m_customCompositionUnderlines.size(); ++i) {
19809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            CompositionUnderline underline = m_customCompositionUnderlines[i];
19909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            underline.startOffset -= baseOffset;
20009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            underline.endOffset -= baseOffset;
20109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            underlines.append(underline);
20209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
2037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        RefPtrWillBeRawPtr<CompositionEvent> event = CompositionEvent::create(EventTypeNames::compositionend, frame().domWindow(), text, underlines);
2043c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        target->dispatchEvent(event, IGNORE_EXCEPTION);
2053c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    }
2063c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2073c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // If text is empty, then delete the old composition here. If text is non-empty, InsertTextCommand::input
2083c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // will delete the old composition with an optimized replace operation.
2098abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (text.isEmpty() && mode != CancelComposition) {
2107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ASSERT(frame().document());
2117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        TypingCommand::deleteSelection(*frame().document(), 0);
2128abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    }
2133c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
214d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_compositionNode = nullptr;
2153c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    m_customCompositionUnderlines.clear();
2163c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2173c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    insertTextForConfirmedComposition(text);
2183c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2193c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (mode == CancelComposition) {
2203c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        // An open typing command that disagrees about current selection would cause issues with typing later on.
2217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        TypingCommand::closeTyping(m_frame);
2223c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    }
223bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
224bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return true;
2253c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
2263c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2273c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdochvoid InputMethodController::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, unsigned selectionStart, unsigned selectionEnd)
2283c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
2293c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    Editor::RevealSelectionScope revealSelectionScope(&editor());
2303c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2313c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // Updates styles before setting selection for composition to prevent
2323c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // inserting the previous composition text into text nodes oddly.
2333c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // See https://bugs.webkit.org/show_bug.cgi?id=46868
2347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    frame().document()->updateRenderTreeIfNeeded();
2353c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2363c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    selectComposition();
2373c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (frame().selection().isNone())
2393c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
2403c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (Element* target = frame().document()->focusedElement()) {
2423c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        // Dispatch an appropriate composition event to the focused node.
2433c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        // We check the composition status and choose an appropriate composition event since this
2443c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        // function is used for three purposes:
2453c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        // 1. Starting a new composition.
2463c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        //    Send a compositionstart and a compositionupdate event when this function creates
2473c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        //    a new composition node, i.e.
2483c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        //    m_compositionNode == 0 && !text.isEmpty().
2493c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        //    Sending a compositionupdate event at this time ensures that at least one
2503c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        //    compositionupdate event is dispatched.
2513c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        // 2. Updating the existing composition node.
2523c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        //    Send a compositionupdate event when this function updates the existing composition
2533c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        //    node, i.e. m_compositionNode != 0 && !text.isEmpty().
2543c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        // 3. Canceling the ongoing composition.
2553c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        //    Send a compositionend event when function deletes the existing composition node, i.e.
2563c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        //    m_compositionNode != 0 && test.isEmpty().
257a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        RefPtrWillBeRawPtr<CompositionEvent> event = nullptr;
258bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        if (!hasComposition()) {
2593c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            // We should send a compositionstart event only when the given text is not empty because this
2603c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            // function doesn't create a composition node when the text is empty.
2613c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            if (!text.isEmpty()) {
2627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                target->dispatchEvent(CompositionEvent::create(EventTypeNames::compositionstart, frame().domWindow(), frame().selectedText(), underlines));
2637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                event = CompositionEvent::create(EventTypeNames::compositionupdate, frame().domWindow(), text, underlines);
2643c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            }
2653c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        } else {
2663c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            if (!text.isEmpty())
2677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                event = CompositionEvent::create(EventTypeNames::compositionupdate, frame().domWindow(), text, underlines);
2683c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            else
2697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                event = CompositionEvent::create(EventTypeNames::compositionend, frame().domWindow(), text, underlines);
2703c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        }
2713c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        if (event.get())
2723c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            target->dispatchEvent(event, IGNORE_EXCEPTION);
2733c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    }
2743c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2753c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // If text is empty, then delete the old composition here. If text is non-empty, InsertTextCommand::input
2763c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    // will delete the old composition with an optimized replace operation.
2778abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    if (text.isEmpty()) {
2787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ASSERT(frame().document());
2797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        TypingCommand::deleteSelection(*frame().document(), TypingCommand::PreventSpellChecking);
2808abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    }
2813c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
282d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_compositionNode = nullptr;
2833c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    m_customCompositionUnderlines.clear();
2843c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2853c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (!text.isEmpty()) {
2867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        ASSERT(frame().document());
2877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        TypingCommand::insertText(*frame().document(), text, TypingCommand::SelectInsertedText | TypingCommand::PreventSpellChecking, TypingCommand::TextCompositionUpdate);
2883c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2893c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        // Find out what node has the composition now.
2907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        Position base = frame().selection().base().downstream();
2917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        Position extent = frame().selection().extent();
2923c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        Node* baseNode = base.deprecatedNode();
2933c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        unsigned baseOffset = base.deprecatedEditingOffset();
2943c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        Node* extentNode = extent.deprecatedNode();
2953c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        unsigned extentOffset = extent.deprecatedEditingOffset();
2963c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
2973c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        if (baseNode && baseNode == extentNode && baseNode->isTextNode() && baseOffset + text.length() == extentOffset) {
2983c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            m_compositionNode = toText(baseNode);
2993c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            m_compositionStart = baseOffset;
3003c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            m_compositionEnd = extentOffset;
3013c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            m_customCompositionUnderlines = underlines;
3023c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            size_t numUnderlines = m_customCompositionUnderlines.size();
3033c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            for (size_t i = 0; i < numUnderlines; ++i) {
3043c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch                m_customCompositionUnderlines[i].startOffset += baseOffset;
3053c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch                m_customCompositionUnderlines[i].endOffset += baseOffset;
3063c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            }
3073c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            if (baseNode->renderer())
3089e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)                baseNode->renderer()->setShouldDoFullPaintInvalidation(true);
3093c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
3103c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            unsigned start = std::min(baseOffset + selectionStart, extentOffset);
3113c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch            unsigned end = std::min(std::max(start, baseOffset + selectionEnd), extentOffset);
312a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            RefPtrWillBeRawPtr<Range> selectedRange = Range::create(baseNode->document(), baseNode, start, baseNode, end);
3137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            frame().selection().setSelectedRange(selectedRange.get(), DOWNSTREAM, FrameSelection::NonDirectional, NotUserTriggered);
3143c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        }
3153c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    }
3163c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
3173c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
31800d3faa021f1e9934a353eeebe4e57e354856cf6Ben Murdochvoid InputMethodController::setCompositionFromExistingText(const Vector<CompositionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd)
31900d3faa021f1e9934a353eeebe4e57e354856cf6Ben Murdoch{
3207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Element* editable = frame().selection().rootEditableElement();
3217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Position base = frame().selection().base().downstream();
32200d3faa021f1e9934a353eeebe4e57e354856cf6Ben Murdoch    Node* baseNode = base.anchorNode();
323e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    if (editable->firstChild() == baseNode && editable->lastChild() == baseNode && baseNode->isTextNode()) {
324d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        m_compositionNode = nullptr;
325e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        m_customCompositionUnderlines.clear();
326e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
327e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (base.anchorType() != Position::PositionIsOffsetInAnchor)
328e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return;
3297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!baseNode || baseNode != frame().selection().extent().anchorNode())
330e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            return;
33100d3faa021f1e9934a353eeebe4e57e354856cf6Ben Murdoch
332e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        m_compositionNode = toText(baseNode);
333197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        RefPtrWillBeRawPtr<Range> range = PlainTextRange(compositionStart, compositionEnd).createRange(*editable);
3347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!range)
3357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            return;
3367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
337197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_compositionStart = range->startOffset();
338197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        m_compositionEnd = range->endOffset();
339e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        m_customCompositionUnderlines = underlines;
340e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        size_t numUnderlines = m_customCompositionUnderlines.size();
341e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (size_t i = 0; i < numUnderlines; ++i) {
342197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            m_customCompositionUnderlines[i].startOffset += m_compositionStart;
343197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            m_customCompositionUnderlines[i].endOffset += m_compositionStart;
344e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        }
345e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        if (baseNode->renderer())
3469e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)            baseNode->renderer()->setShouldDoFullPaintInvalidation(true);
347e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return;
34800d3faa021f1e9934a353eeebe4e57e354856cf6Ben Murdoch    }
349e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
350e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    Editor::RevealSelectionScope revealSelectionScope(&editor());
351e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    SelectionOffsetsScope selectionOffsetsScope(this);
352f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    setSelectionOffsets(PlainTextRange(compositionStart, compositionEnd));
3537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    setComposition(frame().selectedText(), underlines, 0, 0);
35400d3faa021f1e9934a353eeebe4e57e354856cf6Ben Murdoch}
35500d3faa021f1e9934a353eeebe4e57e354856cf6Ben Murdoch
356a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben MurdochPassRefPtrWillBeRawPtr<Range> InputMethodController::compositionRange() const
3573c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
358bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!hasComposition())
359d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
3603c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    unsigned length = m_compositionNode->length();
3613c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    unsigned start = std::min(m_compositionStart, length);
3623c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    unsigned end = std::min(std::max(start, m_compositionEnd), length);
3633c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    if (start >= end)
364d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return nullptr;
3653c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    return Range::create(m_compositionNode->document(), m_compositionNode.get(), start, m_compositionNode.get(), end);
3663c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
3673c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
368f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)PlainTextRange InputMethodController::getSelectionOffsets() const
369e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
3707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RefPtrWillBeRawPtr<Range> range = frame().selection().selection().firstRange();
371e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    if (!range)
372f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        return PlainTextRange();
3737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ContainerNode* editable = frame().selection().rootEditableElementOrTreeScopeRootNode();
374f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    ASSERT(editable);
375f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    return PlainTextRange::create(*editable, *range.get());
376e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
377e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
378f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)bool InputMethodController::setSelectionOffsets(const PlainTextRange& selectionOffsets)
379e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
380e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    if (selectionOffsets.isNull())
381e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        return false;
3827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Element* rootEditableElement = frame().selection().rootEditableElement();
383bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!rootEditableElement)
384bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return false;
385bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
386197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    RefPtrWillBeRawPtr<Range> range = selectionOffsets.createRange(*rootEditableElement);
387bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!range)
388bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return false;
389bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
3907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return frame().selection().setSelectedRange(range.get(), VP_DEFAULT_AFFINITY, FrameSelection::NonDirectional, FrameSelection::CloseTyping);
391bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
392bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
393f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)bool InputMethodController::setEditableSelectionOffsets(const PlainTextRange& selectionOffsets)
394bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
395bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!editor().canEdit())
396bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return false;
397bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return setSelectionOffsets(selectionOffsets);
398bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
399bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)
400bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)void InputMethodController::extendSelectionAndDelete(int before, int after)
401bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
402bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (!editor().canEdit())
403bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return;
404f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    PlainTextRange selectionOffsets(getSelectionOffsets());
405bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (selectionOffsets.isNull())
406bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        return;
407197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
408197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // A common call of before=1 and after=0 will fail if the last character
409197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // is multi-code-word UTF-16, including both multi-16bit code-points and
410197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // Unicode combining character sequences of multiple single-16bit code-
411197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // points (officially called "compositions"). Try more until success.
412197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // http://crbug.com/355995
413197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    //
414197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // FIXME: Note that this is not an ideal solution when this function is
415197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // called to implement "backspace". In that case, there should be some call
416197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // that will not delete a full multi-code-point composition but rather
417197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // only the last code-point so that it's possible for a user to correct
418197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // a composition without starting it from the beginning.
419197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    // http://crbug.com/37993
420197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    do {
421197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        if (!setSelectionOffsets(PlainTextRange(std::max(static_cast<int>(selectionOffsets.start()) - before, 0), selectionOffsets.end() + after)))
422197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return;
423c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (before == 0)
424c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            break;
425197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        ++before;
4267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } while (frame().selection().start() == frame().selection().end() && before <= static_cast<int>(selectionOffsets.start()));
4277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    TypingCommand::deleteSelection(*frame().document());
4287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
4297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
4307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid InputMethodController::trace(Visitor* visitor)
4317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
4327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    visitor->trace(m_frame);
4337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    visitor->trace(m_compositionNode);
434e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
435e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
436c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
437