[Tizen] Fix Crash when the InsertText event is executed multiple times between Relayout. 45/309745/1 tizen
authorANZ1217 <chihun.jeong@samsung.com>
Mon, 8 Apr 2024 11:46:52 +0000 (20:46 +0900)
committerANZ1217 <chihun.jeong@samsung.com>
Tue, 16 Apr 2024 07:28:37 +0000 (16:28 +0900)
When using IME, InsertText may be executed multiple times within one relayout.
Fix the problem that length of the text cannot be calculated correctly.

Change-Id: Id47f7bbacf90a098055fc7b6ae0d4931a9facde2

automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Controller.cpp
dali-toolkit/internal/text/controller/text-controller-event-handler.cpp
dali-toolkit/internal/text/controller/text-controller-text-updater.cpp
dali-toolkit/internal/text/controller/text-controller-text-updater.h

index 6a3a84a..774cce1 100644 (file)
@@ -1362,3 +1362,44 @@ int UtcDaliTextControllerDeleteSurroundings(void)
 
   END_TEST;
 }
+
+int UtcDaliTextControllerMultipleInsert(void)
+{
+  tet_infoline(" UtcDaliTextControllerMultipleInsert");
+  ToolkitTestApplication application;
+
+  // Creates a text controller.
+  ControllerPtr controller = Controller::New();
+
+  ConfigureTextField(controller);
+
+  // Get the implementation of the text controller
+  Controller::Impl& mImpl = Controller::Impl::GetImplementation(*controller.Get());
+
+  DALI_TEST_EQUALS(EventData::INACTIVE, mImpl.mEventData->mState, TEST_LOCATION);
+
+  InputMethodContext inputMethodContext = InputMethodContext::New();
+
+  // When maid thread is busy, multiple event might be executed.
+  InputMethodContext::EventData imfEvent1 = InputMethodContext::EventData(InputMethodContext::PRE_EDIT, "A", 0, 1);
+  InputMethodContext::EventData imfEvent2 = InputMethodContext::EventData(InputMethodContext::PRE_EDIT, "AAAAA", 0, 5);
+  controller->OnInputMethodContextEvent(inputMethodContext, imfEvent1);
+  controller->OnInputMethodContextEvent(inputMethodContext, imfEvent2);
+
+  // Perform a relayout
+  const Size size(application.GetScene().GetSize());
+
+  application.SendNotification();
+  application.Render();
+
+  controller->Relayout(size);
+
+  std::string text;
+  controller->GetText(text);
+
+  DALI_TEST_EQUALS("AAAAA", text, TEST_LOCATION);
+
+  tet_result(TET_PASS);
+
+  END_TEST;
+}
index 8044923..99cc227 100644 (file)
@@ -768,13 +768,13 @@ bool Controller::EventHandler::DeleteEvent(Controller& controller, int keyCode)
   else if((controller.mImpl->mEventData->mPrimaryCursorPosition > 0) && (keyCode == Dali::DALI_KEY_BACKSPACE))
   {
     // Remove the character before the current cursor position
-    removed = TextUpdater::RemoveText(controller, -1, 1, UPDATE_INPUT_STYLE);
+    removed = TextUpdater::RemoveText(controller, -1, 1, UPDATE_INPUT_STYLE, false);
   }
   else if((controller.mImpl->mEventData->mPrimaryCursorPosition < controller.mImpl->mModel->mLogicalModel->mText.Count()) &&
           (keyCode == Dali::DevelKey::DALI_KEY_DELETE))
   {
     // Remove the character after the current cursor position
-    removed = TextUpdater::RemoveText(controller, 0, 1, UPDATE_INPUT_STYLE);
+    removed = TextUpdater::RemoveText(controller, 0, 1, UPDATE_INPUT_STYLE, false);
   }
 
   if(removed)
@@ -825,7 +825,8 @@ InputMethodContext::CallbackData Controller::EventHandler::OnInputMethodContextE
       const bool textDeleted = TextUpdater::RemoveText(controller,
                                                        inputMethodContextEvent.cursorOffset,
                                                        inputMethodContextEvent.numberOfChars,
-                                                       DONT_UPDATE_INPUT_STYLE);
+                                                       DONT_UPDATE_INPUT_STYLE,
+                                                       false);
 
       if(textDeleted)
       {
index 2ceee77..59da80a 100644 (file)
@@ -208,7 +208,8 @@ void Controller::TextUpdater::InsertText(Controller& controller, const std::stri
     removedPrevious = RemoveText(controller,
                                  -static_cast<int>(eventData->mPrimaryCursorPosition - eventData->mPreEditStartPosition),
                                  eventData->mPreEditLength,
-                                 DONT_UPDATE_INPUT_STYLE);
+                                 DONT_UPDATE_INPUT_STYLE,
+                                 true);
 
     eventData->mPrimaryCursorPosition = eventData->mPreEditStartPosition;
     eventData->mPreEditLength         = 0u;
@@ -495,7 +496,8 @@ bool Controller::TextUpdater::RemoveText(
   Controller&          controller,
   int                  cursorOffset,
   int                  numberOfCharacters,
-  UpdateInputStyleType type)
+  UpdateInputStyleType type,
+  bool                 isDeletingPreEdit)
 {
   bool removed   = false;
   bool removeAll = false;
@@ -608,7 +610,10 @@ bool Controller::TextUpdater::RemoveText(
       if(removeAll)
       {
         impl.ClearPreEditFlag();
-        textUpdateInfo.mNumberOfCharactersToAdd = 0;
+        if(!isDeletingPreEdit)
+        {
+          textUpdateInfo.mNumberOfCharactersToAdd = 0;
+        }
       }
 
       // Updates the text style runs by removing characters. Runs with no characters are removed.
index 47403f6..319697f 100644 (file)
@@ -63,9 +63,10 @@ struct Controller::TextUpdater
    * @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
    * @param[in] numberOfCharacters The number of characters to delete from the cursorOffset.
    * @param[in] type Whether to update the input style.
+   * @param[in] isDeletingPreEdit Whether to remove pre-edit when inserting text.
    * @return True if the remove was successful.
    */
-  static bool RemoveText(Controller& controller, int cursorOffset, int numberOfCharacters, UpdateInputStyleType type);
+  static bool RemoveText(Controller& controller, int cursorOffset, int numberOfCharacters, UpdateInputStyleType type, bool isDeletingPreEdit);
 
   /**
    * @brief Checks if text is selected and if so removes it.