2 * Copyright (c) 2021 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.
19 #include <dali/internal/input/ubuntu-x11/input-method-context-impl-x.h>
22 #include <dali/devel-api/common/singleton-service.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/public-api/events/key-event.h>
25 #include <dali/public-api/object/type-registry.h>
28 #include <dali/integration-api/adaptor-framework/adaptor.h>
29 #include <dali/internal/adaptor/common/adaptor-impl.h>
30 #include <dali/internal/input/common/key-impl.h>
31 #include <dali/internal/input/common/virtual-keyboard-impl.h>
32 #include <dali/internal/input/linux/dali-ecore-imf.h>
33 #include <dali/internal/input/tizen-wayland/ecore-virtual-keyboard.h>
34 #include <dali/internal/input/ubuntu-x11/dali-ecore-input.h>
35 #include <dali/internal/system/common/locale-utils.h>
36 #include <dali/internal/system/linux/dali-ecore.h>
37 #include <dali/public-api/adaptor-framework/key.h>
47 #if defined(DEBUG_ENABLED)
48 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_INPUT_METHOD_CONTEXT");
51 // Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead.
52 size_t Utf8SequenceLength(const unsigned char leadByte)
56 if((leadByte & 0x80) == 0) //ASCII character (lead bit zero)
60 else if((leadByte & 0xe0) == 0xc0) //110x xxxx
64 else if((leadByte & 0xf0) == 0xe0) //1110 xxxx
68 else if((leadByte & 0xf8) == 0xf0) //1111 0xxx
72 else if((leadByte & 0xfc) == 0xf8) //1111 10xx
76 else if((leadByte & 0xfe) == 0xfc) //1111 110x
84 // Static function calls used by ecore 'c' style callback registration
85 void Commit(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
89 InputMethodContextX* inputMethodContext = static_cast<InputMethodContextX*>(data);
90 inputMethodContext->CommitReceived(data, imfContext, eventInfo);
94 void PreEdit(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
98 InputMethodContextX* inputMethodContext = static_cast<InputMethodContextX*>(data);
99 inputMethodContext->PreEditChanged(data, imfContext, eventInfo);
103 Eina_Bool ImfRetrieveSurrounding(void* data, Ecore_IMF_Context* imfContext, char** text, int* cursorPosition)
107 InputMethodContextX* inputMethodContext = static_cast<InputMethodContextX*>(data);
108 return inputMethodContext->RetrieveSurrounding(data, imfContext, text, cursorPosition);
117 * Called when an InputMethodContext delete surrounding event is received.
118 * Here we tell the application that it should delete a certain range.
120 void ImfDeleteSurrounding(void* data, Ecore_IMF_Context* imfContext, void* eventInfo)
124 InputMethodContextX* inputMethodContext = static_cast<InputMethodContextX*>(data);
125 inputMethodContext->DeleteSurrounding(data, imfContext, eventInfo);
129 } // unnamed namespace
131 InputMethodContextPtr InputMethodContextX::New(Dali::Actor actor)
133 InputMethodContextPtr manager;
135 if(actor && Dali::Adaptor::IsAvailable())
137 manager = new InputMethodContextX(actor);
143 void InputMethodContextX::Finalize()
145 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::Finalize\n");
146 VirtualKeyboard::DisconnectCallbacks(mIMFContext);
147 DisconnectCallbacks();
151 InputMethodContextX::InputMethodContextX(Dali::Actor actor)
154 mIMFCursorPosition(0),
156 mRestoreAfterFocusLost(false),
157 mIdleCallbackConnected(false)
161 actor.OnSceneSignal().Connect(this, &InputMethodContextX::OnStaged);
164 InputMethodContextX::~InputMethodContextX()
167 ecore_imf_shutdown();
170 void InputMethodContextX::Initialize()
174 VirtualKeyboard::ConnectCallbacks(mIMFContext);
177 void InputMethodContextX::CreateContext()
179 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::CreateContext\n");
186 const char* contextId = ecore_imf_context_default_id_get();
189 mIMFContext = ecore_imf_context_add(contextId);
193 ecore_imf_context_client_window_set(mIMFContext, reinterpret_cast<void*>(mEcoreXwin));
197 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContext Unable to get IMFContext\n");
202 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContext Unable to get IMFContext\n");
206 void InputMethodContextX::DeleteContext()
208 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::DeleteContext\n");
212 ecore_imf_context_del(mIMFContext);
217 // Callbacks for predicitive text support.
218 void InputMethodContextX::ConnectCallbacks()
222 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::ConnectCallbacks\n");
224 ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit, this);
225 ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit, this);
226 ecore_imf_context_event_callback_add(mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding, this);
228 ecore_imf_context_retrieve_surrounding_callback_set(mIMFContext, ImfRetrieveSurrounding, this);
232 void InputMethodContextX::DisconnectCallbacks()
236 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::DisconnectCallbacks\n");
238 ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit);
239 ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit);
240 ecore_imf_context_event_callback_del(mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding);
242 // We do not need to unset the retrieve surrounding callback.
246 void InputMethodContextX::Activate()
248 // Reset mIdleCallbackConnected
249 mIdleCallbackConnected = false;
253 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::Activate\n");
255 ecore_imf_context_focus_in(mIMFContext);
257 // emit keyboard activated signal
258 Dali::InputMethodContext handle(this);
259 mActivatedSignal.Emit(handle);
263 void InputMethodContextX::Deactivate()
267 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::Deactivate\n");
270 ecore_imf_context_focus_out(mIMFContext);
273 // Reset mIdleCallbackConnected
274 mIdleCallbackConnected = false;
277 void InputMethodContextX::Reset()
279 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::Reset\n");
283 ecore_imf_context_reset(mIMFContext);
287 ImfContext* InputMethodContextX::GetContext()
289 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::GetContext\n");
294 bool InputMethodContextX::RestoreAfterFocusLost() const
296 return mRestoreAfterFocusLost;
299 void InputMethodContextX::SetRestoreAfterFocusLost(bool toggle)
301 mRestoreAfterFocusLost = toggle;
305 * Called when an InputMethodContext Pre-Edit changed event is received.
306 * We are still predicting what the user is typing. The latest string is what the InputMethodContext module thinks
307 * the user wants to type.
309 void InputMethodContextX::PreEditChanged(void*, ImfContext* imfContext, void* eventInfo)
311 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::PreEditChanged\n");
312 auto context = static_cast<Ecore_IMF_Context*>(imfContext);
314 char* preEditString(NULL);
315 int cursorPosition(0);
316 Eina_List* attrs = NULL;
319 Ecore_IMF_Preedit_Attr* attr;
321 mPreeditAttrs.Clear();
323 // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string.
324 // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string.
325 ecore_imf_context_preedit_string_with_attributes_get(context, &preEditString, &attrs, &cursorPosition);
329 // iterate through the list of attributes getting the type, start and end position.
330 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))))
332 Dali::InputMethodContext::PreeditAttributeData data;
336 size_t visualCharacterIndex = 0;
337 size_t byteIndex = 0;
339 // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
340 char leadByte = preEditString[byteIndex];
342 while(leadByte != '\0')
344 leadByte = preEditString[byteIndex]; // Update the character to get the number of its byte
346 // attr->end_index is provided as a byte position not character and we need to know the character position.
347 const size_t currentSequenceLength = Utf8SequenceLength(leadByte); // returns number of bytes used to represent character.
348 if(byteIndex <= attr->start_index)
350 data.startIndex = visualCharacterIndex;
352 if(byteIndex >= attr->end_index)
354 data.endIndex = visualCharacterIndex;
356 // end loop as found cursor position that matches byte position
360 byteIndex += currentSequenceLength; // jump to next character
361 visualCharacterIndex++; // increment character count so we know our position for when we get a match
365 switch(attr->preedit_type)
367 case ECORE_IMF_PREEDIT_TYPE_NONE:
369 data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
372 case ECORE_IMF_PREEDIT_TYPE_SUB1:
374 data.preeditType = Dali::InputMethodContext::PreeditStyle::UNDERLINE;
377 case ECORE_IMF_PREEDIT_TYPE_SUB2:
379 data.preeditType = Dali::InputMethodContext::PreeditStyle::REVERSE;
382 case ECORE_IMF_PREEDIT_TYPE_SUB3:
384 data.preeditType = Dali::InputMethodContext::PreeditStyle::HIGHLIGHT;
387 case ECORE_IMF_PREEDIT_TYPE_SUB4:
389 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1;
392 case ECORE_IMF_PREEDIT_TYPE_SUB5:
394 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2;
397 case ECORE_IMF_PREEDIT_TYPE_SUB6:
399 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3;
402 case ECORE_IMF_PREEDIT_TYPE_SUB7:
404 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4;
409 data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
413 mPreeditAttrs.PushBack(data);
417 if(Dali::Adaptor::IsAvailable())
419 Dali::InputMethodContext handle(this);
420 Dali::InputMethodContext::EventData eventData(Dali::InputMethodContext::PRE_EDIT, preEditString, cursorPosition, 0);
421 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, eventData);
423 if(callbackData.update)
425 mIMFCursorPosition = static_cast<int>(callbackData.cursorPosition);
427 NotifyCursorPosition();
430 if(callbackData.preeditResetRequired)
438 void InputMethodContextX::CommitReceived(void*, ImfContext* imfContext, void* eventInfo)
440 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::CommitReceived\n");
442 if(Dali::Adaptor::IsAvailable())
444 const std::string keyString(static_cast<char*>(eventInfo));
446 Dali::InputMethodContext handle(this);
447 Dali::InputMethodContext::EventData eventData(Dali::InputMethodContext::COMMIT, keyString, 0, 0);
448 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, eventData);
450 if(callbackData.update)
452 mIMFCursorPosition = static_cast<int>(callbackData.cursorPosition);
454 NotifyCursorPosition();
460 * Called when an InputMethodContext retrieve surround event is received.
461 * Here the InputMethodContext module wishes to know the string we are working with and where within the string the cursor is
462 * We need to signal the application to tell us this information.
464 bool InputMethodContextX::RetrieveSurrounding(void* data, ImfContext* imfContext, char** text, int* cursorPosition)
466 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::RetrieveSurrounding\n");
468 Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::GET_SURROUNDING, std::string(), 0, 0);
469 Dali::InputMethodContext handle(this);
470 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, imfData);
472 if(callbackData.update)
476 *text = strdup(callbackData.currentText.c_str());
481 mIMFCursorPosition = static_cast<int>(callbackData.cursorPosition);
482 *cursorPosition = mIMFCursorPosition;
490 * Called when an InputMethodContext delete surrounding event is received.
491 * Here we tell the application that it should delete a certain range.
493 void InputMethodContextX::DeleteSurrounding(void* data, ImfContext* imfContext, void* eventInfo)
495 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::DeleteSurrounding\n");
497 if(Dali::Adaptor::IsAvailable())
499 Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>(eventInfo);
501 Dali::InputMethodContext::EventData imfData(Dali::InputMethodContext::DELETE_SURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars);
502 Dali::InputMethodContext handle(this);
503 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit(handle, imfData);
505 if(callbackData.update)
507 mIMFCursorPosition = static_cast<int>(callbackData.cursorPosition);
509 NotifyCursorPosition();
514 void InputMethodContextX::NotifyCursorPosition()
516 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::NotifyCursorPosition\n");
520 ecore_imf_context_cursor_position_set(mIMFContext, mIMFCursorPosition);
524 void InputMethodContextX::SetCursorPosition(unsigned int cursorPosition)
526 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::SetCursorPosition\n");
528 mIMFCursorPosition = static_cast<int>(cursorPosition);
531 unsigned int InputMethodContextX::GetCursorPosition() const
533 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::GetCursorPosition\n");
535 return static_cast<unsigned int>(mIMFCursorPosition);
538 void InputMethodContextX::SetSurroundingText(const std::string& text)
540 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::SetSurroundingText\n");
542 mSurroundingText = text;
545 const std::string& InputMethodContextX::GetSurroundingText() const
547 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::GetSurroundingText\n");
549 return mSurroundingText;
552 void InputMethodContextX::NotifyTextInputMultiLine(bool multiLine)
556 Dali::InputMethodContext::TextDirection InputMethodContextX::GetTextDirection()
558 Dali::InputMethodContext::TextDirection direction(Dali::InputMethodContext::LEFT_TO_RIGHT);
563 ecore_imf_context_input_panel_language_locale_get(mIMFContext, &locale);
567 direction = static_cast<Dali::InputMethodContext::TextDirection>(Locale::GetDirection(std::string(locale)));
575 Rect<int> InputMethodContextX::GetInputMethodArea()
577 int xPos, yPos, width, height;
579 width = height = xPos = yPos = 0;
583 ecore_imf_context_input_panel_geometry_get(mIMFContext, &xPos, &yPos, &width, &height);
587 DALI_LOG_WARNING("VKB Unable to get InputMethodContext Context so GetSize unavailable\n");
590 return Rect<int>(xPos, yPos, width, height);
593 void InputMethodContextX::ApplyOptions(const InputMethodOptions& options)
595 using namespace Dali::InputMethod::Category;
599 if(mIMFContext == NULL)
601 DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
605 if(mOptions.CompareAndSet(PANEL_LAYOUT, options, index))
608 if(mOptions.CompareAndSet(BUTTON_ACTION, options, index))
611 if(mOptions.CompareAndSet(AUTO_CAPITALIZE, options, index))
614 if(mOptions.CompareAndSet(VARIATION, options, index))
619 void InputMethodContextX::SetInputPanelData(const std::string& data)
621 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::SetInputPanelData\n");
625 int length = data.length();
626 ecore_imf_context_input_panel_imdata_set(mIMFContext, data.c_str(), length);
630 void InputMethodContextX::GetInputPanelData(std::string& data)
632 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelData\n");
636 int length = 4096; // The max length is 4096 bytes
637 Dali::Vector<char> buffer;
638 buffer.Resize(length);
639 ecore_imf_context_input_panel_imdata_get(mIMFContext, &buffer[0], &length);
640 data = std::string(buffer.Begin(), buffer.End());
644 Dali::InputMethodContext::State InputMethodContextX::GetInputPanelState()
646 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelState\n");
651 value = ecore_imf_context_input_panel_state_get(mIMFContext);
655 case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
657 return Dali::InputMethodContext::SHOW;
661 case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
663 return Dali::InputMethodContext::HIDE;
667 case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
669 return Dali::InputMethodContext::WILL_SHOW;
675 return Dali::InputMethodContext::DEFAULT;
679 return Dali::InputMethodContext::DEFAULT;
682 void InputMethodContextX::SetReturnKeyState(bool visible)
684 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::SetReturnKeyState\n");
688 ecore_imf_context_input_panel_return_key_disabled_set(mIMFContext, !visible);
692 void InputMethodContextX::AutoEnableInputPanel(bool enabled)
694 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::AutoEnableInputPanel\n");
698 ecore_imf_context_input_panel_enabled_set(mIMFContext, enabled);
702 void InputMethodContextX::ShowInputPanel()
704 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::ShowInputPanel\n");
708 ecore_imf_context_input_panel_show(mIMFContext);
712 void InputMethodContextX::HideInputPanel()
714 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::HideInputPanel\n");
718 ecore_imf_context_input_panel_hide(mIMFContext);
722 Dali::InputMethodContext::KeyboardType InputMethodContextX::GetKeyboardType()
724 return Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD;
727 std::string InputMethodContextX::GetInputPanelLocale()
729 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelLocale\n");
731 std::string locale = "";
736 ecore_imf_context_input_panel_language_locale_get(mIMFContext, &value);
740 std::string valueCopy(value);
743 // The locale string retrieved must be freed with free().
750 void InputMethodContextX::SetContentMIMETypes(const std::string& mimeTypes)
752 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::SetContentMIMETypes\n");
753 // ecore_imf_context_mime_type_accept_set() is supported from ecore-imf 1.20.0 version.
756 bool InputMethodContextX::FilterEventKey(const Dali::KeyEvent& keyEvent)
758 bool eventHandled(false);
760 // If a device key then skip ecore_imf_context_filter_event.
761 if(!KeyLookup::IsDeviceButton(keyEvent.GetKeyName().c_str()))
763 //check whether it's key down or key up event
764 if(keyEvent.GetState() == Dali::KeyEvent::DOWN)
766 eventHandled = ProcessEventKeyDown(keyEvent);
768 else if(keyEvent.GetState() == Dali::KeyEvent::UP)
770 eventHandled = ProcessEventKeyUp(keyEvent);
777 void InputMethodContextX::AllowTextPrediction(bool prediction)
779 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::AllowTextPrediction\n");
783 ecore_imf_context_prediction_allow_set(mIMFContext, prediction);
787 bool InputMethodContextX::IsTextPredictionAllowed() const
789 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::IsTextPredictionAllowed\n");
790 bool prediction = false;
793 prediction = ecore_imf_context_prediction_allow_get(mIMFContext);
798 void InputMethodContextX::SetInputPanelLanguage(Dali::InputMethodContext::InputPanelLanguage language)
800 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::SetInputPanelLanguage\n");
805 case Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC:
807 ecore_imf_context_input_panel_language_set(mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC);
810 case Dali::InputMethodContext::InputPanelLanguage::ALPHABET:
812 ecore_imf_context_input_panel_language_set(mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET);
819 Dali::InputMethodContext::InputPanelLanguage InputMethodContextX::GetInputPanelLanguage() const
821 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelLanguage\n");
825 value = ecore_imf_context_input_panel_language_get(mIMFContext);
829 case ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC:
831 return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
834 case ECORE_IMF_INPUT_PANEL_LANG_ALPHABET:
836 return Dali::InputMethodContext::InputPanelLanguage::ALPHABET;
841 return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
844 void InputMethodContextX::SetInputPanelPosition(unsigned int x, unsigned int y)
846 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::SetInputPanelPosition\n");
848 // ecore_imf_context_input_panel_position_set() is supported from ecore-imf 1.21.0 version.
851 void InputMethodContextX::GetPreeditStyle(Dali::InputMethodContext::PreEditAttributeDataContainer& attrs) const
853 DALI_LOG_INFO(gLogFilter, Debug::General, "InputMethodContextX::GetPreeditStyle\n");
854 attrs = mPreeditAttrs;
857 bool InputMethodContextX::ProcessEventKeyDown(const Dali::KeyEvent& keyEvent)
859 bool eventHandled(false);
862 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());
863 std::string key = integKeyEvent.logicalKey;
865 std::string compose = integKeyEvent.compose;
867 // We're consuming key down event so we have to pass to InputMethodContext so that it can parse it as well.
868 Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
869 ecoreKeyDownEvent.keyname = integKeyEvent.keyName.c_str();
870 ecoreKeyDownEvent.key = key.c_str();
871 ecoreKeyDownEvent.string = integKeyEvent.keyString.c_str();
872 ecoreKeyDownEvent.compose = compose.c_str();
873 ecoreKeyDownEvent.timestamp = integKeyEvent.time;
874 ecoreKeyDownEvent.modifiers = EcoreInputModifierToEcoreIMFModifier(integKeyEvent.keyModifier);
875 ecoreKeyDownEvent.locks = EcoreInputModifierToEcoreIMFLock(integKeyEvent.keyModifier);
877 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR)
878 #if(ECORE_VERSION_MINOR >= 14)
879 ecoreKeyDownEvent.dev_name = "";
880 ecoreKeyDownEvent.dev_class = ECORE_IMF_DEVICE_CLASS_KEYBOARD;
881 ecoreKeyDownEvent.dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
882 #endif // Since ecore_imf 1.14 version
883 #if(ECORE_VERSION_MINOR >= 22)
884 ecoreKeyDownEvent.keycode = integKeyEvent.keyCode;
885 #endif // Since ecore_imf 1.22 version
886 #endif // Since ecore_imf Version 1
888 // 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.
889 if((integKeyEvent.deviceName == "ime") && ((!strncmp(integKeyEvent.keyName.c_str(), "Left", 4)) ||
890 (!strncmp(integKeyEvent.keyName.c_str(), "Right", 5)) ||
891 (!strncmp(integKeyEvent.keyName.c_str(), "Up", 2)) ||
892 (!strncmp(integKeyEvent.keyName.c_str(), "Down", 4))))
898 eventHandled = ecore_imf_context_filter_event(mIMFContext,
899 ECORE_IMF_EVENT_KEY_DOWN,
900 reinterpret_cast<Ecore_IMF_Event*>(&ecoreKeyDownEvent));
903 // If the event has not been handled by InputMethodContext then check if we should reset our IMFcontext
906 if(!strcmp(integKeyEvent.keyName.c_str(), "Escape") ||
907 !strcmp(integKeyEvent.keyName.c_str(), "Return") ||
908 !strcmp(integKeyEvent.keyName.c_str(), "KP_Enter"))
910 ecore_imf_context_reset(mIMFContext);
917 bool InputMethodContextX::ProcessEventKeyUp(const Dali::KeyEvent& keyEvent)
919 bool eventHandled(false);
922 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());
924 std::string key = integKeyEvent.logicalKey;
926 std::string compose = integKeyEvent.compose;
928 // We're consuming key up event so we have to pass to InputMethodContext so that it can parse it as well.
929 Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
930 ecoreKeyUpEvent.keyname = integKeyEvent.keyName.c_str();
931 ecoreKeyUpEvent.key = key.c_str();
932 ecoreKeyUpEvent.string = integKeyEvent.keyString.c_str();
933 ecoreKeyUpEvent.compose = compose.c_str();
934 ecoreKeyUpEvent.timestamp = integKeyEvent.time;
935 ecoreKeyUpEvent.modifiers = EcoreInputModifierToEcoreIMFModifier(integKeyEvent.keyModifier);
936 ecoreKeyUpEvent.locks = EcoreInputModifierToEcoreIMFLock(integKeyEvent.keyModifier);
937 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR)
938 #if(ECORE_VERSION_MINOR >= 14)
939 ecoreKeyUpEvent.dev_name = "";
940 #endif // Since ecore_imf 1.14 version
941 #if(ECORE_VERSION_MINOR >= 22)
942 ecoreKeyUpEvent.keycode = integKeyEvent.keyCode;
943 #endif // Since ecore_imf 1.22 version
944 #endif // Since ecore_imf Version 1
946 eventHandled = ecore_imf_context_filter_event(mIMFContext,
947 ECORE_IMF_EVENT_KEY_UP,
948 reinterpret_cast<Ecore_IMF_Event*>(&ecoreKeyUpEvent));
953 Ecore_IMF_Keyboard_Modifiers InputMethodContextX::EcoreInputModifierToEcoreIMFModifier(unsigned int ecoreModifier)
955 unsigned int modifier(ECORE_IMF_KEYBOARD_MODIFIER_NONE); // If no other matches returns NONE.
957 if(ecoreModifier & ECORE_EVENT_MODIFIER_SHIFT) // enums from ecore_input/Ecore_Input.h
959 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT; // enums from ecore_imf/ecore_imf.h
962 if(ecoreModifier & ECORE_EVENT_MODIFIER_ALT)
964 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
967 if(ecoreModifier & ECORE_EVENT_MODIFIER_CTRL)
969 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
972 if(ecoreModifier & ECORE_EVENT_MODIFIER_WIN)
974 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
977 if(ecoreModifier & ECORE_EVENT_MODIFIER_ALTGR)
979 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
982 return static_cast<Ecore_IMF_Keyboard_Modifiers>(modifier);
985 Ecore_IMF_Keyboard_Locks InputMethodContextX::EcoreInputModifierToEcoreIMFLock(unsigned int modifier)
987 unsigned int lock(ECORE_IMF_KEYBOARD_LOCK_NONE); // If no other matches, returns NONE.
989 if(modifier & ECORE_EVENT_LOCK_NUM)
991 lock |= ECORE_IMF_KEYBOARD_LOCK_NUM; // Num lock is active.
994 if(modifier & ECORE_EVENT_LOCK_CAPS)
996 lock |= ECORE_IMF_KEYBOARD_LOCK_CAPS; // Caps lock is active.
999 if(modifier & ECORE_EVENT_LOCK_SCROLL)
1001 lock |= ECORE_IMF_KEYBOARD_LOCK_SCROLL; // Scroll lock is active.
1004 return static_cast<Ecore_IMF_Keyboard_Locks>(lock);
1007 void InputMethodContextX::OnStaged(Dali::Actor actor)
1009 Ecore_X_Window ecoreXwin(AnyCast<Ecore_X_Window>(Dali::Integration::SceneHolder::Get(actor).GetNativeHandle()));
1011 if(mEcoreXwin != ecoreXwin)
1013 mEcoreXwin = ecoreXwin;
1021 } // namespace Adaptor
1023 } // namespace Internal