1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "adapter/ohos/entrance/subwindow/subwindow_ohos.h"
17
18 #include "dm/display_manager.h"
19 #include "interfaces/innerkits/ace/viewport_config.h"
20 #include "render_service_client/core/ui/rs_ui_director.h"
21
22 #include "adapter/ohos/entrance/ace_application_info.h"
23 #include "adapter/ohos/entrance/ace_container.h"
24 #include "adapter/ohos/entrance/flutter_ace_view.h"
25 #include "adapter/ohos/entrance/utils.h"
26 #include "base/utils/system_properties.h"
27 #include "core/common/container_scope.h"
28 #include "core/common/frontend.h"
29 #include "core/components/popup/popup_component.h"
30
31 namespace OHOS::Ace {
32
33 int32_t SubwindowOhos::id_ = 0;
34
CreateSubwindow(int32_t instanceId)35 RefPtr<Subwindow> Subwindow::CreateSubwindow(int32_t instanceId)
36 {
37 LOGI("Create Subwindow, parent container id is %{public}d", instanceId);
38 return AceType::MakeRefPtr<SubwindowOhos>(instanceId);
39 }
40
SubwindowOhos(int32_t instanceId)41 SubwindowOhos::SubwindowOhos(int32_t instanceId)
42 {
43 parentContainerId_ = instanceId;
44 windowId_ = id_;
45 SetSubwindowId(windowId_);
46 id_++;
47 }
48
InitContainer()49 void SubwindowOhos::InitContainer()
50 {
51 LOGI("Subwindow start initialize container");
52 if (!window_) {
53 LOGI("Window is null, need create a new window");
54 OHOS::sptr<OHOS::Rosen::WindowOption> windowOption = new OHOS::Rosen::WindowOption();
55 auto parentWindowName = Platform::AceContainer::GetContainer(parentContainerId_)->GetWindowName();
56 auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
57 sptr<OHOS::Rosen::Window> parentWindow = OHOS::Rosen::Window::Find(parentWindowName);
58 if (parentWindow == nullptr) {
59 return;
60 }
61 auto windowType = parentWindow->GetType();
62 if (windowType == Rosen::WindowType::WINDOW_TYPE_DESKTOP) {
63 windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_FLOAT);
64 } else {
65 windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_APP_SUB_WINDOW);
66 windowOption->SetParentName(parentWindowName);
67 }
68 windowOption->SetWindowRect({ 0, 0, defaultDisplay->GetWidth(), defaultDisplay->GetHeight() });
69 windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING);
70 window_ = OHOS::Rosen::Window::Create(
71 "ARK_APP_SUBWINDOW_" + parentWindowName + std::to_string(windowId_), windowOption);
72 if (window_ == nullptr) {
73 LOGI("create window error return");
74 return;
75 }
76 }
77 std::string url = "";
78 window_->SetUIContent(url, nullptr, nullptr, false);
79 childContainerId_ = SubwindowManager::GetInstance()->GetContainerId(window_->GetWindowId());
80 SubwindowManager::GetInstance()->AddParentContainerId(childContainerId_, parentContainerId_);
81 auto parentContainer = Platform::AceContainer::GetContainer(parentContainerId_);
82 if (!parentContainer) {
83 LOGE("Get container failed, container is null");
84 return;
85 }
86
87 auto container = Platform::AceContainer::GetContainer(childContainerId_);
88 if (!container) {
89 LOGE("Get container failed, container is null");
90 return;
91 }
92
93 container->SetParentId(parentContainerId_);
94 container->GetSettings().SetUsingSharedRuntime(true);
95 container->SetSharedRuntime(parentContainer->GetSharedRuntime());
96 container->Initialize();
97 container->SetAssetManager(parentContainer->GetAssetManager());
98 container->SetResourceConfiguration(parentContainer->GetResourceConfiguration());
99 container->SetPackagePathStr(parentContainer->GetPackagePathStr());
100 container->SetIsSubContainer(true);
101 container->InitializeSubContainer(parentContainerId_);
102 ViewportConfig config;
103 // create ace_view
104 auto flutterAceView =
105 Platform::FlutterAceView::CreateView(childContainerId_, true, container->GetSettings().usePlatformAsUIThread);
106 Platform::FlutterAceView::SurfaceCreated(flutterAceView, window_);
107
108 int32_t width = static_cast<int32_t>(window_->GetRect().width_);
109 int32_t height = static_cast<int32_t>(window_->GetRect().height_);
110 LOGI("UIContent Initialize: width: %{public}d, height: %{public}d", width, height);
111
112 Ace::Platform::UIEnvCallback callback = nullptr;
113 // set view
114 Platform::AceContainer::SetView(flutterAceView, config.Density(), width, height, window_->GetWindowId(), callback);
115 Platform::FlutterAceView::SurfaceChanged(flutterAceView, width, height, config.Orientation());
116
117 #ifdef ENABLE_ROSEN_BACKEND
118 if (SystemProperties::GetRosenBackendEnabled()) {
119 rsUiDirector = OHOS::Rosen::RSUIDirector::Create();
120 if (rsUiDirector != nullptr) {
121 rsUiDirector->SetRSSurfaceNode(window_->GetSurfaceNode());
122 rsUiDirector->SetUITaskRunner(
123 [taskExecutor = container->GetTaskExecutor()](
124 const std::function<void()>& task) { taskExecutor->PostTask(task, TaskExecutor::TaskType::UI); });
125 auto context = container->GetPipelineContext();
126 if (context != nullptr) {
127 LOGI("Init RSUIDirector");
128 context->SetRSUIDirector(rsUiDirector);
129 }
130 rsUiDirector->Init();
131 LOGI("UIContent Init Rosen Backend");
132 }
133 }
134 #endif
135 auto subPipelineContext = Platform::AceContainer::GetContainer(childContainerId_)->GetPipelineContext();
136 if (!subPipelineContext) {
137 LOGE("Get SubPipelineContext failed, pipelineContext is null");
138 }
139 subPipelineContext->SetupSubRootElement();
140 }
141
ShowWindow()142 void SubwindowOhos::ShowWindow()
143 {
144 LOGI("Show the subwindow");
145 if (!window_) {
146 LOGE("Show window failed, window is null");
147 return;
148 }
149
150 OHOS::Rosen::WMError ret = window_->Show();
151
152 if (ret != OHOS::Rosen::WMError::WM_OK) {
153 LOGE("Show window failed with errCode: %{public}d", static_cast<int32_t>(ret));
154 return;
155 }
156 LOGI("Show the subwindow successfully.");
157 SubwindowManager::GetInstance()->SetCurrentSubwindow(AceType::Claim(this));
158 }
159
HideWindow()160 void SubwindowOhos::HideWindow()
161 {
162 LOGI("Hide the subwindow");
163 if (!window_) {
164 LOGE("Hide window failed, window is null");
165 return;
166 }
167
168 OHOS::Rosen::WMError ret = window_->Hide();
169
170 if (ret != OHOS::Rosen::WMError::WM_OK) {
171 LOGE("Hide window failed with errCode: %{public}d", static_cast<int32_t>(ret));
172 return;
173 }
174 LOGI("Hide the subwindow successfully.");
175 }
176
AddMenu(const RefPtr<Component> & newComponent)177 void SubwindowOhos::AddMenu(const RefPtr<Component>& newComponent)
178 {
179 LOGI("Subwindow push new component start.");
180 auto stack = GetStack();
181 if (!stack) {
182 LOGE("Get stack failed, it is null");
183 return;
184 }
185 // Push the component
186 stack->PopMenu();
187 stack->PushComponent(newComponent);
188 popup_ = AceType::DynamicCast<SelectPopupComponent>(newComponent);
189 if (!popup_) {
190 LOGE("Add menu failed, this is not a popup component.");
191 }
192 LOGI("Subwindow push new component end.");
193 }
194
ClearMenu()195 void SubwindowOhos::ClearMenu()
196 {
197 LOGI("Subwindow Clear menu start.");
198 auto stack = GetStack();
199 if (!stack) {
200 LOGE("Get stack failed, it is null");
201 return;
202 }
203 // Pop the component
204 stack->PopMenu();
205 auto context = stack->GetContext().Upgrade();
206 if (!context) {
207 LOGE("Get context failed, it is null");
208 }
209 context->FlushPipelineImmediately();
210 HideWindow();
211 LOGI("Subwindow clear menu end.");
212 }
213
ShowMenu(const RefPtr<Component> & newComponent)214 void SubwindowOhos::ShowMenu(const RefPtr<Component>& newComponent)
215 {
216 LOGI("Show the menu");
217 ShowWindow();
218 AddMenu(newComponent);
219 }
220
CloseMenu()221 void SubwindowOhos::CloseMenu()
222 {
223 LOGI("Close the menu");
224 if (popup_) {
225 popup_->CloseContextMenu();
226 }
227 }
228
GetStack()229 RefPtr<StackElement> SubwindowOhos::GetStack()
230 {
231 auto aceContainer = Platform::AceContainer::GetContainer(childContainerId_);
232 if (!aceContainer) {
233 LOGE("Get container failed, it is null");
234 return nullptr;
235 }
236
237 auto context = aceContainer->GetPipelineContext();
238 if (!context) {
239 LOGE("Get context failed, it is null");
240 return nullptr;
241 }
242 return context->GetLastStack();
243 }
244
245 } // namespace OHOS::Ace