Merge "Add SelectionCleared signal" into devel/master
authorBowon Ryu <bowon.ryu@samsung.com>
Fri, 27 Aug 2021 01:56:48 +0000 (01:56 +0000)
committerGerrit Code Review <gerrit@review>
Fri, 27 Aug 2021 01:56:48 +0000 (01:56 +0000)
1  2 
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.cpp
dali-toolkit/devel-api/controls/text-controls/text-editor-devel.h
dali-toolkit/devel-api/controls/text-controls/text-field-devel.cpp
dali-toolkit/devel-api/controls/text-controls/text-field-devel.h
dali-toolkit/internal/controls/text-controls/text-editor-impl.cpp
dali-toolkit/internal/controls/text-controls/text-editor-impl.h
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.h
dali-toolkit/internal/text/text-controller-impl-event-handler.cpp

@@@ -136,6 -136,7 +136,7 @@@ const std::string DEFAULT_DEVICE_NAME("
  static bool gSelectionChangedCallbackCalled;
  static uint32_t oldSelectionStart;
  static uint32_t oldSelectionEnd;
+ static bool gSelectionClearedCallbackCalled;
  static bool gAnchorClickedCallBackCalled;
  static bool gAnchorClickedCallBackNotCalled;
  static bool gTextChangedCallBackCalled;
@@@ -161,6 -162,13 +162,13 @@@ struct CallbackFuncto
    bool* mCallbackFlag;
  };
  
+ static void TestSelectionClearedCallback(TextEditor control)
+ {
+   tet_infoline(" TestSelectionClearedCallback");
+   gSelectionClearedCallbackCalled = true;
+ }
  static void TestSelectionChangedCallback(TextEditor control, uint32_t oldStart, uint32_t oldEnd)
  {
    tet_infoline(" TestSelectionChangedCallback");
@@@ -4004,297 -4012,6 +4012,297 @@@ int UtcDaliToolkitTextEditorEllipsisPos
    END_TEST;
  }
  
 +int UtcDaliTextEditorCopyText(void)
 +{
 +  ToolkitTestApplication application;
 +  tet_infoline(" UtcDaliTextEditorCopyText ");
 +
 +  TextEditor textEditor = TextEditor::New();
 +
 +  std::string selectedText = "";
 +  std::string copiedText = "";
 +
 +  application.GetScene().Add( textEditor );
 +
 +  textEditor.SetProperty( Actor::Property::SIZE, Vector2( 300.f, 50.f ) );
 +  textEditor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
 +  textEditor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
 +
 +  // Avoid a crash when core load gl resources.
 +  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  textEditor.SetProperty( TextEditor::Property::TEXT, "Hello world" );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Hello is selected
 +  DevelTextEditor::SelectText( textEditor, 0, 5 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "Hello", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_START ).Get<int>(), 0, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_END ).Get<int>(), 5, TEST_LOCATION );
 +
 +  // Hello is copied
 +  copiedText = DevelTextEditor::CopyText( textEditor );
 +  DALI_TEST_EQUALS( "Hello", copiedText, TEST_LOCATION );
 +
 +  // world is selected
 +  DevelTextEditor::SelectText( textEditor, 6, 11 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "world", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_START ).Get<int>(), 6, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_END ).Get<int>(), 11, TEST_LOCATION );
 +
 +  // world is copied
 +  copiedText = DevelTextEditor::CopyText( textEditor );
 +  DALI_TEST_EQUALS( "world", copiedText, TEST_LOCATION );
 +
 +  // "lo wo" is selected
 +  DevelTextEditor::SelectText( textEditor, 3, 8 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "lo wo", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_START ).Get<int>(), 3, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_END ).Get<int>(), 8, TEST_LOCATION );
 +
 +  // "lo wo" is copied
 +  copiedText = DevelTextEditor::CopyText( textEditor );
 +  DALI_TEST_EQUALS( "lo wo", copiedText, TEST_LOCATION );
 +
 +  END_TEST;
 +}
 +
 +int UtcDaliTextEditorCutText(void)
 +{
 +  ToolkitTestApplication application;
 +  tet_infoline(" UtcDaliTextEditorCutText ");
 +
 +  TextEditor textEditor = TextEditor::New();
 +
 +  std::string selectedText = "";
 +
 +  application.GetScene().Add( textEditor );
 +
 +  textEditor.SetProperty( Actor::Property::SIZE, Vector2( 300.f, 50.f ) );
 +  textEditor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
 +  textEditor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
 +
 +  // Avoid a crash when core load gl resources.
 +  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  textEditor.SetProperty( TextEditor::Property::TEXT, "Hello world" );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Hello is selected
 +  DevelTextEditor::SelectText( textEditor, 0, 5 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "Hello", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_START ).Get<int>(), 0, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_END ).Get<int>(), 5, TEST_LOCATION );
 +
 +  // Hello is cut
 +  DALI_TEST_EQUALS( "Hello", DevelTextEditor::CutText( textEditor ), TEST_LOCATION );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( TextEditor::Property::TEXT ).Get<std::string>(), " world", TEST_LOCATION );
 +
 +  // " w" is selected
 +  DevelTextEditor::SelectText( textEditor, 0, 2 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( " w", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_START ).Get<int>(), 0, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_END ).Get<int>(), 2, TEST_LOCATION );
 +
 +  // " w" is cut
 +  DALI_TEST_EQUALS( " w", DevelTextEditor::CutText( textEditor ), TEST_LOCATION );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( TextEditor::Property::TEXT ).Get<std::string>(), "orld", TEST_LOCATION );
 +
 +  // Test Cut from the middle
 +
 +  // "rl" is selected
 +  DevelTextEditor::SelectText( textEditor, 1, 3 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "rl", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_START ).Get<int>(), 1, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_END ).Get<int>(), 3, TEST_LOCATION );
 +
 +  // "rl" is cut
 +  DALI_TEST_EQUALS( "rl", DevelTextEditor::CutText( textEditor ), TEST_LOCATION );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( TextEditor::Property::TEXT ).Get<std::string>(), "od", TEST_LOCATION );
 +
 +  // Test Cut from the end
 +
 +  // "d" is selected
 +  DevelTextEditor::SelectText( textEditor, 1, 2 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "d", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_START ).Get<int>(), 1, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textEditor.GetProperty( DevelTextEditor::Property::SELECTED_TEXT_END ).Get<int>(), 2, TEST_LOCATION );
 +
 +  // "d" is cut
 +  DALI_TEST_EQUALS( "d", DevelTextEditor::CutText( textEditor ), TEST_LOCATION );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( textEditor.GetProperty( TextEditor::Property::TEXT ).Get<std::string>(), "o", TEST_LOCATION );
 +
 +  END_TEST;
 +}
 +
 +int UtcDaliTextEditorPasteText(void)
 +{
 +  ToolkitTestApplication application;
 +  tet_infoline(" UtcDaliTextEditorPasteText ");
 +
 +  TextEditor editor = TextEditor::New();
 +  DALI_TEST_CHECK( editor );
 +
 +  application.GetScene().Add( editor );
 +
 +  std::string cutText = "";
 +  std::string copiedText = "";
 +
 +  editor.SetProperty( TextEditor::Property::TEXT, "Hello\nworld\nHello world" );
 +  editor.SetProperty( TextEditor::Property::POINT_SIZE, 10.f );
 +  editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) );
 +  editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
 +  editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
 +
 +  // Avoid a crash when core load gl resources.
 +  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Tap on the text editor
 +  TestGenerateTap( application, 3.0f, 25.0f );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Move to second line of the text.
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Select some text in the right of the current cursor position
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_SHIFT_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Cut the selected text
 +  cutText = DevelTextEditor::CutText(editor);
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( "wor", cutText, TEST_LOCATION );
 +  DALI_TEST_EQUALS( "Hello\nld\nHello world", editor.GetProperty<std::string>( TextEditor::Property::TEXT ), TEST_LOCATION );
 +
 +  // Select some text in the left of the current cursor position
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_SHIFT_LEFT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_LEFT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_LEFT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN,  "",DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_LEFT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Copy the selected text
 +  copiedText = DevelTextEditor::CopyText(editor);
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( "lo\n", copiedText, TEST_LOCATION );
 +  DALI_TEST_EQUALS( "Hello\nld\nHello world", editor.GetProperty<std::string>( TextEditor::Property::TEXT ), TEST_LOCATION );
 +
 +
 +  // Move the cursor to the third line
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Paste the selected text at the current cursor position
 +  DevelTextEditor::PasteText(editor);
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( "Hello\nld\nHello lo\nworld", editor.GetProperty<std::string>( TextEditor::Property::TEXT ), TEST_LOCATION );
 +
 +  END_TEST;
 +}
  int UtcDaliTextEditorLineSpacing(void)
  {
    ToolkitTestApplication application;
@@@ -4447,6 -4164,140 +4455,140 @@@ int utcDaliTextEditorCursorPositionChan
    END_TEST;
  }
  
+ int utcDaliTextEditorSelectionClearedSignal(void)
+ {
+   ToolkitTestApplication application;
+   tet_infoline(" utcDaliTextEditorSelectionClearedSignal");
+   TextEditor editor = TextEditor::New();
+   DALI_TEST_CHECK( editor );
+   application.GetScene().Add( editor );
+   // connect to the selection changed signal.
+   ConnectionTracker* testTracker = new ConnectionTracker();
+   DevelTextEditor::SelectionClearedSignal(editor).Connect(&TestSelectionClearedCallback);
+   bool selectionClearedSignal = false;
+   editor.ConnectSignal( testTracker, "selectionCleared",   CallbackFunctor(&selectionClearedSignal) );
+   editor.SetProperty( TextEditor::Property::TEXT, "Hello\nworld\nHello world" );
+   editor.SetProperty( TextEditor::Property::POINT_SIZE, 10.f );
+   editor.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) );
+   editor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+   editor.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+   // Avoid a crash when core load gl resources.
+   application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // Tap on the text editor
+   TestGenerateTap( application, 3.0f, 25.0f );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // Move to second line of the text & Select some text in the right of the current cursor position
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); 
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // remove selection
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_ESCAPE, 0, 0, Integration::KeyEvent::UP, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // Tap on the text editor
+   TestGenerateTap( application, 3.0f, 25.0f );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   gSelectionClearedCallbackCalled = false;
+   // Move to second line of the text & select.
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   //remove selection
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   gSelectionClearedCallbackCalled = false;
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // Move to second line of the text & select.
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // replace C with selected text
+   application.ProcessEvent( GenerateKey( "c", "", "c", KEY_C_CODE, 0, 0, Integration::KeyEvent::DOWN, "c", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   gSelectionClearedCallbackCalled = false;
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DevelTextEditor::SelectText( editor ,1, 3 );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   editor.SetProperty( DevelTextEditor::Property::PRIMARY_CURSOR_POSITION, 3);
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   gSelectionClearedCallbackCalled = false;
+   DevelTextEditor::SelectText( editor ,1, 3 );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // select none
+   DevelTextEditor::SelectNone(editor);
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   END_TEST;
+ }
  int utcDaliTextEditorSelectionChangedSignal(void)
  {
    ToolkitTestApplication application;
@@@ -120,6 -120,7 +120,6 @@@ const std::string DEFAULT_FONT_DIR( "/r
  const int KEY_RETURN_CODE = 36;
  const int KEY_A_CODE = 38;
  const int KEY_D_CODE = 40;
 -
  const int KEY_SHIFT_MODIFIER = 257;
  
  const std::string DEFAULT_DEVICE_NAME("hwKeyboard");
  static bool gSelectionChangedCallbackCalled;
  static uint32_t oldSelectionStart;
  static uint32_t oldSelectionEnd;
+ static bool gSelectionClearedCallbackCalled;
  static bool gAnchorClickedCallBackCalled;
  static bool gAnchorClickedCallBackNotCalled;
  static bool gTextChangedCallBackCalled;
@@@ -218,6 -220,13 +219,13 @@@ struct CallbackFuncto
    bool* mCallbackFlag;
  };
  
+ static void TestSelectionClearedCallback(TextField control)
+ {
+   tet_infoline(" TestSelectionClearedCallback");
+   gSelectionClearedCallbackCalled = true;
+ }
  static void TestSelectionChangedCallback(TextField control, uint32_t oldStart, uint32_t oldEnd)
  {
    tet_infoline(" TestSelectionChangedCallback");
@@@ -4001,286 -4010,6 +4009,286 @@@ int UtcDaliToolkitTextFieldEllipsisPosi
    END_TEST;
  }
  
 +int UtcDaliTextFieldCopyText(void)
 +{
 +  ToolkitTestApplication application;
 +  tet_infoline(" UtcDaliTextFieldCopyText ");
 +
 +  TextField textField = TextField::New();
 +
 +  std::string selectedText = "";
 +  std::string copiedText = "";
 +
 +  application.GetScene().Add( textField );
 +
 +  textField.SetProperty( Actor::Property::SIZE, Vector2( 300.f, 50.f ) );
 +  textField.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
 +  textField.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
 +
 +  // Avoid a crash when core load gl resources.
 +  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  textField.SetProperty( TextField::Property::TEXT, "Hello world" );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Hello is selected
 +  DevelTextField::SelectText( textField, 0, 5 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textField.GetProperty( DevelTextField::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "Hello", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_START ).Get<int>(), 0, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_END ).Get<int>(), 5, TEST_LOCATION );
 +
 +  // Hello is copied
 +  copiedText = DevelTextField::CopyText( textField );
 +  DALI_TEST_EQUALS( "Hello", copiedText, TEST_LOCATION );
 +
 +  // world is selected
 +  DevelTextField::SelectText( textField, 6, 11 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textField.GetProperty( DevelTextField::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "world", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_START ).Get<int>(), 6, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_END ).Get<int>(), 11, TEST_LOCATION );
 +
 +  // world is copied
 +  copiedText = DevelTextField::CopyText( textField );
 +  DALI_TEST_EQUALS( "world", copiedText, TEST_LOCATION );
 +
 +  // "lo wo" is selected
 +  DevelTextField::SelectText( textField, 3, 8 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textField.GetProperty( DevelTextField::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "lo wo", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_START ).Get<int>(), 3, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_END ).Get<int>(), 8, TEST_LOCATION );
 +
 +  // "lo wo" is copied
 +  copiedText = DevelTextField::CopyText( textField );
 +  DALI_TEST_EQUALS( "lo wo", copiedText, TEST_LOCATION );
 +
 +  END_TEST;
 +}
 +
 +int UtcDaliTextFieldCutText(void)
 +{
 +  ToolkitTestApplication application;
 +  tet_infoline(" UtcDaliTextFieldCutText ");
 +
 +  TextField textField = TextField::New();
 +
 +  std::string selectedText = "";
 +
 +  application.GetScene().Add( textField );
 +
 +  textField.SetProperty( Actor::Property::SIZE, Vector2( 300.f, 50.f ) );
 +  textField.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
 +  textField.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
 +
 +  // Avoid a crash when core load gl resources.
 +  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  textField.SetProperty( TextField::Property::TEXT, "Hello world" );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Hello is selected
 +  DevelTextField::SelectText( textField, 0, 5 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textField.GetProperty( DevelTextField::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "Hello", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_START ).Get<int>(), 0, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_END ).Get<int>(), 5, TEST_LOCATION );
 +
 +  // Hello is cut
 +  DALI_TEST_EQUALS( "Hello", DevelTextField::CutText( textField ), TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( TextField::Property::TEXT ).Get<std::string>(), " world", TEST_LOCATION );
 +
 +  // " w" is selected
 +  DevelTextField::SelectText( textField, 0, 2 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textField.GetProperty( DevelTextField::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( " w", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_START ).Get<int>(), 0, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_END ).Get<int>(), 2, TEST_LOCATION );
 +
 +  // " w" is cut
 +  DALI_TEST_EQUALS( " w", DevelTextField::CutText( textField ), TEST_LOCATION );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( TextField::Property::TEXT ).Get<std::string>(), "orld", TEST_LOCATION );
 +
 +  // Test Cut from the middle
 +
 +  // "rl" is selected
 +  DevelTextField::SelectText( textField, 1, 3 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textField.GetProperty( DevelTextField::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "rl", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_START ).Get<int>(), 1, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_END ).Get<int>(), 3, TEST_LOCATION );
 +
 +  // "rl" is cut
 +  DALI_TEST_EQUALS( "rl", DevelTextField::CutText( textField ), TEST_LOCATION );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( TextField::Property::TEXT ).Get<std::string>(), "od", TEST_LOCATION );
 +
 +  // Test Cut from the end
 +
 +  // "d" is selected
 +  DevelTextField::SelectText( textField, 1, 2 );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  selectedText = textField.GetProperty( DevelTextField::Property::SELECTED_TEXT ).Get<std::string>();
 +  DALI_TEST_EQUALS( "d", selectedText, TEST_LOCATION );
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_START ).Get<int>(), 1, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textField.GetProperty( DevelTextField::Property::SELECTED_TEXT_END ).Get<int>(), 2, TEST_LOCATION );
 +
 +  // "d" is cut
 +  DALI_TEST_EQUALS( "d", DevelTextField::CutText( textField ), TEST_LOCATION );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( TextField::Property::TEXT ).Get<std::string>(), "o", TEST_LOCATION );
 +
 +  END_TEST;
 +}
 +
 +int UtcDaliTextFieldPasteText(void)
 +{
 +  ToolkitTestApplication application;
 +  tet_infoline(" UtcDaliTextFieldPasteText ");
 +
 +  TextField textField = TextField::New();
 +
 +  application.GetScene().Add( textField );
 +
 +  std::string cutText = "";
 +  std::string copiedText = "";
 +
 +  textField.SetProperty( Actor::Property::SIZE, Vector2( 300.f, 50.f ) );
 +  textField.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
 +  textField.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
 +
 +  // Avoid a crash when core load gl resources.
 +  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  textField.SetProperty( TextField::Property::TEXT, "Hello World" );
 +
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Tap on the text editor
 +  TestGenerateTap( application, 3.0f, 25.0f );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Select some text in the right of the current cursor position
 +  DevelTextField::SelectText( textField, 0, 3 );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Cut the selected text
 +  cutText = DevelTextField::CutText(textField);
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( "Hel", cutText, TEST_LOCATION );
 +  DALI_TEST_EQUALS( textField.GetProperty( TextField::Property::TEXT ).Get<std::string>(), "lo World", TEST_LOCATION );
 +
 +  DevelTextField::SelectText( textField, 0, 3 );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Copy the selected text
 +  copiedText = DevelTextField::CopyText(textField);
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( "lo ", copiedText, TEST_LOCATION );
 +  DALI_TEST_EQUALS( "lo World", textField.GetProperty<std::string>( TextField::Property::TEXT ), TEST_LOCATION );
 +
 +  // Move the cursor to the end of the line
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +  application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  // Paste the selected text at the current cursor position
 +  DevelTextField::PasteText(textField);
 +
 +  // Render and notify
 +  application.SendNotification();
 +  application.Render();
 +
 +  DALI_TEST_EQUALS( textField.GetProperty( TextField::Property::TEXT ).Get<std::string>(), "lo Worldlo ", TEST_LOCATION );
 +
 +  END_TEST;
 +}
  int utcDaliTextFieldCursorPositionChangedSignal(void)
  {
    ToolkitTestApplication application;
    END_TEST;
  }
  
+ int utcDaliTextFieldSelectionClearedSignal(void)
+ {
+   ToolkitTestApplication application;
+   tet_infoline(" utcDaliTextFieldSelectionClearedSignal");
+   TextField field = TextField::New();
+   DALI_TEST_CHECK( field );
+   application.GetScene().Add( field );
+   // connect to the selection changed signal.
+   ConnectionTracker* testTracker = new ConnectionTracker();
+   DevelTextField::SelectionClearedSignal(field).Connect(&TestSelectionClearedCallback);
+   bool selectionClearedSignal = false;
+   field.ConnectSignal( testTracker, "selectionCleared",   CallbackFunctor(&selectionClearedSignal) );
+   field.SetProperty( TextField::Property::TEXT, "Hello\nworld\nHello world" );
+   field.SetProperty( TextField::Property::POINT_SIZE, 10.f );
+   field.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 50.f ) );
+   field.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT );
+   field.SetProperty( Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT );
+   // Avoid a crash when core load gl resources.
+   application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // Tap on the text editor
+   TestGenerateTap( application, 3.0f, 25.0f );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // Move to second line of the text & Select some text in the right of the current cursor position
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) ); 
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // remove selection
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_ESCAPE, 0, 0, Integration::KeyEvent::UP, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // Tap on the text editor
+   TestGenerateTap( application, 3.0f, 25.0f );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   gSelectionClearedCallbackCalled = false;
+   // Move to second line of the text & select.
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   //remove selection
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   gSelectionClearedCallbackCalled = false;
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // Move to second line of the text & select.
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_DOWN, 0, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   application.ProcessEvent( GenerateKey( "", "", "", DALI_KEY_CURSOR_RIGHT, KEY_SHIFT_MODIFIER, 0, Integration::KeyEvent::DOWN, "", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // replace D with selected text
+   application.ProcessEvent( GenerateKey( "D", "", "D", KEY_D_CODE, 0, 0, Integration::KeyEvent::DOWN, "D", DEFAULT_DEVICE_NAME, Device::Class::NONE, Device::Subclass::NONE ) );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   gSelectionClearedCallbackCalled = false;
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DevelTextField::SelectText( field ,1, 3 );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   field.SetProperty( DevelTextField::Property::PRIMARY_CURSOR_POSITION, 3);
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   gSelectionClearedCallbackCalled = false;
+   DevelTextField::SelectText( field ,1, 3 );
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   // select none
+   DevelTextField::SelectNone(field);
+   // Render and notify
+   application.SendNotification();
+   application.Render();
+   DALI_TEST_CHECK(gSelectionClearedCallbackCalled);
+   END_TEST;
+ }
  int utcDaliTextFieldSelectionChangedSignal(void)
  {
    ToolkitTestApplication application;
@@@ -55,6 -55,11 +55,11 @@@ SelectionChangedSignalType& SelectionCh
    return GetImpl(textEditor).SelectionChangedSignal();
  }
  
+ SelectionClearedSignalType& SelectionClearedSignal(TextEditor textEditor)
+ {
+   return GetImpl(textEditor).SelectionClearedSignal();
+ }
  void SelectWholeText(TextEditor textEditor)
  {
    GetImpl(textEditor).SelectWholeText();
@@@ -75,21 -80,6 +80,21 @@@ void ScrollBy(TextEditor textEditor, Ve
    GetImpl(textEditor).ScrollBy(scroll);
  }
  
 +string CopyText(TextEditor textEditor)
 +{
 +  return GetImpl(textEditor).CopyText();
 +}
 +
 +string CutText(TextEditor textEditor)
 +{
 +  return GetImpl(textEditor).CutText();
 +}
 +
 +void PasteText(TextEditor textEditor)
 +{
 +  GetImpl(textEditor).PasteText();
 +}
 +
  } // namespace DevelTextEditor
  
  } // namespace Toolkit
@@@ -397,6 -397,23 +397,23 @@@ using SelectionChangedSignalType = Sign
  DALI_TOOLKIT_API SelectionChangedSignalType& SelectionChangedSignal(TextEditor textEditor);
  
  /**
+  * @brief selection cleared signal type.
+  */
+ using SelectionClearedSignalType = Signal<void(TextEditor)>;
+ /**
+  * @brief This signal is emitted when the selection has been cleared.
+  *
+  * A callback of the following type may be connected:
+  * @code
+  *   void YourCallbackName( TextEditor textEditor);
+  * @endcode
+  * @param[in] textEditor The instance of TextEditor.
+  * @return The signal to connect to
+  */
+ DALI_TOOLKIT_API SelectionClearedSignalType& SelectionClearedSignal(TextEditor textEditor);
+ /**
   * @brief Select the whole text of TextEditor.
   *
   * @param[in] textEditor The instance of TextEditor.
@@@ -433,29 -450,6 +450,29 @@@ DALI_TOOLKIT_API void SelectText(TextEd
   */
  DALI_TOOLKIT_API void ScrollBy(TextEditor textEditor, Vector2 scroll);
  
 +/**
 + * @brief Copy and return the selected text of TextEditor.
 + *
 + * @param[in] textEditor The instance of TextEditor.
 + * @return The copied text.
 + */
 +DALI_TOOLKIT_API std::string CopyText(TextEditor textEditor);
 +
 +/**
 + * @brief Cut and return the selected text of TextEditor.
 + *
 + * @param[in] textEditor The instance of TextEditor.
 + * @return The cut text.
 + */
 +DALI_TOOLKIT_API std::string CutText(TextEditor textEditor);
 +
 +/**
 + * @brief Paste the most recent clipboard text item into the TextEditor.
 + *
 + * @param[in] textEditor The instance of TextEditor.
 + */
 +DALI_TOOLKIT_API void PasteText(TextEditor textEditor);
 +
  } // namespace DevelTextEditor
  
  } // namespace Toolkit
@@@ -50,6 -50,11 +50,11 @@@ SelectionChangedSignalType& SelectionCh
    return GetImpl(textField).SelectionChangedSignal();
  }
  
+ SelectionClearedSignalType& SelectionClearedSignal(TextField textField)
+ {
+   return GetImpl(textField).SelectionClearedSignal();
+ }
  void SelectWholeText(TextField textField)
  {
    GetImpl(textField).SelectWholeText();
@@@ -65,21 -70,6 +70,21 @@@ void SelectText(TextField textField, co
    GetImpl(textField).SelectText(start, end);
  }
  
 +string CopyText(TextField textField)
 +{
 +  return GetImpl(textField).CopyText();
 +}
 +
 +string CutText(TextField textField)
 +{
 +  return GetImpl(textField).CutText();
 +}
 +
 +void PasteText(TextField textField)
 +{
 +  GetImpl(textField).PasteText();
 +}
 +
  } // namespace DevelTextField
  
  } // namespace Toolkit
@@@ -319,6 -319,23 +319,23 @@@ using SelectionChangedSignalType = Sign
  DALI_TOOLKIT_API SelectionChangedSignalType& SelectionChangedSignal(TextField textField);
  
  /**
+  * @brief selection cleared signal type.
+  */
+ using SelectionClearedSignalType = Signal<void(TextField)>;
+ /**
+  * @brief This signal is emitted when the selection has been cleared.
+  *
+  * A callback of the following type may be connected:
+  * @code
+  *   void YourCallbackName( TextField textField);
+  * @endcode
+  * @param[in] textField The instance of TextField.
+  * @return The signal to connect to
+  */
+ DALI_TOOLKIT_API SelectionClearedSignalType& SelectionClearedSignal(TextField textField);
+ /**
   * @brief Select the whole text of TextField.
   *
   * @param[in] textField The instance of TextField.
@@@ -347,29 -364,6 +364,29 @@@ DALI_TOOLKIT_API void SelectNone(TextFi
   */
  DALI_TOOLKIT_API void SelectText(TextField textField, const uint32_t start, const uint32_t end);
  
 +/**
 + * @brief Copy and return the selected text of TextField.
 + *
 + * @param[in] textField The instance of TextField.
 + * @return The copied text.
 + */
 +DALI_TOOLKIT_API std::string CopyText(TextField textField);
 +
 +/**
 + * @brief Cut and return the selected text of TextField.
 + *
 + * @param[in] textField The instance of TextField.
 + * @return The cut text.
 + */
 +DALI_TOOLKIT_API std::string CutText(TextField textField);
 +
 +/**
 + * @brief Paste the most recent clipboard text item into the TextField.
 + *
 + * @param[in] textField The instance of TextField.
 + */
 +DALI_TOOLKIT_API void PasteText(TextField textField);
 +
  } // namespace DevelTextField
  
  } // namespace Toolkit
@@@ -160,6 -160,7 +160,7 @@@ DALI_SIGNAL_REGISTRATION(Toolkit, TextE
  DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "inputFiltered",         SIGNAL_INPUT_FILTERED         )
  DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "cursorPositionChanged", SIGNAL_CURSOR_POSITION_CHANGED)
  DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "selectionChanged",      SIGNAL_SELECTION_CHANGED      )
+ DALI_SIGNAL_REGISTRATION(Toolkit, TextEditor, "selectionCleared",      SIGNAL_SELECTION_CLEARED      )
  
  DALI_TYPE_REGISTRATION_END()
  // clang-format on
@@@ -1263,35 -1264,6 +1264,35 @@@ void TextEditor::SelectText(const uint3
    }
  }
  
 +string TextEditor::CopyText()
 +{
 +  string copiedText = "";
 +  if(mController && mController->IsShowingRealText())
 +  {
 +    copiedText = mController->CopyText();
 +  }
 +  return copiedText;
 +}
 +
 +string TextEditor::CutText()
 +{
 +  string cutText = "";
 +  if(mController && mController->IsShowingRealText())
 +  {
 +    cutText = mController->CutText();
 +  }
 +  return cutText;
 +}
 +
 +void TextEditor::PasteText()
 +{
 +  if(mController)
 +  {
 +    SetKeyInputFocus(); //Giving focus to the editor that was passed to the PasteText in case the passed editor (current editor) doesn't have focus.
 +    mController->PasteText();
 +  }
 +}
 +
  void TextEditor::ScrollBy(Vector2 scroll)
  {
    if(mController && mController->IsShowingRealText())
@@@ -1358,6 -1330,11 +1359,11 @@@ DevelTextEditor::SelectionChangedSignal
    return mSelectionChangedSignal;
  }
  
+ DevelTextEditor::SelectionClearedSignalType& TextEditor::SelectionClearedSignal()
+ {
+   return mSelectionClearedSignal;
+ }
  Text::ControllerPtr TextEditor::GetTextController()
  {
    return mController;
@@@ -1418,6 -1395,14 +1424,14 @@@ bool TextEditor::DoConnectSignal(BaseOb
        editorImpl.SelectionChangedSignal().Connect(tracker, functor);
      }
    }
+   else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_CLEARED))
+   {
+     if(editor)
+     {
+       Internal::TextEditor& editorImpl(GetImpl(editor));
+       editorImpl.SelectionClearedSignal().Connect(tracker, functor);
+     }
+   }
    else
    {
      // signalName does not match any signal
@@@ -1660,6 -1645,11 +1674,11 @@@ void TextEditor::OnRelayout(const Vecto
      EmitSelectionChangedSignal();
    }
  
+   if(mSelectionCleared)
+   {
+     EmitSelectionClearedSignal();
+   }
    // The text-editor emits signals when the input style changes. These changes of style are
    // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals
    // can't be emitted during the size negotiation as the callbacks may update the UI.
@@@ -2039,10 -2029,22 +2058,22 @@@ void TextEditor::EmitSelectionChangedSi
    mSelectionChanged = false;
  }
  
+ void TextEditor::EmitSelectionClearedSignal()
+ {
+   Dali::Toolkit::TextEditor handle(GetOwner());
+   mSelectionClearedSignal.Emit(handle);
+   mSelectionCleared = false;
+ }
  void TextEditor::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd)
  {
    if(((oldStart != newStart) || (oldEnd != newEnd)) && !mSelectionChanged)
    {
+     if(newStart == newEnd)
+     {
+       mSelectionCleared = true;
+     }
      mSelectionChanged  = true;
      mOldSelectionStart = oldStart;
      mOldSelectionEnd   = oldEnd;
@@@ -2336,7 -2338,8 +2367,8 @@@ TextEditor::TextEditor(
    mScrollStarted(false),
    mTextChanged(false),
    mCursorPositionChanged(false),
-   mSelectionChanged(false)
+   mSelectionChanged(false),
+   mSelectionCleared(false)
  {
  }
  
@@@ -108,6 -108,11 +108,11 @@@ public
    DevelTextEditor::SelectionChangedSignalType& SelectionChangedSignal();
  
    /**
+    * @copydoc Dali::Toollkit::TextEditor::SelectionClearedSignal()
+    */
+   DevelTextEditor::SelectionClearedSignalType& SelectionClearedSignal();
+   /**
     * Connects a callback function with the object's signals.
     * @param[in] object The object providing the signal.
     * @param[in] tracker Used to disconnect the signal.
@@@ -326,21 -331,6 +331,21 @@@ public
     */
    void SetEditable(bool editable) override;
  
 +  /**
 +   * @copydoc Text::EditableControlInterface::CopyText()
 +   */
 +  string CopyText() override;
 +
 +  /**
 +   * @copydoc Text::EditableControlInterface::CutText()
 +   */
 +  string CutText() override;
 +
 +  /**
 +   * @copydoc Text::EditableControlInterface::PasteText()
 +   */
 +  void PasteText() override;
 +
    // From AnchorControlInterface
  
    /**
@@@ -413,6 -403,11 +418,11 @@@ private: // Implementatio
    void EmitSelectionChangedSignal();
  
    /**
+    * @brief Emits SelectionCleared signal.
+    */
+   void EmitSelectionClearedSignal();
+   /**
     * @brief set RenderActor's position with new scrollPosition
     *
     * Apply updated scroll position or start scroll animation if VerticalScrollAnimation is enabled
@@@ -473,6 -468,7 +483,7 @@@ private: // Dat
    Toolkit::DevelTextEditor::InputFilteredSignalType         mInputFilteredSignal;
    Toolkit::DevelTextEditor::CursorPositionChangedSignalType mCursorPositionChangedSignal;
    Toolkit::DevelTextEditor::SelectionChangedSignalType      mSelectionChangedSignal;
+   Toolkit::DevelTextEditor::SelectionClearedSignalType      mSelectionClearedSignal;
  
    InputMethodContext            mInputMethodContext;
    Text::ControllerPtr           mController;
    bool  mTextChanged : 1;           ///< If true, emits TextChangedSignal in next OnRelayout().
    bool  mCursorPositionChanged : 1; ///< If true, emits CursorPositionChangedSignal at the end of OnRelayout().
    bool  mSelectionChanged : 1;      ///< If true, emits SelectionChangedSignal at the end of OnRelayout().
+   bool  mSelectionCleared : 1;      ///< If true, emits SelectionClearedSignal at the end of OnRelayout().
  
    //args for cursor PositionChanged event
    unsigned int mOldPosition;
@@@ -147,6 -147,7 +147,7 @@@ DALI_SIGNAL_REGISTRATION(Toolkit, TextF
  DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "inputFiltered",         SIGNAL_INPUT_FILTERED         )
  DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "cursorPositionChanged", SIGNAL_CURSOR_POSITION_CHANGED)
  DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionChanged",      SIGNAL_SELECTION_CHANGED      )
+ DALI_SIGNAL_REGISTRATION(Toolkit, TextField, "selectionCleared",      SIGNAL_SELECTION_CLEARED      )
  
  DALI_TYPE_REGISTRATION_END()
  // clang-format on
@@@ -1216,35 -1217,6 +1217,35 @@@ Uint32Pair TextField::GetTextSelectionR
    return range;
  }
  
 +string TextField::CopyText()
 +{
 +  string copiedText = "";
 +  if(mController && mController->IsShowingRealText())
 +  {
 +    copiedText = mController->CopyText();
 +  }
 +  return copiedText;
 +}
 +
 +string TextField::CutText()
 +{
 +  string cutText = "";
 +  if(mController && mController->IsShowingRealText())
 +  {
 +    cutText = mController->CutText();
 +  }
 +  return cutText;
 +}
 +
 +void TextField::PasteText()
 +{
 +  if(mController)
 +  {
 +    SetKeyInputFocus(); //Giving focus to the field that was passed to the PasteText in case the passed field (current field) doesn't have focus.
 +    mController->PasteText();
 +  }
 +}
 +
  InputMethodContext TextField::GetInputMethodContext()
  {
    return mInputMethodContext;
@@@ -1301,6 -1273,14 +1302,14 @@@ bool TextField::DoConnectSignal(BaseObj
        fieldImpl.SelectionChangedSignal().Connect(tracker, functor);
      }
    }
+   else if(0 == strcmp(signalName.c_str(), SIGNAL_SELECTION_CLEARED))
+   {
+     if(field)
+     {
+       Internal::TextField& fieldImpl(GetImpl(field));
+       fieldImpl.SelectionClearedSignal().Connect(tracker, functor);
+     }
+   }
    else
    {
      // signalName does not match any signal
@@@ -1345,6 -1325,11 +1354,11 @@@ DevelTextField::SelectionChangedSignalT
    return mSelectionChangedSignal;
  }
  
+ DevelTextField::SelectionClearedSignalType& TextField::SelectionClearedSignal()
+ {
+   return mSelectionClearedSignal;
+ }
  void TextField::OnInitialize()
  {
    Actor self = Self();
@@@ -1551,6 -1536,11 +1565,11 @@@ void TextField::OnRelayout(const Vector
      EmitSelectionChangedSignal();
    }
  
+   if(mSelectionCleared)
+   {
+     EmitSelectionClearedSignal();
+   }
    // The text-field emits signals when the input style changes. These changes of style are
    // detected during the relayout process (size negotiation), i.e after the cursor has been moved. Signals
    // can't be emitted during the size negotiation as the callbacks may update the UI.
@@@ -1947,10 -1937,22 +1966,22 @@@ void TextField::EmitSelectionChangedSig
    mSelectionChanged = false;
  }
  
+ void TextField::EmitSelectionClearedSignal()
+ {
+   Dali::Toolkit::TextField handle(GetOwner());
+   mSelectionClearedSignal.Emit(handle);
+   mSelectionCleared = false;
+ }
  void TextField::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t newStart, uint32_t newEnd)
  {
    if(((oldStart != newStart) || (oldEnd != newEnd)) && !mSelectionChanged)
    {
+     if(newStart == newEnd)
+     {
+       mSelectionCleared = true;
+     }
      mSelectionChanged  = true;
      mOldSelectionStart = oldStart;
      mOldSelectionEnd   = oldEnd;
@@@ -2103,7 -2105,8 +2134,8 @@@ TextField::TextField(
    mHasBeenStaged(false),
    mTextChanged(false),
    mCursorPositionChanged(false),
-   mSelectionChanged(false)
+   mSelectionChanged(false),
+   mSelectionCleared(false)
  {
  }
  
@@@ -131,6 -131,11 +131,11 @@@ public
     */
    DevelTextField::SelectionChangedSignalType& SelectionChangedSignal();
  
+   /**
+    * @copydoc TextField::SelectionClearedSignal()
+    */
+   DevelTextField::SelectionClearedSignalType& SelectionClearedSignal();
  private: // From Control
    /**
     * @copydoc Control::OnInitialize()
@@@ -298,21 -303,6 +303,21 @@@ public
     */
    void SetEditable(bool editable) override;
  
 +  /**
 +   * @copydoc Dali::EditableControlInterface::CopyText()
 +   */
 +  string CopyText() override;
 +
 +  /**
 +   * @copydoc Dali::EditableControlInterface::CutText()
 +   */
 +  string CutText() override;
 +
 +  /**
 +   * @copydoc Text::EditableControlInterface::PasteText()
 +   */
 +  void PasteText() override;
 +
    // From AnchorControlInterface
  
    /**
@@@ -383,6 -373,11 +388,11 @@@ private: // Implementatio
    void EmitSelectionChangedSignal();
  
    /**
+    * @brief Emits SelectionCleared signal.
+    */
+   void EmitSelectionClearedSignal();
+   /**
     * @brief Callback function for when the layout is changed.
     * @param[in] actor The actor whose layoutDirection is changed.
     * @param[in] type  The layoutDirection.
@@@ -428,6 -423,7 +438,7 @@@ private: // Dat
    Toolkit::DevelTextField::InputFilteredSignalType         mInputFilteredSignal;
    Toolkit::DevelTextField::CursorPositionChangedSignalType mCursorPositionChangedSignal;
    Toolkit::DevelTextField::SelectionChangedSignalType      mSelectionChangedSignal;
+   Toolkit::DevelTextField::SelectionClearedSignalType      mSelectionClearedSignal;
  
    InputMethodContext       mInputMethodContext;
    Text::ControllerPtr      mController;
    bool  mTextChanged : 1;           ///< If true, emits TextChangedSignal in next OnRelayout().
    bool  mCursorPositionChanged : 1; ///< If true, emits CursorPositionChangedSignal at the end of OnRelayout().
    bool  mSelectionChanged : 1;      ///< If true, emits SelectionChangedSignal at the end of OnRelayout().
+   bool  mSelectionCleared : 1;      ///< If true, emits SelectionClearedSignal at the end of OnRelayout().
  
    //args for cursor position changed event
    unsigned int mOldPosition;
@@@ -286,6 -286,8 +286,8 @@@ void ControllerImplEventHandler::OnCurs
    ModelPtr&        model           = impl.mModel;
    LogicalModelPtr& logicalModel    = model->mLogicalModel;
    VisualModelPtr&  visualModel     = model->mVisualModel;
+   uint32_t         oldSelStart     = eventData.mLeftSelectionPosition;
+   uint32_t         oldSelEnd       = eventData.mRightSelectionPosition;
  
    CharacterIndex& primaryCursorPosition         = eventData.mPrimaryCursorPosition;
    CharacterIndex  previousPrimaryCursorPosition = primaryCursorPosition;
      // Update selection position after moving the cursor
      eventData.mLeftSelectionPosition  = primaryCursorPosition;
      eventData.mRightSelectionPosition = primaryCursorPosition;
+     if(impl.mSelectableControlInterface != nullptr && eventData.mDecorator->IsHighlightVisible())
+     {
+       impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+     }
    }
  
    if(isShiftModifier && impl.IsShowingRealText() && eventData.mShiftSelectionFlag)
        int cursorPositionDelta = primaryCursorPosition - previousPrimaryCursorPosition;
        if(cursorPositionDelta > 0 || eventData.mRightSelectionPosition > 0u) // Check the boundary
        {
-         uint32_t oldStart = eventData.mLeftSelectionPosition;
-         uint32_t oldEnd   = eventData.mRightSelectionPosition;
          eventData.mRightSelectionPosition += cursorPositionDelta;
  
          if(impl.mSelectableControlInterface != nullptr)
          {
-           impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
+           impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
          }
        }
        selecting = true;
@@@ -477,8 -481,10 +481,10 @@@ void ControllerImplEventHandler::OnTapE
        if(impl.IsShowingRealText())
        {
          // Convert from control's coords to text's coords.
-         const float xPosition = event.p2.mFloat - model->mScrollPosition.x;
-         const float yPosition = event.p3.mFloat - model->mScrollPosition.y;
+         const float xPosition   = event.p2.mFloat - model->mScrollPosition.x;
+         const float yPosition   = event.p3.mFloat - model->mScrollPosition.y;
+         uint32_t    oldSelStart = eventData.mLeftSelectionPosition;
+         uint32_t    oldSelEnd   = eventData.mRightSelectionPosition;
  
          // Keep the tap 'x' position. Used to move the cursor.
          eventData.mCursorHookPositionX = xPosition;
                                                                         CharacterHitTest::TAP,
                                                                         matchedCharacter);
  
+         if(impl.mSelectableControlInterface != nullptr && eventData.mDecorator->IsHighlightVisible())
+         {
+           impl.mSelectableControlInterface->SelectionChanged(oldSelStart, oldSelEnd, eventData.mPrimaryCursorPosition, eventData.mPrimaryCursorPosition);
+         }
          // When the cursor position is changing, delay cursor blinking
          eventData.mDecorator->DelayCursorBlink();
        }
@@@ -839,7 -850,7 +850,7 @@@ void ControllerImplEventHandler::OnHand
      eventData.mIsRightHandleSelected = true;
    }
  
 -  if((impl.mSelectableControlInterface != nullptr) || eventData.mUpdateRightSelectionPosition || eventData.mUpdateLeftSelectionPosition)
 +  if((impl.mSelectableControlInterface != nullptr) && ((oldStart != eventData.mLeftSelectionPosition) || (oldEnd != eventData.mRightSelectionPosition)))
    {
      impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
    }
@@@ -926,7 -937,7 +937,7 @@@ void ControllerImplEventHandler::OnHand
      }
    }
  
 -  if((impl.mSelectableControlInterface != nullptr) || eventData.mUpdateRightSelectionPosition || eventData.mUpdateLeftSelectionPosition)
 +  if((impl.mSelectableControlInterface != nullptr) && ((oldStart != eventData.mLeftSelectionPosition) || (oldEnd != eventData.mRightSelectionPosition)))
    {
      impl.mSelectableControlInterface->SelectionChanged(oldStart, oldEnd, eventData.mLeftSelectionPosition, eventData.mRightSelectionPosition);
    }