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