1 /*
2  * Copyright (c) 2021-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 "core/gestures/press_recognizer.h"
17 
18 namespace OHOS::Ace {
19 namespace {
20 
21 constexpr int32_t PRESS_TIMEOUT = 30;
22 constexpr double MAX_THRESHOLD = 2.0;
23 
24 } // namespace
25 
OnAccepted(size_t touchId)26 void PressRecognizer::OnAccepted(size_t touchId)
27 {
28     state_ = DetectState::DETECTED;
29     if (onPress_) {
30         PressInfo info(touchId);
31         info.SetTimeStamp(trackPoint_.time);
32         info.SetGlobalLocation(trackPoint_.GetOffset()).SetLocalLocation(trackPoint_.GetOffset() - coordinateOffset_);
33         info.SetTarget(GetEventTarget().value_or(EventTarget()));
34         info.SetForce(trackPoint_.force);
35         if (trackPoint_.tiltX.has_value()) {
36             info.SetTiltX(trackPoint_.tiltX.value());
37         }
38         if (trackPoint_.tiltY.has_value()) {
39             info.SetTiltY(trackPoint_.tiltY.value());
40         }
41         info.SetSourceTool(trackPoint_.sourceTool);
42         onPress_(info);
43     }
44 }
45 
OnRejected(size_t touchId)46 void PressRecognizer::OnRejected(size_t touchId)
47 {
48     deadlineTimer_.Cancel();
49     state_ = DetectState::READY;
50 }
51 
HandleTouchDownEvent(const TouchEvent & event)52 void PressRecognizer::HandleTouchDownEvent(const TouchEvent& event)
53 {
54     if (state_ == DetectState::READY) {
55         auto context = context_.Upgrade();
56         if (!context) {
57             LOGE("fail to detect press gesture due to context is nullptr");
58             return;
59         }
60         trackPoint_ = event;
61         state_ = DetectState::DETECTING;
62         deadlineTimer_.Reset([weakPtr = AceType::WeakClaim(this)] {
63             auto refPtr = weakPtr.Upgrade();
64             if (refPtr) {
65                 refPtr->HandleOverdueDeadline();
66             } else {
67                 LOGE("fail to handle overdue deadline due to context is nullptr");
68             }
69         });
70         auto taskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
71         taskExecutor.PostDelayedTask(deadlineTimer_, PRESS_TIMEOUT, "ArkUIGesturePressDeadlineTimer");
72     } else {
73         LOGW("the state is not ready for detecting press gesture");
74     }
75 }
76 
HandleTouchUpEvent(const TouchEvent & event)77 void PressRecognizer::HandleTouchUpEvent(const TouchEvent& event)
78 {
79     if (state_ == DetectState::DETECTING) {
80         OnRejected(trackPoint_.id);
81     } else if (state_ == DetectState::DETECTED) {
82         if (onPressCancel_) {
83             onPressCancel_();
84         }
85     }
86     state_ = DetectState::READY;
87 }
88 
HandleTouchMoveEvent(const TouchEvent & event)89 void PressRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
90 {
91     if (state_ == DetectState::DETECTING) {
92         Offset offset = event.GetOffset() - trackPoint_.GetOffset();
93         if (offset.GetDistance() > MAX_THRESHOLD) {
94             OnRejected(event.id);
95         }
96     } else if (state_ == DetectState::DETECTED) {
97         Offset offset = event.GetOffset() - trackPoint_.GetOffset();
98         if (offset.GetDistance() > MAX_THRESHOLD && onPressCancel_) {
99             onPressCancel_();
100         }
101     }
102 }
103 
HandleTouchCancelEvent(const TouchEvent & event)104 void PressRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
105 {
106     if (state_ == DetectState::DETECTING) {
107         OnRejected(event.id);
108     }
109     state_ = DetectState::READY;
110 }
111 
HandleOverdueDeadline()112 void PressRecognizer::HandleOverdueDeadline()
113 {
114     if (state_ == DetectState::DETECTING) {
115         OnAccepted(trackPoint_.id);
116     } else {
117         LOGW("the state is not detecting for accept press gesture");
118     }
119 }
120 
121 } // namespace OHOS::Ace
122