1885b47fbSopenharmony_ci/* 2885b47fbSopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3885b47fbSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4885b47fbSopenharmony_ci * you may not use this file except in compliance with the License. 5885b47fbSopenharmony_ci * You may obtain a copy of the License at 6885b47fbSopenharmony_ci * 7885b47fbSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8885b47fbSopenharmony_ci * 9885b47fbSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10885b47fbSopenharmony_ci * distributed under the License is distributed On an "AS IS" BASIS, 11885b47fbSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12885b47fbSopenharmony_ci * See the License for the specific language governing permissions and 13885b47fbSopenharmony_ci * limitations under the License. 14885b47fbSopenharmony_ci */ 15885b47fbSopenharmony_ci 16885b47fbSopenharmony_ci#include "accessibility_gesture_recognizer.h" 17885b47fbSopenharmony_ci#include "hilog_wrapper.h" 18885b47fbSopenharmony_ci#include <cinttypes> 19885b47fbSopenharmony_ci 20885b47fbSopenharmony_cinamespace OHOS { 21885b47fbSopenharmony_cinamespace Accessibility { 22885b47fbSopenharmony_cinamespace { 23885b47fbSopenharmony_ci constexpr int32_t LIMIT_SIZE_TWO = 2; 24885b47fbSopenharmony_ci constexpr int32_t LIMIT_SIZE_THREE = 3; 25885b47fbSopenharmony_ci constexpr int32_t POINTER_COUNT_1 = 1; 26885b47fbSopenharmony_ci constexpr float EPSINON = 0.0001f; 27885b47fbSopenharmony_ci constexpr float TOUCH_SLOP = 8.0f; 28885b47fbSopenharmony_ci} // namespace 29885b47fbSopenharmony_ci 30885b47fbSopenharmony_ciGestureHandler::GestureHandler(const std::shared_ptr<AppExecFwk::EventRunner> &runner, 31885b47fbSopenharmony_ci AccessibilityGestureRecognizer &server) : AppExecFwk::EventHandler(runner), server_(server) 32885b47fbSopenharmony_ci{ 33885b47fbSopenharmony_ci} 34885b47fbSopenharmony_ci 35885b47fbSopenharmony_civoid GestureHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) 36885b47fbSopenharmony_ci{ 37885b47fbSopenharmony_ci HILOG_DEBUG(); 38885b47fbSopenharmony_ci if (!event) { 39885b47fbSopenharmony_ci HILOG_ERROR("event is null"); 40885b47fbSopenharmony_ci return; 41885b47fbSopenharmony_ci } 42885b47fbSopenharmony_ci 43885b47fbSopenharmony_ci switch (event->GetInnerEventId()) { 44885b47fbSopenharmony_ci case AccessibilityGestureRecognizer::LONG_PRESS_MSG: 45885b47fbSopenharmony_ci RemoveEvent(AccessibilityGestureRecognizer::SINGLE_TAP_MSG); 46885b47fbSopenharmony_ci server_.SetIsLongpress(true); 47885b47fbSopenharmony_ci server_.MaybeRecognizeLongPress(*server_.GetCurDown()); 48885b47fbSopenharmony_ci break; 49885b47fbSopenharmony_ci case AccessibilityGestureRecognizer::SINGLE_TAP_MSG: 50885b47fbSopenharmony_ci if (!server_.GetContinueDown()) { 51885b47fbSopenharmony_ci server_.SingleTapDetected(); 52885b47fbSopenharmony_ci } 53885b47fbSopenharmony_ci break; 54885b47fbSopenharmony_ci default: 55885b47fbSopenharmony_ci break; 56885b47fbSopenharmony_ci } 57885b47fbSopenharmony_ci} 58885b47fbSopenharmony_ci 59885b47fbSopenharmony_cifloat AccessibilityGestureRecognizer::GetDoubleTapMoveThreshold(float densityDpi) 60885b47fbSopenharmony_ci{ 61885b47fbSopenharmony_ci return densityDpi * (1.0f / 25.4f) * MM_PER_CM; 62885b47fbSopenharmony_ci} 63885b47fbSopenharmony_ci 64885b47fbSopenharmony_ciAccessibilityGestureRecognizer::AccessibilityGestureRecognizer() 65885b47fbSopenharmony_ci{ 66885b47fbSopenharmony_ci HILOG_DEBUG(); 67885b47fbSopenharmony_ci#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER 68885b47fbSopenharmony_ci AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance(); 69885b47fbSopenharmony_ci auto display = displayMgr.GetDefaultDisplay(); 70885b47fbSopenharmony_ci if (!display) { 71885b47fbSopenharmony_ci HILOG_ERROR("get display is nullptr"); 72885b47fbSopenharmony_ci return; 73885b47fbSopenharmony_ci } 74885b47fbSopenharmony_ci 75885b47fbSopenharmony_ci threshold_ = GetDoubleTapMoveThreshold(display->GetDpi()); 76885b47fbSopenharmony_ci xMinPixels_ = MIN_PIXELS(display->GetWidth()); 77885b47fbSopenharmony_ci yMinPixels_ = MIN_PIXELS(display->GetHeight()); 78885b47fbSopenharmony_ci 79885b47fbSopenharmony_ci float densityPixels = display->GetVirtualPixelRatio(); 80885b47fbSopenharmony_ci int32_t slop = static_cast<int32_t>(densityPixels * DOUBLE_TAP_SLOP + 0.5f); 81885b47fbSopenharmony_ci doubleTapScaledSlop_ = slop * slop; 82885b47fbSopenharmony_ci#else 83885b47fbSopenharmony_ci HILOG_DEBUG("not support display manager"); 84885b47fbSopenharmony_ci threshold_ = 1; 85885b47fbSopenharmony_ci xMinPixels_ = 1; 86885b47fbSopenharmony_ci yMinPixels_ = 1; 87885b47fbSopenharmony_ci int32_t slop = static_cast<int32_t>(1 * DOUBLE_TAP_SLOP + 0.5f); 88885b47fbSopenharmony_ci doubleTapScaledSlop_ = slop * slop; 89885b47fbSopenharmony_ci#endif 90885b47fbSopenharmony_ci 91885b47fbSopenharmony_ci runner_ = Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner(); 92885b47fbSopenharmony_ci if (!runner_) { 93885b47fbSopenharmony_ci HILOG_ERROR("get runner failed"); 94885b47fbSopenharmony_ci return; 95885b47fbSopenharmony_ci } 96885b47fbSopenharmony_ci handler_ = std::make_shared<GestureHandler>(runner_, *this); 97885b47fbSopenharmony_ci if (!handler_) { 98885b47fbSopenharmony_ci HILOG_ERROR("create event handler failed"); 99885b47fbSopenharmony_ci return; 100885b47fbSopenharmony_ci } 101885b47fbSopenharmony_ci} 102885b47fbSopenharmony_ci 103885b47fbSopenharmony_civoid AccessibilityGestureRecognizer::RegisterListener(AccessibilityGestureRecognizeListener& listener) 104885b47fbSopenharmony_ci{ 105885b47fbSopenharmony_ci HILOG_DEBUG(); 106885b47fbSopenharmony_ci 107885b47fbSopenharmony_ci listener_ = &listener; 108885b47fbSopenharmony_ci} 109885b47fbSopenharmony_ci 110885b47fbSopenharmony_civoid AccessibilityGestureRecognizer::UnregisterListener() 111885b47fbSopenharmony_ci{ 112885b47fbSopenharmony_ci HILOG_DEBUG(); 113885b47fbSopenharmony_ci 114885b47fbSopenharmony_ci listener_ = nullptr; 115885b47fbSopenharmony_ci} 116885b47fbSopenharmony_ci 117885b47fbSopenharmony_cibool AccessibilityGestureRecognizer::OnPointerEvent(MMI::PointerEvent &event) 118885b47fbSopenharmony_ci{ 119885b47fbSopenharmony_ci HILOG_DEBUG(); 120885b47fbSopenharmony_ci 121885b47fbSopenharmony_ci switch (event.GetPointerAction()) { 122885b47fbSopenharmony_ci case MMI::PointerEvent::POINTER_ACTION_DOWN: 123885b47fbSopenharmony_ci if (isDoubleTap_ && isLongpress_) { 124885b47fbSopenharmony_ci HILOG_INFO("isDoubleTap and longpress, on down event"); 125885b47fbSopenharmony_ci return false; 126885b47fbSopenharmony_ci } 127885b47fbSopenharmony_ci if (event.GetPointerIds().size() == POINTER_COUNT_1) { 128885b47fbSopenharmony_ci HandleTouchDownEvent(event); 129885b47fbSopenharmony_ci } else { 130885b47fbSopenharmony_ci Clear(); 131885b47fbSopenharmony_ci isRecognizingGesture_ = false; 132885b47fbSopenharmony_ci isGestureStarted_ = false; 133885b47fbSopenharmony_ci pointerRoute_.clear(); 134885b47fbSopenharmony_ci } 135885b47fbSopenharmony_ci break; 136885b47fbSopenharmony_ci case MMI::PointerEvent::POINTER_ACTION_MOVE: 137885b47fbSopenharmony_ci if (isDoubleTap_ && isLongpress_) { 138885b47fbSopenharmony_ci HILOG_DEBUG("isDoubleTap and isLongpress, send move event to Multimodel."); 139885b47fbSopenharmony_ci return false; 140885b47fbSopenharmony_ci } 141885b47fbSopenharmony_ci return HandleTouchMoveEvent(event); 142885b47fbSopenharmony_ci case MMI::PointerEvent::POINTER_ACTION_UP: 143885b47fbSopenharmony_ci if (event.GetPointerIds().size() == POINTER_COUNT_1) { 144885b47fbSopenharmony_ci return HandleTouchUpEvent(event); 145885b47fbSopenharmony_ci } 146885b47fbSopenharmony_ci break; 147885b47fbSopenharmony_ci case MMI::PointerEvent::POINTER_ACTION_CANCEL: 148885b47fbSopenharmony_ci Clear(); 149885b47fbSopenharmony_ci break; 150885b47fbSopenharmony_ci default: 151885b47fbSopenharmony_ci break; 152885b47fbSopenharmony_ci } 153885b47fbSopenharmony_ci if (!isRecognizingGesture_) { 154885b47fbSopenharmony_ci return false; 155885b47fbSopenharmony_ci } 156885b47fbSopenharmony_ci return StandardGestureRecognizer(event); 157885b47fbSopenharmony_ci} 158885b47fbSopenharmony_ci 159885b47fbSopenharmony_civoid AccessibilityGestureRecognizer::Clear() 160885b47fbSopenharmony_ci{ 161885b47fbSopenharmony_ci HILOG_DEBUG(); 162885b47fbSopenharmony_ci 163885b47fbSopenharmony_ci isFirstTapUp_ = false; 164885b47fbSopenharmony_ci isDoubleTap_ = false; 165885b47fbSopenharmony_ci isGestureStarted_ = false; 166885b47fbSopenharmony_ci isRecognizingGesture_ = false; 167885b47fbSopenharmony_ci pointerRoute_.clear(); 168885b47fbSopenharmony_ci continueDown_ = false; 169885b47fbSopenharmony_ci StandardGestureCanceled(); 170885b47fbSopenharmony_ci} 171885b47fbSopenharmony_ci 172885b47fbSopenharmony_civoid AccessibilityGestureRecognizer::HandleTouchDownEvent(MMI::PointerEvent &event) 173885b47fbSopenharmony_ci{ 174885b47fbSopenharmony_ci HILOG_DEBUG(); 175885b47fbSopenharmony_ci 176885b47fbSopenharmony_ci Pointer mp; 177885b47fbSopenharmony_ci MMI::PointerEvent::PointerItem pointerIterm; 178885b47fbSopenharmony_ci if (!event.GetPointerItem(event.GetPointerId(), pointerIterm)) { 179885b47fbSopenharmony_ci HILOG_WARN("get GetPointerItem(%{public}d) failed", event.GetPointerId()); 180885b47fbSopenharmony_ci } 181885b47fbSopenharmony_ci mp.px_ = static_cast<float>(pointerIterm.GetDisplayX()); 182885b47fbSopenharmony_ci mp.py_ = static_cast<float>(pointerIterm.GetDisplayY()); 183885b47fbSopenharmony_ci isDoubleTap_ = false; 184885b47fbSopenharmony_ci isRecognizingGesture_ = true; 185885b47fbSopenharmony_ci isGestureStarted_ = false; 186885b47fbSopenharmony_ci pointerRoute_.clear(); 187885b47fbSopenharmony_ci pointerRoute_.push_back(mp); 188885b47fbSopenharmony_ci prePointer_ = pointerIterm; 189885b47fbSopenharmony_ci startPointer_ = pointerIterm; 190885b47fbSopenharmony_ci startTime_ = event.GetActionTime(); 191885b47fbSopenharmony_ci} 192885b47fbSopenharmony_ci 193885b47fbSopenharmony_civoid AccessibilityGestureRecognizer::AddSwipePosition(MMI::PointerEvent::PointerItem &pointerIterm) 194885b47fbSopenharmony_ci{ 195885b47fbSopenharmony_ci HILOG_DEBUG(); 196885b47fbSopenharmony_ci 197885b47fbSopenharmony_ci Pointer mp; 198885b47fbSopenharmony_ci prePointer_ = pointerIterm; 199885b47fbSopenharmony_ci mp.px_ = pointerIterm.GetDisplayX(); 200885b47fbSopenharmony_ci mp.py_ = pointerIterm.GetDisplayY(); 201885b47fbSopenharmony_ci pointerRoute_.push_back(mp); 202885b47fbSopenharmony_ci} 203885b47fbSopenharmony_ci 204885b47fbSopenharmony_cibool AccessibilityGestureRecognizer::HandleTouchMoveEvent(MMI::PointerEvent &event) 205885b47fbSopenharmony_ci{ 206885b47fbSopenharmony_ci HILOG_DEBUG(); 207885b47fbSopenharmony_ci 208885b47fbSopenharmony_ci MMI::PointerEvent::PointerItem pointerIterm; 209885b47fbSopenharmony_ci if (!event.GetPointerItem(event.GetPointerId(), pointerIterm)) { 210885b47fbSopenharmony_ci HILOG_ERROR("get GetPointerItem(%{public}d) failed", event.GetPointerId()); 211885b47fbSopenharmony_ci return false; 212885b47fbSopenharmony_ci } 213885b47fbSopenharmony_ci int64_t eventTime = event.GetActionTime(); 214885b47fbSopenharmony_ci float offsetX = startPointer_.GetDisplayX() - pointerIterm.GetDisplayX(); 215885b47fbSopenharmony_ci float offsetY = startPointer_.GetDisplayY() - pointerIterm.GetDisplayY(); 216885b47fbSopenharmony_ci double duration = hypot(offsetX, offsetY); 217885b47fbSopenharmony_ci if (isRecognizingGesture_) { 218885b47fbSopenharmony_ci if (isDoubleTap_ && duration > TOUCH_SLOP) { 219885b47fbSopenharmony_ci HILOG_DEBUG("Cancel double tap event because the finger moves beyond preset slop."); 220885b47fbSopenharmony_ci isRecognizingGesture_ = false; 221885b47fbSopenharmony_ci isDoubleTap_ = false; 222885b47fbSopenharmony_ci return listener_->OnCancelled(event); 223885b47fbSopenharmony_ci } else if (duration > threshold_) { 224885b47fbSopenharmony_ci startPointer_ = pointerIterm; 225885b47fbSopenharmony_ci startTime_ = eventTime; 226885b47fbSopenharmony_ci isFirstTapUp_ = false; 227885b47fbSopenharmony_ci isDoubleTap_ = false; 228885b47fbSopenharmony_ci if (!isGestureStarted_) { 229885b47fbSopenharmony_ci isGestureStarted_ = true; 230885b47fbSopenharmony_ci listener_->OnStarted(); 231885b47fbSopenharmony_ci return false; 232885b47fbSopenharmony_ci } 233885b47fbSopenharmony_ci } else if (!isFirstTapUp_) { 234885b47fbSopenharmony_ci int64_t durationTime = eventTime - startTime_; 235885b47fbSopenharmony_ci int64_t thresholdTime = isGestureStarted_ ? 236885b47fbSopenharmony_ci GESTURE_STARTED_TIME_THRESHOLD : GESTURE_NOT_STARTED_TIME_THRESHOLD; 237885b47fbSopenharmony_ci if (durationTime > thresholdTime) { 238885b47fbSopenharmony_ci isRecognizingGesture_ = false; 239885b47fbSopenharmony_ci isGestureStarted_ = false; 240885b47fbSopenharmony_ci pointerRoute_.clear(); 241885b47fbSopenharmony_ci return listener_->OnCancelled(event); 242885b47fbSopenharmony_ci } 243885b47fbSopenharmony_ci } 244885b47fbSopenharmony_ci if ((abs(pointerIterm.GetDisplayX() - prePointer_.GetDisplayX())) >= xMinPixels_ || 245885b47fbSopenharmony_ci (abs(pointerIterm.GetDisplayY() - prePointer_.GetDisplayY())) >= yMinPixels_) { 246885b47fbSopenharmony_ci AddSwipePosition(pointerIterm); 247885b47fbSopenharmony_ci } 248885b47fbSopenharmony_ci } 249885b47fbSopenharmony_ci if (!isRecognizingGesture_) { 250885b47fbSopenharmony_ci return false; 251885b47fbSopenharmony_ci } 252885b47fbSopenharmony_ci 253885b47fbSopenharmony_ci return StandardGestureRecognizer(event); 254885b47fbSopenharmony_ci} 255885b47fbSopenharmony_ci 256885b47fbSopenharmony_cibool AccessibilityGestureRecognizer::HandleTouchUpEvent(MMI::PointerEvent &event) 257885b47fbSopenharmony_ci{ 258885b47fbSopenharmony_ci HILOG_DEBUG(); 259885b47fbSopenharmony_ci 260885b47fbSopenharmony_ci Pointer mp; 261885b47fbSopenharmony_ci MMI::PointerEvent::PointerItem pointerIterm; 262885b47fbSopenharmony_ci if (!event.GetPointerItem(event.GetPointerId(), pointerIterm)) { 263885b47fbSopenharmony_ci HILOG_WARN("get GetPointerItem(%{public}d) failed", event.GetPointerId()); 264885b47fbSopenharmony_ci } 265885b47fbSopenharmony_ci 266885b47fbSopenharmony_ci if (isDoubleTap_) { 267885b47fbSopenharmony_ci if (isLongpress_) { 268885b47fbSopenharmony_ci HILOG_DEBUG("up event, isDoubleTap and longpress."); 269885b47fbSopenharmony_ci return false; 270885b47fbSopenharmony_ci } else { 271885b47fbSopenharmony_ci HILOG_DEBUG(); 272885b47fbSopenharmony_ci return DoubleTapRecognized(event); 273885b47fbSopenharmony_ci } 274885b47fbSopenharmony_ci } 275885b47fbSopenharmony_ci if (isGestureStarted_) { 276885b47fbSopenharmony_ci if ((abs(pointerIterm.GetDisplayX() - prePointer_.GetDisplayX())) >= xMinPixels_ || 277885b47fbSopenharmony_ci (abs(pointerIterm.GetDisplayY() - prePointer_.GetDisplayY())) >= yMinPixels_) { 278885b47fbSopenharmony_ci HILOG_DEBUG("Add position to pointer route."); 279885b47fbSopenharmony_ci mp.px_ = pointerIterm.GetDisplayX(); 280885b47fbSopenharmony_ci mp.py_ = pointerIterm.GetDisplayY(); 281885b47fbSopenharmony_ci pointerRoute_.push_back(mp); 282885b47fbSopenharmony_ci } 283885b47fbSopenharmony_ci return recognizeDirectionGesture(event); 284885b47fbSopenharmony_ci } 285885b47fbSopenharmony_ci if (!isRecognizingGesture_) { 286885b47fbSopenharmony_ci return false; 287885b47fbSopenharmony_ci } 288885b47fbSopenharmony_ci return StandardGestureRecognizer(event); 289885b47fbSopenharmony_ci} 290885b47fbSopenharmony_ci 291885b47fbSopenharmony_cibool AccessibilityGestureRecognizer::StandardGestureRecognizer(MMI::PointerEvent &event) 292885b47fbSopenharmony_ci{ 293885b47fbSopenharmony_ci HILOG_DEBUG(); 294885b47fbSopenharmony_ci 295885b47fbSopenharmony_ci switch (event.GetPointerAction()) { 296885b47fbSopenharmony_ci case MMI::PointerEvent::POINTER_ACTION_DOWN: 297885b47fbSopenharmony_ci if (event.GetPointerIds().size() == POINTER_COUNT_1) { 298885b47fbSopenharmony_ci if (pCurDown_ && pPreUp_ && isDoubleTap(event)) { 299885b47fbSopenharmony_ci HILOG_DEBUG("Double tap is recognized"); 300885b47fbSopenharmony_ci isDoubleTapdetecting_ = true; 301885b47fbSopenharmony_ci isDoubleTap_ = true; 302885b47fbSopenharmony_ci } else { 303885b47fbSopenharmony_ci handler_->SendEvent(SINGLE_TAP_MSG, 0, DOUBLE_TAP_TIMEOUT / US_TO_MS); 304885b47fbSopenharmony_ci } 305885b47fbSopenharmony_ci pCurDown_ = std::make_shared<MMI::PointerEvent>(event); 306885b47fbSopenharmony_ci isTapDown_ = true; 307885b47fbSopenharmony_ci continueDown_ = true; 308885b47fbSopenharmony_ci isLongpress_ = false; 309885b47fbSopenharmony_ci handler_->RemoveEvent(LONG_PRESS_MSG); 310885b47fbSopenharmony_ci handler_->SendEvent(LONG_PRESS_MSG, 0, LONG_PRESS_TIMEOUT / US_TO_MS); 311885b47fbSopenharmony_ci } else { 312885b47fbSopenharmony_ci StandardGestureCanceled(); 313885b47fbSopenharmony_ci } 314885b47fbSopenharmony_ci break; 315885b47fbSopenharmony_ci case MMI::PointerEvent::POINTER_ACTION_UP: 316885b47fbSopenharmony_ci if (event.GetPointerIds().size() == POINTER_COUNT_1) { 317885b47fbSopenharmony_ci continueDown_ = false; 318885b47fbSopenharmony_ci if (isLongpress_) { 319885b47fbSopenharmony_ci handler_->RemoveEvent(SINGLE_TAP_MSG); 320885b47fbSopenharmony_ci isLongpress_ = false; 321885b47fbSopenharmony_ci } else if (!isDoubleTapdetecting_ && isTapDown_) { 322885b47fbSopenharmony_ci isFirstTapUp_ = true; 323885b47fbSopenharmony_ci } 324885b47fbSopenharmony_ci pPreUp_ = std::make_unique<MMI::PointerEvent>(event); 325885b47fbSopenharmony_ci isDoubleTapdetecting_ = false; 326885b47fbSopenharmony_ci handler_->RemoveEvent(LONG_PRESS_MSG); 327885b47fbSopenharmony_ci } 328885b47fbSopenharmony_ci break; 329885b47fbSopenharmony_ci default: 330885b47fbSopenharmony_ci break; 331885b47fbSopenharmony_ci } 332885b47fbSopenharmony_ci return false; 333885b47fbSopenharmony_ci} 334885b47fbSopenharmony_ci 335885b47fbSopenharmony_civoid AccessibilityGestureRecognizer::StandardGestureCanceled() 336885b47fbSopenharmony_ci{ 337885b47fbSopenharmony_ci HILOG_DEBUG(); 338885b47fbSopenharmony_ci 339885b47fbSopenharmony_ci handler_->RemoveEvent(LONG_PRESS_MSG); 340885b47fbSopenharmony_ci handler_->RemoveEvent(SINGLE_TAP_MSG); 341885b47fbSopenharmony_ci isLongpress_ = false; 342885b47fbSopenharmony_ci isDoubleTapdetecting_ = false; 343885b47fbSopenharmony_ci isTapDown_ = false; 344885b47fbSopenharmony_ci isDoubleTap_ = false; 345885b47fbSopenharmony_ci} 346885b47fbSopenharmony_ci 347885b47fbSopenharmony_civoid AccessibilityGestureRecognizer::SingleTapDetected() 348885b47fbSopenharmony_ci{ 349885b47fbSopenharmony_ci HILOG_DEBUG(); 350885b47fbSopenharmony_ci 351885b47fbSopenharmony_ci Clear(); 352885b47fbSopenharmony_ci} 353885b47fbSopenharmony_ci 354885b47fbSopenharmony_civoid AccessibilityGestureRecognizer::MaybeRecognizeLongPress(MMI::PointerEvent &event) 355885b47fbSopenharmony_ci{ 356885b47fbSopenharmony_ci HILOG_DEBUG(); 357885b47fbSopenharmony_ci} 358885b47fbSopenharmony_ci 359885b47fbSopenharmony_cibool AccessibilityGestureRecognizer::DoubleTapRecognized(MMI::PointerEvent &event) 360885b47fbSopenharmony_ci{ 361885b47fbSopenharmony_ci HILOG_DEBUG(); 362885b47fbSopenharmony_ci 363885b47fbSopenharmony_ci Clear(); 364885b47fbSopenharmony_ci return listener_->OnDoubleTap(event); 365885b47fbSopenharmony_ci} 366885b47fbSopenharmony_ci 367885b47fbSopenharmony_cibool AccessibilityGestureRecognizer::recognizeDirectionGesture(MMI::PointerEvent &event) 368885b47fbSopenharmony_ci{ 369885b47fbSopenharmony_ci HILOG_DEBUG(); 370885b47fbSopenharmony_ci if (!listener_) { 371885b47fbSopenharmony_ci HILOG_ERROR("listener_ is nullptr."); 372885b47fbSopenharmony_ci return false; 373885b47fbSopenharmony_ci } 374885b47fbSopenharmony_ci 375885b47fbSopenharmony_ci if (pointerRoute_.size() < LIMIT_SIZE_TWO) { 376885b47fbSopenharmony_ci return listener_->OnCancelled(event); 377885b47fbSopenharmony_ci } 378885b47fbSopenharmony_ci 379885b47fbSopenharmony_ci // Check the angle of the most recent motion vector versus the preceding motion vector, 380885b47fbSopenharmony_ci // segment the line if the angle is about 90 degrees. 381885b47fbSopenharmony_ci std::vector<Pointer> pointerPath = GetPointerPath(pointerRoute_); 382885b47fbSopenharmony_ci 383885b47fbSopenharmony_ci if (pointerPath.size() == LIMIT_SIZE_TWO) { 384885b47fbSopenharmony_ci int32_t swipeDirection = GetSwipeDirection(pointerPath[0], pointerPath[1]); 385885b47fbSopenharmony_ci return listener_->OnCompleted(GESTURE_DIRECTION[swipeDirection]); 386885b47fbSopenharmony_ci } else if (pointerPath.size() == LIMIT_SIZE_THREE) { 387885b47fbSopenharmony_ci int32_t swipeDirectionH = GetSwipeDirection(pointerPath[0], pointerPath[1]); 388885b47fbSopenharmony_ci int32_t swipeDirectionHV = GetSwipeDirection(pointerPath[1], pointerPath[2]); 389885b47fbSopenharmony_ci return listener_->OnCompleted(GESTURE_DIRECTION_TO_ID[swipeDirectionH][swipeDirectionHV]); 390885b47fbSopenharmony_ci } 391885b47fbSopenharmony_ci return listener_->OnCancelled(event); 392885b47fbSopenharmony_ci} 393885b47fbSopenharmony_ci 394885b47fbSopenharmony_ciint32_t AccessibilityGestureRecognizer::GetSwipeDirection(Pointer firstP, Pointer secondP) 395885b47fbSopenharmony_ci{ 396885b47fbSopenharmony_ci float offsetX = secondP.px_ - firstP.px_; 397885b47fbSopenharmony_ci float offsetY = secondP.py_ - firstP.py_; 398885b47fbSopenharmony_ci if (abs(offsetX) > abs(offsetY)) { 399885b47fbSopenharmony_ci return offsetX > EPSINON ? SWIPE_RIGHT : SWIPE_LEFT; 400885b47fbSopenharmony_ci } else { 401885b47fbSopenharmony_ci return offsetY < EPSINON ? SWIPE_UP : SWIPE_DOWN; 402885b47fbSopenharmony_ci } 403885b47fbSopenharmony_ci} 404885b47fbSopenharmony_ci 405885b47fbSopenharmony_cistd::vector<Pointer> AccessibilityGestureRecognizer::GetPointerPath(std::vector<Pointer> &route) 406885b47fbSopenharmony_ci{ 407885b47fbSopenharmony_ci HILOG_DEBUG(); 408885b47fbSopenharmony_ci 409885b47fbSopenharmony_ci std::vector<Pointer> pointerPath; 410885b47fbSopenharmony_ci Pointer firstSeparation = route[0]; 411885b47fbSopenharmony_ci Pointer nextPoint; 412885b47fbSopenharmony_ci Pointer newSeparation; 413885b47fbSopenharmony_ci float xUnitVector = 0; 414885b47fbSopenharmony_ci float yUnitVector = 0; 415885b47fbSopenharmony_ci float xVector = 0; 416885b47fbSopenharmony_ci float yVector = 0; 417885b47fbSopenharmony_ci float vectorLength = 0; 418885b47fbSopenharmony_ci int32_t numSinceFirstSep = 0; 419885b47fbSopenharmony_ci 420885b47fbSopenharmony_ci pointerPath.push_back(firstSeparation); 421885b47fbSopenharmony_ci for (size_t i = 1; i < route.size(); i++) { 422885b47fbSopenharmony_ci nextPoint = route[i]; 423885b47fbSopenharmony_ci if (numSinceFirstSep > 0) { 424885b47fbSopenharmony_ci xVector = xUnitVector / numSinceFirstSep; 425885b47fbSopenharmony_ci yVector = yUnitVector / numSinceFirstSep; 426885b47fbSopenharmony_ci newSeparation.px_ = vectorLength * xVector + firstSeparation.px_; 427885b47fbSopenharmony_ci newSeparation.py_ = vectorLength * yVector + firstSeparation.py_; 428885b47fbSopenharmony_ci 429885b47fbSopenharmony_ci float xNextUnitVector = nextPoint.px_ - newSeparation.px_; 430885b47fbSopenharmony_ci float yNextUnitVector = nextPoint.py_ - newSeparation.py_; 431885b47fbSopenharmony_ci float nextVectorLength = hypot(xNextUnitVector, yNextUnitVector); 432885b47fbSopenharmony_ci if (nextVectorLength > EPSINON) { 433885b47fbSopenharmony_ci xNextUnitVector /= nextVectorLength; 434885b47fbSopenharmony_ci yNextUnitVector /= nextVectorLength; 435885b47fbSopenharmony_ci } 436885b47fbSopenharmony_ci 437885b47fbSopenharmony_ci if ((xVector * xNextUnitVector + yVector * yNextUnitVector) < DEGREES_THRESHOLD) { 438885b47fbSopenharmony_ci pointerPath.push_back(newSeparation); 439885b47fbSopenharmony_ci firstSeparation = newSeparation; 440885b47fbSopenharmony_ci xUnitVector = 0; 441885b47fbSopenharmony_ci yUnitVector = 0; 442885b47fbSopenharmony_ci numSinceFirstSep = 0; 443885b47fbSopenharmony_ci } 444885b47fbSopenharmony_ci } 445885b47fbSopenharmony_ci xVector = nextPoint.px_ - firstSeparation.px_; 446885b47fbSopenharmony_ci yVector = nextPoint.py_ - firstSeparation.py_; 447885b47fbSopenharmony_ci vectorLength = hypot(xVector, yVector); 448885b47fbSopenharmony_ci numSinceFirstSep += 1; 449885b47fbSopenharmony_ci if (vectorLength > EPSINON) { 450885b47fbSopenharmony_ci xUnitVector += xVector / vectorLength; 451885b47fbSopenharmony_ci yUnitVector += yVector / vectorLength; 452885b47fbSopenharmony_ci } 453885b47fbSopenharmony_ci } 454885b47fbSopenharmony_ci pointerPath.push_back(nextPoint); 455885b47fbSopenharmony_ci return pointerPath; 456885b47fbSopenharmony_ci} 457885b47fbSopenharmony_ci 458885b47fbSopenharmony_cibool AccessibilityGestureRecognizer::isDoubleTap(MMI::PointerEvent &event) 459885b47fbSopenharmony_ci{ 460885b47fbSopenharmony_ci HILOG_DEBUG(); 461885b47fbSopenharmony_ci int64_t durationTime = event.GetActionTime() - pPreUp_->GetActionTime(); 462885b47fbSopenharmony_ci if (!(durationTime <= DOUBLE_TAP_TIMEOUT)) { 463885b47fbSopenharmony_ci HILOG_WARN("durationTime[%{public}" PRId64 "] is wrong", durationTime); 464885b47fbSopenharmony_ci return false; 465885b47fbSopenharmony_ci } 466885b47fbSopenharmony_ci 467885b47fbSopenharmony_ci MMI::PointerEvent::PointerItem curPI; 468885b47fbSopenharmony_ci if (!event.GetPointerItem(event.GetPointerId(), curPI)) { 469885b47fbSopenharmony_ci HILOG_WARN("get GetPointerItem(%{public}d) failed", event.GetPointerId()); 470885b47fbSopenharmony_ci } 471885b47fbSopenharmony_ci 472885b47fbSopenharmony_ci MMI::PointerEvent::PointerItem firstPI; 473885b47fbSopenharmony_ci pCurDown_->GetPointerItem(pCurDown_->GetPointerId(), firstPI); 474885b47fbSopenharmony_ci int32_t durationX = firstPI.GetDisplayX() - curPI.GetDisplayX(); 475885b47fbSopenharmony_ci int32_t durationY = firstPI.GetDisplayY() - curPI.GetDisplayY(); 476885b47fbSopenharmony_ci 477885b47fbSopenharmony_ci return (durationX * durationX + durationY * durationY < doubleTapScaledSlop_); 478885b47fbSopenharmony_ci} 479885b47fbSopenharmony_ci} // namespace Accessibility 480885b47fbSopenharmony_ci} // namespace OHOS 481