• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 "accessibility_touch_guider.h"
17 #include "accessibility_window_manager.h"
18 #include "hilog_wrapper.h"
19 #include "securec.h"
20 
21 namespace OHOS {
22 namespace Accessibility {
23 namespace {
24     constexpr int32_t POINTER_COUNT_1 = 1;
25     constexpr int32_t POINTER_COUNT_2 = 2;
26 } // namespace
27 
TGEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,TouchGuider & tgServer)28 TGEventHandler::TGEventHandler(
29     const std::shared_ptr<AppExecFwk::EventRunner> &runner, TouchGuider &tgServer)
30     : AppExecFwk::EventHandler(runner), tgServer_(tgServer)
31 {
32 }
33 
TouchGuider()34 TouchGuider::TouchGuider()
35 {
36     HILOG_DEBUG();
37     currentState_ = static_cast<int32_t>(TouchGuideState::TOUCH_GUIDING);
38 }
39 
StartUp()40 void TouchGuider::StartUp()
41 {
42     HILOG_DEBUG();
43     touchGuideListener_ = std::make_unique<TouchGuideListener>(*this);
44     gestureRecognizer_.RegisterListener(*touchGuideListener_.get());
45     runner_ = Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner();
46     if (!runner_) {
47         HILOG_ERROR("get runner failed");
48         return;
49     }
50 
51     handler_ = std::make_shared<TGEventHandler>(runner_, *this);
52     if (!handler_) {
53         HILOG_ERROR("create event handler failed");
54         return;
55     }
56 }
57 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)58 void TGEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
59 {
60     HILOG_DEBUG();
61     switch (event->GetInnerEventId()) {
62         case TouchGuider::EXIT_GESTURE_REC_MSG:
63             tgServer_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_GUIDE_GESTURE_END);
64             break;
65         case TouchGuider::SEND_HOVER_ENTER_MOVE_MSG:
66             HoverEnterAndMoveRunner();
67             break;
68         case TouchGuider::SEND_HOVER_EXIT_MSG:
69             HoverExitRunner();
70             break;
71         case TouchGuider::SEND_TOUCH_INTERACTION_END_MSG:
72             tgServer_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
73             break;
74         case TouchGuider::SEND_TOUCH_GUIDE_END_MSG:
75             tgServer_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_GUIDE_END);
76             break;
77         default:
78             break;
79     }
80 }
81 
OnPointerEvent(MMI::PointerEvent & event)82 bool TouchGuider::OnPointerEvent(MMI::PointerEvent &event)
83 {
84     HILOG_DEBUG();
85     if (event.GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
86         EventTransmission::OnPointerEvent(event);
87         return false;
88     }
89     if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_CANCEL) {
90         Clear(event);
91         return true;
92     }
93     RecordReceivedEvent(event);
94     if (gestureRecognizer_.OnPointerEvent(event)) {
95         return true;
96     }
97     switch (static_cast<TouchGuideState>(currentState_)) {
98         case TouchGuideState::TOUCH_GUIDING:
99             HandleTouchGuidingState(event);
100             break;
101         case TouchGuideState::DRAGGING:
102             HandleDraggingState(event);
103             break;
104         case TouchGuideState::TRANSMITTING:
105             HandleTransmitingState(event);
106             break;
107         default:
108             break;
109     }
110     return true;
111 }
112 
DestroyEvents()113 void TouchGuider::DestroyEvents()
114 {
115     HILOG_DEBUG();
116 
117     Clear();
118     EventTransmission::DestroyEvents();
119 }
120 
SendAccessibilityEventToAA(EventType eventType)121 void TouchGuider::SendAccessibilityEventToAA(EventType eventType)
122 {
123     HILOG_DEBUG("eventType is 0x%{public}x.", eventType);
124 
125     AccessibilityEventInfo eventInfo {};
126     eventInfo.SetEventType(eventType);
127     int32_t windowsId = Singleton<AccessibilityWindowManager>::GetInstance().activeWindowId_;
128     eventInfo.SetWindowId(windowsId);
129     Singleton<AccessibleAbilityManagerService>::GetInstance().SendEvent(eventInfo);
130     if (eventType == EventType::TYPE_TOUCH_GUIDE_BEGIN) {
131         isTouchGuiding_ = true;
132     } else if (eventType == EventType::TYPE_TOUCH_GUIDE_END) {
133         isTouchGuiding_ = false;
134     }
135 }
136 
SendGestureEventToAA(GestureType gestureId)137 void TouchGuider::SendGestureEventToAA(GestureType gestureId)
138 {
139     HILOG_DEBUG("gestureId is %{public}d.", gestureId);
140 
141     AccessibilityEventInfo eventInfo {};
142     int32_t windowsId = Singleton<AccessibilityWindowManager>::GetInstance().activeWindowId_;
143     eventInfo.SetWindowId(windowsId);
144     eventInfo.SetEventType(EventType::TYPE_GESTURE_EVENT);
145     eventInfo.SetGestureType(gestureId);
146     Singleton<AccessibleAbilityManagerService>::GetInstance().SendEvent(eventInfo);
147 }
148 
SendEventToMultimodal(MMI::PointerEvent & event,int32_t action)149 void TouchGuider::SendEventToMultimodal(MMI::PointerEvent &event, int32_t action)
150 {
151     HILOG_DEBUG("action:%{public}d, SourceType:%{public}d.", action, event.GetSourceType());
152 
153     switch (action) {
154         case HOVER_MOVE:
155             if (event.GetSourceType() == MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
156                 event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_MOVE);
157                 event.SetSourceType(MMI::PointerEvent::SOURCE_TYPE_MOUSE);
158             }
159             break;
160         case POINTER_DOWN:
161             if (event.GetSourceType() == MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
162                 event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_DOWN);
163             }
164             break;
165         case POINTER_UP:
166             if (event.GetSourceType() == MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
167                 event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_UP);
168             }
169             break;
170         default:
171             break;
172     }
173     EventTransmission::OnPointerEvent(event);
174     RecordInjectedEvent(event);
175 }
176 
getHoverEnterAndMoveEvent()177 std::list<MMI::PointerEvent> TouchGuider::getHoverEnterAndMoveEvent()
178 {
179     HILOG_DEBUG();
180 
181     return pointerEvents_;
182 }
183 
ClearHoverEnterAndMoveEvent()184 void TouchGuider::ClearHoverEnterAndMoveEvent()
185 {
186     HILOG_DEBUG();
187 
188     pointerEvents_.clear();
189     gestureRecognizer_.Clear();
190 }
191 
getLastReceivedEvent()192 std::shared_ptr<MMI::PointerEvent> TouchGuider::getLastReceivedEvent()
193 {
194     HILOG_DEBUG();
195 
196     return receivedRecorder_.lastEvent;
197 }
198 
OnDoubleTap(MMI::PointerEvent & event)199 bool TouchGuider::TouchGuideListener::OnDoubleTap(MMI::PointerEvent &event)
200 {
201     HILOG_DEBUG();
202 
203     if (server_.currentState_ != static_cast<int32_t>(TouchGuideState::TOUCH_GUIDING)) {
204         return false;
205     }
206     server_.OnTouchInteractionEnd();
207     server_.CancelPostEventIfNeed(server_.SEND_HOVER_ENTER_MOVE_MSG);
208     server_.CancelPostEventIfNeed(server_.SEND_HOVER_EXIT_MSG);
209     server_.ForceSendAndRemoveEvent(server_.SEND_TOUCH_GUIDE_END_MSG, event);
210     server_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
211 
212     return server_.ExecuteActionOnAccessibilityFocused(ActionType::ACCESSIBILITY_ACTION_CLICK);
213 }
214 
OnStarted()215 bool TouchGuider::TouchGuideListener::OnStarted()
216 {
217     HILOG_DEBUG();
218 
219     server_.currentState_ = static_cast<int32_t>(TouchGuideState::TRANSMITTING);
220     server_.CancelPostEventIfNeed(SEND_HOVER_ENTER_MOVE_MSG);
221     server_.CancelPostEventIfNeed(SEND_HOVER_EXIT_MSG);
222     server_.PostGestureRecognizeExit();
223     server_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_GUIDE_GESTURE_BEGIN);
224     return true;
225 }
226 
OnCompleted(GestureType gestureId)227 bool TouchGuider::TouchGuideListener::OnCompleted(GestureType gestureId)
228 {
229     HILOG_DEBUG("gestureId is %{public}d", gestureId);
230 
231     if (server_.currentState_ != static_cast<int32_t>(TouchGuideState::TRANSMITTING)) {
232         HILOG_DEBUG("OnCompleted, state is not transmitting.");
233         return false;
234     }
235     server_.OnTouchInteractionEnd();
236     server_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_GUIDE_GESTURE_END);
237     server_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
238     server_.CancelPostEvent(EXIT_GESTURE_REC_MSG);
239     server_.currentState_ = static_cast<int32_t>(TouchGuideState::TOUCH_GUIDING);
240 
241     // Send customize gesture type to aa
242     server_.SendGestureEventToAA(gestureId);
243     return true;
244 }
245 
OnCancelled(MMI::PointerEvent & event)246 bool TouchGuider::TouchGuideListener::OnCancelled(MMI::PointerEvent &event)
247 {
248     HILOG_DEBUG();
249 
250     switch (static_cast<TouchGuideState>(server_.currentState_)) {
251         case TouchGuideState::TRANSMITTING:
252             server_.OnTouchInteractionEnd();
253             server_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_GUIDE_GESTURE_END);
254             if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP &&
255                 event.GetPointerIds().size() == POINTER_COUNT_1) {
256                 server_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
257             }
258             server_.CancelPostEvent(EXIT_GESTURE_REC_MSG);
259             server_.currentState_ = static_cast<int32_t>(TouchGuideState::TOUCH_GUIDING);
260             break;
261         case TouchGuideState::TOUCH_GUIDING:
262             server_.pointerEvents_.push_back(event);
263             server_.ForceSendAndRemoveEvent(SEND_HOVER_ENTER_MOVE_MSG, event);
264             server_.CancelPostEventIfNeed(SEND_HOVER_EXIT_MSG);
265             server_.SendEventToMultimodal(event, HOVER_MOVE);
266             break;
267         default:
268             return false;
269     }
270     return true;
271 }
272 
SetFindFocusedElementInfoResult(const AccessibilityElementInfo & info,const int32_t requestId)273 void TouchGuider::ElementOperatorCallbackImpl::SetFindFocusedElementInfoResult(const AccessibilityElementInfo &info,
274     const int32_t requestId)
275 {
276     HILOG_DEBUG("Response [requestId:%{public}d]", requestId);
277     accessibilityInfoResult_ = info;
278     promise_.set_value();
279 }
280 
SetSearchElementInfoByTextResult(const std::vector<AccessibilityElementInfo> & infos,const int32_t requestId)281 void TouchGuider::ElementOperatorCallbackImpl::SetSearchElementInfoByTextResult(
282     const std::vector<AccessibilityElementInfo> &infos, const int32_t requestId)
283 {
284     HILOG_DEBUG("Response [requestId:%{public}d]", requestId);
285     elementInfosResult_ = infos;
286     promise_.set_value();
287 }
288 
SetSearchElementInfoByAccessibilityIdResult(const std::vector<AccessibilityElementInfo> & infos,const int32_t requestId)289 void TouchGuider::ElementOperatorCallbackImpl::SetSearchElementInfoByAccessibilityIdResult(
290     const std::vector<AccessibilityElementInfo> &infos, const int32_t requestId)
291 {
292     HILOG_DEBUG("Response [requestId:%{public}d]", requestId);
293     elementInfosResult_ = infos;
294     promise_.set_value();
295 }
296 
SetFocusMoveSearchResult(const AccessibilityElementInfo & info,const int32_t requestId)297 void TouchGuider::ElementOperatorCallbackImpl::SetFocusMoveSearchResult(const AccessibilityElementInfo &info,
298     const int32_t requestId)
299 {
300     HILOG_DEBUG("Response [requestId:%{public}d]", requestId);
301     accessibilityInfoResult_ = info;
302     promise_.set_value();
303 }
304 
SetExecuteActionResult(const bool succeeded,const int32_t requestId)305 void TouchGuider::ElementOperatorCallbackImpl::SetExecuteActionResult(const bool succeeded, const int32_t requestId)
306 {
307     HILOG_DEBUG("Response [result:%{public}d, requestId:%{public}d]", succeeded, requestId);
308     executeActionResult_ = succeeded;
309     promise_.set_value();
310 }
311 
HandleTouchGuidingState(MMI::PointerEvent & event)312 void TouchGuider::HandleTouchGuidingState(MMI::PointerEvent &event)
313 {
314     HILOG_DEBUG();
315 
316     switch (event.GetPointerAction()) {
317         case MMI::PointerEvent::POINTER_ACTION_DOWN:
318             if (event.GetPointerIds().size() == POINTER_COUNT_1) {
319                 HandleTouchGuidingStateInnerDown(event);
320             } else {
321                 CancelPostEventIfNeed(SEND_HOVER_ENTER_MOVE_MSG);
322                 CancelPostEventIfNeed(SEND_HOVER_EXIT_MSG);
323             }
324             break;
325         case MMI::PointerEvent::POINTER_ACTION_MOVE:
326             HandleTouchGuidingStateInnerMove(event);
327             break;
328         case MMI::PointerEvent::POINTER_ACTION_UP:
329             if (event.GetPointerIds().size() == POINTER_COUNT_1) {
330                 OnTouchInteractionEnd();
331                 if (HasEventPending(SEND_HOVER_ENTER_MOVE_MSG)) {
332                     PostHoverExit();
333                 } else {
334                     SendExitEvents();
335                 }
336                 if (!HasEventPending(SEND_TOUCH_INTERACTION_END_MSG)) {
337                     PostAccessibilityEvent(SEND_TOUCH_INTERACTION_END_MSG);
338                 }
339             }
340             break;
341         default:
342             break;
343     }
344 }
345 
HandleDraggingState(MMI::PointerEvent & event)346 void TouchGuider::HandleDraggingState(MMI::PointerEvent &event)
347 {
348     HILOG_DEBUG();
349 
350     switch (event.GetPointerAction()) {
351         case MMI::PointerEvent::POINTER_ACTION_DOWN:
352             if (event.GetPointerIds().size() == POINTER_COUNT_1) {
353                 Clear(event);
354             } else {
355                 currentState_ = static_cast<int32_t>(TouchGuideState::TRANSMITTING);
356                 SendEventToMultimodal(event, POINTER_UP);
357                 SendAllDownEvents(event);
358             }
359             break;
360         case MMI::PointerEvent::POINTER_ACTION_MOVE:
361             HandleDraggingStateInnerMove(event);
362             break;
363         case MMI::PointerEvent::POINTER_ACTION_UP:
364             if (event.GetPointerIds().size() == POINTER_COUNT_1) {
365                 OnTouchInteractionEnd();
366                 SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
367                 SendEventToMultimodal(event, NO_CHANGE);
368                 currentState_ = static_cast<int32_t>(TouchGuideState::TOUCH_GUIDING);
369             } else {
370                 SendEventToMultimodal(event, NO_CHANGE);
371             }
372             break;
373         default:
374             break;
375     }
376 }
377 
HandleTransmitingState(MMI::PointerEvent & event)378 void TouchGuider::HandleTransmitingState(MMI::PointerEvent &event)
379 {
380     HILOG_DEBUG();
381 
382     switch (event.GetPointerAction()) {
383         case MMI::PointerEvent::POINTER_ACTION_DOWN:
384             if (event.GetPointerIds().size() == POINTER_COUNT_1) {
385                 Clear(event);
386             }
387             break;
388         case MMI::PointerEvent::POINTER_ACTION_UP:
389             if (event.GetPointerIds().size() == POINTER_COUNT_1) {
390                 if (longPressPointId_ >= 0) {
391                     // Adjust this event's location.
392                     MMI::PointerEvent::PointerItem pointer = {};
393                     event.GetPointerItem(event.GetPointerId(), pointer);
394                     pointer.SetDisplayX(pointer.GetDisplayX() + longPressOffsetX_);
395                     pointer.SetDisplayY(pointer.GetDisplayY() + longPressOffsetY_);
396                     event.RemovePointerItem(event.GetPointerId());
397                     event.AddPointerItem(pointer);
398                     longPressPointId_ = INIT_POINT_ID;
399                     longPressOffsetX_ = INIT_MMIPOINT;
400                     longPressOffsetY_ = INIT_MMIPOINT;
401                 }
402                 SendEventToMultimodal(event, NO_CHANGE);
403                 OnTouchInteractionEnd();
404                 SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
405                 currentState_ = static_cast<int32_t>(TouchGuideState::TOUCH_GUIDING);
406             }
407             break;
408         default:
409             SendEventToMultimodal(event, NO_CHANGE);
410             break;
411     }
412 }
413 
Clear(MMI::PointerEvent & event)414 void TouchGuider::Clear(MMI::PointerEvent &event)
415 {
416     HILOG_DEBUG();
417 
418     if (currentState_ == static_cast<int32_t>(TouchGuideState::TOUCH_GUIDING)) {
419         SendExitEvents();
420     } else if (currentState_ == static_cast<int32_t>(TouchGuideState::DRAGGING) ||
421         currentState_ == static_cast<int32_t>(TouchGuideState::TRANSMITTING)) {
422         SendUpForAllInjectedEvent(event);
423     }
424 
425     CancelPostEvent(EXIT_GESTURE_REC_MSG);
426     CancelPostEvent(SEND_TOUCH_INTERACTION_END_MSG);
427     CancelPostEvent(SEND_TOUCH_GUIDE_END_MSG);
428     CancelPostEventIfNeed(SEND_HOVER_ENTER_MOVE_MSG);
429     CancelPostEventIfNeed(SEND_HOVER_EXIT_MSG);
430     ClearInjectedEventRecorder();
431     ClearReceivedEventRecorder();
432     pointerEvents_.clear();
433     currentState_ = static_cast<int32_t>(TouchGuideState::TOUCH_GUIDING);
434     isTouchGuiding_ = false;
435     gestureRecognizer_.Clear();
436     longPressPointId_ = INIT_POINT_ID;
437     longPressOffsetX_ = INIT_MMIPOINT;
438     longPressOffsetY_ = INIT_MMIPOINT;
439     OnTouchInteractionEnd();
440 }
441 
Clear()442 void TouchGuider::Clear()
443 {
444     HILOG_DEBUG();
445 
446     std::shared_ptr<MMI::PointerEvent> event = getLastReceivedEvent();
447     if (event) {
448         Clear(*event);
449     }
450 }
451 
SendExitEvents()452 void TouchGuider::SendExitEvents()
453 {
454     HILOG_DEBUG();
455 
456     if (!HasEventPending(SEND_TOUCH_GUIDE_END_MSG)) {
457         PostAccessibilityEvent(SEND_TOUCH_GUIDE_END_MSG);
458     }
459 }
460 
HandleTouchGuidingStateInnerDown(MMI::PointerEvent & event)461 void TouchGuider::HandleTouchGuidingStateInnerDown(MMI::PointerEvent &event)
462 {
463     HILOG_DEBUG();
464 
465     OnTouchInteractionStart();
466     CancelPostEventIfNeed(SEND_HOVER_ENTER_MOVE_MSG);
467     CancelPostEventIfNeed(SEND_HOVER_EXIT_MSG);
468     if (isTouchGuiding_) {
469         SendExitEvents();
470     }
471     if (!gestureRecognizer_.IsfirstTap()) {
472         ForceSendAndRemoveEvent(SEND_TOUCH_GUIDE_END_MSG, event);
473         ForceSendAndRemoveEvent(SEND_TOUCH_INTERACTION_END_MSG, event);
474         SendAccessibilityEventToAA(EventType::TYPE_TOUCH_BEGIN);
475         if (!isTouchGuiding_) {
476             if (!HasEventPending(SEND_HOVER_ENTER_MOVE_MSG)) {
477                 PostHoverEnterAndMove(event);
478             } else {
479                 pointerEvents_.push_back(event);
480             }
481         }
482     } else {
483         CancelPostEvent(SEND_TOUCH_INTERACTION_END_MSG);
484     }
485 }
486 
HandleTouchGuidingStateInnerMove(MMI::PointerEvent & event)487 void TouchGuider::HandleTouchGuidingStateInnerMove(MMI::PointerEvent &event)
488 {
489     HILOG_DEBUG();
490 
491     switch (event.GetPointerIds().size()) {
492         case POINTER_COUNT_1:
493             if (HasEventPending(SEND_HOVER_ENTER_MOVE_MSG)) {
494                 pointerEvents_.push_back(event);
495             } else if (isTouchGuiding_) {
496                 SendEventToMultimodal(event, HOVER_MOVE);
497             }
498             break;
499         case POINTER_COUNT_2:
500             CancelPostEventIfNeed(SEND_HOVER_ENTER_MOVE_MSG);
501             CancelPostEventIfNeed(SEND_HOVER_EXIT_MSG);
502             if (IsDragGestureAccept(event)) {
503                 currentState_ =  static_cast<int32_t>(TouchGuideState::DRAGGING);
504                 SendEventToMultimodal(event, POINTER_DOWN);
505             } else {
506                 currentState_ = static_cast<int32_t>(TouchGuideState::TRANSMITTING);
507                 SendAllDownEvents(event);
508             }
509             break;
510         default:
511             if (HasEventPending(SEND_HOVER_ENTER_MOVE_MSG)) {
512                 CancelPostEventIfNeed(SEND_HOVER_ENTER_MOVE_MSG);
513                 CancelPostEventIfNeed(SEND_HOVER_EXIT_MSG);
514             } else {
515                 SendExitEvents();
516             }
517             currentState_ = static_cast<int32_t>(TouchGuideState::TRANSMITTING);
518             SendAllDownEvents(event);
519             break;
520     }
521 }
522 
HandleDraggingStateInnerMove(MMI::PointerEvent & event)523 void TouchGuider::HandleDraggingStateInnerMove(MMI::PointerEvent &event)
524 {
525     HILOG_DEBUG();
526 
527     std::vector<int32_t> pIds = event.GetPointerIds();
528     int32_t pointCount = pIds.size();
529     if (pointCount == POINTER_COUNT_1) {
530         HILOG_DEBUG("Only two pointers can be received in the dragging state");
531     } else if (pointCount == POINTER_COUNT_2 && IsDragGestureAccept(event)) {
532         // Get densityPixels from WMS
533         AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
534         auto display = displayMgr.GetDefaultDisplay();
535         float densityPixels = display->GetVirtualPixelRatio();
536         int32_t miniZoomPointerDistance = static_cast<int32_t>(MINI_POINTER_DISTANCE_DIP * densityPixels);
537         MMI::PointerEvent::PointerItem pointerF = {};
538         MMI::PointerEvent::PointerItem pointerS = {};
539         event.GetPointerItem(pIds[INDEX_0], pointerF);
540         event.GetPointerItem(pIds[INDEX_1], pointerS);
541         float xPointF = pointerF.GetDisplayX();
542         float xPointS = pointerS.GetDisplayX();
543         float yPointF = pointerF.GetDisplayY();
544         float yPointS = pointerS.GetDisplayY();
545         float offsetX = abs(xPointF - xPointS);
546         float offsetY = abs(yPointF - yPointS);
547         double duration = hypot(offsetX, offsetY);
548         if (duration > miniZoomPointerDistance) {
549             // Adjust this event's location.
550             MMI::PointerEvent::PointerItem pointer = {};
551             event.GetPointerItem(event.GetPointerId(), pointer);
552             pointer.SetDisplayX(pointer.GetDisplayX() + DIVIDE_2(offsetX));
553             pointer.SetDisplayY(pointer.GetDisplayY() + DIVIDE_2(offsetY));
554             event.RemovePointerItem(event.GetPointerId());
555             event.AddPointerItem(pointer);
556         }
557         SendEventToMultimodal(event, NO_CHANGE);
558     } else {
559         currentState_ = static_cast<int32_t>(TouchGuideState::TRANSMITTING);
560         SendEventToMultimodal(event, POINTER_UP);
561         SendAllDownEvents(event);
562     }
563 }
564 
GetAngleCos(float offsetX,float offsetY,bool isGetX)565 float TouchGuider::GetAngleCos(float offsetX, float offsetY, bool isGetX)
566 {
567     HILOG_DEBUG();
568 
569     float ret = isGetX ? offsetX : offsetY;
570     double duration = hypot(offsetX, offsetY);
571     if (duration < - EPSINON || duration > EPSINON) {
572         ret = ret / duration;
573     }
574     return ret;
575 }
576 
IsDragGestureAccept(MMI::PointerEvent & event)577 bool TouchGuider::IsDragGestureAccept(MMI::PointerEvent &event)
578 {
579     HILOG_DEBUG();
580 
581     std::vector<int32_t> pIds = event.GetPointerIds();
582     MMI::PointerEvent::PointerItem pointerF = {};
583     MMI::PointerEvent::PointerItem pointerS = {};
584     if (!event.GetPointerItem(pIds[0], pointerF)) {
585         HILOG_WARN("GetPointerItem(%d) failed", pIds[0]);
586     }
587     if (!event.GetPointerItem(pIds[1], pointerS)) {
588         HILOG_WARN("GetPointerItem(%d) failed", pIds[1]);
589     }
590 
591     float xPointF = pointerF.GetDisplayX();
592     float xPointS = pointerS.GetDisplayX();
593     float yPointF = pointerF.GetDisplayY();
594     float yPointS = pointerS.GetDisplayY();
595     float xPointDownF = receivedRecorder_.pointerDownX[INDEX_0];
596     float xPointDownS = receivedRecorder_.pointerDownX[INDEX_1];
597     float yPointDownF = receivedRecorder_.pointerDownY[INDEX_0];
598     float yPointDownS = receivedRecorder_.pointerDownY[INDEX_1];
599     float firstOffsetX = xPointF - xPointDownF;
600     float firstOffsetY = yPointF - yPointDownF;
601     float secondOffsetX = xPointS - xPointDownS;
602     float secondOffsetY = yPointS - yPointDownS;
603     if ((!firstOffsetX && !firstOffsetY) ||
604         (!secondOffsetX && !secondOffsetY)) {
605         return true;
606     }
607 
608     float firstXCos = GetAngleCos(firstOffsetX, firstOffsetY, true);
609     float firstYCos = GetAngleCos(firstOffsetX, firstOffsetY, false);
610     float secondXCos = GetAngleCos(secondOffsetX, secondOffsetY, true);
611     float secondYCos = GetAngleCos(secondOffsetX, secondOffsetY, false);
612     if ((firstXCos * secondXCos + firstYCos * secondYCos) < MAX_DRAG_GESTURE_COSINE) {
613         return false;
614     }
615     return true;
616 }
617 
RecordInjectedEvent(MMI::PointerEvent & event)618 void TouchGuider::RecordInjectedEvent(MMI::PointerEvent &event)
619 {
620     HILOG_DEBUG();
621 
622     int32_t pointerId = event.GetPointerId();
623     switch (event.GetPointerAction()) {
624         case MMI::PointerEvent::POINTER_ACTION_DOWN:
625             injectedRecorder_.downPointerNum++;
626             injectedRecorder_.downPointers |= (1 << pointerId);
627             injectedRecorder_.lastDownTime = event.GetActionTime() / US_TO_MS;
628             break;
629         case MMI::PointerEvent::POINTER_ACTION_UP:
630             injectedRecorder_.downPointers &= ~(1 << pointerId);
631             if (injectedRecorder_.downPointerNum > 0) {
632                 injectedRecorder_.downPointerNum--;
633             }
634             if (!injectedRecorder_.downPointers) {
635                 injectedRecorder_.lastDownTime = 0;
636             }
637             break;
638         case MMI::PointerEvent::POINTER_ACTION_MOVE:
639             injectedRecorder_.lastHoverEvent = std::make_shared<MMI::PointerEvent>(event);
640             break;
641         default:
642             break;
643     }
644 }
645 
RecordReceivedEvent(MMI::PointerEvent & event)646 void TouchGuider::RecordReceivedEvent(MMI::PointerEvent &event)
647 {
648     HILOG_DEBUG();
649 
650     int32_t pointId = event.GetPointerId();
651     MMI::PointerEvent::PointerItem pointer;
652     if (!event.GetPointerItem(pointId, pointer)) {
653         HILOG_ERROR("GetPointerItem(%d) failed", pointId);
654     }
655     receivedRecorder_.lastEvent = std::make_shared<MMI::PointerEvent>(event);
656     switch (event.GetPointerAction()) {
657         case MMI::PointerEvent::POINTER_ACTION_DOWN:
658             receivedRecorder_.pointerDownX[pointId] = pointer.GetDisplayX();
659             receivedRecorder_.pointerDownY[pointId] = pointer.GetDisplayY();
660             break;
661         case MMI::PointerEvent::POINTER_ACTION_UP:
662             receivedRecorder_.pointerDownX[pointId] = 0;
663             receivedRecorder_.pointerDownY[pointId] = 0;
664             break;
665         default:
666             break;
667     }
668 }
669 
ClearReceivedEventRecorder()670 void TouchGuider::ClearReceivedEventRecorder()
671 {
672     HILOG_DEBUG();
673 
674     (void)memset_s(receivedRecorder_.pointerDownX, sizeof(receivedRecorder_.pointerDownX),
675              0, sizeof(receivedRecorder_.pointerDownX));
676     (void)memset_s(receivedRecorder_.pointerDownY, sizeof(receivedRecorder_.pointerDownY),
677              0, sizeof(receivedRecorder_.pointerDownY));
678     receivedRecorder_.lastEvent = nullptr;
679 }
680 
ClearInjectedEventRecorder()681 void TouchGuider::ClearInjectedEventRecorder()
682 {
683     HILOG_DEBUG();
684 
685     injectedRecorder_.downPointerNum = 0;
686     injectedRecorder_.downPointers = 0;
687     injectedRecorder_.lastHoverEvent = nullptr;
688 }
689 
SendAllDownEvents(MMI::PointerEvent & event)690 void TouchGuider::SendAllDownEvents(MMI::PointerEvent &event)
691 {
692     HILOG_DEBUG();
693 
694     std::vector<int32_t> pIds = event.GetPointerIds();
695     for (auto& pId : pIds) {
696         if (!(injectedRecorder_.downPointers & (1 << pId))) {
697             event.SetPointerId(pId);
698             SendEventToMultimodal(event, POINTER_DOWN);
699         }
700     }
701 }
702 
SendUpForAllInjectedEvent(MMI::PointerEvent & event)703 void TouchGuider::SendUpForAllInjectedEvent(MMI::PointerEvent &event)
704 {
705     HILOG_DEBUG();
706 
707     std::vector<int32_t> pIds = event.GetPointerIds();
708     for (const auto& pId : pIds) {
709         if (!(injectedRecorder_.downPointers & (1 << pId))) {
710             continue;
711         }
712         SendEventToMultimodal(event, POINTER_UP);
713     }
714 }
715 
PostGestureRecognizeExit()716 void TouchGuider::PostGestureRecognizeExit()
717 {
718     HILOG_DEBUG();
719 
720     handler_->SendEvent(EXIT_GESTURE_REC_MSG, 0, EXIT_GESTURE_REC_TIMEOUT);
721 }
722 
PostHoverEnterAndMove(MMI::PointerEvent & event)723 void TouchGuider::PostHoverEnterAndMove(MMI::PointerEvent &event)
724 {
725     HILOG_DEBUG();
726 
727     CancelPostEventIfNeed(SEND_HOVER_ENTER_MOVE_MSG);
728     pointerEvents_.push_back(event);
729     handler_->SendEvent(SEND_HOVER_ENTER_MOVE_MSG, 0, DOUBLE_TAP_TIMEOUT / US_TO_MS);
730 }
731 
PostHoverExit()732 void TouchGuider::PostHoverExit()
733 {
734     HILOG_DEBUG();
735 
736     CancelPostEventIfNeed(SEND_HOVER_EXIT_MSG);
737     handler_->SendEvent(SEND_HOVER_EXIT_MSG, 0, DOUBLE_TAP_TIMEOUT / US_TO_MS);
738 }
739 
PostAccessibilityEvent(uint32_t innerEventID)740 void TouchGuider::PostAccessibilityEvent(uint32_t innerEventID)
741 {
742     HILOG_DEBUG();
743 
744     handler_->SendEvent(innerEventID, 0, EXIT_GESTURE_REC_TIMEOUT);
745 }
746 
CancelPostEvent(uint32_t innerEventID)747 void TouchGuider::CancelPostEvent(uint32_t innerEventID)
748 {
749     HILOG_DEBUG();
750 
751     handler_->RemoveEvent(innerEventID);
752 }
753 
CancelPostEventIfNeed(uint32_t innerEventID)754 void TouchGuider::CancelPostEventIfNeed(uint32_t innerEventID)
755 {
756     HILOG_DEBUG();
757 
758     if (HasEventPending(innerEventID)) {
759         handler_->RemoveEvent(innerEventID);
760         if (innerEventID == SEND_HOVER_ENTER_MOVE_MSG) {
761             pointerEvents_.clear();
762         }
763     }
764 }
765 
HasEventPending(uint32_t innerEventID)766 bool TouchGuider::HasEventPending(uint32_t innerEventID)
767 {
768     HILOG_DEBUG();
769 
770     return handler_->HasInnerEvent(innerEventID);
771 }
772 
ForceSendAndRemoveEvent(uint32_t innerEventID,MMI::PointerEvent & event)773 void TouchGuider::ForceSendAndRemoveEvent(uint32_t innerEventID, MMI::PointerEvent &event)
774 {
775     HILOG_DEBUG();
776 
777     if (!HasEventPending(innerEventID)) {
778         HILOG_DEBUG("No pending event.");
779         return;
780     }
781 
782     switch (innerEventID) {
783         case SEND_HOVER_ENTER_MOVE_MSG:
784             SendAccessibilityEventToAA(EventType::TYPE_TOUCH_GUIDE_BEGIN);
785             if (pointerEvents_.empty()) {
786                 break;
787             }
788             for (auto iter = pointerEvents_.begin(); iter != pointerEvents_.end(); ++iter) {
789                 SendEventToMultimodal(*iter, HOVER_MOVE);
790             }
791             pointerEvents_.clear();
792             break;
793         case SEND_TOUCH_INTERACTION_END_MSG:
794             SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
795             break;
796         case SEND_TOUCH_GUIDE_END_MSG:
797             SendAccessibilityEventToAA(EventType::TYPE_TOUCH_GUIDE_END);
798             break;
799         default:
800             break;
801     }
802     CancelPostEvent(innerEventID);
803 }
804 
ExecuteActionOnAccessibilityFocused(const ActionType & action)805 bool TouchGuider::ExecuteActionOnAccessibilityFocused(const ActionType &action)
806 {
807     HILOG_DEBUG();
808 
809     int32_t elementId = -1;
810     int32_t windowId = ANY_WINDOW_ID;
811     int32_t focusType = FOCUS_TYPE_ACCESSIBILITY;
812     int32_t realId = Singleton<AccessibilityWindowManager>::GetInstance().ConvertToRealWindowId(windowId, focusType);
813 
814     sptr<AccessibilityAccountData> accountData =
815         Singleton<AccessibleAbilityManagerService>::GetInstance().GetCurrentAccountData();
816     if (!accountData) {
817         HILOG_ERROR("GetCurrentAccountData failed");
818         return false;
819     }
820 
821     sptr<AccessibilityWindowConnection> connection = accountData->GetAccessibilityWindowConnection(realId);
822     if (!connection || !connection->GetProxy()) {
823         HILOG_ERROR("GetAccessibilityWindowConnection failed");
824         return false;
825     }
826 
827     uint32_t timeOut = 5000;
828     sptr<ElementOperatorCallbackImpl> focusCallback = new(std::nothrow) ElementOperatorCallbackImpl();
829     if (!focusCallback) {
830         HILOG_ERROR("Failed to create focusCallback.");
831         return false;
832     }
833     std::future<void> focusFuture = focusCallback->promise_.get_future();
834     connection->GetProxy()->FindFocusedElementInfo(elementId, focusType, 0, focusCallback);
835     std::future_status waitFocus = focusFuture.wait_for(std::chrono::milliseconds(timeOut));
836     if (waitFocus != std::future_status::ready) {
837         HILOG_ERROR("Failed to wait result");
838         return false;
839     }
840     elementId = focusCallback->accessibilityInfoResult_.GetAccessibilityId();
841 
842     std::map<std::string, std::string> actionArguments {};
843     sptr<ElementOperatorCallbackImpl> actionCallback = new(std::nothrow) ElementOperatorCallbackImpl();
844     if (!actionCallback) {
845         HILOG_ERROR("Failed to create actionCallback.");
846         return false;
847     }
848     std::future<void> actionFuture = actionCallback->promise_.get_future();
849     connection->GetProxy()->ExecuteAction(elementId, action, actionArguments, 1, actionCallback);
850     std::future_status waitAction = actionFuture.wait_for(std::chrono::milliseconds(timeOut));
851     if (waitAction != std::future_status::ready) {
852         HILOG_ERROR("Failed to wait result");
853         return false;
854     }
855 
856     return actionCallback->executeActionResult_;
857 }
858 
HoverEnterAndMoveRunner()859 void TGEventHandler::HoverEnterAndMoveRunner()
860 {
861     HILOG_DEBUG();
862 
863     std::list<MMI::PointerEvent> motionEvent = tgServer_.getHoverEnterAndMoveEvent();
864     tgServer_.SendAccessibilityEventToAA(EventType::TYPE_TOUCH_GUIDE_BEGIN);
865     if (!motionEvent.empty()) {
866         for (auto iter = motionEvent.begin(); iter != motionEvent.end(); ++iter) {
867             tgServer_.SendEventToMultimodal(*iter, HOVER_MOVE);
868         }
869     }
870     tgServer_.ClearHoverEnterAndMoveEvent();
871 }
872 
HoverExitRunner()873 void TGEventHandler::HoverExitRunner()
874 {
875     HILOG_DEBUG();
876 
877     std::shared_ptr<MMI::PointerEvent> pEvent = tgServer_.getLastReceivedEvent();
878     tgServer_.SendEventToMultimodal(*pEvent, HOVER_MOVE);
879     if (!HasInnerEvent(TouchGuider::SEND_TOUCH_GUIDE_END_MSG)) {
880         RemoveEvent(TouchGuider::SEND_TOUCH_GUIDE_END_MSG);
881         SendEvent(TouchGuider::SEND_TOUCH_GUIDE_END_MSG, 0, EXIT_GESTURE_REC_TIMEOUT);
882     }
883     if (HasInnerEvent(TouchGuider::SEND_TOUCH_INTERACTION_END_MSG)) {
884         RemoveEvent(TouchGuider::SEND_TOUCH_INTERACTION_END_MSG);
885         SendEvent(TouchGuider::SEND_TOUCH_INTERACTION_END_MSG, 0, EXIT_GESTURE_REC_TIMEOUT);
886     }
887 }
888 } // namespace Accessibility
889 } // namespace OHOS