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 
20 namespace OHOS::Ace {
21 
22 std::mutex SubwindowManager::instanceMutex_;
23 std::shared_ptr<SubwindowManager> SubwindowManager::instance_;
24 thread_local RefPtr<Subwindow> SubwindowManager::currentSubwindow_;
25 
GetInstance()26 std::shared_ptr<SubwindowManager> SubwindowManager::GetInstance()
27 {
28     std::lock_guard<std::mutex> lock(instanceMutex_);
29     if (!instance_) {
30         instance_ = std::make_shared<SubwindowManager>();
31     }
32     return instance_;
33 }
34 
AddContainerId(uint32_t windowId, int32_t containerId)35 void SubwindowManager::AddContainerId(uint32_t windowId, int32_t containerId)
36 {
37     std::lock_guard<std::mutex> lock(mutex_);
38     auto result = containerMap_.try_emplace(windowId, containerId);
39     if (!result.second) {
40         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Already have container of this windowId, windowId: %{public}u", windowId);
41     }
42 }
43 
RemoveContainerId(uint32_t windowId)44 void SubwindowManager::RemoveContainerId(uint32_t windowId)
45 {
46     std::lock_guard<std::mutex> lock(mutex_);
47     containerMap_.erase(windowId);
48 }
49 
GetContainerId(uint32_t windowId)50 int32_t SubwindowManager::GetContainerId(uint32_t windowId)
51 {
52     std::lock_guard<std::mutex> lock(mutex_);
53     auto result = containerMap_.find(windowId);
54     if (result != containerMap_.end()) {
55         return result->second;
56     } else {
57         return -1;
58     }
59 }
60 
AddParentContainerId(int32_t containerId, int32_t parentContainerId)61 void SubwindowManager::AddParentContainerId(int32_t containerId, int32_t parentContainerId)
62 {
63     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "Container id is %{public}d, parent id is %{public}d.", containerId,
64         parentContainerId);
65     std::lock_guard<std::mutex> lock(parentMutex_);
66     parentContainerMap_.try_emplace(containerId, parentContainerId);
67 }
68 
RemoveParentContainerId(int32_t containerId)69 void SubwindowManager::RemoveParentContainerId(int32_t containerId)
70 {
71     std::lock_guard<std::mutex> lock(parentMutex_);
72     parentContainerMap_.erase(containerId);
73 }
74 
GetParentContainerId(int32_t containerId)75 int32_t SubwindowManager::GetParentContainerId(int32_t containerId)
76 {
77     std::lock_guard<std::mutex> lock(parentMutex_);
78     auto result = parentContainerMap_.find(containerId);
79     if (result != parentContainerMap_.end()) {
80         return result->second;
81     } else {
82         return -1;
83     }
84 }
85 
GetSubContainerId(int32_t parentContainerId)86 int32_t SubwindowManager::GetSubContainerId(int32_t parentContainerId)
87 {
88     std::lock_guard<std::mutex> lock(parentMutex_);
89     for (auto it = parentContainerMap_.begin(); it != parentContainerMap_.end(); it++) {
90         if (it->second == parentContainerId) {
91             return it->first;
92         }
93     }
94     return -1;
95 }
96 
AddSubwindow(int32_t instanceId, RefPtr<Subwindow> subwindow)97 void SubwindowManager::AddSubwindow(int32_t instanceId, RefPtr<Subwindow> subwindow)
98 {
99     if (!subwindow) {
100         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "add subwindow failed.");
101         return;
102     }
103     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "Add subwindow into map, instanceId is %{public}d, subwindow id is %{public}d.",
104         instanceId, subwindow->GetSubwindowId());
105     std::lock_guard<std::mutex> lock(subwindowMutex_);
106     auto result = subwindowMap_.try_emplace(instanceId, subwindow);
107     if (!result.second) {
108         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add failed of this instance %{public}d", instanceId);
109         return;
110     }
111 }
112 
AddToastSubwindow(int32_t instanceId, RefPtr<Subwindow> subwindow)113 void SubwindowManager::AddToastSubwindow(int32_t instanceId, RefPtr<Subwindow> subwindow)
114 {
115     if (!subwindow) {
116         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "add toast subwindow failed.");
117         return;
118     }
119     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "Add toast into map, instanceId is %{public}d, subwindow id is %{public}d.",
120         instanceId, subwindow->GetSubwindowId());
121     std::lock_guard<std::mutex> lock(toastMutex_);
122     auto result = toastWindowMap_.try_emplace(instanceId, subwindow);
123     if (!result.second) {
124         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add toast failed of this instance %{public}d", instanceId);
125         return;
126     }
127 }
128 
AddSystemToastWindow(int32_t instanceId, RefPtr<Subwindow> subwindow)129 void SubwindowManager::AddSystemToastWindow(int32_t instanceId, RefPtr<Subwindow> subwindow)
130 {
131     if (!subwindow) {
132         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "add system toast subwindow failed.");
133         return;
134     }
135     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW,
136         "Add system toast into map, instanceId is %{public}d, subwindow id is %{public}d.",
137         instanceId, subwindow->GetSubwindowId());
138     std::lock_guard<std::mutex> lock(systemToastMutex_);
139     auto result = systemToastWindowMap_.try_emplace(instanceId, subwindow);
140     if (!result.second) {
141         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add system toast failed of this instance %{public}d", instanceId);
142         return;
143     }
144 }
145 
DeleteHotAreas(int32_t instanceId, int32_t nodeId)146 void SubwindowManager::DeleteHotAreas(int32_t instanceId, int32_t nodeId)
147 {
148     RefPtr<Subwindow> subwindow;
149     if (instanceId != -1) {
150         // get the subwindow which overlay node in, not current
151         subwindow = GetSubwindow(instanceId >= MIN_SUBCONTAINER_ID ? GetParentContainerId(instanceId) : instanceId);
152     } else {
153         subwindow = GetCurrentWindow();
154     }
155     if (subwindow) {
156         subwindow->DeleteHotAreas(nodeId);
157     }
158 }
RemoveSubwindow(int32_t instanceId)159 void SubwindowManager::RemoveSubwindow(int32_t instanceId)
160 {
161     std::lock_guard<std::mutex> lock(subwindowMutex_);
162     subwindowMap_.erase(instanceId);
163 }
164 
GetSubwindow(int32_t instanceId)165 const RefPtr<Subwindow> SubwindowManager::GetSubwindow(int32_t instanceId)
166 {
167     std::lock_guard<std::mutex> lock(subwindowMutex_);
168     auto result = subwindowMap_.find(instanceId);
169     if (result != subwindowMap_.end()) {
170         return result->second;
171     } else {
172         return nullptr;
173     }
174 }
175 
GetToastSubwindow(int32_t instanceId)176 const RefPtr<Subwindow> SubwindowManager::GetToastSubwindow(int32_t instanceId)
177 {
178     std::lock_guard<std::mutex> lock(toastMutex_);
179     auto result = toastWindowMap_.find(instanceId);
180     if (result != toastWindowMap_.end()) {
181         return result->second;
182     }
183     return nullptr;
184 }
185 
GetSystemToastWindow(int32_t instanceId)186 const RefPtr<Subwindow> SubwindowManager::GetSystemToastWindow(int32_t instanceId)
187 {
188     std::lock_guard<std::mutex> lock(systemToastMutex_);
189     auto result = systemToastWindowMap_.find(instanceId);
190     if (result != systemToastWindowMap_.end()) {
191         return result->second;
192     }
193     return nullptr;
194 }
195 
GetOrCreateSubwindow(int32_t instanceId)196 const RefPtr<Subwindow> SubwindowManager::GetOrCreateSubwindow(int32_t instanceId)
197 {
198     auto subwindow = GetSubwindow(instanceId);
199     if (subwindow) {
200         return subwindow;
201     }
202 
203     subwindow = Subwindow::CreateSubwindow(instanceId);
204     if (!subwindow) {
205         TAG_LOGE(AceLogTag::ACE_SUB_WINDOW, "create sub window failed");
206         return nullptr;
207     }
208     AddSubwindow(instanceId, subwindow);
209     return subwindow;
210 }
211 
GetDialogSubwindowInstanceId(int32_t SubwindowId)212 int32_t SubwindowManager::GetDialogSubwindowInstanceId(int32_t SubwindowId)
213 {
214     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "get dialog subwindow instanceid enter");
215     std::lock_guard<std::mutex> lock(subwindowMutex_);
216     for (auto it = subwindowMap_.begin(); it != subwindowMap_.end(); it++) {
217         if (it->second->GetSubwindowId() == SubwindowId) {
218             return it->first;
219         }
220     }
221     return 0;
222 }
223 
SetCurrentSubwindow(const RefPtr<Subwindow>& subwindow)224 void SubwindowManager::SetCurrentSubwindow(const RefPtr<Subwindow>& subwindow)
225 {
226     currentSubwindow_ = subwindow;
227 }
228 
GetCurrentWindow()229 const RefPtr<Subwindow>& SubwindowManager::GetCurrentWindow()
230 {
231     return currentSubwindow_;
232 }
233 
GetParentWindowRect()234 Rect SubwindowManager::GetParentWindowRect()
235 {
236     Rect rect;
237     CHECK_NULL_RETURN(currentSubwindow_, rect);
238     return currentSubwindow_->GetParentWindowRect();
239 }
240 
ShowPreviewNG(bool isStartDraggingFromSubWindow)241 RefPtr<Subwindow> SubwindowManager::ShowPreviewNG(bool isStartDraggingFromSubWindow)
242 {
243     auto containerId = Container::CurrentId();
244     auto subwindow =
245         GetOrCreateSubwindow(containerId >= MIN_SUBCONTAINER_ID ? GetParentContainerId(containerId) : containerId);
246     if (!subwindow) {
247         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
248         return nullptr;
249     }
250     if (!subwindow->ShowPreviewNG(isStartDraggingFromSubWindow)) {
251         return nullptr;
252     }
253     return subwindow;
254 }
255 
ShowMenuNG(const RefPtr<NG::FrameNode>& menuNode, const NG::MenuParam& menuParam, const RefPtr<NG::FrameNode>& targetNode, const NG::OffsetF& offset)256 void SubwindowManager::ShowMenuNG(const RefPtr<NG::FrameNode>& menuNode, const NG::MenuParam& menuParam,
257     const RefPtr<NG::FrameNode>& targetNode, const NG::OffsetF& offset)
258 {
259     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show menu ng enter");
260     CHECK_NULL_VOID(targetNode);
261     auto pipelineContext = targetNode->GetContext();
262     CHECK_NULL_VOID(pipelineContext);
263     auto containerId = pipelineContext->GetInstanceId();
264     auto subwindow = GetOrCreateSubwindow(containerId);
265     if (!subwindow) {
266         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
267         return;
268     }
269     subwindow->ShowMenuNG(menuNode, menuParam, targetNode, offset);
270 }
271 
ShowMenuNG(std::function<void()>&& buildFunc, std::function<void()>&& previewBuildFunc, const NG::MenuParam& menuParam, const RefPtr<NG::FrameNode>& targetNode, const NG::OffsetF& offset)272 void SubwindowManager::ShowMenuNG(std::function<void()>&& buildFunc, std::function<void()>&& previewBuildFunc,
273     const NG::MenuParam& menuParam, const RefPtr<NG::FrameNode>& targetNode, const NG::OffsetF& offset)
274 {
275     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show menu ng enter");
276     CHECK_NULL_VOID(targetNode);
277     auto pipelineContext = targetNode->GetContext();
278     CHECK_NULL_VOID(pipelineContext);
279     auto containerId = pipelineContext->GetInstanceId();
280     auto subwindow = GetOrCreateSubwindow(containerId);
281     if (!subwindow) {
282         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
283         return;
284     }
285     subwindow->ShowMenuNG(std::move(buildFunc), std::move(previewBuildFunc), menuParam, targetNode, offset);
286 }
287 
HidePreviewNG()288 void SubwindowManager::HidePreviewNG()
289 {
290     auto subwindow = GetCurrentWindow();
291     if (subwindow) {
292         subwindow->HidePreviewNG();
293     }
294 }
295 
HideMenuNG(const RefPtr<NG::FrameNode>& menu, int32_t targetId)296 void SubwindowManager::HideMenuNG(const RefPtr<NG::FrameNode>& menu, int32_t targetId)
297 {
298     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "hide menu ng enter");
299     auto subwindow = GetCurrentWindow();
300     if (subwindow) {
301         subwindow->HideMenuNG(menu, targetId);
302     }
303 }
304 
HideMenuNG(bool showPreviewAnimation, bool startDrag)305 void SubwindowManager::HideMenuNG(bool showPreviewAnimation, bool startDrag)
306 {
307     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "hide menu ng enter");
308     auto subwindow = GetCurrentWindow();
309     if (subwindow) {
310         subwindow->HideMenuNG(showPreviewAnimation, startDrag);
311     }
312 }
313 
UpdateHideMenuOffsetNG( const NG::OffsetF& offset, float menuScale, bool isRedragStart, int32_t menuWrapperId)314 void SubwindowManager::UpdateHideMenuOffsetNG(
315     const NG::OffsetF& offset, float menuScale, bool isRedragStart, int32_t menuWrapperId)
316 {
317     auto subwindow = GetCurrentWindow();
318     if (subwindow) {
319         subwindow->UpdateHideMenuOffsetNG(offset, menuScale, isRedragStart, menuWrapperId);
320     }
321 }
322 
ContextMenuSwitchDragPreviewAnimation(const RefPtr<NG::FrameNode>& dragPreviewNode, const NG::OffsetF& offset)323 void SubwindowManager::ContextMenuSwitchDragPreviewAnimation(const RefPtr<NG::FrameNode>& dragPreviewNode,
324     const NG::OffsetF& offset)
325 {
326     CHECK_NULL_VOID(dragPreviewNode);
327     auto subwindow = GetCurrentWindow();
328     if (subwindow) {
329         subwindow->ContextMenuSwitchDragPreviewAnimationtNG(dragPreviewNode, offset);
330     }
331 }
332 
UpdatePreviewPosition()333 void SubwindowManager::UpdatePreviewPosition()
334 {
335     auto subwindow = GetCurrentWindow();
336     if (subwindow) {
337         subwindow->UpdatePreviewPosition();
338     }
339 }
340 
GetMenuPreviewCenter(NG::OffsetF& offset)341 bool SubwindowManager::GetMenuPreviewCenter(NG::OffsetF& offset)
342 {
343     auto subwindow = GetCurrentWindow();
344     if (subwindow) {
345         return subwindow->GetMenuPreviewCenter(offset);
346     }
347     return false;
348 }
349 
ClearMenuNG(int32_t instanceId, int32_t targetId, bool inWindow, bool showAnimation)350 void SubwindowManager::ClearMenuNG(int32_t instanceId, int32_t targetId, bool inWindow, bool showAnimation)
351 {
352     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear menu ng enter");
353     RefPtr<Subwindow> subwindow;
354     if (instanceId != -1) {
355 #ifdef OHOS_STANDARD_SYSTEM
356         // get the subwindow which overlay node in, not current
357         subwindow = GetSubwindow(instanceId >= MIN_SUBCONTAINER_ID ? GetParentContainerId(instanceId) : instanceId);
358 #else
359         subwindow =
360             GetSubwindow(GetParentContainerId(instanceId) != -1 ? GetParentContainerId(instanceId) : instanceId);
361 #endif
362     } else {
363         subwindow = GetCurrentWindow();
364     }
365     if (subwindow) {
366         subwindow->ClearMenuNG(targetId, inWindow, showAnimation);
367     }
368 }
369 
ClearPopupInSubwindow(int32_t instanceId)370 void SubwindowManager::ClearPopupInSubwindow(int32_t instanceId)
371 {
372     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear popup in subwindow enter");
373     RefPtr<Subwindow> subwindow;
374     if (instanceId != -1) {
375         // get the subwindow which overlay node in, not current
376         subwindow = GetSubwindow(instanceId >= MIN_SUBCONTAINER_ID ? GetParentContainerId(instanceId) : instanceId);
377     } else {
378         subwindow = GetCurrentWindow();
379     }
380     if (subwindow) {
381         subwindow->ClearPopupNG();
382     }
383 }
384 
ShowPopupNG(const RefPtr<NG::FrameNode>& targetNode, const NG::PopupInfo& popupInfo, const std::function<void(int32_t)>&& onWillDismiss, bool interactiveDismiss)385 void SubwindowManager::ShowPopupNG(const RefPtr<NG::FrameNode>& targetNode, const NG::PopupInfo& popupInfo,
386     const std::function<void(int32_t)>&& onWillDismiss, bool interactiveDismiss)
387 {
388     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show popup ng enter");
389     CHECK_NULL_VOID(targetNode);
390     auto pipelineContext = targetNode->GetContext();
391     CHECK_NULL_VOID(pipelineContext);
392     auto containerId = pipelineContext->GetInstanceId();
393 
394     auto subwindow = GetOrCreateSubwindow(containerId);
395     if (!subwindow) {
396         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
397         return;
398     }
399     subwindow->ShowPopupNG(targetNode->GetId(), popupInfo, std::move(onWillDismiss), interactiveDismiss);
400 }
401 
HidePopupNG(int32_t targetId, int32_t instanceId)402 void SubwindowManager::HidePopupNG(int32_t targetId, int32_t instanceId)
403 {
404     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "hide popup ng enter");
405     RefPtr<Subwindow> subwindow;
406     if (instanceId != -1) {
407         // get the subwindow which overlay node in, not current
408         subwindow = GetSubwindow(instanceId >= MIN_SUBCONTAINER_ID ? GetParentContainerId(instanceId) : instanceId);
409     } else {
410         subwindow = GetCurrentWindow();
411     }
412 
413     if (subwindow) {
414         subwindow->HidePopupNG(targetId);
415     }
416 }
417 
ShowPopup(const RefPtr<Component>& newComponent, bool disableTouchEvent)418 void SubwindowManager::ShowPopup(const RefPtr<Component>& newComponent, bool disableTouchEvent)
419 {
420     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show popup enter");
421     auto containerId = Container::CurrentId();
422     auto taskExecutor = Container::CurrentTaskExecutor();
423     CHECK_NULL_VOID(taskExecutor);
424     taskExecutor->PostTask(
425         [containerId, newComponentWeak = WeakPtr<Component>(newComponent), disableTouchEvent] {
426             auto subwindow = SubwindowManager::GetInstance()->GetOrCreateSubwindow(containerId);
427             if (!subwindow) {
428                 TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
429                 return;
430             }
431             auto newComponent = newComponentWeak.Upgrade();
432             CHECK_NULL_VOID(newComponent);
433             subwindow->ShowPopup(newComponent, disableTouchEvent);
434         },
435         TaskExecutor::TaskType::PLATFORM, "ArkUISubwindowShowPopup");
436 }
437 
CancelPopup(const std::string& id)438 bool SubwindowManager::CancelPopup(const std::string& id)
439 {
440     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "cancel popup enter");
441     auto subwindow = GetCurrentWindow();
442     if (subwindow) {
443         return subwindow->CancelPopup(id);
444     }
445     return false;
446 }
447 
ShowMenu(const RefPtr<Component>& newComponent)448 void SubwindowManager::ShowMenu(const RefPtr<Component>& newComponent)
449 {
450     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show menu enter");
451     auto containerId = Container::CurrentId();
452     auto taskExecutor = Container::CurrentTaskExecutor();
453     CHECK_NULL_VOID(taskExecutor);
454     taskExecutor->PostTask(
455         [containerId, weakMenu = AceType::WeakClaim(AceType::RawPtr(newComponent))] {
456             auto menu = weakMenu.Upgrade();
457             CHECK_NULL_VOID(menu);
458             auto subwindow = SubwindowManager::GetInstance()->GetOrCreateSubwindow(containerId);
459             if (!subwindow) {
460                 TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
461                 return;
462             }
463             subwindow->ShowMenu(menu);
464         },
465         TaskExecutor::TaskType::PLATFORM, "ArkUISubwindowShowMenu");
466 }
467 
CloseMenu()468 void SubwindowManager::CloseMenu()
469 {
470     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close menu enter");
471     auto subwindow = GetCurrentWindow();
472     if (subwindow) {
473         subwindow->CloseMenu();
474     }
475 }
476 
ClearMenu()477 void SubwindowManager::ClearMenu()
478 {
479     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear menu enter");
480     auto subwindow = GetCurrentWindow();
481     if (subwindow) {
482         subwindow->ClearMenu();
483     }
484 }
485 
SetHotAreas(const std::vector<Rect>& rects, int32_t nodeId, int32_t instanceId)486 void SubwindowManager::SetHotAreas(const std::vector<Rect>& rects, int32_t nodeId, int32_t instanceId)
487 {
488     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "set hot areas enter");
489     RefPtr<Subwindow> subwindow;
490     if (instanceId != -1) {
491         // get the subwindow which overlay node in, not current
492         subwindow = GetSubwindow(instanceId >= MIN_SUBCONTAINER_ID ? GetParentContainerId(instanceId) : instanceId);
493     } else {
494         subwindow = GetCurrentWindow();
495     }
496 
497     if (subwindow) {
498         subwindow->SetHotAreas(rects, nodeId);
499     }
500 }
501 
ShowDialogNG( const DialogProperties& dialogProps, std::function<void()>&& buildFunc)502 RefPtr<NG::FrameNode> SubwindowManager::ShowDialogNG(
503     const DialogProperties& dialogProps, std::function<void()>&& buildFunc)
504 {
505     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show dialog ng enter");
506     auto containerId = Container::CurrentId();
507     auto subwindow = GetOrCreateSubwindow(containerId);
508     if (!subwindow) {
509         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
510         return nullptr;
511     }
512     return subwindow->ShowDialogNG(dialogProps, std::move(buildFunc));
513 }
ShowDialogNGWithNode(const DialogProperties& dialogProps, const RefPtr<NG::UINode>& customNode)514 RefPtr<NG::FrameNode> SubwindowManager::ShowDialogNGWithNode(const DialogProperties& dialogProps,
515     const RefPtr<NG::UINode>& customNode)
516 {
517     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show dialog ng enter");
518     auto containerId = Container::CurrentId();
519     auto subwindow = GetOrCreateSubwindow(containerId);
520     if (!subwindow) {
521         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
522         return nullptr;
523     }
524     return subwindow->ShowDialogNGWithNode(dialogProps, customNode);
525 }
CloseDialogNG(const RefPtr<NG::FrameNode>& dialogNode)526 void SubwindowManager::CloseDialogNG(const RefPtr<NG::FrameNode>& dialogNode)
527 {
528     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close dialog ng enter");
529     auto containerId = Container::CurrentId();
530     auto subwindow = GetSubwindow(containerId);
531     if (!subwindow) {
532         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get subwindow failed.");
533         return;
534     }
535     return subwindow->CloseDialogNG(dialogNode);
536 }
537 
OpenCustomDialogNG(const DialogProperties& dialogProps, std::function<void(int32_t)>&& callback)538 void SubwindowManager::OpenCustomDialogNG(const DialogProperties& dialogProps, std::function<void(int32_t)>&& callback)
539 {
540     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show customDialog ng enter");
541     auto containerId = Container::CurrentId();
542     auto subwindow = GetOrCreateSubwindow(containerId);
543     if (!subwindow) {
544         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
545         return;
546     }
547     return subwindow->OpenCustomDialogNG(dialogProps, std::move(callback));
548 }
549 
CloseCustomDialogNG(int32_t dialogId)550 void SubwindowManager::CloseCustomDialogNG(int32_t dialogId)
551 {
552     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close customDialog ng enter");
553     for (auto &overlay : GetAllSubOverlayManager()) {
554         CHECK_NULL_VOID(overlay);
555         if (overlay->GetDialogMap().find(dialogId) != overlay->GetDialogMap().end()) {
556             return overlay->CloseCustomDialog(dialogId);
557         }
558     }
559 }
560 
CloseCustomDialogNG(const WeakPtr<NG::UINode>& node, std::function<void(int32_t)>&& callback)561 void SubwindowManager::CloseCustomDialogNG(const WeakPtr<NG::UINode>& node, std::function<void(int32_t)>&& callback)
562 {
563     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close customDialog ng enter");
564     for (auto &overlay : GetAllSubOverlayManager()) {
565         CHECK_NULL_VOID(overlay);
566         overlay->CloseCustomDialog(node, std::move(callback));
567     }
568 }
569 
UpdateCustomDialogNG( const WeakPtr<NG::UINode>& node, const PromptDialogAttr &dialogAttr, std::function<void(int32_t)>&& callback)570 void SubwindowManager::UpdateCustomDialogNG(
571     const WeakPtr<NG::UINode>& node, const PromptDialogAttr &dialogAttr, std::function<void(int32_t)>&& callback)
572 {
573     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "update customDialog ng enter");
574     DialogProperties dialogProperties = {
575         .autoCancel = dialogAttr.autoCancel,
576         .maskColor = dialogAttr.maskColor,
577         .isSysBlurStyle = false
578     };
579     if (dialogAttr.alignment.has_value()) {
580         dialogProperties.alignment = dialogAttr.alignment.value();
581     }
582     if (dialogAttr.offset.has_value()) {
583         dialogProperties.offset = dialogAttr.offset.value();
584     }
585     for (auto &overlay : GetAllSubOverlayManager()) {
586         if (overlay) {
587             overlay->UpdateCustomDialog(node, dialogProperties, std::move(callback));
588         }
589     }
590 }
591 
HideDialogSubWindow(int32_t instanceId)592 void SubwindowManager::HideDialogSubWindow(int32_t instanceId)
593 {
594     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "hide dialog subwindow enter");
595     auto subwindow = GetSubwindow(instanceId >= MIN_SUBCONTAINER_ID ? GetParentContainerId(instanceId) : instanceId);
596     CHECK_NULL_VOID(subwindow);
597     auto overlay = subwindow->GetOverlayManager();
598     CHECK_NULL_VOID(overlay);
599     if (overlay->GetDialogMap().size() == 0) {
600         subwindow->HideSubWindowNG();
601     } else {
602         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "fail to hide dialog subwindow, instanceId is %{public}d.", instanceId);
603     }
604 }
605 
AddDialogSubwindow(int32_t instanceId, const RefPtr<Subwindow>& subwindow)606 void SubwindowManager::AddDialogSubwindow(int32_t instanceId, const RefPtr<Subwindow>& subwindow)
607 {
608     if (!subwindow) {
609         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add dialog subwindow failed, the subwindow is null.");
610         return;
611     }
612     std::lock_guard<std::mutex> lock(dialogSubwindowMutex_);
613     auto result = dialogSubwindowMap_.try_emplace(instanceId, subwindow);
614     if (!result.second) {
615         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "Add dialog failed of this instance %{public}d", instanceId);
616         return;
617     }
618 }
619 
GetDialogSubwindow(int32_t instanceId)620 const RefPtr<Subwindow> SubwindowManager::GetDialogSubwindow(int32_t instanceId)
621 {
622     std::lock_guard<std::mutex> lock(dialogSubwindowMutex_);
623     auto result = dialogSubwindowMap_.find(instanceId);
624     if (result != dialogSubwindowMap_.end()) {
625         return result->second;
626     } else {
627         return nullptr;
628     }
629 }
630 
SetCurrentDialogSubwindow(const RefPtr<Subwindow>& subwindow)631 void SubwindowManager::SetCurrentDialogSubwindow(const RefPtr<Subwindow>& subwindow)
632 {
633     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "set current dialog subwindow enter");
634     std::lock_guard<std::mutex> lock(currentDialogSubwindowMutex_);
635     currentDialogSubwindow_ = subwindow;
636 }
637 
GetCurrentDialogWindow()638 const RefPtr<Subwindow>& SubwindowManager::GetCurrentDialogWindow()
639 {
640     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "get current dialog window enter");
641     std::lock_guard<std::mutex> lock(currentDialogSubwindowMutex_);
642     return currentDialogSubwindow_;
643 }
644 
GetOrCreateSubWindow()645 RefPtr<Subwindow> SubwindowManager::GetOrCreateSubWindow()
646 {
647     auto containerId = Container::CurrentId();
648     auto subwindow = GetDialogSubwindow(containerId);
649     if (!subwindow) {
650         subwindow = Subwindow::CreateSubwindow(containerId);
651         CHECK_NULL_RETURN(subwindow, nullptr);
652         AddDialogSubwindow(containerId, subwindow);
653     }
654     return subwindow;
655 }
656 
GetOrCreateSystemSubWindow(int32_t containerId)657 RefPtr<Subwindow> SubwindowManager::GetOrCreateSystemSubWindow(int32_t containerId)
658 {
659     auto subwindow = GetSystemToastWindow(containerId);
660     if (!subwindow) {
661         subwindow = Subwindow::CreateSubwindow(containerId);
662         CHECK_NULL_RETURN(subwindow, nullptr);
663         AddSystemToastWindow(containerId, subwindow);
664     }
665     return subwindow;
666 }
667 
ShowToastNG(const NG::ToastInfo& toastInfo, std::function<void(int32_t)>&& callback)668 void SubwindowManager::ShowToastNG(const NG::ToastInfo& toastInfo, std::function<void(int32_t)>&& callback)
669 {
670     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show toast ng enter");
671     auto containerId = Container::CurrentId();
672     auto windowType = GetToastWindowType(containerId);
673     auto container = Container::GetContainer(containerId);
674     CHECK_NULL_VOID(container);
675     auto windowId = container->GetWindowId();
676     // Get the parent window ID before the asynchronous operation
677     auto mainWindowId = container->GetParentMainWindowId(windowId);
678     // for ability
679     auto taskExecutor = Container::CurrentTaskExecutor();
680     CHECK_NULL_VOID(taskExecutor);
681     taskExecutor->PostTask(
682         [containerId, toastInfo, callbackParam = std::move(callback), windowType, mainWindowId] {
683             auto subwindow = SubwindowManager::GetInstance()->GetOrCreateToastWindowNG(
684                 containerId, windowType, mainWindowId);
685             CHECK_NULL_VOID(subwindow);
686             TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before show toast : %{public}d", containerId);
687             subwindow->ShowToast(toastInfo, std::move(const_cast<std::function<void(int32_t)>&&>(callbackParam)));
688         },
689         TaskExecutor::TaskType::PLATFORM, "ArkUISubwindowShowToastNG");
690 }
691 
GetToastWindowType(int32_t instanceId)692 ToastWindowType SubwindowManager::GetToastWindowType(int32_t instanceId)
693 {
694     auto parentContainer = Container::GetContainer(instanceId);
695     CHECK_NULL_RETURN(parentContainer, ToastWindowType::TOAST_IN_TYPE_TOAST);
696     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "GetToastWindowType instanceId: %{public}d", instanceId);
697     // toast window should be TOAST_IN_TYPE_APP_SUB_WINDOW when parent window is dialog window.
698     if (parentContainer->IsMainWindow() || parentContainer->IsSubWindow() ||
699         parentContainer->IsDialogWindow()) {
700         return ToastWindowType::TOAST_IN_TYPE_APP_SUB_WINDOW;
701     } else if (parentContainer->IsScenceBoardWindow()) {
702         return ToastWindowType::TOAST_IN_TYPE_SYSTEM_FLOAT;
703     } else if (parentContainer->IsSystemWindow()) {
704         return ToastWindowType::TOAST_IN_TYPE_SYSTEM_SUB_WINDOW;
705     } else if (parentContainer->IsUIExtensionWindow()) {
706         if (parentContainer->IsHostMainWindow() || parentContainer->IsHostSubWindow() ||
707             parentContainer->IsHostDialogWindow()) {
708             return ToastWindowType::TOAST_IN_TYPE_APP_SUB_WINDOW;
709         } else if (parentContainer->IsHostSceneBoardWindow()) {
710             return ToastWindowType::TOAST_IN_TYPE_SYSTEM_FLOAT;
711         } else if (parentContainer->IsHostSystemWindow()) {
712             return ToastWindowType::TOAST_IN_TYPE_SYSTEM_SUB_WINDOW;
713         }
714     }
715     return ToastWindowType::TOAST_IN_TYPE_TOAST;
716 }
717 
ShowToast(const NG::ToastInfo& toastInfo, std::function<void(int32_t)>&& callback)718 void SubwindowManager::ShowToast(const NG::ToastInfo& toastInfo, std::function<void(int32_t)>&& callback)
719 {
720     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show toast enter");
721     auto containerId = Container::CurrentId();
722     auto isTopMost = toastInfo.showMode == NG::ToastShowMode::TOP_MOST;
723     // for pa service
724     if ((isTopMost && containerId >= MIN_PA_SERVICE_ID && containerId < MIN_SUBCONTAINER_ID) ||
725         (!isTopMost && containerId >= MIN_PA_SERVICE_ID) || containerId < 0) {
726         auto subwindow = toastInfo.showMode == NG::ToastShowMode::SYSTEM_TOP_MOST ?
727             GetOrCreateSystemSubWindow(containerId) : GetOrCreateSubWindow();
728         CHECK_NULL_VOID(subwindow);
729         subwindow->SetIsSystemTopMost(toastInfo.showMode == NG::ToastShowMode::SYSTEM_TOP_MOST);
730         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before show toast");
731         subwindow->ShowToast(toastInfo, std::move(callback));
732     } else {
733         // for ability
734         auto parentContainer = Container::GetContainer(containerId);
735         // in scenceboard, system_top_most needs to go the old way,
736         // default and top_most need to go showToastNG
737         if (toastInfo.showMode == NG::ToastShowMode::TOP_MOST ||
738             (parentContainer && parentContainer->IsScenceBoardWindow() &&
739             toastInfo.showMode != NG::ToastShowMode::SYSTEM_TOP_MOST)) {
740             ShowToastNG(toastInfo, std::move(callback));
741             return;
742         }
743         auto taskExecutor = Container::CurrentTaskExecutor();
744         CHECK_NULL_VOID(taskExecutor);
745         taskExecutor->PostTask(
746             [containerId, toastInfo, callbackParam = std::move(callback)] {
747 		auto subwindow = SubwindowManager::GetInstance()->GetOrCreateToastWindow(containerId, toastInfo.showMode);
748                 CHECK_NULL_VOID(subwindow);
749                 TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before show toast : %{public}d", containerId);
750                 subwindow->ShowToast(toastInfo, std::move(const_cast<std::function<void(int32_t)>&&>(callbackParam)));
751             },
752             TaskExecutor::TaskType::PLATFORM, "ArkUISubwindowShowToast");
753     }
754 }
755 
CloseToast( const int32_t toastId, const NG::ToastShowMode& showMode, std::function<void(int32_t)>&& callback)756 void SubwindowManager::CloseToast(
757     const int32_t toastId, const NG::ToastShowMode& showMode, std::function<void(int32_t)>&& callback)
758 {
759     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "close toast enter");
760     auto containerId = Container::CurrentId();
761 
762     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
763         // for pa service
764         auto subwindow = showMode == NG::ToastShowMode::SYSTEM_TOP_MOST ?
765             GetSystemToastWindow(containerId) : GetDialogSubwindow(containerId);
766         CHECK_NULL_VOID(subwindow);
767         subwindow->SetIsSystemTopMost(showMode == NG::ToastShowMode::SYSTEM_TOP_MOST);
768         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before close toast");
769         subwindow->CloseToast(toastId, std::move(callback));
770     } else {
771         // for ability
772         if (showMode == NG::ToastShowMode::TOP_MOST) {
773             auto subwindow = GetToastSubwindow(containerId);
774             subwindow->CloseToast(toastId, std::move(callback));
775             return;
776         }
777         auto manager = SubwindowManager::GetInstance();
778         CHECK_NULL_VOID(manager);
779         auto subwindow = showMode == NG::ToastShowMode::SYSTEM_TOP_MOST ?
780             GetSystemToastWindow(containerId) : GetSubwindow(containerId);
781         CHECK_NULL_VOID(subwindow);
782         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "before close toast : %{public}d", containerId);
783         subwindow->CloseToast(toastId, std::move(callback));
784     }
785 }
786 
GetOrCreateToastWindow(int32_t containerId, const NG::ToastShowMode& showMode)787 RefPtr<Subwindow> SubwindowManager::GetOrCreateToastWindow(int32_t containerId, const NG::ToastShowMode& showMode)
788 {
789     auto isSystemTopMost = (showMode == NG::ToastShowMode::SYSTEM_TOP_MOST);
790     RefPtr<Subwindow> subwindow = nullptr;
791     if (isSystemTopMost) {
792         subwindow = GetSystemToastWindow(containerId);
793     } else {
794         subwindow = GetSubwindow(containerId);
795     }
796 
797     if (!subwindow) {
798         subwindow = Subwindow::CreateSubwindow(containerId);
799         if (!subwindow) {
800             TAG_LOGE(AceLogTag::ACE_SUB_WINDOW, "create sub window failed");
801             return nullptr;
802         }
803         subwindow->SetIsSystemTopMost(isSystemTopMost);
804         subwindow->SetAboveApps(showMode == NG::ToastShowMode::TOP_MOST);
805         if (isSystemTopMost) {
806             AddSystemToastWindow(containerId, subwindow);
807         } else {
808             AddSubwindow(containerId, subwindow);
809         }
810     }
811 
812     return subwindow;
813 }
814 
GetOrCreateToastWindowNG(int32_t containerId, const ToastWindowType& windowType, uint32_t mainWindowId)815 RefPtr<Subwindow> SubwindowManager::GetOrCreateToastWindowNG(int32_t containerId,
816     const ToastWindowType& windowType, uint32_t mainWindowId)
817 {
818     RefPtr<Subwindow> subwindow = GetToastSubwindow(containerId);
819     if (!subwindow) {
820         subwindow = Subwindow::CreateSubwindow(containerId);
821         if (!subwindow) {
822             TAG_LOGE(AceLogTag::ACE_SUB_WINDOW, "create toast subwindow failed");
823             return nullptr;
824         }
825         subwindow->SetToastWindowType(windowType);
826         subwindow->SetMainWindowId(mainWindowId);
827         AddToastSubwindow(containerId, subwindow);
828     }
829     return subwindow;
830 }
831 
ClearToastInSubwindow()832 void SubwindowManager::ClearToastInSubwindow()
833 {
834     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear toast in subwindow enter");
835     auto containerId = Container::CurrentId();
836     // Get active container when current instanceid is less than 0
837     if (containerId < 0) {
838         auto container = Container::GetActive();
839         if (container) {
840             containerId = container->GetInstanceId();
841         }
842     }
843     RefPtr<Subwindow> subwindow;
844     // The main window does not need to clear Toast
845     if (containerId != -1 && containerId < MIN_SUBCONTAINER_ID) {
846         // get the subwindow which overlay node in, not current
847         auto parentContainerId = containerId >= MIN_SUBCONTAINER_ID ?
848             GetParentContainerId(containerId) : containerId;
849         subwindow = GetToastSubwindow(parentContainerId);
850     }
851     if (subwindow) {
852         subwindow->ClearToast();
853     }
854 }
855 
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)856 void SubwindowManager::ShowDialog(const std::string& title, const std::string& message,
857     const std::vector<ButtonInfo>& buttons, bool autoCancel, std::function<void(int32_t, int32_t)>&& napiCallback,
858     const std::set<std::string>& dialogCallbacks)
859 {
860     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show dialog enter");
861     auto containerId = Container::CurrentId();
862     // Get active container when current instanceid is less than 0
863     if (containerId < 0) {
864         auto container = Container::GetActive();
865         if (container) {
866             containerId = container->GetInstanceId();
867         }
868     }
869     // for pa service
870     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
871         auto subwindow = GetOrCreateSubWindow();
872         CHECK_NULL_VOID(subwindow);
873         subwindow->ShowDialog(title, message, buttons, autoCancel, std::move(napiCallback), dialogCallbacks);
874         // for ability
875     } else {
876         auto subwindow = GetOrCreateSubwindow(containerId);
877         if (!subwindow) {
878             TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
879             return;
880         }
881         subwindow->ShowDialog(title, message, buttons, autoCancel, std::move(napiCallback), dialogCallbacks);
882     }
883 }
884 
ShowDialog(const PromptDialogAttr& dialogAttr, const std::vector<ButtonInfo>& buttons, std::function<void(int32_t, int32_t)>&& napiCallback, const std::set<std::string>& dialogCallbacks)885 void SubwindowManager::ShowDialog(const PromptDialogAttr& dialogAttr, const std::vector<ButtonInfo>& buttons,
886     std::function<void(int32_t, int32_t)>&& napiCallback, const std::set<std::string>& dialogCallbacks)
887 {
888     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show dialog enter");
889     auto containerId = Container::CurrentId();
890     // Get active container when current instanceid is less than 0
891     if (containerId < 0) {
892         auto container = Container::GetActive();
893         if (container) {
894             containerId = container->GetInstanceId();
895         }
896     }
897     // for pa service
898     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
899         auto subwindow = GetOrCreateSubWindow();
900         CHECK_NULL_VOID(subwindow);
901         subwindow->ShowDialog(dialogAttr, buttons, std::move(napiCallback), dialogCallbacks);
902         // for ability
903     } else {
904         auto subwindow = GetOrCreateSubwindow(containerId);
905         if (!subwindow) {
906             TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
907             return;
908         }
909         subwindow->ShowDialog(dialogAttr, buttons, std::move(napiCallback), dialogCallbacks);
910     }
911 }
912 
ShowActionMenu( const std::string& title, const std::vector<ButtonInfo>& button, std::function<void(int32_t, int32_t)>&& callback)913 void SubwindowManager::ShowActionMenu(
914     const std::string& title, const std::vector<ButtonInfo>& button, std::function<void(int32_t, int32_t)>&& callback)
915 {
916     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "show action menu enter");
917     auto containerId = Container::CurrentId();
918     // Get active container when current instanceid is less than 0
919     if (containerId < 0) {
920         auto container = Container::GetActive();
921         if (container) {
922             containerId = container->GetInstanceId();
923         }
924     }
925     // for pa service
926     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
927         auto subwindow = GetOrCreateSubWindow();
928         CHECK_NULL_VOID(subwindow);
929         subwindow->ShowActionMenu(title, button, std::move(callback));
930         // for ability
931     } else {
932         auto subwindow = GetOrCreateSubwindow(containerId);
933         if (!subwindow) {
934             TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
935             return;
936         }
937         subwindow->ShowActionMenu(title, button, std::move(callback));
938     }
939 }
940 
CloseDialog(int32_t instanceId)941 void SubwindowManager::CloseDialog(int32_t instanceId)
942 {
943     auto subwindow = GetDialogSubwindow(instanceId);
944     if (!subwindow) {
945         subwindow = GetSubwindow(instanceId);
946         if (subwindow) {
947             subwindow->Close();
948             return;
949         }
950         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get dialog subwindow failed.");
951         return;
952     }
953     auto subContainerId = GetSubContainerId(instanceId);
954     if (subContainerId > -1) {
955         subwindow->CloseDialog(subContainerId);
956     }
957 }
958 
OpenCustomDialog(const PromptDialogAttr &dialogAttr, std::function<void(int32_t)> &&callback)959 void SubwindowManager::OpenCustomDialog(const PromptDialogAttr &dialogAttr, std::function<void(int32_t)> &&callback)
960 {
961     PromptDialogAttr tmpPromptAttr = dialogAttr;
962     tmpPromptAttr.showInSubWindow = false;
963     auto containerId = Container::CurrentId();
964     // for pa service
965     TAG_LOGI(AceLogTag::ACE_SUB_WINDOW, "container %{public}d open the custom dialog", containerId);
966     if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
967         auto subwindow = GetOrCreateSubWindow();
968         CHECK_NULL_VOID(subwindow);
969         subwindow->OpenCustomDialog(tmpPromptAttr, std::move(callback));
970         // for ability
971     } else {
972         auto subwindow = GetOrCreateSubwindow(containerId);
973         if (!subwindow) {
974             TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
975             return;
976         }
977         subwindow->OpenCustomDialog(tmpPromptAttr, std::move(callback));
978     }
979     return;
980 }
981 
CloseCustomDialog(const int32_t dialogId)982 void SubwindowManager::CloseCustomDialog(const int32_t dialogId)
983 {
984     auto containerId = Container::CurrentId();
985     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "CloseCustomDialog dialogId = %{public}d, containerId = %{public}d.",
986         dialogId, containerId);
987     auto subwindow = GetDialogSubwindow(containerId);
988     if (!subwindow) {
989         return;
990     }
991     subwindow->CloseCustomDialog(dialogId);
992     return;
993 }
994 
CloseCustomDialog(const WeakPtr<NG::UINode>& node, std::function<void(int32_t)> &&callback)995 void SubwindowManager::CloseCustomDialog(const WeakPtr<NG::UINode>& node, std::function<void(int32_t)> &&callback)
996 {
997     auto containerId = Container::CurrentId();
998     auto subwindow = GetDialogSubwindow(containerId);
999     if (!subwindow) {
1000         return;
1001     }
1002     subwindow->CloseCustomDialog(node, std::move(callback));
1003     return;
1004 }
1005 
HideSubWindowNG()1006 void SubwindowManager::HideSubWindowNG()
1007 {
1008     RefPtr<Subwindow> subwindow;
1009     auto container = Container::Current();
1010     CHECK_NULL_VOID(container);
1011     if (container->IsDialogContainer()) {
1012         subwindow = GetCurrentDialogWindow();
1013     } else {
1014         subwindow = GetCurrentWindow();
1015     }
1016     if (subwindow) {
1017         subwindow->HideSubWindowNG();
1018     }
1019 }
1020 
HideToastSubWindowNG()1021 void SubwindowManager::HideToastSubWindowNG()
1022 {
1023     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "hide toast subwindow enter");
1024     RefPtr<Subwindow> subwindow;
1025     auto container = Container::Current();
1026     auto containerId = Container::CurrentId();
1027     CHECK_NULL_VOID(container);
1028     if (container->IsDialogContainer()) {
1029         subwindow = GetCurrentDialogWindow();
1030     } else if (containerId != -1) {
1031         auto parentContainerId = containerId >= MIN_SUBCONTAINER_ID ?
1032             GetParentContainerId(containerId) : containerId;
1033         subwindow = GetToastSubwindow(parentContainerId);
1034     }
1035     if (subwindow) {
1036         subwindow->HideSubWindowNG();
1037     }
1038 }
1039 
RequestFocusSubwindow(int32_t instanceId)1040 void SubwindowManager::RequestFocusSubwindow(int32_t instanceId)
1041 {
1042     RefPtr<Subwindow> subwindow;
1043     if (instanceId != -1) {
1044         // get the subwindow which overlay node in, not current
1045         subwindow = GetSubwindow(instanceId >= MIN_SUBCONTAINER_ID ? GetParentContainerId(instanceId) : instanceId);
1046     } else {
1047         subwindow = GetCurrentWindow();
1048     }
1049     if (subwindow) {
1050         subwindow->RequestFocus();
1051     }
1052 }
1053 
GetShown()1054 bool SubwindowManager::GetShown()
1055 {
1056     auto containerId = Container::CurrentId();
1057     auto subwindow = GetOrCreateSubwindow(containerId);
1058     if (!subwindow) {
1059         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW, "get or create subwindow failed");
1060         return false;
1061     }
1062     return subwindow->GetShown();
1063 }
1064 
ResizeWindowForFoldStatus(int32_t parentContainerId)1065 void SubwindowManager::ResizeWindowForFoldStatus(int32_t parentContainerId)
1066 {
1067     auto containerId = Container::CurrentId();
1068     auto subwindow = parentContainerId < 0 ? GetDialogSubwindow(parentContainerId) : GetToastSubwindow(containerId);
1069     if (!subwindow) {
1070         TAG_LOGW(AceLogTag::ACE_SUB_WINDOW,
1071             "Get Subwindow error, containerId = %{public}d, parentContainerId = %{public}d", containerId,
1072             parentContainerId);
1073         return;
1074     }
1075     subwindow->ResizeWindowForFoldStatus(parentContainerId);
1076 }
1077 
MarkDirtyDialogSafeArea()1078 void SubwindowManager::MarkDirtyDialogSafeArea()
1079 {
1080     auto containerId = Container::CurrentId();
1081     auto subwindow = SubwindowManager::GetInstance()->GetSubwindow(containerId);
1082     CHECK_NULL_VOID(subwindow);
1083     if (subwindow) {
1084         subwindow->MarkDirtyDialogSafeArea();
1085     }
1086     subwindow = GetToastSubwindow(containerId);
1087     if (subwindow) {
1088         subwindow->MarkDirtyDialogSafeArea();
1089     }
1090 }
1091 
HideSystemTopMostWindow()1092 void SubwindowManager::HideSystemTopMostWindow()
1093 {
1094     auto containerId = Container::CurrentId();
1095     if (containerId < 0) {
1096         auto container = Container::GetActive();
1097         if (container) {
1098             containerId = container->GetInstanceId();
1099         }
1100     }
1101     auto parentContainerId = containerId >= MIN_SUBCONTAINER_ID ?
1102             GetParentContainerId(containerId) : containerId;
1103     auto subwindow = GetSystemToastWindow(parentContainerId);
1104     if (subwindow) {
1105         subwindow->HideSubWindowNG();
1106     } else {
1107         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "can not find systemTopMost window when hide window");
1108     }
1109 }
1110 
ClearToastInSystemSubwindow()1111 void SubwindowManager::ClearToastInSystemSubwindow()
1112 {
1113     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "clear toast in system subwindow enter");
1114     auto containerId = Container::CurrentId();
1115     if (containerId < 0) {
1116         auto container = Container::GetActive();
1117         if (container) {
1118             containerId = container->GetInstanceId();
1119         }
1120     }
1121     auto parentContainerId = containerId >= MIN_SUBCONTAINER_ID ?
1122             GetParentContainerId(containerId) : containerId;
1123     auto subwindow = GetSystemToastWindow(parentContainerId);
1124     if (subwindow) {
1125         subwindow->ClearToast();
1126     } else {
1127         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "can not find systemTopMost window when clear system toast");
1128     }
1129 }
OnWindowSizeChanged(int32_t instanceId, Rect windowRect, WindowSizeChangeReason reason)1130 void SubwindowManager::OnWindowSizeChanged(int32_t instanceId, Rect windowRect, WindowSizeChangeReason reason)
1131 {
1132     auto container = Container::GetContainer(instanceId);
1133     CHECK_NULL_VOID(container);
1134     if (!container->IsUIExtensionWindow() || uiExtensionWindowRect_ == windowRect) {
1135         return;
1136     }
1137     auto subContainer = Container::GetContainer(GetSubContainerId(instanceId));
1138     CHECK_NULL_VOID(subContainer);
1139     auto pipeline = AceType::DynamicCast<NG::PipelineContext>(subContainer->GetPipelineContext());
1140     CHECK_NULL_VOID(pipeline);
1141     auto overlayManager = pipeline->GetOverlayManager();
1142     CHECK_NULL_VOID(overlayManager);
1143     overlayManager->OnUIExtensionWindowSizeChange();
1144     uiExtensionWindowRect_ = windowRect;
1145 }
1146 
GetSubwindowDialogNodeWithExistContent(const RefPtr<NG::UINode>& node)1147 RefPtr<NG::FrameNode> SubwindowManager::GetSubwindowDialogNodeWithExistContent(const RefPtr<NG::UINode>& node)
1148 {
1149     for (auto &overlay : GetAllSubOverlayManager()) {
1150         CHECK_NULL_RETURN(overlay, nullptr);
1151         auto dialogNode = overlay->GetDialogNodeWithExistContent(node);
1152         if (dialogNode) {
1153             return dialogNode;
1154         }
1155     }
1156     return nullptr;
1157 }
1158 
SetRect(const NG::RectF& rect, int32_t instanceId)1159 void SubwindowManager::SetRect(const NG::RectF& rect, int32_t instanceId)
1160 {
1161     TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "set subwindow rect enter");
1162     RefPtr<Subwindow> subwindow;
1163     if (instanceId != -1) {
1164         // get the subwindow which overlay node in, not current
1165         subwindow = GetSubwindow(instanceId >= MIN_SUBCONTAINER_ID ? GetParentContainerId(instanceId) : instanceId);
1166     } else {
1167         subwindow = GetCurrentWindow();
1168     }
1169 
1170     if (subwindow) {
1171         subwindow->SetRect(rect);
1172     } else {
1173         TAG_LOGD(AceLogTag::ACE_SUB_WINDOW, "can not get subwindow, set rect failed");
1174     }
1175 }
1176 
IsFreeMultiWindow(int32_t instanceId) const1177 bool SubwindowManager::IsFreeMultiWindow(int32_t instanceId) const
1178 {
1179     auto parentContainerId = instanceId >= MIN_SUBCONTAINER_ID
1180                                  ? SubwindowManager::GetInstance()->GetParentContainerId(instanceId)
1181                                  : instanceId;
1182     auto subWindow = SubwindowManager::GetInstance()->GetSubwindow(parentContainerId);
1183     CHECK_NULL_RETURN(subWindow, false);
1184     return subWindow->IsFreeMultiWindow();
1185 }
1186 
GetAllSubOverlayManager()1187 const std::vector<RefPtr<NG::OverlayManager>> SubwindowManager::GetAllSubOverlayManager()
1188 {
1189     std::lock_guard<std::mutex> lock(subwindowMutex_);
1190     std::vector<RefPtr<NG::OverlayManager>> subOverlayManager;
1191     subOverlayManager.reserve(subwindowMap_.size());
1192     auto iter = subwindowMap_.begin();
1193     while (iter != subwindowMap_.end()) {
1194         auto subwindow = iter->second;
1195         if (subwindow) {
1196             subOverlayManager.push_back(subwindow->GetOverlayManager());
1197         }
1198         iter++;
1199     }
1200     return subOverlayManager;
1201 }
1202 } // namespace OHOS::Ace
1203