d7f993d50a4d820205af8ceeb23721d71aa55796
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / efl / InputMethodContextEfl.cpp
1 /*
2    Copyright (C) 2011 Samsung Electronics
3    Copyright (C) 2012 Intel Corporation. All rights reserved.
4
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.
9
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.
14
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.
19 */
20
21 #include "config.h"
22 #include "InputMethodContextEfl.h"
23
24 #include "EwkViewImpl.h"
25 #include "WebPageProxy.h"
26 #include <Ecore_Evas.h>
27 #include <Ecore_IMF_Evas.h>
28
29 using namespace WebCore;
30
31 namespace WebKit {
32
33 InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<Ecore_IMF_Context> context)
34     : m_viewImpl(viewImpl)
35     , m_context(context)
36     , m_focused(false)
37 {
38     ASSERT(context);
39 #if ENABLE(TIZEN_ISF_PORT)
40     initializeIMFContext(m_context.get(), ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL);
41 #else
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);
44 #endif
45 }
46
47 InputMethodContextEfl::~InputMethodContextEfl()
48 {
49 }
50
51 #if ENABLE(TIZEN_ISF_PORT)
52 void InputMethodContextEfl::onIMFInputPanelStateChanged(void* data, Ecore_IMF_Context*, int state)
53 {
54     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
55     if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
56         return;
57
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);
62 }
63
64 void InputMethodContextEfl::onIMFInputPanelGeometryChanged(void* data, Ecore_IMF_Context*, int value)
65 {
66     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
67     if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
68         return;
69
70     Eina_Rectangle rect;
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);
73 }
74
75 void InputMethodContextEfl::onIMFCandidatePanelStateChanged(void* data, Ecore_IMF_Context*, int state)
76 {
77     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
78     if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
79         return;
80
81     if (state == ECORE_IMF_CANDIDATE_PANEL_SHOW)
82         evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,opened", 0);
83     else
84         evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,closed", 0);
85 }
86
87 void InputMethodContextEfl::onIMFCandidatePanelGeometryChanged(void* data, Ecore_IMF_Context*, int)
88 {
89     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
90     if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
91         return;
92
93     Eina_Rectangle rect;
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);
96 }
97
98 Eina_Bool InputMethodContextEfl::onIMFRetrieveSurrounding(void* data, Ecore_IMF_Context*, char** text, int* offset)
99 {
100     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
101     if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused || (!text && !offset))
102         return false;
103
104     String surroundingText;
105     int cursorOffset;
106     inputMethodContext->m_viewImpl->page()->getSurroundingTextAndCursorOffset(surroundingText, cursorOffset);
107
108     if (text) {
109         CString utf8Text(surroundingText.utf8());
110         size_t length = utf8Text.length();
111
112         *text = static_cast<char*>(malloc((length + 1) * sizeof(char)));
113         if (!(*text))
114             return false;
115
116         if (length)
117             strncpy(*text, utf8Text.data(), length);
118         (*text)[length] = 0;
119     }
120
121     if (offset)
122         *offset = cursorOffset;
123
124     return true;
125 }
126
127 void InputMethodContextEfl::onIMFDeleteSurrounding(void* data, Ecore_IMF_Context*, void* eventInfo)
128 {
129     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
130     if (!eventInfo || !inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
131         return;
132
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);
135 }
136
137 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
138 {
139     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
140     if (!eventInfo || !inputMethodContext->m_focused)
141         return;
142
143     inputMethodContext->m_viewImpl->page()->confirmComposition(String::fromUTF8(static_cast<char*>(eventInfo)));
144 }
145
146 #if ENABLE(TIZEN_WEBKIT2_SUPPORT_JAPANESE_IME)
147 unsigned getUTF8CharacterIndex(const char* string, unsigned byteIndex)
148 {
149     unsigned index = 0;
150     const char* end = string + byteIndex;
151
152     while (*string && string < end) {
153         unsigned offset;
154
155         if ((*string & 0x80) == 0x00)
156             offset = 1;
157         else if ((*string & 0xe0) == 0xc0)
158             offset = 2;
159         else if ((*string & 0xf0) == 0xe0)
160             offset = 3;
161         else if ((*string & 0xf8) == 0xf0)
162             offset = 4;
163         else if ((*string & 0xfc) == 0xf8)
164             offset = 5;
165         else if ((*string & 0xfe) == 0xfc)
166             offset = 6;
167         else
168             offset = 1;
169
170         ++index;
171         while (*string && offset--)
172             ++string;
173     }
174
175     return index;
176 }
177 #endif
178
179 void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context* context, void*)
180 {
181     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
182
183     if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
184         return;
185
186     WebPageProxy* page = inputMethodContext->m_viewImpl->page();
187     if (!page->focusedFrame())
188         return;
189
190     PageClientImpl* pageClient = inputMethodContext->m_viewImpl->pageClient.get();
191     IntRect caretRect;
192     page->getCaretPosition(caretRect);
193     caretRect.scale(pageClient->scaleFactor());
194
195     int viewX, viewY;
196     evas_object_geometry_get(inputMethodContext->m_viewImpl->view(), &viewX, &viewY, 0, 0);
197
198     int x = caretRect.x() - pageClient->scrollPosition().x() + viewX;
199     int y = caretRect.y() - pageClient->scrollPosition().y() + viewY;
200     int w = caretRect.width();
201     int h = caretRect.height();
202     ecore_imf_context_cursor_location_set(context, x, y, w, h);
203
204     char* buffer = 0;
205     Eina_List* preeditAttrs = 0;
206     int cursorPosition = 0;
207
208     ecore_imf_context_preedit_string_with_attributes_get(context, &buffer, &preeditAttrs, &cursorPosition);
209
210     String preeditString = String::fromUTF8(buffer);
211     Vector<CompositionUnderline> underlines;
212
213     if (preeditAttrs) {
214         void* item = 0;
215 #if ENABLE(TIZEN_WEBKIT2_SUPPORT_JAPANESE_IME)
216         Eina_List* listIterator = 0;
217         EINA_LIST_FOREACH(preeditAttrs, listIterator, item) {
218             Ecore_IMF_Preedit_Attr* preeditAttr = static_cast<Ecore_IMF_Preedit_Attr*>(item);
219
220             unsigned startIndex = getUTF8CharacterIndex(buffer, preeditAttr->start_index);
221             unsigned endIndex = getUTF8CharacterIndex(buffer, preeditAttr->end_index);
222             switch (preeditAttr->preedit_type) {
223             case ECORE_IMF_PREEDIT_TYPE_SUB1:
224                 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), false));
225                 break;
226             case ECORE_IMF_PREEDIT_TYPE_SUB2:
227             case ECORE_IMF_PREEDIT_TYPE_SUB3:
228                 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(255, 255, 255), false));
229                 break;
230             case ECORE_IMF_PREEDIT_TYPE_SUB4:
231                 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(46, 168, 255), false));
232                 break;
233             case ECORE_IMF_PREEDIT_TYPE_SUB5:
234                 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(153, 98, 195), false));
235                 break;
236             case ECORE_IMF_PREEDIT_TYPE_SUB6:
237                 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(118, 222, 55), false));
238                 break;
239             case ECORE_IMF_PREEDIT_TYPE_SUB7:
240                 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(153, 153, 153), false));
241                 break;
242             default:
243                 break;
244             }
245         }
246 #endif
247         EINA_LIST_FREE(preeditAttrs, item)
248             free(item);
249     }
250
251     if (underlines.isEmpty())
252         underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false));
253
254     page->setComposition(preeditString, underlines, cursorPosition);
255
256     if (buffer)
257         free(buffer);
258 }
259 #else
260 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
261 {
262     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
263     if (!eventInfo || !inputMethodContext->m_focused)
264         return;
265
266     inputMethodContext->m_viewImpl->page()->confirmComposition(String::fromUTF8(static_cast<char*>(eventInfo)));
267 }
268
269 void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context* context, void*)
270 {
271     InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
272
273     if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
274         return;
275
276     char* buffer = 0;
277     ecore_imf_context_preedit_string_get(context, &buffer, 0);
278     if (!buffer)
279         return;
280
281     String preeditString = String::fromUTF8(buffer);
282     free(buffer);
283     Vector<CompositionUnderline> underlines;
284     underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false));
285     inputMethodContext->m_viewImpl->page()->setComposition(preeditString, underlines, 0);
286 }
287 #endif
288
289 PassOwnPtr<Ecore_IMF_Context> InputMethodContextEfl::createIMFContext(Evas* canvas)
290 {
291     const char* defaultContextID = ecore_imf_context_default_id_get();
292     if (!defaultContextID)
293         return nullptr;
294
295     OwnPtr<Ecore_IMF_Context> imfContext = adoptPtr(ecore_imf_context_add(defaultContextID));
296     if (!imfContext)
297         return nullptr;
298
299     Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(canvas);
300     ecore_imf_context_client_window_set(imfContext.get(), reinterpret_cast<void*>(ecore_evas_window_get(ecoreEvas)));
301     ecore_imf_context_client_canvas_set(imfContext.get(), canvas);
302
303     return imfContext.release();
304 }
305
306 void InputMethodContextEfl::handleMouseUpEvent(const Evas_Event_Mouse_Up*)
307 {
308     ecore_imf_context_reset(m_context.get());
309 }
310
311 void InputMethodContextEfl::handleKeyDownEvent(const Evas_Event_Key_Down* downEvent, bool* isFiltered)
312 {
313     Ecore_IMF_Event inputMethodEvent;
314     ecore_imf_evas_event_key_down_wrap(const_cast<Evas_Event_Key_Down*>(downEvent), &inputMethodEvent.key_down);
315
316     *isFiltered = ecore_imf_context_filter_event(m_context.get(), ECORE_IMF_EVENT_KEY_DOWN, &inputMethodEvent);
317 }
318
319 void InputMethodContextEfl::updateTextInputState()
320 {
321 #if !ENABLE(TIZEN_ISF_PORT)
322     if (!m_context)
323         return;
324 #endif
325
326     const EditorState& editor = m_viewImpl->page()->editorState();
327
328     if (editor.isContentEditable) {
329 #if ENABLE(TIZEN_ISF_PORT)
330         if (m_context)
331             ecore_imf_context_cursor_position_set(m_context.get(), editor.cursorPosition);
332 #endif
333
334         if (m_focused)
335             return;
336
337 #if ENABLE(TIZEN_ISF_PORT)
338         Ewk_Settings* settings = ewk_view_settings_get(m_viewImpl->view());
339         bool defaultKeypadEnabled = ewk_settings_default_keypad_enabled_get(settings);
340
341 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
342         if (m_viewImpl->pageClient->isClipboardWindowOpened()) {
343             LOG(ISF, "[FAIL] Clipboard\n");
344             return;
345         }
346 #endif
347
348 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
349         if (editor.inputMethodHints == "date") {
350             ewkViewInputPickerRequest(m_viewImpl->view(), EWK_INPUT_TYPE_DATE, editor.surroundingText);
351             return;
352         } else if (editor.inputMethodHints == "datetime") {
353             ewkViewInputPickerRequest(m_viewImpl->view(), EWK_INPUT_TYPE_DATETIME, editor.surroundingText);
354             return;
355         } else if (editor.inputMethodHints == "datetime-local") {
356             ewkViewInputPickerRequest(m_viewImpl->view(), EWK_INPUT_TYPE_DATETIMELOCAL, editor.surroundingText);
357             return;
358         } else if (editor.inputMethodHints == "month") {
359             ewkViewInputPickerRequest(m_viewImpl->view(), EWK_INPUT_TYPE_MONTH, editor.surroundingText);
360             return;
361         } else if (editor.inputMethodHints == "time") {
362             ewkViewInputPickerRequest(m_viewImpl->view(), EWK_INPUT_TYPE_TIME, editor.surroundingText);
363             return;
364         } else if (editor.inputMethodHints == "week") {
365             ewkViewInputPickerRequest(m_viewImpl->view(), EWK_INPUT_TYPE_WEEK, editor.surroundingText);
366             return;
367         }
368
369 #if ENABLE(TIZEN_DATALIST_ELEMENT)
370         Vector<String> optionList = m_viewImpl->page()->getFocusedInputElementDataList();
371         if (optionList.size() > 0) {
372             if (editor.inputMethodHints == "tel")
373                 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_TELEPHONE, optionList);
374             else if (editor.inputMethodHints == "number")
375                 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_NUMBER, optionList);
376             else if (editor.inputMethodHints == "email")
377                 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_EMAIL, optionList);
378             else if (editor.inputMethodHints == "url")
379                 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_URL, optionList);
380             else
381                 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_TEXT, optionList);
382
383             return;
384         }
385 #endif
386 #endif // ENABLE(TIZEN_INPUT_TAG_EXTENSION)
387
388         bool hasFocus = evas_object_focus_get(m_viewImpl->view());
389
390         if (!defaultKeypadEnabled) {
391             if (hasFocus) {
392                 Eina_Rectangle dummyRectForCustomKeypadCallback;
393                 memset(&dummyRectForCustomKeypadCallback, 0, sizeof(Eina_Rectangle));
394                 evas_object_smart_callback_call(m_viewImpl->view(), "inputmethod,changed", &dummyRectForCustomKeypadCallback);
395             }
396             return;
397         }
398
399         setType(editor.inputMethodHints);
400
401         if (!hasFocus)
402             return;
403
404         // input field zoom for external keyboard
405         ewk_view_focused_node_adjust(m_viewImpl->view(), EINA_TRUE);
406 #endif
407
408         ecore_imf_context_reset(m_context.get());
409         ecore_imf_context_focus_in(m_context.get());
410 #if ENABLE(TIZEN_ISF_PORT)
411         ecore_imf_context_input_panel_show(m_context.get());
412 #endif
413         m_focused = true;
414     } else {
415         if (!m_focused)
416             return;
417
418         if (editor.hasComposition)
419             m_viewImpl->page()->cancelComposition();
420
421         m_focused = false;
422         ecore_imf_context_reset(m_context.get());
423         ecore_imf_context_focus_out(m_context.get());
424 #if ENABLE(TIZEN_ISF_PORT)
425         ecore_imf_context_input_panel_hide(m_context.get());
426         revertIMFContext();
427 #endif
428     }
429 }
430
431 #if ENABLE(TIZEN_ISF_PORT)
432 void InputMethodContextEfl::initializeIMFContext(Ecore_IMF_Context* context, Ecore_IMF_Input_Panel_Layout layout)
433 {
434     ecore_imf_context_input_panel_enabled_set(context, false);
435     ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_INPUT_PANEL_STATE_EVENT, onIMFInputPanelStateChanged, this);
436     ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, onIMFInputPanelGeometryChanged, this);
437     ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, onIMFCandidatePanelStateChanged, this);
438     ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, onIMFCandidatePanelGeometryChanged, this);
439     ecore_imf_context_retrieve_surrounding_callback_set(context, onIMFRetrieveSurrounding, this);
440     ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, onIMFDeleteSurrounding, this);
441     ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
442     ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
443     ecore_imf_context_input_panel_layout_set(m_context.get(), layout);
444 }
445
446 void InputMethodContextEfl::setType(const String& type)
447 {
448     Ecore_IMF_Input_Panel_Layout layout;
449     if (type == "number")
450         layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER;
451     else if (type == "email")
452         layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
453     else if (type == "url")
454         layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
455     else if (type == "tel")
456         layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
457     else if (type == "password")
458         layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
459     else
460         layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
461
462     if (m_contextList.contains(layout)) {
463         revertIMFContext();
464         m_context = m_contextList.take(layout);
465     } else if (!m_context || ecore_imf_context_input_panel_layout_get(m_context.get()) != layout) {
466         OwnPtr<Ecore_IMF_Context> context = createIMFContext(evas_object_evas_get(m_viewImpl->view()));
467         if (m_context)
468             revertIMFContext();
469         m_context = context.release();
470         initializeIMFContext(m_context.get(), layout);
471     }
472
473     if (type == "password" || type == "plugin")
474         ecore_imf_context_prediction_allow_set(m_context.get(), false);
475     else
476         ecore_imf_context_prediction_allow_set(m_context.get(), true);
477
478     if (type.isEmpty() || type == "textarea")
479         ecore_imf_context_autocapital_type_set(m_context.get(), ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE);
480     else
481         ecore_imf_context_autocapital_type_set(m_context.get(), ECORE_IMF_AUTOCAPITAL_TYPE_NONE);
482 }
483
484 bool InputMethodContextEfl::isShow()
485 {
486     return (m_context && m_focused && ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE);
487 }
488
489 Ecore_IMF_Autocapital_Type InputMethodContextEfl::autoCapitalType()
490 {
491     return (m_context ? ecore_imf_context_autocapital_type_get(m_context.get()) : ECORE_IMF_AUTOCAPITAL_TYPE_NONE);
492 }
493
494 void InputMethodContextEfl::onFocusIn()
495 {
496     if (!m_context || !m_focused)
497         return;
498
499     ecore_imf_context_focus_in(m_context.get());
500     ecore_imf_context_input_panel_show(m_context.get());
501 }
502
503 void InputMethodContextEfl::onFocusOut()
504 {
505     if (!m_context || !m_focused)
506         return;
507
508     ecore_imf_context_input_panel_hide(m_context.get());
509     ecore_imf_context_focus_out(m_context.get());
510 }
511
512 void InputMethodContextEfl::revertIMFContext()
513 {
514     if (!m_context)
515         return;
516
517     PassOwnPtr<Ecore_IMF_Context> imfContext = m_context.release();
518     m_contextList.add(ecore_imf_context_input_panel_layout_get(imfContext.get()), imfContext);
519 }
520
521 void InputMethodContextEfl::resetIMFContext()
522 {
523     if (!m_context)
524         return;
525
526     ecore_imf_context_reset(m_context.get());
527
528     if (ecore_imf_context_input_panel_state_get(m_context.get()) == ECORE_IMF_INPUT_PANEL_STATE_HIDE)
529         revertIMFContext();
530 }
531
532 void InputMethodContextEfl::hideIMFContext()
533 {
534     if (!m_context)
535         return;
536
537     if (ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
538         ecore_imf_context_reset(m_context.get());
539         ecore_imf_context_input_panel_hide(m_context.get());
540         ecore_imf_context_focus_out(m_context.get());
541     }
542
543     revertIMFContext();
544 }
545
546 void InputMethodContextEfl::destroyIMFContextList()
547 {
548     m_contextList.clear();
549 }
550 #endif
551
552 }