1 /*
2 * Copyright (c) 2021-2023 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 #include "core/event/focus_axis_event.h"
25
26 namespace OHOS::Ace {
27 constexpr int32_t DUMP_START_NUMBER = 4;
28 constexpr int32_t DUMP_LIMIT_SIZE = 500;
29 constexpr int64_t EVENT_CLEAR_DURATION = 1000;
30 constexpr int64_t TRANSLATE_NS_TO_MS = 1000000;
31
TouchTest(const TouchEvent & touchPoint,const RefPtr<RenderNode> & renderNode,TouchRestrict & touchRestrict,const Offset & offset,float viewScale,bool needAppend)32 void EventManager::TouchTest(const TouchEvent& touchPoint, const RefPtr<RenderNode>& renderNode,
33 TouchRestrict& touchRestrict, const Offset& offset, float viewScale, bool needAppend)
34 {
35 ContainerScope scope(instanceId_);
36
37 ACE_FUNCTION_TRACE();
38 CHECK_NULL_VOID(renderNode);
39 // first clean.
40 referee_->CleanGestureScope(touchPoint.id);
41 // collect
42 TouchTestResult hitTestResult;
43 const Point point { touchPoint.x, touchPoint.y, touchPoint.sourceType };
44 // For root node, the parent local point is the same as global point.
45 renderNode->TouchTest(point, point, touchRestrict, hitTestResult);
46 if (needAppend) {
47 #ifdef OHOS_STANDARD_SYSTEM
48 for (auto entry = hitTestResult.begin(); entry != hitTestResult.end(); ++entry) {
49 if ((*entry)) {
50 (*entry)->SetSubPipelineGlobalOffset(offset, viewScale);
51 }
52 }
53 #endif
54 TouchTestResult prevHitTestResult = touchTestResults_[touchPoint.id];
55 hitTestResult.splice(hitTestResult.end(), prevHitTestResult);
56 }
57 touchTestResults_[touchPoint.id] = std::move(hitTestResult);
58 }
59
TouchTest(const TouchEvent & touchPoint,const RefPtr<NG::FrameNode> & frameNode,TouchRestrict & touchRestrict,const Offset & offset,float viewScale,bool needAppend)60 void EventManager::TouchTest(const TouchEvent& touchPoint, const RefPtr<NG::FrameNode>& frameNode,
61 TouchRestrict& touchRestrict, const Offset& offset, float viewScale, bool needAppend)
62 {
63 ContainerScope scope(instanceId_);
64
65 ACE_FUNCTION_TRACE();
66 CHECK_NULL_VOID(frameNode);
67 if (!curAccessibilityHoverResults_.empty()) {
68 FalsifyHoverCancelEventAndDispatch(touchPoint);
69 }
70 // collect
71 TouchTestResult hitTestResult;
72 const NG::PointF point { touchPoint.x, touchPoint.y };
73 if (refereeNG_->CheckEventTypeChange(touchPoint.sourceType)) {
74 AxisEvent axisEvent;
75 FalsifyCancelEventAndDispatch(axisEvent);
76 responseCtrl_->Reset();
77 refereeNG_->CleanAll(true);
78 touchTestResults_.clear();
79 axisTouchTestResults_.clear();
80 }
81 refereeNG_->CheckSourceTypeChange(touchPoint.sourceType);
82 if (refereeNG_->QueryAllDone(touchPoint.id)) {
83 refereeNG_->CleanGestureScope(touchPoint.id);
84 if (touchTestResults_.empty() && refereeNG_->QueryAllDone()) {
85 innerEventWin_ = false;
86 responseCtrl_->Reset();
87 refereeNG_->CleanAll();
88 }
89 }
90 if (lastDownFingerNumber_ == 0 && refereeNG_->QueryAllDone()) {
91 FalsifyCancelEventAndDispatch(touchPoint);
92 refereeNG_->ForceCleanGestureReferee();
93 responseCtrl_->Reset();
94 refereeNG_->CleanAll();
95 CleanGestureEventHub();
96 }
97 ResponseLinkResult responseLinkResult;
98 // For root node, the parent local point is the same as global point.
99 frameNode->TouchTest(point, point, point, touchRestrict, hitTestResult, touchPoint.id, responseLinkResult);
100 TouchTestResult savePrevHitTestResult = touchTestResults_[touchPoint.id];
101 SetResponseLinkRecognizers(hitTestResult, responseLinkResult);
102 if (needAppend) {
103 #ifdef OHOS_STANDARD_SYSTEM
104 for (const auto& entry : hitTestResult) {
105 if (entry) {
106 entry->SetSubPipelineGlobalOffset(offset, viewScale);
107 }
108 }
109 #endif
110 TouchTestResult prevHitTestResult = touchTestResults_[touchPoint.id];
111 hitTestResult.splice(hitTestResult.end(), prevHitTestResult);
112 }
113 std::list<RefPtr<NG::NGGestureRecognizer>> hitTestRecognizers;
114 for (const auto& item : hitTestResult) {
115 auto recognizer = AceType::DynamicCast<NG::NGGestureRecognizer>(item);
116 if (recognizer) {
117 hitTestRecognizers.emplace_back(recognizer);
118 }
119 }
120 SetHittedFrameNode(hitTestRecognizers);
121 refereeNG_->AddGestureToScope(touchPoint.id, hitTestResult);
122 touchTestResults_[touchPoint.id] = std::move(hitTestResult);
123
124 int64_t currentEventTime = static_cast<int64_t>(touchPoint.time.time_since_epoch().count());
125 int64_t lastEventTime = static_cast<int64_t>(lastEventTime_.time_since_epoch().count());
126 int64_t duration = static_cast<int64_t>((currentEventTime - lastEventTime) / TRANSLATE_NS_TO_MS);
127 if (duration >= EVENT_CLEAR_DURATION && !refereeNG_->IsReady()) {
128 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING, "GestureReferee is not ready, force clean gestureReferee.");
129 #ifndef IS_RELEASE_VERSION
130 std::list<std::pair<int32_t, std::string>> dumpList;
131 eventTree_.Dump(dumpList, 0);
132 for (auto& item : dumpList) {
133 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "EventTreeDumpInfo: " SEC_PLD(%{public}s) ".",
134 SEC_PARAM(item.second.c_str()));
135 }
136 #endif
137 eventTree_.eventTreeList.clear();
138 FalsifyCancelEventAndDispatch(touchPoint);
139 refereeNG_->ForceCleanGestureReferee();
140 responseCtrl_->Reset();
141 refereeNG_->CleanAll();
142
143 TouchTestResult reHitTestResult;
144 ResponseLinkResult reResponseLinkResult;
145 frameNode->TouchTest(point, point, point, touchRestrict,
146 reHitTestResult, touchPoint.id, reResponseLinkResult);
147 SetResponseLinkRecognizers(reHitTestResult, reResponseLinkResult);
148 if (!refereeNG_->IsReady()) {
149 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING,
150 "GestureReferee is contaminate by new comming recognizer, force clean gestureReferee.");
151 refereeNG_->ForceCleanGestureReferee();
152 }
153 if (needAppend) {
154 #ifdef OHOS_STANDARD_SYSTEM
155 for (const auto& entry : reHitTestResult) {
156 if (entry) {
157 entry->SetSubPipelineGlobalOffset(offset, viewScale);
158 }
159 }
160 #endif
161 reHitTestResult.splice(reHitTestResult.end(), savePrevHitTestResult);
162 }
163 touchTestResults_[touchPoint.id] = std::move(reHitTestResult);
164 const auto& reTouchTestResult = touchTestResults_.find(touchPoint.id);
165 if (reTouchTestResult != touchTestResults_.end()) {
166 refereeNG_->AddGestureToScope(touchPoint.id, reTouchTestResult->second);
167 }
168 }
169
170 auto container = Container::Current();
171 CHECK_NULL_VOID(container);
172 std::map<int32_t, NG::TouchTestResultInfo> touchTestResultInfo;
173 for (const auto& item : touchTestResults_[touchPoint.id]) {
174 auto node = item->GetAttachedNode().Upgrade();
175 if (!node) {
176 continue;
177 }
178 auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
179 if (!frameNode) {
180 continue;
181 }
182 touchTestResultInfo[frameNode->GetId()] = { frameNode->GetId(), frameNode->GetTag(),
183 frameNode->GetInspectorIdValue(""), frameNode->GetGeometryNode()->GetFrameRect().ToString(),
184 frameNode->GetDepth() };
185 }
186 std::string resultInfo = std::string("fingerId: ").append(std::to_string(touchPoint.id));
187 for (const auto& item : touchTestResultInfo) {
188 resultInfo.append("{ ").append("tag: ").append(item.second.tag);
189 #ifndef IS_RELEASE_VERSION
190 resultInfo.append(", inspectorId: ")
191 .append(item.second.inspectorId)
192 .append(", frameRect: ")
193 .append(item.second.frameRect);
194 #endif
195 resultInfo.append(", depth: ").append(std::to_string(item.second.depth)).append(" };");
196 }
197 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW, "InputTracking id:%{public}d, touch test hitted node info: %{public}s",
198 touchPoint.touchEventId, resultInfo.c_str());
199 if (touchTestResultInfo.empty()) {
200 TAG_LOGW(AceLogTag::ACE_INPUTKEYFLOW, "Touch test result is empty.");
201 std::list<std::pair<int32_t, std::string>> dumpList;
202 eventTree_.Dump(dumpList, 0, DUMP_START_NUMBER);
203 int32_t dumpCount = 0;
204 for ([[maybe_unused]] auto& item : dumpList) {
205 dumpCount++;
206 if (dumpCount > DUMP_LIMIT_SIZE) {
207 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING,
208 "EventTreeDumpInfo size is over limit, the following info is dropped!");
209 break;
210 }
211 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "EventTreeDumpInfo: " SEC_PLD(%{public}s) ".",
212 SEC_PARAM(item.second.c_str()));
213 }
214 RecordHitEmptyMessage(touchPoint, resultInfo, frameNode);
215 }
216 LogTouchTestResultRecognizers(touchTestResults_[touchPoint.id], touchPoint.touchEventId);
217 }
218
RecordHitEmptyMessage(const TouchEvent & touchPoint,const std::string & resultInfo,const RefPtr<NG::FrameNode> & frameNode)219 void EventManager::RecordHitEmptyMessage(
220 const TouchEvent& touchPoint, const std::string& resultInfo, const RefPtr<NG::FrameNode>& frameNode)
221 {
222 auto hitEmptyMessage = JsonUtil::Create(true);
223 auto container = Container::Current();
224 CHECK_NULL_VOID(container);
225 uint32_t windowId = 0;
226 #ifdef WINDOW_SCENE_SUPPORTED
227 windowId = static_cast<uint32_t>(NG::WindowSceneHelper::GetWindowIdForWindowScene(frameNode));
228 #endif
229 if (windowId == 0) {
230 windowId = container->GetWindowId();
231 }
232 hitEmptyMessage->Put("windowId", static_cast<int32_t>(windowId));
233 auto pipelineContext = container->GetPipelineContext();
234 if (pipelineContext) {
235 auto window = pipelineContext->GetWindow();
236 if (window) {
237 hitEmptyMessage->Put("windowName", window->GetWindowName().c_str());
238 }
239 }
240 hitEmptyMessage->Put("resultInfo", resultInfo.c_str());
241 hitEmptyMessage->Put("x", touchPoint.x);
242 hitEmptyMessage->Put("y", touchPoint.y);
243 hitEmptyMessage->Put("currentTime", static_cast<int64_t>(touchPoint.time.time_since_epoch().count()));
244 hitEmptyMessage->Put("bundleName", container->GetBundleName().c_str());
245 auto frontEnd = container->GetFrontend();
246 if (frontEnd) {
247 hitEmptyMessage->Put("pageInfo", frontEnd->GetCurrentPageUrl().c_str());
248 }
249 XcollieInterface::GetInstance().TriggerTimerCount("HIT_EMPTY_WARNING", true, hitEmptyMessage->ToString());
250 }
251
LogTouchTestResultRecognizers(const TouchTestResult & result,int32_t touchEventId)252 void EventManager::LogTouchTestResultRecognizers(const TouchTestResult& result, int32_t touchEventId)
253 {
254 std::map<std::string, std::list<NG::TouchTestResultInfo>> hittedRecognizerInfo;
255 for (const auto& item : result) {
256 if (AceType::InstanceOf<NG::MultiFingersRecognizer>(item) && !AceType::InstanceOf<NG::RecognizerGroup>(item)) {
257 auto node = item->GetAttachedNode().Upgrade();
258 if (!node) {
259 hittedRecognizerInfo.emplace(AceType::TypeName(item), std::list<NG::TouchTestResultInfo>());
260 continue;
261 }
262 auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
263 if (!frameNode) {
264 hittedRecognizerInfo.emplace(AceType::TypeName(item), std::list<NG::TouchTestResultInfo>());
265 continue;
266 }
267 hittedRecognizerInfo[AceType::TypeName(item)].emplace_back(NG::TouchTestResultInfo {
268 frameNode->GetId(), frameNode->GetTag(), frameNode->GetInspectorIdValue("") });
269 }
270 auto group = AceType::DynamicCast<NG::RecognizerGroup>(item);
271 if (group) {
272 group->AddHittedRecognizerType(hittedRecognizerInfo);
273 }
274 }
275 std::string hittedRecognizerTypeInfo = std::string("InputTracking id:");
276 hittedRecognizerTypeInfo.append(std::to_string(touchEventId)).append(", touch test hitted recognizer type info: ");
277 for (const auto& item : hittedRecognizerInfo) {
278 hittedRecognizerTypeInfo.append("recognizer type ").append(item.first).append(" node info:");
279 for (const auto& nodeInfo : item.second) {
280 hittedRecognizerTypeInfo.append(" { ")
281 .append("tag: ")
282 .append(nodeInfo.tag)
283 .append(" };");
284 }
285 }
286 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW, "%{public}s", hittedRecognizerTypeInfo.c_str());
287 if (hittedRecognizerInfo.empty()) {
288 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "Hitted recognizer info is empty.");
289 std::list<std::pair<int32_t, std::string>> dumpList;
290 eventTree_.Dump(dumpList, 0, DUMP_START_NUMBER);
291 for (auto& item : dumpList) {
292 if (!SystemProperties::GetAceCommercialLogEnabled()) {
293 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "EventTreeDumpInfo: %{public}s", item.second.c_str());
294 }
295 }
296 }
297 }
298
PostEventTouchTest(const TouchEvent & touchPoint,const RefPtr<NG::UINode> & uiNode,TouchRestrict & touchRestrict)299 bool EventManager::PostEventTouchTest(
300 const TouchEvent& touchPoint, const RefPtr<NG::UINode>& uiNode, TouchRestrict& touchRestrict)
301 {
302 ContainerScope scope(instanceId_);
303 ACE_FUNCTION_TRACE();
304 CHECK_NULL_RETURN(uiNode, false);
305 // collect
306 TouchTestResult hitTestResult;
307 const NG::PointF point { touchPoint.x, touchPoint.y };
308 postEventRefereeNG_->CheckSourceTypeChange(touchPoint.sourceType);
309 if (postEventRefereeNG_->QueryAllDone(touchPoint.id)) {
310 postEventRefereeNG_->CleanGestureScope(touchPoint.id);
311 if (postEventTouchTestResults_.empty() && postEventRefereeNG_->QueryAllDone()) {
312 postEventRefereeNG_->CleanAll();
313 }
314 }
315 ResponseLinkResult responseLinkResult;
316 // For root node, the parent local point is the same as global point.
317 uiNode->TouchTest(point, point, point, touchRestrict, hitTestResult, touchPoint.id, responseLinkResult);
318 for (const auto& item : hitTestResult) {
319 item->SetIsPostEventResult(true);
320 auto group = AceType::DynamicCast<NG::RecognizerGroup>(item);
321 if (group) {
322 group->SetIsPostEventResultRecursively(true);
323 group->SetResponseLinkRecognizersRecursively(responseLinkResult);
324 continue;
325 }
326 auto recognizer = AceType::DynamicCast<NG::NGGestureRecognizer>(item);
327 if (recognizer) {
328 recognizer->SetResponseLinkRecognizers(responseLinkResult);
329 }
330 }
331 auto result = !hitTestResult.empty();
332 postEventTouchTestResults_[touchPoint.id] = std::move(hitTestResult);
333 return result;
334 }
335
TouchTest(const AxisEvent & event,const RefPtr<NG::FrameNode> & frameNode,TouchRestrict & touchRestrict)336 void EventManager::TouchTest(
337 const AxisEvent& event, const RefPtr<NG::FrameNode>& frameNode, TouchRestrict& touchRestrict)
338 {
339 ContainerScope scope(instanceId_);
340
341 if (refereeNG_->CheckSourceTypeChange(event.sourceType, true)) {
342 TouchEvent touchEvent = ConvertAxisEventToTouchEvent(event);
343 FalsifyCancelEventAndDispatch(touchEvent);
344 responseCtrl_->Reset();
345 refereeNG_->CleanAll(true);
346 if (event.sourceTool != lastSourceTool_) {
347 touchTestResults_.clear();
348 axisTouchTestResults_.clear();
349 }
350 }
351 ACE_FUNCTION_TRACE();
352 CHECK_NULL_VOID(frameNode);
353 if (axisTouchTestResults_.empty() && refereeNG_->QueryAllDone()) {
354 responseCtrl_->Reset();
355 }
356 // collect
357 const NG::PointF point { event.x, event.y };
358 // For root node, the parent local point is the same as global point.
359 TouchTestResult hitTestResult;
360 ResponseLinkResult responseLinkResult;
361 frameNode->TouchTest(point, point, point, touchRestrict, hitTestResult, event.id, responseLinkResult);
362 SetResponseLinkRecognizers(hitTestResult, responseLinkResult);
363 axisTouchTestResults_[event.id] = std::move(hitTestResult);
364 LogTouchTestResultRecognizers(axisTouchTestResults_[event.id], event.touchEventId);
365 }
366
ConvertAxisEventToTouchEvent(const AxisEvent & axisEvent)367 TouchEvent EventManager::ConvertAxisEventToTouchEvent(const AxisEvent& axisEvent)
368 {
369 TouchType type = TouchType::UNKNOWN;
370 if (axisEvent.action == AxisAction::BEGIN) {
371 type = TouchType::DOWN;
372 } else if (axisEvent.action == AxisAction::END) {
373 type = TouchType::UP;
374 } else if (axisEvent.action == AxisAction::UPDATE) {
375 type = TouchType::MOVE;
376 } else if (axisEvent.action == AxisAction::CANCEL) {
377 type = TouchType::CANCEL;
378 } else {
379 type = TouchType::UNKNOWN;
380 }
381 TouchPoint point { .id = axisEvent.id,
382 .x = axisEvent.x,
383 .y = axisEvent.y,
384 .screenX = axisEvent.screenX,
385 .screenY = axisEvent.screenY,
386 .downTime = axisEvent.time,
387 .size = 0.0,
388 .isPressed = (type == TouchType::DOWN),
389 .originalId = axisEvent.id };
390 TouchEvent event;
391 event.SetId(axisEvent.id)
392 .SetX(axisEvent.x)
393 .SetY(axisEvent.y)
394 .SetScreenX(axisEvent.screenX)
395 .SetScreenY(axisEvent.screenY)
396 .SetType(type)
397 .SetTime(axisEvent.time)
398 .SetSize(0.0)
399 .SetDeviceId(axisEvent.deviceId)
400 .SetTargetDisplayId(axisEvent.targetDisplayId)
401 .SetSourceType(axisEvent.sourceType)
402 .SetSourceTool(axisEvent.sourceTool)
403 .SetPointerEvent(axisEvent.pointerEvent)
404 .SetTouchEventId(axisEvent.touchEventId)
405 .SetOriginalId(axisEvent.originalId)
406 .SetIsInjected(axisEvent.isInjected);
407 event.pointers.emplace_back(std::move(point));
408 event.pressedKeyCodes_ = axisEvent.pressedCodes;
409 return event;
410 }
411
HasDifferentDirectionGesture()412 bool EventManager::HasDifferentDirectionGesture()
413 {
414 uint8_t verticalFlag = 0;
415 uint8_t horizontalFlag = 0;
416 for (const auto& axisResult : axisTouchTestResults_) {
417 auto axisRecognizerList = axisResult.second;
418 for (const auto& axisRecognizer : axisRecognizerList) {
419 if (!axisRecognizer) {
420 continue;
421 }
422 auto axisDirection = axisRecognizer->GetAxisDirection();
423 if (axisDirection == Axis::FREE) {
424 return true;
425 }
426 if (axisDirection == Axis::VERTICAL) {
427 verticalFlag = 0x1;
428 } else if (axisDirection == Axis::HORIZONTAL) {
429 horizontalFlag = 0x2;
430 }
431 if ((verticalFlag | horizontalFlag) == 0x3) {
432 return true;
433 }
434 }
435 }
436 return (verticalFlag | horizontalFlag) == 0x3;
437 }
438
HandleGlobalEvent(const TouchEvent & touchPoint,const RefPtr<TextOverlayManager> & textOverlayManager)439 void EventManager::HandleGlobalEvent(const TouchEvent& touchPoint, const RefPtr<TextOverlayManager>& textOverlayManager)
440 {
441 if (touchPoint.type != TouchType::DOWN) {
442 return;
443 }
444 auto coordinateOffset = textOverlayManager->GetCoordinateOffset();
445 const Point point { touchPoint.x - coordinateOffset.GetX(), touchPoint.y - coordinateOffset.GetY(),
446 touchPoint.sourceType };
447 CHECK_NULL_VOID(textOverlayManager);
448 auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
449 CHECK_NULL_VOID(textOverlayBase);
450 auto targetNode = textOverlayManager->GetTargetNode();
451 CHECK_NULL_VOID(targetNode);
452 for (auto& rect : textOverlayManager->GetTextOverlayRect()) {
453 if (rect.IsInRegion(point)) {
454 inSelectedRect_ = true;
455 }
456 }
457 for (auto& rect : textOverlayBase->GetSelectedRect()) {
458 if (rect.IsInRegion(point)) {
459 inSelectedRect_ = true;
460 }
461 }
462 if (!inSelectedRect_) {
463 textOverlayManager->PopTextOverlay();
464 textOverlayBase->ChangeSelection(0, 0);
465 textOverlayBase->MarkIsOverlayShowed(false);
466 targetNode->MarkNeedRender();
467 }
468 inSelectedRect_ = false;
469 }
470
HandleGlobalEventNG(const TouchEvent & touchPoint,const RefPtr<NG::SelectOverlayManager> & selectOverlayManager,const NG::OffsetF & rootOffset)471 void EventManager::HandleGlobalEventNG(const TouchEvent& touchPoint,
472 const RefPtr<NG::SelectOverlayManager>& selectOverlayManager, const NG::OffsetF& rootOffset)
473 {
474 CHECK_NULL_VOID(selectOverlayManager);
475 auto isMousePressAtSelectedNode = false;
476 if (touchPoint.type == TouchType::DOWN &&
477 (touchTestResults_.find(touchPoint.id) != touchTestResults_.end() || !currMouseTestResults_.empty())) {
478 int32_t selectedNodeId = -1;
479 if (touchPoint.sourceType == SourceType::MOUSE) {
480 selectOverlayManager->GetSelectedNodeIdByMouse(selectedNodeId);
481 }
482 if (!touchTestResults_.empty()) {
483 std::vector<std::string> touchTestIds;
484 GetTouchTestIds(touchPoint, touchTestIds, isMousePressAtSelectedNode, selectedNodeId);
485 selectOverlayManager->SetOnTouchTestResults(touchTestIds);
486 } else {
487 // When right-click on another component, close the current component selection.
488 CheckMouseTestResults(isMousePressAtSelectedNode, selectedNodeId);
489 }
490 }
491 selectOverlayManager->HandleGlobalEvent(touchPoint, rootOffset, isMousePressAtSelectedNode);
492 }
493
CheckMouseTestResults(bool & isMousePressAtSelectedNode,int32_t selectedNodeId)494 void EventManager::CheckMouseTestResults(bool& isMousePressAtSelectedNode, int32_t selectedNodeId)
495 {
496 for (const auto& result : currMouseTestResults_) {
497 TAG_LOGD(AceLogTag::ACE_INPUTTRACKING,
498 "HandleGlobalEventNG selectedNodeId: %{public}d mouseTestResult id is: "
499 SEC_PLD(%{public}d) ".", selectedNodeId, SEC_PARAM(result->GetNodeId()));
500 if (result->GetNodeId() == selectedNodeId) {
501 isMousePressAtSelectedNode = true;
502 }
503 }
504 }
505
GetTouchTestIds(const TouchEvent & touchPoint,std::vector<std::string> & touchTestIds,bool & isMousePressAtSelectedNode,int32_t selectedNodeId)506 void EventManager::GetTouchTestIds(const TouchEvent& touchPoint, std::vector<std::string>& touchTestIds,
507 bool& isMousePressAtSelectedNode, int32_t selectedNodeId)
508 {
509 const auto& resultList = touchTestResults_[touchPoint.id];
510 for (const auto& result : resultList) {
511 auto eventTarget = result->GetEventTarget();
512 if (eventTarget.has_value()) {
513 touchTestIds.emplace_back(eventTarget.value().id);
514 if (eventTarget.value().id == std::to_string(selectedNodeId)) {
515 TAG_LOGD(AceLogTag::ACE_INPUTTRACKING,
516 "HandleGlobalEventNG selectedNodeId: %{public}d", selectedNodeId);
517 isMousePressAtSelectedNode = true;
518 }
519 }
520 }
521 }
522
HandleOutOfRectCallback(const Point & point,std::vector<RectCallback> & rectCallbackList)523 void EventManager::HandleOutOfRectCallback(const Point& point, std::vector<RectCallback>& rectCallbackList)
524 {
525 for (auto iter = rectCallbackList.begin(); iter != rectCallbackList.end();) {
526 auto rectCallback = *iter;
527 auto rectGetCallback = rectCallback.rectGetCallback;
528 if (!rectGetCallback) {
529 ++iter;
530 continue;
531 }
532 std::vector<Rect> rectList;
533 rectGetCallback(rectList);
534 if (std::any_of(
535 rectList.begin(), rectList.end(), [point](const Rect& rect) { return rect.IsInRegion(point); })) {
536 ++iter;
537 continue;
538 }
539 for ([[maybe_unused]] const auto& rect : rectList) {
540 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, SEC_PLD(,
541 "Point(%{public}f, %{public}f) out of Rect-[%{public}f, %{public}f, %{public}f, %{public}f]"),
542 SEC_PARAM(point.GetX(), point.GetY(), rect.Left(), rect.Right(), rect.Top(), rect.Bottom()));
543 }
544 if (point.GetSourceType() == SourceType::TOUCH) {
545 if (!rectCallback.touchCallback) {
546 ++iter;
547 continue;
548 }
549 rectCallback.touchCallback();
550 } else if (point.GetSourceType() == SourceType::MOUSE) {
551 if (!rectCallback.mouseCallback) {
552 ++iter;
553 continue;
554 }
555 rectCallback.mouseCallback();
556 }
557 iter = rectCallbackList.erase(iter);
558 }
559 }
560
TouchTest(const AxisEvent & event,const RefPtr<RenderNode> & renderNode,TouchRestrict & touchRestrict)561 void EventManager::TouchTest(
562 const AxisEvent& event, const RefPtr<RenderNode>& renderNode, TouchRestrict& touchRestrict)
563 {
564 ContainerScope scope(instanceId_);
565
566 ACE_FUNCTION_TRACE();
567 CHECK_NULL_VOID(renderNode);
568 // collect
569 const Point point { event.x, event.y, event.sourceType };
570 // For root node, the parent local point is the same as global point.
571 TouchTestResult hitTestResult;
572 renderNode->TouchTest(point, point, touchRestrict, hitTestResult);
573 axisTouchTestResults_[event.id] = std::move(hitTestResult);
574 }
575
FlushTouchEventsBegin(const std::list<TouchEvent> & touchEvents)576 void EventManager::FlushTouchEventsBegin(const std::list<TouchEvent>& touchEvents)
577 {
578 for (auto iter = touchEvents.begin(); iter != touchEvents.end(); ++iter) {
579 const auto result = touchTestResults_.find((*iter).id);
580 if (result != touchTestResults_.end()) {
581 for (auto entry = result->second.rbegin(); entry != result->second.rend(); ++entry) {
582 (*entry)->OnFlushTouchEventsBegin();
583 }
584 }
585 }
586 }
587
FlushTouchEventsEnd(const std::list<TouchEvent> & touchEvents)588 void EventManager::FlushTouchEventsEnd(const std::list<TouchEvent>& touchEvents)
589 {
590 bool isResampled = false;
591 for (auto iter = touchEvents.begin(); iter != touchEvents.end(); ++iter) {
592 const auto result = touchTestResults_.find((*iter).id);
593 if (result != touchTestResults_.end()) {
594 for (auto entry = result->second.rbegin(); entry != result->second.rend(); ++entry) {
595 (*entry)->OnFlushTouchEventsEnd();
596 }
597 // only when no up received situation, the test result can be found
598 if ((*iter).history.size() != 0) {
599 // for resample case, the history list must not be empty
600 isResampled = true;
601 }
602 }
603 }
604
605 if (!isResampled) {
606 // for no-resample case, we do not request a new frame, let the FlushVsync itself to do it as needed.
607 return;
608 }
609
610 // request new frame for the cases we do the resampling for more than one touch events
611 auto container = Container::GetContainer(instanceId_);
612 CHECK_NULL_VOID(container);
613 auto pipeline = container->GetPipelineContext();
614 CHECK_NULL_VOID(pipeline);
615 // Since we cache the received touch move events and process them in FlushVsync, requesting a new frame
616 // when we cache them can not ensure that the frames are continuous afterwhile dure the whole touch access,
617 // as there are some situation where no any dirty generated after FlushVsync, which will not request new frame
618 // by FlushVsync itself, this is not friendly for some components, like UIExtension, which relies on the events
619 // dispatching on host to resend the touchs to the supplier, so we also need to request a new frame after all
620 // resampled touch move events are actually dispatched.
621 pipeline->RequestFrame();
622 }
623
PostEventFlushTouchEventEnd(const TouchEvent & touchEvent)624 void EventManager::PostEventFlushTouchEventEnd(const TouchEvent& touchEvent)
625 {
626 const auto result = postEventTouchTestResults_.find(touchEvent.id);
627 if (result != postEventTouchTestResults_.end()) {
628 for (auto entry = result->second.rbegin(); entry != result->second.rend(); ++entry) {
629 (*entry)->OnFlushTouchEventsEnd();
630 }
631 }
632 }
633
CheckDownEvent(const TouchEvent & touchEvent)634 void EventManager::CheckDownEvent(const TouchEvent& touchEvent)
635 {
636 auto touchEventFindResult = downFingerIds_.find(touchEvent.id);
637 if (touchEvent.type == TouchType::DOWN) {
638 if (touchEventFindResult != downFingerIds_.end()) {
639 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING,
640 "InputTracking id:%{public}d, eventManager receive DOWN event twice,"
641 " touchEvent id is %{public}d",
642 touchEvent.touchEventId, touchEvent.id);
643 FalsifyCancelEventAndDispatch(touchEvent);
644 refereeNG_->ForceCleanGestureReferee();
645 touchTestResults_.clear();
646 downFingerIds_.clear();
647 }
648 downFingerIds_[touchEvent.id] = touchEvent.originalId;
649 }
650 }
651
CheckUpEvent(const TouchEvent & touchEvent)652 void EventManager::CheckUpEvent(const TouchEvent& touchEvent)
653 {
654 if (touchEvent.isFalsified) {
655 return;
656 }
657 auto touchEventFindResult = downFingerIds_.find(touchEvent.id);
658 if (touchEvent.type == TouchType::UP || touchEvent.type == TouchType::CANCEL) {
659 if (touchEventFindResult == downFingerIds_.end()) {
660 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING,
661 "InputTracking id:%{public}d, eventManager receive UP/CANCEL event "
662 "without receive DOWN event, touchEvent id is %{public}d",
663 touchEvent.touchEventId, touchEvent.id);
664 FalsifyCancelEventAndDispatch(touchEvent);
665 refereeNG_->ForceCleanGestureReferee();
666 downFingerIds_.clear();
667 } else {
668 downFingerIds_.erase(touchEvent.id);
669 }
670 }
671 }
672
DispatchTouchEvent(const TouchEvent & event)673 bool EventManager::DispatchTouchEvent(const TouchEvent& event)
674 {
675 ContainerScope scope(instanceId_);
676 TouchEvent point = event;
677 if (point.type == TouchType::PULL_MOVE || point.pullType == TouchType::PULL_MOVE) {
678 isDragging_ = false;
679 point.type = TouchType::CANCEL;
680 point.pullType = TouchType::PULL_MOVE;
681 }
682 if (point.type == TouchType::PULL_UP || point.type == TouchType::UP) {
683 isDragging_ = false;
684 point.type = TouchType::UP;
685 }
686 const auto iter = touchTestResults_.find(point.id);
687 if (iter == touchTestResults_.end()) {
688 CheckUpEvent(event);
689 lastDownFingerNumber_ = static_cast<int32_t>(downFingerIds_.size());
690 return false;
691 }
692 ACE_SCOPED_TRACE("DispatchTouchEvent id:%d, pointX=%f pointY=%f type=%d",
693 point.id, point.x, point.y, (int)point.type);
694 lastTouchEvent_ = event;
695
696 if (point.type == TouchType::DOWN) {
697 refereeNG_->CleanGestureRefereeState(event.id);
698 // add gesture snapshot to dump
699 for (const auto& target : iter->second) {
700 AddGestureSnapshot(point.id, 0, target, NG::EventTreeType::TOUCH);
701 }
702 }
703
704 bool dispatchSuccess = true;
705 for (auto entry = iter->second.rbegin(); entry != iter->second.rend(); ++entry) {
706 if (!(*entry)->DispatchMultiContainerEvent(point)) {
707 dispatchSuccess = false;
708 if ((*entry)->GetAttachedNode().Upgrade()) {
709 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "FrameNode %{public}s dispatch multi container event fail.",
710 (*entry)->GetAttachedNode().Upgrade()->GetTag().c_str());
711 }
712 break;
713 }
714 }
715 // If one gesture recognizer has already been won, other gesture recognizers will still be affected by
716 // the event, each recognizer needs to filter the extra events by itself.
717 if (dispatchSuccess) {
718 if (Container::IsCurrentUseNewPipeline()) {
719 if (point.type == TouchType::CANCEL && point.pullType == TouchType::PULL_MOVE) {
720 CleanRecognizersForDragBegin(point);
721 lastEventTime_ = point.time;
722 lastTouchEventEndTimestamp_ = GetSysTimestamp();
723 return true;
724 }
725 // Need update here: onTouch/Recognizer need update
726 bool hasFailRecognizer = false;
727 bool allDone = false;
728 if (point.type == TouchType::DOWN) {
729 hasFailRecognizer = refereeNG_->HasFailRecognizer(point.id);
730 allDone = refereeNG_->QueryAllDone();
731 }
732 DispatchTouchEventToTouchTestResult(point, iter->second, true);
733 if (!allDone && point.type == TouchType::DOWN && !hasFailRecognizer &&
734 refereeNG_->HasFailRecognizer(point.id) && downFingerIds_.size() <= 1) {
735 refereeNG_->ForceCleanGestureReferee();
736 DispatchTouchEventToTouchTestResult(point, iter->second, false);
737 }
738 } else {
739 for (const auto& entry : iter->second) {
740 if (!entry->HandleMultiContainerEvent(point)) {
741 break;
742 }
743 }
744 }
745 }
746
747 CheckUpEvent(event);
748 if (point.type == TouchType::UP || point.type == TouchType::CANCEL) {
749 LogTouchTestRecognizerStates(point.id);
750 refereeNG_->CleanGestureScope(point.id);
751 referee_->CleanGestureScope(point.id);
752 touchTestResults_.erase(point.id);
753 if (touchTestResults_.empty()) {
754 refereeNG_->CleanRedundanceScope();
755 }
756 }
757
758 lastEventTime_ = point.time;
759 lastTouchEventEndTimestamp_ = GetSysTimestamp();
760 lastDownFingerNumber_ = static_cast<int32_t>(downFingerIds_.size());
761 lastSourceTool_ = event.sourceTool;
762 return true;
763 }
764
LogTouchTestRecognizerStates(int32_t touchEventId)765 void EventManager::LogTouchTestRecognizerStates(int32_t touchEventId)
766 {
767 if (eventTree_.eventTreeList.size() == 0) {
768 return;
769 }
770 std::string log = "";
771 auto lastEventTree = eventTree_.eventTreeList.back();
772
773 std::map<int32_t, std::string> hitFrameNode;
774 std::list<NG::FrameNodeSnapshot> frameNodeSnapShots = lastEventTree.hitTestTree;
775 for (auto iter : frameNodeSnapShots) {
776 hitFrameNode[iter.nodeId] = iter.tag;
777 }
778
779 std::list<RefPtr<GestureSnapshot>> gestureSnapshots = lastEventTree.gestureTree[touchEventId];
780 for (auto gestureSnapshot : gestureSnapshots) {
781 if (gestureSnapshot->type.find("TouchEventActuator") != std::string::npos ||
782 gestureSnapshot->type.find("ExclusiveRecognizer") != std::string::npos ||
783 gestureSnapshot->type.find("ParallelRecognizer") != std::string::npos ||
784 gestureSnapshot->type.find("SequenceRecognizer") != std::string::npos) {
785 continue;
786 }
787 std::string gestureLog = "{";
788 gestureLog += "types: " + gestureSnapshot->type.substr(0, gestureSnapshot->type.find("Recognizer"));
789 gestureLog += ", node: " + hitFrameNode[gestureSnapshot->nodeId];
790
791 auto stateHistorys = gestureSnapshot->stateHistory;
792 for (auto stateHistory : stateHistorys) {
793 if (stateHistory.procedure.find("Down") != std::string::npos) {
794 gestureLog += ", prcd: Down";
795 } else {
796 gestureLog += ", prcd: Up";
797 }
798 gestureLog += ", state: " + stateHistory.state;
799 if (stateHistory.extraInfo != "") {
800 gestureLog += ", extraInfo: " + stateHistory.extraInfo;
801 }
802 }
803 gestureLog += "}";
804 log += gestureLog;
805 }
806 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW, "id: %{public}d, log: %{public}s", touchEventId, log.c_str());
807 }
808
ClearTouchTestTargetForPenStylus(TouchEvent & touchEvent)809 void EventManager::ClearTouchTestTargetForPenStylus(TouchEvent& touchEvent)
810 {
811 refereeNG_->CleanGestureScope(touchEvent.id);
812 referee_->CleanGestureScope(touchEvent.id);
813 touchTestResults_.erase(touchEvent.id);
814 touchEvent.isFalsified = true;
815 touchEvent.type = TouchType::CANCEL;
816 for (const auto& iter : downFingerIds_) {
817 touchEvent.id = iter.first;
818 DispatchTouchEvent(touchEvent);
819 }
820 }
821
CleanRecognizersForDragBegin(TouchEvent & touchEvent)822 void EventManager::CleanRecognizersForDragBegin(TouchEvent& touchEvent)
823 {
824 // send cancel to all recognizer
825 for (const auto& iter : touchTestResults_) {
826 touchEvent.id = iter.first;
827 touchEvent.isInterpolated = true;
828 if (!downFingerIds_.empty() && downFingerIds_.find(iter.first) != downFingerIds_.end()) {
829 touchEvent.originalId = downFingerIds_[touchEvent.id];
830 }
831 DispatchTouchEventToTouchTestResult(touchEvent, iter.second, true);
832 refereeNG_->CleanGestureScope(touchEvent.id);
833 referee_->CleanGestureScope(touchEvent.id);
834 }
835 downFingerIds_.erase(touchEvent.id);
836 touchTestResults_.clear();
837 refereeNG_->CleanRedundanceScope();
838 }
839
DispatchTouchEventToTouchTestResult(TouchEvent touchEvent,TouchTestResult touchTestResult,bool sendOnTouch)840 void EventManager::DispatchTouchEventToTouchTestResult(TouchEvent touchEvent,
841 TouchTestResult touchTestResult, bool sendOnTouch)
842 {
843 bool isStopTouchEvent = false;
844 for (const auto& entry : touchTestResult) {
845 auto recognizer = AceType::DynamicCast<NG::NGGestureRecognizer>(entry);
846 if (recognizer) {
847 entry->HandleMultiContainerEvent(touchEvent);
848 eventTree_.AddGestureProcedure(reinterpret_cast<uintptr_t>(AceType::RawPtr(recognizer)), touchEvent, "",
849 NG::TransRefereeState(recognizer->GetRefereeState()),
850 NG::TransGestureDisposal(recognizer->GetGestureDisposal()));
851 }
852 if (!recognizer && !isStopTouchEvent && sendOnTouch) {
853 isStopTouchEvent = !entry->HandleMultiContainerEvent(touchEvent);
854 eventTree_.AddGestureProcedure(reinterpret_cast<uintptr_t>(AceType::RawPtr(entry)), "",
855 std::string("Handle").append(GestureSnapshot::TransTouchType(touchEvent.type)), "", "");
856 }
857 }
858 }
859
DispatchTouchCancelToRecognizer(TouchEventTarget * touchEventTarget,const std::vector<std::pair<int32_t,TouchTestResult::iterator>> & items)860 void EventManager::DispatchTouchCancelToRecognizer(
861 TouchEventTarget* touchEventTarget, const std::vector<std::pair<int32_t, TouchTestResult::iterator>>& items)
862 {
863 TouchEvent touchEvent;
864 touchEvent.type = TouchType::CANCEL;
865 touchEvent.isFalsified = true;
866 for (auto& item : items) {
867 touchEvent.originalId = item.first;
868 touchEvent.id = item.first;
869 touchEventTarget->HandleMultiContainerEvent(touchEvent);
870 eventTree_.AddGestureProcedure(reinterpret_cast<uintptr_t>(touchEventTarget), "",
871 std::string("Handle").append(GestureSnapshot::TransTouchType(touchEvent.type)), "", "");
872
873 touchTestResults_[item.first].erase(item.second);
874 if (touchTestResults_[item.first].empty()) {
875 touchTestResults_.erase(item.first);
876 }
877 }
878 }
879
PostEventDispatchTouchEvent(const TouchEvent & event)880 bool EventManager::PostEventDispatchTouchEvent(const TouchEvent& event)
881 {
882 ContainerScope scope(instanceId_);
883 TouchEvent point = event;
884 const auto iter = postEventTouchTestResults_.find(point.id);
885 if (iter == postEventTouchTestResults_.end()) {
886 return false;
887 }
888 ACE_SCOPED_TRACE(
889 "PostEventDispatchTouchEvent id:%d, pointX=%f pointY=%f type=%d", point.id, point.x, point.y, (int)point.type);
890
891 if (point.type == TouchType::DOWN) {
892 // first collect gesture into gesture referee.
893 postEventRefereeNG_->AddGestureToScope(point.id, iter->second);
894 // add gesture snapshot to dump
895 for (const auto& target : iter->second) {
896 AddGestureSnapshot(point.id, 0, target, NG::EventTreeType::POST_EVENT);
897 }
898 }
899
900 bool dispatchSuccess = true;
901 for (auto entry = iter->second.rbegin(); entry != iter->second.rend(); ++entry) {
902 if (!(*entry)->DispatchMultiContainerEvent(point)) {
903 dispatchSuccess = false;
904 break;
905 }
906 }
907 // If one gesture recognizer has already been won, other gesture recognizers will still be affected by
908 // the event, each recognizer needs to filter the extra events by itself.
909 if (dispatchSuccess) {
910 bool isStopTouchEvent = false;
911 for (const auto& entry : iter->second) {
912 auto recognizer = AceType::DynamicCast<NG::NGGestureRecognizer>(entry);
913 if (recognizer) {
914 entry->HandleMultiContainerEvent(point);
915 postEventTree_.AddGestureProcedure(reinterpret_cast<uintptr_t>(AceType::RawPtr(recognizer)), point, "",
916 NG::TransRefereeState(recognizer->GetRefereeState()),
917 NG::TransGestureDisposal(recognizer->GetGestureDisposal()));
918 }
919 if (!recognizer && !isStopTouchEvent) {
920 isStopTouchEvent = !entry->HandleMultiContainerEvent(point);
921 postEventTree_.AddGestureProcedure(reinterpret_cast<uintptr_t>(AceType::RawPtr(entry)), "",
922 std::string("Handle").append(GestureSnapshot::TransTouchType(point.type)), "", "");
923 }
924 }
925 }
926
927 if (point.type == TouchType::UP || point.type == TouchType::CANCEL) {
928 postEventRefereeNG_->CleanGestureScope(point.id);
929 postEventTouchTestResults_.erase(point.id);
930 if (postEventTouchTestResults_.empty()) {
931 postEventRefereeNG_->CleanRedundanceScope();
932 }
933 }
934 return true;
935 }
936
DispatchTouchEvent(const AxisEvent & event)937 bool EventManager::DispatchTouchEvent(const AxisEvent& event)
938 {
939 ContainerScope scope(instanceId_);
940
941 const auto curResultIter = axisTouchTestResults_.find(event.id);
942 if (curResultIter == axisTouchTestResults_.end()) {
943 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "the %{public}d axis test result does not exist!", event.id);
944 return false;
945 }
946 // rotate event is no need to add scope.
947 if (event.action == AxisAction::BEGIN && !event.isRotationEvent) {
948 // first collect gesture into gesture referee.
949 if (Container::IsCurrentUseNewPipeline()) {
950 if (refereeNG_) {
951 refereeNG_->AddGestureToScope(event.id, curResultIter->second);
952 }
953 }
954 }
955
956 ACE_FUNCTION_TRACE();
957 for (const auto& entry : curResultIter->second) {
958 if (!entry->HandleEvent(event)) {
959 break;
960 }
961 }
962 if ((event.action == AxisAction::END || event.action == AxisAction::NONE || event.action == AxisAction::CANCEL) &&
963 !event.isRotationEvent) {
964 if (Container::IsCurrentUseNewPipeline()) {
965 if (refereeNG_) {
966 refereeNG_->CleanGestureScope(event.id);
967 }
968 }
969 axisTouchTestResults_.erase(event.id);
970 }
971 lastEventTime_ = event.time;
972 lastTouchEventEndTimestamp_ = GetSysTimestamp();
973 lastSourceTool_ = event.sourceTool;
974 return true;
975 }
976
MouseTest(const MouseEvent & event,const RefPtr<RenderNode> & renderNode)977 void EventManager::MouseTest(const MouseEvent& event, const RefPtr<RenderNode>& renderNode)
978 {
979 CHECK_NULL_VOID(renderNode);
980 const Point point { event.x, event.y };
981 MouseHoverTestList hitTestResult;
982 WeakPtr<RenderNode> hoverNode = nullptr;
983 renderNode->MouseDetect(point, point, hitTestResult, hoverNode);
984
985 if (event.action == MouseAction::WINDOW_LEAVE) {
986 mouseHoverTestResultsPre_ = std::move(mouseHoverTestResults_);
987 mouseHoverTestResults_.clear();
988 } else if (event.action == MouseAction::WINDOW_ENTER) {
989 mouseHoverTestResultsPre_.clear();
990 mouseHoverTestResults_ = std::move(hitTestResult);
991 } else {
992 mouseHoverTestResultsPre_ = std::move(mouseHoverTestResults_);
993 mouseHoverTestResults_ = std::move(hitTestResult);
994 }
995 mouseHoverNodePre_ = mouseHoverNode_;
996 mouseHoverNode_ = hoverNode;
997 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "MouseDetect hit test last/new result size = %{public}zu/%{public}zu",
998 mouseHoverTestResultsPre_.size(), mouseHoverTestResults_.size());
999 }
1000
DispatchMouseEvent(const MouseEvent & event)1001 bool EventManager::DispatchMouseEvent(const MouseEvent& event)
1002 {
1003 if (event.action == MouseAction::PRESS || event.action == MouseAction::RELEASE ||
1004 event.action == MouseAction::MOVE) {
1005 for (const auto& wp : mouseHoverTestResults_) {
1006 auto hoverNode = wp.Upgrade();
1007 if (hoverNode) {
1008 if (hoverNode->HandleMouseEvent(event)) {
1009 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "Do HandleMouseEvent. Dispatch node: %{public}s",
1010 AceType::TypeName(hoverNode));
1011 break;
1012 }
1013 }
1014 }
1015 return true;
1016 }
1017 return false;
1018 }
1019
DispatchMouseHoverAnimation(const MouseEvent & event)1020 void EventManager::DispatchMouseHoverAnimation(const MouseEvent& event)
1021 {
1022 auto hoverNodeCur = mouseHoverNode_.Upgrade();
1023 auto hoverNodePre = mouseHoverNodePre_.Upgrade();
1024 if (event.action == MouseAction::PRESS) {
1025 if (hoverNodeCur) {
1026 hoverNodeCur->AnimateMouseHoverExit();
1027 }
1028 } else if (event.action == MouseAction::RELEASE) {
1029 if (hoverNodeCur) {
1030 hoverNodeCur->AnimateMouseHoverEnter();
1031 }
1032 } else if (event.button == MouseButton::NONE_BUTTON && event.action == MouseAction::MOVE) {
1033 if (hoverNodeCur != hoverNodePre) {
1034 if (hoverNodeCur) {
1035 hoverNodeCur->AnimateMouseHoverEnter();
1036 }
1037 if (hoverNodePre) {
1038 hoverNodePre->AnimateMouseHoverExit();
1039 }
1040 }
1041 } else if (event.action == MouseAction::WINDOW_ENTER) {
1042 if (hoverNodeCur) {
1043 hoverNodeCur->AnimateMouseHoverEnter();
1044 }
1045 } else if (event.action == MouseAction::WINDOW_LEAVE) {
1046 if (hoverNodeCur) {
1047 hoverNodeCur->AnimateMouseHoverExit();
1048 }
1049 }
1050 }
1051
DispatchMouseHoverEvent(const MouseEvent & event)1052 bool EventManager::DispatchMouseHoverEvent(const MouseEvent& event)
1053 {
1054 for (const auto& wp : mouseHoverTestResultsPre_) {
1055 // get all previous hover nodes while it's not in current hover nodes. Those nodes exit hover
1056 auto it = std::find(mouseHoverTestResults_.begin(), mouseHoverTestResults_.end(), wp);
1057 if (it == mouseHoverTestResults_.end()) {
1058 auto hoverNode = wp.Upgrade();
1059 if (hoverNode) {
1060 hoverNode->HandleMouseHoverEvent(MouseState::NONE);
1061 }
1062 }
1063 }
1064 for (const auto& wp : mouseHoverTestResults_) {
1065 // get all current hover nodes while it's not in previous hover nodes. Those nodes are new hover
1066 auto it = std::find(mouseHoverTestResultsPre_.begin(), mouseHoverTestResultsPre_.end(), wp);
1067 if (it == mouseHoverTestResultsPre_.end()) {
1068 auto hoverNode = wp.Upgrade();
1069 if (hoverNode) {
1070 hoverNode->HandleMouseHoverEvent(MouseState::HOVER);
1071 }
1072 }
1073 }
1074 return true;
1075 }
1076
LogPrintMouseTest()1077 void EventManager::LogPrintMouseTest()
1078 {
1079 if (!SystemProperties::GetDebugEnabled()) {
1080 return;
1081 }
1082 if (currMouseTestResults_.empty()) {
1083 TAG_LOGD(AceLogTag::ACE_MOUSE, "Mouse test onMouse result is empty.");
1084 } else {
1085 for (const auto& result : currMouseTestResults_) {
1086 TAG_LOGD(AceLogTag::ACE_MOUSE, "Mouse test onMouse result: %{public}s/"
1087 SEC_PLD(%{public}d) ".",
1088 result->GetNodeName().c_str(), SEC_PARAM(result->GetNodeId()));
1089 }
1090 }
1091 if (lastHoverTestResults_.empty()) {
1092 TAG_LOGD(AceLogTag::ACE_MOUSE, "Mouse test onHover last result is empty.");
1093 } else {
1094 for (const auto& result : lastHoverTestResults_) {
1095 TAG_LOGD(AceLogTag::ACE_MOUSE, "Mouse test onHover last result: %{public}s/"
1096 SEC_PLD(%{public}d) ".",
1097 result->GetNodeName().c_str(), SEC_PARAM(result->GetNodeId()));
1098 }
1099 }
1100 if (currHoverTestResults_.empty()) {
1101 TAG_LOGD(AceLogTag::ACE_MOUSE, "Mouse test onHover current result is empty.");
1102 } else {
1103 for (const auto& result : currHoverTestResults_) {
1104 TAG_LOGD(AceLogTag::ACE_MOUSE, "Mouse test onHover current result: %{public}s/"
1105 SEC_PLD(%{public}d) ".",
1106 result->GetNodeName().c_str(), SEC_PARAM(result->GetNodeId()));
1107 }
1108 }
1109 auto lastNode = lastHoverNode_.Upgrade();
1110 auto currNode = currHoverNode_.Upgrade();
1111 TAG_LOGD(AceLogTag::ACE_MOUSE,
1112 "Mouse test last/current hoverEffect node: %{public}s/%{public}d / %{public}s/%{public}d",
1113 lastNode ? lastNode->GetTag().c_str() : "NULL", lastNode ? lastNode->GetId() : -1,
1114 currNode ? currNode->GetTag().c_str() : "NULL", currNode ? currNode->GetId() : -1);
1115 }
1116
AccessibilityHoverTest(const TouchEvent & event,const RefPtr<NG::FrameNode> & frameNode,TouchRestrict & touchRestrict)1117 void EventManager::AccessibilityHoverTest(
1118 const TouchEvent& event, const RefPtr<NG::FrameNode>& frameNode, TouchRestrict& touchRestrict)
1119 {
1120 CHECK_NULL_VOID(frameNode);
1121 if (downFingerIds_.empty()) {
1122 FalsifyCancelEventAndDispatch(event);
1123 responseCtrl_->Reset();
1124 refereeNG_->CleanAll();
1125 touchTestResults_.clear();
1126 downFingerIds_.clear();
1127 }
1128 const NG::PointF point { event.x, event.y };
1129 TouchTestResult testResult;
1130 ResponseLinkResult responseLinkResult;
1131 frameNode->TouchTest(
1132 point, point, point, touchRestrict, testResult, event.id, responseLinkResult);
1133 SetResponseLinkRecognizers(testResult, responseLinkResult);
1134 UpdateAccessibilityHoverNode(event, testResult);
1135 }
1136
MouseTest(const MouseEvent & event,const RefPtr<NG::FrameNode> & frameNode,TouchRestrict & touchRestrict)1137 void EventManager::MouseTest(
1138 const MouseEvent& event, const RefPtr<NG::FrameNode>& frameNode, TouchRestrict& touchRestrict)
1139 {
1140 TAG_LOGD(AceLogTag::ACE_MOUSE,
1141 "Mouse test start. Event is (" SEC_PLD(%{public}f) "," SEC_PLD(%{public}f) "), "
1142 "button: %{public}d, action: %{public}d", SEC_PARAM(event.x), SEC_PARAM(event.y),
1143 event.button, event.action);
1144 CHECK_NULL_VOID(frameNode);
1145 const NG::PointF point { event.x, event.y };
1146 TouchTestResult testResult;
1147
1148 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1149 if (event.pullAction == MouseAction::PULL_MOVE) {
1150 UpdateHoverNode(event, testResult);
1151 LogPrintMouseTest();
1152 return;
1153 } else if ((event.action == MouseAction::MOVE && event.button != MouseButton::NONE_BUTTON)) {
1154 testResult = mouseTestResults_[event.GetPointerId(event.id)];
1155 } else {
1156 ResponseLinkResult responseLinkResult;
1157 if (event.action != MouseAction::MOVE) {
1158 touchRestrict.touchEvent.isMouseTouchTest = true;
1159 }
1160 frameNode->TouchTest(
1161 point, point, point, touchRestrict, testResult, event.GetPointerId(event.id), responseLinkResult);
1162 SetResponseLinkRecognizers(testResult, responseLinkResult);
1163 mouseTestResults_[event.GetPointerId(event.id)] = testResult;
1164 }
1165 } else {
1166 ResponseLinkResult responseLinkResult;
1167 if (event.action != MouseAction::MOVE) {
1168 touchRestrict.touchEvent.isMouseTouchTest = true;
1169 }
1170 frameNode->TouchTest(
1171 point, point, point, touchRestrict, testResult, event.GetPointerId(event.id), responseLinkResult);
1172 SetResponseLinkRecognizers(testResult, responseLinkResult);
1173 }
1174 UpdateHoverNode(event, testResult);
1175 LogPrintMouseTest();
1176 }
1177
UpdateAccessibilityHoverNode(const TouchEvent & event,const TouchTestResult & testResult)1178 void EventManager::UpdateAccessibilityHoverNode(const TouchEvent& event, const TouchTestResult& testResult)
1179 {
1180 HoverTestResult hoverTestResult;
1181 for (const auto& result : testResult) {
1182 auto hoverResult = AceType::DynamicCast<HoverEventTarget>(result);
1183 if (hoverResult && hoverResult->IsAccessibilityHoverTarget()) {
1184 hoverTestResult.emplace_back(hoverResult);
1185 }
1186 }
1187 if (event.type == TouchType::HOVER_EXIT) {
1188 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "Exit hover by HOVER_EXIT event.");
1189 lastAccessibilityHoverResults_ = std::move(curAccessibilityHoverResults_);
1190 curAccessibilityHoverResults_.clear();
1191 } else if (event.type == TouchType::HOVER_CANCEL) {
1192 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "Cancel hover by HOVER_CANCEL event.");
1193 lastAccessibilityHoverResults_ = std::move(curAccessibilityHoverResults_);
1194 curAccessibilityHoverResults_.clear();
1195 } else if (event.type == TouchType::HOVER_ENTER) {
1196 TAG_LOGI(AceLogTag::ACE_ACCESSIBILITY, "Enter hover by HOVER_ENTER event.");
1197 lastAccessibilityHoverResults_.clear();
1198 curAccessibilityHoverResults_ = std::move(hoverTestResult);
1199 } else {
1200 lastAccessibilityHoverResults_ = std::move(curAccessibilityHoverResults_);
1201 curAccessibilityHoverResults_ = std::move(hoverTestResult);
1202 }
1203 }
1204
UpdateHoverNode(const MouseEvent & event,const TouchTestResult & testResult)1205 void EventManager::UpdateHoverNode(const MouseEvent& event, const TouchTestResult& testResult)
1206 {
1207 currMouseTestResults_.clear();
1208 HoverTestResult hoverTestResult;
1209 WeakPtr<NG::FrameNode> hoverNode = nullptr;
1210 for (const auto& result : testResult) {
1211 auto mouseResult = AceType::DynamicCast<MouseEventTarget>(result);
1212 if (mouseResult) {
1213 currMouseTestResults_.emplace_back(mouseResult);
1214 }
1215 auto hoverResult = AceType::DynamicCast<HoverEventTarget>(result);
1216 if (hoverResult && hoverResult->IsHoverTarget()) {
1217 hoverTestResult.emplace_back(hoverResult);
1218 }
1219 if (!hoverNode.Upgrade()) {
1220 auto hoverEffectResult = AceType::DynamicCast<HoverEffectTarget>(result);
1221 if (hoverEffectResult) {
1222 hoverNode = hoverEffectResult->GetHoverNode();
1223 }
1224 }
1225 }
1226 if (event.action == MouseAction::WINDOW_LEAVE) {
1227 TAG_LOGI(AceLogTag::ACE_MOUSE, "Exit hover by leave-window event.");
1228 lastHoverTestResults_ = std::move(currHoverTestResults_);
1229 currHoverTestResults_.clear();
1230 } else if (event.action == MouseAction::WINDOW_ENTER) {
1231 TAG_LOGI(AceLogTag::ACE_MOUSE, "Enter hover by enter-window event.");
1232 lastHoverTestResults_.clear();
1233 currHoverTestResults_ = std::move(hoverTestResult);
1234 } else {
1235 lastHoverTestResults_ = std::move(currHoverTestResults_);
1236 currHoverTestResults_ = std::move(hoverTestResult);
1237 }
1238 lastHoverNode_ = currHoverNode_;
1239 currHoverNode_ = hoverNode;
1240 }
1241
DispatchMouseEventNG(const MouseEvent & event)1242 bool EventManager::DispatchMouseEventNG(const MouseEvent& event)
1243 {
1244 const static std::set<MouseAction> validAction = {
1245 MouseAction::PRESS,
1246 MouseAction::RELEASE,
1247 MouseAction::MOVE,
1248 MouseAction::WINDOW_ENTER,
1249 MouseAction::WINDOW_LEAVE
1250 };
1251 if (validAction.find(event.action) == validAction.end()) {
1252 return false;
1253 }
1254 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_THIRTEEN)) {
1255 return DispatchMouseEventInGreatOrEqualAPI13(event);
1256 }
1257 return DispatchMouseEventInLessAPI13(event);
1258 }
1259
DispatchMouseEventInGreatOrEqualAPI13(const MouseEvent & event)1260 bool EventManager::DispatchMouseEventInGreatOrEqualAPI13(const MouseEvent& event)
1261 {
1262 MouseTestResult handledResults;
1263 bool isStopPropagation = false;
1264 if (event.button != MouseButton::NONE_BUTTON) {
1265 if (auto mouseTargetIter = pressMouseTestResultsMap_.find(event.button);
1266 mouseTargetIter != pressMouseTestResultsMap_.end()) {
1267 DispatchMouseEventToPressResults(event, mouseTargetIter->second, handledResults, isStopPropagation);
1268 }
1269 if (event.action == MouseAction::PRESS) {
1270 pressMouseTestResultsMap_[event.button] = currMouseTestResults_;
1271 }
1272 }
1273 auto result = DispatchMouseEventToCurResults(event, handledResults, isStopPropagation);
1274 if (event.action == MouseAction::RELEASE) {
1275 DoSingleMouseActionRelease(event.button);
1276 }
1277 return result;
1278 }
1279
DispatchMouseEventInLessAPI13(const MouseEvent & event)1280 bool EventManager::DispatchMouseEventInLessAPI13(const MouseEvent& event)
1281 {
1282 MouseTestResult handledResults;
1283 bool isStopPropagation = false;
1284 if (event.button == MouseButton::LEFT_BUTTON) {
1285 DispatchMouseEventToPressResults(event, pressMouseTestResults_, handledResults, isStopPropagation);
1286 if (event.action == MouseAction::PRESS) {
1287 pressMouseTestResults_ = currMouseTestResults_;
1288 }
1289 }
1290 auto result = DispatchMouseEventToCurResultsInLessAPI13(event, handledResults, isStopPropagation);
1291 if (event.action == MouseAction::RELEASE) {
1292 DoMouseActionRelease();
1293 }
1294 return result;
1295 }
1296
DispatchMouseEventToPressResults(const MouseEvent & event,const MouseTestResult & targetResults,MouseTestResult & handledResults,bool & isStopPropagation)1297 void EventManager::DispatchMouseEventToPressResults(const MouseEvent& event, const MouseTestResult& targetResults,
1298 MouseTestResult& handledResults, bool& isStopPropagation)
1299 {
1300 for (const auto& mouseTarget : targetResults) {
1301 if (!mouseTarget) {
1302 continue;
1303 }
1304 handledResults.emplace_back(mouseTarget);
1305 if (mouseTarget->HandleMouseEvent(event)) {
1306 isStopPropagation = true;
1307 break;
1308 }
1309 }
1310 }
1311
DispatchMouseEventToCurResults(const MouseEvent & event,const MouseTestResult & handledResults,bool isStopPropagation)1312 bool EventManager::DispatchMouseEventToCurResults(
1313 const MouseEvent& event, const MouseTestResult& handledResults, bool isStopPropagation)
1314 {
1315 auto currMouseTestResults = currMouseTestResults_;
1316 for (const auto& mouseTarget : currMouseTestResults) {
1317 if (!mouseTarget) {
1318 continue;
1319 }
1320 if (!isStopPropagation) {
1321 auto ret = std::find(handledResults.begin(), handledResults.end(), mouseTarget) == handledResults.end();
1322 // if pressMouseTestResults doesn't have any isStopPropagation, use default handledResults.
1323 if (ret && mouseTarget->HandleMouseEvent(event)) {
1324 return true;
1325 }
1326 continue;
1327 }
1328 auto mouseTargetIter = pressMouseTestResultsMap_.find(event.button);
1329 if ((mouseTargetIter != pressMouseTestResultsMap_.end() &&
1330 std::find(mouseTargetIter->second.begin(), mouseTargetIter->second.end(), mouseTarget) ==
1331 mouseTargetIter->second.end()) || mouseTargetIter == pressMouseTestResultsMap_.end()) {
1332 // if pressMouseTestResults has isStopPropagation, use pressMouseTestResults as handledResults.
1333 if (mouseTarget->HandleMouseEvent(event)) {
1334 return true;
1335 }
1336 }
1337 }
1338 return false;
1339 }
1340
DispatchMouseEventToCurResultsInLessAPI13(const MouseEvent & event,const MouseTestResult & handledResults,bool isStopPropagation)1341 bool EventManager::DispatchMouseEventToCurResultsInLessAPI13(
1342 const MouseEvent& event, const MouseTestResult& handledResults, bool isStopPropagation)
1343 {
1344 auto currMouseTestResults = currMouseTestResults_;
1345 for (const auto& mouseTarget : currMouseTestResults) {
1346 if (!mouseTarget) {
1347 continue;
1348 }
1349 if (!isStopPropagation) {
1350 auto ret = std::find(handledResults.begin(), handledResults.end(), mouseTarget) == handledResults.end();
1351 // if pressMouseTestResults doesn't have any isStopPropagation, use default handledResults.
1352 if (ret && mouseTarget->HandleMouseEvent(event)) {
1353 return true;
1354 }
1355 continue;
1356 }
1357 if (std::find(pressMouseTestResults_.begin(), pressMouseTestResults_.end(), mouseTarget) ==
1358 pressMouseTestResults_.end()) {
1359 // if pressMouseTestResults has isStopPropagation, use pressMouseTestResults as handledResults.
1360 if (mouseTarget->HandleMouseEvent(event)) {
1361 return true;
1362 }
1363 }
1364 }
1365 return false;
1366 }
1367
DoMouseActionRelease()1368 void EventManager::DoMouseActionRelease()
1369 {
1370 pressMouseTestResults_.clear();
1371 }
1372
DoSingleMouseActionRelease(MouseButton button)1373 void EventManager::DoSingleMouseActionRelease(MouseButton button)
1374 {
1375 pressMouseTestResultsMap_.erase(button);
1376 }
1377
DispatchMouseHoverAnimationNG(const MouseEvent & event)1378 void EventManager::DispatchMouseHoverAnimationNG(const MouseEvent& event)
1379 {
1380 auto hoverNodeCur = currHoverNode_.Upgrade();
1381 auto hoverNodePre = lastHoverNode_.Upgrade();
1382 if (event.action == MouseAction::PRESS) {
1383 if (hoverNodeCur) {
1384 hoverNodeCur->AnimateHoverEffect(false);
1385 }
1386 } else if (event.action == MouseAction::RELEASE) {
1387 if (hoverNodeCur) {
1388 hoverNodeCur->AnimateHoverEffect(true);
1389 }
1390 } else if (event.button == MouseButton::NONE_BUTTON && event.action == MouseAction::MOVE) {
1391 if (hoverNodeCur != hoverNodePre) {
1392 if (hoverNodeCur) {
1393 hoverNodeCur->AnimateHoverEffect(true);
1394 }
1395 if (hoverNodePre) {
1396 hoverNodePre->AnimateHoverEffect(false);
1397 }
1398 }
1399 } else if (event.action == MouseAction::WINDOW_ENTER) {
1400 if (hoverNodeCur) {
1401 hoverNodeCur->AnimateHoverEffect(true);
1402 }
1403 } else if (event.action == MouseAction::WINDOW_LEAVE) {
1404 if (hoverNodeCur) {
1405 hoverNodeCur->AnimateHoverEffect(false);
1406 }
1407 }
1408 }
1409
DispatchMouseHoverEventNG(const MouseEvent & event)1410 bool EventManager::DispatchMouseHoverEventNG(const MouseEvent& event)
1411 {
1412 auto lastHoverEndNode = lastHoverTestResults_.begin();
1413 auto currHoverEndNode = currHoverTestResults_.begin();
1414 RefPtr<HoverEventTarget> lastHoverEndNodeTarget;
1415 uint32_t iterCountLast = 0;
1416 uint32_t iterCountCurr = 0;
1417 for (const auto& hoverResult : lastHoverTestResults_) {
1418 // get valid part of previous hover nodes while it's not in current hover nodes. Those nodes exit hover
1419 // there may have some nodes in currHoverTestResults_ but intercepted
1420 iterCountLast++;
1421 if (lastHoverEndNode != currHoverTestResults_.end()) {
1422 lastHoverEndNode++;
1423 }
1424 if (std::find(currHoverTestResults_.begin(), currHoverTestResults_.end(), hoverResult) ==
1425 currHoverTestResults_.end()) {
1426 hoverResult->HandleHoverEvent(false, event);
1427 }
1428 if ((iterCountLast >= lastHoverDispatchLength_) && (lastHoverDispatchLength_ != 0)) {
1429 lastHoverEndNodeTarget = hoverResult;
1430 break;
1431 }
1432 }
1433 lastHoverDispatchLength_ = 0;
1434 for (const auto& hoverResult : currHoverTestResults_) {
1435 // get valid part of current hover nodes while it's not in previous hover nodes. Those nodes are new hover
1436 // the valid part stops at first interception
1437 iterCountCurr++;
1438 if (currHoverEndNode != currHoverTestResults_.end()) {
1439 currHoverEndNode++;
1440 }
1441 if (std::find(lastHoverTestResults_.begin(), lastHoverEndNode, hoverResult) == lastHoverEndNode) {
1442 if (!hoverResult->HandleHoverEvent(true, event)) {
1443 lastHoverDispatchLength_ = iterCountCurr;
1444 break;
1445 }
1446 }
1447 if (hoverResult == lastHoverEndNodeTarget) {
1448 lastHoverDispatchLength_ = iterCountCurr;
1449 break;
1450 }
1451 }
1452 for (auto hoverResultIt = lastHoverTestResults_.begin(); hoverResultIt != lastHoverEndNode; ++hoverResultIt) {
1453 // there may have previous hover nodes in the invalid part of current hover nodes. Those nodes exit hover also
1454 if (std::find(currHoverEndNode, currHoverTestResults_.end(), *hoverResultIt) != currHoverTestResults_.end()) {
1455 (*hoverResultIt)->HandleHoverEvent(false, event);
1456 }
1457 }
1458 return true;
1459 }
1460
DispatchAccessibilityHoverEventNG(const TouchEvent & event)1461 void EventManager::DispatchAccessibilityHoverEventNG(const TouchEvent& event)
1462 {
1463 auto lastHoverEndNode = lastAccessibilityHoverResults_.begin();
1464 auto currHoverEndNode = curAccessibilityHoverResults_.begin();
1465 RefPtr<HoverEventTarget> lastHoverEndNodeTarget;
1466 uint32_t iterCountLast = 0;
1467 uint32_t iterCountCurr = 0;
1468 for (const auto& hoverResult : lastAccessibilityHoverResults_) {
1469 // get valid part of previous hover nodes while it's not in current hover nodes. Those nodes exit hover
1470 // there may have some nodes in curAccessibilityHoverResults_ but intercepted
1471 iterCountLast++;
1472 if (lastHoverEndNode != curAccessibilityHoverResults_.end()) {
1473 lastHoverEndNode++;
1474 }
1475 if (std::find(curAccessibilityHoverResults_.begin(), curAccessibilityHoverResults_.end(), hoverResult) ==
1476 curAccessibilityHoverResults_.end()) {
1477 hoverResult->HandleAccessibilityHoverEvent(false, event);
1478 }
1479 if ((iterCountLast >= lastAccessibilityHoverDispatchLength_) && (lastAccessibilityHoverDispatchLength_ != 0)) {
1480 lastHoverEndNodeTarget = hoverResult;
1481 break;
1482 }
1483 }
1484 lastAccessibilityHoverDispatchLength_ = 0;
1485 for (const auto& hoverResult : curAccessibilityHoverResults_) {
1486 // get valid part of current hover nodes while it's not in previous hover nodes. Those nodes are new hover
1487 // the valid part stops at first interception
1488 iterCountCurr++;
1489 if (currHoverEndNode != curAccessibilityHoverResults_.end()) {
1490 currHoverEndNode++;
1491 }
1492 if (std::find(lastAccessibilityHoverResults_.begin(), lastHoverEndNode, hoverResult) == lastHoverEndNode) {
1493 hoverResult->HandleAccessibilityHoverEvent(true, event);
1494 }
1495 if (hoverResult == lastHoverEndNodeTarget) {
1496 lastAccessibilityHoverDispatchLength_ = iterCountCurr;
1497 break;
1498 }
1499 }
1500 for (auto hoverResultIt = lastAccessibilityHoverResults_.begin(); hoverResultIt != lastHoverEndNode;
1501 ++hoverResultIt) {
1502 // there may have previous hover nodes in the invalid part of current hover nodes. Those nodes exit hover also
1503 if (std::find(currHoverEndNode, curAccessibilityHoverResults_.end(), *hoverResultIt) !=
1504 curAccessibilityHoverResults_.end()) {
1505 (*hoverResultIt)->HandleAccessibilityHoverEvent(false, event);
1506 }
1507 }
1508 }
1509
AxisTest(const AxisEvent & event,const RefPtr<RenderNode> & renderNode)1510 void EventManager::AxisTest(const AxisEvent& event, const RefPtr<RenderNode>& renderNode)
1511 {
1512 CHECK_NULL_VOID(renderNode);
1513 const Point point { event.x, event.y };
1514 WeakPtr<RenderNode> axisNode = nullptr;
1515 renderNode->AxisDetect(point, point, axisNode, event.GetDirection());
1516 axisNode_ = axisNode;
1517 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING, "Current axis node is %{public}s", AceType::TypeName(axisNode_.Upgrade()));
1518 }
1519
DispatchAxisEvent(const AxisEvent & event)1520 bool EventManager::DispatchAxisEvent(const AxisEvent& event)
1521 {
1522 auto responseNode = axisNode_.Upgrade();
1523 if (responseNode) {
1524 responseNode->HandleAxisEvent(event);
1525 }
1526 return true;
1527 }
1528
AxisTest(const AxisEvent & event,const RefPtr<NG::FrameNode> & frameNode)1529 void EventManager::AxisTest(const AxisEvent& event, const RefPtr<NG::FrameNode>& frameNode)
1530 {
1531 CHECK_NULL_VOID(frameNode);
1532 const NG::PointF point { event.x, event.y };
1533 TouchRestrict touchRestrict { TouchRestrict::NONE };
1534 touchRestrict.sourceType = event.sourceType;
1535 touchRestrict.hitTestType = SourceType::MOUSE;
1536 touchRestrict.inputEventType = InputEventType::AXIS;
1537 touchRestrict.touchEvent = ConvertAxisEventToTouchEvent(event);
1538 frameNode->AxisTest(point, point, point, touchRestrict, axisTestResults_);
1539 }
1540
DispatchAxisEventNG(const AxisEvent & event)1541 bool EventManager::DispatchAxisEventNG(const AxisEvent& event)
1542 {
1543 // when api >= 15, do not block this event.
1544 if (!AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_FIFTEEN)) {
1545 if (event.horizontalAxis == 0 && event.verticalAxis == 0 && event.pinchAxisScale == 0 &&
1546 !event.isRotationEvent) {
1547 axisTestResults_.clear();
1548 return false;
1549 }
1550 }
1551 for (const auto& axisTarget : axisTestResults_) {
1552 if (axisTarget && axisTarget->HandleAxisEvent(event)) {
1553 axisTestResults_.clear();
1554 return true;
1555 }
1556 }
1557 axisTestResults_.clear();
1558 return true;
1559 }
1560
DispatchRotationEvent(const RotationEvent & event,const RefPtr<RenderNode> & renderNode,const RefPtr<RenderNode> & requestFocusNode)1561 bool EventManager::DispatchRotationEvent(
1562 const RotationEvent& event, const RefPtr<RenderNode>& renderNode, const RefPtr<RenderNode>& requestFocusNode)
1563 {
1564 CHECK_NULL_RETURN(renderNode, false);
1565 if (requestFocusNode && renderNode->RotationMatchTest(requestFocusNode)) {
1566 return requestFocusNode->RotationTestForward(event);
1567 } else {
1568 return renderNode->RotationTest(event);
1569 }
1570 }
1571
ClearResults()1572 void EventManager::ClearResults()
1573 {
1574 touchTestResults_.clear();
1575 postEventTouchTestResults_.clear();
1576 mouseTestResults_.clear();
1577 axisTouchTestResults_.clear();
1578 }
1579
EventManager()1580 EventManager::EventManager()
1581 {
1582 refereeNG_ = AceType::MakeRefPtr<NG::GestureReferee>();
1583 postEventRefereeNG_ = AceType::MakeRefPtr<NG::GestureReferee>();
1584 referee_ = AceType::MakeRefPtr<GestureReferee>();
1585 responseCtrl_ = AceType::MakeRefPtr<NG::ResponseCtrl>();
1586 mouseStyleManager_ = AceType::MakeRefPtr<MouseStyleManager>();
1587
1588 auto callback = [weak = WeakClaim(this)](size_t touchId) -> bool {
1589 auto eventManager = weak.Upgrade();
1590 CHECK_NULL_RETURN(eventManager, false);
1591 auto refereeNG = eventManager->refereeNG_;
1592 CHECK_NULL_RETURN(refereeNG, false);
1593 return refereeNG->HasGestureAccepted(touchId);
1594 };
1595 referee_->SetQueryStateFunc(std::move(callback));
1596
1597 auto cleanReferee = [weak = WeakClaim(this)](size_t touchId) -> void {
1598 auto eventManager = weak.Upgrade();
1599 CHECK_NULL_VOID(eventManager);
1600 auto referee = eventManager->referee_;
1601 CHECK_NULL_VOID(referee);
1602 auto gestureScope = referee->GetGestureScope();
1603 const auto iter = gestureScope.find(touchId);
1604 if (iter == gestureScope.end()) {
1605 return;
1606 }
1607
1608 auto highRecognizers = iter->second.GetHighRecognizers();
1609 auto lowRecognizers = iter->second.GetLowRecognizers();
1610 auto parallelRecognizers = iter->second.GetParallelRecognizers();
1611
1612 for (const auto& weak : highRecognizers) {
1613 auto gesture = weak.Upgrade();
1614 if (gesture) {
1615 gesture->OnRejected(touchId);
1616 }
1617 }
1618
1619 for (const auto& weak : lowRecognizers) {
1620 auto gesture = weak.Upgrade();
1621 if (gesture) {
1622 gesture->OnRejected(touchId);
1623 }
1624 }
1625
1626 for (const auto& weak : parallelRecognizers) {
1627 auto gesture = weak.Upgrade();
1628 if (gesture) {
1629 gesture->OnRejected(touchId);
1630 }
1631 }
1632 };
1633 refereeNG_->SetQueryStateFunc(std::move(cleanReferee));
1634 }
1635
DumpEvent(NG::EventTreeType type)1636 void EventManager::DumpEvent(NG::EventTreeType type)
1637 {
1638 auto& eventTree = GetEventTreeRecord(type);
1639 std::list<std::pair<int32_t, std::string>> dumpList;
1640 eventTree.Dump(dumpList, 0);
1641 for (auto& item : dumpList) {
1642 DumpLog::GetInstance().Print(item.first, item.second);
1643 }
1644 }
1645
AddGestureSnapshot(int32_t finger,int32_t depth,const RefPtr<TouchEventTarget> & target,NG::EventTreeType type)1646 void EventManager::AddGestureSnapshot(
1647 int32_t finger, int32_t depth, const RefPtr<TouchEventTarget>& target, NG::EventTreeType type)
1648 {
1649 if (!target) {
1650 return;
1651 }
1652 RefPtr<GestureSnapshot> info = target->Dump();
1653 auto frameNode = target->GetAttachedNode().Upgrade();
1654 if (frameNode) {
1655 info->nodeId = frameNode->GetId();
1656 }
1657 info->depth = depth;
1658 auto& eventTree = GetEventTreeRecord(type);
1659 eventTree.AddGestureSnapshot(finger, std::move(info));
1660
1661 // add child gesture if target is group
1662 auto group = AceType::DynamicCast<NG::RecognizerGroup>(target);
1663 if (group) {
1664 for (const auto& child : group->GetGroupRecognizer()) {
1665 AddGestureSnapshot(finger, depth + 1, child, type);
1666 }
1667 }
1668 }
1669
SetHittedFrameNode(const std::list<RefPtr<NG::NGGestureRecognizer>> & touchTestResults)1670 void EventManager::SetHittedFrameNode(const std::list<RefPtr<NG::NGGestureRecognizer>>& touchTestResults)
1671 {
1672 if (touchTestResults.empty()) {
1673 return;
1674 }
1675 for (const auto& item : touchTestResults) {
1676 auto node = item->GetAttachedNode().Upgrade();
1677 if (node) {
1678 hittedFrameNode_.emplace(node);
1679 }
1680 auto group = AceType::DynamicCast<NG::RecognizerGroup>(item);
1681 if (group) {
1682 auto groupRecognizers = group->GetGroupRecognizer();
1683 SetHittedFrameNode(groupRecognizers);
1684 }
1685 }
1686 }
1687
CleanGestureEventHub()1688 void EventManager::CleanGestureEventHub()
1689 {
1690 for (const auto& item : hittedFrameNode_) {
1691 auto frameNode = item.Upgrade();
1692 if (frameNode) {
1693 auto gestureEventHub = frameNode->GetOrCreateGestureEventHub();
1694 if (gestureEventHub) {
1695 gestureEventHub->CleanExternalRecognizers();
1696 gestureEventHub->CleanInnerRecognizer();
1697 gestureEventHub->CleanNodeRecognizer();
1698 }
1699 }
1700 }
1701 hittedFrameNode_.clear();
1702 }
1703
CheckAndLogLastReceivedTouchEventInfo(int32_t eventId,TouchType type)1704 void EventManager::CheckAndLogLastReceivedTouchEventInfo(int32_t eventId, TouchType type)
1705 {
1706 CheckAndLogLastReceivedEventInfo(
1707 eventId, type == TouchType::DOWN || type == TouchType::UP || type == TouchType::CANCEL);
1708 }
1709
CheckAndLogLastConsumedTouchEventInfo(int32_t eventId,TouchType type)1710 void EventManager::CheckAndLogLastConsumedTouchEventInfo(int32_t eventId, TouchType type)
1711 {
1712 CheckAndLogLastConsumedEventInfo(
1713 eventId, type == TouchType::DOWN || type == TouchType::UP || type == TouchType::CANCEL);
1714 }
1715
CheckAndLogLastReceivedMouseEventInfo(int32_t eventId,MouseAction action)1716 void EventManager::CheckAndLogLastReceivedMouseEventInfo(int32_t eventId, MouseAction action)
1717 {
1718 CheckAndLogLastReceivedEventInfo(eventId, action == MouseAction::PRESS || action == MouseAction::RELEASE);
1719 }
1720
CheckAndLogLastConsumedMouseEventInfo(int32_t eventId,MouseAction action)1721 void EventManager::CheckAndLogLastConsumedMouseEventInfo(int32_t eventId, MouseAction action)
1722 {
1723 CheckAndLogLastConsumedEventInfo(eventId, action == MouseAction::PRESS || action == MouseAction::RELEASE);
1724 }
1725
CheckAndLogLastReceivedAxisEventInfo(int32_t eventId,AxisAction action)1726 void EventManager::CheckAndLogLastReceivedAxisEventInfo(int32_t eventId, AxisAction action)
1727 {
1728 CheckAndLogLastReceivedEventInfo(
1729 eventId, action == AxisAction::BEGIN || action == AxisAction::END || action == AxisAction::CANCEL);
1730 }
1731
CheckAndLogLastConsumedAxisEventInfo(int32_t eventId,AxisAction action)1732 void EventManager::CheckAndLogLastConsumedAxisEventInfo(int32_t eventId, AxisAction action)
1733 {
1734 CheckAndLogLastConsumedEventInfo(
1735 eventId, action == AxisAction::BEGIN || action == AxisAction::END || action == AxisAction::CANCEL);
1736 }
1737
CheckAndLogLastReceivedEventInfo(int32_t eventId,bool logImmediately)1738 void EventManager::CheckAndLogLastReceivedEventInfo(int32_t eventId, bool logImmediately)
1739 {
1740 if (logImmediately) {
1741 if (SystemProperties::GetDebugEnabled()) {
1742 TAG_LOGD(AceLogTag::ACE_INPUTKEYFLOW,
1743 "Received new event id=%{public}d in ace_container, lastEventInfo: id:%{public}d", eventId,
1744 lastReceivedEvent_.eventId);
1745 }
1746 return;
1747 }
1748 auto currentTime = GetSysTimestamp();
1749 auto lastLogTimeStamp = lastReceivedEvent_.lastLogTimeStamp;
1750 if (lastReceivedEvent_.lastLogTimeStamp != 0 &&
1751 (currentTime - lastReceivedEvent_.lastLogTimeStamp) > EVENT_CLEAR_DURATION * TRANSLATE_NS_TO_MS) {
1752 if (SystemProperties::GetDebugEnabled()) {
1753 TAG_LOGD(AceLogTag::ACE_INPUTKEYFLOW,
1754 "Received new event id=%{public}d has been more than a second since the last one event "
1755 "received "
1756 "in ace_container, lastEventInfo: id:%{public}d",
1757 eventId, lastReceivedEvent_.eventId);
1758 }
1759 lastLogTimeStamp = currentTime;
1760 }
1761 lastReceivedEvent_ = { eventId, lastLogTimeStamp };
1762 }
1763
CheckAndLogLastConsumedEventInfo(int32_t eventId,bool logImmediately)1764 void EventManager::CheckAndLogLastConsumedEventInfo(int32_t eventId, bool logImmediately)
1765 {
1766 if (logImmediately) {
1767 TAG_LOGI(AceLogTag::ACE_INPUTTRACKING,
1768 "Consumed new event id=%{public}d in ace_container, lastEventInfo: id:%{public}d", eventId,
1769 lastConsumedEvent_.eventId);
1770 return;
1771 }
1772 auto currentTime = GetSysTimestamp();
1773 auto lastLogTimeStamp = lastConsumedEvent_.lastLogTimeStamp;
1774 if (lastConsumedEvent_.lastLogTimeStamp != 0 &&
1775 (currentTime - lastConsumedEvent_.lastLogTimeStamp) > EVENT_CLEAR_DURATION * TRANSLATE_NS_TO_MS) {
1776 TAG_LOGW(AceLogTag::ACE_INPUTTRACKING,
1777 "Consumed new event id=%{public}d has been more than a second since the last one event "
1778 "markProcessed "
1779 "in ace_container, lastEventInfo: id:%{public}d",
1780 eventId, lastConsumedEvent_.eventId);
1781 lastLogTimeStamp = currentTime;
1782 }
1783 lastConsumedEvent_ = { eventId, lastLogTimeStamp };
1784 }
1785
SetResponseLinkRecognizers(const TouchTestResult & result,const ResponseLinkResult & responseLinkRecognizers)1786 void EventManager::SetResponseLinkRecognizers(
1787 const TouchTestResult& result, const ResponseLinkResult& responseLinkRecognizers)
1788 {
1789 for (const auto& item : result) {
1790 auto group = AceType::DynamicCast<NG::RecognizerGroup>(item);
1791 if (group) {
1792 group->SetResponseLinkRecognizersRecursively(responseLinkRecognizers);
1793 continue;
1794 }
1795 auto recognizer = AceType::DynamicCast<NG::NGGestureRecognizer>(item);
1796 if (recognizer) {
1797 recognizer->SetResponseLinkRecognizers(responseLinkRecognizers);
1798 }
1799 }
1800 }
1801
FalsifyCancelEventAndDispatch(const TouchEvent & touchPoint)1802 void EventManager::FalsifyCancelEventAndDispatch(const TouchEvent& touchPoint)
1803 {
1804 TouchEvent falsifyEvent = touchPoint;
1805 falsifyEvent.isFalsified = true;
1806 falsifyEvent.type = TouchType::CANCEL;
1807 falsifyEvent.sourceType = SourceType::TOUCH;
1808 falsifyEvent.isInterpolated = true;
1809 auto downFingerIds = downFingerIds_;
1810 for (const auto& iter : downFingerIds) {
1811 falsifyEvent.id = iter.first;
1812 falsifyEvent.pointers = lastTouchEvent_.pointers;
1813 if (touchPoint.id != iter.first) {
1814 falsifyEvent.history.clear();
1815 }
1816 falsifyEvent.originalId = iter.second;
1817 DispatchTouchEvent(falsifyEvent);
1818 }
1819 }
1820
FalsifyCancelEventAndDispatch(const AxisEvent & axisEvent)1821 void EventManager::FalsifyCancelEventAndDispatch(const AxisEvent& axisEvent)
1822 {
1823 if (axisTouchTestResults_.empty()) {
1824 return;
1825 }
1826 AxisEvent falsifyEvent = axisEvent;
1827 falsifyEvent.action = AxisAction::CANCEL;
1828 falsifyEvent.id = static_cast<int32_t>(axisTouchTestResults_.begin()->first);
1829 DispatchTouchEvent(falsifyEvent);
1830 }
1831 #if defined(SUPPORT_TOUCH_TARGET_TEST)
1832
TouchTargetHitTest(const TouchEvent & touchPoint,const RefPtr<NG::FrameNode> & frameNode,TouchRestrict & touchRestrict,const Offset & offset,float viewScale,bool needAppend,const std::string & target)1833 bool EventManager::TouchTargetHitTest(const TouchEvent& touchPoint, const RefPtr<NG::FrameNode>& frameNode,
1834 TouchRestrict& touchRestrict, const Offset& offset, float viewScale, bool needAppend, const std::string& target)
1835 {
1836 CHECK_NULL_RETURN(frameNode, false);
1837 TouchTestResult hitTestResult;
1838 ResponseLinkResult responseLinkResult;
1839 const NG::PointF point { touchPoint.x, touchPoint.y };
1840 frameNode->TouchTest(point, point, point, touchRestrict, hitTestResult, touchPoint.id, responseLinkResult);
1841 for (const auto& entry : hitTestResult) {
1842 if (entry) {
1843 auto frameNodeInfo = entry->GetAttachedNode().Upgrade();
1844 if (frameNodeInfo && frameNodeInfo->GetTag().compare(target) == 0) {
1845 return true;
1846 }
1847 }
1848 }
1849 return false;
1850 }
1851 #endif
1852
FalsifyHoverCancelEventAndDispatch(const TouchEvent & touchPoint)1853 void EventManager::FalsifyHoverCancelEventAndDispatch(const TouchEvent& touchPoint)
1854 {
1855 lastAccessibilityHoverResults_ = std::move(curAccessibilityHoverResults_);
1856 curAccessibilityHoverResults_.clear();
1857 TouchEvent falsifyEvent = touchPoint;
1858 falsifyEvent.isFalsified = true;
1859 falsifyEvent.type = TouchType::HOVER_CANCEL;
1860 DispatchAccessibilityHoverEventNG(falsifyEvent);
1861 }
1862
GetResampleTouchEvent(const std::vector<TouchEvent> & history,const std::vector<TouchEvent> & current,uint64_t nanoTimeStamp,TouchEvent & newTouchEvent)1863 bool EventManager::GetResampleTouchEvent(const std::vector<TouchEvent>& history,
1864 const std::vector<TouchEvent>& current, uint64_t nanoTimeStamp, TouchEvent& newTouchEvent)
1865 {
1866 auto newXy = ResampleAlgo::GetResampleCoord(std::vector<PointerEvent>(history.begin(), history.end()),
1867 std::vector<PointerEvent>(current.begin(), current.end()), nanoTimeStamp, false);
1868 auto newScreenXy = ResampleAlgo::GetResampleCoord(std::vector<PointerEvent>(history.begin(), history.end()),
1869 std::vector<PointerEvent>(current.begin(), current.end()), nanoTimeStamp, true);
1870 newTouchEvent = GetLatestPoint(current, nanoTimeStamp);
1871 bool ret = false;
1872 if (newXy.x != 0 && newXy.y != 0) {
1873 newTouchEvent.x = newXy.x;
1874 newTouchEvent.y = newXy.y;
1875 newTouchEvent.screenX = newScreenXy.x;
1876 newTouchEvent.screenY = newScreenXy.y;
1877 std::chrono::nanoseconds nanoseconds(nanoTimeStamp);
1878 newTouchEvent.time = TimeStamp(nanoseconds);
1879 newTouchEvent.history = current;
1880 newTouchEvent.isInterpolated = true;
1881 newTouchEvent.inputXDeltaSlope = newXy.inputXDeltaSlope;
1882 newTouchEvent.inputYDeltaSlope = newXy.inputYDeltaSlope;
1883 ret = true;
1884 }
1885 if (SystemProperties::GetDebugEnabled()) {
1886 TAG_LOGD(AceLogTag::ACE_UIEVENT,
1887 "Touch Interpolate point is %{public}d, %{public}f, %{public}f, %{public}f, %{public}f, %{public}"
1888 PRIu64 "", newTouchEvent.id, newTouchEvent.x, newTouchEvent.y,
1889 newTouchEvent.screenX, newTouchEvent.screenY,
1890 static_cast<uint64_t>(newTouchEvent.time.time_since_epoch().count()));
1891 }
1892 return ret;
1893 }
1894
GetLatestPoint(const std::vector<TouchEvent> & current,uint64_t nanoTimeStamp)1895 TouchEvent EventManager::GetLatestPoint(const std::vector<TouchEvent>& current, uint64_t nanoTimeStamp)
1896 {
1897 TouchEvent result;
1898 uint64_t gap = UINT64_MAX;
1899 for (auto iter = current.begin(); iter != current.end(); iter++) {
1900 uint64_t timeStamp = static_cast<uint64_t>(iter->time.time_since_epoch().count());
1901 if (timeStamp == nanoTimeStamp) {
1902 result = *iter;
1903 return result;
1904 } else if (timeStamp > nanoTimeStamp) {
1905 if (timeStamp - nanoTimeStamp < gap) {
1906 gap = timeStamp - nanoTimeStamp;
1907 result = *iter;
1908 }
1909 } else {
1910 if (nanoTimeStamp - timeStamp < gap) {
1911 gap = nanoTimeStamp - timeStamp;
1912 result = *iter;
1913 }
1914 }
1915 }
1916 return result;
1917 }
1918
OnNonPointerEvent(const NonPointerEvent & event)1919 bool EventManager::OnNonPointerEvent(const NonPointerEvent& event)
1920 {
1921 if (event.eventType == UIInputEventType::KEY) {
1922 return OnKeyEvent(static_cast<const KeyEvent&>(event));
1923 }
1924 if (event.eventType == UIInputEventType::FOCUS_AXIS) {
1925 return OnFocusAxisEvent(static_cast<const NG::FocusAxisEvent&>(event));
1926 }
1927 return false;
1928 }
1929 } // namespace OHOS::Ace
1930