1/*
2 * Copyright (c) 2022-2023 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 "adapter/ohos/entrance/dialog_container.h"
17
18#include <mutex>
19
20#include "adapter/ohos/entrance/ace_application_info.h"
21#if defined(ENABLE_ROSEN_BACKEND) and !defined(UPLOAD_GPU_DISABLED)
22#include "adapter/ohos/entrance/ace_rosen_sync_task.h"
23#endif
24#include "adapter/ohos/entrance/ace_view_ohos.h"
25#include "base/log/frame_report.h"
26#include "base/log/log.h"
27#include "base/utils/utils.h"
28#include "core/common/ace_engine.h"
29#include "core/common/container_scope.h"
30#include "core/common/task_executor_impl.h"
31#include "core/common/text_field_manager.h"
32#include "core/components/theme/theme_constants.h"
33#include "core/components/theme/theme_manager_impl.h"
34#include "core/pipeline/pipeline_context.h"
35#include "core/pipeline_ng/pipeline_context.h"
36#include "frameworks/base/subwindow/subwindow_manager.h"
37#include "frameworks/bridge/common/utils/engine_helper.h"
38#include "frameworks/bridge/declarative_frontend/declarative_frontend.h"
39
40namespace OHOS::Ace::Platform {
41DialogContainer::DialogContainer(int32_t instanceId, FrontendType type) : instanceId_(instanceId), type_(type)
42{
43    auto taskExecutorImpl = Referenced::MakeRefPtr<TaskExecutorImpl>();
44    taskExecutorImpl->InitPlatformThread(true);
45    taskExecutor_ = taskExecutorImpl;
46    GetSettings().useUIAsJSThread = true;
47    GetSettings().usePlatformAsUIThread = true;
48    GetSettings().usingSharedRuntime = true;
49}
50
51void DialogContainer::InitializeTouchEventCallback()
52{
53    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
54    auto&& touchEventCallback = [context = pipelineContext_, id = instanceId_](
55                                    const TouchEvent& event, const std::function<void()>& markProcess,
56                                    const RefPtr<OHOS::Ace::NG::FrameNode>& node) {
57        ContainerScope scope(id);
58        context->GetTaskExecutor()->PostTask(
59            [context, event, markProcess]() {
60                context->OnTouchEvent(event);
61                context->NotifyDispatchTouchEventDismiss(event);
62                CHECK_NULL_VOID(markProcess);
63                markProcess();
64            },
65            TaskExecutor::TaskType::UI, "ArkUIDialogTouchEvent");
66    };
67    aceView_->RegisterTouchEventCallback(touchEventCallback);
68}
69
70void DialogContainer::InitializeMouseEventCallback()
71{
72    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
73    auto&& mouseEventCallback = [context = pipelineContext_, id = instanceId_](
74                                    const MouseEvent& event, const std::function<void()>& markProcess,
75                                    const RefPtr<OHOS::Ace::NG::FrameNode>& node) {
76        ContainerScope scope(id);
77        context->GetTaskExecutor()->PostTask(
78            [context, event, markProcess]() {
79                context->OnMouseEvent(event);
80                CHECK_NULL_VOID(markProcess);
81                markProcess();
82            },
83            TaskExecutor::TaskType::UI, "ArkUIDialogMouseEvent");
84    };
85    aceView_->RegisterMouseEventCallback(mouseEventCallback);
86}
87
88void DialogContainer::InitializeAxisEventCallback()
89{
90    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
91    auto&& axisEventCallback = [context = pipelineContext_, id = instanceId_](
92                                   const AxisEvent& event, const std::function<void()>& markProcess,
93                                   const RefPtr<OHOS::Ace::NG::FrameNode>& node) {
94        ContainerScope scope(id);
95        context->GetTaskExecutor()->PostTask(
96            [context, event, markProcess]() {
97                context->OnAxisEvent(event);
98                CHECK_NULL_VOID(markProcess);
99                markProcess();
100            },
101            TaskExecutor::TaskType::UI, "ArkUIDialogAxisEvent");
102    };
103    aceView_->RegisterAxisEventCallback(axisEventCallback);
104}
105
106void DialogContainer::InitializeKeyEventCallback()
107{
108    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
109    auto&& keyEventCallback = [context = pipelineContext_, id = instanceId_](const KeyEvent& event) {
110        ContainerScope scope(id);
111        bool result = false;
112        context->GetTaskExecutor()->PostSyncTask(
113            [context, event, &result]() { result = context->OnKeyEvent(event); },
114            TaskExecutor::TaskType::UI, "ArkUIDialogKeyEvent");
115        return result;
116    };
117    aceView_->RegisterKeyEventCallback(keyEventCallback);
118}
119
120void DialogContainer::InitializeRotationEventCallback()
121{
122    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
123    auto&& rotationEventCallback = [context = pipelineContext_, id = instanceId_](const RotationEvent& event) {
124        ContainerScope scope(id);
125        bool result = false;
126        context->GetTaskExecutor()->PostSyncTask(
127            [context, event, &result]() { result = context->OnRotationEvent(event); },
128            TaskExecutor::TaskType::UI, "ArkUIDialogRotationEvent");
129        return result;
130    };
131    aceView_->RegisterRotationEventCallback(rotationEventCallback);
132}
133
134void DialogContainer::InitializeViewChangeCallback()
135{
136    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
137    auto&& viewChangeCallback = [context = pipelineContext_, id = instanceId_](int32_t width, int32_t height,
138                                    WindowSizeChangeReason type,
139                                    const std::shared_ptr<Rosen::RSTransaction>& rsTransaction) {
140        ContainerScope scope(id);
141        ACE_SCOPED_TRACE("ViewChangeCallback(%d, %d)", width, height);
142        context->GetTaskExecutor()->PostTask(
143            [context, width, height, type, rsTransaction]() {
144                context->OnSurfaceChanged(width, height, type, rsTransaction);
145            },
146            TaskExecutor::TaskType::UI, "ArkUIDialogSurfaceChanged");
147    };
148    aceView_->RegisterViewChangeCallback(viewChangeCallback);
149}
150
151void DialogContainer::InitializeDensityChangeCallback()
152{
153    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
154    auto&& densityChangeCallback = [context = pipelineContext_, id = instanceId_](double density) {
155        ContainerScope scope(id);
156        ACE_SCOPED_TRACE("DensityChangeCallback(%lf)", density);
157        context->GetTaskExecutor()->PostTask(
158            [context, density]() { context->OnSurfaceDensityChanged(density); },
159            TaskExecutor::TaskType::UI, "ArkUIDialogSurfaceDensityChanged");
160    };
161    aceView_->RegisterDensityChangeCallback(densityChangeCallback);
162}
163
164void DialogContainer::InitializeSystemBarHeightChangeCallback()
165{
166    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
167    auto&& systemBarHeightChangeCallback = [context = pipelineContext_, id = instanceId_](
168                                               double statusBar, double navigationBar) {
169        ContainerScope scope(id);
170        ACE_SCOPED_TRACE("SystemBarHeightChangeCallback(%lf, %lf)", statusBar, navigationBar);
171        context->GetTaskExecutor()->PostTask(
172            [context, statusBar, navigationBar]() { context->OnSystemBarHeightChanged(statusBar, navigationBar); },
173            TaskExecutor::TaskType::UI, "ArkUIDialogSystemBarHeightChanged");
174    };
175    aceView_->RegisterSystemBarHeightChangeCallback(systemBarHeightChangeCallback);
176}
177
178void DialogContainer::InitializeSurfaceDestroyCallback()
179{
180    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
181    auto&& surfaceDestroyCallback = [context = pipelineContext_, id = instanceId_]() {
182        ContainerScope scope(id);
183        context->GetTaskExecutor()->PostTask(
184            [context]() { context->OnSurfaceDestroyed(); },
185            TaskExecutor::TaskType::UI, "ArkUIDialogSurfaceDestroyed");
186    };
187    aceView_->RegisterSurfaceDestroyCallback(surfaceDestroyCallback);
188}
189
190void DialogContainer::InitializeDragEventCallback()
191{
192    ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
193    auto&& dragEventCallback = [context = pipelineContext_, id = instanceId_](
194                                    const PointerEvent& pointerEvent, const DragEventAction& action,
195                                    const RefPtr<OHOS::Ace::NG::FrameNode>& node) {
196        ContainerScope scope(id);
197        context->GetTaskExecutor()->PostTask(
198            [context, pointerEvent, action, node]() { context->OnDragEvent(pointerEvent, action, node); },
199            TaskExecutor::TaskType::UI, "ArkUIDialogDragEvent");
200    };
201    aceView_->RegisterDragEventCallback(dragEventCallback);
202}
203
204void DialogContainer::InitializeCallback()
205{
206    ACE_FUNCTION_TRACE();
207    InitializeTouchEventCallback();
208    InitializeMouseEventCallback();
209    InitializeAxisEventCallback();
210    InitializeKeyEventCallback();
211    InitializeRotationEventCallback();
212    InitializeViewChangeCallback();
213    InitializeDensityChangeCallback();
214    InitializeSystemBarHeightChangeCallback();
215    InitializeSurfaceDestroyCallback();
216    InitializeDragEventCallback();
217}
218
219RefPtr<DialogContainer> DialogContainer::GetContainer(int32_t instanceId)
220{
221    auto container = AceEngine::Get().GetContainer(instanceId);
222    CHECK_NULL_RETURN(container, nullptr);
223    auto dialogContainer = AceType::DynamicCast<DialogContainer>(container);
224    return dialogContainer;
225}
226
227void DialogContainer::DestroyContainer(int32_t instanceId, const std::function<void()>& destroyCallback)
228{
229    TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer DestroyContainer begin %{public}d", instanceId);
230    auto container = AceEngine::Get().GetContainer(instanceId);
231    CHECK_NULL_VOID(container);
232    container->Destroy();
233    auto taskExecutor = container->GetTaskExecutor();
234    CHECK_NULL_VOID(taskExecutor);
235    taskExecutor->PostSyncTask(
236        [] { TAG_LOGI(AceLogTag::ACE_DIALOG,  "Wait UI thread..."); },
237        TaskExecutor::TaskType::UI, "ArkUIDialogWaitLog");
238    taskExecutor->PostSyncTask(
239        [] { TAG_LOGI(AceLogTag::ACE_DIALOG,  "Wait JS thread..."); },
240        TaskExecutor::TaskType::JS, "ArkUIDialogWaitLog");
241    container->DestroyView(); // Stop all threads(ui,gpu,io) for current ability.
242    taskExecutor->PostTask(
243        [instanceId, destroyCallback] {
244            TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer DestroyContainer Remove on Platform thread...");
245            EngineHelper::RemoveEngine(instanceId);
246            AceEngine::Get().RemoveContainer(instanceId);
247            CHECK_NULL_VOID(destroyCallback);
248            destroyCallback();
249        },
250        TaskExecutor::TaskType::PLATFORM, "ArkUIDialogContainerDestroy");
251}
252
253void DialogContainer::Destroy()
254{
255    TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer Destroy begin");
256    ContainerScope scope(instanceId_);
257    if (pipelineContext_ && taskExecutor_) {
258        // 1. Destroy Pipeline on UI thread.
259        RefPtr<PipelineBase>& context = pipelineContext_;
260        if (GetSettings().usePlatformAsUIThread) {
261            context->Destroy();
262        } else {
263            taskExecutor_->PostTask([context]() { context->Destroy(); },
264                TaskExecutor::TaskType::UI, "ArkUIDialogDestoryPipeline");
265        }
266        // 2. Destroy Frontend on JS thread.
267        RefPtr<Frontend>& frontend = frontend_;
268        if (GetSettings().usePlatformAsUIThread && GetSettings().useUIAsJSThread) {
269            frontend->UpdateState(Frontend::State::ON_DESTROY);
270            frontend->Destroy();
271        } else {
272            taskExecutor_->PostTask(
273                [frontend]() {
274                    frontend->UpdateState(Frontend::State::ON_DESTROY);
275                    frontend->Destroy();
276                },
277                TaskExecutor::TaskType::JS, "ArkUIDialogFrontendDestroy");
278        }
279    }
280    DestroyToastSubwindow(instanceId_);
281    resRegister_.Reset();
282    assetManager_.Reset();
283}
284
285void DialogContainer::DestroyView()
286{
287    TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer DestroyView begin");
288    ContainerScope scope(instanceId_);
289    std::lock_guard<std::mutex> lock(viewMutex_);
290    aceView_ = nullptr;
291}
292
293void DialogContainer::SetView(
294    const RefPtr<AceView>& view, double density, int32_t width, int32_t height, sptr<OHOS::Rosen::Window>& rsWindow)
295{
296    CHECK_NULL_VOID(view);
297    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(view->GetInstanceId()));
298    CHECK_NULL_VOID(container);
299#ifdef ENABLE_ROSEN_BACKEND
300    auto taskExecutor = container->GetTaskExecutor();
301    CHECK_NULL_VOID(taskExecutor);
302
303    auto window = std::make_shared<NG::RosenWindow>(rsWindow, taskExecutor, view->GetInstanceId());
304#else
305    auto platformWindow = PlatformWindow::Create(view);
306    CHECK_NULL_VOID(platformWindow);
307    auto window = std::make_shared<Window>(std::move(platformWindow));
308#endif
309    container->AttachView(std::move(window), view, density, width, height, rsWindow->GetWindowId());
310}
311
312void DialogContainer::SetViewNew(
313    const RefPtr<AceView>& view, double density, int32_t width, int32_t height, sptr<OHOS::Rosen::Window>& rsWindow)
314{
315#ifdef ENABLE_ROSEN_BACKEND
316    CHECK_NULL_VOID(view);
317    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(view->GetInstanceId()));
318    CHECK_NULL_VOID(container);
319    auto taskExecutor = container->GetTaskExecutor();
320    CHECK_NULL_VOID(taskExecutor);
321
322    auto window = std::make_shared<NG::RosenWindow>(rsWindow, taskExecutor, view->GetInstanceId());
323    container->AttachView(std::move(window), view, density, width, height, rsWindow->GetWindowId());
324#endif
325}
326
327void DialogContainer::AttachView(std::shared_ptr<Window> window, const RefPtr<AceView>& view, double density,
328    int32_t width, int32_t height, uint32_t windowId)
329{
330    aceView_ = view;
331    auto instanceId = aceView_->GetInstanceId();
332    auto taskExecutorImpl = AceType::DynamicCast<TaskExecutorImpl>(taskExecutor_);
333    auto aceView = AceType::DynamicCast<AceViewOhos>(aceView_);
334    ACE_DCHECK(aceView != nullptr);
335    taskExecutorImpl->InitOtherThreads(aceView->GetThreadModelImpl());
336    ContainerScope scope(instanceId);
337    // For DECLARATIVE_JS frontend display UI in JS thread temporarily.
338    taskExecutorImpl->InitJsThread(false);
339    InitializeFrontend();
340    SetUseNewPipeline();
341
342    InitPipelineContext(std::move(window), instanceId, density, width, height, windowId);
343    InitializeCallback();
344    CheckAndSetFontFamily();
345
346    taskExecutor_->PostTask([] { FrameReport::GetInstance().Init(); },
347        TaskExecutor::TaskType::UI, "ArkUIDialogFrameReportInit");
348    ThemeConstants::InitDeviceType();
349    // Load custom style at UI thread before frontend attach, to make sure style can be loaded before building dom tree.
350    RefPtr<ThemeManagerImpl> themeManager = nullptr;
351    if (SystemProperties::GetResourceDecoupling()) {
352        auto resAdapter = ResourceAdapter::CreateV2();
353        themeManager = AceType::MakeRefPtr<ThemeManagerImpl>(resAdapter);
354    } else {
355        themeManager = AceType::MakeRefPtr<ThemeManagerImpl>();
356    }
357    if (themeManager) {
358        pipelineContext_->SetThemeManager(themeManager);
359        // Init resource
360        themeManager->InitResource(resourceInfo_);
361        taskExecutor_->PostTask(
362            [themeManager, assetManager = assetManager_, colorScheme = colorScheme_] {
363                ACE_SCOPED_TRACE("OHOS::LoadThemes()");
364                TAG_LOGI(AceLogTag::ACE_DIALOG, "UIContent load theme");
365                themeManager->SetColorScheme(colorScheme);
366                themeManager->LoadCustomTheme(assetManager);
367                themeManager->LoadResourceThemes();
368            },
369            TaskExecutor::TaskType::UI, "ArkUIDialogLoadTheme");
370    }
371    aceView_->Launch();
372    // Only MainWindow instance will be registered to watch dog.
373    frontend_->AttachPipelineContext(pipelineContext_);
374#if defined(ENABLE_ROSEN_BACKEND) and !defined(UPLOAD_GPU_DISABLED)
375    pipelineContext_->SetPostRTTaskCallBack([](std::function<void()>&& task) {
376        auto syncTask = std::make_shared<AceRosenSyncTask>(std::move(task));
377        Rosen::RSTransactionProxy::GetInstance()->ExecuteSynchronousTask(syncTask);
378    });
379#endif
380}
381
382void DialogContainer::InitPipelineContext(std::shared_ptr<Window> window, int32_t instanceId, double density,
383    int32_t width, int32_t height, uint32_t windowId)
384{
385#ifdef NG_BUILD
386    TAG_LOGI(AceLogTag::ACE_DIALOG, "New pipeline version creating...");
387    pipelineContext_ = AceType::MakeRefPtr<NG::PipelineContext>(
388        std::move(window), taskExecutor_, assetManager_, resRegister_, frontend_, instanceId);
389#else
390    if (useNewPipeline_) {
391        TAG_LOGI(AceLogTag::ACE_DIALOG, "New pipeline version creating...");
392        pipelineContext_ = AceType::MakeRefPtr<NG::PipelineContext>(
393            std::move(window), taskExecutor_, assetManager_, resRegister_, frontend_, instanceId);
394    } else {
395        pipelineContext_ = AceType::MakeRefPtr<PipelineContext>(
396            std::move(window), taskExecutor_, assetManager_, resRegister_, frontend_, instanceId);
397    }
398#endif
399    pipelineContext_->SetRootSize(density, width, height);
400    pipelineContext_->SetTextFieldManager(AceType::MakeRefPtr<TextFieldManager>());
401    pipelineContext_->SetIsRightToLeft(AceApplicationInfo::GetInstance().IsRightToLeft());
402    pipelineContext_->SetWindowId(windowId);
403    pipelineContext_->SetWindowModal(windowModal_);
404    pipelineContext_->SetDrawDelegate(aceView_->GetDrawDelegate());
405    pipelineContext_->SetIsSubPipeline(true);
406}
407
408void DialogContainer::InitializeFrontend()
409{
410    frontend_ = AceType::MakeRefPtr<DeclarativeFrontend>();
411    CHECK_NULL_VOID(frontend_);
412    frontend_->Initialize(type_, taskExecutor_);
413    auto front = GetFrontend();
414    CHECK_NULL_VOID(front);
415    front->UpdateState(Frontend::State::ON_CREATE);
416    front->SetJsMessageDispatcher(AceType::Claim(this));
417    front->SetAssetManager(assetManager_);
418}
419
420void DialogContainer::DumpHeapSnapshot(bool isPrivate)
421{
422    taskExecutor_->PostTask(
423        [isPrivate, frontend = WeakPtr<Frontend>(frontend_)] {
424            auto sp = frontend.Upgrade();
425            CHECK_NULL_VOID(sp);
426            sp->DumpHeapSnapshot(isPrivate);
427        },
428        TaskExecutor::TaskType::JS, "ArkUIDialogDumpHeapSnapshot");
429}
430void DialogContainer::SetUIWindow(int32_t instanceId, sptr<OHOS::Rosen::Window>& uiWindow)
431{
432    CHECK_NULL_VOID(uiWindow);
433    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
434    CHECK_NULL_VOID(container);
435    container->SetUIWindowInner(uiWindow);
436}
437
438sptr<OHOS::Rosen::Window> DialogContainer::GetUIWindow(int32_t instanceId)
439{
440    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
441    CHECK_NULL_RETURN(container, nullptr);
442    return container->GetUIWindowInner();
443}
444
445void DialogContainer::SetUIWindowInner(sptr<OHOS::Rosen::Window> uiWindow)
446{
447    uiWindow_ = std::move(uiWindow);
448}
449
450sptr<OHOS::Rosen::Window> DialogContainer::GetUIWindowInner() const
451{
452    return uiWindow_;
453}
454
455void DialogContainer::ShowToast(int32_t instanceId, const std::string& message, int32_t duration,
456    const std::string& bottom, std::function<void(int32_t)>&& callback)
457{
458    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
459    CHECK_NULL_VOID(container);
460    auto frontend = AceType::DynamicCast<DeclarativeFrontend>(container->GetFrontend());
461    CHECK_NULL_VOID(frontend);
462    auto delegate = frontend->GetDelegate();
463    CHECK_NULL_VOID(delegate);
464    delegate->SetToastStopListenerCallback([instanceId = instanceId]() {
465        if (ContainerScope::CurrentId() >= 0) {
466            DialogContainer::HideWindow(instanceId);
467        }
468    });
469    auto toastInfo = NG::ToastInfo { .message = message,
470        .duration = duration,
471        .bottom = bottom,
472        .showMode = NG::ToastShowMode::DEFAULT,
473        .alignment = -1,
474        .offset = std::nullopt };
475    delegate->ShowToast(toastInfo, std::move(callback));
476}
477
478void DialogContainer::CloseToast(int32_t instanceId, int32_t toastId, std::function<void(int32_t)>&& callback)
479{
480    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
481    CHECK_NULL_VOID(container);
482
483    auto frontend = AceType::DynamicCast<DeclarativeFrontend>(container->GetFrontend());
484    CHECK_NULL_VOID(frontend);
485
486    auto delegate = frontend->GetDelegate();
487    CHECK_NULL_VOID(delegate);
488    delegate->SetToastStopListenerCallback([instanceId = instanceId]() {
489        if (ContainerScope::CurrentId() >= 0) {
490            DialogContainer::HideWindow(instanceId);
491        }
492    });
493
494    delegate->CloseToast(toastId, std::move(callback));
495}
496
497void DialogContainer::ShowDialog(int32_t instanceId, const std::string& title, const std::string& message,
498    const std::vector<ButtonInfo>& buttons, bool autoCancel, std::function<void(int32_t, int32_t)>&& callback,
499    const std::set<std::string>& callbacks)
500{
501    TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer ShowDialog begin");
502    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
503    CHECK_NULL_VOID(container);
504    auto frontend = AceType::DynamicCast<DeclarativeFrontend>(container->GetFrontend());
505    CHECK_NULL_VOID(frontend);
506    auto delegate = frontend->GetDelegate();
507    CHECK_NULL_VOID(delegate);
508    delegate->ShowDialog(
509        title, message, buttons, autoCancel, std::move(callback), callbacks, [instanceId = instanceId](bool isShow) {
510            TAG_LOGI(
511                AceLogTag::ACE_DIALOG, "DialogContainer ShowDialog HideWindow instanceId = %{public}d", instanceId);
512            if (!isShow) {
513                DialogContainer::HideWindow(instanceId);
514            }
515        });
516}
517
518void DialogContainer::ShowDialog(int32_t instanceId, const PromptDialogAttr& dialogAttr,
519    const std::vector<ButtonInfo>& buttons, std::function<void(int32_t, int32_t)>&& callback,
520    const std::set<std::string>& callbacks)
521{
522    TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer ShowDialog with attr begin");
523    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
524    CHECK_NULL_VOID(container);
525    auto frontend = AceType::DynamicCast<DeclarativeFrontend>(container->GetFrontend());
526    CHECK_NULL_VOID(frontend);
527    auto delegate = frontend->GetDelegate();
528    CHECK_NULL_VOID(delegate);
529    delegate->ShowDialog(dialogAttr, buttons, std::move(callback), callbacks, [instanceId = instanceId](bool isShow) {
530        TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer ShowDialog HideWindow instanceId = %{public}d", instanceId);
531        if (!isShow) {
532            DialogContainer::HideWindow(instanceId);
533        }
534    });
535}
536
537void DialogContainer::ShowActionMenu(int32_t instanceId, const std::string& title,
538    const std::vector<ButtonInfo>& button, std::function<void(int32_t, int32_t)>&& callback)
539{
540    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
541    CHECK_NULL_VOID(container);
542    auto frontend = AceType::DynamicCast<DeclarativeFrontend>(container->GetFrontend());
543    CHECK_NULL_VOID(frontend);
544    auto delegate = frontend->GetDelegate();
545    CHECK_NULL_VOID(delegate);
546    delegate->ShowActionMenu(title, button, std::move(callback), [instanceId = instanceId](bool isShow) {
547        if (!isShow) {
548            DialogContainer::HideWindow(instanceId);
549        }
550    });
551}
552
553bool DialogContainer::ShowToastDialogWindow(
554    int32_t instanceId, int32_t posX, int32_t posY, int32_t width, int32_t height, bool isToast)
555{
556    TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer ShowToastDialogWindow begin");
557    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
558    CHECK_NULL_RETURN(container, false);
559    auto window = container->GetUIWindowInner();
560    CHECK_NULL_RETURN(window, false);
561    window->SetTransparent(true);
562    if (isToast) {
563        window->SetTouchable(false);
564    }
565    window->SetNeedDefaultAnimation(false);
566    OHOS::Rosen::WMError ret = window->MoveTo(posX, posY);
567    if (ret != OHOS::Rosen::WMError::WM_OK) {
568        TAG_LOGW(AceLogTag::ACE_DIALOG, "DialogContainer ShowToastDialogWindow MoveTo window failed code: %{public}d",
569            static_cast<int32_t>(ret));
570        return false;
571    }
572    ret = window->Resize(width, height);
573    if (ret != OHOS::Rosen::WMError::WM_OK) {
574        TAG_LOGW(AceLogTag::ACE_DIALOG, "DialogContainer ShowToastDialogWindow Resize window failed code: %{public}d",
575            static_cast<int32_t>(ret));
576        return false;
577    }
578    ret = window->Show();
579    if (ret != OHOS::Rosen::WMError::WM_OK) {
580        TAG_LOGE(AceLogTag::ACE_DIALOG, "DialogContainer ShowToastDialogWindow Show window failed code: %{public}d",
581            static_cast<int32_t>(ret));
582        return false;
583    }
584    return true;
585}
586
587bool DialogContainer::HideWindow(int32_t instanceId)
588{
589    TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer HideWindow begin");
590    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
591    CHECK_NULL_RETURN(container, false);
592    auto window = container->GetUIWindowInner();
593    CHECK_NULL_RETURN(window, false);
594    OHOS::Rosen::WMError ret = window->Hide();
595    if (ret != OHOS::Rosen::WMError::WM_OK) {
596        TAG_LOGE(AceLogTag::ACE_DIALOG, "DialogContainer HideWindow Failed to hide the window.");
597        return false;
598    }
599    sptr<OHOS::Rosen::Window> uiWindow = nullptr;
600    DialogContainer::SetUIWindow(instanceId, uiWindow);
601    return true;
602}
603
604bool DialogContainer::CloseWindow(int32_t instanceId)
605{
606    TAG_LOGI(AceLogTag::ACE_DIALOG, "DialogContainer CloseWindow begin");
607    auto container = AceType::DynamicCast<DialogContainer>(AceEngine::Get().GetContainer(instanceId));
608    CHECK_NULL_RETURN(container, false);
609    auto window = container->GetUIWindowInner();
610    CHECK_NULL_RETURN(window, false);
611    OHOS::Rosen::WMError ret = window->Close();
612    if (ret != OHOS::Rosen::WMError::WM_OK) {
613        TAG_LOGE(AceLogTag::ACE_DIALOG, "DialogContainer CloseWindow Failed to close the window.");
614        return false;
615    }
616    sptr<OHOS::Rosen::Window> uiWindow = nullptr;
617    DialogContainer::SetUIWindow(instanceId, uiWindow);
618    return true;
619}
620
621bool DialogContainer::OnBackPressed(int32_t instanceId)
622{
623    return DialogContainer::CloseWindow(instanceId);
624}
625
626void DialogContainer::SetFontScaleAndWeightScale(int32_t instanceId)
627{
628    float fontScale = SystemProperties::GetFontScale();
629    float fontWeightScale = SystemProperties::GetFontWeightScale();
630    Container::SetFontScale(instanceId, fontScale);
631    Container::SetFontWeightScale(instanceId, fontWeightScale);
632}
633
634void DialogContainer::UpdateConfiguration(const ParsedConfig& parsedConfig)
635{
636    if (!parsedConfig.IsValid()) {
637        LOGW("DialogContainer::OnConfigurationUpdated param is empty");
638        return;
639    }
640
641    CHECK_NULL_VOID(pipelineContext_);
642    auto themeManager = pipelineContext_->GetThemeManager();
643    CHECK_NULL_VOID(themeManager);
644    auto resConfig = GetResourceConfiguration();
645    if (!parsedConfig.colorMode.empty()) {
646        if (parsedConfig.colorMode == "dark") {
647            SystemProperties::SetColorMode(ColorMode::DARK);
648            resConfig.SetColorMode(ColorMode::DARK);
649        } else {
650            SystemProperties::SetColorMode(ColorMode::LIGHT);
651            resConfig.SetColorMode(ColorMode::LIGHT);
652        }
653    }
654
655    SetResourceConfiguration(resConfig);
656    themeManager->UpdateConfig(resConfig);
657    themeManager->LoadResourceThemes();
658    // change color mode and theme to clear image cache
659    pipelineContext_->ClearImageCache();
660}
661
662void DialogContainer::CheckAndSetFontFamily()
663{
664    CHECK_NULL_VOID(pipelineContext_);
665    auto fontManager = pipelineContext_->GetFontManager();
666    CHECK_NULL_VOID(fontManager);
667    if (fontManager->IsUseAppCustomFont()) {
668        return;
669    }
670    std::string familyName = "";
671    std::string path = "/data/themes/a/app";
672    if (!IsFontFileExistInPath(path)) {
673        path = "/data/themes/b/app";
674        if (!IsFontFileExistInPath(path)) {
675            return;
676        }
677    }
678    path = path.append("/fonts/");
679    familyName = GetFontFamilyName(path);
680    if (familyName.empty()) {
681        return;
682    }
683    path = path.append(familyName);
684    fontManager->SetFontFamily(familyName.c_str(), path.c_str());
685}
686} // namespace OHOS::Ace::Platform
687