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