• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "window_operator.h"
17 #include <map>
18 
19 namespace OHOS::uitest {
20     using namespace std;
21     using namespace nlohmann;
22 
23     enum WindowAction : uint8_t {
24         FOCUS,
25         MOVETO,
26         RESIZE,
27         SPLIT,
28         MAXIMIZE,
29         RESUME,
30         MINIMIZE,
31         CLOSE
32     };
33 
34     struct Operational {
35         WindowAction action;
36         WindowMode windowMode;
37         bool support;
38         std::string_view buttonId;
39         std::string_view message;
40     };
41 
42     static constexpr Operational OPERATIONS[] = {
43         {MOVETO, FULLSCREEN, false, "", "Fullscreen window can not move"},
44         {MOVETO, SPLIT_PRIMARY, false, "", "SPLIT_PRIMARY window can not move"},
45         {MOVETO, SPLIT_SECONDARY, false, "", "SPLIT_SECONDARY window can not move"},
46         {MOVETO, FLOATING, true, "", ""},
47         {RESIZE, FULLSCREEN, false, "", "Fullscreen window can not resize"},
48         {RESIZE, SPLIT_PRIMARY, true, "", ""},
49         {RESIZE, SPLIT_SECONDARY, true, "", ""},
50         {RESIZE, FLOATING, true, "", ""},
51         {SPLIT, FULLSCREEN, true, "container_modal_split_left_button", ""},
52         {SPLIT, SPLIT_PRIMARY, false, "container_modal_split_left_button", "SPLIT_PRIMARY can not split again"},
53         {SPLIT, SPLIT_SECONDARY, true, "container_modal_split_left_button", ""},
54         {SPLIT, FLOATING, true, "container_modal_split_left_button", ""},
55         {MAXIMIZE, FULLSCREEN, false, "container_modal_maximize_button", "Fullscreen window is already maximized"},
56         {MAXIMIZE, SPLIT_PRIMARY, true, "container_modal_maximize_button", ""},
57         {MAXIMIZE, SPLIT_SECONDARY, true, "container_modal_maximize_button", ""},
58         {MAXIMIZE, FLOATING, true, "container_modal_maximize_button", ""},
59         {RESUME, FULLSCREEN, true, "container_modal_maximize_button", ""},
60         {RESUME, SPLIT_PRIMARY, true, "container_modal_maximize_button", ""},
61         {RESUME, SPLIT_SECONDARY, true, "container_modal_maximize_button", ""},
62         {RESUME, FLOATING, true, "container_modal_maximize_button", ""},
63         {MINIMIZE, FULLSCREEN, true, "container_modal_minimize_button", ""},
64         {MINIMIZE, SPLIT_PRIMARY, true, "container_modal_minimize_button", ""},
65         {MINIMIZE, SPLIT_SECONDARY, true, "container_modal_minimize_button", ""},
66         {MINIMIZE, FLOATING, true, "container_modal_minimize_button", ""},
67         {CLOSE, FULLSCREEN, true, "container_modal_close_button", ""},
68         {CLOSE, SPLIT_PRIMARY, true, "container_modal_close_button", ""},
69         {CLOSE, SPLIT_SECONDARY, true, "container_modal_close_button", ""},
70         {CLOSE, FLOATING, true, "container_modal_close_button", ""}
71     };
72 
CheckOperational(WindowAction action,WindowMode mode,ApiReplyInfo & out,string & buttonId)73     static bool CheckOperational(WindowAction action, WindowMode mode, ApiReplyInfo &out, string &buttonId)
74     {
75         for (unsigned long index = 0; index < sizeof(OPERATIONS) / sizeof(Operational); index++) {
76             if (OPERATIONS[index].action == action && OPERATIONS[index].windowMode == mode) {
77                 if (OPERATIONS[index].support) {
78                     buttonId = OPERATIONS[index].buttonId;
79                     return true;
80                 } else {
81                     out.exception_ = ApiCallErr(ERR_OPERATION_UNSUPPORTED, OPERATIONS[index].message);
82                     return false;
83                 }
84             }
85         }
86         out.exception_ = ApiCallErr(ERR_INTERNAL, "No such window mode-action combination registered");
87         return false;
88     }
89 
WindowOperator(UiDriver & driver,const Window & window,UiOpArgs & options)90     WindowOperator::WindowOperator(UiDriver &driver, const Window &window, UiOpArgs &options)
91         : driver_(driver), window_(window), options_(options)
92     {
93     }
94 
CallBar(ApiReplyInfo & out)95     void WindowOperator::CallBar(ApiReplyInfo &out)
96     {
97         Focus(out);
98         if (window_.mode_ == WindowMode::FLOATING) {
99             return;
100         }
101         auto rect = window_.bounds_;
102         static constexpr uint32_t step1 = 10;
103         static constexpr uint32_t step2 = 40;
104         Point from(rect.GetCenterX(), rect.top_ + step1);
105         Point to(rect.GetCenterX(), rect.top_ + step2);
106         auto touch = GenericSwipe(TouchOp::DRAG, from, to);
107         driver_.PerformTouch(touch, options_, out.exception_);
108         driver_.DelayMs(options_.uiSteadyThresholdMs_);
109     }
110 
Focus(ApiReplyInfo & out)111     void WindowOperator::Focus(ApiReplyInfo &out)
112     {
113         if (window_.focused_) {
114             return;
115         } else {
116             auto rect = window_.visibleBounds_;
117             static constexpr uint32_t step = 10;
118             Point focus(rect.GetCenterX(), rect.top_ + step);
119             auto touch = GenericClick(TouchOp::CLICK, focus);
120             driver_.PerformTouch(touch, options_, out.exception_);
121         }
122     }
123 
MoveTo(uint32_t endX,uint32_t endY,ApiReplyInfo & out)124     void WindowOperator::MoveTo(uint32_t endX, uint32_t endY, ApiReplyInfo &out)
125     {
126         Focus(out);
127         string targetBtnId;
128         if (!CheckOperational(MOVETO, window_.mode_, out, targetBtnId)) {
129             return;
130         }
131         auto rect = window_.bounds_;
132         static constexpr uint32_t step = 40;
133         Point from(rect.left_ + step, rect.top_ + step);
134         Point to(endX + step, endY + step);
135         auto touch = GenericSwipe(TouchOp::DRAG, from, to);
136         driver_.PerformTouch(touch, options_, out.exception_);
137     }
138 
Resize(int32_t width,int32_t highth,ResizeDirection direction,ApiReplyInfo & out)139     void WindowOperator::Resize(int32_t width, int32_t highth, ResizeDirection direction, ApiReplyInfo &out)
140     {
141         Focus(out);
142         string targetBtnId;
143         if (!CheckOperational(RESIZE, window_.mode_, out, targetBtnId)) {
144             return;
145         }
146         Point from;
147         Point to;
148         switch (direction) {
149             case (LEFT):
150                 from = Point(window_.bounds_.left_, window_.bounds_.GetCenterY());
151                 to = Point((window_.bounds_.right_ - width), window_.bounds_.GetCenterY());
152                 break;
153             case (RIGHT):
154                 from = Point(window_.bounds_.right_, window_.bounds_.GetCenterY());
155                 to = Point((window_.bounds_.left_ + width), window_.bounds_.GetCenterY());
156                 break;
157             case (D_UP):
158                 from = Point(window_.bounds_.GetCenterX(), window_.bounds_.top_);
159                 to = Point(window_.bounds_.GetCenterX(), window_.bounds_.bottom_ - highth);
160                 break;
161             case (D_DOWN):
162                 from = Point(window_.bounds_.GetCenterX(), window_.bounds_.bottom_);
163                 to = Point(window_.bounds_.GetCenterX(), window_.bounds_.top_ + highth);
164                 break;
165             case (LEFT_UP):
166                 from = Point(window_.bounds_.left_, window_.bounds_.top_);
167                 to = Point(window_.bounds_.right_ - width, window_.bounds_.bottom_ - highth);
168                 break;
169             case (LEFT_DOWN):
170                 from = Point(window_.bounds_.left_, window_.bounds_.bottom_);
171                 to = Point(window_.bounds_.right_ - width, window_.bounds_.top_ + highth);
172                 break;
173             case (RIGHT_UP):
174                 from = Point(window_.bounds_.right_, window_.bounds_.top_);
175                 to = Point(window_.bounds_.left_ + width, window_.bounds_.bottom_ - highth);
176                 break;
177             case (RIGHT_DOWN):
178                 from = Point(window_.bounds_.right_, window_.bounds_.bottom_);
179                 to = Point(window_.bounds_.left_ + width, window_.bounds_.top_ + highth);
180                 break;
181             default:
182                 break;
183         }
184         driver_.PerformTouch(GenericSwipe(TouchOp::DRAG, from, to), options_, out.exception_);
185     }
186 
Split(ApiReplyInfo & out)187     void WindowOperator::Split(ApiReplyInfo &out)
188     {
189         string targetBtnId;
190         if (!CheckOperational(SPLIT, window_.mode_, out, targetBtnId)) {
191             return;
192         }
193         BarAction(targetBtnId, out);
194     }
195 
Maximize(ApiReplyInfo & out)196     void  WindowOperator::Maximize(ApiReplyInfo &out)
197     {
198         string targetBtnId;
199         if (!CheckOperational(MAXIMIZE, window_.mode_, out, targetBtnId)) {
200             return;
201         }
202         BarAction(targetBtnId, out);
203     }
204 
Resume(ApiReplyInfo & out)205     void WindowOperator::Resume(ApiReplyInfo &out)
206     {
207         string targetBtnId;
208         if (!CheckOperational(RESUME, window_.mode_, out, targetBtnId)) {
209             return;
210         }
211         BarAction(targetBtnId, out);
212     }
213 
Minimize(ApiReplyInfo & out)214     void WindowOperator::Minimize(ApiReplyInfo &out)
215     {
216         string targetBtnId;
217         if (!CheckOperational(MINIMIZE, window_.mode_, out, targetBtnId)) {
218             return;
219         }
220         BarAction(targetBtnId, out);
221     }
222 
Close(ApiReplyInfo & out)223     void WindowOperator::Close(ApiReplyInfo &out)
224     {
225         string targetBtnId;
226         if (!CheckOperational(CLOSE, window_.mode_, out, targetBtnId)) {
227             return;
228         }
229         BarAction(targetBtnId, out);
230     }
231 
BarAction(string_view buttonId,ApiReplyInfo & out)232     void WindowOperator::BarAction(string_view buttonId, ApiReplyInfo &out)
233     {
234         CallBar(out);
235         auto selector = WidgetSelector();
236         auto attrMatcher = WidgetAttrMatcher(ATTR_NAMES[UiAttr::KEY], buttonId, EQ);
237         auto windowMatcher = WidgetAttrMatcher(ATTR_NAMES[UiAttr::HOST_WINDOW_ID], to_string(window_.id_), EQ);
238         selector.AddMatcher(attrMatcher);
239         selector.AddMatcher(windowMatcher);
240         selector.AddAppLocator(window_.bundleName_);
241         vector<unique_ptr<Widget>> widgets;
242         driver_.FindWidgets(selector, widgets, out.exception_);
243         if (out.exception_.code_ != NO_ERROR) {
244             return;
245         }
246         if (widgets.empty()) {
247             out.exception_ = ApiCallErr(USAGE_ERROR, "Not find target winAction button");
248             return;
249         }
250         auto rect = widgets[0]->GetBounds();
251         Point widgetCenter(rect.GetCenterX(), rect.GetCenterY());
252         auto touch = GenericClick(TouchOp::CLICK, widgetCenter);
253         driver_.PerformTouch(touch, options_, out.exception_);
254     }
255 } // namespace OHOS::uitest
256