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