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 message; 39 }; 40 41 static constexpr Operational OPERATIONS[] = { 42 {MOVETO, FULLSCREEN, false, "Fullscreen window can not move"}, 43 {MOVETO, SPLIT_PRIMARY, false, "SPLIT_PRIMARY window can not move"}, 44 {MOVETO, SPLIT_SECONDARY, false, "SPLIT_SECONDARY window can not move"}, 45 {MOVETO, FLOATING, true, ""}, 46 {RESIZE, FULLSCREEN, false, "Fullscreen window can not resize"}, 47 {RESIZE, SPLIT_PRIMARY, true, ""}, 48 {RESIZE, SPLIT_SECONDARY, true, ""}, 49 {RESIZE, FLOATING, true, ""}, 50 {SPLIT, FULLSCREEN, true, ""}, 51 {SPLIT, SPLIT_PRIMARY, false, "SPLIT_PRIMARY can not split again"}, 52 {SPLIT, SPLIT_SECONDARY, true, ""}, 53 {SPLIT, FLOATING, true, ""}, 54 {MAXIMIZE, FULLSCREEN, false, "Fullscreen window is already maximized"}, 55 {MAXIMIZE, SPLIT_PRIMARY, true, ""}, 56 {MAXIMIZE, SPLIT_SECONDARY, true, ""}, 57 {MAXIMIZE, FLOATING, true, ""}, 58 {RESUME, FULLSCREEN, true, ""}, 59 {RESUME, SPLIT_PRIMARY, true, ""}, 60 {RESUME, SPLIT_SECONDARY, true, ""}, 61 {RESUME, FLOATING, true, ""}, 62 {MINIMIZE, FULLSCREEN, true, ""}, 63 {MINIMIZE, SPLIT_PRIMARY, true, ""}, 64 {MINIMIZE, SPLIT_SECONDARY, true, ""}, 65 {MINIMIZE, FLOATING, true, ""}, 66 {CLOSE, FULLSCREEN, true, ""}, 67 {CLOSE, SPLIT_PRIMARY, true, ""}, 68 {CLOSE, SPLIT_SECONDARY, true, ""}, 69 {CLOSE, FLOATING, true, ""}}; 70 CheckOperational(WindowAction action,WindowMode mode,ApiReplyInfo & out)71 static bool CheckOperational(WindowAction action, WindowMode mode, ApiReplyInfo &out) 72 { 73 for (unsigned long index = 0; index < sizeof(OPERATIONS) / sizeof(Operational); index++) { 74 if (OPERATIONS[index].action == action && OPERATIONS[index].windowMode == mode) { 75 if (OPERATIONS[index].support) { 76 return true; 77 } else { 78 out.exception_ = ApiCallErr(ERR_OPERATION_UNSUPPORTED, OPERATIONS[index].message); 79 return false; 80 } 81 } 82 } 83 out.exception_ = ApiCallErr(ERR_INTERNAL, "No such window mode-action combination registered"); 84 return false; 85 } 86 WindowOperator(UiDriver & driver,const Window & window,UiOpArgs & options)87 WindowOperator::WindowOperator(UiDriver &driver, const Window &window, UiOpArgs &options) 88 : driver_(driver), window_(window), options_(options) 89 { 90 } 91 Focus(ApiReplyInfo & out)92 void WindowOperator::Focus(ApiReplyInfo &out) 93 { 94 if (window_.focused_) { 95 return; 96 } else { 97 auto rect = window_.visibleBounds_; 98 static constexpr uint32_t step = 10; 99 Point focus(rect.GetCenterX(), rect.top_ + step, window_.displayId_); 100 auto touch = GenericClick(TouchOp::CLICK, focus); 101 driver_.PerformTouch(touch, options_, out.exception_); 102 } 103 } 104 MoveTo(uint32_t endX,uint32_t endY,ApiReplyInfo & out)105 void WindowOperator::MoveTo(uint32_t endX, uint32_t endY, ApiReplyInfo &out) 106 { 107 Focus(out); 108 if (!CheckOperational(MOVETO, window_.mode_, out)) { 109 return; 110 } 111 auto rect = window_.bounds_; 112 static constexpr uint32_t step = 40; 113 Point from(rect.left_ + step, rect.top_ + step); 114 Point to(endX + step, endY + step); 115 from.displayId_ = window_.displayId_; 116 to.displayId_ = window_.displayId_; 117 auto touch = GenericSwipe(TouchOp::DRAG, from, to); 118 driver_.PerformTouch(touch, options_, out.exception_); 119 } 120 Resize(int32_t width,int32_t highth,ResizeDirection direction,ApiReplyInfo & out)121 void WindowOperator::Resize(int32_t width, int32_t highth, ResizeDirection direction, ApiReplyInfo &out) 122 { 123 Focus(out); 124 if (!CheckOperational(RESIZE, window_.mode_, out)) { 125 return; 126 } 127 Point from; 128 Point to; 129 switch (direction) { 130 case (LEFT): 131 from = Point(window_.bounds_.left_, window_.bounds_.GetCenterY()); 132 to = Point((window_.bounds_.right_ - width), window_.bounds_.GetCenterY()); 133 break; 134 case (RIGHT): 135 from = Point(window_.bounds_.right_, window_.bounds_.GetCenterY()); 136 to = Point((window_.bounds_.left_ + width), window_.bounds_.GetCenterY()); 137 break; 138 case (D_UP): 139 from = Point(window_.bounds_.GetCenterX(), window_.bounds_.top_); 140 to = Point(window_.bounds_.GetCenterX(), window_.bounds_.bottom_ - highth); 141 break; 142 case (D_DOWN): 143 from = Point(window_.bounds_.GetCenterX(), window_.bounds_.bottom_); 144 to = Point(window_.bounds_.GetCenterX(), window_.bounds_.top_ + highth); 145 break; 146 case (LEFT_UP): 147 from = Point(window_.bounds_.left_, window_.bounds_.top_); 148 to = Point(window_.bounds_.right_ - width, window_.bounds_.bottom_ - highth); 149 break; 150 case (LEFT_DOWN): 151 from = Point(window_.bounds_.left_, window_.bounds_.bottom_); 152 to = Point(window_.bounds_.right_ - width, window_.bounds_.top_ + highth); 153 break; 154 case (RIGHT_UP): 155 from = Point(window_.bounds_.right_, window_.bounds_.top_); 156 to = Point(window_.bounds_.left_ + width, window_.bounds_.bottom_ - highth); 157 break; 158 case (RIGHT_DOWN): 159 from = Point(window_.bounds_.right_, window_.bounds_.bottom_); 160 to = Point(window_.bounds_.left_ + width, window_.bounds_.top_ + highth); 161 break; 162 default: 163 break; 164 } 165 from.displayId_ = window_.displayId_; 166 to.displayId_ = window_.displayId_; 167 driver_.PerformTouch(GenericSwipe(TouchOp::DRAG, from, to), options_, out.exception_); 168 } 169 Split(ApiReplyInfo & out)170 void WindowOperator::Split(ApiReplyInfo &out) 171 { 172 if (!CheckOperational(SPLIT, window_.mode_, out)) { 173 return; 174 } 175 driver_.ChangeWindowMode(window_.id_, WindowMode::SPLIT_PRIMARY); 176 } 177 Maximize(ApiReplyInfo & out)178 void WindowOperator::Maximize(ApiReplyInfo &out) 179 { 180 string targetBtnId; 181 if (!CheckOperational(MAXIMIZE, window_.mode_, out)) { 182 return; 183 } 184 driver_.ChangeWindowMode(window_.id_, WindowMode::FULLSCREEN); 185 } 186 Resume(ApiReplyInfo & out)187 void WindowOperator::Resume(ApiReplyInfo &out) 188 { 189 string targetBtnId; 190 if (!CheckOperational(RESUME, window_.mode_, out)) { 191 return; 192 } 193 if (window_.mode_ == WindowMode::FULLSCREEN) { 194 driver_.ChangeWindowMode(window_.id_, WindowMode::FLOATING); 195 } else { 196 driver_.ChangeWindowMode(window_.id_, WindowMode::FULLSCREEN); 197 } 198 } 199 Minimize(ApiReplyInfo & out)200 void WindowOperator::Minimize(ApiReplyInfo &out) 201 { 202 if (!CheckOperational(MINIMIZE, window_.mode_, out)) { 203 return; 204 } 205 driver_.ChangeWindowMode(window_.id_, WindowMode::MINIMIZED); 206 } 207 Close(ApiReplyInfo & out)208 void WindowOperator::Close(ApiReplyInfo &out) 209 { 210 if (!CheckOperational(CLOSE, window_.mode_, out)) { 211 return; 212 } 213 driver_.ChangeWindowMode(window_.id_, WindowMode::CLOSED); 214 } 215 } // namespace OHOS::uitest 216