1 /*
2 * Copyright (c) 2022 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 <memory>
19 #include <mutex>
20
21 #include "unistd.h"
22
23 #include "base/log/log.h"
24 #include "base/memory/ace_type.h"
25 #include "core/common/ace_page.h"
26 #include "core/common/container.h"
27
28 namespace OHOS::Ace {
29
30 std::mutex SubwindowManager::instanceMutex_;
31 std::shared_ptr<SubwindowManager> SubwindowManager::instance_;
32
GetInstance()33 std::shared_ptr<SubwindowManager> SubwindowManager::GetInstance()
34 {
35 std::lock_guard<std::mutex> lock(instanceMutex_);
36 if (!instance_) {
37 instance_ = std::make_shared<SubwindowManager>();
38 }
39 return instance_;
40 }
41
AddContainerId(uint32_t windowId,int32_t containerId)42 void SubwindowManager::AddContainerId(uint32_t windowId, int32_t containerId)
43 {
44 std::lock_guard<std::mutex> lock(mutex_);
45 auto result = containerMap_.try_emplace(windowId, containerId);
46 if (!result.second) {
47 LOGW("Already have container of this windowId, windowId: %{public}u", windowId);
48 }
49 }
50
RemoveContainerId(uint32_t windowId)51 void SubwindowManager::RemoveContainerId(uint32_t windowId)
52 {
53 std::lock_guard<std::mutex> lock(mutex_);
54 containerMap_.erase(windowId);
55 }
56
GetContainerId(uint32_t windowId)57 int32_t SubwindowManager::GetContainerId(uint32_t windowId)
58 {
59 std::lock_guard<std::mutex> lock(mutex_);
60 auto result = containerMap_.find(windowId);
61 if (result != containerMap_.end()) {
62 return result->second;
63 } else {
64 return -1;
65 }
66 }
67
AddParentContainerId(int32_t containerId,int32_t parentContainerId)68 void SubwindowManager::AddParentContainerId(int32_t containerId, int32_t parentContainerId)
69 {
70 LOGI("Container id is %{public}d, parent id is %{public}d.", containerId, parentContainerId);
71 std::lock_guard<std::mutex> lock(parentMutex_);
72 auto result = parentContainerMap_.try_emplace(containerId, parentContainerId);
73 if (!result.second) {
74 LOGW("Already have container of this %{public}d", containerId);
75 }
76 }
77
RemoveParentContainerId(int32_t containerId)78 void SubwindowManager::RemoveParentContainerId(int32_t containerId)
79 {
80 std::lock_guard<std::mutex> lock(parentMutex_);
81 parentContainerMap_.erase(containerId);
82 }
83
GetParentContainerId(int32_t containerId)84 int32_t SubwindowManager::GetParentContainerId(int32_t containerId)
85 {
86 std::lock_guard<std::mutex> lock(parentMutex_);
87 auto result = parentContainerMap_.find(containerId);
88 if (result != parentContainerMap_.end()) {
89 return result->second;
90 } else {
91 return 0;
92 }
93 }
94
AddSubwindow(int32_t instanceId,RefPtr<Subwindow> subwindow)95 void SubwindowManager::AddSubwindow(int32_t instanceId, RefPtr<Subwindow> subwindow)
96 {
97 if (!subwindow) {
98 LOGE("Add subwindow failed, the subwindow is null.");
99 return;
100 }
101 LOGI("Add subwindow into map, instanceId is %{public}d, subwindow id is %{public}d.", instanceId,
102 subwindow->GetSubwindowId());
103 std::lock_guard<std::mutex> lock(subwindowMutex_);
104 auto result = subwindowMap_.try_emplace(instanceId, subwindow);
105 if (!result.second) {
106 LOGE("Add failed of this instance %{public}d", instanceId);
107 return;
108 }
109 LOGI("Add subwindow success of this instance %{public}d.", instanceId);
110 }
111
RemoveSubwindow(int32_t instanceId)112 void SubwindowManager::RemoveSubwindow(int32_t instanceId)
113 {
114 LOGI("Remove subwindow of this instance %{public}d", instanceId);
115 std::lock_guard<std::mutex> lock(subwindowMutex_);
116 int res = static_cast<int>(subwindowMap_.erase(instanceId));
117 if (res == 0) {
118 LOGW("Remove subwindow of instance %{public}d failed.", instanceId);
119 }
120 }
121
GetSubwindow(int32_t instanceId)122 const RefPtr<Subwindow> SubwindowManager::GetSubwindow(int32_t instanceId)
123 {
124 LOGI("Get subwindow of instance %{public}d.", instanceId);
125 std::lock_guard<std::mutex> lock(subwindowMutex_);
126 auto result = subwindowMap_.find(instanceId);
127 if (result != subwindowMap_.end()) {
128 return result->second;
129 } else {
130 return nullptr;
131 }
132 }
133
SetCurrentSubwindowName(const std::string & currentSubwindowName)134 void SubwindowManager::SetCurrentSubwindowName(const std::string& currentSubwindowName)
135 {
136 std::lock_guard<std::mutex> lock(currentSubwindowMutex_);
137 currentSubwindowName_ = currentSubwindowName;
138 }
139
GetCurrentSubWindowName()140 std::string SubwindowManager::GetCurrentSubWindowName()
141 {
142 std::lock_guard<std::mutex> lock(currentSubwindowMutex_);
143 return currentSubwindowName_;
144 }
145
SetCurrentSubwindow(const RefPtr<Subwindow> & subwindow)146 void SubwindowManager::SetCurrentSubwindow(const RefPtr<Subwindow>& subwindow)
147 {
148 std::lock_guard<std::mutex> lock(currentSubwindowMutex_);
149 currentSubwindow_ = subwindow;
150 }
151
GetCurrentWindow()152 const RefPtr<Subwindow>& SubwindowManager::GetCurrentWindow()
153 {
154 std::lock_guard<std::mutex> lock(currentSubwindowMutex_);
155 return currentSubwindow_;
156 }
157
ShowMenuNG(const RefPtr<NG::FrameNode> menuNode,int32_t targetId,const NG::OffsetF & offset)158 void SubwindowManager::ShowMenuNG(const RefPtr<NG::FrameNode> menuNode, int32_t targetId,
159 const NG::OffsetF& offset)
160 {
161 auto containerId = Container::CurrentId();
162 auto subwindow = GetSubwindow(containerId);
163 if (!subwindow) {
164 LOGI("Subwindow is null, add a new one.");
165 subwindow = Subwindow::CreateSubwindow(containerId);
166 subwindow->InitContainer();
167 AddSubwindow(containerId, subwindow);
168 }
169 subwindow->ShowMenuNG(menuNode, targetId, offset);
170 }
171
HideMenuNG(int32_t targetId)172 void SubwindowManager::HideMenuNG(int32_t targetId)
173 {
174 auto subwindow = GetCurrentWindow();
175 if (subwindow) {
176 subwindow->HideMenuNG(targetId);
177 }
178 }
179
HideMenuNG()180 void SubwindowManager::HideMenuNG()
181 {
182 auto subwindow = GetCurrentWindow();
183 if (subwindow) {
184 subwindow->HideMenuNG();
185 }
186 }
187
ClearMenuNG()188 void SubwindowManager::ClearMenuNG()
189 {
190 auto subwindow = GetCurrentWindow();
191 if (subwindow) {
192 subwindow->ClearMenuNG();
193 }
194 }
195
ShowPopupNG(int32_t targetId,const NG::PopupInfo & popupInfo)196 void SubwindowManager::ShowPopupNG(int32_t targetId, const NG::PopupInfo& popupInfo)
197 {
198 auto containerId = Container::CurrentId();
199 auto subwindow = GetSubwindow(containerId);
200 if (!subwindow) {
201 LOGI("Subwindow is null, add a new one.");
202 subwindow = Subwindow::CreateSubwindow(containerId);
203 subwindow->InitContainer();
204 AddSubwindow(containerId, subwindow);
205 }
206 subwindow->ShowPopupNG(targetId, popupInfo);
207 }
208
HidePopupNG(int32_t targetId)209 void SubwindowManager::HidePopupNG(int32_t targetId)
210 {
211 auto subwindow = GetCurrentWindow();
212 if (subwindow) {
213 subwindow->HidePopupNG(targetId);
214 }
215 }
216
HidePopupNG()217 void SubwindowManager::HidePopupNG()
218 {
219 auto subwindow = GetCurrentWindow();
220 if (subwindow) {
221 subwindow->HidePopupNG();
222 }
223 }
224
ShowPopup(const RefPtr<Component> & newComponent,bool disableTouchEvent)225 void SubwindowManager::ShowPopup(const RefPtr<Component>& newComponent, bool disableTouchEvent)
226 {
227 auto containerId = Container::CurrentId();
228 auto subwindow = GetSubwindow(containerId);
229 if (!subwindow) {
230 LOGI("Subwindow is null, add a new one.");
231 subwindow = Subwindow::CreateSubwindow(containerId);
232 subwindow->InitContainer();
233 AddSubwindow(containerId, subwindow);
234 }
235 subwindow->ShowPopup(newComponent, disableTouchEvent);
236 }
237
CancelPopup(const std::string & id)238 bool SubwindowManager::CancelPopup(const std::string& id)
239 {
240 auto subwindow = GetCurrentWindow();
241 if (subwindow) {
242 return subwindow->CancelPopup(id);
243 }
244 return false;
245 }
246
ShowMenu(const RefPtr<Component> & newComponent)247 void SubwindowManager::ShowMenu(const RefPtr<Component>& newComponent)
248 {
249 auto containerId = Container::CurrentId();
250 auto subwindow = GetSubwindow(containerId);
251 if (!subwindow) {
252 LOGI("Subwindow is null, add a new one.");
253 subwindow = Subwindow::CreateSubwindow(containerId);
254 subwindow->InitContainer();
255 AddSubwindow(containerId, subwindow);
256 }
257 subwindow->ShowMenu(newComponent);
258 }
259
CloseMenu()260 void SubwindowManager::CloseMenu()
261 {
262 auto subwindow = GetCurrentWindow();
263 if (subwindow) {
264 subwindow->CloseMenu();
265 }
266 }
267
ClearMenu()268 void SubwindowManager::ClearMenu()
269 {
270 auto subwindow = GetCurrentWindow();
271 if (subwindow) {
272 subwindow->ClearMenu();
273 }
274 }
275
SetHotAreas(const std::vector<Rect> & rects)276 void SubwindowManager::SetHotAreas(const std::vector<Rect>& rects)
277 {
278 auto subwindow = GetCurrentWindow();
279 if (subwindow) {
280 subwindow->SetHotAreas(rects);
281 }
282 }
283
ShowDialogNG(const DialogProperties & dialogProps,const RefPtr<NG::UINode> & customNode)284 RefPtr<NG::FrameNode> SubwindowManager::ShowDialogNG(
285 const DialogProperties& dialogProps, const RefPtr<NG::UINode>& customNode)
286 {
287 auto containerId = Container::CurrentId();
288 auto subwindow = GetSubwindow(containerId);
289 if (!subwindow) {
290 LOGI("Subwindow is null, add a new one.");
291 subwindow = Subwindow::CreateSubwindow(containerId);
292 subwindow->InitContainer();
293 AddSubwindow(containerId, subwindow);
294 }
295 return subwindow->ShowDialogNG(dialogProps, customNode);
296 }
297
AddDialogSubwindow(int32_t instanceId,const RefPtr<Subwindow> & subwindow)298 void SubwindowManager::AddDialogSubwindow(int32_t instanceId, const RefPtr<Subwindow>& subwindow)
299 {
300 if (!subwindow) {
301 LOGE("Add dialog subwindow failed, the subwindow is null.");
302 return;
303 }
304 LOGI("Add dialog subwindow into map, instanceId is %{public}d, subwindow id is %{public}d.", instanceId,
305 subwindow->GetSubwindowId());
306 std::lock_guard<std::mutex> lock(dialogSubwindowMutex_);
307 auto result = dialogSubwindowMap_.try_emplace(instanceId, subwindow);
308 if (!result.second) {
309 LOGE("Add dialog failed of this instance %{public}d", instanceId);
310 return;
311 }
312 LOGI("Add dialog subwindow success of this instance %{public}d.", instanceId);
313 }
314
GetDialogSubwindow(int32_t instanceId)315 const RefPtr<Subwindow> SubwindowManager::GetDialogSubwindow(int32_t instanceId)
316 {
317 LOGI("Get dialog subwindow of instance %{public}d.", instanceId);
318 std::lock_guard<std::mutex> lock(dialogSubwindowMutex_);
319 auto result = dialogSubwindowMap_.find(instanceId);
320 if (result != dialogSubwindowMap_.end()) {
321 return result->second;
322 } else {
323 return nullptr;
324 }
325 }
326
SetCurrentDialogSubwindow(const RefPtr<Subwindow> & subwindow)327 void SubwindowManager::SetCurrentDialogSubwindow(const RefPtr<Subwindow>& subwindow)
328 {
329 std::lock_guard<std::mutex> lock(currentDialogSubwindowMutex_);
330 currentDialogSubwindow_ = subwindow;
331 }
332
GetCurrentDialogWindow()333 const RefPtr<Subwindow>& SubwindowManager::GetCurrentDialogWindow()
334 {
335 std::lock_guard<std::mutex> lock(currentDialogSubwindowMutex_);
336 return currentDialogSubwindow_;
337 }
338
GetOrCreateSubWindow()339 RefPtr<Subwindow> SubwindowManager::GetOrCreateSubWindow()
340 {
341 auto containerId = Container::CurrentId();
342 LOGI("SubwindowManager::GetOrCreateSubWindow containerId = %{public}d.", containerId);
343 auto subwindow = GetDialogSubwindow(containerId);
344 if (!subwindow) {
345 LOGI("Subwindow is null, add a new one.");
346 subwindow = Subwindow::CreateSubwindow(containerId);
347 AddDialogSubwindow(containerId, subwindow);
348 }
349 return subwindow;
350 }
351
ShowToast(const std::string & message,int32_t duration,const std::string & bottom)352 void SubwindowManager::ShowToast(const std::string& message, int32_t duration, const std::string& bottom)
353 {
354 auto containerId = Container::CurrentId();
355 // Get active container when current instanceid is less than 0
356 if (containerId < 0) {
357 auto container = Container::GetActive();
358 if (container) {
359 containerId = container->GetInstanceId();
360 }
361 }
362 // for pa service
363 if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
364 auto subwindow = GetOrCreateSubWindow();
365 CHECK_NULL_VOID(subwindow);
366 subwindow->ShowToast(message, duration, bottom);
367 // for ability
368 } else {
369 auto subwindow = GetSubwindow(containerId);
370 if (!subwindow) {
371 LOGI("Subwindow is null, add a new one.");
372 subwindow = Subwindow::CreateSubwindow(containerId);
373 subwindow->InitContainer();
374 AddSubwindow(containerId, subwindow);
375 }
376 subwindow->ShowToast(message, duration, bottom);
377 }
378 }
379
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)380 void SubwindowManager::ShowDialog(const std::string& title, const std::string& message,
381 const std::vector<ButtonInfo>& buttons, bool autoCancel, std::function<void(int32_t, int32_t)>&& napiCallback,
382 const std::set<std::string>& dialogCallbacks)
383 {
384 auto containerId = Container::CurrentId();
385 // Get active container when current instanceid is less than 0
386 if (containerId < 0) {
387 auto container = Container::GetActive();
388 if (container) {
389 containerId = container->GetInstanceId();
390 }
391 }
392 // for pa service
393 if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
394 auto subwindow = GetOrCreateSubWindow();
395 CHECK_NULL_VOID(subwindow);
396 subwindow->ShowDialog(title, message, buttons, autoCancel, std::move(napiCallback), dialogCallbacks);
397 // for ability
398 } else {
399 auto subwindow = GetSubwindow(containerId);
400 if (!subwindow) {
401 LOGI("Subwindow is null, add a new one.");
402 subwindow = Subwindow::CreateSubwindow(containerId);
403 subwindow->InitContainer();
404 AddSubwindow(containerId, subwindow);
405 }
406 subwindow->ShowDialog(title, message, buttons, autoCancel, std::move(napiCallback), dialogCallbacks);
407 }
408 }
409
ShowActionMenu(const std::string & title,const std::vector<ButtonInfo> & button,std::function<void (int32_t,int32_t)> && callback)410 void SubwindowManager::ShowActionMenu(
411 const std::string& title, const std::vector<ButtonInfo>& button, std::function<void(int32_t, int32_t)>&& callback)
412 {
413 auto containerId = Container::CurrentId();
414 // Get active container when current instanceid is less than 0
415 if (containerId < 0) {
416 auto container = Container::GetActive();
417 if (container) {
418 containerId = container->GetInstanceId();
419 }
420 }
421 // for pa service
422 if (containerId >= MIN_PA_SERVICE_ID || containerId < 0) {
423 auto subwindow = GetOrCreateSubWindow();
424 CHECK_NULL_VOID(subwindow);
425 subwindow->ShowActionMenu(title, button, std::move(callback));
426 // for ability
427 } else {
428 auto subwindow = GetSubwindow(containerId);
429 if (!subwindow) {
430 LOGI("Subwindow is null, add a new one.");
431 subwindow = Subwindow::CreateSubwindow(containerId);
432 subwindow->InitContainer();
433 AddSubwindow(containerId, subwindow);
434 }
435 subwindow->ShowActionMenu(title, button, std::move(callback));
436 }
437 }
438
CloseDialog(int32_t instanceId)439 void SubwindowManager::CloseDialog(int32_t instanceId)
440 {
441 LOGI("SubwindowManager::CloseDialog containerId = %{public}d.", instanceId);
442 auto subwindow = GetDialogSubwindow(instanceId);
443 if (!subwindow) {
444 LOGE("SubwindowManager::CloseDialog Subwindow is null.");
445 return;
446 }
447 for (auto& containerMap : parentContainerMap_) {
448 if (containerMap.second == instanceId) {
449 subwindow->CloseDialog(containerMap.first);
450 }
451 }
452 }
453
HideSubWindowNG()454 void SubwindowManager::HideSubWindowNG()
455 {
456 RefPtr<Subwindow> subwindow;
457 auto container = Container::Current();
458 CHECK_NULL_VOID(container);
459 if (container->IsDialogContainer()) {
460 subwindow = GetCurrentDialogWindow();
461 } else {
462 subwindow = GetCurrentWindow();
463 }
464 if (subwindow) {
465 subwindow->HideSubWindowNG();
466 }
467 }
468 } // namespace OHOS::Ace
469