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_pattern.h"
17 
18 #include "session_manager/include/scene_session_manager.h"
19 #include "start_window_option.h"
20 #include "ui/rs_surface_node.h"
21 
22 #include "adapter/ohos/entrance/mmi_event_convertor.h"
23 #include "base/utils/system_properties.h"
24 #include "core/components_ng/pattern/text/text_pattern.h"
25 #include "core/components_ng/pattern/text/text_styles.h"
26 #include "core/components_ng/image_provider/image_utils.h"
27 #include "core/components_ng/pattern/image/image_pattern.h"
28 #include "core/components_ng/pattern/window_scene/scene/window_event_process.h"
29 #include "core/components_ng/render/adapter/rosen_render_context.h"
30 #include "core/components_v2/inspector/inspector_constants.h"
31 #ifdef ATOMIC_SERVICE_ATTRIBUTION_ENABLE
32 #include "core/components_ng/pattern/window_scene/scene/atomicservice_basic_engine_plugin.h"
33 #endif
34 
35 namespace OHOS::Ace::NG {
36 namespace {
37 constexpr uint32_t COLOR_BLACK = 0xff000000;
38 constexpr uint32_t COLOR_WHITE = 0xffffffff;
39 constexpr uint32_t COLOR_TRANSLUCENT_WHITE = 0x66ffffff;
40 constexpr uint32_t COLOR_TRANSLUCENT_BLACK = 0x66000000;
41 constexpr Dimension SNAPSHOT_RADIUS = 16.0_vp;
42 
43 #ifdef ATOMIC_SERVICE_ATTRIBUTION_ENABLE
44 constexpr uint32_t ASENGINE_ATTRIBUTIONS_COUNT = 3;
45 constexpr uint32_t CIRCLE_ICON_INDEX = 1;
46 constexpr uint32_t EYELASHRING_ICON_INDEX = 2;
47 constexpr float HALF_PERCENT_TAG = 0.5f;
48 constexpr float BASE_X_OFFSET = 0.25f;
49 constexpr float BASE_Y_OFFSET = 0.4f;
50 constexpr float ROTATION_ANGLE = 360.0f;
51 constexpr uint32_t TEXT_NODE_HEIGHT = 42;
52 constexpr uint32_t TEXT_OFFSET_Y = 44;
53 constexpr uint32_t TEXT_NODE_FONT_SIZE = 16;
54 constexpr uint32_t TEXT_MAX_LINE = 2;
55 constexpr uint32_t IMAGE_NODE_SIZE = 72;
56 constexpr uint32_t ANIMATION_DURATION = 1750;
57 constexpr Dimension IMAGE_NODE_OFFSET = Dimension(-36, DimensionUnit::VP);
58 const Rosen::RSAnimationTimingCurve NODE_ANIMATION_TIMING_CURVE =
59     Rosen::RSAnimationTimingCurve::CreateCubicCurve(0.40f, 0.08f, 0.60f, 0.92f);
60 #endif
61 } // namespace
62 
63 class LifecycleListener : public Rosen::ILifecycleListener {
64 public:
LifecycleListener(const WeakPtr<WindowPattern> & windowPattern)65     explicit LifecycleListener(const WeakPtr<WindowPattern>& windowPattern) : windowPattern_(windowPattern) {}
66     virtual ~LifecycleListener() = default;
67 
OnActivation()68     void OnActivation() override
69     {
70         auto windowPattern = windowPattern_.Upgrade();
71         CHECK_NULL_VOID(windowPattern);
72         windowPattern->OnActivation();
73     }
74 
OnConnect()75     void OnConnect() override
76     {
77         auto windowPattern = windowPattern_.Upgrade();
78         CHECK_NULL_VOID(windowPattern);
79         windowPattern->OnConnect();
80     }
81 
OnForeground()82     void OnForeground() override
83     {
84         auto windowPattern = windowPattern_.Upgrade();
85         CHECK_NULL_VOID(windowPattern);
86         windowPattern->OnForeground();
87     }
88 
OnBackground()89     void OnBackground() override
90     {
91         auto windowPattern = windowPattern_.Upgrade();
92         CHECK_NULL_VOID(windowPattern);
93         windowPattern->OnBackground();
94     }
95 
OnDisconnect()96     void OnDisconnect() override
97     {
98         auto windowPattern = windowPattern_.Upgrade();
99         CHECK_NULL_VOID(windowPattern);
100         windowPattern->OnDisconnect();
101     }
102 
OnLayoutFinished()103     void OnLayoutFinished() override
104     {
105         auto windowPattern = windowPattern_.Upgrade();
106         CHECK_NULL_VOID(windowPattern);
107         windowPattern->OnLayoutFinished();
108     }
109 
OnDrawingCompleted()110     void OnDrawingCompleted() override
111     {
112         auto windowPattern = windowPattern_.Upgrade();
113         CHECK_NULL_VOID(windowPattern);
114         windowPattern->OnDrawingCompleted();
115     }
116 
OnRemoveBlank()117     void OnRemoveBlank() override
118     {
119         auto windowPattern = windowPattern_.Upgrade();
120         CHECK_NULL_VOID(windowPattern);
121         windowPattern->OnRemoveBlank();
122     }
123 
OnAppRemoveStartingWindow()124     void OnAppRemoveStartingWindow() override
125     {
126         auto windowPattern = windowPattern_.Upgrade();
127         CHECK_NULL_VOID(windowPattern);
128         windowPattern->OnAppRemoveStartingWindow();
129     }
130 
131 private:
132     WeakPtr<WindowPattern> windowPattern_;
133 };
134 
RegisterLifecycleListener()135 void WindowPattern::RegisterLifecycleListener()
136 {
137     CHECK_NULL_VOID(session_);
138     lifecycleListener_ = std::make_shared<LifecycleListener>(WeakClaim(this));
139     session_->RegisterLifecycleListener(lifecycleListener_);
140 }
141 
UnregisterLifecycleListener()142 void WindowPattern::UnregisterLifecycleListener()
143 {
144     CHECK_NULL_VOID(session_);
145     session_->UnregisterLifecycleListener(lifecycleListener_);
146 }
147 
IsMainWindow() const148 bool WindowPattern::IsMainWindow() const
149 {
150     CHECK_NULL_RETURN(session_, false);
151     return session_->GetWindowType() == Rosen::WindowType::WINDOW_TYPE_APP_MAIN_WINDOW;
152 }
153 
OnAttachToFrameNode()154 void WindowPattern::OnAttachToFrameNode()
155 {
156     CreateAppWindow();
157     auto host = GetHost();
158     CHECK_NULL_VOID(host);
159     auto state = session_->GetSessionState();
160     TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "[WMSMain]OnAttachToFrameNode id: %{public}d, node id: %{public}d, "
161         "name: %{public}s, state: %{public}u, in recents: %{public}d", session_->GetPersistentId(), host->GetId(),
162         session_->GetSessionInfo().bundleName_.c_str(), state, session_->GetShowRecent());
163     if (state == Rosen::SessionState::STATE_DISCONNECT) {
164         CHECK_EQUAL_VOID(HasStartingPage(), false);
165         if (session_->GetShowRecent() && session_->GetScenePersistence() &&
166             (session_->GetScenePersistence()->IsSnapshotExisted() ||
167             session_->GetScenePersistence()->IsSavingSnapshot())) {
168             CreateSnapshotWindow();
169             AddChild(host, snapshotWindow_, snapshotWindowName_);
170             return;
171         }
172         CreateStartingWindow();
173         AddChild(host, startingWindow_, startingWindowName_);
174         return;
175     }
176 
177     CHECK_EQUAL_VOID(CheckAndAddStartingWindowAboveLocked(), true);
178 
179     if (state == Rosen::SessionState::STATE_BACKGROUND && session_->GetScenePersistence() &&
180         session_->GetScenePersistence()->HasSnapshot()) {
181         if (!session_->GetShowRecent()) {
182             AddChild(host, appWindow_, appWindowName_, 0);
183         }
184         CreateSnapshotWindow();
185         AddChild(host, snapshotWindow_, snapshotWindowName_);
186         attachToFrameNodeFlag_ = true;
187         return;
188     }
189 
190     if (session_->GetShowRecent()) {
191         CreateStartingWindow();
192         AddChild(host, startingWindow_, startingWindowName_);
193         return;
194     }
195 
196     AddChild(host, appWindow_, appWindowName_, 0);
197     auto surfaceNode = session_->GetSurfaceNode();
198     CHECK_NULL_VOID(surfaceNode);
199     if (!surfaceNode->IsBufferAvailable()) {
200         CreateStartingWindow();
201         AddChild(host, startingWindow_, startingWindowName_);
202         surfaceNode->SetBufferAvailableCallback(callback_);
203         return;
204     }
205     attachToFrameNodeFlag_ = true;
206 }
207 
CreateBlankWindow()208 void WindowPattern::CreateBlankWindow()
209 {
210     auto host = GetHost();
211     CHECK_NULL_VOID(host);
212     ACE_SCOPED_TRACE("CreateBlankWindow[id:%d][self:%d]", session_->GetPersistentId(), host->GetId());
213     blankWindow_ = FrameNode::CreateFrameNode(
214         V2::WINDOW_SCENE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>());
215     auto layoutProperty = blankWindow_->GetLayoutProperty<LayoutProperty>();
216     layoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
217     auto backgroundColor = SystemProperties::GetColorMode() == ColorMode::DARK ? COLOR_BLACK : COLOR_WHITE;
218     blankWindow_->GetRenderContext()->UpdateBackgroundColor(Color(backgroundColor));
219 }
220 
CreateAppWindow()221 void WindowPattern::CreateAppWindow()
222 {
223     auto host = GetHost();
224     CHECK_NULL_VOID(host);
225     ACE_SCOPED_TRACE("CreateAppWindow[id:%d][self:%d]", session_->GetPersistentId(), host->GetId());
226     appWindow_ = FrameNode::CreateFrameNode(
227         V2::WINDOW_SCENE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<Pattern>());
228     appWindow_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
229     appWindow_->SetHitTestMode(HitTestMode::HTMNONE);
230     CHECK_NULL_VOID(session_);
231     auto surfaceNode = session_->GetSurfaceNode();
232     if (surfaceNode) {
233         auto context = AceType::DynamicCast<NG::RosenRenderContext>(appWindow_->GetRenderContext());
234         CHECK_NULL_VOID(context);
235         context->SetRSNode(surfaceNode);
236         surfaceNode->SetVisible(true);
237     }
238 }
239 
240 #ifdef ATOMIC_SERVICE_ATTRIBUTION_ENABLE
BuildTextNode(const std::string & appNameInfo)241 RefPtr<FrameNode> WindowPattern::BuildTextNode(const std::string& appNameInfo)
242 {
243     auto textNode = FrameNode::CreateFrameNode(
244         V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
245     CHECK_NULL_RETURN(textNode, nullptr);
246     // set size
247     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
248     CHECK_NULL_RETURN(textLayoutProperty, nullptr);
249     auto textNodeHeight = CalcLength(Dimension(TEXT_NODE_HEIGHT, DimensionUnit::VP));
250     auto textNodeWidth = CalcLength(Dimension(HALF_PERCENT_TAG, DimensionUnit::PERCENT));
251     textLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(textNodeWidth, textNodeHeight));
252     // set basic attributions
253     textLayoutProperty->UpdateContent(appNameInfo);
254     textLayoutProperty->UpdateAlignment(Alignment::TOP_CENTER);
255     textLayoutProperty->UpdateFontSize(Dimension(TEXT_NODE_FONT_SIZE, DimensionUnit::FP));
256     textLayoutProperty->UpdateFontWeight(FontWeight::MEDIUM);
257     textLayoutProperty->UpdateMaxLines(TEXT_MAX_LINE);
258     textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
259     textLayoutProperty->UpdateTextAlign(TextAlign::CENTER);
260     // set position
261     double textOffsetY = Dimension(TEXT_OFFSET_Y, DimensionUnit::VP).ConvertToPx();
262     auto basePositionX = Dimension(BASE_X_OFFSET, DimensionUnit::PERCENT);
263     auto basePositionY = Dimension(BASE_Y_OFFSET, DimensionUnit::PERCENT);
264     auto textContext = AceType::DynamicCast<RosenRenderContext>(textNode->GetRenderContext());
265     CHECK_NULL_RETURN(textContext, nullptr);
266     textContext->UpdatePosition(OffsetT<Dimension>(basePositionX, basePositionY));
267     textContext->SetTranslate(0, textOffsetY, 0);
268     textNode->MarkModifyDone();
269     return textNode;
270 }
271 
BuildAnimateNode(const std::string & base64Resource)272 RefPtr<FrameNode> WindowPattern::BuildAnimateNode(const std::string& base64Resource)
273 {
274     CHECK_NULL_RETURN(session_, nullptr);
275     const auto& sessionInfo = session_->GetSessionInfo();
276     auto testImageSource = ImageSourceInfo(
277         base64Resource, sessionInfo.bundleName_, sessionInfo.moduleName_);
278     auto animateNode = FrameNode::CreateFrameNode(
279         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
280     CHECK_NULL_RETURN(animateNode, nullptr);
281     auto animateLayoutProperty = animateNode->GetLayoutProperty<ImageLayoutProperty>();
282     CHECK_NULL_RETURN(animateLayoutProperty, nullptr);
283     animateLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
284     animateLayoutProperty->UpdateImageSourceInfo(testImageSource);
285     animateLayoutProperty->UpdateImageFit(ImageFit::FILL);
286     auto animateContext = AceType::DynamicCast<RosenRenderContext>(animateNode->GetRenderContext());
287     CHECK_NULL_RETURN(animateContext, nullptr);
288     auto animateRSNode = animateContext->GetRSNode();
289     CHECK_NULL_RETURN(animateRSNode, nullptr);
290     auto animatePaintProperty = animateNode->GetPaintProperty<ImageRenderProperty>();
291     CHECK_NULL_RETURN(animatePaintProperty, nullptr);
292     animatePaintProperty->UpdateImageInterpolation(ImageInterpolation::HIGH);
293     // set position
294     auto basePositionX = Dimension(HALF_PERCENT_TAG, DimensionUnit::PERCENT);
295     auto basePositionY = Dimension(BASE_Y_OFFSET, DimensionUnit::PERCENT);
296     animateContext->UpdatePosition(OffsetT<Dimension>(basePositionX, basePositionY));
297     animateContext->SetTranslate(IMAGE_NODE_OFFSET.ConvertToPx(), IMAGE_NODE_OFFSET.ConvertToPx(), 0);
298     // set size
299     auto animateNodeHeight = CalcLength(Dimension(IMAGE_NODE_SIZE, DimensionUnit::VP));
300     auto animateNodeWidth = CalcLength(Dimension(IMAGE_NODE_SIZE, DimensionUnit::VP));
301     animateLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(animateNodeWidth, animateNodeHeight));
302     // set animation
303     Rosen::RSAnimationTimingProtocol protocol;
304     animateContext->UpdateTransformRotate(Vector5F(0.0f, 0.0f, 1.0f, 0.0f, 0.0f));
305     protocol.SetDuration(ANIMATION_DURATION);
306     protocol.SetRepeatCount(-1);
307     Rosen::RSNode::Animate(protocol, NODE_ANIMATION_TIMING_CURVE, [animateContext] {
308         animateContext->UpdateTransformRotate(Vector5F(0.0f, 0.0f, 1.0f, ROTATION_ANGLE, 0.0f));
309     });
310     animateNode->MarkModifyDone();
311     return animateNode;
312 }
313 
BuildStaticImageNode(const std::string & base64Resource)314 RefPtr<FrameNode> WindowPattern::BuildStaticImageNode(const std::string& base64Resource)
315 {
316     CHECK_NULL_RETURN(session_, nullptr);
317     const auto& sessionInfo = session_->GetSessionInfo();
318     auto testImageSource = ImageSourceInfo(
319         base64Resource, sessionInfo.bundleName_, sessionInfo.moduleName_);
320     auto staticNode = FrameNode::CreateFrameNode(
321         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
322     CHECK_NULL_RETURN(staticNode, nullptr);
323     auto staticLayoutProperty = staticNode->GetLayoutProperty<ImageLayoutProperty>();
324     CHECK_NULL_RETURN(staticLayoutProperty, nullptr);
325     staticLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
326     staticLayoutProperty->UpdateImageSourceInfo(testImageSource);
327     staticLayoutProperty->UpdateImageFit(ImageFit::CONTAIN);
328     // set size
329     auto staticNodeHeight = CalcLength(Dimension(IMAGE_NODE_SIZE, DimensionUnit::VP));
330     auto staticNodeWidth = CalcLength(Dimension(IMAGE_NODE_SIZE, DimensionUnit::VP));
331     staticLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(staticNodeWidth, staticNodeHeight));
332     // get context and property
333     auto staticContext = AceType::DynamicCast<RosenRenderContext>(staticNode->GetRenderContext());
334     CHECK_NULL_RETURN(staticContext, nullptr);
335     auto staticPaintProperty = staticNode->GetPaintProperty<ImageRenderProperty>();
336     CHECK_NULL_RETURN(staticPaintProperty, nullptr);
337     staticPaintProperty->UpdateImageInterpolation(ImageInterpolation::HIGH);
338     // set position
339     auto basePositionX = Dimension(HALF_PERCENT_TAG, DimensionUnit::PERCENT);
340     auto basePositionY = Dimension(BASE_Y_OFFSET, DimensionUnit::PERCENT);
341     staticContext->UpdatePosition(OffsetT<Dimension>(basePositionX, basePositionY));
342     staticContext->SetTranslate(IMAGE_NODE_OFFSET.ConvertToPx(), IMAGE_NODE_OFFSET.ConvertToPx(), 0);
343     staticNode->MarkModifyDone();
344     return staticNode;
345 }
346 
CreateASStartingWindow()347 void WindowPattern::CreateASStartingWindow()
348 {
349     auto host = GetHost();
350     CHECK_NULL_VOID(host);
351     ACE_SCOPED_TRACE("CreateASStartingWindow[id:%d][self:%d]", session_->GetPersistentId(), host->GetId());
352 
353     CHECK_NULL_VOID(session_);
354     const auto& sessionInfo = session_->GetSessionInfo();
355     // get atomic service resources
356     std::string appNameInfo = "";
357     std::string eyelashRingIcon = "";
358     std::string circleIcon = "";
359 
360 #ifdef ACE_ENGINE_PLUGIN_PATH
361     std::vector<std::string> atomicServiceIconInfo = AtomicServiceBasicEnginePlugin::GetInstance().
362         getParamsFromAtomicServiceBasicEngine(sessionInfo.bundleName_);
363     if (atomicServiceIconInfo.size() >= ASENGINE_ATTRIBUTIONS_COUNT) {
364         appNameInfo = atomicServiceIconInfo[0];
365         circleIcon = atomicServiceIconInfo[CIRCLE_ICON_INDEX];
366         eyelashRingIcon = atomicServiceIconInfo[EYELASHRING_ICON_INDEX];
367     }
368     AtomicServiceBasicEnginePlugin::GetInstance().releaseData();
369 #endif // ACE_ENGINE_PLUGIN_PATH
370 
371     startingWindow_ = FrameNode::CreateFrameNode(
372         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<StackPattern>());
373     CHECK_NULL_VOID(startingWindow_);
374     auto asStartingLayoutProperty = startingWindow_->GetLayoutProperty<StackLayoutProperty>();
375     CHECK_NULL_VOID(asStartingLayoutProperty);
376     asStartingLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
377     startingWindow_->SetHitTestMode(HitTestMode::HTMNONE);
378     startingWindow_->GetRenderContext()->UpdateBackgroundColor(
379         SystemProperties::GetColorMode() == ColorMode::DARK ? Color::BLACK : Color::WHITE);
380 
381     auto staticNode = BuildStaticImageNode(circleIcon);
382     CHECK_NULL_VOID(staticNode);
383     auto animateNode = BuildAnimateNode(eyelashRingIcon);
384     CHECK_NULL_VOID(animateNode);
385     auto textNode = BuildTextNode(appNameInfo);
386     CHECK_NULL_VOID(textNode);
387 
388     startingWindow_->AddChild(staticNode);
389     startingWindow_->AddChild(animateNode);
390     startingWindow_->AddChild(textNode);
391     startingWindow_->MarkModifyDone();
392 }
393 #endif
394 
UpdateStartingWindowProperty(const Rosen::SessionInfo & sessionInfo,Color & color,ImageSourceInfo & sourceInfo)395 void WindowPattern::UpdateStartingWindowProperty(const Rosen::SessionInfo& sessionInfo,
396     Color &color, ImageSourceInfo &sourceInfo)
397 {
398     if (sessionInfo.startWindowOption == nullptr || !sessionInfo.startWindowOption->hasStartWindow) {
399         return;
400     }
401     TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "Get starting window info from session info");
402     if (!sessionInfo.startWindowOption->startWindowBackgroundColor.empty()) {
403         Color::ParseColorString(sessionInfo.startWindowOption->startWindowBackgroundColor, color);
404     }
405     if (sessionInfo.startWindowOption->startWindowIcon != nullptr) {
406         auto pixelMap = PixelMap::CreatePixelMap(&(sessionInfo.startWindowOption->startWindowIcon));
407         sourceInfo = ImageSourceInfo(pixelMap);
408     }
409 }
410 
CheckAndAddStartingWindowAboveLocked()411 bool WindowPattern::CheckAndAddStartingWindowAboveLocked()
412 {
413     CHECK_EQUAL_RETURN(
414         Rosen::SceneSessionManager::GetInstance().IsScreenLocked() && session_->UseStartingWindowAboveLocked(),
415         false, false);
416     auto host = GetHost();
417     CHECK_NULL_RETURN(host, false);
418     auto surfaceNode = session_->GetSurfaceNode();
419     CHECK_NULL_RETURN(surfaceNode, false);
420     AddChild(host, appWindow_, appWindowName_, 0);
421     CreateStartingWindow();
422     AddChild(host, startingWindow_, startingWindowName_);
423     surfaceNode->SetBufferAvailableCallback(callback_);
424     return true;
425 }
426 
CreateStartingWindow()427 void WindowPattern::CreateStartingWindow()
428 {
429     const auto& sessionInfo = session_->GetSessionInfo();
430 #ifdef ATOMIC_SERVICE_ATTRIBUTION_ENABLE
431     if (sessionInfo.isAtomicService_) {
432         CreateASStartingWindow();
433         return;
434     }
435 #endif
436 
437     auto host = GetHost();
438     CHECK_NULL_VOID(host);
439     ACE_SCOPED_TRACE("CreateStartingWindow[id:%d][self:%d]", session_->GetPersistentId(), host->GetId());
440     startingWindow_ = FrameNode::CreateFrameNode(
441         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
442     auto imageLayoutProperty = startingWindow_->GetLayoutProperty<ImageLayoutProperty>();
443     imageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
444     startingWindow_->SetHitTestMode(HitTestMode::HTMNONE);
445 
446     std::string startupPagePath;
447     auto backgroundColor = SystemProperties::GetColorMode() == ColorMode::DARK ? COLOR_BLACK : COLOR_WHITE;
448     Rosen::SceneSessionManager::GetInstance().GetStartupPage(sessionInfo, startupPagePath, backgroundColor);
449     startingWindow_->GetRenderContext()->UpdateBackgroundColor(Color(backgroundColor));
450     imageLayoutProperty->UpdateImageSourceInfo(
451         ImageSourceInfo(startupPagePath, sessionInfo.bundleName_, sessionInfo.moduleName_));
452     auto sourceInfo = ImageSourceInfo(startupPagePath, sessionInfo.bundleName_, sessionInfo.moduleName_);
453     auto color = Color(backgroundColor);
454     UpdateStartingWindowProperty(sessionInfo, color, sourceInfo);
455 
456     imageLayoutProperty->UpdateImageSourceInfo(sourceInfo);
457     startingWindow_->GetRenderContext()->UpdateBackgroundColor(color);
458     imageLayoutProperty->UpdateImageFit(ImageFit::NONE);
459     startingWindow_->MarkModifyDone();
460 }
461 
UpdateSnapshotWindowProperty()462 void WindowPattern::UpdateSnapshotWindowProperty()
463 {
464     CHECK_NULL_VOID(snapshotWindow_ && session_);
465     auto isExitSplitOnBackground = session_->IsExitSplitOnBackground();
466     if (isExitSplitOnBackground) {
467         auto imagePattern = snapshotWindow_->GetPattern<ImagePattern>();
468         auto renderContext = snapshotWindow_->GetRenderContext();
469         auto imageRenderProperty = snapshotWindow_->GetPaintProperty<ImageRenderProperty>();
470         CHECK_NULL_VOID(imagePattern && renderContext && imageRenderProperty);
471 
472         BorderRadiusProperty borderRadius;
473         borderRadius.SetRadius(SNAPSHOT_RADIUS);
474         borderRadius.multiValued = false;
475         renderContext->UpdateBorderRadius(borderRadius);
476         auto backgroundColor =
477             SystemProperties::GetColorMode() == ColorMode::DARK ? COLOR_TRANSLUCENT_BLACK : COLOR_TRANSLUCENT_WHITE;
478         renderContext->UpdateBackgroundColor(Color(backgroundColor));
479         imagePattern->SetNeedBorderRadius(true);
480         imageRenderProperty->UpdateNeedBorderRadius(true);
481     }
482     auto imageLayoutProperty = snapshotWindow_->GetLayoutProperty<ImageLayoutProperty>();
483     CHECK_NULL_VOID(imageLayoutProperty);
484     imageLayoutProperty->UpdateImageFit(isExitSplitOnBackground ? ImageFit::CONTAIN : ImageFit::COVER_TOP_LEFT);
485     snapshotWindow_->MarkModifyDone();
486 }
487 
CreateSnapshotWindow(std::optional<std::shared_ptr<Media::PixelMap>> snapshot)488 void WindowPattern::CreateSnapshotWindow(std::optional<std::shared_ptr<Media::PixelMap>> snapshot)
489 {
490     auto host = GetHost();
491     CHECK_NULL_VOID(host);
492     ACE_SCOPED_TRACE("CreateSnapshotWindow[id:%d][self:%d]", session_->GetPersistentId(), host->GetId());
493     session_->SetNeedSnapshot(false);
494     snapshotWindow_ = FrameNode::CreateFrameNode(
495         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
496     auto imageLayoutProperty = snapshotWindow_->GetLayoutProperty<ImageLayoutProperty>();
497     imageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
498     auto imagePaintProperty = snapshotWindow_->GetPaintProperty<ImageRenderProperty>();
499     imagePaintProperty->UpdateImageInterpolation(ImageInterpolation::MEDIUM);
500     snapshotWindow_->SetHitTestMode(HitTestMode::HTMNONE);
501 
502     if (snapshot) {
503         auto pixelMap = PixelMap::CreatePixelMap(&snapshot.value());
504         imageLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(pixelMap));
505         snapshotWindow_->GetPattern<ImagePattern>()->SetSyncLoad(true);
506     } else {
507         ImageSourceInfo sourceInfo;
508         auto scenePersistence = session_->GetScenePersistence();
509         CHECK_NULL_VOID(scenePersistence);
510         if (scenePersistence->IsSavingSnapshot()) {
511             auto snapshotPixelMap = session_->GetSnapshotPixelMap();
512             CHECK_NULL_VOID(snapshotPixelMap);
513             auto pixelMap = PixelMap::CreatePixelMap(&snapshotPixelMap);
514             sourceInfo = ImageSourceInfo(pixelMap);
515         } else {
516             sourceInfo = ImageSourceInfo("file://" + scenePersistence->GetSnapshotFilePath());
517         }
518         imageLayoutProperty->UpdateImageSourceInfo(sourceInfo);
519         ClearImageCache(sourceInfo);
520         auto eventHub = snapshotWindow_->GetEventHub<ImageEventHub>();
521         CHECK_NULL_VOID(eventHub);
522         eventHub->SetOnError([weakThis = WeakClaim(this)](const LoadImageFailEvent& info) {
523             auto self = weakThis.Upgrade();
524             CHECK_NULL_VOID(self && self->snapshotWindow_);
525             TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "load snapshot failed: %{public}s", info.GetErrorMessage().c_str());
526             auto backgroundColor = SystemProperties::GetColorMode() == ColorMode::DARK ? COLOR_BLACK : COLOR_WHITE;
527             self->snapshotWindow_->GetRenderContext()->UpdateBackgroundColor(Color(backgroundColor));
528             self->snapshotWindow_->MarkNeedRenderOnly();
529         });
530     }
531     UpdateSnapshotWindowProperty();
532 }
533 
ClearImageCache(const ImageSourceInfo & sourceInfo)534 void WindowPattern::ClearImageCache(const ImageSourceInfo& sourceInfo)
535 {
536     if (!Rosen::ScenePersistence::IsAstcEnabled()) {
537         auto pipelineContext = PipelineContext::GetCurrentContext();
538         CHECK_NULL_VOID(pipelineContext);
539         auto imageCache = pipelineContext->GetImageCache();
540         CHECK_NULL_VOID(imageCache);
541         auto snapshotSize = session_->GetScenePersistence()->GetSnapshotSize();
542         imageCache->ClearCacheImage(
543             ImageUtils::GenerateImageKey(sourceInfo, SizeF(snapshotSize.first, snapshotSize.second)));
544         imageCache->ClearCacheImage(
545             ImageUtils::GenerateImageKey(sourceInfo, SizeF(snapshotSize.second, snapshotSize.first)));
546         imageCache->ClearCacheImage(sourceInfo.GetKey());
547     }
548 }
549 
DispatchPointerEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)550 void WindowPattern::DispatchPointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
551 {
552     CHECK_NULL_VOID(session_);
553     CHECK_NULL_VOID(pointerEvent);
554     session_->TransferPointerEvent(pointerEvent);
555     if (pointerEvent->GetPointerAction() >= MMI::PointerEvent::POINTER_ACTION_PULL_DOWN &&
556         pointerEvent->GetPointerAction() <= MMI::PointerEvent::POINTER_ACTION_PULL_UP) {
557         auto pipeline = PipelineContext::GetCurrentContext();
558         if (pipeline) {
559             auto manager = pipeline->GetDragDropManager();
560             CHECK_NULL_VOID(manager);
561             manager->SetIsWindowConsumed(true);
562         }
563     }
564 }
565 
DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)566 void WindowPattern::DispatchKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
567 {
568     CHECK_NULL_VOID(session_);
569     CHECK_NULL_VOID(keyEvent);
570     session_->TransferKeyEvent(keyEvent);
571 }
572 
DispatchKeyEventForConsumed(const std::shared_ptr<MMI::KeyEvent> & keyEvent,bool & isConsumed)573 void WindowPattern::DispatchKeyEventForConsumed(const std::shared_ptr<MMI::KeyEvent>& keyEvent, bool& isConsumed)
574 {
575     CHECK_NULL_VOID(session_);
576     session_->TransferKeyEventForConsumed(keyEvent, isConsumed);
577 }
578 
DisPatchFocusActiveEvent(bool isFocusActive)579 void WindowPattern::DisPatchFocusActiveEvent(bool isFocusActive)
580 {
581     CHECK_NULL_VOID(session_);
582     session_->TransferFocusActiveEvent(isFocusActive);
583 }
584 
GetSession()585 sptr<Rosen::Session> WindowPattern::GetSession()
586 {
587     return session_;
588 }
589 
TransferFocusState(bool focusState)590 void WindowPattern::TransferFocusState(bool focusState)
591 {
592     CHECK_NULL_VOID(session_);
593     session_->TransferFocusStateEvent(focusState);
594 }
595 
GetHotAreas()596 std::vector<Rosen::Rect> WindowPattern::GetHotAreas()
597 {
598     if (session_ == nullptr) {
599         return std::vector<Rosen::Rect>();
600     }
601     return session_->GetTouchHotAreas();
602 }
603 
AddChild(const RefPtr<FrameNode> & host,const RefPtr<FrameNode> & child,const std::string & nodeType,int32_t index)604 void WindowPattern::AddChild(const RefPtr<FrameNode>& host, const RefPtr<FrameNode>& child,
605     const std::string& nodeType, int32_t index)
606 {
607     ACE_SCOPED_TRACE("WindowScene::AddChild[%s][self:%d]", nodeType.c_str(), host->GetId());
608     host->AddChild(child, index);
609     TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "AddChild %{public}s, %{public}d", nodeType.c_str(), host->GetId());
610 }
611 
RemoveChild(const RefPtr<FrameNode> & host,const RefPtr<FrameNode> & child,const std::string & nodeType,bool allowTransition)612 void WindowPattern::RemoveChild(const RefPtr<FrameNode>& host, const RefPtr<FrameNode>& child,
613     const std::string& nodeType, bool allowTransition)
614 {
615     ACE_SCOPED_TRACE("WindowScene::RemoveChild[%s][self:%d]", nodeType.c_str(), host->GetId());
616     host->RemoveChild(child, allowTransition);
617     TAG_LOGI(AceLogTag::ACE_WINDOW_SCENE, "RemoveChild %{public}s, %{public}d", nodeType.c_str(), host->GetId());
618 }
619 } // namespace OHOS::Ace::NG
620