From 0b64596b93d1889b4df1edfacf2535b4ac4b64c2 Mon Sep 17 00:00:00 2001 From: hid06197980 <2089450903@qq.com> Date: Fri, 25 Jul 2025 20:57:14 +0800 Subject: [PATCH] ANI need all change xxx Signed-off-by: hid06197980 <2089450903@qq.com> --- interfaces/kits/ani/window_runtime/BUILD.gn | 1 + .../window_stage_ani/ets/@ohos.window.ets | 125 +++++++++- .../window_stage_ani/include/ani_window.h | 10 + .../include/ani_window_stage.h | 6 + .../include/ani_window_utils.h | 10 + .../window_stage_ani/src/ani_window.cpp | 169 +++++++++++++ .../window_stage_ani/src/ani_window_stage.cpp | 113 +++++++++ .../window_stage_ani/src/ani_window_utils.cpp | 232 ++++++++++++++++++ 8 files changed, 664 insertions(+), 2 deletions(-) diff --git a/interfaces/kits/ani/window_runtime/BUILD.gn b/interfaces/kits/ani/window_runtime/BUILD.gn index 09bc59e3c0..8a49dbae86 100644 --- a/interfaces/kits/ani/window_runtime/BUILD.gn +++ b/interfaces/kits/ani/window_runtime/BUILD.gn @@ -82,6 +82,7 @@ ohos_shared_library("windowstageani_kit") { "image_framework:image_native", "ipc:ipc_napi", "ipc:ipc_single", + "ipc:rpc_ani", "napi:ace_napi", "runtime_core:ani", ] diff --git a/interfaces/kits/ani/window_runtime/window_stage_ani/ets/@ohos.window.ets b/interfaces/kits/ani/window_runtime/window_stage_ani/ets/@ohos.window.ets index c3b485e59a..96faf3d7f5 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/ets/@ohos.window.ets +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/ets/@ohos.window.ets @@ -20,6 +20,8 @@ import image from '@ohos.multimedia.image'; import BaseContext from 'application.BaseContext'; import hilog from '@ohos.hilog'; import { ColorMetrics } from '@ohos.arkui.node'; +import rpc from '@ohos.rpc'; +import dialogRequest from '@ohos.app.ability.dialogRequest'; export type AsyncCallbackVoid = (err: BusinessError) => void; export type WindowEventCallback = (data: window.WindowEventType) => void; export type WindowRectCallback = (data: window.Rect) => void; @@ -692,6 +694,17 @@ export enum ModalityType { APPLICATION_MODALITY = 1 } +export interface SubWindowOptions { + title: string; + decorEnabled: boolean; + isModal?: boolean; + isTopmost?: boolean; + modalityType?: ModalityType; + windowRect?: Rect; + maximizeSupported?: boolean; + zLevel?: number; +} + export interface SystemBarProperties { /** * The color of the status bar. @@ -1626,7 +1639,7 @@ export class ScaleOptionsInternal implements ScaleOptions { pivotX?: double; pivotY?: double; } - + /** * Describes the rotate Transition Options of window * @@ -1694,7 +1707,7 @@ export class RotateOptionsInternal implements RotateOptions { pivotX?: double; pivotY?: double; } - + /** * Describes the translate Transition Options of window * @@ -1759,6 +1772,8 @@ export class WindowStageInternal implements WindowStage { public native createSubWindowSync(nativeObj: long, name: String): Window; native onSync(nativeObj: long, eventType: 'windowStageEvent', callback: Object): void; native offSync(nativeObj: long, eventType: 'windowStageEvent', callback?: Object): void; + public native getSubWindowSync(nativeObj: long): Array; + public native createSubWindowWithOptionsSync(nativeObj: long, name: string, options: SubWindowOptions): Window; public setWindowRectAutoSave(enabled: boolean, isSaveBySpecifiedFlag: boolean): Promise { return new Promise((resolve: (value: undefined) => void, reject: (error: BusinessError) => void): void => { @@ -1903,6 +1918,41 @@ export class WindowStageInternal implements WindowStage { public off(eventType: 'windowStageEvent', callback?: Callback): void { this.offSync(this.nativeObj, eventType, callback); } + + public getSubWindow(): Promise> { + return new Promise>((resolve: (value: Array) => void, + reject: (error: BusinessError) => void) => { + taskpool.execute((): Array => { + return this.getSubWindowSync(this.nativeObj); + }).then((ret: NullishType) => { + resolve(ret as Array); + }).catch((err: NullishType) => { + reject(err as BusinessError); + }) + }) + } + + public getSubWindow(callback: AsyncCallback | undefined>): void { + taskpool.execute((): Array => { + return this.getSubWindowSync(this.nativeObj); + }).then((ret: NullishType) => { + callback(new BusinessError(), ret as Array); + }).catch((err: NullishType) => { + callback(err as BusinessError, undefined); + }) + } + + public createSubWindowWithOptions(name: string, options: SubWindowOptions): Promise { + return new Promise((resolve: (value: Window) => void, reject: (error: BusinessError) => void) => { + taskpool.execute((): Window => { + return this.createSubWindowWithOptionsSync(this.nativeObj, name, options); + }).then((ret: NullishType) => { + resolve(ret as Window); + }).catch((err: NullishType) => { + reject(err as BusinessError); + }) + }) + } } export interface WindowStage { @@ -1922,6 +1972,9 @@ export interface WindowStage { setShowOnLockScreen(showOnLockScreen: boolean): void; on(eventType: 'windowStageEvent', callback: Callback): void; off(eventType: 'windowStageEvent', callback?: Callback): void; + getSubWindow(callback: AsyncCallback | undefined>): void; + getSubWindow(): Promise>; + createSubWindowWithOptions(name: string, options: SubWindowOptions): Promise; } export native function windowDestroyCallback(nativeObj: long): void; @@ -2008,6 +2061,10 @@ export class WindowInternal implements Window { private native keepKeyboardOnFocusSync(nativeObj: long, enable: boolean): void; private native onSync(nativeObj: long, type: string, callback: object): void; private native offSync(nativeObj: long, type: string, callback?: object): void; + private native bindDialogTargetSync(nativeObj: long, token: rpc.RemoteObject, deathCallback: object): void; + private native bindDialogTargetSync(nativeObj: long, requestInfo: dialogRequest.RequestInfo, + deathCallback: object): void; + private native createSubWindowWithOptionsSync(nativeObj: long, name: string, options: SubWindowOptions): Window; public setFollowParentWindowLayoutEnabled(enabled: boolean): Promise { return new Promise((resolve: (value: undefined) => void, reject: (error: BusinessError) => void ): void => { @@ -2857,6 +2914,64 @@ export class WindowInternal implements Window { }); }); } + + public bindDialogTarget(token: rpc.RemoteObject, deathCallback: Callback): Promise { + return new Promise((resolve: (value: undefined) => void, reject: (error: BusinessError) => void): void => { + taskpool.execute((): void => { + this.bindDialogTargetSync(this.nativeObj, token, deathCallback); + }).then((ret: NullishType) => { + resolve(undefined); + }).catch((err: NullishType) => { + reject(err as BusinessError); + }); + }); + } + + public bindDialogTarget(token: rpc.RemoteObject, deathCallback: Callback, callback: AsyncCallback): void + { + taskpool.execute((): void => { + this.bindDialogTargetSync(this.nativeObj, token, deathCallback); + }).then((ret: NullishType) => { + callback(new BusinessError(), undefined); + }).catch((err: NullishType) => { + callback(err as BusinessError, undefined); + }); + } + + public bindDialogTarget(requestInfo: dialogRequest.RequestInfo, deathCallback: Callback): Promise { + return new Promise((resolve: (value: undefined) => void, reject: (error: BusinessError) => void): void => { + taskpool.execute((): void => { + this.bindDialogTargetSync(this.nativeObj, requestInfo, deathCallback); + }).then((ret: NullishType) => { + resolve(undefined); + }).catch((err: NullishType) => { + reject(err as BusinessError); + }); + }); + } + + public bindDialogTarget(requestInfo: dialogRequest.RequestInfo, deathCallback: Callback, callback: AsyncCallback): void + { + taskpool.execute((): void => { + this.bindDialogTargetSync(this.nativeObj, requestInfo, deathCallback); + }).then((ret: NullishType) => { + callback(new BusinessError(), undefined); + }).catch((err: NullishType) => { + callback(err as BusinessError, undefined); + }); + } + + public createSubWindowWithOptions(name: string, options: SubWindowOptions): Promise { + return new Promise((resolve: (value: Window) => void, reject: (error: BusinessError) => void) => { + taskpool.execute((): Window => { + return this.createSubWindowWithOptionsSync(this.nativeObj, name, options); + }).then((ret: NullishType) => { + resolve(ret as Window); + }).catch((err: NullishType) => { + reject(err as BusinessError); + }) + }) + } } export interface Window { @@ -2953,6 +3068,12 @@ export interface Window { on(type: string, callback: Callback): void; on(type: 'noInteractionDetected', timeout: long, callback: Callback): void; off(type: string, callback?: Callback): void; + bindDialogTarget(token: rpc.RemoteObject, deathCallback: Callback): Promise; + bindDialogTarget(token: rpc.RemoteObject, deathCallback: Callback, callback: AsyncCallback): void; + bindDialogTarget(requestInfo: dialogRequest.RequestInfo, deathCallback: Callback): Promise; + bindDialogTarget(requestInfo: dialogRequest.RequestInfo, deathCallback: Callback, + callback: AsyncCallback): void; + createSubWindowWithOptions(name: string, options: SubWindowOptions): Promise; } export native function CreateWindowStage(scene: long): WindowStageInternal; diff --git a/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window.h b/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window.h index b4a36f9f16..be26535c3e 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window.h +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window.h @@ -18,6 +18,7 @@ #include "ani.h" #include "ani_window_register_manager.h" +#include "ani_remote_object.h" #include "window.h" namespace OHOS { @@ -73,6 +74,12 @@ public: static void SetShadow(ani_env* env, ani_object obj, ani_long nativeObj, ani_double radius, ani_string color, ani_object offsetX, ani_object offsetY); static void Finalizer(ani_env* env, ani_long nativeObj); + static void BindDialogTarget(ani_env* env, ani_object obj, ani_long nativeObj, + ani_object token, ani_ref deathCallback); + static void BindDialogTargetNew(ani_env* env, ani_object obj, ani_long nativeObj, + ani_object requestInfo, ani_ref deathCallback); + static ani_object CreateSubWindowWithOptions(ani_env* env, ani_object obj, ani_long nativeObj, + ani_string name, ani_object options); void SetFollowParentWindowLayoutEnabled(ani_env* env, ani_boolean enabled); void SetWindowDelayRaiseOnDrag(ani_env* env, ani_boolean isEnabled); @@ -141,6 +148,9 @@ private: void OnTranslate(ani_env* env, ani_object translateOptions); void OnRotate(ani_env* env, ani_object rotateOptions); void OnSetShadow(ani_env* env, ani_double radius, ani_string color, ani_object offsetX, ani_object offsetY); + void OnBindDialogTarget(ani_env* env, ani_object token, ani_ref deathCallback); + void OnBindDialogTargetNew(ani_env* env, ani_object requestInfo, ani_ref deathCallback); + ani_object OnCreateSubWindowWithOptions(ani_env* env, ani_string name, ani_object options); static bool ParseScaleOption(ani_env* env, ani_object scaleOptions, Transform& trans); static bool ParseTranslateOption(ani_env* env, ani_object translateOptions, Transform& trans); static bool ParseRotateOption(ani_env* env, ani_object rotateOptions, Transform& trans); diff --git a/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_stage.h b/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_stage.h index e615db79ba..5dfb691b4d 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_stage.h +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_stage.h @@ -40,6 +40,9 @@ class AniWindowStage { ani_ref callback); static void UnregisterWindowCallback(ani_env* env, ani_object obj, ani_long nativeObj, ani_string type, ani_ref callback); + static ani_object GetSubWindow(ani_env* env, ani_object obj, ani_long nativeObj); + static ani_object CreateSubWindowWithOptions(ani_env* env, ani_object obj, ani_long nativeObj, + ani_string name, ani_object options); void SetWindowRectAutoSave(ani_env* env, ani_boolean enabled, ani_boolean isSaveBySpecifiedFlag); ani_boolean IsWindowRectAutoSave(ani_env* env); @@ -54,10 +57,13 @@ private: void OnSetShowOnLockScreen(ani_env* env, ani_boolean showOnLockScreen); void OnRegisterWindowCallback(ani_env* env, ani_string type, ani_ref callback); void OnUnregisterWindowCallback(ani_env* env, ani_string type, ani_ref callback); + ani_object OnGetSubWindow(ani_env* env); + ani_object OnCreateSubWindowWithOptions(ani_env* env, ani_string name, ani_object options); std::weak_ptr windowScene_; std::unique_ptr registerManager_ = nullptr; }; +ani_object CreateSubWindowArrayObject(ani_env* env, std::vector>& subWindowVec); ani_object CreateAniWindowStage(ani_env* env, std::shared_ptr& windowScene); AniWindowStage* GetWindowStageFromAni(void* aniObj); void DropWindowStageByAni(ani_object obj); diff --git a/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_utils.h b/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_utils.h index eed09e859c..1769188529 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_utils.h +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_utils.h @@ -318,6 +318,16 @@ public: static void GetSpecificBarStatus(sptr& window, const std::string& name, std::map& newSystemBarProperties, std::map& systemBarProperties); + static ani_status GetPropertyBooleanObject(ani_env* env, ani_object boolean_object, + const char* propertyName, bool& result); + static int32_t SetRectWidthModule(ani_env* env, ani_object jsObject); + static int32_t SetRectHeightModule(ani_env* env, ani_object jsObject); + static int32_t SetRectLeftModule(ani_env* env, ani_object jsObject); + static int32_t SetRectTopModule(ani_env* env, ani_object jsObject); + static bool ParseSubWindowOption(ani_env* env, ani_object jsObject, const sptr& windowOption); + static bool ParseRectParams(ani_env* env, ani_object jsObject, const sptr& windowOption); + static bool ParseModalityParams(ani_env* env, ani_object jsObject, const sptr& windowOption); + static bool ParseZLevelParams(ani_env* env, ani_object jsObject, const sptr& windowOption); private: static void SetSystemPropertiesWindowRect(ani_env* env, const sptr& window, diff --git a/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window.cpp b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window.cpp index fc7b297893..b0801d9ba0 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window.cpp +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window.cpp @@ -2084,6 +2084,167 @@ void AniWindow::Finalizer(ani_env* env, ani_long nativeObj) TLOGE(WmsLogTag::DEFAULT, "[ANI] aniWindow is nullptr"); } } + +void AniWindow::BindDialogTarget(ani_env* env, ani_object obj, ani_long nativeObj, + ani_object token, ani_ref deathCallback) +{ + TLOGI(WmsLogTag::WMS_DIALOG, "[ANI]"); + AniWindow* aniWindow = reinterpret_cast(nativeObj); + if (aniWindow != nullptr) { + aniWindow->OnBindDialogTarget(env, token, deathCallback); + } else { + TLOGE(WmsLogTag::WMS_DIALOG, "[ANI] aniWindow is nullptr"); + } +} + +void AniWindow::OnBindDialogTarget(ani_env* env, ani_object token, ani_ref deathCallback) +{ + TLOGI(WmsLogTag::WMS_DIALOG, "[ANI] OnBindDialogTarget in"); + if (windowToken_ == nullptr) { + TLOGE(WmsLogTag::WMS_DIALOG, "[ANI] window is nullptr"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY); + return; + } + if (!Permission::IsSystemCalling()) { + TLOGE(WmsLogTag::WMS_DIALOG, "permission denied, require system application!"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_NOT_SYSTEM_APP); + return; + } + + sptr token_go = AniGetNativeRemoteObject(env, token); + if (token_go == nullptr) { + TLOGE(WmsLogTag::WMS_DIALOG, "token is null"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM); + return; + } + + registerManager_->RegisterListener(windowToken_, "dialogDeathRecipient", + CaseType::CASE_WINDOW, env, deathCallback, 0.0); + wptr weakToken(windowToken_); + auto window = weakToken.promote(); + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(window->BindDialogTarget(token_go)); + if (ret != WmErrorCode::WM_OK) { + AniWindowUtils::AniThrowError(env, ret, "Bind Dialog Target failed"); + } + TLOGI(WmsLogTag::WMS_SYSTEM, "BindDialogTarget end, window [%{public}u, %{public}s]", + weakToken->GetWindowId(), weakToken->GetWindowName().c_str()); +} + +void AniWindow::BindDialogTargetNew(ani_env* env, ani_object obj, ani_long nativeObj, + ani_object requestInfo, ani_ref deathCallback) +{ + TLOGI(WmsLogTag::WMS_DIALOG, "[ANI]"); + AniWindow* aniWindow = reinterpret_cast(nativeObj); + if (aniWindow != nullptr) { + aniWindow->OnBindDialogTargetNew(env, requestInfo, deathCallback); + } else { + TLOGE(WmsLogTag::WMS_DIALOG, "[ANI] aniWindow is nullptr"); + } +} + +void AniWindow::OnBindDialogTargetNew(ani_env* env, ani_object requestInfo, ani_ref deathCallback) +{ + TLOGI(WmsLogTag::WMS_DIALOG, "[ANI] OnBindDialogTarget in"); + if (windowToken_ == nullptr) { + TLOGE(WmsLogTag::WMS_DIALOG, "[ANI] window is nullptr"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY); + return; + } + if (!Permission::IsSystemCalling()) { + TLOGE(WmsLogTag::WMS_DIALOG, "permission denied, require system application!"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_NOT_SYSTEM_APP); + return; + } + + sptr token_go = AniGetNativeRemoteObject(env, requestInfo); + if (token_go == nullptr) { + TLOGE(WmsLogTag::WMS_DIALOG, "token is null"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM); + return; + } + + registerManager_->RegisterListener(windowToken_, "dialogDeathRecipient", + CaseType::CASE_WINDOW, env, deathCallback, 0.0); + wptr weakToken(windowToken_); + auto window = weakToken.promote(); + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(window->BindDialogTarget(token_go)); + if (ret != WmErrorCode::WM_OK) { + AniWindowUtils::AniThrowError(env, ret, "Bind Dialog Target failed"); + } + TLOGI(WmsLogTag::WMS_SYSTEM, "BindDialogTarget end, window [%{public}u, %{public}s]", + weakToken->GetWindowId(), weakToken->GetWindowName().c_str()); +} + +ani_object AniWindow::CreateSubWindowWithOptions(ani_env* env, ani_object obj, ani_long nativeObj, + ani_string name, ani_object options) +{ + TLOGD(WmsLogTag::WMS_SUB, "[ANI]"); + AniWindow* aniWindow = reinterpret_cast(nativeObj); + if (aniWindow != nullptr) { + return aniWindow->OnCreateSubWindowWithOptions(env, name, options); + } else { + TLOGE(WmsLogTag::WMS_SUB, "[ANI] aniWindow is nullptr"); + return AniWindowUtils::CreateAniUndefined(env); + } +} + +ani_object AniWindow::OnCreateSubWindowWithOptions(ani_env* env, ani_string name, ani_object options) +{ + TLOGI(WmsLogTag::WMS_SUB, "[ANI] OnCreateSubWindowWithOptions in"); + if (windowToken_ == nullptr) { + TLOGE(WmsLogTag::WMS_SUB, "window is null, device not support"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY); + return AniWindowUtils::CreateAniUndefined(env); + } + if (!windowToken_->IsPcOrFreeMultiWindowCapabilityEnabled()) { + TLOGE(WmsLogTag::WMS_SUB, "device not support"); + return AniWindowUtils::CreateAniUndefined(env); + } + std::string windowName; + AniWindowUtils::GetStdString(env, name, windowName); + sptr windowOption = new WindowOption(); + if (!AniWindowUtils::ParseSubWindowOption(env, options, windowOption)) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to options"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM); + return AniWindowUtils::CreateAniUndefined(env); + } + if ((windowOption->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_IS_APPLICATION_MODAL)) && + !windowToken_->IsPcOrPadFreeMultiWindowMode()) { + TLOGE(WmsLogTag::WMS_SUB, "device not support"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_NOT_SYSTEM_APP); + return AniWindowUtils::CreateAniUndefined(env); + } + if (windowOption->GetWindowTopmost() && !Permission::IsSystemCalling() && !Permission::IsStartByHdcd()) { + TLOGE(WmsLogTag::WMS_SUB, "Modal subwindow has topmost, but no system permission"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_NOT_SYSTEM_APP); + return AniWindowUtils::CreateAniUndefined(env); + } + auto window = wptr(windowToken_).promote(); + if (window == nullptr) { + TLOGE(WmsLogTag::WMS_SUB, "window is nullptr"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY, "window is nullptr"); + return AniWindowUtils::CreateAniUndefined(env); + } + if (!WindowHelper::IsFloatOrSubWindow(window->GetType()) && + !WindowHelper::IsMainWindow(window->GetType())) { + TLOGE(WmsLogTag::WMS_SUB, "%{public}d", window->GetType()); + return AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_INVALID_CALLING, + "invalid window type"); + } + windowOption->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + windowOption->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + windowOption->SetOnlySupportSceneBoard(true); + windowOption->SetParentId(window->GetWindowId()); + windowOption->SetWindowTag(WindowTag::SUB_WINDOW); + auto subWindow = Window::Create(windowName, windowOption, window->GetContext()); + if (subWindow == nullptr) { + TLOGE(WmsLogTag::WMS_SUB, "create sub window failed"); + return AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY, + "create sub window failed"); + } + TLOGI(WmsLogTag::WMS_SUB, "Create sub window %{public}s end", windowName.c_str()); + return static_cast(CreateAniWindowObject(env, subWindow)); +} } // namespace Rosen } // namespace OHOS @@ -2752,6 +2913,14 @@ ani_status OHOS::Rosen::ANI_Window_Constructor(ani_vm *vm, uint32_t *result) reinterpret_cast(AniWindow::HideWithAnimation)}, ani_native_function {"showWithAnimationSync", nullptr, reinterpret_cast(AniWindow::ShowWithAnimation)}, + ani_native_function {"bindDialogTargetSync", "JL@ohos/window/rpc/RemoteObject;Lstd/core/Function0;:V", + reinterpret_cast(AniWindow::BindDialogTarget)}, + ani_native_function {"bindDialogTargetSync", + "JL@ohos/app/ability/dialogRequest/dialogRequest/RequestInfo;Lstd/core/Function0;:V", + reinterpret_cast(AniWindow::BindDialogTargetNew)}, + ani_native_function {"createSubWindowWithOptionsSync", + "JLstd/core/String;L@ohos/window/window/SubWindowOptions;:L@ohos/window/window/Window;", + reinterpret_cast(AniWindow::CreateSubWindowWithOptions)}, }; for (auto method : methods) { if ((ret = env->Class_BindNativeMethods(cls, &method, 1u)) != ANI_OK) { diff --git a/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_stage.cpp b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_stage.cpp index 3192528053..8ccc56e2b4 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_stage.cpp +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_stage.cpp @@ -413,6 +413,114 @@ ani_ref AniWindowStage::OnCreateSubWindow(ani_env* env, ani_string name) } return CreateAniWindowObject(env, window); } + +ani_object CreateSubWindowArrayObject(ani_env* env, std::vector>& subWindowVec) +__attribute__((no_sanitize("cfi"))) +{ + if (env == nullptr) { + TLOGE(WmsLogTag::DEFAULT, "[ANI] null env"); + return AniWindowUtils::CreateAniUndefined(env); + } + ani_array_ref arrayValue = nullptr; + ani_class cls = nullptr; + env->FindClass("Lescompat/Array", &cls); + ani_ref element = CreateAniWindowObject(env, subWindowVec[0]); + env->Array_New_Ref(cls, subWindowVec.size(), element, &arrayValue); + if (arrayValue == nullptr) { + TLOGD(WmsLogTag::DEFAULT, "Failed to convert subWinVec to jsArrayObject"); + return AniWindowUtils::CreateAniUndefined(env); + } + for (size_t i = 0; i < subWindowVec.size(); i++) { + env->Array_Set_Ref(arrayValue, i, CreateAniWindowObject(env, subWindowVec[i])); + } + return static_cast(arrayValue); +} + +ani_object AniWindowStage::GetSubWindow(ani_env* env, ani_object obj, ani_long nativeObj) +{ + TLOGD(WmsLogTag::WMS_LIFE, "[ANI]"); + AniWindowStage* aniWindowStage = reinterpret_cast(nativeObj); + if (aniWindowStage == nullptr || aniWindowStage->GetMainWindow(env) == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "[ANI] aniWindowStage is nullptr!"); + return AniWindowUtils::CreateAniUndefined(env); + } + return aniWindowStage->OnGetSubWindow(env); +} + +ani_object AniWindowStage::OnGetSubWindow(ani_env* env) +{ + TLOGI(WmsLogTag::WMS_LIFE, "[ANI]"); + auto windowScene = GetWindowScene().lock(); + if (windowScene == nullptr) { + TLOGE(WmsLogTag::WMS_LIFE, "[ANI] Window scene is nullptr"); + return AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY); + } + + std::vector> subWindowVec = windowScene->GetSubWindow(); + TLOGI(WmsLogTag::WMS_LIFE, "Get sub windows, size = %{public}zu", subWindowVec.size()); + return CreateSubWindowArrayObject(env, subWindowVec); +} + +ani_object AniWindowStage::CreateSubWindowWithOptions(ani_env* env, ani_object obj, ani_long nativeObj, + ani_string name, ani_object options) +{ + TLOGI(WmsLogTag::WMS_SUB, "[ANI]"); + AniWindowStage* aniWindowStage = reinterpret_cast(nativeObj); + if (aniWindowStage != nullptr) { + return aniWindowStage->OnCreateSubWindowWithOptions(env, name, options); + } else { + TLOGE(WmsLogTag::WMS_SUB, "[ANI] aniWindowStage is nullptr"); + return AniWindowUtils::CreateAniUndefined(env); + } +} + +ani_object AniWindowStage::OnCreateSubWindowWithOptions(ani_env* env, ani_string name, ani_object options) +{ + TLOGI(WmsLogTag::WMS_SUB, "[ANI] OnCreateSubWindowWithOptions in"); + auto windowScene = GetWindowScene().lock(); + if (windowScene == nullptr) { + TLOGE(WmsLogTag::WMS_SUB, "WindowScene is null"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM); + return AniWindowUtils::CreateAniUndefined(env); + } + std::string windowName; + ani_status window_name = AniWindowUtils::GetStdString(env, name, windowName); + if (window_name != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to windowName"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM); + return AniWindowUtils::CreateAniUndefined(env); + } + sptr windowOption = new WindowOption(); + if (!AniWindowUtils::ParseSubWindowOption(env, options, windowOption)) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to options"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_INVALID_PARAM); + return AniWindowUtils::CreateAniUndefined(env); + } + if ((windowOption->GetWindowFlags() & static_cast(WindowFlag::WINDOW_FLAG_IS_APPLICATION_MODAL)) && + !windowScene->GetMainWindow()->IsPcOrPadFreeMultiWindowMode()) { + TLOGE(WmsLogTag::WMS_SUB, "device not support"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_DEVICE_NOT_SUPPORT); + return AniWindowUtils::CreateAniUndefined(env); + } + + if (windowOption->GetWindowTopmost() && !Permission::IsSystemCalling() && !Permission::IsStartByHdcd()) { + TLOGE(WmsLogTag::WMS_SUB, "Modal subWindow has topmost, but no system permission"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_NOT_SYSTEM_APP); + return AniWindowUtils::CreateAniUndefined(env); + } + std::string aniName = std::move(windowName); + windowOption->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + windowOption->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + windowOption->SetOnlySupportSceneBoard(true); + auto window = windowScene->CreateWindow(aniName, windowOption); + if (window == nullptr) { + TLOGE(WmsLogTag::WMS_SUB, "Get window failed"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_STATE_ABNORMALLY, "get window failed"); + return AniWindowUtils::CreateAniUndefined(env); + } + TLOGI(WmsLogTag::WMS_SUB, "Create sub window %{public}s end", aniName.c_str()); + return static_cast(CreateAniWindowObject(env, window)); +} } // namespace Rosen } // namespace OHOS @@ -518,6 +626,11 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) reinterpret_cast(AniWindowStage::RegisterWindowCallback)}, ani_native_function {"offSync", nullptr, reinterpret_cast(AniWindowStage::UnregisterWindowCallback)}, + ani_native_function {"getSubWindowSync", "J:Lescompat/Array", + reinterpret_cast(AniWindowStage::GetSubWindow)}, + ani_native_function {"createSubWindowWithOptionsSync", + "JLstd/core/String;L@ohos/window/window/SubWindowOptions;:L@ohos/window/window/Window", + reinterpret_cast(AniWindowStage::CreateSubWindowWithOptions)}, }; for (auto method : methods) { if ((ret = env->Class_BindNativeMethods(cls, &method, 1u)) != ANI_OK) { diff --git a/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_utils.cpp b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_utils.cpp index 8404f32522..225251dcc8 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_utils.cpp +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_utils.cpp @@ -83,6 +83,38 @@ ani_status AniWindowUtils::GetStdStringVector(ani_env* env, ani_object ary, std: return ANI_OK; } +ani_status AniWindowUtils::GetPropertyBooleanObject(ani_env* env, ani_object boolean_object, + const char* propertyName, bool& result) +{ + ani_ref boolean_ref; + ani_status ret = env->Object_GetPropertyByName_Ref(boolean_object, propertyName, &boolean_ref); + if (ret != ANI_OK) { + TLOGE(WmsLogTag::DEFAULT, "[ANI] Object_GetPropertyByName_Ref %{public}s Failed, ret: %{public}u", + propertyName, static_cast(ret)); + return ret; + } + + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(boolean_ref, &isUndefined)) { + TLOGE(WmsLogTag::DEFAULT, "[ANI] Object_GetPropertyByName_Ref %{public}s Failed", propertyName); + return ret; + } + + if (isUndefined) { + TLOGE(WmsLogTag::DEFAULT, "[ANI] %{public}s is Undefined Now", propertyName); + return ret; + } + ani_boolean boolean_value; + if (ANI_OK != env->Object_CallMethodByName_Boolean(static_cast(boolean_ref), + "booleanValue", nullptr, &boolean_value)) { + TLOGE(WmsLogTag::DEFAULT, "[ANI] Object_GetPropertyByName_Ref %{public}s Failed", propertyName); + return ret; + } + result = static_cast(boolean_value); + TLOGI(WmsLogTag::DEFAULT, "[ANI] %{public}s is: %{public}d", propertyName, result); + return ret; +} + ani_status AniWindowUtils::GetPropertyIntObject(ani_env* env, const char* propertyName, ani_object object, int32_t& result) { @@ -1073,5 +1105,205 @@ void AniWindowUtils::GetSpecificBarStatus(sptr& window, const std::strin systemBarProperties[type].settingFlag_ = systemBarProperties[type].settingFlag_ | SystemBarSettingFlag::ENABLE_SETTING; } + +int32_t AniWindowUtils::SetRectWidthModule(ani_env* env, ani_object jsObject) +{ + ani_class cls = nullptr; + env->FindClass("L@ohos/app/ability/dialogRequest/dialogRequest/WindowRect", &cls); + ani_field aniWidth; + if (env->Class_FindField(cls, "width", &aniWidth) != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to width"); + return 0; + } + ani_int* ani_width = nullptr; + if (env->Object_GetField_Int(jsObject, aniWidth, ani_width) != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to width"); + return 0; + } + return reinterpret_cast(*ani_width); +} + +int32_t AniWindowUtils::SetRectHeightModule(ani_env* env, ani_object jsObject) +{ + ani_class cls = nullptr; + env->FindClass("L@ohos/app/ability/dialogRequest/dialogRequest/WindowRect", &cls); + ani_field aniHeight; + if (env->Class_FindField(cls, "height", &aniHeight) != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to height"); + return 0; + } + ani_int* ani_height = nullptr; + if (env->Object_GetField_Int(jsObject, aniHeight, ani_height) != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to height"); + return 0; + } + return reinterpret_cast(*ani_height); +} + +int32_t AniWindowUtils::SetRectLeftModule(ani_env* env, ani_object jsObject) +{ + ani_class cls = nullptr; + env->FindClass("L@ohos/app/ability/dialogRequest/dialogRequest/WindowRect", &cls); + ani_field aniLeft; + if (env->Class_FindField(cls, "left", &aniLeft) != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to left"); + return 0; + } + ani_int* ani_left = nullptr; + if (env->Object_GetField_Int(jsObject, aniLeft, ani_left) != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to left"); + return 0; + } + return reinterpret_cast(*ani_left); +} + +int32_t AniWindowUtils::SetRectTopModule(ani_env* env, ani_object jsObject) +{ + ani_class cls = nullptr; + env->FindClass("L@ohos/app/ability/dialogRequest/dialogRequest/WindowRect", &cls); + ani_field aniTop; + if (env->Class_FindField(cls, "top", &aniTop) != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to top"); + return 0; + } + ani_int* ani_top = nullptr; + if (env->Object_GetField_Int(jsObject, aniTop, ani_top) != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to top"); + return 0; + } + return reinterpret_cast(*ani_top); +} + +bool AniWindowUtils::ParseModalityParams(ani_env* env, ani_object jsObject, const sptr& windowOption) +{ + bool isModal = false; + ani_status ani_isModal = AniWindowUtils::GetPropertyBooleanObject(env, jsObject, "isModal", isModal); + if (ani_isModal == ANI_OK) { + if (isModal) { + windowOption->AddWindowFlag(WindowFlag::WINDOW_FLAG_IS_MODAL); + } + } + bool isTopmost = false; + ani_status ani_isTopmost = AniWindowUtils::GetPropertyBooleanObject(env, jsObject, "isTopmost", isTopmost); + if (ani_isTopmost == ANI_OK) { + if (isModal && isTopmost) { + TLOGE(WmsLogTag::WMS_SUB, "Normal subwindow not support topmost"); + return false; + } + windowOption->SetWindowTopmost(isTopmost); + } + int32_t aniModalityType = 0; + ani_status ani_modalityType = AniWindowUtils::GetPropertyIntObject(env, "modalityType", jsObject, aniModalityType); + ApiModalityType apiModalityType = static_cast(static_cast(aniModalityType)); + if (ani_modalityType == ANI_OK) { + if (!isModal) { + TLOGE(WmsLogTag::WMS_SUB, "Normal subwindow not support modalityType"); + return false; + } + using T = std::underlying_type_t; + T modalityType = static_cast(apiModalityType); + if (modalityType >= static_cast(ApiModalityType::BEGIN) && + modalityType <= static_cast(ApiModalityType::END)) { + auto type = JS_TO_NATIVE_MODALITY_TYPE_MAP.at(apiModalityType); + if (type == ModalityType::APPLICATION_MODALITY) { + windowOption->AddWindowFlag(WindowFlag::WINDOW_FLAG_IS_APPLICATION_MODAL); + } + } else { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to modalityType"); + return false; + } + } + TLOGI(WmsLogTag::WMS_SUB, "isModal: %{public}d, isTopmost: %{public}d, WindowFlag: %{public}d", + isModal, isTopmost, windowOption->GetWindowFlags()); + return true; +} + +bool AniWindowUtils::ParseZLevelParams(ani_env* env, ani_object jsObject, const sptr& windowOption) +{ + int32_t zLevel = 0; + bool isModal = false; + ani_status ani_zLevel = AniWindowUtils::GetPropertyIntObject(env, "zLevel", jsObject, zLevel); + ani_status ani_isModal = AniWindowUtils::GetPropertyBooleanObject(env, jsObject, "isModal", isModal); + if (ani_zLevel == ANI_OK) { + if (zLevel < MINIMUM_Z_LEVEL || zLevel > MAXIMUM_Z_LEVEL) { + TLOGE(WmsLogTag::WMS_SUB, "zLevel value %{public}d exceeds valid range [-10000, 10000]!", zLevel); + return false; + } + if (ani_isModal == ANI_OK) { + if (isModal) { + TLOGE(WmsLogTag::WMS_SUB, "modal window not support custom zLevel"); + return false; + } + } + windowOption->SetSubWindowZLevel(zLevel); + } + TLOGI(WmsLogTag::WMS_SUB, "zLevel: %{public}d", zLevel); + return true; +} + +bool AniWindowUtils::ParseRectParams(ani_env* env, ani_object jsObject, const sptr& windowOption) +{ + int32_t widthRect = AniWindowUtils::SetRectWidthModule(env, jsObject); + int32_t heightRect = AniWindowUtils::SetRectHeightModule(env, jsObject); + if (widthRect <= 0 || heightRect <= 0) { + TLOGE(WmsLogTag::WMS_SUB, "width or height should greater than 0!"); + return false; + } + int32_t leftRect = AniWindowUtils::SetRectLeftModule(env, jsObject); + int32_t topRect = AniWindowUtils::SetRectTopModule(env, jsObject); + if (leftRect <= 0 || topRect <= 0) { + TLOGE(WmsLogTag::WMS_SUB, "left or top should greater than 0!"); + return false; + } + Rect rect = { leftRect, topRect, + static_cast(widthRect), static_cast(heightRect) }; + TLOGI(WmsLogTag::WMS_SUB, "windowRect: %{public}s", rect.ToString().c_str()); + windowOption->SetWindowRect(rect); + return true; +} + +bool AniWindowUtils::ParseSubWindowOption(ani_env* env, ani_object jsObject, const sptr& windowOption) +{ + if (env == nullptr) { + TLOGE(WmsLogTag::DEFAULT, "[ANI] null env"); + return false; + } + if (jsObject == nullptr || windowOption == nullptr) { + TLOGE(WmsLogTag::WMS_SUB, "jsObject is null"); + return false; + } + if (windowOption == nullptr) { + TLOGE(WmsLogTag::WMS_SUB, "windowOption is null"); + return false; + } + std::string title; + ani_ref result; + ani_status titleResult = env->Object_GetPropertyByName_Ref(jsObject, "title", &result); + if (titleResult != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to get title"); + return false; + } + ani_string aniResult = reinterpret_cast(result); + ani_status optionFirst = AniWindowUtils::GetStdString(env, aniResult, title); + if (optionFirst != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to title"); + return false; + } + bool decorEnabled = false; + ani_status optionSecond = AniWindowUtils::GetPropertyBooleanObject(env, jsObject, "decorEnabled", decorEnabled); + if (optionSecond != ANI_OK) { + TLOGE(WmsLogTag::WMS_SUB, "Failed to convert parameter to decorEnabled"); + return false; + } + windowOption->SetSubWindowTitle(title); + windowOption->SetSubWindowDecorEnable(decorEnabled); + if (!ParseRectParams(env, jsObject, windowOption)) { + return false; + } + if (!ParseModalityParams(env, jsObject, windowOption)) { + return false; + } + return ParseZLevelParams(env, jsObject, windowOption); +} } // namespace Rosen } // namespace OHOS -- Gitee