1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed On an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "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 pointerIterm;
176 std::vector<int32_t> pIds = event.GetPointerIds();
177 for (auto& pId : pIds) {
178 if (!event.GetPointerItem(pId, pointerIterm)) {
179 HILOG_ERROR("get pointerItem(%{public}d) failed", pId);
180 return false;
181 }
182 if (pointerIterm.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 pointerIterm;
221 event.GetPointerItem(event.GetPointerId(), pointerIterm);
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 !pointerIterm.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 AccessibilityEventInfoParcel eventInfoParcel(eventInfo);
239 Singleton<AccessibleAbilityManagerService>::GetInstance().SendEvent(eventInfoParcel, 0);
240 }
241
SendTouchEventToAA(MMI::PointerEvent & event)242 void TouchExploration::SendTouchEventToAA(MMI::PointerEvent &event)
243 {
244 if (event.GetPointerIds().size() != static_cast<uint32_t>(PointerCount::POINTER_COUNT_1) ||
245 event.GetPointerId() >= SIMULATE_POINTER_ID) {
246 return;
247 }
248
249 MMI::PointerEvent::PointerItem pointerIterm {};
250 event.GetPointerItem(event.GetPointerId(), pointerIterm);
251 if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
252 SendAccessibilityEventToAA(EventType::TYPE_TOUCH_BEGIN);
253 } else if (!pointerIterm.IsPressed()) {
254 SendAccessibilityEventToAA(EventType::TYPE_TOUCH_END);
255 }
256 }
257
SendGestureEventToAA(GestureType gestureId)258 void TouchExploration::SendGestureEventToAA(GestureType gestureId)
259 {
260 HILOG_INFO("gestureId is %{public}d.", static_cast<int32_t>(gestureId));
261
262 AccessibilityEventInfo eventInfo {};
263 int32_t windowsId = Singleton<AccessibilityWindowManager>::GetInstance().GetActiveWindowId();
264 eventInfo.SetWindowId(windowsId);
265 eventInfo.SetEventType(EventType::TYPE_GESTURE_EVENT);
266 eventInfo.SetGestureType(gestureId);
267 AccessibilityEventInfoParcel eventInfoParcel(eventInfo);
268 Singleton<AccessibleAbilityManagerService>::GetInstance().SendEvent(eventInfoParcel, 0);
269 }
270
SendEventToMultimodal(MMI::PointerEvent event,ChangeAction action)271 void TouchExploration::SendEventToMultimodal(MMI::PointerEvent event, ChangeAction action)
272 {
273 HILOG_DEBUG("action:%{public}d, SourceType:%{public}d.", action, event.GetSourceType());
274
275 switch (action) {
276 case ChangeAction::HOVER_MOVE:
277 event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_MOVE);
278 break;
279 case ChangeAction::POINTER_DOWN:
280 event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_DOWN);
281 break;
282 case ChangeAction::POINTER_UP:
283 event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_UP);
284 break;
285 case ChangeAction::HOVER_ENTER:
286 event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_ENTER);
287 break;
288 case ChangeAction::HOVER_EXIT:
289 event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_EXIT);
290 break;
291 case ChangeAction::HOVER_CANCEL:
292 event.SetPointerAction(MMI::PointerEvent::POINTER_ACTION_HOVER_CANCEL);
293 break;
294 default:
295 break;
296 }
297 EventTransmission::OnPointerEvent(event);
298 }
299
SendScreenWakeUpEvent(MMI::PointerEvent & event)300 void TouchExploration::SendScreenWakeUpEvent(MMI::PointerEvent &event)
301 {
302 HILOG_DEBUG();
303 // Send move event to wake up the screen and prevent the screen from turning off.
304 MMI::PointerEvent::PointerItem pointerItem {};
305 for (auto& pId : event.GetPointerIds()) {
306 event.GetPointerItem(pId, pointerItem);
307 pointerItem.SetPressed(false);
308 event.RemovePointerItem(pId);
309 event.AddPointerItem(pointerItem);
310 }
311 SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
312 }
313
HoverEventRunner()314 void TouchExploration::HoverEventRunner()
315 {
316 for (auto& event : receivedPointerEvents_) {
317 if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN) {
318 SendEventToMultimodal(event, ChangeAction::HOVER_ENTER);
319 } else if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) {
320 SendEventToMultimodal(event, ChangeAction::HOVER_MOVE);
321 } else if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) {
322 SendEventToMultimodal(event, ChangeAction::HOVER_EXIT);
323 }
324 }
325 }
326
HandleInitStateDown(MMI::PointerEvent & event)327 void TouchExploration::HandleInitStateDown(MMI::PointerEvent &event)
328 {
329 if (event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) {
330 receivedPointerEvents_.push_back(event);
331 SetCurrentState(TouchExplorationState::ONE_FINGER_DOWN);
332 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SEND_HOVER_MSG), 0,
333 static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
334 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::LONG_PRESS_MSG), 0,
335 static_cast<int32_t>(TimeoutDuration::LONG_PRESS_TIMEOUT));
336 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG), 0,
337 static_cast<int32_t>(TimeoutDuration::MULTI_FINGER_TAP_INTERVAL_TIMEOUT));
338 return;
339 }
340
341 SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
342 SetCurrentState(TouchExplorationState::PASSING_THROUGH);
343 }
344
HandleInitStateUp(MMI::PointerEvent & event)345 void TouchExploration::HandleInitStateUp(MMI::PointerEvent &event)
346 {
347 SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
348
349 if (event.GetPointerIds().size() != static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) {
350 SetCurrentState(TouchExplorationState::PASSING_THROUGH);
351 }
352 }
353
HandleInitStateMove(MMI::PointerEvent & event)354 void TouchExploration::HandleInitStateMove(MMI::PointerEvent &event)
355 {
356 SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
357 SetCurrentState(TouchExplorationState::PASSING_THROUGH);
358 }
359
HandlePassingThroughState(MMI::PointerEvent & event)360 void TouchExploration::HandlePassingThroughState(MMI::PointerEvent &event)
361 {
362 SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
363
364 MMI::PointerEvent::PointerItem pointerIterm {};
365 event.GetPointerItem(event.GetPointerId(), pointerIterm);
366
367 // the last finger is lifted
368 if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
369 (!pointerIterm.IsPressed())) {
370 SetCurrentState(TouchExplorationState::TOUCH_INIT);
371 }
372 }
373
HandleInvalidState(MMI::PointerEvent & event)374 void TouchExploration::HandleInvalidState(MMI::PointerEvent &event)
375 {
376 MMI::PointerEvent::PointerItem pointerIterm {};
377 event.GetPointerItem(event.GetPointerId(), pointerIterm);
378
379 if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_MOVE) {
380 SendScreenWakeUpEvent(event);
381 }
382
383 // the last finger is lifted
384 if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
385 (!pointerIterm.IsPressed())) {
386 SetCurrentState(TouchExplorationState::TOUCH_INIT);
387 }
388 }
389
HandleCancelEvent(MMI::PointerEvent & event)390 void TouchExploration::HandleCancelEvent(MMI::PointerEvent &event)
391 {
392 if (GetCurrentState() == TouchExplorationState::TWO_FINGERS_DRAG && event.GetPointerId() == draggingPid_) {
393 SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
394 }
395 SendEventToMultimodal(event, ChangeAction::HOVER_CANCEL);
396
397 MMI::PointerEvent::PointerItem pointerIterm {};
398 event.GetPointerItem(event.GetPointerId(), pointerIterm);
399
400 // the last finger is lifted
401 if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
402 (!pointerIterm.IsPressed())) {
403 Clear();
404 SetCurrentState(TouchExplorationState::TOUCH_INIT);
405 }
406 }
407
HandleOneFingerDownStateDown(MMI::PointerEvent & event)408 void TouchExploration::HandleOneFingerDownStateDown(MMI::PointerEvent &event)
409 {
410 receivedPointerEvents_.push_back(event);
411 CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
412 CancelPostEvent(TouchExplorationMsg::LONG_PRESS_MSG);
413 draggingPid_ = event.GetPointerId();
414 if (!handler_->HasInnerEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG))) {
415 SetCurrentState(TouchExplorationState::TWO_FINGERS_UNKNOWN);
416 return;
417 }
418
419 CancelPostEvent(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG);
420 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG), 0,
421 static_cast<int32_t>(TimeoutDuration::MULTI_FINGER_TAP_INTERVAL_TIMEOUT));
422 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::TWO_FINGER_SINGLE_TAP_MSG), 0,
423 static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
424 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::TWO_FINGER_LONG_PRESS_MSG), 0,
425 static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
426 SetCurrentState(TouchExplorationState::TWO_FINGERS_DOWN);
427 }
428
HandleOneFingerDownStateUp(MMI::PointerEvent & event)429 void TouchExploration::HandleOneFingerDownStateUp(MMI::PointerEvent &event)
430 {
431 CancelPostEvent(TouchExplorationMsg::LONG_PRESS_MSG);
432 CancelPostEvent(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG);
433 receivedPointerEvents_.push_back(event);
434 SetCurrentState(TouchExplorationState::ONE_FINGER_SINGLE_TAP);
435 }
436
HandleOneFingerDownStateMove(MMI::PointerEvent & event)437 void TouchExploration::HandleOneFingerDownStateMove(MMI::PointerEvent &event)
438 {
439 receivedPointerEvents_.push_back(event);
440
441 MMI::PointerEvent::PointerItem pointerIterm;
442 event.GetPointerItem(event.GetPointerId(), pointerIterm);
443
444 MMI::PointerEvent startPointerEvent = receivedPointerEvents_.front();
445 MMI::PointerEvent::PointerItem startPointerIterm;
446 startPointerEvent.GetPointerItem(startPointerEvent.GetPointerId(), startPointerIterm);
447
448 float offsetX = startPointerIterm.GetDisplayX() - pointerIterm.GetDisplayX();
449 float offsetY = startPointerIterm.GetDisplayY() - pointerIterm.GetDisplayY();
450 double duration = hypot(offsetX, offsetY);
451 if (duration > moveThreshold_) {
452 CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
453 CancelPostEvent(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG);
454 CancelPostEvent(TouchExplorationMsg::LONG_PRESS_MSG);
455 receivedPointerEvents_.clear();
456 receivedPointerEvents_.push_back(event);
457 oneFingerSwipePrePointer_ = startPointerIterm;
458 Pointer mp;
459 mp.px_ = static_cast<float>(startPointerIterm.GetDisplayX());
460 mp.py_ = static_cast<float>(startPointerIterm.GetDisplayY());
461 oneFingerSwipeRoute_.clear();
462 oneFingerSwipeRoute_.push_back(mp);
463 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG), 0,
464 static_cast<int32_t>(TimeoutDuration::SWIPE_COMPLETE_TIMEOUT));
465 SetCurrentState(TouchExplorationState::ONE_FINGER_SWIPE);
466 SendScreenWakeUpEvent(event);
467 }
468 }
469
HandleOneFingerLongPressStateDown(MMI::PointerEvent & event)470 void TouchExploration::HandleOneFingerLongPressStateDown(MMI::PointerEvent &event)
471 {
472 receivedPointerEvents_.push_back(event);
473 draggingPid_ = event.GetPointerId();
474 SetCurrentState(TouchExplorationState::TWO_FINGERS_UNKNOWN);
475 }
476
HandleOneFingerLongPressStateUp(MMI::PointerEvent & event)477 void TouchExploration::HandleOneFingerLongPressStateUp(MMI::PointerEvent &event)
478 {
479 Clear();
480 SendEventToMultimodal(event, ChangeAction::HOVER_EXIT);
481 SetCurrentState(TouchExplorationState::TOUCH_INIT);
482 }
483
HandleOneFingerLongPressStateMove(MMI::PointerEvent & event)484 void TouchExploration::HandleOneFingerLongPressStateMove(MMI::PointerEvent &event)
485 {
486 SendEventToMultimodal(event, ChangeAction::HOVER_MOVE);
487 }
488
HandleOneFingerSwipeStateDown(MMI::PointerEvent & event)489 void TouchExploration::HandleOneFingerSwipeStateDown(MMI::PointerEvent &event)
490 {
491 Clear();
492 CancelPostEvent(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG);
493 SetCurrentState(TouchExplorationState::INVALID);
494 }
495
AddOneFingerSwipeEvent(MMI::PointerEvent & event)496 void TouchExploration::AddOneFingerSwipeEvent(MMI::PointerEvent &event)
497 {
498 HILOG_DEBUG();
499 MMI::PointerEvent::PointerItem pointerIterm {};
500 event.GetPointerItem(event.GetPointerId(), pointerIterm);
501
502 if (receivedPointerEvents_.empty()) {
503 HILOG_ERROR("received pointer event is null!");
504 return;
505 }
506
507 MMI::PointerEvent preMoveEvent = receivedPointerEvents_.back();
508 MMI::PointerEvent::PointerItem preMovePointerIterm {};
509 preMoveEvent.GetPointerItem(preMoveEvent.GetPointerId(), preMovePointerIterm);
510 float offsetX = preMovePointerIterm.GetDisplayX() - pointerIterm.GetDisplayX();
511 float offsetY = preMovePointerIterm.GetDisplayY() - pointerIterm.GetDisplayY();
512 double duration = hypot(offsetX, offsetY);
513 if (duration > moveThreshold_) {
514 receivedPointerEvents_.push_back(event);
515 CancelPostEvent(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG);
516 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG), 0,
517 static_cast<int32_t>(TimeoutDuration::SWIPE_COMPLETE_TIMEOUT));
518 }
519
520 if ((abs(pointerIterm.GetDisplayX() - oneFingerSwipePrePointer_.GetDisplayX())) >= xMinPixels_ ||
521 (abs(pointerIterm.GetDisplayY() - oneFingerSwipePrePointer_.GetDisplayY())) >= yMinPixels_) {
522 Pointer mp;
523 oneFingerSwipePrePointer_ = pointerIterm;
524 mp.px_ = pointerIterm.GetDisplayX();
525 mp.py_ = pointerIterm.GetDisplayY();
526 oneFingerSwipeRoute_.push_back(mp);
527 }
528 }
529
GetOneFingerSwipePath()530 std::vector<Pointer> TouchExploration::GetOneFingerSwipePath()
531 {
532 HILOG_DEBUG();
533 std::vector<Pointer> pointerPath;
534 Pointer firstSeparation = oneFingerSwipeRoute_[0];
535 Pointer nextPoint;
536 Pointer newSeparation;
537 float xUnitVector = 0;
538 float yUnitVector = 0;
539 float xVector = 0;
540 float yVector = 0;
541 float vectorLength = 0;
542 int32_t numSinceFirstSep = 0;
543
544 pointerPath.push_back(firstSeparation);
545 for (size_t i = 1; i < oneFingerSwipeRoute_.size(); i++) {
546 nextPoint = oneFingerSwipeRoute_[i];
547 if (numSinceFirstSep > 0) {
548 xVector = xUnitVector / numSinceFirstSep;
549 yVector = yUnitVector / numSinceFirstSep;
550 newSeparation.px_ = vectorLength * xVector + firstSeparation.px_;
551 newSeparation.py_ = vectorLength * yVector + firstSeparation.py_;
552
553 float xNextUnitVector = nextPoint.px_ - newSeparation.px_;
554 float yNextUnitVector = nextPoint.py_ - newSeparation.py_;
555 float nextVectorLength = hypot(xNextUnitVector, yNextUnitVector);
556 if (nextVectorLength > EPSINON) {
557 xNextUnitVector /= nextVectorLength;
558 yNextUnitVector /= nextVectorLength;
559 }
560
561 if ((xVector * xNextUnitVector + yVector * yNextUnitVector) < DEGREES_THRESHOLD) {
562 pointerPath.push_back(newSeparation);
563 firstSeparation = newSeparation;
564 xUnitVector = 0;
565 yUnitVector = 0;
566 numSinceFirstSep = 0;
567 }
568 }
569 xVector = nextPoint.px_ - firstSeparation.px_;
570 yVector = nextPoint.py_ - firstSeparation.py_;
571 vectorLength = hypot(xVector, yVector);
572 numSinceFirstSep += 1;
573 if (vectorLength > EPSINON) {
574 xUnitVector += xVector / vectorLength;
575 yUnitVector += yVector / vectorLength;
576 }
577 }
578 pointerPath.push_back(nextPoint);
579 return pointerPath;
580 }
581
GetSwipeDirection(const int32_t dx,const int32_t dy)582 int32_t TouchExploration::GetSwipeDirection(const int32_t dx, const int32_t dy)
583 {
584 if (abs(dx) > abs(dy)) {
585 return dx > EPSINON ? SWIPE_RIGHT : SWIPE_LEFT;
586 } else {
587 return dy < EPSINON ? SWIPE_UP : SWIPE_DOWN;
588 }
589 }
590
HandleOneFingerSwipeStateUp(MMI::PointerEvent & event)591 void TouchExploration::HandleOneFingerSwipeStateUp(MMI::PointerEvent &event)
592 {
593 AddOneFingerSwipeEvent(event);
594 CancelPostEvent(TouchExplorationMsg::SWIPE_COMPLETE_TIMEOUT_MSG);
595
596 if (oneFingerSwipeRoute_.size() < LIMIT_SIZE_TWO) {
597 Clear();
598 SetCurrentState(TouchExplorationState::TOUCH_INIT);
599 return;
600 }
601
602 std::vector<Pointer> pointerPath = GetOneFingerSwipePath();
603 if (pointerPath.size() == LIMIT_SIZE_TWO) {
604 int32_t swipeDirection = GetSwipeDirection(pointerPath[1].px_ - pointerPath[0].px_,
605 pointerPath[1].py_ - pointerPath[0].py_);
606 SendGestureEventToAA(GESTURE_DIRECTION[swipeDirection]);
607 } else if (pointerPath.size() == LIMIT_SIZE_THREE) {
608 int32_t swipeDirectionH = GetSwipeDirection(pointerPath[1].px_ - pointerPath[0].px_,
609 pointerPath[1].py_ - pointerPath[0].py_);
610 int32_t swipeDirectionHV = GetSwipeDirection(pointerPath[2].px_ - pointerPath[1].px_,
611 pointerPath[2].py_ - pointerPath[1].py_);
612 SendGestureEventToAA(GESTURE_DIRECTION_TO_ID[swipeDirectionH][swipeDirectionHV]);
613 }
614
615 Clear();
616 SetCurrentState(TouchExplorationState::TOUCH_INIT);
617 }
618
HandleOneFingerSwipeStateMove(MMI::PointerEvent & event)619 void TouchExploration::HandleOneFingerSwipeStateMove(MMI::PointerEvent &event)
620 {
621 AddOneFingerSwipeEvent(event);
622 SendScreenWakeUpEvent(event);
623 }
624
RecordFocusedLocation(MMI::PointerEvent & event)625 bool TouchExploration::RecordFocusedLocation(MMI::PointerEvent &event)
626 {
627 HILOG_DEBUG();
628 AccessibilityElementInfo focusedElementInfo {};
629 bool ret = Singleton<AccessibleAbilityManagerService>::GetInstance().FindFocusedElement(focusedElementInfo,
630 FIND_FOCUS_TIMEOUT);
631 if (!ret) {
632 HILOG_ERROR("find focused element failed.");
633 return false;
634 }
635
636 MMI::PointerEvent::PointerItem pointer {};
637 event.GetPointerItem(event.GetPointerId(), pointer);
638
639 focusedWindowId_ = focusedElementInfo.GetWindowId();
640
641 offsetX_ = (focusedElementInfo.GetRectInScreen().GetLeftTopXScreenPostion() +
642 focusedElementInfo.GetRectInScreen().GetRightBottomXScreenPostion()) / DIVIDE_NUM - pointer.GetDisplayX();
643 offsetY_ = (focusedElementInfo.GetRectInScreen().GetLeftTopYScreenPostion() +
644 focusedElementInfo.GetRectInScreen().GetRightBottomYScreenPostion()) / DIVIDE_NUM - pointer.GetDisplayY();
645 return true;
646 }
647
HandleOneFingerSingleTapStateDown(MMI::PointerEvent & event)648 void TouchExploration::HandleOneFingerSingleTapStateDown(MMI::PointerEvent &event)
649 {
650 CancelPostEvent(TouchExplorationMsg::SEND_HOVER_MSG);
651 if (receivedPointerEvents_.empty()) {
652 Clear();
653 SetCurrentState(TouchExplorationState::INVALID);
654 return;
655 }
656
657 MMI::PointerEvent::PointerItem curPointerItem;
658 event.GetPointerItem(event.GetPointerId(), curPointerItem);
659 MMI::PointerEvent preDownEvent = receivedPointerEvents_.front();
660 MMI::PointerEvent::PointerItem preDownPointerItem;
661 preDownEvent.GetPointerItem(preDownEvent.GetPointerId(), preDownPointerItem);
662 int32_t durationX = preDownPointerItem.GetDisplayX() - curPointerItem.GetDisplayX();
663 int32_t durationY = preDownPointerItem.GetDisplayY() - curPointerItem.GetDisplayY();
664 if (durationX * durationX + durationY * durationY > multiTapOffsetThresh_ * multiTapOffsetThresh_) {
665 HoverEventRunner();
666 Clear();
667 receivedPointerEvents_.push_back(event);
668 SetCurrentState(TouchExplorationState::ONE_FINGER_DOWN);
669 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::SEND_HOVER_MSG), 0,
670 static_cast<int32_t>(TimeoutDuration::DOUBLE_TAP_TIMEOUT));
671 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::LONG_PRESS_MSG), 0,
672 static_cast<int32_t>(TimeoutDuration::LONG_PRESS_TIMEOUT));
673 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::WAIT_ANOTHER_FINGER_DOWN_MSG), 0,
674 static_cast<int32_t>(TimeoutDuration::MULTI_FINGER_TAP_INTERVAL_TIMEOUT));
675 return;
676 }
677
678 Clear();
679 receivedPointerEvents_.push_back(event);
680 handler_->SendEvent(static_cast<uint32_t>(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG), 0,
681 static_cast<int32_t>(TimeoutDuration::LONG_PRESS_TIMEOUT));
682 SetCurrentState(TouchExplorationState::ONE_FINGER_SINGLE_TAP_THEN_DOWN);
683 }
684
HandleOneFingerSingleTapThenDownStateDown(MMI::PointerEvent & event)685 void TouchExploration::HandleOneFingerSingleTapThenDownStateDown(MMI::PointerEvent &event)
686 {
687 Clear();
688 CancelPostEvent(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG);
689 SetCurrentState(TouchExplorationState::INVALID);
690 }
691
HandleOneFingerSingleTapThenDownStateUp(MMI::PointerEvent & event)692 void TouchExploration::HandleOneFingerSingleTapThenDownStateUp(MMI::PointerEvent &event)
693 {
694 CancelPostEvent(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG);
695 Clear();
696 SetCurrentState(TouchExplorationState::TOUCH_INIT);
697
698 if (!gestureHandler_) {
699 HILOG_ERROR("gestureHandler is nullptr!");
700 return;
701 }
702
703 gestureHandler_->PostTask([this]() {
704 Singleton<AccessibleAbilityManagerService>::GetInstance().ExecuteActionOnAccessibilityFocused(
705 ActionType::ACCESSIBILITY_ACTION_CLICK);
706 }, "TASK_CLICK_ON_FOCUS");
707 }
708
HandleOneFingerSingleTapThenDownStateMove(MMI::PointerEvent & event)709 void TouchExploration::HandleOneFingerSingleTapThenDownStateMove(MMI::PointerEvent &event)
710 {
711 MMI::PointerEvent::PointerItem pointerIterm;
712 event.GetPointerItem(event.GetPointerId(), pointerIterm);
713
714 MMI::PointerEvent startPointerEvent = receivedPointerEvents_.front();
715 MMI::PointerEvent::PointerItem startPointerIterm;
716 startPointerEvent.GetPointerItem(startPointerEvent.GetPointerId(), startPointerIterm);
717
718 float offsetX = startPointerIterm.GetDisplayX() - pointerIterm.GetDisplayX();
719 float offsetY = startPointerIterm.GetDisplayY() - pointerIterm.GetDisplayY();
720 double duration = hypot(offsetX, offsetY);
721 if (duration > moveThreshold_) {
722 CancelPostEvent(TouchExplorationMsg::DOUBLE_TAP_AND_LONG_PRESS_MSG);
723 Clear();
724 SetCurrentState(TouchExplorationState::INVALID);
725 }
726 }
727
OffsetEvent(MMI::PointerEvent & event)728 void TouchExploration::OffsetEvent(MMI::PointerEvent &event)
729 {
730 HILOG_DEBUG();
731 if (receivedPointerEvents_.empty()) {
732 HILOG_ERROR("received pointer event is null!");
733 return;
734 }
735
736 MMI::PointerEvent startPointerEvent = receivedPointerEvents_.front();
737 if (event.GetPointerId() != startPointerEvent.GetPointerId()) {
738 return;
739 }
740
741 AccessibilityWindowInfo windowInfo = {};
742 if (Singleton<AccessibilityWindowManager>::GetInstance().GetAccessibilityWindow(focusedWindowId_, windowInfo)) {
743 event.SetZOrder(static_cast<float>(windowInfo.GetWindowLayer() + 1));
744 } else {
745 HILOG_ERROR("get windowInfo failed");
746 }
747
748 MMI::PointerEvent::PointerItem pointer {};
749 event.GetPointerItem(event.GetPointerId(), pointer);
750 pointer.SetTargetWindowId(focusedWindowId_);
751 int32_t x = offsetX_ + pointer.GetDisplayX();
752 int32_t y = offsetY_ + pointer.GetDisplayY();
753 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
754 AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
755 int32_t displayWidth = displayMgr.GetWidth();
756 int32_t displayHeight = displayMgr.GetHeight();
757 x = x < 0 ? 0 : (x >= displayWidth ? displayWidth - 1 : x);
758 y = y < 0 ? 0 : (y >= displayHeight ? displayHeight - 1 : y);
759 #endif
760 pointer.SetDisplayX(x);
761 pointer.SetDisplayY(y);
762 event.RemovePointerItem(event.GetPointerId());
763 event.AddPointerItem(pointer);
764 }
765
SendDoubleTapAndLongPressDownEvent()766 bool TouchExploration::SendDoubleTapAndLongPressDownEvent()
767 {
768 if (receivedPointerEvents_.empty()) {
769 HILOG_ERROR("receivedPointerEvents_ is empty!");
770 return false;
771 }
772 if (!RecordFocusedLocation(receivedPointerEvents_.front())) {
773 return false;
774 }
775 OffsetEvent(receivedPointerEvents_.front());
776 SendEventToMultimodal(receivedPointerEvents_.front(), ChangeAction::NO_CHANGE);
777 return true;
778 }
779
HandleOneFingerDoubleTapAndLongPressState(MMI::PointerEvent & event)780 void TouchExploration::HandleOneFingerDoubleTapAndLongPressState(MMI::PointerEvent &event)
781 {
782 OffsetEvent(event);
783 SendEventToMultimodal(event, ChangeAction::NO_CHANGE);
784
785 MMI::PointerEvent::PointerItem pointer {};
786 event.GetPointerItem(event.GetPointerId(), pointer);
787 if ((event.GetPointerIds().size() == static_cast<uint32_t>(PointerCount::POINTER_COUNT_1)) &&
788 (!pointer.IsPressed())) {
789 Clear();
790 SetCurrentState(TouchExplorationState::TOUCH_INIT);
791 }
792 }
793
Clear()794 void TouchExploration::Clear()
795 {
796 receivedPointerEvents_.clear();
797 draggingDownEvent_ = nullptr;
798 offsetX_ = 0;
799 offsetY_ = 0;
800 oneFingerSwipeRoute_.clear();
801 oneFingerSwipePrePointer_ = {};
802 draggingPid_ = -1;
803 multiTapNum_ = 0;
804 multiFingerSwipeDirection_ = -1;
805 multiFingerSwipeRoute_.clear();
806 multiFingerSwipePrePoint_.clear();
807 }
808
DestroyEvents()809 void TouchExploration::DestroyEvents()
810 {
811 HILOG_INFO();
812 Clear();
813 handler_->RemoveAllEvents();
814 SetCurrentState(TouchExplorationState::TOUCH_INIT);
815 EventTransmission::DestroyEvents();
816 }
817 } // namespace Accessibility
818 } // namespace OHOS