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 #ifndef UI_ACTION_H 16 #define UI_ACTION_H 17 18 #include <vector> 19 #include "ui_model.h" 20 21 namespace OHOS::uitest { 22 // frequently used keys. 23 constexpr int32_t KEYCODE_NONE = 0; 24 constexpr int32_t KEYCODE_BACK = 2; 25 constexpr int32_t KEYCODE_DPAD_RIGHT = 2015; 26 constexpr int32_t KEYCODE_DEL = 2055; 27 constexpr int32_t KEYCODE_CTRL = 2072; 28 constexpr int32_t KEYCODE_V = 2038; 29 constexpr int32_t KEYCODE_POWER = 18; 30 constexpr int32_t KEYCODE_HOME = 1; 31 constexpr int32_t KEYCODE_D = 2020; 32 constexpr int32_t KEYCODE_WIN = 2076; 33 34 /**Enumerates all the supported coordinate-based touch operations.*/ 35 enum TouchOp : uint8_t { CLICK, LONG_CLICK, DOUBLE_CLICK_P, SWIPE, DRAG, FLING}; 36 37 /**Enumerates the supported Key actions.*/ 38 enum UiKey : uint8_t { BACK, GENERIC }; 39 40 enum ActionStage : uint8_t { 41 NONE = 0, DOWN = 1, MOVE = 2, UP = 3, AXIS_UP = 4, AXIS_DOWN = 5, AXIS_STOP = 6 42 }; 43 44 enum ResizeDirection : uint8_t { 45 LEFT, 46 RIGHT, 47 D_UP, 48 D_DOWN, 49 LEFT_UP, 50 LEFT_DOWN, 51 RIGHT_UP, 52 RIGHT_DOWN 53 }; 54 55 enum DisplayRotation : uint32_t { 56 ROTATION_0, 57 ROTATION_90, 58 ROTATION_180, 59 ROTATION_270 60 }; 61 62 enum MouseButton : int32_t { 63 BUTTON_NONE = -1, 64 BUTTON_LEFT = 0, 65 BUTTON_RIGHT = 1, 66 BUTTON_MIDDLE = 2 67 }; 68 69 enum Direction : uint32_t { 70 TO_LEFT, 71 TO_RIGHT, 72 TO_UP, 73 TO_DOWN 74 }; 75 76 struct TouchEvent { 77 ActionStage stage_; 78 Point point_; 79 uint32_t downTimeOffsetMs_; 80 uint32_t holdMs_; 81 uint32_t flags_; 82 }; 83 84 struct KeyEvent { 85 ActionStage stage_; 86 int32_t code_; 87 uint32_t holdMs_; 88 }; 89 90 struct MouseEvent { 91 ActionStage stage_; 92 Point point_; 93 MouseButton button_; 94 vector<KeyEvent> keyEvents_; 95 uint32_t holdMs_; 96 }; 97 98 class PointerMatrix : public BackendClass { 99 public: 100 PointerMatrix(); 101 102 PointerMatrix(uint32_t fingersNum, uint32_t stepsNum); 103 104 PointerMatrix(PointerMatrix&& other); 105 106 PointerMatrix& operator=(PointerMatrix&& other); 107 108 ~PointerMatrix() override; 109 GetFrontendClassDef()110 const FrontEndClassDef &GetFrontendClassDef() const override 111 { 112 return POINTER_MATRIX_DEF; 113 } 114 115 void PushAction(const TouchEvent& ptr); 116 117 bool Empty() const; 118 119 TouchEvent& At(uint32_t fingerIndex, uint32_t stepIndex) const; 120 121 uint32_t GetCapacity() const; 122 123 uint32_t GetSize() const; 124 125 uint32_t GetSteps() const; 126 127 uint32_t GetFingers() const; 128 129 void ConvertToMouseEvents(vector<MouseEvent> &recv) const; 130 private: 131 std::unique_ptr<TouchEvent[]> data_ = nullptr; 132 uint32_t capacity_ = 0; 133 uint32_t stepNum_ = 0; 134 uint32_t fingerNum_ = 0; 135 uint32_t size_ = 0; 136 }; 137 138 /** 139 * Options of the UI operations, initialized with system default values. 140 **/ 141 class UiOpArgs { 142 public: 143 const uint32_t maxSwipeVelocityPps_ = 40000; 144 const uint32_t minSwipeVelocityPps_ = 200; 145 const uint32_t defaultSwipeVelocityPps_ = 600; 146 const uint32_t maxMultiTouchFingers = 10; 147 const uint32_t maxMultiTouchSteps = 1000; 148 uint32_t clickHoldMs_ = 100; 149 uint32_t longClickHoldMs_ = 1500; 150 uint32_t doubleClickIntervalMs_ = 200; 151 uint32_t keyHoldMs_ = 100; 152 uint32_t swipeVelocityPps_ = defaultSwipeVelocityPps_; 153 uint32_t uiSteadyThresholdMs_ = 1000; 154 uint32_t waitUiSteadyMaxMs_ = 3000; 155 uint32_t waitWidgetMaxMs_ = 5000; 156 int32_t scrollWidgetDeadZone_ = 80; // make sure the scrollWidget does not slide more than one page. 157 int32_t pinchWidgetDeadZone_ = 80; // pinching at the edges of the widget has no effect. 158 uint16_t swipeStepsCounts_ = 50; 159 }; 160 161 class TouchAction { 162 public: 163 /**Compute the touch event sequence that are needed to implement this action. 164 * @param recv: the event seqence receiver. 165 * @param options the ui operation agruments. 166 * */ 167 virtual void Decompose(PointerMatrix &recv, const UiOpArgs &options) const = 0; 168 }; 169 170 /** 171 * Base type of all raw pointer click actions. 172 **/ 173 class GenericClick : public TouchAction { 174 public: GenericClick(TouchOp type,const Point & point)175 GenericClick(TouchOp type, const Point &point) : type_(type), point_(point) {}; 176 177 void Decompose(PointerMatrix &recv, const UiOpArgs &options) const override; 178 179 ~GenericClick() = default; 180 181 private: 182 const TouchOp type_; 183 const Point point_; 184 }; 185 186 /** 187 * Base type of all raw pointer swipe actions. 188 **/ 189 class GenericSwipe : public TouchAction { 190 public: GenericSwipe(TouchOp type,const Point & from,const Point & to)191 explicit GenericSwipe(TouchOp type, const Point &from, const Point &to) : type_(type), from_(from), to_(to) {}; 192 193 void Decompose(PointerMatrix &recv, const UiOpArgs &options) const override; 194 195 ~GenericSwipe() = default; 196 197 private: 198 const TouchOp type_; 199 const Point from_; 200 const Point to_; 201 }; 202 203 /** 204 * Base type of all raw pointer pinch actions. 205 **/ 206 class GenericPinch : public TouchAction { 207 public: GenericPinch(const Rect & rect,float_t scale)208 explicit GenericPinch(const Rect &rect, float_t scale) : rect_(rect), scale_(scale) {}; 209 210 void Decompose(PointerMatrix &recv, const UiOpArgs &options) const override; 211 212 ~GenericPinch() = default; 213 214 private: 215 const Rect rect_; 216 const float_t scale_; 217 }; 218 219 /** 220 * Base type of multi pointer actions. 221 **/ 222 class MultiPointerAction : public TouchAction { 223 public: MultiPointerAction(const PointerMatrix & pointer)224 explicit MultiPointerAction(const PointerMatrix &pointer) : pointers_(pointer) {}; 225 226 void Decompose(PointerMatrix &recv, const UiOpArgs &options) const override; 227 228 ~MultiPointerAction() = default; 229 230 private: 231 const PointerMatrix& pointers_; 232 }; 233 234 /** 235 * Base type of all key actions. 236 * */ 237 class KeyAction { 238 public: 239 /**Compute the key event sequence that are needed to implement this action.*/ 240 virtual void ComputeEvents(std::vector<KeyEvent> &recv, const UiOpArgs &options) const = 0; 241 242 virtual ~KeyAction() = default; 243 }; 244 245 class KeysForwarder : public KeyAction { 246 public: KeysForwarder(const vector<KeyEvent> & evetns)247 explicit KeysForwarder(const vector<KeyEvent> &evetns) : events_(evetns) {}; 248 ComputeEvents(vector<KeyEvent> & recv,const UiOpArgs & opt)249 void ComputeEvents(vector<KeyEvent> &recv, const UiOpArgs &opt) const override 250 { 251 recv = events_; 252 } 253 254 private: 255 const vector<KeyEvent> &events_; 256 }; 257 258 /**Base type of named single-key actions with at most 1 ctrl key.*/ 259 template<uint32_t kCode, uint32_t kCtrlCode = KEYCODE_NONE> 260 class NamedPlainKey : public KeyAction { 261 public: 262 explicit NamedPlainKey() = default; 263 ComputeEvents(std::vector<KeyEvent> & recv,const UiOpArgs & opt)264 void ComputeEvents(std::vector<KeyEvent> &recv, const UiOpArgs &opt) const override 265 { 266 if (kCtrlCode != KEYCODE_NONE) { 267 recv.push_back(KeyEvent {ActionStage::DOWN, kCtrlCode, 0}); 268 } 269 recv.push_back(KeyEvent {ActionStage::DOWN, kCode, opt.keyHoldMs_}); 270 recv.push_back(KeyEvent {ActionStage::UP, kCode, 0}); 271 if (kCtrlCode != KEYCODE_NONE) { 272 recv.push_back(KeyEvent {ActionStage::UP, kCtrlCode, 0}); 273 } 274 } 275 }; 276 277 /**Generic key actions without name and ctrl key.*/ 278 class AnonymousSingleKey final : public KeyAction { 279 public: AnonymousSingleKey(int32_t code)280 explicit AnonymousSingleKey(int32_t code) : code_(code) {}; 281 ComputeEvents(std::vector<KeyEvent> & recv,const UiOpArgs & opt)282 void ComputeEvents(std::vector<KeyEvent> &recv, const UiOpArgs &opt) const override 283 { 284 recv.push_back(KeyEvent {ActionStage::DOWN, code_, opt.keyHoldMs_}); 285 recv.push_back(KeyEvent {ActionStage::UP, code_, 0}); 286 } 287 288 private: 289 const int32_t code_; 290 }; 291 292 /**Generic Combinedkeys actions.*/ 293 class CombinedKeys final : public KeyAction { 294 public: CombinedKeys(int32_t codeZero,int32_t codeOne,int32_t codeTwo)295 CombinedKeys(int32_t codeZero, int32_t codeOne, int32_t codeTwo) 296 : codeZero_(codeZero), codeOne_(codeOne), codeTwo_(codeTwo) {}; 297 ComputeEvents(std::vector<KeyEvent> & recv,const UiOpArgs & opt)298 void ComputeEvents(std::vector<KeyEvent> &recv, const UiOpArgs &opt) const override 299 { 300 recv.push_back(KeyEvent {ActionStage::DOWN, codeZero_, 0}); 301 recv.push_back(KeyEvent {ActionStage::DOWN, codeOne_, 0}); 302 if (codeTwo_ != KEYCODE_NONE) { 303 recv.push_back(KeyEvent {ActionStage::DOWN, codeTwo_, opt.keyHoldMs_}); 304 } else { 305 recv.at(INDEX_ONE).holdMs_ = opt.keyHoldMs_; 306 } 307 if (codeTwo_ != KEYCODE_NONE) { 308 recv.push_back(KeyEvent {ActionStage::UP, codeTwo_, 0}); 309 } 310 recv.push_back(KeyEvent {ActionStage::UP, codeOne_, 0}); 311 recv.push_back(KeyEvent {ActionStage::UP, codeZero_, 0}); 312 } 313 314 private: 315 const int32_t codeZero_; 316 const int32_t codeOne_; 317 const int32_t codeTwo_; 318 }; 319 320 using Back = NamedPlainKey<KEYCODE_BACK>; 321 using Power = NamedPlainKey<KEYCODE_POWER>; 322 using Home = NamedPlainKey<KEYCODE_HOME>; 323 using Paste = NamedPlainKey<KEYCODE_V, KEYCODE_CTRL>; 324 325 class MouseAction { 326 public: 327 /**Compute the mouse event sequence that are needed to implement this action. 328 * @param recv: the event seqence receiver. 329 * @param options the ui operation agruments. 330 * */ 331 virtual void Decompose(std::vector<MouseEvent> &recv, const UiOpArgs &opt) const = 0; 332 }; 333 334 class MouseMoveTo : public MouseAction { 335 public: MouseMoveTo(const Point & point)336 explicit MouseMoveTo(const Point &point) : point_(point) {}; 337 338 void Decompose(std::vector<MouseEvent> &recv, const UiOpArgs &opt) const override; 339 340 ~MouseMoveTo() = default; 341 342 private: 343 const Point point_; 344 }; 345 346 class MouseSwipe : public MouseAction { 347 public: MouseSwipe(TouchOp type,const Point & from,const Point & to)348 explicit MouseSwipe(TouchOp type, const Point &from, const Point &to) : type_(type), from_(from), to_(to) {}; 349 350 void Decompose(std::vector<MouseEvent> &recv, const UiOpArgs &opt) const override; 351 352 ~MouseSwipe() = default; 353 354 private: 355 const TouchOp type_; 356 const Point from_; 357 const Point to_; 358 }; 359 360 class MouseClick : public MouseAction { 361 public: MouseClick(TouchOp type,const Point & point,const MouseButton & button,int32_t & key1,int32_t & key2)362 explicit MouseClick(TouchOp type, const Point &point, const MouseButton &button, int32_t &key1, int32_t &key2) 363 : type_(type), point_(point), button_(button), key1_(key1), key2_(key2) {}; 364 365 void Decompose(std::vector<MouseEvent> &recv, const UiOpArgs &opt) const override; 366 367 ~MouseClick() = default; 368 369 private: 370 const TouchOp type_; 371 const Point point_; 372 const MouseButton button_; 373 const int32_t key1_; 374 const int32_t key2_; 375 }; 376 377 class MouseScroll : public MouseAction { 378 public: MouseScroll(const Point & point,int32_t scrollValue,int32_t key1,int32_t key2,uint32_t speed)379 explicit MouseScroll(const Point &point, int32_t scrollValue, int32_t key1, int32_t key2, uint32_t speed) 380 : point_(point), scrollValue_(scrollValue), key1_(key1), key2_(key2), speed_(speed) {}; 381 382 void Decompose(std::vector<MouseEvent> &recv, const UiOpArgs &opt) const override; 383 384 ~MouseScroll() = default; 385 386 private: 387 const Point point_; 388 const int32_t scrollValue_; 389 const int32_t key1_; 390 const int32_t key2_; 391 const uint32_t speed_; 392 }; 393 394 /** 395 * Base type of all atomic actions. 396 * */ 397 class GenericAtomicAction : public TouchAction { 398 public: GenericAtomicAction(const ActionStage stage,const Point point)399 explicit GenericAtomicAction(const ActionStage stage, const Point point) : stage_(stage), point_(point) {}; 400 401 void Decompose(PointerMatrix &recv, const UiOpArgs &options) const override; 402 403 ~GenericAtomicAction() = default; 404 405 private: 406 const ActionStage stage_; 407 const Point point_; 408 }; 409 } 410 411 #endif