• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }