Merge "fix cursor visible issue" into devel/master
authorBowon Ryu <bowon.ryu@samsung.com>
Thu, 24 Feb 2022 10:16:22 +0000 (10:16 +0000)
committerGerrit Code Review <gerrit@review>
Thu, 24 Feb 2022 10:16:22 +0000 (10:16 +0000)
12 files changed:
automated-tests/src/dali-toolkit-internal/utc-Dali-TextField-internal.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextEditor.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
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/decorator/text-decorator.cpp
dali-toolkit/internal/text/decorator/text-decorator.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-editable-control-interface.h

index 77366b6..8967f0e 100644 (file)
@@ -101,8 +101,8 @@ int UtcDaliTextFieldMultipleBackgroundText(void)
   application.SendNotification();
   application.Render();
 
-  // Now the offscreen root actor should have three children: the renderable, the highlight, and the background.
-  DALI_TEST_CHECK(stencil.GetChildCount() == 3u);
+  // Now the offscreen root actor should have four children: the renderable, the clipped cursor, the highlight, and the background.
+  DALI_TEST_CHECK(stencil.GetChildCount() == 4u);
   // The renderable actor should have one child only: the text
   DALI_TEST_CHECK(renderableActor.GetChildCount() == 1u);
 
index acf34a6..24fdf54 100644 (file)
@@ -1920,7 +1920,7 @@ int utcDaliTextEditorEvent02(void)
   application.SendNotification();
   application.Render();
 
-  Actor layer = editor.GetChildAt(1u);
+  Actor layer = editor.GetChildAt(2u);
   DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION); // The cursor.
   DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
 
@@ -1934,7 +1934,7 @@ int utcDaliTextEditorEvent02(void)
 
   // Checks the cursor and the renderer have been created.
   DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION);   // The cursor.
-  DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION); // The renderer
+  DALI_TEST_EQUALS(stencil.GetChildCount(), 2u, TEST_LOCATION); // The renderer, clipped cursor
 
   Control cursor = Control::DownCast(layer.GetChildAt(0u));
   DALI_TEST_CHECK(cursor);
@@ -2011,8 +2011,8 @@ int utcDaliTextEditorEvent02(void)
 
   DALI_TEST_EQUALS(position2, position6, TEST_LOCATION); // Should be in the same position2.
 
-  // Should not be a renderer.
-  DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
+  // Should not be a renderer, there is only a clipped cursor.
+  DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION);
 
   END_TEST;
 }
@@ -2830,7 +2830,7 @@ int utcDaliTextEditorHandles(void)
   Actor activeLayer = editor.GetChildAt(1u);
 
   // Get the handle's actor.
-  Actor handle = activeLayer.GetChildAt(1u);
+  Actor handle = activeLayer.GetChildAt(0u);
   handle.SetProperty(Actor::Property::SIZE, Vector2(100.f, 100.f));
 
   // Render and notify
index 06612b8..d175568 100644 (file)
@@ -2372,7 +2372,7 @@ int utcDaliTextFieldEvent02(void)
   application.SendNotification();
   application.Render();
 
-  Actor layer = field.GetChildAt(1u);
+  Actor layer = field.GetChildAt(2u);
   DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION); // The cursor.
   DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
 
@@ -2386,7 +2386,7 @@ int utcDaliTextFieldEvent02(void)
 
   // Checks the cursor and the renderer have been created.
   DALI_TEST_EQUALS(layer.GetChildCount(), 1u, TEST_LOCATION);   // The cursor.
-  DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION); // The renderer
+  DALI_TEST_EQUALS(stencil.GetChildCount(), 2u, TEST_LOCATION); // The renderer, clipped cursor
 
   Control cursor = Control::DownCast(layer.GetChildAt(0u));
   DALI_TEST_CHECK(cursor);
@@ -2468,8 +2468,8 @@ int utcDaliTextFieldEvent02(void)
 
   DALI_TEST_EQUALS(position4, position7, TEST_LOCATION); // Should be in the same position2.
 
-  // Should not be a renderer.
-  DALI_TEST_EQUALS(stencil.GetChildCount(), 0u, TEST_LOCATION);
+  // Should not be a renderer, there is only a clipped cursor.
+  DALI_TEST_EQUALS(stencil.GetChildCount(), 1u, TEST_LOCATION);
 
   // Chanege exceed policy (EXCEED_POLICY_ORIGINAL doesn't use stencil )
   field.SetProperty(TextField::Property::TEXT, "This is a long text for the size of the text-field.");
index 7e4b241..40fdcad 100644 (file)
@@ -700,6 +700,11 @@ void TextEditor::OnRelayout(const Vector2& size, RelayoutContainer& container)
     mActiveLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
     ResizeActor(mActiveLayer, contentSize);
   }
+  if(mCursorLayer)
+  {
+    mCursorLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
+    ResizeActor(mCursorLayer, contentSize);
+  }
 
   // If there is text changed, callback is called.
   if(mTextChanged)
@@ -1032,7 +1037,7 @@ void TextEditor::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t n
   }
 }
 
-void TextEditor::AddDecoration(Actor& actor, bool needsClipping)
+void TextEditor::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
 {
   if(actor)
   {
@@ -1040,16 +1045,27 @@ void TextEditor::AddDecoration(Actor& actor, bool needsClipping)
     {
       mClippingDecorationActors.push_back(actor);
     }
-    else
+
+    // If the actor is a layer type, add it.
+    if(type == DecorationType::ACTIVE_LAYER)
     {
-      actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
-      actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
-      Self().Add(actor);
-      mActiveLayer = actor;
+      AddLayer(mActiveLayer, actor);
+    }
+    else if(type == DecorationType::CURSOR_LAYER)
+    {
+      AddLayer(mCursorLayer, actor);
     }
   }
 }
 
+void TextEditor::AddLayer(Actor& layer, Actor& actor)
+{
+  actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  Self().Add(actor);
+  layer = actor;
+}
+
 void TextEditor::SetTextSelectionRange(const uint32_t* start, const uint32_t* end)
 {
   if(mController && mController->IsShowingRealText())
index 8118a1c..a2521ed 100644 (file)
@@ -266,7 +266,7 @@ private: // From Control
   /**
    * @copydoc Text::EditableControlInterface::AddDecoration()
    */
-  void AddDecoration(Actor& actor, bool needsClipping) override;
+  void AddDecoration(Actor& actor, Toolkit::Text::DecorationType type, bool needsClipping) override;
 
   /**
    * @copydoc Text::EditableControlInterface::InputFiltered()
@@ -479,6 +479,13 @@ private: // Implementation
   void OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type);
 
   /**
+  * @brief Add a layer for active or cursor.
+  * @param[in] layer The actor in which to store the layer.
+  * @param[in] actor The new layer to add.
+  */
+  void AddLayer(Actor& layer, Actor& actor);
+
+  /**
    * Construct a new TextEditor.
    */
   TextEditor();
@@ -539,6 +546,7 @@ private: // Data
 
   Actor         mRenderableActor;
   Actor         mActiveLayer;
+  Actor         mCursorLayer;
   Actor         mBackgroundActor;
   CallbackBase* mIdleCallback;
 
index 8152f4b..f0d6c68 100644 (file)
@@ -658,6 +658,11 @@ void TextField::OnRelayout(const Vector2& size, RelayoutContainer& container)
     mActiveLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
     ResizeActor(mActiveLayer, contentSize);
   }
+  if(mCursorLayer)
+  {
+    mCursorLayer.SetProperty(Actor::Property::POSITION, Vector2(padding.start, padding.top));
+    ResizeActor(mCursorLayer, contentSize);
+  }
 
   // If there is text changed, callback is called.
   if(mTextChanged)
@@ -1008,7 +1013,7 @@ void TextField::SelectionChanged(uint32_t oldStart, uint32_t oldEnd, uint32_t ne
   }
 }
 
-void TextField::AddDecoration(Actor& actor, bool needsClipping)
+void TextField::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
 {
   if(actor)
   {
@@ -1016,16 +1021,27 @@ void TextField::AddDecoration(Actor& actor, bool needsClipping)
     {
       mClippingDecorationActors.push_back(actor);
     }
-    else
+
+    // If the actor is a layer type, add it.
+    if(type == DecorationType::ACTIVE_LAYER)
     {
-      actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
-      actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
-      Self().Add(actor);
-      mActiveLayer = actor;
+      AddLayer(mActiveLayer, actor);
+    }
+    else if(type == DecorationType::CURSOR_LAYER)
+    {
+      AddLayer(mCursorLayer, actor);
     }
   }
 }
 
+void TextField::AddLayer(Actor& layer, Actor& actor)
+{
+  actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT);
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  Self().Add(actor);
+  layer = actor;
+}
+
 void TextField::GetControlBackgroundColor(Vector4& color) const
 {
   Property::Value propValue = Self().GetProperty(Toolkit::Control::Property::BACKGROUND);
index 51a97c7..3ba2954 100644 (file)
@@ -257,7 +257,7 @@ private: // From Control
   /**
    * @copydoc Text::EditableControlInterface::AddDecoration()
    */
-  void AddDecoration(Actor& actor, bool needsClipping) override;
+  void AddDecoration(Actor& actor, Toolkit::Text::DecorationType type, bool needsClipping) override;
 
   /**
    * @copydoc Text::EditableControlInterface::InputFiltered()
@@ -271,6 +271,7 @@ private: // From Control
 
   // From SelectableControlInterface
 public:
+
   /**
    * @copydoc Text::SelectableControlInterface::SetTextSelectionRange()
    */
@@ -435,6 +436,13 @@ private: // Implementation
   void OnLayoutDirectionChanged(Actor actor, LayoutDirection::Type type);
 
   /**
+  * @brief Add a layer for active or cursor.
+  * @param[in] layer The actor in which to store the layer.
+  * @param[in] actor The new layer to add.
+  */
+  void AddLayer(Actor& layer, Actor& actor);
+
+  /**
    * Construct a new TextField.
    */
   TextField();
@@ -490,6 +498,7 @@ private: // Data
 
   Actor         mRenderableActor;
   Actor         mActiveLayer;
+  Actor         mCursorLayer;
   Actor         mBackgroundActor;
   CallbackBase* mIdleCallback;
 
index c948701..f4d2ca4 100644 (file)
@@ -256,7 +256,8 @@ struct Decorator::Impl : public ConnectionTracker
     mControlSize = size;
 
     // TODO - Remove this if nothing is active
-    CreateActiveLayer();
+    CreateLayer(mActiveLayer, DecorationType::ACTIVE_LAYER);
+    CreateLayer(mCursorLayer, DecorationType::CURSOR_LAYER);
 
     // Show or hide the cursors
     CreateCursors();
@@ -266,8 +267,8 @@ struct Decorator::Impl : public ConnectionTracker
       const CursorImpl& cursor = mCursor[PRIMARY_CURSOR];
       mPrimaryCursorVisible    = (!mHidePrimaryCursorAndGrabHandle) && ((mControlSize.width - (cursor.position.x + mCursorWidth) > -Math::MACHINE_EPSILON_1000) &&
                                                                      (cursor.position.x > -Math::MACHINE_EPSILON_1000) &&
-                                                                     (mControlSize.height - (cursor.position.y + cursor.cursorHeight) > -Math::MACHINE_EPSILON_1000) &&
-                                                                     (cursor.position.y > -Math::MACHINE_EPSILON_1000));
+                                                                     (mControlSize.height - cursor.position.y > -Math::MACHINE_EPSILON_1000) &&
+                                                                     (cursor.position.y + cursor.cursorHeight > -Math::MACHINE_EPSILON_1000));
       if(mPrimaryCursorVisible)
       {
         mPrimaryCursor.SetProperty(Actor::Property::POSITION, Vector2(cursor.position.x, cursor.position.y));
@@ -280,8 +281,8 @@ struct Decorator::Impl : public ConnectionTracker
       const CursorImpl& cursor = mCursor[SECONDARY_CURSOR];
       mSecondaryCursorVisible  = ((mControlSize.width - (cursor.position.x + mCursorWidth) > -Math::MACHINE_EPSILON_1000) &&
                                  (cursor.position.x > -Math::MACHINE_EPSILON_1000) &&
-                                 (mControlSize.height - (cursor.position.y + cursor.cursorHeight) > -Math::MACHINE_EPSILON_1000) &&
-                                 (cursor.position.y > -Math::MACHINE_EPSILON_1000));
+                                 (mControlSize.height - cursor.position.y > -Math::MACHINE_EPSILON_1000) &&
+                                 (cursor.position.y + cursor.cursorHeight > -Math::MACHINE_EPSILON_1000));
       if(mSecondaryCursorVisible)
       {
         mSecondaryCursor.SetProperty(Actor::Property::POSITION, Vector2(cursor.position.x, cursor.position.y));
@@ -299,8 +300,8 @@ struct Decorator::Impl : public ConnectionTracker
     {
       grabHandle.horizontallyVisible = ((mControlSize.width - (grabHandle.position.x + floor(0.5f * mCursorWidth)) > -Math::MACHINE_EPSILON_1000) &&
                                         (grabHandle.position.x > -Math::MACHINE_EPSILON_1000));
-      grabHandle.verticallyVisible   = (((mControlSize.height - grabHandle.lineHeight) - grabHandle.position.y > -Math::MACHINE_EPSILON_1000) &&
-                                      (grabHandle.position.y > -Math::MACHINE_EPSILON_1000));
+      grabHandle.verticallyVisible   = ((fabsf(mControlSize.height - grabHandle.lineHeight) - grabHandle.position.y > -Math::MACHINE_EPSILON_1000) &&
+                                        (grabHandle.position.y + grabHandle.lineHeight > -Math::MACHINE_EPSILON_1000));
 
       const bool isVisible = grabHandle.horizontallyVisible && grabHandle.verticallyVisible && (!mHidePrimaryCursorAndGrabHandle);
       if(isVisible)
@@ -334,11 +335,11 @@ struct Decorator::Impl : public ConnectionTracker
 
     primary.horizontallyVisible   = ((mControlSize.width - primary.position.x > -Math::MACHINE_EPSILON_1000) &&
                                    (primary.position.x > -Math::MACHINE_EPSILON_1000));
-    primary.verticallyVisible     = (((mControlSize.height - primary.lineHeight) - primary.position.y > -Math::MACHINE_EPSILON_1000) &&
+    primary.verticallyVisible     = ((fabsf(mControlSize.height - primary.lineHeight) - primary.position.y > -Math::MACHINE_EPSILON_1000) &&
                                  (primary.position.y + (primary.verticallyFlipped ? 0.f : primary.lineHeight) > -Math::MACHINE_EPSILON_1000));
     secondary.horizontallyVisible = ((mControlSize.width - secondary.position.x > -Math::MACHINE_EPSILON_1000) &&
                                      (secondary.position.x > -Math::MACHINE_EPSILON_1000));
-    secondary.verticallyVisible   = (((mControlSize.height - secondary.lineHeight) - secondary.position.y > -Math::MACHINE_EPSILON_1000) &&
+    secondary.verticallyVisible   = ((fabsf(mControlSize.height - secondary.lineHeight) - secondary.position.y > -Math::MACHINE_EPSILON_1000) &&
                                    (secondary.position.y + (secondary.verticallyFlipped ? 0.f : secondary.lineHeight) > -Math::MACHINE_EPSILON_1000));
 
     const bool primaryVisible   = primary.horizontallyVisible && primary.verticallyVisible;
@@ -665,7 +666,7 @@ struct Decorator::Impl : public ConnectionTracker
 
         if(!mPrimaryCursor.GetParent())
         {
-          mActiveLayer.Add(mPrimaryCursor);
+          mCursorLayer.Add(mPrimaryCursor);
         }
       }
 
@@ -681,7 +682,7 @@ struct Decorator::Impl : public ConnectionTracker
 
         if(!mSecondaryCursor.GetParent())
         {
-          mActiveLayer.Add(mSecondaryCursor);
+          mCursorLayer.Add(mSecondaryCursor);
         }
       }
       else
@@ -735,23 +736,34 @@ struct Decorator::Impl : public ConnectionTracker
     mPanDetector.DetectedSignal().Connect(this, &Decorator::Impl::OnPan);
   }
 
-  void CreateActiveLayer()
+  void CreateLayer(Actor& layer, DecorationType type)
   {
-    if(!mActiveLayer)
+    if(!layer)
     {
-      mActiveLayer = Actor::New();
+      layer = Actor::New();
 #ifdef DECORATOR_DEBUG
-      mActiveLayer.SetProperty(Actor::Property::NAME, "ActiveLayerActor");
+      if(type == DecorationType::ACTIVE_LAYER)
+      {
+        layer.SetProperty(Actor::Property::NAME, "ActiveLayerActor");
+      }
+      else if(type == DecorationType::CURSOR_LAYER)
+      {
+        layer.SetProperty(Actor::Property::NAME, "CursorLayerActor");
+      }
 #endif
+      bool needsClipping = false;
+      if(type == DecorationType::CURSOR_LAYER)
+      {
+        needsClipping = true;
+      }
 
-      mActiveLayer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-      mActiveLayer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
+      layer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+      layer.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS);
 
-      // Add the active layer telling the controller it doesn't need clipping.
-      mController.AddDecoration(mActiveLayer, false);
+      mController.AddDecoration(layer, type, needsClipping);
     }
 
-    mActiveLayer.RaiseToTop();
+    layer.RaiseToTop();
   }
 
   void SetSelectionHandleMarkerSize(HandleImpl& handle)
@@ -1160,7 +1172,7 @@ struct Decorator::Impl : public ConnectionTracker
     }
 
     // Add the highlight box telling the controller it needs clipping.
-    mController.AddDecoration(mHighlightActor, true);
+    mController.AddDecoration(mHighlightActor, DecorationType::NONE_LAYER, true);
   }
 
   void UpdateHighlight()
@@ -1881,6 +1893,7 @@ struct Decorator::Impl : public ConnectionTracker
   Timer mScrollTimer;      ///< Timer used to scroll the text when the grab handle is moved close to the edges.
 
   Actor                mActiveLayer;                             ///< Actor for active handles and alike that ensures they are above all else.
+  Actor                mCursorLayer;                             ///< Actor for cursor layer. this is for cursor clipping.
   PropertyNotification mHandleVerticalLessThanNotification;      ///< Notifies when the 'y' coord of the active layer is less than a given value.
   PropertyNotification mHandleVerticalGreaterThanNotification;   ///< Notifies when the 'y' coord of the active layer is grater than a given value.
   PropertyNotification mHandleHorizontalLessThanNotification;    ///< Notifies when the 'x' coord of the active layer is less than a given value.
index 59b06e1..ad3037e 100644 (file)
@@ -83,6 +83,14 @@ enum HandleType
   HANDLE_TYPE_COUNT
 };
 
+// Types of decoration.
+enum DecorationType
+{
+  NONE_LAYER,
+  ACTIVE_LAYER,
+  CURSOR_LAYER
+};
+
 /**
  * @brief A Text Decorator is used to display cursors, handles, selection highlights and pop-ups.
  *
@@ -122,9 +130,11 @@ public:
     /**
      * @brief Add a decoration to the parent UI control.
      *
-     * @param[in] decoration The actor displaying a decoration.
+     * @param[in] actor The actor displaying a decoration.
+     * @param[in] type Whether this decoration is a layer or not, which layer it is.
+     * @param[in] needsClipping Whether the actor needs clipping.
      */
-    virtual void AddDecoration(Actor& actor, bool needsClipping) = 0;
+    virtual void AddDecoration(Actor& actor, DecorationType type, bool needsClipping) = 0;
 
     /**
      * @brief An input event from one of the handles.
index 1e1ab68..9ea1e60 100644 (file)
@@ -1521,11 +1521,11 @@ void Controller::GetTargetSize(Vector2& targetSize)
   targetSize = mImpl->mModel->mVisualModel->mControlSize;
 }
 
-void Controller::AddDecoration(Actor& actor, bool needsClipping)
+void Controller::AddDecoration(Actor& actor, DecorationType type, bool needsClipping)
 {
   if(mImpl->mEditableControlInterface)
   {
-    mImpl->mEditableControlInterface->AddDecoration(actor, needsClipping);
+    mImpl->mEditableControlInterface->AddDecoration(actor, type, needsClipping);
   }
 }
 
index 4c7a1ad..f461058 100644 (file)
@@ -1935,7 +1935,7 @@ protected: // Inherit from Text::Decorator::ControllerInterface.
   /**
    * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::AddDecoration()
    */
-  void AddDecoration(Actor& actor, bool needsClipping) override;
+  void AddDecoration(Actor& actor, DecorationType type, bool needsClipping) override;
 
   /**
    * @copydoc Dali::Toolkit::Text::Decorator::ControllerInterface::DecorationEvent()
index 12d4256..f64da8c 100644 (file)
@@ -88,9 +88,10 @@ public:
    * @brief Add a decoration.
    *
    * @param[in] decoration The actor displaying a decoration.
+   * @param[in] type Whether this decoration is a layer or not, which layer it is.
    * @param[in] needsClipping Whether the actor needs clipping.
    */
-  virtual void AddDecoration(Actor& actor, bool needsClipping) = 0;
+  virtual void AddDecoration(Actor& actor, DecorationType type, bool needsClipping) = 0;
 
   /**
    * @brief Gets the color of the control.