// EXTERNAL INCLUDES
#include <Ecore_Input.h>
+#ifdef ECORE_WAYLAND2
+#include <Ecore_Wl2.h>
+#else
+#include <Ecore_Wayland.h>
+#endif
+
#include <dali/public-api/events/key-event.h>
#include <dali/public-api/adaptor-framework/key.h>
#include <dali/public-api/object/type-registry.h>
// INTERNAL INCLUDES
#include <dali/integration-api/adaptor.h>
+#include <dali/integration-api/scene-holder.h>
#include <dali/internal/system/common/locale-utils.h>
#include <dali/internal/system/common/singleton-service-impl.h>
#include <dali/public-api/adaptor-framework/input-method.h>
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)
{
}
// Static function calls used by ecore 'c' style callback registration
-void Commit( void *data, Ecore_IMF_Context *imfContext, void *event_info )
+void Commit( void *data, Ecore_IMF_Context *imfContext, void *eventInfo )
{
if ( data )
{
- InputMethodContextEcoreWl* inputMethodContext = reinterpret_cast< InputMethodContextEcoreWl* > ( data );
- inputMethodContext->CommitReceived( data, imfContext, event_info );
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
+ inputMethodContext->CommitReceived( data, imfContext, eventInfo );
}
}
-void PreEdit( void *data, Ecore_IMF_Context *imfContext, void *event_info )
+void PreEdit( void *data, Ecore_IMF_Context *imfContext, void *eventInfo )
{
if ( data )
{
- InputMethodContextEcoreWl* inputMethodContext = reinterpret_cast< InputMethodContextEcoreWl* > ( data );
- inputMethodContext->PreEditChanged( data, imfContext, event_info );
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
+ inputMethodContext->PreEditChanged( data, imfContext, eventInfo );
}
}
{
if ( data )
{
- InputMethodContextEcoreWl* inputMethodContext = reinterpret_cast< InputMethodContextEcoreWl* > ( data );
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
return inputMethodContext->RetrieveSurrounding( data, imfContext, text, cursorPosition );
}
else
{
return;
}
- InputMethodContextEcoreWl* inputMethodContext = reinterpret_cast< InputMethodContextEcoreWl* > ( data );
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
switch (value)
{
case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
{
return;
}
- InputMethodContextEcoreWl* inputMethodContext = reinterpret_cast< InputMethodContextEcoreWl* > ( data );
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
// Emit the signal that the language has changed
inputMethodContext->LanguageChangedSignal().Emit(value);
}
{
return;
}
- InputMethodContextEcoreWl* inputMethodContext = reinterpret_cast< InputMethodContextEcoreWl* > ( data );
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
// Emit signal that the keyboard is resized
inputMethodContext->ResizedSignal().Emit(value);
}
return;
}
- InputMethodContextEcoreWl* inputMethodContext = reinterpret_cast< InputMethodContextEcoreWl* > ( data );
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
switch (value)
{
case ECORE_IMF_INPUT_PANEL_SW_KEYBOARD_MODE:
* Called when an IMF delete surrounding event is received.
* Here we tell the application that it should delete a certain range.
*/
-void ImfDeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *event_info )
+void ImfDeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *eventInfo )
{
if ( data )
{
- InputMethodContextEcoreWl* inputMethodContext = reinterpret_cast< InputMethodContextEcoreWl* > ( data );
- inputMethodContext->DeleteSurrounding( data, imfContext, event_info );
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
+ inputMethodContext->DeleteSurrounding( data, imfContext, eventInfo );
}
}
/**
* Called when the input method sends a private command.
*/
-void PrivateCommand( void *data, Ecore_IMF_Context *imfContext, void *event_info )
+void PrivateCommand( void *data, Ecore_IMF_Context *imfContext, void *eventInfo )
+{
+ if ( data )
+ {
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
+ inputMethodContext->SendPrivateCommand( data, imfContext, eventInfo );
+ }
+}
+
+/**
+ * Called when the input method commits content, such as an image.
+ */
+void CommitContent( void *data, Ecore_IMF_Context *imfContext, void *eventInfo )
{
if ( data )
{
- InputMethodContextEcoreWl* inputMethodContext = reinterpret_cast< InputMethodContextEcoreWl* > ( data );
- inputMethodContext->SendPrivateCommand( data, imfContext, event_info );
+ InputMethodContextEcoreWl* inputMethodContext = static_cast< InputMethodContextEcoreWl* >( data );
+ inputMethodContext->SendCommitContent( data, imfContext, 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.
- // Only when the render surface is window, we can get the window.
- 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;
}
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()
{
DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContext::CreateContext\n" );
+ if( mWindowId == kUninitializedWindowId )
+ {
+ return;
+ }
+
const char *contextId = ecore_imf_context_default_id_get();
if( contextId )
{
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.
- // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent().
- Dali::RenderSurfaceInterface& renderSurface = Dali::Adaptor::Get().GetSurface();
- WindowRenderSurface& windowRenderSurface = static_cast< WindowRenderSurface& >( renderSurface );
-
- int windowId = windowRenderSurface.GetNativeWindowId();
- 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" );
}
}
ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit, this );
ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding, this );
ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand, this );
+ ecore_imf_context_event_callback_add( mIMFContext, ECORE_IMF_CALLBACK_COMMIT_CONTENT, CommitContent, this );
ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback, this );
ecore_imf_context_input_panel_event_callback_add( mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback, this );
ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_COMMIT, Commit );
ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, ImfDeleteSurrounding );
ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_PRIVATE_COMMAND_SEND, PrivateCommand );
+ ecore_imf_context_event_callback_del( mIMFContext, ECORE_IMF_CALLBACK_COMMIT_CONTENT, CommitContent );
ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_STATE_EVENT, InputPanelStateChangeCallback );
ecore_imf_context_input_panel_event_callback_del( mIMFContext, ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, InputPanelLanguageChangeCallback );
* We are still predicting what the user is typing. The latest string is what the InputMethodContext module thinks
* the user wants to type.
*/
-void InputMethodContextEcoreWl::PreEditChanged( void*, ImfContext* imfContext, void* event_info )
+void InputMethodContextEcoreWl::PreEditChanged( void*, ImfContext* imfContext, void* eventInfo )
{
DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::PreEditChanged\n" );
- auto context = reinterpret_cast<Ecore_IMF_Context*>(imfContext);
+ auto context = static_cast<Ecore_IMF_Context*>( imfContext );
char* preEditString( NULL );
int cursorPosition( 0 );
free( preEditString );
}
-void InputMethodContextEcoreWl::CommitReceived( void*, ImfContext* imfContext, void* event_info )
+void InputMethodContextEcoreWl::CommitReceived( void*, ImfContext* imfContext, void* eventInfo )
{
DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::CommitReceived\n" );
if ( Dali::Adaptor::IsAvailable() )
{
- const std::string keyString( static_cast<char*>( event_info ) );
+ const std::string keyString( static_cast<char*>( eventInfo ) );
Dali::InputMethodContext handle( this );
Dali::InputMethodContext::EventData eventData( Dali::InputMethodContext::COMMIT, keyString, 0, 0 );
{
if( text )
{
+ const char* plainText = callbackData.currentText.c_str();
+ if( 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 )
+ {
+ char* iter = NULL;
+ for( iter = const_cast<char*>( plainText ); iter && *iter; ++iter )
+ {
+ *iter = '*';
+ }
+ }
+ }
// The memory allocated by strdup() can be freed by ecore_imf_context_surrounding_get() internally.
- *text = strdup( callbackData.currentText.c_str() );
+ *text = strdup( plainText );
}
if( cursorPosition )
* Called when an InputMethodContext delete surrounding event is received.
* Here we tell the application that it should delete a certain range.
*/
-void InputMethodContextEcoreWl::DeleteSurrounding( void* data, ImfContext* imfContext, void* event_info )
+void InputMethodContextEcoreWl::DeleteSurrounding( void* data, ImfContext* imfContext, void* eventInfo )
{
DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::DeleteSurrounding\n" );
if( Dali::Adaptor::IsAvailable() )
{
- Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>( event_info );
+ Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>( eventInfo );
Dali::InputMethodContext::EventData imfData( Dali::InputMethodContext::DELETE_SURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars );
Dali::InputMethodContext handle( this );
/**
* Called when the input method sends a private command.
*/
-void InputMethodContextEcoreWl::SendPrivateCommand( void* data, ImfContext* imfContext, void* event_info )
+void InputMethodContextEcoreWl::SendPrivateCommand( void* data, ImfContext* imfContext, void* eventInfo )
{
DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendPrivateCommand\n" );
if( Dali::Adaptor::IsAvailable() )
{
- const char* privateCommandSendEvent = static_cast<const char*>( event_info );
+ const char* privateCommandSendEvent = static_cast<const char*>( eventInfo );
Dali::InputMethodContext::EventData imfData( Dali::InputMethodContext::PRIVATE_COMMAND, privateCommandSendEvent, 0, 0 );
Dali::InputMethodContext handle( this );
}
}
+/**
+ * Called when the input method commits content, such as an image.
+ */
+void InputMethodContextEcoreWl::SendCommitContent( void* data, ImfContext* imfContext, void* eventInfo )
+{
+ DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendCommitContent\n" );
+
+ if( Dali::Adaptor::IsAvailable() )
+ {
+ Ecore_IMF_Event_Commit_Content* commitContent = static_cast<Ecore_IMF_Event_Commit_Content *>( eventInfo );
+ if( commitContent )
+ {
+ DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::SendCommitContent commit content : %s, description : %s, mime type : %s\n",
+ commitContent->content_uri, commitContent->description, commitContent->mime_types );
+ mContentReceivedSignal.Emit( commitContent->content_uri, commitContent->description, commitContent->mime_types );
+ }
+ }
+}
+
void InputMethodContextEcoreWl::NotifyCursorPosition()
{
DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::NotifyCursorPosition\n" );
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()
int index;
- if (mIMFContext == NULL)
+ if( mIMFContext == NULL )
{
DALI_LOG_WARNING("VKB Unable to excute ApplyOptions with Null ImfContext\n");
return;
}
- if ( mOptions.CompareAndSet(PANEL_LAYOUT, options, index) )
+ if( mOptions.CompareAndSet(PANEL_LAYOUT, options, index) )
{
ecore_imf_context_input_panel_layout_set( mIMFContext, panelLayoutMap[index] );
+
+ // Sets the input hint which allows input methods to fine-tune their behavior.
+ if( panelLayoutMap[index] == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD )
+ {
+ ecore_imf_context_input_hint_set( mIMFContext, static_cast< Ecore_IMF_Input_Hints >( ecore_imf_context_input_hint_get( mIMFContext ) | ECORE_IMF_INPUT_HINT_SENSITIVE_DATA ) );
+ }
+ else
+ {
+ ecore_imf_context_input_hint_set( mIMFContext, static_cast< Ecore_IMF_Input_Hints >( ecore_imf_context_input_hint_get( mIMFContext ) & ~ECORE_IMF_INPUT_HINT_SENSITIVE_DATA ) );
+ }
}
- if ( mOptions.CompareAndSet(BUTTON_ACTION, options, index) )
+ if( mOptions.CompareAndSet(BUTTON_ACTION, options, index) )
{
ecore_imf_context_input_panel_return_key_type_set( mIMFContext, returnKeyTypeMap[index] );
}
- if ( mOptions.CompareAndSet(AUTO_CAPITALIZE, options, index) )
+ if( mOptions.CompareAndSet(AUTO_CAPITALIZE, options, index) )
{
ecore_imf_context_autocapital_type_set( mIMFContext, autoCapitalMap[index] );
}
- if ( mOptions.CompareAndSet(VARIATION, options, index) )
+ if( mOptions.CompareAndSet(VARIATION, options, index) )
{
ecore_imf_context_input_panel_layout_variation_set( mIMFContext, index );
}
{
DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetKeyboardType\n" );
-#ifdef OVER_TIZEN_VERSION_4
if( mIMFContext )
{
int value;
}
}
}
-#endif // OVER_TIZEN_VERSION_4
+
return Dali::InputMethodContext::KeyboardType::SOFTWARE_KEYBOARD;
}
return locale;
}
+void InputMethodContextEcoreWl::SetContentMIMETypes( const std::string& mimeTypes )
+{
+ DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetContentMIMETypes\n" );
+
+ if( mIMFContext )
+ {
+ ecore_imf_context_mime_type_accept_set( mIMFContext, mimeTypes.c_str() );
+ }
+}
+
bool InputMethodContextEcoreWl::FilterEventKey( const Dali::KeyEvent& keyEvent )
{
bool eventHandled( false );
return prediction;
}
+void InputMethodContextEcoreWl::SetInputPanelLanguage( Dali::InputMethodContext::InputPanelLanguage language )
+{
+ DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::SetInputPanelLanguage\n" );
+ if( mIMFContext )
+ {
+ switch (language)
+ {
+ case Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC:
+ {
+ ecore_imf_context_input_panel_language_set( mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC );
+ break;
+ }
+ case Dali::InputMethodContext::InputPanelLanguage::ALPHABET:
+ {
+ ecore_imf_context_input_panel_language_set( mIMFContext, ECORE_IMF_INPUT_PANEL_LANG_ALPHABET );
+ break;
+ }
+ }
+ }
+}
+
+Dali::InputMethodContext::InputPanelLanguage InputMethodContextEcoreWl::GetInputPanelLanguage() const
+{
+ DALI_LOG_INFO( gLogFilter, Debug::General, "InputMethodContextEcoreWl::GetInputPanelLanguage\n" );
+ if( mIMFContext )
+ {
+ int value;
+ value = ecore_imf_context_input_panel_language_get( mIMFContext );
+
+ switch (value)
+ {
+ case ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC:
+ {
+ return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
+ break;
+ }
+ case ECORE_IMF_INPUT_PANEL_LANG_ALPHABET:
+ {
+ return Dali::InputMethodContext::InputPanelLanguage::ALPHABET;
+ break;
+ }
+ }
+ }
+ return Dali::InputMethodContext::InputPanelLanguage::AUTOMATIC;
+}
+
bool InputMethodContextEcoreWl::ProcessEventKeyDown( const KeyEvent& keyEvent )
{
bool eventHandled( false );
return static_cast<Ecore_IMF_Keyboard_Locks>( lock );
}
+void InputMethodContextEcoreWl::OnStaged( Dali::Actor actor )
+{
+ int windowId = GetWindowIdFromActor( actor );
+
+ if( mWindowId != windowId )
+ {
+ mWindowId = windowId;
+
+ // Reset
+ Finalize();
+ Initialize();
+ }
+}
+
} // Adaptor
} // Internal