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/Text.h" 35 #include "core/editing/InputMethodController.h" 36 #include "core/html/ime/Composition.h" 37 #include "core/frame/Frame.h" 38 39 namespace WebCore { 40 41 PassOwnPtr<InputMethodContext> InputMethodContext::create(HTMLElement* element) 42 { 43 return adoptPtr(new InputMethodContext(element)); 44 } 45 46 InputMethodContext::InputMethodContext(HTMLElement* element) 47 : m_element(element) 48 { 49 ScriptWrappable::init(this); 50 } 51 52 InputMethodContext::~InputMethodContext() 53 { 54 } 55 56 Composition* InputMethodContext::composition() 57 { 58 if (!m_composition) 59 m_composition = Composition::create(this); 60 return m_composition.get(); 61 } 62 63 String InputMethodContext::locale() const 64 { 65 // FIXME: Implement this. 66 return emptyString(); 67 } 68 69 HTMLElement* InputMethodContext::target() const 70 { 71 return m_element; 72 } 73 74 unsigned InputMethodContext::compositionStartOffset() 75 { 76 if (hasFocus()) 77 return inputMethodController().compositionStart(); 78 return 0; 79 } 80 81 unsigned InputMethodContext::compositionEndOffset() 82 { 83 if (hasFocus()) 84 return inputMethodController().compositionEnd(); 85 return 0; 86 } 87 88 void InputMethodContext::confirmComposition() 89 { 90 if (hasFocus()) 91 inputMethodController().confirmCompositionAndResetState(); 92 } 93 94 bool InputMethodContext::hasFocus() const 95 { 96 Frame* frame = m_element->document().frame(); 97 if (!frame) 98 return false; 99 100 const Element* element = frame->document()->focusedElement(); 101 return element && element->isHTMLElement() && m_element == toHTMLElement(element); 102 } 103 104 String InputMethodContext::compositionText() const 105 { 106 if (!hasFocus()) 107 return emptyString(); 108 109 Text* text = inputMethodController().compositionNode(); 110 return text ? text->wholeText() : emptyString(); 111 } 112 113 CompositionUnderline InputMethodContext::selectedSegment() const 114 { 115 CompositionUnderline underline; 116 if (!hasFocus()) 117 return underline; 118 119 const InputMethodController& controller = inputMethodController(); 120 if (!controller.hasComposition()) 121 return underline; 122 123 Vector<CompositionUnderline> underlines = controller.customCompositionUnderlines(); 124 for (size_t i = 0; i < underlines.size(); ++i) { 125 if (underlines[i].thick) 126 return underlines[i]; 127 } 128 129 // When no underline information is available while composition exists, 130 // build a CompositionUnderline whose element is the whole composition. 131 underline.endOffset = controller.compositionEnd() - controller.compositionStart(); 132 return underline; 133 134 } 135 136 int InputMethodContext::selectionStart() const 137 { 138 return selectedSegment().startOffset; 139 } 140 141 int InputMethodContext::selectionEnd() const 142 { 143 return selectedSegment().endOffset; 144 } 145 146 const Vector<unsigned>& InputMethodContext::segments() 147 { 148 m_segments.clear(); 149 if (!hasFocus()) 150 return m_segments; 151 const InputMethodController& controller = inputMethodController(); 152 if (!controller.hasComposition()) 153 return m_segments; 154 155 Vector<CompositionUnderline> underlines = controller.customCompositionUnderlines(); 156 if (!underlines.size()) { 157 m_segments.append(0); 158 } else { 159 for (size_t i = 0; i < underlines.size(); ++i) 160 m_segments.append(underlines[i].startOffset); 161 } 162 163 return m_segments; 164 } 165 166 InputMethodController& InputMethodContext::inputMethodController() const 167 { 168 return m_element->document().frame()->inputMethodController(); 169 } 170 171 const AtomicString& InputMethodContext::interfaceName() const 172 { 173 return EventTargetNames::InputMethodContext; 174 } 175 176 ExecutionContext* InputMethodContext::executionContext() const 177 { 178 return &m_element->document(); 179 } 180 181 void InputMethodContext::dispatchCandidateWindowShowEvent() 182 { 183 dispatchEvent(Event::create(EventTypeNames::candidatewindowshow)); 184 } 185 186 void InputMethodContext::dispatchCandidateWindowUpdateEvent() 187 { 188 dispatchEvent(Event::create(EventTypeNames::candidatewindowupdate)); 189 } 190 191 void InputMethodContext::dispatchCandidateWindowHideEvent() 192 { 193 dispatchEvent(Event::create(EventTypeNames::candidatewindowhide)); 194 } 195 196 } // namespace WebCore 197