From b7b0f86c3e503fde247cebd5f193af22932cd6d0 Mon Sep 17 00:00:00 2001 From: hct95 Date: Sun, 21 Jul 2024 14:57:36 +0000 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=89=8B=E5=86=99=E7=AC=94?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=EF=BC=8C=E5=91=BD=E4=B8=AD=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E7=B1=BB=E7=BB=84=E4=BB=B6=E5=BC=82=E5=B8=B8=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hct95 Change-Id: If8c11b4fa327dcf9f3b03f4fbe18c2c451fd9a8f --- adapter/ohos/osal/stylus_detector_mgr.cpp | 161 +++++++----------- adapter/preview/osal/stylus_detector_mgr.cpp | 21 +-- frameworks/core/common/event_manager.cpp | 13 ++ frameworks/core/common/event_manager.h | 2 + .../core/common/stylus/stylus_detector_mgr.h | 13 +- .../core/components_ng/base/frame_node.cpp | 15 +- .../core/components_ng/base/frame_node.h | 2 +- .../pattern/hyperlink/hyperlink_pattern.cpp | 3 +- .../core/components_ng/pattern/pattern.h | 10 ++ .../rich_editor/rich_editor_pattern.cpp | 28 +++ .../pattern/rich_editor/rich_editor_pattern.h | 4 + .../pattern/text_field/text_field_pattern.cpp | 28 +++ .../pattern/text_field/text_field_pattern.h | 5 + .../window_scene/scene/window_node.cpp | 4 +- .../pattern/window_scene/scene/window_node.h | 2 +- .../window_scene/scene/window_pattern.cpp | 4 +- .../core/pipeline_ng/pipeline_context.cpp | 7 +- .../core/common/mock_stylus_detector_mgr.cpp | 21 +-- .../unittest/core/base/frame_node_test_ng.cpp | 5 +- .../base/frame_node_test_ng_coverage_new.cpp | 6 +- 20 files changed, 211 insertions(+), 143 deletions(-) diff --git a/adapter/ohos/osal/stylus_detector_mgr.cpp b/adapter/ohos/osal/stylus_detector_mgr.cpp index d4be3deacd5..b2699d96c27 100644 --- a/adapter/ohos/osal/stylus_detector_mgr.cpp +++ b/adapter/ohos/osal/stylus_detector_mgr.cpp @@ -27,6 +27,7 @@ #include "core/common/stylus/stylus_detector_loader.h" #include "core/components_ng/base/frame_node.h" #include "core/components_ng/base/view_stack_processor.h" +#include "core/components_ng/gestures/recognizers/gesture_recognizer.h" #include "core/components_ng/pattern/rich_editor/rich_editor_pattern.h" #include "core/components_ng/pattern/search/search_text_field.h" #include "core/components_ng/pattern/text_field/text_field_pattern.h" @@ -35,9 +36,6 @@ #include "frameworks/base/log/log_wrapper.h" namespace OHOS::Ace { -namespace { -const Dimension HOT_AREA_ADJUST_SIZE = 20.0_vp; -} const static std::unordered_set TEXT_FIELD_COMPONENT_TAGS = { V2::TEXTINPUT_ETS_TAG, V2::TEXTAREA_ETS_TAG, @@ -178,19 +176,69 @@ bool StylusDetectorMgr::Notify(const NotifyInfo& notifyInfo) return engine_->Notify(notifyInfo); } -bool StylusDetectorMgr::IsNeedInterceptedTouchEvent(const TouchEvent& touchEvent) +RefPtr StylusDetectorMgr::FindHitFrameNode( + const TouchEvent& touchEvent, const TouchTestResult& touchTestResult) +{ + RefPtr frameNode; + // TextField, textInput, search and richEditor has default touchEventTarget. + for (const auto& entry : touchTestResult) { + auto recognizer = AceType::DynamicCast(entry); + if (recognizer) { + continue; + } + auto nodeId = entry->GetNodeId(); + auto UiNode = ElementRegister::GetInstance()->GetUINodeById(nodeId); + frameNode = AceType::DynamicCast(UiNode); + if (frameNode) { + break; + } + } + CHECK_NULL_RETURN(frameNode, nullptr); + + auto pipeline = frameNode->GetContextRefPtr(); + if (!pipeline) { + LOGI("Can't find pipeline for find hit node."); + return nullptr; + } + auto nanoTimestamp = pipeline->GetVsyncTime(); + + // only textField, textInput, search and richEditor need to response stylus event. + auto tag = frameNode->GetTag(); + auto iterEx = TEXT_FIELD_COMPONENT_TAGS.find(tag); + if (iterEx == TEXT_FIELD_COMPONENT_TAGS.end()) { + return nullptr; + } + if (!CheckTextEditable(frameNode) || + IsHitCleanNodeResponseArea({ touchEvent.x, touchEvent.y }, frameNode, nanoTimestamp)) { + return nullptr; + } + return frameNode; +} + +bool StylusDetectorMgr::IsNeedInterceptedTouchEvent( + const TouchEvent& touchEvent, std::unordered_map touchTestResults) { if (!IsStylusTouchEvent(touchEvent)) { return false; } - auto frameNode = FindTextInputFrameNodeByPosition(touchEvent.x, touchEvent.y); - CHECK_NULL_RETURN(frameNode, false); + const auto iter = touchTestResults.find(touchEvent.id); + if (iter == touchTestResults.end() || iter->second.empty()) { + LOGI("TouchTestResult is empty"); + return false; + } + + auto frameNode = FindHitFrameNode(touchEvent, iter->second); + if (!frameNode) { + LOGI("Stylus hit position is (%{public}f, %{public}f). TargetNode is None", touchEvent.x, touchEvent.y); + return false; + } LOGI("Stylus hit position is (%{public}f, %{public}f). TargetNode is %{public}s, id is %{public}s", touchEvent.x, touchEvent.y, frameNode->GetTag().c_str(), frameNode->GetInspectorId()->c_str()); if (!IsEnable()) { + LOGI("Stylus service is not enable"); return false; } @@ -244,103 +292,26 @@ StylusDetectorMgr::StylusDetectorMgr() : engine_(nullptr), isRegistered_(false) } } -bool StylusDetectorMgr::CheckTextEditable(const RefPtr parentNode) +bool StylusDetectorMgr::CheckTextEditable(const RefPtr frameNode) { - CHECK_NULL_RETURN(parentNode, false); - auto focusHub = parentNode->GetFocusHub(); - if (!focusHub->IsFocusable() || !parentNode->IsVisible()) { + CHECK_NULL_RETURN(frameNode, false); + auto focusHub = frameNode->GetFocusHub(); + // if frameNode is not focusable or invisible, no need to hit frameNode. + if (!focusHub->IsFocusable() || !frameNode->IsVisible()) { return false; } - if (parentNode->GetTag() == V2::RICH_EDITOR_ETS_TAG) { - return true; + auto renderContext = frameNode->GetRenderContext(); + CHECK_NULL_RETURN(renderContext, false); + auto opacity = renderContext->GetOpacity(); + // if opacity is 0.0f, no need to hit frameNode. + if (NearZero(opacity.value_or(1.0f))) { + return false; } - auto pattern = parentNode->GetPattern(); + auto pattern = frameNode->GetPattern(); CHECK_NULL_RETURN(pattern, false); return !pattern->IsInPasswordMode(); } -RefPtr StylusDetectorMgr::FindTargetInChildNodes( - const RefPtr parentNode, const FrameNodeSet& hitFrameNodes) -{ - CHECK_NULL_RETURN(parentNode, nullptr); - auto parentFrameNode = AceType::DynamicCast(parentNode); - if (parentFrameNode && (!parentFrameNode->IsActive() || !parentFrameNode->IsVisible())) { - return nullptr; - } - auto children = parentFrameNode->GetFrameChildren(); - - for (auto iter = children.rbegin(); iter != children.rend(); iter++) { - auto child = iter->Upgrade(); - if (child == nullptr) { - continue; - } - auto childNode = AceType::DynamicCast(child); - auto childFindResult = FindTargetInChildNodes(childNode, hitFrameNodes); - if (childFindResult) { - return childFindResult; - } - } - - CHECK_NULL_RETURN(parentFrameNode, nullptr); - auto iter = hitFrameNodes.find(parentFrameNode); - if (iter != hitFrameNodes.end() && CheckTextEditable(parentFrameNode)) { - return *iter; - } - return nullptr; -} - -RefPtr StylusDetectorMgr::FindTextInputFrameNodeByPosition(float globalX, float globalY) -{ - if (textFieldNodes_.empty()) { - return nullptr; - } - - auto pipeline = NG::PipelineContext::GetCurrentContext(); - CHECK_NULL_RETURN(pipeline, nullptr); - auto nanoTimestamp = pipeline->GetVsyncTime(); - NG::PointF point(globalX, globalY); - - FrameNodeSet hitFrameNodes; - for (auto iterOfFrameNode = textFieldNodes_.begin(); iterOfFrameNode != textFieldNodes_.end(); iterOfFrameNode++) { - auto frameNode = iterOfFrameNode->second.Upgrade(); - if (!frameNode || !frameNode->IsVisible()) { - continue; - } - auto geometryNode = frameNode->GetGeometryNode(); - if (!geometryNode) { - continue; - } - auto imageContext = frameNode->GetRenderContext(); - CHECK_NULL_RETURN(imageContext, nullptr); - auto opacity = imageContext->GetOpacity(); - if (NearZero(opacity.value_or(1.0f))) { - continue; - } - auto globalFrameRect = geometryNode->GetFrameRect() + NG::SizeF(0, HOT_AREA_ADJUST_SIZE.ConvertToPx() * 2); - globalFrameRect.SetOffset(frameNode->CalculateCachedTransformRelativeOffset(nanoTimestamp) + - NG::OffsetF(0, -HOT_AREA_ADJUST_SIZE.ConvertToPx())); - if (globalFrameRect.IsInRegion(point) && !IsHitCleanNodeResponseArea(point, frameNode, nanoTimestamp)) { - hitFrameNodes.insert(frameNode); - } - } - - if (hitFrameNodes.empty()) { - LOGD("Cannot find targetNodes."); - return nullptr; - } - - auto rootNode = pipeline->GetRootElement(); - auto container = Container::Current(); - if (container && container->IsScenceBoardWindow()) { - rootNode = pipeline->GetFocusedWindowSceneNode(); - } - - auto result = FindTargetInChildNodes(rootNode, hitFrameNodes); - if (result) { - return result; - } - return nullptr; -} bool StylusDetectorMgr::IsStylusTouchEvent(const TouchEvent& touchEvent) const { return touchEvent.sourceTool == SourceTool::PEN && touchEvent.type == TouchType::DOWN; diff --git a/adapter/preview/osal/stylus_detector_mgr.cpp b/adapter/preview/osal/stylus_detector_mgr.cpp index 0413c768190..73012440cae 100644 --- a/adapter/preview/osal/stylus_detector_mgr.cpp +++ b/adapter/preview/osal/stylus_detector_mgr.cpp @@ -53,7 +53,14 @@ bool StylusDetectorMgr::Notify(const NotifyInfo& notifyInfo) return false; } -bool StylusDetectorMgr::IsNeedInterceptedTouchEvent(const TouchEvent& touchEvent) +RefPtr StylusDetectorMgr::FindHitFrameNode( + const TouchEvent& touchEvent, const TouchTestResult& touchTestResult) +{ + return nullptr; +} + +bool StylusDetectorMgr::IsNeedInterceptedTouchEvent( + const TouchEvent& touchEvent, std::unordered_map touchTestResults) { return false; } @@ -63,21 +70,11 @@ void StylusDetectorMgr::RemoveTextFieldFrameNode(const int32_t id) {} StylusDetectorMgr::StylusDetectorMgr() : engine_(nullptr), isRegistered_(false) {} -bool StylusDetectorMgr::CheckTextEditable(const RefPtr parentNode) +bool StylusDetectorMgr::CheckTextEditable(const RefPtr frameNode) { return false; } -RefPtr StylusDetectorMgr::FindTargetInChildNodes( - const RefPtr parentNode, const FrameNodeSet& hitFrameNodes) -{ - return nullptr; -} - -RefPtr StylusDetectorMgr::FindTextInputFrameNodeByPosition(float globalX, float globalY) -{ - return nullptr; -} bool StylusDetectorMgr::IsStylusTouchEvent(const TouchEvent& touchEvent) const { return false; diff --git a/frameworks/core/common/event_manager.cpp b/frameworks/core/common/event_manager.cpp index b8520a0a13f..bcc5c96d783 100644 --- a/frameworks/core/common/event_manager.cpp +++ b/frameworks/core/common/event_manager.cpp @@ -738,6 +738,19 @@ bool EventManager::DispatchTouchEvent(const TouchEvent& event) return true; } +void EventManager::ClearTouchTestTargetForPenStylus(TouchEvent& touchEvent) +{ + refereeNG_->CleanGestureScope(touchEvent.id); + referee_->CleanGestureScope(touchEvent.id); + touchTestResults_.erase(touchEvent.id); + touchEvent.isMocked = true; + touchEvent.type = TouchType::CANCEL; + for (const auto& iter : downFingerIds_) { + touchEvent.id = iter; + DispatchTouchEvent(touchEvent); + } +} + void EventManager::CleanRecognizersForDragBegin(TouchEvent& touchEvent) { downFingerIds_.erase(touchEvent.id); diff --git a/frameworks/core/common/event_manager.h b/frameworks/core/common/event_manager.h index 6abcc918646..38b239bcd92 100644 --- a/frameworks/core/common/event_manager.h +++ b/frameworks/core/common/event_manager.h @@ -282,6 +282,8 @@ public: void CheckAndLogLastConsumedEventInfo(int32_t eventId, bool logImmediately = false); + void ClearTouchTestTargetForPenStylus(TouchEvent& touchEvent); + #if defined(SUPPORT_TOUCH_TARGET_TEST) bool TouchTargetHitTest(const TouchEvent& touchPoint, const RefPtr& frameNode, TouchRestrict& touchRestrict, const Offset& offset = Offset(), float viewScale = 1.0f, diff --git a/frameworks/core/common/stylus/stylus_detector_mgr.h b/frameworks/core/common/stylus/stylus_detector_mgr.h index b244424c831..834124535ea 100644 --- a/frameworks/core/common/stylus/stylus_detector_mgr.h +++ b/frameworks/core/common/stylus/stylus_detector_mgr.h @@ -29,6 +29,8 @@ #include "core/event/touch_event.h" namespace OHOS::Ace { +constexpr int32_t HOT_AREA_EXPAND_TIME = 2; +constexpr Dimension HOT_AREA_ADJUST_SIZE = 20.0_vp; struct Hash { size_t operator()(const RefPtr& node) const { @@ -47,7 +49,9 @@ public: void UnRegisterStylusInteractionListener(const std::string& bundleName) override; bool Notify(const NotifyInfo& notifyInfo) override; - bool IsNeedInterceptedTouchEvent(const TouchEvent& touchEvent); + RefPtr FindHitFrameNode(const TouchEvent& touchEvent, const TouchTestResult& touchTestResult); + bool IsNeedInterceptedTouchEvent( + const TouchEvent& touchEvent, std::unordered_map touchTestResults); void AddTextFieldFrameNode(const RefPtr& textFieldNode); void RemoveTextFieldFrameNode(const int32_t id); @@ -78,12 +82,7 @@ private: bool IsHitCleanNodeResponseArea( const NG::PointF& point, const RefPtr& frameNode, uint64_t nanoTimestamp); - RefPtr FindTextInputFrameNodeByPosition(float globalX, float globalY); - - RefPtr FindTargetInChildNodes( - const RefPtr parentNode, const FrameNodeSet& hitFrameNodes); - - bool CheckTextEditable(const RefPtr parentNode); + bool CheckTextEditable(const RefPtr frameNode); std::unordered_map> textFieldNodes_; diff --git a/frameworks/core/components_ng/base/frame_node.cpp b/frameworks/core/components_ng/base/frame_node.cpp index e481e3775cd..0ae28917c28 100644 --- a/frameworks/core/components_ng/base/frame_node.cpp +++ b/frameworks/core/components_ng/base/frame_node.cpp @@ -41,6 +41,7 @@ #include "core/common/container.h" #include "core/common/recorder/event_recorder.h" #include "core/common/recorder/node_data_cache.h" +#include "core/common/stylus/stylus_detector_mgr.h" #include "core/components/common/layout/constants.h" #include "core/components/common/layout/grid_system_manager.h" #include "core/components_ng/base/extension_handler.h" @@ -2261,11 +2262,14 @@ bool FrameNode::IsPaintRectWithTransformValid() return false; } -bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, int32_t sourceType) +bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, const TouchEvent& touchEvent) { bool isInChildRegion = false; auto paintRect = renderContext_->GetPaintRectWithoutTransform(); - auto responseRegionList = GetResponseRegionList(paintRect, sourceType); + if (pattern_->IsResponseRegionExpandingNeededForStylus(touchEvent)) { + paintRect = pattern_->ExpandDefaultResponseRegion(paintRect); + } + auto responseRegionList = GetResponseRegionList(paintRect, static_cast(touchEvent.sourceType)); auto revertPoint = parentRevertPoint; MapPointTo(revertPoint, GetOrRefreshRevertMatrixFromCache()); @@ -2278,7 +2282,7 @@ bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, int32_t } for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) { const auto& child = iter->Upgrade(); - if (child && !child->IsOutOfTouchTestRegion(subRevertPoint, sourceType)) { + if (child && !child->IsOutOfTouchTestRegion(subRevertPoint, touchEvent)) { isInChildRegion = true; break; } @@ -2342,6 +2346,9 @@ HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& pare parentId = parent->GetId(); } + if (pattern_->IsResponseRegionExpandingNeededForStylus(touchRestrict.touchEvent)) { + origRect = pattern_->ExpandDefaultResponseRegion(origRect); + } auto responseRegionList = GetResponseRegionList(origRect, static_cast(touchRestrict.sourceType)); if (SystemProperties::GetDebugEnabled()) { TAG_LOGD(AceLogTag::ACE_UIEVENT, "TouchTest: point is %{public}s in %{public}s, depth: %{public}d", @@ -2353,7 +2360,7 @@ HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& pare } { ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion"); - bool isOutOfRegion = IsOutOfTouchTestRegion(parentRevertPoint, static_cast(touchRestrict.sourceType)); + bool isOutOfRegion = IsOutOfTouchTestRegion(parentRevertPoint, touchRestrict.touchEvent); AddFrameNodeSnapshot(!isOutOfRegion, parentId, responseRegionList); if ((!isDispatch) && isOutOfRegion) { return HitTestResult::OUT_OF_REGION; diff --git a/frameworks/core/components_ng/base/frame_node.h b/frameworks/core/components_ng/base/frame_node.h index ed63aa1420e..87ed7f955c6 100644 --- a/frameworks/core/components_ng/base/frame_node.h +++ b/frameworks/core/components_ng/base/frame_node.h @@ -496,7 +496,7 @@ public: void AddHotZoneRect(const DimensionRect& hotZoneRect) const; void RemoveLastHotZoneRect() const; - virtual bool IsOutOfTouchTestRegion(const PointF& parentLocalPoint, int32_t sourceType); + virtual bool IsOutOfTouchTestRegion(const PointF& parentLocalPoint, const TouchEvent& touchEvent); bool IsLayoutDirtyMarked() const { diff --git a/frameworks/core/components_ng/pattern/hyperlink/hyperlink_pattern.cpp b/frameworks/core/components_ng/pattern/hyperlink/hyperlink_pattern.cpp index bbafae66194..6cc1174e95e 100644 --- a/frameworks/core/components_ng/pattern/hyperlink/hyperlink_pattern.cpp +++ b/frameworks/core/components_ng/pattern/hyperlink/hyperlink_pattern.cpp @@ -304,11 +304,12 @@ void HyperlinkPattern::OnMouseEvent(MouseInfo& info) auto frame = GetHost(); CHECK_NULL_VOID(frame); auto frameId = frame->GetId(); + TouchEvent touchEvent; if (frame->IsOutOfTouchTestRegion( { static_cast(info.GetLocalLocation().GetX()) + GetHostFrameOffset()->GetX(), static_cast(info.GetLocalLocation().GetY()) + GetHostFrameOffset()->GetY() }, - 0)) { + touchEvent)) { pipeline->ChangeMouseStyle(frameId, MouseFormat::DEFAULT); pipeline->FreeMouseStyleHoldNode(frameId); } else { diff --git a/frameworks/core/components_ng/pattern/pattern.h b/frameworks/core/components_ng/pattern/pattern.h index 0317fe6391c..b36e680c475 100644 --- a/frameworks/core/components_ng/pattern/pattern.h +++ b/frameworks/core/components_ng/pattern/pattern.h @@ -614,6 +614,16 @@ public: return 0; } + virtual bool IsResponseRegionExpandingNeededForStylus(const TouchEvent& touchEvent) const + { + return false; + } + + virtual RectF ExpandDefaultResponseRegion(RectF& rect) + { + return RectF(); + } + protected: virtual void OnAttachToFrameNode() {} virtual void OnDetachFromFrameNode(FrameNode* frameNode) {} 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 af53e35b1d6..4dd85552933 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 @@ -9669,4 +9669,32 @@ void RichEditorPattern::RequestKeyboardToEdit() HandleOnEditChanged(true); previewLongPress_ = false; } + +bool RichEditorPattern::IsResponseRegionExpandingNeededForStylus(const TouchEvent& touchEvent) const +{ + if (touchEvent.sourceTool != SourceTool::PEN || touchEvent.type != TouchType::DOWN) { + return false; + } + auto host = GetHost(); + CHECK_NULL_RETURN(host, false); + auto focusHub = host->GetFocusHub(); + CHECK_NULL_RETURN(focusHub, false); + if (!focusHub->IsFocusable() || !host->IsVisible()) { + return false; + } + auto renderContext = host->GetRenderContext(); + CHECK_NULL_RETURN(renderContext, false); + auto opacity = renderContext->GetOpacity(); + // if opacity is 0.0f, no need to hit frameNode. + if (NearZero(opacity.value_or(1.0f))) { + return false; + } + return true; +} + +RectF RichEditorPattern::ExpandDefaultResponseRegion(RectF& rect) +{ + return rect + NG::SizeF(0, OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx() * OHOS::Ace::HOT_AREA_EXPAND_TIME) + + NG::OffsetF(0, -OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx()); +} } // namespace OHOS::Ace::NG 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 0700ca652b9..089e14d884c 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 @@ -817,6 +817,10 @@ public: return isTouchCaret_; } + bool IsResponseRegionExpandingNeededForStylus(const TouchEvent& touchEvent) const override; + + RectF ExpandDefaultResponseRegion(RectF& rect) override; + protected: bool CanStartAITask() override; diff --git a/frameworks/core/components_ng/pattern/text_field/text_field_pattern.cpp b/frameworks/core/components_ng/pattern/text_field/text_field_pattern.cpp index 8b8c7de5a8a..75a05a73e6b 100644 --- a/frameworks/core/components_ng/pattern/text_field/text_field_pattern.cpp +++ b/frameworks/core/components_ng/pattern/text_field/text_field_pattern.cpp @@ -7835,4 +7835,32 @@ bool TextFieldPattern::GetTouchInnerPreviewText(const Offset& offset) const auto touchDownIndex = selectController_->ConvertTouchOffsetToPosition(offset); return GetPreviewTextStart() <= touchDownIndex && touchDownIndex <= GetPreviewTextEnd() && HasFocus(); } + +bool TextFieldPattern::IsResponseRegionExpandingNeededForStylus(const TouchEvent& touchEvent) const +{ + if (touchEvent.sourceTool != SourceTool::PEN || touchEvent.type != TouchType::DOWN) { + return false; + } + auto host = GetHost(); + CHECK_NULL_RETURN(host, false); + auto focusHub = host->GetFocusHub(); + CHECK_NULL_RETURN(focusHub, false); + if (!focusHub->IsFocusable() || !host->IsVisible()) { + return false; + } + auto renderContext = host->GetRenderContext(); + CHECK_NULL_RETURN(renderContext, false); + auto opacity = renderContext->GetOpacity(); + // if opacity is 0.0f, no need to hit frameNode. + if (NearZero(opacity.value_or(1.0f))) { + return false; + } + return !IsInPasswordMode(); +} + +RectF TextFieldPattern::ExpandDefaultResponseRegion(RectF& rect) +{ + return rect + NG::SizeF(0, OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx() * OHOS::Ace::HOT_AREA_EXPAND_TIME) + + NG::OffsetF(0, -OHOS::Ace::HOT_AREA_ADJUST_SIZE.ConvertToPx()); +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/text_field/text_field_pattern.h b/frameworks/core/components_ng/pattern/text_field/text_field_pattern.h index 96b0104505e..754d24cfab9 100644 --- a/frameworks/core/components_ng/pattern/text_field/text_field_pattern.h +++ b/frameworks/core/components_ng/pattern/text_field/text_field_pattern.h @@ -1373,6 +1373,11 @@ public: { isTextChangedAtCreation_ = changed; } + + bool IsResponseRegionExpandingNeededForStylus(const TouchEvent& touchEvent) const override; + + RectF ExpandDefaultResponseRegion(RectF& rect) override; + protected: virtual void InitDragEvent(); void OnAttachToMainTree() override diff --git a/frameworks/core/components_ng/pattern/window_scene/scene/window_node.cpp b/frameworks/core/components_ng/pattern/window_scene/scene/window_node.cpp index 6ca5c894613..fa75e41abc9 100644 --- a/frameworks/core/components_ng/pattern/window_scene/scene/window_node.cpp +++ b/frameworks/core/components_ng/pattern/window_scene/scene/window_node.cpp @@ -77,7 +77,7 @@ void WindowNode::SetParent(const WeakPtr& parent) UINode::SetParent(parent); } -bool WindowNode::IsOutOfTouchTestRegion(const PointF& parentLocalPoint, int32_t sourceType) +bool WindowNode::IsOutOfTouchTestRegion(const PointF& parentLocalPoint, const TouchEvent& touchEvent) { auto pattern = GetPattern(); if (pattern != nullptr) { @@ -93,7 +93,7 @@ bool WindowNode::IsOutOfTouchTestRegion(const PointF& parentLocalPoint, int32_t } } const auto& rect = GetPaintRectWithTransform(); - const auto& hotRect = ConvertHotRect(rect, sourceType); + const auto& hotRect = ConvertHotRect(rect, static_cast(touchEvent.sourceType)); if (!hotRect.IsInRegion(parentLocalPoint)) { return true; } diff --git a/frameworks/core/components_ng/pattern/window_scene/scene/window_node.h b/frameworks/core/components_ng/pattern/window_scene/scene/window_node.h index 9471b5736c4..39befffece6 100644 --- a/frameworks/core/components_ng/pattern/window_scene/scene/window_node.h +++ b/frameworks/core/components_ng/pattern/window_scene/scene/window_node.h @@ -33,7 +33,7 @@ public: int32_t nodeId, int32_t sessionId, const std::function(void)>& patternCreator); void SetParent(const WeakPtr& parent) override; - bool IsOutOfTouchTestRegion(const PointF& parentLocalPoint, int32_t sourceType) override; + bool IsOutOfTouchTestRegion(const PointF& parentLocalPoint, const TouchEvent& touchEvent) override; std::vector GetResponseRegionList(const RectF& rect, int32_t sourceType) override; private: diff --git a/frameworks/core/components_ng/pattern/window_scene/scene/window_pattern.cpp b/frameworks/core/components_ng/pattern/window_scene/scene/window_pattern.cpp index 3e55e20e947..7c0df458ba9 100644 --- a/frameworks/core/components_ng/pattern/window_scene/scene/window_pattern.cpp +++ b/frameworks/core/components_ng/pattern/window_scene/scene/window_pattern.cpp @@ -605,7 +605,9 @@ void WindowPattern::FilterInvalidPointerItem(const std::shared_ptr(item.GetDisplayX()), static_cast(item.GetDisplayY()) }; - if (host->IsOutOfTouchTestRegion(point, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN)) { + OHOS::Ace::TouchEvent touchEvent; + touchEvent.sourceType = static_cast(MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN); + if (host->IsOutOfTouchTestRegion(point, touchEvent)) { pointerEvent->RemovePointerItem(id); } } diff --git a/frameworks/core/pipeline_ng/pipeline_context.cpp b/frameworks/core/pipeline_ng/pipeline_context.cpp index 8c03d2b377c..5fa099d465d 100644 --- a/frameworks/core/pipeline_ng/pipeline_context.cpp +++ b/frameworks/core/pipeline_ng/pipeline_context.cpp @@ -2063,15 +2063,16 @@ void PipelineContext::OnTouchEvent(const TouchEvent& point, const RefPtrIsNeedInterceptedTouchEvent(scalePoint)) { - return; - } eventManager_->TouchTest(scalePoint, node, touchRestrict, GetPluginEventOffset(), viewScale_, isSubPipe); if (!touchRestrict.childTouchTestList.empty()) { scalePoint.childTouchTestList = touchRestrict.childTouchTestList; } touchTestResults_ = eventManager_->touchTestResults_; + if (StylusDetectorMgr::GetInstance()->IsNeedInterceptedTouchEvent(scalePoint, touchTestResults_)) { + eventManager_->ClearTouchTestTargetForPenStylus(scalePoint); + return; + } HandleEtsCardTouchEvent(oriPoint, etsSerializedGesture); diff --git a/test/mock/core/common/mock_stylus_detector_mgr.cpp b/test/mock/core/common/mock_stylus_detector_mgr.cpp index 0413c768190..73012440cae 100644 --- a/test/mock/core/common/mock_stylus_detector_mgr.cpp +++ b/test/mock/core/common/mock_stylus_detector_mgr.cpp @@ -53,7 +53,14 @@ bool StylusDetectorMgr::Notify(const NotifyInfo& notifyInfo) return false; } -bool StylusDetectorMgr::IsNeedInterceptedTouchEvent(const TouchEvent& touchEvent) +RefPtr StylusDetectorMgr::FindHitFrameNode( + const TouchEvent& touchEvent, const TouchTestResult& touchTestResult) +{ + return nullptr; +} + +bool StylusDetectorMgr::IsNeedInterceptedTouchEvent( + const TouchEvent& touchEvent, std::unordered_map touchTestResults) { return false; } @@ -63,21 +70,11 @@ void StylusDetectorMgr::RemoveTextFieldFrameNode(const int32_t id) {} StylusDetectorMgr::StylusDetectorMgr() : engine_(nullptr), isRegistered_(false) {} -bool StylusDetectorMgr::CheckTextEditable(const RefPtr parentNode) +bool StylusDetectorMgr::CheckTextEditable(const RefPtr frameNode) { return false; } -RefPtr StylusDetectorMgr::FindTargetInChildNodes( - const RefPtr parentNode, const FrameNodeSet& hitFrameNodes) -{ - return nullptr; -} - -RefPtr StylusDetectorMgr::FindTextInputFrameNodeByPosition(float globalX, float globalY) -{ - return nullptr; -} bool StylusDetectorMgr::IsStylusTouchEvent(const TouchEvent& touchEvent) const { return false; diff --git a/test/unittest/core/base/frame_node_test_ng.cpp b/test/unittest/core/base/frame_node_test_ng.cpp index 73941dd1b92..6904947b4af 100644 --- a/test/unittest/core/base/frame_node_test_ng.cpp +++ b/test/unittest/core/base/frame_node_test_ng.cpp @@ -927,11 +927,12 @@ HWTEST_F(FrameNodeTestNg, FrameNodeIsOutOfTouchTestRegion0025, TestSize.Level1) */ PointF pointF; std::vector rectF; - auto test = FRAME_NODE2->IsOutOfTouchTestRegion(std::move(pointF), 0); + TouchEvent touchEvent; + auto test = FRAME_NODE2->IsOutOfTouchTestRegion(std::move(pointF), touchEvent); EXPECT_TRUE(test); auto test1 = FRAME_NODE2->InResponseRegionList(pointF, rectF); - auto test2 = FRAME_NODE2->IsOutOfTouchTestRegion(std::move(pointF), 0); + auto test2 = FRAME_NODE2->IsOutOfTouchTestRegion(std::move(pointF), touchEvent); EXPECT_FALSE(test1); EXPECT_TRUE(test2); } diff --git a/test/unittest/core/base/frame_node_test_ng_coverage_new.cpp b/test/unittest/core/base/frame_node_test_ng_coverage_new.cpp index 42542991d5f..9b0b75d4f8b 100644 --- a/test/unittest/core/base/frame_node_test_ng_coverage_new.cpp +++ b/test/unittest/core/base/frame_node_test_ng_coverage_new.cpp @@ -149,9 +149,11 @@ HWTEST_F(FrameNodeTestNg, FrameNodeIsOutOfTouchTestRegion01, TestSize.Level1) */ NG::PointF point { 1.0, 1.0 }; frameNode->renderContext_->UpdateClipEdge(true); - frameNode->IsOutOfTouchTestRegion(point, 1); + TouchEvent touchEvent; + touchEvent.sourceType = static_cast(1); + frameNode->IsOutOfTouchTestRegion(point, touchEvent); testNode->renderContext_->UpdateClipEdge(false); - testNode->IsOutOfTouchTestRegion(point, 1); + testNode->IsOutOfTouchTestRegion(point, touchEvent); } /** -- Gitee