2 Copyright (C) 2011 Samsung Electronics
3 Copyright (C) 2012 Intel Corporation. All rights reserved.
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 #include "InputMethodContextEfl.h"
24 #include "EwkViewImpl.h"
25 #include "WebPageProxy.h"
26 #include <Ecore_Evas.h>
27 #include <Ecore_IMF_Evas.h>
29 using namespace WebCore;
33 InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<Ecore_IMF_Context> context)
34 : m_viewImpl(viewImpl)
39 #if ENABLE(TIZEN_ISF_PORT)
40 initializeIMFContext(m_context.get(), ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL);
42 ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
43 ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
47 InputMethodContextEfl::~InputMethodContextEfl()
51 #if ENABLE(TIZEN_ISF_PORT)
52 void InputMethodContextEfl::onIMFInputPanelStateChanged(void* data, Ecore_IMF_Context*, int state)
54 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
55 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
58 if (state == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
59 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,ime,closed", 0);
60 else if (state == ECORE_IMF_INPUT_PANEL_STATE_SHOW)
61 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,ime,opened", 0);
64 void InputMethodContextEfl::onIMFInputPanelGeometryChanged(void* data, Ecore_IMF_Context*, int value)
66 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
67 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
71 ecore_imf_context_input_panel_geometry_get(inputMethodContext->m_context.get(), &rect.x, &rect.y, &rect.w, &rect.h);
72 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "inputmethod,changed", &rect);
75 void InputMethodContextEfl::onIMFCandidatePanelStateChanged(void* data, Ecore_IMF_Context*, int state)
77 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
78 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
81 if (state == ECORE_IMF_CANDIDATE_PANEL_SHOW)
82 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,opened", 0);
84 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,closed", 0);
87 void InputMethodContextEfl::onIMFCandidatePanelGeometryChanged(void* data, Ecore_IMF_Context*, int)
89 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
90 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
94 ecore_imf_context_candidate_panel_geometry_get(inputMethodContext->m_context.get(), &rect.x, &rect.y, &rect.w, &rect.h);
95 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,changed", &rect);
98 Eina_Bool InputMethodContextEfl::onIMFRetrieveSurrounding(void* data, Ecore_IMF_Context*, char** text, int* offset)
100 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
101 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused || (!text && !offset))
104 String surroundingText;
106 inputMethodContext->m_viewImpl->page()->getSurroundingTextAndCursorOffset(surroundingText, cursorOffset);
109 CString utf8Text(surroundingText.utf8());
110 size_t length = utf8Text.length();
112 *text = static_cast<char*>(malloc((length + 1) * sizeof(char)));
117 strncpy(*text, utf8Text.data(), length);
122 *offset = cursorOffset;
127 void InputMethodContextEfl::onIMFDeleteSurrounding(void* data, Ecore_IMF_Context*, void* eventInfo)
129 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
130 if (!eventInfo || !inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
133 Ecore_IMF_Event_Delete_Surrounding* event = static_cast<Ecore_IMF_Event_Delete_Surrounding*>(eventInfo);
134 inputMethodContext->m_viewImpl->page()->deleteSurroundingText(event->offset, event->n_chars);
137 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
139 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
140 if (!eventInfo || !inputMethodContext->m_focused)
143 inputMethodContext->m_viewImpl->pageClient->imContextCommitted(inputMethodContext->m_context.get(), static_cast<char*>(eventInfo));
146 void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context*, void*)
148 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
149 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
152 inputMethodContext->m_viewImpl->pageClient->imContextPreeditChanged(inputMethodContext->m_context.get());
155 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
157 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
158 if (!eventInfo || !inputMethodContext->m_focused)
161 inputMethodContext->m_viewImpl->page()->confirmComposition(String::fromUTF8(static_cast<char*>(eventInfo)));
164 void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context* context, void*)
166 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
168 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
172 ecore_imf_context_preedit_string_get(context, &buffer, 0);
176 String preeditString = String::fromUTF8(buffer);
178 Vector<CompositionUnderline> underlines;
179 underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false));
180 inputMethodContext->m_viewImpl->page()->setComposition(preeditString, underlines, 0);
184 PassOwnPtr<Ecore_IMF_Context> InputMethodContextEfl::createIMFContext(Evas* canvas)
186 const char* defaultContextID = ecore_imf_context_default_id_get();
187 if (!defaultContextID)
190 OwnPtr<Ecore_IMF_Context> imfContext = adoptPtr(ecore_imf_context_add(defaultContextID));
194 Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(canvas);
195 ecore_imf_context_client_window_set(imfContext.get(), reinterpret_cast<void*>(ecore_evas_window_get(ecoreEvas)));
196 ecore_imf_context_client_canvas_set(imfContext.get(), canvas);
198 return imfContext.release();
201 void InputMethodContextEfl::handleMouseUpEvent(const Evas_Event_Mouse_Up*)
203 ecore_imf_context_reset(m_context.get());
206 void InputMethodContextEfl::handleKeyDownEvent(const Evas_Event_Key_Down* downEvent, bool* isFiltered)
208 Ecore_IMF_Event inputMethodEvent;
209 ecore_imf_evas_event_key_down_wrap(const_cast<Evas_Event_Key_Down*>(downEvent), &inputMethodEvent.key_down);
211 *isFiltered = ecore_imf_context_filter_event(m_context.get(), ECORE_IMF_EVENT_KEY_DOWN, &inputMethodEvent);
214 void InputMethodContextEfl::updateTextInputState()
219 const EditorState& editor = m_viewImpl->page()->editorState();
221 if (editor.isContentEditable) {
225 ecore_imf_context_reset(m_context.get());
226 ecore_imf_context_focus_in(m_context.get());
232 if (editor.hasComposition)
233 m_viewImpl->page()->cancelComposition();
236 ecore_imf_context_reset(m_context.get());
237 ecore_imf_context_focus_out(m_context.get());
241 #if ENABLE(TIZEN_ISF_PORT)
242 void InputMethodContextEfl::initializeIMFContext(Ecore_IMF_Context* context, Ecore_IMF_Input_Panel_Layout layout)
244 ecore_imf_context_input_panel_enabled_set(context, false);
245 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_INPUT_PANEL_STATE_EVENT, onIMFInputPanelStateChanged, this);
246 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, onIMFInputPanelGeometryChanged, this);
247 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, onIMFCandidatePanelStateChanged, this);
248 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, onIMFCandidatePanelGeometryChanged, this);
249 ecore_imf_context_retrieve_surrounding_callback_set(context, onIMFRetrieveSurrounding, this);
250 ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, onIMFDeleteSurrounding, this);
251 ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
252 ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
253 ecore_imf_context_input_panel_layout_set(m_context.get(), layout);
256 void InputMethodContextEfl::setType(const String& type)
258 Ecore_IMF_Input_Panel_Layout layout;
259 if (type == "number")
260 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER;
261 else if (type == "email")
262 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
263 else if (type == "url")
264 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
265 else if (type == "tel")
266 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
267 else if (type == "password")
268 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
270 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
272 if (m_contextList.contains(layout)) {
274 m_context = m_contextList.take(layout);
275 } else if (!m_context || ecore_imf_context_input_panel_layout_get(m_context.get()) != layout) {
276 OwnPtr<Ecore_IMF_Context> context = createIMFContext(evas_object_evas_get(m_viewImpl->view()));
280 m_context = context.release();
281 initializeIMFContext(m_context.get(), layout);
284 if (type == "password" || type == "plugin")
285 ecore_imf_context_prediction_allow_set(m_context.get(), false);
287 ecore_imf_context_prediction_allow_set(m_context.get(), true);
289 if (type.isEmpty() || type == "textarea")
290 ecore_imf_context_autocapital_type_set(m_context.get(), ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE);
292 ecore_imf_context_autocapital_type_set(m_context.get(), ECORE_IMF_AUTOCAPITAL_TYPE_NONE);
295 void InputMethodContextEfl::showIMFContext()
300 ecore_imf_context_focus_in(m_context.get());
301 ecore_imf_context_input_panel_show(m_context.get());
302 ecore_imf_context_cursor_position_set(m_context.get(), m_viewImpl->page()->getCursorOffset());
305 void InputMethodContextEfl::setIMFContextCursorPosition(int position)
310 ecore_imf_context_cursor_position_set(m_context.get(), position);
313 void InputMethodContextEfl::setIMData(const String& data)
318 CString utf8Data = data.utf8();
319 ecore_imf_context_input_panel_imdata_set(m_context.get(), utf8Data.data(), utf8Data.length());
322 bool InputMethodContextEfl::isShow()
324 return (m_context && m_focused && ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE);
327 Ecore_IMF_Autocapital_Type InputMethodContextEfl::autoCapitalType()
329 return (m_context ? ecore_imf_context_autocapital_type_get(m_context.get()) : ECORE_IMF_AUTOCAPITAL_TYPE_NONE);
332 void InputMethodContextEfl::onFocusIn()
334 if (!m_context || !m_focused)
337 ecore_imf_context_focus_in(m_context.get());
338 ecore_imf_context_input_panel_show(m_context.get());
341 void InputMethodContextEfl::onFocusOut()
343 if (!m_context || !m_focused)
346 ecore_imf_context_input_panel_hide(m_context.get());
347 ecore_imf_context_focus_out(m_context.get());
350 void InputMethodContextEfl::revertIMFContext()
355 PassOwnPtr<Ecore_IMF_Context> imfContext = m_context.release();
356 m_contextList.add(ecore_imf_context_input_panel_layout_get(imfContext.get()), imfContext);
359 void InputMethodContextEfl::resetIMFContext()
364 ecore_imf_context_reset(m_context.get());
366 if (ecore_imf_context_input_panel_state_get(m_context.get()) == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
370 void InputMethodContextEfl::hideIMFContext()
375 if (ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
376 ecore_imf_context_reset(m_context.get());
377 ecore_imf_context_input_panel_hide(m_context.get());
378 ecore_imf_context_focus_out(m_context.get());
384 void InputMethodContextEfl::destroyIMFContextList()
386 m_contextList.clear();