• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-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_zoom_gesture.h"
17 #include "accessible_ability_manager_service.h"
18 #include "hilog_wrapper.h"
19 #include "window_accessibility_controller.h"
20 #include "accessibility_window_manager.h"
21 #include "utils.h"
22 #ifdef OHOS_BUILD_ENABLE_POWER_MANAGER
23 #include "accessibility_power_manager.h"
24 #endif
25 
26 namespace OHOS {
27 namespace Accessibility {
28 namespace {
29     constexpr size_t POINTER_COUNT_1 = 1;
30     constexpr size_t POINTER_COUNT_2 = 2;
31     constexpr float TAP_MIN_DISTANCE = 8.0f;
32     constexpr int32_t MULTI_TAP_TIMER = 250; // ms
33     constexpr int32_t LONG_PRESS_TIMER = 300; // ms
34     constexpr float DOUBLE_TAP_SLOP = 100.0f;
35     constexpr uint32_t DOUBLE = 2;
36     constexpr uint32_t TRIPLE_TAP_COUNT = 3;
37     constexpr float NORMAL_SCALE = 1.0f;
38     constexpr float MIN_SCROLL_SPAN = 2.0f;
39     constexpr float MIN_SCALE_SPAN = 2.0f;
40     constexpr float DEFAULT_ANCHOR = 0.5f;
41     constexpr float MIN_SCALE = 0.1f;
42 } // namespace
43 
AccessibilityZoomGesture(std::shared_ptr<FullScreenMagnificationManager> fullScreenManager,std::shared_ptr<MagnificationMenuManager> menuManager)44 AccessibilityZoomGesture::AccessibilityZoomGesture(
45     std::shared_ptr<FullScreenMagnificationManager> fullScreenManager,
46     std::shared_ptr<MagnificationMenuManager> menuManager)
47     : fullScreenManager_(fullScreenManager), menuManager_(menuManager)
48 {
49     HILOG_DEBUG();
50     zoomGestureEventHandler_ = std::make_shared<ZoomGestureEventHandler>(
51         Singleton<AccessibleAbilityManagerService>::GetInstance().GetInputManagerRunner(), *this);
52 
53     tapDistance_ = TAP_MIN_DISTANCE;
54 
55 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
56     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
57     auto display = displayMgr.GetDefaultDisplay();
58     if (!display) {
59         HILOG_ERROR("get display is nullptr");
60         return;
61     }
62 
63     float densityPixels = display->GetVirtualPixelRatio();
64     multiTapDistance_ = densityPixels * DOUBLE_TAP_SLOP + 0.5f;
65 #else
66     HILOG_DEBUG("not support display manager");
67     multiTapDistance_ = 1 * DOUBLE_TAP_SLOP + 0.5f;
68 #endif
69 }
70 
IsTapOnInputMethod(MMI::PointerEvent & event)71 bool AccessibilityZoomGesture::IsTapOnInputMethod(MMI::PointerEvent &event)
72 {
73     size_t pointerCount = event.GetPointerIds().size();
74     if (pointerCount != POINTER_COUNT_1) {
75         HILOG_DEBUG("not single finger.");
76         return false;
77     }
78     std::vector<AccessibilityWindowInfo> windowInfos =
79         Singleton<AccessibilityWindowManager>::GetInstance().GetAccessibilityWindows();
80     for (auto &window : windowInfos) {
81         if (window.GetWindowType() == INPUT_METHOD_WINDOW_TYPE) {
82             Rect inputRect = window.GetRectInScreen();
83             int32_t leftTopX = inputRect.GetLeftTopXScreenPostion();
84             int32_t leftTopY = inputRect.GetLeftTopYScreenPostion();
85             int32_t rightBottomX = inputRect.GetRightBottomXScreenPostion();
86             int32_t rightBottomY = inputRect.GetRightBottomYScreenPostion();
87 
88             MMI::PointerEvent::PointerItem item;
89             event.GetPointerItem(event.GetPointerId(), item);
90             int32_t itemX = item.GetDisplayX();
91             int32_t itemY = item.GetDisplayY();
92             if ((itemX >= leftTopX) && (itemX <= rightBottomX) &&
93             (itemY >= leftTopY) && (itemY <= rightBottomY)) {
94                 HILOG_INFO("tap on input method window.");
95                 return true;
96             }
97         }
98     }
99     HILOG_DEBUG("have no input method window.");
100     return false;
101 }
102 
OnPointerEvent(MMI::PointerEvent & event)103 bool AccessibilityZoomGesture::OnPointerEvent(MMI::PointerEvent &event)
104 {
105     HILOG_DEBUG("state_ is %{public}d.", state_);
106 
107     if (shieldZoomGestureFlag_) {
108         EventTransmission::OnPointerEvent(event);
109         return true;
110     }
111 
112     if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN ||
113         event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) {
114         HILOG_INFO("PointerAction: %{public}d.", event.GetPointerAction());
115     }
116 
117     int32_t sourceType = event.GetSourceType();
118     if (state_ == READY_STATE && sourceType != MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
119         EventTransmission::OnPointerEvent(event);
120         return false;
121     }
122 
123     if (event.GetPointerId() == SCROLL_SHOT_POINTER_ID) {
124         HILOG_DEBUG("scrollshot injected.");
125         EventTransmission::OnPointerEvent(event);
126         return false;
127     }
128 
129     switch (state_) {
130         case READY_STATE:
131             CacheEvents(event);
132             RecognizeInReadyState(event);
133             break;
134         case ZOOMIN_STATE:
135             CacheEvents(event);
136             RecognizeInZoomState(event);
137             break;
138         case SLIDING_STATE:
139             RecognizeInSlidingState(event);
140             break;
141         case MENU_SLIDING_STATE:
142             RecognizeInMenuSlidingState(event);
143             break;
144         case DRAGGING_STATE:
145             RecognizeInDraggingState(event);
146             break;
147         default:
148             break;
149     }
150     return true;
151 }
152 
TransferState(ACCESSIBILITY_ZOOM_STATE state)153 void AccessibilityZoomGesture::TransferState(ACCESSIBILITY_ZOOM_STATE state)
154 {
155     HILOG_INFO("old state= %{public}d, new state= %{public}d", state_, state);
156     state_ = state;
157 }
158 
CacheEvents(MMI::PointerEvent & event)159 void AccessibilityZoomGesture::CacheEvents(MMI::PointerEvent &event)
160 {
161     HILOG_DEBUG();
162 
163     int32_t action = event.GetPointerAction();
164     size_t pointerCount = event.GetPointerIds().size();
165     std::shared_ptr<MMI::PointerEvent> pointerEvent = std::make_shared<MMI::PointerEvent>(event);
166 
167     switch (action) {
168         case MMI::PointerEvent::POINTER_ACTION_DOWN:
169             if (pointerCount == POINTER_COUNT_1) {
170                 HILOG_DEBUG("Cache pointer down");
171                 preLastDownEvent_ = lastDownEvent_;
172                 lastDownEvent_ = pointerEvent;
173             }
174             break;
175         case MMI::PointerEvent::POINTER_ACTION_UP:
176             if (pointerCount == POINTER_COUNT_1) {
177                 HILOG_DEBUG("Cache pointer up");
178                 preLastUpEvent_ = lastUpEvent_;
179                 lastUpEvent_ = pointerEvent;
180             }
181             break;
182         case MMI::PointerEvent::POINTER_ACTION_MOVE:
183             if (pointerCount == POINTER_COUNT_1) {
184                 HILOG_DEBUG("Cache pointer move.");
185                 currentMoveEvent_ = pointerEvent;
186             }
187             break;
188         default:
189             HILOG_DEBUG("Action is %{public}d", action);
190             break;
191     }
192     cacheEvents_.emplace_back(pointerEvent);
193 }
194 
SendCacheEventsToNext()195 void AccessibilityZoomGesture::SendCacheEventsToNext()
196 {
197     HILOG_DEBUG();
198 
199     bool isStartNewAction = false;
200     int32_t action = MMI::PointerEvent::POINTER_ACTION_UNKNOWN;
201     std::vector<std::shared_ptr<MMI::PointerEvent>> cacheEventsTmp;
202     std::copy(cacheEvents_.begin(), cacheEvents_.end(), std::back_inserter(cacheEventsTmp));
203 
204     ClearCacheEventsAndMsg();
205 
206     size_t cacheEventsNum = 0;
207     size_t cacheEventsTotalNum = cacheEventsTmp.size();
208 
209     if (fullScreenManager_ == nullptr) {
210         HILOG_ERROR("fullScreenManager_ is nullptr.");
211         return;
212     }
213 
214     for (auto &pointerEvent : cacheEventsTmp) {
215         cacheEventsNum++;
216         action = pointerEvent->GetPointerAction();
217         if ((cacheEventsNum > 1) &&
218             (cacheEventsNum == cacheEventsTotalNum) &&
219             (action == MMI::PointerEvent::POINTER_ACTION_DOWN)) {
220             HILOG_DEBUG("The down event needs to be parsed again");
221             isStartNewAction = true;
222         }
223         if (isStartNewAction) {
224             OnPointerEvent(*pointerEvent);
225             continue;
226         }
227         if (state_ != READY_STATE && fullScreenManager_->IsMagnificationWindowShow()) {
228             MMI::PointerEvent::PointerItem pointer {};
229             pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointer);
230             PointerPos coordinates  = fullScreenManager_->ConvertCoordinates(pointer.GetDisplayX(),
231                 pointer.GetDisplayY());
232             if (gestureType_ != INVALID_GESTURE_TYPE) {
233                 coordinates = fullScreenManager_->ConvertGesture(gestureType_, coordinates);
234             }
235             pointer.SetDisplayX(coordinates.posX);
236             pointer.SetDisplayY(coordinates.posY);
237             pointer.SetTargetWindowId(-1);
238             pointerEvent->RemovePointerItem(pointerEvent->GetPointerId());
239             pointerEvent->AddPointerItem(pointer);
240             pointerEvent->SetZOrder(10000); // 10000 is magnification window zorder
241         }
242         pointerEvent->SetActionTime(Utils::GetSystemTime() * US_TO_MS);
243         EventTransmission::OnPointerEvent(*pointerEvent);
244     }
245 }
246 
ClearCacheEventsAndMsg()247 void AccessibilityZoomGesture::ClearCacheEventsAndMsg()
248 {
249     HILOG_DEBUG();
250 
251     cacheEvents_.clear();
252     preLastDownEvent_ = nullptr;
253     lastDownEvent_ = nullptr;
254     preLastUpEvent_ = nullptr;
255     lastUpEvent_ = nullptr;
256 }
257 
RecognizeInReadyState(MMI::PointerEvent & event)258 void AccessibilityZoomGesture::RecognizeInReadyState(MMI::PointerEvent &event)
259 {
260     HILOG_DEBUG();
261 
262     int32_t action = event.GetPointerAction();
263     size_t pointerCount = event.GetPointerIds().size();
264     bool isTripleTaps = false;
265 
266     HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
267     switch (action) {
268         case MMI::PointerEvent::POINTER_ACTION_DOWN:
269             zoomGestureEventHandler_->RemoveEvent(MULTI_TAP_MSG);
270             if ((pointerCount == POINTER_COUNT_1) && IsDownValid()) {
271                 zoomGestureEventHandler_->SendEvent(MULTI_TAP_MSG, 0, MULTI_TAP_TIMER);
272                 IsTripleTaps();
273             } else {
274                 SendCacheEventsToNext();
275             }
276             break;
277         case MMI::PointerEvent::POINTER_ACTION_UP:
278             if ((pointerCount == POINTER_COUNT_1) && IsUpValid() && !(IsTapOnInputMethod(event))) {
279                 isTripleTaps = IsTripleTaps();
280             } else {
281                 SendCacheEventsToNext();
282                 HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
283             }
284             break;
285         case MMI::PointerEvent::POINTER_ACTION_MOVE:
286             if ((pointerCount == POINTER_COUNT_1) && IsMoveValid()) {
287                 HILOG_DEBUG("move valid.");
288             } else {
289                 SendCacheEventsToNext();
290                 HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
291             }
292             break;
293         case MMI::PointerEvent::POINTER_ACTION_CANCEL:
294             SendCacheEventsToNext();
295             break;
296         default:
297             break;
298     }
299 
300     if (isTripleTaps) {
301         OnTripleTap(event);
302         zoomGestureEventHandler_->RemoveEvent(MULTI_TAP_MSG);
303     }
304 }
305 
RecognizeInZoomStateDownEvent(MMI::PointerEvent & event)306 void AccessibilityZoomGesture::RecognizeInZoomStateDownEvent(MMI::PointerEvent &event)
307 {
308     if (fullScreenManager_ == nullptr) {
309         HILOG_ERROR("fullScreenManager_ is nullptr.");
310         return;
311     }
312     if (menuManager_ == nullptr) {
313         HILOG_ERROR("menuManager_ is nullptr.");
314         return;
315     }
316     gestureType_ = INVALID_GESTURE_TYPE;
317     std::vector<int32_t> pointerIdList = event.GetPointerIds();
318     size_t pointerCount = pointerIdList.size();
319     zoomGestureEventHandler_->RemoveEvent(MULTI_TAP_MSG);
320     if (pointerCount == POINTER_COUNT_1) {
321         isLongPress_ = false;
322         MMI::PointerEvent::PointerItem pointerItem;
323         event.GetPointerItem(event.GetPointerId(), pointerItem);
324         gestureType_ = fullScreenManager_->CheckTapOnHotArea(pointerItem.GetDisplayX(), pointerItem.GetDisplayY());
325         isTapOnMenu_ = menuManager_->IsTapOnMenu(pointerItem.GetDisplayX(), pointerItem.GetDisplayY());
326         std::shared_ptr<MMI::PointerEvent> pointerEvent = std::make_shared<MMI::PointerEvent>(event);
327         longPressDownEvent_ = pointerEvent;
328         downPid_ = event.GetPointerId();
329         if (IsDownValid()) {
330             if (!isTapOnMenu_) {
331                 zoomGestureEventHandler_->SendEvent(MULTI_TAP_MSG, 0, MULTI_TAP_TIMER);
332             }
333         } else {
334             SendCacheEventsToNext();
335         }
336     } else if (pointerCount == POINTER_COUNT_2) {
337         gestureType_ = INVALID_GESTURE_TYPE;
338         if (isLongPress_ || IsKnuckles(event)) {
339             HILOG_INFO("not transferState sliding.");
340             SendCacheEventsToNext();
341         } else {
342             TransferState(SLIDING_STATE);
343             scale_ = fullScreenManager_->GetScale();
344             isScale_ = false;
345             ClearCacheEventsAndMsg();
346             ZOOM_FOCUS_COORDINATE focusXY = {0.0f, 0.0f};
347             CalcFocusCoordinate(event, focusXY);
348             lastScrollFocusX_ = focusXY.centerX;
349             lastScrollFocusY_ = focusXY.centerY;
350             float span = CalcScaleSpan(event, focusXY);
351             preSpan_ = lastSpan_ = span;
352         }
353     } else {
354         HILOG_INFO("invalid pointer count.");
355     }
356 }
357 
RecognizeInZoomStateMoveEvent(MMI::PointerEvent & event)358 void AccessibilityZoomGesture::RecognizeInZoomStateMoveEvent(MMI::PointerEvent &event)
359 {
360     int32_t action = event.GetPointerAction();
361     std::vector<int32_t> pointerIdList = event.GetPointerIds();
362     size_t pointerCount = pointerIdList.size();
363     HILOG_DEBUG();
364     if ((pointerCount == POINTER_COUNT_1) && !IsLongPress() && IsMoveValid()) {
365         HILOG_DEBUG("move valid.");
366     } else if (isTapOnMenu_ && (!IsMoveValid() || IsLongPress())) {
367         TransferState(MENU_SLIDING_STATE);
368         ClearCacheEventsAndMsg();
369     } else {
370         SendCacheEventsToNext();
371         HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
372     }
373 }
374 
RecognizeInZoomState(MMI::PointerEvent & event)375 void AccessibilityZoomGesture::RecognizeInZoomState(MMI::PointerEvent &event)
376 {
377     HILOG_DEBUG();
378 
379     int32_t action = event.GetPointerAction();
380     std::vector<int32_t> pointerIdList = event.GetPointerIds();
381     size_t pointerCount = pointerIdList.size();
382     bool isTripleTaps = false;
383 
384     HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
385     switch (action) {
386         case MMI::PointerEvent::POINTER_ACTION_DOWN:
387             RecognizeInZoomStateDownEvent(event);
388             break;
389         case MMI::PointerEvent::POINTER_ACTION_UP:
390             if (downPid_ == event.GetPointerId()) {
391                 isLongPress_ = false;
392             }
393             if ((pointerCount == POINTER_COUNT_1) && IsUpValid() && !(IsTapOnInputMethod(event))) {
394                 if (isTapOnMenu_ && menuManager_ != nullptr) {
395                     menuManager_->OnMenuTap();
396                     ClearCacheEventsAndMsg();
397                 } else {
398                     isTripleTaps = IsTripleTaps();
399                 }
400             } else {
401                 SendCacheEventsToNext();
402             }
403             break;
404         case MMI::PointerEvent::POINTER_ACTION_MOVE:
405             RecognizeInZoomStateMoveEvent(event);
406             break;
407         case MMI::PointerEvent::POINTER_ACTION_CANCEL:
408             SendCacheEventsToNext();
409             HILOG_DEBUG("action:%{public}d", action);
410             break;
411         default:
412             break;
413     }
414 
415     if (isTripleTaps) {
416         OnTripleTap(event);
417     }
418 }
419 
RecognizeInSlidingState(MMI::PointerEvent & event)420 void AccessibilityZoomGesture::RecognizeInSlidingState(MMI::PointerEvent &event)
421 {
422     HILOG_DEBUG();
423 
424     int32_t action = event.GetPointerAction();
425     size_t pointerCount = event.GetPointerIds().size();
426     ZOOM_FOCUS_COORDINATE coordinate = {0.0f, 0.0f};
427     CalcFocusCoordinate(event, coordinate);
428 
429     if (pointerCount == POINTER_COUNT_2) {
430         RecognizeScale(event, coordinate);
431         RecognizeScroll(event, coordinate);
432     }
433 
434     HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
435 
436     if (fullScreenManager_ == nullptr) {
437         HILOG_ERROR("fullScreenManager_ is nullptr.");
438         return;
439     }
440 
441     switch (action) {
442         case MMI::PointerEvent::POINTER_ACTION_UP:
443             if (pointerCount == POINTER_COUNT_1) {
444                 TransferState(ZOOMIN_STATE);
445                 if (isScale_ && (abs(scale_ - fullScreenManager_->GetScale()) > MIN_SCALE)) {
446                     fullScreenManager_->PersistScale();
447                     isScale_ = false;
448                 }
449             }
450             break;
451         case MMI::PointerEvent::POINTER_ACTION_CANCEL:
452             TransferState(ZOOMIN_STATE);
453             isScale_ = false;
454             break;
455         default:
456             break;
457     }
458 }
459 
RecognizeInMenuSlidingState(MMI::PointerEvent & event)460 void AccessibilityZoomGesture::RecognizeInMenuSlidingState(MMI::PointerEvent &event)
461 {
462     HILOG_INFO();
463     if (menuManager_ == nullptr) {
464         HILOG_ERROR("menuManager_ is nullptr.");
465         return;
466     }
467     int32_t action = event.GetPointerAction();
468     switch (action) {
469         case MMI::PointerEvent::POINTER_ACTION_MOVE:
470             if (isTapOnMenu_) {
471                 ClearCacheEventsAndMsg();
472                 if (lastSlidingEvent_ == nullptr) {
473                     lastSlidingEvent_ = std::make_shared<MMI::PointerEvent>(event);
474                 }
475                 MMI::PointerEvent::PointerItem lastSlidingItem;
476                 lastSlidingEvent_->GetPointerItem(lastSlidingEvent_->GetPointerId(), lastSlidingItem);
477 
478                 MMI::PointerEvent::PointerItem currentItem;
479                 event.GetPointerItem(event.GetPointerId(), currentItem);
480 
481                 int32_t deltaX = currentItem.GetDisplayX() - lastSlidingItem.GetDisplayX();
482                 int32_t deltaY = currentItem.GetDisplayY() - lastSlidingItem.GetDisplayY();
483                 menuManager_->MoveMenuWindow(deltaX, deltaY);
484 
485                 lastSlidingEvent_ = std::make_shared<MMI::PointerEvent>(event);
486             } else {
487                 if (lastSlidingEvent_ != nullptr) {
488                     lastSlidingEvent_ = nullptr;
489                 }
490             }
491             break;
492         case MMI::PointerEvent::POINTER_ACTION_UP:
493             lastSlidingEvent_ = nullptr;
494             isTapOnMenu_ = false;
495             menuManager_->AttachToEdge();
496             TransferState(ZOOMIN_STATE);
497             ClearCacheEventsAndMsg();
498             break;
499         default:
500             break;
501     }
502 }
503 
RecognizeScroll(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE & coordinate)504 void AccessibilityZoomGesture::RecognizeScroll(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate)
505 {
506     HILOG_DEBUG();
507 
508     int32_t action = event.GetPointerAction();
509     switch (action) {
510         case MMI::PointerEvent::POINTER_ACTION_DOWN:
511         case MMI::PointerEvent::POINTER_ACTION_UP:
512             lastScrollFocusX_ = coordinate.centerX;
513             lastScrollFocusY_ = coordinate.centerY;
514             break;
515         case MMI::PointerEvent::POINTER_ACTION_MOVE: {
516             float offsetX = coordinate.centerX - lastScrollFocusX_;
517             float offsetY = coordinate.centerY - lastScrollFocusY_;
518             if ((abs(offsetX) > MIN_SCROLL_SPAN) || (abs(offsetY) > MIN_SCROLL_SPAN)) {
519                 lastScrollFocusX_ = coordinate.centerX;
520                 lastScrollFocusY_ = coordinate.centerY;
521                 OnScroll(offsetX, offsetY);
522             }
523             break;
524         }
525         default:
526             break;
527     }
528 }
529 
RecognizeScale(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE & coordinate)530 void AccessibilityZoomGesture::RecognizeScale(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate)
531 {
532     HILOG_DEBUG();
533 
534     int32_t action = event.GetPointerAction();
535     size_t pointerCount = event.GetPointerIds().size();
536     if (((action == MMI::PointerEvent::POINTER_ACTION_UP) && (pointerCount != POINTER_COUNT_2)) ||
537         (action == MMI::PointerEvent::POINTER_ACTION_CANCEL)) {
538         HILOG_DEBUG("Scaling is end");
539         startScaling_ = false;
540         preSpan_ = lastSpan_ = 0;
541         return;
542     }
543 
544     float span = CalcScaleSpan(event, coordinate);
545 
546     if (action == MMI::PointerEvent::POINTER_ACTION_MOVE) {
547         if (abs(preSpan_ - span) >= MIN_SCALE_SPAN) {
548             startScaling_ = true;
549             HILOG_DEBUG("start scaling.");
550         }
551     }
552     if (!startScaling_) {
553         // When the span is greater than or equal to MIN_SCALE_SPAN, start scaling.
554         if (abs(preSpan_ - span) >= MIN_SCALE_SPAN) {
555             startScaling_ = true;
556             HILOG_DEBUG("start scaling.");
557         }
558     } else {
559         // When the span is smaller than the MIN_SCALE_SPAN,
560         // the scale recognition will be restarted.
561         if (abs(lastSpan_ - span) < 1) {
562             startScaling_ = false;
563             preSpan_ = lastSpan_ = span;
564         }
565         if ((action == MMI::PointerEvent::POINTER_ACTION_UP) ||
566             (action == MMI::PointerEvent::POINTER_ACTION_DOWN)) {
567             preSpan_ = lastSpan_ = span;
568         }
569     }
570 
571     if (!startScaling_) {
572         HILOG_DEBUG("Current is not scaling");
573         return;
574     }
575 
576     if (action != MMI::PointerEvent::POINTER_ACTION_MOVE) {
577         HILOG_DEBUG("Action(%{public}d) is not move", action);
578         return;
579     }
580 
581     float scaleSpan = span - lastSpan_;
582     if (abs(scaleSpan) > EPS) {
583         OnScale(scaleSpan);
584         lastSpan_ = span;
585         isScale_ = true;
586     }
587 }
588 
RecognizeInDraggingState(MMI::PointerEvent & event)589 void AccessibilityZoomGesture::RecognizeInDraggingState(MMI::PointerEvent &event)
590 {
591     HILOG_DEBUG();
592     int32_t action = event.GetPointerAction();
593     if (event.GetPointerId() != DEFAULT_POINTER_ID) {
594         return;
595     }
596     switch (action) {
597         case MMI::PointerEvent::POINTER_ACTION_MOVE: {
598             int32_t pointerId = event.GetPointerId();
599             MMI::PointerEvent::PointerItem item;
600             event.GetPointerItem(pointerId, item);
601             int32_t anchorX = item.GetDisplayX();
602             int32_t anchorY = item.GetDisplayY();
603             float offsetX = lastScrollFocusX_ - anchorX;
604             float offsetY = lastScrollFocusY_ - anchorY;
605             if ((abs(offsetX) > MIN_SCROLL_SPAN) || (abs(offsetY) > MIN_SCROLL_SPAN)) {
606                 lastScrollFocusX_ = anchorX;
607                 lastScrollFocusY_ = anchorY;
608                 OnScroll(offsetX, offsetY);
609             }
610             break;
611         }
612         case MMI::PointerEvent::POINTER_ACTION_UP:
613             OffZoom();
614             TransferState(READY_STATE);
615             break;
616         default:
617             break;
618     }
619 }
620 
CalcFocusCoordinate(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE & coordinate)621 void AccessibilityZoomGesture::CalcFocusCoordinate(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate)
622 {
623     HILOG_DEBUG();
624 
625     float sumX = 0.0f;
626     float sumY = 0.0f;
627     int32_t upPointerId = -1;
628     int32_t action = event.GetPointerAction();
629     std::vector<int32_t> pointerIdList = event.GetPointerIds();
630     size_t count = pointerIdList.size();
631     if (!count) {
632         HILOG_DEBUG("The size of PointerIds is 0");
633         return;
634     }
635 
636     if (action == MMI::PointerEvent::POINTER_ACTION_UP) {
637         upPointerId = event.GetPointerId();
638         HILOG_DEBUG("The pointer id of up is %{public}d", upPointerId);
639         count--;
640     }
641 
642     if (!count) {
643         HILOG_DEBUG("The size of PointerIds(down) is invalid");
644         return;
645     }
646 
647     for (int32_t pointerId : pointerIdList) {
648         if (pointerId == upPointerId) {
649             continue;
650         }
651         MMI::PointerEvent::PointerItem item;
652         event.GetPointerItem(pointerId, item);
653         sumX += static_cast<float>(item.GetRawDisplayX());
654         sumY += static_cast<float>(item.GetRawDisplayY());
655     }
656 
657     coordinate.centerX = sumX / count;
658     coordinate.centerY = sumY / count;
659     HILOG_DEBUG("centerX:%{public}f, centerY:%{public}f", coordinate.centerX, coordinate.centerY);
660 }
661 
CalcScaleSpan(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE coordinate)662 float AccessibilityZoomGesture::CalcScaleSpan(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE coordinate)
663 {
664     HILOG_DEBUG();
665 
666     float span = 0.0f;
667     float sumSpanX = 0.0f;
668     float sumSpanY = 0.0f;
669     int32_t upPointerId = -1;
670     int32_t action = event.GetPointerAction();
671     std::vector<int32_t> pointerIdList = event.GetPointerIds();
672     size_t count = pointerIdList.size();
673     if (!count) {
674         HILOG_DEBUG("The size of PointerIds is 0");
675         return span;
676     }
677 
678     if (action == MMI::PointerEvent::POINTER_ACTION_UP) {
679         upPointerId = event.GetPointerId();
680         HILOG_DEBUG("The pointer id of up is %{public}d", upPointerId);
681         count--;
682     }
683 
684     if (!count) {
685         HILOG_DEBUG("The size of PointerIds(down) is invalid");
686         return span;
687     }
688 
689     for (int32_t pointerId : pointerIdList) {
690         if (pointerId == upPointerId) {
691             continue;
692         }
693         MMI::PointerEvent::PointerItem item;
694         event.GetPointerItem(pointerId, item);
695         sumSpanX += static_cast<float>(abs(item.GetRawDisplayX() - coordinate.centerX));
696         sumSpanY += static_cast<float>(abs(item.GetRawDisplayY() - coordinate.centerY));
697     }
698 
699     float spanX = sumSpanX / count;
700     float spanY = sumSpanY / count;
701     span = hypot(spanX, spanY) / HALF;
702     HILOG_DEBUG("The span is %{public}f", span);
703     return span;
704 }
705 
IsDownValid()706 bool AccessibilityZoomGesture::IsDownValid()
707 {
708     HILOG_DEBUG();
709 
710     if (!preLastDownEvent_) {
711         HILOG_DEBUG("This is the first down event");
712         return true;
713     }
714 
715     if (CalcSeparationDistance(preLastDownEvent_, lastDownEvent_) >= multiTapDistance_) {
716         HILOG_DEBUG("The down event is vailid");
717         return false;
718     }
719     return true;
720 }
721 
IsUpValid()722 bool AccessibilityZoomGesture::IsUpValid()
723 {
724     HILOG_DEBUG();
725 
726     if (!lastDownEvent_) {
727         HILOG_DEBUG("The up event is invailid");
728         return false;
729     }
730 
731     if (CalcIntervalTime(lastDownEvent_, lastUpEvent_) >= LONG_PRESS_TIMER) {
732         HILOG_DEBUG("The time has exceeded the long press time");
733         return false;
734     }
735 
736     if (CalcSeparationDistance(lastDownEvent_, lastUpEvent_) >= tapDistance_) {
737         HILOG_DEBUG("The distance has exceeded the threshold");
738         return false;
739     }
740     return true;
741 }
742 
IsMoveValid()743 bool AccessibilityZoomGesture::IsMoveValid()
744 {
745     HILOG_DEBUG();
746 
747     if (!lastDownEvent_) {
748         HILOG_DEBUG("The move event is invailid");
749         return false;
750     }
751 
752     if (CalcIntervalTime(lastDownEvent_, currentMoveEvent_) >= LONG_PRESS_TIMER) {
753         HILOG_DEBUG("The time has exceeded the long press time");
754         return false;
755     }
756 
757     if (CalcSeparationDistance(lastDownEvent_, currentMoveEvent_) >= tapDistance_) {
758         HILOG_DEBUG("The distance has exceeded the threshold");
759         return false;
760     }
761     return true;
762 }
763 
IsLongPress()764 bool AccessibilityZoomGesture::IsLongPress()
765 {
766     HILOG_DEBUG();
767 
768     if (CalcIntervalTime(longPressDownEvent_, currentMoveEvent_) >= LONG_PRESS_TIMER) {
769         HILOG_DEBUG("The time has exceeded the long press time");
770         isLongPress_ = true;
771         return true;
772     }
773     return false;
774 }
775 
IsKnuckles(MMI::PointerEvent & event)776 bool AccessibilityZoomGesture::IsKnuckles(MMI::PointerEvent &event)
777 {
778     HILOG_DEBUG();
779 
780     std::vector<int32_t> pointerIdList = event.GetPointerIds();
781     for (int32_t pointerId : pointerIdList) {
782         MMI::PointerEvent::PointerItem item;
783         event.GetPointerItem(pointerId, item);
784         int32_t toolType = item.GetToolType();
785         if (toolType == MMI::PointerEvent::TOOL_TYPE_KNUCKLE) {
786             HILOG_INFO("is knuckle event.");
787             return true;
788         }
789     }
790     return false;
791 }
792 
IsTripleTaps()793 bool AccessibilityZoomGesture::IsTripleTaps()
794 {
795     HILOG_DEBUG();
796 
797     uint32_t upEventCount = 0;
798     uint32_t downEventCount = 0;
799     int32_t action = MMI::PointerEvent::POINTER_ACTION_UNKNOWN;
800     for (auto &pointerEvent : cacheEvents_) {
801         action = pointerEvent->GetPointerAction();
802         if (action == MMI::PointerEvent::POINTER_ACTION_UP) {
803             upEventCount++;
804         }
805         if (action == MMI::PointerEvent::POINTER_ACTION_DOWN) {
806             downEventCount++;
807         }
808     }
809 
810     if (downEventCount == TRIPLE_TAP_COUNT && upEventCount == TAP_COUNT_TWO) {
811         HILOG_INFO("Triple down detected");
812         isTripleDown_ = true;
813     }
814 
815     if (upEventCount >= TRIPLE_TAP_COUNT) {
816         HILOG_DEBUG("Triple tap detected");
817         isTripleDown_ = false;
818         return true;
819     }
820 
821     return false;
822 }
823 
CalcIntervalTime(std::shared_ptr<MMI::PointerEvent> firstEvent,std::shared_ptr<MMI::PointerEvent> secondEvent)824 int64_t AccessibilityZoomGesture::CalcIntervalTime(std::shared_ptr<MMI::PointerEvent> firstEvent,
825     std::shared_ptr<MMI::PointerEvent> secondEvent)
826 {
827     HILOG_DEBUG();
828 
829     if (!firstEvent || !secondEvent) {
830         HILOG_DEBUG("The event is null");
831         return 0;
832     }
833 
834     int64_t firstTime = firstEvent->GetActionTime();
835     int64_t secondTime = secondEvent->GetActionTime();
836     int64_t intervalTime = (secondTime - firstTime) / US_TO_MS;
837 
838     return intervalTime;
839 }
840 
CalcSeparationDistance(std::shared_ptr<MMI::PointerEvent> firstEvent,std::shared_ptr<MMI::PointerEvent> secondEvent)841 float AccessibilityZoomGesture::CalcSeparationDistance(std::shared_ptr<MMI::PointerEvent> firstEvent,
842     std::shared_ptr<MMI::PointerEvent> secondEvent)
843 {
844     HILOG_DEBUG();
845 
846     if (!firstEvent || !secondEvent) {
847         HILOG_DEBUG("The event is null");
848         return 0;
849     }
850 
851     MMI::PointerEvent::PointerItem firstItem;
852     MMI::PointerEvent::PointerItem secondItem;
853     firstEvent->GetPointerItem(firstEvent->GetPointerId(), firstItem);
854     secondEvent->GetPointerItem(secondEvent->GetPointerId(), secondItem);
855     int32_t durationX = secondItem.GetDisplayX() - firstItem.GetDisplayX();
856     int32_t durationY = secondItem.GetDisplayY() - firstItem.GetDisplayY();
857     float distance = static_cast<float>(hypot(durationX, durationY));
858 
859     return distance;
860 }
861 
OnTripleTap(MMI::PointerEvent & event)862 void AccessibilityZoomGesture::OnTripleTap(MMI::PointerEvent &event)
863 {
864     HILOG_INFO("state_ is %{public}d.", state_);
865 
866     switch (state_) {
867         case READY_STATE: {
868             TransferState(ZOOMIN_STATE);
869             int32_t pointerId = event.GetPointerId();
870             MMI::PointerEvent::PointerItem item;
871             event.GetPointerItem(pointerId, item);
872             int32_t anchorX = item.GetDisplayX();
873             int32_t anchorY = item.GetDisplayY();
874             HILOG_DEBUG("anchorX:%{private}d, anchorY:%{private}d.", anchorX, anchorY);
875             OnZoom(anchorX, anchorY, true);
876             break;
877         }
878         case ZOOMIN_STATE:
879             TransferState(READY_STATE);
880             OffZoom();
881             break;
882         default:
883             break;
884     }
885 
886     ClearCacheEventsAndMsg();
887 }
888 
ZoomGestureEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,AccessibilityZoomGesture & zoomGesture)889 AccessibilityZoomGesture::ZoomGestureEventHandler::ZoomGestureEventHandler(
890     const std::shared_ptr<AppExecFwk::EventRunner> &runner,
891     AccessibilityZoomGesture &zoomGesture): AppExecFwk::EventHandler(runner), zoomGesture_(zoomGesture)
892 {
893     HILOG_DEBUG();
894 }
895 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)896 void AccessibilityZoomGesture::ZoomGestureEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
897 {
898     HILOG_DEBUG();
899 
900     uint32_t eventId = event->GetInnerEventId();
901 
902     switch (eventId) {
903         case MULTI_TAP_MSG:
904             HILOG_DEBUG("process multi tap msg.");
905             if (zoomGesture_.isTripleDown_) {
906                 zoomGesture_.OnDrag();
907             } else {
908                 zoomGesture_.SendCacheEventsToNext();
909             }
910             break;
911         default:
912             break;
913     }
914 }
915 
GetWindowParam(bool needRefresh)916 void AccessibilityZoomGesture::GetWindowParam(bool needRefresh)
917 {
918     HILOG_DEBUG();
919 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
920     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
921     uint64_t currentScreen = displayMgr.GetDefaultDisplayId();
922     OHOS::Rosen::DisplayOrientation currentOrientation = displayMgr.GetOrientation();
923     if (needRefresh || (currentScreen != screenId_) || (currentOrientation != orientation_)) {
924         HILOG_INFO("display id or orientation changed.");
925         screenId_ = currentScreen;
926         orientation_ = currentOrientation;
927         sptr<Rosen::Display> display = displayMgr.GetDisplay(screenId_);
928         screenWidth_ = static_cast<uint32_t>(display->GetWidth());
929         screenHeight_ = static_cast<uint32_t>(display->GetHeight());
930         HILOG_INFO("screenWidth_ = %{public}d, screenHeight_ = %{public}d.", screenWidth_, screenHeight_);
931     }
932     screenSpan_ = hypot(screenWidth_, screenHeight_);
933 #else
934     HILOG_INFO("not support zoom");
935 #endif
936 }
937 
StartMagnificationInteract()938 void AccessibilityZoomGesture::StartMagnificationInteract()
939 {
940     HILOG_INFO();
941     TransferState(ZOOMIN_STATE);
942 }
943 
DisableGesture()944 void AccessibilityZoomGesture::DisableGesture()
945 {
946     HILOG_INFO();
947     TransferState(READY_STATE);
948 }
949 
OnZoom(int32_t anchorX,int32_t anchorY,bool showMenu)950 void AccessibilityZoomGesture::OnZoom(int32_t anchorX, int32_t anchorY, bool showMenu)
951 {
952     HILOG_INFO();
953     centerX_ = anchorX;
954     centerY_ = anchorY;
955     if (fullScreenManager_ == nullptr) {
956         HILOG_ERROR("fullScreenManager_ is nullptr.");
957         return;
958     }
959     fullScreenManager_->EnableMagnification(anchorX, anchorY);
960     Singleton<AccessibleAbilityManagerService>::GetInstance().AnnouncedForMagnification(
961         AnnounceType::ANNOUNCE_MAGNIFICATION_SCALE);
962     if (showMenu && menuManager_ != nullptr) {
963         menuManager_->ShowMenuWindow(FULL_SCREEN_MAGNIFICATION);
964     }
965     Utils::RecordOnZoomGestureEvent("on", true);
966 }
967 
OffZoom()968 void AccessibilityZoomGesture::OffZoom()
969 {
970     HILOG_INFO();
971     if (fullScreenManager_ == nullptr) {
972         HILOG_ERROR("fullScreenManager_ is nullptr.");
973         return;
974     }
975     if (menuManager_ == nullptr) {
976         HILOG_ERROR("menuManager_ is nullptr.");
977         return;
978     }
979     if (fullScreenManager_->IsMagnificationWindowShow()) {
980         HILOG_INFO("full magnification disable.");
981         fullScreenManager_->DisableMagnification(false);
982         menuManager_->DisableMenuWindow();
983         Singleton<AccessibleAbilityManagerService>::GetInstance().AnnouncedForMagnification(
984             AnnounceType::ANNOUNCE_MAGNIFICATION_DISABLE);
985     }
986     Utils::RecordOnZoomGestureEvent("off", true);
987 }
988 
OnScroll(float offsetX,float offsetY)989 void AccessibilityZoomGesture::OnScroll(float offsetX, float offsetY)
990 {
991     HILOG_DEBUG("offsetX:%{public}f, offsetY:%{public}f.", offsetX, offsetY);
992 
993     if (fullScreenManager_ == nullptr) {
994         HILOG_ERROR("fullScreenManager_ is nullptr.");
995         return;
996     }
997     fullScreenManager_->MoveMagnification(static_cast<int32_t>(offsetX), static_cast<int32_t>(offsetY));
998 
999 #ifdef OHOS_BUILD_ENABLE_POWER_MANAGER
1000     AccessibilityPowerManager &powerMgr = Singleton<AccessibilityPowerManager>::GetInstance();
1001     powerMgr.RefreshActivity();
1002 #endif
1003 }
1004 
OnScale(float scaleSpan)1005 void AccessibilityZoomGesture::OnScale(float scaleSpan)
1006 {
1007     HILOG_DEBUG();
1008     if (fullScreenManager_ == nullptr) {
1009         HILOG_ERROR("fullScreenManager_ is nullptr.");
1010         return;
1011     }
1012     fullScreenManager_->SetScale(scaleSpan);
1013 }
1014 
Clear()1015 void AccessibilityZoomGesture::Clear()
1016 {
1017     HILOG_DEBUG();
1018     SendCacheEventsToNext();
1019     TransferState(READY_STATE);
1020 }
1021 
DestroyEvents()1022 void AccessibilityZoomGesture::DestroyEvents()
1023 {
1024     HILOG_INFO();
1025     Clear();
1026     OffZoom();
1027     EventTransmission::DestroyEvents();
1028 }
1029 
ShieldZoomGesture(bool state)1030 void AccessibilityZoomGesture::ShieldZoomGesture(bool state)
1031 {
1032     shieldZoomGestureFlag_ = state;
1033     if (menuManager_ == nullptr) {
1034         HILOG_ERROR("menuManager_ is nullptr.");
1035         return;
1036     }
1037     HILOG_INFO("ShieldZoomGesture state = %{public}d", state);
1038     if (state) {
1039         Clear();
1040         menuManager_->DisableMenuWindow();
1041         if (fullScreenManager_ == nullptr) {
1042             HILOG_ERROR("fullScreenManager_ is nullptr.");
1043             return;
1044         }
1045         fullScreenManager_->DisableMagnification(true);
1046         Singleton<AccessibleAbilityManagerService>::GetInstance().AnnouncedForMagnification(
1047             AnnounceType::ANNOUNCE_MAGNIFICATION_DISABLE);
1048     }
1049 }
1050 
OnDrag()1051 void AccessibilityZoomGesture::OnDrag()
1052 {
1053     TransferState(DRAGGING_STATE);
1054     if (lastDownEvent_ == nullptr) {
1055         HILOG_ERROR("lastDownEvent_ is nullptr");
1056         return;
1057     }
1058 
1059     MMI::PointerEvent::PointerItem item;
1060     lastDownEvent_->GetPointerItem(lastDownEvent_->GetPointerId(), item);
1061 
1062     int32_t anchorX = item.GetDisplayX();
1063     int32_t anchorY = item.GetDisplayY();
1064     OnZoom(anchorX, anchorY, false);
1065     lastScrollFocusX_ = static_cast<float>(anchorX);
1066     lastScrollFocusY_ = static_cast<float>(anchorY);
1067     isTripleDown_ = false;
1068     ClearCacheEventsAndMsg();
1069 }
1070 } // namespace Accessibility
1071 } // namespace OHOS
1072