• 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 float HALF = 0.5f;
36     constexpr uint32_t DOUBLE = 2;
37     constexpr uint32_t TRIPLE_TAP_COUNT = 3;
38     constexpr float DEFAULT_SCALE = 2.0f;
39     constexpr float NORMAL_SCALE = 1.0f;
40     constexpr float MAX_SCALE = 8.0f;
41     constexpr uint32_t INPUT_METHOD_WINDOW_TYPE = 2105;
42     constexpr float EPS = 1e-6;
43     constexpr float MIN_SCROLL_SPAN = 2.0f;
44     constexpr float MIN_SCALE_SPAN = 2.0f;
45     constexpr float DEFAULT_ANCHOR = 0.5f;
46 } // namespace
47 
AccessibilityZoomGesture()48 AccessibilityZoomGesture::AccessibilityZoomGesture()
49 {
50     HILOG_DEBUG();
51 
52     zoomGestureEventHandler_ = std::make_shared<ZoomGestureEventHandler>(
53         Singleton<AccessibleAbilityManagerService>::GetInstance().GetInputManagerRunner(), *this);
54 
55     tapDistance_ = TAP_MIN_DISTANCE;
56 
57 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
58     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
59     auto display = displayMgr.GetDefaultDisplay();
60     if (!display) {
61         HILOG_ERROR("get display is nullptr");
62         return;
63     }
64 
65     float densityPixels = display->GetVirtualPixelRatio();
66     multiTapDistance_ = densityPixels * DOUBLE_TAP_SLOP + 0.5f;
67 #else
68     HILOG_DEBUG("not support display manager");
69     multiTapDistance_ = 1 * DOUBLE_TAP_SLOP + 0.5f;
70 #endif
71 }
72 
IsTapOnInputMethod(MMI::PointerEvent & event)73 bool AccessibilityZoomGesture::IsTapOnInputMethod(MMI::PointerEvent &event)
74 {
75     size_t pointerCount = event.GetPointerIds().size();
76     if (pointerCount != POINTER_COUNT_1) {
77         HILOG_DEBUG("not single finger.");
78         return false;
79     }
80     std::vector<AccessibilityWindowInfo> windowInfos =
81         Singleton<AccessibilityWindowManager>::GetInstance().GetAccessibilityWindows();
82     for (auto &window : windowInfos) {
83         if (window.GetWindowType() == INPUT_METHOD_WINDOW_TYPE) {
84             Rect inputRect = window.GetRectInScreen();
85             int32_t leftTopX = inputRect.GetLeftTopXScreenPostion();
86             int32_t leftTopY = inputRect.GetLeftTopYScreenPostion();
87             int32_t rightBottomX = inputRect.GetRightBottomXScreenPostion();
88             int32_t rightBottomY = inputRect.GetRightBottomYScreenPostion();
89 
90             MMI::PointerEvent::PointerItem item;
91             event.GetPointerItem(event.GetPointerId(), item);
92             int32_t itemX = item.GetDisplayX();
93             int32_t itemY = item.GetDisplayY();
94             if ((itemX >= leftTopX) && (itemX <= rightBottomX) &&
95             (itemY >= leftTopY) && (itemY <= rightBottomY)) {
96                 HILOG_INFO("tap on input method window.");
97                 return true;
98             }
99         }
100     }
101     HILOG_DEBUG("have no input method window.");
102     return false;
103 }
104 
OnPointerEvent(MMI::PointerEvent & event)105 bool AccessibilityZoomGesture::OnPointerEvent(MMI::PointerEvent &event)
106 {
107     HILOG_DEBUG("state_ is %{public}d.", state_);
108 
109     if (event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN ||
110         event.GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_UP) {
111         HILOG_INFO("PointerAction: %{public}d.", event.GetPointerAction());
112     }
113 
114     int32_t sourceType = event.GetSourceType();
115     if (sourceType != MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
116         EventTransmission::OnPointerEvent(event);
117         return false;
118     }
119 
120     if (IsTapOnInputMethod(event)) {
121         EventTransmission::OnPointerEvent(event);
122         return true;
123     }
124 
125     switch (state_) {
126         case READY_STATE:
127             CacheEvents(event);
128             RecognizeInReadyState(event);
129             break;
130         case ZOOMIN_STATE:
131             CacheEvents(event);
132             RecognizeInZoomState(event);
133             break;
134         case SLIDING_STATE:
135             RecognizeInSlidingState(event);
136             break;
137         default:
138             break;
139     }
140     return true;
141 }
142 
TransferState(ACCESSIBILITY_ZOOM_STATE state)143 void AccessibilityZoomGesture::TransferState(ACCESSIBILITY_ZOOM_STATE state)
144 {
145     HILOG_DEBUG("old state= %{public}d, new state= %{public}d", state_, state);
146 
147     state_ = state;
148 }
149 
CacheEvents(MMI::PointerEvent & event)150 void AccessibilityZoomGesture::CacheEvents(MMI::PointerEvent &event)
151 {
152     HILOG_DEBUG();
153 
154     int32_t action = event.GetPointerAction();
155     size_t pointerCount = event.GetPointerIds().size();
156     std::shared_ptr<MMI::PointerEvent> pointerEvent = std::make_shared<MMI::PointerEvent>(event);
157 
158     switch (action) {
159         case MMI::PointerEvent::POINTER_ACTION_DOWN:
160             if (pointerCount == POINTER_COUNT_1) {
161                 HILOG_DEBUG("Cache pointer down");
162                 preLastDownEvent_ = lastDownEvent_;
163                 lastDownEvent_ = pointerEvent;
164             }
165             break;
166         case MMI::PointerEvent::POINTER_ACTION_UP:
167             if (pointerCount == POINTER_COUNT_1) {
168                 HILOG_DEBUG("Cache pointer up");
169                 preLastUpEvent_ = lastUpEvent_;
170                 lastUpEvent_ = pointerEvent;
171             }
172             break;
173         case MMI::PointerEvent::POINTER_ACTION_MOVE:
174             if (pointerCount == POINTER_COUNT_1) {
175                 HILOG_DEBUG("Cache pointer move.");
176                 currentMoveEvent_ = pointerEvent;
177             }
178             break;
179         default:
180             HILOG_DEBUG("Action is %{public}d", action);
181             break;
182     }
183     cacheEvents_.emplace_back(pointerEvent);
184 }
185 
SendCacheEventsToNext()186 void AccessibilityZoomGesture::SendCacheEventsToNext()
187 {
188     HILOG_DEBUG();
189 
190     bool isStartNewAction = false;
191     int32_t action = MMI::PointerEvent::POINTER_ACTION_UNKNOWN;
192     std::vector<std::shared_ptr<MMI::PointerEvent>> cacheEventsTmp;
193     std::copy(cacheEvents_.begin(), cacheEvents_.end(), std::back_inserter(cacheEventsTmp));
194 
195     ClearCacheEventsAndMsg();
196 
197     size_t cacheEventsNum = 0;
198     size_t cacheEventsTotalNum = cacheEventsTmp.size();
199     for (auto &pointerEvent : cacheEventsTmp) {
200         cacheEventsNum++;
201         action = pointerEvent->GetPointerAction();
202         if ((cacheEventsNum > 1) &&
203             (cacheEventsNum == cacheEventsTotalNum) &&
204             (action == MMI::PointerEvent::POINTER_ACTION_DOWN)) {
205             HILOG_DEBUG("The down event needs to be parsed again");
206             isStartNewAction = true;
207         }
208         if (isStartNewAction) {
209             OnPointerEvent(*pointerEvent);
210         } else {
211             pointerEvent->SetActionTime(Utils::GetSystemTime() * US_TO_MS);
212             EventTransmission::OnPointerEvent(*pointerEvent);
213         }
214     }
215 }
216 
ClearCacheEventsAndMsg()217 void AccessibilityZoomGesture::ClearCacheEventsAndMsg()
218 {
219     HILOG_DEBUG();
220 
221     cacheEvents_.clear();
222     preLastDownEvent_ = nullptr;
223     lastDownEvent_ = nullptr;
224     preLastUpEvent_ = nullptr;
225     lastUpEvent_ = nullptr;
226 }
227 
RecognizeInReadyState(MMI::PointerEvent & event)228 void AccessibilityZoomGesture::RecognizeInReadyState(MMI::PointerEvent &event)
229 {
230     HILOG_DEBUG();
231 
232     int32_t action = event.GetPointerAction();
233     size_t pointerCount = event.GetPointerIds().size();
234     bool isTripleTaps = false;
235 
236     HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
237     switch (action) {
238         case MMI::PointerEvent::POINTER_ACTION_DOWN:
239             zoomGestureEventHandler_->RemoveEvent(MULTI_TAP_MSG);
240             if ((pointerCount == POINTER_COUNT_1) && IsDownValid()) {
241                 zoomGestureEventHandler_->SendEvent(MULTI_TAP_MSG, 0, MULTI_TAP_TIMER);
242             } else {
243                 SendCacheEventsToNext();
244             }
245             break;
246         case MMI::PointerEvent::POINTER_ACTION_UP:
247             if ((pointerCount == POINTER_COUNT_1) && IsUpValid()) {
248                 isTripleTaps = IsTripleTaps();
249             } else {
250                 SendCacheEventsToNext();
251                 HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
252             }
253             break;
254         case MMI::PointerEvent::POINTER_ACTION_MOVE:
255             if ((pointerCount == POINTER_COUNT_1) && IsMoveValid()) {
256                 HILOG_DEBUG("move valid.");
257             } else {
258                 SendCacheEventsToNext();
259                 HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
260             }
261             break;
262         case MMI::PointerEvent::POINTER_ACTION_CANCEL:
263             SendCacheEventsToNext();
264             break;
265         default:
266             break;
267     }
268 
269     if (isTripleTaps) {
270         OnTripleTaps(event);
271     }
272 }
273 
RecognizeInZoomStateDownEvent(MMI::PointerEvent & event)274 void AccessibilityZoomGesture::RecognizeInZoomStateDownEvent(MMI::PointerEvent &event)
275 {
276     HILOG_DEBUG();
277 
278     std::vector<int32_t> pointerIdList = event.GetPointerIds();
279     size_t pointerCount = pointerIdList.size();
280     zoomGestureEventHandler_->RemoveEvent(MULTI_TAP_MSG);
281     if (pointerCount == POINTER_COUNT_1) {
282         isLongPress_ = false;
283         std::shared_ptr<MMI::PointerEvent> pointerEvent = std::make_shared<MMI::PointerEvent>(event);
284         longPressDownEvent_ = pointerEvent;
285         downPid_ = event.GetPointerId();
286         if (IsDownValid()) {
287             zoomGestureEventHandler_->SendEvent(MULTI_TAP_MSG, 0, MULTI_TAP_TIMER);
288         } else {
289             SendCacheEventsToNext();
290         }
291     } else if (pointerCount == POINTER_COUNT_2) {
292         if (isLongPress_ || IsKnuckles(event)) {
293             HILOG_INFO("not transferState sliding.");
294             SendCacheEventsToNext();
295         } else {
296             TransferState(SLIDING_STATE);
297             ClearCacheEventsAndMsg();
298             ZOOM_FOCUS_COORDINATE focusXY = {0.0f, 0.0f};
299             CalcFocusCoordinate(event, focusXY);
300             lastScrollFocusX_ = focusXY.centerX;
301             lastScrollFocusY_ = focusXY.centerY;
302             float span = CalcScaleSpan(event, focusXY);
303             preSpan_ = lastSpan_ = span;
304         }
305     } else {
306         HILOG_INFO("invalid pointer count.");
307     }
308 }
309 
RecognizeInZoomState(MMI::PointerEvent & event)310 void AccessibilityZoomGesture::RecognizeInZoomState(MMI::PointerEvent &event)
311 {
312     HILOG_DEBUG();
313 
314     int32_t action = event.GetPointerAction();
315     std::vector<int32_t> pointerIdList = event.GetPointerIds();
316     size_t pointerCount = pointerIdList.size();
317     bool isTripleTaps = false;
318 
319     HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
320     switch (action) {
321         case MMI::PointerEvent::POINTER_ACTION_DOWN:
322             RecognizeInZoomStateDownEvent(event);
323             break;
324         case MMI::PointerEvent::POINTER_ACTION_UP:
325             if (downPid_ == event.GetPointerId()) {
326                 isLongPress_ = false;
327             }
328             if ((pointerCount == POINTER_COUNT_1) && IsUpValid()) {
329                 isTripleTaps = IsTripleTaps();
330             } else {
331                 SendCacheEventsToNext();
332             }
333             break;
334         case MMI::PointerEvent::POINTER_ACTION_MOVE:
335             if ((pointerCount == POINTER_COUNT_1) && !IsLongPress() && IsMoveValid()) {
336                 HILOG_DEBUG("move valid.");
337             } else {
338                 SendCacheEventsToNext();
339                 HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
340             }
341             break;
342         case MMI::PointerEvent::POINTER_ACTION_CANCEL:
343             SendCacheEventsToNext();
344             HILOG_DEBUG("action:%{public}d", action);
345             break;
346         default:
347             break;
348     }
349 
350     if (isTripleTaps) {
351         OnTripleTaps(event);
352     }
353 }
354 
RecognizeInSlidingState(MMI::PointerEvent & event)355 void AccessibilityZoomGesture::RecognizeInSlidingState(MMI::PointerEvent &event)
356 {
357     HILOG_DEBUG();
358 
359     int32_t action = event.GetPointerAction();
360     size_t pointerCount = event.GetPointerIds().size();
361     ZOOM_FOCUS_COORDINATE coordinate = {0.0f, 0.0f};
362     CalcFocusCoordinate(event, coordinate);
363 
364     if (pointerCount == POINTER_COUNT_2) {
365         RecognizeScale(event, coordinate);
366         RecognizeScroll(event, coordinate);
367     }
368 
369     HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
370     switch (action) {
371         case MMI::PointerEvent::POINTER_ACTION_UP:
372             if (pointerCount == POINTER_COUNT_1) {
373                 TransferState(ZOOMIN_STATE);
374             }
375             break;
376         case MMI::PointerEvent::POINTER_ACTION_CANCEL:
377             TransferState(ZOOMIN_STATE);
378             break;
379         default:
380             break;
381     }
382 }
383 
RecognizeScroll(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE & coordinate)384 void AccessibilityZoomGesture::RecognizeScroll(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate)
385 {
386     HILOG_DEBUG();
387 
388     int32_t action = event.GetPointerAction();
389     switch (action) {
390         case MMI::PointerEvent::POINTER_ACTION_DOWN:
391         case MMI::PointerEvent::POINTER_ACTION_UP:
392             lastScrollFocusX_ = coordinate.centerX;
393             lastScrollFocusY_ = coordinate.centerY;
394             break;
395         case MMI::PointerEvent::POINTER_ACTION_MOVE: {
396             float offsetX = coordinate.centerX - lastScrollFocusX_;
397             float offsetY = coordinate.centerY - lastScrollFocusY_;
398             if ((abs(offsetX) > MIN_SCROLL_SPAN) || (abs(offsetY) > MIN_SCROLL_SPAN)) {
399                 lastScrollFocusX_ = coordinate.centerX;
400                 lastScrollFocusY_ = coordinate.centerY;
401                 OnScroll(offsetX, offsetY);
402             }
403             break;
404         }
405         default:
406             break;
407     }
408 }
409 
RecognizeScale(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE & coordinate)410 void AccessibilityZoomGesture::RecognizeScale(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate)
411 {
412     HILOG_DEBUG();
413 
414     int32_t action = event.GetPointerAction();
415     size_t pointerCount = event.GetPointerIds().size();
416     if (((action == MMI::PointerEvent::POINTER_ACTION_UP) && (pointerCount != POINTER_COUNT_2)) ||
417         (action == MMI::PointerEvent::POINTER_ACTION_CANCEL)) {
418         HILOG_DEBUG("Scaling is end");
419         startScaling_ = false;
420         preSpan_ = lastSpan_ = 0;
421         return;
422     }
423 
424     float span = CalcScaleSpan(event, coordinate);
425 
426     if (action == MMI::PointerEvent::POINTER_ACTION_MOVE) {
427         if (abs(preSpan_ - span) >= MIN_SCALE_SPAN) {
428             startScaling_ = true;
429             HILOG_DEBUG("start scaling.");
430         }
431     }
432     if (!startScaling_) {
433         // When the span is greater than or equal to MIN_SCALE_SPAN, start scaling.
434         if (abs(preSpan_ - span) >= MIN_SCALE_SPAN) {
435             startScaling_ = true;
436             HILOG_DEBUG("start scaling.");
437         }
438     } else {
439         // When the span is smaller than the MIN_SCALE_SPAN,
440         // the scale recognition will be restarted.
441         if (abs(lastSpan_ - span) < 1) {
442             startScaling_ = false;
443             preSpan_ = lastSpan_ = span;
444         }
445         if ((action == MMI::PointerEvent::POINTER_ACTION_UP) ||
446             (action == MMI::PointerEvent::POINTER_ACTION_DOWN)) {
447             preSpan_ = lastSpan_ = span;
448         }
449     }
450 
451     if (!startScaling_) {
452         HILOG_DEBUG("Current is not scaling");
453         return;
454     }
455 
456     if (action != MMI::PointerEvent::POINTER_ACTION_MOVE) {
457         HILOG_DEBUG("Action(%{public}d) is not move", action);
458         return;
459     }
460 
461     float scaleSpan = (span - lastSpan_) * scaleRatio_;
462     if (abs(scaleSpan) > EPS) {
463         OnScale(scaleSpan);
464         lastSpan_ = span;
465     }
466 }
467 
CalcFocusCoordinate(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE & coordinate)468 void AccessibilityZoomGesture::CalcFocusCoordinate(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate)
469 {
470     HILOG_DEBUG();
471 
472     float sumX = 0.0f;
473     float sumY = 0.0f;
474     int32_t upPointerId = -1;
475     int32_t action = event.GetPointerAction();
476     std::vector<int32_t> pointerIdList = event.GetPointerIds();
477     size_t count = pointerIdList.size();
478     if (!count) {
479         HILOG_DEBUG("The size of PointerIds is 0");
480         return;
481     }
482 
483     if (action == MMI::PointerEvent::POINTER_ACTION_UP) {
484         upPointerId = event.GetPointerId();
485         HILOG_DEBUG("The pointer id of up is %{public}d", upPointerId);
486         count--;
487     }
488 
489     if (!count) {
490         HILOG_DEBUG("The size of PointerIds(down) is invalid");
491         return;
492     }
493 
494     for (int32_t pointerId : pointerIdList) {
495         if (pointerId == upPointerId) {
496             continue;
497         }
498         MMI::PointerEvent::PointerItem item;
499         event.GetPointerItem(pointerId, item);
500         sumX += static_cast<float>(item.GetRawDisplayX());
501         sumY += static_cast<float>(item.GetRawDisplayY());
502     }
503 
504     coordinate.centerX = sumX / count;
505     coordinate.centerY = sumY / count;
506     HILOG_DEBUG("centerX:%{public}f, centerY:%{public}f", coordinate.centerX, coordinate.centerY);
507 }
508 
CalcScaleSpan(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE coordinate)509 float AccessibilityZoomGesture::CalcScaleSpan(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE coordinate)
510 {
511     HILOG_DEBUG();
512 
513     float span = 0.0f;
514     float sumSpanX = 0.0f;
515     float sumSpanY = 0.0f;
516     int32_t upPointerId = -1;
517     int32_t action = event.GetPointerAction();
518     std::vector<int32_t> pointerIdList = event.GetPointerIds();
519     size_t count = pointerIdList.size();
520     if (!count) {
521         HILOG_DEBUG("The size of PointerIds is 0");
522         return span;
523     }
524 
525     if (action == MMI::PointerEvent::POINTER_ACTION_UP) {
526         upPointerId = event.GetPointerId();
527         HILOG_DEBUG("The pointer id of up is %{public}d", upPointerId);
528         count--;
529     }
530 
531     if (!count) {
532         HILOG_DEBUG("The size of PointerIds(down) is invalid");
533         return span;
534     }
535 
536     for (int32_t pointerId : pointerIdList) {
537         if (pointerId == upPointerId) {
538             continue;
539         }
540         MMI::PointerEvent::PointerItem item;
541         event.GetPointerItem(pointerId, item);
542         sumSpanX += static_cast<float>(abs(item.GetRawDisplayX() - coordinate.centerX));
543         sumSpanY += static_cast<float>(abs(item.GetRawDisplayY() - coordinate.centerY));
544     }
545 
546     float spanX = sumSpanX / count;
547     float spanY = sumSpanY / count;
548     span = hypot(spanX, spanY) / HALF;
549     HILOG_DEBUG("The span is %{public}f", span);
550     return span;
551 }
552 
IsDownValid()553 bool AccessibilityZoomGesture::IsDownValid()
554 {
555     HILOG_DEBUG();
556 
557     if (!preLastDownEvent_) {
558         HILOG_DEBUG("This is the first down event");
559         return true;
560     }
561 
562     if (CalcSeparationDistance(preLastDownEvent_, lastDownEvent_) >= multiTapDistance_) {
563         HILOG_DEBUG("The down event is vailid");
564         return false;
565     }
566     return true;
567 }
568 
IsUpValid()569 bool AccessibilityZoomGesture::IsUpValid()
570 {
571     HILOG_DEBUG();
572 
573     if (!lastDownEvent_) {
574         HILOG_DEBUG("The up event is invailid");
575         return false;
576     }
577 
578     if (CalcIntervalTime(lastDownEvent_, lastUpEvent_) >= LONG_PRESS_TIMER) {
579         HILOG_DEBUG("The time has exceeded the long press time");
580         return false;
581     }
582 
583     if (CalcSeparationDistance(lastDownEvent_, lastUpEvent_) >= tapDistance_) {
584         HILOG_DEBUG("The distance has exceeded the threshold");
585         return false;
586     }
587     return true;
588 }
589 
IsMoveValid()590 bool AccessibilityZoomGesture::IsMoveValid()
591 {
592     HILOG_DEBUG();
593 
594     if (!lastDownEvent_) {
595         HILOG_DEBUG("The move event is invailid");
596         return false;
597     }
598 
599     if (CalcIntervalTime(lastDownEvent_, currentMoveEvent_) >= LONG_PRESS_TIMER) {
600         HILOG_DEBUG("The time has exceeded the long press time");
601         return false;
602     }
603 
604     if (CalcSeparationDistance(lastDownEvent_, currentMoveEvent_) >= tapDistance_) {
605         HILOG_DEBUG("The distance has exceeded the threshold");
606         return false;
607     }
608     return true;
609 }
610 
IsLongPress()611 bool AccessibilityZoomGesture::IsLongPress()
612 {
613     HILOG_DEBUG();
614 
615     if (CalcIntervalTime(longPressDownEvent_, currentMoveEvent_) >= LONG_PRESS_TIMER) {
616         HILOG_DEBUG("The time has exceeded the long press time");
617         isLongPress_ = true;
618         return true;
619     }
620     return false;
621 }
622 
IsKnuckles(MMI::PointerEvent & event)623 bool AccessibilityZoomGesture::IsKnuckles(MMI::PointerEvent &event)
624 {
625     HILOG_DEBUG();
626 
627     std::vector<int32_t> pointerIdList = event.GetPointerIds();
628     for (int32_t pointerId : pointerIdList) {
629         MMI::PointerEvent::PointerItem item;
630         event.GetPointerItem(pointerId, item);
631         int32_t toolType = item.GetToolType();
632         if (toolType == MMI::PointerEvent::TOOL_TYPE_KNUCKLE) {
633             HILOG_INFO("is knuckle event.");
634             return true;
635         }
636     }
637     return false;
638 }
639 
IsTripleTaps()640 bool AccessibilityZoomGesture::IsTripleTaps()
641 {
642     HILOG_DEBUG();
643 
644     uint32_t upEventCount = 0;
645     int32_t action = MMI::PointerEvent::POINTER_ACTION_UNKNOWN;
646     for (auto &pointerEvent : cacheEvents_) {
647         action = pointerEvent->GetPointerAction();
648         if (action == MMI::PointerEvent::POINTER_ACTION_UP) {
649             upEventCount++;
650         }
651     }
652 
653     if (upEventCount >= TRIPLE_TAP_COUNT) {
654         HILOG_DEBUG("Triple tap detected");
655         return true;
656     }
657 
658     return false;
659 }
660 
CalcIntervalTime(std::shared_ptr<MMI::PointerEvent> firstEvent,std::shared_ptr<MMI::PointerEvent> secondEvent)661 int64_t AccessibilityZoomGesture::CalcIntervalTime(std::shared_ptr<MMI::PointerEvent> firstEvent,
662     std::shared_ptr<MMI::PointerEvent> secondEvent)
663 {
664     HILOG_DEBUG();
665 
666     if (!firstEvent || !secondEvent) {
667         HILOG_DEBUG("The event is null");
668         return 0;
669     }
670 
671     int64_t firstTime = firstEvent->GetActionTime();
672     int64_t secondTime = secondEvent->GetActionTime();
673     int64_t intervalTime = (secondTime - firstTime) / US_TO_MS;
674 
675     return intervalTime;
676 }
677 
CalcSeparationDistance(std::shared_ptr<MMI::PointerEvent> firstEvent,std::shared_ptr<MMI::PointerEvent> secondEvent)678 float AccessibilityZoomGesture::CalcSeparationDistance(std::shared_ptr<MMI::PointerEvent> firstEvent,
679     std::shared_ptr<MMI::PointerEvent> secondEvent)
680 {
681     HILOG_DEBUG();
682 
683     if (!firstEvent || !secondEvent) {
684         HILOG_DEBUG("The event is null");
685         return 0;
686     }
687 
688     MMI::PointerEvent::PointerItem firstItem;
689     MMI::PointerEvent::PointerItem secondItem;
690     firstEvent->GetPointerItem(firstEvent->GetPointerId(), firstItem);
691     secondEvent->GetPointerItem(secondEvent->GetPointerId(), secondItem);
692     int32_t durationX = secondItem.GetDisplayX() - firstItem.GetDisplayX();
693     int32_t durationY = secondItem.GetDisplayY() - firstItem.GetDisplayY();
694     float distance = static_cast<float>(hypot(durationX, durationY));
695 
696     return distance;
697 }
698 
OnTripleTaps(MMI::PointerEvent & event)699 void AccessibilityZoomGesture::OnTripleTaps(MMI::PointerEvent &event)
700 {
701     HILOG_DEBUG("state_ is %{public}d.", state_);
702 
703     switch (state_) {
704         case READY_STATE: {
705             TransferState(ZOOMIN_STATE);
706             int32_t pointerId = event.GetPointerId();
707             MMI::PointerEvent::PointerItem item;
708             event.GetPointerItem(pointerId, item);
709             int32_t anchorX = item.GetDisplayX();
710             int32_t anchorY = item.GetDisplayY();
711             HILOG_DEBUG("anchorX:%{private}d, anchorY:%{private}d.", anchorX, anchorY);
712             OnZoom(anchorX, anchorY);
713             break;
714         }
715         case ZOOMIN_STATE:
716             TransferState(READY_STATE);
717             OffZoom();
718             break;
719         default:
720             break;
721     }
722 
723     ClearCacheEventsAndMsg();
724 }
725 
ZoomGestureEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,AccessibilityZoomGesture & zoomGesture)726 AccessibilityZoomGesture::ZoomGestureEventHandler::ZoomGestureEventHandler(
727     const std::shared_ptr<AppExecFwk::EventRunner> &runner,
728     AccessibilityZoomGesture &zoomGesture): AppExecFwk::EventHandler(runner), zoomGesture_(zoomGesture)
729 {
730     HILOG_DEBUG();
731 }
732 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)733 void AccessibilityZoomGesture::ZoomGestureEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
734 {
735     HILOG_DEBUG();
736 
737     uint32_t eventId = event->GetInnerEventId();
738 
739     switch (eventId) {
740         case MULTI_TAP_MSG:
741             zoomGesture_.SendCacheEventsToNext();
742             HILOG_DEBUG("process multi tap msg.");
743             break;
744         default:
745             break;
746     }
747 }
748 
GetWindowParam()749 void AccessibilityZoomGesture::GetWindowParam()
750 {
751     HILOG_DEBUG();
752 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
753     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
754     uint64_t currentScreen = displayMgr.GetDefaultDisplayId();
755     OHOS::Rosen::DisplayOrientation currentOrientation = displayMgr.GetOrientation();
756     if ((currentScreen != screenId_) || (currentOrientation != orientation_)) {
757         HILOG_INFO("display id or orientation changed.");
758         screenId_ = currentScreen;
759         orientation_ = currentOrientation;
760         sptr<Rosen::Display> display = displayMgr.GetDisplay(screenId_);
761         screenWidth_ = static_cast<uint32_t>(display->GetWidth());
762         screenHeight_ = static_cast<uint32_t>(display->GetHeight());
763         HILOG_INFO("screenWidth_ = %{public}d, screenHeight_ = %{public}d.", screenWidth_, screenHeight_);
764     }
765     screenSpan_ = hypot(screenWidth_, screenHeight_);
766 #else
767     HILOG_INFO("not support zoom");
768 #endif
769 }
770 
OnZoom(int32_t anchorX,int32_t anchorY)771 void AccessibilityZoomGesture::OnZoom(int32_t anchorX, int32_t anchorY)
772 {
773     HILOG_INFO();
774 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
775     GetWindowParam();
776     if (screenWidth_ == 0 || screenHeight_ == 0) {
777         HILOG_ERROR("screen param invalid.");
778         return;
779     }
780     anchorPointX_ = static_cast<float>(anchorX);
781     anchorPointY_ = static_cast<float>(anchorY);
782 
783     float x = anchorPointX_ / screenWidth_;
784     float y = anchorPointY_ / screenHeight_;
785     scaleRatio_ = DEFAULT_SCALE;
786     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
787     Utils::RecordOnZoomGestureEvent("on");
788     displayMgr.SetDisplayScale(screenId_, scaleRatio_, scaleRatio_, x, y);
789 #else
790     HILOG_INFO("not support zoom");
791     return;
792 #endif
793 }
794 
OffZoom()795 void AccessibilityZoomGesture::OffZoom()
796 {
797     HILOG_INFO();
798 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
799     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
800     uint64_t currentScreen = displayMgr.GetDefaultDisplayId();
801     Utils::RecordOnZoomGestureEvent("off");
802     displayMgr.SetDisplayScale(currentScreen, NORMAL_SCALE, NORMAL_SCALE, DEFAULT_ANCHOR, DEFAULT_ANCHOR);
803 #else
804     HILOG_INFO("not support zoom");
805     return;
806 #endif
807 }
808 
OnScroll(float offsetX,float offsetY)809 void AccessibilityZoomGesture::OnScroll(float offsetX, float offsetY)
810 {
811     HILOG_DEBUG("offsetX:%{public}f, offsetY:%{public}f.", offsetX, offsetY);
812 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
813     GetWindowParam();
814     if (screenWidth_ == 0 || screenHeight_ == 0) {
815         HILOG_ERROR("screen param invalid.");
816         return;
817     }
818 
819     if (abs(scaleRatio_) < EPS) {
820         HILOG_ERROR("scaleRatio_ param invalid.");
821         return;
822     }
823     anchorPointX_ -= (offsetX * DOUBLE / scaleRatio_);
824     anchorPointY_ -= (offsetY * DOUBLE / scaleRatio_);
825 
826     if (anchorPointX_ < 0) {
827         anchorPointX_ = 0;
828     }
829     if (anchorPointX_ > screenWidth_) {
830         anchorPointX_ = screenWidth_;
831     }
832     if (anchorPointY_ < 0) {
833         anchorPointY_ = 0;
834     }
835     if (anchorPointY_ > screenHeight_) {
836         anchorPointY_ = screenHeight_;
837     }
838 
839     float x = anchorPointX_ / screenWidth_;
840     float y = anchorPointY_ / screenHeight_;
841     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
842     displayMgr.SetDisplayScale(screenId_, scaleRatio_, scaleRatio_, x, y);
843 #ifdef OHOS_BUILD_ENABLE_POWER_MANAGER
844     AccessibilityPowerManager &powerMgr = Singleton<AccessibilityPowerManager>::GetInstance();
845     powerMgr.RefreshActivity();
846 #endif
847 #else
848     HILOG_INFO("not support zoom");
849     return;
850 #endif
851 }
852 
OnScale(float scaleSpan)853 void AccessibilityZoomGesture::OnScale(float scaleSpan)
854 {
855     HILOG_DEBUG();
856 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
857     GetWindowParam();
858     if (screenWidth_ == 0 || screenHeight_ == 0 || abs(screenSpan_) < EPS) {
859         HILOG_ERROR("screen param invalid.");
860         return;
861     }
862 
863     float ratio = scaleSpan / screenSpan_;
864     scaleRatio_ = scaleRatio_ + ratio;
865     if (scaleRatio_ > MAX_SCALE) {
866         scaleRatio_ = MAX_SCALE;
867     }
868     if (scaleRatio_ < DEFAULT_SCALE) {
869         scaleRatio_ = DEFAULT_SCALE;
870     }
871 
872     float x = anchorPointX_ / screenWidth_;
873     float y = anchorPointY_ / screenHeight_;
874     AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
875     displayMgr.SetDisplayScale(screenId_, scaleRatio_, scaleRatio_, x, y);
876 #else
877     HILOG_INFO("not support zoom");
878     return;
879 #endif
880 }
881 
Clear()882 void AccessibilityZoomGesture::Clear()
883 {
884     HILOG_DEBUG();
885     SendCacheEventsToNext();
886     TransferState(READY_STATE);
887 }
888 
DestroyEvents()889 void AccessibilityZoomGesture::DestroyEvents()
890 {
891     HILOG_INFO();
892     Clear();
893     EventTransmission::DestroyEvents();
894 }
895 } // namespace Accessibility
896 } // namespace OHOS
897