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