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