1 /*
2 * Copyright (c) 2021-2022 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/geometry/ng/point_t.h"
19 #include "base/log/ace_trace.h"
20 #include "base/memory/ace_type.h"
21 #include "base/utils/utils.h"
22 #include "core/common/container.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/event/ace_events.h"
25 #include "core/event/key_event.h"
26 #include "core/event/touch_event.h"
27 #include "core/gestures/gesture_referee.h"
28 #include "core/pipeline/base/element.h"
29 #include "core/pipeline/base/render_node.h"
30
31 namespace OHOS::Ace {
32
TouchTest(const TouchEvent & touchPoint,const RefPtr<RenderNode> & renderNode,const TouchRestrict & touchRestrict,const Offset & offset,float viewScale,bool needAppend)33 void EventManager::TouchTest(const TouchEvent& touchPoint, const RefPtr<RenderNode>& renderNode,
34 const TouchRestrict& touchRestrict, const Offset& offset, float viewScale, bool needAppend)
35 {
36 ContainerScope scope(instanceId_);
37
38 ACE_FUNCTION_TRACE();
39 CHECK_NULL_VOID(renderNode);
40 // first clean.
41 referee_->CleanGestureScope(touchPoint.id);
42 // collect
43 TouchTestResult hitTestResult;
44 const Point point { touchPoint.x, touchPoint.y, touchPoint.sourceType };
45 // For root node, the parent local point is the same as global point.
46 renderNode->TouchTest(point, point, touchRestrict, hitTestResult);
47 if (needAppend) {
48 #ifdef OHOS_STANDARD_SYSTEM
49 for (auto entry = hitTestResult.begin(); entry != hitTestResult.end(); ++entry) {
50 if ((*entry)) {
51 (*entry)->SetSubPipelineGlobalOffset(offset, viewScale);
52 }
53 }
54 #endif
55 TouchTestResult prevHitTestResult = touchTestResults_[touchPoint.id];
56 hitTestResult.splice(hitTestResult.end(), prevHitTestResult);
57 }
58 touchTestResults_[touchPoint.id] = std::move(hitTestResult);
59 }
60
TouchTest(const TouchEvent & touchPoint,const RefPtr<NG::FrameNode> & frameNode,const TouchRestrict & touchRestrict,const Offset & offset,float viewScale,bool needAppend)61 void EventManager::TouchTest(const TouchEvent& touchPoint, const RefPtr<NG::FrameNode>& frameNode,
62 const TouchRestrict& touchRestrict, const Offset& offset, float viewScale, bool needAppend)
63 {
64 ContainerScope scope(instanceId_);
65
66 ACE_FUNCTION_TRACE();
67 CHECK_NULL_VOID(frameNode);
68 // collect
69 TouchTestResult hitTestResult;
70 const NG::PointF point { touchPoint.x, touchPoint.y };
71 if (refereeNG_->QueryAllDone(touchPoint.id)) {
72 refereeNG_->CleanGestureScope(touchPoint.id);
73 }
74 // For root node, the parent local point is the same as global point.
75 frameNode->TouchTest(point, point, touchRestrict, hitTestResult, touchPoint.id);
76 if (needAppend) {
77 #ifdef OHOS_STANDARD_SYSTEM
78 for (const auto& entry : hitTestResult) {
79 if (entry) {
80 entry->SetSubPipelineGlobalOffset(offset, viewScale);
81 }
82 }
83 #endif
84 TouchTestResult prevHitTestResult = touchTestResults_[touchPoint.id];
85 hitTestResult.splice(hitTestResult.end(), prevHitTestResult);
86 }
87 touchTestResults_[touchPoint.id] = std::move(hitTestResult);
88 }
89
TouchTest(const AxisEvent & event,const RefPtr<NG::FrameNode> & frameNode,const TouchRestrict & touchRestrict)90 void EventManager::TouchTest(
91 const AxisEvent& event, const RefPtr<NG::FrameNode>& frameNode, const TouchRestrict& touchRestrict)
92 {
93 ContainerScope scope(instanceId_);
94
95 ACE_FUNCTION_TRACE();
96 CHECK_NULL_VOID(frameNode);
97 // collect
98 const NG::PointF point { event.x, event.y };
99 // For root node, the parent local point is the same as global point.
100 frameNode->TouchTest(point, point, touchRestrict, axisTouchTestResult_, event.id);
101 }
102
HandleGlobalEvent(const TouchEvent & touchPoint,const RefPtr<TextOverlayManager> & textOverlayManager)103 void EventManager::HandleGlobalEvent(const TouchEvent& touchPoint, const RefPtr<TextOverlayManager>& textOverlayManager)
104 {
105 if (touchPoint.type != TouchType::DOWN) {
106 return;
107 }
108 auto coordinateOffset = textOverlayManager->GetCoordinateOffset();
109 const Point point { touchPoint.x - coordinateOffset.GetX(), touchPoint.y - coordinateOffset.GetY(),
110 touchPoint.sourceType };
111 CHECK_NULL_VOID_NOLOG(textOverlayManager);
112 auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
113 CHECK_NULL_VOID_NOLOG(textOverlayBase);
114 auto targetNode = textOverlayManager->GetTargetNode();
115 CHECK_NULL_VOID_NOLOG(targetNode);
116 for (auto& rect : textOverlayManager->GetTextOverlayRect()) {
117 if (rect.IsInRegion(point)) {
118 inSelectedRect_ = true;
119 }
120 }
121 for (auto& rect : textOverlayBase->GetSelectedRect()) {
122 if (rect.IsInRegion(point)) {
123 inSelectedRect_ = true;
124 }
125 }
126 if (!inSelectedRect_) {
127 textOverlayManager->PopTextOverlay();
128 textOverlayBase->ChangeSelection(0, 0);
129 textOverlayBase->MarkIsOverlayShowed(false);
130 targetNode->MarkNeedRender();
131 }
132 inSelectedRect_ = false;
133 }
134
HandleOutOfRectCallback(const Point & point,std::vector<RectCallback> & rectCallbackList)135 void EventManager::HandleOutOfRectCallback(const Point& point, std::vector<RectCallback>& rectCallbackList)
136 {
137 for (auto iter = rectCallbackList.begin(); iter != rectCallbackList.end();) {
138 auto rectCallback = *iter;
139 auto rectGetCallback = rectCallback.rectGetCallback;
140 if (!rectGetCallback) {
141 ++iter;
142 continue;
143 }
144 std::vector<Rect> rectList;
145 rectGetCallback(rectList);
146 if (std::any_of(
147 rectList.begin(), rectList.end(), [point](const Rect& rect) { return rect.IsInRegion(point); })) {
148 ++iter;
149 continue;
150 }
151 for (const auto& rect : rectList) {
152 LOGI("Point(%{public}f, %{public}f) out of Rect-[%{public}f, %{public}f, %{public}f, %{public}f]",
153 point.GetX(), point.GetY(), rect.Left(), rect.Right(), rect.Top(), rect.Bottom());
154 }
155 if (point.GetSourceType() == SourceType::TOUCH) {
156 if (!rectCallback.touchCallback) {
157 ++iter;
158 continue;
159 }
160 rectCallback.touchCallback();
161 } else if (point.GetSourceType() == SourceType::MOUSE) {
162 if (!rectCallback.mouseCallback) {
163 ++iter;
164 continue;
165 }
166 rectCallback.mouseCallback();
167 }
168 iter = rectCallbackList.erase(iter);
169 }
170 }
171
TouchTest(const AxisEvent & event,const RefPtr<RenderNode> & renderNode,const TouchRestrict & touchRestrict)172 void EventManager::TouchTest(
173 const AxisEvent& event, const RefPtr<RenderNode>& renderNode, const TouchRestrict& touchRestrict)
174 {
175 ContainerScope scope(instanceId_);
176
177 ACE_FUNCTION_TRACE();
178 CHECK_NULL_VOID(renderNode);
179 // collect
180 const Point point { event.x, event.y, event.sourceType };
181 // For root node, the parent local point is the same as global point.
182 renderNode->TouchTest(point, point, touchRestrict, axisTouchTestResult_);
183 }
184
FlushTouchEventsBegin(const std::list<TouchEvent> & touchEvents)185 void EventManager::FlushTouchEventsBegin(const std::list<TouchEvent>& touchEvents)
186 {
187 for (auto iter = touchEvents.begin(); iter != touchEvents.end(); ++iter) {
188 const auto result = touchTestResults_.find((*iter).id);
189 if (result != touchTestResults_.end()) {
190 for (auto entry = result->second.rbegin(); entry != result->second.rend(); ++entry) {
191 (*entry)->OnFlushTouchEventsBegin();
192 }
193 }
194 }
195 }
196
FlushTouchEventsEnd(const std::list<TouchEvent> & touchEvents)197 void EventManager::FlushTouchEventsEnd(const std::list<TouchEvent>& touchEvents)
198 {
199 for (auto iter = touchEvents.begin(); iter != touchEvents.end(); ++iter) {
200 const auto result = touchTestResults_.find((*iter).id);
201 if (result != touchTestResults_.end()) {
202 for (auto entry = result->second.rbegin(); entry != result->second.rend(); ++entry) {
203 (*entry)->OnFlushTouchEventsEnd();
204 }
205 }
206 }
207 }
208
DispatchTouchEvent(const TouchEvent & point)209 bool EventManager::DispatchTouchEvent(const TouchEvent& point)
210 {
211 ContainerScope scope(instanceId_);
212
213 ACE_FUNCTION_TRACE();
214 const auto iter = touchTestResults_.find(point.id);
215 if (iter == touchTestResults_.end()) {
216 LOGI("the %{public}d touch test result does not exist!", point.id);
217 return false;
218 }
219
220 if (point.type == TouchType::DOWN) {
221 // first collect gesture into gesture referee.
222 if (Container::IsCurrentUseNewPipeline()) {
223 refereeNG_->AddGestureToScope(point.id, iter->second);
224 }
225 }
226
227 bool dispatchSuccess = true;
228 for (auto entry = iter->second.rbegin(); entry != iter->second.rend(); ++entry) {
229 if (!(*entry)->DispatchMultiContainerEvent(point)) {
230 dispatchSuccess = false;
231 break;
232 }
233 }
234 // If one gesture recognizer has already been won, other gesture recognizers will still be affected by
235 // the event, each recognizer needs to filter the extra events by itself.
236 if (dispatchSuccess) {
237 if (Container::IsCurrentUseNewPipeline()) {
238 // Need update here: onTouch/Recognizer need update
239 bool isStopTouchEvent = false;
240 for (const auto& entry : iter->second) {
241 auto recognizer = AceType::DynamicCast<NG::NGGestureRecognizer>(entry);
242 if (recognizer) {
243 entry->HandleMultiContainerEvent(point);
244 }
245 if (!recognizer && !isStopTouchEvent) {
246 isStopTouchEvent = !entry->HandleMultiContainerEvent(point);
247 }
248 }
249 } else {
250 for (const auto& entry : iter->second) {
251 if (!entry->HandleMultiContainerEvent(point)) {
252 break;
253 }
254 }
255 }
256 }
257
258 if (point.type == TouchType::UP || point.type == TouchType::CANCEL) {
259 refereeNG_->CleanGestureScope(point.id);
260 referee_->CleanGestureScope(point.id);
261 touchTestResults_.erase(point.id);
262 }
263
264 return true;
265 }
266
DispatchTouchEvent(const AxisEvent & event)267 bool EventManager::DispatchTouchEvent(const AxisEvent& event)
268 {
269 ContainerScope scope(instanceId_);
270
271 if (event.action == AxisAction::BEGIN) {
272 // first collect gesture into gesture referee.
273 if (Container::IsCurrentUseNewPipeline()) {
274 if (refereeNG_) {
275 refereeNG_->AddGestureToScope(event.id, axisTouchTestResult_);
276 }
277 }
278 }
279
280 ACE_FUNCTION_TRACE();
281 for (const auto& entry : axisTouchTestResult_) {
282 if (!entry->HandleEvent(event)) {
283 break;
284 }
285 }
286 if (event.action == AxisAction::END || event.action == AxisAction::NONE || event.action == AxisAction::CANCEL) {
287 if (Container::IsCurrentUseNewPipeline()) {
288 if (refereeNG_) {
289 refereeNG_->CleanGestureScope(event.id);
290 }
291 }
292 axisTouchTestResult_.clear();
293 }
294 return true;
295 }
296
DispatchTabIndexEvent(const KeyEvent & event,const RefPtr<FocusNode> & focusNode,const RefPtr<FocusGroup> & mainNode)297 bool EventManager::DispatchTabIndexEvent(
298 const KeyEvent& event, const RefPtr<FocusNode>& focusNode, const RefPtr<FocusGroup>& mainNode)
299 {
300 LOGD("The key code is %{public}d, the key action is %{public}d, the repeat time is %{public}d.", event.code,
301 event.action, event.repeatTime);
302 CHECK_NULL_RETURN(focusNode, false);
303 CHECK_NULL_RETURN(mainNode, false);
304 if (focusNode->HandleFocusByTabIndex(event, mainNode)) {
305 LOGI("Tab index focus system handled this event");
306 return true;
307 }
308 return false;
309 }
310
DispatchKeyEvent(const KeyEvent & event,const RefPtr<FocusNode> & focusNode)311 bool EventManager::DispatchKeyEvent(const KeyEvent& event, const RefPtr<FocusNode>& focusNode)
312 {
313 CHECK_NULL_RETURN(focusNode, false);
314 LOGD("The key code is %{public}d, the key action is %{public}d, the repeat time is %{public}d.", event.code,
315 event.action, event.repeatTime);
316 if (focusNode->HandleKeyEvent(event)) {
317 LOGI("Default focus system handled this event");
318 return true;
319 }
320 LOGI("Use platform to handle this event");
321 return false;
322 }
323
DispatchTabIndexEventNG(const KeyEvent & event,const RefPtr<NG::FrameNode> & focusNode,const RefPtr<NG::FrameNode> & mainNode)324 bool EventManager::DispatchTabIndexEventNG(
325 const KeyEvent& event, const RefPtr<NG::FrameNode>& focusNode, const RefPtr<NG::FrameNode>& mainNode)
326 {
327 LOGD("The key code is %{public}d, the key action is %{public}d, the repeat time is %{public}d.", event.code,
328 event.action, event.repeatTime);
329 CHECK_NULL_RETURN(focusNode, false);
330 CHECK_NULL_RETURN(mainNode, false);
331 auto focusNodeHub = focusNode->GetFocusHub();
332 CHECK_NULL_RETURN(focusNodeHub, false);
333 auto mainNodeHub = mainNode->GetFocusHub();
334 CHECK_NULL_RETURN(mainNodeHub, false);
335 if (focusNodeHub->HandleFocusByTabIndex(event, mainNodeHub)) {
336 LOGI("Tab index focus system handled this event");
337 return true;
338 }
339 return false;
340 }
341
DispatchKeyEventNG(const KeyEvent & event,const RefPtr<NG::FrameNode> & focusNode)342 bool EventManager::DispatchKeyEventNG(const KeyEvent& event, const RefPtr<NG::FrameNode>& focusNode)
343 {
344 CHECK_NULL_RETURN(focusNode, false);
345 LOGD("The key code is %{public}d, the key action is %{public}d, the repeat time is %{public}d.", event.code,
346 event.action, event.repeatTime);
347 auto focusNodeHub = focusNode->GetFocusHub();
348 CHECK_NULL_RETURN(focusNodeHub, false);
349 if (focusNodeHub->HandleKeyEvent(event)) {
350 LOGI("Default focus system handled this event");
351 return true;
352 }
353 LOGI("Use platform to handle this event");
354 return false;
355 }
356
MouseTest(const MouseEvent & event,const RefPtr<RenderNode> & renderNode)357 void EventManager::MouseTest(const MouseEvent& event, const RefPtr<RenderNode>& renderNode)
358 {
359 CHECK_NULL_VOID(renderNode);
360 const Point point { event.x, event.y };
361 MouseHoverTestList hitTestResult;
362 WeakPtr<RenderNode> hoverNode = nullptr;
363 renderNode->MouseDetect(point, point, hitTestResult, hoverNode);
364 if (hitTestResult.empty()) {
365 LOGD("mouse hover test result is empty");
366 }
367 if (event.action == MouseAction::WINDOW_LEAVE) {
368 mouseHoverTestResultsPre_ = std::move(mouseHoverTestResults_);
369 mouseHoverTestResults_.clear();
370 } else if (event.action == MouseAction::WINDOW_ENTER) {
371 mouseHoverTestResultsPre_.clear();
372 mouseHoverTestResults_ = std::move(hitTestResult);
373 } else {
374 mouseHoverTestResultsPre_ = std::move(mouseHoverTestResults_);
375 mouseHoverTestResults_ = std::move(hitTestResult);
376 }
377 mouseHoverNodePre_ = mouseHoverNode_;
378 mouseHoverNode_ = hoverNode;
379 LOGI("MouseDetect hit test last/new result size = %{public}zu/%{public}zu", mouseHoverTestResultsPre_.size(),
380 mouseHoverTestResults_.size());
381 }
382
DispatchMouseEvent(const MouseEvent & event)383 bool EventManager::DispatchMouseEvent(const MouseEvent& event)
384 {
385 if (event.action == MouseAction::PRESS || event.action == MouseAction::RELEASE ||
386 event.action == MouseAction::MOVE) {
387 LOGD("RenderBox::HandleMouseEvent, button is %{public}d, action is %{public}d", event.button, event.action);
388 for (const auto& wp : mouseHoverTestResults_) {
389 auto hoverNode = wp.Upgrade();
390 if (hoverNode) {
391 if (hoverNode->HandleMouseEvent(event)) {
392 LOGI("Do HandleMouseEvent. Dispatch node: %{public}s", AceType::TypeName(hoverNode));
393 break;
394 }
395 }
396 }
397 return true;
398 }
399 return false;
400 }
401
DispatchMouseHoverAnimation(const MouseEvent & event)402 void EventManager::DispatchMouseHoverAnimation(const MouseEvent& event)
403 {
404 auto hoverNodeCur = mouseHoverNode_.Upgrade();
405 auto hoverNodePre = mouseHoverNodePre_.Upgrade();
406 if (event.action == MouseAction::PRESS) {
407 if (hoverNodeCur) {
408 hoverNodeCur->AnimateMouseHoverExit();
409 }
410 } else if (event.action == MouseAction::RELEASE) {
411 if (hoverNodeCur) {
412 hoverNodeCur->AnimateMouseHoverEnter();
413 }
414 } else if (event.button == MouseButton::NONE_BUTTON && event.action == MouseAction::MOVE) {
415 if (hoverNodeCur != hoverNodePre) {
416 if (hoverNodeCur) {
417 hoverNodeCur->AnimateMouseHoverEnter();
418 }
419 if (hoverNodePre) {
420 hoverNodePre->AnimateMouseHoverExit();
421 }
422 }
423 } else if (event.action == MouseAction::WINDOW_ENTER) {
424 if (hoverNodeCur) {
425 hoverNodeCur->AnimateMouseHoverEnter();
426 }
427 } else if (event.action == MouseAction::WINDOW_LEAVE) {
428 if (hoverNodeCur) {
429 hoverNodeCur->AnimateMouseHoverExit();
430 }
431 }
432 }
433
DispatchMouseHoverEvent(const MouseEvent & event)434 bool EventManager::DispatchMouseHoverEvent(const MouseEvent& event)
435 {
436 for (const auto& wp : mouseHoverTestResultsPre_) {
437 // get all previous hover nodes while it's not in current hover nodes. Those nodes exit hover
438 auto it = std::find(mouseHoverTestResults_.begin(), mouseHoverTestResults_.end(), wp);
439 if (it == mouseHoverTestResults_.end()) {
440 auto hoverNode = wp.Upgrade();
441 if (hoverNode) {
442 hoverNode->HandleMouseHoverEvent(MouseState::NONE);
443 }
444 }
445 }
446 for (const auto& wp : mouseHoverTestResults_) {
447 // get all current hover nodes while it's not in previous hover nodes. Those nodes are new hover
448 auto it = std::find(mouseHoverTestResultsPre_.begin(), mouseHoverTestResultsPre_.end(), wp);
449 if (it == mouseHoverTestResultsPre_.end()) {
450 auto hoverNode = wp.Upgrade();
451 if (hoverNode) {
452 hoverNode->HandleMouseHoverEvent(MouseState::HOVER);
453 }
454 }
455 }
456 return true;
457 }
458
LogPrintMouseTest()459 void EventManager::LogPrintMouseTest()
460 {
461 if (!SystemProperties::GetDebugEnabled()) {
462 return;
463 }
464 if (currMouseTestResults_.empty()) {
465 LOGD("Mouse test onMouse result is empty.");
466 } else {
467 for (const auto& result : currMouseTestResults_) {
468 LOGD("Mouse test onMouse result: %{public}s/%{public}d.", result->GetNodeName().c_str(),
469 result->GetNodeId());
470 }
471 }
472 if (lastHoverTestResults_.empty()) {
473 LOGD("Mouse test onHover last result is empty.");
474 } else {
475 for (const auto& result : lastHoverTestResults_) {
476 LOGD("Mouse test onHover last result: %{public}s/%{public}d.", result->GetNodeName().c_str(),
477 result->GetNodeId());
478 }
479 }
480 if (currHoverTestResults_.empty()) {
481 LOGD("Mouse test onHover current result is empty.");
482 } else {
483 for (const auto& result : currHoverTestResults_) {
484 LOGD("Mouse test onHover current result: %{public}s/%{public}d.", result->GetNodeName().c_str(),
485 result->GetNodeId());
486 }
487 }
488 auto lastNode = lastHoverNode_.Upgrade();
489 auto currNode = currHoverNode_.Upgrade();
490 LOGD("Mouse test last/current hoverEffect node: %{public}s/%{public}d / %{public}s/%{public}d",
491 lastNode ? lastNode->GetTag().c_str() : "NULL", lastNode ? lastNode->GetId() : -1,
492 currNode ? currNode->GetTag().c_str() : "NULL", currNode ? currNode->GetId() : -1);
493 }
494
MouseTest(const MouseEvent & event,const RefPtr<NG::FrameNode> & frameNode,const TouchRestrict & touchRestrict)495 void EventManager::MouseTest(
496 const MouseEvent& event, const RefPtr<NG::FrameNode>& frameNode, const TouchRestrict& touchRestrict)
497 {
498 LOGD("Mouse test start. Mouse event is (%{public}f,%{public}f), button: %{public}d, action: %{public}d", event.x,
499 event.y, event.button, event.action);
500 CHECK_NULL_VOID(frameNode);
501 const NG::PointF point { event.x, event.y };
502 TouchTestResult testResult;
503 frameNode->TouchTest(point, point, touchRestrict, testResult, event.GetId());
504 if (testResult.empty()) {
505 LOGD("mouse hover test result is empty");
506 }
507 currMouseTestResults_.clear();
508 HoverTestResult hoverTestResult;
509 WeakPtr<NG::FrameNode> hoverNode = nullptr;
510 for (const auto& result : testResult) {
511 auto mouseResult = AceType::DynamicCast<MouseEventTarget>(result);
512 if (mouseResult) {
513 currMouseTestResults_.emplace_back(mouseResult);
514 }
515 auto hoverResult = AceType::DynamicCast<HoverEventTarget>(result);
516 if (hoverResult) {
517 hoverTestResult.emplace_back(hoverResult);
518 }
519 if (!hoverNode.Upgrade()) {
520 auto hoverEffectResult = AceType::DynamicCast<HoverEffectTarget>(result);
521 if (hoverEffectResult) {
522 hoverNode = hoverEffectResult->GetHoverNode();
523 }
524 }
525 }
526 if (event.action == MouseAction::WINDOW_LEAVE) {
527 lastHoverTestResults_ = std::move(currHoverTestResults_);
528 currHoverTestResults_.clear();
529 } else if (event.action == MouseAction::WINDOW_ENTER) {
530 lastHoverTestResults_.clear();
531 currHoverTestResults_ = std::move(hoverTestResult);
532 } else {
533 lastHoverTestResults_ = std::move(currHoverTestResults_);
534 currHoverTestResults_ = std::move(hoverTestResult);
535 }
536 lastHoverNode_ = currHoverNode_;
537 currHoverNode_ = hoverNode;
538 LogPrintMouseTest();
539 LOGD("Mouse test end.");
540 }
541
DispatchMouseEventNG(const MouseEvent & event)542 bool EventManager::DispatchMouseEventNG(const MouseEvent& event)
543 {
544 LOGD("DispatchMouseEventNG: button is %{public}d, action is %{public}d.", event.button, event.action);
545 if (event.action == MouseAction::PRESS || event.action == MouseAction::RELEASE ||
546 event.action == MouseAction::MOVE) {
547 for (const auto& mouseTarget : currMouseTestResults_) {
548 if (mouseTarget) {
549 if (mouseTarget->HandleMouseEvent(event)) {
550 return true;
551 }
552 }
553 }
554 }
555 return false;
556 }
557
DispatchMouseHoverAnimationNG(const MouseEvent & event)558 void EventManager::DispatchMouseHoverAnimationNG(const MouseEvent& event)
559 {
560 LOGD("DispatchMouseHoverAnimationNG: button is %{public}d, action is %{public}d.", event.button, event.action);
561 auto hoverNodeCur = currHoverNode_.Upgrade();
562 auto hoverNodePre = lastHoverNode_.Upgrade();
563 if (event.action == MouseAction::PRESS) {
564 if (hoverNodeCur) {
565 hoverNodeCur->AnimateHoverEffect(false);
566 }
567 } else if (event.action == MouseAction::RELEASE) {
568 if (hoverNodeCur) {
569 hoverNodeCur->AnimateHoverEffect(true);
570 }
571 } else if (event.button == MouseButton::NONE_BUTTON && event.action == MouseAction::MOVE) {
572 if (hoverNodeCur != hoverNodePre) {
573 if (hoverNodeCur) {
574 hoverNodeCur->AnimateHoverEffect(true);
575 }
576 if (hoverNodePre) {
577 hoverNodePre->AnimateHoverEffect(false);
578 }
579 }
580 } else if (event.action == MouseAction::WINDOW_ENTER) {
581 if (hoverNodeCur) {
582 hoverNodeCur->AnimateHoverEffect(true);
583 }
584 } else if (event.action == MouseAction::WINDOW_LEAVE) {
585 if (hoverNodeCur) {
586 hoverNodeCur->AnimateHoverEffect(false);
587 }
588 }
589 }
590
DispatchMouseHoverEventNG(const MouseEvent & event)591 bool EventManager::DispatchMouseHoverEventNG(const MouseEvent& event)
592 {
593 LOGD("DispatchMouseHoverEventNG: button is %{public}d, action is %{public}d.", event.button, event.action);
594 for (const auto& hoverResult : lastHoverTestResults_) {
595 // get all previous hover nodes while it's not in current hover nodes. Those nodes exit hover
596 auto it = std::find(currHoverTestResults_.begin(), currHoverTestResults_.end(), hoverResult);
597 if (it == currHoverTestResults_.end()) {
598 hoverResult->HandleHoverEvent(false);
599 }
600 }
601 for (const auto& hoverResult : currHoverTestResults_) {
602 // get all current hover nodes while it's not in previous hover nodes. Those nodes are new hover
603 auto it = std::find(lastHoverTestResults_.begin(), lastHoverTestResults_.end(), hoverResult);
604 if (it == lastHoverTestResults_.end()) {
605 hoverResult->HandleHoverEvent(true);
606 }
607 }
608 return true;
609 }
610
AxisTest(const AxisEvent & event,const RefPtr<RenderNode> & renderNode)611 void EventManager::AxisTest(const AxisEvent& event, const RefPtr<RenderNode>& renderNode)
612 {
613 CHECK_NULL_VOID(renderNode);
614 const Point point { event.x, event.y };
615 WeakPtr<RenderNode> axisNode = nullptr;
616 renderNode->AxisDetect(point, point, axisNode, event.GetDirection());
617 axisNode_ = axisNode;
618 LOGI("Current axis node is %{public}s", AceType::TypeName(axisNode_.Upgrade()));
619 }
620
DispatchAxisEvent(const AxisEvent & event)621 bool EventManager::DispatchAxisEvent(const AxisEvent& event)
622 {
623 auto responseNode = axisNode_.Upgrade();
624 if (responseNode) {
625 responseNode->HandleAxisEvent(event);
626 }
627 return true;
628 }
629
AxisTest(const AxisEvent & event,const RefPtr<NG::FrameNode> & frameNode)630 void EventManager::AxisTest(const AxisEvent& event, const RefPtr<NG::FrameNode>& frameNode)
631 {
632 CHECK_NULL_VOID(frameNode);
633 const NG::PointF point { event.x, event.y };
634 frameNode->AxisTest(point, point, axisTestResults_);
635 }
636
DispatchAxisEventNG(const AxisEvent & event)637 bool EventManager::DispatchAxisEventNG(const AxisEvent& event)
638 {
639 if (event.horizontalAxis == 0 && event.verticalAxis == 0 && event.pinchAxisScale == 0) {
640 return false;
641 }
642 LOGD("DispatchAxisEventNG, action is %{public}d, axis is %{public}f / %{public}f / %{public}f", event.action,
643 event.horizontalAxis, event.verticalAxis, event.pinchAxisScale);
644 for (const auto& axisTarget : axisTestResults_) {
645 if (axisTarget && axisTarget->HandleAxisEvent(event)) {
646 return true;
647 }
648 }
649 return true;
650 }
651
DispatchRotationEvent(const RotationEvent & event,const RefPtr<RenderNode> & renderNode,const RefPtr<RenderNode> & requestFocusNode)652 bool EventManager::DispatchRotationEvent(
653 const RotationEvent& event, const RefPtr<RenderNode>& renderNode, const RefPtr<RenderNode>& requestFocusNode)
654 {
655 CHECK_NULL_RETURN(renderNode, false);
656 if (requestFocusNode && renderNode->RotationMatchTest(requestFocusNode)) {
657 LOGD("RotationMatchTest: dispatch rotation to request node.");
658 return requestFocusNode->RotationTestForward(event);
659 } else {
660 LOGD("RotationMatchTest: dispatch rotation to stack render node.");
661 return renderNode->RotationTest(event);
662 }
663 }
664
ClearResults()665 void EventManager::ClearResults()
666 {
667 touchTestResults_.clear();
668 mouseTestResults_.clear();
669 }
670
EventManager()671 EventManager::EventManager()
672 {
673 LOGD("EventManger Constructor.");
674 refereeNG_ = AceType::MakeRefPtr<NG::GestureReferee>();
675 referee_ = AceType::MakeRefPtr<GestureReferee>();
676
677 auto callback = [weak = WeakClaim(this)](size_t touchId) -> bool {
678 auto eventManager = weak.Upgrade();
679 CHECK_NULL_RETURN(eventManager, false);
680 auto refereeNG = eventManager->refereeNG_;
681 CHECK_NULL_RETURN(refereeNG, false);
682 return refereeNG->HasGestureAccepted(touchId);
683 };
684 referee_->SetQueryStateFunc(std::move(callback));
685
686 auto cleanReferee = [weak = WeakClaim(this)](size_t touchId) -> void {
687 auto eventManager = weak.Upgrade();
688 CHECK_NULL_VOID(eventManager);
689 auto referee = eventManager->referee_;
690 CHECK_NULL_VOID(referee);
691 auto gestureScope = referee->GetGestureScope();
692 const auto iter = gestureScope.find(touchId);
693 if (iter == gestureScope.end()) {
694 return;
695 }
696
697 auto highRecognizers = iter->second.GetHighRecognizers();
698 auto lowRecognizers = iter->second.GetLowRecognizers();
699 auto parallelRecognizers = iter->second.GetParallelRecognizers();
700
701 for (const auto& weak : highRecognizers) {
702 auto gesture = weak.Upgrade();
703 if (gesture) {
704 gesture->OnRejected(touchId);
705 }
706 }
707
708 for (const auto& weak : lowRecognizers) {
709 auto gesture = weak.Upgrade();
710 if (gesture) {
711 gesture->OnRejected(touchId);
712 }
713 }
714
715 for (const auto& weak : parallelRecognizers) {
716 auto gesture = weak.Upgrade();
717 if (gesture) {
718 gesture->OnRejected(touchId);
719 }
720 }
721 };
722 refereeNG_->SetQueryStateFunc(std::move(cleanReferee));
723 }
724
725 } // namespace OHOS::Ace
726