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 #include "display_zoom_controller.h" 16 #include "display_group_info.h" 17 #include "window_helper.h" 18 19 namespace OHOS::Rosen { 20 namespace { 21 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DisplayZoomController"}; 22 } 23 SetAnchorAndScale(int32_t x,int32_t y,float scale)24 void DisplayZoomController::SetAnchorAndScale(int32_t x, int32_t y, float scale) 25 { 26 WLOGFD("DisplayZoom: On, anchor x:%{public}d, y:%{public}d, scale:%{public}f", x, y, scale); 27 if (scale <= 0) { 28 return; 29 } else if (zoomInfo_.scale * scale < DISPLAY_ZOOM_MIN_SCALE) { 30 scale = DISPLAY_ZOOM_MIN_SCALE / zoomInfo_.scale; 31 } else if (zoomInfo_.scale * scale > DISPLAY_ZOOM_MAX_SCALE) { 32 scale = DISPLAY_ZOOM_MAX_SCALE / zoomInfo_.scale; 33 } 34 DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId(); 35 sptr<WindowNodeContainer> windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); 36 if (windowNodeContainer == nullptr) { 37 return; 38 } 39 std::vector<sptr<WindowNode>> windowNodes; 40 windowNodeContainer->TraverseContainer(windowNodes); 41 bool isAlreadyCalcu = false; 42 for (auto& node : windowNodes) { 43 if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) != 44 displayZoomWindowTypeSkipped_.end()) { 45 continue; 46 } 47 Transform zoomTrans; 48 if (!isAlreadyCalcu) { 49 zoomTrans = CalcuZoomTrans(node, {x, y, scale, 0, 0}); 50 zoomInfo_.scale *= scale; 51 Rect rect = node->GetWindowRect(); 52 zoomInfo_.pivotX = rect.posX_ + zoomTrans.pivotX_ * rect.width_; 53 zoomInfo_.pivotY = rect.posY_ + zoomTrans.pivotY_ * rect.height_; 54 zoomInfo_.translateX = zoomTrans.translateX_; 55 zoomInfo_.translateY = zoomTrans.translateY_; 56 isAlreadyCalcu = true; 57 } else { 58 zoomTrans = CalcuZoomTransByZoomInfo(node); 59 } 60 UpdateClientAndSurfaceZoomInfo(node, zoomTrans); 61 } 62 } 63 SetAnchorOffset(int32_t deltaX,int32_t deltaY)64 void DisplayZoomController::SetAnchorOffset(int32_t deltaX, int32_t deltaY) 65 { 66 WLOGFD("DisplayZoom: SetAnchorOffset"); 67 DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId(); 68 sptr<WindowNodeContainer> windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); 69 if (windowNodeContainer == nullptr) { 70 return; 71 } 72 if (!UpdateZoomTranslateInfo(windowNodeContainer, displayId, deltaX, deltaY)) { 73 return; 74 } 75 WindowNodeOperationFunc translateFunc = [this, deltaX, deltaY](sptr<WindowNode> node) { 76 if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) != 77 displayZoomWindowTypeSkipped_.end()) { 78 return false; 79 } 80 Transform zoomTrans = node->GetZoomTransform(); 81 zoomTrans.translateX_ += static_cast<float>(deltaX); 82 zoomTrans.translateY_ += static_cast<float>(deltaY); 83 UpdateClientAndSurfaceZoomInfo(node, zoomTrans); 84 return false; 85 }; 86 windowNodeContainer->TraverseWindowTree(translateFunc, false); 87 } 88 OffWindowZoom()89 void DisplayZoomController::OffWindowZoom() 90 { 91 WLOGFD("DisplayZoom: Off"); 92 DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId(); 93 sptr<WindowNodeContainer> windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); 94 if (windowNodeContainer == nullptr) { 95 return; 96 } 97 zoomInfo_ = {0, 0, 1.0, 0, 0}; 98 std::vector<sptr<WindowNode>> windowNodes; 99 windowNodeContainer->TraverseContainer(windowNodes); 100 for (auto& node : windowNodes) { 101 if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) != 102 displayZoomWindowTypeSkipped_.end()) { 103 continue; 104 } 105 ClearZoomTransformInner(node); 106 } 107 } 108 UpdateAllWindowsZoomInfo(DisplayId displayId)109 void DisplayZoomController::UpdateAllWindowsZoomInfo(DisplayId displayId) 110 { 111 if (zoomInfo_.scale == DISPLAY_ZOOM_OFF_SCALE) { 112 return; 113 } 114 DisplayId defaultDisplayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId(); 115 if (defaultDisplayId != displayId) { 116 return; 117 } 118 sptr<WindowNodeContainer> windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId); 119 if (windowNodeContainer == nullptr) { 120 return; 121 } 122 int32_t deltaX, deltaY; 123 deltaX = deltaY = 0; 124 if (UpdateZoomTranslateInfo(windowNodeContainer, displayId, deltaX, deltaY)) { 125 WLOGFD("Change ZoomInfo translation, deltaX:%{public}d, deltaY:%{public}d", deltaX, deltaY); 126 } 127 std::vector<sptr<WindowNode>> windowNodes; 128 windowNodeContainer->TraverseContainer(windowNodes); 129 for (auto& node: windowNodes) { 130 HandleUpdateWindowZoomInfo(node); 131 } 132 } 133 UpdateWindowZoomInfo(uint32_t windowId)134 void DisplayZoomController::UpdateWindowZoomInfo(uint32_t windowId) 135 { 136 if (zoomInfo_.scale == DISPLAY_ZOOM_OFF_SCALE) { 137 return; 138 } 139 auto node = windowRoot_->GetWindowNode(windowId); 140 if (node == nullptr) { 141 return; 142 } 143 if (!node->currentVisibility_) { 144 return; 145 } 146 DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId(); 147 if (node->GetDisplayId() != displayId) { 148 return; 149 } 150 std::vector<sptr<WindowNode>> windowNodes; 151 windowNodes.push_back(node); 152 if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) { 153 windowNodes = windowRoot_->GetSplitScreenWindowNodes(node->GetDisplayId()); 154 } 155 for (auto& windowNode: windowNodes) { 156 HandleUpdateWindowZoomInfo(windowNode); 157 } 158 } 159 ClearZoomTransform(std::vector<sptr<WindowNode>> nodes)160 void DisplayZoomController::ClearZoomTransform(std::vector<sptr<WindowNode>> nodes) 161 { 162 if (zoomInfo_.scale == DISPLAY_ZOOM_OFF_SCALE) { 163 return; 164 } 165 for (auto& node: nodes) { 166 ClearZoomTransformInner(node); 167 } 168 } 169 ClearZoomTransformInner(sptr<WindowNode> node)170 void DisplayZoomController::ClearZoomTransformInner(sptr<WindowNode> node) 171 { 172 Transform recoverTrans; 173 node->UpdateZoomTransform(recoverTrans, false); 174 auto surfaceNode = node->leashWinSurfaceNode_ ? node->leashWinSurfaceNode_ : node->surfaceNode_; 175 if (!node->GetWindowProperty()->IsAnimateWindow()) { 176 TransformSurfaceNode(surfaceNode, recoverTrans); 177 } 178 } 179 UpdateZoomTranslateInfo(sptr<WindowNodeContainer> windowNodeContainer,DisplayId displayId,int32_t & deltaX,int32_t & deltaY)180 bool DisplayZoomController::UpdateZoomTranslateInfo(sptr<WindowNodeContainer> windowNodeContainer, 181 DisplayId displayId, int32_t& deltaX, int32_t& deltaY) 182 { 183 sptr<WindowNode> deskTop = windowNodeContainer->GetDeskTopWindow(); 184 if (deskTop == nullptr) { 185 WLOGFE("DisplayZoom: can't find deskTop windowNode"); 186 return false; 187 } 188 Transform zoomTrans = deskTop->GetZoomTransform(); 189 Rect originalRect = deskTop->GetWindowRect(); 190 Rect zoomRect = originalRect; 191 if (zoomTrans != Transform::Identity()) { 192 deskTop->ComputeTransform(); 193 zoomRect = WindowHelper::TransformRect(deskTop->GetWindowProperty()->GetTransformMat(), originalRect); 194 } 195 sptr<DisplayInfo> displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(displayId); 196 if (displayInfo == nullptr) { 197 WLOGFE("DisplayZoom: can't get displayInfo"); 198 return false; 199 } 200 int32_t deltaXMax = displayInfo->GetOffsetX() - zoomRect.posX_; 201 int32_t deltaXMin = displayInfo->GetOffsetX() + displayInfo->GetWidth() - zoomRect.posX_ 202 - static_cast<int32_t>(zoomRect.width_); 203 int32_t deltaYMax = displayInfo->GetOffsetY() - zoomRect.posY_; 204 int32_t deltaYMin = displayInfo->GetOffsetY() + displayInfo->GetHeight() - zoomRect.posY_ 205 - static_cast<int32_t>(zoomRect.height_); 206 deltaX = MathHelper::Clamp(deltaX, deltaXMin, deltaXMax); 207 deltaY = MathHelper::Clamp(deltaY, deltaYMin, deltaYMax); 208 if (deltaX == 0 && deltaY == 0) { 209 return false; 210 } 211 zoomInfo_.translateX += deltaX; 212 zoomInfo_.translateY += deltaY; 213 return true; 214 } 215 CalcuAnimateZoomTrans(sptr<WindowNode> node)216 Transform DisplayZoomController::CalcuAnimateZoomTrans(sptr<WindowNode> node) 217 { 218 Rect rect = node->GetWindowRect(); 219 if (rect.width_ == 0 || rect.height_ == 0) { 220 return Transform::Identity(); 221 } 222 Transform lastZoomTrans = CalcuZoomTransByZoomInfo(node); 223 TransformHelper::Vector3 lastPivotPos = { rect.posX_ + lastZoomTrans.pivotX_ * rect.width_, 224 rect.posY_ + lastZoomTrans.pivotY_ * rect.height_, 0 }; 225 TransformHelper::Matrix4 lastWorldMat = TransformHelper::CreateTranslation(-lastPivotPos) * 226 WindowHelper::ComputeWorldTransformMat4(lastZoomTrans) * 227 TransformHelper::CreateTranslation(lastPivotPos); 228 229 Transform animateTrans = node->GetWindowProperty()->GetTransform(); 230 if (animateTrans.translateZ_ != 0.f) { 231 node->GetWindowProperty()->ClearTransformZAxisOffset(animateTrans); 232 } 233 TransformHelper::Vector3 animatePivotPos = { rect.posX_ + animateTrans.pivotX_ * rect.width_, 234 rect.posY_ + animateTrans.pivotY_ * rect.height_, 0 }; 235 TransformHelper::Matrix4 animateWorldMat = TransformHelper::CreateTranslation(-animatePivotPos) * 236 WindowHelper::ComputeWorldTransformMat4(animateTrans) * 237 TransformHelper::CreateTranslation(animatePivotPos); 238 239 TransformHelper::Matrix4 finalWorldMat = animateWorldMat * lastWorldMat; 240 Transform finalZoomTrans; 241 finalZoomTrans.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_; 242 finalZoomTrans.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_; 243 TransformHelper::Vector3 scale = finalWorldMat.GetScale(); 244 TransformHelper::Vector3 translation = finalWorldMat.GetTranslation(); 245 finalZoomTrans.scaleX_ = scale.x_; 246 finalZoomTrans.scaleY_ = scale.y_; 247 finalZoomTrans.translateX_ = translation.x_; 248 finalZoomTrans.translateY_ = translation.y_; 249 finalZoomTrans.translateZ_ = translation.z_; 250 finalZoomTrans.rotationX_ = animateTrans.rotationX_; 251 finalZoomTrans.rotationY_ = animateTrans.rotationY_; 252 finalZoomTrans.rotationZ_ = animateTrans.rotationZ_; 253 254 return finalZoomTrans; 255 } 256 CalcuZoomTransByZoomInfo(sptr<WindowNode> node)257 Transform DisplayZoomController::CalcuZoomTransByZoomInfo(sptr<WindowNode> node) 258 { 259 Transform zoomTrans; 260 Rect rect = node->GetWindowRect(); 261 if (rect.width_ == 0 || rect.height_ == 0) { 262 return zoomTrans; 263 } 264 zoomTrans.pivotX_ = (zoomInfo_.pivotX - rect.posX_) * 1.0 / rect.width_; 265 zoomTrans.pivotY_ = (zoomInfo_.pivotY - rect.posY_) * 1.0 / rect.height_; 266 zoomTrans.scaleX_ = zoomTrans.scaleY_ = zoomInfo_.scale; 267 zoomTrans.translateX_ = zoomInfo_.translateX; 268 zoomTrans.translateY_ = zoomInfo_.translateY; 269 return zoomTrans; 270 } 271 CalcuZoomTrans(sptr<WindowNode> node,const DisplayZoomInfo & zoomInfo)272 Transform DisplayZoomController::CalcuZoomTrans(sptr<WindowNode> node, const DisplayZoomInfo& zoomInfo) 273 { 274 Rect rect = node->GetWindowRect(); 275 if (rect.width_ == 0 || rect.height_ == 0) { 276 return Transform::Identity(); 277 } 278 Transform lastZoomTrans = node->GetZoomTransform(); 279 TransformHelper::Vector3 lastPivotPos = { rect.posX_ + lastZoomTrans.pivotX_ * rect.width_, 280 rect.posY_ + lastZoomTrans.pivotY_ * rect.height_, 0 }; 281 TransformHelper::Matrix4 lastWorldMat = TransformHelper::CreateTranslation(-lastPivotPos) * 282 WindowHelper::ComputeWorldTransformMat4(lastZoomTrans) * 283 TransformHelper::CreateTranslation(lastPivotPos); 284 285 Transform zoomTrans; 286 zoomTrans.scaleX_ = zoomTrans.scaleY_ = zoomInfo.scale; 287 zoomTrans.translateX_ = zoomInfo.translateX; 288 zoomTrans.translateY_ = zoomInfo.translateY; 289 TransformHelper::Vector3 pivotPos = { zoomInfo.pivotX, zoomInfo.pivotY, 0 }; 290 TransformHelper::Matrix4 worldMat = TransformHelper::CreateTranslation(-pivotPos) * 291 WindowHelper::ComputeWorldTransformMat4(zoomTrans) * 292 TransformHelper::CreateTranslation(pivotPos); 293 294 TransformHelper::Matrix4 finalWorldMat = lastWorldMat * worldMat; 295 Transform finalZoomTrans; 296 finalZoomTrans.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_; 297 finalZoomTrans.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_; 298 TransformHelper::Vector3 scale = finalWorldMat.GetScale(); 299 TransformHelper::Vector3 translation = finalWorldMat.GetTranslation(); 300 finalZoomTrans.scaleX_ = scale.x_; 301 finalZoomTrans.scaleY_ = scale.y_; 302 finalZoomTrans.translateX_ = translation.x_; 303 finalZoomTrans.translateY_ = translation.y_; 304 305 return finalZoomTrans; 306 } 307 UpdateClientAndSurfaceZoomInfo(sptr<WindowNode> node,const Transform & zoomTrans)308 void DisplayZoomController::UpdateClientAndSurfaceZoomInfo(sptr<WindowNode> node, const Transform& zoomTrans) 309 { 310 node->UpdateZoomTransform(zoomTrans, true); 311 auto surfaceNode = node->leashWinSurfaceNode_ ? node->leashWinSurfaceNode_ : node->surfaceNode_; 312 if (!node->GetWindowProperty()->IsAnimateWindow()) { 313 TransformSurfaceNode(surfaceNode, zoomTrans); 314 } 315 WLOGFD("%{public}s zoomTrans, pivotX:%{public}f, pivotY:%{public}f, scaleX:%{public}f, scaleY:%{public}f" 316 ", transX:%{public}f, transY:%{public}f, transZ:%{public}f, rotateX:%{public}f, rotateY:%{public}f " 317 "rotateZ:%{public}f", node->GetWindowName().c_str(), zoomTrans.pivotX_, zoomTrans.pivotY_, zoomTrans.scaleX_, 318 zoomTrans.scaleY_, zoomTrans.translateX_, zoomTrans.translateY_, zoomTrans.translateZ_, zoomTrans.rotationX_, 319 zoomTrans.rotationY_, zoomTrans.rotationZ_); 320 } 321 HandleUpdateWindowZoomInfo(sptr<WindowNode> node)322 void DisplayZoomController::HandleUpdateWindowZoomInfo(sptr<WindowNode> node) 323 { 324 if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) != 325 displayZoomWindowTypeSkipped_.end()) { 326 return; 327 } 328 Transform zoomTrans; 329 if (node->GetWindowProperty()->IsAnimateWindow()) { 330 zoomTrans = CalcuAnimateZoomTrans(node); 331 } else { 332 zoomTrans = CalcuZoomTransByZoomInfo(node); 333 } 334 UpdateClientAndSurfaceZoomInfo(node, zoomTrans); 335 } 336 TransformSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode,const Transform & trans)337 void DisplayZoomController::TransformSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode, const Transform& trans) 338 { 339 if (surfaceNode == nullptr) { 340 return; 341 } 342 surfaceNode->SetPivotX(trans.pivotX_); 343 surfaceNode->SetPivotY(trans.pivotY_); 344 surfaceNode->SetScaleX(trans.scaleX_); 345 surfaceNode->SetScaleY(trans.scaleY_); 346 surfaceNode->SetTranslateX(trans.translateX_); 347 surfaceNode->SetTranslateY(trans.translateY_); 348 surfaceNode->SetTranslateZ(trans.translateZ_); 349 surfaceNode->SetRotationX(trans.rotationX_); 350 surfaceNode->SetRotationY(trans.rotationY_); 351 surfaceNode->SetRotation(trans.rotationZ_); 352 } 353 }