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 UpdatePenHoverMoveNode(event, testResult);
39 }
40
UpdatePenHoverNode(const TouchEvent & event,const TouchTestResult & testResult)41 void EventManager::UpdatePenHoverNode(const TouchEvent& event, const TouchTestResult& testResult)
42 {
43 HoverTestResult penHoverTestResult;
44 for (const auto& result : testResult) {
45 auto penHoverResult = AceType::DynamicCast<HoverEventTarget>(result);
46 if (penHoverResult && penHoverResult->IsPenHoverTarget()) {
47 penHoverTestResult.emplace_back(penHoverResult);
48 }
49 }
50
51 if (event.type == TouchType::PROXIMITY_IN) {
52 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "pen proximity in hover event.");
53 lastPenHoverResults_.clear();
54 curPenHoverResults_ = std::move(penHoverTestResult);
55 } else if (event.type == TouchType::PROXIMITY_OUT) {
56 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "pen proximity out hover event.");
57 lastPenHoverResults_ = std::move(curPenHoverResults_);
58 curPenHoverResults_.clear();
59 } else {
60 lastPenHoverResults_ = std::move(curPenHoverResults_);
61 curPenHoverResults_ = std::move(penHoverTestResult);
62 }
63 }
64
UpdatePenHoverMoveNode(const TouchEvent & event,const TouchTestResult & testResult)65 void EventManager::UpdatePenHoverMoveNode(const TouchEvent& event, const TouchTestResult& testResult)
66 {
67 HoverTestResult penHoverTestResult;
68 for (const auto& result : testResult) {
69 auto penHoverResult = AceType::DynamicCast<HoverEventTarget>(result);
70 if (penHoverResult && penHoverResult->IsPenHoverMoveTarget()) {
71 penHoverTestResult.emplace_back(penHoverResult);
72 }
73 }
74 curPenHoverMoveResults_ = std::move(penHoverTestResult);
75 }
76
DispatchPenHoverEventNG(const TouchEvent & event)77 void EventManager::DispatchPenHoverEventNG(const TouchEvent& event)
78 {
79 auto lastHoverEndNode = lastPenHoverResults_.begin();
80 auto currHoverEndNode = curPenHoverResults_.begin();
81 RefPtr<HoverEventTarget> lastHoverEndNodeTarget;
82 uint32_t iterCountLast = 0;
83 uint32_t iterCountCurr = 0;
84 for (const auto& hoverResult : lastPenHoverResults_) {
85 // get valid part of previous hover nodes while it's not in current hover nodes. Those nodes exit hover
86 // there may have some nodes in curPenHoverResults_ but intercepted
87 iterCountLast++;
88 if (lastHoverEndNode != curPenHoverResults_.end()) {
89 lastHoverEndNode++;
90 }
91 if (std::find(curPenHoverResults_.begin(), curPenHoverResults_.end(), hoverResult) ==
92 curPenHoverResults_.end()) {
93 hoverResult->HandlePenHoverEvent(false, event);
94 }
95 if ((iterCountLast >= lastPenHoverDispatchLength_) && (lastPenHoverDispatchLength_ != 0)) {
96 lastHoverEndNodeTarget = hoverResult;
97 break;
98 }
99 }
100 lastPenHoverDispatchLength_ = 0;
101 for (const auto& hoverResult : curPenHoverResults_) {
102 // get valid part of current hover nodes while it's not in previous hover nodes. Those nodes are new hover
103 // the valid part stops at first interception
104 iterCountCurr++;
105 if (currHoverEndNode != curPenHoverResults_.end()) {
106 currHoverEndNode++;
107 }
108 if (std::find(lastPenHoverResults_.begin(), lastHoverEndNode, hoverResult) == lastHoverEndNode) {
109 if (!hoverResult->HandlePenHoverEvent(true, event)) {
110 lastPenHoverDispatchLength_ = iterCountCurr;
111 break;
112 }
113 }
114 if (hoverResult == lastHoverEndNodeTarget) {
115 lastPenHoverDispatchLength_ = iterCountCurr;
116 break;
117 }
118 }
119 for (auto hoverResultIt = lastPenHoverResults_.begin(); hoverResultIt != lastHoverEndNode; ++hoverResultIt) {
120 // there may have previous hover nodes in the invalid part of current hover nodes. Those nodes exit hover also
121 if (std::find(currHoverEndNode, curPenHoverResults_.end(), *hoverResultIt) != curPenHoverResults_.end()) {
122 (*hoverResultIt)->HandlePenHoverEvent(false, event);
123 }
124 }
125 }
126
DispatchPenHoverMoveEventNG(const TouchEvent & event)127 void EventManager::DispatchPenHoverMoveEventNG(const TouchEvent& event)
128 {
129 for (const auto& hoverMoveResult : curPenHoverMoveResults_) {
130 if (!hoverMoveResult->HandlePenHoverMoveEvent(event)) {
131 break;
132 }
133 }
134 }
135 } // namespace OHOS::Ace
136