1 /*
2  * Copyright (c) 2024 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 #include "js_err_utils.h"
16 #include "js_window_manager.h"
17 #include "js_window.h"
18 #include "js_window_utils.h"
19 #include "window_helper.h"
20 #include "window_manager_hilog.h"
21 #include "window_option.h"
22 namespace OHOS {
23 namespace Rosen {
24 using namespace AbilityRuntime;
25 namespace {
26 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JsWindowManager"};
27 const std::string PIP_WINDOW = "pip_window";
28 }
29 
JsWindowManager()30 JsWindowManager::JsWindowManager() : registerManager_(std::make_unique<JsWindowRegisterManager>())
31 {
32 }
33 
~JsWindowManager()34 JsWindowManager::~JsWindowManager()
35 {
36 }
37 
Finalizer(napi_env env,void * data,void * hint)38 void JsWindowManager::Finalizer(napi_env env, void* data, void* hint)
39 {
40     WLOGI("Finalizer");
41     std::unique_ptr<JsWindowManager>(static_cast<JsWindowManager*>(data));
42 }
43 
Create(napi_env env,napi_callback_info info)44 napi_value JsWindowManager::Create(napi_env env, napi_callback_info info)
45 {
46     WLOGI("mock: Create");
47     return nullptr;
48 }
49 
CreateWindowNapi(napi_env env,napi_callback_info info)50 napi_value JsWindowManager::CreateWindowNapi(napi_env env, napi_callback_info info)
51 {
52     WLOGI("mock: CreateWindowNapi");
53     return nullptr;
54 }
55 
FindWindow(napi_env env,napi_callback_info info)56 napi_value JsWindowManager::FindWindow(napi_env env, napi_callback_info info)
57 {
58     WLOGI("mock: FindWindow");
59     return nullptr;
60 }
61 
FindWindowSync(napi_env env,napi_callback_info info)62 napi_value JsWindowManager::FindWindowSync(napi_env env, napi_callback_info info)
63 {
64     WLOGI("mock: FindWindowSync");
65     return nullptr;
66 }
67 
RegisterWindowManagerCallback(napi_env env,napi_callback_info info)68 napi_value JsWindowManager::RegisterWindowManagerCallback(napi_env env, napi_callback_info info)
69 {
70     WLOGI("mock: RegisterWindowManagerCallback");
71     return nullptr;
72 }
73 
UnregisterWindowMangerCallback(napi_env env,napi_callback_info info)74 napi_value JsWindowManager::UnregisterWindowMangerCallback(napi_env env, napi_callback_info info)
75 {
76     WLOGI("mock: UnregisterWindowMangerCallback");
77     return nullptr;
78 }
79 
GetTopWindow(napi_env env,napi_callback_info info)80 napi_value JsWindowManager::GetTopWindow(napi_env env, napi_callback_info info)
81 {
82     WLOGI("mock: GetTopWindow");
83     return nullptr;
84 }
85 
86 /** @note @window.hierarchy */
GetLastWindow(napi_env env,napi_callback_info info)87 napi_value JsWindowManager::GetLastWindow(napi_env env, napi_callback_info info)
88 {
89     WLOGI("GetLastWindow");
90     JsWindowManager* me = CheckParamsAndGetThis<JsWindowManager>(env, info);
91     return (me != nullptr) ? me->OnGetLastWindow(env, info) : nullptr;
92 }
93 
MinimizeAll(napi_env env,napi_callback_info info)94 napi_value JsWindowManager::MinimizeAll(napi_env env, napi_callback_info info)
95 {
96     WLOGI("mock: MinimizeAll");
97     return nullptr;
98 }
99 
ToggleShownStateForAllAppWindows(napi_env env,napi_callback_info info)100 napi_value JsWindowManager::ToggleShownStateForAllAppWindows(napi_env env, napi_callback_info info)
101 {
102     WLOGI("mock: ToggleShownStateForAllAppWindows");
103     return nullptr;
104 }
105 
SetWindowLayoutMode(napi_env env,napi_callback_info info)106 napi_value JsWindowManager::SetWindowLayoutMode(napi_env env, napi_callback_info info)
107 {
108     WLOGI("mock: SetWindowLayoutMode");
109     return nullptr;
110 }
111 
SetGestureNavigationEnabled(napi_env env,napi_callback_info info)112 napi_value JsWindowManager::SetGestureNavigationEnabled(napi_env env, napi_callback_info info)
113 {
114     WLOGI("mock: SetGestureNavigationEnabled");
115     return nullptr;
116 }
117 
SetWaterMarkImage(napi_env env,napi_callback_info info)118 napi_value JsWindowManager::SetWaterMarkImage(napi_env env, napi_callback_info info)
119 {
120     WLOGI("mock: SetWaterMarkImage");
121     return nullptr;
122 }
123 
ShiftAppWindowFocus(napi_env env,napi_callback_info info)124 napi_value JsWindowManager::ShiftAppWindowFocus(napi_env env, napi_callback_info info)
125 {
126     WLOGI("mock: ShiftAppWindowFocus");
127     return nullptr;
128 }
129 
GetNativeContext(napi_env env,napi_value nativeContext,void * & contextPtr,WMError & errCode)130 static void GetNativeContext(napi_env env, napi_value nativeContext, void*& contextPtr, WMError& errCode)
131 {
132     AppExecFwk::Ability* ability = nullptr;
133     bool isOldApi = GetAPI7Ability(env, ability);
134     WLOGFD("FA mode:%{public}u", isOldApi);
135     if (isOldApi) {
136         return;
137     }
138     if (nativeContext != nullptr) {
139         napi_unwrap(env, nativeContext, &contextPtr);
140     }
141 }
142 
GetTopWindowTask(void * contextPtr,napi_env env,napi_value callback,bool newApi)143 static napi_value GetTopWindowTask(void* contextPtr, napi_env env, napi_value callback, bool newApi)
144 {
145     struct TopWindowInfoList {
146         sptr<Window> window = nullptr;
147     };
148     std::shared_ptr<TopWindowInfoList> lists = std::make_shared<TopWindowInfoList>();
149     NapiAsyncTask::ExecuteCallback execute = [lists, newApi, contextPtr]() {
150         if (lists == nullptr) {
151             WLOGFE("lists == nullptr");
152             return;
153         }
154         lists->window = Window::GetTopWindowWithId(0);
155     };
156     NapiAsyncTask::CompleteCallback complete = [lists, newApi](napi_env env, NapiAsyncTask& task, int32_t status) {
157         if (lists == nullptr) {
158             if (newApi) {
159                 task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY,
160                     "napi abnormal"));
161             } else {
162                 task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_NULLPTR, "napi abnormal"));
163             }
164             return;
165         }
166         if (lists->window == nullptr) {
167             if (newApi) {
168                 task.Reject(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY,
169                     "Get top window failed"));
170             } else {
171                 task.Reject(env, JsErrUtils::CreateJsError(env, WMError::WM_ERROR_NULLPTR, "Get top window failed"));
172             }
173             return;
174         }
175         task.Resolve(env, CreateJsWindowObject(env, lists->window));
176         WLOGD("Get top window success");
177     };
178     napi_value result = nullptr;
179     NapiAsyncTask::Schedule("JsWindowManager::OnGetTopWindow",
180         env, CreateAsyncTaskWithLastParam(env, callback, std::move(execute), std::move(complete), &result));
181     return result;
182 }
183 
OnGetLastWindow(napi_env env,napi_callback_info info)184 napi_value JsWindowManager::OnGetLastWindow(napi_env env, napi_callback_info info)
185 {
186     WMError errCode = WMError::WM_OK;
187     napi_value nativeContext = nullptr;
188     napi_value nativeCallback = nullptr;
189     void* contextPtr = nullptr;
190     size_t argc = 4;
191     napi_value argv[4] = {nullptr};
192     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
193     if (argc < 1) {
194         WLOGFE("Argc is invalid: %{public}zu", argc);
195         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
196         return NapiGetUndefined(env);
197     } else {
198         nativeContext = argv[0];
199         nativeCallback = (argc == 1) ? nullptr : argv[1];
200         GetNativeContext(env, nativeContext, contextPtr, errCode);
201     }
202     if (errCode != WMError::WM_OK) {
203         napi_throw(env, JsErrUtils::CreateJsError(env, WmErrorCode::WM_ERROR_INVALID_PARAM));
204         return NapiGetUndefined(env);
205     }
206 
207     return GetTopWindowTask(contextPtr, env, nativeCallback, true);
208 }
209 
JsWindowManagerInit(napi_env env,napi_value exportObj)210 napi_value JsWindowManagerInit(napi_env env, napi_value exportObj)
211 {
212     if (env == nullptr || exportObj == nullptr) {
213         WLOGFE("JsWindowManagerInit env or exportObj is nullptr");
214         return nullptr;
215     }
216 
217     std::unique_ptr<JsWindowManager> jsWinManager = std::make_unique<JsWindowManager>();
218     napi_wrap(env, exportObj, jsWinManager.release(), JsWindowManager::Finalizer, nullptr, nullptr);
219     napi_set_named_property(env, exportObj, "WindowType", WindowTypeInit(env));
220     napi_set_named_property(env, exportObj, "AvoidAreaType", AvoidAreaTypeInit(env));
221     napi_set_named_property(env, exportObj, "WindowMode", WindowModeInit(env));
222     napi_set_named_property(env, exportObj, "ColorSpace", ColorSpaceInit(env));
223     napi_set_named_property(env, exportObj, "WindowStageEventType", WindowStageEventTypeInit(env));
224     napi_set_named_property(env, exportObj, "WindowEventType", WindowEventTypeInit(env));
225     napi_set_named_property(env, exportObj, "WindowLayoutMode", WindowLayoutModeInit(env));
226     napi_set_named_property(env, exportObj, "Orientation", OrientationInit(env));
227     napi_set_named_property(env, exportObj, "BlurStyle", BlurStyleInit(env));
228     napi_set_named_property(env, exportObj, "WmErrorCode", WindowErrorCodeInit(env));
229     napi_set_named_property(env, exportObj, "WMError", WindowErrorInit(env));
230     napi_set_named_property(env, exportObj, "WindowStatusType", WindowStatusTypeInit(env));
231     napi_set_named_property(env, exportObj, "MaximizePresentation", MaximizePresentationInit(env));
232     const char* moduleName = "JsWindowManager";
233     BindNativeFunction(env, exportObj, "create", moduleName, JsWindowManager::Create);
234     BindNativeFunction(env, exportObj, "createWindow", moduleName, JsWindowManager::CreateWindowNapi);
235     BindNativeFunction(env, exportObj, "find", moduleName, JsWindowManager::FindWindow);
236     BindNativeFunction(env, exportObj, "findWindow", moduleName, JsWindowManager::FindWindowSync);
237     BindNativeFunction(env, exportObj, "on", moduleName, JsWindowManager::RegisterWindowManagerCallback);
238     BindNativeFunction(env, exportObj, "off", moduleName, JsWindowManager::UnregisterWindowMangerCallback);
239     BindNativeFunction(env, exportObj, "getTopWindow", moduleName, JsWindowManager::GetTopWindow);
240     BindNativeFunction(env, exportObj, "getLastWindow", moduleName, JsWindowManager::GetLastWindow);
241     BindNativeFunction(env, exportObj, "minimizeAll", moduleName, JsWindowManager::MinimizeAll);
242     BindNativeFunction(env, exportObj, "toggleShownStateForAllAppWindows", moduleName,
243         JsWindowManager::ToggleShownStateForAllAppWindows);
244     BindNativeFunction(env, exportObj, "setWindowLayoutMode", moduleName, JsWindowManager::SetWindowLayoutMode);
245     BindNativeFunction(env, exportObj, "setGestureNavigationEnabled", moduleName,
246         JsWindowManager::SetGestureNavigationEnabled);
247     BindNativeFunction(env, exportObj, "setWaterMarkImage", moduleName, JsWindowManager::SetWaterMarkImage);
248     BindNativeFunction(env, exportObj, "shiftAppWindowFocus", moduleName, JsWindowManager::ShiftAppWindowFocus);
249     return NapiGetUndefined(env);
250 }
251 }  // namespace Rosen
252 }  // namespace OHOS
253