diff --git a/interfaces/kits/ani/window_runtime/BUILD.gn b/interfaces/kits/ani/window_runtime/BUILD.gn index 9f31495230c5f61e8868b3bf20e30b3c0a8cb939..d8cdf37df8b0201f11ccf2c50212d30d2c77565d 100644 --- a/interfaces/kits/ani/window_runtime/BUILD.gn +++ b/interfaces/kits/ani/window_runtime/BUILD.gn @@ -88,6 +88,7 @@ ohos_shared_library("windowstageani_kit") { "ipc:ipc_napi", "ipc:ipc_single", "napi:ace_napi", + "ipc:rpc_ani", "runtime_core:ani", "runtime_core:ani_helpers", ] @@ -144,6 +145,7 @@ ohos_shared_library("windowstageani_module") { "ipc:ipc_napi", "ipc:ipc_single", "napi:ace_napi", + "ipc:rpc_ani", "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 a036640b9a3755a832fbab814221b2c1925162cc..2396eba57ed890a1b32e824fb7c49ac1c614d314 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; @@ -2014,6 +2016,8 @@ export class WindowStageInternal implements WindowStage { public native createSubWindowSync(nativeObj: long, name: String): Window; public native setCustomDensitySync(nativeObj: long, density: double): void; public native setDefaultDensityEnabledSync(nativeObj: long, enabled: boolean): void; + public native getSubWindowSync(nativeObj: long): Array; + public native createSubWindowWithOptionsSync(nativeObj: long, name: string, options: SubWindowOptions): Window; native onSync(nativeObj: long, eventType: 'windowStageEvent', callback: Object): void; native offSync(nativeObj: long, eventType: 'windowStageEvent', callback?: Object): void; @@ -2191,6 +2195,41 @@ export class WindowStageInternal implements WindowStage { }); } + 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>): 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); + }); + }); + } + public on(eventType: 'windowStageEvent', callback: Callback): void { this.onSync(this.nativeObj, eventType, callback); } @@ -2215,6 +2254,9 @@ export interface WindowStage { createSubWindow(name: string, callback: AsyncCallback): void; disableWindowDecor(): void; setShowOnLockScreen(showOnLockScreen: boolean): void; + getSubWindow(): Promise>; + getSubWindow(callback: AsyncCallback>): void; + createSubWindowWithOptions(name: string, options: SubWindowOptions): Promise; setWindowModal(isModal: boolean): Promise; setCustomDensity(density: double): void; setDefaultDensityEnabled(enabled: boolean): void; @@ -2347,6 +2389,11 @@ export class WindowInternal implements Window { private native setWindowMaskSync(nativeObj: long, windowMask: Array>): void; private native onNoInteractionDetected(nativeObj: long, type: string, timeout: long, callback: Object): void; private native keepKeyboardOnFocusSync(nativeObj: long, enable: boolean): void; + private native bindDialogTargetWithRemoteObjectSync(nativeObj: long, token: rpc.RemoteObject, + deathCallback: object): void; + private native bindDialogTargetWithRequestInfoSync(nativeObj: long, requestInfo: dialogRequest.RequestInfo, + deathCallback: object): void; + private native createSubWindowWithOptionsSync(nativeObj: long, name: string, options: SubWindowOptions): Window; private native onSync(nativeObj: long, type: string, callback: object): void; private native offSync(nativeObj: long, type: string, callback?: object): void; @@ -2444,7 +2491,7 @@ export class WindowInternal implements Window { } public setWindowTopmost(isWindowTopmost: boolean): Promise { - return new Promise((resolve: (value: undefined) => void, reject: (error: BusinessError) => void): void => { + return new Promise((resolve: (value: undefined) => void, reject: (error: BusinessError) => void ): void => { taskpool.execute((): void => { this.setWindowTopmost(this.nativeObj, isWindowTopmost); }).then((ret: NullishType): void => { @@ -3447,6 +3494,65 @@ 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.bindDialogTargetWithRemoteObjectSync(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.bindDialogTargetWithRemoteObjectSync(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.bindDialogTargetWithRequestInfoSync(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.bindDialogTargetWithRequestInfoSync(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); + }); + }); + } + public setWindowBrightness(brightness: double): Promise { return new Promise((resolve: (value: undefined) => void, reject: (error: BusinessError) => void): void => { taskpool.execute((): void => { @@ -3721,6 +3827,12 @@ export interface Window { setGestureBackEnabled(enabled: boolean): Promise; setSingleFrameComposerEnabled(enabled: boolean): Promise; getTransitionController(): TransitionController; + 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; on(type: string, callback: Callback): void; on(type: 'noInteractionDetected', timeout: long, callback: Callback): void; off(type: string, callback?: Callback): void; @@ -3750,6 +3862,7 @@ native function getSnapshot(nativeObj: long, windowId: number): image.PixelMap; native function getVisibleWindowInfo(nativeObj: long): Array; native function setGestureNavigationEnabled(nativeObj: long, enabled: boolean): void; native function setWaterMarkImage(nativeObj: long, pixelMap: image.PixelMap, enabled: boolean): void; +native function toggleShownStateForAllAppWindowsSync(nativeObj: long): void; export function getLastWindow(ctx: BaseContext): Promise { return new Promise((resolve: (value: Window) => void, reject: (error: BusinessError) => void) => { @@ -3983,13 +4096,35 @@ function runAvoidAreaChangeCallback(cb: object, area: object, type: int): void { export function shiftAppWindowFocus(sourceWindowId: int, targetWindowId: int): Promise { return new Promise((resolve: (value: undefined) => void, reject: (error: BusinessError) => void): void => { + taskpool.execute((): void => { + return shiftAppWindowFocusSync(nativeObj, sourceWindowId, targetWindowId); + }).then((ret: NullishType) => { + resolve(undefined); + }).catch((err: NullishType) => { + reject(err as BusinessError); + }); + }); +} + +export function toggleShownStateForAllAppWindows(callback: AsyncCallback): void { taskpool.execute((): void => { - return shiftAppWindowFocusSync(nativeObj, sourceWindowId, targetWindowId); + toggleShownStateForAllAppWindowsSync(nativeObj); }).then((ret: NullishType) => { - resolve(undefined); + callback(new BusinessError(), undefined); }).catch((err: NullishType) => { - reject(err as BusinessError); + callback(err as BusinessError, undefined); }); +} + +export function toggleShownStateForAllAppWindows(): Promise { + return new Promise((resolve: (value: undefined) => void, reject: (error: BusinessError) => void): void => { + taskpool.execute((): void => { + return toggleShownStateForAllAppWindowsSync(nativeObj); + }).then((ret: NullishType) => { + resolve(undefined); + }).catch((err: NullishType) => { + reject(err as BusinessError); + }); }); } 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 cf46015fb9c924d279ff8e5455348e406b633b0a..42958f339b0e0a7e0508c50133170af67064917a 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 { @@ -101,6 +102,12 @@ public: static void SetWindowShadowRadius(ani_env* env, ani_object obj, ani_long nativeObj, ani_double radius); static void Finalizer(ani_env* env, ani_long nativeObj); static ani_object GetTransitionController(ani_env* env, ani_object obj, 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); @@ -209,6 +216,9 @@ private: 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 OnSetCornerRadius(ani_env* env, ani_double cornerRadius); + 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_manager.h b/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_manager.h index f92a8cf07656b09b4f1a5f15953f22b393b1e7ad..fee7b21d5cf8dd4f8a09fe9531fa9044e743bae8 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_manager.h +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/include/ani_window_manager.h @@ -50,6 +50,7 @@ public: static ani_object GetVisibleWindowInfo(ani_env* env, ani_long nativeObj); static void SetGestureNavigationEnabled(ani_env* env, ani_long nativeObj, ani_boolean enabled); static void SetWaterMarkImage(ani_env* env, ani_long nativeObj, ani_object nativePixelMap, ani_boolean enabled); + static void ToggleShownStateForAllAppWindows(ani_env* env, ani_long nativeObj); private: ani_object OnGetWindowsByCoordinate(ani_env* env, ani_object getWindowsParam); ani_ref OnGetLastWindow(ani_env* env, ani_object context); @@ -66,6 +67,7 @@ private: ani_object OnGetVisibleWindowInfo(ani_env* env); void OnSetGestureNavigationEnabled(ani_env* env, ani_boolean enabled); void OnSetWaterMarkImage(ani_env* env, ani_object nativePixelMap, ani_boolean enabled); + void OnToggleShownStateForAllAppWindows(ani_env* env); std::unique_ptr registerManager_ = nullptr; }; 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 7aafe9ae15f790eff8e47aee1a603e64111887bd..2e2b8440e57442697b1e29d27541dc3fa51c9e24 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 @@ -45,7 +45,10 @@ class AniWindowStage { ani_ref callback); static void SetCustomDensity(ani_env* env, ani_object obj, ani_long nativeObj, ani_double density); static void SetDefaultDensityEnabled(ani_env* env, ani_object obj, ani_long nativeObj, ani_boolean enabled); - + 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); void RemoveStartingWindow(ani_env* env); @@ -62,6 +65,8 @@ private: void OnSetWindowModal(ani_env* env, ani_boolean isModal); 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; }; 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 09d7e3e11c742017f07c90ade6495179be4e7b50..213bc8d3fe2636740e7fd476626b69a1749b4980 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 @@ -130,6 +130,12 @@ public: * @return Corresponding WmErrorCode or defaultCode if unmapped. */ static WmErrorCode ToErrorCode(WMError error, WmErrorCode defaultCode = WmErrorCode::WM_ERROR_STATE_ABNORMALLY); + 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); + + }; } } 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 b1ea1e1df35b6ec26082b48066f51a896f82da5e..9e2381d13a33d080cb26113f06eac6103ebff1f0 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 @@ -3483,6 +3483,158 @@ void AniWindow::SetSingleFrameComposerEnabled(ani_env* env, ani_boolean enabled) windowToken_->GetWindowId(), windowToken_->GetWindowName().c_str(), enabled); } +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) +{ + 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) +{ + 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) +{ + 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"); + AniWindowUtils::AniThrowError(env, WmErrorCode::WM_ERROR_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); + } + if (!WindowHelper::IsFloatOrSubWindow(windowToken_->GetType()) && + !WindowHelper::IsMainWindow(windowToken_->GetType())) { + TLOGE(WmsLogTag::WMS_SUB, "%{public}d", windowToken_->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(windowToken_->GetWindowId()); + windowOption->SetWindowTag(WindowTag::SUB_WINDOW); + auto subWindow = Window::Create(windowName, windowOption, windowToken_->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 @@ -4505,6 +4657,13 @@ ani_status OHOS::Rosen::ANI_Window_Constructor(ani_vm *vm, uint32_t *result) reinterpret_cast(SetSingleFrameComposerEnabled)}, ani_native_function {"getTransitionControllerSync", "l:C{@ohos.window.window.TransitionController}", reinterpret_cast(AniWindow::GetTransitionController)}, + ani_native_function {"bindDialogTargetWithRemoteObjectInfoSync", nullptr, + reinterpret_cast(AniWindow::BindDialogTarget)}, + ani_native_function {"bindDialogTargetWithRequestSync", nullptr, + reinterpret_cast(AniWindow::BindDialogTargetNew)}, + ani_native_function {"createSubWindowWithOptionsSync", + "lC{std.core.String}C{@ohos.window.window.SubWindowOptions}:C{@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_manager.cpp b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_manager.cpp index f979be7d5ddee26b255dafaec28548aa19d81161..0c73856cdd5462d59a1a7aba7f23df4f645a2126 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_manager.cpp +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_manager.cpp @@ -91,6 +91,8 @@ ani_status AniWindowManager::AniWindowManagerInit(ani_env* env) reinterpret_cast(AniWindowManager::SetGestureNavigationEnabled)}, ani_native_function {"setWaterMarkImage", "lC{@ohos.multimedia.image.image.PixelMap}z:", reinterpret_cast(AniWindowManager::SetWaterMarkImage)}, + ani_native_function {"toggleShownStateForAllAppWindowsSync", "l:", + reinterpret_cast(AniWindowManager::ToggleShownStateForAllAppWindows)}, }; if ((ret = env->Namespace_BindNativeFunctions(ns, functions.data(), functions.size())) != ANI_OK) { TLOGE(WmsLogTag::DEFAULT, "[ANI] bind ns func %{public}u", ret); @@ -654,5 +656,26 @@ void AniWindowManager::OnSetWaterMarkImage(ani_env* env, ani_object nativePixelM } RSInterfaces::GetInstance().ShowWatermark(pixelMap, enable); } + +void AniWindowManager::OnToggleShownStateForAllAppWindows(ani_env* env) +{ + TLOGI(WmsLogTag::DEFAULT, "[ANI]"); + WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at( + SingletonContainer::Get().ToggleShownStateForAllAppWindows()); + if(ret != WmErrorCode::WM_OK) { + AniWindowUtils::AniThrowError(env, ret, "ToggleShownStateForAllAppWindows failed."); + } +} + +void AniWindowManager::ToggleShownStateForAllAppWindows(ani_env* env, ani_long nativeObj) +{ + TLOGI(WmsLogTag::DEFAULT, "[ANI]"); + AniWindowManager* aniWindowManager = reinterpret_cast(nativeObj); + if (aniWindowManager != nullptr) { + return aniWindowManager->OnToggleShownStateForAllAppWindows(env); + } else { + TLOGE(WmsLogTag::DEFAULT, "[ANI] aniWindowManager is nullptr"); + } +} } // namespace Rosen } // namespace OHOS 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 4057478afb139c96e9f7be7ac861aa76871358ce..e6697f3ea57ade16b3a86961e17e2a6c57078dd4 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 @@ -582,6 +582,94 @@ void AniWindowStage::OnSetDefaultDensityEnabled(ani_env* env, ani_boolean enable TLOGI(WmsLogTag::WMS_ATTRIBUTE, "Window [%{public}u,%{public}s] enabled=%{public}u ret=%{public}d", window->GetWindowId(), window->GetWindowName().c_str(), enabled, ret); } + +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()); + + std::vector windows(subWindowVec.size()); + for (size_t i = 0; i < subWindowVec.size(); i++) { + windows[i] = CreateAniWindowObject(env, subWindowVec[i]); + } + return AniWindowUtils::CreateAniWindowArray(env, windows); +} + +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) +{ + 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 = sptr::MakeSptr(); + 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); + } + windowOption->SetWindowType(WindowType::WINDOW_TYPE_APP_SUB_WINDOW); + windowOption->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING); + windowOption->SetOnlySupportSceneBoard(true); + auto window = windowScene->CreateWindow(windowName, windowOption); + if (window == nullptr) { + TLOGE(WmsLogTag::WMS_SUB, "create 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", windowName.c_str()); + return static_cast(CreateAniWindowObject(env, window)); +} } // namespace Rosen } // namespace OHOS diff --git a/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_stage_module.cpp b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_stage_module.cpp index edda21a6af08ca5ee5349771e3a5eac63f062293..6e137e69b0c8c6c5a858fd617f3c22df86d154ac 100644 --- a/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_stage_module.cpp +++ b/interfaces/kits/ani/window_runtime/window_stage_ani/src/ani_window_stage_module.cpp @@ -124,6 +124,11 @@ ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) reinterpret_cast(WindowGetMainWindow)}, ani_native_function {"createSubWindowSync", "lC{std.core.String}:C{@ohos.window.window.Window}", reinterpret_cast(CreateSubWindow)}, + ani_native_function {"getSubWindowSync", "l:C{escompat.Array}", + reinterpret_cast(AniWindowStage::GetSubWindow)}, + ani_native_function {"createSubWindowWithOptionsSync", + "lC{std.core.String}C{@ohos.window.window.SubWindowOptions}:C{@ohos.window.window.Window}", + reinterpret_cast(AniWindowStage::CreateSubWindowWithOptions)}, ani_native_function {"onSync", nullptr, reinterpret_cast(AniWindowStage::RegisterWindowCallback)}, ani_native_function {"offSync", nullptr, 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 208e82e0f587c227082e76c137f09b08e98eb995..41014754331c20cddf0828d8ffec5c712d6f054a 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 @@ -1519,5 +1519,137 @@ bool AniWindowUtils::ParseAndCheckRect(ani_env* env, ani_object rect, const Rect } return true; } + +bool AniWindowUtils::ParseModalityParams(ani_env* env, ani_object jsObject, const sptr& windowOption) +{ + ani_boolean isModal { false }; + env->Object_GetPropertyByName_Boolean(jsObject, "isModal", &isModal); + if (isModal) { + windowOption->AddWindowFlag(WindowFlag::WINDOW_FLAG_IS_MODAL); + } + ani_boolean isTopmost { false }; + env->Object_GetPropertyByName_Boolean(jsObject, "isTopmost", &isTopmost); + if (!isModal && isTopmost) { + TLOGE(WmsLogTag::WMS_SUB, "Normal subwindow not support topmost"); + return false; + } + windowOption->SetWindowTopmost(isTopmost); + ani_int aniModalityType { 0 }; + auto ret = env->Object_GetPropertyByName_Int(jsObject, "modalityType", &aniModalityType); + ApiModalityType apiModalityType = static_cast(static_cast(aniModalityType)); + if (ret == 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) +{ + ani_int zLevel { 0 }; + ani_status ani_zLevel = env->Object_GetPropertyByName_Int(jsObject, "zLevel", &zLevel); + ani_boolean isModal { 0 }; + ani_status ani_isModal = env->Object_GetPropertyByName_Boolean(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) +{ + ani_ref rectRef; + if (ANI_OK != env->Object_GetPropertyByName_Ref(jsObject, "windowRect", &rectRef)) { + TLOGE(WmsLogTag::WMS_SUB, "get windowRect fail"); + return false; + } + ani_boolean isUndefined; + if (ANI_OK != env->Reference_IsUndefined(rectRef, &isUndefined) || isUndefined) { + TLOGI(WmsLogTag::WMS_SUB, "windowRect is undefined"); + return true; + } + Rect windowRect; + if (!GetPropertyRectObject(env, "windowRect", (ani_object)rectRef, windowRect)) { + return false; + } + if (windowRect.width_ <= 0 || windowRect.height_ <= 0) { + TLOGE(WmsLogTag::WMS_SUB, "width or height should greater than 0!"); + return false; + } + TLOGI(WmsLogTag::WMS_SUB, "windowRect: %{public}s", windowRect.ToString().c_str()); + windowOption->SetWindowRect(windowRect); + 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; + } + ani_boolean decorEnabled; + auto ret = env->Object_GetPropertyByName_Boolean(jsObject, "decorEnabled", &decorEnabled); + if (ret != 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 diff --git a/wm/src/window_session_impl.cpp b/wm/src/window_session_impl.cpp index 401c35854a308a20043773510f4cda1803c93ac1..5ee6c15858d121bc45b4b8a1103dd5ada0ab624c 100644 --- a/wm/src/window_session_impl.cpp +++ b/wm/src/window_session_impl.cpp @@ -1848,9 +1848,14 @@ void WindowSessionImpl::HideTitleButton(bool& hideSplitButton, bool& hideMaximiz WMError WindowSessionImpl::NapiSetUIContent(const std::string& contentInfo, ani_env* env, ani_object storage, BackupAndRestoreType type, sptr token, AppExecFwk::Ability* ability) { - return SetUIContentInner(contentInfo, env, storage, - type == BackupAndRestoreType::NONE ? WindowSetUIContentType::DEFAULT : WindowSetUIContentType::RESTORE, - type, ability, 1u); + WindowSetUIContentType setUIContentType; + if (!navDestinationInfo_.empty()) { + setUIContentType = WindowSetUIContentType::BY_SHARED; + } else { + setUIContentType = + type == BackupAndRestoreType::NONE ? WindowSetUIContentType::DEFAULT : WindowSetUIContentType::RESTORE; + } + return SetUIContentInner(contentInfo, env, storage, setUIContentType, type, ability, 1u); } WMError WindowSessionImpl::NapiSetUIContent(const std::string& contentInfo, napi_env env, napi_value storage,