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