1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/common/event_manager.h"
17 
18 #include "base/log/dump_log.h"
19 #include "base/thread/frame_trace_adapter.h"
20 #include "core/common/container.h"
21 #include "core/common/xcollie/xcollieInterface.h"
22 #include "core/components_ng/manager/select_overlay/select_overlay_manager.h"
23 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
24 
25 namespace OHOS::Ace {
26 
PenHoverTest(const TouchEvent & event,const RefPtr<NG::FrameNode> & frameNode,TouchRestrict & touchRestrict)27 void EventManager::PenHoverTest(
28     const TouchEvent& event, const RefPtr<NG::FrameNode>& frameNode, TouchRestrict& touchRestrict)
29 {
30     CHECK_NULL_VOID(frameNode);
31     const NG::PointF point { event.x, event.y };
32     TouchTestResult testResult;
33     ResponseLinkResult responseLinkResult;
34     frameNode->TouchTest(
35         point, point, point, touchRestrict, testResult, event.id, responseLinkResult);
36     SetResponseLinkRecognizers(testResult, responseLinkResult);
37     UpdatePenHoverNode(event, testResult);
38 }
39 
UpdatePenHoverNode(const TouchEvent & event,const TouchTestResult & testResult)40 void EventManager::UpdatePenHoverNode(const TouchEvent& event, const TouchTestResult& testResult)
41 {
42     HoverTestResult penHoverTestResult;
43     for (const auto& result : testResult) {
44         auto penHoverResult = AceType::DynamicCast<HoverEventTarget>(result);
45         if (penHoverResult && penHoverResult->IsPenHoverTarget()) {
46             penHoverTestResult.emplace_back(penHoverResult);
47         }
48     }
49 
50     if (event.type == TouchType::PROXIMITY_IN) {
51         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "pen proximity in hover event.");
52         lastPenHoverResults_.clear();
53         curPenHoverResults_ = std::move(penHoverTestResult);
54     } else if (event.type == TouchType::PROXIMITY_OUT) {
55         TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "pen proximity out hover event.");
56         lastPenHoverResults_ = std::move(curPenHoverResults_);
57         curPenHoverResults_.clear();
58     } else {
59         lastPenHoverResults_ = std::move(curPenHoverResults_);
60         curPenHoverResults_ = std::move(penHoverTestResult);
61     }
62 }
63 
DispatchPenHoverEventNG(const TouchEvent & event)64 void EventManager::DispatchPenHoverEventNG(const TouchEvent& event)
65 {
66     auto lastHoverEndNode = lastPenHoverResults_.begin();
67     auto currHoverEndNode = curPenHoverResults_.begin();
68     RefPtr<HoverEventTarget> lastHoverEndNodeTarget;
69     uint32_t iterCountLast = 0;
70     uint32_t iterCountCurr = 0;
71     for (const auto& hoverResult : lastPenHoverResults_) {
72         // get valid part of previous hover nodes while it's not in current hover nodes. Those nodes exit hover
73         // there may have some nodes in curPenHoverResults_ but intercepted
74         iterCountLast++;
75         if (lastHoverEndNode != curPenHoverResults_.end()) {
76             lastHoverEndNode++;
77         }
78         if (std::find(curPenHoverResults_.begin(), curPenHoverResults_.end(), hoverResult) ==
79             curPenHoverResults_.end()) {
80             hoverResult->HandlePenHoverEvent(false, event);
81         }
82         if ((iterCountLast >= lastPenHoverDispatchLength_) && (lastPenHoverDispatchLength_ != 0)) {
83             lastHoverEndNodeTarget = hoverResult;
84             break;
85         }
86     }
87     lastPenHoverDispatchLength_ = 0;
88     for (const auto& hoverResult : curPenHoverResults_) {
89         // get valid part of current hover nodes while it's not in previous hover nodes. Those nodes are new hover
90         // the valid part stops at first interception
91         iterCountCurr++;
92         if (currHoverEndNode != curPenHoverResults_.end()) {
93             currHoverEndNode++;
94         }
95         if (std::find(lastPenHoverResults_.begin(), lastHoverEndNode, hoverResult) == lastHoverEndNode) {
96             if (!hoverResult->HandlePenHoverEvent(true, event)) {
97                 lastPenHoverDispatchLength_ = iterCountCurr;
98                 break;
99             }
100         }
101         if (hoverResult == lastHoverEndNodeTarget) {
102             lastPenHoverDispatchLength_ = iterCountCurr;
103             break;
104         }
105     }
106     for (auto hoverResultIt = lastPenHoverResults_.begin(); hoverResultIt != lastHoverEndNode; ++hoverResultIt) {
107         // there may have previous hover nodes in the invalid part of current hover nodes. Those nodes exit hover also
108         if (std::find(currHoverEndNode, curPenHoverResults_.end(), *hoverResultIt) != curPenHoverResults_.end()) {
109             (*hoverResultIt)->HandlePenHoverEvent(false, event);
110         }
111     }
112 }
113 } // namespace OHOS::Ace
114