From 5cdb62a3357f02eef562bb9c8d1cdf9a15e4a390 Mon Sep 17 00:00:00 2001 From: Jiyun Yang Date: Wed, 26 Jun 2019 15:55:18 +0900 Subject: [PATCH] Fix InputMethodContext to work well in multi-window env Change-Id: I6ddb1442b03d45b483b484df9c50424061b21133 Signed-off-by: Jiyun Yang --- .../adaptor-framework/input-method-context.cpp | 7 +- .../adaptor-framework/input-method-context.h | 9 ++ dali/integration-api/adaptor.h | 8 ++ dali/integration-api/scene-holder-impl.cpp | 13 +++ dali/integration-api/scene-holder-impl.h | 5 ++ dali/integration-api/scene-holder.cpp | 10 +++ dali/integration-api/scene-holder.h | 8 ++ dali/internal/adaptor/common/adaptor-impl.cpp | 18 ++++ dali/internal/adaptor/common/adaptor-impl.h | 8 ++ dali/internal/adaptor/common/adaptor.cpp | 5 ++ .../input/common/input-method-context-factory.h | 2 +- .../input/common/input-method-context-impl.cpp | 4 +- .../input/common/input-method-context-impl.h | 3 +- .../input-method-context-factory-ecore-wl.cpp | 4 +- .../input-method-context-impl-ecore-wl.cpp | 100 +++++++++++++-------- .../input-method-context-impl-ecore-wl.h | 16 +++- .../ubuntu-x11/input-method-context-factory-x.cpp | 4 +- .../ubuntu-x11/input-method-context-impl-x.cpp | 58 ++++++------ .../input/ubuntu-x11/input-method-context-impl-x.h | 17 ++-- .../windows/input-method-context-factory-win.cpp | 4 +- .../windows/input-method-context-impl-win.cpp | 40 +++++---- .../input/windows/input-method-context-impl-win.h | 12 ++- dali/internal/window-system/common/window-impl.cpp | 1 - 23 files changed, 244 insertions(+), 112 deletions(-) diff --git a/dali/devel-api/adaptor-framework/input-method-context.cpp b/dali/devel-api/adaptor-framework/input-method-context.cpp index e5deaca..492b9ae 100755 --- a/dali/devel-api/adaptor-framework/input-method-context.cpp +++ b/dali/devel-api/adaptor-framework/input-method-context.cpp @@ -32,7 +32,12 @@ InputMethodContext::~InputMethodContext() = default; InputMethodContext InputMethodContext::New() { - Internal::Adaptor::InputMethodContextPtr inputMethodContext = Internal::Adaptor::InputMethodContext::New(); + return InputMethodContext::New( Actor() ); +} + +InputMethodContext InputMethodContext::New( Actor actor ) +{ + Internal::Adaptor::InputMethodContextPtr inputMethodContext = Internal::Adaptor::InputMethodContext::New( actor ); if( inputMethodContext ) { diff --git a/dali/devel-api/adaptor-framework/input-method-context.h b/dali/devel-api/adaptor-framework/input-method-context.h index e67f5fd..4310c77 100755 --- a/dali/devel-api/adaptor-framework/input-method-context.h +++ b/dali/devel-api/adaptor-framework/input-method-context.h @@ -37,6 +37,8 @@ class InputMethodContext; } } +class Actor; + /** * @brief The InputMethodContext class * @@ -201,6 +203,13 @@ public: static InputMethodContext New(); /** + * @brief Create a new instance of an InputMethodContext. + * + * @param[in] actor The actor that uses the new InputMethodContext instance. + */ + static InputMethodContext New( Actor actor ); + + /** * @brief Copy constructor. * * @param[in] inputMethodContext InputMethodContext to copy. The copied inputMethodContext will point at the same implementation. diff --git a/dali/integration-api/adaptor.h b/dali/integration-api/adaptor.h index 2bce86e..cb19fa0 100755 --- a/dali/integration-api/adaptor.h +++ b/dali/integration-api/adaptor.h @@ -308,6 +308,14 @@ public: Any GetNativeWindowHandle(); /** + * @brief Retrieve native window handle that the given actor is added to. + * + * @param[in] actor The actor + * @return native window handle + */ + Any GetNativeWindowHandle( Actor actor ); + + /** * @brief Get the native display associated with the graphics backend * * @return A handle to the native display diff --git a/dali/integration-api/scene-holder-impl.cpp b/dali/integration-api/scene-holder-impl.cpp index 3a7bc5a..a5eca04 100644 --- a/dali/integration-api/scene-holder-impl.cpp +++ b/dali/integration-api/scene-holder-impl.cpp @@ -337,6 +337,19 @@ void SceneHolder::FeedKeyEvent( Dali::Integration::KeyEvent& keyEvent ) mAdaptor->ProcessCoreEvents(); } +Dali::Integration::SceneHolder SceneHolder::Get( Dali::Actor actor ) +{ + SceneHolder* sceneHolderImpl = nullptr; + + if ( Internal::Adaptor::Adaptor::IsAvailable() ) + { + Dali::Internal::Adaptor::Adaptor& adaptor = Internal::Adaptor::Adaptor::GetImplementation( Internal::Adaptor::Adaptor::Get() ); + sceneHolderImpl = adaptor.GetWindow( actor ); + } + + return Dali::Integration::SceneHolder( sceneHolderImpl ); +} + void SceneHolder::Reset() { mCombiner.Reset(); diff --git a/dali/integration-api/scene-holder-impl.h b/dali/integration-api/scene-holder-impl.h index 6b4e488..78682ea 100644 --- a/dali/integration-api/scene-holder-impl.h +++ b/dali/integration-api/scene-holder-impl.h @@ -167,6 +167,11 @@ public: */ void FeedKeyEvent( Dali::Integration::KeyEvent& keyEvent ); + /** + * @copydoc Dali::Integration::SceneHolder::Get() + */ + static Dali::Integration::SceneHolder Get( Dali::Actor actor ); + public: // The following methods can be overridden if required /** diff --git a/dali/integration-api/scene-holder.cpp b/dali/integration-api/scene-holder.cpp index ca5e4f4..8f456d9 100644 --- a/dali/integration-api/scene-holder.cpp +++ b/dali/integration-api/scene-holder.cpp @@ -83,6 +83,11 @@ Vector4 SceneHolder::GetBackgroundColor() const return GetImplementation(*this).GetBackgroundColor(); } +Any SceneHolder::GetNativeHandle() const +{ + return GetImplementation(*this).GetNativeHandle(); +} + void SceneHolder::FeedTouchPoint( Dali::TouchPoint& point, int timeStamp ) { Integration::Point convertedPoint( point ); @@ -101,6 +106,11 @@ void SceneHolder::FeedKeyEvent( Dali::KeyEvent& keyEvent ) GetImplementation(*this).FeedKeyEvent( convertedEvent ); } +SceneHolder SceneHolder::Get( Actor actor ) +{ + return Internal::Adaptor::SceneHolder::Get( actor ); +} + }// Integration } // Dali diff --git a/dali/integration-api/scene-holder.h b/dali/integration-api/scene-holder.h index 59a2055..4881d22 100644 --- a/dali/integration-api/scene-holder.h +++ b/dali/integration-api/scene-holder.h @@ -150,6 +150,14 @@ public: */ void FeedKeyEvent( Dali::KeyEvent& keyEvent ); + /** + * @brief Retrieve the SceneHolder that the given actor is added to. + * + * @param[in] actor The actor + * @return The SceneHolder the actor is added to or an empty handle if the actor is not added to any SceneHolder. + */ + static SceneHolder Get( Actor actor ); + public: // Not intended for application developers /** diff --git a/dali/internal/adaptor/common/adaptor-impl.cpp b/dali/internal/adaptor/common/adaptor-impl.cpp index d42eff5..868345d 100755 --- a/dali/internal/adaptor/common/adaptor-impl.cpp +++ b/dali/internal/adaptor/common/adaptor-impl.cpp @@ -799,6 +799,24 @@ Any Adaptor::GetNativeWindowHandle() return mWindows.front()->GetNativeHandle(); } +Any Adaptor::GetNativeWindowHandle( Dali::Actor actor ) +{ + Any nativeWindowHandle; + + Dali::Integration::Scene scene = Dali::Integration::Scene::Get( actor ); + + for( auto sceneHolder : mWindows ) + { + if ( scene == sceneHolder->GetScene() ) + { + nativeWindowHandle = sceneHolder->GetNativeHandle(); + break; + } + } + + return nativeWindowHandle; +} + Any Adaptor::GetGraphicsDisplay() { Any display; diff --git a/dali/internal/adaptor/common/adaptor-impl.h b/dali/internal/adaptor/common/adaptor-impl.h index a716bea..99e4a0c 100755 --- a/dali/internal/adaptor/common/adaptor-impl.h +++ b/dali/internal/adaptor/common/adaptor-impl.h @@ -345,6 +345,14 @@ public: Any GetNativeWindowHandle(); /** + * @brief Retrieve native window handle that the given actor is added to. + * + * @param[in] actor The actor + * @return native window handle + */ + Any GetNativeWindowHandle( Dali::Actor actor ); + + /** * Get the native display associated with the graphics backend * * @return A handle to the native display diff --git a/dali/internal/adaptor/common/adaptor.cpp b/dali/internal/adaptor/common/adaptor.cpp index 9b300bf..73fe2b3 100755 --- a/dali/internal/adaptor/common/adaptor.cpp +++ b/dali/internal/adaptor/common/adaptor.cpp @@ -161,6 +161,11 @@ Any Adaptor::GetNativeWindowHandle() return mImpl->GetNativeWindowHandle(); } +Any Adaptor::GetNativeWindowHandle( Actor actor ) +{ + return mImpl->GetNativeWindowHandle( actor ); +} + Any Adaptor::GetGraphicsDisplay() { return mImpl->GetGraphicsDisplay(); diff --git a/dali/internal/input/common/input-method-context-factory.h b/dali/internal/input/common/input-method-context-factory.h index a231f3d..f000748 100755 --- a/dali/internal/input/common/input-method-context-factory.h +++ b/dali/internal/input/common/input-method-context-factory.h @@ -32,7 +32,7 @@ namespace InputMethodContextFactory // Factory function creating new InputMethodContext // Symbol exists but may be overriden during linking -InputMethodContextPtr CreateInputMethodContext(); +InputMethodContextPtr CreateInputMethodContext( Dali::Actor actor ); } } diff --git a/dali/internal/input/common/input-method-context-impl.cpp b/dali/internal/input/common/input-method-context-impl.cpp index 5ca15af..d145b30 100755 --- a/dali/internal/input/common/input-method-context-impl.cpp +++ b/dali/internal/input/common/input-method-context-impl.cpp @@ -28,9 +28,9 @@ namespace Internal namespace Adaptor { -InputMethodContextPtr InputMethodContext::New() +InputMethodContextPtr InputMethodContext::New( Dali::Actor actor ) { - return Dali::Internal::Adaptor::InputMethodContextFactory::CreateInputMethodContext(); + return Dali::Internal::Adaptor::InputMethodContextFactory::CreateInputMethodContext( actor ); } const std::string& InputMethodContext::GetSurroundingText() const diff --git a/dali/internal/input/common/input-method-context-impl.h b/dali/internal/input/common/input-method-context-impl.h index 33ab2a6..1527cc3 100755 --- a/dali/internal/input/common/input-method-context-impl.h +++ b/dali/internal/input/common/input-method-context-impl.h @@ -19,6 +19,7 @@ */ // EXTERNAL INCLUDES +#include #include #include #include @@ -61,7 +62,7 @@ public: /** * Create a new input method context instance. */ - static InputMethodContextPtr New(); + static InputMethodContextPtr New( Dali::Actor actor ); /** * Initialize the object. diff --git a/dali/internal/input/tizen-wayland/input-method-context-factory-ecore-wl.cpp b/dali/internal/input/tizen-wayland/input-method-context-factory-ecore-wl.cpp index 9615886..a30e996 100755 --- a/dali/internal/input/tizen-wayland/input-method-context-factory-ecore-wl.cpp +++ b/dali/internal/input/tizen-wayland/input-method-context-factory-ecore-wl.cpp @@ -31,9 +31,9 @@ namespace InputMethodContextFactory { // InputMethodContext Factory to be implemented by the platform -InputMethodContextPtr CreateInputMethodContext() +InputMethodContextPtr CreateInputMethodContext( Dali::Actor actor ) { - return Dali::Internal::Adaptor::InputMethodContextEcoreWl::New(); + return Dali::Internal::Adaptor::InputMethodContextEcoreWl::New( actor ); } } 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..73b1a43 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 @@ -35,6 +35,7 @@ // INTERNAL INCLUDES #include +#include #include #include #include @@ -97,6 +98,8 @@ 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) { @@ -268,33 +271,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 +318,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() @@ -333,6 +347,11 @@ 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 +359,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" ); } } @@ -722,11 +727,14 @@ 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))); + } } Dali::InputMethodContext::TextDirection InputMethodContextEcoreWl::GetTextDirection() @@ -1196,6 +1204,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 diff --git a/dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.h b/dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.h index 3d2e170..ba3fdf8 100755 --- a/dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.h +++ b/dali/internal/input/tizen-wayland/input-method-context-impl-ecore-wl.h @@ -40,16 +40,17 @@ namespace Internal namespace Adaptor { -class InputMethodContextEcoreWl : public Dali::Internal::Adaptor::InputMethodContext +class InputMethodContextEcoreWl : public Dali::Internal::Adaptor::InputMethodContext, public Dali::ConnectionTracker { public: /** * @brief Creates a new InputMethodContext handle * + * @param[in] actor The actor that uses the new InputMethodContext instance. * @return InputMethodContext pointer */ - static InputMethodContextPtr New(); + static InputMethodContextPtr New( Dali::Actor actor ); /** * @brief Initializes member data. @@ -300,11 +301,16 @@ private: */ Ecore_IMF_Keyboard_Locks EcoreInputModifierToEcoreIMFLock( unsigned int modifier ); + /** + * Called when the binded actor is added to a window. + */ + void OnStaged( Dali::Actor actor ); + private: /** * @brief Constructor. */ - explicit InputMethodContextEcoreWl(); + explicit InputMethodContextEcoreWl( Dali::Actor actor ); protected: /** @@ -328,7 +334,9 @@ private: bool mIdleCallbackConnected:1; ///< Whether the idle callback is already connected. std::vector mKeyEvents; ///< Stores key events to be sent from idle call-back. - InputMethodOptions mOptions; + InputMethodOptions mOptions; + + int mWindowId; }; diff --git a/dali/internal/input/ubuntu-x11/input-method-context-factory-x.cpp b/dali/internal/input/ubuntu-x11/input-method-context-factory-x.cpp index be7b442..fb0fe9e 100755 --- a/dali/internal/input/ubuntu-x11/input-method-context-factory-x.cpp +++ b/dali/internal/input/ubuntu-x11/input-method-context-factory-x.cpp @@ -31,9 +31,9 @@ namespace InputMethodContextFactory { // InputMethodContext Factory to be implemented by the platform -InputMethodContextPtr CreateInputMethodContext() +InputMethodContextPtr CreateInputMethodContext( Dali::Actor actor ) { - return Dali::Internal::Adaptor::InputMethodContextX::New(); + return Dali::Internal::Adaptor::InputMethodContextX::New( actor ); } } diff --git a/dali/internal/input/ubuntu-x11/input-method-context-impl-x.cpp b/dali/internal/input/ubuntu-x11/input-method-context-impl-x.cpp index 60a5446..6a19a01 100755 --- a/dali/internal/input/ubuntu-x11/input-method-context-impl-x.cpp +++ b/dali/internal/input/ubuntu-x11/input-method-context-impl-x.cpp @@ -122,31 +122,13 @@ void ImfDeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *even } // unnamed namespace -InputMethodContextPtr InputMethodContextX::New() +InputMethodContextPtr InputMethodContextX::New( Dali::Actor actor ) { InputMethodContextPtr manager; - if ( Adaptor::IsAvailable() ) + if( actor && Dali::Adaptor::IsAvailable() ) { - // Create instance and register singleton only if the adaptor is available - Adaptor& adaptorImpl( Adaptor::GetImplementation( Adaptor::Get() ) ); - Any nativeWindow = adaptorImpl.GetNativeWindowHandle(); - - // The Ecore_X_Window needs to use the InputMethodContext. - // Only when the render surface is window, we can get the Ecore_X_Window. - Ecore_X_Window ecoreXwin( AnyCast(nativeWindow) ); - if (ecoreXwin) - { - // If we fail to get Ecore_X_Window, we can't use the InputMethodContext correctly. - // Thus you have to call "ecore_imf_context_client_window_set" somewhere. - // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent(). - - manager = new InputMethodContextX( ecoreXwin ); - } - else - { - DALI_LOG_ERROR("Failed to get native window handle\n"); - } + manager = new InputMethodContextX( actor ); } return manager; @@ -160,15 +142,17 @@ void InputMethodContextX::Finalize() DeleteContext(); } -InputMethodContextX::InputMethodContextX( Ecore_X_Window ecoreXwin ) +InputMethodContextX::InputMethodContextX( Dali::Actor actor ) : mIMFContext(), - mEcoreXwin( ecoreXwin ), + mEcoreXwin( 0 ), mIMFCursorPosition( 0 ), mSurroundingText(), mRestoreAfterFocusLost( false ), mIdleCallbackConnected( false ) { ecore_imf_init(); + + actor.OnStageSignal().Connect( this, &InputMethodContextX::OnStaged ); } InputMethodContextX::~InputMethodContextX() @@ -179,15 +163,20 @@ InputMethodContextX::~InputMethodContextX() void InputMethodContextX::Initialize() { - CreateContext( mEcoreXwin ); + CreateContext(); ConnectCallbacks(); VirtualKeyboard::ConnectCallbacks( mIMFContext ); } -void InputMethodContextX::CreateContext( Ecore_X_Window ecoreXwin ) +void InputMethodContextX::CreateContext() { DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextX::CreateContext\n" ); + if( !mEcoreXwin ) + { + return; + } + const char *contextId = ecore_imf_context_default_id_get(); if( contextId ) { @@ -195,10 +184,7 @@ void InputMethodContextX::CreateContext( Ecore_X_Window ecoreXwin ) if( mIMFContext ) { - if( ecoreXwin ) - { - ecore_imf_context_client_window_set( mIMFContext, reinterpret_cast( ecoreXwin ) ); - } + ecore_imf_context_client_window_set( mIMFContext, reinterpret_cast( mEcoreXwin ) ); } else { @@ -935,6 +921,20 @@ Ecore_IMF_Keyboard_Locks InputMethodContextX::EcoreInputModifierToEcoreIMFLock( return static_cast( lock ); } +void InputMethodContextX::OnStaged( Dali::Actor actor ) +{ + Ecore_X_Window ecoreXwin( AnyCast< Ecore_X_Window >( Dali::Integration::SceneHolder::Get( actor ).GetNativeHandle() ) ); + + if( mEcoreXwin != ecoreXwin ) + { + mEcoreXwin = ecoreXwin; + + // Reset + Finalize(); + Initialize(); + } +} + } // Adaptor } // Internal diff --git a/dali/internal/input/ubuntu-x11/input-method-context-impl-x.h b/dali/internal/input/ubuntu-x11/input-method-context-impl-x.h index 894d0f1..43fe822 100755 --- a/dali/internal/input/ubuntu-x11/input-method-context-impl-x.h +++ b/dali/internal/input/ubuntu-x11/input-method-context-impl-x.h @@ -39,21 +39,22 @@ namespace Internal namespace Adaptor { -class InputMethodContextX : public Dali::Internal::Adaptor::InputMethodContext +class InputMethodContextX : public Dali::Internal::Adaptor::InputMethodContext, public Dali::ConnectionTracker { public: /** * @brief Creates a new InputMethodContext handle * + * @param[in] actor The actor that uses the new InputMethodContext instance. * @return InputMethodContext pointer */ - static InputMethodContextPtr New(); + static InputMethodContextPtr New( Dali::Actor actor ); /** * Constructor - * @param[in] ecoreXwin, The window is created by application. + * @param[in] actor The actor that uses the new InputMethodContext instance. */ - explicit InputMethodContextX( Ecore_X_Window ecoreXwin ); + explicit InputMethodContextX( Dali::Actor actor ); public: @@ -265,9 +266,8 @@ public: private: /** * Context created the first time and kept until deleted. - * @param[in] ecoreXwin, The window is created by application. */ - void CreateContext( Ecore_X_Window ecoreXwin ); + void CreateContext(); /** * @copydoc Dali::InputMethodContext::DeleteContext() @@ -307,6 +307,11 @@ private: */ Ecore_IMF_Keyboard_Locks EcoreInputModifierToEcoreIMFLock( unsigned int modifier ); + /** + * Called when the binded actor is added to a window. + */ + void OnStaged( Dali::Actor actor ); + public: /** diff --git a/dali/internal/input/windows/input-method-context-factory-win.cpp b/dali/internal/input/windows/input-method-context-factory-win.cpp index 817dacb..131bbb5 100755 --- a/dali/internal/input/windows/input-method-context-factory-win.cpp +++ b/dali/internal/input/windows/input-method-context-factory-win.cpp @@ -31,9 +31,9 @@ namespace InputMethodContextFactory { // InputMethodContext Factory to be implemented by the platform -InputMethodContextPtr CreateInputMethodContext() +InputMethodContextPtr CreateInputMethodContext( Dali::Actor actor ) { - return Dali::Internal::Adaptor::InputMethodContextWin::New(); + return Dali::Internal::Adaptor::InputMethodContextWin::New( actor ); } } diff --git a/dali/internal/input/windows/input-method-context-impl-win.cpp b/dali/internal/input/windows/input-method-context-impl-win.cpp index ee3ff2b..5df001d 100755 --- a/dali/internal/input/windows/input-method-context-impl-win.cpp +++ b/dali/internal/input/windows/input-method-context-impl-win.cpp @@ -41,27 +41,13 @@ namespace Internal namespace Adaptor { -InputMethodContextPtr InputMethodContextWin::New() +InputMethodContextPtr InputMethodContextWin::New( Dali::Actor actor ) { InputMethodContextPtr manager; - if ( Adaptor::IsAvailable() ) + if ( actor && Adaptor::IsAvailable() ) { - // Create instance and register singleton only if the adaptor is available - Adaptor& adaptorImpl( Adaptor::GetImplementation( Adaptor::Get() ) ); - Any nativeWindow = adaptorImpl.GetNativeWindowHandle(); - - // The Win_Window_Handle needs to use the InputMethodContext. - // Only when the render surface is window, we can get the Win_Window_Handle. - WinWindowHandle winWindow( AnyCast(nativeWindow) ); - if ( winWindow ) - { - manager = new InputMethodContextWin( winWindow ); - } - else - { - DALI_LOG_ERROR("Failed to get native window handle\n"); - } + manager = new InputMethodContextWin( actor ); } return manager; @@ -71,13 +57,15 @@ void InputMethodContextWin::Finalize() { } -InputMethodContextWin::InputMethodContextWin( WinWindowHandle winWindow ) -: mWin32Window( winWindow ), +InputMethodContextWin::InputMethodContextWin( Dali::Actor actor ) +: mWin32Window( 0 ), mIMFCursorPosition( 0 ), mSurroundingText(), mRestoreAfterFocusLost( false ), mIdleCallbackConnected( false ) { + + actor.OnStageSignal().Connect( this, &InputMethodContextWin::OnStaged ); } InputMethodContextWin::~InputMethodContextWin() @@ -383,6 +371,20 @@ bool InputMethodContextWin::ProcessEventKeyUp( const KeyEvent& keyEvent ) return eventHandled; } +void InputMethodContextWin::OnStaged( Dali::Actor actor ) +{ + WinWindowHandle winWindow( AnyCast< WinWindowHandle >( Dali::Integration::SceneHolder::Get( actor ).GetNativeHandle() ) ); + + if( mWin32Window != winWindow ) + { + mWin32Window = winWindow; + + // Reset + Finalize(); + Initialize(); + } +} + } // Adaptor } // Internal diff --git a/dali/internal/input/windows/input-method-context-impl-win.h b/dali/internal/input/windows/input-method-context-impl-win.h index e1c1e33..a0eed9d 100755 --- a/dali/internal/input/windows/input-method-context-impl-win.h +++ b/dali/internal/input/windows/input-method-context-impl-win.h @@ -37,21 +37,22 @@ namespace Internal namespace Adaptor { -class InputMethodContextWin : public Dali::Internal::Adaptor::InputMethodContext +class InputMethodContextWin : public Dali::Internal::Adaptor::InputMethodContext, public Dali::ConnectionTracker { public: /** * @brief Creates a new InputMethodContext handle * + * @param[in] actor The actor that uses the new InputMethodContext instance. * @return InputMethodContext pointer */ - static InputMethodContextPtr New(); + static InputMethodContextPtr New( Dali::Actor actor ); /** * Constructor * @param[in] win32Window, The window is created by application. */ - explicit InputMethodContextWin( WinWindowHandle win32Window ); + explicit InputMethodContextWin( Dali::Actor actor ); public: @@ -280,6 +281,11 @@ private: */ bool ProcessEventKeyUp( const KeyEvent& keyEvent ); + /** + * Called when the binded actor is added to a window. + */ + void OnStaged( Dali::Actor actor ); + public: /** diff --git a/dali/internal/window-system/common/window-impl.cpp b/dali/internal/window-system/common/window-impl.cpp index 4ecda0d..4411ffa 100644 --- a/dali/internal/window-system/common/window-impl.cpp +++ b/dali/internal/window-system/common/window-impl.cpp @@ -694,7 +694,6 @@ Dali::Window Window::Get( Dali::Actor actor ) return Dali::Window( windowImpl ); } - void Window::SetParent( Dali::Window& parent ) { if ( DALI_UNLIKELY( parent ) ) -- 2.7.4