2 * Copyright (c) 2020 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/public-api/events/key-event.h>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/devel-api/common/singleton-service.h>
25 #include <dali/integration-api/debug.h>
28 #include <dali/public-api/adaptor-framework/key.h>
29 #include <dali/integration-api/adaptor-framework/adaptor.h>
30 #include <dali/internal/adaptor/common/adaptor-impl.h>
31 #include <dali/internal/input/common/key-impl.h>
32 #include <dali/internal/input/common/virtual-keyboard-impl.h>
33 #include <dali/internal/input/linux/dali-ecore-imf.h>
34 #include <dali/internal/input/tizen-wayland/ecore-virtual-keyboard.h>
35 #include <dali/internal/input/ubuntu-x11/dali-ecore-input.h>
36 #include <dali/internal/system/common/locale-utils.h>
37 #include <dali/internal/system/linux/dali-ecore.h>
50 #if defined(DEBUG_ENABLED)
51 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_INPUT_METHOD_CONTEXT");
54 // Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead.
55 size_t Utf8SequenceLength(const unsigned char leadByte)
59 if( ( leadByte & 0x80 ) == 0 ) //ASCII character (lead bit zero)
63 else if( ( leadByte & 0xe0 ) == 0xc0 ) //110x xxxx
67 else if( ( leadByte & 0xf0 ) == 0xe0 ) //1110 xxxx
71 else if( ( leadByte & 0xf8 ) == 0xf0 ) //1111 0xxx
75 else if( ( leadByte & 0xfc ) == 0xf8 ) //1111 10xx
79 else if( ( leadByte & 0xfe ) == 0xfc ) //1111 110x
87 // Static function calls used by ecore 'c' style callback registration
88 void Commit( void *data, Ecore_IMF_Context *imfContext, void *eventInfo )
92 InputMethodContextX* inputMethodContext = static_cast< InputMethodContextX* >( data );
93 inputMethodContext->CommitReceived( data, imfContext, eventInfo );
97 void PreEdit( void *data, Ecore_IMF_Context *imfContext, void *eventInfo )
101 InputMethodContextX* inputMethodContext = static_cast< InputMethodContextX* >( data );
102 inputMethodContext->PreEditChanged( data, imfContext, eventInfo );
106 Eina_Bool ImfRetrieveSurrounding(void *data, Ecore_IMF_Context *imfContext, char** text, int* cursorPosition )
110 InputMethodContextX* inputMethodContext = static_cast< InputMethodContextX* >( data );
111 return inputMethodContext->RetrieveSurrounding( data, imfContext, text, cursorPosition );
120 * Called when an InputMethodContext delete surrounding event is received.
121 * Here we tell the application that it should delete a certain range.
123 void ImfDeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *eventInfo )
127 InputMethodContextX* inputMethodContext = static_cast< InputMethodContextX* >( data );
128 inputMethodContext->DeleteSurrounding( data, imfContext, eventInfo );
132 } // unnamed namespace
134 InputMethodContextPtr InputMethodContextX::New( Dali::Actor actor )
136 InputMethodContextPtr manager;
138 if( actor && Dali::Adaptor::IsAvailable() )
140 manager = new InputMethodContextX( actor );
146 void InputMethodContextX::Finalize()
148 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::Finalize\n" );
149 VirtualKeyboard::DisconnectCallbacks( mIMFContext );
150 DisconnectCallbacks();
154 InputMethodContextX::InputMethodContextX( Dali::Actor actor )
157 mIMFCursorPosition( 0 ),
159 mRestoreAfterFocusLost( false ),
160 mIdleCallbackConnected( false )
164 actor.OnSceneSignal().Connect( this, &InputMethodContextX::OnStaged );
167 InputMethodContextX::~InputMethodContextX()
170 ecore_imf_shutdown();
173 void InputMethodContextX::Initialize()
177 VirtualKeyboard::ConnectCallbacks( mIMFContext );
180 void InputMethodContextX::CreateContext()
182 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::CreateContext\n" );
189 const char *contextId = ecore_imf_context_default_id_get();
192 mIMFContext = ecore_imf_context_add( contextId );
196 ecore_imf_context_client_window_set( mIMFContext, reinterpret_cast<void*>( mEcoreXwin ) );
200 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContext Unable to get IMFContext\n");
205 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContext Unable to get IMFContext\n");
209 void InputMethodContextX::DeleteContext()
211 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::DeleteContext\n" );
215 ecore_imf_context_del( mIMFContext );
220 // Callbacks for predicitive text support.
221 void InputMethodContextX::ConnectCallbacks()
225 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::ConnectCallbacks\n" );
227 ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit, this );
228 ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit, this );
229 ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding, this );
231 ecore_imf_context_retrieve_surrounding_callback_set( mIMFContext, ImfRetrieveSurrounding, this);
235 void InputMethodContextX::DisconnectCallbacks()
239 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::DisconnectCallbacks\n" );
241 ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit );
242 ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit );
243 ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding );
245 // We do not need to unset the retrieve surrounding callback.
249 void InputMethodContextX::Activate()
251 // Reset mIdleCallbackConnected
252 mIdleCallbackConnected = false;
256 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::Activate\n" );
258 ecore_imf_context_focus_in( mIMFContext );
260 // emit keyboard activated signal
261 Dali::InputMethodContext handle( this );
262 mActivatedSignal.Emit( handle );
266 void InputMethodContextX::Deactivate()
270 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::Deactivate\n" );
273 ecore_imf_context_focus_out( mIMFContext );
276 // Reset mIdleCallbackConnected
277 mIdleCallbackConnected = false;
280 void InputMethodContextX::Reset()
282 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::Reset\n" );
286 ecore_imf_context_reset( mIMFContext );
290 ImfContext* InputMethodContextX::GetContext()
292 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetContext\n" );
297 bool InputMethodContextX::RestoreAfterFocusLost() const
299 return mRestoreAfterFocusLost;
302 void InputMethodContextX::SetRestoreAfterFocusLost( bool toggle )
304 mRestoreAfterFocusLost = toggle;
308 * Called when an InputMethodContext Pre-Edit changed event is received.
309 * We are still predicting what the user is typing. The latest string is what the InputMethodContext module thinks
310 * the user wants to type.
312 void InputMethodContextX::PreEditChanged( void*, ImfContext* imfContext, void* eventInfo )
314 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::PreEditChanged\n" );
315 auto context = static_cast<Ecore_IMF_Context*>( imfContext );
317 char* preEditString( NULL );
318 int cursorPosition( 0 );
319 Eina_List* attrs = NULL;
322 Ecore_IMF_Preedit_Attr* attr;
324 mPreeditAttrs.Clear();
326 // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string.
327 // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string.
328 ecore_imf_context_preedit_string_with_attributes_get( context, &preEditString, &attrs, &cursorPosition );
332 // iterate through the list of attributes getting the type, start and end position.
333 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) ) ))
335 Dali::InputMethodContext::PreeditAttributeData data;
339 size_t visualCharacterIndex = 0;
340 size_t byteIndex = 0;
342 // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
343 char leadByte = preEditString[byteIndex];
345 while( leadByte != '\0' )
347 leadByte = preEditString[byteIndex]; // Update the character to get the number of its byte
349 // attr->end_index is provided as a byte position not character and we need to know the character position.
350 const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character.
351 if( byteIndex <= attr->start_index )
353 data.startIndex = visualCharacterIndex;
355 if( byteIndex >= attr->end_index )
357 data.endIndex = visualCharacterIndex;
359 // end loop as found cursor position that matches byte position
363 byteIndex += currentSequenceLength; // jump to next character
364 visualCharacterIndex++; // increment character count so we know our position for when we get a match
368 switch( attr->preedit_type )
370 case ECORE_IMF_PREEDIT_TYPE_NONE:
372 data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
375 case ECORE_IMF_PREEDIT_TYPE_SUB1:
377 data.preeditType = Dali::InputMethodContext::PreeditStyle::UNDERLINE;
380 case ECORE_IMF_PREEDIT_TYPE_SUB2:
382 data.preeditType = Dali::InputMethodContext::PreeditStyle::REVERSE;
385 case ECORE_IMF_PREEDIT_TYPE_SUB3:
387 data.preeditType = Dali::InputMethodContext::PreeditStyle::HIGHLIGHT;
390 case ECORE_IMF_PREEDIT_TYPE_SUB4:
392 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1;
395 case ECORE_IMF_PREEDIT_TYPE_SUB5:
397 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2;
400 case ECORE_IMF_PREEDIT_TYPE_SUB6:
402 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3;
405 case ECORE_IMF_PREEDIT_TYPE_SUB7:
407 data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4;
412 data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE;
416 mPreeditAttrs.PushBack( data );
420 if ( Dali::Adaptor::IsAvailable() )
422 Dali::InputMethodContext handle( this );
423 Dali::InputMethodContext::EventData eventData( Dali::InputMethodContext::PRE_EDIT, preEditString, cursorPosition, 0 );
424 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, eventData );
426 if( callbackData.update )
428 mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
430 NotifyCursorPosition();
433 if( callbackData.preeditResetRequired )
438 free( preEditString );
441 void InputMethodContextX::CommitReceived( void*, ImfContext* imfContext, void* eventInfo )
443 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::CommitReceived\n" );
445 if ( Dali::Adaptor::IsAvailable() )
447 const std::string keyString( static_cast<char*>( eventInfo ) );
449 Dali::InputMethodContext handle( this );
450 Dali::InputMethodContext::EventData eventData( Dali::InputMethodContext::COMMIT, keyString, 0, 0 );
451 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, eventData );
453 if( callbackData.update )
455 mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
457 NotifyCursorPosition();
463 * Called when an InputMethodContext retrieve surround event is received.
464 * Here the InputMethodContext module wishes to know the string we are working with and where within the string the cursor is
465 * We need to signal the application to tell us this information.
467 bool InputMethodContextX::RetrieveSurrounding( void* data, ImfContext* imfContext, char** text, int* cursorPosition )
469 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::RetrieveSurrounding\n" );
471 Dali::InputMethodContext::EventData imfData( Dali::InputMethodContext::GET_SURROUNDING, std::string(), 0, 0 );
472 Dali::InputMethodContext handle( this );
473 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, imfData );
475 if( callbackData.update )
479 *text = strdup( callbackData.currentText.c_str() );
484 mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
485 *cursorPosition = mIMFCursorPosition;
493 * Called when an InputMethodContext delete surrounding event is received.
494 * Here we tell the application that it should delete a certain range.
496 void InputMethodContextX::DeleteSurrounding( void* data, ImfContext* imfContext, void* eventInfo )
498 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::DeleteSurrounding\n" );
500 if( Dali::Adaptor::IsAvailable() )
502 Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>( eventInfo );
504 Dali::InputMethodContext::EventData imfData( Dali::InputMethodContext::DELETE_SURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars );
505 Dali::InputMethodContext handle( this );
506 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, imfData );
508 if( callbackData.update )
510 mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
512 NotifyCursorPosition();
517 void InputMethodContextX::NotifyCursorPosition()
519 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::NotifyCursorPosition\n" );
523 ecore_imf_context_cursor_position_set( mIMFContext, mIMFCursorPosition );
527 void InputMethodContextX::SetCursorPosition( unsigned int cursorPosition )
529 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetCursorPosition\n" );
531 mIMFCursorPosition = static_cast<int>( cursorPosition );
534 unsigned int InputMethodContextX::GetCursorPosition() const
536 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetCursorPosition\n" );
538 return static_cast<unsigned int>( mIMFCursorPosition );
541 void InputMethodContextX::SetSurroundingText( const std::string& text )
543 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetSurroundingText\n" );
545 mSurroundingText = text;
548 const std::string& InputMethodContextX::GetSurroundingText() const
550 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetSurroundingText\n" );
552 return mSurroundingText;
555 void InputMethodContextX::NotifyTextInputMultiLine( bool multiLine )
559 Dali::InputMethodContext::TextDirection InputMethodContextX::GetTextDirection()
561 Dali::InputMethodContext::TextDirection direction ( Dali::InputMethodContext::LeftToRight );
565 char* locale( NULL );
566 ecore_imf_context_input_panel_language_locale_get( mIMFContext, &locale );
570 direction = static_cast< Dali::InputMethodContext::TextDirection >( Locale::GetDirection( std::string( locale ) ) );
578 Rect<int> InputMethodContextX::GetInputMethodArea()
580 int xPos, yPos, width, height;
582 width = height = xPos = yPos = 0;
586 ecore_imf_context_input_panel_geometry_get( mIMFContext, &xPos, &yPos, &width, &height );
590 DALI_LOG_WARNING("VKB Unable to get InputMethodContext Context so GetSize unavailable\n");
593 return Rect<int>(xPos,yPos,width,height);
596 void InputMethodContextX::ApplyOptions( const InputMethodOptions& options )
598 using namespace Dali::InputMethod::Category;
602 if (mIMFContext == NULL)
604 DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
608 if ( mOptions.CompareAndSet(PANEL_LAYOUT, options, index) )
611 if ( mOptions.CompareAndSet(BUTTON_ACTION, options, index) )
614 if ( mOptions.CompareAndSet(AUTO_CAPITALIZE, options, index) )
617 if ( mOptions.CompareAndSet(VARIATION, options, index) )
622 void InputMethodContextX::SetInputPanelData( const std::string& data )
624 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetInputPanelData\n" );
628 int length = data.length();
629 ecore_imf_context_input_panel_imdata_set( mIMFContext, data.c_str(), length );
633 void InputMethodContextX::GetInputPanelData( std::string& data )
635 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelData\n" );
639 int length = 4096; // The max length is 4096 bytes
640 Dali::Vector< char > buffer;
641 buffer.Resize( length );
642 ecore_imf_context_input_panel_imdata_get( mIMFContext, &buffer[0], &length );
643 data = std::string( buffer.Begin(), buffer.End() );
647 Dali::InputMethodContext::State InputMethodContextX::GetInputPanelState()
649 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelState\n" );
654 value = ecore_imf_context_input_panel_state_get( mIMFContext );
658 case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
660 return Dali::InputMethodContext::SHOW;
664 case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
666 return Dali::InputMethodContext::HIDE;
670 case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
672 return Dali::InputMethodContext::WILL_SHOW;
678 return Dali::InputMethodContext::DEFAULT;
682 return Dali::InputMethodContext::DEFAULT;
685 void InputMethodContextX::SetReturnKeyState( bool visible )
687 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetReturnKeyState\n" );
691 ecore_imf_context_input_panel_return_key_disabled_set( mIMFContext, !visible );
695 void InputMethodContextX::AutoEnableInputPanel( bool enabled )
697 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::AutoEnableInputPanel\n" );
701 ecore_imf_context_input_panel_enabled_set( mIMFContext, enabled );
705 void InputMethodContextX::ShowInputPanel()
707 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::ShowInputPanel\n" );
711 ecore_imf_context_input_panel_show( mIMFContext );
715 void InputMethodContextX::HideInputPanel()
717 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::HideInputPanel\n" );
721 ecore_imf_context_input_panel_hide( mIMFContext );
725 Dali::InputMethodContext::KeyboardType InputMethodContextX::GetKeyboardType()
727 return Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD;
730 std::string InputMethodContextX::GetInputPanelLocale()
732 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelLocale\n" );
734 std::string locale = "";
739 ecore_imf_context_input_panel_language_locale_get( mIMFContext, &value );
743 std::string valueCopy( value );
746 // The locale string retrieved must be freed with free().
753 void InputMethodContextX::SetContentMIMETypes( const std::string& mimeTypes )
755 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetContentMIMETypes\n" );
756 // ecore_imf_context_mime_type_accept_set() is supported from ecore-imf 1.20.0 version.
759 bool InputMethodContextX::FilterEventKey( const Dali::KeyEvent& keyEvent )
761 bool eventHandled( false );
763 // If a device key then skip ecore_imf_context_filter_event.
764 if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ))
766 //check whether it's key down or key up event
767 if ( keyEvent.state == KeyEvent::Down )
769 eventHandled = ProcessEventKeyDown( keyEvent );
771 else if ( keyEvent.state == KeyEvent::Up )
773 eventHandled = ProcessEventKeyUp( keyEvent );
780 void InputMethodContextX::AllowTextPrediction( bool prediction )
782 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::AllowTextPrediction\n" );
786 ecore_imf_context_prediction_allow_set( mIMFContext, prediction );
790 bool InputMethodContextX::IsTextPredictionAllowed() const
792 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::IsTextPredictionAllowed\n" );
793 bool prediction = false;
796 prediction = ecore_imf_context_prediction_allow_get( mIMFContext );
801 void InputMethodContextX::SetInputPanelLanguage( Dali::InputMethodContext::InputPanelLanguage language )
803 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetInputPanelLanguage\n" );
808 case Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC:
810 ecore_imf_context_input_panel_language_set( mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC );
813 case Dali::InputMethodContext::InputPanelLanguage::ALPHABET:
815 ecore_imf_context_input_panel_language_set( mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET );
822 Dali::InputMethodContext::InputPanelLanguage InputMethodContextX::GetInputPanelLanguage() const
824 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelLanguage\n" );
828 value = ecore_imf_context_input_panel_language_get( mIMFContext );
832 case ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC:
834 return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
837 case ECORE_IMF_INPUT_PANEL_LANG_ALPHABET:
839 return Dali::InputMethodContext::InputPanelLanguage::ALPHABET;
844 return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
847 void InputMethodContextX::SetInputPanelPosition( unsigned int x, unsigned int y )
849 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetInputPanelPosition\n" );
851 // ecore_imf_context_input_panel_position_set() is supported from ecore-imf 1.21.0 version.
854 void InputMethodContextX::GetPreeditStyle( Dali::InputMethodContext::PreEditAttributeDataContainer& attrs ) const
856 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetPreeditStyle\n" );
857 attrs = mPreeditAttrs;
860 bool InputMethodContextX::ProcessEventKeyDown( const KeyEvent& keyEvent )
862 bool eventHandled( false );
865 Integration::KeyEvent integKeyEvent( keyEvent );
866 std::string key = integKeyEvent.logicalKey;
868 std::string compose = keyEvent.GetCompose();
870 // We're consuming key down event so we have to pass to InputMethodContext so that it can parse it as well.
871 Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
872 ecoreKeyDownEvent.keyname = keyEvent.keyPressedName.c_str();
873 ecoreKeyDownEvent.key = key.c_str();
874 ecoreKeyDownEvent.string = keyEvent.keyPressed.c_str();
875 ecoreKeyDownEvent.compose = compose.c_str();
876 ecoreKeyDownEvent.timestamp = keyEvent.time;
877 ecoreKeyDownEvent.modifiers = EcoreInputModifierToEcoreIMFModifier( keyEvent.keyModifier );
878 ecoreKeyDownEvent.locks = EcoreInputModifierToEcoreIMFLock( keyEvent.keyModifier );
880 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR)
881 #if (ECORE_VERSION_MINOR >= 14)
882 ecoreKeyDownEvent.dev_name = "";
883 ecoreKeyDownEvent.dev_class = ECORE_IMF_DEVICE_CLASS_KEYBOARD;
884 ecoreKeyDownEvent.dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
885 #endif // Since ecore_imf 1.14 version
886 #if (ECORE_VERSION_MINOR >= 22)
887 ecoreKeyDownEvent.keycode = keyEvent.keyCode;
888 #endif // Since ecore_imf 1.22 version
889 #endif // Since ecore_imf Version 1
891 // 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.
892 if ((keyEvent.GetDeviceName() == "ime") && ((!strncmp(keyEvent.keyPressedName.c_str(), "Left", 4)) ||
893 (!strncmp(keyEvent.keyPressedName.c_str(), "Right", 5)) ||
894 (!strncmp(keyEvent.keyPressedName.c_str(), "Up", 2)) ||
895 (!strncmp(keyEvent.keyPressedName.c_str(), "Down", 4))))
901 eventHandled = ecore_imf_context_filter_event(mIMFContext,
902 ECORE_IMF_EVENT_KEY_DOWN,
903 reinterpret_cast<Ecore_IMF_Event *>( &ecoreKeyDownEvent ));
906 // If the event has not been handled by InputMethodContext then check if we should reset our IMFcontext
909 if (!strcmp(keyEvent.keyPressedName.c_str(), "Escape") ||
910 !strcmp(keyEvent.keyPressedName.c_str(), "Return") ||
911 !strcmp(keyEvent.keyPressedName.c_str(), "KP_Enter"))
913 ecore_imf_context_reset(mIMFContext);
920 bool InputMethodContextX::ProcessEventKeyUp( const KeyEvent& keyEvent )
922 bool eventHandled( false );
925 Integration::KeyEvent integKeyEvent( keyEvent );
926 std::string key = integKeyEvent.logicalKey;
928 std::string compose = keyEvent.GetCompose();
930 // We're consuming key up event so we have to pass to InputMethodContext so that it can parse it as well.
931 Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
932 ecoreKeyUpEvent.keyname = keyEvent.keyPressedName.c_str();
933 ecoreKeyUpEvent.key = key.c_str();
934 ecoreKeyUpEvent.string = keyEvent.keyPressed.c_str();
935 ecoreKeyUpEvent.compose = compose.c_str();
936 ecoreKeyUpEvent.timestamp = keyEvent.time;
937 ecoreKeyUpEvent.modifiers = EcoreInputModifierToEcoreIMFModifier( keyEvent.keyModifier );
938 ecoreKeyUpEvent.locks = EcoreInputModifierToEcoreIMFLock( keyEvent.keyModifier );
939 #if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR)
940 #if (ECORE_VERSION_MINOR >= 14)
941 ecoreKeyUpEvent.dev_name = "";
942 #endif // Since ecore_imf 1.14 version
943 #if (ECORE_VERSION_MINOR >= 22)
944 ecoreKeyUpEvent.keycode = keyEvent.keyCode;
945 #endif // Since ecore_imf 1.22 version
946 #endif // Since ecore_imf Version 1
948 eventHandled = ecore_imf_context_filter_event(mIMFContext,
949 ECORE_IMF_EVENT_KEY_UP,
950 reinterpret_cast<Ecore_IMF_Event *>( &ecoreKeyUpEvent ));
955 Ecore_IMF_Keyboard_Modifiers InputMethodContextX::EcoreInputModifierToEcoreIMFModifier( unsigned int ecoreModifier )
957 unsigned int modifier( ECORE_IMF_KEYBOARD_MODIFIER_NONE ); // If no other matches returns NONE.
959 if ( ecoreModifier & ECORE_EVENT_MODIFIER_SHIFT ) // enums from ecore_input/Ecore_Input.h
961 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT; // enums from ecore_imf/ecore_imf.h
964 if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALT )
966 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
969 if ( ecoreModifier & ECORE_EVENT_MODIFIER_CTRL )
971 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
974 if ( ecoreModifier & ECORE_EVENT_MODIFIER_WIN )
976 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
979 if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALTGR )
981 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
984 return static_cast<Ecore_IMF_Keyboard_Modifiers>( modifier );
987 Ecore_IMF_Keyboard_Locks InputMethodContextX::EcoreInputModifierToEcoreIMFLock( unsigned int modifier )
989 unsigned int lock( ECORE_IMF_KEYBOARD_LOCK_NONE ); // If no other matches, returns NONE.
991 if( modifier & ECORE_EVENT_LOCK_NUM )
993 lock |= ECORE_IMF_KEYBOARD_LOCK_NUM; // Num lock is active.
996 if( modifier & ECORE_EVENT_LOCK_CAPS )
998 lock |= ECORE_IMF_KEYBOARD_LOCK_CAPS; // Caps lock is active.
1001 if( modifier & ECORE_EVENT_LOCK_SCROLL )
1003 lock |= ECORE_IMF_KEYBOARD_LOCK_SCROLL; // Scroll lock is active.
1006 return static_cast<Ecore_IMF_Keyboard_Locks>( lock );
1009 void InputMethodContextX::OnStaged( Dali::Actor actor )
1011 Ecore_X_Window ecoreXwin( AnyCast< Ecore_X_Window >( Dali::Integration::SceneHolder::Get( actor ).GetNativeHandle() ) );
1013 if( mEcoreXwin != ecoreXwin )
1015 mEcoreXwin = ecoreXwin;