1 /*
2  * Copyright (c) 2023 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 "core/components_ng/pattern/window_scene/scene/window_scene.h"
17 
18 #include "session_manager/include/scene_session_manager.h"
19 #include "transaction/rs_sync_transaction_controller.h"
20 #include "ui/rs_surface_node.h"
21 
22 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
23 #include "core/components_ng/render/adapter/rosen_render_context.h"
24 #include "core/pipeline_ng/pipeline_context.h"
25 
26 namespace OHOS::Ace::NG {
27 namespace {
28 const std::map<std::string, RefPtr<Curve>> curveMap {
29     { "default",            Curves::EASE_IN_OUT },
30     { "linear",             Curves::LINEAR      },
31     { "ease",               Curves::EASE        },
32     { "easeIn",             Curves::EASE_IN     },
33     { "easeOut",            Curves::EASE_OUT    },
34     { "easeInOut",          Curves::EASE_IN_OUT },
35 };
36 const uint32_t CLEAN_WINDOW_DELAY_TIME = 3000;
37 const uint32_t REMOVE_STARTING_WINDOW_TIMEOUT_MS = 5000;
38 const int32_t ANIMATION_DURATION = 200;
39 } // namespace
40 
WindowScene(const sptr<Rosen::Session> & session)41 WindowScene::WindowScene(const sptr<Rosen::Session>& session)
42 {
43     session_ = session;
44     boundsChangedCallback_ = [weakThis = WeakClaim(this)](const Rosen::Vector4f& bounds) {
45         auto self = weakThis.Upgrade();
46         CHECK_NULL_VOID(self);
47         self->OnBoundsChanged(bounds);
48     };
49     CHECK_NULL_VOID(IsMainWindow());
50     CHECK_NULL_VOID(session_);
51     initWindowMode_ = session_->GetWindowMode();
52     session_->SetNeedSnapshot(true);
53     RegisterLifecycleListener();
54     callback_ = [weakThis = WeakClaim(this), weakSession = wptr(session_)]() {
55         auto session = weakSession.promote();
56         CHECK_NULL_VOID(session);
57         ACE_SCOPED_TRACE("BufferAvailableCallback[id:%d]", session->GetPersistentId());
58         TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
59             "BufferAvailableCallback id:%{public}d", session->GetPersistentId());
60         if (!session->GetBufferAvailable()) {
61             session->SetBufferAvailable(true);
62             Rosen::SceneSessionManager::GetInstance().NotifyCompleteFirstFrameDrawing(session->GetPersistentId());
63         }
64         // In a locked screen scenario, the lifetime of the session is larger than the lifetime of the object self
65         auto self = weakThis.Upgrade();
66         CHECK_NULL_VOID(self);
67         if (self->startingWindow_) {
68             self->BufferAvailableCallback();
69             return;
70         }
71         CHECK_EQUAL_VOID(self->session_->IsAnco(), true);
72         if (self->snapshotWindow_) {
73             self->BufferAvailableCallbackForSnapshot();
74         }
75     };
76 }
77 
~WindowScene()78 WindowScene::~WindowScene()
79 {
80     CHECK_NULL_VOID(IsMainWindow());
81     CHECK_NULL_VOID(session_);
82     session_->SetShowRecent(false);
83     session_->SetNeedSnapshot(false);
84     UnregisterLifecycleListener();
85 }
86 
CreateLeashWindowNode()87 std::shared_ptr<Rosen::RSSurfaceNode> WindowScene::CreateLeashWindowNode()
88 {
89     auto name = session_->GetSessionInfo().bundleName_;
90     auto pos = name.find_last_of('.');
91     name = (pos == std::string::npos) ? name : name.substr(pos + 1); // skip '.'
92     Rosen::RSSurfaceNodeConfig config;
93     config.SurfaceNodeName = "WindowScene_" + name + std::to_string(session_->GetPersistentId());
94     auto surfaceNode = Rosen::RSSurfaceNode::Create(config, Rosen::RSSurfaceNodeType::LEASH_WINDOW_NODE);
95     CHECK_NULL_RETURN(surfaceNode, nullptr);
96     surfaceNode->SetLeashPersistentId(static_cast<int64_t>(session_->GetPersistentId()));
97     return surfaceNode;
98 }
99 
OnAttachToFrameNode()100 void WindowScene::OnAttachToFrameNode()
101 {
102     auto host = GetHost();
103     CHECK_NULL_VOID(host);
104     CHECK_NULL_VOID(session_);
105     auto windowName = IsMainWindow() ? session_->GetSessionInfo().bundleName_ : session_->GetWindowName();
106     ACE_SCOPED_TRACE("OnAttachToFrameNode[id:%d][self:%d][type:%d][name:%s]",
107         session_->GetPersistentId(), host->GetId(), session_->GetWindowType(), windowName.c_str());
108     session_->SetAttachState(true, initWindowMode_);
109     session_->SetUINodeId(host->GetAccessibilityId());
110     RegisterResponseRegionCallback();
111 
112     if (!IsMainWindow()) {
113         auto surfaceNode = session_->GetSurfaceNode();
114         CHECK_NULL_VOID(surfaceNode);
115         auto context = AceType::DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
116         CHECK_NULL_VOID(context);
117         context->SetRSNode(surfaceNode);
118         surfaceNode->SetBoundsChangedCallback(boundsChangedCallback_);
119         SetSubWindowBufferAvailableCallback(surfaceNode);
120         TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
121             "[WMSSystem]OnAttachToFrameNode id: %{public}d, node id: %{public}d, type: %{public}d, name: %{public}s",
122             session_->GetPersistentId(), host->GetId(), session_->GetWindowType(), session_->GetWindowName().c_str());
123         return;
124     }
125 
126     auto surfaceNode = CreateLeashWindowNode();
127     session_->SetLeashWinSurfaceNode(surfaceNode);
128     CHECK_NULL_VOID(surfaceNode);
129     auto context = AceType::DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
130     CHECK_NULL_VOID(context);
131     context->SetRSNode(surfaceNode);
132     surfaceNode->SetBoundsChangedCallback(boundsChangedCallback_);
133 
134     RegisterFocusCallback();
135     WindowPattern::OnAttachToFrameNode();
136 }
137 
OnDetachFromFrameNode(FrameNode * frameNode)138 void WindowScene::OnDetachFromFrameNode(FrameNode* frameNode)
139 {
140     CHECK_NULL_VOID(session_);
141     session_->SetUINodeId(0);
142     session_->SetAttachState(false, initWindowMode_);
143     CHECK_NULL_VOID(frameNode);
144     auto windowName = IsMainWindow() ? session_->GetSessionInfo().bundleName_ : session_->GetWindowName();
145     ACE_SCOPED_TRACE("OnDetachFromFrameNode[id:%d][self:%d][type:%d][name:%s]",
146         session_->GetPersistentId(), frameNode->GetId(), session_->GetWindowType(), windowName.c_str());
147     TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
148         "OnDetachFromFrameNode id: %{public}d, node id: %{public}d, type: %{public}d, name: %{public}s",
149         session_->GetPersistentId(), frameNode->GetId(), session_->GetWindowType(), windowName.c_str());
150 }
151 
OnMountToParentDone()152 void WindowScene::OnMountToParentDone()
153 {
154     if (snapshotWindow_) {
155         snapshotWindow_->MovePosition(-1);
156     }
157 }
158 
RegisterResponseRegionCallback()159 void WindowScene::RegisterResponseRegionCallback()
160 {
161     auto responseRegionCallback = [weakThis = WeakClaim(this), weakSession = wptr(session_)](
162         const std::vector<DimensionRect>& responseRegion) {
163         auto self = weakThis.Upgrade();
164         CHECK_NULL_VOID(self);
165         auto session = weakSession.promote();
166         CHECK_NULL_VOID(session);
167         std::vector<Rosen::Rect> hotAreas;
168         for (auto& rect : responseRegion) {
169             Rosen::Rect windowRect {
170                 .posX_ = std::round(rect.GetOffset().GetX().Value()),
171                 .posY_ = std::round(rect.GetOffset().GetY().Value()),
172                 .width_ = std::round(rect.GetWidth().Value()),
173                 .height_ = std::round(rect.GetHeight().Value()),
174             };
175             hotAreas.push_back(windowRect);
176         }
177         session->SetTouchHotAreas(hotAreas);
178     };
179     auto host = GetHost();
180     CHECK_NULL_VOID(host);
181     auto gestureHub = host->GetOrCreateGestureEventHub();
182     if (gestureHub) {
183         gestureHub->SetResponseRegionFunc(responseRegionCallback);
184     }
185 }
186 
RegisterFocusCallback()187 void WindowScene::RegisterFocusCallback()
188 {
189     CHECK_NULL_VOID(session_);
190     auto requestFocusCallback = [weakThis = WeakClaim(this), instanceId = instanceId_]() {
191         ContainerScope scope(instanceId);
192         auto pipelineContext = PipelineContext::GetCurrentContext();
193         CHECK_NULL_VOID(pipelineContext);
194         pipelineContext->PostAsyncEvent(
195             [weakThis]() {
196                 auto self = weakThis.Upgrade();
197                 CHECK_NULL_VOID(self);
198                 auto host = self->GetHost();
199                 CHECK_NULL_VOID(host);
200                 auto focusHub = host->GetFocusHub();
201                 CHECK_NULL_VOID(focusHub);
202                 focusHub->SetParentFocusable(true);
203             },
204             "ArkUIWindowSceneRequestFocus", TaskExecutor::TaskType::UI);
205     };
206     session_->SetNotifyUIRequestFocusFunc(requestFocusCallback);
207 
208     auto lostFocusCallback = [weakThis = WeakClaim(this), instanceId = instanceId_]() {
209         ContainerScope scope(instanceId);
210         auto pipelineContext = PipelineContext::GetCurrentContext();
211         CHECK_NULL_VOID(pipelineContext);
212         pipelineContext->PostAsyncEvent(
213             [weakThis]() {
214                 auto self = weakThis.Upgrade();
215                 CHECK_NULL_VOID(self);
216                 auto host = self->GetHost();
217                 CHECK_NULL_VOID(host);
218                 auto focusHub = host->GetFocusHub();
219                 CHECK_NULL_VOID(focusHub);
220                 focusHub->SetParentFocusable(false);
221             },
222             "ArkUIWindowSceneLostFocus", TaskExecutor::TaskType::UI);
223     };
224     session_->SetNotifyUILostFocusFunc(lostFocusCallback);
225 }
226 
OnBoundsChanged(const Rosen::Vector4f & bounds)227 void WindowScene::OnBoundsChanged(const Rosen::Vector4f& bounds)
228 {
229     Rosen::WSRect windowRect {
230         .posX_ = std::round(bounds.x_),
231         .posY_ = std::round(bounds.y_),
232         .width_ = std::round(bounds.z_),
233         .height_ = std::round(bounds.w_),
234     };
235     auto host = GetHost();
236     CHECK_NULL_VOID(host);
237     host->GetGeometryNode()->SetFrameSize(SizeF(windowRect.width_, windowRect.height_));
238 
239     CHECK_NULL_VOID(session_);
240     Rosen::WSRectF originBounds = {
241         .posX_ = bounds.x_,
242         .posY_ = bounds.y_,
243         .width_ = bounds.z_,
244         .height_ = bounds.w_,
245     };
246     session_->SetBounds(originBounds);
247     windowRect.posX_ = std::round(bounds.x_ + session_->GetOffsetX());
248     windowRect.posY_ = std::round(bounds.y_ + session_->GetOffsetY());
249     auto transactionController = Rosen::RSSyncTransactionController::GetInstance();
250     auto transaction = transactionController && session_->GetSessionRect() != windowRect ?
251         transactionController->GetRSTransaction() : nullptr;
252     auto ret = session_->UpdateRect(windowRect, Rosen::SizeChangeReason::UNDEFINED, "OnBoundsChanged", transaction);
253     auto sizeChangeReason = session_->GetSizeChangeReason();
254     if ((sizeChangeReason >= Rosen::SizeChangeReason::MAXIMIZE &&
255         sizeChangeReason <= Rosen::SizeChangeReason::ROTATION) ||
256         sizeChangeReason == Rosen::SizeChangeReason::RESIZE) {
257         TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "Update rect id:%{public}d, reason:%{public}u, rect:%{public}s",
258             session_->GetPersistentId(), sizeChangeReason, windowRect.ToString().c_str());
259     }
260     if (ret != Rosen::WSError::WS_OK) {
261         TAG_LOGW(AceLogTag::ACE_WINDOW_SCENE, "Update rect failed, id: %{public}d, ret: %{public}d",
262             session_->GetPersistentId(), static_cast<int32_t>(ret));
263     }
264 }
265 
BufferAvailableCallback()266 void WindowScene::BufferAvailableCallback()
267 {
268     TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
269         "BufferAvailableCallback id: %{public}d, enableRemoveStartingWindow: %{public}d, appBufferReady: %{public}d",
270         session_->GetPersistentId(), session_->GetEnableRemoveStartingWindow(), session_->GetAppBufferReady());
271     auto uiTask = [weakThis = WeakClaim(this)]() {
272         ACE_SCOPED_TRACE("WindowScene::BufferAvailableCallback");
273         auto self = weakThis.Upgrade();
274         CHECK_NULL_VOID(self);
275 
276         CHECK_NULL_VOID(self->startingWindow_);
277         auto surfaceNode = self->session_->GetSurfaceNode();
278         bool isWindowSizeEqual = self->IsWindowSizeEqual();
279         if (!isWindowSizeEqual || surfaceNode == nullptr || !surfaceNode->IsBufferAvailable()) {
280             TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
281                 "BufferAvailableCallback id: %{public}d, isWindowSizeEqual: %{public}d",
282                 self->session_->GetPersistentId(), isWindowSizeEqual);
283             return;
284         }
285         const auto& config =
286             Rosen::SceneSessionManager::GetInstance().GetWindowSceneConfig().startingWindowAnimationConfig_;
287         if (config.enabled_ && self->session_->NeedStartingWindowExitAnimation()) {
288             auto context = AceType::DynamicCast<RosenRenderContext>(self->startingWindow_->GetRenderContext());
289             CHECK_NULL_VOID(context);
290             context->SetMarkNodeGroup(true);
291             context->SetOpacity(config.opacityStart_);
292             RefPtr<Curve> curve = Curves::LINEAR;
293             auto iter = curveMap.find(config.curve_);
294             if (iter != curveMap.end()) {
295                 curve = iter->second;
296             }
297             auto effect = AceType::MakeRefPtr<ChainedOpacityEffect>(config.opacityEnd_);
298             effect->SetAnimationOption(std::make_shared<AnimationOption>(curve, config.duration_));
299             context->UpdateChainedTransition(effect);
300             AceAsyncTraceBegin(0, "StartingWindowExitAnimation");
301             context->SetTransitionUserCallback([](bool) {
302                 AceAsyncTraceEnd(0, "StartingWindowExitAnimation");
303             });
304         }
305 
306         auto host = self->GetHost();
307         CHECK_NULL_VOID(host);
308         self->RemoveChild(host, self->startingWindow_, self->startingWindowName_, true);
309         self->startingWindow_.Reset();
310         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
311         TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
312             "[WMSMain] Remove starting window finished, id: %{public}d, node id: %{public}d, name: %{public}s",
313             self->session_->GetPersistentId(), host->GetId(), self->session_->GetSessionInfo().bundleName_.c_str());
314     };
315 
316     ContainerScope scope(instanceId_);
317     auto pipelineContext = PipelineContext::GetCurrentContext();
318     CHECK_NULL_VOID(pipelineContext);
319     if (session_->GetEnableRemoveStartingWindow() && !session_->GetAppBufferReady()) {
320         auto taskExecutor = pipelineContext->GetTaskExecutor();
321         CHECK_NULL_VOID(taskExecutor);
322         removeStartingWindowTask_.Cancel();
323         removeStartingWindowTask_.Reset(uiTask);
324         taskExecutor->PostDelayedTask(removeStartingWindowTask_, TaskExecutor::TaskType::UI,
325             REMOVE_STARTING_WINDOW_TIMEOUT_MS, "ArkUIWindowSceneBufferAvailableDelayedCallback");
326     } else {
327         pipelineContext->PostAsyncEvent(
328             std::move(uiTask), "ArkUIWindowSceneBufferAvailableCallback", TaskExecutor::TaskType::UI);
329     }
330 }
331 
BufferAvailableCallbackForBlank(bool fromMainThread)332 void WindowScene::BufferAvailableCallbackForBlank(bool fromMainThread)
333 {
334     auto uiTask = [weakThis = WeakClaim(this)]() {
335         ACE_SCOPED_TRACE("WindowScene::BufferAvailableCallbackForBlank");
336         auto self = weakThis.Upgrade();
337         CHECK_NULL_VOID(self);
338 
339         CHECK_NULL_VOID(self->blankWindow_);
340         auto surfaceNode = self->session_->GetSurfaceNode();
341         if (surfaceNode) {
342             surfaceNode->SetVisible(true);
343         }
344 
345         RefPtr<Curve> curve = Curves::LINEAR;
346         auto effect = AceType::MakeRefPtr<ChainedOpacityEffect>(0);
347         effect->SetAnimationOption(std::make_shared<AnimationOption>(curve, ANIMATION_DURATION));
348         auto blankWindowContext = self->blankWindow_->GetRenderContext();
349         CHECK_NULL_VOID(blankWindowContext);
350         blankWindowContext->UpdateChainedTransition(effect);
351 
352         auto host = self->GetHost();
353         CHECK_NULL_VOID(host);
354         self->RemoveChild(host, self->blankWindow_, self->blankWindowName_, true);
355         self->blankWindow_.Reset();
356         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
357     };
358 
359     CHECK_EQUAL_RETURN(fromMainThread, true, uiTask());
360     ContainerScope scope(instanceId_);
361     auto pipelineContext = PipelineContext::GetCurrentContext();
362     CHECK_NULL_VOID(pipelineContext);
363     pipelineContext->PostAsyncEvent(
364         std::move(uiTask), "ArkUIBufferAvailableCallbackForBlank", TaskExecutor::TaskType::UI);
365 }
366 
BufferAvailableCallbackForSnapshot()367 void WindowScene::BufferAvailableCallbackForSnapshot()
368 {
369     TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
370         "BufferAvailableCallbackForSnapshot id:%{public}d", session_->GetPersistentId());
371     auto uiTask = [weakThis = WeakClaim(this)]() {
372         ACE_SCOPED_TRACE("WindowScene::BufferAvailableCallbackForSnapshot");
373         auto self = weakThis.Upgrade();
374         CHECK_NULL_VOID(self);
375 
376         CHECK_NULL_VOID(self->snapshotWindow_);
377         auto host = self->GetHost();
378         CHECK_NULL_VOID(host);
379         self->RemoveChild(host, self->snapshotWindow_, self->snapshotWindowName_);
380         self->snapshotWindow_.Reset();
381         self->session_->SetNeedSnapshot(true);
382         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
383     };
384 
385     ContainerScope scope(instanceId_);
386     auto pipelineContext = PipelineContext::GetCurrentContext();
387     CHECK_NULL_VOID(pipelineContext);
388     pipelineContext->PostAsyncEvent(
389         std::move(uiTask), "ArkUIWindowSceneBufferAvailableCallbackForSnapshot", TaskExecutor::TaskType::UI);
390 }
391 
OnActivation()392 void WindowScene::OnActivation()
393 {
394     auto uiTask = [weakThis = WeakClaim(this)]() {
395         ACE_SCOPED_TRACE("WindowScene::OnActivation");
396         auto self = weakThis.Upgrade();
397         CHECK_NULL_VOID(self);
398 
399         bool showingInRecents = self->session_->GetShowRecent();
400         self->session_->SetShowRecent(false);
401         auto host = self->GetHost();
402         CHECK_NULL_VOID(host);
403         if (self->destroyed_) {
404             self->destroyed_ = false;
405             self->RemoveChild(host, self->startingWindow_, self->startingWindowName_);
406             self->RemoveChild(host, self->appWindow_, self->appWindowName_);
407             self->RemoveChild(host, self->snapshotWindow_, self->snapshotWindowName_);
408             self->RemoveChild(host, self->blankWindow_, self->blankWindowName_);
409             self->startingWindow_.Reset();
410             self->appWindow_.Reset();
411             self->snapshotWindow_.Reset();
412             self->session_->SetNeedSnapshot(true);
413             self->blankWindow_.Reset();
414             self->OnAttachToFrameNode();
415             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
416         } else if (showingInRecents &&
417             self->session_->GetSessionState() == Rosen::SessionState::STATE_DISCONNECT && self->snapshotWindow_) {
418             self->RemoveChild(host, self->snapshotWindow_, self->snapshotWindowName_);
419             self->snapshotWindow_.Reset();
420             self->session_->SetNeedSnapshot(true);
421             self->CreateStartingWindow();
422             self->AddChild(host, self->startingWindow_, self->startingWindowName_);
423             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
424         } else if (self->startingWindow_ &&
425             self->session_->GetSessionState() != Rosen::SessionState::STATE_DISCONNECT) {
426             auto surfaceNode = self->session_->GetSurfaceNode();
427             CHECK_NULL_VOID(surfaceNode);
428             self->AddChild(host, self->appWindow_, self->appWindowName_, 0);
429             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
430             surfaceNode->SetBufferAvailableCallback(self->callback_);
431         } else if (self->snapshotWindow_) {
432             self->DisposeSnapshotAndBlankWindow();
433         }
434     };
435 
436     ContainerScope scope(instanceId_);
437     auto pipelineContext = PipelineContext::GetCurrentContext();
438     CHECK_NULL_VOID(pipelineContext);
439     pipelineContext->PostAsyncEvent(std::move(uiTask), "ArkUIWindowSceneActivation", TaskExecutor::TaskType::UI);
440 }
441 
DisposeSnapshotAndBlankWindow()442 void WindowScene::DisposeSnapshotAndBlankWindow()
443 {
444     CHECK_NULL_VOID(session_);
445     if (session_->GetBlankFlag()) {
446         return;
447     }
448     auto surfaceNode = session_->GetSurfaceNode();
449     CHECK_NULL_VOID(surfaceNode);
450     auto host = GetHost();
451     CHECK_NULL_VOID(host);
452     AddChild(host, appWindow_, appWindowName_, 0);
453     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
454     surfaceNode->SetBufferAvailableCallback(callback_);
455     CHECK_EQUAL_VOID(session_->GetSystemConfig().uiType_, "pc");
456     CHECK_EQUAL_VOID(session_->GetSystemConfig().freeMultiWindowEnable_, true);
457     CHECK_EQUAL_VOID(IsWindowSizeEqual(), true);
458     RemoveChild(host, snapshotWindow_, snapshotWindowName_);
459     snapshotWindow_.Reset();
460     session_->SetNeedSnapshot(true);
461     if (!blankWindow_) {
462         CreateBlankWindow();
463         AddChild(host, blankWindow_, blankWindowName_);
464         CleanBlankWindow();
465     }
466 }
467 
OnConnect()468 void WindowScene::OnConnect()
469 {
470     auto uiTask = [weakThis = WeakClaim(this)]() {
471         ACE_SCOPED_TRACE("WindowScene::OnConnect");
472         auto self = weakThis.Upgrade();
473         CHECK_NULL_VOID(self);
474 
475         CHECK_NULL_VOID(self->session_);
476         auto surfaceNode = self->session_->GetSurfaceNode();
477         CHECK_NULL_VOID(surfaceNode);
478 
479         CHECK_NULL_VOID(self->appWindow_);
480         auto context = AceType::DynamicCast<NG::RosenRenderContext>(self->appWindow_->GetRenderContext());
481         CHECK_NULL_VOID(context);
482         context->SetRSNode(surfaceNode);
483 
484         auto host = self->GetHost();
485         CHECK_NULL_VOID(host);
486         auto geometryNode = host->GetGeometryNode();
487         CHECK_NULL_VOID(geometryNode);
488         auto frameSize = geometryNode->GetFrameSize();
489         RectF windowRect(0, 0, frameSize.Width(), frameSize.Height());
490         context->SyncGeometryProperties(windowRect);
491 
492         self->AddChild(host, self->appWindow_, self->appWindowName_, 0);
493         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
494         TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
495             "[WMSMain] Add app window finished, id: %{public}d, node id: %{public}d, "
496             "name: %{public}s, rect: %{public}s", self->session_->GetPersistentId(), host->GetId(),
497             self->session_->GetSessionInfo().bundleName_.c_str(), windowRect.ToString().c_str());
498 
499         surfaceNode->SetBufferAvailableCallback(self->callback_);
500     };
501 
502     ContainerScope scope(instanceId_);
503     auto pipelineContext = PipelineContext::GetCurrentContext();
504     CHECK_NULL_VOID(pipelineContext);
505     pipelineContext->PostAsyncEvent(std::move(uiTask), "ArkUIWindowSceneConnect", TaskExecutor::TaskType::UI);
506 }
507 
OnDisconnect()508 void WindowScene::OnDisconnect()
509 {
510     CHECK_NULL_VOID(session_);
511     auto snapshot = session_->GetSnapshot();
512 
513     auto uiTask = [weakThis = WeakClaim(this), snapshot]() {
514         ACE_SCOPED_TRACE("WindowScene::OnDisconnect");
515         auto self = weakThis.Upgrade();
516         CHECK_NULL_VOID(self);
517         self->destroyed_ = true;
518 
519         auto host = self->GetHost();
520         CHECK_NULL_VOID(host);
521         if (!self->snapshotWindow_ && !self->startingWindow_) {
522             if (snapshot) {
523                 self->CreateSnapshotWindow(snapshot);
524                 self->AddChild(host, self->snapshotWindow_, self->snapshotWindowName_);
525             } else {
526                 self->CreateStartingWindow();
527                 self->AddChild(host, self->startingWindow_, self->startingWindowName_);
528             }
529         }
530         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
531     };
532 
533     ContainerScope scope(instanceId_);
534     auto pipelineContext = PipelineContext::GetCurrentContext();
535     CHECK_NULL_VOID(pipelineContext);
536     pipelineContext->PostAsyncEvent(std::move(uiTask), "ArkUIWindowSceneDisconnect", TaskExecutor::TaskType::UI);
537 }
538 
OnLayoutFinished()539 void WindowScene::OnLayoutFinished()
540 {
541     auto uiTask = [weakThis = WeakClaim(this)]() {
542         auto self = weakThis.Upgrade();
543         CHECK_NULL_VOID(self);
544         auto host = self->GetHost();
545         CHECK_NULL_VOID(host);
546         ACE_SCOPED_TRACE("WindowScene::OnLayoutFinished[id:%d][self:%d][enabled:%d]",
547             self->session_->GetPersistentId(), host->GetId(), self->session_->GetBufferAvailableCallbackEnable());
548         if (self->startingWindow_) {
549             self->BufferAvailableCallback();
550             return;
551         }
552         CHECK_EQUAL_VOID(self->session_->IsAnco(), true);
553         if (self->session_->GetBufferAvailableCallbackEnable()) {
554             TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "buffer available callback enable is true, no need remove blank.");
555             return;
556         }
557         CHECK_EQUAL_VOID(self->IsWindowSizeEqual(), false);
558         if (self->blankWindow_) {
559             self->BufferAvailableCallbackForBlank(true);
560         }
561     };
562 
563     ContainerScope scope(instanceId_);
564     auto pipelineContext = PipelineContext::GetCurrentContext();
565     CHECK_NULL_VOID(pipelineContext);
566     pipelineContext->PostAsyncEvent(std::move(uiTask), "ArkUIWindowSceneLayoutFinished", TaskExecutor::TaskType::UI);
567 }
568 
OnDrawingCompleted()569 void WindowScene::OnDrawingCompleted()
570 {
571     auto uiTask = [weakThis = WeakClaim(this)]() {
572         ACE_SCOPED_TRACE("WindowScene::OnDrawingCompleted");
573         auto self = weakThis.Upgrade();
574         CHECK_NULL_VOID(self);
575 
576         if (self->blankWindow_) {
577             self->BufferAvailableCallbackForBlank(true);
578             return;
579         }
580         CHECK_NULL_VOID(self->snapshotWindow_);
581         auto host = self->GetHost();
582         CHECK_NULL_VOID(host);
583         self->RemoveChild(host, self->snapshotWindow_, self->snapshotWindowName_);
584         self->snapshotWindow_.Reset();
585         self->session_->SetNeedSnapshot(true);
586         self->AddChild(host, self->appWindow_, self->appWindowName_, 0);
587         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
588     };
589 
590     ContainerScope scope(instanceId_);
591     auto pipelineContext = PipelineContext::GetCurrentContext();
592     CHECK_NULL_VOID(pipelineContext);
593     pipelineContext->PostAsyncEvent(std::move(uiTask), "ArkUIWindowSceneDrawingCompleted", TaskExecutor::TaskType::UI);
594 }
595 
OnRemoveBlank()596 void WindowScene::OnRemoveBlank()
597 {
598     auto uiTask = [weakThis = WeakClaim(this)]() {
599         auto self = weakThis.Upgrade();
600         CHECK_NULL_VOID(self);
601         if (self->blankWindow_) {
602             self->BufferAvailableCallbackForBlank(true);
603         }
604     };
605 
606     ContainerScope scope(instanceId_);
607     auto pipelineContext = PipelineContext::GetCurrentContext();
608     CHECK_NULL_VOID(pipelineContext);
609     pipelineContext->PostAsyncEvent(std::move(uiTask), "ArkUIWindowSceneRemoveBlank", TaskExecutor::TaskType::UI);
610 }
611 
OnAppRemoveStartingWindow()612 void WindowScene::OnAppRemoveStartingWindow()
613 {
614     CHECK_EQUAL_VOID(session_->GetEnableRemoveStartingWindow(), false);
615     session_->SetAppBufferReady(true);
616     BufferAvailableCallback();
617 }
618 
IsWindowSizeEqual()619 bool WindowScene::IsWindowSizeEqual()
620 {
621     auto host = GetHost();
622     CHECK_NULL_RETURN(host, false);
623     auto geometryNode = host->GetGeometryNode();
624     CHECK_NULL_RETURN(geometryNode, false);
625     auto frameSize = geometryNode->GetFrameSize();
626     ACE_SCOPED_TRACE("WindowScene::IsWindowSizeEqual[id:%d][self:%d][%s][%s]",
627         session_->GetPersistentId(), host->GetId(),
628         frameSize.ToString().c_str(), session_->GetLayoutRect().ToString().c_str());
629     if (NearEqual(frameSize.Width(), session_->GetLayoutRect().width_, 1.0f) &&
630         NearEqual(frameSize.Height(), session_->GetLayoutRect().height_, 1.0f)) {
631         return true;
632     }
633     return false;
634 }
635 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)636 bool WindowScene::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
637 {
638     CHECK_EQUAL_RETURN(IsMainWindow(), false, false);
639     CHECK_EQUAL_RETURN(attachToFrameNodeFlag_ || session_->GetBlankFlag(), false, false);
640     ACE_SCOPED_TRACE("WindowScene::OnDirtyLayoutWrapperSwap");
641     attachToFrameNodeFlag_ = false;
642     CHECK_EQUAL_RETURN(session_->GetShowRecent() && !session_->GetBlankFlag(), true, false);
643     auto surfaceNode = session_->GetSurfaceNode();
644     if (surfaceNode) {
645         surfaceNode->SetBufferAvailableCallback(callback_);
646     }
647     CHECK_EQUAL_RETURN(session_->GetSystemConfig().uiType_, "pc", false);
648     CHECK_EQUAL_RETURN(session_->GetSystemConfig().freeMultiWindowEnable_, true, false);
649     CHECK_NULL_RETURN(dirty, false);
650     auto geometryNode = dirty->GetGeometryNode();
651     CHECK_NULL_RETURN(geometryNode, false);
652     auto size = geometryNode->GetFrameSize();
653     if (NearEqual(size.Width(), session_->GetLayoutRect().width_, 1.0f) &&
654         NearEqual(size.Height(), session_->GetLayoutRect().height_, 1.0f) && !session_->GetBlankFlag()) {
655         return false;
656     }
657     session_->SetBlankFlag(false);
658     auto host = GetHost();
659     CHECK_NULL_RETURN(host, false);
660     RemoveChild(host, snapshotWindow_, snapshotWindowName_);
661     snapshotWindow_.Reset();
662     session_->SetNeedSnapshot(true);
663     RemoveChild(host, startingWindow_, startingWindowName_);
664     startingWindow_.Reset();
665     AddChild(host, appWindow_, appWindowName_, 0);
666     if (surfaceNode) {
667         surfaceNode->SetVisible(false);
668     }
669     if (!blankWindow_) {
670         CreateBlankWindow();
671         AddChild(host, blankWindow_, blankWindowName_);
672         auto blankWindowContext = blankWindow_->GetRenderContext();
673         CHECK_NULL_RETURN(blankWindowContext, false);
674         blankWindowContext->SyncGeometryProperties(RectF(0, 0, size.Width(), size.Height()));
675         blankWindow_->SetActive(true);
676         CleanBlankWindow();
677     }
678     host->RebuildRenderContextTree();
679     return false;
680 }
681 
CleanBlankWindow()682 void WindowScene::CleanBlankWindow()
683 {
684     auto context = PipelineContext::GetCurrentContext();
685     CHECK_NULL_VOID(context);
686     auto taskExecutor = context->GetTaskExecutor();
687     CHECK_NULL_VOID(taskExecutor);
688     deleteWindowTask_.Cancel();
689     deleteWindowTask_.Reset([weakThis = WeakClaim(this)]() {
690         ACE_SCOPED_TRACE("WindowScene::CleanBlankWindow");
691         auto self = weakThis.Upgrade();
692         CHECK_NULL_VOID(self);
693         auto host = self->GetHost();
694         CHECK_NULL_VOID(host);
695         if (self->blankWindow_) {
696             self->RemoveChild(host, self->blankWindow_, self->blankWindowName_);
697             self->blankWindow_.Reset();
698             self->AddChild(host, self->appWindow_, self->appWindowName_, 0);
699             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
700             auto surfaceNode = self->session_->GetSurfaceNode();
701             CHECK_NULL_VOID(surfaceNode);
702             surfaceNode->SetVisible(true);
703         }
704     });
705     taskExecutor->PostDelayedTask(
706         deleteWindowTask_, TaskExecutor::TaskType::UI, CLEAN_WINDOW_DELAY_TIME, "ArkUICleanBlankWindow");
707 }
708 
SetSubWindowBufferAvailableCallback(const std::shared_ptr<Rosen::RSSurfaceNode> & surfaceNode)709 void WindowScene::SetSubWindowBufferAvailableCallback(const std::shared_ptr<Rosen::RSSurfaceNode>& surfaceNode)
710 {
711     CHECK_NULL_VOID(surfaceNode);
712     auto subWindowCallback = [weakSession = wptr(session_), weakThis = WeakClaim(this)]() {
713         auto self = weakThis.Upgrade();
714         CHECK_NULL_VOID(self);
715         auto host = self->GetHost();
716         CHECK_NULL_VOID(host);
717         auto session = weakSession.promote();
718         CHECK_NULL_VOID(session);
719         TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE,
720             "subWindowBufferAvailable id: %{public}d, node id: %{public}d, type: %{public}d, name: %{public}s",
721             session->GetPersistentId(), host->GetId(), session->GetWindowType(), session->GetWindowName().c_str());
722         session->SetBufferAvailable(true);
723     };
724     surfaceNode->SetBufferAvailableCallback(subWindowCallback);
725 }
726 
GetWindowPatternType() const727 uint32_t WindowScene::GetWindowPatternType() const
728 {
729     return static_cast<uint32_t>(WindowPatternType::WINDOW_SCENE);
730 }
731 } // namespace OHOS::Ace::NG
732