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