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;
35 Ecore_X_Atom InputMethodContextEfl::s_externalKeyboardProperty = 0;
36 bool InputMethodContextEfl::s_shouldUseExternalKeyboard = false;
38 void InputMethodContextEfl::initializeExternalKeyboard()
40 s_externalKeyboardProperty = ecore_x_atom_get("X External Keyboard Exist");
41 if (!s_externalKeyboardProperty)
44 Ecore_X_Window rootWin = ecore_x_window_root_first_get();
45 ecore_x_event_mask_set(rootWin, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
47 ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, windowPropertyChanged, 0);
50 if (ecore_x_window_prop_card32_get(rootWin, s_externalKeyboardProperty, &value, 1) <= 0)
53 s_shouldUseExternalKeyboard = value;
56 Eina_Bool InputMethodContextEfl::windowPropertyChanged(void*, int, void* event)
58 Ecore_X_Event_Window_Property* propertyEvent = static_cast<Ecore_X_Event_Window_Property*>(event);
60 if (propertyEvent->atom != s_externalKeyboardProperty)
61 return ECORE_CALLBACK_PASS_ON;
64 if (ecore_x_window_prop_card32_get(propertyEvent->win, s_externalKeyboardProperty, &value, 1) <= 0 || s_shouldUseExternalKeyboard == value)
65 return ECORE_CALLBACK_PASS_ON;
67 s_shouldUseExternalKeyboard = value;
69 #if ENABLE(TIZEN_FOCUS_UI)
70 if (!s_shouldUseExternalKeyboard) {
71 Vector<RefPtr<WebPageProxy> > pages;
72 EwkViewImpl::pages(pages);
74 for (size_t i = 0; i < pages.size(); ++i)
75 pages[i]->setSpatialNavigationEnabled(false);
79 return ECORE_CALLBACK_PASS_ON;
83 InputMethodContextEfl::InputMethodContextEfl(EwkViewImpl* viewImpl, PassOwnPtr<Ecore_IMF_Context> context)
84 : m_viewImpl(viewImpl)
87 #if ENABLE(TIZEN_ISF_PORT)
89 , m_state(ECORE_IMF_INPUT_PANEL_STATE_HIDE)
90 , m_inputPickerType(-1)
91 , m_doNotHandleFakeKeyEvent(false)
92 , m_fakeKeyEventTimer(this, &InputMethodContextEfl::fakeKeyEventTimerFired)
95 #if ENABLE(TIZEN_ISF_PORT)
96 if (!s_externalKeyboardProperty)
97 initializeExternalKeyboard();
100 ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
101 ecore_imf_context_event_callback_add(m_context.get(), ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
105 InputMethodContextEfl::~InputMethodContextEfl()
109 #if ENABLE(TIZEN_ISF_PORT)
110 void InputMethodContextEfl::onIMFInputPanelStateChanged(void* data, Ecore_IMF_Context*, int state)
112 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
114 inputMethodContext->setState(state);
116 if (state == ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
117 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
118 if (inputMethodContext->m_viewImpl->pageClient->isClipboardWindowOpened())
119 inputMethodContext->m_viewImpl->pageClient->closeClipboardWindow();
121 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,ime,closed", 0);
122 } else if (state == ECORE_IMF_INPUT_PANEL_STATE_SHOW)
123 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,ime,opened", 0);
126 void InputMethodContextEfl::onIMFInputPanelGeometryChanged(void* data, Ecore_IMF_Context*, int)
128 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
129 if (!inputMethodContext->m_context)
133 ecore_imf_context_input_panel_geometry_get(inputMethodContext->m_context.get(), &rect.x, &rect.y, &rect.w, &rect.h);
134 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "inputmethod,changed", &rect);
136 inputMethodContext->setIMERect(IntRect(rect.x, rect.y, rect.w, rect.h));
139 void InputMethodContextEfl::onIMFCandidatePanelStateChanged(void* data, Ecore_IMF_Context*, int state)
141 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
143 if (state == ECORE_IMF_CANDIDATE_PANEL_SHOW)
144 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,opened", 0);
146 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,closed", 0);
149 void InputMethodContextEfl::onIMFCandidatePanelGeometryChanged(void* data, Ecore_IMF_Context*, int)
151 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
152 if (!inputMethodContext->m_context)
156 ecore_imf_context_candidate_panel_geometry_get(inputMethodContext->m_context.get(), &rect.x, &rect.y, &rect.w, &rect.h);
157 evas_object_smart_callback_call(inputMethodContext->m_viewImpl->view(), "editorclient,candidate,changed", &rect);
160 Eina_Bool InputMethodContextEfl::onIMFRetrieveSurrounding(void* data, Ecore_IMF_Context*, char** text, int* offset)
162 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
163 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused || (!text && !offset))
166 String surroundingText;
168 inputMethodContext->m_viewImpl->page()->getSurroundingTextAndCursorOffset(surroundingText, cursorOffset);
171 CString utf8Text(surroundingText.utf8());
172 size_t length = utf8Text.length();
174 *text = static_cast<char*>(malloc((length + 1) * sizeof(char)));
179 strncpy(*text, utf8Text.data(), length);
184 *offset = cursorOffset;
189 void InputMethodContextEfl::onIMFDeleteSurrounding(void* data, Ecore_IMF_Context*, void* eventInfo)
191 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
192 if (!eventInfo || !inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
195 inputMethodContext->requestFakeKeyEvent();
197 Ecore_IMF_Event_Delete_Surrounding* event = static_cast<Ecore_IMF_Event_Delete_Surrounding*>(eventInfo);
198 inputMethodContext->m_viewImpl->page()->deleteSurroundingText(event->offset, event->n_chars);
201 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
203 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
204 if (!eventInfo || !inputMethodContext->m_focused)
207 inputMethodContext->requestFakeKeyEvent();
209 inputMethodContext->m_viewImpl->page()->confirmComposition(String::fromUTF8(static_cast<char*>(eventInfo)));
212 #if ENABLE(TIZEN_WEBKIT2_SUPPORT_JAPANESE_IME)
213 unsigned getUTF8CharacterIndex(const char* string, unsigned byteIndex)
216 const char* end = string + byteIndex;
218 while (*string && string < end) {
221 if ((*string & 0x80) == 0x00)
223 else if ((*string & 0xe0) == 0xc0)
225 else if ((*string & 0xf0) == 0xe0)
227 else if ((*string & 0xf8) == 0xf0)
229 else if ((*string & 0xfc) == 0xf8)
231 else if ((*string & 0xfe) == 0xfc)
237 while (*string && offset--)
245 void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context* context, void*)
247 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
249 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
252 WebPageProxy* page = inputMethodContext->m_viewImpl->page();
253 if (!page->focusedFrame())
256 inputMethodContext->requestFakeKeyEvent();
258 PageClientImpl* pageClient = inputMethodContext->m_viewImpl->pageClient.get();
260 page->getCaretPosition(caretRect);
261 caretRect.scale(pageClient->scaleFactor());
264 evas_object_geometry_get(inputMethodContext->m_viewImpl->view(), &viewX, &viewY, 0, 0);
266 int x = caretRect.x() - pageClient->scrollPosition().x() + viewX;
267 int y = caretRect.y() - pageClient->scrollPosition().y() + viewY;
268 int w = caretRect.width();
269 int h = caretRect.height();
270 ecore_imf_context_cursor_location_set(context, x, y, w, h);
273 Eina_List* preeditAttrs = 0;
274 int cursorPosition = 0;
276 ecore_imf_context_preedit_string_with_attributes_get(context, &buffer, &preeditAttrs, &cursorPosition);
278 String preeditString = String::fromUTF8(buffer);
279 Vector<CompositionUnderline> underlines;
283 #if ENABLE(TIZEN_WEBKIT2_SUPPORT_JAPANESE_IME)
284 Eina_List* listIterator = 0;
285 EINA_LIST_FOREACH(preeditAttrs, listIterator, item) {
286 Ecore_IMF_Preedit_Attr* preeditAttr = static_cast<Ecore_IMF_Preedit_Attr*>(item);
288 unsigned startIndex = getUTF8CharacterIndex(buffer, preeditAttr->start_index);
289 unsigned endIndex = getUTF8CharacterIndex(buffer, preeditAttr->end_index);
290 switch (preeditAttr->preedit_type) {
291 case ECORE_IMF_PREEDIT_TYPE_SUB1:
292 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), false));
294 case ECORE_IMF_PREEDIT_TYPE_SUB2:
295 case ECORE_IMF_PREEDIT_TYPE_SUB3:
296 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(255, 255, 255), false));
298 case ECORE_IMF_PREEDIT_TYPE_SUB4:
299 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(46, 168, 255), false));
301 case ECORE_IMF_PREEDIT_TYPE_SUB5:
302 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(153, 98, 195), false));
304 case ECORE_IMF_PREEDIT_TYPE_SUB6:
305 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(118, 222, 55), false));
307 case ECORE_IMF_PREEDIT_TYPE_SUB7:
308 underlines.append(CompositionUnderline(startIndex, endIndex, Color(0, 0, 0), Color(153, 153, 153), false));
315 EINA_LIST_FREE(preeditAttrs, item)
319 if (underlines.isEmpty())
320 underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false));
322 page->setComposition(preeditString, underlines, cursorPosition);
328 void InputMethodContextEfl::onIMFInputSequenceComplete(void* data, Ecore_IMF_Context*, void* eventInfo)
330 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
331 if (!eventInfo || !inputMethodContext->m_focused)
334 inputMethodContext->m_viewImpl->page()->confirmComposition(String::fromUTF8(static_cast<char*>(eventInfo)));
337 void InputMethodContextEfl::onIMFPreeditSequenceChanged(void* data, Ecore_IMF_Context* context, void*)
339 InputMethodContextEfl* inputMethodContext = static_cast<InputMethodContextEfl*>(data);
341 if (!inputMethodContext->m_viewImpl->page()->focusedFrame() || !inputMethodContext->m_focused)
345 ecore_imf_context_preedit_string_get(context, &buffer, 0);
349 String preeditString = String::fromUTF8(buffer);
351 Vector<CompositionUnderline> underlines;
352 underlines.append(CompositionUnderline(0, preeditString.length(), Color(0, 0, 0), false));
353 inputMethodContext->m_viewImpl->page()->setComposition(preeditString, underlines, 0);
357 PassOwnPtr<Ecore_IMF_Context> InputMethodContextEfl::createIMFContext(Evas* canvas)
359 const char* defaultContextID = ecore_imf_context_default_id_get();
360 if (!defaultContextID)
363 OwnPtr<Ecore_IMF_Context> imfContext = adoptPtr(ecore_imf_context_add(defaultContextID));
367 Ecore_Evas* ecoreEvas = ecore_evas_ecore_evas_get(canvas);
368 ecore_imf_context_client_window_set(imfContext.get(), reinterpret_cast<void*>(ecore_evas_window_get(ecoreEvas)));
369 ecore_imf_context_client_canvas_set(imfContext.get(), canvas);
371 return imfContext.release();
374 void InputMethodContextEfl::handleMouseUpEvent(const Evas_Event_Mouse_Up*)
376 #if ENABLE(TIZEN_ISF_PORT)
382 ecore_imf_context_reset(m_context.get());
386 void InputMethodContextEfl::handleKeyDownEvent(const Evas_Event_Key_Down* downEvent, bool* isFiltered)
388 #if ENABLE(TIZEN_FOCUS_UI)
389 if (s_shouldUseExternalKeyboard)
390 m_viewImpl->page()->setSpatialNavigationEnabled(true);
393 #if ENABLE(TIZEN_ISF_PORT)
397 if (m_fakeKeyEventTimer.isActive())
398 m_fakeKeyEventTimer.stop();
400 m_viewImpl->page()->prepareKeyDownEvent();
402 m_doNotHandleFakeKeyEvent = true;
405 Ecore_IMF_Event inputMethodEvent;
406 ecore_imf_evas_event_key_down_wrap(const_cast<Evas_Event_Key_Down*>(downEvent), &inputMethodEvent.key_down);
408 *isFiltered = ecore_imf_context_filter_event(m_context.get(), ECORE_IMF_EVENT_KEY_DOWN, &inputMethodEvent);
410 #if ENABLE(TIZEN_ISF_PORT)
411 m_doNotHandleFakeKeyEvent = false;
415 #if ENABLE(TIZEN_ISF_PORT)
416 void InputMethodContextEfl::updateTextInputState()
418 const EditorState& editor = m_viewImpl->page()->editorState();
419 if (editor.shouldIgnoreCompositionSelectionChange || editor.updateEditorRectOnly)
422 if (editor.isContentEditable)
423 showIMFContext(editor);
428 ecore_imf_context_cursor_position_set(m_context.get(), editor.cursorPosition);
431 void InputMethodContextEfl::updateTextInputStateByUserAction(bool setFocus)
433 const EditorState& editor = m_viewImpl->page()->editorState();
435 if (editor.isContentEditable) {
437 evas_object_focus_set(m_viewImpl->view(), true);
439 showIMFContext(editor, true);
444 void InputMethodContextEfl::updateTextInputState()
449 const EditorState& editor = m_viewImpl->page()->editorState();
451 if (editor.isContentEditable) {
455 ecore_imf_context_reset(m_context.get());
456 ecore_imf_context_focus_in(m_context.get());
462 if (editor.hasComposition)
463 m_viewImpl->page()->cancelComposition();
466 ecore_imf_context_reset(m_context.get());
467 ecore_imf_context_focus_out(m_context.get());
472 #if ENABLE(TIZEN_ISF_PORT)
473 void InputMethodContextEfl::initializeIMFContext(Ecore_IMF_Context* context, Ecore_IMF_Input_Panel_Layout layout, int layoutVariation, Ecore_IMF_Input_Panel_Return_Key_Type returnKeyType)
475 ecore_imf_context_input_panel_enabled_set(context, false);
476 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_INPUT_PANEL_STATE_EVENT, onIMFInputPanelStateChanged, this);
477 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, onIMFInputPanelGeometryChanged, this);
478 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, onIMFCandidatePanelStateChanged, this);
479 ecore_imf_context_input_panel_event_callback_add(context, ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, onIMFCandidatePanelGeometryChanged, this);
480 ecore_imf_context_retrieve_surrounding_callback_set(context, onIMFRetrieveSurrounding, this);
481 ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, onIMFDeleteSurrounding, this);
482 ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, onIMFPreeditSequenceChanged, this);
483 ecore_imf_context_event_callback_add(context, ECORE_IMF_CALLBACK_COMMIT, onIMFInputSequenceComplete, this);
485 ecore_imf_context_input_panel_layout_set(context, layout);
486 if (layoutVariation >= 0)
487 ecore_imf_context_input_panel_layout_variation_set(context, layoutVariation);
488 ecore_imf_context_input_panel_return_key_type_set(context, returnKeyType);
491 PassOwnPtr<Ecore_IMF_Context> InputMethodContextEfl::takeContext(uintptr_t contextID)
493 size_t i = m_contextList.size();
496 if (m_contextList[i].first == contextID) {
497 PassOwnPtr<Ecore_IMF_Context> context = m_contextList[i].second.release();
498 m_contextList.remove(i);
503 return PassOwnPtr<Ecore_IMF_Context>();
506 void InputMethodContextEfl::setIMFContext(const EditorState& editor)
508 const String& type = editor.inputMethodHints;
509 Ecore_IMF_Input_Panel_Layout layout;
510 int layoutVariation = -1;
511 Ecore_IMF_Input_Panel_Return_Key_Type returnKeyType = ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
513 if (type == "number") {
514 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
515 layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_NORMAL;
516 } else if (type == "signedNumber") {
517 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
518 layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED;
519 } else if (type == "decimalNumber") {
520 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
521 layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL;
522 } else if (type == "signedDecimalNumber") {
523 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
524 layoutVariation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL;
525 } else if (type == "email")
526 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
527 else if (type == "url")
528 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
529 else if (type == "tel")
530 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
531 else if (type == "password")
532 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
534 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
535 if (type == "search")
536 returnKeyType = ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH;
539 OwnPtr<Ecore_IMF_Context> context;
540 if (m_contextID == editor.inputMethodContextID)
541 context = m_context.release();
543 context = takeContext(editor.inputMethodContextID);
548 context = createIMFContext(evas_object_evas_get(m_viewImpl->view()));
551 initializeIMFContext(context.get(), layout, layoutVariation, returnKeyType);
554 m_context = context.release();
555 m_contextID = editor.inputMethodContextID;
557 if (type == "password" || type == "plugin")
558 ecore_imf_context_prediction_allow_set(m_context.get(), false);
560 ecore_imf_context_prediction_allow_set(m_context.get(), true);
562 if (type.isEmpty() || type == "textarea")
563 ecore_imf_context_autocapital_type_set(m_context.get(), ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE);
565 ecore_imf_context_autocapital_type_set(m_context.get(), ECORE_IMF_AUTOCAPITAL_TYPE_NONE);
568 bool InputMethodContextEfl::isShow()
570 return (m_context && m_focused && ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE);
573 Ecore_IMF_Autocapital_Type InputMethodContextEfl::autoCapitalType()
575 return (m_context ? ecore_imf_context_autocapital_type_get(m_context.get()) : ECORE_IMF_AUTOCAPITAL_TYPE_NONE);
578 void InputMethodContextEfl::onFocusIn()
580 if (m_inputPickerType >= 0) {
581 showInputPicker(m_viewImpl->page()->editorState());
585 if (!m_context || !m_focused)
588 ecore_imf_context_focus_in(m_context.get());
589 ecore_imf_context_input_panel_show(m_context.get());
591 setKeyboardMode(true);
594 void InputMethodContextEfl::onFocusOut()
596 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
597 if (m_state != ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
598 if (m_viewImpl->pageClient->isClipboardWindowOpened())
599 m_viewImpl->pageClient->closeClipboardWindow();
603 if (!m_context || !m_focused)
606 ecore_imf_context_input_panel_hide(m_context.get());
607 ecore_imf_context_focus_out(m_context.get());
609 setKeyboardMode(false);
612 void InputMethodContextEfl::revertIMFContext()
617 if (m_contextList.size() >= maxContextSize)
618 m_contextList.remove(0);
620 PassOwnPtr<Ecore_IMF_Context> imfContext = m_context.release();
621 m_contextList.append(std::make_pair(m_contextID, imfContext));
625 void InputMethodContextEfl::resetIMFContext()
630 m_doNotHandleFakeKeyEvent = true;
631 ecore_imf_context_reset(m_context.get());
632 m_doNotHandleFakeKeyEvent = false;
635 void InputMethodContextEfl::showIMFContext(const EditorState& editor, bool isUserAction)
637 Ewk_Settings* settings = ewk_view_settings_get(m_viewImpl->view());
638 bool isContextTransition = (m_context ? m_contextID != editor.inputMethodContextID : m_state != ECORE_IMF_INPUT_PANEL_STATE_HIDE);
640 if (!isUserAction && !isContextTransition) {
641 if (!ewk_settings_uses_keypad_without_user_action_get(settings) || (m_focused && m_contextID == editor.inputMethodContextID))
645 if (m_contextID != editor.inputMethodContextID)
650 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
651 if (editor.inputMethodHints == "date")
652 m_inputPickerType = EWK_INPUT_TYPE_DATE;
653 else if (editor.inputMethodHints == "datetime")
654 m_inputPickerType = EWK_INPUT_TYPE_DATETIME;
655 else if (editor.inputMethodHints == "datetime-local")
656 m_inputPickerType = EWK_INPUT_TYPE_DATETIMELOCAL;
657 else if (editor.inputMethodHints == "month")
658 m_inputPickerType = EWK_INPUT_TYPE_MONTH;
659 else if (editor.inputMethodHints == "time")
660 m_inputPickerType = EWK_INPUT_TYPE_TIME;
661 else if (editor.inputMethodHints == "week")
662 m_inputPickerType = EWK_INPUT_TYPE_WEEK;
664 m_inputPickerType = -1;
666 if (m_inputPickerType >= 0) {
667 showInputPicker(editor);
668 m_contextID = editor.inputMethodContextID;
673 #if ENABLE(TIZEN_DATALIST_ELEMENT)
674 Vector<String> optionList = m_viewImpl->page()->getFocusedInputElementDataList();
675 if (optionList.size() > 0) {
676 if (editor.selectionIsRange || !evas_object_focus_get(m_viewImpl->view()))
679 if (editor.inputMethodHints == "tel")
680 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_TELEPHONE, optionList);
681 else if (editor.inputMethodHints == "number")
682 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_NUMBER, optionList);
683 else if (editor.inputMethodHints == "email")
684 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_EMAIL, optionList);
685 else if (editor.inputMethodHints == "url")
686 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_URL, optionList);
688 ewkViewDataListShowRequest(m_viewImpl->view(), EWK_INPUT_TYPE_TEXT, optionList);
690 m_contextID = editor.inputMethodContextID;
695 #endif // ENABLE(TIZEN_INPUT_TAG_EXTENSION)
697 bool hasFocus = evas_object_focus_get(m_viewImpl->view());
699 if (!ewk_settings_default_keypad_enabled_get(settings)) {
701 Eina_Rectangle dummyRectForCustomKeypadCallback;
702 memset(&dummyRectForCustomKeypadCallback, 0, sizeof(Eina_Rectangle));
703 evas_object_smart_callback_call(m_viewImpl->view(), "inputmethod,changed", &dummyRectForCustomKeypadCallback);
708 setIMFContext(editor);
715 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
716 if (m_viewImpl->pageClient->isClipboardWindowOpened())
717 m_viewImpl->pageClient->closeClipboardWindow();
721 ecore_imf_context_focus_in(m_context.get());
722 ecore_imf_context_input_panel_show(m_context.get());
724 // input field zoom for external keyboard
725 ewk_view_focused_node_adjust(m_viewImpl->view(), EINA_TRUE);
727 setKeyboardMode(true);
730 void InputMethodContextEfl::hideIMFContext()
732 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
733 if (m_state != ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
734 if (m_viewImpl->pageClient->isClipboardWindowOpened())
735 m_viewImpl->pageClient->closeClipboardWindow();
739 m_inputPickerType = -1;
741 if (!m_context || !m_focused)
744 if (ecore_imf_context_input_panel_state_get(m_context.get()) != ECORE_IMF_INPUT_PANEL_STATE_HIDE
745 && evas_object_focus_get(m_viewImpl->view())) {
747 ecore_imf_context_input_panel_hide(m_context.get());
748 ecore_imf_context_focus_out(m_context.get());
751 setKeyboardMode(false);
757 void InputMethodContextEfl::destroyIMFContextList()
759 m_contextList.clear();
762 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
763 void InputMethodContextEfl::showInputPicker(const EditorState& editorState)
765 if (editorState.selectionIsRange || !evas_object_focus_get(m_viewImpl->view()))
768 ewkViewInputPickerRequest(m_viewImpl->view(), static_cast<Ewk_Input_Type>(m_inputPickerType), editorState.surroundingText);
769 m_inputPickerType = -1;
773 bool InputMethodContextEfl::isIMEPostion(int x, int y)
775 if (m_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW)
776 return m_imeRect.contains(x, y);
781 void InputMethodContextEfl::removeIMFContext(uintptr_t contextID)
783 if (m_contextID == contextID)
786 takeContext(contextID);
789 void InputMethodContextEfl::setKeyboardMode(bool isOn)
791 Evas_Object* parent = elm_object_parent_widget_get(m_viewImpl->view());
793 const char* type = elm_object_widget_type_get(parent);
794 if (type && !strcmp(type, "elm_win")) {
795 elm_win_keyboard_mode_set(parent, isOn ? ELM_WIN_KEYBOARD_ON : ELM_WIN_KEYBOARD_OFF);
799 parent = elm_object_parent_widget_get(parent);
803 void InputMethodContextEfl::requestFakeKeyEvent()
805 if (m_doNotHandleFakeKeyEvent || m_fakeKeyEventTimer.isActive())
808 m_fakeKeyEventTimer.startOneShot(0);
809 m_viewImpl->page()->prepareKeyDownEvent();
812 void InputMethodContextEfl::fakeKeyEventTimerFired(WebCore::Timer<InputMethodContextEfl>*)
814 const char* text = " ";
816 Evas_Event_Key_Down downEvent;
817 memset(&downEvent, 0, sizeof(Evas_Event_Key_Down));
818 downEvent.key = text;
819 downEvent.string = text;
820 m_viewImpl->page()->handleKeyboardEvent(NativeWebKeyboardEvent(&downEvent, true));
822 Evas_Event_Key_Up upEvent;
823 memset(&upEvent, 0, sizeof(Evas_Event_Key_Up));
825 upEvent.string = text;
826 m_viewImpl->page()->handleKeyboardEvent(NativeWebKeyboardEvent(&upEvent));
828 #endif // #if ENABLE(TIZEN_ISF_PORT)