2 Copyright (C) 2011 Samsung Electronics
3 Copyright (C) 2012 Intel Corporation. All rights reserved.
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.
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.
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.
22 #include "InputMethodContextEfl.h"
24 #include "EwkViewImpl.h"
25 #include "WebPageProxy.h"
26 #include <Ecore_Evas.h>
27 #include <Ecore_IMF_Evas.h>
29 using namespace WebCore;
33 #if ENABLE(TIZEN_ISF_PORT)
34 const unsigned InputMethodContextEfl::maxContextSize = 10;
37 InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<Ecore_IMF_Context> context)
38 : m_viewImpl(viewImpl)
41 #if ENABLE(TIZEN_ISF_PORT)
43 , m_state(ECORE_IMF_INPUT_PANEL_STATE_HIDE)
44 , m_inputPickerType(-1)
45 , m_doNotHandleFakeKeyEvent(false)
46 , m_fakeKeyEventTimer(this, &InputMethodContextEfl::fakeKeyEventTimerFired)
49 #if !ENABLE(TIZEN_ISF_PORT)
51 ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
52 ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
56 InputMethodContextEfl::~InputMethodContextEfl()
60 #if ENABLE(TIZEN_ISF_PORT)
61 void InputMethodContextEfl::onIMFInputPanelStateChanged(void* data, Ecore_IMF_Context*, int state)
63 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
65 inputMethodContext->setState(state);
67 if (state == ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
68 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
69 if (inputMethodContext->m_viewImpl->pageClient->isClipboardWindowOpened())
70 inputMethodContext->m_viewImpl->pageClient->closeClipboardWindow();
72 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,ime,closed", 0);
73 } else if (state == ECORE_IMF_INPUT_PANEL_STATE_SHOW)
74 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,ime,opened", 0);
77 void InputMethodContextEfl::onIMFInputPanelGeometryChanged(void* data, Ecore_IMF_Context*, int)
79 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
80 if (!inputMethodContext->m_context)
84 ecore_imf_context_input_panel_geometry_get(inputMethodContext->m_context.get(), &rect.x, &rect.y, &rect.w, &rect.h);
85 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "inputmethod,changed", &rect);
87 inputMethodContext->setIMERect(IntRect(rect.x, rect.y, rect.w, rect.h));
90 void InputMethodContextEfl::onIMFCandidatePanelStateChanged(void* data, Ecore_IMF_Context*, int state)
92 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
94 if (state == ECORE_IMF_CANDIDATE_PANEL_SHOW)
95 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,opened", 0);
97 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,closed", 0);
100 void InputMethodContextEfl::onIMFCandidatePanelGeometryChanged(void* data, Ecore_IMF_Context*, int)
102 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
103 if (!inputMethodContext->m_context)
107 ecore_imf_context_candidate_panel_geometry_get(inputMethodContext->m_context.get(), &rect.x, &rect.y, &rect.w, &rect.h);
108 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,changed", &rect);
111 Eina_Bool InputMethodContextEfl::onIMFRetrieveSurrounding(void* data, Ecore_IMF_Context*, char** text, int* offset)
113 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
114 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused || (!text && !offset))
117 String surroundingText;
119 inputMethodContext->m_viewImpl->page()->getSurroundingTextAndCursorOffset(surroundingText, cursorOffset);
122 CString utf8Text(surroundingText.utf8());
123 size_t length = utf8Text.length();
125 *text = static_cast<char*>(malloc((length + 1) * sizeof(char)));
130 strncpy(*text, utf8Text.data(), length);
135 *offset = cursorOffset;
140 void InputMethodContextEfl::onIMFDeleteSurrounding(void* data, Ecore_IMF_Context*, void* eventInfo)
142 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
143 if (!eventInfo || !inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
146 inputMethodContext->requestFakeKeyEvent();
148 Ecore_IMF_Event_Delete_Surrounding* event = static_cast<Ecore_IMF_Event_Delete_Surrounding*>(eventInfo);
149 inputMethodContext->m_viewImpl->page()->deleteSurroundingText(event->offset, event->n_chars);
152 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
154 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
155 if (!eventInfo || !inputMethodContext->m_focused)
158 inputMethodContext->requestFakeKeyEvent();
160 inputMethodContext->m_viewImpl->page()->confirmComposition(String::fromUTF8(static_cast<char*>(eventInfo)));
163 #if ENABLE(TIZEN_WEBKIT2_SUPPORT_JAPANESE_IME)
164 unsigned getUTF8CharacterIndex(const char* string, unsigned byteIndex)
167 const char* end = string + byteIndex;
169 while (*string && string < end) {
172 if ((*string & 0x80) == 0x00)
174 else if ((*string & 0xe0) == 0xc0)
176 else if ((*string & 0xf0) == 0xe0)
178 else if ((*string & 0xf8) == 0xf0)
180 else if ((*string & 0xfc) == 0xf8)
182 else if ((*string & 0xfe) == 0xfc)
188 while (*string && offset--)
196 void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context* context, void*)
198 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
200 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
203 WebPageProxy* page = inputMethodContext->m_viewImpl->page();
204 if (!page->focusedFrame())
207 inputMethodContext->requestFakeKeyEvent();
209 PageClientImpl* pageClient = inputMethodContext->m_viewImpl->pageClient.get();
211 page->getCaretPosition(caretRect);
212 caretRect.scale(pageClient->scaleFactor());
215 evas_object_geometry_get(inputMethodContext->m_viewImpl->view(), &viewX, &viewY, 0, 0);
217 int x = caretRect.x() - pageClient->scrollPosition().x() + viewX;
218 int y = caretRect.y() - pageClient->scrollPosition().y() + viewY;
219 int w = caretRect.width();
220 int h = caretRect.height();
221 ecore_imf_context_cursor_location_set(context, x, y, w, h);
224 Eina_List* preeditAttrs = 0;
225 int cursorPosition = 0;
227 ecore_imf_context_preedit_string_with_attributes_get(context, &buffer, &preeditAttrs, &cursorPosition);
229 String preeditString = String::fromUTF8(buffer);
230 Vector<CompositionUnderline> underlines;
234 #if ENABLE(TIZEN_WEBKIT2_SUPPORT_JAPANESE_IME)
235 Eina_List* listIterator = 0;
236 EINA_LIST_FOREACH(preeditAttrs, listIterator, item) {
237 Ecore_IMF_Preedit_Attr* preeditAttr = static_cast<Ecore_IMF_Preedit_Attr*>(item);
239 unsigned startIndex = getUTF8CharacterIndex(buffer, preeditAttr->start_index);
240 unsigned endIndex = getUTF8CharacterIndex(buffer, preeditAttr->end_index);
241 switch (preeditAttr->preedit_type) {
242 case ECORE_IMF_PREEDIT_TYPE_SUB1:
243 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), false));
245 case ECORE_IMF_PREEDIT_TYPE_SUB2:
246 case ECORE_IMF_PREEDIT_TYPE_SUB3:
247 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(255, 255, 255), false));
249 case ECORE_IMF_PREEDIT_TYPE_SUB4:
250 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(46, 168, 255), false));
252 case ECORE_IMF_PREEDIT_TYPE_SUB5:
253 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(153, 98, 195), false));
255 case ECORE_IMF_PREEDIT_TYPE_SUB6:
256 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(118, 222, 55), false));
258 case ECORE_IMF_PREEDIT_TYPE_SUB7:
259 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(153, 153, 153), false));
266 EINA_LIST_FREE(preeditAttrs, item)
270 if (underlines.isEmpty())
271 underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false));
273 page->setComposition(preeditString, underlines, cursorPosition);
279 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
281 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
282 if (!eventInfo || !inputMethodContext->m_focused)
285 inputMethodContext->m_viewImpl->page()->confirmComposition(String::fromUTF8(static_cast<char*>(eventInfo)));
288 void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context* context, void*)
290 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
292 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
296 ecore_imf_context_preedit_string_get(context, &buffer, 0);
300 String preeditString = String::fromUTF8(buffer);
302 Vector<CompositionUnderline> underlines;
303 underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false));
304 inputMethodContext->m_viewImpl->page()->setComposition(preeditString, underlines, 0);
308 PassOwnPtr<Ecore_IMF_Context> InputMethodContextEfl::createIMFContext(Evas* canvas)
310 const char* defaultContextID = ecore_imf_context_default_id_get();
311 if (!defaultContextID)
314 OwnPtr<Ecore_IMF_Context> imfContext = adoptPtr(ecore_imf_context_add(defaultContextID));
318 Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(canvas);
319 ecore_imf_context_client_window_set(imfContext.get(), reinterpret_cast<void*>(ecore_evas_window_get(ecoreEvas)));
320 ecore_imf_context_client_canvas_set(imfContext.get(), canvas);
322 return imfContext.release();
325 void InputMethodContextEfl::handleMouseUpEvent(const Evas_Event_Mouse_Up*)
327 #if ENABLE(TIZEN_ISF_PORT)
333 ecore_imf_context_reset(m_context.get());
337 void InputMethodContextEfl::handleKeyDownEvent(const Evas_Event_Key_Down* downEvent, bool* isFiltered)
339 #if ENABLE(TIZEN_ISF_PORT)
343 if (m_fakeKeyEventTimer.isActive())
344 m_fakeKeyEventTimer.stop();
346 m_viewImpl->page()->prepareKeyDownEvent();
348 m_doNotHandleFakeKeyEvent = true;
351 Ecore_IMF_Event inputMethodEvent;
352 ecore_imf_evas_event_key_down_wrap(const_cast<Evas_Event_Key_Down*>(downEvent), &inputMethodEvent.key_down);
354 *isFiltered = ecore_imf_context_filter_event(m_context.get(), ECORE_IMF_EVENT_KEY_DOWN, &inputMethodEvent);
356 #if ENABLE(TIZEN_ISF_PORT)
357 m_doNotHandleFakeKeyEvent = false;
361 #if ENABLE(TIZEN_ISF_PORT)
362 void InputMethodContextEfl::updateTextInputState()
364 const EditorState& editor = m_viewImpl->page()->editorState();
365 if (editor.shouldIgnoreCompositionSelectionChange || editor.updateEditorRectOnly)
368 if (editor.isContentEditable)
369 showIMFContext(editor);
374 ecore_imf_context_cursor_position_set(m_context.get(), editor.cursorPosition);
377 void InputMethodContextEfl::updateTextInputState()
382 const EditorState& editor = m_viewImpl->page()->editorState();
384 if (editor.isContentEditable) {
388 ecore_imf_context_reset(m_context.get());
389 ecore_imf_context_focus_in(m_context.get());
395 if (editor.hasComposition)
396 m_viewImpl->page()->cancelComposition();
399 ecore_imf_context_reset(m_context.get());
400 ecore_imf_context_focus_out(m_context.get());
405 #if ENABLE(TIZEN_ISF_PORT)
406 void InputMethodContextEfl::initializeIMFContext(Ecore_IMF_Context* context, Ecore_IMF_Input_Panel_Layout layout, int layoutVariation, Ecore_IMF_Input_Panel_Return_Key_Type returnKeyType)
408 ecore_imf_context_input_panel_enabled_set(context, false);
409 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_INPUT_PANEL_STATE_EVENT, onIMFInputPanelStateChanged, this);
410 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, onIMFInputPanelGeometryChanged, this);
411 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, onIMFCandidatePanelStateChanged, this);
412 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, onIMFCandidatePanelGeometryChanged, this);
413 ecore_imf_context_retrieve_surrounding_callback_set(context, onIMFRetrieveSurrounding, this);
414 ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, onIMFDeleteSurrounding, this);
415 ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
416 ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
418 ecore_imf_context_input_panel_layout_set(context, layout);
419 if (layoutVariation >= 0)
420 ecore_imf_context_input_panel_layout_variation_set(context, layoutVariation);
421 ecore_imf_context_input_panel_return_key_type_set(context, returnKeyType);
424 PassOwnPtr<Ecore_IMF_Context> InputMethodContextEfl::takeContext(uintptr_t contextID)
426 size_t i = m_contextList.size();
429 if (m_contextList[i].first == contextID) {
430 PassOwnPtr<Ecore_IMF_Context> context = m_contextList[i].second.release();
431 m_contextList.remove(i);
436 return PassOwnPtr<Ecore_IMF_Context>();
439 void InputMethodContextEfl::setIMFContext(const EditorState& editor)
441 const String& type = editor.inputMethodHints;
442 Ecore_IMF_Input_Panel_Layout layout;
443 int layoutVariation = -1;
444 Ecore_IMF_Input_Panel_Return_Key_Type returnKeyType = ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
446 if (type == "number") {
447 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
448 layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_NORMAL;
449 } else if (type == "signedNumber") {
450 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
451 layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED;
452 } else if (type == "decimalNumber") {
453 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
454 layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL;
455 } else if (type == "signedDecimalNumber") {
456 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
457 layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL;
458 } else if (type == "email")
459 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
460 else if (type == "url")
461 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
462 else if (type == "tel")
463 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
464 else if (type == "password")
465 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
467 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
468 if (type == "search")
469 returnKeyType = ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH;
472 OwnPtr<Ecore_IMF_Context> context;
473 if (m_contextID == editor.inputMethodContextID)
474 context = m_context.release();
476 context = takeContext(editor.inputMethodContextID);
481 context = createIMFContext(evas_object_evas_get(m_viewImpl->view()));
484 initializeIMFContext(context.get(), layout, layoutVariation, returnKeyType);
487 m_context = context.release();
488 m_contextID = editor.inputMethodContextID;
490 if (type == "password" || type == "plugin")
491 ecore_imf_context_prediction_allow_set(m_context.get(), false);
493 ecore_imf_context_prediction_allow_set(m_context.get(), true);
495 if (type.isEmpty() || type == "textarea")
496 ecore_imf_context_autocapital_type_set(m_context.get(), ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE);
498 ecore_imf_context_autocapital_type_set(m_context.get(), ECORE_IMF_AUTOCAPITAL_TYPE_NONE);
501 bool InputMethodContextEfl::isShow()
503 return (m_context && m_focused && ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE);
506 Ecore_IMF_Autocapital_Type InputMethodContextEfl::autoCapitalType()
508 return (m_context ? ecore_imf_context_autocapital_type_get(m_context.get()) : ECORE_IMF_AUTOCAPITAL_TYPE_NONE);
511 void InputMethodContextEfl::onFocusIn()
513 if (m_inputPickerType >= 0) {
514 showInputPicker(m_viewImpl->page()->editorState());
518 if (!m_context || !m_focused)
521 ecore_imf_context_focus_in(m_context.get());
522 ecore_imf_context_input_panel_show(m_context.get());
524 setKeyboardMode(true);
527 void InputMethodContextEfl::onFocusOut()
529 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
530 if (m_state != ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
531 if (m_viewImpl->pageClient->isClipboardWindowOpened())
532 m_viewImpl->pageClient->closeClipboardWindow();
536 if (!m_context || !m_focused)
539 ecore_imf_context_input_panel_hide(m_context.get());
540 ecore_imf_context_focus_out(m_context.get());
542 setKeyboardMode(false);
545 void InputMethodContextEfl::revertIMFContext()
550 if (m_contextList.size() >= maxContextSize)
551 m_contextList.remove(0);
553 PassOwnPtr<Ecore_IMF_Context> imfContext = m_context.release();
554 m_contextList.append(std::make_pair(m_contextID, imfContext));
558 void InputMethodContextEfl::resetIMFContext()
563 m_doNotHandleFakeKeyEvent = true;
564 ecore_imf_context_reset(m_context.get());
565 m_doNotHandleFakeKeyEvent = false;
568 void InputMethodContextEfl::showIMFContext(const EditorState& editor)
570 Ewk_Settings* settings = ewk_view_settings_get(m_viewImpl->view());
571 if (!editor.isTapEventHandling) {
572 if (!ewk_settings_uses_keypad_without_user_action_get(settings) || (m_focused && m_contextID == editor.inputMethodContextID))
578 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
579 if (editor.inputMethodHints == "date")
580 m_inputPickerType = EWK_INPUT_TYPE_DATE;
581 else if (editor.inputMethodHints == "datetime")
582 m_inputPickerType = EWK_INPUT_TYPE_DATETIME;
583 else if (editor.inputMethodHints == "datetime-local")
584 m_inputPickerType = EWK_INPUT_TYPE_DATETIMELOCAL;
585 else if (editor.inputMethodHints == "month")
586 m_inputPickerType = EWK_INPUT_TYPE_MONTH;
587 else if (editor.inputMethodHints == "time")
588 m_inputPickerType = EWK_INPUT_TYPE_TIME;
589 else if (editor.inputMethodHints == "week")
590 m_inputPickerType = EWK_INPUT_TYPE_WEEK;
592 m_inputPickerType = -1;
594 if (m_inputPickerType >= 0) {
595 showInputPicker(editor);
597 m_contextID = editor.inputMethodContextID;
602 #if ENABLE(TIZEN_DATALIST_ELEMENT)
603 Vector<String> optionList = m_viewImpl->page()->getFocusedInputElementDataList();
604 if (optionList.size() > 0) {
605 if (editor.selectionIsRange || !evas_object_focus_get(m_viewImpl->view()))
608 if (editor.inputMethodHints == "tel")
609 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_TELEPHONE, optionList);
610 else if (editor.inputMethodHints == "number")
611 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_NUMBER, optionList);
612 else if (editor.inputMethodHints == "email")
613 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_EMAIL, optionList);
614 else if (editor.inputMethodHints == "url")
615 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_URL, optionList);
617 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_TEXT, optionList);
620 m_contextID = editor.inputMethodContextID;
625 #endif // ENABLE(TIZEN_INPUT_TAG_EXTENSION)
627 bool hasFocus = evas_object_focus_get(m_viewImpl->view());
629 if (!ewk_settings_default_keypad_enabled_get(settings)) {
631 Eina_Rectangle dummyRectForCustomKeypadCallback;
632 memset(&dummyRectForCustomKeypadCallback, 0, sizeof(Eina_Rectangle));
633 evas_object_smart_callback_call(m_viewImpl->view(), "inputmethod,changed", &dummyRectForCustomKeypadCallback);
638 setIMFContext(editor);
645 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
646 if (m_viewImpl->pageClient->isClipboardWindowOpened())
647 m_viewImpl->pageClient->closeClipboardWindow();
651 ecore_imf_context_focus_in(m_context.get());
652 ecore_imf_context_input_panel_show(m_context.get());
654 // input field zoom for external keyboard
655 ewk_view_focused_node_adjust(m_viewImpl->view(), EINA_TRUE);
657 setKeyboardMode(true);
660 void InputMethodContextEfl::hideIMFContext()
662 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
663 if (m_state != ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
664 if (m_viewImpl->pageClient->isClipboardWindowOpened())
665 m_viewImpl->pageClient->closeClipboardWindow();
669 m_inputPickerType = -1;
671 if (!m_context || !m_focused)
674 if (ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE
675 && evas_object_focus_get(m_viewImpl->view())) {
677 ecore_imf_context_input_panel_hide(m_context.get());
678 ecore_imf_context_focus_out(m_context.get());
681 setKeyboardMode(false);
687 void InputMethodContextEfl::destroyIMFContextList()
689 m_contextList.clear();
692 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
693 void InputMethodContextEfl::showInputPicker(const EditorState& editorState)
695 if (editorState.selectionIsRange || !evas_object_focus_get(m_viewImpl->view()))
698 ewkViewInputPickerRequest(m_viewImpl->view(), static_cast<Ewk_Input_Type>(m_inputPickerType), editorState.surroundingText);
699 m_inputPickerType = -1;
703 bool InputMethodContextEfl::isIMEPostion(int x, int y)
705 if (m_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW)
706 return m_imeRect.contains(x, y);
711 void InputMethodContextEfl::removeIMFContext(uintptr_t contextID)
713 if (m_contextID == contextID)
716 takeContext(contextID);
719 void InputMethodContextEfl::setKeyboardMode(bool isOn)
721 Evas_Object* parent = elm_object_parent_widget_get(m_viewImpl->view());
723 const char* type = elm_object_widget_type_get(parent);
724 if (type && !strcmp(type, "elm_win")) {
725 elm_win_keyboard_mode_set(parent, isOn ? ELM_WIN_KEYBOARD_ON : ELM_WIN_KEYBOARD_OFF);
729 parent = elm_object_parent_widget_get(parent);
733 void InputMethodContextEfl::requestFakeKeyEvent()
735 if (m_doNotHandleFakeKeyEvent || m_fakeKeyEventTimer.isActive())
738 m_fakeKeyEventTimer.startOneShot(0);
739 m_viewImpl->page()->prepareKeyDownEvent();
742 void InputMethodContextEfl::fakeKeyEventTimerFired(WebCore::Timer<InputMethodContextEfl>*)
744 const char* text = " ";
746 Evas_Event_Key_Down downEvent;
747 memset(&downEvent, 0, sizeof(Evas_Event_Key_Down));
748 downEvent.key = text;
749 downEvent.string = text;
750 m_viewImpl->page()->handleKeyboardEvent(NativeWebKeyboardEvent(&downEvent, true));
752 Evas_Event_Key_Up upEvent;
753 memset(&upEvent, 0, sizeof(Evas_Event_Key_Up));
755 upEvent.string = text;
756 m_viewImpl->page()->handleKeyboardEvent(NativeWebKeyboardEvent(&upEvent));
758 #endif // #if ENABLE(TIZEN_ISF_PORT)