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