1 /*
2  * Copyright (C) 2023 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_MULTIFINGER_MULTITAP_H
17 #define ACCESSIBILITY_MULTIFINGER_MULTITAP_H
18 
19 #include <cmath>
20 #include <vector>
21 
22 #include "accessibility_gesture_recognizer.h"
23 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
24 #include "accessibility_display_manager.h"
25 #endif
26 #include "accessibility_event_info.h"
27 #include "accessible_ability_manager_service.h"
28 #include "accessibility_def.h"
29 #include "event_handler.h"
30 #include "event_runner.h"
31 #include "pointer_event.h"
32 #include "singleton.h"
33 
34 namespace OHOS {
35 namespace Accessibility {
36 namespace {
37     constexpr uint32_t MAX_TAP_NUM = 3;
38     constexpr uint32_t MAX_MULTI_FINGER_TYPE = 3;
39 } // namespace
40 
41 enum MoveGirectionType : int32_t {
42     SWIPE_LEFT = 0,
43     SWIPE_RIGHT = 1,
44     SWIPE_UP = 2,
45     SWIPE_DOWN = 3
46 };
47 
48 enum FingerTouchUpState : int32_t {
49     NOT_ALL_FINGER_TOUCH_UP = 0,
50     ALL_FINGER_TOUCH_UP = 1,
51     TOUCH_DOWN_AFTER_ALL_FINGER_TOUCH_UP = 2,
52 };
53 
54 enum MultiFingerGestureState : int32_t {
55     GESTURE_NOT_START = 0,
56     GESTURE_START = 1,
57     GESTURE_CANCLE = 2,
58     GESTURE_COMPLETE = 3,
59     GESTURE_WAIT = 4,
60 };
61 
62 class AccessibilityMultiTapGestureRecognizer;
63 class MultiFingerGestureHandler : public AppExecFwk::EventHandler {
64 public:
65     MultiFingerGestureHandler(const std::shared_ptr<AppExecFwk::EventRunner> &runner,
66         AccessibilityMultiTapGestureRecognizer &server);
67     virtual ~MultiFingerGestureHandler() = default;
68     /**
69      * @brief Process the event of install system bundles.
70      * @param event Indicates the event to be processed.
71      */
72     virtual void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) override;
73 private:
74     /**
75      * @brief Process the multi finger gesture by Gesture type.
76      * @param gestureType Indicates the gesture type to be processed.
77      */
78     void ProcessMultiFingerGestureTypeEvent(const GestureType gestureType);
79 
80     /**
81      * @brief Process the multi finger gesture event.
82      * @param event Indicates the event to be processed.
83      * @return true if the gesture event is processed success, else false.
84      */
85     bool ProcessMultiFingerGestureEvent(const AppExecFwk::InnerEvent::Pointer &event);
86 
87     /**
88      * @brief check whether the gesture is a tap gesture.
89      * @param gestureType Indicates the gesture to be processed.
90      * @return true if the gesture is a tap gesture, else false.
91      */
92     bool IsTapGesture(const GestureType gestureType);
93 
94     AccessibilityMultiTapGestureRecognizer &server_;
95 };
96 
97 class AccessibilityMultiTapGestureRecognizer : public AppExecFwk::EventHandler {
98 public:
99     static constexpr uint32_t TWO_FINGER_SINGLE_TAP_MSG = 3;
100     static constexpr uint32_t TWO_FINGER_LONG_PRESS_MSG = 4;
101     static constexpr uint32_t TWO_FINGER_DOUBLE_TAP_MSG = 5;
102     static constexpr uint32_t TWO_FINGER_DOUBLE_TAP_AND_HOLD_MSG = 6;
103     static constexpr uint32_t TWO_FINGER_TRIPLE_TAP_MSG = 7;
104     static constexpr uint32_t TWO_FINGER_TRIPLE_TAP_AND_HOLD_MSG = 8;
105     static constexpr uint32_t THREE_FINGER_SINGLE_TAP_MSG = 9;
106     static constexpr uint32_t THREE_FINGER_LONG_PRESS_MSG = 10;
107     static constexpr uint32_t THREE_FINGER_DOUBLE_TAP_MSG = 11;
108     static constexpr uint32_t THREE_FINGER_DOUBLE_TAP_AND_HOLD_MSG = 12;
109     static constexpr uint32_t THREE_FINGER_TRIPLE_TAP_MSG = 13;
110     static constexpr uint32_t THREE_FINGER_TRIPLE_TAP_AND_HOLD_MSG = 14;
111     static constexpr uint32_t FOUR_FINGER_SINGLE_TAP_MSG = 15;
112     static constexpr uint32_t FOUR_FINGER_LONG_PRESS_MSG = 16;
113     static constexpr uint32_t FOUR_FINGER_DOUBLE_TAP_MSG = 17;
114     static constexpr uint32_t FOUR_FINGER_DOUBLE_TAP_AND_HOLD_MSG = 18;
115     static constexpr uint32_t FOUR_FINGER_TRIPLE_TAP_MSG = 19;
116     static constexpr uint32_t FOUR_FINGER_TRIPLE_TAP_AND_HOLD_MSG = 20;
117     static constexpr uint32_t WAIT_ANOTHER_FINGER_DOWN_MSG = 21;
118     static constexpr uint32_t CANCEL_WAIT_FINGER_DOWN_MSG = 22;
119     static constexpr uint32_t CANCEL_GESTURE = 23;
120     static constexpr uint32_t COMPLETE_GESTURE = 24;
121 
122     static constexpr uint32_t GESTURE_TAP_MSG[MAX_TAP_NUM][MAX_MULTI_FINGER_TYPE] = {
123         {
124             TWO_FINGER_SINGLE_TAP_MSG,
125             THREE_FINGER_SINGLE_TAP_MSG,
126             FOUR_FINGER_SINGLE_TAP_MSG,
127         },
128         {
129             TWO_FINGER_DOUBLE_TAP_MSG,
130             THREE_FINGER_DOUBLE_TAP_MSG,
131             FOUR_FINGER_DOUBLE_TAP_MSG,
132         },
133         {
134             TWO_FINGER_TRIPLE_TAP_MSG,
135             THREE_FINGER_TRIPLE_TAP_MSG,
136             FOUR_FINGER_TRIPLE_TAP_MSG,
137         }
138     };
139 
140     static constexpr uint32_t GESTURE_HOLD_MSG[MAX_TAP_NUM][MAX_MULTI_FINGER_TYPE] = {
141         {
142             TWO_FINGER_LONG_PRESS_MSG,
143             THREE_FINGER_LONG_PRESS_MSG,
144             FOUR_FINGER_LONG_PRESS_MSG,
145         },
146         {
147             TWO_FINGER_DOUBLE_TAP_AND_HOLD_MSG,
148             THREE_FINGER_DOUBLE_TAP_AND_HOLD_MSG,
149             FOUR_FINGER_DOUBLE_TAP_AND_HOLD_MSG,
150         },
151         {
152             TWO_FINGER_TRIPLE_TAP_AND_HOLD_MSG,
153             THREE_FINGER_TRIPLE_TAP_AND_HOLD_MSG,
154             FOUR_FINGER_TRIPLE_TAP_AND_HOLD_MSG,
155         }
156     };
157 
158     AccessibilityMultiTapGestureRecognizer();
159     ~AccessibilityMultiTapGestureRecognizer() = default;
160 
161     /**
162      * @brief Register GestureRecognizeListener.
163      * @param listener the listener from touchguide.
164      */
165     void RegisterListener(AccessibilityGestureRecognizeListener &listener);
166 
167     /**
168      * @brief Get the GestureRecognizeListener.
169      * @return AccessibilityGestureRecognizeListener ptr.
170      */
GetRecognizeListener()171     AccessibilityGestureRecognizeListener *GetRecognizeListener() const
172     {
173         return listener_;
174     }
175 
176     /**
177      * @brief Handle a touch event. If an action is completed, the appropriate callback is called.
178      *
179      * @param event  the touch event to be handled.
180      */
181     void OnPointerEvent(MMI::PointerEvent &event);
182 
183     /**
184      * @brief Cancle multi finger gesture rocognize state, buffer etc.
185      */
186     void Clear();
187 
188     /**
189      * @brief Get the target fingers number touch down in first round.
190      * @return the finger numbers touch down in first round.
191      */
GetTargetFingers()192     int32_t GetTargetFingers() const
193     {
194         return targetFingers_;
195     }
196 
197     /**
198      * @brief Get finger touch up state.
199      * @return the touch up state, indicates if fingers is still on the screen.
200      */
GetFingerTouchUpState()201     int32_t GetFingerTouchUpState() const
202     {
203         return fingerTouchUpState_;
204     }
205 
206     /**
207      * @brief Set the finger touch up state when touch up or finish touch down.
208      * @param touchUpState the touchUpState to be set.
209      */
SetFingerTouchUpState(const int32_t touchUpState)210     void SetFingerTouchUpState(const int32_t touchUpState)
211     {
212         fingerTouchUpState_ = touchUpState;
213     }
214 
215     /**
216      * @brief Set multi finger gesture state, when gesture recognize start, cancel, complete etc.
217      * @param gestureState the multiFingerGestureState to be set.
218      */
SetMultiFingerGestureState(const int32_t gestureState)219     void SetMultiFingerGestureState(const int32_t gestureState)
220     {
221         multiFingerGestureState_ = gestureState;
222     }
223 
224     /**
225      * @brief Determine whether multi finger gesture is started.
226      * @return true if gesture recognize is started, else false.
227      */
IsMultiFingerGestureStarted()228     bool IsMultiFingerGestureStarted() const
229     {
230         return multiFingerGestureState_ == MultiFingerGestureState::GESTURE_START;
231     }
232 
233     /**
234      * @brief Determine whether multi finger gesture is started or finished.
235      * @return true if gesture recognize is started or finished, else false.
236      */
IsMultiFingerRecognize()237     bool IsMultiFingerRecognize() const
238     {
239         return (multiFingerGestureState_ == MultiFingerGestureState::GESTURE_START ||
240             multiFingerGestureState_ == MultiFingerGestureState::GESTURE_COMPLETE);
241     }
242 
243     /**
244      * @brief Get the two finger move threshold.
245      * @return the two finger move threshold, indicates tap state to move state.
246      */
GetTouchSlop()247     float GetTouchSlop() const
248     {
249         return touchSlop_;
250     }
251 private:
252     /**
253      * @brief Cancle the pendding two finger gesture recognize event.
254      */
255     void CancelTwoFingerEvent();
256 
257     /**
258      * @brief Cancle the pendding three finger gesture recognize event.
259      */
260     void CancelThreeFingerEvent();
261 
262     /**
263      * @brief Cancle the pendding four finger gesture recognize event.
264      */
265     void CancelFourFingerEvent();
266 
267     /**
268      * @brief Cancle the pendding finger gesture recognize event by finger num.
269      * @param fingerNum which type gesture pendding event to be canceled.
270      */
271     void CancelTapAndHoldGestureEvent(const int32_t fingerNum);
272 
273     /**
274      * @brief Cancle the pendding multi finger hold gesture recognize event.
275      */
276     void CancelHoldGestureEvent();
277 
278     /**
279      * @brief Cancle All pendding inner event.
280      */
281     void CancelAllPenddingEvent();
282 
283     /**
284      * @brief Cancel the multi gesture recognize process.
285      * @param isNoDelayFlag if gesture cancel event is immediately processed.
286      */
287     void CancelGesture(const bool isNoDelayFlag);
288 
289     /**
290      * @brief param check for two finger Double tap recognize gesture.
291      * @param fingerNum the touch event from Multimodal.
292      * @return true if the used param is ok, else false.
293      */
294     bool ParamCheck(const int32_t fingerNum);
295 
296     /**
297      * @brief Get the last touch up time of the first finger.
298      * @param fingerNum total touch down finger nums, means the lastUpPoint_ size.
299      * @return the first finger's last touch up time.
300      */
301     int64_t GetLastFirstPointUpTime(const int32_t fingerNum);
302 
303     /**
304      * @brief Get the current and pre PointerItems with fingerNum, store in curPoints and prePoints.
305      * @param curPoints to store the cur touch event pointerItems rst, size is fingerNum.
306      * @param prePoints to store the pre touch event pointerItems rst, size is fingerNum.
307      * @param event current touch event, to get the curPoints.
308      * @param prePointsEventInfo pre touch Event storage, to get the prePoints.
309      * @return true if the get rst is ok, else false.
310      */
311     bool GetPointerItemWithFingerNum(int32_t fingerNum, std::vector<MMI::PointerEvent::PointerItem> &curPoints,
312         std::vector<MMI::PointerEvent::PointerItem> &prePoints, MMI::PointerEvent &event,
313         std::map<int32_t, std::shared_ptr<MMI::PointerEvent>> &prePointsEventInfo);
314 
315     /**
316      * @brief check whether the two taps offset is less than slop threshold.
317      * @param fingerNum touch down finger nums to be processed.
318      * @param curPoints current touch down pointer infos, size is fingerNum.
319      * @param prePoints first round touch down pointer infos, size is fingfingerNumerNums.
320      * @return true if the offset of two taps is less than slop threshold, else false.
321      */
322     bool IsDoubelTapSlopConditionMatch(const int32_t fingerNum,
323         const std::vector<MMI::PointerEvent::PointerItem> &curPoints,
324         const std::vector<MMI::PointerEvent::PointerItem> &prePoints);
325 
326     /**
327      * @brief Determine whether it is a multi finger double tap gesture.
328      * @param event the touch event from Multimodal.
329      * @param fingerNum the target fingerNum to be processed.
330      * @return true if the gesture is multi finger double tap, else false.
331      */
332     bool IsMultiFingerDoubleTap(MMI::PointerEvent &event, const int32_t fingerNum);
333 
334     /**
335      * @brief save touch down point event info.
336      */
337     void storeBaseDownPoint();
338 
339     /**
340      * @brief Get move direction by move distance.
341      * @param dx the x axis distance between base point and current point.
342      * @param dy the y axis distance between base point and current point.
343      * @return the move direction, value range is MoveGirectionType.
344      */
345     int32_t GetSwipeDirection(const int32_t dx, const int32_t dy);
346 
347     /**
348      * @brief Get the base point Item info by point Id.
349      * @param basePointerIterm to save th base pointItem info.
350      * @param pId the point Id to get the pointItem.
351      * @param pointInfo the touch down event point info storage.
352      * @return true if get base pointItem success, else false.
353      */
354     bool GetBasePointItem(MMI::PointerEvent::PointerItem &basePointerIterm,
355         int32_t pId, std::map<int32_t, std::shared_ptr<MMI::PointerEvent>> &pointInfo);
356 
357     /**
358      * @brief Save move gesture path info.
359      * @param event the touch event to be handled.
360      * @param pId the point Id to be handled.
361      * @param pointerIterm the point Item info to be saved.
362      * @param dx the x axis distance between base point and current point.
363      * @param dy the y axis distance between base point and current point.
364      */
365     void SaveMoveGesturePointerInfo(MMI::PointerEvent &event,
366         const int32_t pId, const MMI::PointerEvent::PointerItem &pointerIterm, const int32_t dx, const int32_t dy);
367 
368     /**
369      * @brief recognize the move path is correct and match a move gesture.
370      * @param path move path pointer info storage.
371      * @return true if the move path is correct and match a move gesture, else false.
372      */
373     bool recognizeGesturePath(const std::vector<Pointer> &path);
374 
375     /**
376      * @brief Get the matched move gesture by moveDirection and fingerNum.
377      * @return the matched gesture Id.
378      */
379     GestureType GetMoveGestureId();
380 
381     /**
382      * @brief whether the multi finger move event match a move gesture.
383      * @return true if multi finger move event match a move gesture, else false.
384      */
385     bool IsMoveGestureRecognize();
386 
387     /**
388      * @brief Save move gesture path info when finger up.
389      * @param event the touch event to be handled.
390      */
391     void StoreUpPointInPointerRoute(MMI::PointerEvent &event);
392 
393     /**
394      * @brief Handle the first touch down event.
395      * @param event the touch event to be handled.
396      */
397     void HanleFirstTouchDownEvent(MMI::PointerEvent &event);
398 
399     /**
400      * @brief Handle the continue touch down event.
401      * @param event the touch event to be handled.
402      */
403     void HandleContinueTouchDownEvent(MMI::PointerEvent &event);
404 
405     /**
406      * @brief Handle the multi finger touch move event.
407      * @param event the touch event to be handled.
408      */
409     void HandleMultiFingerMoveEvent(MMI::PointerEvent &event);
410 
411     /**
412      * @brief Handle the touch up event, not a move gesture.
413      * @param event the touch event to be handled.
414      */
415     void HandleMultiFingerTouchUpEvent(MMI::PointerEvent &event);
416 
417     /**
418      * @brief Handle the continue touch down event, decide whether it is a multi tap event.
419      * @param event the touch event to be handled.
420      * @param fingerNum the touch down fingerNum to be handled.
421      */
422     void HandleMultiTapEvent(MMI::PointerEvent &event, const int32_t fingerNum);
423 
424     float touchSlop_ = 0.0f;
425     int32_t doubleTapOffsetThresh_ = 0;
426     int32_t targetFingers_ = -1; // touch down finger numbers before first time the finger touch up
427     uint32_t addContinueTapNum_ = 0; // total number of touch down, except the first touch down
428     int32_t multiFingerGestureState_ = 0; // recognize state, value is MultiFingerGestureState
429     int32_t fingerTouchUpState_ = FingerTouchUpState::ALL_FINGER_TOUCH_UP;
430     bool isFirstUp_ = 0; // whether the first time finger touch up
431     bool isMoveGestureRecognizing = false; // in move gesture recognize process or not
432     int32_t moveDirection = -1;
433     float mMinPixelsBetweenSamplesX_ = 0;
434     float mMinPixelsBetweenSamplesY_ = 0;
435 
436     std::map<int32_t, std::shared_ptr<MMI::PointerEvent>> firstDownPoint_; // first round touch down points
437     std::map<int32_t, std::shared_ptr<MMI::PointerEvent>> currentDownPoint_; // current round touch down points
438     std::map<int32_t, std::shared_ptr<MMI::PointerEvent>> preGesturePoint_; // pre move event points
439     std::map<int32_t, std::shared_ptr<MMI::PointerEvent>> lastUpPoint_; // last time finger touch up points
440     std::map<int32_t, std::vector<Pointer>> pointerRoute_;
441 
442     AccessibilityGestureRecognizeListener *listener_ = nullptr;
443     std::shared_ptr<MultiFingerGestureHandler> handler_ = nullptr; // multi finger gesture recognize event handler
444     std::shared_ptr<AppExecFwk::EventRunner> runner_ = nullptr;
445 };
446 } // namespace Accessibility
447 } // namespace OHOS
448 #endif // ACCESSIBILITY_MULTIFINGER_MULTITAP_H