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 #ifndef UI_MODEL_H 17 #define UI_MODEL_H 18 19 #include <vector> 20 #include <sstream> 21 #include "common_utilities_hpp.h" 22 #include "frontend_api_handler.h" 23 #include "nlohmann/json.hpp" 24 25 namespace OHOS::uitest { 26 using namespace std; 27 using namespace nlohmann; 28 const std::string ROOT_HIERARCHY = "ROOT"; 29 /**Enumerates the supported string value match rules.*/ 30 enum ValueMatchPattern : uint8_t { EQ, CONTAINS, STARTS_WITH, ENDS_WITH, REG_EXP, REG_EXP_ICASE }; 31 32 enum AamsWorkMode : uint8_t { NORMAL, FASTGETNODE, END }; 33 34 /**Enumerates the supported UiComponent attributes.*/ 35 enum UiAttr : uint8_t { 36 ACCESSIBILITY_ID, 37 ID, 38 TEXT, 39 KEY, 40 DESCRIPTION, 41 TYPE, 42 BOUNDS, 43 ENABLED, 44 FOCUSED, 45 SELECTED, 46 CLICKABLE, 47 LONG_CLICKABLE, 48 SCROLLABLE, 49 CHECKABLE, 50 CHECKED, 51 HOST_WINDOW_ID, 52 DISPLAY_ID, 53 ORIGBOUNDS, 54 ZINDEX, 55 OPACITY, 56 BACKGROUNDCOLOR, 57 BACKGROUNDIMAGE, 58 BLUR, 59 HITTESTBEHAVIOR, 60 CLIP, 61 // inner used attributes 62 HIERARCHY, 63 HASHCODE, 64 BOUNDSCENTER, 65 VISIBLE, 66 ABILITYNAME, 67 BUNDLENAME, 68 PAGEPATH, 69 DUMMY_ATTRNAME_SELECTION, 70 HINT, 71 MAX, // mark the max length 72 }; 73 74 /**Supported UiComponent attribute names. Ordered by <code>UiAttr</code> definition.*/ 75 constexpr std::string_view ATTR_NAMES[] = { 76 "accessibilityId", // ACCESSIBILITY_ID 77 "id", // ID 78 "text", // TEXT 79 "key", // KEY 80 "description", // DESCRIPTION 81 "type", // TYPE 82 "bounds", // BOUNDS 83 "enabled", // ENABLED 84 "focused", // FOCUSED 85 "selected", // SELECTED 86 "clickable", // CLICKABLE 87 "longClickable", // LONG_CLICKABLE 88 "scrollable", // SCROLLABLE 89 "checkable", // CHECKABLE 90 "checked", // CHECKED 91 "hostWindowId", // HOST_WINDOW_ID 92 "displayId", // DISPLAY_ID 93 "origBounds", // ORIGBOUNDS 94 "zIndex", // ZINDEX 95 "opacity", //OPACITY 96 "backgroundColor", // BACKGROUNDCOLOR 97 "backgroundImage", // BACKGROUNDIMAGE 98 "blur", //BLUR 99 "hitTestBehavior", // HITTESTBEHAVIOR 100 "clip", // CLIP 101 "hierarchy", // HIERARCHY 102 "hashcode", // HASHCODE 103 "boundsCenter", // BOUNDSCENTER 104 "visible", // VISIBLE 105 "abilityName", // ABILITYNAME 106 "bundleName", // BUNDLENAME 107 "pagePath", // PAGEPATH 108 "dummyAttrnameSelection", // DUMMY_ATTRNAME_SELECTION 109 "hint", // HINT 110 }; 111 112 struct Point { PointPoint113 Point() : px_(0), py_(0), displayId_(-1) {}; px_Point114 Point(int32_t px, int32_t py, int32_t displayId = -1) : px_(px), py_(py), displayId_(displayId) {}; 115 int32_t px_; 116 int32_t py_; 117 int32_t displayId_; 118 }; 119 120 /**Represents a reasonable rectangle area.*/ 121 struct Rect { 122 Rect(int32_t left, int32_t right, int32_t top, int32_t bottom, int32_t displayId = -1) left_Rect123 : left_(left), right_(right), top_(top), bottom_(bottom), displayId_(displayId) {}; RectRect124 Rect() 125 { 126 left_ = 0; 127 right_ = 0; 128 top_ = 0; 129 bottom_ = 0; 130 displayId_ = -1; 131 }; 132 int32_t left_; 133 int32_t right_; 134 int32_t top_; 135 int32_t bottom_; 136 int32_t displayId_; 137 GetCenterXRect138 FORCE_INLINE int32_t GetCenterX() const 139 { 140 return (left_ + right_) / TWO; 141 } 142 GetCenterYRect143 FORCE_INLINE int32_t GetCenterY() const 144 { 145 return (top_ + bottom_) / TWO; 146 } 147 GetWidthRect148 FORCE_INLINE int32_t GetWidth() const 149 { 150 return right_ - left_; 151 } 152 GetHeightRect153 FORCE_INLINE int32_t GetHeight() const 154 { 155 return bottom_ - top_; 156 } 157 DescribeRect158 std::string Describe() const 159 { 160 std::stringstream ss; 161 ss << "Rect {left:" << left_ << ",right:" << right_ << ",top:" << top_ << ",bottom:" << bottom_ << "}"; 162 return ss.str(); 163 } 164 }; 165 166 struct WidgetMatchModel { WidgetMatchModelWidgetMatchModel167 WidgetMatchModel(UiAttr name, string value, ValueMatchPattern matchPattern) 168 : attrName(name), attrValue(value), pattern(matchPattern) 169 { 170 } WidgetMatchModelWidgetMatchModel171 WidgetMatchModel() {} DescribeWidgetMatchModel172 std::string Describe() const 173 { 174 stringstream ss; 175 ss << "{"; 176 ss << "attrName:" << ATTR_NAMES[attrName].data() << "; value:" << attrValue 177 << "; Pattern:" << to_string(pattern); 178 ss << "}"; 179 return ss.str(); 180 } 181 UiAttr attrName; 182 string attrValue; 183 ValueMatchPattern pattern; 184 }; 185 186 /**Algorithm of rectangle.*/ 187 class RectAlgorithm { 188 public: 189 FORCE_INLINE static bool CheckEqual(const Rect &ra, const Rect &rb); 190 FORCE_INLINE static bool CheckIntersectant(const Rect &ra, const Rect &rb); 191 FORCE_INLINE static bool IsInnerPoint(const Rect &rect, const Point &point); 192 FORCE_INLINE static bool IsPointOnEdge(const Rect &rect, const Point &point); 193 static bool ComputeIntersection(const Rect &ra, const Rect &rb, Rect &result); 194 static bool ComputeMaxVisibleRegion(const Rect &rect, const std::vector<Rect> &overlays, Rect &out); 195 }; 196 CheckEqual(const Rect & ra,const Rect & rb)197 FORCE_INLINE bool RectAlgorithm::CheckEqual(const Rect &ra, const Rect &rb) 198 { 199 return ra.left_ == rb.left_ && ra.right_ == rb.right_ && ra.top_ == rb.top_ && ra.bottom_ == rb.bottom_; 200 } 201 CheckIntersectant(const Rect & ra,const Rect & rb)202 FORCE_INLINE bool RectAlgorithm::CheckIntersectant(const Rect &ra, const Rect &rb) 203 { 204 if (ra.left_ >= rb.right_ || ra.right_ <= rb.left_) { 205 return false; 206 } 207 if (ra.top_ >= rb.bottom_ || ra.bottom_ <= rb.top_) { 208 return false; 209 } 210 return true; 211 } 212 IsInnerPoint(const Rect & rect,const Point & point)213 FORCE_INLINE bool RectAlgorithm::IsInnerPoint(const Rect &rect, const Point& point) 214 { 215 if (point.px_ <= rect.left_ || point.px_ >= rect.right_ 216 || point.py_ <= rect.top_ || point.py_ >= rect.bottom_) { 217 return false; 218 } 219 return true; 220 } 221 IsPointOnEdge(const Rect & rect,const Point & point)222 FORCE_INLINE bool RectAlgorithm::IsPointOnEdge(const Rect &rect, const Point& point) 223 { 224 if ((point.px_ == rect.left_ || point.px_ == rect.right_) 225 && point.py_ >= rect.top_ && point.py_ <= rect.bottom_) { 226 return true; 227 } 228 if ((point.py_ == rect.top_ || point.py_ == rect.bottom_) 229 && point.px_ >= rect.left_ && point.px_ <= rect.right_) { 230 return true; 231 } 232 return false; 233 } 234 235 class Widget : public BackendClass { 236 public: 237 // disable default constructor, copy constructor and assignment operator Widget(std::string_view hierarchy)238 explicit Widget(std::string_view hierarchy) : hierarchy_(hierarchy) 239 { 240 attributeVec_[UiAttr::HIERARCHY] = hierarchy; 241 }; 242 ~Widget()243 ~Widget() override {} 244 GetFrontendClassDef()245 const FrontEndClassDef &GetFrontendClassDef() const override 246 { 247 return COMPONENT_DEF; 248 } 249 GetBounds()250 Rect GetBounds() const 251 { 252 return bounds_; 253 } 254 GetHierarchy()255 std::string GetHierarchy() const 256 { 257 return hierarchy_; 258 } 259 GetDisplayId()260 int32_t GetDisplayId() const 261 { 262 return displayId_; 263 } 264 SetDisplayId(const int32_t id)265 void SetDisplayId(const int32_t id) 266 { 267 displayId_ = id; 268 attributeVec_[UiAttr::DISPLAY_ID] = to_string(id); 269 } 270 271 void SetBounds(const Rect &bounds); 272 273 std::string ToStr() const; 274 275 std::unique_ptr<Widget> Clone(std::string_view hierarchy) const; 276 277 std::vector<std::string> GetAttrVec() const; 278 IsVisible()279 bool IsVisible() const 280 { 281 return GetAttr(UiAttr::VISIBLE) == "true"; 282 } 283 284 void SetAttr(UiAttr attrId, string value); 285 286 std::string GetAttr(UiAttr attrId) const; 287 288 bool MatchAttr(const WidgetMatchModel& matchModel) const; 289 290 void SetHierarchy(const std::string& hierarch); 291 292 void WrapperWidgetToJson(nlohmann::json& out); 293 private: 294 std::string hierarchy_; 295 std::vector<string> attributeVec_ = std::vector<string>(UiAttr::MAX + 1); 296 Rect bounds_ = {0, 0, 0, 0}; 297 std::int32_t displayId_ = 0; 298 }; 299 300 // ensure Widget is movable, since we need to move a constructed Widget object into WidgetTree 301 static_assert(std::is_move_constructible<Widget>::value, "Widget need to be movable"); 302 303 /**Enumerates the supported UiComponent attributes.*/ 304 enum WindowMode : uint8_t { UNKNOWN, FULLSCREEN, SPLIT_PRIMARY, SPLIT_SECONDARY, FLOATING, PIP }; 305 306 // Represents a UI window on screen. 307 class Window : public BackendClass { 308 public: Window(int32_t id)309 explicit Window(int32_t id) : id_(id) {}; 310 ~Window()311 ~Window() override {} 312 GetFrontendClassDef()313 const FrontEndClassDef &GetFrontendClassDef() const override 314 { 315 return UI_WINDOW_DEF; 316 } 317 318 // plain properties, make them public for easy access 319 int32_t id_ = 0; 320 int32_t windowLayer_ = 0; 321 std::string bundleName_ = ""; 322 std::string title_ = ""; 323 bool focused_ = false; 324 bool actived_ = false; 325 bool decoratorEnabled_ = false; 326 Rect bounds_ = {0, 0, 0, 0}; 327 Rect visibleBounds_ = {0, 0, 0, 0}; 328 std::vector<Rect> invisibleBoundsVec_; 329 std::string abilityName_ = ""; 330 std::string pagePath_ = ""; 331 WindowMode mode_ = UNKNOWN; 332 int32_t displayId_ = 0; 333 std::vector<Rect> touchHotAreas_; 334 Point offset_ = {0, 0}; 335 }; 336 337 class DumpHandler { 338 public: 339 static void AddExtraAttrs(nlohmann::json &root, const map<int32_t, string_view> &elementTrees, size_t index); 340 static void DumpWindowInfoToJson(vector<Widget> &allWidget, nlohmann::json &root); 341 }; 342 343 class WidgetHierarchyBuilder { 344 public: 345 static string Build(string_view parentWidgetHierarchy, uint32_t childIndex); 346 347 static string GetParentWidgetHierarchy(string_view hierarchy); 348 349 static string GetChildHierarchy(string_view hierarchy, uint32_t childIndex); 350 351 private: 352 static constexpr auto HIERARCHY_SEPARATOR = ","; 353 }; 354 355 struct DumpOption { 356 string savePath_ = ""; 357 bool listWindows_ = false; 358 bool addExternAttr_ = false; 359 string bundleName_ = ""; 360 string windowId_ = ""; 361 bool notMergeWindow_ = false; 362 int32_t displayId_ = 0; 363 }; 364 } // namespace OHOS::uitest 365 366 #endif