2 * Copyright (c) 2018 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 <Ecore_IMF.h>
23 #include <Ecore_Input.h>
24 #include <dali/public-api/events/key-event.h>
25 #include <dali/public-api/adaptor-framework/key.h>
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/integration-api/debug.h>
30 #include <dali/integration-api/adaptor.h>
31 #include <dali/internal/window-system/ubuntu-x11/window-render-surface-x.h>
32 #include <dali/internal/adaptor/common/adaptor-impl.h>
33 #include <dali/internal/system/common/locale-utils.h>
34 #include <dali/internal/system/common/singleton-service-impl.h>
35 #include <dali/internal/input/common/virtual-keyboard-impl.h>
36 #include <dali/internal/input/common/key-impl.h>
37 // Ecore is littered with C style cast
38 #pragma GCC diagnostic push
39 #pragma GCC diagnostic ignored "-Wold-style-cast"
40 #include <dali/internal/input/tizen-wayland/ecore-virtual-keyboard.h>
53 #if defined(DEBUG_ENABLED)
54 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_INPUT_METHOD_CONTEXT");
57 // Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead.
58 size_t Utf8SequenceLength(const unsigned char leadByte)
62 if ((leadByte & 0x80) == 0 ) //ASCII character (lead bit zero)
66 else if (( leadByte & 0xe0 ) == 0xc0 ) //110x xxxx
70 else if (( leadByte & 0xf0 ) == 0xe0 ) //1110 xxxx
74 else if (( leadByte & 0xf8 ) == 0xf0 ) //1111 0xxx
82 // Static function calls used by ecore 'c' style callback registration
83 void Commit( void *data, Ecore_IMF_Context *imfContext, void *event_info )
87 InputMethodContextX* inputMethodContext = reinterpret_cast< InputMethodContextX* > ( data );
88 inputMethodContext->CommitReceived( data, imfContext, event_info );
92 void PreEdit( void *data, Ecore_IMF_Context *imfContext, void *event_info )
96 InputMethodContextX* inputMethodContext = reinterpret_cast< InputMethodContextX* > ( data );
97 inputMethodContext->PreEditChanged( data, imfContext, event_info );
101 Eina_Bool ImfRetrieveSurrounding(void *data, Ecore_IMF_Context *imfContext, char** text, int* cursorPosition )
105 InputMethodContextX* inputMethodContext = reinterpret_cast< InputMethodContextX* > ( data );
106 return inputMethodContext->RetrieveSurrounding( data, imfContext, text, cursorPosition );
115 * Called when an InputMethodContext delete surrounding event is received.
116 * Here we tell the application that it should delete a certain range.
118 void ImfDeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *event_info )
122 InputMethodContextX* inputMethodContext = reinterpret_cast< InputMethodContextX* > ( data );
123 inputMethodContext->DeleteSurrounding( data, imfContext, event_info );
127 } // unnamed namespace
129 InputMethodContextPtr InputMethodContextX::New()
131 InputMethodContextPtr manager;
133 if ( Adaptor::IsAvailable() )
135 // Create instance and register singleton only if the adaptor is available
136 Adaptor& adaptorImpl( Adaptor::GetImplementation( Adaptor::Get() ) );
137 Any nativeWindow = adaptorImpl.GetNativeWindowHandle();
139 // The Ecore_X_Window needs to use the InputMethodContext.
140 // Only when the render surface is window, we can get the Ecore_X_Window.
141 Ecore_X_Window ecoreXwin( AnyCast<Ecore_X_Window>(nativeWindow) );
144 // If we fail to get Ecore_X_Window, we can't use the InputMethodContext correctly.
145 // Thus you have to call "ecore_imf_context_client_window_set" somewhere.
146 // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent().
148 manager = new InputMethodContextX( ecoreXwin );
152 DALI_LOG_ERROR("Failed to get native window handle\n");
159 void InputMethodContextX::Finalize()
161 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::Finalize\n" );
162 VirtualKeyboard::DisconnectCallbacks( mIMFContext );
163 DisconnectCallbacks();
167 InputMethodContextX::InputMethodContextX( Ecore_X_Window ecoreXwin )
169 mEcoreXwin( ecoreXwin ),
170 mIMFCursorPosition( 0 ),
172 mRestoreAfterFocusLost( false ),
173 mIdleCallbackConnected( false )
178 InputMethodContextX::~InputMethodContextX()
181 ecore_imf_shutdown();
184 void InputMethodContextX::Initialize()
186 CreateContext( mEcoreXwin );
188 VirtualKeyboard::ConnectCallbacks( mIMFContext );
191 void InputMethodContextX::CreateContext( Ecore_X_Window ecoreXwin )
193 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::CreateContext\n" );
195 const char *contextId = ecore_imf_context_default_id_get();
198 mIMFContext = ecore_imf_context_add( contextId );
204 ecore_imf_context_client_window_set( mIMFContext, reinterpret_cast<void*>( ecoreXwin ) );
209 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContext Unable to get IMFContext\n");
214 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContext Unable to get IMFContext\n");
218 void InputMethodContextX::DeleteContext()
220 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::DeleteContext\n" );
224 ecore_imf_context_del( mIMFContext );
229 // Callbacks for predicitive text support.
230 void InputMethodContextX::ConnectCallbacks()
234 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::ConnectCallbacks\n" );
236 ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit, this );
237 ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit, this );
238 ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding, this );
240 ecore_imf_context_retrieve_surrounding_callback_set( mIMFContext, ImfRetrieveSurrounding, this);
244 void InputMethodContextX::DisconnectCallbacks()
248 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::DisconnectCallbacks\n" );
250 ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, PreEdit );
251 ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit );
252 ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding );
254 // We do not need to unset the retrieve surrounding callback.
258 void InputMethodContextX::Activate()
260 // Reset mIdleCallbackConnected
261 mIdleCallbackConnected = false;
265 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::Activate\n" );
267 ecore_imf_context_focus_in( mIMFContext );
269 // emit keyboard activated signal
270 Dali::InputMethodContext handle( this );
271 mActivatedSignal.Emit( handle );
275 void InputMethodContextX::Deactivate()
279 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::Deactivate\n" );
282 ecore_imf_context_focus_out( mIMFContext );
285 // Reset mIdleCallbackConnected
286 mIdleCallbackConnected = false;
289 void InputMethodContextX::Reset()
291 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::Reset\n" );
295 ecore_imf_context_reset( mIMFContext );
299 ImfContext* InputMethodContextX::GetContext()
301 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetContext\n" );
306 bool InputMethodContextX::RestoreAfterFocusLost() const
308 return mRestoreAfterFocusLost;
311 void InputMethodContextX::SetRestoreAfterFocusLost( bool toggle )
313 mRestoreAfterFocusLost = toggle;
317 * Called when an InputMethodContext Pre-Edit changed event is received.
318 * We are still predicting what the user is typing. The latest string is what the InputMethodContext module thinks
319 * the user wants to type.
321 void InputMethodContextX::PreEditChanged( void*, ImfContext* imfContext, void* event_info )
323 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::PreEditChanged\n" );
324 auto context = reinterpret_cast<Ecore_IMF_Context*>(imfContext);
326 char* preEditString( NULL );
327 int cursorPosition( 0 );
328 Eina_List* attrs = NULL;
331 Ecore_IMF_Preedit_Attr* attr;
333 // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string.
334 // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string.
335 ecore_imf_context_preedit_string_with_attributes_get( context, &preEditString, &attrs, &cursorPosition );
339 // iterate through the list of attributes getting the type, start and end position.
340 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) ) ))
342 #ifdef DALI_PROFILE_UBUNTU
343 if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3 ) // (Ecore_IMF)
344 #else // DALI_PROFILE_UBUNTU
345 if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB4 ) // (Ecore_IMF)
346 #endif // DALI_PROFILE_UBUNTU
348 // check first byte so know how many bytes a character is represented by as keyboard returns cursor position in bytes. Which is different for some languages.
350 size_t visualCharacterIndex = 0;
351 size_t byteIndex = 0;
353 // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
354 const char leadByte = preEditString[byteIndex];
355 while( leadByte != '\0' )
357 // attr->end_index is provided as a byte position not character and we need to know the character position.
358 const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character.
359 if ( byteIndex == attr->end_index )
361 cursorPosition = visualCharacterIndex;
363 // end loop as found cursor position that matches byte position
367 byteIndex += currentSequenceLength; // jump to next character
368 visualCharacterIndex++; // increment character count so we know our position for when we get a match
371 DALI_ASSERT_DEBUG( visualCharacterIndex < strlen( preEditString ));
377 if ( Dali::Adaptor::IsAvailable() )
379 Dali::InputMethodContext handle( this );
380 Dali::InputMethodContext::EventData eventData( Dali::InputMethodContext::PRE_EDIT, preEditString, cursorPosition, 0 );
381 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, eventData );
383 if( callbackData.update )
385 mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
387 NotifyCursorPosition();
390 if( callbackData.preeditResetRequired )
395 free( preEditString );
398 void InputMethodContextX::CommitReceived( void*, ImfContext* imfContext, void* event_info )
400 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::CommitReceived\n" );
402 if ( Dali::Adaptor::IsAvailable() )
404 const std::string keyString( static_cast<char*>( event_info ) );
406 Dali::InputMethodContext handle( this );
407 Dali::InputMethodContext::EventData eventData( Dali::InputMethodContext::COMMIT, keyString, 0, 0 );
408 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, eventData );
410 if( callbackData.update )
412 mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
414 NotifyCursorPosition();
420 * Called when an InputMethodContext retrieve surround event is received.
421 * Here the InputMethodContext module wishes to know the string we are working with and where within the string the cursor is
422 * We need to signal the application to tell us this information.
424 bool InputMethodContextX::RetrieveSurrounding( void* data, ImfContext* imfContext, char** text, int* cursorPosition )
426 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::RetrieveSurrounding\n" );
428 Dali::InputMethodContext::EventData imfData( Dali::InputMethodContext::GET_SURROUNDING, std::string(), 0, 0 );
429 Dali::InputMethodContext handle( this );
430 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, imfData );
432 if( callbackData.update )
436 *text = strdup( callbackData.currentText.c_str() );
441 mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
442 *cursorPosition = mIMFCursorPosition;
450 * Called when an InputMethodContext delete surrounding event is received.
451 * Here we tell the application that it should delete a certain range.
453 void InputMethodContextX::DeleteSurrounding( void* data, ImfContext* imfContext, void* event_info )
455 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::DeleteSurrounding\n" );
457 if( Dali::Adaptor::IsAvailable() )
459 Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>( event_info );
461 Dali::InputMethodContext::EventData imfData( Dali::InputMethodContext::DELETE_SURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars );
462 Dali::InputMethodContext handle( this );
463 Dali::InputMethodContext::CallbackData callbackData = mEventSignal.Emit( handle, imfData );
465 if( callbackData.update )
467 mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
469 NotifyCursorPosition();
474 void InputMethodContextX::NotifyCursorPosition()
476 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::NotifyCursorPosition\n" );
480 ecore_imf_context_cursor_position_set( mIMFContext, mIMFCursorPosition );
484 void InputMethodContextX::SetCursorPosition( unsigned int cursorPosition )
486 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetCursorPosition\n" );
488 mIMFCursorPosition = static_cast<int>( cursorPosition );
491 unsigned int InputMethodContextX::GetCursorPosition() const
493 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetCursorPosition\n" );
495 return static_cast<unsigned int>( mIMFCursorPosition );
498 void InputMethodContextX::SetSurroundingText( const std::string& text )
500 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetSurroundingText\n" );
502 mSurroundingText = text;
505 const std::string& InputMethodContextX::GetSurroundingText() const
507 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetSurroundingText\n" );
509 return mSurroundingText;
512 void InputMethodContextX::NotifyTextInputMultiLine( bool multiLine )
516 Dali::InputMethodContext::TextDirection InputMethodContextX::GetTextDirection()
518 Dali::InputMethodContext::TextDirection direction ( Dali::InputMethodContext::LeftToRight );
522 char* locale( NULL );
523 ecore_imf_context_input_panel_language_locale_get( mIMFContext, &locale );
527 direction = static_cast< Dali::InputMethodContext::TextDirection >( Locale::GetDirection( std::string( locale ) ) );
535 Rect<int> InputMethodContextX::GetInputMethodArea()
537 int xPos, yPos, width, height;
539 width = height = xPos = yPos = 0;
543 ecore_imf_context_input_panel_geometry_get( mIMFContext, &xPos, &yPos, &width, &height );
547 DALI_LOG_WARNING("VKB Unable to get InputMethodContext Context so GetSize unavailable\n");
550 return Rect<int>(xPos,yPos,width,height);
553 void InputMethodContextX::ApplyOptions( const InputMethodOptions& options )
555 using namespace Dali::InputMethod::Category;
559 if (mIMFContext == NULL)
561 DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
565 if ( mOptions.CompareAndSet(PANEL_LAYOUT, options, index) )
568 if ( mOptions.CompareAndSet(BUTTON_ACTION, options, index) )
571 if ( mOptions.CompareAndSet(AUTO_CAPITALIZE, options, index) )
574 if ( mOptions.CompareAndSet(VARIATION, options, index) )
579 void InputMethodContextX::SetInputPanelData( const std::string& data )
581 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetInputPanelData\n" );
585 int length = data.length();
586 ecore_imf_context_input_panel_imdata_set( mIMFContext, data.c_str(), length );
590 void InputMethodContextX::GetInputPanelData( std::string& data )
592 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelData\n" );
596 int length = 4096; // The max length is 4096 bytes
597 Dali::Vector< char > buffer;
598 buffer.Resize( length );
599 ecore_imf_context_input_panel_imdata_get( mIMFContext, &buffer[0], &length );
600 data = std::string( buffer.Begin(), buffer.End() );
604 Dali::InputMethodContext::State InputMethodContextX::GetInputPanelState()
606 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelState\n" );
611 value = ecore_imf_context_input_panel_state_get( mIMFContext );
615 case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
617 return Dali::InputMethodContext::SHOW;
621 case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
623 return Dali::InputMethodContext::HIDE;
627 case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
629 return Dali::InputMethodContext::WILL_SHOW;
635 return Dali::InputMethodContext::DEFAULT;
639 return Dali::InputMethodContext::DEFAULT;
642 void InputMethodContextX::SetReturnKeyState( bool visible )
644 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::SetReturnKeyState\n" );
648 ecore_imf_context_input_panel_return_key_disabled_set( mIMFContext, !visible );
652 void InputMethodContextX::AutoEnableInputPanel( bool enabled )
654 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::AutoEnableInputPanel\n" );
658 ecore_imf_context_input_panel_enabled_set( mIMFContext, enabled );
662 void InputMethodContextX::ShowInputPanel()
664 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::ShowInputPanel\n" );
668 ecore_imf_context_input_panel_show( mIMFContext );
672 void InputMethodContextX::HideInputPanel()
674 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::HideInputPanel\n" );
678 ecore_imf_context_input_panel_hide( mIMFContext );
682 Dali::InputMethodContext::KeyboardType InputMethodContextX::GetKeyboardType()
684 return Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD;
687 std::string InputMethodContextX::GetInputPanelLocale()
689 DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::GetInputPanelLocale\n" );
691 std::string locale = "";
696 ecore_imf_context_input_panel_language_locale_get( mIMFContext, &value );
700 std::string valueCopy( value );
703 // The locale string retrieved must be freed with free().
710 bool InputMethodContextX::FilterEventKey( const Dali::KeyEvent& keyEvent )
712 bool eventHandled( false );
714 // If a device key then skip ecore_imf_context_filter_event.
715 if ( ! KeyLookup::IsDeviceButton( keyEvent.keyPressedName.c_str() ))
717 //check whether it's key down or key up event
718 if ( keyEvent.state == KeyEvent::Down )
720 eventHandled = ProcessEventKeyDown( keyEvent );
722 else if ( keyEvent.state == KeyEvent::Up )
724 eventHandled = ProcessEventKeyUp( keyEvent );
731 bool InputMethodContextX::ProcessEventKeyDown( const KeyEvent& keyEvent )
733 bool eventHandled( false );
736 // We're consuming key down event so we have to pass to InputMethodContext so that it can parse it as well.
737 Ecore_IMF_Event_Key_Down ecoreKeyDownEvent;
738 ecoreKeyDownEvent.keyname = keyEvent.keyPressedName.c_str();
739 ecoreKeyDownEvent.key = keyEvent.keyPressedName.c_str();
740 ecoreKeyDownEvent.string = keyEvent.keyPressed.c_str();
741 ecoreKeyDownEvent.compose = keyEvent.GetCompose().c_str();
742 ecoreKeyDownEvent.timestamp = keyEvent.time;
743 ecoreKeyDownEvent.modifiers = EcoreInputModifierToEcoreIMFModifier( keyEvent.keyModifier );
744 ecoreKeyDownEvent.locks = EcoreInputModifierToEcoreIMFLock( keyEvent.keyModifier );
745 #ifdef ECORE_IMF_1_13
746 ecoreKeyDownEvent.dev_name = "";
747 ecoreKeyDownEvent.dev_class = ECORE_IMF_DEVICE_CLASS_KEYBOARD;
748 ecoreKeyDownEvent.dev_subclass = ECORE_IMF_DEVICE_SUBCLASS_NONE;
749 #endif // ECORE_IMF_1_13
751 // 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.
752 if ((keyEvent.GetDeviceName() == "ime") && ((!strncmp(keyEvent.keyPressedName.c_str(), "Left", 4)) ||
753 (!strncmp(keyEvent.keyPressedName.c_str(), "Right", 5)) ||
754 (!strncmp(keyEvent.keyPressedName.c_str(), "Up", 2)) ||
755 (!strncmp(keyEvent.keyPressedName.c_str(), "Down", 4))))
761 eventHandled = ecore_imf_context_filter_event(mIMFContext,
762 ECORE_IMF_EVENT_KEY_DOWN,
763 (Ecore_IMF_Event *) &ecoreKeyDownEvent);
766 // If the event has not been handled by InputMethodContext then check if we should reset our IMFcontext
769 if (!strcmp(keyEvent.keyPressedName.c_str(), "Escape") ||
770 !strcmp(keyEvent.keyPressedName.c_str(), "Return") ||
771 !strcmp(keyEvent.keyPressedName.c_str(), "KP_Enter"))
773 ecore_imf_context_reset(mIMFContext);
780 bool InputMethodContextX::ProcessEventKeyUp( const KeyEvent& keyEvent )
782 bool eventHandled( false );
785 // We're consuming key up event so we have to pass to InputMethodContext so that it can parse it as well.
786 Ecore_IMF_Event_Key_Up ecoreKeyUpEvent;
787 ecoreKeyUpEvent.keyname = keyEvent.keyPressedName.c_str();
788 ecoreKeyUpEvent.key = keyEvent.keyPressedName.c_str();
789 ecoreKeyUpEvent.string = keyEvent.keyPressed.c_str();
790 ecoreKeyUpEvent.compose = keyEvent.GetCompose().c_str();
791 ecoreKeyUpEvent.timestamp = keyEvent.time;
792 ecoreKeyUpEvent.modifiers = EcoreInputModifierToEcoreIMFModifier( keyEvent.keyModifier );
793 ecoreKeyUpEvent.locks = EcoreInputModifierToEcoreIMFLock( keyEvent.keyModifier );
794 #ifdef ECORE_IMF_1_13
795 ecoreKeyUpEvent.dev_name = "";
796 #endif // ECORE_IMF_1_13
798 eventHandled = ecore_imf_context_filter_event(mIMFContext,
799 ECORE_IMF_EVENT_KEY_UP,
800 (Ecore_IMF_Event *) &ecoreKeyUpEvent);
805 Ecore_IMF_Keyboard_Modifiers InputMethodContextX::EcoreInputModifierToEcoreIMFModifier( unsigned int ecoreModifier )
807 unsigned int modifier( ECORE_IMF_KEYBOARD_MODIFIER_NONE ); // If no other matches returns NONE.
809 if ( ecoreModifier & ECORE_EVENT_MODIFIER_SHIFT ) // enums from ecore_input/Ecore_Input.h
811 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT; // enums from ecore_imf/ecore_imf.h
814 if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALT )
816 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
819 if ( ecoreModifier & ECORE_EVENT_MODIFIER_CTRL )
821 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
824 if ( ecoreModifier & ECORE_EVENT_MODIFIER_WIN )
826 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
829 if ( ecoreModifier & ECORE_EVENT_MODIFIER_ALTGR )
831 modifier |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
834 return static_cast<Ecore_IMF_Keyboard_Modifiers>( modifier );
837 Ecore_IMF_Keyboard_Locks InputMethodContextX::EcoreInputModifierToEcoreIMFLock( unsigned int modifier )
839 unsigned int lock( ECORE_IMF_KEYBOARD_LOCK_NONE ); // If no other matches, returns NONE.
841 if( modifier & ECORE_EVENT_LOCK_NUM )
843 lock |= ECORE_IMF_KEYBOARD_LOCK_NUM; // Num lock is active.
846 if( modifier & ECORE_EVENT_LOCK_CAPS )
848 lock |= ECORE_IMF_KEYBOARD_LOCK_CAPS; // Caps lock is active.
851 if( modifier & ECORE_EVENT_LOCK_SCROLL )
853 lock |= ECORE_IMF_KEYBOARD_LOCK_SCROLL; // Scroll lock is active.
856 return static_cast<Ecore_IMF_Keyboard_Locks>( lock );
865 #pragma GCC diagnostic pop