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 #ifndef ACCESSIBILITY_GESTURE_RECOGNIZER_H 17 #define ACCESSIBILITY_GESTURE_RECOGNIZER_H 18 19 #include <cmath> 20 #include <vector> 21 22 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER 23 #include "accessibility_display_manager.h" 24 #endif 25 #include "accessibility_event_info.h" 26 #include "accessible_ability_manager_service.h" 27 #include "event_handler.h" 28 #include "event_runner.h" 29 #include "pointer_event.h" 30 #include "singleton.h" 31 32 namespace OHOS { 33 namespace Accessibility { 34 const int64_t GESTURE_STARTED_TIME_THRESHOLD = 300000; // microsecond 35 const int64_t GESTURE_NOT_STARTED_TIME_THRESHOLD = 200000; // microsecond 36 const float DOUBLE_TAP_SLOP = 100.0f; 37 const int64_t MIN_DOUBLE_TAP_TIME = 40000; // microsecond 38 const int64_t DOUBLE_TAP_TIMEOUT = 300000; // microsecond 39 const int64_t LONG_PRESS_TIMEOUT = 300000; // microsecond 40 const int64_t TAP_INTERVAL_TIMEOUT = 100000; // microsecond 41 const float DEGREES_THRESHOLD = 0.0f; 42 const int32_t DIRECTION_NUM = 4; 43 const int64_t US_TO_MS = 1000; 44 const int32_t MM_PER_CM = 10; 45 #define CALCULATION_DIMENSION(xdpi) ((xdpi) * 0.25f) 46 #define MIN_PIXELS(xyDpi) ((xyDpi) * 0.1f) 47 48 struct Pointer { 49 float px_; 50 float py_; 51 }; 52 53 class AccessibilityGestureRecognizer; 54 class GestureHandler : public AppExecFwk::EventHandler { 55 public: 56 GestureHandler(const std::shared_ptr<AppExecFwk::EventRunner> &runner, AccessibilityGestureRecognizer &server); 57 virtual ~GestureHandler() = default; 58 /** 59 * @brief Process the event of install system bundles. 60 * @param event Indicates the event to be processed. 61 */ 62 virtual void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) override; 63 private: 64 AccessibilityGestureRecognizer &server_; 65 }; 66 67 class AccessibilityGestureRecognizeListener { 68 public: 69 /** 70 * @brief A destructor used to delete the listener instance. 71 */ 72 virtual ~AccessibilityGestureRecognizeListener() = default; 73 74 /** 75 * @brief The callback function when lifted the finger on the second tap of a double tap. 76 * 77 * @param event the touch event received. 78 * @return true if the event is consumed, else false 79 */ 80 virtual bool OnDoubleTap(MMI::PointerEvent &event); 81 82 /** 83 * @brief The callback function when recognized an event stream as a gesture. 84 * @return true if the event is consumed, else false 85 */ 86 virtual bool OnStarted(); 87 88 /** 89 * @brief The callback function when recognized an event stream as a multi finger gesture. 90 * @param isTwoFingerGesture whether the gesture is triggered by two finger. 91 */ 92 virtual void MultiFingerGestureOnStarted(bool isTwoFingerGesture); 93 94 /** 95 * @brief The callback function when decided the event stream is a gesture. 96 * @param gestureId the recognized gesture ID. 97 * @return true if the event is consumed, else false 98 */ 99 virtual bool OnCompleted(GestureType gestureId); 100 101 /** 102 * @brief The callback function when decided the event stream is a multi finger gesture. 103 * @param gestureId the recognized gesture ID. 104 */ 105 virtual void MultiFingerGestureOnCompleted(GestureType gestureId); 106 107 /** 108 * @brief The callback function when decided an event stream doesn't match any known gesture. 109 * @param event the touch event received. 110 * @return true if the event is consumed, else false 111 */ 112 virtual bool OnCancelled(MMI::PointerEvent &event); 113 114 /** 115 * @brief The callback function when decided an event stream doesn't match any known multi finger gesture. 116 * @param isNoDelayFlag whether the gesture recognize process is immediately canceled. 117 */ 118 virtual void MultiFingerGestureOnCancelled(const bool isNoDelayFlag); 119 }; 120 121 class AccessibilityGestureRecognizer : public AppExecFwk::EventHandler { 122 public: 123 static constexpr uint32_t LONG_PRESS_MSG = 1; 124 static constexpr uint32_t SINGLE_TAP_MSG = 2; 125 126 /** 127 * @brief A constructor used to create a accessibilityGestureRecognizer instance. 128 */ 129 AccessibilityGestureRecognizer(); 130 131 /** 132 * @brief A destructor used to delete the accessibilityGestureRecognizer instance. 133 */ ~AccessibilityGestureRecognizer()134 ~AccessibilityGestureRecognizer() {} 135 136 /** 137 * @brief Register GestureRecognizeListener. 138 * @param listener the listener from touchguide 139 */ 140 void RegisterListener(AccessibilityGestureRecognizeListener& listener); 141 142 /** 143 * @brief Register GestureRecognizeListener. 144 * @param listener the listener from touchguide 145 */ 146 void UnregisterListener(); 147 148 /** 149 * @brief Determine whether a single tap has occurred. 150 * @return true if a single tap has occurred, else false. 151 */ IsfirstTap()152 bool IsfirstTap() 153 { 154 return isFirstTapUp_; 155 } 156 157 /** 158 * @brief Determine whether a double tap has occurred. 159 * @return true if a double tap has occurred, else false. 160 */ GetIsDoubleTap()161 bool GetIsDoubleTap() 162 { 163 return isDoubleTap_; 164 } 165 166 /** 167 * @brief Determine whether a longpress has occurred. 168 * @return true if longpress has occurred, else false. 169 */ GetIsLongpress()170 bool GetIsLongpress() 171 { 172 return isLongpress_; 173 } 174 175 /** 176 * @brief Handle a touch event. If an action is completed, the appropriate callback is called. 177 * 178 * @param event the touch event to be handled. 179 * @param rawEvent The raw touch event. 180 * @return true if the gesture be recognized, else false 181 */ 182 bool OnPointerEvent(MMI::PointerEvent &event); 183 184 /** 185 * @brief Clear state. 186 */ 187 void Clear(); 188 189 /** 190 * @brief Judge whether the double click and long press gesture is recognized. 191 * @param event the touch event from touchguide 192 */ 193 void MaybeRecognizeLongPress(MMI::PointerEvent &event); 194 195 /** 196 * @brief If a single tap completed. 197 */ 198 void SingleTapDetected(); 199 200 /** 201 * @brief Set isLongpress_ flag; 202 * @param value set isLongpress_ flag 203 */ SetIsLongpress(bool value)204 void SetIsLongpress (bool value) 205 { 206 isLongpress_ = value; 207 } 208 209 /** 210 * @brief Get pCurDown_ ptr. 211 */ GetCurDown()212 std::shared_ptr<MMI::PointerEvent> GetCurDown() 213 { 214 return pCurDown_; 215 } 216 217 /** 218 * @brief Get continueDown_ flag. 219 */ GetContinueDown()220 bool GetContinueDown() 221 { 222 return continueDown_; 223 } 224 225 private: 226 /** 227 * @brief Recognize the standard gesture. 228 * @param event the touch event from touchguide 229 * @return true if the standard gesture be recognized, else false 230 */ 231 bool StandardGestureRecognizer(MMI::PointerEvent &event); 232 233 /** 234 * @brief A double tap has occurred, call OnDoubleTap callback. 235 * @param event the touch event from touchguide 236 * @return true if the DoubleTap be recognized, else false 237 */ 238 bool DoubleTapRecognized(MMI::PointerEvent &event); 239 240 /** 241 * @brief Recognize gestures based on the sequence of motions. 242 * @param event the touch event from touchguide 243 * @return true if the Direction be recognized, else false 244 */ 245 bool recognizeDirectionGesture(MMI::PointerEvent &event); 246 247 /** 248 * @brief Handle the down event from touchguide. 249 * @param event the touch event from touchguide 250 */ 251 void HandleTouchDownEvent(MMI::PointerEvent &event); 252 253 /** 254 * @brief Handle the move event from touchguide. 255 * @param event the touch event from touchguide 256 */ 257 bool HandleTouchMoveEvent(MMI::PointerEvent &event); 258 259 /** 260 * @brief Handle the up event from touchguide. 261 * @param event the touch event from touchguide 262 */ 263 bool HandleTouchUpEvent(MMI::PointerEvent &event); 264 265 /** 266 * @brief Check if it's double tap. 267 * @param event the touch event from touchguide 268 * @return true if it's double tap, else false 269 */ 270 bool isDoubleTap(MMI::PointerEvent &event); 271 272 /** 273 * @brief Cancel the gesture. 274 */ 275 void StandardGestureCanceled(); 276 277 /** 278 * @brief Add position to pointer route. 279 * @param pointerIterm the touch item from touchguide 280 */ 281 void AddSwipePosition(MMI::PointerEvent::PointerItem &pointerIterm); 282 283 /** 284 * @brief Calculate the move threshold for the double tap gesture. 285 * @param densityDpi the physical density 286 */ 287 float GetDoubleTapMoveThreshold(float densityDpi); 288 289 /** 290 * @brief Get pointer path. 291 * @param route all pointer route 292 * @return the vector of PointerPath 293 */ 294 std::vector<Pointer> GetPointerPath(std::vector<Pointer> &route); 295 296 /** 297 * @brief Get swipe direction. 298 * @param firstP the start point 299 * @param secondP the endpoint 300 * @return the type of swipe direction 301 */ 302 int32_t GetSwipeDirection(Pointer firstP, Pointer secondP); 303 304 static constexpr int32_t SWIPE_UP = 0; 305 static constexpr int32_t SWIPE_DOWN = 1; 306 static constexpr int32_t SWIPE_LEFT = 2; 307 static constexpr int32_t SWIPE_RIGHT = 3; 308 309 static constexpr GestureType GESTURE_DIRECTION[DIRECTION_NUM] = { 310 GestureType::GESTURE_SWIPE_UP, 311 GestureType::GESTURE_SWIPE_DOWN, 312 GestureType::GESTURE_SWIPE_LEFT, 313 GestureType::GESTURE_SWIPE_RIGHT 314 }; 315 316 static constexpr GestureType GESTURE_DIRECTION_TO_ID[DIRECTION_NUM][DIRECTION_NUM] = { 317 { 318 GestureType::GESTURE_SWIPE_UP, 319 GestureType::GESTURE_SWIPE_UP_THEN_DOWN, 320 GestureType::GESTURE_SWIPE_UP_THEN_LEFT, 321 GestureType::GESTURE_SWIPE_UP_THEN_RIGHT, 322 }, 323 { 324 GestureType::GESTURE_SWIPE_DOWN_THEN_UP, 325 GestureType::GESTURE_SWIPE_DOWN, 326 GestureType::GESTURE_SWIPE_DOWN_THEN_LEFT, 327 GestureType::GESTURE_SWIPE_DOWN_THEN_RIGHT, 328 329 }, 330 { 331 GestureType::GESTURE_SWIPE_LEFT_THEN_UP, 332 GestureType::GESTURE_SWIPE_LEFT_THEN_DOWN, 333 GestureType::GESTURE_SWIPE_LEFT, 334 GestureType::GESTURE_SWIPE_LEFT_THEN_RIGHT, 335 336 }, 337 { 338 GestureType::GESTURE_SWIPE_RIGHT_THEN_UP, 339 GestureType::GESTURE_SWIPE_RIGHT_THEN_DOWN, 340 GestureType::GESTURE_SWIPE_RIGHT_THEN_LEFT, 341 GestureType::GESTURE_SWIPE_RIGHT 342 } 343 }; 344 345 bool continueDown_ = false; 346 bool isLongpress_ = false; 347 bool isDoubleTapdetecting_ = false; 348 bool isTapDown_ = false; 349 bool isFirstTapUp_ = false; 350 bool isDoubleTap_ = false; 351 bool isRecognizingGesture_ = false; 352 bool isGestureStarted_ = false; 353 int64_t startTime_ = 0; // microsecond 354 float xMinPixels_ = 0; 355 float yMinPixels_ = 0; 356 float threshold_ = 0; 357 int32_t doubleTapScaledSlop_ = 0; 358 MMI::PointerEvent::PointerItem prePointer_ = {}; 359 MMI::PointerEvent::PointerItem startPointer_ = {}; 360 std::vector<Pointer> pointerRoute_ {}; 361 AccessibilityGestureRecognizeListener *listener_ = nullptr; 362 std::unique_ptr<MMI::PointerEvent> pPreUp_ = nullptr; 363 std::shared_ptr<MMI::PointerEvent> pCurDown_ = nullptr; 364 std::shared_ptr<GestureHandler> handler_ = nullptr; 365 std::shared_ptr<AppExecFwk::EventRunner> runner_ = nullptr; 366 }; 367 } // namespace Accessibility 368 } // namespace OHOS 369 #endif // ACCESSIBILITY_GESTURE_RECOGNIZER_H