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