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