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