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