• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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