• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 "base/subwindow/subwindow_manager.h"
17 
18 #include "core/pipeline_ng/pipeline_context.h"
19 #include "core/components/select/select_theme.h"
20 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
21 
22 namespace OHOS::Ace {
23 namespace {
24 constexpr uint64_t DEFAULT_DISPLAY_ID = 0;
25 constexpr uint64_t VIRTUAL_DISPLAY_ID = 999;
26 constexpr int32_t TIPS_TIME_MAX = 4000; // ms
27 } // namespace
28 std::mutex SubwindowManager::instanceMutex_;
29 std::shared_ptr<SubwindowManager> SubwindowManager::instance_;
30 thread_local RefPtr<Subwindow> SubwindowManager::currentSubwindow_;
31 const std::unordered_set<SubwindowType> NORMAL_SUBWINDOW_TYPE = { SubwindowType::TYPE_MENU,
32     SubwindowType::TYPE_DIALOG, SubwindowType::TYPE_POPUP };
33 
GetInstance()34 std::shared_ptr<SubwindowManager> SubwindowManager::GetInstance()
35 {
36     std::lock_guard<std::mutex> lock(instanceMutex_);
37     if (!instance_) {
38         instance_ = std::make_shared<SubwindowManager>();
39         if (instance_) {
40             instance_->isSuperFoldDisplayDevice_ = SystemProperties::IsSuperFoldDisplayDevice();
41         }
42     }
43     return instance_;
44 }
45 
AddContainerId(uint32_t windowId,int32_t containerId)46 void SubwindowManager::AddContainerId(uint32_t windowId, int32_t containerId)
47 {
48     std::lock_guard<std::mutex> lock(mutex_);
49     auto result = containerMap_.find(windowId);
50     if (result != containerMap_.end()) {
51         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Already have container of this windowId, windowId: %{public}u", windowId);
52     }
53     containerMap_.emplace(windowId, containerId);
54 }
55 
RemoveContainerId(uint32_t windowId)56 void SubwindowManager::RemoveContainerId(uint32_t windowId)
57 {
58     std::lock_guard<std::mutex> lock(mutex_);
59     containerMap_.erase(windowId);
60 }
61 
GetContainerId(uint32_t windowId)62 int32_t SubwindowManager::GetContainerId(uint32_t windowId)
63 {
64     std::lock_guard<std::mutex> lock(mutex_);
65     auto result = containerMap_.find(windowId);
66     if (result != containerMap_.end()) {
67         return result->second;
68     } else {
69         return -1;
70     }
71 }
72 
AddParentContainerId(int32_t containerId,int32_t parentContainerId)73 void SubwindowManager::AddParentContainerId(int32_t containerId, int32_t parentContainerId)
74 {
75     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "Container id is %{public}d, parent id is %{public}d.", containerId,
76         parentContainerId);
77     std::lock_guard<std::mutex> lock(parentMutex_);
78     parentContainerMap_.try_emplace(containerId, parentContainerId);
79 }
80 
RemoveParentContainerId(int32_t containerId)81 void SubwindowManager::RemoveParentContainerId(int32_t containerId)
82 {
83     std::lock_guard<std::mutex> lock(parentMutex_);
84     parentContainerMap_.erase(containerId);
85 }
86 
GetParentContainerId(int32_t containerId)87 int32_t SubwindowManager::GetParentContainerId(int32_t containerId)
88 {
89     std::lock_guard<std::mutex> lock(parentMutex_);
90     auto result = parentContainerMap_.find(containerId);
91     if (result != parentContainerMap_.end()) {
92         return result->second;
93     } else {
94         return -1;
95     }
96 }
97 
GetSubContainerId(int32_t parentContainerId)98 int32_t SubwindowManager::GetSubContainerId(int32_t parentContainerId)
99 {
100     std::lock_guard<std::mutex> lock(parentMutex_);
101     for (auto it = parentContainerMap_.begin(); it != parentContainerMap_.end(); it++) {
102         if (it->second == parentContainerId) {
103             return it->first;
104         }
105     }
106     return -1;
107 }
108 
GetAllSubContainerId(int32_t parentContainerId)109 const std::vector<int32_t> SubwindowManager::GetAllSubContainerId(int32_t parentContainerId)
110 {
111     std::lock_guard<std::mutex> lock(parentMutex_);
112     std::vector<int32_t> subContainerId;
113     subContainerId.reserve(parentContainerMap_.size());
114     for (auto it = parentContainerMap_.begin(); it != parentContainerMap_.end(); it++) {
115         if (it->second == parentContainerId) {
116             subContainerId.push_back(it->first);
117         }
118     }
119 
120     return subContainerId;
121 }
122 
AddInstanceSubwindowMap(int32_t subInstanceId,RefPtr<Subwindow> subwindow)123 void SubwindowManager::AddInstanceSubwindowMap(int32_t subInstanceId, RefPtr<Subwindow> subwindow)
124 {
125     if (!subwindow) {
126         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "add instance subwindow map failed.");
127         return;
128     }
129 
130     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW,
131         "add subwindow into map, subInstanceId is %{public}d, subwindow id is %{public}d.", subInstanceId,
132         subwindow->GetSubwindowId());
133 
134     std::lock_guard<std::mutex> lock(instanceSubwindowMutex_);
135     auto result = instanceSubwindowMap_.try_emplace(subInstanceId, subwindow);
136     if (!result.second) {
137         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "add failed of this subInstance %{public}d", subInstanceId);
138         return;
139     }
140 }
141 
OnDestroyContainer(int32_t subInstanceId)142 void SubwindowManager::OnDestroyContainer(int32_t subInstanceId)
143 {
144     if (subInstanceId < MIN_SUBCONTAINER_ID) {
145         return;
146     }
147 
148     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "remove subwindow from map, subInstanceId is %{public}d", subInstanceId);
149     RemoveParentContainerId(subInstanceId);
150     std::lock_guard<std::mutex> lock(instanceSubwindowMutex_);
151     instanceSubwindowMap_.erase(subInstanceId);
152 }
153 
AddSubwindow(int32_t instanceId,RefPtr<Subwindow> subwindow)154 void SubwindowManager::AddSubwindow(int32_t instanceId, RefPtr<Subwindow> subwindow)
155 {
156     AddSubwindow(instanceId, SubwindowType::TYPE_DIALOG, subwindow);
157 }
158 
AddToastSubwindow(int32_t instanceId,RefPtr<Subwindow> subwindow)159 void SubwindowManager::AddToastSubwindow(int32_t instanceId, RefPtr<Subwindow> subwindow)
160 {
161     AddSubwindow(instanceId, SubwindowType::TYPE_TOP_MOST_TOAST, subwindow);
162 }
163 
AddSystemToastWindow(int32_t instanceId,RefPtr<Subwindow> subwindow)164 void SubwindowManager::AddSystemToastWindow(int32_t instanceId, RefPtr<Subwindow> subwindow)
165 {
166     AddSubwindow(instanceId, SubwindowType::TYPE_SYSTEM_TOP_MOST_TOAST, subwindow);
167 }
168 
DeleteHotAreas(int32_t instanceId,int32_t nodeId,SubwindowType type)169 void SubwindowManager::DeleteHotAreas(int32_t instanceId, int32_t nodeId, SubwindowType type)
170 {
171     RefPtr<Subwindow> subwindow;
172     if (instanceId != -1) {
173         // get the subwindow which overlay node in, not current
174         subwindow = GetSubwindowByType(instanceId, type);
175     } else {
176         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Fail to get the subwindow which overlay node in, so get the current one.");
177         subwindow = GetCurrentWindow();
178     }
179     if (subwindow) {
180         subwindow->DeleteHotAreas(nodeId);
181     }
182 }
183 
RemoveSubwindow(int32_t instanceId,SubwindowType windowType)184 void SubwindowManager::RemoveSubwindow(int32_t instanceId, SubwindowType windowType)
185 {
186     SubwindowKey searchKey = GetCurrentSubwindowKey(instanceId, windowType);
187     std::lock_guard<std::mutex> lock(subwindowMutex_);
188     subwindowMap_.erase(searchKey);
189 }
190 
GetSubwindow(int32_t instanceId)191 const RefPtr<Subwindow> SubwindowManager::GetSubwindow(int32_t instanceId)
192 {
193     return GetSubwindowByType(instanceId, SubwindowType::TYPE_DIALOG);
194 }
195 
GetSubwindowById(int32_t subinstanceId)196 const RefPtr<Subwindow> SubwindowManager::GetSubwindowById(int32_t subinstanceId)
197 {
198     std::lock_guard<std::mutex> lock(instanceSubwindowMutex_);
199     auto result = instanceSubwindowMap_.find(subinstanceId);
200     if (result != instanceSubwindowMap_.end()) {
201         return result->second;
202     }
203 
204     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "Fail to find subwindow in instanceSubwindowMap_, subinstanceId is %{public}d",
205         subinstanceId);
206     return nullptr;
207 }
208 
GetToastSubwindow(int32_t instanceId)209 const RefPtr<Subwindow> SubwindowManager::GetToastSubwindow(int32_t instanceId)
210 {
211     return GetSubwindowByType(instanceId, SubwindowType::TYPE_TOP_MOST_TOAST);
212 }
213 
GetSystemToastWindow(int32_t instanceId)214 const RefPtr<Subwindow> SubwindowManager::GetSystemToastWindow(int32_t instanceId)
215 {
216     return GetSubwindowByType(instanceId, SubwindowType::TYPE_SYSTEM_TOP_MOST_TOAST);
217 }
218 
GetDialogSubwindowInstanceId(int32_t SubwindowId)219 int32_t SubwindowManager::GetDialogSubwindowInstanceId(int32_t SubwindowId)
220 {
221     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "get dialog subwindow instanceid enter");
222     std::lock_guard<std::mutex> lock(subwindowMutex_);
223     for (auto it = subwindowMap_.begin(); it != subwindowMap_.end(); it++) {
224         if (it->second->GetSubwindowId() == SubwindowId) {
225             return (it->first).instanceId;
226         }
227     }
228     TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Fail to get parentContainerId of subwindow in subwindowMap_,"
229         "subwindowId is %{public}d.", SubwindowId);
230     return 0;
231 }
232 
SetCurrentSubwindow(const RefPtr<Subwindow> & subwindow)233 void SubwindowManager::SetCurrentSubwindow(const RefPtr<Subwindow>& subwindow)
234 {
235     currentSubwindow_ = subwindow;
236 }
237 
GetCurrentWindow()238 const RefPtr<Subwindow> SubwindowManager::GetCurrentWindow()
239 {
240     auto containerId = Container::CurrentId();
241     if (containerId >= MIN_SUBCONTAINER_ID) {
242         return SubwindowManager::GetInstance()->GetSubwindowById(containerId);
243     }
244     return currentSubwindow_;
245 }
246 
GetParentWindowRect()247 Rect SubwindowManager::GetParentWindowRect()
248 {
249     Rect rect;
250     CHECK_NULL_RETURN(currentSubwindow_, rect);
251     return currentSubwindow_->GetParentWindowRect();
252 }
253 
ShowPreviewNG(bool isStartDraggingFromSubWindow)254 RefPtr<Subwindow> SubwindowManager::ShowPreviewNG(bool isStartDraggingFromSubWindow)
255 {
256     auto containerId = Container::CurrentId();
257     auto subwindow = GetSubwindowByType(containerId, SubwindowType::TYPE_MENU);
258     if (!IsSubwindowExist(subwindow)) {
259         subwindow = Subwindow::CreateSubwindow(containerId);
260         subwindow->InitContainer();
261         CHECK_NULL_RETURN(subwindow->GetIsRosenWindowCreate(), nullptr);
262         AddSubwindow(containerId, SubwindowType::TYPE_MENU, subwindow);
263     }
264     if (!subwindow->ShowPreviewNG(isStartDraggingFromSubWindow)) {
265         return nullptr;
266     }
267     return subwindow;
268 }
269 
ShowMenuNG(const RefPtr<NG::FrameNode> & menuNode,const NG::MenuParam & menuParam,const RefPtr<NG::FrameNode> & targetNode,const NG::OffsetF & offset)270 void SubwindowManager::ShowMenuNG(const RefPtr<NG::FrameNode>& menuNode, const NG::MenuParam& menuParam,
271     const RefPtr<NG::FrameNode>& targetNode, const NG::OffsetF& offset)
272 {
273     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show menu ng enter");
274     CHECK_NULL_VOID(targetNode);
275     auto pipelineContext = targetNode->GetContext();
276     CHECK_NULL_VOID(pipelineContext);
277     auto containerId = pipelineContext->GetInstanceId();
278     if (containerId >= MIN_SUBCONTAINER_ID) {
279         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "subwindow can not show menu again");
280         return;
281     }
282     auto subwindow = GetOrCreateMenuSubWindow(containerId);
283     CHECK_NULL_VOID(subwindow);
284     subwindow->ShowMenuNG(menuNode, menuParam, targetNode, offset);
285 }
286 
ShowMenuNG(std::function<void ()> && buildFunc,std::function<void ()> && previewBuildFunc,const NG::MenuParam & menuParam,const RefPtr<NG::FrameNode> & targetNode,const NG::OffsetF & offset)287 void SubwindowManager::ShowMenuNG(std::function<void()>&& buildFunc, std::function<void()>&& previewBuildFunc,
288     const NG::MenuParam& menuParam, const RefPtr<NG::FrameNode>& targetNode, const NG::OffsetF& offset)
289 {
290     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show menu ng enter");
291     CHECK_NULL_VOID(targetNode);
292     auto pipelineContext = targetNode->GetContext();
293     CHECK_NULL_VOID(pipelineContext);
294     auto containerId = pipelineContext->GetInstanceId();
295     if (containerId >= MIN_SUBCONTAINER_ID) {
296         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "subwindow can not show menu again");
297         return;
298     }
299     auto subwindow = GetOrCreateMenuSubWindow(containerId);
300     CHECK_NULL_VOID(subwindow);
301     subwindow->ShowMenuNG(std::move(buildFunc), std::move(previewBuildFunc), menuParam, targetNode, offset);
302 }
303 
HidePreviewNG()304 void SubwindowManager::HidePreviewNG()
305 {
306     auto subwindow = GetCurrentWindow();
307     if (subwindow) {
308         subwindow->HidePreviewNG();
309     }
310 }
311 
HideMenuNG(const RefPtr<NG::FrameNode> & menu,int32_t targetId)312 void SubwindowManager::HideMenuNG(const RefPtr<NG::FrameNode>& menu, int32_t targetId)
313 {
314     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "hide menu ng enter");
315     auto subwindow =
316         SubwindowManager::GetInstance()->GetSubwindowByType(Container::CurrentId(), SubwindowType::TYPE_MENU);
317     if (subwindow) {
318         subwindow->HideMenuNG(menu, targetId);
319     }
320 }
321 
HideMenuNG(bool showPreviewAnimation,bool startDrag)322 void SubwindowManager::HideMenuNG(bool showPreviewAnimation, bool startDrag)
323 {
324     auto subwindow = SubwindowManager::GetInstance()->GetSubwindowByType(
325         Container::CurrentId(), SubwindowType::TYPE_MENU);
326     if (subwindow) {
327         TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "hide menu ng enter");
328         subwindow->HideMenuNG(showPreviewAnimation, startDrag);
329     } else {
330         TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "hide menu ng exit, window not exist");
331     }
332 }
333 
UpdateHideMenuOffsetNG(const NG::OffsetF & offset,float menuScale,bool isRedragStart,int32_t menuWrapperId)334 void SubwindowManager::UpdateHideMenuOffsetNG(
335     const NG::OffsetF& offset, float menuScale, bool isRedragStart, int32_t menuWrapperId)
336 {
337     auto subwindow =
338         SubwindowManager::GetInstance()->GetSubwindowByType(Container::CurrentId(), SubwindowType::TYPE_MENU);
339     if (subwindow) {
340         subwindow->UpdateHideMenuOffsetNG(offset, menuScale, isRedragStart, menuWrapperId);
341     }
342 }
343 
ContextMenuSwitchDragPreviewAnimation(const RefPtr<NG::FrameNode> & dragPreviewNode,const NG::OffsetF & offset)344 void SubwindowManager::ContextMenuSwitchDragPreviewAnimation(const RefPtr<NG::FrameNode>& dragPreviewNode,
345     const NG::OffsetF& offset)
346 {
347     CHECK_NULL_VOID(dragPreviewNode);
348     auto subwindow =
349         SubwindowManager::GetInstance()->GetSubwindowByType(Container::CurrentId(), SubwindowType::TYPE_MENU);
350     if (subwindow) {
351         subwindow->ContextMenuSwitchDragPreviewAnimationtNG(dragPreviewNode, offset);
352     }
353 }
354 
UpdatePreviewPosition()355 void SubwindowManager::UpdatePreviewPosition()
356 {
357     auto subwindow = GetCurrentWindow();
358     if (subwindow) {
359         subwindow->UpdatePreviewPosition();
360     }
361 }
362 
GetMenuPreviewCenter(NG::OffsetF & offset)363 bool SubwindowManager::GetMenuPreviewCenter(NG::OffsetF& offset)
364 {
365     auto subwindow =
366         SubwindowManager::GetInstance()->GetSubwindowByType(Container::CurrentId(), SubwindowType::TYPE_MENU);
367     if (subwindow) {
368         return subwindow->GetMenuPreviewCenter(offset);
369     }
370     return false;
371 }
372 
ClearMenuNG(int32_t instanceId,int32_t targetId,bool inWindow,bool showAnimation)373 void SubwindowManager::ClearMenuNG(int32_t instanceId, int32_t targetId, bool inWindow, bool showAnimation)
374 {
375     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear menu ng enter");
376     RefPtr<Subwindow> subwindow;
377     if (instanceId != -1) {
378 #ifdef OHOS_STANDARD_SYSTEM
379         // get the subwindow which overlay node in, not current
380         subwindow = GetSubwindowByType(instanceId, SubwindowType::TYPE_MENU);
381 #else
382         subwindow = GetSubwindowByType(GetParentContainerId(instanceId) != -1 ?
383             GetParentContainerId(instanceId) : instanceId, SubwindowType::TYPE_MENU);
384 #endif
385     } else {
386         subwindow = GetCurrentWindow();
387     }
388     if (subwindow) {
389         subwindow->ClearMenuNG(targetId, inWindow, showAnimation);
390     }
391 }
392 
ClearPopupInSubwindow(int32_t instanceId,bool isForceClear)393 void SubwindowManager::ClearPopupInSubwindow(int32_t instanceId, bool isForceClear)
394 {
395     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear popup in subwindow enter");
396     RefPtr<Subwindow> subwindow;
397     if (instanceId != -1) {
398         // get the subwindow which overlay node in, not current
399         subwindow = GetSubwindowByType(instanceId, SubwindowType::TYPE_POPUP);
400     } else {
401         subwindow = GetCurrentWindow();
402     }
403     if (subwindow) {
404         subwindow->ClearPopupNG(isForceClear);
405     }
406 }
407 
ClearAllMenuPopup(int32_t instanceId)408 void SubwindowManager::ClearAllMenuPopup(int32_t instanceId)
409 {
410     auto allSubcontainerId = GetAllSubContainerId(instanceId);
411     for (auto subContainerId : allSubcontainerId) {
412         auto subContainer = Container::GetContainer(subContainerId);
413         CHECK_NULL_CONTINUE(subContainer);
414         auto pipeline = AceType::DynamicCast<NG::PipelineContext>(subContainer->GetPipelineContext());
415         CHECK_NULL_CONTINUE(pipeline);
416         auto overlayManager = pipeline->GetOverlayManager();
417         CHECK_NULL_CONTINUE(overlayManager);
418         overlayManager->HideAllPopupsWithoutAnimation();
419         overlayManager->HideAllMenusWithoutAnimation(true);
420         auto subwindow = GetSubwindowById(subContainerId);
421         CHECK_NULL_CONTINUE(subwindow);
422         subwindow->HideSubWindowNG();
423     }
424 }
425 
ShowPopupNG(const RefPtr<NG::FrameNode> & targetNode,const NG::PopupInfo & popupInfo,const std::function<void (int32_t)> && onWillDismiss,bool interactiveDismiss)426 void SubwindowManager::ShowPopupNG(const RefPtr<NG::FrameNode>& targetNode, const NG::PopupInfo& popupInfo,
427     const std::function<void(int32_t)>&& onWillDismiss, bool interactiveDismiss)
428 {
429     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show popup ng enter");
430     CHECK_NULL_VOID(targetNode);
431     auto pipelineContext = targetNode->GetContext();
432     CHECK_NULL_VOID(pipelineContext);
433     auto containerId = pipelineContext->GetInstanceId();
434     if (containerId >= MIN_SUBCONTAINER_ID && !GetIsExpandDisplay()) {
435         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "subwindow can not show popup ng again");
436         return;
437     }
438 
439     auto manager = SubwindowManager::GetInstance();
440     CHECK_NULL_VOID(manager);
441     SubwindowKey searchKey = GetCurrentSubwindowKey(containerId, SubwindowType::TYPE_POPUP);
442     auto subwindow = GetSubwindowBySearchkey(containerId, searchKey);
443     if (!IsSubwindowExist(subwindow)) {
444         subwindow = Subwindow::CreateSubwindow(containerId);
445         subwindow->InitContainer();
446         CHECK_NULL_VOID(subwindow->GetIsRosenWindowCreate());
447         manager->AddSubwindowBySearchKey(searchKey, subwindow);
448     }
449     subwindow->ShowPopupNG(targetNode->GetId(), popupInfo, std::move(onWillDismiss), interactiveDismiss);
450 }
451 
HidePopupNG(int32_t targetId,int32_t instanceId)452 void SubwindowManager::HidePopupNG(int32_t targetId, int32_t instanceId)
453 {
454     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "hide popup ng enter");
455     RefPtr<Subwindow> subwindow;
456     if (instanceId != -1) {
457         // get the subwindow which overlay node in, not current
458         subwindow = GetSubwindowByType(instanceId, SubwindowType::TYPE_POPUP);
459     } else {
460         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Fail to get the subwindow which overlay node in, so get the current one.");
461         subwindow = GetCurrentWindow();
462     }
463 
464     if (subwindow) {
465         subwindow->HidePopupNG(targetId);
466     }
467 }
468 
ShowPopup(const RefPtr<Component> & newComponent,bool disableTouchEvent)469 void SubwindowManager::ShowPopup(const RefPtr<Component>& newComponent, bool disableTouchEvent)
470 {
471     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show popup enter");
472     auto containerId = Container::CurrentId();
473     if (containerId >= MIN_SUBCONTAINER_ID && !GetIsExpandDisplay()) {
474         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "subwindow can not show popup again");
475         return;
476     }
477     auto taskExecutor = Container::CurrentTaskExecutor();
478     CHECK_NULL_VOID(taskExecutor);
479     taskExecutor->PostTask(
480         [containerId, newComponentWeak = WeakPtr<Component>(newComponent), disableTouchEvent] {
481             auto manager = SubwindowManager::GetInstance();
482             CHECK_NULL_VOID(manager);
483             auto subwindow = manager->GetSubwindowByType(containerId, SubwindowType::TYPE_POPUP);
484             if (!manager->IsSubwindowExist(subwindow)) {
485                 subwindow = Subwindow::CreateSubwindow(containerId);
486                 subwindow->InitContainer();
487                 CHECK_NULL_VOID(subwindow->GetIsRosenWindowCreate());
488                 manager->AddSubwindow(containerId, SubwindowType::TYPE_POPUP, subwindow);
489             }
490             auto newComponent = newComponentWeak.Upgrade();
491             CHECK_NULL_VOID(newComponent);
492             subwindow->ShowPopup(newComponent, disableTouchEvent);
493         },
494         TaskExecutor::TaskType::PLATFORM, "ArkUISubwindowShowPopup");
495 }
496 
ShowTipsNG(const RefPtr<NG::FrameNode> & targetNode,const NG::PopupInfo & popupInfo,int32_t appearingTime,int32_t appearingTimeWithContinuousOperation)497 void SubwindowManager::ShowTipsNG(const RefPtr<NG::FrameNode>& targetNode, const NG::PopupInfo& popupInfo,
498     int32_t appearingTime, int32_t appearingTimeWithContinuousOperation)
499 {
500     CHECK_NULL_VOID(targetNode);
501     auto pipelineContext = targetNode->GetContext();
502     CHECK_NULL_VOID(pipelineContext);
503     auto containerId = pipelineContext->GetInstanceId();
504     if (containerId >= MIN_SUBCONTAINER_ID && !GetIsExpandDisplay()) {
505         return;
506     }
507     auto targetId = targetNode->GetId();
508     auto manager = SubwindowManager::GetInstance();
509     CHECK_NULL_VOID(manager);
510     SubwindowKey searchKey = GetCurrentSubwindowKey(containerId, SubwindowType::TYPE_TIPS);
511     auto subwindow = GetSubwindowBySearchkey(containerId, searchKey);
512     if (!IsSubwindowExist(subwindow)) {
513         subwindow = Subwindow::CreateSubwindow(containerId);
514         subwindow->InitContainer();
515         CHECK_NULL_VOID(subwindow->GetIsRosenWindowCreate());
516         manager->AddSubwindowBySearchKey(searchKey, subwindow);
517     }
518     auto overlayManager = subwindow->GetOverlayManager();
519     CHECK_NULL_VOID(overlayManager);
520 
521     overlayManager->UpdateTipsEnterAndLeaveInfoBool(targetId);
522     auto duration = appearingTime;
523     if (overlayManager->TipsInfoListIsEmpty(targetId)) {
524         overlayManager->UpdateTipsStatus(targetId, false);
525         duration = appearingTime;
526     } else {
527         overlayManager->UpdateTipsStatus(targetId, true);
528         overlayManager->UpdatePreviousDisappearingTime(targetId);
529         duration = appearingTimeWithContinuousOperation;
530     }
531     if (duration > TIPS_TIME_MAX) {
532         duration = TIPS_TIME_MAX;
533     }
534     overlayManager->UpdateTipsEnterAndLeaveInfo(targetId);
535     auto taskExecutor = Container::CurrentTaskExecutor();
536     CHECK_NULL_VOID(taskExecutor);
537     bool isSubwindow = true;
538     auto times = overlayManager->GetTipsEnterAndLeaveInfo(targetId);
539     taskExecutor->PostDelayedTask(
540         [subwindow, targetId, popupInfo, appearingTime, times, isSubwindow] {
541             CHECK_NULL_VOID(subwindow);
542             subwindow->ShowTipsNG(targetId, popupInfo, appearingTime, times, isSubwindow);
543         },
544         TaskExecutor::TaskType::UI, duration, "ArkUIOverlayContinuousTips");
545 }
546 
HideTipsNG(int32_t targetId,int32_t disappearingTime,int32_t instanceId)547 void SubwindowManager::HideTipsNG(int32_t targetId, int32_t disappearingTime, int32_t instanceId)
548 {
549     RefPtr<Subwindow> subwindow;
550     if (instanceId != -1) {
551         // get the subwindow which overlay node in, not current
552         subwindow = GetSubwindowByType(instanceId, SubwindowType::TYPE_TIPS);
553     } else {
554         subwindow = GetCurrentWindow();
555     }
556 
557     if (subwindow) {
558         subwindow->HideTipsNG(targetId, disappearingTime);
559     }
560 }
561 
CancelPopup(const std::string & id)562 bool SubwindowManager::CancelPopup(const std::string& id)
563 {
564     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "cancel popup enter");
565     auto subwindow =
566         SubwindowManager::GetInstance()->GetSubwindowByType(Container::CurrentId(), SubwindowType::TYPE_POPUP);
567     if (subwindow) {
568         return subwindow->CancelPopup(id);
569     }
570     return false;
571 }
572 
ShowMenu(const RefPtr<Component> & newComponent)573 void SubwindowManager::ShowMenu(const RefPtr<Component>& newComponent)
574 {
575     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show menu enter");
576     auto containerId = Container::CurrentId();
577     auto taskExecutor = Container::CurrentTaskExecutor();
578     CHECK_NULL_VOID(taskExecutor);
579     taskExecutor->PostTask(
580         [containerId, weakMenu = AceType::WeakClaim(AceType::RawPtr(newComponent))] {
581             auto manager = SubwindowManager::GetInstance();
582             CHECK_NULL_VOID(manager);
583             auto menu = weakMenu.Upgrade();
584             CHECK_NULL_VOID(menu);
585             auto subwindow = manager->GetOrCreateMenuSubWindow(containerId);
586             CHECK_NULL_VOID(subwindow);
587             subwindow->ShowMenu(menu);
588         },
589         TaskExecutor::TaskType::PLATFORM, "ArkUISubwindowShowMenu");
590 }
591 
CloseMenu()592 void SubwindowManager::CloseMenu()
593 {
594     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close menu enter");
595     auto subwindow =
596         SubwindowManager::GetInstance()->GetSubwindowByType(Container::CurrentId(), SubwindowType::TYPE_MENU);
597     if (subwindow) {
598         subwindow->CloseMenu();
599     }
600 }
601 
ClearMenu()602 void SubwindowManager::ClearMenu()
603 {
604     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear menu enter");
605     auto subwindow =
606         SubwindowManager::GetInstance()->GetSubwindowByType(Container::CurrentId(), SubwindowType::TYPE_MENU);
607     if (subwindow) {
608         subwindow->ClearMenu();
609     }
610 }
611 
SetWindowAnchorInfo(const NG::OffsetF & offset,SubwindowType type,int32_t nodeId,int32_t instanceId)612 void SubwindowManager::SetWindowAnchorInfo(
613     const NG::OffsetF& offset, SubwindowType type, int32_t nodeId, int32_t instanceId)
614 {
615     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "set windowAnchorInfo enter");
616     RefPtr<Subwindow> subwindow;
617     if (instanceId != -1) {
618         // get the subwindow which overlay node in, not current
619         subwindow = GetSubwindowByNodeId(instanceId, type, nodeId);
620     } else {
621         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Fail to get the subwindow which overlay node in, so get the current one.");
622         subwindow = GetCurrentWindow();
623     }
624 
625     if (subwindow) {
626         subwindow->SetWindowAnchorInfo(offset, type, nodeId);
627     }
628 }
629 
SetHotAreas(const std::vector<Rect> & rects,SubwindowType type,int32_t nodeId,int32_t instanceId)630 void SubwindowManager::SetHotAreas(
631     const std::vector<Rect>& rects, SubwindowType type, int32_t nodeId, int32_t instanceId)
632 {
633     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "set hot areas enter");
634     RefPtr<Subwindow> subwindow;
635     if (instanceId != -1) {
636         // get the subwindow which overlay node in, not current
637         subwindow = GetSubwindowByNodeId(instanceId, type, nodeId);
638     } else {
639         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Fail to get the subwindow which overlay node in, so get the current one.");
640         subwindow = GetCurrentWindow();
641     }
642 
643     if (subwindow) {
644         subwindow->SetHotAreas(rects, nodeId);
645     }
646 }
647 
GetSubwindowByNodeId(int32_t instanceId,SubwindowType type,int32_t nodeId)648 RefPtr<Subwindow> SubwindowManager::GetSubwindowByNodeId(int32_t instanceId,  SubwindowType type, int32_t nodeId)
649 {
650     auto subwindow = GetSubwindowByType(instanceId, type);
651     auto dialogNode = ElementRegister::GetInstance()->GetSpecificItemById<NG::FrameNode>(nodeId);
652     CHECK_NULL_RETURN(dialogNode, subwindow);
653     auto dialogPattern = dialogNode->GetPattern<NG::DialogPattern>();
654     CHECK_NULL_RETURN(dialogPattern, subwindow);
655     auto dialogProps = AceType::DynamicCast<NG::DialogLayoutProperty>(dialogNode->GetLayoutProperty());
656     CHECK_NULL_RETURN(dialogProps, subwindow);
657     if (dialogPattern->IsUIExtensionSubWindow() && dialogProps->GetIsModal().value_or(true)) {
658         return GetSubwindowByType(instanceId, type, nodeId);
659     }
660     return subwindow;
661 }
662 
ShowBindSheetNG(bool isShow,std::function<void (const std::string &)> && callback,std::function<RefPtr<NG::UINode> ()> && buildNodeFunc,std::function<RefPtr<NG::UINode> ()> && buildtitleNodeFunc,NG::SheetStyle & sheetStyle,std::function<void ()> && onAppear,std::function<void ()> && onDisappear,std::function<void ()> && shouldDismiss,std::function<void (const int32_t)> && onWillDismiss,std::function<void ()> && onWillAppear,std::function<void ()> && onWillDisappear,std::function<void (const float)> && onHeightDidChange,std::function<void (const float)> && onDetentsDidChange,std::function<void (const float)> && onWidthDidChange,std::function<void (const float)> && onTypeDidChange,std::function<void ()> && sheetSpringBack,const RefPtr<NG::FrameNode> & targetNode)663 void SubwindowManager::ShowBindSheetNG(bool isShow, std::function<void(const std::string&)>&& callback,
664     std::function<RefPtr<NG::UINode>()>&& buildNodeFunc, std::function<RefPtr<NG::UINode>()>&& buildtitleNodeFunc,
665     NG::SheetStyle& sheetStyle, std::function<void()>&& onAppear, std::function<void()>&& onDisappear,
666     std::function<void()>&& shouldDismiss, std::function<void(const int32_t)>&& onWillDismiss,
667     std::function<void()>&& onWillAppear, std::function<void()>&& onWillDisappear,
668     std::function<void(const float)>&& onHeightDidChange,
669     std::function<void(const float)>&& onDetentsDidChange,
670     std::function<void(const float)>&& onWidthDidChange,
671     std::function<void(const float)>&& onTypeDidChange,
672     std::function<void()>&& sheetSpringBack, const RefPtr<NG::FrameNode>& targetNode)
673 {
674     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show sheet ng enter");
675     auto containerId = Container::CurrentId();
676     auto subwindow = GetSubwindowByType(containerId, SubwindowType::TYPE_SHEET);
677     if (!IsSubwindowExist(subwindow)) {
678         subwindow = Subwindow::CreateSubwindow(containerId);
679         CHECK_NULL_VOID(subwindow);
680         CHECK_NULL_VOID(subwindow->CheckHostWindowStatus());
681         subwindow->InitContainer();
682         CHECK_NULL_VOID(subwindow->GetIsRosenWindowCreate());
683         AddSubwindow(containerId, SubwindowType::TYPE_SHEET, subwindow);
684     }
685     return subwindow->ShowBindSheetNG(isShow, std::move(callback), std::move(buildNodeFunc),
686         std::move(buildtitleNodeFunc), sheetStyle, std::move(onAppear), std::move(onDisappear),
687         std::move(shouldDismiss), std::move(onWillDismiss),
688         std::move(onWillAppear), std::move(onWillDisappear), std::move(onHeightDidChange),
689         std::move(onDetentsDidChange), std::move(onWidthDidChange), std::move(onTypeDidChange),
690         std::move(sheetSpringBack), targetNode);
691 }
692 
OnWindowSizeChanged(int32_t containerId,Rect windowRect,WindowSizeChangeReason reason)693 void SubwindowManager::OnWindowSizeChanged(int32_t containerId, Rect windowRect, WindowSizeChangeReason reason)
694 {
695     OnUIExtensionWindowSizeChange(containerId, windowRect, reason);
696     OnHostWindowSizeChanged(containerId, windowRect, reason);
697 }
698 
OnHostWindowSizeChanged(int32_t containerId,Rect windowRect,WindowSizeChangeReason reason)699 void SubwindowManager::OnHostWindowSizeChanged(int32_t containerId, Rect windowRect, WindowSizeChangeReason reason)
700 {
701     auto container = Container::GetContainer(containerId);
702     CHECK_NULL_VOID(container);
703     auto subContinerId = GetSubContainerId(containerId);
704     auto subContainer = Container::GetContainer(subContinerId);
705     CHECK_NULL_VOID(subContainer);
706     auto pipeline = AceType::DynamicCast<NG::PipelineContext>(subContainer->GetPipelineContext());
707     CHECK_NULL_VOID(pipeline);
708     auto overlayManager = pipeline->GetOverlayManager();
709     CHECK_NULL_VOID(overlayManager);
710     overlayManager->OnMainWindowSizeChange(subContinerId, reason);
711 }
712 
HideSheetSubWindow(int32_t containerId)713 void SubwindowManager::HideSheetSubWindow(int32_t containerId)
714 {
715     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "hide sheet subwindow enter %u", containerId);
716     auto subwindow = GetSubwindowByType(containerId, SubwindowType::TYPE_SHEET);
717     CHECK_NULL_VOID(subwindow);
718     auto overlay = subwindow->GetOverlayManager();
719     CHECK_NULL_VOID(overlay);
720     if (overlay->GetSheetMap().empty()) {
721         subwindow->HideSubWindowNG();
722         return;
723     }
724 }
725 
ShowDialogNG(const DialogProperties & dialogProps,std::function<void ()> && buildFunc)726 RefPtr<NG::FrameNode> SubwindowManager::ShowDialogNG(
727     const DialogProperties& dialogProps, std::function<void()>&& buildFunc)
728 {
729     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show dialog ng enter");
730     auto subwindow = GetOrCreateSubWindowByType(SubwindowType::TYPE_DIALOG, dialogProps.isModal);
731     CHECK_NULL_RETURN(subwindow, nullptr);
732     return subwindow->ShowDialogNG(dialogProps, std::move(buildFunc));
733 }
ShowDialogNGWithNode(const DialogProperties & dialogProps,const RefPtr<NG::UINode> & customNode)734 RefPtr<NG::FrameNode> SubwindowManager::ShowDialogNGWithNode(const DialogProperties& dialogProps,
735     const RefPtr<NG::UINode>& customNode)
736 {
737     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show dialog ng enter");
738     auto subwindow = GetOrCreateSubWindowByType(SubwindowType::TYPE_DIALOG, dialogProps.isModal);
739     CHECK_NULL_RETURN(subwindow, nullptr);
740     return subwindow->ShowDialogNGWithNode(dialogProps, customNode);
741 }
CloseDialogNG(const RefPtr<NG::FrameNode> & dialogNode)742 void SubwindowManager::CloseDialogNG(const RefPtr<NG::FrameNode>& dialogNode)
743 {
744     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close dialog ng enter");
745     CHECK_NULL_VOID(dialogNode);
746     auto containerId = Container::CurrentId();
747     auto pipeline = dialogNode->GetContextRefPtr();
748     if (pipeline) {
749         containerId = pipeline->GetInstanceId();
750     }
751     auto dialogPattern = dialogNode->GetPattern<NG::DialogPattern>();
752     CHECK_NULL_VOID(dialogPattern);
753     auto dialogProps = AceType::DynamicCast<NG::DialogLayoutProperty>(dialogNode->GetLayoutProperty());
754     CHECK_NULL_VOID(dialogProps);
755     auto nodeId =
756         dialogPattern->IsUIExtensionSubWindow() && dialogProps->GetIsModal().value_or(true) ? dialogNode->GetId() : -1;
757     auto subwindow = GetSubwindowByType(containerId, SubwindowType::TYPE_DIALOG, nodeId);
758     if (!subwindow) {
759         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get subwindow failed.");
760         return;
761     }
762     return subwindow->CloseDialogNG(dialogNode);
763 }
764 
OpenCustomDialogNG(const DialogProperties & dialogProps,std::function<void (int32_t)> && callback)765 void SubwindowManager::OpenCustomDialogNG(const DialogProperties& dialogProps, std::function<void(int32_t)>&& callback)
766 {
767     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show customDialog ng enter");
768     auto subwindow = GetOrCreateSubWindowByType(SubwindowType::TYPE_DIALOG, dialogProps.isModal);
769     CHECK_NULL_VOID(subwindow);
770     return subwindow->OpenCustomDialogNG(dialogProps, std::move(callback));
771 }
772 
CloseCustomDialogNG(int32_t dialogId)773 void SubwindowManager::CloseCustomDialogNG(int32_t dialogId)
774 {
775     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close customDialog ng enter");
776     for (auto &overlay : GetAllSubOverlayManager()) {
777         CHECK_NULL_CONTINUE(overlay);
778         if (overlay->GetDialogMap().find(dialogId) != overlay->GetDialogMap().end()) {
779             return overlay->CloseCustomDialog(dialogId);
780         }
781     }
782 }
783 
CloseCustomDialogNG(const WeakPtr<NG::UINode> & node,std::function<void (int32_t)> && callback)784 void SubwindowManager::CloseCustomDialogNG(const WeakPtr<NG::UINode>& node, std::function<void(int32_t)>&& callback)
785 {
786     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close customDialog ng enter");
787     for (auto &overlay : GetAllSubOverlayManager()) {
788         CHECK_NULL_CONTINUE(overlay);
789         overlay->CloseCustomDialog(node, std::move(callback));
790     }
791 }
792 
UpdateCustomDialogNG(const WeakPtr<NG::UINode> & node,const PromptDialogAttr & dialogAttr,std::function<void (int32_t)> && callback)793 void SubwindowManager::UpdateCustomDialogNG(
794     const WeakPtr<NG::UINode>& node, const PromptDialogAttr &dialogAttr, std::function<void(int32_t)>&& callback)
795 {
796     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "update customDialog ng enter");
797     DialogProperties dialogProperties = {
798         .autoCancel = dialogAttr.autoCancel,
799         .maskColor = dialogAttr.maskColor,
800         .isSysBlurStyle = false
801     };
802     if (dialogAttr.alignment.has_value()) {
803         dialogProperties.alignment = dialogAttr.alignment.value();
804     }
805     if (dialogAttr.offset.has_value()) {
806         dialogProperties.offset = dialogAttr.offset.value();
807     }
808     for (auto &overlay : GetAllSubOverlayManager()) {
809         if (overlay) {
810             overlay->UpdateCustomDialog(node, dialogProperties, std::move(callback));
811         }
812     }
813 }
814 
UpdateCustomDialogNGWithNode(const WeakPtr<NG::UINode> & node,const PromptDialogAttr & dialogAttr,std::function<void (int32_t)> && callback)815 void SubwindowManager::UpdateCustomDialogNGWithNode(
816     const WeakPtr<NG::UINode>& node, const PromptDialogAttr &dialogAttr, std::function<void(int32_t)>&& callback)
817 {
818     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "update customDialogWithNode ng enter");
819     DialogProperties dialogProperties = {
820         .autoCancel = dialogAttr.autoCancel,
821         .maskColor = dialogAttr.maskColor,
822         .isSysBlurStyle = false
823     };
824     if (dialogAttr.alignment.has_value()) {
825         dialogProperties.alignment = dialogAttr.alignment.value();
826     }
827     if (dialogAttr.offset.has_value()) {
828         dialogProperties.offset = dialogAttr.offset.value();
829     }
830     for (auto &overlay : GetAllSubOverlayManager()) {
831         if (overlay) {
832             overlay->UpdateCustomDialogWithNode(node, dialogProperties, std::move(callback));
833         }
834     }
835 }
836 
GetTopOrder()837 std::optional<double> SubwindowManager::GetTopOrder()
838 {
839     auto containerId = Container::CurrentIdSafelyWithCheck();
840     auto container = Container::GetContainer(containerId);
841     CHECK_NULL_RETURN(container, std::nullopt);
842     auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
843     CHECK_NULL_RETURN(context, std::nullopt);
844     auto overlayManager = context->GetOverlayManager();
845     CHECK_NULL_RETURN(overlayManager, std::nullopt);
846     return overlayManager->GetTopOrder();
847 }
848 
GetBottomOrder()849 std::optional<double> SubwindowManager::GetBottomOrder()
850 {
851     auto containerId = Container::CurrentIdSafelyWithCheck();
852     auto container = Container::GetContainer(containerId);
853     CHECK_NULL_RETURN(container, std::nullopt);
854     auto context = AceType::DynamicCast<NG::PipelineContext>(container->GetPipelineContext());
855     CHECK_NULL_RETURN(context, std::nullopt);
856     auto overlayManager = context->GetOverlayManager();
857     CHECK_NULL_RETURN(overlayManager, std::nullopt);
858     return overlayManager->GetBottomOrder();
859 }
860 
HideDialogSubWindow(int32_t instanceId)861 void SubwindowManager::HideDialogSubWindow(int32_t instanceId)
862 {
863     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "hide dialog subwindow enter");
864 #ifdef OHOS_STANDARD_SYSTEM
865     auto subwindow = GetSubwindowByType(instanceId, SubwindowType::TYPE_DIALOG);
866 #else
867     auto subwindow = GetSubwindowByType(GetParentContainerId(instanceId) != -1 ?
868         GetParentContainerId(instanceId) : instanceId, SubwindowType::TYPE_DIALOG);
869 #endif
870     CHECK_NULL_VOID(subwindow);
871     auto overlay = subwindow->GetOverlayManager();
872     CHECK_NULL_VOID(overlay);
873     if (overlay->GetDialogMap().size() == 0) {
874         subwindow->HideSubWindowNG();
875     } else {
876         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "fail to hide dialog subwindow, instanceId is %{public}d.", instanceId);
877     }
878 }
879 
AddDialogSubwindow(int32_t instanceId,const RefPtr<Subwindow> & subwindow)880 void SubwindowManager::AddDialogSubwindow(int32_t instanceId, const RefPtr<Subwindow>& subwindow)
881 {
882     if (!subwindow) {
883         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add dialog subwindow failed, the subwindow is null.");
884         return;
885     }
886     std::lock_guard<std::mutex> lock(dialogSubwindowMutex_);
887     auto result = dialogSubwindowMap_.try_emplace(instanceId, subwindow);
888     if (!result.second) {
889         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add dialog failed of this instance %{public}d", instanceId);
890         return;
891     }
892     AddInstanceSubwindowMap(subwindow->GetChildContainerId(), subwindow);
893 }
894 
GetDialogSubwindow(int32_t instanceId)895 const RefPtr<Subwindow> SubwindowManager::GetDialogSubwindow(int32_t instanceId)
896 {
897     std::lock_guard<std::mutex> lock(dialogSubwindowMutex_);
898     auto result = dialogSubwindowMap_.find(instanceId);
899     if (result != dialogSubwindowMap_.end()) {
900         return result->second;
901     } else {
902         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Fail to get subwindow in dialogSubwindowMap_, instanceId is %{public}d",
903             instanceId);
904         return nullptr;
905     }
906 }
907 
SetCurrentDialogSubwindow(const RefPtr<Subwindow> & subwindow)908 void SubwindowManager::SetCurrentDialogSubwindow(const RefPtr<Subwindow>& subwindow)
909 {
910     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "set current dialog subwindow enter");
911     std::lock_guard<std::mutex> lock(currentDialogSubwindowMutex_);
912     currentDialogSubwindow_ = subwindow;
913 }
914 
GetCurrentDialogWindow()915 const RefPtr<Subwindow>& SubwindowManager::GetCurrentDialogWindow()
916 {
917     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "get current dialog window enter");
918     std::lock_guard<std::mutex> lock(currentDialogSubwindowMutex_);
919     return currentDialogSubwindow_;
920 }
921 
GetOrCreateSubWindow(bool isDialog)922 RefPtr<Subwindow> SubwindowManager::GetOrCreateSubWindow(bool isDialog)
923 {
924     auto containerId = Container::CurrentId();
925     auto subwindow = GetDialogSubwindow(containerId);
926     if (!subwindow) {
927         subwindow = Subwindow::CreateSubwindow(containerId);
928         CHECK_NULL_RETURN(subwindow, nullptr);
929         if (isDialog) {
930             CHECK_NULL_RETURN(subwindow->CheckHostWindowStatus(), nullptr);
931         }
932         AddDialogSubwindow(containerId, subwindow);
933     }
934     return subwindow;
935 }
936 
GetOrCreateSystemSubWindow(int32_t containerId)937 RefPtr<Subwindow> SubwindowManager::GetOrCreateSystemSubWindow(int32_t containerId)
938 {
939     auto subwindow = GetSystemToastWindow(containerId);
940     if (!subwindow) {
941         subwindow = Subwindow::CreateSubwindow(containerId);
942         CHECK_NULL_RETURN(subwindow, nullptr);
943         AddSystemToastWindow(containerId, subwindow);
944     }
945     return subwindow;
946 }
947 
ShowToastNG(const NG::ToastInfo & toastInfo,std::function<void (int32_t)> && callback)948 void SubwindowManager::ShowToastNG(const NG::ToastInfo& toastInfo, std::function<void(int32_t)>&& callback)
949 {
950     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show toast ng enter");
951     auto containerId = Container::CurrentId();
952     auto windowType = GetToastWindowType(containerId);
953     auto container = Container::GetContainer(containerId);
954     CHECK_NULL_VOID(container);
955     auto windowId = container->GetWindowId();
956     // Get the parent window ID before the asynchronous operation
957     auto mainWindowId = container->GetParentMainWindowId(windowId);
958     // for ability
959     auto taskExecutor = Container::CurrentTaskExecutor();
960     CHECK_NULL_VOID(taskExecutor);
961     taskExecutor->PostTask(
962         [containerId, toastInfo, callbackParam = std::move(callback), windowType, mainWindowId] {
963             auto subwindow = SubwindowManager::GetInstance()->GetOrCreateToastWindowNG(
964                 containerId, windowType, mainWindowId);
965             CHECK_NULL_VOID(subwindow);
966             TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before show toast : %{public}d", containerId);
967             subwindow->ShowToast(toastInfo, std::move(const_cast<std::function<void(int32_t)>&&>(callbackParam)));
968         },
969         TaskExecutor::TaskType::PLATFORM, "ArkUISubwindowShowToastNG");
970 }
971 
GetToastWindowType(int32_t instanceId)972 ToastWindowType SubwindowManager::GetToastWindowType(int32_t instanceId)
973 {
974     auto parentContainer = Container::GetContainer(instanceId);
975     CHECK_NULL_RETURN(parentContainer, ToastWindowType::TOAST_IN_TYPE_TOAST);
976     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "GetToastWindowType instanceId: %{public}d", instanceId);
977     // toast window should be TOAST_IN_TYPE_APP_SUB_WINDOW when parent window is dialog window.
978     if (parentContainer->IsMainWindow() || parentContainer->IsSubWindow() ||
979         parentContainer->IsDialogWindow()) {
980         return ToastWindowType::TOAST_IN_TYPE_APP_SUB_WINDOW;
981     } else if (parentContainer->IsSceneBoardWindow()) {
982         return ToastWindowType::TOAST_IN_TYPE_SYSTEM_FLOAT;
983     } else if (parentContainer->IsSystemWindow()) {
984         return ToastWindowType::TOAST_IN_TYPE_SYSTEM_SUB_WINDOW;
985     } else if (parentContainer->IsUIExtensionWindow()) {
986         if (parentContainer->IsHostMainWindow() || parentContainer->IsHostSubWindow() ||
987             parentContainer->IsHostDialogWindow()) {
988             return ToastWindowType::TOAST_IN_TYPE_APP_SUB_WINDOW;
989         } else if (parentContainer->IsHostSceneBoardWindow()) {
990             return ToastWindowType::TOAST_IN_TYPE_SYSTEM_FLOAT;
991         } else if (parentContainer->IsHostSystemWindow()) {
992             return ToastWindowType::TOAST_IN_TYPE_SYSTEM_SUB_WINDOW;
993         }
994     }
995     return ToastWindowType::TOAST_IN_TYPE_TOAST;
996 }
997 
ShowToast(const NG::ToastInfo & toastInfo,std::function<void (int32_t)> && callback)998 void SubwindowManager::ShowToast(const NG::ToastInfo& toastInfo, std::function<void(int32_t)>&& callback)
999 {
1000     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show toast enter");
1001     auto containerId = Container::CurrentId();
1002     auto isTopMost = toastInfo.showMode == NG::ToastShowMode::TOP_MOST;
1003     // for pa service
1004     if ((isTopMost && containerId >= MIN_PA_SERVICE_ID && containerId < MIN_SUBCONTAINER_ID) ||
1005         (!isTopMost && containerId >= MIN_PA_SERVICE_ID) || containerId < 0) {
1006         auto subwindow = toastInfo.showMode == NG::ToastShowMode::SYSTEM_TOP_MOST ?
1007             GetOrCreateSystemSubWindow(containerId) : GetOrCreateSubWindow();
1008         CHECK_NULL_VOID(subwindow);
1009         subwindow->SetIsSystemTopMost(toastInfo.showMode == NG::ToastShowMode::SYSTEM_TOP_MOST);
1010         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before show toast");
1011         subwindow->ShowToast(toastInfo, std::move(callback));
1012     } else {
1013         // for ability
1014         auto parentContainer = Container::GetContainer(containerId);
1015         // in sceneboard, system_top_most needs to go the old way,
1016         // default and top_most need to go showToastNG
1017         if (toastInfo.showMode == NG::ToastShowMode::TOP_MOST ||
1018             (parentContainer && parentContainer->IsSceneBoardWindow() &&
1019             toastInfo.showMode != NG::ToastShowMode::SYSTEM_TOP_MOST)) {
1020             ShowToastNG(toastInfo, std::move(callback));
1021             return;
1022         }
1023         auto taskExecutor = Container::CurrentTaskExecutor();
1024         CHECK_NULL_VOID(taskExecutor);
1025         taskExecutor->PostTask(
1026             [containerId, toastInfo, callbackParam = std::move(callback)] {
1027                 auto manager = SubwindowManager::GetInstance();
1028                 CHECK_NULL_VOID(manager);
1029                 auto subwindow = manager->GetOrCreateToastWindow(containerId, toastInfo.showMode);
1030                 CHECK_NULL_VOID(subwindow);
1031                 TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before show toast : %{public}d", containerId);
1032                 subwindow->ShowToast(toastInfo, std::move(const_cast<std::function<void(int32_t)>&&>(callbackParam)));
1033             },
1034             TaskExecutor::TaskType::PLATFORM, "ArkUISubwindowShowToast");
1035     }
1036 }
1037 
CloseToast(const int32_t toastId,const NG::ToastShowMode & showMode,std::function<void (int32_t)> && callback)1038 void SubwindowManager::CloseToast(
1039     const int32_t toastId, const NG::ToastShowMode& showMode, std::function<void(int32_t)>&& callback)
1040 {
1041     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close toast enter");
1042     auto containerId = Container::CurrentId();
1043 
1044     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
1045         // for pa service
1046         auto subwindow = showMode == NG::ToastShowMode::SYSTEM_TOP_MOST ?
1047             GetSystemToastWindow(containerId) : GetDialogSubwindow(containerId);
1048         CHECK_NULL_VOID(subwindow);
1049         subwindow->SetIsSystemTopMost(showMode == NG::ToastShowMode::SYSTEM_TOP_MOST);
1050         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before close toast");
1051         subwindow->CloseToast(toastId, std::move(callback));
1052     } else {
1053         // for ability
1054         if (showMode == NG::ToastShowMode::TOP_MOST) {
1055             auto subwindow =
1056                 containerId < MIN_SUBCONTAINER_ID ? GetToastSubwindow(containerId) : GetSubwindow(containerId);
1057             CHECK_NULL_VOID(subwindow);
1058             subwindow->CloseToast(toastId, std::move(callback));
1059             return;
1060         }
1061         auto manager = SubwindowManager::GetInstance();
1062         CHECK_NULL_VOID(manager);
1063         auto subwindow = (showMode == NG::ToastShowMode::SYSTEM_TOP_MOST && containerId < MIN_SUBCONTAINER_ID)
1064                             ? GetSystemToastWindow(containerId)
1065                             : GetSubwindow(containerId);
1066         CHECK_NULL_VOID(subwindow);
1067         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before close toast : %{public}d", containerId);
1068         subwindow->CloseToast(toastId, std::move(callback));
1069     }
1070 }
1071 
GetOrCreateToastWindow(int32_t containerId,const NG::ToastShowMode & showMode)1072 RefPtr<Subwindow> SubwindowManager::GetOrCreateToastWindow(int32_t containerId, const NG::ToastShowMode& showMode)
1073 {
1074     auto isSystemTopMost = (showMode == NG::ToastShowMode::SYSTEM_TOP_MOST);
1075     auto subwindow = (isSystemTopMost && containerId < MIN_SUBCONTAINER_ID) ? GetSystemToastWindow(containerId)
1076                                                                             : GetSubwindow(containerId);
1077     if (!IsSubwindowExist(subwindow)) {
1078         subwindow = Subwindow::CreateSubwindow(containerId);
1079         subwindow->SetIsSystemTopMost(isSystemTopMost);
1080         subwindow->SetAboveApps(showMode == NG::ToastShowMode::TOP_MOST);
1081         subwindow->InitContainer();
1082         CHECK_NULL_RETURN(subwindow->GetIsRosenWindowCreate(), nullptr);
1083         if (isSystemTopMost) {
1084             AddSystemToastWindow(containerId, subwindow);
1085         } else {
1086             AddSubwindow(containerId, subwindow);
1087         }
1088     }
1089 
1090     return subwindow;
1091 }
1092 
GetOrCreateToastWindowNG(int32_t containerId,const ToastWindowType & windowType,uint32_t mainWindowId)1093 RefPtr<Subwindow> SubwindowManager::GetOrCreateToastWindowNG(int32_t containerId,
1094     const ToastWindowType& windowType, uint32_t mainWindowId)
1095 {
1096     RefPtr<Subwindow> subwindow = GetToastSubwindow(containerId);
1097     if (!subwindow) {
1098         subwindow = Subwindow::CreateSubwindow(containerId);
1099         if (!subwindow) {
1100             TAG_LOGE(AceLogTag::ACE_SUB_WINDOW, "create toast subwindow failed");
1101             return nullptr;
1102         }
1103         subwindow->SetToastWindowType(windowType);
1104         subwindow->SetMainWindowId(mainWindowId);
1105         subwindow->InitContainer();
1106         AddToastSubwindow(containerId, subwindow);
1107     }
1108     return subwindow;
1109 }
1110 
ClearToastInSubwindow()1111 void SubwindowManager::ClearToastInSubwindow()
1112 {
1113     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear toast in subwindow enter");
1114     auto containerId = Container::CurrentId();
1115     // Get active container when current instanceid is less than 0
1116     if (containerId < 0) {
1117         auto container = Container::GetActive();
1118         if (container) {
1119             containerId = container->GetInstanceId();
1120         }
1121     }
1122     RefPtr<Subwindow> subwindow;
1123     // The main window does not need to clear Toast
1124     if (containerId != -1 && containerId < MIN_SUBCONTAINER_ID) {
1125         // get the subwindow which overlay node in, not current
1126         subwindow = GetToastSubwindow(containerId);
1127     }
1128     if (subwindow) {
1129         subwindow->ClearToast();
1130     }
1131 }
1132 
ShowDialog(const std::string & title,const std::string & message,const std::vector<ButtonInfo> & buttons,bool autoCancel,std::function<void (int32_t,int32_t)> && napiCallback,const std::set<std::string> & dialogCallbacks)1133 void SubwindowManager::ShowDialog(const std::string& title, const std::string& message,
1134     const std::vector<ButtonInfo>& buttons, bool autoCancel, std::function<void(int32_t, int32_t)>&& napiCallback,
1135     const std::set<std::string>& dialogCallbacks)
1136 {
1137     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show dialog enter");
1138     auto containerId = Container::CurrentId();
1139     // Get active container when current instanceid is less than 0
1140     if (containerId < 0) {
1141         auto container = Container::GetActive();
1142         if (container) {
1143             containerId = container->GetInstanceId();
1144         }
1145     }
1146     // for pa service
1147     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
1148         auto subwindow = GetOrCreateSubWindow();
1149         CHECK_NULL_VOID(subwindow);
1150         subwindow->ShowDialog(title, message, buttons, autoCancel, std::move(napiCallback), dialogCallbacks);
1151         // for ability
1152     } else {
1153         auto subwindow = GetOrCreateSubWindowByType(SubwindowType::TYPE_DIALOG);
1154         CHECK_NULL_VOID(subwindow);
1155         subwindow->ShowDialog(title, message, buttons, autoCancel, std::move(napiCallback), dialogCallbacks);
1156     }
1157 }
1158 
ShowDialog(const PromptDialogAttr & dialogAttr,const std::vector<ButtonInfo> & buttons,std::function<void (int32_t,int32_t)> && napiCallback,const std::set<std::string> & dialogCallbacks)1159 void SubwindowManager::ShowDialog(const PromptDialogAttr& dialogAttr, const std::vector<ButtonInfo>& buttons,
1160     std::function<void(int32_t, int32_t)>&& napiCallback, const std::set<std::string>& dialogCallbacks)
1161 {
1162     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show dialog enter");
1163     auto containerId = Container::CurrentId();
1164     // Get active container when current instanceid is less than 0
1165     if (containerId < 0) {
1166         auto container = Container::GetActive();
1167         if (container) {
1168             containerId = container->GetInstanceId();
1169         }
1170     }
1171     // for pa service
1172     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
1173         auto subwindow = GetOrCreateSubWindow(true);
1174         CHECK_NULL_VOID(subwindow);
1175         subwindow->ShowDialog(dialogAttr, buttons, std::move(napiCallback), dialogCallbacks);
1176         // for ability
1177     } else {
1178         auto subwindow = GetOrCreateSubWindowByType(SubwindowType::TYPE_DIALOG, dialogAttr.isModal);
1179         CHECK_NULL_VOID(subwindow);
1180         subwindow->ShowDialog(dialogAttr, buttons, std::move(napiCallback), dialogCallbacks);
1181     }
1182 }
1183 
ShowActionMenu(const std::string & title,const std::vector<ButtonInfo> & button,std::function<void (int32_t,int32_t)> && callback)1184 void SubwindowManager::ShowActionMenu(
1185     const std::string& title, const std::vector<ButtonInfo>& button, std::function<void(int32_t, int32_t)>&& callback)
1186 {
1187     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show action menu enter");
1188     auto containerId = Container::CurrentId();
1189     // Get active container when current instanceid is less than 0
1190     if (containerId < 0) {
1191         auto container = Container::GetActive();
1192         if (container) {
1193             containerId = container->GetInstanceId();
1194         }
1195     }
1196     // for pa service
1197     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
1198         auto subwindow = GetOrCreateSubWindow(true);
1199         CHECK_NULL_VOID(subwindow);
1200         subwindow->ShowActionMenu(title, button, std::move(callback));
1201         // for ability
1202     } else {
1203         auto subwindow = GetOrCreateSubWindowByType(SubwindowType::TYPE_DIALOG);
1204         CHECK_NULL_VOID(subwindow);
1205         subwindow->ShowActionMenu(title, button, std::move(callback));
1206     }
1207 }
1208 
CloseDialog(int32_t parentInstanceId)1209 void SubwindowManager::CloseDialog(int32_t parentInstanceId)
1210 {
1211     auto subwindow = GetDialogSubwindow(parentInstanceId);
1212     // Triggered when the main window is destroyed
1213     auto isSubwindow = parentInstanceId >= MIN_SUBCONTAINER_ID && parentInstanceId < MIN_PLUGIN_SUBCONTAINER_ID;
1214     if (!subwindow && !isSubwindow) {
1215         auto subwindows = RemoveSubwindowMapByInstanceId(parentInstanceId);
1216         for (const auto& window : subwindows) {
1217             CHECK_NULL_CONTINUE(window);
1218             if (!window->Close()) {
1219                 TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "fail to close subwindow when container is destroying.");
1220             }
1221         }
1222         return;
1223     }
1224     auto subContainerId = GetSubContainerId(parentInstanceId);
1225     if (subContainerId > -1) {
1226         CHECK_NULL_VOID(subwindow);
1227         subwindow->CloseDialog(subContainerId);
1228     }
1229 }
1230 
OpenCustomDialog(const PromptDialogAttr & dialogAttr,std::function<void (int32_t)> && callback)1231 void SubwindowManager::OpenCustomDialog(const PromptDialogAttr &dialogAttr, std::function<void(int32_t)> &&callback)
1232 {
1233     PromptDialogAttr tmpPromptAttr = dialogAttr;
1234     tmpPromptAttr.showInSubWindow = false;
1235     auto containerId = Container::CurrentId();
1236     // for pa service
1237     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "container %{public}d open the custom dialog", containerId);
1238     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
1239         auto subwindow = GetOrCreateSubWindow();
1240         CHECK_NULL_VOID(subwindow);
1241         subwindow->OpenCustomDialog(tmpPromptAttr, std::move(callback));
1242         // for ability
1243     } else {
1244         auto subwindow = GetOrCreateSubWindowByType(SubwindowType::TYPE_DIALOG, dialogAttr.isModal);
1245         CHECK_NULL_VOID(subwindow);
1246         subwindow->OpenCustomDialog(tmpPromptAttr, std::move(callback));
1247     }
1248     return;
1249 }
1250 
CloseCustomDialog(const int32_t dialogId)1251 void SubwindowManager::CloseCustomDialog(const int32_t dialogId)
1252 {
1253     auto containerId = Container::CurrentId();
1254     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "CloseCustomDialog dialogId = %{public}d, containerId = %{public}d.",
1255         dialogId, containerId);
1256     auto subwindow = GetDialogSubwindow(containerId);
1257     if (!subwindow) {
1258         return;
1259     }
1260     subwindow->CloseCustomDialog(dialogId);
1261     return;
1262 }
1263 
CloseCustomDialog(const WeakPtr<NG::UINode> & node,std::function<void (int32_t)> && callback)1264 void SubwindowManager::CloseCustomDialog(const WeakPtr<NG::UINode>& node, std::function<void(int32_t)> &&callback)
1265 {
1266     auto containerId = Container::CurrentId();
1267     auto subwindow = GetDialogSubwindow(containerId);
1268     if (!subwindow) {
1269         return;
1270     }
1271     subwindow->CloseCustomDialog(node, std::move(callback));
1272     return;
1273 }
1274 
HideSubWindowNG()1275 void SubwindowManager::HideSubWindowNG()
1276 {
1277     RefPtr<Subwindow> subwindow;
1278     auto container = Container::Current();
1279     CHECK_NULL_VOID(container);
1280     if (container->IsDialogContainer()) {
1281         subwindow = GetCurrentDialogWindow();
1282     } else {
1283         subwindow = GetCurrentWindow();
1284     }
1285     if (subwindow) {
1286         subwindow->HideSubWindowNG();
1287     } else {
1288         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "fail to hide subwindow, subwindow is null.");
1289     }
1290 }
1291 
HideToastSubWindowNG()1292 void SubwindowManager::HideToastSubWindowNG()
1293 {
1294     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "hide toast subwindow enter");
1295     RefPtr<Subwindow> subwindow;
1296     auto container = Container::Current();
1297     auto containerId = Container::CurrentId();
1298     CHECK_NULL_VOID(container);
1299     if (container->IsDialogContainer()) {
1300         subwindow = GetCurrentDialogWindow();
1301     } else if (containerId != -1) {
1302         auto parentContainerId = containerId >= MIN_SUBCONTAINER_ID ?
1303             GetParentContainerId(containerId) : containerId;
1304         subwindow = GetToastSubwindow(parentContainerId);
1305     }
1306     if (subwindow) {
1307         subwindow->HideSubWindowNG();
1308     } else {
1309         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "fail to hide toast subwindow, subwindow is null.");
1310     }
1311 }
1312 
ResizeWindowForFoldStatus(int32_t parentContainerId)1313 void SubwindowManager::ResizeWindowForFoldStatus(int32_t parentContainerId)
1314 {
1315     auto containerId = Container::CurrentId();
1316     std::vector<RefPtr<Subwindow>> serviceToastSubwindows;
1317     auto subwindow = parentContainerId < 0 || parentContainerId >= MIN_PA_SERVICE_ID
1318                          ? GetDialogSubwindow(parentContainerId)
1319                          : GetToastSubwindow(containerId);
1320     if (subwindow) {
1321         serviceToastSubwindows.push_back(subwindow);
1322     }
1323     auto systemToastWindow = GetSystemToastWindow(parentContainerId);
1324     if (systemToastWindow) {
1325         serviceToastSubwindows.push_back(systemToastWindow);
1326     }
1327     if (serviceToastSubwindows.empty()) {
1328         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW,
1329             "Get Subwindow error, containerId = %{public}d, parentContainerId = %{public}d", containerId,
1330             parentContainerId);
1331         return;
1332     }
1333     for (const auto& window : serviceToastSubwindows) {
1334         window->ResizeWindowForFoldStatus(parentContainerId);
1335     }
1336 }
1337 
MarkSubwindowSafeAreaDirtyByType(std::shared_ptr<SubwindowManager> manager,int32_t containerId,SubwindowType type)1338 void MarkSubwindowSafeAreaDirtyByType(std::shared_ptr<SubwindowManager> manager,
1339     int32_t containerId, SubwindowType type)
1340 {
1341     CHECK_NULL_VOID(manager);
1342     auto subwindow = manager->GetSubwindowByType(containerId, type);
1343     if (subwindow) {
1344         subwindow->MarkDirtyDialogSafeArea();
1345     }
1346 }
1347 
MarkDirtyDialogSafeArea()1348 void SubwindowManager::MarkDirtyDialogSafeArea()
1349 {
1350     auto allSubwindow = GetAllSubwindow();
1351     for (const auto& subwindow : allSubwindow) {
1352         CHECK_NULL_CONTINUE(subwindow);
1353         subwindow->MarkDirtyDialogSafeArea();
1354     }
1355 }
1356 
HideSystemTopMostWindow()1357 void SubwindowManager::HideSystemTopMostWindow()
1358 {
1359     auto containerId = Container::CurrentId();
1360     if (containerId < 0) {
1361         auto container = Container::GetActive();
1362         if (container) {
1363             containerId = container->GetInstanceId();
1364         }
1365     }
1366     auto parentContainerId = containerId >= MIN_SUBCONTAINER_ID ?
1367             GetParentContainerId(containerId) : containerId;
1368     auto subwindow = GetSystemToastWindow(parentContainerId);
1369     if (subwindow) {
1370         subwindow->HideSubWindowNG();
1371     } else {
1372         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "can not find systemTopMost window when hide window");
1373     }
1374 }
1375 
ClearToastInSystemSubwindow()1376 void SubwindowManager::ClearToastInSystemSubwindow()
1377 {
1378     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear toast in system subwindow enter");
1379     auto containerId = Container::CurrentId();
1380     if (containerId < 0) {
1381         auto container = Container::GetActive();
1382         if (container) {
1383             containerId = container->GetInstanceId();
1384         }
1385     }
1386     RefPtr<Subwindow> subwindow;
1387     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
1388         if (containerId != -1 && containerId < MIN_SUBCONTAINER_ID) {
1389             subwindow = GetSystemToastWindow(containerId);
1390         }
1391     } else {
1392         auto parentContainerId = containerId >= MIN_SUBCONTAINER_ID ?
1393             GetParentContainerId(containerId) : containerId;
1394         subwindow = GetSystemToastWindow(parentContainerId);
1395     }
1396     if (subwindow) {
1397         subwindow->ClearToast();
1398     } else {
1399         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "can not find systemTopMost window when clear system toast");
1400     }
1401 }
1402 
OnUIExtensionWindowSizeChange(int32_t instanceId,Rect windowRect,WindowSizeChangeReason reason)1403 void SubwindowManager::OnUIExtensionWindowSizeChange(int32_t instanceId, Rect windowRect, WindowSizeChangeReason reason)
1404 {
1405     auto container = Container::GetContainer(instanceId);
1406     CHECK_NULL_VOID(container);
1407     if (!container->IsUIExtensionWindow() || uiExtensionWindowRect_ == windowRect) {
1408         return;
1409     }
1410     uiExtensionWindowRect_ = windowRect;
1411 
1412     auto allSubcontainerId = GetAllSubContainerId(instanceId);
1413     std::for_each(allSubcontainerId.begin(), allSubcontainerId.end(), [](int32_t subContainerId) {
1414         auto subContainer = Container::GetContainer(subContainerId);
1415         CHECK_NULL_VOID(subContainer);
1416         auto pipeline = AceType::DynamicCast<NG::PipelineContext>(subContainer->GetPipelineContext());
1417         CHECK_NULL_VOID(pipeline);
1418         auto overlayManager = pipeline->GetOverlayManager();
1419         CHECK_NULL_VOID(overlayManager);
1420         overlayManager->OnUIExtensionWindowSizeChange();
1421     });
1422 }
1423 
FlushSubWindowUITasks(int32_t instanceId)1424 void SubwindowManager::FlushSubWindowUITasks(int32_t instanceId)
1425 {
1426     auto subwindowContainerId = GetSubContainerId(instanceId);
1427     if (subwindowContainerId >= MIN_SUBCONTAINER_ID) {
1428         auto subPipline = NG::PipelineContext::GetContextByContainerId(subwindowContainerId);
1429         CHECK_NULL_VOID(subPipline);
1430         ContainerScope scope(subwindowContainerId);
1431         subPipline->FlushUITasks();
1432     }
1433 }
1434 
IsSubwindowExist(RefPtr<Subwindow> subwindow)1435 bool SubwindowManager::IsSubwindowExist(RefPtr<Subwindow> subwindow)
1436 {
1437     return subwindow && subwindow->GetIsRosenWindowCreate();
1438 }
1439 
GetSubwindowDialogNodeWithExistContent(const RefPtr<NG::UINode> & node)1440 RefPtr<NG::FrameNode> SubwindowManager::GetSubwindowDialogNodeWithExistContent(const RefPtr<NG::UINode>& node)
1441 {
1442     for (auto &overlay : GetAllSubOverlayManager()) {
1443         CHECK_NULL_CONTINUE(overlay);
1444         auto dialogNode = overlay->GetDialogNodeWithExistContent(node);
1445         if (dialogNode) {
1446             return dialogNode;
1447         }
1448     }
1449     return nullptr;
1450 }
1451 
MarkSetSubwindowRect(const NG::RectF & rect,int32_t instanceId,SubwindowType type)1452 void SubwindowManager::MarkSetSubwindowRect(const NG::RectF& rect, int32_t instanceId, SubwindowType type)
1453 {
1454     RefPtr<Subwindow> subwindow;
1455     if (instanceId != -1) {
1456         // get the subwindow which overlay node in, not current
1457         subwindow = GetSubwindowByType(instanceId, type);
1458     } else {
1459         subwindow = GetCurrentWindow();
1460     }
1461 
1462     if (subwindow) {
1463         subwindow->SetRect(rect);
1464     } else {
1465         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "can not get subwindow, set rect failed");
1466     }
1467 }
1468 
SetRect(const NG::RectF & rect,int32_t instanceId)1469 void SubwindowManager::SetRect(const NG::RectF& rect, int32_t instanceId)
1470 {
1471     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "set subwindow rect enter");
1472     MarkSetSubwindowRect(rect, instanceId, SubwindowType::TYPE_DIALOG);
1473     MarkSetSubwindowRect(rect, instanceId, SubwindowType::TYPE_MENU);
1474     MarkSetSubwindowRect(rect, instanceId, SubwindowType::TYPE_POPUP);
1475 }
1476 
IsFreeMultiWindow(int32_t instanceId) const1477 bool SubwindowManager::IsFreeMultiWindow(int32_t instanceId) const
1478 {
1479     auto subWindow = SubwindowManager::GetInstance()->GetSubwindow(instanceId);
1480     CHECK_NULL_RETURN(subWindow, false);
1481     return subWindow->IsFreeMultiWindow();
1482 }
1483 
GetAllSubOverlayManager()1484 const std::vector<RefPtr<NG::OverlayManager>> SubwindowManager::GetAllSubOverlayManager()
1485 {
1486     std::lock_guard<std::mutex> lock(subwindowMutex_);
1487     std::vector<RefPtr<NG::OverlayManager>> subOverlayManager;
1488     subOverlayManager.reserve(subwindowMap_.size());
1489     auto iter = subwindowMap_.begin();
1490     while (iter != subwindowMap_.end()) {
1491         auto subwindow = iter->second;
1492         if (subwindow) {
1493             subOverlayManager.push_back(subwindow->GetOverlayManager());
1494         }
1495         iter++;
1496     }
1497     return subOverlayManager;
1498 }
1499 
GetCurrentSubwindowKey(int32_t instanceId,SubwindowType windowType,int32_t nodeId)1500 SubwindowKey SubwindowManager::GetCurrentSubwindowKey(int32_t instanceId, SubwindowType windowType, int32_t nodeId)
1501 {
1502     uint64_t displayId = 0;
1503     SubwindowKey searchKey;
1504     searchKey.instanceId = instanceId;
1505     searchKey.subwindowType = static_cast<int32_t>(windowType);
1506     if (windowType == SubwindowType::TYPE_POPUP || windowType == SubwindowType::TYPE_MENU) {
1507         windowType = SubwindowType::TYPE_DIALOG;
1508     }
1509     searchKey.windowType = windowType;
1510     searchKey.foldStatus = FoldStatus::UNKNOWN;
1511     searchKey.nodeId = nodeId;
1512     auto container = Container::GetContainer(instanceId);
1513     if (container) {
1514         displayId = container->GetCurrentDisplayId();
1515         searchKey.foldStatus =
1516             isSuperFoldDisplayDevice_ && (displayId == DEFAULT_DISPLAY_ID || displayId == VIRTUAL_DISPLAY_ID)
1517                 ? container->GetFoldStatusFromListener()
1518                 : FoldStatus::UNKNOWN;
1519     }
1520 
1521     searchKey.displayId = displayId;
1522     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "Get current subwindow searchKey is %{public}s.",
1523         searchKey.ToString().c_str());
1524     return searchKey;
1525 }
1526 
ShowSelectOverlay(const RefPtr<NG::FrameNode> & overlayNode)1527 int32_t SubwindowManager::ShowSelectOverlay(const RefPtr<NG::FrameNode>& overlayNode)
1528 {
1529     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "Show selectOverlay enter.");
1530     CHECK_NULL_RETURN(overlayNode, -1);
1531     auto containerId = Container::CurrentIdSafelyWithCheck();
1532     auto windowType = GetToastWindowType(containerId);
1533     auto container = Container::GetContainer(containerId);
1534     CHECK_NULL_RETURN(container, -1);
1535     auto windowId = container->GetWindowId();
1536     // Get the parent window ID before the asynchronous operation
1537     auto mainWindowId = container->GetParentMainWindowId(windowId);
1538     auto subwindow = GetOrCreateSelectOverlayWindow(containerId, windowType, mainWindowId);
1539     if (!IsSubwindowExist(subwindow)) {
1540         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Get or create SelectOverlay subwindow failed.");
1541         return -1;
1542     }
1543     auto isShowSuccess = subwindow->ShowSelectOverlay(overlayNode);
1544     if (!isShowSuccess) {
1545         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Show selectOverlay subwindow failed.");
1546         return -1;
1547     }
1548     return containerId;
1549 }
1550 
HideSelectOverlay(const int32_t instanceId)1551 void SubwindowManager::HideSelectOverlay(const int32_t instanceId)
1552 {
1553     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "Hide selectOverlay subwindow enter.");
1554     auto subwindow = GetSelectOverlaySubwindow(instanceId);
1555     if (subwindow) {
1556         TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "Hide the existed selectOverlay subwindow.");
1557         subwindow->HideSubWindowNG();
1558     } else {
1559         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Fail to hide selectOverlay subwindow, subwindow is not existed.");
1560     }
1561 }
1562 
GetSelectOverlaySubwindow(int32_t instanceId)1563 const RefPtr<Subwindow> SubwindowManager::GetSelectOverlaySubwindow(int32_t instanceId)
1564 {
1565     return GetSubwindowByType(instanceId, SubwindowType::TYPE_SELECT_MENU);
1566 }
1567 
AddSelectOverlaySubwindow(int32_t instanceId,RefPtr<Subwindow> subwindow)1568 void SubwindowManager::AddSelectOverlaySubwindow(int32_t instanceId, RefPtr<Subwindow> subwindow)
1569 {
1570     if (!subwindow) {
1571         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add selectOverlay subwindow failed, subwindow is null.");
1572         return;
1573     }
1574 
1575     if (!subwindow->GetIsRosenWindowCreate()) {
1576         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add selectOverlay subwindow failed, subwindow is invalid.");
1577         subwindow->DestroyWindow();
1578         return;
1579     }
1580 
1581     AddSubwindow(instanceId, SubwindowType::TYPE_SELECT_MENU, subwindow);
1582 }
1583 
GetOrCreateSelectOverlayWindow(int32_t containerId,const ToastWindowType & windowType,uint32_t mainWindowId)1584 RefPtr<Subwindow> SubwindowManager::GetOrCreateSelectOverlayWindow(
1585     int32_t containerId, const ToastWindowType& windowType, uint32_t mainWindowId)
1586 {
1587     RefPtr<Subwindow> subwindow = GetSelectOverlaySubwindow(containerId);
1588     if (!subwindow) {
1589         subwindow = Subwindow::CreateSubwindow(containerId);
1590         if (!subwindow) {
1591             TAG_LOGE(AceLogTag::ACE_SUB_WINDOW, "Create selectOverlay subwindow failed.");
1592             return nullptr;
1593         }
1594         subwindow->SetIsSelectOverlaySubWindow(true);
1595         subwindow->SetToastWindowType(windowType);
1596         subwindow->SetMainWindowId(mainWindowId);
1597         subwindow->InitContainer();
1598         if (!subwindow->GetIsRosenWindowCreate()) {
1599             TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Create selectOverlay subwindow failed, subwindow is invalid.");
1600             subwindow->DestroyWindow();
1601             return nullptr;
1602         }
1603         AddSelectOverlaySubwindow(containerId, subwindow);
1604     }
1605     return subwindow;
1606 }
1607 
SetSelectOverlayHotAreas(const std::vector<Rect> & rects,int32_t nodeId,int32_t instanceId)1608 void SubwindowManager::SetSelectOverlayHotAreas(const std::vector<Rect>& rects, int32_t nodeId, int32_t instanceId)
1609 {
1610     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "Set selectOverlay hot areas enter.");
1611     auto subwindow = GetSelectOverlaySubwindow(instanceId);
1612     if (subwindow) {
1613         subwindow->SetHotAreas(rects, nodeId);
1614     } else {
1615         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Fail to set selectOverlay subwindow hotAreas, subwindow is null.");
1616     }
1617 }
1618 
DeleteSelectOverlayHotAreas(int32_t instanceId,int32_t nodeId)1619 void SubwindowManager::DeleteSelectOverlayHotAreas(int32_t instanceId, int32_t nodeId)
1620 {
1621     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "Delete selectOverlay subwindow hot areas enter.");
1622     auto subwindow = GetSelectOverlaySubwindow(instanceId);
1623     if (subwindow) {
1624         subwindow->DeleteHotAreas(nodeId);
1625     } else {
1626         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Fail to delete selectOverlay subwindow hotAreas, subwindow is null.");
1627     }
1628 }
1629 
IsWindowEnableSubWindowMenu(const int32_t instanceId,const RefPtr<NG::FrameNode> & callerFrameNode)1630 bool SubwindowManager::IsWindowEnableSubWindowMenu(
1631     const int32_t instanceId, const RefPtr<NG::FrameNode>& callerFrameNode)
1632 {
1633     auto container = Container::GetContainer(instanceId);
1634     CHECK_NULL_RETURN(container, false);
1635 
1636     if (instanceId >= MIN_SUBCONTAINER_ID) {
1637         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Subwindow does not support create subwindow menu.");
1638         return false;
1639     }
1640 
1641     if (container->IsUIExtensionWindow()) {
1642         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "UIExtensionWindow does not support create subwindow menu.");
1643         return false;
1644     }
1645 
1646     if (container->IsSceneBoardWindow()) {
1647         if (!container->IsSceneBoardEnabled()) {
1648             TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Disabled sceneBoard does not support create subwindow menu.");
1649             return false;
1650         }
1651         // If the callerFrameNode is on the lock screen, the subwinow menu will be obscured by the lock screen.
1652         if (Container::IsNodeInKeyGuardWindow(callerFrameNode)) {
1653             TAG_LOGW(
1654                 AceLogTag::ACE_SUB_WINDOW, "The node in the key guard window does not support create subwindow menu.");
1655             return false;
1656         }
1657 
1658         return true;
1659     }
1660 
1661     if (container->IsSubWindow() || container->IsMainWindow() || container->IsDialogWindow()) {
1662         return true;
1663     }
1664 
1665     if (container->IsSystemWindow()) {
1666         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "System window does not support create subwindow menu.");
1667         return false;
1668     }
1669 
1670     return false;
1671 }
1672 
GetSubwindowByType(int32_t instanceId,SubwindowType windowType,int32_t nodeId)1673 const RefPtr<Subwindow> SubwindowManager::GetSubwindowByType(
1674     int32_t instanceId, SubwindowType windowType, int32_t nodeId)
1675 {
1676     if (instanceId >= MIN_SUBCONTAINER_ID && windowType != SubwindowType::TYPE_SYSTEM_TOP_MOST_TOAST &&
1677         windowType != SubwindowType::TYPE_TOP_MOST_TOAST) {
1678         auto subwindow = GetSubwindowById(instanceId);
1679         CHECK_NULL_RETURN(subwindow, nullptr);
1680         if (subwindow->GetNodeId() == nodeId) {
1681             return subwindow;
1682         }
1683     }
1684 
1685     auto index = static_cast<int32_t>(windowType);
1686     if (index >= static_cast<int32_t>(SubwindowType::SUB_WINDOW_TYPE_COUNT)) {
1687         return nullptr;
1688     }
1689     SubwindowKey searchKey = GetCurrentSubwindowKey(instanceId, windowType, nodeId);
1690     std::lock_guard<std::mutex> lock(subwindowMutex_);
1691     auto result = subwindowMap_.find(searchKey);
1692     if (result != subwindowMap_.end()) {
1693         return CheckSubwindowDisplayId(searchKey, result->second);
1694     } else {
1695         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "Fail to find subwindow in subwindowMap_, searchKey is %{public}s.",
1696             searchKey.ToString().c_str());
1697         return nullptr;
1698     }
1699 }
1700 
GetSubwindowBySearchkey(int32_t instanceId,const SubwindowKey & searchKey)1701 RefPtr<Subwindow> SubwindowManager::GetSubwindowBySearchkey(int32_t instanceId, const SubwindowKey& searchKey)
1702 {
1703     if (instanceId >= MIN_SUBCONTAINER_ID && searchKey.windowType != SubwindowType::TYPE_SYSTEM_TOP_MOST_TOAST &&
1704         searchKey.windowType != SubwindowType::TYPE_TOP_MOST_TOAST) {
1705         auto subwindow = GetSubwindowById(instanceId);
1706         CHECK_NULL_RETURN(subwindow, nullptr);
1707         if (subwindow->GetNodeId() == searchKey.nodeId) {
1708             return subwindow;
1709         }
1710     }
1711 
1712     auto index = static_cast<int32_t>(searchKey.windowType);
1713     if (index >= static_cast<int32_t>(SubwindowType::SUB_WINDOW_TYPE_COUNT)) {
1714         return nullptr;
1715     }
1716 
1717     std::lock_guard<std::mutex> lock(subwindowMutex_);
1718     auto result = subwindowMap_.find(searchKey);
1719     if (result != subwindowMap_.end()) {
1720         return CheckSubwindowDisplayId(searchKey, result->second);
1721     }
1722     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "Fail to find subwindow by key in subwindowMap_, searchKey is %{public}s.",
1723         searchKey.ToString().c_str());
1724     return nullptr;
1725 }
1726 
AddSubwindow(int32_t instanceId,SubwindowType windowType,RefPtr<Subwindow> subwindow,int32_t nodeId)1727 void SubwindowManager::AddSubwindow(
1728     int32_t instanceId, SubwindowType windowType, RefPtr<Subwindow> subwindow, int32_t nodeId)
1729 {
1730     if (!subwindow) {
1731         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "add subwindow is nullptr.");
1732         return;
1733     }
1734     auto index = static_cast<int32_t>(windowType);
1735     if (index >= static_cast<int32_t>(SubwindowType::SUB_WINDOW_TYPE_COUNT)) {
1736         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "add subwindow window scene/%{public}d is error.", index);
1737         return;
1738     }
1739     SubwindowKey searchKey = GetCurrentSubwindowKey(instanceId, windowType, nodeId);
1740     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "Add subwindow into map, searchKey is %{public}s, subwindow id is %{public}d.",
1741         searchKey.ToString().c_str(), subwindow->GetSubwindowId());
1742     std::lock_guard<std::mutex> lock(subwindowMutex_);
1743     auto result = subwindowMap_.try_emplace(searchKey, subwindow);
1744     if (!result.second) {
1745         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add failed of this searchkey, searchKey is %{public}s.",
1746             searchKey.ToString().c_str());
1747         return;
1748     }
1749     AddInstanceSubwindowMap(subwindow->GetChildContainerId(), subwindow);
1750 }
1751 
GetSortSubwindow(int32_t instanceId)1752 const std::vector<RefPtr<Subwindow>> SubwindowManager::GetSortSubwindow(int32_t instanceId)
1753 {
1754     std::vector<RefPtr<Subwindow>> sortSubwindow;
1755     for (SubwindowType type : NORMAL_SUBWINDOW_TYPE) {
1756         auto subwindow = GetSubwindowByType(instanceId, type);
1757         if (subwindow) {
1758             sortSubwindow.push_back(subwindow);
1759         }
1760     }
1761 
1762     std::sort(sortSubwindow.begin(), sortSubwindow.end(), [](RefPtr<Subwindow> first, RefPtr<Subwindow> second) {
1763         if (!first) {
1764             return false;
1765         }
1766         if (!second) {
1767             return true;
1768         }
1769         return first->GetSubwindowId() > second->GetSubwindowId();
1770     });
1771     return sortSubwindow;
1772 }
1773 
GetIsExpandDisplay()1774 bool SubwindowManager::GetIsExpandDisplay()
1775 {
1776     auto pipeline = PipelineBase::GetCurrentContextSafelyWithCheck();
1777     CHECK_NULL_RETURN(pipeline, false);
1778     auto theme = pipeline->GetTheme<SelectTheme>();
1779     CHECK_NULL_RETURN(theme, false);
1780     return theme->GetExpandDisplay();
1781 }
1782 
RemoveSubwindowByNodeId(const int32_t nodeId)1783 void SubwindowManager::RemoveSubwindowByNodeId(const int32_t nodeId)
1784 {
1785     auto subwindow = RemoveSubwindowMapByNodeId(nodeId);
1786     CHECK_NULL_VOID(subwindow);
1787     if (!subwindow->Close()) {
1788         TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "fail to close subwindow by nodeid.");
1789     }
1790 }
1791 
RemoveSubwindowMapByNodeId(const int32_t nodeId)1792 RefPtr<Subwindow> SubwindowManager::RemoveSubwindowMapByNodeId(const int32_t nodeId)
1793 {
1794     std::lock_guard<std::mutex> lock(subwindowMutex_);
1795     auto it = subwindowMap_.begin();
1796     for (; it != subwindowMap_.end(); ++it) {
1797         if (it->first.nodeId == nodeId) {
1798             break;
1799         }
1800     }
1801     auto subwindow = it->second;
1802     subwindowMap_.erase(it);
1803     return subwindow;
1804 }
1805 
RemoveSubwindowMapByInstanceId(const int32_t instanceId)1806 const std::vector<RefPtr<Subwindow>> SubwindowManager::RemoveSubwindowMapByInstanceId(const int32_t instanceId)
1807 {
1808     std::lock_guard<std::mutex> lock(subwindowMutex_);
1809     std::vector<RefPtr<Subwindow>> subwindows;
1810     for (auto it = subwindowMap_.begin(); it != subwindowMap_.end();) {
1811         // Only close subwindows reused with dialog
1812         auto isDialogTypeWindow = it->first.windowType == SubwindowType::TYPE_MENU ||
1813                                   it->first.windowType == SubwindowType::TYPE_POPUP ||
1814                                   it->first.windowType == SubwindowType::TYPE_DIALOG;
1815         if (it->first.instanceId == instanceId && isDialogTypeWindow) {
1816             subwindows.push_back(it->second);
1817             it = subwindowMap_.erase(it);
1818         } else {
1819             ++it;
1820         }
1821     }
1822     return subwindows;
1823 }
1824 
GetAllSubwindow()1825 const std::vector<RefPtr<Subwindow>> SubwindowManager::GetAllSubwindow()
1826 {
1827     std::lock_guard<std::mutex> lock(subwindowMutex_);
1828     std::vector<RefPtr<Subwindow>> subwindows;
1829     subwindows.reserve(subwindowMap_.size());
1830     for (auto it = subwindowMap_.begin(); it != subwindowMap_.end(); ++it) {
1831         subwindows.push_back(it->second);
1832     }
1833     return subwindows;
1834 }
1835 
GetOrCreateSubWindowByType(SubwindowType windowType,bool isModal)1836 RefPtr<Subwindow> SubwindowManager::GetOrCreateSubWindowByType(SubwindowType windowType, bool isModal)
1837 {
1838     auto containerId = Container::CurrentId();
1839     auto container = Container::GetContainer(containerId);
1840     SubwindowKey searchKey = GetCurrentSubwindowKey(containerId, windowType);
1841     auto subWindow = GetSubwindowBySearchkey(containerId, searchKey);
1842     auto notReuseFlag = false;
1843     if (container) {
1844         notReuseFlag = container->IsUIExtensionWindow() && isModal;
1845         if (container->IsSubContainer()) {
1846             auto parentContainerId = GetParentContainerId(containerId);
1847             auto parentContainer = Container::GetContainer(parentContainerId);
1848             notReuseFlag = parentContainer && parentContainer->IsUIExtensionWindow() && isModal;
1849         }
1850     }
1851     if (notReuseFlag || !IsSubwindowExist(subWindow)) {
1852         subWindow = Subwindow::CreateSubwindow(containerId);
1853         CHECK_NULL_RETURN(subWindow, nullptr);
1854         CHECK_NULL_RETURN(subWindow->CheckHostWindowStatus(), nullptr);
1855         subWindow->InitContainer();
1856         CHECK_NULL_RETURN(subWindow->GetIsRosenWindowCreate(), nullptr);
1857         if (!notReuseFlag) {
1858             AddSubwindowBySearchKey(searchKey, subWindow);
1859         }
1860     }
1861     return subWindow;
1862 }
1863 
GetOrCreateMenuSubWindow(int32_t instanceId)1864 RefPtr<Subwindow> SubwindowManager::GetOrCreateMenuSubWindow(int32_t instanceId)
1865 {
1866     SubwindowKey searchKey = GetCurrentSubwindowKey(instanceId, SubwindowType::TYPE_MENU);
1867     auto subwindow = GetSubwindowBySearchKey(searchKey);
1868     if (!IsSubwindowExist(subwindow)) {
1869         subwindow = Subwindow::CreateSubwindow(instanceId);
1870         CHECK_NULL_RETURN(subwindow, nullptr);
1871         subwindow->InitContainer();
1872         CHECK_NULL_RETURN(subwindow->GetIsRosenWindowCreate(), nullptr);
1873         AddSubwindowBySearchKey(searchKey, subwindow);
1874     } else if (subwindow->GetDetachState() == MenuWindowState::DETACHING) {
1875         TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "recreate subwindow");
1876         RemoveSubwindowBySearchKey(searchKey);
1877         subwindow = Subwindow::CreateSubwindow(instanceId);
1878         CHECK_NULL_RETURN(subwindow, nullptr);
1879         subwindow->InitContainer();
1880         CHECK_NULL_RETURN(subwindow->GetIsRosenWindowCreate(), nullptr);
1881         AddSubwindowBySearchKey(searchKey, subwindow);
1882     }
1883     return subwindow;
1884 }
1885 
GetSubwindowBySearchKey(const SubwindowKey & searchKey)1886 RefPtr<Subwindow> SubwindowManager::GetSubwindowBySearchKey(const SubwindowKey& searchKey)
1887 {
1888     std::lock_guard<std::mutex> lock(subwindowMutex_);
1889     auto result = subwindowMap_.find(searchKey);
1890     if (result != subwindowMap_.end()) {
1891         return CheckSubwindowDisplayId(searchKey, result->second);
1892     } else {
1893         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "Fail to find subwindow in subwindowMap_, searchKey is %{public}s.",
1894             searchKey.ToString().c_str());
1895         return nullptr;
1896     }
1897 }
1898 
CheckSubwindowDisplayId(const SubwindowKey & searchKey,const RefPtr<Subwindow> & subwindow)1899 RefPtr<Subwindow> SubwindowManager::CheckSubwindowDisplayId(const SubwindowKey& searchKey,
1900     const RefPtr<Subwindow>& subwindow)
1901 {
1902     CHECK_NULL_RETURN(subwindow, nullptr);
1903     if (searchKey.displayId != subwindow->GetDisplayId() && !subwindow->GetShown()) {
1904         TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "Remove subwindow by displayId changed, "
1905             "searchKey: %{public}s, subwindowId: %{public}d, newDisplayId: %{public}u, oldDisplayId: %{public}u",
1906             searchKey.ToString().c_str(), subwindow->GetSubwindowId(), (uint32_t)searchKey.displayId,
1907             (uint32_t)subwindow->GetDisplayId());
1908         subwindowMap_.erase(searchKey);
1909         subwindow->DestroyWindow();
1910         return nullptr;
1911     }
1912     return subwindow;
1913 }
1914 
RemoveSubwindowBySearchKey(const SubwindowKey & searchKey)1915 void SubwindowManager::RemoveSubwindowBySearchKey(const SubwindowKey& searchKey)
1916 {
1917     std::lock_guard<std::mutex> lock(subwindowMutex_);
1918     subwindowMap_.erase(searchKey);
1919 }
1920 
AddSubwindowBySearchKey(const SubwindowKey & searchKey,const RefPtr<Subwindow> & subwindow)1921 void SubwindowManager::AddSubwindowBySearchKey(const SubwindowKey& searchKey, const RefPtr<Subwindow>& subwindow)
1922 {
1923     if (!subwindow) {
1924         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "add subwindow is nullptr.");
1925         return;
1926     }
1927     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "Add subwindow into map, searchKey is %{public}s, subwindow id is %{public}d.",
1928         searchKey.ToString().c_str(), subwindow->GetSubwindowId());
1929     std::lock_guard<std::mutex> lock(subwindowMutex_);
1930     auto result = subwindowMap_.try_emplace(searchKey, subwindow);
1931     if (!result.second) {
1932         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add failed of this searchkey, searchKey is %{public}s.",
1933             searchKey.ToString().c_str());
1934         return;
1935     }
1936     AddInstanceSubwindowMap(subwindow->GetChildContainerId(), subwindow);
1937 }
1938 } // namespace OHOS::Ace
1939