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