2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.h>
23 #include <Ecore_Input.h>
26 #include <Ecore_Wl2.h>
28 #include <Ecore_Wayland.h>
31 #include <dali/devel-api/common/singleton-service.h>
32 #include <dali/integration-api/debug.h>
33 #include <dali/public-api/adaptor-framework/key.h>
34 #include <dali/public-api/events/key-event.h>
35 #include <dali/public-api/object/type-registry.h>
38 #include <dali/integration-api/adaptor-framework/adaptor.h>
39 #include <dali/integration-api/adaptor-framework/scene-holder.h>
40 #include <dali/internal/input/common/key-impl.h>
41 #include <dali/internal/system/common/locale-utils.h>
42 #include <dali/internal/window-system/common/window-render-surface.h>
43 #include <dali/public-api/adaptor-framework/input-method.h>
45 Ecore_IMF_Input_Panel_Layout panelLayoutMap[] =
47 ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL,
48 ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER,
49 ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL,
50 ECORE_IMF_INPUT_PANEL_LAYOUT_URL,
51 ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER,
52 ECORE_IMF_INPUT_PANEL_LAYOUT_IP,
53 ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH,
54 ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY,
55 ECORE_IMF_INPUT_PANEL_LAYOUT_HEX,
56 ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL,
57 ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD,
58 ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME,
59 ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON,
60 ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE};
62 Ecore_IMF_Autocapital_Type autoCapitalMap[] =
64 ECORE_IMF_AUTOCAPITAL_TYPE_NONE,
65 ECORE_IMF_AUTOCAPITAL_TYPE_WORD,
66 ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE,
67 ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER,
70 Ecore_IMF_Input_Panel_Return_Key_Type returnKeyTypeMap[] =
72 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT,
73 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DONE,
74 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_GO,
75 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_JOIN,
76 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN,
77 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_NEXT,
78 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH,
79 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEND,
80 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN};
90 #if defined(DEBUG_ENABLED)
91 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_INPUT_METHOD_CONTEXT");
94 const int kUninitializedWindowId = 0;
96 // Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead.
97 size_t Utf8SequenceLength(const unsigned char leadByte)
101 if((leadByte & 0x80) == 0) //ASCII character (lead bit zero)
105 else if((leadByte & 0xe0) == 0xc0) //110x xxxx
109 else if((leadByte & 0xf0) == 0xe0) //1110 xxxx
113 else if((leadByte & 0xf8) == 0xf0) //1111 0xxx
117 else if((leadByte & 0xfc) == 0xf8) //1111 10xx
121 else if((leadByte & 0xfe) == 0xfc) //1111 110x
129 size_t GetNumberOfUtf8Characters(const char* utf8, size_t length)
131 size_t numberOfCharacters = 0u;
133 const uint8_t* begin = reinterpret_cast<const uint8_t*>(utf8);
134 const uint8_t* end = reinterpret_cast<const uint8_t*>(utf8 + length);
138 size_t sequenceLength = Utf8SequenceLength(static_cast<unsigned char>(*begin));
139 if(sequenceLength == 0u)
141 // Invalid case, return zero to avoid infinity loop.
144 begin += sequenceLength;
145 numberOfCharacters++;
147 return numberOfCharacters;
150 // Static function calls used by ecore 'c' style callback registration
151 void Commit(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
155 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
156 inputMethodContext->CommitReceived(data, imfContext, eventInfo);
160 void PreEdit(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
164 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
165 inputMethodContext->PreEditChanged(data, imfContext, eventInfo);
169 Eina_Bool ImfRetrieveSurrounding(void* data, Ecore_IMF_Context* imfContext, char** text, int* cursorPosition)
173 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
174 return inputMethodContext->RetrieveSurrounding(data, imfContext, text, cursorPosition);
182 void InputPanelStateChangeCallback(void* data, Ecore_IMF_Context* context, int value)
188 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
191 case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
193 inputMethodContext->StatusChangedSignal().Emit(true);
197 case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
199 inputMethodContext->StatusChangedSignal().Emit(false);
203 case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
212 void InputPanelLanguageChangeCallback(void* data, Ecore_IMF_Context* context, int value)
218 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
219 // Emit the signal that the language has changed
220 inputMethodContext->LanguageChangedSignal().Emit(value);
223 void InputPanelGeometryChangedCallback(void* data, Ecore_IMF_Context* context, int value)
229 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
230 // Emit signal that the keyboard is resized
231 inputMethodContext->ResizedSignal().Emit(value);
234 void InputPanelKeyboardTypeChangedCallback(void* data, Ecore_IMF_Context* context, int value)
241 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
244 case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE:
246 // Emit Signal that the keyboard type is changed to Software Keyboard
247 inputMethodContext->KeyboardTypeChangedSignal().Emit(Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD);
250 case ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE:
252 // Emit Signal that the keyboard type is changed to Hardware Keyboard
253 inputMethodContext->KeyboardTypeChangedSignal().Emit(Dali::InputMethodContext::KeyboardType::HARDWARE_KEYBOARD);
260 * Called when an IMF delete surrounding event is received.
261 * Here we tell the application that it should delete a certain range.
263 void ImfDeleteSurrounding(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
267 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
268 inputMethodContext->DeleteSurrounding(data, imfContext, eventInfo);
273 * Called when the input method sends a private command.
275 void PrivateCommand(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
279 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
280 inputMethodContext->SendPrivateCommand(data, imfContext, eventInfo);
285 * Called when the input method commits content, such as an image.
287 void CommitContent(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
291 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
292 inputMethodContext->SendCommitContent(data, imfContext, eventInfo);
297 * Called when the input method sends a selection set.
299 void SelectionSet(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
303 InputMethodContextEcoreWl* inputMethodContext = static_cast<InputMethodContextEcoreWl*>(data);
304 inputMethodContext->SendSelectionSet(data, imfContext, eventInfo);
308 int GetWindowIdFromActor(Dali::Actor actor)
310 int windowId = kUninitializedWindowId;
312 if(actor.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
314 auto sceneHolder = Dali::Integration::SceneHolder::Get(actor);
315 if(DALI_LIKELY(sceneHolder))
317 Any nativeWindowHandle = sceneHolder.GetNativeHandle();
319 #ifdef ECORE_WAYLAND2
320 windowId = ecore_wl2_window_id_get(AnyCast<Ecore_Wl2_Window*>(nativeWindowHandle));
322 windowId = ecore_wl_window_id_get(AnyCast<Ecore_Wl_Window*>(nativeWindowHandle));
332 return Dali::InputMethodContext::New(Dali::Actor());
335 Dali::TypeRegistration type(typeid(Dali::InputMethodContext), typeid(Dali::BaseHandle), Create);
337 } // unnamed namespace
339 InputMethodContextPtr InputMethodContextEcoreWl::New(Dali::Actor actor)
341 InputMethodContextPtr inputMethodContext;
343 // Create instance only if the adaptor is available and the valid actor exists
344 if(actor && Dali::Adaptor::IsAvailable())
346 inputMethodContext = new InputMethodContextEcoreWl(actor);
348 return inputMethodContext;
351 void InputMethodContextEcoreWl::Finalize()
353 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContext::Finalize\n");
355 DisconnectCallbacks();
359 InputMethodContextEcoreWl::InputMethodContextEcoreWl(Dali::Actor actor)
361 mIMFCursorPosition(0),
363 mRestoreAfterFocusLost(false),
364 mIdleCallbackConnected(false),
365 mWindowId(GetWindowIdFromActor(actor))
369 actor.OnSceneSignal().Connect(this, &InputMethodContextEcoreWl::OnStaged);
372 InputMethodContextEcoreWl::~InputMethodContextEcoreWl()
377 ecore_imf_shutdown();
379 catch(std::bad_weak_ptr const& ex)
381 DALI_LOG_ERROR("InputMethodContextEcoreWl::~InputMethodContextEcoreWl() - std::bad_weak_ptr caught: %s\n", ex.what());
385 void InputMethodContextEcoreWl::Initialize()
389 ApplyBackupOperations();
392 void InputMethodContextEcoreWl::CreateContext()
394 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContext::CreateContext\n");
396 if(mWindowId == kUninitializedWindowId)
401 const char* contextId = ecore_imf_context_default_id_get();
404 mIMFContext = ecore_imf_context_add(contextId);
408 ecore_imf_context_client_window_set(mIMFContext, reinterpret_cast<void*>(mWindowId));
412 DALI_LOG_WARNING("InputMethodContext Unable to get IMFContext\n");
417 DALI_LOG_WARNING("InputMethodContext Unable to get IMFContext\n");
421 void InputMethodContextEcoreWl::DeleteContext()
423 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::DeleteContext\n");
427 ecore_imf_context_del(mIMFContext);
432 // Callbacks for predicitive text support.
433 void InputMethodContextEcoreWl::ConnectCallbacks()
437 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::ConnectCallbacks\n");
439 ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit, this);
440 ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit, this);
441 ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding, this);
442 ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand, this);
443 ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_COMMIT_CONTENT, CommitContent, this);
444 ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_SELECTION_SET, SelectionSet, this);
446 ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback, this);
447 ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback, this);
448 ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback, this);
449 ecore_imf_context_input_panel_event_callback_add(mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback, this);
451 ecore_imf_context_retrieve_surrounding_callback_set(mIMFContext, ImfRetrieveSurrounding, this);
455 void InputMethodContextEcoreWl::DisconnectCallbacks()
459 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::DisconnectCallbacks\n");
461 ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit);
462 ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit);
463 ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding);
464 ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand);
465 ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_COMMIT_CONTENT, CommitContent);
466 ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_SELECTION_SET, SelectionSet);
468 ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback);
469 ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback);
470 ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, InputPanelGeometryChangedCallback);
471 ecore_imf_context_input_panel_event_callback_del(mIMFContext, ECORE_IMF_INPUT_PANEL_KEYBOARD_MODE_EVENT, InputPanelKeyboardTypeChangedCallback);
473 // We do not need to unset the retrieve surrounding callback.
477 void InputMethodContextEcoreWl::Activate()
479 // Reset mIdleCallbackConnected
480 mIdleCallbackConnected = false;
484 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::Activate\n");
486 ecore_imf_context_focus_in(mIMFContext);
488 // emit keyboard activated signal
489 Dali::InputMethodContext handle(this);
490 mActivatedSignal.Emit(handle);
494 void InputMethodContextEcoreWl::Deactivate()
498 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::Deactivate\n");
501 ecore_imf_context_focus_out(mIMFContext);
504 // Reset mIdleCallbackConnected
505 mIdleCallbackConnected = false;
508 void InputMethodContextEcoreWl::Reset()
510 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::Reset\n");
514 ecore_imf_context_reset(mIMFContext);
518 ImfContext* InputMethodContextEcoreWl::GetContext()
520 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetContext\n");
525 bool InputMethodContextEcoreWl::RestoreAfterFocusLost() const
527 return mRestoreAfterFocusLost;
530 void InputMethodContextEcoreWl::SetRestoreAfterFocusLost(bool toggle)
532 mRestoreAfterFocusLost = toggle;
536 * Called when an InputMethodContext Pre-Edit changed event is received.
537 * We are still predicting what the user is typing. The latest string is what the InputMethodContext module thinks
538 * the user wants to type.
540 void InputMethodContextEcoreWl::PreEditChanged(void*, ImfContext* imfContext, void* eventInfo)
542 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::PreEditChanged\n");
543 auto context = static_cast<Ecore_IMF_Context*>(imfContext);
545 char* preEditString(NULL);
546 int cursorPosition(0);
547 Eina_List* attrs = NULL;
550 Ecore_IMF_Preedit_Attr* attr;
552 mPreeditAttrs.Clear();
554 // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string.
555 // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string.
556 ecore_imf_context_preedit_string_with_attributes_get(context, &preEditString, &attrs, &cursorPosition);
560 // iterate through the list of attributes getting the type, start and end position.
561 for(l = attrs, (attr = static_cast<Ecore_IMF_Preedit_Attr*>(eina_list_data_get(l))); l; l = eina_list_next(l), (attr = static_cast<Ecore_IMF_Preedit_Attr*>(eina_list_data_get(l))))
563 Dali::InputMethodContext::PreeditAttributeData data;
567 uint32_t visualCharacterIndex = 0;
568 size_t byteIndex = 0;
570 // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
571 char leadByte = preEditString[byteIndex];
573 while(leadByte != '\0')
575 leadByte = preEditString[byteIndex]; // Update the character to get the number of its byte
577 // attr->end_index is provided as a byte position not character and we need to know the character position.
578 const size_t currentSequenceLength = Utf8SequenceLength(leadByte); // returns number of bytes used to represent character.
579 if(byteIndex <= attr->start_index)
581 data.startIndex = visualCharacterIndex;
583 if(byteIndex >= attr->end_index)
585 data.endIndex = visualCharacterIndex;
587 // end loop as found cursor position that matches byte position
591 byteIndex += currentSequenceLength; // jump to next character
592 visualCharacterIndex++; // increment character count so we know our position for when we get a match
596 switch(attr->preedit_type)
598 case ECORE_IMF_PREEDIT_TYPE_NONE:
600 data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
603 case ECORE_IMF_PREEDIT_TYPE_SUB1:
605 data.preeditType = Dali::InputMethodContext::PreeditStyle::UNDERLINE;
608 case ECORE_IMF_PREEDIT_TYPE_SUB2:
610 data.preeditType = Dali::InputMethodContext::PreeditStyle::REVERSE;
613 case ECORE_IMF_PREEDIT_TYPE_SUB3:
615 data.preeditType = Dali::InputMethodContext::PreeditStyle::HIGHLIGHT;
618 case ECORE_IMF_PREEDIT_TYPE_SUB4:
620 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1;
623 case ECORE_IMF_PREEDIT_TYPE_SUB5:
625 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2;
628 case ECORE_IMF_PREEDIT_TYPE_SUB6:
630 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3;
633 case ECORE_IMF_PREEDIT_TYPE_SUB7:
635 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4;
640 data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
644 mPreeditAttrs.PushBack(data);
648 if(Dali::Adaptor::IsAvailable())
650 Dali::InputMethodContext handle(this);
651 Dali::InputMethodContext::EventData eventData(Dali::InputMethodContext::PRE_EDIT, preEditString, cursorPosition, 0);
652 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, eventData);
654 if(callbackData.update)
656 SetCursorPosition(callbackData.cursorPosition);
657 SetSurroundingText(callbackData.currentText);
659 NotifyCursorPosition();
662 if(callbackData.preeditResetRequired)
670 void InputMethodContextEcoreWl::CommitReceived(void*, ImfContext* imfContext, void* eventInfo)
672 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::CommitReceived\n");
674 if(Dali::Adaptor::IsAvailable())
676 const std::string keyString(static_cast<char*>(eventInfo));
678 Dali::InputMethodContext handle(this);
679 Dali::InputMethodContext::EventData eventData(Dali::InputMethodContext::COMMIT, keyString, 0, 0);
680 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, eventData);
682 if(callbackData.update)
684 SetCursorPosition(callbackData.cursorPosition);
685 SetSurroundingText(callbackData.currentText);
687 NotifyCursorPosition();
693 * Called when an InputMethodContext retrieve surround event is received.
694 * Here the InputMethodContext module wishes to know the string we are working with and where within the string the cursor is
695 * We need to signal the application to tell us this information.
697 bool InputMethodContextEcoreWl::RetrieveSurrounding(void* data, ImfContext* imfContext, char** text, int* cursorPosition)
699 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::RetrieveSurrounding\n");
701 Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::GET_SURROUNDING, std::string(), 0, 0);
702 Dali::InputMethodContext handle(this);
703 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, imfData);
705 if(callbackData.update)
709 mIMFCursorPosition = static_cast<int>(callbackData.cursorPosition);
710 *cursorPosition = mIMFCursorPosition;
715 const char* plainText = callbackData.currentText.c_str();
719 // If the current input panel is password mode, dali should replace the plain text with '*' (Asterisk) character.
720 if(ecore_imf_context_input_hint_get(mIMFContext) & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA)
722 size_t textLength = callbackData.currentText.length();
723 size_t utf8Length = GetNumberOfUtf8Characters(plainText, textLength);
724 if(textLength > 0u && utf8Length == 0u)
726 DALI_LOG_ERROR("Invalid utf8 characters, utf8 len:%zu, text len:%zu, text:%s\n", utf8Length, textLength, plainText);
730 std::string asterisks(utf8Length, '*');
731 *text = strdup(asterisks.c_str());
735 // The memory allocated by strdup() can be freed by ecore_imf_context_surrounding_get() internally.
736 *text = strdup(plainText);
748 * Called when an InputMethodContext delete surrounding event is received.
749 * Here we tell the application that it should delete a certain range.
751 void InputMethodContextEcoreWl::DeleteSurrounding(void* data, ImfContext* imfContext, void* eventInfo)
753 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::DeleteSurrounding\n");
755 if(Dali::Adaptor::IsAvailable())
757 Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>(eventInfo);
759 Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::DELETE_SURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars);
760 Dali::InputMethodContext handle(this);
761 mEventSignal.Emit(handle, imfData);
766 * Called when the input method sends a private command.
768 void InputMethodContextEcoreWl::SendPrivateCommand(void* data, ImfContext* imfContext, void* eventInfo)
770 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendPrivateCommand\n");
772 if(Dali::Adaptor::IsAvailable())
774 const char* privateCommandSendEvent = static_cast<const char*>(eventInfo);
776 Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::PRIVATE_COMMAND, privateCommandSendEvent, 0, 0);
777 Dali::InputMethodContext handle(this);
778 mEventSignal.Emit(handle, imfData);
783 * Called when the input method commits content, such as an image.
785 void InputMethodContextEcoreWl::SendCommitContent(void* data, ImfContext* imfContext, void* eventInfo)
787 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendCommitContent\n");
789 if(Dali::Adaptor::IsAvailable())
791 Ecore_IMF_Event_Commit_Content* commitContent = static_cast<Ecore_IMF_Event_Commit_Content*>(eventInfo);
794 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendCommitContent commit content : %s, description : %s, mime type : %s\n", commitContent->content_uri, commitContent->description, commitContent->mime_types);
795 mContentReceivedSignal.Emit(commitContent->content_uri, commitContent->description, commitContent->mime_types);
801 * Called when the input method selection set.
803 void InputMethodContextEcoreWl::SendSelectionSet(void* data, ImfContext* imfContext, void* eventInfo)
805 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendCommitContent\n");
807 if(Dali::Adaptor::IsAvailable())
809 Ecore_IMF_Event_Selection* selection = static_cast<Ecore_IMF_Event_Selection*>(eventInfo);
812 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendSelectionSet selection start index : %d, end index : %d\n", selection->start, selection->end);
813 Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::SELECTION_SET, selection->start, selection->end);
814 Dali::InputMethodContext handle(this);
815 mEventSignal.Emit(handle, imfData);
820 void InputMethodContextEcoreWl::NotifyCursorPosition()
822 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::NotifyCursorPosition\n");
826 ecore_imf_context_cursor_position_set(mIMFContext, mIMFCursorPosition);
830 void InputMethodContextEcoreWl::SetCursorPosition(unsigned int cursorPosition)
832 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetCursorPosition\n");
834 mIMFCursorPosition = static_cast<int>(cursorPosition);
837 unsigned int InputMethodContextEcoreWl::GetCursorPosition() const
839 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetCursorPosition\n");
841 return static_cast<unsigned int>(mIMFCursorPosition);
844 void InputMethodContextEcoreWl::SetSurroundingText(const std::string& text)
846 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetSurroundingText\n");
848 mSurroundingText = text;
851 const std::string& InputMethodContextEcoreWl::GetSurroundingText() const
853 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetSurroundingText\n");
855 return mSurroundingText;
858 void InputMethodContextEcoreWl::NotifyTextInputMultiLine(bool multiLine)
862 Ecore_IMF_Input_Hints currentHint = ecore_imf_context_input_hint_get(mIMFContext);
863 ecore_imf_context_input_hint_set(mIMFContext,
864 static_cast<Ecore_IMF_Input_Hints>(multiLine ? (currentHint | ECORE_IMF_INPUT_HINT_MULTILINE) : (currentHint & ~ECORE_IMF_INPUT_HINT_MULTILINE)));
867 mBackupOperations[Operation::NOTIFY_TEXT_INPUT_MULTILINE] = std::bind(&InputMethodContextEcoreWl::NotifyTextInputMultiLine, this, multiLine);
870 Dali::InputMethodContext::TextDirection InputMethodContextEcoreWl::GetTextDirection()
872 Dali::InputMethodContext::TextDirection direction(Dali::InputMethodContext::LEFT_TO_RIGHT);
877 ecore_imf_context_input_panel_language_locale_get(mIMFContext, &locale);
881 direction = static_cast<Dali::InputMethodContext::TextDirection>(Locale::GetDirection(std::string(locale)));
889 Rect<int> InputMethodContextEcoreWl::GetInputMethodArea()
891 int xPos, yPos, width, height;
893 width = height = xPos = yPos = 0;
897 ecore_imf_context_input_panel_geometry_get(mIMFContext, &xPos, &yPos, &width, &height);
901 DALI_LOG_WARNING("VKB Unable to get IMFContext so GetSize unavailable\n");
902 // return 0 as real size unknown.
905 return Rect<int>(xPos, yPos, width, height);
908 void InputMethodContextEcoreWl::ApplyOptions(const InputMethodOptions& options)
910 using namespace Dali::InputMethod::Category;
914 if(mIMFContext == NULL)
916 DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
920 if(mOptions.CompareAndSet(PANEL_LAYOUT, options, index))
922 ecore_imf_context_input_panel_layout_set(mIMFContext, panelLayoutMap[index]);
924 // Sets the input hint which allows input methods to fine-tune their behavior.
925 if(panelLayoutMap[index] == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
927 ecore_imf_context_input_hint_set(mIMFContext, static_cast<Ecore_IMF_Input_Hints>(ecore_imf_context_input_hint_get(mIMFContext) | ECORE_IMF_INPUT_HINT_SENSITIVE_DATA));
931 ecore_imf_context_input_hint_set(mIMFContext, static_cast<Ecore_IMF_Input_Hints>(ecore_imf_context_input_hint_get(mIMFContext) & ~ECORE_IMF_INPUT_HINT_SENSITIVE_DATA));
934 if(mOptions.CompareAndSet(BUTTON_ACTION, options, index))
936 ecore_imf_context_input_panel_return_key_type_set(mIMFContext, returnKeyTypeMap[index]);
938 if(mOptions.CompareAndSet(AUTO_CAPITALIZE, options, index))
940 ecore_imf_context_autocapital_type_set(mIMFContext, autoCapitalMap[index]);
942 if(mOptions.CompareAndSet(VARIATION, options, index))
944 ecore_imf_context_input_panel_layout_variation_set(mIMFContext, index);
948 void InputMethodContextEcoreWl::SetInputPanelData(const std::string& data)
950 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelData\n");
954 int length = data.length();
955 ecore_imf_context_input_panel_imdata_set(mIMFContext, data.c_str(), length);
958 mBackupOperations[Operation::SET_INPUT_PANEL_DATA] = std::bind(&InputMethodContextEcoreWl::SetInputPanelData, this, data);
961 void InputMethodContextEcoreWl::GetInputPanelData(std::string& data)
963 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelData\n");
967 int length = 4096; // The max length is 4096 bytes
968 Dali::Vector<char> buffer;
969 buffer.Resize(length);
970 ecore_imf_context_input_panel_imdata_get(mIMFContext, &buffer[0], &length);
971 data = std::string(buffer.Begin(), buffer.End());
975 Dali::InputMethodContext::State InputMethodContextEcoreWl::GetInputPanelState()
977 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelState\n");
982 value = ecore_imf_context_input_panel_state_get(mIMFContext);
986 case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
988 return Dali::InputMethodContext::SHOW;
992 case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
994 return Dali::InputMethodContext::HIDE;
998 case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
1000 return Dali::InputMethodContext::WILL_SHOW;
1006 return Dali::InputMethodContext::DEFAULT;
1010 return Dali::InputMethodContext::DEFAULT;
1013 void InputMethodContextEcoreWl::SetReturnKeyState(bool visible)
1015 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetReturnKeyState\n");
1019 ecore_imf_context_input_panel_return_key_disabled_set(mIMFContext, !visible);
1022 mBackupOperations[Operation::SET_RETURN_KEY_STATE] = std::bind(&InputMethodContextEcoreWl::SetReturnKeyState, this, visible);
1025 void InputMethodContextEcoreWl::AutoEnableInputPanel(bool enabled)
1027 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::AutoEnableInputPanel\n");
1031 ecore_imf_context_input_panel_enabled_set(mIMFContext, enabled);
1034 mBackupOperations[Operation::AUTO_ENABLE_INPUT_PANEL] = std::bind(&InputMethodContextEcoreWl::AutoEnableInputPanel, this, enabled);
1037 void InputMethodContextEcoreWl::ShowInputPanel()
1039 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::ShowInputPanel\n");
1043 ecore_imf_context_input_panel_show(mIMFContext);
1047 void InputMethodContextEcoreWl::HideInputPanel()
1049 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::HideInputPanel\n");
1053 ecore_imf_context_input_panel_hide(mIMFContext);
1057 Dali::InputMethodContext::KeyboardType InputMethodContextEcoreWl::GetKeyboardType()
1059 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetKeyboardType\n");
1064 value = ecore_imf_context_keyboard_mode_get(mIMFContext);
1068 case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE:
1070 return Dali::InputMethodContext::SOFTWARE_KEYBOARD;
1073 case ECORE_IMF_INPUT_PANEL_HW_KEYBOARD_MODE:
1075 return Dali::InputMethodContext::HARDWARE_KEYBOARD;
1081 return Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD;
1084 std::string InputMethodContextEcoreWl::GetInputPanelLocale()
1086 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelLocale\n");
1088 std::string locale = "";
1093 ecore_imf_context_input_panel_language_locale_get(mIMFContext, &value);
1097 std::string valueCopy(value);
1100 // The locale string retrieved must be freed with free().
1107 void InputMethodContextEcoreWl::SetContentMIMETypes(const std::string& mimeTypes)
1109 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetContentMIMETypes\n");
1113 ecore_imf_context_mime_type_accept_set(mIMFContext, mimeTypes.c_str());
1116 mBackupOperations[Operation::SET_CONTENT_MIME_TYPES] = std::bind(&InputMethodContextEcoreWl::SetContentMIMETypes, this, mimeTypes);
1119 bool InputMethodContextEcoreWl::FilterEventKey(const Dali::KeyEvent& keyEvent)
1121 bool eventHandled(false);
1123 // If a device key then skip ecore_imf_context_filter_event.
1124 if(!KeyLookup::IsDeviceButton(keyEvent.GetKeyName().c_str()))
1126 //check whether it's key down or key up event
1127 if(keyEvent.GetState() == Dali::KeyEvent::DOWN)
1129 eventHandled = ProcessEventKeyDown(keyEvent);
1131 else if(keyEvent.GetState() == Dali::KeyEvent::UP)
1133 eventHandled = ProcessEventKeyUp(keyEvent);
1137 return eventHandled;
1140 void InputMethodContextEcoreWl::AllowTextPrediction(bool prediction)
1142 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::AllowTextPrediction\n");
1146 ecore_imf_context_prediction_allow_set(mIMFContext, prediction);
1149 mBackupOperations[Operation::ALLOW_TEXT_PREDICTION] = std::bind(&InputMethodContextEcoreWl::AllowTextPrediction, this, prediction);
1152 bool InputMethodContextEcoreWl::IsTextPredictionAllowed() const
1154 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::IsTextPredictionAllowed\n");
1155 bool prediction = false;
1158 prediction = ecore_imf_context_prediction_allow_get(mIMFContext);
1163 void InputMethodContextEcoreWl::SetInputPanelLanguage(Dali::InputMethodContext::InputPanelLanguage language)
1165 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelLanguage\n");
1170 case Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC:
1172 ecore_imf_context_input_panel_language_set(mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC);
1175 case Dali::InputMethodContext::InputPanelLanguage::ALPHABET:
1177 ecore_imf_context_input_panel_language_set(mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET);
1183 mBackupOperations[Operation::SET_INPUT_PANEL_LANGUAGE] = std::bind(&InputMethodContextEcoreWl::SetInputPanelLanguage, this, language);
1186 Dali::InputMethodContext::InputPanelLanguage InputMethodContextEcoreWl::GetInputPanelLanguage() const
1188 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelLanguage\n");
1192 value = ecore_imf_context_input_panel_language_get(mIMFContext);
1196 case ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC:
1198 return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
1201 case ECORE_IMF_INPUT_PANEL_LANG_ALPHABET:
1203 return Dali::InputMethodContext::InputPanelLanguage::ALPHABET;
1208 return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
1211 void InputMethodContextEcoreWl::SetInputPanelPosition(unsigned int x, unsigned int y)
1213 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelPosition\n");
1217 ecore_imf_context_input_panel_position_set(mIMFContext, x, y);
1220 mBackupOperations[Operation::SET_INPUT_PANEL_POSITION] = std::bind(&InputMethodContextEcoreWl::SetInputPanelPosition, this, x, y);
1223 bool InputMethodContextEcoreWl::SetInputPanelPositionAlign(int x, int y, Dali::InputMethodContext::InputPanelAlign align)
1225 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelPositionAlign\n");
1226 bool result = false;
1230 Ecore_IMF_Input_Panel_Align inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_TOP_LEFT;
1233 case Dali::InputMethodContext::InputPanelAlign::TOP_LEFT:
1235 inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_TOP_LEFT;
1238 case Dali::InputMethodContext::InputPanelAlign::TOP_CENTER:
1240 inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_TOP_CENTER;
1243 case Dali::InputMethodContext::InputPanelAlign::TOP_RIGHT:
1245 inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_TOP_RIGHT;
1248 case Dali::InputMethodContext::InputPanelAlign::MIDDLE_LEFT:
1250 inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_MIDDLE_LEFT;
1253 case Dali::InputMethodContext::InputPanelAlign::MIDDLE_CENTER:
1255 inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_MIDDLE_CENTER;
1258 case Dali::InputMethodContext::InputPanelAlign::MIDDLE_RIGHT:
1260 inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_MIDDLE_RIGHT;
1263 case Dali::InputMethodContext::InputPanelAlign::BOTTOM_LEFT:
1265 inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_BOTTOM_LEFT;
1268 case Dali::InputMethodContext::InputPanelAlign::BOTTOM_CENTER:
1270 inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_BOTTOM_CENTER;
1273 case Dali::InputMethodContext::InputPanelAlign::BOTTOM_RIGHT:
1275 inputPanelAlign = ECORE_IMF_INPUT_PANEL_ALIGN_BOTTOM_RIGHT;
1280 result = ecore_imf_context_input_panel_position_align_set(mIMFContext, x, y, inputPanelAlign);
1283 mBackupOperations[Operation::SET_INPUT_PANEL_POSITION_ALIGN] = std::bind(&InputMethodContextEcoreWl::SetInputPanelPositionAlign, this, x, y, align);
1288 void InputMethodContextEcoreWl::GetPreeditStyle(Dali::InputMethodContext::PreEditAttributeDataContainer& attrs) const
1290 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetPreeditStyle\n");
1291 attrs = mPreeditAttrs;
1294 bool InputMethodContextEcoreWl::ProcessEventKeyDown(const Dali::KeyEvent& keyEvent)
1296 bool eventHandled(false);
1299 Integration::KeyEvent integKeyEvent(keyEvent.GetKeyName(), keyEvent.GetLogicalKey(), keyEvent.GetKeyString(), keyEvent.GetKeyCode(), keyEvent.GetKeyModifier(), keyEvent.GetTime(), static_cast<Integration::KeyEvent::State>(keyEvent.GetState()), keyEvent.GetCompose(), keyEvent.GetDeviceName(), keyEvent.GetDeviceClass(), keyEvent.GetDeviceSubclass());
1300 std::string key = integKeyEvent.logicalKey;
1302 std::string compose = integKeyEvent.compose;
1303 std::string deviceName = integKeyEvent.deviceName;
1305 // We're consuming key down event so we have to pass to InputMethodContext so that it can parse it as well.
1306 Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
1307 ecoreKeyDownEvent.keyname = integKeyEvent.keyName.c_str();
1308 ecoreKeyDownEvent.key = key.c_str();
1309 ecoreKeyDownEvent.string = integKeyEvent.keyString.c_str();
1310 ecoreKeyDownEvent.compose = compose.c_str();
1311 ecoreKeyDownEvent.timestamp = static_cast<uint32_t>(integKeyEvent.time);
1312 ecoreKeyDownEvent.modifiers = EcoreInputModifierToEcoreIMFModifier(integKeyEvent.keyModifier);
1313 ecoreKeyDownEvent.locks = EcoreInputModifierToEcoreIMFLock(integKeyEvent.keyModifier);
1314 ecoreKeyDownEvent.dev_name = deviceName.c_str();
1315 ecoreKeyDownEvent.dev_class = static_cast<Ecore_IMF_Device_Class>(integKeyEvent.deviceClass); //ECORE_IMF_DEVICE_CLASS_KEYBOARD;
1316 ecoreKeyDownEvent.dev_subclass = static_cast<Ecore_IMF_Device_Subclass>(integKeyEvent.deviceSubclass); //ECORE_IMF_DEVICE_SUBCLASS_NONE;
1317 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR) && (ECORE_VERSION_MINOR >= 22)
1318 ecoreKeyDownEvent.keycode = integKeyEvent.keyCode; // Ecore_IMF_Event structure has added 'keycode' variable since ecore_imf 1.22 version.
1319 #endif // Since ecore_imf 1.22 version
1321 // If the device is IME and the focused key is the direction keys, then we should send a key event to move a key cursor.
1322 if((integKeyEvent.deviceName == "ime") && ((!strncmp(integKeyEvent.keyName.c_str(), "Left", 4)) ||
1323 (!strncmp(integKeyEvent.keyName.c_str(), "Right", 5)) ||
1324 (!strncmp(integKeyEvent.keyName.c_str(), "Up", 2)) ||
1325 (!strncmp(integKeyEvent.keyName.c_str(), "Down", 4))))
1331 eventHandled = ecore_imf_context_filter_event(mIMFContext,
1332 ECORE_IMF_EVENT_KEY_DOWN,
1333 reinterpret_cast<Ecore_IMF_Event*>(&ecoreKeyDownEvent));
1336 // If the event has not been handled by InputMethodContext then check if we should reset our input method context
1339 if(!strcmp(integKeyEvent.keyName.c_str(), "Escape") ||
1340 !strcmp(integKeyEvent.keyName.c_str(), "Return") ||
1341 !strcmp(integKeyEvent.keyName.c_str(), "KP_Enter"))
1343 ecore_imf_context_reset(mIMFContext);
1347 return eventHandled;
1350 bool InputMethodContextEcoreWl::ProcessEventKeyUp(const Dali::KeyEvent& keyEvent)
1352 bool eventHandled(false);
1355 Integration::KeyEvent integKeyEvent(keyEvent.GetKeyName(), keyEvent.GetLogicalKey(), keyEvent.GetKeyString(), keyEvent.GetKeyCode(), keyEvent.GetKeyModifier(), keyEvent.GetTime(), static_cast<Integration::KeyEvent::State>(keyEvent.GetState()), keyEvent.GetCompose(), keyEvent.GetDeviceName(), keyEvent.GetDeviceClass(), keyEvent.GetDeviceSubclass());
1356 std::string key = integKeyEvent.logicalKey;
1358 std::string compose = integKeyEvent.compose;
1359 std::string deviceName = integKeyEvent.deviceName;
1361 // We're consuming key up event so we have to pass to InputMethodContext so that it can parse it as well.
1362 Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
1363 ecoreKeyUpEvent.keyname = integKeyEvent.keyName.c_str();
1364 ecoreKeyUpEvent.key = key.c_str();
1365 ecoreKeyUpEvent.string = integKeyEvent.keyString.c_str();
1366 ecoreKeyUpEvent.compose = compose.c_str();
1367 ecoreKeyUpEvent.timestamp = static_cast<uint32_t>(integKeyEvent.time);
1368 ecoreKeyUpEvent.modifiers = EcoreInputModifierToEcoreIMFModifier(integKeyEvent.keyModifier);
1369 ecoreKeyUpEvent.locks = EcoreInputModifierToEcoreIMFLock(integKeyEvent.keyModifier);
1370 ecoreKeyUpEvent.dev_name = deviceName.c_str();
1371 ecoreKeyUpEvent.dev_class = static_cast<Ecore_IMF_Device_Class>(integKeyEvent.deviceClass); //ECORE_IMF_DEVICE_CLASS_KEYBOARD;
1372 ecoreKeyUpEvent.dev_subclass = static_cast<Ecore_IMF_Device_Subclass>(integKeyEvent.deviceSubclass); //ECORE_IMF_DEVICE_SUBCLASS_NONE;
1373 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR) && (ECORE_VERSION_MINOR >= 22)
1374 ecoreKeyUpEvent.keycode = integKeyEvent.keyCode; // Ecore_IMF_Event structure has added 'keycode' variable since ecore_imf 1.22 version.
1375 #endif // Since ecore_imf 1.22 version
1377 eventHandled = ecore_imf_context_filter_event(mIMFContext,
1378 ECORE_IMF_EVENT_KEY_UP,
1379 reinterpret_cast<Ecore_IMF_Event*>(&ecoreKeyUpEvent));
1381 return eventHandled;
1384 Ecore_IMF_Keyboard_Modifiers InputMethodContextEcoreWl::EcoreInputModifierToEcoreIMFModifier(unsigned int ecoreModifier)
1386 unsigned int modifier(ECORE_IMF_KEYBOARD_MODIFIER_NONE); // If no other matches returns NONE.
1388 if(ecoreModifier & ECORE_EVENT_MODIFIER_SHIFT) // enums from ecore_input/Ecore_Input.h
1390 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT; // enums from ecore_imf/ecore_imf.h
1393 if(ecoreModifier & ECORE_EVENT_MODIFIER_ALT)
1395 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
1398 if(ecoreModifier & ECORE_EVENT_MODIFIER_CTRL)
1400 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
1403 if(ecoreModifier & ECORE_EVENT_MODIFIER_WIN)
1405 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
1408 if(ecoreModifier & ECORE_EVENT_MODIFIER_ALTGR)
1410 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
1413 return static_cast<Ecore_IMF_Keyboard_Modifiers>(modifier);
1416 Ecore_IMF_Keyboard_Locks InputMethodContextEcoreWl::EcoreInputModifierToEcoreIMFLock(unsigned int modifier)
1418 unsigned int lock(ECORE_IMF_KEYBOARD_LOCK_NONE); // If no other matches, returns NONE.
1420 if(modifier & ECORE_EVENT_LOCK_NUM)
1422 lock |= ECORE_IMF_KEYBOARD_LOCK_NUM; // Num lock is active.
1425 if(modifier & ECORE_EVENT_LOCK_CAPS)
1427 lock |= ECORE_IMF_KEYBOARD_LOCK_CAPS; // Caps lock is active.
1430 if(modifier & ECORE_EVENT_LOCK_SCROLL)
1432 lock |= ECORE_IMF_KEYBOARD_LOCK_SCROLL; // Scroll lock is active.
1435 return static_cast<Ecore_IMF_Keyboard_Locks>(lock);
1438 void InputMethodContextEcoreWl::OnStaged(Dali::Actor actor)
1440 int windowId = GetWindowIdFromActor(actor);
1442 if(mWindowId != windowId)
1444 mWindowId = windowId;
1452 } // namespace Adaptor
1454 } // namespace Internal