• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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_exploration.h"
17 #include "accessibility_window_manager.h"
18 #include "accessibility_event_info.h"
19 #include "hilog_wrapper.h"
20 #include "securec.h"
21 #include "utils.h"
22 
23 namespace OHOS {
24 namespace Accessibility {
25 
InitOneFingerGestureFuncMap()26 void TouchExploration::InitOneFingerGestureFuncMap()
27 {
28     handleEventFuncMap_ = {
29         {TouchExplorationState::TOUCH_INIT, {
30             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleInitStateDown)},
31             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleInitStateUp)},
32             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleInitStateMove)},
33             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)},
34             {MMI::PointerEvent::POINTER_ACTION_PULL_MOVE, BIND(HandleInitStateMove)},
35             {MMI::PointerEvent::POINTER_ACTION_PULL_UP, BIND(HandleInitStateUp)}}
36         },
37         {TouchExplorationState::ONE_FINGER_DOWN, {
38             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerDownStateDown)},
39             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleOneFingerDownStateUp)},
40             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleOneFingerDownStateMove)},
41             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
42         },
43         {TouchExplorationState::ONE_FINGER_LONG_PRESS, {
44             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerLongPressStateDown)},
45             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleOneFingerLongPressStateUp)},
46             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleOneFingerLongPressStateMove)},
47             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
48         },
49         {TouchExplorationState::ONE_FINGER_SWIPE, {
50             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerSwipeStateDown)},
51             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleOneFingerSwipeStateUp)},
52             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleOneFingerSwipeStateMove)},
53             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
54         },
55         {TouchExplorationState::ONE_FINGER_SINGLE_TAP, {
56             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerSingleTapStateDown)},
57             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
58         },
59         {TouchExplorationState::ONE_FINGER_SINGLE_TAP_THEN_DOWN, {
60             {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleOneFingerSingleTapThenDownStateDown)},
61             {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleOneFingerSingleTapThenDownStateUp)},
62             {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleOneFingerSingleTapThenDownStateMove)},
63             {MMI::PointerEvent::POINTER_ACTION_CANCEL, BIND(HandleCancelEvent)}}
64         }
65     };
66 }
67 
TouchExplorationEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,TouchExploration & server)68 TouchExplorationEventHandler::TouchExplorationEventHandler(
69     const std::shared_ptr<AppExecFwk::EventRunner> &runner, TouchExploration &server): AppExecFwk::EventHandler(runner),
70     server_(server)
71 {
72 }
73 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)74 void TouchExplorationEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
75 {
76     HILOG_INFO("TEhandler process event id = %{public}d, currentState is %{public}d", event->GetInnerEventId(),
77         server_.GetCurrentState());
78 
79     TouchExplorationMsg msg = static_cast<TouchExplorationMsg>(event->GetInnerEventId());
80     switch (msg) {
81         case TouchExplorationMsg::SEND_HOVER_MSG:
82             server_.HoverEventRunner();
83             server_.Clear();
84             server_.SetCurrentState(TouchExplorationState::TOUCH_INIT);
85             break;
86         case TouchExplorationMsg::LONG_PRESS_MSG:
87             server_.CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
88             server_.HoverEventRunner();
89             server_.SetCurrentState(TouchExplorationState::ONE_FINGER_LONG_PRESS);
90             break;
91         case TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG:
92             if (!(server_.SendDoubleTapAndLongPressDownEvent())) {
93                 server_.SetCurrentState(TouchExplorationState::INVALID);
94                 return;
95             }
96             server_.SetCurrentState(TouchExplorationState::ONE_FINGER_DOUBLE_TAP_AND_LONG_PRESS);
97             break;
98         case TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG:
99             server_.HoverEventRunner();
100             server_.SetCurrentState(TouchExplorationState::ONE_FINGER_LONG_PRESS);
101             break;
102         case TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG:
103             if (server_.GetCurrentState() == TouchExplorationState::TWO_FINGERS_TAP ||
104                 server_.GetCurrentState() == TouchExplorationState::THREE_FINGERS_TAP ||
105                 server_.GetCurrentState() == TouchExplorationState::FOUR_FINGERS_TAP) {
106                 server_.Clear();
107                 server_.SetCurrentState(TouchExplorationState::INVALID);
108             }
109             break;
110         default:
111             server_.ProcessMultiFingerGesture(msg);
112             break;
113     }
114 }
115 
TouchExploration()116 TouchExploration::TouchExploration()
117 {
118     InitOneFingerGestureFuncMap();
119     InitTwoFingerGestureFuncMap();
120     InitThreeFingerGestureFuncMap();
121     InitFourFingerGestureFuncMap();
122 
123 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
124     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
125     auto display = displayMgr.GetDefaultDisplay();
126     if (display == nullptr) {
127         HILOG_ERROR("get display is nullptr");
128         return;
129     }
130     moveThreshold_ = CalculateMoveThreshold(display->GetDpi());
131     xMinPixels_ = display->GetWidth() * PIXEL_MULTIPLIER;
132     yMinPixels_ = display->GetHeight() * PIXEL_MULTIPLIER;
133     float density = display->GetVirtualPixelRatio();
134     multiTapOffsetThresh_ = static_cast<int32_t>(density * MULTI_TAP_SLOP + MULTI_TAP_SLOP_DELTA);
135     mMinPixelsBetweenSamplesX_ = display->GetWidth() * PIXEL_MULTIPLIER;
136     mMinPixelsBetweenSamplesY_ = display->GetHeight() * PIXEL_MULTIPLIER;
137 #else
138     HILOG_WARN("not support display manager");
139     moveThreshold_ = 1;
140     xMinPixels_ = 1;
141     yMinPixels_ = 1;
142     multiTapOffsetThresh_ = static_cast<int32_t>(1 * MULTI_TAP_SLOP + MULTI_TAP_SLOP_DELTA);
143     mMinPixelsBetweenSamplesX_ = 1;
144     mMinPixelsBetweenSamplesY_ = 1;
145 #endif
146 }
147 
StartUp()148 void TouchExploration::StartUp()
149 {
150     runner_ = Singleton<AccessibleAbilityManagerService>::GetInstance().GetInputManagerRunner();
151     if (!runner_) {
152         HILOG_ERROR("get runner failed");
153         return;
154     }
155 
156     handler_ = std::make_shared<TouchExplorationEventHandler>(runner_, *this);
157     if (!handler_) {
158         HILOG_ERROR("create event handler failed");
159         return;
160     }
161 
162     gestureHandler_ = std::make_shared<AppExecFwk::EventHandler>(
163         Singleton<AccessibleAbilityManagerService>::GetInstance().GetGestureRunner());
164 }
165 
OnPointerEvent(MMI::PointerEvent & event)166 bool TouchExploration::OnPointerEvent(MMI::PointerEvent &event)
167 {
168     HILOG_DEBUG("PointerAction:%{public}d, PointerId:%{public}d, currentState:%{public}d.", event.GetPointerAction(),
169         event.GetPointerId(), static_cast<int32_t>(GetCurrentState()));
170     if (event.GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
171         EventTransmission::OnPointerEvent(event);
172         return false;
173     }
174 
175     MMI::PointerEvent::PointerItem pointerItem;
176     std::vector<int32_t> pIds = event.GetPointerIds();
177     for (auto& pId : pIds) {
178         if (!event.GetPointerItem(pId, pointerItem)) {
179             HILOG_ERROR("get pointerItem(%{public}d) failed", pId);
180             return false;
181         }
182         if (pointerItem.GetToolType() == MMI::PointerEvent::TOOL_TYPE_PEN) {
183             EventTransmission::OnPointerEvent(event);
184             return false;
185         }
186     }
187 
188     // Send touch event to AA to control volume adjustment.
189     SendTouchEventToAA(event);
190 
191     HandlePointerEvent(event);
192     return true;
193 }
194 
HandlePointerEvent(MMI::PointerEvent & event)195 void TouchExploration::HandlePointerEvent(MMI::PointerEvent &event)
196 {
197     HILOG_DEBUG();
198     if (GetCurrentState() == TouchExplorationState::PASSING_THROUGH) {
199         HandlePassingThroughState(event);
200         return;
201     }
202     if (GetCurrentState() == TouchExplorationState::INVALID) {
203         HandleInvalidState(event);
204         return;
205     }
206     if (GetCurrentState() == TouchExplorationState::ONE_FINGER_DOUBLE_TAP_AND_LONG_PRESS) {
207         HandleOneFingerDoubleTapAndLongPressState(event);
208         return;
209     }
210 
211     auto iter = handleEventFuncMap_.find(GetCurrentState());
212     if (iter != handleEventFuncMap_.end()) {
213         auto funcMap = iter->second.find(event.GetPointerAction());
214         if (funcMap != iter->second.end()) {
215             funcMap->second(event);
216             return;
217         }
218     }
219 
220     MMI::PointerEvent::PointerItem pointerItem;
221     event.GetPointerItem(event.GetPointerId(), pointerItem);
222     // If the event is not processed, GetCurrentState() is set to TOUCH_INIT when the last finger is lifted.
223     if (event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1) ||
224         !pointerItem.IsPressed()) {
225         Clear();
226         SetCurrentState(TouchExplorationState::TOUCH_INIT);
227     }
228 }
229 
SendAccessibilityEventToAA(EventType eventType)230 void TouchExploration::SendAccessibilityEventToAA(EventType eventType)
231 {
232     HILOG_INFO("eventType is 0x%{public}x.", eventType);
233 
234     AccessibilityEventInfo eventInfo {};
235     eventInfo.SetEventType(eventType);
236     int32_t windowsId = Singleton<AccessibilityWindowManager>::GetInstance().GetActiveWindowId();
237     eventInfo.SetWindowId(windowsId);
238     Singleton<AccessibleAbilityManagerService>::GetInstance().SendEvent(eventInfo);
239 }
240 
SendTouchEventToAA(MMI::PointerEvent & event)241 void TouchExploration::SendTouchEventToAA(MMI::PointerEvent &event)
242 {
243     if (event.GetPointerIds().size() != static_cast<uint32_t>(PointerCount::POINTER_COUNT_1) ||
244         event.GetPointerId() >= SIMULATE_POINTER_ID) {
245         return;
246     }
247 
248     MMI::PointerEvent::PointerItem pointerItem {};
249     event.GetPointerItem(event.GetPointerId(), pointerItem);
250     if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
251         SendAccessibilityEventToAA(EventType::TYPE_TOUCH_BEGIN);
252     } else if (!pointerItem.IsPressed()) {
253         SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
254     }
255 }
256 
SendGestureEventToAA(GestureType gestureId)257 void TouchExploration::SendGestureEventToAA(GestureType gestureId)
258 {
259     HILOG_INFO("gestureId is %{public}d.", static_cast<int32_t>(gestureId));
260 
261     AccessibilityEventInfo eventInfo {};
262     int32_t windowsId = Singleton<AccessibilityWindowManager>::GetInstance().GetActiveWindowId();
263     eventInfo.SetWindowId(windowsId);
264     eventInfo.SetEventType(EventType::TYPE_GESTURE_EVENT);
265     eventInfo.SetGestureType(gestureId);
266     Singleton<AccessibleAbilityManagerService>::GetInstance().SendEvent(eventInfo);
267 }
268 
SendEventToMultimodal(MMI::PointerEvent event,ChangeAction action)269 void TouchExploration::SendEventToMultimodal(MMI::PointerEvent event, ChangeAction action)
270 {
271     HILOG_DEBUG("action:%{public}d, SourceType:%{public}d.", action, event.GetSourceType());
272 
273     switch (action) {
274         case ChangeAction::HOVER_MOVE:
275             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_MOVE);
276             break;
277         case ChangeAction::POINTER_DOWN:
278             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_DOWN);
279             break;
280         case ChangeAction::POINTER_UP:
281             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_UP);
282             break;
283         case ChangeAction::HOVER_ENTER:
284             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_ENTER);
285             break;
286         case ChangeAction::HOVER_EXIT:
287             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_EXIT);
288             break;
289         case ChangeAction::HOVER_CANCEL:
290             event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_CANCEL);
291             break;
292         default:
293             break;
294     }
295     EventTransmission::OnPointerEvent(event);
296 }
297 
SendScreenWakeUpEvent(MMI::PointerEvent & event)298 void TouchExploration::SendScreenWakeUpEvent(MMI::PointerEvent &event)
299 {
300     HILOG_DEBUG();
301     // Send move event to wake up the screen and prevent the screen from turning off.
302     MMI::PointerEvent::PointerItem pointerItem {};
303     for (auto& pId : event.GetPointerIds()) {
304         event.GetPointerItem(pId, pointerItem);
305         pointerItem.SetPressed(false);
306         event.RemovePointerItem(pId);
307         event.AddPointerItem(pointerItem);
308     }
309     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
310 }
311 
HoverEventRunner()312 void TouchExploration::HoverEventRunner()
313 {
314     for (auto& event : receivedPointerEvents_) {
315         if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
316             SendEventToMultimodal(event, ChangeAction::HOVER_ENTER);
317         } else if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) {
318             SendEventToMultimodal(event, ChangeAction::HOVER_MOVE);
319         } else if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) {
320             SendEventToMultimodal(event, ChangeAction::HOVER_EXIT);
321         }
322     }
323 }
324 
HandleInitStateDown(MMI::PointerEvent & event)325 void TouchExploration::HandleInitStateDown(MMI::PointerEvent &event)
326 {
327     if (event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) {
328         receivedPointerEvents_.push_back(event);
329         SetCurrentState(TouchExplorationState::ONE_FINGER_DOWN);
330         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SEND_HOVER_MSG), 0,
331             static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
332         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::LONG_PRESS_MSG), 0,
333             static_cast<int32_t>(TimeoutDuration::LONG_PRESS_TIMEOUT));
334         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG), 0,
335             static_cast<int32_t>(TimeoutDuration::MULTI_FINGER_TAP_INTERVAL_TIMEOUT));
336         return;
337     }
338 
339     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
340     SetCurrentState(TouchExplorationState::PASSING_THROUGH);
341 }
342 
HandleInitStateUp(MMI::PointerEvent & event)343 void TouchExploration::HandleInitStateUp(MMI::PointerEvent &event)
344 {
345     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
346 
347     if (event.GetPointerIds().size() != static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) {
348         SetCurrentState(TouchExplorationState::PASSING_THROUGH);
349     }
350 }
351 
HandleInitStateMove(MMI::PointerEvent & event)352 void TouchExploration::HandleInitStateMove(MMI::PointerEvent &event)
353 {
354     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
355     SetCurrentState(TouchExplorationState::PASSING_THROUGH);
356 }
357 
HandlePassingThroughState(MMI::PointerEvent & event)358 void TouchExploration::HandlePassingThroughState(MMI::PointerEvent &event)
359 {
360     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
361 
362     MMI::PointerEvent::PointerItem pointerItem {};
363     event.GetPointerItem(event.GetPointerId(), pointerItem);
364 
365     // the last finger is lifted
366     if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
367         (!pointerItem.IsPressed())) {
368         SetCurrentState(TouchExplorationState::TOUCH_INIT);
369     }
370 }
371 
HandleInvalidState(MMI::PointerEvent & event)372 void TouchExploration::HandleInvalidState(MMI::PointerEvent &event)
373 {
374     MMI::PointerEvent::PointerItem pointerItem {};
375     event.GetPointerItem(event.GetPointerId(), pointerItem);
376 
377     if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) {
378         SendScreenWakeUpEvent(event);
379     }
380 
381     // the last finger is lifted
382     if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
383         (!pointerItem.IsPressed())) {
384         SetCurrentState(TouchExplorationState::TOUCH_INIT);
385     }
386 }
387 
HandleCancelEvent(MMI::PointerEvent & event)388 void TouchExploration::HandleCancelEvent(MMI::PointerEvent &event)
389 {
390     if (GetCurrentState() == TouchExplorationState::TWO_FINGERS_DRAG && event.GetPointerId() == draggingPid_) {
391         SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
392     }
393     SendEventToMultimodal(event, ChangeAction::HOVER_CANCEL);
394 
395     MMI::PointerEvent::PointerItem pointerItem {};
396     event.GetPointerItem(event.GetPointerId(), pointerItem);
397 
398     // the last finger is lifted
399     if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
400         (!pointerItem.IsPressed())) {
401         Clear();
402         SetCurrentState(TouchExplorationState::TOUCH_INIT);
403     }
404 }
405 
HandleOneFingerDownStateDown(MMI::PointerEvent & event)406 void TouchExploration::HandleOneFingerDownStateDown(MMI::PointerEvent &event)
407 {
408     receivedPointerEvents_.push_back(event);
409     CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
410     CancelPostEvent(TouchExplorationMsg::LONG_PRESS_MSG);
411     draggingPid_ = event.GetPointerId();
412     if (!handler_->HasInnerEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG))) {
413         SetCurrentState(TouchExplorationState::TWO_FINGERS_UNKNOWN);
414         return;
415     }
416 
417     CancelPostEvent(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG);
418     handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG), 0,
419         static_cast<int32_t>(TimeoutDuration::MULTI_FINGER_TAP_INTERVAL_TIMEOUT));
420     handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::TWO_FINGER_SINGLE_TAP_MSG), 0,
421         static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
422     handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::TWO_FINGER_LONG_PRESS_MSG), 0,
423         static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
424     SetCurrentState(TouchExplorationState::TWO_FINGERS_DOWN);
425 }
426 
HandleOneFingerDownStateUp(MMI::PointerEvent & event)427 void TouchExploration::HandleOneFingerDownStateUp(MMI::PointerEvent &event)
428 {
429     CancelPostEvent(TouchExplorationMsg::LONG_PRESS_MSG);
430     CancelPostEvent(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG);
431     receivedPointerEvents_.push_back(event);
432     SetCurrentState(TouchExplorationState::ONE_FINGER_SINGLE_TAP);
433 }
434 
HandleOneFingerDownStateMove(MMI::PointerEvent & event)435 void TouchExploration::HandleOneFingerDownStateMove(MMI::PointerEvent &event)
436 {
437     receivedPointerEvents_.push_back(event);
438 
439     MMI::PointerEvent::PointerItem pointerItem;
440     event.GetPointerItem(event.GetPointerId(), pointerItem);
441 
442     MMI::PointerEvent startPointerEvent = receivedPointerEvents_.front();
443     MMI::PointerEvent::PointerItem startPointerItem;
444     startPointerEvent.GetPointerItem(startPointerEvent.GetPointerId(), startPointerItem);
445 
446     float offsetX = startPointerItem.GetDisplayX() - pointerItem.GetDisplayX();
447     float offsetY = startPointerItem.GetDisplayY() - pointerItem.GetDisplayY();
448     double duration = hypot(offsetX, offsetY);
449     if (duration > moveThreshold_) {
450         CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
451         CancelPostEvent(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG);
452         CancelPostEvent(TouchExplorationMsg::LONG_PRESS_MSG);
453         receivedPointerEvents_.clear();
454         receivedPointerEvents_.push_back(event);
455         oneFingerSwipePrePointer_ = startPointerItem;
456         Pointer mp;
457         mp.px_ = static_cast<float>(startPointerItem.GetDisplayX());
458         mp.py_ = static_cast<float>(startPointerItem.GetDisplayY());
459         oneFingerSwipeRoute_.clear();
460         oneFingerSwipeRoute_.push_back(mp);
461         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG), 0,
462             static_cast<int32_t>(TimeoutDuration::SWIPE_COMPLETE_TIMEOUT));
463         SetCurrentState(TouchExplorationState::ONE_FINGER_SWIPE);
464         SendScreenWakeUpEvent(event);
465     }
466 }
467 
HandleOneFingerLongPressStateDown(MMI::PointerEvent & event)468 void TouchExploration::HandleOneFingerLongPressStateDown(MMI::PointerEvent &event)
469 {
470     receivedPointerEvents_.push_back(event);
471     draggingPid_ = event.GetPointerId();
472     SetCurrentState(TouchExplorationState::TWO_FINGERS_UNKNOWN);
473 }
474 
HandleOneFingerLongPressStateUp(MMI::PointerEvent & event)475 void TouchExploration::HandleOneFingerLongPressStateUp(MMI::PointerEvent &event)
476 {
477     Clear();
478     SendEventToMultimodal(event, ChangeAction::HOVER_EXIT);
479     SetCurrentState(TouchExplorationState::TOUCH_INIT);
480 }
481 
HandleOneFingerLongPressStateMove(MMI::PointerEvent & event)482 void TouchExploration::HandleOneFingerLongPressStateMove(MMI::PointerEvent &event)
483 {
484     SendEventToMultimodal(event, ChangeAction::HOVER_MOVE);
485 }
486 
HandleOneFingerSwipeStateDown(MMI::PointerEvent & event)487 void TouchExploration::HandleOneFingerSwipeStateDown(MMI::PointerEvent &event)
488 {
489     Clear();
490     CancelPostEvent(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG);
491     SetCurrentState(TouchExplorationState::INVALID);
492 }
493 
AddOneFingerSwipeEvent(MMI::PointerEvent & event)494 void TouchExploration::AddOneFingerSwipeEvent(MMI::PointerEvent &event)
495 {
496     HILOG_DEBUG();
497     MMI::PointerEvent::PointerItem pointerItem {};
498     event.GetPointerItem(event.GetPointerId(), pointerItem);
499 
500     if (receivedPointerEvents_.empty()) {
501         HILOG_ERROR("received pointer event is null!");
502         return;
503     }
504 
505     MMI::PointerEvent preMoveEvent = receivedPointerEvents_.back();
506     MMI::PointerEvent::PointerItem preMovePointerItem {};
507     preMoveEvent.GetPointerItem(preMoveEvent.GetPointerId(), preMovePointerItem);
508     float offsetX = preMovePointerItem.GetDisplayX() - pointerItem.GetDisplayX();
509     float offsetY = preMovePointerItem.GetDisplayY() - pointerItem.GetDisplayY();
510     double duration = hypot(offsetX, offsetY);
511     if (duration > moveThreshold_) {
512         receivedPointerEvents_.push_back(event);
513         CancelPostEvent(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG);
514         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG), 0,
515             static_cast<int32_t>(TimeoutDuration::SWIPE_COMPLETE_TIMEOUT));
516     }
517 
518     if ((abs(pointerItem.GetDisplayX() - oneFingerSwipePrePointer_.GetDisplayX())) >= xMinPixels_ ||
519         (abs(pointerItem.GetDisplayY() - oneFingerSwipePrePointer_.GetDisplayY())) >= yMinPixels_) {
520         Pointer mp;
521         oneFingerSwipePrePointer_ = pointerItem;
522         mp.px_ = pointerItem.GetDisplayX();
523         mp.py_ = pointerItem.GetDisplayY();
524         oneFingerSwipeRoute_.push_back(mp);
525     }
526 }
527 
GetOneFingerSwipePath()528 std::vector<Pointer> TouchExploration::GetOneFingerSwipePath()
529 {
530     HILOG_DEBUG();
531     std::vector<Pointer> pointerPath;
532     Pointer firstSeparation = oneFingerSwipeRoute_[0];
533     Pointer nextPoint;
534     Pointer newSeparation;
535     float xUnitVector = 0;
536     float yUnitVector = 0;
537     float xVector = 0;
538     float yVector = 0;
539     float vectorLength = 0;
540     int32_t numSinceFirstSep = 0;
541 
542     pointerPath.push_back(firstSeparation);
543     for (size_t i = 1; i < oneFingerSwipeRoute_.size(); i++) {
544         nextPoint = oneFingerSwipeRoute_[i];
545         if (numSinceFirstSep > 0) {
546             xVector = xUnitVector / numSinceFirstSep;
547             yVector = yUnitVector / numSinceFirstSep;
548             newSeparation.px_ = vectorLength * xVector + firstSeparation.px_;
549             newSeparation.py_ = vectorLength * yVector + firstSeparation.py_;
550 
551             float xNextUnitVector = nextPoint.px_ - newSeparation.px_;
552             float yNextUnitVector = nextPoint.py_ - newSeparation.py_;
553             float nextVectorLength = hypot(xNextUnitVector, yNextUnitVector);
554             if (nextVectorLength > EPSINON) {
555                 xNextUnitVector /= nextVectorLength;
556                 yNextUnitVector /= nextVectorLength;
557             }
558 
559             if ((xVector * xNextUnitVector + yVector * yNextUnitVector) < DEGREES_THRESHOLD) {
560                 pointerPath.push_back(newSeparation);
561                 firstSeparation = newSeparation;
562                 xUnitVector = 0;
563                 yUnitVector = 0;
564                 numSinceFirstSep = 0;
565             }
566         }
567         xVector = nextPoint.px_ - firstSeparation.px_;
568         yVector = nextPoint.py_ - firstSeparation.py_;
569         vectorLength = hypot(xVector, yVector);
570         numSinceFirstSep += 1;
571         if (vectorLength > EPSINON) {
572             xUnitVector += xVector / vectorLength;
573             yUnitVector += yVector / vectorLength;
574         }
575     }
576     pointerPath.push_back(nextPoint);
577     return pointerPath;
578 }
579 
GetSwipeDirection(const int32_t dx,const int32_t dy)580 int32_t TouchExploration::GetSwipeDirection(const int32_t dx, const int32_t dy)
581 {
582     if (abs(dx) > abs(dy)) {
583         return dx > EPSINON ? SWIPE_RIGHT : SWIPE_LEFT;
584     } else {
585         return dy < EPSINON ? SWIPE_UP : SWIPE_DOWN;
586     }
587 }
588 
HandleOneFingerSwipeStateUp(MMI::PointerEvent & event)589 void TouchExploration::HandleOneFingerSwipeStateUp(MMI::PointerEvent &event)
590 {
591     AddOneFingerSwipeEvent(event);
592     CancelPostEvent(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG);
593 
594     if (oneFingerSwipeRoute_.size() < LIMIT_SIZE_TWO) {
595         Clear();
596         SetCurrentState(TouchExplorationState::TOUCH_INIT);
597         return;
598     }
599 
600     std::vector<Pointer> pointerPath = GetOneFingerSwipePath();
601     if (pointerPath.size() == LIMIT_SIZE_TWO) {
602         int32_t swipeDirection = GetSwipeDirection(pointerPath[1].px_ - pointerPath[0].px_,
603             pointerPath[1].py_ - pointerPath[0].py_);
604         SendGestureEventToAA(GESTURE_DIRECTION[swipeDirection]);
605     } else if (pointerPath.size() == LIMIT_SIZE_THREE) {
606         int32_t swipeDirectionH = GetSwipeDirection(pointerPath[1].px_ - pointerPath[0].px_,
607             pointerPath[1].py_ - pointerPath[0].py_);
608         int32_t swipeDirectionHV = GetSwipeDirection(pointerPath[2].px_ - pointerPath[1].px_,
609             pointerPath[2].py_ - pointerPath[1].py_);
610         SendGestureEventToAA(GESTURE_DIRECTION_TO_ID[swipeDirectionH][swipeDirectionHV]);
611     }
612 
613     Clear();
614     SetCurrentState(TouchExplorationState::TOUCH_INIT);
615 }
616 
HandleOneFingerSwipeStateMove(MMI::PointerEvent & event)617 void TouchExploration::HandleOneFingerSwipeStateMove(MMI::PointerEvent &event)
618 {
619     AddOneFingerSwipeEvent(event);
620     SendScreenWakeUpEvent(event);
621 }
622 
RecordFocusedLocation(MMI::PointerEvent & event)623 bool TouchExploration::RecordFocusedLocation(MMI::PointerEvent &event)
624 {
625     HILOG_DEBUG();
626     AccessibilityElementInfo focusedElementInfo {};
627     bool ret = Singleton<AccessibleAbilityManagerService>::GetInstance().FindFocusedElement(focusedElementInfo,
628         FIND_FOCUS_TIMEOUT);
629     if (!ret) {
630         HILOG_ERROR("find focused element failed.");
631         return false;
632     }
633 
634     MMI::PointerEvent::PointerItem pointer {};
635     event.GetPointerItem(event.GetPointerId(), pointer);
636     offsetX_ = (focusedElementInfo.GetRectInScreen().GetLeftTopXScreenPostion() +
637         focusedElementInfo.GetRectInScreen().GetRightBottomXScreenPostion()) / DIVIDE_NUM - pointer.GetDisplayX();
638     offsetY_ = (focusedElementInfo.GetRectInScreen().GetLeftTopYScreenPostion() +
639         focusedElementInfo.GetRectInScreen().GetRightBottomYScreenPostion()) / DIVIDE_NUM - pointer.GetDisplayY();
640     return true;
641 }
642 
HandleOneFingerSingleTapStateDown(MMI::PointerEvent & event)643 void TouchExploration::HandleOneFingerSingleTapStateDown(MMI::PointerEvent &event)
644 {
645     CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
646     if (receivedPointerEvents_.empty()) {
647         Clear();
648         SetCurrentState(TouchExplorationState::INVALID);
649         return;
650     }
651 
652     MMI::PointerEvent::PointerItem curPointerItem;
653     event.GetPointerItem(event.GetPointerId(), curPointerItem);
654     MMI::PointerEvent preDownEvent = receivedPointerEvents_.front();
655     MMI::PointerEvent::PointerItem preDownPointerItem;
656     preDownEvent.GetPointerItem(preDownEvent.GetPointerId(), preDownPointerItem);
657     int32_t durationX = preDownPointerItem.GetDisplayX() - curPointerItem.GetDisplayX();
658     int32_t durationY = preDownPointerItem.GetDisplayY() - curPointerItem.GetDisplayY();
659     if (durationX * durationX + durationY * durationY > multiTapOffsetThresh_ * multiTapOffsetThresh_) {
660         HoverEventRunner();
661         Clear();
662         receivedPointerEvents_.push_back(event);
663         SetCurrentState(TouchExplorationState::ONE_FINGER_DOWN);
664         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SEND_HOVER_MSG), 0,
665             static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
666         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::LONG_PRESS_MSG), 0,
667             static_cast<int32_t>(TimeoutDuration::LONG_PRESS_TIMEOUT));
668         handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG), 0,
669             static_cast<int32_t>(TimeoutDuration::MULTI_FINGER_TAP_INTERVAL_TIMEOUT));
670         return;
671     }
672 
673     Clear();
674     receivedPointerEvents_.push_back(event);
675     handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG), 0,
676         static_cast<int32_t>(TimeoutDuration::LONG_PRESS_TIMEOUT));
677     SetCurrentState(TouchExplorationState::ONE_FINGER_SINGLE_TAP_THEN_DOWN);
678 }
679 
HandleOneFingerSingleTapThenDownStateDown(MMI::PointerEvent & event)680 void TouchExploration::HandleOneFingerSingleTapThenDownStateDown(MMI::PointerEvent &event)
681 {
682     Clear();
683     CancelPostEvent(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG);
684     SetCurrentState(TouchExplorationState::INVALID);
685 }
686 
HandleOneFingerSingleTapThenDownStateUp(MMI::PointerEvent & event)687 void TouchExploration::HandleOneFingerSingleTapThenDownStateUp(MMI::PointerEvent &event)
688 {
689     CancelPostEvent(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG);
690     Clear();
691     SetCurrentState(TouchExplorationState::TOUCH_INIT);
692 
693     if (!gestureHandler_) {
694         HILOG_ERROR("gestureHandler is nullptr!");
695         return;
696     }
697 
698     gestureHandler_->PostTask([this]() {
699         Singleton<AccessibleAbilityManagerService>::GetInstance().ExecuteActionOnAccessibilityFocused(
700             ActionType::ACCESSIBILITY_ACTION_CLICK);
701         }, "TASK_CLICK_ON_FOCUS");
702 }
703 
HandleOneFingerSingleTapThenDownStateMove(MMI::PointerEvent & event)704 void TouchExploration::HandleOneFingerSingleTapThenDownStateMove(MMI::PointerEvent &event)
705 {
706     MMI::PointerEvent::PointerItem pointerItem;
707     event.GetPointerItem(event.GetPointerId(), pointerItem);
708 
709     MMI::PointerEvent startPointerEvent = receivedPointerEvents_.front();
710     MMI::PointerEvent::PointerItem startPointerItem;
711     startPointerEvent.GetPointerItem(startPointerEvent.GetPointerId(), startPointerItem);
712 
713     float offsetX = startPointerItem.GetDisplayX() - pointerItem.GetDisplayX();
714     float offsetY = startPointerItem.GetDisplayY() - pointerItem.GetDisplayY();
715     double duration = hypot(offsetX, offsetY);
716     if (duration > moveThreshold_) {
717         CancelPostEvent(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG);
718         Clear();
719         SetCurrentState(TouchExplorationState::INVALID);
720     }
721 }
722 
OffsetEvent(MMI::PointerEvent & event)723 void TouchExploration::OffsetEvent(MMI::PointerEvent &event)
724 {
725     HILOG_DEBUG();
726     if (receivedPointerEvents_.empty()) {
727         HILOG_ERROR("received pointer event is null!");
728         return;
729     }
730 
731     MMI::PointerEvent startPointerEvent = receivedPointerEvents_.front();
732     if (event.GetPointerId() != startPointerEvent.GetPointerId()) {
733         return;
734     }
735 
736     MMI::PointerEvent::PointerItem pointer {};
737     event.GetPointerItem(event.GetPointerId(), pointer);
738     pointer.SetDisplayX(offsetX_ + pointer.GetDisplayX());
739     pointer.SetDisplayY(offsetY_ + pointer.GetDisplayY());
740     event.RemovePointerItem(event.GetPointerId());
741     event.AddPointerItem(pointer);
742 }
743 
SendDoubleTapAndLongPressDownEvent()744 bool TouchExploration::SendDoubleTapAndLongPressDownEvent()
745 {
746     if (receivedPointerEvents_.empty()) {
747         HILOG_ERROR("receivedPointerEvents_ is empty!");
748         return false;
749     }
750     if (!RecordFocusedLocation(receivedPointerEvents_.front())) {
751         return false;
752     }
753     OffsetEvent(receivedPointerEvents_.front());
754     SendEventToMultimodal(receivedPointerEvents_.front(), ChangeAction::NO_CHANGE);
755     return true;
756 }
757 
HandleOneFingerDoubleTapAndLongPressState(MMI::PointerEvent & event)758 void TouchExploration::HandleOneFingerDoubleTapAndLongPressState(MMI::PointerEvent &event)
759 {
760     OffsetEvent(event);
761     SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
762 
763     MMI::PointerEvent::PointerItem pointer {};
764     event.GetPointerItem(event.GetPointerId(), pointer);
765     if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
766         (!pointer.IsPressed())) {
767         Clear();
768         SetCurrentState(TouchExplorationState::TOUCH_INIT);
769     }
770 }
771 
Clear()772 void TouchExploration::Clear()
773 {
774     receivedPointerEvents_.clear();
775     draggingDownEvent_ = nullptr;
776     offsetX_ = 0;
777     offsetY_ = 0;
778     oneFingerSwipeRoute_.clear();
779     oneFingerSwipePrePointer_ = {};
780     draggingPid_ = -1;
781     multiTapNum_ = 0;
782     multiFingerSwipeDirection_ = -1;
783     multiFingerSwipeRoute_.clear();
784     multiFingerSwipePrePoint_.clear();
785 }
786 } // namespace Accessibility
787 } // namespace OHOS