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