• 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 
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 }