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