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 }