diff --git a/adapter/ohos/entrance/BUILD.gn b/adapter/ohos/entrance/BUILD.gn index b069881320918c287cca99b2c0885f17f3175f5e..4e2e4c1f4e8a53f80d2a4ddc5278597fce7df51e 100644 --- a/adapter/ohos/entrance/BUILD.gn +++ b/adapter/ohos/entrance/BUILD.gn @@ -35,6 +35,7 @@ template("ace_ohos_standard_source_set") { "$ace_root/adapter/ohos/entrance/flutter_ace_view.cpp", "$ace_root/adapter/ohos/entrance/pa_container.cpp", "$ace_root/adapter/ohos/entrance/plugin_utils_impl.cpp", + "$ace_root/adapter/ohos/entrance/subwindow/subwindow_ohos.cpp", # innerkits impl "$ace_root/adapter/ohos/entrance/ui_content_impl.cpp", diff --git a/adapter/ohos/entrance/ace_ability.cpp b/adapter/ohos/entrance/ace_ability.cpp old mode 100755 new mode 100644 index 6c1fe78eda29ec2e99fb1d765eddc6475c702af1..1c08e7173f9fac31bb6e61bc752fe9946543bd7c --- a/adapter/ohos/entrance/ace_ability.cpp +++ b/adapter/ohos/entrance/ace_ability.cpp @@ -37,6 +37,7 @@ #include "adapter/ohos/entrance/plugin_utils_impl.h" #include "adapter/ohos/entrance/utils.h" #include "base/log/log.h" +#include "base/subwindow/subwindow_manager.h" #include "base/utils/system_properties.h" #include "core/common/container_scope.h" #include "core/common/frontend.h" @@ -265,7 +266,8 @@ void AceAbility::OnStart(const Want& want) container->SetResourceConfiguration(aceResCfg); container->SetPackagePathStr(resPath); } - + container->SetWindowName(window->GetWindowName()); + SubwindowManager::GetInstance()->AddContainerId(window->GetWindowId(), abilityId_); // create view. auto flutterAceView = Platform::FlutterAceView::CreateView(abilityId_); Platform::FlutterAceView::SurfaceCreated(flutterAceView, window); diff --git a/adapter/ohos/entrance/ace_container.cpp b/adapter/ohos/entrance/ace_container.cpp index c0963c9e649c3acc161b8de87316a42417399023..2e11c9d05afedc0e2a9f0b8dfdc6ef6c413b134f 100644 --- a/adapter/ohos/entrance/ace_container.cpp +++ b/adapter/ohos/entrance/ace_container.cpp @@ -82,8 +82,8 @@ const char* GetDeclarativeSharedLibrary(bool isArkApp) } // namespace AceContainer::AceContainer(int32_t instanceId, FrontendType type, bool isArkApp, - std::shared_ptr aceAbility, - std::unique_ptr callback, bool useCurrentEventRunner) + std::shared_ptr aceAbility, std::unique_ptr callback, + bool useCurrentEventRunner) : instanceId_(instanceId), type_(type), isArkApp_(isArkApp), aceAbility_(aceAbility), useCurrentEventRunner_(useCurrentEventRunner) { @@ -96,12 +96,14 @@ AceContainer::AceContainer(int32_t instanceId, FrontendType type, bool isArkApp, AceContainer::AceContainer(int32_t instanceId, FrontendType type, bool isArkApp, std::weak_ptr runtimeContext, std::weak_ptr abilityInfo, std::unique_ptr callback, - bool useCurrentEventRunner) + bool useCurrentEventRunner, bool isSubAceContainer) : instanceId_(instanceId), type_(type), isArkApp_(isArkApp), runtimeContext_(runtimeContext), - abilityInfo_(abilityInfo), useCurrentEventRunner_(useCurrentEventRunner) + abilityInfo_(abilityInfo), useCurrentEventRunner_(useCurrentEventRunner), isSubContainer_(isSubAceContainer) { ACE_DCHECK(callback); - InitializeTask(); + if (!isSubContainer_) { + InitializeTask(); + } platformEventCallback_ = std::move(callback); useStageModel_ = true; } @@ -138,6 +140,10 @@ void AceContainer::Destroy() context.Swap(pipelineContext_); taskExecutor_->PostTask([context]() { context->Destroy(); }, TaskExecutor::TaskType::UI); + if (isSubContainer_) { + // SubAcecontainer just return. + return; + } // 2. Destroy Frontend on JS thread. RefPtr frontend; frontend_.Swap(frontend); @@ -179,22 +185,27 @@ void AceContainer::InitializeFrontend() AceApplicationInfo::GetInstance().SetCardType(); frontend_ = AceType::MakeRefPtr(); } else if (type_ == FrontendType::DECLARATIVE_JS) { - frontend_ = AceType::MakeRefPtr(); - auto declarativeFrontend = AceType::DynamicCast(frontend_); - auto& loader = Framework::JsEngineLoader::GetDeclarative(GetDeclarativeSharedLibrary(isArkApp_)); - RefPtr jsEngine; - if (GetSettings().usingSharedRuntime) { - jsEngine = loader.CreateJsEngineUsingSharedRuntime(instanceId_, sharedRuntime_); - LOGI("Create engine using runtime, engine %{public}p", RawPtr(jsEngine)); + if (!isSubContainer_) { + frontend_ = AceType::MakeRefPtr(); + auto declarativeFrontend = AceType::DynamicCast(frontend_); + auto& loader = Framework::JsEngineLoader::GetDeclarative(GetDeclarativeSharedLibrary(isArkApp_)); + RefPtr jsEngine; + if (GetSettings().usingSharedRuntime) { + jsEngine = loader.CreateJsEngineUsingSharedRuntime(instanceId_, sharedRuntime_); + LOGI("Create engine using runtime, engine %{public}p", RawPtr(jsEngine)); + } else { + jsEngine = loader.CreateJsEngine(instanceId_); + } + jsEngine->AddExtraNativeObject("ability", aceAbility.get()); + EngineHelper::AddEngine(instanceId_, jsEngine); + declarativeFrontend->SetJsEngine(jsEngine); + declarativeFrontend->SetPageProfile(pageProfile_); + declarativeFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint()); + declarativeFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion()); } else { - jsEngine = loader.CreateJsEngine(instanceId_); + frontend_ = OHOS::Ace::Platform::AceContainer::GetContainer(parentId_)->GetFrontend(); + return; } - jsEngine->AddExtraNativeObject("ability", aceAbility.get()); - EngineHelper::AddEngine(instanceId_, jsEngine); - declarativeFrontend->SetJsEngine(jsEngine); - declarativeFrontend->SetPageProfile(pageProfile_); - declarativeFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint()); - declarativeFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion()); } else { LOGE("Frontend type not supported"); EventReport::SendAppStartException(AppStartExcepType::FRONTEND_TYPE_ERR); @@ -446,7 +457,8 @@ void AceContainer::InitializeCallback() [context, event]() { context->OnTouchEvent(event); context->NotifyDispatchTouchEventDismiss(event); - }, TaskExecutor::TaskType::UI); + }, + TaskExecutor::TaskType::UI); }; aceView_->RegisterTouchEventCallback(touchEventCallback); @@ -482,8 +494,8 @@ void AceContainer::InitializeCallback() }; aceView_->RegisterRotationEventCallback(rotationEventCallback); - auto&& viewChangeCallback = [context = pipelineContext_, id = instanceId_](int32_t width, int32_t height, - WindowSizeChangeReason type) { + auto&& viewChangeCallback = [context = pipelineContext_, id = instanceId_]( + int32_t width, int32_t height, WindowSizeChangeReason type) { ContainerScope scope(id); ACE_SCOPED_TRACE("ViewChangeCallback(%d, %d)", width, height); context->GetTaskExecutor()->PostTask( @@ -575,8 +587,8 @@ void AceContainer::DestroyContainer(int32_t instanceId) AceEngine::Get().RemoveContainer(instanceId); } -void AceContainer::SetView(AceView* view, double density, int32_t width, int32_t height, int32_t windowId, - UIEnvCallback callback) +void AceContainer::SetView( + AceView* view, double density, int32_t width, int32_t height, int32_t windowId, UIEnvCallback callback) { if (view == nullptr) { return; @@ -788,20 +800,19 @@ void AceContainer::AddLibPath(int32_t instanceId, const std::string& libPath) } } -void AceContainer::AttachView( - std::unique_ptr window, AceView* view, double density, int32_t width, int32_t height, int32_t windowId, - UIEnvCallback callback) +void AceContainer::AttachView(std::unique_ptr window, AceView* view, double density, int32_t width, + int32_t height, int32_t windowId, UIEnvCallback callback) { aceView_ = view; auto instanceId = aceView_->GetInstanceId(); - auto state = flutter::UIDartState::Current()->GetStateById(instanceId); - ACE_DCHECK(state != nullptr); auto flutterTaskExecutor = AceType::DynamicCast(taskExecutor_); - flutterTaskExecutor->InitOtherThreads(state->GetTaskRunners()); - if (GetSettings().usePlatformAsUIThread) { - ContainerScope::SetScopeNotify([](int32_t id) { - flutter::UIDartState::Current()->SetCurInstance(id); - }); + if (!isSubContainer_) { + auto state = flutter::UIDartState::Current()->GetStateById(instanceId); + ACE_DCHECK(state != nullptr); + flutterTaskExecutor->InitOtherThreads(state->GetTaskRunners()); + if (GetSettings().usePlatformAsUIThread) { + ContainerScope::SetScopeNotify([](int32_t id) { flutter::UIDartState::Current()->SetCurInstance(id); }); + } } ContainerScope scope(instanceId); if (type_ == FrontendType::DECLARATIVE_JS) { @@ -826,6 +837,9 @@ void AceContainer::AttachView( pipelineContext_->SetWindowModal(windowModal_); pipelineContext_->SetDrawDelegate(aceView_->GetDrawDelegate()); pipelineContext_->SetWindowId(windowId); + if (isSubContainer_) { + pipelineContext_->SetIsSubPipeline(true); + } InitializeCallback(); auto&& finishEventHandler = [weak = WeakClaim(this), instanceId] { @@ -880,7 +894,7 @@ void AceContainer::AttachView( }; pipelineContext_->SetStatusBarEventHandler(setStatusBarEventHandler); - taskExecutor_->PostTask([] { FrameReport::GetInstance().Init(); }, TaskExecutor::TaskType::UI); + taskExecutor_->PostTask([] { FrameReport::GetInstance().Init(); }, TaskExecutor::TaskType::UI); ThemeConstants::InitDeviceType(); // Load custom style at UI thread before frontend attach, to make sure style can be loaded before building dom tree. @@ -897,20 +911,29 @@ void AceContainer::AttachView( TaskExecutor::TaskType::UI); } taskExecutor_->PostTask( - [context = pipelineContext_, callback]() { + [context = pipelineContext_, callback, isSubContainer = isSubContainer_]() { if (callback != nullptr) { callback(context); } - context->SetupRootElement(); + if (!isSubContainer) { + context->SetupRootElement(); + } }, TaskExecutor::TaskType::UI); aceView_->Launch(); - frontend_->AttachPipelineContext(pipelineContext_); - AceEngine::Get().RegisterToWatchDog(instanceId, taskExecutor_, GetSettings().useUIAsJSThread); + if (!isSubContainer_) { + frontend_->AttachPipelineContext(pipelineContext_); + } else { + auto declarativeFrontend = AceType::DynamicCast(frontend_); + if (declarativeFrontend) { + declarativeFrontend->AttachSubPipelineContext(pipelineContext_); + } + return; + } auto dataAbilityHelperImpl = [ability = GetAbilityInner(), runtimeContext = runtimeContext_, - useStageModel = useStageModel_] () { + useStageModel = useStageModel_]() { return AceType::MakeRefPtr(ability.lock(), runtimeContext.lock(), useStageModel); }; auto dataProviderManager = MakeRefPtr(dataAbilityHelperImpl); @@ -1000,4 +1023,10 @@ std::string AceContainer::GetContentInfo(int32_t instanceId) } } +void AceContainer::InitializeSubContainer(int32_t parentContainerId) +{ + auto taskExec = AceEngine::Get().GetContainer(parentContainerId)->GetTaskExecutor(); + taskExecutor_ = AceType::DynamicCast(std::move(taskExec)); + GetSettings().useUIAsJSThread = true; +} } // namespace OHOS::Ace::Platform diff --git a/adapter/ohos/entrance/ace_container.h b/adapter/ohos/entrance/ace_container.h index 352b970a65a508ea8395715c0de5a6c4dd86cd3c..8c3752ebc3277b38902e01bb5d67b7b08c2924f5 100644 --- a/adapter/ohos/entrance/ace_container.h +++ b/adapter/ohos/entrance/ace_container.h @@ -19,8 +19,8 @@ #include #include "ability_context.h" -#include "native_engine/native_value.h" #include "native_engine/native_reference.h" +#include "native_engine/native_value.h" #include "adapter/ohos/entrance/ace_ability.h" #include "adapter/ohos/entrance/platform_event_callback.h" @@ -38,12 +38,12 @@ class ACE_FORCE_EXPORT AceContainer : public Container, public JsMessageDispatch public: AceContainer(int32_t instanceId, FrontendType type, bool isArkApp, - std::shared_ptr aceAbility, - std::unique_ptr callback, bool useCurrentEventRunner = false); + std::shared_ptr aceAbility, std::unique_ptr callback, + bool useCurrentEventRunner = false); AceContainer(int32_t instanceId, FrontendType type, bool isArkApp, std::weak_ptr runtimeContext, std::weak_ptr abilityInfo, std::unique_ptr callback, - bool useCurrentEventRunner = false); + bool useCurrentEventRunner = false, bool isSubContainer = false); ~AceContainer() override = default; void Initialize() override; @@ -187,6 +187,26 @@ public: pageProfile_ = pageProfile; } + bool IsSubContainer() const override + { + return isSubContainer_; + } + + void* GetSharedRuntime() + { + return sharedRuntime_; + } + + void SetParentId(int32_t parentId) + { + parentId_ = parentId; + } + + int32_t GetParentId() + { + return parentId_; + } + static void CreateContainer(int32_t instanceId, FrontendType type, bool isArkApp, std::string instanceName, std::shared_ptr aceAbility, std::unique_ptr callback, bool useCurrentEventRunner = false); @@ -209,7 +229,7 @@ public: static void AddAssetPath(int32_t instanceId, const std::string& packagePath, const std::vector& paths); static void AddLibPath(int32_t instanceId, const std::string& libPath); static void SetView(AceView* view, double density, int32_t width, int32_t height, int32_t windowId, - UIEnvCallback callback = nullptr); + UIEnvCallback callback = nullptr); static void SetUIWindow(int32_t instanceId, sptr uiWindow); static sptr GetUIWindow(int32_t instanceId); static OHOS::AppExecFwk::Ability* GetAbility(int32_t instanceId); @@ -221,6 +241,22 @@ public: static RefPtr GetContainer(int32_t instanceId); static bool UpdatePage(int32_t instanceId, int32_t pageId, const std::string& content); + void SetWindowName(const std::string& name) + { + windowName_ = name; + } + + std::string& GetWindowName() + { + return windowName_; + } + + void SetIsSubContainer(bool isSubContainer) + { + isSubContainer_ = isSubContainer; + } + + void InitializeSubContainer(int32_t parentContainerId); static void SetDialogCallback(int32_t instanceId, FrontendDialogCallback callback); private: @@ -229,7 +265,7 @@ private: void InitializeTask(); void AttachView(std::unique_ptr window, AceView* view, double density, int32_t width, int32_t height, - int32_t windowId, UIEnvCallback callback = nullptr); + int32_t windowId, UIEnvCallback callback = nullptr); void SetUIWindowInner(sptr uiWindow); sptr GetUIWindowInner() const; std::weak_ptr GetAbilityInner() const; @@ -254,6 +290,10 @@ private: int32_t pageId_ = 0; bool useCurrentEventRunner_ = false; sptr uiWindow_ = nullptr; + std::string windowName_; + + bool isSubContainer_ = false; + int32_t parentId_ = 0; bool useStageModel_ = false; ACE_DISALLOW_COPY_AND_MOVE(AceContainer); diff --git a/adapter/ohos/entrance/flutter_ace_view.cpp b/adapter/ohos/entrance/flutter_ace_view.cpp index 6b4e9f620e3d14c9e933b4e86ef74b457ab749fb..2e3119639e23c548aa617a74ccb3f0b04f69668f 100644 --- a/adapter/ohos/entrance/flutter_ace_view.cpp +++ b/adapter/ohos/entrance/flutter_ace_view.cpp @@ -73,6 +73,8 @@ TouchPoint ConvertTouchPoint(const MMI::PointerEvent::PointerItem& pointerItem) touchPoint.downTime = TimeStamp(std::chrono::microseconds(pointerItem.GetDownTime())); touchPoint.x = pointerItem.GetLocalX(); touchPoint.y = pointerItem.GetLocalY(); + touchPoint.screenX = pointerItem.GetGlobalX(); + touchPoint.screenY = pointerItem.GetGlobalY(); touchPoint.isPressed = pointerItem.IsPressed(); return touchPoint; } @@ -104,8 +106,8 @@ TouchEvent ConvertTouchEvent(const std::shared_ptr& pointerEv auto touchPoint = ConvertTouchPoint(item); std::chrono::microseconds microseconds(pointerEvent->GetActionTime()); TimeStamp time(microseconds); - TouchEvent event { touchPoint.id, touchPoint.x, touchPoint.y, TouchType::UNKNOWN, time, touchPoint.size, - touchPoint.force, pointerEvent->GetDeviceId() }; + TouchEvent event { touchPoint.id, touchPoint.x, touchPoint.y, touchPoint.screenX, touchPoint.screenY, + TouchType::UNKNOWN, time, touchPoint.size, touchPoint.force, pointerEvent->GetDeviceId() }; int32_t orgDevice = pointerEvent->GetSourceType(); GetEventDevice(orgDevice, event); int32_t orgAction = pointerEvent->GetPointerAction(); @@ -178,6 +180,8 @@ void ConvertMouseEvent(const std::shared_ptr& pointerEvent, M events.x = item.GetLocalX(); events.y = item.GetLocalY(); + events.screenX = item.GetGlobalX(); + events.screenY = item.GetGlobalY(); int32_t orgAction = pointerEvent->GetPointerAction(); GetMouseEventAction(orgAction, events); int32_t orgButton = pointerEvent->GetButtonId(); diff --git a/adapter/ohos/entrance/subwindow/subwindow_ohos.cpp b/adapter/ohos/entrance/subwindow/subwindow_ohos.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79ca335de89825616a837432e98b0f041820403e --- /dev/null +++ b/adapter/ohos/entrance/subwindow/subwindow_ohos.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2022 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/ohos/entrance/subwindow/subwindow_ohos.h" + +#include "dm/display_manager.h" +#include "interfaces/innerkits/ace/viewport_config.h" +#include "render_service_client/core/ui/rs_ui_director.h" + +#include "adapter/ohos/entrance/ace_application_info.h" +#include "adapter/ohos/entrance/ace_container.h" +#include "adapter/ohos/entrance/flutter_ace_view.h" +#include "adapter/ohos/entrance/utils.h" +#include "base/utils/system_properties.h" +#include "core/common/container_scope.h" +#include "core/common/frontend.h" +#include "core/components/popup/popup_component.h" + +namespace OHOS::Ace { + +int32_t SubwindowOhos::id_ = 0; + +RefPtr Subwindow::CreateSubwindow(int32_t instanceId) +{ + LOGI("Create Subwindow, parent container id is %{public}d", instanceId); + return AceType::MakeRefPtr(instanceId); +} + +SubwindowOhos::SubwindowOhos(int32_t instanceId) +{ + parentContainerId_ = instanceId; + windowId_ = id_; + SetSubwindowId(windowId_); + id_++; +} + +void SubwindowOhos::InitContainer() +{ + LOGI("Subwindow start initialize container"); + if (!window_) { + LOGI("Window is null, need create a new window"); + OHOS::sptr windowOption = new OHOS::Rosen::WindowOption(); + auto parentWindowName = Platform::AceContainer::GetContainer(parentContainerId_)->GetWindowName(); + auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay(); + sptr parentWindow = OHOS::Rosen::Window::Find(parentWindowName); + if (parentWindow == nullptr) { + return; + } + auto windowType = parentWindow->GetType(); + if (windowType == Rosen::WindowType::WINDOW_TYPE_DESKTOP) { + windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_FLOAT); + } else { + windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + windowOption->SetParentName(parentWindowName); + } + windowOption->SetWindowRect({ 0, 0, defaultDisplay->GetWidth(), defaultDisplay->GetHeight() }); + windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING); + window_ = OHOS::Rosen::Window::Create( + "ARK_APP_SUBWINDOW_" + parentWindowName + std::to_string(windowId_), windowOption); + if (window_ == nullptr) { + LOGI("create window error return"); + return; + } + } + std::string url = ""; + window_->SetUIContent(url, nullptr, nullptr, false); + childContainerId_ = SubwindowManager::GetInstance()->GetContainerId(window_->GetWindowId()); + SubwindowManager::GetInstance()->AddParentContainerId(childContainerId_, parentContainerId_); + auto parentContainer = Platform::AceContainer::GetContainer(parentContainerId_); + if (!parentContainer) { + LOGE("Get container failed, container is null"); + return; + } + + auto container = Platform::AceContainer::GetContainer(childContainerId_); + if (!container) { + LOGE("Get container failed, container is null"); + return; + } + + container->SetParentId(parentContainerId_); + container->GetSettings().SetUsingSharedRuntime(true); + container->SetSharedRuntime(parentContainer->GetSharedRuntime()); + container->Initialize(); + container->SetAssetManager(parentContainer->GetAssetManager()); + container->SetResourceConfiguration(parentContainer->GetResourceConfiguration()); + container->SetPackagePathStr(parentContainer->GetPackagePathStr()); + container->SetIsSubContainer(true); + container->InitializeSubContainer(parentContainerId_); + ViewportConfig config; + // create ace_view + auto flutterAceView = + Platform::FlutterAceView::CreateView(childContainerId_, true, container->GetSettings().usePlatformAsUIThread); + Platform::FlutterAceView::SurfaceCreated(flutterAceView, window_); + + int32_t width = window_->GetRect().width_; + int32_t height = window_->GetRect().height_; + LOGI("UIContent Initialize: width: %{public}d, height: %{public}d", width, height); + + Ace::Platform::UIEnvCallback callback = nullptr; + // set view + Platform::AceContainer::SetView(flutterAceView, config.Density(), width, height, window_->GetWindowId(), callback); + Platform::FlutterAceView::SurfaceChanged(flutterAceView, width, height, config.Orientation()); + +#ifdef ENABLE_ROSEN_BACKEND + if (SystemProperties::GetRosenBackendEnabled()) { + rsUiDirector = OHOS::Rosen::RSUIDirector::Create(); + if (rsUiDirector != nullptr) { + rsUiDirector->SetRSSurfaceNode(window_->GetSurfaceNode()); + rsUiDirector->SetUITaskRunner( + [taskExecutor = container->GetTaskExecutor()]( + const std::function& task) { taskExecutor->PostTask(task, TaskExecutor::TaskType::UI); }); + auto context = container->GetPipelineContext(); + if (context != nullptr) { + LOGI("Init RSUIDirector"); + context->SetRSUIDirector(rsUiDirector); + } + rsUiDirector->Init(); + LOGI("UIContent Init Rosen Backend"); + } + } +#endif + auto subPipelineContext = Platform::AceContainer::GetContainer(childContainerId_)->GetPipelineContext(); + if (!subPipelineContext) { + LOGE("Get SubPipelineContext failed, pipelineContext is null"); + } + subPipelineContext->SetupSubRootElement(); +} + +void SubwindowOhos::ShowWindow() +{ + LOGI("Show the subwindow"); + if (!window_) { + LOGE("Show window failed, window is null"); + return; + } + + OHOS::Rosen::WMError ret = window_->Show(); + + if (ret != OHOS::Rosen::WMError::WM_OK) { + LOGE("Show window failed with errCode: %{public}d", static_cast(ret)); + return; + } + LOGI("Show the subwindow successfully."); + SubwindowManager::GetInstance()->SetCurrentSubwindow(AceType::Claim(this)); +} + +void SubwindowOhos::HideWindow() +{ + LOGI("Hide the subwindow"); + if (!window_) { + LOGE("Hide window failed, window is null"); + return; + } + + OHOS::Rosen::WMError ret = window_->Hide(); + + if (ret != OHOS::Rosen::WMError::WM_OK) { + LOGE("Hide window failed with errCode: %{public}d", static_cast(ret)); + return; + } + LOGI("Hide the subwindow successfully."); +} + +void SubwindowOhos::AddMenu(const RefPtr& newComponent) +{ + LOGI("Subwindow push new component start."); + auto stack = GetStack(); + if (!stack) { + LOGE("Get stack failed, it is null"); + return; + } + // Push the component + stack->PushComponent(newComponent); + LOGI("Subwindow push new component end."); +} + +void SubwindowOhos::ClearMenu() +{ + LOGI("Subwindow Clear menu start."); + auto stack = GetStack(); + if (!stack) { + LOGE("Get stack failed, it is null"); + return; + } + // Pop the component + stack->PopMenu(); + auto context = stack->GetContext().Upgrade(); + if (!context) { + LOGE("Get context failed, it is null"); + } + context->FlushPipelineImmediately(); + LOGI("Subwindow clear menu end."); +} + +void SubwindowOhos::ShowMenu(const RefPtr& newComponent) +{ + LOGI("Show the menu"); + ShowWindow(); + AddMenu(newComponent); +} + +void SubwindowOhos::CloseMenu() +{ + LOGI("Close the menu"); + ClearMenu(); + HideWindow(); +} + +RefPtr SubwindowOhos::GetStack() +{ + auto aceContainer = Platform::AceContainer::GetContainer(childContainerId_); + if (!aceContainer) { + LOGE("Get container failed, it is null"); + return nullptr; + } + + auto context = aceContainer->GetPipelineContext(); + if (!context) { + LOGE("Get context failed, it is null"); + return nullptr; + } + return context->GetLastStack(); +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/adapter/ohos/entrance/subwindow/subwindow_ohos.h b/adapter/ohos/entrance/subwindow/subwindow_ohos.h new file mode 100644 index 0000000000000000000000000000000000000000..fe4d9ae9d2b90cc86b7ab9be2cdecf226bcf8dd5 --- /dev/null +++ b/adapter/ohos/entrance/subwindow/subwindow_ohos.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022 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_ACE_ADAPTER_OHOS_ENTRANCE_SUBWINDOW_OHOS_H +#define FOUNDATION_ACE_ADAPTER_OHOS_ENTRANCE_SUBWINDOW_OHOS_H + +#include "wm/window.h" + +#include "base/subwindow/subwindow.h" +#include "base/subwindow/subwindow_manager.h" +#include "core/components/stack/stack_element.h" + +namespace OHOS::Rosen { +class Window; +class WindowOption; +class RSUIDirector; +} // namespace OHOS::Rosen + +namespace OHOS::Ace { + +class SubwindowOhos : public Subwindow { + DECLARE_ACE_TYPE(SubwindowOhos, Subwindow) + +public: + explicit SubwindowOhos(int32_t instanceId); + ~SubwindowOhos() = default; + + void InitContainer() override; + void ShowMenu(const RefPtr& newComponent) override; + void CloseMenu() override; + +private: + RefPtr GetStack(); + void AddMenu(const RefPtr& newComponent); + void ClearMenu(); + void ShowWindow(); + void HideWindow(); + + static int32_t id_; + int32_t windowId_ = 0; + int32_t parentContainerId_ = -1; + int32_t childContainerId_ = -1; + std::shared_ptr rsUiDirector; + sptr window_ = nullptr; +}; + +} // namespace OHOS::Ace + +#endif // FOUNDATION_ACE_ADAPTER_OHOS_ENTRANCE_SUBWINDOW_OHOS_H \ No newline at end of file diff --git a/adapter/ohos/entrance/ui_content_impl.cpp b/adapter/ohos/entrance/ui_content_impl.cpp index ecb34d6519f1de0d009c1fbbe1e9ef05ea501584..cec7d22c9f6a1ae47ee150fffa24d32571e1a81d 100644 --- a/adapter/ohos/entrance/ui_content_impl.cpp +++ b/adapter/ohos/entrance/ui_content_impl.cpp @@ -40,6 +40,8 @@ #include "adapter/ohos/entrance/plugin_utils_impl.h" #include "base/geometry/rect.h" #include "base/log/log.h" +#include "base/subwindow/subwindow_manager.h" +#include "base/utils/string_utils.h" #include "base/utils/system_properties.h" #include "core/common/ace_engine.h" #include "core/common/container_scope.h" @@ -78,6 +80,8 @@ WindowMode GetWindowMode(OHOS::Rosen::Window* window) } // namespace static std::atomic gInstanceId = 0; +static std::atomic gSubInstanceId = 1000000; +const std::string SUBWINDOW_PREFIX = "ARK_APP_SUBWINDOW_"; using ContentFinishCallback = std::function; class ContentEventCallback final : public Platform::PlatformEventCallback { @@ -196,6 +200,10 @@ void UIContentImpl::CommonInitialize(OHOS::Rosen::Window* window, const std::str LOGE("Null window, can't initialize UI content"); return; } + if (StringUtils::StartWith(window->GetWindowName(), SUBWINDOW_PREFIX)) { + InitializeSubWindow(window_); + return; + } auto context = context_.lock(); if (!context) { LOGE("context is null"); @@ -364,6 +372,10 @@ void UIContentImpl::CommonInitialize(OHOS::Rosen::Window* window, const std::str abilityContext->TerminateSelf(); } })); + container->SetWindowName(window_->GetWindowName()); + + // Mark the relationship between windowId and containerId, it is 1:1 + SubwindowManager::GetInstance()->AddContainerId(window->GetWindowId(), instanceId_); AceEngine::Get().AddContainer(instanceId_, container); container->GetSettings().SetUsingSharedRuntime(true); container->SetSharedRuntime(runtime_); @@ -650,4 +662,28 @@ void UIContentImpl::InitWindowCallback(const std::shared_ptrRegisterDragListener(dragWindowListener_); } +void UIContentImpl::InitializeSubWindow(OHOS::Rosen::Window* window) +{ + window_ = window; + LOGI("The window name is %{public}s", window->GetWindowName().c_str()); + if (!window_) { + LOGE("Null window, can't initialize UI content"); + return; + } + + RefPtr container; + instanceId_ = gSubInstanceId.fetch_add(1, std::memory_order_relaxed); + + std::weak_ptr abilityInfo; + std::weak_ptr runtimeContext; + container = AceType::MakeRefPtr(instanceId_, FrontendType::DECLARATIVE_JS, true, + runtimeContext, abilityInfo, std::make_unique([] { + // Subwindow ,just return. + LOGI("Content event callback"); + }), + false, true); + SubwindowManager::GetInstance()->AddContainerId(window->GetWindowId(), instanceId_); + AceEngine::Get().AddContainer(instanceId_, container); +} + } // namespace OHOS::Ace diff --git a/adapter/ohos/entrance/ui_content_impl.h b/adapter/ohos/entrance/ui_content_impl.h index d9b8e5da22dd7623699e4d4e844c5ba3fa339ec9..f13b68c946bfc57436b8b7c95a49085ceb0933a0 100644 --- a/adapter/ohos/entrance/ui_content_impl.h +++ b/adapter/ohos/entrance/ui_content_impl.h @@ -66,7 +66,7 @@ public: private: void CommonInitialize(OHOS::Rosen::Window* window, const std::string& contentInfo, NativeValue* storage); void InitWindowCallback(const std::shared_ptr& info); - + void InitializeSubWindow(OHOS::Rosen::Window* window); std::weak_ptr context_; void* runtime_ = nullptr; OHOS::Rosen::Window* window_ = nullptr; diff --git a/adapter/preview/entrance/BUILD.gn b/adapter/preview/entrance/BUILD.gn index e84c43397ae8b7cddc5398d967cf36d0a049b696..afa5453e48c1207dc807de468aec4f4a667424ef 100644 --- a/adapter/preview/entrance/BUILD.gn +++ b/adapter/preview/entrance/BUILD.gn @@ -28,6 +28,7 @@ template("preview_entrance_source") { "ace_container.cpp", "ace_resource_register.cpp", "flutter_ace_view.cpp", + "subwindow_preview.cpp", ] deps = [ diff --git a/adapter/preview/entrance/flutter_ace_view.cpp b/adapter/preview/entrance/flutter_ace_view.cpp index 37e4a88e6dfedfc1c99d19e08d408a69f6647f2f..a30b75b5ad766ac352f6de76ca74725041314800 100644 --- a/adapter/preview/entrance/flutter_ace_view.cpp +++ b/adapter/preview/entrance/flutter_ace_view.cpp @@ -41,6 +41,8 @@ TouchPoint ConvertTouchPoint(flutter::PointerData* pointerItem) touchPoint.force = pointerItem->pressure; touchPoint.x = pointerItem->physical_x; touchPoint.y = pointerItem->physical_y; + touchPoint.screenX = pointerItem->physical_x; + touchPoint.screenY = pointerItem->physical_y; return touchPoint; } @@ -56,6 +58,7 @@ void ConvertTouchEvent(const std::vector& data, std::vector TimeStamp time(micros); TouchEvent point { static_cast(DEFAULT_ACTION_ID), static_cast(current->physical_x), + static_cast(current->physical_y), static_cast(current->physical_x), static_cast(current->physical_y), TouchType::UNKNOWN, time, current->size, static_cast(current->pressure), static_cast(current->device) }; diff --git a/adapter/preview/entrance/subwindow_preview.cpp b/adapter/preview/entrance/subwindow_preview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..480db81dd818c0f6eb70a15b919407b0ee251a0c --- /dev/null +++ b/adapter/preview/entrance/subwindow_preview.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 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 "base/subwindow/subwindow.h" + +namespace OHOS::Ace { + +RefPtr Subwindow::CreateSubwindow(int32_t instanceId) +{ + return nullptr; +} + +} // namespace OHOS::Ace \ No newline at end of file diff --git a/frameworks/base/BUILD.gn b/frameworks/base/BUILD.gn index c3a563c3429ba95fa158809a6d0e61d33810a9e5..bd749ec5701968782effc8e2cebe648b3a5fda6d 100644 --- a/frameworks/base/BUILD.gn +++ b/frameworks/base/BUILD.gn @@ -44,6 +44,7 @@ template("ace_base_source_set") { "log/dump_log.cpp", "memory/memory_monitor.cpp", "ressched/ressched_report.cpp", + "subwindow/subwindow_manager.cpp", "thread/background_task_executor.cpp", "utils/base_id.cpp", "utils/date_util.cpp", diff --git a/frameworks/base/subwindow/subwindow.h b/frameworks/base/subwindow/subwindow.h new file mode 100644 index 0000000000000000000000000000000000000000..d8e7180eebcf44cd9562f9c985d58138d524b7c7 --- /dev/null +++ b/frameworks/base/subwindow/subwindow.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022 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_ACE_FRAMEWORKS_BASE_SUBWINDOW_SUBWINDOW_H +#define FOUNDATION_ACE_FRAMEWORKS_BASE_SUBWINDOW_SUBWINDOW_H + +#include "base/memory/ace_type.h" +#include "core/pipeline/base/component.h" + +namespace OHOS::Ace { + +class ACE_EXPORT Subwindow : public AceType { + DECLARE_ACE_TYPE(Subwindow, AceType) + +public: + static RefPtr CreateSubwindow(int32_t instanceId); + + virtual void InitContainer() = 0; + virtual void ShowMenu(const RefPtr& newComponent) = 0; + virtual void CloseMenu() = 0; + + int32_t GetSubwindowId() + { + return subwindowId_; + } + + void SetSubwindowId(int32_t id) + { + subwindowId_ = id; + } + +private: + int32_t subwindowId_; +}; + +} // namespace OHOS::Ace + +#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_SUBWINDOW_SUBWINDOW_H \ No newline at end of file diff --git a/frameworks/base/subwindow/subwindow_manager.cpp b/frameworks/base/subwindow/subwindow_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7f5728f5ad47a6d99cad912df05aee87602bfa75 --- /dev/null +++ b/frameworks/base/subwindow/subwindow_manager.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2022 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 "base/subwindow/subwindow_manager.h" + +#include +#include + +#include "unistd.h" + +#include "base/log/log.h" +#include "base/memory/ace_type.h" +#include "core/common/container.h" + +namespace OHOS::Ace { + +std::mutex SubwindowManager::instanceMutex_; +std::shared_ptr SubwindowManager::instance_; + +std::shared_ptr SubwindowManager::GetInstance() +{ + std::lock_guard lock(instanceMutex_); + if (!instance_) { + instance_ = std::make_shared(); + } + return instance_; +} + +void SubwindowManager::AddContainerId(uint32_t windowId, int32_t containerId) +{ + std::lock_guard lock(mutex_); + auto result = containerMap_.try_emplace(windowId, containerId); + if (!result.second) { + LOGW("Already have container of this windowId, windowId: %{public}u", windowId); + } +} + +void SubwindowManager::RemoveContainerId(uint32_t windowId) +{ + std::lock_guard lock(mutex_); + containerMap_.erase(windowId); +} + +int32_t SubwindowManager::GetContainerId(uint32_t windowId) +{ + std::lock_guard lock(mutex_); + auto result = containerMap_.find(windowId); + if (result != containerMap_.end()) { + return result->second; + } else { + return -1; + } +} + +void SubwindowManager::AddParentContainerId(int32_t containerId, int32_t parentContainerId) +{ + LOGI("Container id is %{public}d, parent id is %{public}d.", containerId, parentContainerId); + std::lock_guard lock(parentMutex_); + auto result = parentContainerMap_.try_emplace(containerId, parentContainerId); + if (!result.second) { + LOGW("Already have container of this %{public}d", containerId); + } +} + +void SubwindowManager::RemoveParentContainerId(int32_t containerId) +{ + std::lock_guard lock(parentMutex_); + parentContainerMap_.erase(containerId); +} + +int32_t SubwindowManager::GetParentContainerId(int32_t containerId) +{ + std::lock_guard lock(parentMutex_); + auto result = parentContainerMap_.find(containerId); + if (result != parentContainerMap_.end()) { + return result->second; + } else { + return 0; + } +} + +void SubwindowManager::AddSubwindow(int32_t instanceId, RefPtr subwindow) +{ + if (!subwindow) { + LOGE("Add subwindow failed, the subwndow is null."); + return; + } + LOGI("Add subwindow into map, instanceId is %{public}d, subwindow id is %{public}d.", instanceId, + subwindow->GetSubwindowId()); + std::lock_guard lock(subwindowMutex_); + if (isShow_) { + return; + } + auto result = subwindowMap_.try_emplace(instanceId, subwindow); + if (!result.second) { + LOGE("Add failed of this instance %{public}d", instanceId); + return; + } + LOGI("Add subwindow success of this instance %{public}d.", instanceId); +} + +void SubwindowManager::RemoveSubwindow(int32_t instanceId) +{ + LOGI("Remove subwindow of this instance %{public}d", instanceId); + std::lock_guard lock(subwindowMutex_); + int res = subwindowMap_.erase(instanceId); + if (res == 0) { + LOGW("Remove subwindow of instance %{public}d failed.", instanceId); + } +} + +const RefPtr SubwindowManager::GetSubwindow(int32_t instanceId) +{ + LOGI("Get subwindow of instance %{public}d.", instanceId); + std::lock_guard lock(subwindowMutex_); + auto result = subwindowMap_.find(instanceId); + if (result != subwindowMap_.end()) { + return result->second; + } else { + return nullptr; + } +} + +void SubwindowManager::SetCurrentSubwindowName(const std::string& currentSubwindowName) +{ + std::lock_guard lock(currentSubwindowMutex_); + currentSubwindowName_ = currentSubwindowName; +} + +std::string SubwindowManager::GetCurrentSubWindowName() +{ + std::lock_guard lock(currentSubwindowMutex_); + return currentSubwindowName_; +} + +void SubwindowManager::SetCurrentSubwindow(const RefPtr& subwindow) +{ + std::lock_guard lock(currentSubwindowMutex_); + currentSubwindow_ = subwindow; +} + +const RefPtr& SubwindowManager::GetCurrentWindow() +{ + std::lock_guard lock(currentSubwindowMutex_); + return currentSubwindow_; +} + +void SubwindowManager::ShowMenu(const RefPtr& newComponent) +{ + if (isShow_) { + LOGI("Menu is show already, just return."); + return; + } + auto containerId = Container::CurrentId(); + auto subwindow = GetSubwindow(containerId); + if (!subwindow) { + LOGI("Subwindow is null, add a new one."); + subwindow = Subwindow::CreateSubwindow(containerId); + subwindow->InitContainer(); + AddSubwindow(containerId, subwindow); + } + subwindow->ShowMenu(newComponent); + isShow_ = true; +} + +void SubwindowManager::CloseMenu() +{ + auto subwindow = GetCurrentWindow(); + if (subwindow) { + subwindow->CloseMenu(); + isShow_ = false; + } +} + +} // namespace OHOS::Ace diff --git a/frameworks/base/subwindow/subwindow_manager.h b/frameworks/base/subwindow/subwindow_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..0bac27fa1a4e2e90b763b5f303da56541842d9d6 --- /dev/null +++ b/frameworks/base/subwindow/subwindow_manager.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022 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_ACE_FRAMEWORKS_CORE_COMMON_SUBWINDOW_SUBWINDOW_MANAGER_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_SUBWINDOW_SUBWINDOW_MANAGER_H + +#include +#include + +#include "base/memory/referenced.h" +#include "base/subwindow/subwindow.h" +#include "base/utils/macros.h" +#include "base/utils/noncopyable.h" + +namespace OHOS::Ace { + +constexpr int32_t MIN_SUBCONTAINER_ID = 1000000; + +using SubwindowMap = std::unordered_map>; + +class ACE_EXPORT SubwindowManager final : public NonCopyable { +public: + // Get the instance + static std::shared_ptr GetInstance(); + + void AddContainerId(uint32_t windowId, int32_t containerId); + void RemoveContainerId(uint32_t windowId); + int32_t GetContainerId(uint32_t windowId); + + void AddParentContainerId(int32_t containerId, int32_t parentContainerId); + void RemoveParentContainerId(int32_t containerId); + int32_t GetParentContainerId(int32_t containerId); + + void AddSubwindow(int32_t instanceId, RefPtr); + void RemoveSubwindow(int32_t instanceId); + + // Get the subwindow of instance, return the window or nullptr. + const RefPtr GetSubwindow(int32_t instanceId); + + void HideCurrentSubwindow(); + + void SetCurrentSubwindowName(const std::string& currentSubwindow); + std::string GetCurrentSubWindowName(); + + void SetCurrentSubwindow(const RefPtr& subwindow); + + const RefPtr& GetCurrentWindow(); + + void ShowMenu(const RefPtr& newComponent); + void CloseMenu(); + +private: + static std::mutex instanceMutex_; + static std::shared_ptr instance_; + + std::mutex mutex_; + std::unordered_map containerMap_; + + std::mutex parentMutex_; + std::unordered_map parentContainerMap_; + + // Used to save the relationship between container and subwindow, it is 1:1 + std::mutex subwindowMutex_; + SubwindowMap subwindowMap_; + + std::mutex currentSubwindowMutex_; + std::string currentSubwindowName_; + + RefPtr currentSubwindow_; + bool isShow_ = false; +}; + +} // namespace OHOS::Ace + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMMON_SUBWINDOW_SUBWINDOW_MANAGER_H diff --git a/frameworks/bridge/common/utils/engine_helper.cpp b/frameworks/bridge/common/utils/engine_helper.cpp index 716083ba4ff0cd9715849b6ee1ec3f1fa5af8c88..3174e1c6eca062e12dc856969c1707b5d79dea87 100644 --- a/frameworks/bridge/common/utils/engine_helper.cpp +++ b/frameworks/bridge/common/utils/engine_helper.cpp @@ -15,10 +15,10 @@ #include "frameworks/bridge/common/utils/engine_helper.h" +#include "base/subwindow/subwindow_manager.h" #include "core/common/container.h" namespace OHOS::Ace { - std::shared_mutex EngineHelper::mutex_; std::unordered_map> EngineHelper::engineWeakMap_; @@ -31,6 +31,9 @@ void EngineHelper::AddEngine(int32_t id, WeakPtr engine) RefPtr EngineHelper::GetEngine(int32_t id) { std::shared_lock lock(mutex_); + if (id >= MIN_SUBCONTAINER_ID) { + id = SubwindowManager::GetInstance()->GetParentContainerId(id); + } auto iter = engineWeakMap_.find(id); if (iter != engineWeakMap_.end()) { return iter->second.Upgrade(); diff --git a/frameworks/bridge/declarative_frontend/declarative_frontend.cpp b/frameworks/bridge/declarative_frontend/declarative_frontend.cpp index f7b424f9d9956e266323a0cce9bfadef2760a9f2..0220cfdc33a1c26f4c99d8f67a8cc38936f461c7 100644 --- a/frameworks/bridge/declarative_frontend/declarative_frontend.cpp +++ b/frameworks/bridge/declarative_frontend/declarative_frontend.cpp @@ -204,6 +204,15 @@ void DeclarativeFrontend::AttachPipelineContext(const RefPtr& c delegate_->AttachPipelineContext(context); } +void DeclarativeFrontend::AttachSubPipelineContext(const RefPtr& context) +{ + LOGI("DeclarativeFrontend AttachSubPipelineContext."); + if (!delegate_) { + return; + } + context->RegisterEventHandler(handler_); +} + void DeclarativeFrontend::SetAssetManager(const RefPtr& assetManager) { LOGI("DeclarativeFrontend SetAssetManager."); diff --git a/frameworks/bridge/declarative_frontend/declarative_frontend.h b/frameworks/bridge/declarative_frontend/declarative_frontend.h index 8b970f02c73ff4cff2e0f18eabe67145f5b1b113..0a231f6160188224ed2c465ee719767fce2dae92 100644 --- a/frameworks/bridge/declarative_frontend/declarative_frontend.h +++ b/frameworks/bridge/declarative_frontend/declarative_frontend.h @@ -193,6 +193,8 @@ public: return jsEngine_; } + void AttachSubPipelineContext(const RefPtr& context); + private: void InitializeFrontendDelegate(const RefPtr& taskExecutor); diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h index dc9dd22eb0ea6bd41818d20a1c918ca458406a10..41f50013b8691ecfd9d18b62b7c536cd9c293ad5 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h +++ b/frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h @@ -25,6 +25,7 @@ #include "base/log/log.h" #include "base/memory/ace_type.h" +#include "base/subwindow/subwindow_manager.h" #include "base/utils/noncopyable.h" #include "core/common/ace_application_info.h" #include "core/common/ace_page.h" diff --git a/frameworks/bridge/declarative_frontend/jsview/dialog/js_custom_dialog_controller.cpp b/frameworks/bridge/declarative_frontend/jsview/dialog/js_custom_dialog_controller.cpp index e7b399ee5c3187ce02a4d753f5921f99ed3592a4..00a2aaea3c0655eaf6efa0341fad34ffcdcb290a 100644 --- a/frameworks/bridge/declarative_frontend/jsview/dialog/js_custom_dialog_controller.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/dialog/js_custom_dialog_controller.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 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 @@ -15,16 +15,17 @@ #include "bridge/declarative_frontend/jsview/dialog/js_custom_dialog_controller.h" +#include "base/subwindow/subwindow_manager.h" +#include "core/common/ace_engine.h" #include "core/common/container.h" #include "frameworks/bridge/declarative_frontend/view_stack_processor.h" namespace OHOS::Ace::Framework { namespace { -const std::vector DIALOG_ALIGNMENT = { - DialogAlignment::TOP, DialogAlignment::CENTER, DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, - DialogAlignment::TOP_START, DialogAlignment::TOP_END, DialogAlignment::CENTER_START, - DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START, DialogAlignment::BOTTOM_END -}; +const std::vector DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER, + DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END, + DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START, + DialogAlignment::BOTTOM_END }; } // namespace void JSCustomDialogController::ConstructorCallback(const JSCallbackInfo& info) @@ -118,8 +119,20 @@ void JSCustomDialogController::DestructorCallback(JSCustomDialogController* cont void JSCustomDialogController::ShowDialog(const JSCallbackInfo& info) { LOGI("JSCustomDialogController(ShowDialog)"); - auto container = Container::Current(); + RefPtr container; + auto current = Container::Current(); + if (!current) { + LOGE("Container is null."); + return; + } + if (current->IsSubContainer()) { + auto parentContainerId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId()); + container = AceEngine::Get().GetContainer(parentContainerId); + } else { + container = std::move(current); + } if (!container) { + LOGE("Container is null."); return; } auto context = container->GetPipelineContext(); @@ -154,9 +167,20 @@ void JSCustomDialogController::ShowDialog(const JSCallbackInfo& info) void JSCustomDialogController::CloseDialog() { LOGI("JSCustomDialogController(CloseDialog)"); - auto container = Container::Current(); + RefPtr container; + auto current = Container::Current(); + if (!current) { + LOGE("Container is null."); + return; + } + if (current->IsSubContainer()) { + auto parentContainerId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId()); + container = AceEngine::Get().GetContainer(parentContainerId); + } else { + container = std::move(current); + } if (!container) { - LOGE("container is null."); + LOGE("Container is null."); return; } auto context = container->GetPipelineContext(); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp index acc32bdffd701fba103ca7b51f4e2e956efadfe0..143bb6ba78ba0da9f5b8322e148137a7af1ef4d4 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_view_abstract.cpp @@ -3524,7 +3524,7 @@ void JSViewAbstract::JsBindContextMenu(const JSCallbackInfo& info) if (!menuComponent) { return; } - menuComponent->SetContextMenu(true); + menuComponent->SetIsContextMenu(true); int32_t responseType = static_cast(ResponseType::LONGPRESS); if (info.Length() == 2 && info[1]->IsNumber()) { responseType = info[1]->ToNumber(); @@ -3540,7 +3540,7 @@ void JSViewAbstract::JsBindContextMenu(const JSCallbackInfo& info) } if (info.GetButton() == MouseButton::RIGHT_BUTTON && info.GetAction() == MouseAction::RELEASE) { auto showMenu = refPtr->GetTargetCallback(); - showMenu("", info.GetGlobalLocation()); + showMenu("", info.GetScreenLocation()); } }); } else if (responseType == static_cast(ResponseType::LONGPRESS)) { @@ -3553,7 +3553,7 @@ void JSViewAbstract::JsBindContextMenu(const JSCallbackInfo& info) return; } auto showMenu = refPtr->GetTargetCallback(); - showMenu("", info.GetGlobalLocation()); + showMenu("", info.GetScreenLocation()); }); box->SetOnLongPress(longGesture); } else { diff --git a/frameworks/bridge/declarative_frontend/jsview/menu/js_context_menu.cpp b/frameworks/bridge/declarative_frontend/jsview/menu/js_context_menu.cpp index a57c331e7ecc1ad7d5d35c6cba6f92fb4917399c..b59e970c734ba80ae51e5f43f64d865943767f5b 100644 --- a/frameworks/bridge/declarative_frontend/jsview/menu/js_context_menu.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/menu/js_context_menu.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2022 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 @@ -16,26 +16,14 @@ #include "frameworks/bridge/declarative_frontend/jsview/menu/js_context_menu.h" #include "core/common/container.h" +#include "base/subwindow/subwindow_manager.h" +#include "base/subwindow/subwindow.h" namespace OHOS::Ace::Framework { void JSContextMenu::Close(const JSCallbackInfo& args) { - // Close context menu. - auto container = Container::Current(); - if (container) { - auto context = container->GetPipelineContext(); - auto executor = Container::CurrentTaskExecutor(); - if (executor) { - executor->PostTask( - [context]() { - if (context) { - context->CloseContextMenu(); - } - }, - TaskExecutor::TaskType::UI); - } - } + SubwindowManager::GetInstance()->CloseMenu(); args.SetReturnValue(args.This()); } diff --git a/frameworks/bridge/test/unittest/jsfrontend/dom_mock.h b/frameworks/bridge/test/unittest/jsfrontend/dom_mock.h index 3e08970216968a2818caab7074074f4bbd3f797d..233f669a46491a3c4f0d649b1a3ec5f6d8e812f9 100644 --- a/frameworks/bridge/test/unittest/jsfrontend/dom_mock.h +++ b/frameworks/bridge/test/unittest/jsfrontend/dom_mock.h @@ -16,11 +16,20 @@ #ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_TEST_UNITTEST_JSFRONTEND_DOM_MOCK_H #define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_TEST_UNITTEST_JSFRONTEND_DOM_MOCK_H +#include "base/subwindow/subwindow.h" #include "core/common/frontend.h" #include "core/common/platform_window.h" #include "core/common/window.h" #include "core/pipeline/pipeline_context.h" +namespace OHOS::Ace { + +RefPtr Subwindow::CreateSubwindow(int32_t instanceId) +{ + return nullptr; +} + +} // namespace OHOS::Ace namespace OHOS::Ace::Framework { class MockPlatformWindow : public PlatformWindow { diff --git a/frameworks/core/common/container.h b/frameworks/core/common/container.h index 672c571f3ed4aa2acb518f94f9c385e8badf06e0..b392b73c573d36efcc5bbac6c4b32058455a5bc7 100644 --- a/frameworks/core/common/container.h +++ b/frameworks/core/common/container.h @@ -131,6 +131,11 @@ public: return false; } + virtual bool IsSubContainer() const + { + return false; + } + const std::string& GetCardHapPath() const { return cardHapPath_; diff --git a/frameworks/core/components/box/render_box.cpp b/frameworks/core/components/box/render_box.cpp index 42f633a7d2ef2fca6d971d93943164d81a642796..38edbc8c024ce89b6ec7e6e6bfc841de46cfaed6 100644 --- a/frameworks/core/components/box/render_box.cpp +++ b/frameworks/core/components/box/render_box.cpp @@ -1112,6 +1112,7 @@ bool RenderBox::HandleMouseEvent(const MouseEvent& event) info.SetAction(event.action); info.SetGlobalLocation(event.GetOffset()); info.SetLocalLocation(event.GetOffset() - Offset(GetCoordinatePoint().GetX(), GetCoordinatePoint().GetY())); + info.SetScreenLocation(event.GetScreenOffset()); info.SetTimeStamp(event.time); info.SetDeviceId(event.deviceId); info.SetSourceDevice(event.sourceType); diff --git a/frameworks/core/components/menu/menu_component.h b/frameworks/core/components/menu/menu_component.h index 08006a65e691f268c79fe770024fab3d08cad7c3..ef7d4a73e4d047821713382ffdcd5dc916be9c2a 100644 --- a/frameworks/core/components/menu/menu_component.h +++ b/frameworks/core/components/menu/menu_component.h @@ -146,7 +146,7 @@ public: void SetIsBindTarget(bool isBindTarget) {} const RefPtr& GetPopup() const; - void SetContextMenu(bool isContextMenu) + void SetIsContextMenu(bool isContextMenu) { isContextMenu_ = isContextMenu; if (popup_) { diff --git a/frameworks/core/components/menu/menu_element.cpp b/frameworks/core/components/menu/menu_element.cpp index bfa7aa5d9993a4815dca55435c6163897aa9ac53..6ff37f1ded3ec6c9d09ed9f142d639f1c9d10730 100644 --- a/frameworks/core/components/menu/menu_element.cpp +++ b/frameworks/core/components/menu/menu_element.cpp @@ -54,13 +54,20 @@ void MenuElement::PerformBuild() if (!data_->GetOnSuccess().IsEmpty()) { jsSuccessCallback_ = AceAsyncEvent::Create(data_->GetOnSuccess(), context_); } - data_->SetTargetCallback([weak = WeakClaim(this)](const ComposeId& id, const Offset& point) { - auto refPtr = weak.Upgrade(); - if (!refPtr) { - return; - } - refPtr->OnTargetCallback(id, point); - }); + + data_->SetTargetCallback( + [weak = WeakClaim(this), isContextMenu = data_->IsContextMenu()](const ComposeId& id, const Offset& point) { + auto refPtr = weak.Upgrade(); + if (!refPtr) { + return; + } + if (isContextMenu) { + LOGI("The menu is contextMenu, set the callback."); + refPtr->OnTargetContextCallback(id, point); + } else { + refPtr->OnTargetCallback(id, point); + } + }); } void MenuElement::OnTargetCallback(const ComposeId& id, const Offset& point) @@ -104,6 +111,28 @@ void MenuElement::OnTargetCallback(const ComposeId& id, const Offset& point) popup->ShowDialog(stack, targetGlobalOffset, targetRightBottom, true); } +void MenuElement::OnTargetContextCallback(const ComposeId& id, const Offset& point) +{ + LOGI("Execute the callback"); + auto context = context_.Upgrade(); + if (!context) { + LOGE("Get Context failed, context is null."); + return; + } + + if (!data_ || !data_->GetPopup()) { + LOGE("Get component failed, component is null."); + return; + } + + auto popup = data_->GetPopup(); + if (popup) { + LOGI("Window is ready, prepare to show the menu."); + popup->ShowContextMenu(point); + } + +} + RefPtr MenuElement::GetBoxRenderChild(const RefPtr& element) { auto targetElement = element; diff --git a/frameworks/core/components/menu/menu_element.h b/frameworks/core/components/menu/menu_element.h index ca1fcf75656646be654afb8217b674e643fee842..413c247cce2ec1d5a2a77684db019bdf4477bf01 100644 --- a/frameworks/core/components/menu/menu_element.h +++ b/frameworks/core/components/menu/menu_element.h @@ -52,6 +52,7 @@ public: private: void OnTargetCallback(const ComposeId& id, const Offset& point); + void OnTargetContextCallback(const ComposeId& id, const Offset& point); void OnOptionCallback(std::size_t index); void OnCanceledCallback(); RefPtr GetBoxRenderChild(const RefPtr& element); diff --git a/frameworks/core/components/root/render_root.cpp b/frameworks/core/components/root/render_root.cpp index f77b4a83f99230171074023e3fee6b34ca59fa2f..c32926dd1318459da7799f0f9870a99752c4a055 100644 --- a/frameworks/core/components/root/render_root.cpp +++ b/frameworks/core/components/root/render_root.cpp @@ -15,6 +15,7 @@ #include "core/components/root/render_root.h" +#include "root_component.h" #include "base/log/log.h" #include "core/animation/curve.h" #include "core/animation/curve_animation.h" @@ -38,12 +39,16 @@ bool IsShadowModal(const WeakPtr& contextWeak) RenderRoot::RenderRoot() : RenderNode(true) {} -void RenderRoot::Update(const RefPtr&) +void RenderRoot::Update(const RefPtr& component) { if (!controller_ && IsShadowModal(context_)) { controller_ = AceType::MakeRefPtr(GetContext()); controller_->SetFillMode(FillMode::FORWARDS); } + auto root = AceType::DynamicCast(component); + if (root) { + isContextMenu_ = root->IsContextMenu(); + } MarkNeedLayout(); } @@ -70,6 +75,9 @@ void RenderRoot::PerformLayout() }); controller_->AddInterpolator(colorAnimation); } + if (isContextMenu_) { + bgColor_ = Color::TRANSPARENT; + } isBgColorInit_ = true; } viewPort_ = GetPaintRect().GetSize(); @@ -106,14 +114,14 @@ void RenderRoot::SetDefaultBgColor() if (!appTheme) { return; } - bgColor_ = appTheme->GetBackgroundColor(); + bgColor_ = isContextMenu_ ? Color::TRANSPARENT : appTheme->GetBackgroundColor(); forceColor_ = false; MarkNeedRender(); } void RenderRoot::SetBgColor(const Color& color) { - bgColor_ = color; + bgColor_ = isContextMenu_ ? Color::TRANSPARENT : color; forceColor_ = true; MarkNeedRender(); } diff --git a/frameworks/core/components/root/render_root.h b/frameworks/core/components/root/render_root.h index d568bdfc27522104a6fba7c05a1014ae507fcf67..463e7c38a25d08c081b376a33a05e489fa6f228d 100644 --- a/frameworks/core/components/root/render_root.h +++ b/frameworks/core/components/root/render_root.h @@ -86,6 +86,7 @@ protected: bool isBgColorInit_ = false; bool isReset_ = false; RefPtr controller_; + bool isContextMenu_; }; } // namespace OHOS::Ace diff --git a/frameworks/core/components/root/root_component.h b/frameworks/core/components/root/root_component.h index 5593ec8be4dc6378d25d1e712fa100ab97bb7c6f..63916d11da748ce75320d2d7108f10f5d117dba7 100644 --- a/frameworks/core/components/root/root_component.h +++ b/frameworks/core/components/root/root_component.h @@ -42,8 +42,18 @@ public: return child_; } + void MarkContextMenu() + { + isContextMenu_ = true; + } + + bool IsContextMenu() + { + return isContextMenu_; + } private: RefPtr child_; + bool isContextMenu_ = false; }; } // namespace OHOS::Ace diff --git a/frameworks/core/components/root/rosen_render_root.cpp b/frameworks/core/components/root/rosen_render_root.cpp index 297ac9de9f9007e882bcd4e3639df989a59003cb..2cf51ba4e323a378372655e8b414a39257c2ffb6 100644 --- a/frameworks/core/components/root/rosen_render_root.cpp +++ b/frameworks/core/components/root/rosen_render_root.cpp @@ -30,6 +30,10 @@ void RosenRenderRoot::Paint(RenderContext& context, const Offset& offset) LOGE("Paint canvas is null"); return; } + LOGI("color is %{public}s", bgColor_.ColorToString().c_str()); + if (isContextMenu_) { + bgColor_ = Color::TRANSPARENT; + } rsNode->SetBackgroundColor(bgColor_.GetValue()); rsNode->SetPivot(0.0f, 0.0f); rsNode->SetScale(scale_); diff --git a/frameworks/core/components/select_popup/render_select_popup.cpp b/frameworks/core/components/select_popup/render_select_popup.cpp index abf76ed1388766e71df9faccced595078b85b359..f9daa2b7371bca2f6a73ddf892ffcabc3895bc01 100644 --- a/frameworks/core/components/select_popup/render_select_popup.cpp +++ b/frameworks/core/components/select_popup/render_select_popup.cpp @@ -305,7 +305,9 @@ void RenderSelectPopup::PerformLayout() normalPadding_ = NormalizeToPx(rrectSize_); globalRightBottom_ = Offset() + renderRoot_->GetLayoutSize(); double outPadding = NormalizeToPx(4.0_vp); // the out padding is 4dp from doc. - + if (isContextMenu_) { + outPadding = 0.0; + } Size totalSize; double fixHeight = 0.0; if (renderTitleBox_) { @@ -380,13 +382,20 @@ void RenderSelectPopup::PerformLayout() void RenderSelectPopup::HandleRawEvent(const Offset& clickPosition) { + LOGD("Handle Raw Event, Position is %{public}s.", clickPosition.ToString().c_str()); if (touchRegion_.ContainsInRegion(clickPosition.GetX(), clickPosition.GetY())) { + LOGI("Contains the touch region."); return; } if (!selectPopup_) { return; } + if (isContextMenu_) { + LOGI("Hide the contextmenu."); + selectPopup_->CloseContextMenu(); + return; + } selectPopup_->HideDialog(SELECT_INVALID_INDEX); } @@ -410,10 +419,14 @@ void RenderSelectPopup::ProcessTouchUp(const TouchEventInfo& info) } auto offset = touches.front().GetGlobalLocation(); - firstFingerUpOffset_ = offset; - if ((offset - firstFingerDownOffset_).GetDistance() <= DEFAULT_DISTANCE) { - selectPopup_->HideDialog(SELECT_INVALID_INDEX); - firstFingerDownOffset_ = Offset(); + if (!isContextMenu_) { + firstFingerUpOffset_ = offset; + if ((offset - firstFingerDownOffset_).GetDistance() <= DEFAULT_DISTANCE) { + selectPopup_->HideDialog(SELECT_INVALID_INDEX); + firstFingerDownOffset_ = Offset(); + } + } else { + HandleRawEvent(offset); } } diff --git a/frameworks/core/components/select_popup/render_select_popup.h b/frameworks/core/components/select_popup/render_select_popup.h index a9ac41dddec442a3688acdab1e002b14c7e27a6b..b495acc8d876f5314f89cd6e96c10eb3f6f2bc9d 100644 --- a/frameworks/core/components/select_popup/render_select_popup.h +++ b/frameworks/core/components/select_popup/render_select_popup.h @@ -82,6 +82,7 @@ protected: Dimension optionInterval_; Dimension rrectSize_; + bool isContextMenu_ = false; private: void AdjustTvChildVerticalLayout(const Size& size, double& y, double& height); void AdjustTvChildHorizontalLayout(const Size& size, double& x, double& width); @@ -120,7 +121,7 @@ private: bool screenHorizontal_ = false; bool screenVertical_ = false; bool animationCreated_ = false; - bool isContextMenu_ = false; + double normalPadding_ = 0.0; RefPtr theme_; diff --git a/frameworks/core/components/select_popup/select_popup_component.cpp b/frameworks/core/components/select_popup/select_popup_component.cpp index 89fca58443c0398cfb2b4db47f4fbbf111e4a565..6945b209342f1e1e6d53f3fd2539f35c190e2bd2 100644 --- a/frameworks/core/components/select_popup/select_popup_component.cpp +++ b/frameworks/core/components/select_popup/select_popup_component.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 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 @@ -15,6 +15,7 @@ #include "core/components/select_popup/select_popup_component.h" +#include "base/subwindow/subwindow_manager.h" #include "base/utils/string_utils.h" #include "core/components/clip/clip_component.h" #include "core/components/common/properties/shadow_config.h" @@ -166,6 +167,41 @@ void SelectPopupComponent::ShowDialog( isMenu_ = isMenu; } +void SelectPopupComponent::ShowContextMenu(const Offset& offset) +{ + LOGI("Show contextMenu, position is %{public}s", offset.ToString().c_str()); + RefPtr positioned = AceType::DynamicCast(GetChild()); + if (positioned) { + positioned->SetAutoFocus(true); + } + selectLeftTop_ = offset; + selectRightBottom_ = offset; + SubwindowManager::GetInstance()->ShowMenu(AceType::Claim(this)); +} + +void SelectPopupComponent::CloseContextMenu() +{ + LOGI("Close Contextmenu."); + SubwindowManager::GetInstance()->CloseMenu(); +#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) + auto parentNode = node_->GetParentNode(); + if (parentNode) { + parentNode->SetLeft(0); + parentNode->SetTop(0); + parentNode->SetWidth(0); + parentNode->SetHeight(0); + } +#endif + auto manager = manager_.Upgrade(); + if (manager) { + for (const auto& option : options_) { + option->SetNode(nullptr); + } + manager->RemoveAccessibilityNodes(node_); + SetNode(nullptr); + } +} + RefPtr SelectPopupComponent::InitializeInnerBox(const RefPtr& scroll) { RefPtr innerBox = AceType::MakeRefPtr(); diff --git a/frameworks/core/components/select_popup/select_popup_component.h b/frameworks/core/components/select_popup/select_popup_component.h index 9258274898269d79d6bdc4910471ffddb7a90c55..ee5405c67d5a6d51a18149186823bcc82c48fa28 100644 --- a/frameworks/core/components/select_popup/select_popup_component.h +++ b/frameworks/core/components/select_popup/select_popup_component.h @@ -248,6 +248,8 @@ public: void HideDialog(uint32_t index); void ShowDialog( const RefPtr& stackElement, const Offset& leftTop, const Offset& rightBottom, bool isMenu); + void ShowContextMenu(const Offset& offset); + void CloseContextMenu(); bool Initialize(const RefPtr& manager); diff --git a/frameworks/core/components/test/unittest/menu/menu_component_test.cpp b/frameworks/core/components/test/unittest/menu/menu_component_test.cpp index 1bb705d3b94c1996be433edd7758f222f5bb453c..a4d5872b64f0a1a53073426fe6cfbf1231f75ee2 100644 --- a/frameworks/core/components/test/unittest/menu/menu_component_test.cpp +++ b/frameworks/core/components/test/unittest/menu/menu_component_test.cpp @@ -15,6 +15,7 @@ #include "gtest/gtest.h" +#include "base/subwindow/subwindow.h" #include "base/utils/utils.h" #include "core/components/menu/menu_component.h" @@ -30,6 +31,11 @@ const uint32_t TEST_OPTION_COUNT = 10u; } // namespace +RefPtr Subwindow::CreateSubwindow(int32_t instanceId) +{ + return nullptr; +} + class MenuComponentTest : public testing::Test { public: static void SetUpTestCase() {} diff --git a/frameworks/core/components/test/unittest/mock/window_mock.h b/frameworks/core/components/test/unittest/mock/window_mock.h index ddb5dfeac2e71acf471297ce65ff6b9d9ff280d1..466cca46cccb1225d6be7817e60e623485310e55 100644 --- a/frameworks/core/components/test/unittest/mock/window_mock.h +++ b/frameworks/core/components/test/unittest/mock/window_mock.h @@ -18,6 +18,7 @@ #include +#include "base/subwindow/subwindow.h" #include "core/common/platform_window.h" #include "core/common/window.h" #include "core/components/box/render_box.h" @@ -115,6 +116,11 @@ RefPtr RenderContext::Create() return AceType::MakeRefPtr(); } +RefPtr Subwindow::CreateSubwindow(int32_t instanceId) +{ + return nullptr; +} + class TweenTestUtils { public: TweenTestUtils() = delete; diff --git a/frameworks/core/components/touch_listener/render_touch_listener.cpp b/frameworks/core/components/touch_listener/render_touch_listener.cpp index 2abd9f4f8c33510bdd9abbaf1147cbfb6c6044f7..7821e440eb0e8e15edd26d101ef103c937ad5c2a 100644 --- a/frameworks/core/components/touch_listener/render_touch_listener.cpp +++ b/frameworks/core/components/touch_listener/render_touch_listener.cpp @@ -131,6 +131,7 @@ bool RenderTouchListener::TriggerTouchCallBack(const TouchEvent& changedPoint) float localY = changedPoint.y - coordinateOffset_.GetY(); changedInfo.SetLocalLocation(Offset(localX, localY)); changedInfo.SetGlobalLocation(Offset(changedPoint.x, changedPoint.y)); + changedInfo.SetScreenLocation(Offset(changedPoint.screenX, changedPoint.screenY)); changedInfo.SetTouchType(changedPoint.type); event->AddChangedTouchLocationInfo(std::move(changedInfo)); @@ -138,11 +139,14 @@ bool RenderTouchListener::TriggerTouchCallBack(const TouchEvent& changedPoint) for (const auto& pointPair : touchPointMap_) { float globalX = pointPair.second.x; float globalY = pointPair.second.y; + float screenX = pointPair.second.screenX; + float screenY = pointPair.second.screenY; float localX = pointPair.second.x - coordinateOffset_.GetX(); float localY = pointPair.second.y - coordinateOffset_.GetY(); TouchLocationInfo info(pointPair.second.id); info.SetGlobalLocation(Offset(globalX, globalY)); info.SetLocalLocation(Offset(localX, localY)); + info.SetScreenLocation(Offset(screenX, screenY)); info.SetTouchType(pointPair.second.type); event->AddTouchLocationInfo(std::move(info)); } diff --git a/frameworks/core/event/event_convertor.cpp b/frameworks/core/event/event_convertor.cpp index cdaf307f891197b705e84e32bf04de9ebc7f4839..7e172f95ab62818acf94d9e893658f465115b69c 100644 --- a/frameworks/core/event/event_convertor.cpp +++ b/frameworks/core/event/event_convertor.cpp @@ -31,6 +31,7 @@ void ConvertTouchEvent(const std::vector& data, std::vector std::chrono::microseconds micros(current->timeStamp); TimeStamp time(micros); TouchEvent point { static_cast(current->actionId), static_cast(current->physicalX), + static_cast(current->physicalY), static_cast(current->physicalX), static_cast(current->physicalY), TouchType::UNKNOWN, time, current->size, static_cast(current->pressure), static_cast(current->sourceDeviceId) }; switch (current->actionType) { diff --git a/frameworks/core/event/mouse_event.h b/frameworks/core/event/mouse_event.h index 9b7e3eae4c8c33896443cc467f5dafe48ea17f15..453f3f57987e84e5083e46a5f7efaf926bfe9341 100644 --- a/frameworks/core/event/mouse_event.h +++ b/frameworks/core/event/mouse_event.h @@ -57,6 +57,8 @@ struct MouseEvent final { float scrollX = 0.0f; float scrollY = 0.0f; float scrollZ = 0.0f; + float screenX = 0.0f; + float screenY = 0.0f; MouseAction action = MouseAction::NONE; MouseButton button = MouseButton::NONE_BUTTON; int32_t pressedButtons = 0; // combined by MouseButtons @@ -69,6 +71,11 @@ struct MouseEvent final { return Offset(x, y); } + Offset GetScreenOffset() const + { + return Offset(screenX, screenY); + } + int32_t GetId() const { if (pressedButtons > 0) { @@ -90,6 +97,8 @@ struct MouseEvent final { .scrollX = scrollX, .scrollY = scrollY, .scrollZ = scrollZ, + .screenX = screenX, + .screenY = screenY, .action = action, .button = button, .pressedButtons = pressedButtons, @@ -107,6 +116,8 @@ struct MouseEvent final { .scrollX = scrollX / scale, .scrollY = scrollY / scale, .scrollZ = scrollZ / scale, + .screenX = screenX / scale, + .screenY = screenY / scale, .action = action, .button = button, .pressedButtons = pressedButtons, @@ -128,12 +139,19 @@ struct MouseEvent final { type = TouchType::UNKNOWN; } int32_t id = GetId(); - TouchPoint point { - .id = id, .x = x, .y = y, .downTime = time, .size = 0.0, .isPressed = (type == TouchType::DOWN) - }; + TouchPoint point { .id = id, + .x = x, + .y = y, + .screenX = screenX, + .screenY = screenY, + .downTime = time, + .size = 0.0, + .isPressed = (type == TouchType::DOWN) }; TouchEvent event { .id = id, .x = x, .y = y, + .screenX = screenX, + .screenY = screenY, .type = type, .time = time, .size = 0.0, @@ -154,6 +172,8 @@ struct MouseEvent final { .scrollX = scrollX, .scrollY = scrollY, .scrollZ = scrollZ, + .screenX = screenX - offset.GetX(), + .screenY = screenY - offset.GetY(), .action = action, .button = button, .pressedButtons = pressedButtons, @@ -201,6 +221,17 @@ public: return *this; } + MouseInfo& SetScreenLocation(const Offset& screenLocation) + { + screenLocation_ = screenLocation; + return *this; + } + + const Offset& GetScreenLocation() const + { + return screenLocation_; + } + const Offset& GetLocalLocation() const { return localLocation_; @@ -218,6 +249,7 @@ private: // Different from global location, The local location refers to the location of the contact point relative to the // current node which has the recognizer. Offset localLocation_; + Offset screenLocation_; }; class MouseEventTarget : public virtual AceType { diff --git a/frameworks/core/event/touch_event.h b/frameworks/core/event/touch_event.h index 976a33276da2b179fd59838ced1ec1eba23e083b..6a5d2a9e1905b5dbfa9f8ca91f27661d64cb3612 100644 --- a/frameworks/core/event/touch_event.h +++ b/frameworks/core/event/touch_event.h @@ -57,6 +57,8 @@ struct TouchPoint final { int32_t id = 0; float x = 0.0f; float y = 0.0f; + float screenX = 0.0f; + float screenY = 0.0f; TimeStamp downTime; double size = 0.0; float force = 0.0f; @@ -73,6 +75,8 @@ struct TouchEvent final { int32_t id = 0; float x = 0.0f; float y = 0.0f; + float screenX = 0.0f; + float screenY = 0.0f; TouchType type = TouchType::UNKNOWN; // nanosecond time stamp. TimeStamp time; @@ -89,17 +93,25 @@ struct TouchEvent final { return Offset(x, y); } + Offset GetScreenOffset() const + { + return Offset(screenX, screenY); + } + TouchEvent CreateScalePoint(float scale) const { if (NearZero(scale)) { - return { id, x, y, type, time, size, force, deviceId, sourceType, pointers }; + return { id, x, y, screenX, screenY, type, time, size, force, deviceId, sourceType, pointers }; } auto temp = pointers; std::for_each(temp.begin(), temp.end(), [scale](auto&& point) { point.x = point.x / scale; point.y = point.y / scale; + point.screenX = point.screenX / scale; + point.screenY = point.screenY / scale; }); - return { id, x / scale, y / scale, type, time, size, force, deviceId, sourceType, temp }; + return { id, x / scale, y / scale, screenX / scale, screenY / scale, type, time, size, force, deviceId, + sourceType, temp }; } TouchEvent UpdateScalePoint(float scale, float offsetX, float offsetY, int32_t pointId) const @@ -109,16 +121,21 @@ struct TouchEvent final { std::for_each(temp.begin(), temp.end(), [offsetX, offsetY](auto&& point) { point.x = point.x - offsetX; point.y = point.y - offsetY; + point.screenX = point.screenX - offsetX; + point.screenY = point.screenY - offsetY; }); - return { pointId, x - offsetX, y - offsetY, type, time, size, force, deviceId, sourceType, temp }; + return { pointId, x - offsetX, y - offsetY, screenX - offsetX, screenY - offsetY, type, time, size, force, + deviceId, sourceType, temp }; } std::for_each(temp.begin(), temp.end(), [scale, offsetX, offsetY](auto&& point) { point.x = (point.x - offsetX) / scale; point.y = (point.y - offsetY) / scale; + point.screenX = (point.screenX - offsetX) / scale; + point.screenY = (point.screenY - offsetY) / scale; }); - return { pointId, (x - offsetX) / scale, (y - offsetY) / scale, type, time, size, force, deviceId, sourceType, - temp }; + return { pointId, (x - offsetX) / scale, (y - offsetY) / scale, (screenX - offsetX) / scale, + (screenY - offsetY) / scale, type, time, size, force, deviceId, sourceType, temp }; } }; @@ -214,6 +231,17 @@ public: return *this; } + TouchLocationInfo& SetScreenLocation(const Offset& screenLocation) + { + screenLocation_ = screenLocation; + return *this; + } + + const Offset& GetScreenLocation() const + { + return screenLocation_; + } + const Offset& GetLocalLocation() const { return localLocation_; @@ -275,6 +303,8 @@ private: // current node which has the recognizer. Offset localLocation_; + Offset screenLocation_; + // finger touch size double size_ = 0.0; diff --git a/frameworks/core/gestures/gesture_info.h b/frameworks/core/gestures/gesture_info.h index 929a2bd0f4ef8688065c2c0f56144d6145bea8cb..9ce18b3bf28e8eecddc4da189875751c4e0978a0 100644 --- a/frameworks/core/gestures/gesture_info.h +++ b/frameworks/core/gestures/gesture_info.h @@ -388,6 +388,17 @@ public: return globalPoint_; } + GestureEvent& SetScreenLocation(const Offset& screenLocation) + { + screenLocation_ = screenLocation; + return *this; + } + + const Offset& GetScreenLocation() const + { + return screenLocation_; + } + GestureEvent& SetGlobalLocation(const Offset& globalLocation) { globalLocation_ = globalLocation; @@ -463,6 +474,7 @@ private: // Different from global location, The local location refers to the location of the contact point relative to the // current node which has the recognizer. Offset localLocation_; + Offset screenLocation_; Offset pinchCenter_; std::list fingerList_; }; diff --git a/frameworks/core/gestures/long_press_recognizer.cpp b/frameworks/core/gestures/long_press_recognizer.cpp index 697e096bed098fd2932b8f769f660d08e51f3819..1858c7f4e3fc841831e5ae00f646c0708bd02919 100644 --- a/frameworks/core/gestures/long_press_recognizer.cpp +++ b/frameworks/core/gestures/long_press_recognizer.cpp @@ -32,6 +32,7 @@ void LongPressRecognizer::OnAccepted() TouchEvent trackPoint = touchMap_.begin()->second; LongPressInfo info(trackPoint.id); info.SetTimeStamp(time_); + info.SetScreenLocation(trackPoint.GetScreenOffset()); info.SetGlobalLocation(trackPoint.GetOffset()).SetLocalLocation(trackPoint.GetOffset() - coordinateOffset_); onLongPress_(info); } @@ -228,6 +229,7 @@ void LongPressRecognizer::SendCallbackMsg(const std::unique_ptr PipelineContext::SetupRootElement() return rootElement_; } +RefPtr PipelineContext::SetupSubRootElement() +{ + LOGI("Set up SubRootElement!"); + + RefPtr rootStage = AceType::MakeRefPtr(std::list>()); + if (isRightToLeft_) { + rootStage->SetTextDirection(TextDirection::RTL); + } + if (GetIsDeclarative()) { + rootStage->SetMainStackSize(MainStackSize::MAX); + } else { + rootStage->SetMainStackSize(MainStackSize::LAST_CHILD_HEIGHT); + } + auto stack = AceType::MakeRefPtr( + Alignment::TOP_LEFT, StackFit::KEEP, Overflow::OBSERVABLE, std::list>()); + + auto overlay = AceType::MakeRefPtr(std::list>()); + overlay->SetTouchable(false); + stack->AppendChild(rootStage); + stack->AppendChild(overlay); + RefPtr rootComponent; + rootComponent = RootComponent::Create(stack); + rootComponent->MarkContextMenu(); + rootElement_ = rootComponent->SetupElementTree(AceType::Claim(this)); + if (!rootElement_) { + LOGE("Set up SubRootElement failed!"); + EventReport::SendAppStartException(AppStartExcepType::PIPELINE_CONTEXT_ERR); + return RefPtr(); + } + const auto& rootRenderNode = rootElement_->GetRenderNode(); + window_->SetRootRenderNode(rootRenderNode); +#ifdef ENABLE_ROSEN_BACKEND + if (SystemProperties::GetRosenBackendEnabled() && rsUIDirector_) { + rsUIDirector_->SetRoot(rootRenderNode->GetRSNode()->GetId()); + } +#endif + sharedTransitionController_->RegisterTransitionListener(); + cardTransitionController_->RegisterTransitionListener(); + requestedRenderNode_.Reset(); + LOGI("Set up SubRootElement success!"); + return rootElement_; +} + void PipelineContext::Dump(const std::vector& params) const { if (params.empty()) { @@ -932,6 +975,18 @@ void PipelineContext::DumpInfo(const std::vector& params, std::vect RefPtr PipelineContext::GetLastStack() const { + if (!rootElement_) { + LOGE("Rootelement is null"); + return RefPtr(); + } + if (isSubPipeline_) { + const auto& stack = AceType::DynamicCast(rootElement_->GetFirstChild()); + if (!stack) { + LOGE("Get stack failed, it is null"); + return RefPtr(); + } + return stack; + } const auto& pageElement = GetLastPage(); if (!pageElement) { return RefPtr(); @@ -2476,6 +2531,9 @@ void PipelineContext::OnHide() if (!context) { return; } + if (context->IsSubPipeline()) { + context->FlushPipelineImmediately(); + } #ifdef ENABLE_ROSEN_BACKEND if (context->rsUIDirector_) { context->rsUIDirector_->GoBackground(); diff --git a/frameworks/core/pipeline/pipeline_context.h b/frameworks/core/pipeline/pipeline_context.h index 7fe9c54b4cb9d8a3d7ffdfca943b01ada2132cbc..dc0ed721a7d2865d7d421fb69bbac15381905876 100644 --- a/frameworks/core/pipeline/pipeline_context.h +++ b/frameworks/core/pipeline/pipeline_context.h @@ -122,6 +122,8 @@ public: RefPtr SetupRootElement(); + // This is used for subwindow, when the subwindow is created,a new subrootElement will be built + RefPtr SetupSubRootElement(); RefPtr ShowDialog(const DialogProperties& dialogProperties, bool isRightToLeft, const std::string& inspectorTag = ""); void CloseContextMenu(); @@ -1202,6 +1204,15 @@ public: std::string GetRestoreInfo(int32_t restoreId); + void SetIsSubPipeline(bool isSubPipeline) + { + isSubPipeline_ = isSubPipeline; + } + + bool IsSubPipeline() const + { + return isSubPipeline_; + } private: void FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount); void FlushPipelineWithoutAnimation(); @@ -1443,6 +1454,7 @@ private: std::unordered_map> storeNode_; std::unordered_map restoreNodeInfo_; + bool isSubPipeline_ = false; ACE_DISALLOW_COPY_AND_MOVE(PipelineContext); };