diff --git a/adapter/ohos/entrance/ace_container.cpp b/adapter/ohos/entrance/ace_container.cpp index 4088b018fec3bbea2a4af15382dc92065048d9b5..9484d48321c816d05fc4222b1b2bcdb7c43dda11 100644 --- a/adapter/ohos/entrance/ace_container.cpp +++ b/adapter/ohos/entrance/ace_container.cpp @@ -819,6 +819,8 @@ void AceContainer::InitializeCallback() if (event.type == TouchType::HOVER_ENTER || event.type == TouchType::HOVER_MOVE || event.type == TouchType::HOVER_EXIT || event.type == TouchType::HOVER_CANCEL) { context->OnAccessibilityHoverEvent(event, node); + } else if (event.IsPenHoverEvent()) { + context->OnPenHoverEvent(event, node); } else { if (node) { context->OnTouchEvent(event, node); diff --git a/adapter/ohos/entrance/mmi_event_convertor.cpp b/adapter/ohos/entrance/mmi_event_convertor.cpp index 7df84c5f7f2fbd222bf9ab3032c48bf8853d91d9..59d2b6d6a41a9688dad37d88311e4903b2618370 100644 --- a/adapter/ohos/entrance/mmi_event_convertor.cpp +++ b/adapter/ohos/entrance/mmi_event_convertor.cpp @@ -226,6 +226,8 @@ void SetTouchEventType(int32_t orgAction, TouchEvent& event) { OHOS::MMI::PointerEvent::POINTER_ACTION_HOVER_MOVE, TouchType::HOVER_MOVE }, { OHOS::MMI::PointerEvent::POINTER_ACTION_HOVER_EXIT, TouchType::HOVER_EXIT }, { OHOS::MMI::PointerEvent::POINTER_ACTION_HOVER_CANCEL, TouchType::HOVER_CANCEL }, + { OHOS::MMI::PointerEvent::POINTER_ACTION_PROXIMITY_IN, TouchType::PROXIMITY_IN }, + { OHOS::MMI::PointerEvent::POINTER_ACTION_PROXIMITY_OUT, TouchType::PROXIMITY_OUT }, }; auto typeIter = actionMap.find(orgAction); if (typeIter == actionMap.end()) { diff --git a/frameworks/core/BUILD.gn b/frameworks/core/BUILD.gn index c36e0d19fbfe943ba40e1eb2fc288aaf25d9da93..cb306b63b50f89db13fda9aa77a092a6de24a9da 100644 --- a/frameworks/core/BUILD.gn +++ b/frameworks/core/BUILD.gn @@ -120,6 +120,7 @@ template("ace_core_source_set") { "common/environment/environment_proxy.cpp", "common/event_dump.cpp", "common/event_manager.cpp", + "common/event_manager_pen.cpp", "common/focus_animation_manager.cpp", "common/font_loader.cpp", "common/font_manager.cpp", @@ -700,6 +701,7 @@ template("ace_core_ng_source_set") { "common/environment/environment_proxy.cpp", "common/event_dump.cpp", "common/event_manager.cpp", + "common/event_manager_pen.cpp", "common/focus_animation_manager.cpp", "common/font_loader.cpp", "common/font_manager.cpp", diff --git a/frameworks/core/animation/test/unittest/framework/BUILD.gn b/frameworks/core/animation/test/unittest/framework/BUILD.gn index 233a38d499a7dba728b4826a69e98924211712a2..efbf3331aaacddd4b66001e8799acb5b497435d8 100644 --- a/frameworks/core/animation/test/unittest/framework/BUILD.gn +++ b/frameworks/core/animation/test/unittest/framework/BUILD.gn @@ -50,6 +50,7 @@ ohos_unittest("AnimationTest") { "$ace_root/frameworks/core/common/container.cpp", "$ace_root/frameworks/core/common/container_scope.cpp", "$ace_root/frameworks/core/common/event_manager.cpp", + "$ace_root/frameworks/core/common/event_manager_pen.cpp", "$ace_root/frameworks/core/common/focus_animation_manager.cpp", "$ace_root/frameworks/core/common/font_loader.cpp", "$ace_root/frameworks/core/common/font_manager.cpp", diff --git a/frameworks/core/animation/test/unittest/spring_chain/BUILD.gn b/frameworks/core/animation/test/unittest/spring_chain/BUILD.gn index 7652bbd1753a1da07e38eaa0d6df4b63c509bca6..5856d721ecee8b0d6ae6ccdccfea4cb894e95bd9 100644 --- a/frameworks/core/animation/test/unittest/spring_chain/BUILD.gn +++ b/frameworks/core/animation/test/unittest/spring_chain/BUILD.gn @@ -53,6 +53,7 @@ ohos_unittest("SpringChainTest") { "$ace_root/frameworks/core/common/container.cpp", "$ace_root/frameworks/core/common/container_scope.cpp", "$ace_root/frameworks/core/common/event_manager.cpp", + "$ace_root/frameworks/core/common/event_manager_pen.cpp", "$ace_root/frameworks/core/common/focus_animation_manager.cpp", "$ace_root/frameworks/core/common/font_loader.cpp", "$ace_root/frameworks/core/common/font_manager.cpp", diff --git a/frameworks/core/animation/test/unittest/svg_animate/BUILD.gn b/frameworks/core/animation/test/unittest/svg_animate/BUILD.gn index 8bd3bf59bae1191ea803f40fc4730ed1e2d23244..3556ea797a82782e631074057c9502c66dd6a726 100644 --- a/frameworks/core/animation/test/unittest/svg_animate/BUILD.gn +++ b/frameworks/core/animation/test/unittest/svg_animate/BUILD.gn @@ -52,6 +52,7 @@ ohos_unittest("SvgAnimateTest") { "$ace_root/frameworks/core/common/container.cpp", "$ace_root/frameworks/core/common/container_scope.cpp", "$ace_root/frameworks/core/common/event_manager.cpp", + "$ace_root/frameworks/core/common/event_manager_pen.cpp", "$ace_root/frameworks/core/common/focus_animation_manager.cpp", "$ace_root/frameworks/core/common/font_loader.cpp", "$ace_root/frameworks/core/common/font_manager.cpp", diff --git a/frameworks/core/common/event_manager.h b/frameworks/core/common/event_manager.h index 3af647bab4b2d8e112e0da98732300f45f405e1c..ca0a7d13040afc1073d5a988dab027f0a1678b20 100644 --- a/frameworks/core/common/event_manager.h +++ b/frameworks/core/common/event_manager.h @@ -126,12 +126,15 @@ public: void AccessibilityHoverTest( const TouchEvent& event, const RefPtr& frameNode, TouchRestrict& touchRestrict); void UpdateAccessibilityHoverNode(const TouchEvent& event, const TouchTestResult& testResult); + void PenHoverTest(const TouchEvent& event, const RefPtr& frameNode, TouchRestrict& touchRestrict); + void UpdatePenHoverNode(const TouchEvent& event, const TouchTestResult& testResult); void UpdateHoverNode(const MouseEvent& event, const TouchTestResult& testResult); bool DispatchMouseEventNG(const MouseEvent& event); void DispatchMouseHoverAnimationNG(const MouseEvent& event); bool DispatchMouseHoverEventNG(const MouseEvent& event); void DispatchHoverEffectEvent(const MouseEvent& event); void DispatchAccessibilityHoverEventNG(const TouchEvent& event); + void DispatchPenHoverEventNG(const TouchEvent& event); void AxisTest(const AxisEvent& event, const RefPtr& renderNode); bool DispatchAxisEvent(const AxisEvent& event); @@ -311,6 +314,8 @@ private: HoverTestResult lastHoverTestResults_; HoverTestResult curAccessibilityHoverResults_; HoverTestResult lastAccessibilityHoverResults_; + HoverTestResult curPenHoverResults_; + HoverTestResult lastPenHoverResults_; AxisTestResult axisTestResults_; WeakPtr lastHoverNode_; WeakPtr currHoverNode_; @@ -323,6 +328,7 @@ private: int32_t instanceId_ = 0; uint32_t lastHoverDispatchLength_ = 0; uint32_t lastAccessibilityHoverDispatchLength_ = 0; + uint32_t lastPenHoverDispatchLength_ = 0; bool inSelectedRect_ = false; bool isDragging_ = false; bool isLastMoveBeforeUp_ = false; diff --git a/frameworks/core/common/event_manager_pen.cpp b/frameworks/core/common/event_manager_pen.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9eee4e0965e5575ce01cbd30698289e909b864e1 --- /dev/null +++ b/frameworks/core/common/event_manager_pen.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/common/event_manager.h" + +#include "base/log/dump_log.h" +#include "base/thread/frame_trace_adapter.h" +#include "core/common/container.h" +#include "core/common/xcollie/xcollieInterface.h" +#include "core/components_ng/manager/select_overlay/select_overlay_manager.h" +#include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h" + +namespace OHOS::Ace { + +void EventManager::PenHoverTest( + const TouchEvent& event, const RefPtr& frameNode, TouchRestrict& touchRestrict) +{ + CHECK_NULL_VOID(frameNode); + const NG::PointF point { event.x, event.y }; + TouchTestResult testResult; + ResponseLinkResult responseLinkResult; + frameNode->TouchTest( + point, point, point, touchRestrict, testResult, event.id, responseLinkResult); + SetResponseLinkRecognizers(testResult, responseLinkResult); + UpdatePenHoverNode(event, testResult); +} + +void EventManager::UpdatePenHoverNode(const TouchEvent& event, const TouchTestResult& testResult) +{ + HoverTestResult penHoverTestResult; + for (const auto& result : testResult) { + auto penHoverResult = AceType::DynamicCast(result); + if (penHoverResult && penHoverResult->IsPenHoverTarget()) { + penHoverTestResult.emplace_back(penHoverResult); + } + } + + if (event.type == TouchType::PROXIMITY_IN) { + TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "pen proximity in hover event."); + lastPenHoverResults_.clear(); + curPenHoverResults_ = std::move(penHoverTestResult); + } else if (event.type == TouchType::PROXIMITY_OUT) { + TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "pen proximity out hover event."); + lastPenHoverResults_ = std::move(curPenHoverResults_); + curPenHoverResults_.clear(); + } else { + lastPenHoverResults_ = std::move(curPenHoverResults_); + curPenHoverResults_ = std::move(penHoverTestResult); + } +} + +void EventManager::DispatchPenHoverEventNG(const TouchEvent& event) +{ + auto lastHoverEndNode = lastPenHoverResults_.begin(); + auto currHoverEndNode = curPenHoverResults_.begin(); + RefPtr lastHoverEndNodeTarget; + uint32_t iterCountLast = 0; + uint32_t iterCountCurr = 0; + for (const auto& hoverResult : lastPenHoverResults_) { + // get valid part of previous hover nodes while it's not in current hover nodes. Those nodes exit hover + // there may have some nodes in curPenHoverResults_ but intercepted + iterCountLast++; + if (lastHoverEndNode != curPenHoverResults_.end()) { + lastHoverEndNode++; + } + if (std::find(curPenHoverResults_.begin(), curPenHoverResults_.end(), hoverResult) == + curPenHoverResults_.end()) { + hoverResult->HandlePenHoverEvent(false, event); + } + if ((iterCountLast >= lastPenHoverDispatchLength_) && (lastPenHoverDispatchLength_ != 0)) { + lastHoverEndNodeTarget = hoverResult; + break; + } + } + lastPenHoverDispatchLength_ = 0; + for (const auto& hoverResult : curPenHoverResults_) { + // get valid part of current hover nodes while it's not in previous hover nodes. Those nodes are new hover + // the valid part stops at first interception + iterCountCurr++; + if (currHoverEndNode != curPenHoverResults_.end()) { + currHoverEndNode++; + } + if (std::find(lastPenHoverResults_.begin(), lastHoverEndNode, hoverResult) == lastHoverEndNode) { + if (!hoverResult->HandlePenHoverEvent(true, event)) { + lastPenHoverDispatchLength_ = iterCountCurr; + break; + } + } + if (hoverResult == lastHoverEndNodeTarget) { + lastPenHoverDispatchLength_ = iterCountCurr; + break; + } + } + for (auto hoverResultIt = lastPenHoverResults_.begin(); hoverResultIt != lastHoverEndNode; ++hoverResultIt) { + // there may have previous hover nodes in the invalid part of current hover nodes. Those nodes exit hover also + if (std::find(currHoverEndNode, curPenHoverResults_.end(), *hoverResultIt) != curPenHoverResults_.end()) { + (*hoverResultIt)->HandlePenHoverEvent(false, event); + } + } +} +} // namespace OHOS::Ace diff --git a/frameworks/core/components_ng/base/frame_node.cpp b/frameworks/core/components_ng/base/frame_node.cpp index beeb92fc84f58a85a1e4ddc867f66c49aa2971f0..79ed0c1581e07739c3097dbff1baf19c886e6c2c 100644 --- a/frameworks/core/components_ng/base/frame_node.cpp +++ b/frameworks/core/components_ng/base/frame_node.cpp @@ -2586,11 +2586,7 @@ HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& pare responseLinkResult.splice(responseLinkResult.end(), std::move(newComingResponseLinkTargets)); } } else if (touchRestrict.hitTestType == SourceType::MOUSE) { - auto mouseHub = eventHub_->GetInputEventHub(); - if (mouseHub) { - const auto coordinateOffset = globalPoint - localPoint; - preventBubbling = mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets); - } + preventBubbling = ProcessMouseTestHit(globalPoint, localPoint, touchRestrict, newComingTargets); } } @@ -2620,6 +2616,22 @@ HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& pare return testResult; } +bool FrameNode::ProcessMouseTestHit(const PointF& globalPoint, const PointF& localPoint, + TouchRestrict& touchRestrict, TouchTestResult& newComingTargets) +{ + auto mouseHub = eventHub_->GetInputEventHub(); + if (!mouseHub) { + return false; + } + + const auto coordinateOffset = globalPoint - localPoint; + if (touchRestrict.touchEvent.IsPenHoverEvent()) { + return mouseHub->ProcessPenHoverTestHit(coordinateOffset, newComingTargets); + } + + return mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets); +} + std::vector FrameNode::GetResponseRegionList(const RectF& rect, int32_t sourceType) { std::vector responseRegionList; diff --git a/frameworks/core/components_ng/base/frame_node.h b/frameworks/core/components_ng/base/frame_node.h index 72a68374a9f98eaade2f468b646dcf408f2b7bf5..8f35aca418f000c15f8c716d15df992056123a3f 100644 --- a/frameworks/core/components_ng/base/frame_node.h +++ b/frameworks/core/components_ng/base/frame_node.h @@ -1190,6 +1190,9 @@ private: bool AllowVisibleAreaCheck() const; + bool ProcessMouseTestHit(const PointF& globalPoint, const PointF& localPoint, + TouchRestrict& touchRestrict, TouchTestResult& newComingTargets); + // sort in ZIndex. std::multiset, ZIndexComparator> frameChildren_; RefPtr geometryNode_ = MakeRefPtr(); diff --git a/frameworks/core/components_ng/event/input_event.cpp b/frameworks/core/components_ng/event/input_event.cpp index d7d26caabe6566b877471e3d9fbb82fe18f0dd15..6290cf87d6674c8398ac8a997b657406ff7e7cdb 100644 --- a/frameworks/core/components_ng/event/input_event.cpp +++ b/frameworks/core/components_ng/event/input_event.cpp @@ -29,6 +29,7 @@ InputEventActuator::InputEventActuator(const WeakPtr& inputEventH hoverEventTarget_ = MakeRefPtr(frameNode->GetTag(), frameNode->GetId()); hoverEffectTarget_ = MakeRefPtr(frameNode->GetTag(), frameNode->GetId()); accessibilityHoverEventTarget_ = MakeRefPtr(frameNode->GetTag(), frameNode->GetId()); + penHoverEventTarget_ = MakeRefPtr(frameNode->GetTag(), frameNode->GetId()); axisEventTarget_ = MakeRefPtr(frameNode->GetTag()); } @@ -95,6 +96,38 @@ void InputEventActuator::OnCollectHoverEvent( result.emplace_back(hoverEventTarget_); } +void InputEventActuator::OnCollectPenHoverEvent( + const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result) +{ + if (inputEvents_.empty() && !userCallback_ && !userJSFrameNodeCallback_) { + return; + } + + auto penHoverCallback = [weakClaim = WeakClaim(this)](bool isHover, HoverInfo& penHoverInfo) { + auto actuator = weakClaim.Upgrade(); + CHECK_NULL_VOID(actuator); + auto inputEvents = actuator->inputEvents_; + for (const auto& inputCallback : inputEvents) { + if (inputCallback) { + (*inputCallback)(isHover); + (*inputCallback)(isHover, penHoverInfo); + } + } + auto userCallback = actuator->userCallback_; + if (userCallback) { + (*userCallback)(isHover, penHoverInfo); + } + auto userJSCallback = actuator->userJSFrameNodeCallback_; + if (userJSCallback) { + (*userJSCallback)(isHover, penHoverInfo); + } + }; + penHoverEventTarget_->SetPenHoverCallback(penHoverCallback); + penHoverEventTarget_->SetCoordinateOffset(Offset(coordinateOffset.GetX(), coordinateOffset.GetY())); + penHoverEventTarget_->SetGetEventTargetImpl(getEventTargetImpl); + result.emplace_back(penHoverEventTarget_); +} + void InputEventActuator::OnCollectHoverEffect( const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result) { diff --git a/frameworks/core/components_ng/event/input_event.h b/frameworks/core/components_ng/event/input_event.h index 18a0ab7acfd6ed097e4a8482292721aede7019e2..651b191d77b63cc148d885c347645d7c57007504 100644 --- a/frameworks/core/components_ng/event/input_event.h +++ b/frameworks/core/components_ng/event/input_event.h @@ -199,6 +199,9 @@ public: void OnCollectAccessibilityHoverEvent(const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result, const RefPtr& host); + void OnCollectPenHoverEvent( + const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, TouchTestResult& result); + void OnCollectAxisEvent( const OffsetF& coordinateOffset, const GetEventTargetImpl& getEventTargetImpl, AxisTestResult& onAxisResult); @@ -208,6 +211,7 @@ private: RefPtr hoverEventTarget_; RefPtr hoverEffectTarget_; RefPtr accessibilityHoverEventTarget_; + RefPtr penHoverEventTarget_; RefPtr axisEventTarget_; std::list> inputEvents_; RefPtr userCallback_; diff --git a/frameworks/core/components_ng/event/input_event_hub.cpp b/frameworks/core/components_ng/event/input_event_hub.cpp index da8f7e40c283402b353dc41da1af6b9224cdeb0c..2c5a950f2c7d0b2f9d7c103f5fec0024abde5dae 100644 --- a/frameworks/core/components_ng/event/input_event_hub.cpp +++ b/frameworks/core/components_ng/event/input_event_hub.cpp @@ -53,6 +53,18 @@ bool InputEventHub::ProcessMouseTestHit(const OffsetF& coordinateOffset, TouchTe return false; } +bool InputEventHub::ProcessPenHoverTestHit(const OffsetF& coordinateOffset, TouchTestResult& result) +{ + auto eventHub = eventHub_.Upgrade(); + auto getEventTargetImpl = eventHub ? eventHub->CreateGetEventTargetImpl() : nullptr; + + if (hoverEventActuator_) { + hoverEventActuator_->OnCollectPenHoverEvent(coordinateOffset, getEventTargetImpl, result); + } + + return false; +} + bool InputEventHub::ProcessAxisTestHit(const OffsetF& coordinateOffset, AxisTestResult& onAxisResult) { auto eventHub = eventHub_.Upgrade(); diff --git a/frameworks/core/components_ng/event/input_event_hub.h b/frameworks/core/components_ng/event/input_event_hub.h index 900d50f8ea68e5a98c50aefea920d2feb0e4bb47..7ee5a8917e82cc8aaa2cd0fa8da3a5e12dee110f 100644 --- a/frameworks/core/components_ng/event/input_event_hub.h +++ b/frameworks/core/components_ng/event/input_event_hub.h @@ -147,6 +147,8 @@ public: // the return value means prevents event bubbling. bool ProcessMouseTestHit(const OffsetF& coordinateOffset, TouchTestResult& result); + bool ProcessPenHoverTestHit(const OffsetF& coordinateOffset, TouchTestResult& result); + bool ProcessAxisTestHit(const OffsetF& coordinateOffset, AxisTestResult& onAxisResult); RefPtr GetFrameNode() const; diff --git a/frameworks/core/components_ng/pattern/model/model_touch_handler.cpp b/frameworks/core/components_ng/pattern/model/model_touch_handler.cpp index cc32538445ca015158d89d4c2c23d17f335b0ccf..22e651c5b70dc47bef96ee5cf92e939499e2811c 100644 --- a/frameworks/core/components_ng/pattern/model/model_touch_handler.cpp +++ b/frameworks/core/components_ng/pattern/model/model_touch_handler.cpp @@ -120,6 +120,8 @@ Render3D::PointerEvent ModelTouchHandler::CreateSceneTouchEvent(const TouchEvent case TouchType::HOVER_MOVE: case TouchType::HOVER_EXIT: case TouchType::HOVER_CANCEL: + case TouchType::PROXIMITY_IN: + case TouchType::PROXIMITY_OUT: case TouchType::UNKNOWN: break; } diff --git a/frameworks/core/event/mouse_event.cpp b/frameworks/core/event/mouse_event.cpp index dc50a255ad81cd90787858a5f15fb096b913b822..d39269cc5aa585cd7dc3caea00c8edb42819017e 100644 --- a/frameworks/core/event/mouse_event.cpp +++ b/frameworks/core/event/mouse_event.cpp @@ -33,6 +33,21 @@ bool HoverEventTarget::HandleHoverEvent(bool isHovered, const MouseEvent& event) return !hoverInfo.IsStopPropagation(); } +bool HoverEventTarget::HandlePenHoverEvent(bool isHovered, const TouchEvent& event) +{ + if (!onPenHoverEventCallback_) { + return false; + } + HoverInfo hoverInfo; + hoverInfo.SetTimeStamp(event.time); + hoverInfo.SetDeviceId(event.deviceId); + hoverInfo.SetSourceDevice(event.sourceType); + hoverInfo.SetSourceTool(event.sourceTool); + hoverInfo.SetTarget(GetEventTarget().value_or(EventTarget())); + onPenHoverEventCallback_(isHovered, hoverInfo); + return !hoverInfo.IsStopPropagation(); +} + void HoverEventTarget::HandleAccessibilityHoverEvent(bool isHovered, const TouchEvent& event) { if (!onAccessibilityHoverCallback_) { @@ -77,6 +92,8 @@ AccessibilityHoverAction HoverEventTarget::ConvertAccessibilityHoverAction(Touch case TouchType::PULL_MOVE: case TouchType::PULL_IN_WINDOW: case TouchType::PULL_OUT_WINDOW: + case TouchType::PROXIMITY_IN: + case TouchType::PROXIMITY_OUT: case TouchType::UNKNOWN: return AccessibilityHoverAction::UNKNOWN; } diff --git a/frameworks/core/event/mouse_event.h b/frameworks/core/event/mouse_event.h index b13bd0e7c49778e6fc6eba8c71aa07f91ef7a00e..4651f0b8198a60fc51d293dfbb259dc54edc09c5 100644 --- a/frameworks/core/event/mouse_event.h +++ b/frameworks/core/event/mouse_event.h @@ -502,15 +502,27 @@ public: onAccessibilityHoverCallback_ = onAccessibilityHoverCallback; } + void SetPenHoverCallback(const OnHoverFunc& onPenHoverEventCallback) + { + onPenHoverEventCallback_ = onPenHoverEventCallback; + } + bool HandleHoverEvent(bool isHovered, const MouseEvent& event); void HandleAccessibilityHoverEvent(bool isHovered, const TouchEvent& event); + bool HandlePenHoverEvent(bool isHovered, const TouchEvent& event); + bool IsAccessibilityHoverTarget() { return onAccessibilityHoverCallback_ != nullptr; } + bool IsPenHoverTarget() const + { + return onPenHoverEventCallback_ != nullptr; + } + bool HandleHoverEvent(bool isHovered) { if (!onHoverCallback_) { @@ -535,6 +547,7 @@ private: OnHoverEventFunc onHoverCallback_; OnHoverFunc onHoverEventCallback_; OnAccessibilityHoverFunc onAccessibilityHoverCallback_; + OnHoverFunc onPenHoverEventCallback_; }; class HoverEffectTarget : public virtual TouchEventTarget { diff --git a/frameworks/core/event/touch_event.h b/frameworks/core/event/touch_event.h index dd06cacdac3e78b87a5b8a19e0b0a8c585a3fd95..f57f2ac441a85c4a6eaff922254a5a522cd3da81 100755 --- a/frameworks/core/event/touch_event.h +++ b/frameworks/core/event/touch_event.h @@ -52,6 +52,8 @@ enum class TouchType : size_t { HOVER_MOVE, HOVER_EXIT, HOVER_CANCEL, + PROXIMITY_IN, + PROXIMITY_OUT, UNKNOWN, }; @@ -451,6 +453,12 @@ struct TouchEvent final : public UIInputEvent { event.pointers.emplace_back(std::move(point)); return event; } + + bool IsPenHoverEvent() const + { + return sourceTool == SourceTool::PEN && (type == TouchType::PROXIMITY_IN || + type == TouchType::PROXIMITY_OUT || (type == TouchType::MOVE && NearZero(force))); + } }; namespace Platform { diff --git a/frameworks/core/pipeline/pipeline_base.h b/frameworks/core/pipeline/pipeline_base.h index 6ae09b71b1d02ac9c244609c1fd1225b4d1d372e..6c21021ab26ca4f0c06384f3c637f4fe5e568d53 100644 --- a/frameworks/core/pipeline/pipeline_base.h +++ b/frameworks/core/pipeline/pipeline_base.h @@ -170,6 +170,10 @@ public: virtual void OnAccessibilityHoverEvent(const TouchEvent& point, const RefPtr& node) {} + virtual void OnPenHoverEvent(const TouchEvent& point, const RefPtr& node) {} + + virtual void HandlePenHoverOut(const TouchEvent& point) {} + // Called by container when key event received. // if return false, then this event needs platform to handle it. virtual bool OnKeyEvent(const KeyEvent& event) = 0; diff --git a/frameworks/core/pipeline_ng/pipeline_context.cpp b/frameworks/core/pipeline_ng/pipeline_context.cpp index 907d3a0c42692eaf75218f76e9c1d05caf579a6a..31a572f39c087498a374e2c7ce3cc7da0c8e77bd 100644 --- a/frameworks/core/pipeline_ng/pipeline_context.cpp +++ b/frameworks/core/pipeline_ng/pipeline_context.cpp @@ -2031,6 +2031,8 @@ void PipelineContext::OnTouchEvent(const TouchEvent& point, const RefPtr& node) +{ + CHECK_RUN_ON(UI); + auto scaleEvent = point.CreateScalePoint(viewScale_); + if (scaleEvent.type != TouchType::MOVE) { + eventManager_->GetEventTreeRecord().AddTouchPoint(scaleEvent); + TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, + "OnPenHoverEvent event id:%{public}d, fingerId:%{public}d " + "type=%{public}d, " + "inject=%{public}d", + scaleEvent.touchEventId, scaleEvent.id, (int)scaleEvent.type, + scaleEvent.isInjected); + } + + auto targerNode = node ? node : rootNode_; + TouchRestrict touchRestrict { TouchRestrict::NONE }; + touchRestrict.sourceType = scaleEvent.sourceType; + touchRestrict.touchEvent.sourceTool = scaleEvent.sourceTool; + touchRestrict.touchEvent.type = scaleEvent.type; + touchRestrict.touchEvent.force = scaleEvent.force; + + // use mouse to collect pen hover target + touchRestrict.hitTestType = SourceType::MOUSE; + touchRestrict.inputEventType = InputEventType::TOUCH_SCREEN; + eventManager_->PenHoverTest(scaleEvent, targerNode, touchRestrict); + eventManager_->DispatchPenHoverEventNG(scaleEvent); + RequestFrame(); +} + +void PipelineContext::HandlePenHoverOut(const TouchEvent& point) +{ + if (point.sourceTool != SourceTool::PEN || point.type != TouchType::DOWN || NearZero(point.force)) { + return; + } + + CHECK_RUN_ON(UI); + auto oriPoint = point; + oriPoint.type = TouchType::PROXIMITY_OUT; + + TouchTestResult testResult; + eventManager_->UpdatePenHoverNode(oriPoint, testResult); + eventManager_->DispatchPenHoverEventNG(oriPoint); +} + void PipelineContext::OnMouseEvent(const MouseEvent& event, const RefPtr& node) { CHECK_RUN_ON(UI); diff --git a/frameworks/core/pipeline_ng/pipeline_context.h b/frameworks/core/pipeline_ng/pipeline_context.h index 4bfefb96c29e3e31f49a30a4384ab841febf9f57..206b53c9f9a0a6c484c3fa5c5b3e7bbc74080e2f 100644 --- a/frameworks/core/pipeline_ng/pipeline_context.h +++ b/frameworks/core/pipeline_ng/pipeline_context.h @@ -138,6 +138,10 @@ public: void OnAccessibilityHoverEvent(const TouchEvent& point, const RefPtr& node) override; + void OnPenHoverEvent(const TouchEvent& point, const RefPtr& node) override; + + void HandlePenHoverOut(const TouchEvent& point) override; + void OnMouseEvent(const MouseEvent& event, const RefPtr& node) override; void OnAxisEvent(const AxisEvent& event, const RefPtr& node) override; diff --git a/test/mock/core/pipeline/mock_pipeline_context.cpp b/test/mock/core/pipeline/mock_pipeline_context.cpp index 42c766f0fc096869dd2b406eae81e33323c779b0..68ad35c20a45e93b16e9d1bc7447ebf8a86f8b4b 100644 --- a/test/mock/core/pipeline/mock_pipeline_context.cpp +++ b/test/mock/core/pipeline/mock_pipeline_context.cpp @@ -215,6 +215,10 @@ void PipelineContext::OnTouchEvent(const TouchEvent& point, bool isSubPipe) {} void PipelineContext::OnAccessibilityHoverEvent(const TouchEvent& point, const RefPtr& node) {} +void PipelineContext::OnPenHoverEvent(const TouchEvent& point, const RefPtr& node) {} + +void PipelineContext::HandlePenHoverOut(const TouchEvent& point) {} + void PipelineContext::OnMouseEvent(const MouseEvent& event) {} void PipelineContext::FlushTouchEvents() {} diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 9cf9e598339faa5e17049483afb36d815263d29b..3f092c6468c6e1e649ddbd30aa7c64c41d434688 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -420,6 +420,7 @@ ohos_source_set("ace_core_extra") { "$ace_root/frameworks/core/common/container_scope.cpp", "$ace_root/frameworks/core/common/event_dump.cpp", "$ace_root/frameworks/core/common/event_manager.cpp", + "$ace_root/frameworks/core/common/event_manager_pen.cpp", "$ace_root/frameworks/core/common/ime/text_editing_value.cpp", "$ace_root/frameworks/core/common/ime/text_input_action.cpp", "$ace_root/frameworks/core/common/ime/text_input_client.cpp",