Fix Set and Get InputPanelData()
[platform/core/uifw/dali-adaptor.git] / adaptors / x11 / imf-manager-impl-x.cpp
index 3e681b0..6d9d2a2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <imf-manager-impl.h>
 
 // EXTERNAL INCLUDES
-#include <boost/bind.hpp>
 #include <dali/public-api/events/key-event.h>
 #include <dali/public-api/object/type-registry.h>
-#include <adaptor.h>
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
+#include <adaptor.h>
 #include <window-render-surface.h>
 #include <adaptor-impl.h>
+#include <locale-utils.h>
 #include <singleton-service-impl.h>
 #include <virtual-keyboard-impl.h>
+// Ecore is littered with C style cast
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#include "ecore-virtual-keyboard.h"
 
 namespace Dali
 {
@@ -42,7 +46,6 @@ namespace Adaptor
 
 namespace
 {
-
 #if defined(DEBUG_ENABLED)
 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_IMF_MANAGER");
 #endif
@@ -117,40 +120,21 @@ void ImfDeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *even
   }
 }
 
-BaseHandle Create()
+} // unnamed namespace
+
+bool ImfManager::IsAvailable()
 {
-  BaseHandle handle( ImfManager::Get() );
+  bool available( false );
 
   Dali::SingletonService service( SingletonService::Get() );
-  if ( !handle && Adaptor::IsAvailable() && service )
+  if ( service )
   {
-    Adaptor& adaptorImpl( Adaptor::GetImplementation( Adaptor::Get() ) );
-
-    // The Ecore_X_Window needs to use the ImfManager.
-    // Only when the render surface is window, we can get the Ecore_X_Window.
-    Ecore_X_Window ecoreXwin( 0 );
-    Dali::RenderSurface& surface( adaptorImpl.GetSurface() );
-    if( surface.GetType() == Dali::RenderSurface::WINDOW )
-    {
-      ecoreXwin = AnyCast< Ecore_X_Window >( adaptorImpl.GetSurface().GetSurface() );
-    }
-
-    // If we fail to get Ecore_X_Window, we can't use the ImfManager correctly.
-    // Thus you have to call "ecore_imf_context_client_window_set" somewhere.
-    // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent().
-
-    Dali::ImfManager manager = Dali::ImfManager( new ImfManager( ecoreXwin ) );
-    service.Register( typeid( manager ), manager );
-    handle = manager;
+    available = service.GetSingleton( typeid( Dali::ImfManager ) );
   }
 
-  return handle;
+  return available;
 }
 
-TypeRegistration IMF_MANAGER_TYPE( typeid(Dali::ImfManager), typeid(Dali::BaseHandle), Create, true /* Create Instance At Startup */ );
-
-} // unnamed namespace
-
 Dali::ImfManager ImfManager::Get()
 {
   Dali::ImfManager manager;
@@ -160,11 +144,35 @@ Dali::ImfManager ImfManager::Get()
   {
     // Check whether the singleton is already created
     Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::ImfManager ) );
-    if(handle)
+    if( handle )
     {
       // If so, downcast the handle
       manager = Dali::ImfManager( dynamic_cast< ImfManager* >( handle.GetObjectPtr() ) );
     }
+    else if ( 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 ImfManager.
+      // Only when the render surface is window, we can get the Ecore_X_Window.
+      Ecore_X_Window ecoreXwin( AnyCast<Ecore_X_Window>(nativeWindow) );
+      if (ecoreXwin)
+      {
+        // If we fail to get Ecore_X_Window, we can't use the ImfManager correctly.
+        // Thus you have to call "ecore_imf_context_client_window_set" somewhere.
+        // In EvasPlugIn, this function is called in EvasPlugin::ConnectEcoreEvent().
+
+        manager = Dali::ImfManager( new ImfManager( ecoreXwin ) );
+        service.Register( typeid( manager ), manager );
+      }
+      else
+      {
+        DALI_LOG_ERROR("Failed to get native window handle\n");
+      }
+    }
   }
 
   return manager;
@@ -173,10 +181,9 @@ Dali::ImfManager ImfManager::Get()
 ImfManager::ImfManager( Ecore_X_Window ecoreXwin )
 : mIMFContext(),
   mIMFCursorPosition( 0 ),
-  mSurroundingText(""),
+  mSurroundingText(),
   mRestoreAfterFocusLost( false ),
-  mIdleCallbackConnected( false ),
-  mKeyEvents()
+  mIdleCallbackConnected( false )
 {
   ecore_imf_init();
   CreateContext( ecoreXwin );
@@ -212,12 +219,12 @@ void ImfManager::CreateContext( Ecore_X_Window ecoreXwin )
     }
     else
     {
-      DALI_LOG_WARNING("IMF Unable to get IMF Context\n");
+      DALI_LOG_INFO( gLogFilter, Debug::General, "IMF Unable to get IMF Context\n");
     }
   }
   else
   {
-    DALI_LOG_WARNING("IMF Unable to get IMF Context\n");
+    DALI_LOG_INFO( gLogFilter, Debug::General, "IMF Unable to get IMF Context\n");
   }
 }
 
@@ -227,6 +234,7 @@ void ImfManager::DeleteContext()
 
   if ( mIMFContext )
   {
+    ecore_imf_context_del( mIMFContext );
     mIMFContext = NULL;
   }
 }
@@ -273,7 +281,7 @@ void ImfManager::Activate()
 
     // emit keyboard activated signal
     Dali::ImfManager handle( this );
-    mActivatedSignalV2.Emit( handle );
+    mActivatedSignal.Emit( handle );
   }
 }
 
@@ -313,7 +321,7 @@ bool ImfManager::RestoreAfterFocusLost() const
   return mRestoreAfterFocusLost;
 }
 
-void ImfManager::SetRestoreAferFocusLost( bool toggle )
+void ImfManager::SetRestoreAfterFocusLost( bool toggle )
 {
   mRestoreAfterFocusLost = toggle;
 }
@@ -323,16 +331,16 @@ void ImfManager::SetRestoreAferFocusLost( bool toggle )
  * We are still predicting what the user is typing.  The latest string is what the IMF module thinks
  * the user wants to type.
  */
-void ImfManager::PreEditChanged( void *, Ecore_IMF_Context *imfContext, void *event_info )
+void ImfManager::PreEditChanged( void*, Ecore_IMF_Context* imfContext, void* event_info )
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::PreEditChanged\n" );
 
-  char *preEditString( NULL );
+  charpreEditString( NULL );
   int cursorPosition( 0 );
-  Eina_List *attrs = NULL;
-  Eina_List *l = NULL;
+  Eina_Listattrs = NULL;
+  Eina_Listl = NULL;
 
-  Ecore_IMF_Preedit_Attr *attr;
+  Ecore_IMF_Preedit_Attrattr;
 
   // 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.
@@ -341,7 +349,7 @@ void ImfManager::PreEditChanged( void *, Ecore_IMF_Context *imfContext, void *ev
   if ( attrs )
   {
     // iterate through the list of attributes getting the type, start and end position.
-    for ( l = attrs, (attr =  (Ecore_IMF_Preedit_Attr*)eina_list_data_get(l) ); l; l = eina_list_next(l), ( attr = (Ecore_IMF_Preedit_Attr*)eina_list_data_get(l) ))
+    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) ) ))
     {
 #ifdef DALI_PROFILE_UBUNTU
       if ( attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3 ) // (Ecore_IMF)
@@ -355,10 +363,11 @@ void ImfManager::PreEditChanged( void *, Ecore_IMF_Context *imfContext, void *ev
         size_t byteIndex = 0;
 
         // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
-        while ( preEditString[byteIndex] != '\0' )
+        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.
-          size_t currentSequenceLength = Utf8SequenceLength(preEditString[byteIndex]); // returns number of bytes used to represent character.
+          const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character.
           if ( byteIndex == attr->end_index )
           {
             cursorPosition = visualCharacterIndex;
@@ -379,22 +388,18 @@ void ImfManager::PreEditChanged( void *, Ecore_IMF_Context *imfContext, void *ev
 
   if ( Dali::Adaptor::IsAvailable() )
   {
-    std::string keyString ( preEditString );
-    int numberOfChars( 0 );
-
     Dali::ImfManager handle( this );
-    Dali::ImfManager::ImfEventData imfEventData ( Dali::ImfManager::PREEDIT, keyString, cursorPosition, numberOfChars );
-    Dali::ImfManager::ImfCallbackData callbackData = mEventSignalV2.Emit( handle, imfEventData );
+    Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::PREEDIT, preEditString, cursorPosition, 0 );
+    Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
 
-    if ( callbackData.update )
+    if( callbackData.update )
     {
-      SetCursorPosition( callbackData.cursorPosition );
-      SetSurroundingText( callbackData.currentText );
+      mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
 
       NotifyCursorPosition();
     }
 
-    if ( callbackData.preeditResetRequired )
+    if( callbackData.preeditResetRequired )
     {
       Reset();
     }
@@ -402,24 +407,21 @@ void ImfManager::PreEditChanged( void *, Ecore_IMF_Context *imfContext, void *ev
   free( preEditString );
 }
 
-void ImfManager::CommitReceived( void *, Ecore_IMF_Context *imfContext, void *event_info )
+void ImfManager::CommitReceived( void*, Ecore_IMF_Context* imfContext, void* event_info )
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::CommitReceived\n" );
 
   if ( Dali::Adaptor::IsAvailable() )
   {
-    const std::string keyString( (char *)event_info );
-    const int cursorOffset( 0 );
-    const int numberOfChars( 0 );
+    const std::string keyString( static_cast<char*>( event_info ) );
 
     Dali::ImfManager handle( this );
-    Dali::ImfManager::ImfEventData imfEventData ( Dali::ImfManager::COMMIT, keyString, cursorOffset, numberOfChars );
-    Dali::ImfManager::ImfCallbackData callbackData = mEventSignalV2.Emit( handle, imfEventData );
+    Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::COMMIT, keyString, 0, 0 );
+    Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
 
-    if ( callbackData.update )
+    if( callbackData.update )
     {
-      SetCursorPosition( callbackData.cursorPosition );
-      SetSurroundingText( callbackData.currentText );
+      mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
 
       NotifyCursorPosition();
     }
@@ -431,38 +433,28 @@ void ImfManager::CommitReceived( void *, Ecore_IMF_Context *imfContext, void *ev
  * Here the IMF module wishes to know the string we are working with and where within the string the cursor is
  * We need to signal the application to tell us this information.
  */
-Eina_Bool ImfManager::RetrieveSurrounding( void *data, Ecore_IMF_Context *imfContext, char** text, int* cursorPosition )
+Eina_Bool ImfManager::RetrieveSurrounding( void* data, Ecore_IMF_Context* imfContext, char** text, int* cursorPosition )
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::RetrieveSurrounding\n" );
 
-  std::string keyString ( "" );
-  int cursorOffset( 0 );
-  int numberOfChars( 0 );
-
-  Dali::ImfManager::ImfEventData imfData ( Dali::ImfManager::GETSURROUNDING , keyString, cursorOffset, numberOfChars );
+  Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::GETSURROUNDING, std::string(), 0, 0 );
   Dali::ImfManager handle( this );
-  mEventSignalV2.Emit( handle, imfData );
+  Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfData );
 
-  if ( text )
+  if( callbackData.update )
   {
-    std::string surroundingText( GetSurroundingText() );
-
-    if ( !surroundingText.empty() )
+    if( text )
     {
-      *text = strdup( surroundingText.c_str() );
+      *text = strdup( callbackData.currentText.c_str() );
     }
-    else
+
+    if( cursorPosition )
     {
-      *text = strdup( "" );
+      mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
+      *cursorPosition = mIMFCursorPosition;
     }
   }
 
-  if ( cursorPosition )
-  {
-    *cursorPosition = GetCursorPosition();
-  }
-
-
   return EINA_TRUE;
 }
 
@@ -470,21 +462,24 @@ Eina_Bool ImfManager::RetrieveSurrounding( void *data, Ecore_IMF_Context *imfCon
  * Called when an IMF delete surrounding event is received.
  * Here we tell the application that it should delete a certain range.
  */
-void ImfManager::DeleteSurrounding( void *data, Ecore_IMF_Context *imfContext, void *event_info )
+void ImfManager::DeleteSurrounding( void* data, Ecore_IMF_Context* imfContext, void* event_info )
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DeleteSurrounding\n" );
 
-  if ( Dali::Adaptor::IsAvailable() )
+  if( Dali::Adaptor::IsAvailable() )
   {
-    Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = (Ecore_IMF_Event_Delete_Surrounding*) event_info;
-
-    const std::string keyString( "" );
-    const int cursorOffset( deleteSurroundingEvent->offset );
-    const int numberOfChars( deleteSurroundingEvent->n_chars );
+    Ecore_IMF_Event_Delete_Surrounding* deleteSurroundingEvent = static_cast<Ecore_IMF_Event_Delete_Surrounding*>( event_info );
 
-    Dali::ImfManager::ImfEventData imfData ( Dali::ImfManager::DELETESURROUNDING , keyString, cursorOffset, numberOfChars );
+    Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::DELETESURROUNDING, std::string(), deleteSurroundingEvent->offset, deleteSurroundingEvent->n_chars );
     Dali::ImfManager handle( this );
-    mEventSignalV2.Emit( handle, imfData );
+    Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfData );
+
+    if( callbackData.update )
+    {
+      mIMFCursorPosition = static_cast<int>( callbackData.cursorPosition );
+
+      NotifyCursorPosition();
+    }
   }
 }
 
@@ -492,42 +487,244 @@ void ImfManager::NotifyCursorPosition()
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::NotifyCursorPosition\n" );
 
-  if ( mIMFContext )
+  if( mIMFContext )
   {
     ecore_imf_context_cursor_position_set( mIMFContext, mIMFCursorPosition );
   }
 }
 
-int ImfManager::GetCursorPosition()
+void ImfManager::SetCursorPosition( unsigned int cursorPosition )
 {
-  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetCursorPosition\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetCursorPosition\n" );
 
-  return mIMFCursorPosition;
+  mIMFCursorPosition = static_cast<int>( cursorPosition );
 }
 
-void ImfManager::SetCursorPosition( unsigned int cursorPosition )
+unsigned int ImfManager::GetCursorPosition() const
 {
-  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetCursorPosition\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetCursorPosition\n" );
 
-  mIMFCursorPosition = ( int )cursorPosition;
+  return static_cast<unsigned int>( mIMFCursorPosition );
 }
 
-void ImfManager::SetSurroundingText( std::string text )
+void ImfManager::SetSurroundingText( const std::string& text )
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetSurroundingText\n" );
 
   mSurroundingText = text;
 }
 
-std::string ImfManager::GetSurroundingText()
+const std::string& ImfManager::GetSurroundingText() const
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetSurroundingText\n" );
 
   return mSurroundingText;
 }
 
+void ImfManager::NotifyTextInputMultiLine( bool multiLine )
+{
+}
+
+Dali::ImfManager::TextDirection ImfManager::GetTextDirection()
+{
+  Dali::ImfManager::TextDirection direction ( Dali::ImfManager::LeftToRight );
+
+  if ( ImfManager::IsAvailable() /* We do not want to create an instance of ImfManager */ )
+  {
+    if ( mIMFContext )
+    {
+      char* locale( NULL );
+      ecore_imf_context_input_panel_language_locale_get( mIMFContext, &locale );
+
+      if ( locale )
+      {
+        direction = static_cast< Dali::ImfManager::TextDirection >( Locale::GetDirection( std::string( locale ) ) );
+        free( locale );
+      }
+    }
+  }
+  return direction;
+}
+
+Rect<int> ImfManager::GetInputMethodArea()
+{
+  int xPos, yPos, width, height;
+
+  width = height = xPos = yPos = 0;
+
+  if( mIMFContext )
+  {
+    ecore_imf_context_input_panel_geometry_get( mIMFContext, &xPos, &yPos, &width, &height );
+  }
+  else
+  {
+    DALI_LOG_WARNING("VKB Unable to get IMF Context so GetSize unavailable\n");
+  }
+
+  return Rect<int>(xPos,yPos,width,height);
+}
+
+void ImfManager::ApplyOptions( const InputMethodOptions& options )
+{
+  using namespace Dali::InputMethod::Category;
+
+  int index;
+
+  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(AUTO_CAPITALISE, options, index) )
+  {
+  }
+  if ( mOptions.CompareAndSet(ACTION_BUTTON_TITLE, options, index) )
+  {
+  }
+  if ( mOptions.CompareAndSet(VARIATION, options, index) )
+  {
+  }
+}
+
+void ImfManager::SetInputPanelData( const std::string& data )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetInputPanelData\n" );
+
+  if( mIMFContext )
+  {
+    int length = data.length();
+    ecore_imf_context_input_panel_imdata_set( mIMFContext, data.c_str(), length );
+  }
+}
+
+void ImfManager::GetInputPanelData( std::string& data )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelData\n" );
+
+  if( mIMFContext )
+  {
+    int length = 4096; // The max length is 4096 bytes
+    Dali::Vector< char > buffer;
+    buffer.Resize( length );
+    ecore_imf_context_input_panel_imdata_get( mIMFContext, &buffer[0], &length );
+    data = std::string( buffer.Begin(), buffer.End() );
+  }
+}
+
+Dali::ImfManager::State ImfManager::GetInputPanelState()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelState\n" );
+
+  if( mIMFContext )
+  {
+    int value;
+    value = ecore_imf_context_input_panel_state_get( mIMFContext );
+
+    switch (value)
+    {
+      case ECORE_IMF_INPUT_PANEL_STATE_SHOW:
+      {
+        return Dali::ImfManager::SHOW;
+        break;
+      }
+
+      case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
+      {
+        return Dali::ImfManager::HIDE;
+        break;
+      }
+
+      case ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW:
+      {
+        return Dali::ImfManager::WILL_SHOW;
+        break;
+      }
+
+      default:
+      {
+        return Dali::ImfManager::DEFAULT;
+      }
+    }
+  }
+  return Dali::ImfManager::DEFAULT;
+}
+
+void ImfManager::SetReturnKeyState( bool visible )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::SetReturnKeyState\n" );
+
+  if( mIMFContext )
+  {
+    ecore_imf_context_input_panel_return_key_disabled_set( mIMFContext, !visible );
+  }
+}
+
+void ImfManager::AutoEnableInputPanel( bool enabled )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::AutoEnableInputPanel\n" );
+
+  if( mIMFContext )
+  {
+    ecore_imf_context_input_panel_enabled_set( mIMFContext, enabled );
+  }
+}
+
+void ImfManager::ShowInputPanel()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::ShowInputPanel\n" );
+
+  if( mIMFContext )
+  {
+    ecore_imf_context_input_panel_show( mIMFContext );
+  }
+}
+
+void ImfManager::HideInputPanel()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::HideInputPanel\n" );
+
+  if( mIMFContext )
+  {
+    ecore_imf_context_input_panel_hide( mIMFContext );
+  }
+}
+
+Dali::ImfManager::KeyboardType ImfManager::GetKeyboardType()
+{
+  return Dali::ImfManager::KeyboardType::SOFTWARE_KEYBOARD;
+}
+
+std::string ImfManager::GetInputPanelLocale()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::GetInputPanelLocale\n" );
+
+  std::string locale = "";
+
+  if( mIMFContext )
+  {
+    char* value = NULL;
+    ecore_imf_context_input_panel_language_locale_get( mIMFContext, &value );
+
+    if( value )
+    {
+      std::string valueCopy( value );
+      locale = valueCopy;
+
+      // The locale string retrieved must be freed with free().
+      free( value );
+    }
+  }
+  return locale;
+}
+
 } // Adaptor
 
 } // Internal
 
 } // Dali
+
+#pragma GCC diagnostic pop