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 40 namespace blink { 41 42 PassOwnPtrWillBeRawPtr<InputMethodContext> InputMethodContext::create(HTMLElement* element) 43 { 44 return adoptPtrWillBeNoop(new InputMethodContext(element)); 45 } 46 47 InputMethodContext::InputMethodContext(HTMLElement* element) 48 : m_element(element) 49 { 50 } 51 52 InputMethodContext::~InputMethodContext() 53 { 54 } 55 56 String InputMethodContext::locale() const 57 { 58 // FIXME: Implement this. 59 return emptyString(); 60 } 61 62 HTMLElement* InputMethodContext::target() const 63 { 64 return m_element; 65 } 66 67 unsigned InputMethodContext::compositionStartOffset() 68 { 69 if (hasFocus()) 70 return inputMethodController().compositionStart(); 71 return 0; 72 } 73 74 unsigned InputMethodContext::compositionEndOffset() 75 { 76 if (hasFocus()) 77 return inputMethodController().compositionEnd(); 78 return 0; 79 } 80 81 void InputMethodContext::confirmComposition() 82 { 83 if (hasFocus()) 84 inputMethodController().confirmCompositionAndResetState(); 85 } 86 87 bool 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 97 String InputMethodContext::compositionText() const 98 { 99 if (!hasFocus()) 100 return emptyString(); 101 102 Text* text = inputMethodController().compositionNode(); 103 return text ? text->wholeText() : emptyString(); 104 } 105 106 CompositionUnderline 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 129 int InputMethodContext::selectionStart() const 130 { 131 return selectedSegment().startOffset; 132 } 133 134 int InputMethodContext::selectionEnd() const 135 { 136 return selectedSegment().endOffset; 137 } 138 139 const 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 159 InputMethodController& InputMethodContext::inputMethodController() const 160 { 161 return m_element->document().frame()->inputMethodController(); 162 } 163 164 const AtomicString& InputMethodContext::interfaceName() const 165 { 166 return EventTargetNames::InputMethodContext; 167 } 168 169 ExecutionContext* InputMethodContext::executionContext() const 170 { 171 return &m_element->document(); 172 } 173 174 void InputMethodContext::dispatchCandidateWindowShowEvent() 175 { 176 dispatchEvent(Event::create(EventTypeNames::candidatewindowshow)); 177 } 178 179 void InputMethodContext::dispatchCandidateWindowUpdateEvent() 180 { 181 dispatchEvent(Event::create(EventTypeNames::candidatewindowupdate)); 182 } 183 184 void InputMethodContext::dispatchCandidateWindowHideEvent() 185 { 186 dispatchEvent(Event::create(EventTypeNames::candidatewindowhide)); 187 } 188 189 void InputMethodContext::trace(Visitor* visitor) 190 { 191 visitor->trace(m_element); 192 EventTargetWithInlineData::trace(visitor); 193 } 194 195 } // namespace blink 196