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