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