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 <cmath> 17 #include "ui_action.h" 18 19 namespace OHOS::uitest { 20 using namespace std; 21 using namespace nlohmann; 22 DecomposeClick(PointerMatrix & recv,const Point & point,const UiOpArgs & options)23 static void DecomposeClick(PointerMatrix &recv, const Point &point, const UiOpArgs &options) 24 { 25 constexpr uint32_t fingers = 1; 26 constexpr uint32_t steps = 2; 27 PointerMatrix pointer(fingers, steps); 28 pointer.PushAction(TouchEvent {ActionStage::DOWN, point, 0, options.clickHoldMs_}); 29 pointer.PushAction(TouchEvent {ActionStage::UP, point, options.clickHoldMs_, 0}); 30 recv = move(pointer); 31 } 32 DecomposeLongClick(PointerMatrix & recv,const Point & point,const UiOpArgs & options)33 static void DecomposeLongClick(PointerMatrix &recv, const Point &point, const UiOpArgs &options) 34 { 35 // should sleep after touch-down to make long-click duration 36 constexpr uint32_t fingers = 1; 37 constexpr uint32_t steps = 2; 38 PointerMatrix pointer(fingers, steps); 39 pointer.PushAction(TouchEvent {ActionStage::DOWN, point, 0, options.longClickHoldMs_}); 40 pointer.PushAction(TouchEvent {ActionStage::UP, point, options.longClickHoldMs_, 0}); 41 recv = move(pointer); 42 } 43 DecomposeDoubleClick(PointerMatrix & recv,const Point & point,const UiOpArgs & options)44 static void DecomposeDoubleClick(PointerMatrix &recv, const Point &point, const UiOpArgs &options) 45 { 46 const auto msInterval = options.doubleClickIntervalMs_; 47 constexpr uint32_t fingers = 1; 48 constexpr uint32_t steps = 4; 49 PointerMatrix pointer(fingers, steps); 50 pointer.PushAction(TouchEvent {ActionStage::DOWN, point, 0, options.clickHoldMs_}); 51 pointer.PushAction(TouchEvent {ActionStage::UP, point, options.clickHoldMs_, msInterval}); 52 53 pointer.PushAction(TouchEvent {ActionStage::DOWN, point, 0, options.clickHoldMs_}); 54 pointer.PushAction(TouchEvent {ActionStage::UP, point, options.clickHoldMs_, 0}); 55 recv = move(pointer); 56 } 57 DecomposeComputeSwipe(PointerMatrix & recv,const Point & from,const Point & to,bool drag,const UiOpArgs & options)58 static void DecomposeComputeSwipe(PointerMatrix &recv, const Point &from, const Point &to, bool drag, 59 const UiOpArgs &options) 60 { 61 const int32_t distanceX = to.px_ - from.px_; 62 const int32_t distanceY = to.py_ - from.py_; 63 const uint32_t distance = sqrt(distanceX * distanceX + distanceY * distanceY); 64 const uint32_t timeCostMs = (distance * 1000) / options.swipeVelocityPps_; 65 if (distance < 1) { 66 // do not need to execute swipe 67 return; 68 } 69 const auto steps = options.swipeStepsCounts_; 70 const uint32_t intervalMs = timeCostMs / steps + 1; 71 constexpr uint32_t fingers = 1; 72 PointerMatrix pointer(fingers, steps + 1); 73 74 pointer.PushAction(TouchEvent {ActionStage::DOWN, {from.px_, from.py_}, 0, intervalMs}); 75 for (uint16_t step = 1; step < steps; step++) { 76 const int32_t pointX = from.px_ + (distanceX * step) / steps; 77 const int32_t pointY = from.py_ + (distanceY * step) / steps; 78 const uint32_t timeOffsetMs = (timeCostMs * step) / steps; 79 pointer.PushAction(TouchEvent {ActionStage::MOVE, {pointX, pointY}, timeOffsetMs, intervalMs}); 80 } 81 82 pointer.PushAction(TouchEvent {ActionStage::UP, {to.px_, to.py_}, timeCostMs, intervalMs}); 83 if (drag) { 84 // drag needs longPressDown firstly 85 pointer.At(fingers - 1, 0).holdMs_ += options.longClickHoldMs_; 86 for (uint32_t idx = 1; idx < pointer.GetSize(); idx++) { 87 pointer.At(fingers - 1, idx).downTimeOffsetMs_ += options.longClickHoldMs_; 88 } 89 } 90 recv = move(pointer); 91 } 92 Decompose(PointerMatrix & recv,const UiOpArgs & options) const93 void GenericClick::Decompose(PointerMatrix &recv, const UiOpArgs &options) const 94 { 95 DCHECK(type_ >= TouchOp::CLICK && type_ <= TouchOp::DOUBLE_CLICK_P); 96 switch (type_) { 97 case CLICK: 98 DecomposeClick(recv, point_, options); 99 break; 100 case LONG_CLICK: 101 DecomposeLongClick(recv, point_, options); 102 break; 103 case DOUBLE_CLICK_P: 104 DecomposeDoubleClick(recv, point_, options); 105 break; 106 default: 107 break; 108 } 109 for (uint32_t index = 0; index < recv.GetSize(); index++) { 110 recv.At(recv.GetFingers() - 1, index).flags_ = type_; 111 } 112 } 113 Decompose(PointerMatrix & recv,const UiOpArgs & options) const114 void GenericSwipe::Decompose(PointerMatrix &recv, const UiOpArgs &options) const 115 { 116 DCHECK(type_ >= TouchOp::SWIPE && type_ <= TouchOp::DRAG); 117 DecomposeComputeSwipe(recv, from_, to_, type_ == TouchOp::DRAG, options); 118 for (uint32_t index = 0; index < recv.GetSize(); index++) { 119 recv.At(recv.GetFingers() - 1, index).flags_ = type_; 120 } 121 } 122 Decompose(PointerMatrix & recv,const UiOpArgs & options) const123 void GenericPinch::Decompose(PointerMatrix &recv, const UiOpArgs &options) const 124 { 125 const int32_t distanceX0 = abs(rect_.GetCenterX() - rect_.left_) * abs(scale_ - 1); 126 PointerMatrix pointer1; 127 PointerMatrix pointer2; 128 if (scale_ > 1) { 129 auto fromPoint0 = Point(rect_.GetCenterX() - options.scrollWidgetDeadZone_, rect_.GetCenterY()); 130 auto toPoint0 = Point((rect_.GetCenterX() - distanceX0), rect_.GetCenterY()); 131 auto fromPoint1 = Point(rect_.GetCenterX() + options.scrollWidgetDeadZone_, rect_.GetCenterY()); 132 auto toPoint1 = Point((rect_.GetCenterX() + distanceX0), rect_.GetCenterY()); 133 DecomposeComputeSwipe(pointer1, fromPoint0, toPoint0, false, options); 134 DecomposeComputeSwipe(pointer2, fromPoint1, toPoint1, false, options); 135 } else if (scale_ < 1) { 136 auto fromPoint0 = Point(rect_.left_ + options.scrollWidgetDeadZone_, rect_.GetCenterY()); 137 auto toPoint0 = Point((rect_.left_ + distanceX0), rect_.GetCenterY()); 138 auto fromPoint1 = Point(rect_.right_ - options.scrollWidgetDeadZone_, rect_.GetCenterY()); 139 auto toPoint1 = Point((rect_.right_ - distanceX0), rect_.GetCenterY()); 140 DecomposeComputeSwipe(pointer1, fromPoint0, toPoint0, false, options); 141 DecomposeComputeSwipe(pointer2, fromPoint1, toPoint1, false, options); 142 } 143 144 PointerMatrix pointer3(pointer1.GetFingers() + pointer2.GetFingers(), pointer1.GetSteps()); 145 for (uint32_t index = 0; index < pointer1.GetSize(); index++) { 146 pointer3.PushAction(pointer1.At(0, index)); 147 } 148 for (uint32_t index = 0; index < pointer2.GetSize(); index++) { 149 pointer3.PushAction(pointer2.At(0, index)); 150 } 151 recv = move(pointer3); 152 } 153 Decompose(PointerMatrix & recv,const UiOpArgs & options) const154 void MultiPointerAction::Decompose(PointerMatrix &recv, const UiOpArgs &options) const 155 { 156 PointerMatrix matrix(pointers_.GetFingers(), pointers_.GetSteps()); 157 for (uint32_t finger = 0; finger < pointers_.GetFingers(); finger++) { 158 uint32_t timeOffsetMs = 0; 159 uint32_t intervalMs = 0; 160 constexpr uint32_t unitConversionConstant = 1000; 161 for (uint32_t step = 0; step < pointers_.GetSteps() - 1; step++) { 162 const int32_t pxTo = pointers_.At(finger, step + 1).point_.px_; 163 const int32_t pxFrom = pointers_.At(finger, step).point_.px_; 164 const int32_t distanceX = pxTo - pxFrom; 165 const int32_t pyTo = pointers_.At(finger, step + 1).point_.py_; 166 const int32_t pyFrom = pointers_.At(finger, step).point_.py_; 167 const int32_t distanceY = pyTo - pyFrom; 168 const uint32_t distance = sqrt(distanceX * distanceX + distanceY * distanceY); 169 intervalMs = (distance * unitConversionConstant) / options.swipeVelocityPps_; 170 if (distance < 1) { 171 return; 172 } 173 if (step == 0) { 174 matrix.PushAction(TouchEvent {ActionStage::DOWN, {pxFrom, pyFrom}, 0, intervalMs}); 175 } else { 176 timeOffsetMs += intervalMs; 177 matrix.PushAction(TouchEvent {ActionStage::MOVE, {pxFrom, pyFrom}, timeOffsetMs, intervalMs}); 178 } 179 } 180 auto endPx = pointers_.At(finger, pointers_.GetSteps() - 1).point_.px_; 181 auto endPy = pointers_.At(finger, pointers_.GetSteps() - 1).point_.py_; 182 matrix.PushAction(TouchEvent {ActionStage::UP, {endPx, endPy}, timeOffsetMs, intervalMs}); 183 } 184 recv = move(matrix); 185 } 186 PointerMatrix()187 PointerMatrix::PointerMatrix() {}; 188 PointerMatrix(uint32_t fingersNum,uint32_t stepsNum)189 PointerMatrix::PointerMatrix(uint32_t fingersNum, uint32_t stepsNum) 190 { 191 this->fingerNum_ = fingersNum; 192 this->stepNum_ = stepsNum; 193 this->capacity_ = this->fingerNum_ * this->stepNum_; 194 this->size_ = 0; 195 this->data_ = std::make_unique<TouchEvent[]>(this->capacity_); 196 } 197 operator =(PointerMatrix && other)198 PointerMatrix& PointerMatrix::operator=(PointerMatrix&& other) 199 { 200 this->data_ = move(other.data_); 201 this->fingerNum_ = other.fingerNum_; 202 this->stepNum_ = other.stepNum_; 203 this->capacity_ = other.capacity_; 204 this->size_ = other.size_; 205 other.fingerNum_ = 0; 206 other.stepNum_ = 0; 207 other.capacity_ = 0; 208 other.size_ = 0; 209 return *this; 210 } 211 ~PointerMatrix()212 PointerMatrix::~PointerMatrix() {} 213 PushAction(const TouchEvent & ptr)214 void PointerMatrix::PushAction(const TouchEvent& ptr) 215 { 216 if (this->capacity_ == this->size_) { 217 return; 218 } 219 *(this->data_.get() + this->size_) = ptr; 220 this->size_++; 221 } 222 Empty() const223 bool PointerMatrix::Empty() const 224 { 225 if (this->size_ == 0) { 226 return true; 227 } 228 return false; 229 } 230 At(uint32_t fingerIndex,uint32_t stepIndex) const231 TouchEvent& PointerMatrix::At(uint32_t fingerIndex, uint32_t stepIndex) const 232 { 233 return *(this->data_.get() + (fingerIndex * this->stepNum_ + stepIndex)); 234 } 235 GetCapacity() const236 uint32_t PointerMatrix::GetCapacity() const 237 { 238 return this->capacity_; 239 } 240 GetSize() const241 uint32_t PointerMatrix::GetSize() const 242 { 243 return this->size_; 244 } 245 GetSteps() const246 uint32_t PointerMatrix::GetSteps() const 247 { 248 return this->stepNum_; 249 } 250 GetFingers() const251 uint32_t PointerMatrix::GetFingers() const 252 { 253 return this->fingerNum_; 254 } 255 } 256