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