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