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