X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Finput%2Ftizen-wayland%2Finput-method-context-impl-ecore-wl.cpp;h=bdbd8733231d4206c0c098f0daa76ff7dbf587b6;hb=5f6ec1d800c08c7eac93932921884ebf7eacf1c2;hp=3abaf472735ca65b49896b8239ca3e7db2e6bc6d;hpb=fedaf28a0fa85c9ed775d8cdf7934231b0999508;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git diff --git a/dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.cpp b/dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.cpp index 3abaf47..bdbd873 100755 --- a/dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.cpp +++ b/dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.cpp @@ -31,18 +31,17 @@ #include #include #include +#include #include // INTERNAL INCLUDES -#include -#include -#include #include +#include +#include #include +#include #include -#define TOKEN_STRING(x) #x - Ecore_IMF_Input_Panel_Layout panelLayoutMap[] = { ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL, @@ -97,27 +96,37 @@ namespace Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_INPUT_METHOD_CONTEXT"); #endif +const int kUninitializedWindowId = 0; + // Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead. size_t Utf8SequenceLength(const unsigned char leadByte) { size_t length = 0; - if ((leadByte & 0x80) == 0 ) //ASCII character (lead bit zero) + if( ( leadByte & 0x80 ) == 0 ) //ASCII character (lead bit zero) { length = 1; } - else if (( leadByte & 0xe0 ) == 0xc0 ) //110x xxxx + else if( ( leadByte & 0xe0 ) == 0xc0 ) //110x xxxx { length = 2; } - else if (( leadByte & 0xf0 ) == 0xe0 ) //1110 xxxx + else if( ( leadByte & 0xf0 ) == 0xe0 ) //1110 xxxx { length = 3; } - else if (( leadByte & 0xf8 ) == 0xf0 ) //1111 0xxx + else if( ( leadByte & 0xf8 ) == 0xf0 ) //1111 0xxx { length = 4; } + else if( ( leadByte & 0xfc ) == 0xf8 ) //1111 10xx + { + length = 5; + } + else if( ( leadByte & 0xfe ) == 0xfc ) //1111 110x + { + length = 6; + } return length; } @@ -268,33 +277,41 @@ void CommitContent( void *data, Ecore_IMF_Context *imfContext, void *eventInfo ) } } +int GetWindowIdFromActor( Dali::Actor actor ) +{ + int windowId = kUninitializedWindowId; + + if( actor.OnStage() ) + { + Any nativeWindowHandle = Dali::Integration::SceneHolder::Get( actor ).GetNativeHandle(); + +#ifdef ECORE_WAYLAND2 + windowId = ecore_wl2_window_id_get( AnyCast< Ecore_Wl2_Window* >( nativeWindowHandle ) ); +#else + windowId = ecore_wl_window_id_get( AnyCast< Ecore_Wl_Window* >( nativeWindowHandle ) ); +#endif + } + + return windowId; +} + BaseHandle Create() { - return Dali::InputMethodContext::New(); + return Dali::InputMethodContext::New( Dali::Actor() ); } Dali::TypeRegistration type( typeid(Dali::InputMethodContext), typeid(Dali::BaseHandle), Create ); } // unnamed namespace -InputMethodContextPtr InputMethodContextEcoreWl::New() +InputMethodContextPtr InputMethodContextEcoreWl::New( Dali::Actor actor ) { InputMethodContextPtr inputMethodContext; - // Create instance only if the adaptor is available - if ( Dali::Adaptor::IsAvailable() ) + // Create instance only if the adaptor is available and the valid actor exists + if ( actor && Dali::Adaptor::IsAvailable() ) { - Any nativeWindow = Dali::Adaptor::Get().GetNativeWindowHandle(); - - // The window needs to use the InputMethodContext. - if( !nativeWindow.Empty() ) - { - inputMethodContext = new InputMethodContextEcoreWl(); - } - else - { - DALI_LOG_ERROR("Failed to get native window handle, can't create InputMethodContext instance.\n"); - } + inputMethodContext = new InputMethodContextEcoreWl( actor ); } return inputMethodContext; } @@ -307,14 +324,17 @@ void InputMethodContextEcoreWl::Finalize() DeleteContext(); } -InputMethodContextEcoreWl::InputMethodContextEcoreWl() +InputMethodContextEcoreWl::InputMethodContextEcoreWl( Dali::Actor actor ) : mIMFContext(), mIMFCursorPosition( 0 ), mSurroundingText(), mRestoreAfterFocusLost( false ), - mIdleCallbackConnected( false ) + mIdleCallbackConnected( false ), + mWindowId( GetWindowIdFromActor( actor ) ) { ecore_imf_init(); + + actor.OnStageSignal().Connect( this, &InputMethodContextEcoreWl::OnStaged ); } InputMethodContextEcoreWl::~InputMethodContextEcoreWl() @@ -327,12 +347,18 @@ void InputMethodContextEcoreWl::Initialize() { CreateContext(); ConnectCallbacks(); + ApplyBackupOperations(); } void InputMethodContextEcoreWl::CreateContext() { DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContext::CreateContext\n" ); + if( mWindowId == kUninitializedWindowId ) + { + return; + } + const char *contextId = ecore_imf_context_default_id_get(); if( contextId ) { @@ -340,30 +366,16 @@ void InputMethodContextEcoreWl::CreateContext() if( mIMFContext ) { - // If we fail to get window id, we can't use the InputMethodContext correctly. - // Thus you have to call "ecore_imf_context_client_window_set" somewhere. - - Any nativeWindowHandle = Dali::Adaptor::Get().GetNativeWindowHandle(); - -#ifdef ECORE_WAYLAND2 - int windowId = ecore_wl2_window_id_get( AnyCast< Ecore_Wl2_Window* >( nativeWindowHandle ) ); -#else - int windowId = ecore_wl_window_id_get( AnyCast< Ecore_Wl_Window* >( nativeWindowHandle ) ); -#endif - - if( windowId != 0 ) - { - ecore_imf_context_client_window_set( mIMFContext, reinterpret_cast< void* >( windowId ) ); - } + ecore_imf_context_client_window_set( mIMFContext, reinterpret_cast< void* >( mWindowId ) ); } else { - DALI_LOG_WARNING("InputMethodContext Unable to get IMFContext\n"); + DALI_LOG_WARNING( "InputMethodContext Unable to get IMFContext\n" ); } } else { - DALI_LOG_WARNING("InputMethodContext Unable to get IMFContext\n"); + DALI_LOG_WARNING( "InputMethodContext Unable to get IMFContext\n" ); } } @@ -496,6 +508,8 @@ void InputMethodContextEcoreWl::PreEditChanged( void*, ImfContext* imfContext, v Ecore_IMF_Preedit_Attr* attr; + mPreeditAttrs.Clear(); + // Retrieves attributes as well as the string the cursor position offset from start of pre-edit string. // the attributes (attrs) is used in languages that use the soft arrows keys to insert characters into a current pre-edit string. ecore_imf_context_preedit_string_with_attributes_get( context, &preEditString, &attrs, &cursorPosition ); @@ -505,38 +519,88 @@ void InputMethodContextEcoreWl::PreEditChanged( void*, ImfContext* imfContext, v // iterate through the list of attributes getting the type, start and end position. for ( l = attrs, (attr = static_cast( eina_list_data_get(l) ) ); l; l = eina_list_next(l), ( attr = static_cast( eina_list_data_get(l) ) )) { -#ifdef DALI_PROFILE_UBUNTU - if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3 ) // (Ecore_IMF) -#else // DALI_PROFILE_UBUNTU - if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB4 ) // (Ecore_IMF) -#endif // DALI_PROFILE_UBUNTU - { - // 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. + Dali::InputMethodContext::PreeditAttributeData data; + data.startIndex = 0; + data.endIndex = 0; - size_t visualCharacterIndex = 0; - size_t byteIndex = 0; + size_t visualCharacterIndex = 0; + size_t byteIndex = 0; + + // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ). + char leadByte = preEditString[byteIndex]; + + while( leadByte != '\0' ) + { + leadByte = preEditString[byteIndex]; // Update the character to get the number of its byte - // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ). - const char leadByte = preEditString[byteIndex]; - while( leadByte != '\0' ) + // attr->end_index is provided as a byte position not character and we need to know the character position. + const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character. + if( byteIndex <= attr->start_index ) { - // attr->end_index is provided as a byte position not character and we need to know the character position. - const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character. - if ( byteIndex == attr->end_index ) - { - cursorPosition = visualCharacterIndex; - break; - // end loop as found cursor position that matches byte position - } - else - { - byteIndex += currentSequenceLength; // jump to next character - visualCharacterIndex++; // increment character count so we know our position for when we get a match - } + data.startIndex = visualCharacterIndex; + } + if( byteIndex >= attr->end_index ) + { + data.endIndex = visualCharacterIndex; + break; + // end loop as found cursor position that matches byte position + } + else + { + byteIndex += currentSequenceLength; // jump to next character + visualCharacterIndex++; // increment character count so we know our position for when we get a match + } + } - DALI_ASSERT_DEBUG( visualCharacterIndex < strlen( preEditString )); + switch( attr->preedit_type ) + { + case ECORE_IMF_PREEDIT_TYPE_NONE: + { + data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE; + break; + } + case ECORE_IMF_PREEDIT_TYPE_SUB1: + { + data.preeditType = Dali::InputMethodContext::PreeditStyle::UNDERLINE; + break; + } + case ECORE_IMF_PREEDIT_TYPE_SUB2: + { + data.preeditType = Dali::InputMethodContext::PreeditStyle::REVERSE; + break; + } + case ECORE_IMF_PREEDIT_TYPE_SUB3: + { + data.preeditType = Dali::InputMethodContext::PreeditStyle::HIGHLIGHT; + break; + } + case ECORE_IMF_PREEDIT_TYPE_SUB4: + { + data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1; + break; + } + case ECORE_IMF_PREEDIT_TYPE_SUB5: + { + data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2; + break; + } + case ECORE_IMF_PREEDIT_TYPE_SUB6: + { + data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3; + break; + } + case ECORE_IMF_PREEDIT_TYPE_SUB7: + { + data.preeditType = Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4; + break; + } + default: + { + data.preeditType = Dali::InputMethodContext::PreeditStyle::NONE; + break; } } + mPreeditAttrs.PushBack( data ); } } @@ -599,33 +663,36 @@ bool InputMethodContextEcoreWl::RetrieveSurrounding( void* data, ImfContext* imf if( callbackData.update ) { + if( cursorPosition ) + { + mIMFCursorPosition = static_cast( callbackData.cursorPosition ); + *cursorPosition = mIMFCursorPosition; + } + if( text ) { const char* plainText = callbackData.currentText.c_str(); + if( plainText ) { + // The memory allocated by strdup() can be freed by ecore_imf_context_surrounding_get() internally. + *text = strdup( plainText ); + // If the current input panel is password mode, dali should replace the plain text with '*' (Asterisk) character. - if( ecore_imf_context_input_hint_get( mIMFContext ) & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA ) + if( ( ecore_imf_context_input_hint_get( mIMFContext ) & ECORE_IMF_INPUT_HINT_SENSITIVE_DATA ) && *text ) { - char* iter = NULL; - for( iter = const_cast( plainText ); iter && *iter; ++iter ) + for( char* iter = *text; *iter; ++iter ) { *iter = '*'; } } - } - // The memory allocated by strdup() can be freed by ecore_imf_context_surrounding_get() internally. - *text = strdup( plainText ); - } - if( cursorPosition ) - { - mIMFCursorPosition = static_cast( callbackData.cursorPosition ); - *cursorPosition = mIMFCursorPosition; + return EINA_TRUE; + } } } - return EINA_TRUE; + return EINA_FALSE; } /** @@ -722,11 +789,16 @@ const std::string& InputMethodContextEcoreWl::GetSurroundingText() const void InputMethodContextEcoreWl::NotifyTextInputMultiLine( bool multiLine ) { - Ecore_IMF_Input_Hints currentHint = ecore_imf_context_input_hint_get(mIMFContext); - ecore_imf_context_input_hint_set( mIMFContext, - static_cast< Ecore_IMF_Input_Hints >( multiLine ? - (currentHint | ECORE_IMF_INPUT_HINT_MULTILINE) : - (currentHint & ~ECORE_IMF_INPUT_HINT_MULTILINE))); + if( mIMFContext ) + { + Ecore_IMF_Input_Hints currentHint = ecore_imf_context_input_hint_get(mIMFContext); + ecore_imf_context_input_hint_set( mIMFContext, + static_cast< Ecore_IMF_Input_Hints >( multiLine ? + (currentHint | ECORE_IMF_INPUT_HINT_MULTILINE) : + (currentHint & ~ECORE_IMF_INPUT_HINT_MULTILINE))); + } + + mBackupOperations[Operation::NOTIFY_TEXT_INPUT_MULTILINE] = std::bind( &InputMethodContextEcoreWl::NotifyTextInputMultiLine, this, multiLine ); } Dali::InputMethodContext::TextDirection InputMethodContextEcoreWl::GetTextDirection() @@ -816,6 +888,8 @@ void InputMethodContextEcoreWl::SetInputPanelData( const std::string& data ) int length = data.length(); ecore_imf_context_input_panel_imdata_set( mIMFContext, data.c_str(), length ); } + + mBackupOperations[Operation::SET_INPUT_PANEL_DATA] = std::bind( &InputMethodContextEcoreWl::SetInputPanelData, this, data ); } void InputMethodContextEcoreWl::GetInputPanelData( std::string& data ) @@ -878,6 +952,8 @@ void InputMethodContextEcoreWl::SetReturnKeyState( bool visible ) { ecore_imf_context_input_panel_return_key_disabled_set( mIMFContext, !visible ); } + + mBackupOperations[Operation::SET_RETURN_KEY_STATE] = std::bind( &InputMethodContextEcoreWl::SetReturnKeyState, this, visible ); } void InputMethodContextEcoreWl::AutoEnableInputPanel( bool enabled ) @@ -888,6 +964,8 @@ void InputMethodContextEcoreWl::AutoEnableInputPanel( bool enabled ) { ecore_imf_context_input_panel_enabled_set( mIMFContext, enabled ); } + + mBackupOperations[Operation::AUTO_ENABLE_INPUT_PANEL] = std::bind( &InputMethodContextEcoreWl::AutoEnableInputPanel, this, enabled ); } void InputMethodContextEcoreWl::ShowInputPanel() @@ -968,6 +1046,8 @@ void InputMethodContextEcoreWl::SetContentMIMETypes( const std::string& mimeType { ecore_imf_context_mime_type_accept_set( mIMFContext, mimeTypes.c_str() ); } + + mBackupOperations[Operation::SET_CONTENT_MIME_TYPES] = std::bind( &InputMethodContextEcoreWl::SetContentMIMETypes, this, mimeTypes ); } bool InputMethodContextEcoreWl::FilterEventKey( const Dali::KeyEvent& keyEvent ) @@ -999,6 +1079,8 @@ void InputMethodContextEcoreWl::AllowTextPrediction( bool prediction ) { ecore_imf_context_prediction_allow_set( mIMFContext, prediction ); } + + mBackupOperations[Operation::ALLOW_TEXT_PREDICTION] = std::bind( &InputMethodContextEcoreWl::AllowTextPrediction, this, prediction ); } bool InputMethodContextEcoreWl::IsTextPredictionAllowed() const @@ -1031,6 +1113,8 @@ void InputMethodContextEcoreWl::SetInputPanelLanguage( Dali::InputMethodContext: } } } + + mBackupOperations[Operation::SET_INPUT_PANEL_LANGUAGE] = std::bind( &InputMethodContextEcoreWl::SetInputPanelLanguage, this, language ); } Dali::InputMethodContext::InputPanelLanguage InputMethodContextEcoreWl::GetInputPanelLanguage() const @@ -1058,6 +1142,24 @@ Dali::InputMethodContext::InputPanelLanguage InputMethodContextEcoreWl::GetInput return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC; } +void InputMethodContextEcoreWl::SetInputPanelPosition( unsigned int x, unsigned int y ) +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelPosition\n" ); + + if( mIMFContext ) + { + ecore_imf_context_input_panel_position_set( mIMFContext, x, y ); + } + + mBackupOperations[Operation::SET_INPUT_PANEL_POSITION] = std::bind( &InputMethodContextEcoreWl::SetInputPanelPosition, this, x, y ); +} + +void InputMethodContextEcoreWl::GetPreeditStyle( Dali::InputMethodContext::PreEditAttributeDataContainer& attrs ) const +{ + DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetPreeditStyle\n" ); + attrs = mPreeditAttrs; +} + bool InputMethodContextEcoreWl::ProcessEventKeyDown( const KeyEvent& keyEvent ) { bool eventHandled( false ); @@ -1081,6 +1183,9 @@ bool InputMethodContextEcoreWl::ProcessEventKeyDown( const KeyEvent& keyEvent ) ecoreKeyDownEvent.dev_name = deviceName.c_str(); ecoreKeyDownEvent.dev_class = static_cast ( keyEvent.GetDeviceClass() );//ECORE_IMF_DEVICE_CLASS_KEYBOARD; ecoreKeyDownEvent.dev_subclass = static_cast ( keyEvent.GetDeviceSubclass() );//ECORE_IMF_DEVICE_SUBCLASS_NONE; +#if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR) && (ECORE_VERSION_MINOR >= 22) + ecoreKeyDownEvent.keycode = keyEvent.keyCode; // Ecore_IMF_Event structure has added 'keycode' variable since ecore_imf 1.22 version. +#endif // Since ecore_imf 1.22 version // 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. if ((keyEvent.GetDeviceName() == "ime") && ((!strncmp(keyEvent.keyPressedName.c_str(), "Left", 4)) || @@ -1134,6 +1239,9 @@ bool InputMethodContextEcoreWl::ProcessEventKeyUp( const KeyEvent& keyEvent ) ecoreKeyUpEvent.dev_name = deviceName.c_str(); ecoreKeyUpEvent.dev_class = static_cast ( keyEvent.GetDeviceClass() );//ECORE_IMF_DEVICE_CLASS_KEYBOARD; ecoreKeyUpEvent.dev_subclass = static_cast ( keyEvent.GetDeviceSubclass() );//ECORE_IMF_DEVICE_SUBCLASS_NONE; +#if defined(ECORE_VERSION_MAJOR) && (ECORE_VERSION_MAJOR >= 1) && defined(ECORE_VERSION_MINOR) && (ECORE_VERSION_MINOR >= 22) + ecoreKeyUpEvent.keycode = keyEvent.keyCode; // Ecore_IMF_Event structure has added 'keycode' variable since ecore_imf 1.22 version. +#endif // Since ecore_imf 1.22 version eventHandled = ecore_imf_context_filter_event(mIMFContext, ECORE_IMF_EVENT_KEY_UP, @@ -1196,6 +1304,20 @@ Ecore_IMF_Keyboard_Locks InputMethodContextEcoreWl::EcoreInputModifierToEcoreIMF return static_cast( lock ); } +void InputMethodContextEcoreWl::OnStaged( Dali::Actor actor ) +{ + int windowId = GetWindowIdFromActor( actor ); + + if( mWindowId != windowId ) + { + mWindowId = windowId; + + // Reset + Finalize(); + Initialize(); + } +} + } // Adaptor } // Internal