1/* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32#include "core/html/ime/InputMethodContext.h" 33 34#include "core/dom/Document.h" 35#include "core/dom/Text.h" 36#include "core/editing/InputMethodController.h" 37#include "core/events/Event.h" 38#include "core/frame/LocalFrame.h" 39 40namespace blink { 41 42PassOwnPtrWillBeRawPtr<InputMethodContext> InputMethodContext::create(HTMLElement* element) 43{ 44 return adoptPtrWillBeNoop(new InputMethodContext(element)); 45} 46 47InputMethodContext::InputMethodContext(HTMLElement* element) 48 : m_element(element) 49{ 50} 51 52InputMethodContext::~InputMethodContext() 53{ 54} 55 56String InputMethodContext::locale() const 57{ 58 // FIXME: Implement this. 59 return emptyString(); 60} 61 62HTMLElement* InputMethodContext::target() const 63{ 64 return m_element; 65} 66 67unsigned InputMethodContext::compositionStartOffset() 68{ 69 if (hasFocus()) 70 return inputMethodController().compositionStart(); 71 return 0; 72} 73 74unsigned InputMethodContext::compositionEndOffset() 75{ 76 if (hasFocus()) 77 return inputMethodController().compositionEnd(); 78 return 0; 79} 80 81void InputMethodContext::confirmComposition() 82{ 83 if (hasFocus()) 84 inputMethodController().confirmCompositionAndResetState(); 85} 86 87bool InputMethodContext::hasFocus() const 88{ 89 LocalFrame* frame = m_element->document().frame(); 90 if (!frame) 91 return false; 92 93 const Element* element = frame->document()->focusedElement(); 94 return element && element->isHTMLElement() && m_element == toHTMLElement(element); 95} 96 97String InputMethodContext::compositionText() const 98{ 99 if (!hasFocus()) 100 return emptyString(); 101 102 Text* text = inputMethodController().compositionNode(); 103 return text ? text->wholeText() : emptyString(); 104} 105 106CompositionUnderline InputMethodContext::selectedSegment() const 107{ 108 CompositionUnderline underline; 109 if (!hasFocus()) 110 return underline; 111 112 const InputMethodController& controller = inputMethodController(); 113 if (!controller.hasComposition()) 114 return underline; 115 116 Vector<CompositionUnderline> underlines = controller.customCompositionUnderlines(); 117 for (size_t i = 0; i < underlines.size(); ++i) { 118 if (underlines[i].thick) 119 return underlines[i]; 120 } 121 122 // When no underline information is available while composition exists, 123 // build a CompositionUnderline whose element is the whole composition. 124 underline.endOffset = controller.compositionEnd() - controller.compositionStart(); 125 return underline; 126 127} 128 129int InputMethodContext::selectionStart() const 130{ 131 return selectedSegment().startOffset; 132} 133 134int InputMethodContext::selectionEnd() const 135{ 136 return selectedSegment().endOffset; 137} 138 139const Vector<unsigned>& InputMethodContext::segments() 140{ 141 m_segments.clear(); 142 if (!hasFocus()) 143 return m_segments; 144 const InputMethodController& controller = inputMethodController(); 145 if (!controller.hasComposition()) 146 return m_segments; 147 148 Vector<CompositionUnderline> underlines = controller.customCompositionUnderlines(); 149 if (!underlines.size()) { 150 m_segments.append(0); 151 } else { 152 for (size_t i = 0; i < underlines.size(); ++i) 153 m_segments.append(underlines[i].startOffset); 154 } 155 156 return m_segments; 157} 158 159InputMethodController& InputMethodContext::inputMethodController() const 160{ 161 return m_element->document().frame()->inputMethodController(); 162} 163 164const AtomicString& InputMethodContext::interfaceName() const 165{ 166 return EventTargetNames::InputMethodContext; 167} 168 169ExecutionContext* InputMethodContext::executionContext() const 170{ 171 return &m_element->document(); 172} 173 174void InputMethodContext::dispatchCandidateWindowShowEvent() 175{ 176 dispatchEvent(Event::create(EventTypeNames::candidatewindowshow)); 177} 178 179void InputMethodContext::dispatchCandidateWindowUpdateEvent() 180{ 181 dispatchEvent(Event::create(EventTypeNames::candidatewindowupdate)); 182} 183 184void InputMethodContext::dispatchCandidateWindowHideEvent() 185{ 186 dispatchEvent(Event::create(EventTypeNames::candidatewindowhide)); 187} 188 189void InputMethodContext::trace(Visitor* visitor) 190{ 191 visitor->trace(m_element); 192 EventTargetWithInlineData::trace(visitor); 193} 194 195} // namespace blink 196