From 33ef32a5cb0ddea3887e763c5ed02c0c128d5bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A7=9A=E6=98=8E?= Date: Thu, 31 Oct 2024 11:35:39 +0800 Subject: [PATCH] =?UTF-8?q?RichEditor=E6=96=B0=E9=81=BF=E8=AE=A9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 姚明 --- .../rich_editor_base_controller.cpp | 7 +- .../rich_editor/rich_editor_controller.cpp | 4 +- .../rich_editor/rich_editor_paint_method.cpp | 9 +++ .../rich_editor/rich_editor_pattern.cpp | 68 +++++++------------ .../pattern/rich_editor/rich_editor_pattern.h | 46 ++++++++++--- .../rich_editor_select_overlay.cpp | 4 +- .../core/pipeline_ng/pipeline_context.cpp | 22 +++++- .../core/pipeline_ng/pipeline_context.h | 2 + .../rich_editor/rich_editor_click_test_ng.cpp | 2 +- 9 files changed, 101 insertions(+), 63 deletions(-) diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_base_controller.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_base_controller.cpp index c4a54716933..71787f023c1 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_base_controller.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_base_controller.cpp @@ -42,8 +42,9 @@ bool RichEditorBaseController::SetCaretOffset(int32_t caretPosition) { auto richEditorPattern = pattern_.Upgrade(); CHECK_NULL_RETURN(richEditorPattern, false); - richEditorPattern->TriggerAvoidOnCaretChange(); - return richEditorPattern->SetCaretOffset(caretPosition); + auto result = richEditorPattern->SetCaretOffset(caretPosition); + richEditorPattern->ForceTriggerAvoidOnCaretChange(true); + return result; } void RichEditorBaseController::SetTypingStyle(std::optional typingStyle, @@ -88,7 +89,7 @@ void RichEditorBaseController::SetSelection( auto richEditorPattern = pattern_.Upgrade(); CHECK_NULL_VOID(richEditorPattern); richEditorPattern->SetSelection(selectionStart, selectionEnd, options, isForward); - richEditorPattern->TriggerAvoidOnCaretChange(); + richEditorPattern->ForceTriggerAvoidOnCaretChange(); } const PreviewTextInfo RichEditorBaseController::GetPreviewTextInfo() const diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.cpp index fcf91132d72..8d9d43aa734 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.cpp @@ -65,7 +65,7 @@ void RichEditorController::UpdateSpanStyle( } richEditorPattern->SetUpdateSpanStyle(updateSpanStyle_); richEditorPattern->UpdateSpanStyle(start, end, textStyle, imageStyle); - richEditorPattern->TriggerAvoidOnCaretChange(); + richEditorPattern->ForceTriggerAvoidOnCaretChange(); } void RichEditorController::SetUpdateSpanStyle(struct UpdateSpanStyle updateSpanStyle) @@ -110,7 +110,7 @@ void RichEditorController::UpdateParagraphStyle(int32_t start, int32_t end, cons auto richEditorPattern = pattern_.Upgrade(); CHECK_NULL_VOID(richEditorPattern); richEditorPattern->UpdateParagraphStyle(start, end, style); - richEditorPattern->TriggerAvoidOnCaretChange(); + richEditorPattern->ForceTriggerAvoidOnCaretChange(); } std::vector RichEditorController::GetParagraphsInfo(int32_t start, int32_t end) { diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_paint_method.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_paint_method.cpp index be2c1b32848..d4e891cf459 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_paint_method.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_paint_method.cpp @@ -86,7 +86,16 @@ void RichEditorPaintMethod::SetCaretOffsetAndHeight(PaintWrapper* paintWrapper) CHECK_NULL_VOID(overlayMod); CHECK_NULL_VOID(!richEditorPattern->IsMoveCaretAnywhere()); // Avoid to reset caret offset auto [caretOffset, caretHeight] = richEditorPattern->CalculateCaretOffsetAndHeight(); + auto lastOffset = overlayMod->GetCaretOffset(); + auto lastCaretY = lastOffset.GetY() + overlayMod->GetCaretHeight() - richEditorPattern->GetLastTextRect().GetY(); + auto curCaretY = caretOffset.GetY() + caretHeight - richEditorPattern->GetTextRect().GetY(); overlayMod->SetCaretOffsetAndHeight(caretOffset, caretHeight); + if (richEditorPattern->IsTriggerAvoidOnCaretAvoidMode() || !NearEqual(lastCaretY, curCaretY) || + !NearEqual(lastOffset.GetX(), caretOffset.GetX())) { + richEditorPattern->NotifyCaretChange(); + richEditorPattern->ResetTriggerAvoidFlagOnCaretChange(); + } + richEditorPattern->ChangeLastRichTextRect(); } void RichEditorPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper) diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp index a872e82059c..7c36dbefe76 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp @@ -158,6 +158,7 @@ void RichEditorPattern::SetStyledString(const RefPtr& value) styledString_->AddCustomSpan(); styledString_->SetFramNode(WeakClaim(host.GetRawPtr())); host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); + ForceTriggerAvoidOnCaretChange(); } void RichEditorPattern::UpdateSpanItems(const std::list>& spanItems) @@ -466,7 +467,7 @@ void RichEditorPattern::AfterStyledStringChange(int32_t start, int32_t length, c changeValue.SetRangeAfter({ changeStart, stringEnd }); eventHub->FireOnStyledStringDidChange(changeValue); } - TriggerAvoidOnCaretChange(); + ForceTriggerAvoidOnCaretChange(); } void RichEditorPattern::OnModifyDone() @@ -517,7 +518,6 @@ void RichEditorPattern::OnModifyDone() enabled_ = enabledCache; host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); } - TriggerAvoidOnCaretChangeAfterLayoutTask(); } void RichEditorPattern::HandleEnabled() @@ -594,7 +594,6 @@ void RichEditorPattern::ClearOnFocusTextField() bool RichEditorPattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, const DirtySwapConfig& config) { CHECK_NULL_RETURN(!config.skipMeasure && !dirty->SkipMeasureContent(), false); - auto originHeight = frameRect_.Height(); frameRect_ = dirty->GetGeometryNode()->GetFrameRect(); auto layoutAlgorithmWrapper = DynamicCast(dirty->GetLayoutAlgorithm()); CHECK_NULL_RETURN(layoutAlgorithmWrapper, false); @@ -614,7 +613,7 @@ bool RichEditorPattern::OnDirtyLayoutWrapperSwap(const RefPtr& di if (!isRichEditorInit_) { FireOnReady(); } - MoveCaretOnLayoutSwap(LessNotEqual(originHeight, frameRect_.Height())); + MoveCaretOnLayoutSwap(); HandleTasksOnLayoutSwap(); HandleSelectOverlayOnLayoutSwap(); if (!isModifyingContent_) { @@ -671,10 +670,15 @@ void RichEditorPattern::SupplementIdealSizeWidth(const RefPtr& frameN } } -void RichEditorPattern::MoveCaretOnLayoutSwap(bool isReduceSize) +void RichEditorPattern::MoveCaretOnLayoutSwap() { MoveCaretAfterTextChange(); - bool needScroll = (needMoveCaretToContentRect_ || isEditing_) && !isReduceSize; + auto context = GetContext(); + bool isResize = false; + if (context) { + isResize = context->GetEnableKeyBoardAvoidMode() == KeyBoardAvoidMode::RESIZE; + } + bool needScroll = (needMoveCaretToContentRect_ || isEditing_) && !isResize; if (needScroll) { MoveCaretToContentRect(); needMoveCaretToContentRect_ = false; @@ -798,7 +802,6 @@ RichEditorPattern::OneStepDragParam::OneStepDragParam(const std::function(BlurStyle::NO_MATERIAL); } @@ -1055,7 +1058,6 @@ int32_t RichEditorPattern::AddPlaceholderSpan(const RefPtr& customNode, placeholderPipelineContext->SetDoKeyboardAvoidAnimate(false); } SetNeedMoveCaretToContentRect(); - TriggerAvoidOnCaretChange(); placeholderSpanNode->MarkModifyDone(); placeholderSpanNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); host->MarkModifyDone(); @@ -1286,7 +1288,7 @@ void RichEditorPattern::AfterContentChange(RichEditorChangeValue& changeValue) if (eventHub && eventHub->HasOnDidChange()) { eventHub->FireOnDidChange(changeValue); } - TriggerAvoidOnCaretChange(); + ForceTriggerAvoidOnCaretChange(); } void RichEditorPattern::SpanNodeFission(RefPtr& spanNode) @@ -2700,7 +2702,7 @@ void RichEditorPattern::HandleClickEvent(GestureEvent& info) HandleDoubleClickEvent(info); } else { HandleSingleClickEvent(info); - TriggerAvoidOnCaretChange(); + NotifyCaretChange(); } } @@ -3174,11 +3176,9 @@ void RichEditorPattern::HandleFocusEvent() isFontScaleChanged = !NearEqual(lastFontScale_, currentFontScale); lastFontScale_ = currentFontScale; } - if (isCaretInContentArea_ && isFontScaleChanged) { - auto host = GetHost(); - if (host) { - host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); - } + auto host = GetHost(); + if (host) { + host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); } if (!usingMouseRightButton_ && !isLongPress_ && !isDragging_ && !dataDetectorAdapter_->hasClickedMenuOption_) { auto windowMode = GetWindowMode(); @@ -3355,6 +3355,11 @@ std::pair RichEditorPattern::CalculateEmptyValueCaretRect() return std::make_pair(offset, caretHeight); } +void RichEditorPattern::NotifyCaretChange() +{ + IF_TRUE(!IsSelected(), TriggerAvoidOnCaretChange()); +} + TextAlign RichEditorPattern::GetTextAlignByDirection() { auto layoutProperty = GetLayoutProperty(); @@ -3448,6 +3453,7 @@ void RichEditorPattern::HandleDoubleClickOrLongPress(GestureEvent& info) return; } HandleDoubleClickOrLongPress(info, host); + ForceTriggerAvoidOnCaretChange(true); } Offset RichEditorPattern::ConvertGlobalToLocalOffset(const Offset& globalOffset) @@ -6690,7 +6696,7 @@ void RichEditorPattern::HandleTouchUpAfterLongPress() CalculateHandleOffsetAndShowOverlay(); selectOverlay_->ProcessOverlay({ .animation = true }); FireOnSelectionChange(selectStart, selectEnd); - IF_TRUE(IsSingleHandle(), TriggerAvoidOnCaretChange()); + IF_TRUE(IsSingleHandle(), ForceTriggerAvoidOnCaretChange()); } void RichEditorPattern::HandleTouchMove(const Offset& offset) @@ -7103,9 +7109,8 @@ void RichEditorPattern::TriggerAvoidOnCaretChange() if (!safeAreaManager || NearZero(safeAreaManager->GetKeyboardInset().Length(), 0)) { return; } + textFieldManager->SetHeight(GetCaretRect().Height()); textFieldManager->TriggerAvoidOnCaretChange(); - auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight(); - SetLastCaretPos(caretPos); } void RichEditorPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) @@ -7136,11 +7141,6 @@ void RichEditorPattern::OnWindowSizeChanged(int32_t width, int32_t height, Windo TaskExecutor::TaskType::UI, "ArkUIRichEditorOnWindowSizeChangedRotation"); } -void RichEditorPattern::OnFontScaleConfigurationUpdate() -{ - TriggerAvoidOnCaretChangeAfterLayoutTask(); -} - void RichEditorPattern::CopySelectionMenuParams(SelectOverlayInfo& selectInfo, TextResponseType responseType) { auto selectType = selectedType_.value_or(TextSpanType::NONE); @@ -7264,26 +7264,6 @@ void RichEditorPattern::EncodeTlvDataByResultObject(const ResultObject& result, spanString->EncodeTlv(tlvData); } -void RichEditorPattern::TriggerAvoidOnCaretChangeAfterLayoutTask() -{ - auto context = GetContext(); - CHECK_NULL_VOID(context); - CHECK_NULL_VOID(context->UsingCaretAvoidMode()); - auto textFieldManager = DynamicCast(context->GetTextFieldManager()); - CHECK_NULL_VOID(textFieldManager); - context->AddAfterLayoutTask([weak = WeakClaim(this), manager = WeakPtr(textFieldManager)] { - auto textField = weak.Upgrade(); - CHECK_NULL_VOID(textField); - auto textFieldManager = manager.Upgrade(); - CHECK_NULL_VOID(textFieldManager); - auto caretPos = textFieldManager->GetFocusedNodeCaretRect().Top() + textFieldManager->GetHeight(); - if (caretPos != textField->GetLastCaretPos()) { - TAG_LOGI(ACE_KEYBOARD, "Caret Position Change, Retrigger Avoid"); - textField->TriggerAvoidOnCaretChange(); - } - }); -} - void RichEditorPattern::HandleOnCopy(bool isUsingExternalKeyboard) { CHECK_NULL_VOID(clipboard_); @@ -7828,7 +7808,6 @@ void RichEditorPattern::InitSelection(const Offset& pos) TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "select rect is empty, select nothing"); textSelector_.Update(currentPosition, currentPosition); } - TriggerAvoidOnCaretChangeAfterLayoutTask(); } std::pair RichEditorPattern::JudgeSelectType(const Offset& pos) @@ -10793,6 +10772,7 @@ void RichEditorPattern::UpdateSelectionByTouchMove(const Offset& touchOffset) StartVibratorByIndexChange(start, textSelector_.GetTextStart()); } HandleSelectionChange(start, end); + TriggerAvoidOnCaretChange(); host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF); } diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h index 25b3ce77d5a..c39aa52bb22 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h @@ -386,7 +386,7 @@ public: void HandleSelectOverlayOnLayoutSwap(); void FireOnReady(); void SupplementIdealSizeWidth(const RefPtr& frameNode); - void MoveCaretOnLayoutSwap(bool isReduceSize); + void MoveCaretOnLayoutSwap(); void UpdateEditingValue(const std::shared_ptr& value, bool needFireChangeEvent = true) override; void PerformAction(TextInputAction action, bool forceCloseKeyboard = true) override; @@ -566,6 +566,7 @@ public: bool JudgeContentDraggable(); std::pair CalculateCaretOffsetAndHeight(); std::pair CalculateEmptyValueCaretRect(); + void NotifyCaretChange(); TextAlign GetTextAlignByDirection(); void RemoveEmptySpan(std::set>& deleteSpanIndexs); void RemoveEmptySpanItems(); @@ -958,18 +959,41 @@ public: void TriggerAvoidOnCaretChange(); - void OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) override; - - void OnFontScaleConfigurationUpdate() override; - - float GetLastCaretPos() + void ForceTriggerAvoidOnCaretChange(bool isMoveContent = false) { - return lastCaretPos_; + auto pipeline = GetContext(); + CHECK_NULL_VOID(pipeline && pipeline->UsingCaretAvoidMode()); + IF_TRUE(isMoveContent, MoveCaretToContentRect()); + isTriggerAvoidOnCaretAvoidMode_ = true; } - void SetLastCaretPos(float lastCaretPos) + void ResetTriggerAvoidFlagOnCaretChange() { - lastCaretPos_ = lastCaretPos; + isTriggerAvoidOnCaretAvoidMode_ = false; + } + + void OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) override; + + bool IsTriggerAvoidOnCaretAvoidMode() + { + return isTriggerAvoidOnCaretAvoidMode_; + } + + void SetAvoidFlagOnCaretAvoidMode(bool isTriggerAvoidOnCaretAvoidMode) + { + auto pipeline = GetContext(); + CHECK_NULL_VOID(pipeline && pipeline->UsingCaretAvoidMode()); + isTriggerAvoidOnCaretAvoidMode_ = isTriggerAvoidOnCaretAvoidMode; + } + + void ChangeLastRichTextRect() + { + lastRichTextRect_ = richTextRect_; + } + + const RectF& GetLastTextRect() + { + return lastRichTextRect_; } protected: @@ -1298,7 +1322,6 @@ private: void ClearOnFocusTextField(); void ProcessResultObject(RefPtr pasteData, const ResultObject& result); void EncodeTlvDataByResultObject(const ResultObject& result, std::vector& tlvData); - void TriggerAvoidOnCaretChangeAfterLayoutTask(); #if defined(ENABLE_STANDARD_INPUT) sptr richEditTextChangeListener_; @@ -1419,7 +1442,8 @@ private: bool isImageSelfResponseEvent_ = true; std::optional barDisplayMode_ = std::nullopt; uint32_t twinklingInterval_ = 0; - float lastCaretPos_ = 0.0f; + bool isTriggerAvoidOnCaretAvoidMode_ = false; + RectF lastRichTextRect_; }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_select_overlay.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_select_overlay.cpp index 66188cbe1d5..33d57bad118 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_select_overlay.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_select_overlay.cpp @@ -154,7 +154,9 @@ void RichEditorSelectOverlay::OnHandleMove(const RectF& handleRect, bool isFirst auto magnifierLocalOffset = OffsetF(x, y); GetLocalPointWithTransform(magnifierLocalOffset); // do affine transformation pattern->magnifierController_->SetLocalOffset(magnifierLocalOffset); - + bool isChangeSecondHandle = isFirst ? pattern->textSelector_.StartGreaterDest() : + (!pattern->textSelector_.StartGreaterDest()); + IF_TRUE(isChangeSecondHandle, pattern->TriggerAvoidOnCaretChange()); if (isFirst) { pattern->textSelector_.firstHandle.SetOffset(localOffset); } else { diff --git a/frameworks/core/pipeline_ng/pipeline_context.cpp b/frameworks/core/pipeline_ng/pipeline_context.cpp index 6366ab74024..93f19b006da 100644 --- a/frameworks/core/pipeline_ng/pipeline_context.cpp +++ b/frameworks/core/pipeline_ng/pipeline_context.cpp @@ -2394,7 +2394,7 @@ void PipelineContext::DoKeyboardAvoidFunc(float keyboardHeight, double positionY height = rootSize.Height() - positionY; } auto lastKeyboardOffset = safeAreaManager_->GetKeyboardOffsetDirectly(); - auto newKeyboardOffset = CalcAvoidOffset(keyboardHeight, positionY, height, rootSize); + auto newKeyboardOffset = CalcNewKeyboardOffset(keyboardHeight, positionY, height, rootSize); if (NearZero(keyboardHeight) || LessOrEqual(newKeyboardOffset, lastKeyboardOffset) || (manager->GetOnFocusTextFieldId() == manager->GetLastAvoidFieldId() && !keyboardHeightChanged)) { safeAreaManager_->UpdateKeyboardOffset(newKeyboardOffset); @@ -2420,6 +2420,26 @@ void PipelineContext::DoKeyboardAvoidFunc(float keyboardHeight, double positionY } } +float PipelineContext::CalcNewKeyboardOffset(float keyboardHeight, float positionY, + float height, SizeF& rootSize) +{ + auto newKeyboardOffset = CalcAvoidOffset(keyboardHeight, positionY, height, rootSize); + CHECK_NULL_RETURN(safeAreaManager_, newKeyboardOffset); + auto manager = DynamicCast(PipelineBase::GetTextFieldManager()); + CHECK_NULL_RETURN(manager, newKeyboardOffset); + auto onFocusField = manager->GetOnFocusTextField().Upgrade(); + CHECK_NULL_RETURN(onFocusField, newKeyboardOffset); + auto host = onFocusField->GetHost(); + CHECK_NULL_RETURN(host, newKeyboardOffset); + auto geometryNode = host->GetGeometryNode(); + CHECK_NULL_RETURN(geometryNode, newKeyboardOffset); + auto paintOffset = host->GetPaintRectOffset(); + auto frameSize = geometryNode->GetFrameSize(); + auto offset = CalcAvoidOffset(keyboardHeight, paintOffset.GetY() - safeAreaManager_->GetKeyboardOffsetDirectly(), + frameSize.Height(), rootSize); + return std::max(offset, newKeyboardOffset); +} + float PipelineContext::CalcAvoidOffset(float keyboardHeight, float positionY, float height, SizeF rootSize) { diff --git a/frameworks/core/pipeline_ng/pipeline_context.h b/frameworks/core/pipeline_ng/pipeline_context.h index a17909b0e5a..ea4486077dd 100644 --- a/frameworks/core/pipeline_ng/pipeline_context.h +++ b/frameworks/core/pipeline_ng/pipeline_context.h @@ -375,6 +375,8 @@ public: const std::shared_ptr& rsTransaction = nullptr, bool forceChange = false); void DoKeyboardAvoidFunc(float keyboardHeight, double positionY, double height, bool keyboardHeightChanged); + float CalcNewKeyboardOffset(float keyboardHeight, float positionYWithOffset, + float height, SizeF& rootSize); float CalcAvoidOffset(float keyboardHeight, float positionYWithOffset, float height, SizeF rootSize); diff --git a/test/unittest/core/pattern/rich_editor/rich_editor_click_test_ng.cpp b/test/unittest/core/pattern/rich_editor/rich_editor_click_test_ng.cpp index 9503409ea93..442884a0303 100644 --- a/test/unittest/core/pattern/rich_editor/rich_editor_click_test_ng.cpp +++ b/test/unittest/core/pattern/rich_editor/rich_editor_click_test_ng.cpp @@ -960,7 +960,7 @@ HWTEST_F(RichEditorClickTestNg, MoveCaretOnLayoutSwap, TestSize.Level1) richEditorPattern->isTextChange_ = true; richEditorPattern->moveDirection_ = MoveDirection::FORWARD; richEditorPattern->moveLength_ = 1; - richEditorPattern->MoveCaretOnLayoutSwap(true); + richEditorPattern->MoveCaretOnLayoutSwap(); EXPECT_EQ(richEditorPattern->GetCaretPosition(), 1); EXPECT_EQ(richEditorPattern->moveLength_, 0); EXPECT_FALSE(richEditorPattern->isTextChange_);