From e8dc6c8806a8a54997aade945311baec5d6c9dae Mon Sep 17 00:00:00 2001 From: Far Date: Sun, 2 Mar 2025 14:46:35 +0800 Subject: [PATCH] Add create/destroy container without window interface. Signed-off-by: Far Change-Id: Ifbabc8127f34fca5fa469dba95b67009c440189f --- .gitee/CODEOWNERS | 3 + adapter/ohos/entrance/BUILD.gn | 1 + adapter/ohos/entrance/ace_container.h | 1 + .../ohos/entrance/window_free_container.cpp | 240 ++++++++++++++++++ adapter/preview/entrance/BUILD.gn | 1 + adapter/preview/entrance/ace_container.h | 1 + .../entrance/window_free_container.cpp | 79 ++++++ adapter/preview/sdk/sharedlib_config.gni | 6 + build/libace.map | 2 + frameworks/base/i18n/localization.h | 6 + .../engine/jsUIContext.js | 19 +- .../arkts_native_common_bridge.cpp | 4 +- frameworks/core/common/container_consts.h | 2 + .../core/common/window_free_container.h | 30 +++ .../render/adapter/rosen_window.cpp | 8 +- interfaces/napi/kits/container_utils/BUILD.gn | 64 +++++ .../container_utils/js_container_utils.cpp | 100 ++++++++ interfaces/napi/kits/napi_lib.gni | 4 + 18 files changed, 567 insertions(+), 4 deletions(-) create mode 100644 adapter/ohos/entrance/window_free_container.cpp create mode 100644 adapter/preview/entrance/window_free_container.cpp create mode 100644 frameworks/core/common/window_free_container.h create mode 100644 interfaces/napi/kits/container_utils/BUILD.gn create mode 100644 interfaces/napi/kits/container_utils/js_container_utils.cpp diff --git a/.gitee/CODEOWNERS b/.gitee/CODEOWNERS index bff9688e7c2..bc4cf35aaf3 100644 --- a/.gitee/CODEOWNERS +++ b/.gitee/CODEOWNERS @@ -83,6 +83,7 @@ adapter/ohos/entrance/ui_event_impl.h @arkuiframework adapter/ohos/entrance/ui_session/ @arkuiframework adapter/ohos/entrance/utils.cpp @arkuiframework adapter/ohos/entrance/utils.h @arkuiframework +adapter/ohos/entrance/window_free_container.cpp @arkuiframework adapter/ohos/entrance/vibrator/vibrator_utils.cpp @arkuiscroll adapter/ohos/entrance/window/drag_window_ohos.cpp @arkuievent adapter/ohos/entrance/window/drag_window_ohos.h @arkuievent @@ -179,6 +180,7 @@ adapter/ohos/services/ @arkuiframework adapter/ohos/tools/raw_input_injector/ @arkuievent [Preview adapter] +adapter/preview/entrance/window_free_container.cpp @arkuiframework adapter/preview/ @arkuistatemgmt [Advanced UI Components] @@ -3014,6 +3016,7 @@ interfaces/napi/kits/BUILD.gn @arkui_architecture interfaces/napi/kits/component_snapshot/ @arkuievent interfaces/napi/kits/componentutils/ @arkuievent interfaces/napi/kits/configuration/ @arkuiframework +interfaces/napi/kits/container_utils/ @arkuiframework interfaces/napi/kits/device/ @arkuiframework interfaces/napi/kits/display_sync/ @arkuiframework interfaces/napi/kits/drag_controller/ @arkuievent diff --git a/adapter/ohos/entrance/BUILD.gn b/adapter/ohos/entrance/BUILD.gn index 34e6ee621eb..715ee017826 100644 --- a/adapter/ohos/entrance/BUILD.gn +++ b/adapter/ohos/entrance/BUILD.gn @@ -50,6 +50,7 @@ template("ace_ohos_standard_source_set") { "$ace_root/adapter/ohos/entrance/subwindow/subwindow_ohos.cpp", "$ace_root/adapter/ohos/entrance/touch_event_convertor.cpp", "$ace_root/adapter/ohos/entrance/window/foldable_window_ohos.cpp", + "$ace_root/adapter/ohos/entrance/window_free_container.cpp", # innerkits impl "$ace_root/adapter/ohos/entrance/ui_content_impl.cpp", diff --git a/adapter/ohos/entrance/ace_container.h b/adapter/ohos/entrance/ace_container.h index 08fcb6c17fa..b692f9e7fcf 100644 --- a/adapter/ohos/entrance/ace_container.h +++ b/adapter/ohos/entrance/ace_container.h @@ -915,6 +915,7 @@ private: std::shared_ptr currentPointerEvent_; std::unordered_map> stopDragCallbackMap_; std::map> currentEvents_; + friend class WindowFreeContainer; ACE_DISALLOW_COPY_AND_MOVE(AceContainer); RefPtr renderBoundaryManager_ = Referenced::MakeRefPtr(); diff --git a/adapter/ohos/entrance/window_free_container.cpp b/adapter/ohos/entrance/window_free_container.cpp new file mode 100644 index 00000000000..437cda1df57 --- /dev/null +++ b/adapter/ohos/entrance/window_free_container.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ability_info.h" +#include "ability_context.h" +#include "ui_extension_context.h" + +#include "adapter/ohos/entrance/ace_container.h" +#include "adapter/ohos/entrance/ace_application_info.h" +#include "adapter/ohos/entrance/ace_view_ohos.h" +#include "adapter/ohos/entrance/hap_asset_provider_impl.h" +#include "adapter/ohos/entrance/file_asset_provider_impl.h" +#include "frameworks/base/i18n/localization.h" +#include "frameworks/core/common/ace_engine.h" +#include "frameworks/core/common/ace_view.h" +#include "frameworks/core/common/asset_manager_impl.h" +#include "frameworks/core/common/window_free_container.h" +#include "frameworks/core/components_ng/render/adapter/rosen_window.h" + +namespace OHOS::Ace::Platform { +namespace { +static RefPtr g_WindowFreeContainer = nullptr; + +constexpr char ABS_BUNDLE_CODE_PATH[] = "/data/app/el1/bundle/public/"; +constexpr char LOCAL_BUNDLE_CODE_PATH[] = "/data/storage/el1/bundle/"; +constexpr char FILE_SEPARATOR[] = "/"; + +} + +class PseudoEventCallback final : public Platform::PlatformEventCallback { +public: + PseudoEventCallback() = default; + virtual ~PseudoEventCallback() = default; + void OnFinish() const override {} + void OnStatusBarBgColorChanged(uint32_t) override {} +}; + +void InitAssetManager(RefPtr &assetManagerImpl, std::shared_ptr info, + std::shared_ptr context) +{ + if (!assetManagerImpl) { + return; + } + + bool isModelJson = info != nullptr ? info->isModuleJson : false; + if (!isModelJson) { + LOGW("The application doesn't use module.json5."); + return; + } + + std::string moduleName = info != nullptr ? info->moduleName : ""; + auto appInfo = context != nullptr ? context->GetApplicationInfo() : nullptr; + auto hapModuleInfo = context != nullptr ? context->GetHapModuleInfo() : nullptr; + auto bundleName = info != nullptr ? info->bundleName : ""; + std::string resPath; + + std::string hapPath = info != nullptr ? info->hapPath : ""; + // first use hap provider + if (!hapPath.empty()) { + auto hapAssetProviderImpl = AceType::MakeRefPtr(); + if (hapAssetProviderImpl->Initialize(hapPath, { "", "ets/", "resources/base/profile/" })) { + assetManagerImpl->PushBack(std::move(hapAssetProviderImpl)); + } + } + + if (appInfo) { + std::vector moduleList = appInfo->moduleInfos; + for (const auto& module : moduleList) { + if (module.moduleName == moduleName) { + std::regex pattern(ABS_BUNDLE_CODE_PATH + bundleName + FILE_SEPARATOR); + auto moduleSourceDir = + std::regex_replace(module.moduleSourceDir, pattern, LOCAL_BUNDLE_CODE_PATH); + resPath = moduleSourceDir + "/"; + break; + } + } + } + + // second use file provider, will remove later + auto assetBasePathStr = { std::string("ets/"), std::string("resources/base/profile/") }; + if (!resPath.empty()) { + auto assetProvider = AceType::MakeRefPtr(); + if (assetProvider->Initialize(resPath, assetBasePathStr)) { + assetManagerImpl->PushBack(std::move(assetProvider)); + } + } +} + +std::shared_ptr GetAbilityInfo(std::shared_ptr& context, + std::string& tempDir) +{ + std::shared_ptr info; + auto abilityContext = OHOS::AbilityRuntime::Context::ConvertTo(context); + if (abilityContext) { + info = abilityContext->GetAbilityInfo(); + tempDir = abilityContext->GetTempDir(); + return info; + } + + auto extensionContext = + OHOS::AbilityRuntime::Context::ConvertTo(context); + if (extensionContext) { + info = extensionContext->GetAbilityInfo(); + } + return info; +} + +std::string GetHapPath(std::shared_ptr& info) +{ + std::string hapPath; + std::string moduleHapPath = info != nullptr ? info->hapPath : ""; + if (moduleHapPath.empty()) { + return hapPath; + } + + if (moduleHapPath.find(ABS_BUNDLE_CODE_PATH) == std::string::npos) { + hapPath = moduleHapPath; + } else { + auto pos = moduleHapPath.find_last_of('/'); + if (pos != std::string::npos) { + hapPath = LOCAL_BUNDLE_CODE_PATH + moduleHapPath.substr(pos + 1); + } + } + return hapPath; +} + +void InitLocalizationIfNeeded(std::shared_ptr& context) +{ + if (Localization::GetInstance()->IsInit()) { + return; + } + + std::unique_ptr resConfig(Global::Resource::CreateResConfig()); + auto resourceManager = context->GetResourceManager(); + if (resourceManager == nullptr) { + return; + } + + resourceManager->GetResConfig(*resConfig); + auto localeInfo = resConfig->GetLocaleInfo(); + Platform::AceApplicationInfoImpl::GetInstance().SetResourceManager(resourceManager); + if (localeInfo != nullptr) { + auto language = localeInfo->getLanguage(); + auto region = localeInfo->getCountry(); + auto script = localeInfo->getScript(); + AceApplicationInfo::GetInstance().SetLocale((language == nullptr) ? "" : language, + (region == nullptr) ? "" : region, (script == nullptr) ? "" : script, ""); + } +} + +double GetDensity() +{ + double density = 1.0; + auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay(); + if (defaultDisplay) { + auto temp = defaultDisplay->GetVirtualPixelRatio(); + if (!NearEqual(temp, 1.0f)) { + density = temp; + } + } + return density; +} + +RefPtr WindowFreeContainer::CreateWindowFreeContainer(void *runtime, void *ctx) +{ + if (g_WindowFreeContainer) { + return g_WindowFreeContainer; + } + CHECK_NULL_RETURN(runtime, nullptr); + CHECK_NULL_RETURN(ctx, nullptr); + int32_t instanceId = Container::GenerateId(); + + std::shared_ptr context = + (static_cast*>(ctx))->lock(); + CHECK_NULL_RETURN(context, nullptr); + std::string tempDir; + std::shared_ptr info = GetAbilityInfo(context, tempDir); + auto container = AceType::MakeRefPtr(instanceId, FrontendType::DECLARATIVE_JS, + context, info, std::make_unique(), false, false, true); + if (!container) { + LOGW("Create container failed."); + return container; + } + + AceEngine::Get().AddContainer(instanceId, container); + g_WindowFreeContainer = container; + + container->SetSharedRuntime(runtime); + container->GetSettings().SetUsingSharedRuntime(true); + container->GetSettings().usePlatformAsUIThread = true; + container->GetSettings().useUIAsJSThread = true; + + container->Initialize(); + container->SetBundlePath(context->GetBundleCodeDir()); + container->SetFilesDataPath(context->GetFilesDir()); + std::string hapPath = GetHapPath(info); + container->SetHapPath(hapPath); + container->SetTempDir(tempDir); + + ContainerScope scope(instanceId); + InitLocalizationIfNeeded(context); + RefPtr assetManagerImpl; + InitAssetManager(assetManagerImpl, info, context); + container->SetAssetManager(assetManagerImpl); + + auto window = std::make_shared(nullptr, container->GetTaskExecutor(), instanceId); + RefPtr aceView = + Platform::AceViewOhos::CreateView(instanceId, false, container->GetSettings().usePlatformAsUIThread); + double density = GetDensity(); + float width = 0.0f; + float height = 0.0f; + + container->AttachView(window, aceView, density, width, height, Rosen::INVALID_WINDOW_ID, nullptr); + return container; +} + +void WindowFreeContainer::DestroyWindowFreeContainer() +{ + if (!g_WindowFreeContainer) { + LOGW("Container without window doesn't exist."); + return; + } + int32_t instanceId = g_WindowFreeContainer->GetInstanceId(); + Platform::AceContainer::DestroyContainer(instanceId, nullptr); + ContainerScope::RemoveAndCheck(instanceId); + g_WindowFreeContainer.Reset(); +} +} // namespace OHOS::Ace diff --git a/adapter/preview/entrance/BUILD.gn b/adapter/preview/entrance/BUILD.gn index ff4af6c3e29..bc02814513d 100644 --- a/adapter/preview/entrance/BUILD.gn +++ b/adapter/preview/entrance/BUILD.gn @@ -64,6 +64,7 @@ ohos_source_set("preview_entrance_source") { "ui_content_impl.cpp", "ui_session/ui_session_manager_preview.cpp", "vibrator/vibrator_utils.cpp", + "window_free_container.cpp", "xcollie/xcollieInterface_impl.cpp", ] diff --git a/adapter/preview/entrance/ace_container.h b/adapter/preview/entrance/ace_container.h index ccbae0fc666..00bf29a06f0 100644 --- a/adapter/preview/entrance/ace_container.h +++ b/adapter/preview/entrance/ace_container.h @@ -361,6 +361,7 @@ private: int32_t labelId_; static bool isComponentMode_; std::string containerSdkPath_; + friend class WindowFreeContainer; ACE_DISALLOW_COPY_AND_MOVE(AceContainer); }; diff --git a/adapter/preview/entrance/window_free_container.cpp b/adapter/preview/entrance/window_free_container.cpp new file mode 100644 index 00000000000..8f542b15e0d --- /dev/null +++ b/adapter/preview/entrance/window_free_container.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "adapter/preview/entrance/ace_container.h" +#include "adapter/preview/external/ability/context.h" +#include "bridge/common/utils/engine_helper.h" + +#include "frameworks/base/i18n/localization.h" +#include "frameworks/core/common/ace_engine.h" +#include "frameworks/core/components_ng/render/adapter/rosen_window.h" + +#include "frameworks/core/common/window_free_container.h" + +namespace OHOS::Ace::Platform { +static RefPtr g_windowFreeContainer = nullptr; +static RefPtr g_jsEngine = nullptr; +RefPtr WindowFreeContainer::CreateWindowFreeContainer(void *runtime, void *ctx) +{ + LOGI("Create container without window."); + auto container = AceContainer::GetContainerInstance(WINDOW_FREE_CONTAINER_ID); + if (container) { + return container; + } + + if (g_windowFreeContainer) { + AceEngine::Get().AddContainer(WINDOW_FREE_CONTAINER_ID, g_windowFreeContainer); + EngineHelper::AddEngine(WINDOW_FREE_CONTAINER_ID, g_jsEngine); + return g_windowFreeContainer; + } + + CHECK_NULL_RETURN(runtime, nullptr); + + AceContainer::CreateContainer(WINDOW_FREE_CONTAINER_ID, FrontendType::DECLARATIVE_JS, true); + auto ncontainer = AceContainer::GetContainerInstance(WINDOW_FREE_CONTAINER_ID); + ncontainer->SetSharedRuntime(runtime); + + auto& setting = ncontainer->GetSettings(); + setting.usePlatformAsUIThread = true; + setting.useUIAsJSThread = true; + if (!Localization::GetInstance()->IsInit()) { + AceApplicationInfo::GetInstance().SetLocale("", "", "", ""); + } + + auto view = AceViewPreview::CreateView(WINDOW_FREE_CONTAINER_ID, false, true); + auto window = std::make_shared(nullptr, ncontainer->GetTaskExecutor(), WINDOW_FREE_CONTAINER_ID); + float width = 0.0f; + float height = 0.0f; + double density = 0.0; + ncontainer->AttachView(window, view, density, width, height, nullptr); + g_windowFreeContainer = ncontainer; + g_jsEngine = EngineHelper::GetEngine(WINDOW_FREE_CONTAINER_ID); + return ncontainer; +} + +void WindowFreeContainer::DestroyWindowFreeContainer() +{ + LOGI("Destroy container without window."); + // Destroy any container will make the rs being background, and stop rendering. + // So just keep the container here. + auto container = AceEngine::Get().GetContainer(WINDOW_FREE_CONTAINER_ID); + if (!container) { + return; + } + EngineHelper::RemoveEngine(WINDOW_FREE_CONTAINER_ID); + AceEngine::Get().RemoveContainer(WINDOW_FREE_CONTAINER_ID); +} +} // namespace OHOS::Ace diff --git a/adapter/preview/sdk/sharedlib_config.gni b/adapter/preview/sdk/sharedlib_config.gni index 9f07d4e5395..910e41aa336 100644 --- a/adapter/preview/sdk/sharedlib_config.gni +++ b/adapter/preview/sdk/sharedlib_config.gni @@ -245,6 +245,12 @@ _arkui_shared_libs = [ part_name = "ace_engine" lib_names = [ "focuscontroller" ] }, + { + label = "//foundation/arkui/ace_engine/interfaces/napi/kits:napi_group" + subsystem_name = "arkui" + part_name = "ace_engine" + lib_names = [ "containerutils" ] + }, { label = "//foundation/arkui/ace_engine/component_ext/arc_alphabet_indexer:arcalphabetindexer" subsystem_name = "arkui" diff --git a/build/libace.map b/build/libace.map index 0a5c7b49893..624542e339b 100644 --- a/build/libace.map +++ b/build/libace.map @@ -65,6 +65,8 @@ OHOS::Ace::Platform::AceApplicationInfoImpl::*; OHOS::Ace::Platform::AceContainer::*; OHOS::Ace::Platform::FlutterAceView::*; + "OHOS::Ace::Platform::WindowFreeContainer::CreateWindowFreeContainer(void*, void*)"; + "OHOS::Ace::Platform::WindowFreeContainer::DestroyWindowFreeContainer()"; OHOS::Ace::PluginComponentManager::*; OHOS::Ace::Scheduler::*; OHOS::Ace::ScopedDelegate::*; diff --git a/frameworks/base/i18n/localization.h b/frameworks/base/i18n/localization.h index 8f3177cb4ad..85d07a41380 100644 --- a/frameworks/base/i18n/localization.h +++ b/frameworks/base/i18n/localization.h @@ -130,6 +130,12 @@ public: return hasZero; } + bool IsInit() + { + std::lock_guard lock(mutex_); + return isInit_; + } + std::string GetLanguage(); std::string GetLanguageTag(); std::string GetFontLocale(); diff --git a/frameworks/bridge/declarative_frontend/engine/jsUIContext.js b/frameworks/bridge/declarative_frontend/engine/jsUIContext.js index 6f4031d34d6..781362c7f96 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsUIContext.js +++ b/frameworks/bridge/declarative_frontend/engine/jsUIContext.js @@ -263,6 +263,23 @@ class UIContext { this.instanceId_ = instanceId; } + static createUIContextWithoutWindow(context) { + let utils = globalThis.requireNapi('arkui.containerUtils'); + let uicontext = undefined; + if (utils) { + uicontext = utils.createContainerWithoutWindow(context); + } + + return uicontext; + } + + static destroyUIContextWithoutWindow() { + let utils = globalThis.requireNapi('arkui.containerUtils'); + if (utils) { + utils.destroyContainerWithoutWindow(); + } + } + getDragController() { this.dragController_ = new DragController(this.instanceId_); return this.dragController_; @@ -1649,4 +1666,4 @@ function __checkRegexValid__(pattern) { } finally { return result; } -} \ No newline at end of file +} diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_common_bridge.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_common_bridge.cpp index 24262515e31..adaa7c131f9 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_common_bridge.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_common_bridge.cpp @@ -8451,7 +8451,9 @@ ArkUINativeModuleValue CommonBridge::GetWindowName(ArkUIRuntimeCallInfo* runtime CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm)); auto context = PipelineBase::GetCurrentContext(); CHECK_NULL_RETURN(context, panda::JSValueRef::Undefined(vm)); - std::string windowName = context->GetWindow()->GetWindowName(); + auto window = context->GetWindow(); + CHECK_NULL_RETURN(window, panda::JSValueRef::Undefined(vm)); + std::string windowName = window->GetWindowName(); return panda::StringRef::NewFromUtf8(vm, windowName.c_str()); } diff --git a/frameworks/core/common/container_consts.h b/frameworks/core/common/container_consts.h index 473cf608240..b31bb391af2 100755 --- a/frameworks/core/common/container_consts.h +++ b/frameworks/core/common/container_consts.h @@ -26,6 +26,7 @@ enum ContainerType { PA_DATA_CONTAINER, PA_FORM_CONTAINER, FA_SUBWINDOW_CONTAINER, + WINDOW_FREE_CONTAINER = 9, COMPONENT_SUBWINDOW_CONTAINER = 10, PLUGIN_SUBCONTAINER = 20, }; @@ -36,6 +37,7 @@ constexpr int32_t CONTAINER_ID_DIVIDE_SIZE = 100000; constexpr int32_t MIN_PLUGIN_SUBCONTAINER_ID = PLUGIN_SUBCONTAINER * CONTAINER_ID_DIVIDE_SIZE; constexpr int32_t MIN_SUBCONTAINER_ID = COMPONENT_SUBWINDOW_CONTAINER * CONTAINER_ID_DIVIDE_SIZE; constexpr int32_t MIN_PA_SERVICE_ID = PA_SERVICE_CONTAINER * CONTAINER_ID_DIVIDE_SIZE; +constexpr int32_t WINDOW_FREE_CONTAINER_ID = WINDOW_FREE_CONTAINER * CONTAINER_ID_DIVIDE_SIZE; } // namespace OHOS::Ace #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_CONTAINER_CONSTS_H diff --git a/frameworks/core/common/window_free_container.h b/frameworks/core/common/window_free_container.h new file mode 100644 index 00000000000..5030a1f47f8 --- /dev/null +++ b/frameworks/core/common/window_free_container.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ARKUI_ACE_ENGINE_FRAMEWORKS_CORE_COMMON_WINDOW_FREE_CONTAINER_H +#define FOUNDATION_ARKUI_ACE_ENGINE_FRAMEWORKS_CORE_COMMON_WINDOW_FREE_CONTAINER_H + +#include "frameworks/base/utils/macros.h" +#include "base/memory/referenced.h" + +namespace OHOS::Ace::Platform { +class ACE_FORCE_EXPORT WindowFreeContainer { +public: +WindowFreeContainer() = delete; +static RefPtr CreateWindowFreeContainer(void *env, void *context); +static void DestroyWindowFreeContainer(); +}; +} // namespace OHOS::Ace +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_WINDOW_FREE_CONTAINER_H diff --git a/frameworks/core/components_ng/render/adapter/rosen_window.cpp b/frameworks/core/components_ng/render/adapter/rosen_window.cpp index 2ee758ba60e..5ec74326ef7 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_window.cpp +++ b/frameworks/core/components_ng/render/adapter/rosen_window.cpp @@ -100,7 +100,7 @@ RosenWindow::RosenWindow(const OHOS::sptr& window, RefPtrGetSurfaceNode()) { + if (window && window->GetSurfaceNode()) { rsUIDirector_->SetRSSurfaceNode(window->GetSurfaceNode()); } rsUIDirector_->SetCacheDir(AceApplicationInfo::GetInstance().GetDataFileDirPath()); @@ -290,7 +290,11 @@ int64_t RosenWindow::GetVSyncPeriod() const std::string RosenWindow::GetWindowName() const { - return rsWindow_->GetWindowName(); + std::string windowName; + if (rsWindow_) { + windowName = rsWindow_->GetWindowName(); + } + return windowName; } void RosenWindow::OnVsync(uint64_t nanoTimestamp, uint32_t frameCount) diff --git a/interfaces/napi/kits/container_utils/BUILD.gn b/interfaces/napi/kits/container_utils/BUILD.gn new file mode 100644 index 00000000000..333d1752173 --- /dev/null +++ b/interfaces/napi/kits/container_utils/BUILD.gn @@ -0,0 +1,64 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import("//foundation/arkui/ace_engine/ace_config.gni") + +template("napi_containerutils_static") { + forward_variables_from(invoker, "*") + + ohos_source_set(target_name) { + defines += invoker.defines + cflags_cc += invoker.cflags_cc + configs = [ "$ace_root/interfaces/napi/kits:ace_napi_config" ] + + sources = [ "js_container_utils.cpp" ] + deps = [] + if (platform != "" && is_arkui_x) { + deps += [ "${crossplatform_plugin_root}/libs/napi:napi_$platform" ] + } else { + external_deps = [ "napi:ace_napi" ] + } + + if (defined(config.libace_target)) { + deps += [ config.libace_target ] + } + + deps += [ "../utils:napi_utils_static_${platform}" ] + + subsystem_name = ace_engine_subsystem + part_name = ace_engine_part + } +} + +foreach(item, ace_platforms) { + napi_containerutils_static("containerutils_static_" + item.name) { + defines = [] + cflags_cc = [] + platform = item.name + config = { + } + + if (defined(item.config)) { + config = item.config + } + + if (defined(config.defines)) { + defines = config.defines + } + + if (defined(config.cflags_cc)) { + cflags_cc = config.cflags_cc + } + } +} diff --git a/interfaces/napi/kits/container_utils/js_container_utils.cpp b/interfaces/napi/kits/container_utils/js_container_utils.cpp new file mode 100644 index 00000000000..a2849465358 --- /dev/null +++ b/interfaces/napi/kits/container_utils/js_container_utils.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "interfaces/napi/kits/utils/napi_utils.h" + +#include "core/common/ace_engine.h" +#include "frameworks/core/common/window_free_container.h" +#include "frameworks/bridge/common/utils/engine_helper.h" + +namespace OHOS::Ace::Napi { +static napi_value JSCreateContainerWithoutWindow(napi_env env, napi_callback_info info) +{ + napi_handle_scope scope = nullptr; + napi_value result = nullptr; + + napi_value thisVal = nullptr; + std::size_t argc = 1; + napi_value argv = nullptr; + void *context = nullptr; + + napi_open_handle_scope(env, &scope); + + napi_get_cb_info(env, info, &argc, &argv, &thisVal, nullptr); + if (argc != 1) { + LOGE("Wrong arg count."); + NapiThrow(env, "The number of parameters is incorrect.", ERROR_CODE_PARAM_INVALID); + return result; + } + +#ifndef PREVIEW + // There is no napi context in previewer, no need to check .. + if (napi_unwrap(env, argv, &context) != napi_ok || !context) { + NapiThrow(env, "Invalid parameter type of context.", ERROR_CODE_PARAM_INVALID); + return result; + } +#endif + + auto container = OHOS::Ace::Platform::WindowFreeContainer::CreateWindowFreeContainer(env, context); + if (!container) { + NapiThrow(env, "Create container without window failed.", ERROR_CODE_INTERNAL_ERROR); + return result; + } + + auto frontend = container->GetFrontend(); + CHECK_NULL_RETURN(frontend, result); + result = frontend->GetContextValue(); + + napi_close_handle_scope(env, scope); + return result; +} + +static napi_value JSDestroyContainerWithoutWindow(napi_env, napi_callback_info info) +{ + napi_value result = nullptr; + OHOS::Ace::Platform::WindowFreeContainer::DestroyWindowFreeContainer(); + + return result; +} + +static napi_value containerUtilsExport(napi_env env, napi_value exports) +{ + napi_property_descriptor containerUtilsDesc[] = { + DECLARE_NAPI_FUNCTION("createContainerWithoutWindow", JSCreateContainerWithoutWindow), + DECLARE_NAPI_FUNCTION("destroyContainerWithoutWindow", JSDestroyContainerWithoutWindow), + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(containerUtilsDesc) / sizeof(containerUtilsDesc[0]), + containerUtilsDesc)); + + return exports; +} + +static napi_module containerUtilsModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = containerUtilsExport, + .nm_modname = "arkui.containerUtils", + .nm_priv = ((void*)0), + .reserved = { 0 }, +}; + +extern "C" __attribute__((constructor)) void ContainerUtilsRegister() +{ + napi_module_register(&containerUtilsModule); +} + +} // namespace OHOS::Ace::Napi diff --git a/interfaces/napi/kits/napi_lib.gni b/interfaces/napi/kits/napi_lib.gni index 6ce4cc840a0..ea0839dc0cf 100644 --- a/interfaces/napi/kits/napi_lib.gni +++ b/interfaces/napi/kits/napi_lib.gni @@ -42,6 +42,10 @@ if (is_arkui_x) { common_napi_libs += [ "arkui/drawabledescriptor" ] } +if (!is_arkui_x) { + common_napi_libs += [ "arkui/container_utils" ] +} + template("ace_napi_lib") { forward_variables_from(invoker, "*") -- Gitee