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