1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/accessibility/accessibility_manager_ng.h"
17
18 #include "core/accessibility/accessibility_constants.h"
19 #include "core/accessibility/accessibility_session_adapter.h"
20 #include "core/components_ng/pattern/pattern.h"
21 #include "core/pipeline_ng/pipeline_context.h"
22
23 namespace OHOS::Ace::NG {
24 namespace {
AddTouchEventAllFingersInfo(const RefPtr<NG::FrameNode> & node,TouchEventInfo & eventInfo,const TouchEvent & event)25 void AddTouchEventAllFingersInfo(const RefPtr<NG::FrameNode>& node, TouchEventInfo& eventInfo, const TouchEvent& event)
26 {
27 // all fingers collection
28 for (const auto& item : event.pointers) {
29 float globalX = item.x;
30 float globalY = item.y;
31 float screenX = item.screenX;
32 float screenY = item.screenY;
33 double globalDisplayX = item.globalDisplayX;
34 double globalDisplayY = item.globalDisplayY;
35 PointF localPoint(globalX, globalY);
36 NGGestureRecognizer::Transform(localPoint, node, false, false);
37 auto localX = static_cast<float>(localPoint.GetX());
38 auto localY = static_cast<float>(localPoint.GetY());
39 TouchLocationInfo info("onTouch", item.originalId);
40 info.SetGlobalLocation(Offset(globalX, globalY));
41 info.SetLocalLocation(Offset(localX, localY));
42 info.SetScreenLocation(Offset(screenX, screenY));
43 info.SetGlobalDisplayLocation(Offset(globalDisplayX, globalDisplayY));
44 info.SetTouchType(event.type);
45 info.SetForce(item.force);
46 info.SetPressedTime(item.downTime);
47 info.SetWidth(item.width);
48 info.SetHeight(item.height);
49 if (item.tiltX.has_value()) {
50 info.SetTiltX(item.tiltX.value());
51 }
52 if (item.tiltY.has_value()) {
53 info.SetTiltY(item.tiltY.value());
54 }
55 info.SetSourceTool(item.sourceTool);
56 eventInfo.AddTouchLocationInfo(std::move(info));
57 }
58 }
59
ConvertTouchEvent2TouchEventInfo(const RefPtr<NG::FrameNode> & node,const TouchEvent & event,TouchEventInfo & eventInfo)60 void ConvertTouchEvent2TouchEventInfo(const RefPtr<NG::FrameNode>& node, const TouchEvent& event,
61 TouchEventInfo& eventInfo)
62 {
63 eventInfo.SetTimeStamp(event.time);
64 eventInfo.SetDeviceId(event.deviceId);
65 eventInfo.SetPointerEvent(event.GetTouchEventPointerEvent());
66 TouchLocationInfo changedInfo("onTouch", event.originalId);
67 PointF lastLocalPoint(event.x, event.y);
68 NGGestureRecognizer::Transform(lastLocalPoint, node, false, false);
69 auto localX = static_cast<float>(lastLocalPoint.GetX());
70 auto localY = static_cast<float>(lastLocalPoint.GetY());
71 changedInfo.SetLocalLocation(Offset(localX, localY));
72 changedInfo.SetGlobalLocation(Offset(event.x, event.y));
73 changedInfo.SetScreenLocation(Offset(event.screenX, event.screenY));
74 changedInfo.SetGlobalDisplayLocation(Offset(event.globalDisplayX, event.globalDisplayY));
75 changedInfo.SetTouchType(event.type);
76 changedInfo.SetForce(event.force);
77 changedInfo.SetPressedTime(event.pressedTime);
78 changedInfo.SetWidth(event.width);
79 changedInfo.SetHeight(event.height);
80 if (event.tiltX.has_value()) {
81 changedInfo.SetTiltX(event.tiltX.value());
82 }
83 if (event.tiltY.has_value()) {
84 changedInfo.SetTiltY(event.tiltY.value());
85 }
86 changedInfo.SetSourceTool(event.sourceTool);
87 eventInfo.AddChangedTouchLocationInfo(std::move(changedInfo));
88
89 AddTouchEventAllFingersInfo(node, eventInfo, event);
90 eventInfo.SetSourceDevice(event.sourceType);
91 eventInfo.SetForce(event.force);
92 if (event.tiltX.has_value()) {
93 eventInfo.SetTiltX(event.tiltX.value());
94 }
95 if (event.tiltY.has_value()) {
96 eventInfo.SetTiltY(event.tiltY.value());
97 }
98 if (event.rollAngle.has_value()) {
99 eventInfo.SetRollAngle(event.rollAngle.value());
100 }
101 eventInfo.SetSourceTool(event.sourceTool);
102 EventTarget eventTarget;
103 eventTarget.id = node->GetInspectorId().value_or("").c_str();
104 eventInfo.SetTarget(eventTarget);
105 }
106
CheckAndSendHoverEnterByAncestor(const RefPtr<NG::FrameNode> & ancestor)107 bool CheckAndSendHoverEnterByAncestor(const RefPtr<NG::FrameNode>& ancestor)
108 {
109 CHECK_NULL_RETURN(ancestor, false);
110 auto pipeline = ancestor->GetContext();
111 CHECK_NULL_RETURN(pipeline, false);
112 // Inter Process is showed as a component with rect like form process,
113 // need send hover enter when no component hovered to focus outside
114 if (pipeline->IsFormRender() || pipeline->IsJsCard() || pipeline->IsJsPlugin()) {
115 TAG_LOGD(AceLogTag::ACE_ACCESSIBILITY, "SendHoverEnterByAncestor");
116 ancestor->OnAccessibilityEvent(AccessibilityEventType::HOVER_ENTER_EVENT);
117 return true;
118 }
119 return false;
120 }
121
IsTouchExplorationEnabled(const RefPtr<FrameNode> & root)122 bool IsTouchExplorationEnabled(const RefPtr<FrameNode>& root)
123 {
124 CHECK_NULL_RETURN(root, true);
125 auto pipeline = root->GetContext();
126 CHECK_NULL_RETURN(pipeline, true);
127 auto jsAccessibilityManager = pipeline->GetAccessibilityManager();
128 CHECK_NULL_RETURN(jsAccessibilityManager, true);
129 auto accessibilityWorkMode = jsAccessibilityManager->GenerateAccessibilityWorkMode();
130 return accessibilityWorkMode.isTouchExplorationEnabled;
131 }
132
GetEmbedNodeBySurfaceId(const std::string & surfaceId)133 WeakPtr<NG::FrameNode> GetEmbedNodeBySurfaceId(const std::string& surfaceId)
134 {
135 std::stringstream ss(surfaceId);
136 uint64_t id;
137 if (ss >> id) {
138 return ElementRegister::GetInstance()->GetEmbedNodeBySurfaceId(id);
139 }
140 return nullptr;
141 }
142 }
143
HandleAccessibilityHoverEvent(const RefPtr<FrameNode> & root,const MouseEvent & event)144 void AccessibilityManagerNG::HandleAccessibilityHoverEvent(const RefPtr<FrameNode>& root, const MouseEvent& event)
145 {
146 if (root == nullptr || !AceApplicationInfo::GetInstance().IsAccessibilityEnabled() ||
147 !IsTouchExplorationEnabled(root) || event.sourceType != SourceType::MOUSE) {
148 return;
149 }
150 AccessibilityHoverEventType type = AccessibilityHoverEventType::MOVE;
151 switch (event.action) {
152 case MouseAction::WINDOW_ENTER:
153 type = AccessibilityHoverEventType::ENTER;
154 break;
155 case MouseAction::MOVE:
156 type = AccessibilityHoverEventType::MOVE;
157 break;
158 case MouseAction::WINDOW_LEAVE:
159 type = AccessibilityHoverEventType::EXIT;
160 break;
161 default:
162 return;
163 }
164 PointF point(event.x, event.y);
165 HandleHoverEventParam param {point, SourceType::MOUSE, type, event.time};
166 TouchEvent touchEvent;
167 HandleAccessibilityHoverEventInner(root, param, touchEvent);
168 }
169
HandleAccessibilityHoverEvent(const RefPtr<FrameNode> & root,const TouchEvent & event)170 void AccessibilityManagerNG::HandleAccessibilityHoverEvent(const RefPtr<FrameNode>& root, const TouchEvent& event)
171 {
172 if (root == nullptr ||
173 !AceApplicationInfo::GetInstance().IsAccessibilityEnabled() ||
174 !IsTouchExplorationEnabled(root) ||
175 event.sourceType == SourceType::MOUSE) {
176 return;
177 }
178 AccessibilityHoverEventType type = AccessibilityHoverEventType::MOVE;
179 switch (event.type) {
180 case TouchType::HOVER_ENTER:
181 type = AccessibilityHoverEventType::ENTER;
182 break;
183 case TouchType::HOVER_MOVE:
184 type = AccessibilityHoverEventType::MOVE;
185 break;
186 case TouchType::HOVER_EXIT:
187 type = AccessibilityHoverEventType::EXIT;
188 break;
189 default:
190 return;
191 }
192 PointF point(event.x, event.y);
193 auto& hoverState = hoverStateManager_.GetHoverState(root->GetAccessibilityId());
194 if (event.pointers.size() > 1 && event.sourceType == SourceType::TOUCH) {
195 if (hoverState.source == SourceType::TOUCH) {
196 hoverStateManager_.ResetHoverState(hoverState);
197 return;
198 }
199 }
200 HandleHoverEventParam param {point, event.sourceType, type, event.time};
201 HandleAccessibilityHoverEventInner(root, param, event);
202 }
203
HandleAccessibilityHoverEvent(const RefPtr<FrameNode> & root,float pointX,float pointY,int32_t sourceType,int32_t eventType,int64_t timeMs)204 void AccessibilityManagerNG::HandleAccessibilityHoverEvent(const RefPtr<FrameNode>& root, float pointX, float pointY,
205 int32_t sourceType, int32_t eventType, int64_t timeMs)
206 {
207 if (root == nullptr ||
208 !AceApplicationInfo::GetInstance().IsAccessibilityEnabled() ||
209 !IsTouchExplorationEnabled(root) ||
210 eventType < 0 || eventType >= static_cast<int32_t>(AccessibilityHoverEventType::Count)) {
211 return;
212 }
213 PointF point(pointX, pointY);
214 TimeStamp time((std::chrono::milliseconds(timeMs)));
215
216 if (IsHandlePipelineAccessibilityHoverEnter(root)) {
217 TouchEvent event;
218 event.x = pointX;
219 event.y = pointY;
220 event.sourceType = static_cast<SourceType>(sourceType);
221 event.time = time;
222 HandlePipelineAccessibilityHoverEnter(root, event, eventType);
223 }
224 HandleHoverEventParam param {point, static_cast<SourceType>(sourceType),
225 static_cast<AccessibilityHoverEventType>(eventType), time};
226 TouchEvent touchEvent;
227 HandleAccessibilityHoverEventInner(root, param, touchEvent);
228 }
229
IsHoverTransparentCallbackListEmpty(const RefPtr<NG::FrameNode> & node)230 bool IsHoverTransparentCallbackListEmpty(const RefPtr<NG::FrameNode>& node)
231 {
232 CHECK_NULL_RETURN(node, true);
233 auto pipeline = node->GetContextRefPtr();
234 CHECK_NULL_RETURN(pipeline, true);
235 auto accessibilityManager = pipeline->GetAccessibilityManager();
236 CHECK_NULL_RETURN(accessibilityManager, true);
237 auto containerId = pipeline->GetInstanceId();
238 return accessibilityManager->CheckHoverTransparentCallbackListEmpty(containerId);
239 }
240
ExecuteChildNodeHoverTransparentCallback(const RefPtr<FrameNode> & root,const PointF & point,const TouchEvent & event)241 bool AccessibilityManagerNG::ExecuteChildNodeHoverTransparentCallback(const RefPtr<FrameNode>& root,
242 const PointF& point, const TouchEvent& event)
243 {
244 CHECK_NULL_RETURN(root, false);
245 auto renderContext = root->GetRenderContext();
246 auto accessibilityProperty = root->GetAccessibilityProperty<NG::AccessibilityProperty>();
247 PointF selfPoint = point;
248 if (accessibilityProperty) {
249 bool isInHoverArea = false;
250 if (renderContext) {
251 auto rect = AccessibilityProperty::UpdateHoverTestRect(root);
252 renderContext->GetPointWithRevert(selfPoint);
253 isInHoverArea = rect.IsInnerRegion(selfPoint);
254 }
255 auto callback = accessibilityProperty->GetAccessibilityTransparentCallbackFunc();
256 if (callback && isInHoverArea) {
257 TouchEventInfo eventInfo("touchEvent");
258 ConvertTouchEvent2TouchEventInfo(root, event, eventInfo);
259 callback(eventInfo);
260 }
261 }
262 auto children = root->GetFrameChildren();
263 for (auto childWeak = children.rbegin(); childWeak != children.rend(); ++childWeak) {
264 auto child = childWeak->Upgrade();
265 if (child == nullptr) {
266 continue;
267 }
268 PointF noOffsetPoint = selfPoint;
269 if (renderContext) {
270 auto orginRect = renderContext->GetPaintRectWithoutTransform();
271 noOffsetPoint = selfPoint - orginRect.GetOffset();
272 }
273 ExecuteChildNodeHoverTransparentCallback(child, noOffsetPoint, event);
274 }
275 return true;
276 }
277
HandleAccessibilityHoverTransparentCallback(bool transformed,const RefPtr<FrameNode> & root,const HandleTransparentCallbackParam & param,const PointF & point,const TouchEvent & event)278 bool AccessibilityManagerNG::HandleAccessibilityHoverTransparentCallback(bool transformed,
279 const RefPtr<FrameNode>& root,
280 const HandleTransparentCallbackParam& param,
281 const PointF& point,
282 const TouchEvent& event)
283 {
284 static constexpr int32_t INVALID_NODE_ID = -1;
285 if (transformed) {
286 return false;
287 }
288 if ((param.currentHoveringId == INVALID_NODE_ID) && (param.lastHoveringId == INVALID_NODE_ID)
289 && !IsHoverTransparentCallbackListEmpty(root)) {
290 return ExecuteChildNodeHoverTransparentCallback(root, point, event);
291 }
292 return false;
293 }
294
HandleAccessibilityHoverEventInner(const RefPtr<FrameNode> & root,const HandleHoverEventParam & param,const TouchEvent & event)295 HandleHoverRet AccessibilityManagerNG::HandleAccessibilityHoverEventInner(
296 const RefPtr<FrameNode>& root,
297 const HandleHoverEventParam& param,
298 const TouchEvent& event)
299 {
300 CHECK_NULL_RETURN(root, HandleHoverRet::HOVER_FAIL);
301 auto& hoverState = hoverStateManager_.GetHoverState(root->GetAccessibilityId());
302 auto sourceType = param.sourceType;
303 auto eventType = param.eventType;
304 auto time = param.time;
305 static constexpr size_t THROTTLE_INTERVAL_HOVER_EVENT = 10;
306 uint64_t duration =
307 static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(time - hoverState.time).count());
308 if (!hoverState.idle) {
309 if ((!IsEventTypeChangeDirectHandleHover(eventType, hoverState.eventType))
310 && (duration < THROTTLE_INTERVAL_HOVER_EVENT)) {
311 return HandleHoverRet::IN_TIME_LIMIT;
312 }
313 }
314
315 static constexpr size_t MIN_SOURCE_CHANGE_GAP_MS = 1000;
316 if (sourceType != hoverState.source && !hoverState.idle) {
317 if (duration < MIN_SOURCE_CHANGE_GAP_MS) {
318 return HandleHoverRet::IN_TIME_LIMIT;
319 }
320 hoverStateManager_.ResetHoverState(hoverState);
321 }
322
323 ACE_SCOPED_TRACE("HandleAccessibilityHoverEventInner");
324 if (eventType == AccessibilityHoverEventType::ENTER) {
325 hoverStateManager_.ResetHoverState(hoverState);
326 }
327 std::vector<WeakPtr<FrameNode>> currentNodesHovering;
328 std::vector<RefPtr<FrameNode>> lastNodesHovering;
329 std::vector<int32_t> lastNodesHoveringId;
330 for (const auto& nodeWeak: hoverState.nodesHovering) {
331 auto node = nodeWeak.Upgrade();
332 if (node != nullptr) {
333 lastNodesHovering.push_back(node);
334 lastNodesHoveringId.push_back(node->GetId());
335 }
336 }
337 if (eventType != AccessibilityHoverEventType::EXIT) {
338 std::unique_ptr<AccessibilityProperty::HoverTestDebugTraceInfo> debugInfo = nullptr;
339 AccessibilityHoverTestPath path = AccessibilityProperty::HoverTest(param.point, root, debugInfo);
340 for (const auto& node: path) {
341 auto id = node->GetId();
342 if (std::find(lastNodesHoveringId.begin(), lastNodesHoveringId.end(), id) != lastNodesHoveringId.end() ||
343 AccessibilityProperty::IsAccessibilityFocusable(node)) {
344 currentNodesHovering.push_back(node);
345 }
346 }
347 }
348 auto sendHoverEnter = false;
349 static constexpr int32_t INVALID_NODE_ID = -1;
350 int32_t lastHoveringId = INVALID_NODE_ID;
351 RefPtr<FrameNode> lastHovering = nullptr;
352 if (!lastNodesHovering.empty()) {
353 lastHovering = lastNodesHovering.back();
354 lastHoveringId = lastHovering->GetId();
355 }
356 int32_t currentHoveringId = INVALID_NODE_ID;
357 RefPtr<FrameNode> currentHovering = nullptr;
358 if (!currentNodesHovering.empty()) {
359 currentHovering = currentNodesHovering.back().Upgrade();
360 currentHoveringId = currentHovering->GetId();
361 }
362 bool transformHover = false;
363 if (lastHoveringId != INVALID_NODE_ID && lastHoveringId != currentHoveringId) {
364 lastHovering->OnAccessibilityEvent(AccessibilityEventType::HOVER_EXIT_EVENT);
365 transformHover = NotifyHoverEventToNodeSession(lastHovering, root, param.point,
366 sourceType, AccessibilityHoverEventType::EXIT, time);
367 }
368 if (currentHovering && (currentHoveringId != INVALID_NODE_ID)) {
369 if (currentHoveringId != lastHoveringId && (!IgnoreCurrentHoveringNode(currentHovering))) {
370 currentHovering->OnAccessibilityEvent(AccessibilityEventType::HOVER_ENTER_EVENT);
371 sendHoverEnter = true;
372 }
373 transformHover = NotifyHoverEventToNodeSession(currentHovering, root, param.point,
374 sourceType, eventType, time);
375 }
376
377 if (!sendHoverEnter && (eventType == AccessibilityHoverEventType::ENTER)) {
378 // check need send hover enter when no component hovered to focus outside
379 transformHover |= CheckAndSendHoverEnterByAncestor(root);
380 }
381
382 if ((sourceType != SourceType::MOUSE) && (!param.ignoreTransparent)) {
383 HandleTransparentCallbackParam callbackParam = {currentHoveringId, lastHoveringId};
384 HandleAccessibilityHoverTransparentCallback(transformHover, root, callbackParam, param.point, event);
385 }
386
387 hoverState.nodesHovering = std::move(currentNodesHovering);
388 hoverState.time = time;
389 hoverState.source = sourceType;
390 hoverState.idle = eventType == AccessibilityHoverEventType::EXIT;
391 hoverState.eventType = eventType;
392 if (sendHoverEnter && !transformHover) {
393 return HandleHoverRet::HOVER_HIT;
394 }
395 return HandleHoverRet::HOVER_FAIL;
396 }
397
HandleAccessibilityHoverEventBySurfaceId(const std::string & surfaceId,HandleHoverEventParam & param)398 HandleHoverRet AccessibilityManagerNG::HandleAccessibilityHoverEventBySurfaceId(
399 const std::string& surfaceId,
400 HandleHoverEventParam& param)
401 {
402 auto root = GetEmbedNodeBySurfaceId(surfaceId).Upgrade();
403 CHECK_NULL_RETURN(root, HandleHoverRet::HOVER_FAIL);
404 TouchEvent event;
405 param.ignoreTransparent = true;
406 return HandleAccessibilityHoverEventInner(root, param, event);
407 }
408
IgnoreCurrentHoveringNode(const RefPtr<FrameNode> & node)409 bool AccessibilityManagerNG::IgnoreCurrentHoveringNode(const RefPtr<FrameNode> &node)
410 {
411 auto sessionAdapter = AccessibilitySessionAdapter::GetSessionAdapter(node);
412 CHECK_NULL_RETURN(sessionAdapter, false);
413 return sessionAdapter->IgnoreHostNode();
414 }
415
NotifyHoverEventToNodeSession(const RefPtr<FrameNode> & node,const RefPtr<FrameNode> & rootNode,const PointF & pointRoot,SourceType sourceType,AccessibilityHoverEventType eventType,TimeStamp time)416 bool AccessibilityManagerNG::NotifyHoverEventToNodeSession(const RefPtr<FrameNode>& node,
417 const RefPtr<FrameNode>& rootNode, const PointF& pointRoot,
418 SourceType sourceType, AccessibilityHoverEventType eventType, TimeStamp time)
419 {
420 auto eventHub = node->GetOrCreateEventHub<EventHub>();
421 if (!eventHub->IsEnabled()) {
422 // If the host component is disabled, do not transfer hover event.
423 return false;
424 }
425 auto sessionAdapter = AccessibilitySessionAdapter::GetSessionAdapter(node);
426 CHECK_NULL_RETURN(sessionAdapter, false);
427 // mouse event will not be hover and may be transformed by component self through touch event transform
428 if ((sourceType == SourceType::MOUSE) && (sessionAdapter->IgnoreTransformMouseEvent())) {
429 return false;
430 }
431 PointF pointNode(pointRoot);
432 if (AccessibilityManagerNG::ConvertPointFromAncestorToNode(rootNode, node, pointRoot, pointNode)) {
433 sessionAdapter->TransferHoverEvent(pointNode, sourceType, eventType, time);
434 return true;
435 }
436 return false;
437 }
438
HoverTestDebug(const RefPtr<FrameNode> & root,const PointF & point,std::string & summary,std::string & detail) const439 void AccessibilityManagerNG::HoverTestDebug(const RefPtr<FrameNode>& root, const PointF& point,
440 std::string& summary, std::string& detail) const
441 {
442 auto summaryJson = JsonUtil::Create();
443 auto detailJson = JsonUtil::Create();
444 std::stringstream summaryNodesSearched;
445 auto debugInfo = std::make_unique<AccessibilityProperty::HoverTestDebugTraceInfo>();
446 AccessibilityHoverTestPath path = AccessibilityProperty::HoverTest(point, root, debugInfo);
447 auto summaryPath = JsonUtil::CreateArray();
448 auto summarySelected = JsonUtil::CreateArray();
449
450 auto detaiSelectionInfo = JsonUtil::CreateArray();
451 size_t numNodesSelected = 0;
452 for (size_t i = 0; i < path.size(); ++i) {
453 summaryPath->Put(std::to_string(i).c_str(), path[i]->GetAccessibilityId());
454 auto detailNodeSelection = JsonUtil::Create();
455 if (AccessibilityProperty::IsAccessibilityFocusableDebug(path[i], detailNodeSelection)) {
456 summarySelected->Put(std::to_string(numNodesSelected).c_str(), path[i]->GetAccessibilityId());
457 ++numNodesSelected;
458 }
459 detaiSelectionInfo->PutRef(std::move(detailNodeSelection));
460 }
461 summaryJson->PutRef("path", std::move(summaryPath));
462 summaryJson->PutRef("nodesSelected", std::move(summarySelected));
463
464 auto detailSearchInfo = JsonUtil::CreateArray();
465 for (size_t i = 0; i < debugInfo->trace.size(); ++i) {
466 auto detailNodeSearch = std::move(debugInfo->trace[i]);
467 detailSearchInfo->Put(std::to_string(i).c_str(), detailNodeSearch);
468 }
469 detailJson->PutRef("detailSearch", std::move(detailSearchInfo));
470 detailJson->PutRef("detailSelection", std::move(detaiSelectionInfo));
471 summary = summaryJson->ToString();
472 detail = detailJson->ToString();
473 }
474
ConvertPointFromAncestorToNode(const RefPtr<NG::FrameNode> & ancestor,const RefPtr<NG::FrameNode> & endNode,const PointF & pointAncestor,PointF & pointNode)475 bool AccessibilityManagerNG::ConvertPointFromAncestorToNode(
476 const RefPtr<NG::FrameNode>& ancestor, const RefPtr<NG::FrameNode>& endNode,
477 const PointF& pointAncestor, PointF& pointNode)
478 {
479 CHECK_NULL_RETURN(ancestor, false);
480 CHECK_NULL_RETURN(endNode, false);
481 // revert scale from endNode to ancestor
482 std::vector<RefPtr<NG::FrameNode>> path;
483 RefPtr<NG::FrameNode> curr = endNode;
484 while (curr != nullptr && curr->GetId() != ancestor->GetId()) {
485 path.push_back(curr);
486 curr = curr->GetAncestorNodeOfFrame(true);
487 }
488 CHECK_NULL_RETURN(curr, false);
489 pointNode = pointAncestor;
490 for (auto nodePtr = path.rbegin(); nodePtr != path.rend(); ++nodePtr) {
491 auto renderContext = (*nodePtr)->GetRenderContext();
492 CHECK_NULL_CONTINUE(renderContext);
493 renderContext->GetPointWithRevert(pointNode);
494 auto rect = renderContext->GetPaintRectWithoutTransform();
495 pointNode = pointNode - rect.GetOffset();
496 }
497 return true;
498 }
499
IsEventTypeChangeDirectHandleHover(AccessibilityHoverEventType eventType,AccessibilityHoverEventType prevEventType)500 bool AccessibilityManagerNG::IsEventTypeChangeDirectHandleHover(
501 AccessibilityHoverEventType eventType,
502 AccessibilityHoverEventType prevEventType)
503 {
504 if ((prevEventType == AccessibilityHoverEventType::MOVE)
505 && (eventType == AccessibilityHoverEventType::EXIT)) {
506 return true;
507 }
508 return false;
509 }
510
IsHandlePipelineAccessibilityHoverEnter(const RefPtr<NG::FrameNode> & root)511 bool AccessibilityManagerNG::IsHandlePipelineAccessibilityHoverEnter(const RefPtr<NG::FrameNode>& root)
512 {
513 auto pipeline = root->GetContext();
514 CHECK_NULL_RETURN(pipeline, false);
515 auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipeline);
516 CHECK_NULL_RETURN(ngPipeline, false);
517
518 auto container = Container::GetContainer(ngPipeline->GetInstanceId());
519 if (container && (container->IsUIExtensionWindow())) {
520 return true;
521 }
522 return false;
523 }
524
HandlePipelineAccessibilityHoverEnter(const RefPtr<NG::FrameNode> & root,TouchEvent & event,int32_t eventType)525 void AccessibilityManagerNG::HandlePipelineAccessibilityHoverEnter(
526 const RefPtr<NG::FrameNode>& root,
527 TouchEvent& event,
528 int32_t eventType)
529 {
530 CHECK_NULL_VOID(root);
531 AccessibilityHoverEventType eventHoverType = static_cast<AccessibilityHoverEventType>(eventType);
532 event.type = TouchType::HOVER_MOVE;
533 switch (eventHoverType) {
534 case AccessibilityHoverEventType::ENTER:
535 event.type = TouchType::HOVER_ENTER;
536 break;
537 case AccessibilityHoverEventType::MOVE:
538 event.type = TouchType::HOVER_MOVE;
539 break;
540 case AccessibilityHoverEventType::EXIT:
541 event.type = TouchType::HOVER_EXIT;
542 break;
543 default:
544 break;
545 }
546
547 auto pipeline = root->GetContext();
548 CHECK_NULL_VOID(pipeline);
549 pipeline->OnAccessibilityHoverEvent(event, root);
550 }
551
GetHoverState(int64_t accessibilityId)552 AccessibilityHoverState& AccessibilityHoverStateManager::GetHoverState(int64_t accessibilityId)
553 {
554 auto it = hoverStateMap_.find(accessibilityId);
555 if (it != hoverStateMap_.end()) {
556 return it->second;
557 }
558 hoverStateMap_.emplace(accessibilityId, AccessibilityHoverState {});
559 return hoverStateMap_[accessibilityId];
560 }
561
ResetHoverState(AccessibilityHoverState & hoverState)562 void AccessibilityHoverStateManager::ResetHoverState(AccessibilityHoverState& hoverState)
563 {
564 hoverState.idle = true;
565 hoverState.nodesHovering.clear();
566 }
567 } // namespace OHOS::Ace::NG
568