From d393a93957a14f1de4bbdbaef04f4c73e5bd1bcb Mon Sep 17 00:00:00 2001 From: l00574490 Date: Wed, 18 Jan 2023 11:38:05 +0800 Subject: [PATCH] add:setAspectRatio Signed-off-by: l00574490 Change-Id: I9836f0f792d9c864734cc23d8453249aae1a62a3 --- bundle.json | 3 +- dmserver/src/display_cutout_controller.cpp | 6 +- interfaces/innerkits/wm/window.h | 15 ++- interfaces/innerkits/wm/wm_common.h | 8 +- .../napi/window_runtime/api/@ohos.window.d.ts | 42 ++++++- .../window_runtime/window_napi/js_window.cpp | 119 +++++++++++++++++- .../window_runtime/window_napi/js_window.h | 6 +- previewer/include/window_impl.h | 4 +- previewer/src/window_impl.cpp | 12 +- utils/BUILD.gn | 2 + utils/include/cutout_info.h | 8 +- utils/include/persistent_storage.h | 81 ++++++++++++ utils/include/window_helper.h | 29 ++++- utils/include/window_property.h | 5 +- utils/include/wm_common_inner.h | 14 ++- utils/src/persistent_storage.cpp | 65 ++++++++++ utils/src/window_property.cpp | 18 ++- wm/include/window_impl.h | 4 +- wm/src/window_impl.cpp | 41 +++++- wmserver/include/display_group_controller.h | 2 +- wmserver/include/drag_controller.h | 16 ++- wmserver/include/window_controller.h | 4 +- wmserver/include/window_inner_manager.h | 5 +- wmserver/include/window_layout_policy.h | 5 +- .../include/window_layout_policy_cascade.h | 3 +- wmserver/include/window_layout_policy_tile.h | 2 +- wmserver/include/window_node.h | 4 +- wmserver/include/window_node_container.h | 2 +- wmserver/include/window_root.h | 3 +- wmserver/src/display_group_controller.cpp | 5 +- wmserver/src/drag_controller.cpp | 113 +++++++++++------ wmserver/src/window_controller.cpp | 51 +++++++- wmserver/src/window_inner_manager.cpp | 14 ++- wmserver/src/window_layout_policy.cpp | 57 +++++---- wmserver/src/window_layout_policy_cascade.cpp | 82 ++++++++++-- wmserver/src/window_layout_policy_tile.cpp | 2 +- wmserver/src/window_node.cpp | 12 +- wmserver/src/window_node_container.cpp | 4 +- wmserver/src/window_root.cpp | 28 ++++- .../test/unittest/drag_controller_test.cpp | 73 +++++++---- .../unittest/window_layout_policy_test.cpp | 22 ++-- 41 files changed, 832 insertions(+), 159 deletions(-) create mode 100644 utils/include/persistent_storage.h create mode 100644 utils/src/persistent_storage.cpp diff --git a/bundle.json b/bundle.json index 4a10bbe2b1..6a03e95b25 100644 --- a/bundle.json +++ b/bundle.json @@ -49,7 +49,8 @@ "display_manager", "config_policy", "ace_engine", - "multimedia_image_framework" + "multimedia_image_framework", + "preferences" ], "third_party": [ "flutter", diff --git a/dmserver/src/display_cutout_controller.cpp b/dmserver/src/display_cutout_controller.cpp index 5d1badb5b1..b3147c811d 100644 --- a/dmserver/src/display_cutout_controller.cpp +++ b/dmserver/src/display_cutout_controller.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -105,7 +105,7 @@ void DisplayCutoutController::CheckBoundingRectsBoundary(DisplayId displayId, st static_cast(boundingRect.width_) + boundingRect.posX_ > static_cast(displayWidth) || static_cast(boundingRect.height_) + boundingRect.posY_ > static_cast(displayHeight) || boundingRect.width_ > displayWidth || boundingRect.height_ > displayHeight || - boundingRect.isUninitializedRect()) { + boundingRect.IsUninitializedRect()) { WLOGFE("boundingRect boundary is invalid"); iter = boundingRects.erase(iter); } else { @@ -260,7 +260,7 @@ void DisplayCutoutController::TransferBoundingRectsByRotation(DisplayId displayI } uint32_t displayHeight = modes->height_; uint32_t displayWidth = modes->width_; - + switch (currentRotation) { case Rotation::ROTATION_90: { for (DMRect rect : displayBoundingRects) { diff --git a/interfaces/innerkits/wm/window.h b/interfaces/innerkits/wm/window.h index 1b28e004d9..39a4fd7da5 100644 --- a/interfaces/innerkits/wm/window.h +++ b/interfaces/innerkits/wm/window.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -477,6 +477,19 @@ public: * @param configuration configuration for app */ virtual bool IsAllowHaveSystemSubWindow() = 0; + + /** + * @brief Set aspect ratio of this window + * + * @param ratio the aspect ratio of window except decoration + * @return WMError + */ + virtual WMError SetAspectRatio(float ratio) = 0; + /** + * @brief Unset aspect ratio + * @return WMError + */ + virtual WMError UnsetAspectRatio() = 0; }; } } diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index 5660b0568a..074da4b335 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -349,7 +349,7 @@ struct Rect { return !this->operator==(a); } - bool isUninitializedRect() const + bool IsUninitializedRect() const { return (posX_ == 0 && posY_ == 0 && width_ == 0 && height_ == 0); } @@ -404,8 +404,8 @@ public: bool isEmptyAvoidArea() const { - return topRect_.isUninitializedRect() && leftRect_.isUninitializedRect() && - rightRect_.isUninitializedRect() && bottomRect_.isUninitializedRect(); + return topRect_.IsUninitializedRect() && leftRect_.IsUninitializedRect() && + rightRect_.IsUninitializedRect() && bottomRect_.IsUninitializedRect(); } static inline bool WriteParcel(Parcel& parcel, const Rect& rect) diff --git a/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts b/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts index 39c76a5760..9e5427be8e 100644 --- a/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts +++ b/interfaces/kits/napi/window_runtime/api/@ohos.window.d.ts @@ -1,5 +1,5 @@ /* -* Copyright (c) 2021-2022 Huawei Device Co., Ltd. +* Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -1240,6 +1240,46 @@ declare namespace window { * @since 9 */ snapshot(): Promise; + + /** + * Sets the aspect ratio of window + * @param { number } ratio - The aspect ratio of window except decoration + * @param { AsyncCallback } callback - The callback of setAspectRatio. + * @throws { BusinessError } 401 - If param is invalid + * @throws { BusinessError } 1300002 - If window state is abnormally + * @throws { BusinessError } 1300004 - If this window can not set aspect ratio + * @since 10 + */ + setAspectRatio(ratio: number, callback: AsyncCallback): void; + + /** + * Sets the aspect ratio of window + * @param { number } ratio - The aspect ratio of window except decoration + * @returns { Promise } - The promise returned by the function. + * @throws { BusinessError } 401 - If param is invalid + * @throws { BusinessError } 1300002 - If window state is abnormally + * @throws { BusinessError } 1300004 - If this window can not set aspect ratio + * @since 10 + */ + setAspectRatio(ratio: number): Promise; + + /** + * Unsets the aspect ratio of window + * @param { AsyncCallback } callback - The callback of setAspectRatio. + * @throws { BusinessError } 1300002 - If window state is abnormally + * @throws { BusinessError } 1300004 - If this window can not unset aspect ratio + * @since 10 + */ + unsetAspectRatio(callback: AsyncCallback): void; + + /** + * Unsets the aspect ratio of window + * @returns { Promise } - The promise returned by the function. + * @throws { BusinessError } 1300002 - If window state is abnormally + * @throws { BusinessError } 1300004 - If this window can not unset aspect ratio + * @since 10 + */ + unsetAspectRatio(): Promise; } /** * Transition Context diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp index cdd77f7058..c693375ae0 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -581,6 +581,20 @@ NativeValue* JsWindow::SetBackdropBlurStyle(NativeEngine* engine, NativeCallback return (me != nullptr) ? me->OnSetBackdropBlurStyle(*engine, *info) : nullptr; } +NativeValue* JsWindow::SetAspectRatio(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGI("[NAPI]SetAspectRatio"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnSetAspectRatio(*engine, *info) : nullptr; +} + +NativeValue* JsWindow::UnsetAspectRatio(NativeEngine* engine, NativeCallbackInfo* info) +{ + WLOGI("[NAPI]UnsetAspectRatio"); + JsWindow* me = CheckParamsAndGetThis(engine, info); + return (me != nullptr) ? me->OnUnsetAspectRatio(*engine, *info) : nullptr; +} + NativeValue* JsWindow::OnShow(NativeEngine& engine, NativeCallbackInfo& info) { WMError errCode = WMError::WM_OK; @@ -3103,7 +3117,7 @@ NativeValue* JsWindow::OnRaiseToAppTop(NativeEngine& engine, NativeCallbackInfo& static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY))); return; } - + WmErrorCode errCode = window->RaiseToAppTop(); if (errCode != WmErrorCode::WM_OK) { WLOGFE("raise window zorder failed"); @@ -3618,6 +3632,105 @@ NativeValue* JsWindow::OnSetBackdropBlurStyle(NativeEngine& engine, NativeCallba return engine.CreateUndefined(); } +NativeValue* JsWindow::OnSetAspectRatio(NativeEngine& engine, NativeCallbackInfo& info) +{ + WMError errCode = WMError::WM_OK; + if (info.argc < 1 || info.argc > 2) { // 2: maximum params num + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + errCode = WMError::WM_ERROR_INVALID_PARAM; + } + + if (!WindowHelper::IsMainWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]SetAspectRatio is not allowed since window is main window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + + float aspectRatio = 0.0; + if (errCode == WMError::WM_OK) { + NativeNumber* nativeVal = ConvertNativeValueTo(info.argv[0]); + if (nativeVal == nullptr) { + errCode = WMError::WM_ERROR_INVALID_PARAM; + } else { + aspectRatio = static_cast(*nativeVal); + } + } + + if (errCode == WMError::WM_ERROR_INVALID_PARAM || aspectRatio <= 0.0) { + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken, aspectRatio](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "OnSetAspectRatio failed.")); + return; + } + WMError ret = weakWindow->SetAspectRatio(aspectRatio); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "SetAspectRatio failed.")); + } + WLOGI("[NAPI]Window [%{public}u, %{public}s] set aspect ratio end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + NativeValue* lastParam = (info.argc == 1) ? nullptr : + (info.argv[1]->TypeOf() == NATIVE_FUNCTION ? info.argv[1] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::SetAspectRatio", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + +NativeValue* JsWindow::OnUnsetAspectRatio(NativeEngine& engine, NativeCallbackInfo& info) +{ + if (info.argc >= 1) { + WLOGFE("[NAPI]Argc is invalid: %{public}zu", info.argc); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_PARAM))); + return engine.CreateUndefined(); + } + + if (!WindowHelper::IsMainWindow(windowToken_->GetType())) { + WLOGFE("[NAPI]UnsetAspectRatio is not allowed since window is main window"); + engine.Throw(CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_INVALID_CALLING))); + return engine.CreateUndefined(); + } + + wptr weakToken(windowToken_); + AsyncTask::CompleteCallback complete = + [weakToken](NativeEngine& engine, AsyncTask& task, int32_t status) { + auto weakWindow = weakToken.promote(); + if (weakWindow == nullptr) { + task.Reject(engine, + CreateJsError(engine, static_cast(WmErrorCode::WM_ERROR_STATE_ABNORMALLY), + "OnUnsetAspectRatio failed.")); + return; + } + WMError ret = weakWindow->UnsetAspectRatio(); + if (ret == WMError::WM_OK) { + task.Resolve(engine, engine.CreateUndefined()); + } else { + task.Reject(engine, CreateJsError(engine, static_cast(ret), "UnsetAspectRatio failed.")); + } + WLOGI("[NAPI]Window [%{public}u, %{public}s] unset aspect ratio end, ret = %{public}d", + weakWindow->GetWindowId(), weakWindow->GetWindowName().c_str(), ret); + }; + + NativeValue* lastParam = (info.argc == 0) ? nullptr : + (info.argv[0]->TypeOf() == NATIVE_FUNCTION ? info.argv[0] : nullptr); + NativeValue* result = nullptr; + AsyncTask::Schedule("JsWindow::OnUnsetAspectRatio", + engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result)); + return result; +} + std::shared_ptr FindJsWindowObject(std::string windowName) { WLOGFD("Try to find window %{public}s in g_jsWindowMap", windowName.c_str()); @@ -3728,6 +3841,8 @@ void BindFunctions(NativeEngine& engine, NativeObject* object, const char *modul BindNativeFunction(engine, *object, "setBlur", moduleName, JsWindow::SetBlur); BindNativeFunction(engine, *object, "setBackdropBlur", moduleName, JsWindow::SetBackdropBlur); BindNativeFunction(engine, *object, "setBackdropBlurStyle", moduleName, JsWindow::SetBackdropBlurStyle); + BindNativeFunction(engine, *object, "setAspectRatio", moduleName, JsWindow::SetAspectRatio); + BindNativeFunction(engine, *object, "unsetAspectRatio", moduleName, JsWindow::UnsetAspectRatio); } } // namespace Rosen } // namespace OHOS diff --git a/interfaces/kits/napi/window_runtime/window_napi/js_window.h b/interfaces/kits/napi/window_runtime/window_napi/js_window.h index bc908a1647..d7b6b2135d 100644 --- a/interfaces/kits/napi/window_runtime/window_napi/js_window.h +++ b/interfaces/kits/napi/window_runtime/window_napi/js_window.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -91,6 +91,8 @@ public: static NativeValue* DisableWindowDecor(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* SetSnapshotSkip(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* RaiseToAppTop(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* SetAspectRatio(NativeEngine* engine, NativeCallbackInfo* info); + static NativeValue* UnsetAspectRatio(NativeEngine* engine, NativeCallbackInfo* info); // colorspace, gamut static NativeValue* IsSupportWideGamut(NativeEngine* engine, NativeCallbackInfo* info); static NativeValue* IsWindowSupportWideGamut(NativeEngine* engine, NativeCallbackInfo* info); @@ -155,6 +157,8 @@ private: NativeValue* OnIsWindowShowingSync(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnSetPreferredOrientation(NativeEngine& engine, NativeCallbackInfo& info); NativeValue* OnRaiseToAppTop(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnSetAspectRatio(NativeEngine& engine, NativeCallbackInfo& info); + NativeValue* OnUnsetAspectRatio(NativeEngine& engine, NativeCallbackInfo& info); // colorspace, gamut NativeValue* OnIsSupportWideGamut(NativeEngine& engine, NativeCallbackInfo& info); diff --git a/previewer/include/window_impl.h b/previewer/include/window_impl.h index 03bb5205eb..1086c75455 100644 --- a/previewer/include/window_impl.h +++ b/previewer/include/window_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -189,6 +189,8 @@ public: virtual WMError NotifyMemoryLevel(int32_t level) const override; virtual bool IsAllowHaveSystemSubWindow() override; WmErrorCode RaiseToAppTop() override; + virtual WMError SetAspectRatio(float ratio) override; + virtual WMError UnsetAspectRatio() override; private: static std::map>> windowMap_; diff --git a/previewer/src/window_impl.cpp b/previewer/src/window_impl.cpp index f77cbcf2fd..0cc3cd047b 100644 --- a/previewer/src/window_impl.cpp +++ b/previewer/src/window_impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -763,5 +763,15 @@ WmErrorCode WindowImpl::RaiseToAppTop() { return WmErrorCode::WM_OK; } + +WMError WindowImpl::SetAspectRatio(float ratio) +{ + return WMError::WM_OK; +} + +WMError WindowImpl::UnsetAspectRatio() +{ + return WMError::WM_OK; +} } // namespace Rosen } // namespace OHOS diff --git a/utils/BUILD.gn b/utils/BUILD.gn index 0955f841fc..d30dcdfa89 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -36,6 +36,7 @@ ohos_shared_library("libwmutil") { "src/display_info.cpp", "src/perform_reporter.cpp", "src/permission.cpp", + "src/persistent_storage.cpp", "src/screen_group_info.cpp", "src/screen_info.cpp", "src/screenshot_info.cpp", @@ -76,6 +77,7 @@ ohos_shared_library("libwmutil") { "input:libmmi-client", "ipc:ipc_core", "multimedia_image_framework:image_native", + "preferences:native_preferences", "samgr:samgr_proxy", ] part_name = "window_manager" diff --git a/utils/include/cutout_info.h b/utils/include/cutout_info.h index 4b82c1fe8c..b857ee5f2c 100644 --- a/utils/include/cutout_info.h +++ b/utils/include/cutout_info.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -39,7 +39,7 @@ struct DMRect { return !this->operator==(a); } - bool isUninitializedRect() const + bool IsUninitializedRect() const { return (posX_ == 0 && posY_ == 0 && width_ == 0 && height_ == 0); } @@ -59,8 +59,8 @@ struct WaterfallDisplayAreaRects { bool isUninitialized() const { - return (left.isUninitializedRect() && top.isUninitializedRect() && right.isUninitializedRect() && - bottom.isUninitializedRect()); + return (left.IsUninitializedRect() && top.IsUninitializedRect() && right.IsUninitializedRect() && + bottom.IsUninitializedRect()); } }; diff --git a/utils/include/persistent_storage.h b/utils/include/persistent_storage.h new file mode 100644 index 0000000000..fc9ef4bcd5 --- /dev/null +++ b/utils/include/persistent_storage.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_ROSEN_WINDOW_PERSISTENT_STORAGE_H +#define OHOS_ROSEN_WINDOW_PERSISTENT_STORAGE_H + +#include "preferences.h" +#include "preferences_helper.h" + +#include "window_manager_hilog.h" +#include "wm_common_inner.h" + +namespace OHOS { +namespace Rosen { +using PersistentPerference = NativePreferences::Preferences; +class PersistentStorage { +public: + PersistentStorage() = default; + ~PersistentStorage() = default; + + template + static void Insert(const std::string& key, const T& value, PersistentStorageType storageType) + { + auto pref = GetPreference(storageType); + if (!pref) { + WLOG_E("[PersistentStorage] Preferences is nullptr"); + return; + } + switch (storageType) { + case PersistentStorageType::ASPECT_RATIO: { + pref->PutFloat(key, value); + WLOG_D("[PersistentStorage] Insert aspect ratio, key %{public}s, value %{public}f", key.c_str(), value); + break; + } + default: + WLOG_W("[PersistentStorage] Unknown storage type!"); + } + pref->Flush(); + } + + template + static void Get(const std::string& key, T& value, PersistentStorageType storageType) + { + auto pref = GetPreference(storageType); + if (!pref) { + WLOG_E("[PersistentStorage] Preferences is nullptr"); + return; + } + switch (storageType) { + case PersistentStorageType::ASPECT_RATIO: { + value = pref->GetFloat(key); + WLOG_D("[PersistentStorage] Get aspect ratio, key: %{public}s, value:%{public}f", key.c_str(), value); + break; + } + default: + WLOG_W("[PersistentStorage] Unknown storage type!"); + } + } + + static bool HasKey(const std::string& key, PersistentStorageType storageType); + static void Delete(const std::string& key, PersistentStorageType storageType); + +private: + static std::shared_ptr GetPreference(PersistentStorageType storageType); + static std::map storagePath_; +}; +} // namespace Rosen +} // namespace OHOS +#endif // OHOS_ROSEN_WINDOW_PERSISTENT_STORAGE_H \ No newline at end of file diff --git a/utils/include/window_helper.h b/utils/include/window_helper.h index 59507aeb84..39bd711303 100644 --- a/utils/include/window_helper.h +++ b/utils/include/window_helper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -526,6 +526,33 @@ public: return true; } + static bool IsAspectRatioSatisfiedWithSizeLimits(const WindowSizeLimits& sizeLimits, float ratio, float vpr) + { + /* + * 1) Usually the size limits won't be empty after show window. + * In case of SetAspectRatio is called befor show (size limits may be empty at that time) or the + * sizeLimits is empty, there is no need to check ratio (layout will check), return true directly. + * 2) ratio : 0.0 means unset aspect ratio + */ + if (sizeLimits.IsEmpty() || MathHelper::NearZero(ratio)) { + return true; + } + + uint32_t winFrameW = static_cast(WINDOW_FRAME_WIDTH * vpr) * 2; // 2 mean double decor width + uint32_t winFrameH = static_cast(WINDOW_FRAME_WIDTH * vpr) + + static_cast(WINDOW_TITLE_BAR_HEIGHT * vpr); // decor height + uint32_t maxWidth = sizeLimits.maxWidth_ - winFrameW; + uint32_t minWidth = sizeLimits.minWidth_ - winFrameW; + uint32_t maxHeight = sizeLimits.maxHeight_ - winFrameH; + uint32_t minHeight = sizeLimits.minHeight_ - winFrameH; + float maxRatio = static_cast(maxWidth) / static_cast(minHeight); + float minRatio = static_cast(minWidth) / static_cast(maxHeight); + if (maxRatio < ratio || ratio < minRatio) { + return false; + } + return true; + } + private: WindowHelper() = default; ~WindowHelper() = default; diff --git a/utils/include/window_property.h b/utils/include/window_property.h index fe22b5c8dc..5e54a765a8 100644 --- a/utils/include/window_property.h +++ b/utils/include/window_property.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -87,6 +87,7 @@ public: void UpdatePointerEvent(const std::shared_ptr& pointerEvent); bool isNeedComputerTransform(); void ClearTransformZAxisOffset(Transform& trans); + void SetAspectRatio(float ratio); const std::string& GetWindowName() const; const AbilityInfo& GetAbilityInfo() const; @@ -132,6 +133,7 @@ public: WindowSizeLimits GetUpdatedSizeLimits() const; const TransformHelper::Matrix4& GetTransformMat() const; const TransformHelper::Matrix4& GetWorldTransformMat() const; + float GetAspectRatio() const; virtual bool Marshalling(Parcel& parcel) const override; static WindowProperty* Unmarshalling(Parcel& parcel); @@ -201,6 +203,7 @@ private: // if scale of trans_ is less than 1.0, zoomTrans_ may be an identity matrix bool isDisplayZoomOn_ {false}; bool isAnimateWindow_ {false}; + float aspectRatio_ {0.0}; DEFINE_VAR_DEFAULT_FUNC_GET_SET(Orientation, RequestedOrientation, requestedOrientation, Orientation::UNSPECIFIED); WindowSizeLimits sizeLimits_; diff --git a/utils/include/wm_common_inner.h b/utils/include/wm_common_inner.h index ecc848ecd7..e41db90710 100644 --- a/utils/include/wm_common_inner.h +++ b/utils/include/wm_common_inner.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -43,6 +43,7 @@ enum class WindowUpdateReason : uint32_t { UPDATE_RECT, UPDATE_FLAGS, UPDATE_TYPE, + UPDATE_ASPECT_RATIO, NEED_SWITCH_CASCADE_END, UPDATE_OTHER_PROPS, UPDATE_TRANSFORM, @@ -79,6 +80,7 @@ enum class PropertyChangeAction : uint32_t { ACTION_UPDATE_TRANSFORM_PROPERTY = 1 << 13, ACTION_UPDATE_ANIMATION_FLAG = 1 << 14, ACTION_UPDATE_PRIVACY_MODE = 1 << 15, + ACTION_UPDATE_ASPECT_RATIO = 1 << 16, }; struct ModeChangeHotZonesConfig { @@ -188,6 +190,11 @@ struct WindowSizeLimits { uint32_t minWidth, uint32_t minHeight, float maxRatio, float minRatio) : maxWidth_(maxWidth), maxHeight_(maxHeight), minWidth_(minWidth), minHeight_(minHeight), maxRatio_(maxRatio), minRatio_(minRatio) {} + + bool IsEmpty() const + { + return (maxWidth_ == 0 || minWidth_ == 0 || maxHeight_ == 0 || minHeight_ == 0); + } }; struct ModeChangeHotZones { @@ -220,6 +227,11 @@ enum class TraceTaskId : int32_t { START_WINDOW_ANIMATION, }; +enum class PersistentStorageType : uint32_t { + UKNOWN = 0, + ASPECT_RATIO, +}; + struct MoveDragProperty : public Parcelable { int32_t startPointPosX_; int32_t startPointPosY_; diff --git a/utils/src/persistent_storage.cpp b/utils/src/persistent_storage.cpp new file mode 100644 index 0000000000..e8bfe4cef4 --- /dev/null +++ b/utils/src/persistent_storage.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "persistent_storage.h" + +namespace OHOS { +namespace Rosen { +namespace { + constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "PersistentStorage"}; +} +std::map PersistentStorage::storagePath_ = { + { PersistentStorageType::ASPECT_RATIO, "/data/service/el1/public/window/window_aspect_ratio.xml" }, +}; + +bool PersistentStorage::HasKey(const std::string& key, PersistentStorageType storageType) +{ + bool res = false; + auto pref = GetPreference(storageType); + if (!pref) { + WLOGE("[PersistentStorage] Preferences is nullptr"); + return res; + } + res = pref->HasKey(key); + WLOGD("[PersistentStorage] Key: %{public}s, hasKey: %{public}d", key.c_str(), res); + return res; +} + +void PersistentStorage::Delete(const std::string& key, PersistentStorageType storageType) +{ + auto pref = GetPreference(storageType); + if (!pref) { + WLOGE("[PersistentStorage] Preferences is nullptr"); + return; + } + pref->Delete(key); + pref->Flush(); + WLOGD("[PersistentStorage] Delete key %{public}s", key.c_str()); +} + +std::shared_ptr PersistentStorage::GetPreference(PersistentStorageType storageType) +{ + auto iter = storagePath_.find(storageType); + if (iter == storagePath_.end()) { + return nullptr; + } + auto fileName = storagePath_[storageType]; + int errCode; + auto pref = NativePreferences::PreferencesHelper::GetPreferences(fileName, errCode); + WLOGD("[PersistentStorage] GetPreference fileName: %{public}s, errCode: %{public}d", fileName.c_str(), errCode); + return pref; +} +} // namespace Rosen +} // namespace OHOS \ No newline at end of file diff --git a/utils/src/window_property.cpp b/utils/src/window_property.cpp index b40f852801..f19d6bbeff 100644 --- a/utils/src/window_property.cpp +++ b/utils/src/window_property.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -557,6 +557,16 @@ void WindowProperty::GetTouchHotAreas(std::vector& rects) const rects = touchHotAreas_; } +void WindowProperty::SetAspectRatio(float ratio) +{ + aspectRatio_ = ratio; +} + +float WindowProperty::GetAspectRatio() const +{ + return aspectRatio_; +} + uint32_t WindowProperty::GetAccessTokenId() const { return accessTokenId_; @@ -800,6 +810,9 @@ bool WindowProperty::Write(Parcel& parcel, PropertyChangeAction action) case PropertyChangeAction::ACTION_UPDATE_PRIVACY_MODE: ret = ret && parcel.WriteBool(isPrivacyMode_); break; + case PropertyChangeAction::ACTION_UPDATE_ASPECT_RATIO: + ret = ret && parcel.WriteFloat(aspectRatio_); + break; default: break; } @@ -863,6 +876,9 @@ void WindowProperty::Read(Parcel& parcel, PropertyChangeAction action) case PropertyChangeAction::ACTION_UPDATE_PRIVACY_MODE: SetPrivacyMode(parcel.ReadBool()); break; + case PropertyChangeAction::ACTION_UPDATE_ASPECT_RATIO: + SetAspectRatio(parcel.ReadFloat()); + break; default: break; } diff --git a/wm/include/window_impl.h b/wm/include/window_impl.h index d5c9ef24a0..f314f20cd5 100644 --- a/wm/include/window_impl.h +++ b/wm/include/window_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -169,6 +169,8 @@ public: virtual WMError BindDialogTarget(sptr targetToken) override; virtual void SetSnapshotSkip(bool isSkip) override; WmErrorCode RaiseToAppTop() override; + virtual WMError SetAspectRatio(float ratio) override; + virtual WMError UnsetAspectRatio() override; // window effect virtual WMError SetCornerRadius(float cornerRadius) override; diff --git a/wm/src/window_impl.cpp b/wm/src/window_impl.cpp index 4b5df03744..7d08103666 100755 --- a/wm/src/window_impl.cpp +++ b/wm/src/window_impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -737,6 +737,45 @@ WMError WindowImpl::SetFullScreen(bool status) return ret; } +WMError WindowImpl::SetAspectRatio(float ratio) +{ + WLOGFI("windowId: %{public}u, ratio: %{public}f", GetWindowId(), ratio); + if (!WindowHelper::IsMainWindow(GetType())) { + WLOGFE("Invalid operation, windowId: %{public}u", GetWindowId()); + return WMError::WM_ERROR_INVALID_OPERATION; + } + if (MathHelper::NearZero(ratio) || ratio < 0.0f) { + WLOGFE("Invalid param, ratio: %{public}f", ratio); + return WMError::WM_ERROR_INVALID_PARAM; + } + if (std::abs(property_->GetAspectRatio() - ratio) < 0.0001f) { + return WMError::WM_OK; + } + property_->SetAspectRatio(ratio); + if (state_ == WindowState::STATE_HIDDEN || state_ == WindowState::STATE_CREATED) { + WLOGFD("window is hidden or created! id: %{public}u, ratio: %{public}f ", property_->GetWindowId(), ratio); + return WMError::WM_OK; + } + UpdateProperty(PropertyChangeAction::ACTION_UPDATE_ASPECT_RATIO); + return WMError::WM_OK; +} + +WMError WindowImpl::UnsetAspectRatio() +{ + WLOGFI("windowId: %{public}u", GetWindowId()); + if (!WindowHelper::IsMainWindow(GetType())) { + WLOGFE("Invalid operation, windowId: %{public}u", GetWindowId()); + return WMError::WM_ERROR_INVALID_OPERATION; + } + property_->SetAspectRatio(0.0); + if (state_ == WindowState::STATE_HIDDEN || state_ == WindowState::STATE_CREATED) { + WLOGFD("window is hidden or created! id: %{public}u", property_->GetWindowId()); + return WMError::WM_OK; + } + UpdateProperty(PropertyChangeAction::ACTION_UPDATE_ASPECT_RATIO); + return WMError::WM_OK; +} + void WindowImpl::MapFloatingWindowToAppIfNeeded() { if (!WindowHelper::IsAppFloatingWindow(GetType()) || context_.get() == nullptr) { diff --git a/wmserver/include/display_group_controller.h b/wmserver/include/display_group_controller.h index 807136a2ea..55d5932526 100644 --- a/wmserver/include/display_group_controller.h +++ b/wmserver/include/display_group_controller.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/wmserver/include/drag_controller.h b/wmserver/include/drag_controller.h index f42e365a21..006224faa2 100644 --- a/wmserver/include/drag_controller.h +++ b/wmserver/include/drag_controller.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,6 +18,8 @@ #include +#include "display_group_info.h" +#include "display_info.h" #include "event_handler.h" #include "event_runner.h" #include "input_manager.h" @@ -73,7 +75,8 @@ public: void HandleWindowRemovedOrDestroyed(uint32_t windowId); void ConsumePointerEvent(const std::shared_ptr& pointerEvent); uint32_t GetActiveWindowId() const; - void HandleDisplayChange(const std::map& displayRectMap); + void SetDisplayGroupInfo(sptr displayGroupInfo); + void HandleDisplayLimitRectChange(const std::map& limitRectMap); void SetInputEventConsumer(); private: @@ -86,18 +89,21 @@ private: void ConvertPointerPosToDisplayGroupPos(DisplayId displayId, int32_t& posX, int32_t& posY); void HandlePointerEvent(const std::shared_ptr& pointerEvent); - void HandleDragEvent(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType); - void HandleMoveEvent(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType); + void HandleDragEvent(DisplayId displayId, int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType); + void HandleMoveEvent(DisplayId displayId, int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType); void OnReceiveVsync(int64_t timeStamp); void ResetMoveOrDragState(); + bool CheckWindowRect(DisplayId displayId, float vpr, const Rect& rect); + void CalculateNewWindowRect(Rect& newRect, DisplayId displayId, int32_t posX, int32_t posY); sptr windowProperty_; sptr moveDragProperty_; + sptr displayGroupInfo_; uint32_t activeWindowId_ = INVALID_WINDOW_ID; std::shared_ptr moveEvent_ = nullptr; std::shared_ptr inputListener_ = nullptr; std::shared_ptr vsyncCallback_ = std::make_shared(VsyncCallback()); - std::map displayRectMap_; + std::map limitRectMap_; // event handler for input event std::shared_ptr inputEventHandler_; diff --git a/wmserver/include/window_controller.h b/wmserver/include/window_controller.h index 759285ac9e..facc29e2d7 100644 --- a/wmserver/include/window_controller.h +++ b/wmserver/include/window_controller.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -81,6 +81,8 @@ public: WMError ChangeMouseStyle(uint32_t windowId, sptr& moveDragProperty); void RecoverDefaultMouseStyle(uint32_t windowId); WmErrorCode RaiseToAppTop(uint32_t windowId); + WMError SetAspectRatio(uint32_t windowId, float ratio); + private: uint32_t GenWindowId(); void FlushWindowInfo(uint32_t windowId); diff --git a/wmserver/include/window_inner_manager.h b/wmserver/include/window_inner_manager.h index 101157d0fc..47b3df9bb9 100644 --- a/wmserver/include/window_inner_manager.h +++ b/wmserver/include/window_inner_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -54,7 +54,8 @@ public: void CompleteFirstFrameDrawing(const wptr &node); void ConsumePointerEvent(const std::shared_ptr& pointerEvent); - void NotifyDisplayChange(const std::map& displayRectMap); + void SetDisplayGroupInfo(sptr displayGroupInfo); + void NotifyDisplayLimitRectChange(const std::map& limitRectMap); bool NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, sptr& moveDragProperty); void NotifyWindowEndUpMovingOrDragging(uint32_t windowId); diff --git a/wmserver/include/window_layout_policy.h b/wmserver/include/window_layout_policy.h index 0fcb728d8c..bde8b540bc 100644 --- a/wmserver/include/window_layout_policy.h +++ b/wmserver/include/window_layout_policy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -98,7 +98,7 @@ protected: * methods for floating window limitSize and position */ DockWindowShowState GetDockWindowShowState(DisplayId displayId, Rect& dockWinRect) const; - void LimitFloatingWindowSize(const sptr& node, const Rect& displayRect, Rect& winRect) const; + void LimitFloatingWindowSize(const sptr& node, Rect& winRect) const; void LimitMainFloatingWindowPosition(const sptr& node, Rect& winRect) const; void UpdateFloatingWindowSizeForStretchableWindow(const sptr& node, const Rect& displayRect, Rect& winRect) const; @@ -107,6 +107,7 @@ protected: void LimitWindowPositionWhenInitRectOrMove(const sptr& node, Rect& winRect) const; void LimitWindowPositionWhenDrag(const sptr& node, Rect& winRect) const; void FixWindowSizeByRatioIfDragBeyondLimitRegion(const sptr& node, Rect& winRect); + void FixWindowRectWhenDrag(const sptr& node, const Rect& oriWinRect, Rect& winRect) const; /* * methods for update node latest information, include: diff --git a/wmserver/include/window_layout_policy_cascade.h b/wmserver/include/window_layout_policy_cascade.h index 1b75b7e524..d333949eb5 100644 --- a/wmserver/include/window_layout_policy_cascade.h +++ b/wmserver/include/window_layout_policy_cascade.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -68,6 +68,7 @@ private: void UpdateLayoutRect(const sptr& node) override; void ComputeDecoratedRequestRect(const sptr& node) const; void ApplyWindowRectConstraints(const sptr& node, Rect& winRect) const; + void ComputeRectByAspectRatio(const sptr& node) const; struct CascadeRects { Rect primaryRect_; diff --git a/wmserver/include/window_layout_policy_tile.h b/wmserver/include/window_layout_policy_tile.h index 093b4b6ff5..65048e1a1d 100644 --- a/wmserver/include/window_layout_policy_tile.h +++ b/wmserver/include/window_layout_policy_tile.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/wmserver/include/window_node.h b/wmserver/include/window_node.h index 52ec3e9159..8c5d0852c5 100644 --- a/wmserver/include/window_node.h +++ b/wmserver/include/window_node.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -89,6 +89,7 @@ public: std::shared_ptr GetSnapshot(); Transform GetZoomTransform() const; void UpdateZoomTransform(const Transform& trans, bool isDisplayZoomOn); + void SetAspectRatio(float ratio); const sptr& GetWindowToken() const; uint32_t GetWindowId() const; @@ -125,6 +126,7 @@ public: uint32_t GetAccessTokenId() const; WindowSizeLimits GetWindowSizeLimits() const; WindowSizeLimits GetWindowUpdatedSizeLimits() const; + float GetAspectRatio() const; bool EnableDefaultAnimation(bool animationPlayed); sptr parent_; diff --git a/wmserver/include/window_node_container.h b/wmserver/include/window_node_container.h index 6a325ded1f..f036e9aa01 100644 --- a/wmserver/include/window_node_container.h +++ b/wmserver/include/window_node_container.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/wmserver/include/window_root.h b/wmserver/include/window_root.h index 729e02fd72..26d0d6f8b4 100644 --- a/wmserver/include/window_root.h +++ b/wmserver/include/window_root.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -153,6 +153,7 @@ private: WMError BindDialogToParent(sptr& node, sptr& parentNode); void ChangeRSRenderModeIfNeeded(bool isToUnified); bool IsAppWindowExceed() const; + void GetStoragedAspectRatio(const sptr& node); std::map> windowNodeMap_; std::map, uint32_t> windowIdMap_; diff --git a/wmserver/src/display_group_controller.cpp b/wmserver/src/display_group_controller.cpp index 5bd05869fa..e81a346510 100644 --- a/wmserver/src/display_group_controller.cpp +++ b/wmserver/src/display_group_controller.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -391,7 +391,6 @@ void DisplayGroupController::ProcessNotCrossNodesOnDestroyedDisplay(DisplayId di void DisplayGroupController::ProcessDisplayCreate(DisplayId defaultDisplayId, sptr displayInfo, const std::map& displayRectMap) { - WindowInnerManager::GetInstance().NotifyDisplayChange(displayRectMap); defaultDisplayId_ = defaultDisplayId; WLOGI("defaultDisplay, displayId: %{public}" PRIu64"", defaultDisplayId); @@ -417,7 +416,6 @@ void DisplayGroupController::ProcessDisplayDestroy(DisplayId defaultDisplayId, s const std::map& displayRectMap, std::vector& windowIds) { - WindowInnerManager::GetInstance().NotifyDisplayChange(displayRectMap); DisplayId displayId = displayInfo->GetDisplayId(); // delete nodes and map element of deleted display @@ -481,7 +479,6 @@ void DisplayGroupController::ProcessDisplayChange(DisplayId defaultDisplayId, sp const std::map& displayRectMap, DisplayStateChangeType type) { - WindowInnerManager::GetInstance().NotifyDisplayChange(displayRectMap); DisplayId displayId = displayInfo->GetDisplayId(); WLOGI("display change, displayId: %{public}" PRIu64", type: %{public}d", displayId, type); switch (type) { diff --git a/wmserver/src/drag_controller.cpp b/wmserver/src/drag_controller.cpp index 87561f8bbd..27efc221a0 100644 --- a/wmserver/src/drag_controller.cpp +++ b/wmserver/src/drag_controller.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,7 +18,6 @@ #include "display.h" #include "vsync_station.h" -#include "wm_common.h" #include "window_helper.h" #include "window_inner_manager.h" #include "window_manager_hilog.h" @@ -26,6 +25,8 @@ #include "window_node.h" #include "window_node_container.h" #include "window_property.h" +#include "wm_common.h" +#include "wm_math.h" #include "xcollie/watchdog.h" namespace OHOS { @@ -248,24 +249,21 @@ void MoveDragController::HandleWindowRemovedOrDestroyed(uint32_t windowId) void MoveDragController::ConvertPointerPosToDisplayGroupPos(DisplayId displayId, int32_t& posX, int32_t& posY) { - if (displayRectMap_.size() <= 1) { - return; - } - - auto iter = displayRectMap_.find(displayId); - if (iter == displayRectMap_.end()) { - return; - } - auto displayRect = iter->second; + auto displayRect = displayGroupInfo_->GetDisplayRect(displayId); posX += displayRect.posX_; posY += displayRect.posY_; } -void MoveDragController::HandleDisplayChange(const std::map& displayRectMap) +void MoveDragController::SetDisplayGroupInfo(sptr displayGroupInfo) +{ + displayGroupInfo_ = displayGroupInfo; +} + +void MoveDragController::HandleDisplayLimitRectChange(const std::map& limitRectMap) { - displayRectMap_.clear(); - for (auto& elem : displayRectMap) { - displayRectMap_.insert(elem); + limitRectMap_.clear(); + for (auto& elem : limitRectMap) { + limitRectMap_.insert(elem); } } @@ -318,49 +316,87 @@ Rect MoveDragController::GetHotZoneRect() return hotZoneRect; } -void MoveDragController::HandleDragEvent(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType) +bool MoveDragController::CheckWindowRect(DisplayId displayId, float vpr, const Rect& rect) { - if (moveDragProperty_ == nullptr) { - return; - } - if (!moveDragProperty_->startDragFlag_ || - (pointId != moveDragProperty_->startPointerId_) || - (sourceType != moveDragProperty_->sourceType_)) { - return; + uint32_t titleBarHeight = static_cast(WINDOW_TITLE_BAR_HEIGHT * vpr); + auto iter = limitRectMap_.find(displayId); + Rect limitRect; + if (iter != limitRectMap_.end()) { + limitRect = iter->second; + } + if (WindowHelper::IsEmptyRect(limitRect) || MathHelper::NearZero(vpr)) { + return true; // If limitRect is empty, we can't use limitRect to check window rect + } + + if ((rect.posX_ > static_cast(limitRect.posX_ + limitRect.width_ - titleBarHeight)) || + (rect.posX_ + static_cast(rect.width_) < + static_cast(limitRect.posX_ + titleBarHeight)) || + (rect.posY_ < limitRect.posY_) || + (rect.posY_ > static_cast(limitRect.posY_ + limitRect.height_ - titleBarHeight))) { + WLOGFD("[WMS] Invalid window rect, id: %{public}u, rect: [%{public}d, %{public}d, %{public}d, %{public}d]", + windowProperty_->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_); + return false; } + return true; +} + +void MoveDragController::CalculateNewWindowRect(Rect& newRect, DisplayId displayId, int32_t posX, int32_t posY) +{ auto startPointPosX = moveDragProperty_->startPointPosX_; auto startPointPosY = moveDragProperty_->startPointPosY_; ConvertPointerPosToDisplayGroupPos(moveDragProperty_->targetDisplayId_, startPointPosX, startPointPosY); const auto& startPointRect = moveDragProperty_->startPointRect_; - Rect newRect = startPointRect; Rect hotZoneRect = GetHotZoneRect(); int32_t diffX = posX - startPointPosX; int32_t diffY = posY - startPointPosY; + float vpr = displayGroupInfo_->GetDisplayVirtualPixelRatio(displayId); + if (MathHelper::NearZero(vpr)) { + return; + } + uint32_t minWidth = static_cast(MIN_FLOATING_WIDTH * vpr); + uint32_t minHeight = static_cast(MIN_FLOATING_HEIGHT * vpr); if (startPointPosX <= hotZoneRect.posX_) { - if (diffX > static_cast(startPointRect.width_)) { - diffX = static_cast(startPointRect.width_); + if (diffX > static_cast(startPointRect.width_ - minWidth)) { + diffX = static_cast(startPointRect.width_ - minWidth); } newRect.posX_ += diffX; newRect.width_ = static_cast(static_cast(newRect.width_) - diffX); } else if (startPointPosX >= hotZoneRect.posX_ + static_cast(hotZoneRect.width_)) { - if (diffX < 0 && (-diffX > static_cast(startPointRect.width_))) { - diffX = -(static_cast(startPointRect.width_)); + if (diffX < 0 && (-diffX > static_cast(startPointRect.width_ - minWidth))) { + diffX = -(static_cast(startPointRect.width_ - minWidth)); } newRect.width_ = static_cast(static_cast(newRect.width_) + diffX); } if (startPointPosY <= hotZoneRect.posY_) { - if (diffY > static_cast(startPointRect.height_)) { - diffY = static_cast(startPointRect.height_); + if (diffY > static_cast(startPointRect.height_ - minHeight)) { + diffY = static_cast(startPointRect.height_ - minHeight); } newRect.posY_ += diffY; newRect.height_ = static_cast(static_cast(newRect.height_) - diffY); } else if (startPointPosY >= hotZoneRect.posY_ + static_cast(hotZoneRect.height_)) { - if (diffY < 0 && (-diffY > static_cast(startPointRect.height_))) { - diffY = -(static_cast(startPointRect.height_)); + if (diffY < 0 && (-diffY > static_cast(startPointRect.height_ - minHeight))) { + diffY = -(static_cast(startPointRect.height_ - minHeight)); } newRect.height_ = static_cast(static_cast(newRect.height_) + diffY); } +} + +void MoveDragController::HandleDragEvent(DisplayId displayId, int32_t posX, int32_t posY, + int32_t pointId, int32_t sourceType) +{ + if (moveDragProperty_ == nullptr || !moveDragProperty_->startDragFlag_ || + (pointId != moveDragProperty_->startPointerId_) || (sourceType != moveDragProperty_->sourceType_)) { + return; + } + + Rect newRect = moveDragProperty_->startPointRect_; + CalculateNewWindowRect(newRect, displayId, posX, posY); + + if (!CheckWindowRect(displayId, displayGroupInfo_->GetDisplayVirtualPixelRatio(displayId), newRect)) { + return; + } + WLOGFD("[WMS] HandleDragEvent, id: %{public}u, newRect: [%{public}d, %{public}d, %{public}d, %{public}d]", windowProperty_->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_); windowProperty_->SetRequestRect(newRect); @@ -369,7 +405,8 @@ void MoveDragController::HandleDragEvent(int32_t posX, int32_t posY, int32_t poi WindowManagerService::GetInstance().UpdateProperty(windowProperty_, PropertyChangeAction::ACTION_UPDATE_RECT, true); } -void MoveDragController::HandleMoveEvent(int32_t posX, int32_t posY, int32_t pointId, int32_t sourceType) +void MoveDragController::HandleMoveEvent(DisplayId displayId, int32_t posX, int32_t posY, + int32_t pointId, int32_t sourceType) { if (moveDragProperty_ == nullptr) { return; @@ -385,8 +422,12 @@ void MoveDragController::HandleMoveEvent(int32_t posX, int32_t posY, int32_t poi int32_t targetX = moveDragProperty_->startPointRect_.posX_ + (posX - startPointPosX); int32_t targetY = moveDragProperty_->startPointRect_.posY_ + (posY - startPointPosY); - const Rect& oriRect = windowProperty_->GetRequestRect(); + const Rect& oriRect = moveDragProperty_->startPointRect_; Rect newRect = { targetX, targetY, oriRect.width_, oriRect.height_ }; + float vpr = displayGroupInfo_->GetDisplayVirtualPixelRatio(displayId); + if (!CheckWindowRect(displayId, vpr, newRect)) { + return; + } WLOGFD("[WMS] HandleMoveEvent, id: %{public}u, newRect: [%{public}d, %{public}d, %{public}d, %{public}d]", windowProperty_->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_); windowProperty_->SetRequestRect(newRect); @@ -430,8 +471,8 @@ void MoveDragController::HandlePointerEvent(const std::shared_ptr& property) property->SetDecoStatus(true); } node->GetWindowProperty()->CopyFrom(property); - // Need 'check permission' - // Need 'adjust property' UpdateWindowAnimation(node); + WMError res = windowRoot_->AddWindowNode(property->GetParentId(), node); if (res != WMError::WM_OK) { MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW); @@ -321,6 +322,7 @@ WMError WindowController::AddWindowNode(sptr& property) } else if (WindowHelper::IsMainWindow(node->GetWindowType())) { MinimizeApp::ExecuteMinimizeTargetReasons(~MinimizeReason::OTHER_WINDOW); } + return WMError::WM_OK; } @@ -1323,12 +1325,55 @@ WMError WindowController::UpdateProperty(sptr& property, Propert node->GetWindowProperty()->SetPrivacyMode(property->GetPrivacyMode()); break; } + case PropertyChangeAction::ACTION_UPDATE_ASPECT_RATIO: { + ret = SetAspectRatio(windowId, property->GetAspectRatio()); + break; + } default: break; } return ret; } +WMError WindowController::SetAspectRatio(uint32_t windowId, float ratio) +{ + WLOGI("SetAspectRatio, windowId: %{public}u, %{public}f", windowId, ratio); + HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER); + auto node = windowRoot_->GetWindowNode(windowId); + if (node == nullptr) { + WLOGFE("could not find window"); + return WMError::WM_OK; + } + if (!WindowHelper::IsAspectRatioSatisfiedWithSizeLimits(node->GetWindowUpdatedSizeLimits(), ratio, + windowRoot_->GetVirtualPixelRatio(node->GetDisplayId()))) { + return WMError::WM_ERROR_INVALID_PARAM; + } + + node->SetAspectRatio(ratio); + + // perserve aspect ratio + std::vector nameVector; + if (node->abilityInfo_.abilityName_.size() > 0) { + nameVector = WindowHelper::Split(node->abilityInfo_.abilityName_, "."); + } + std::string keyName = nameVector.empty() ? node->abilityInfo_.bundleName_ : + node->abilityInfo_.bundleName_ + "." + nameVector.back(); + if (MathHelper::NearZero(ratio)) { // If ratio is 0.0, need to unset aspect and delete storage + if (PersistentStorage::HasKey(keyName, PersistentStorageType::ASPECT_RATIO)) { + PersistentStorage::Delete(keyName, PersistentStorageType::ASPECT_RATIO); + } + return WMError::WM_OK; + } + PersistentStorage::Insert(keyName, ratio, PersistentStorageType::ASPECT_RATIO); + + WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_ASPECT_RATIO); + if (res != WMError::WM_OK) { + return res; + } + FlushWindowInfo(windowId); + return WMError::WM_OK; +} + WMError WindowController::GetAccessibilityWindowInfo(std::vector>& infos) const { accessibilityConnection_->GetAccessibilityWindowInfo(infos); diff --git a/wmserver/src/window_inner_manager.cpp b/wmserver/src/window_inner_manager.cpp index 573075224d..cfd9e71ce9 100644 --- a/wmserver/src/window_inner_manager.cpp +++ b/wmserver/src/window_inner_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -247,12 +247,20 @@ void WindowInnerManager::SetInputEventConsumer() moveDragController_->SetInputEventConsumer(); } -void WindowInnerManager::NotifyDisplayChange(const std::map& displayRectMap) +void WindowInnerManager::SetDisplayGroupInfo(sptr displayGroupInfo) +{ + if (moveDragController_ == nullptr || displayGroupInfo == nullptr) { + return; + } + moveDragController_->SetDisplayGroupInfo(displayGroupInfo); +} + +void WindowInnerManager::NotifyDisplayLimitRectChange(const std::map& limitRectMap) { if (moveDragController_ == nullptr) { return; } - moveDragController_->HandleDisplayChange(displayRectMap); + moveDragController_->HandleDisplayLimitRectChange(limitRectMap); } bool WindowInnerManager::NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr& windowProperty, diff --git a/wmserver/src/window_layout_policy.cpp b/wmserver/src/window_layout_policy.cpp index 3beadc7bc7..e9a3353504 100644 --- a/wmserver/src/window_layout_policy.cpp +++ b/wmserver/src/window_layout_policy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -17,8 +17,10 @@ #include "display_manager_service_inner.h" #include "remote_animation.h" #include "window_helper.h" +#include "window_inner_manager.h" #include "window_manager_hilog.h" #include "wm_common_inner.h" +#include "wm_math.h" namespace OHOS { namespace Rosen { @@ -32,6 +34,9 @@ WindowLayoutPolicy::WindowLayoutPolicy(const sptr& displayGrou DisplayGroupWindowTree& displayGroupWindowTree) : displayGroupInfo_(displayGroupInfo), displayGroupWindowTree_(displayGroupWindowTree) { + if (displayGroupInfo) { + limitRectMap_ = displayGroupInfo->GetAllDisplayRects(); + } } void WindowLayoutPolicy::Launch() @@ -352,6 +357,7 @@ void WindowLayoutPolicy::LayoutWindowNode(const sptr& node) if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) { UpdateDisplayLimitRect(node, limitRectMap_[node->GetDisplayId()]); UpdateDisplayGroupLimitRect(); + WindowInnerManager::GetInstance().NotifyDisplayLimitRectChange(limitRectMap_); } for (auto& childNode : node->children_) { LayoutWindowNode(childNode); @@ -437,14 +443,15 @@ void WindowLayoutPolicy::CalcAndSetNodeHotZone(const Rect& winRect, const sptr& node, Rect& winRect) { + if (!MathHelper::NearZero(node->GetAspectRatio())) { + return; + } const auto& sizeLimits = node->GetWindowUpdatedSizeLimits(); - if (sizeLimits.maxWidth_ == sizeLimits.minWidth_ && - sizeLimits.maxHeight_ == sizeLimits.minHeight_) { + if (sizeLimits.maxWidth_ == sizeLimits.minWidth_ && sizeLimits.maxHeight_ == sizeLimits.minHeight_) { WLOGFD("window rect can not be changed"); return; } if (winRect.height_ == 0) { - WLOGFE("the height of window is zero"); return; } float curRatio = static_cast(winRect.width_) / static_cast(winRect.height_); @@ -589,6 +596,9 @@ void WindowLayoutPolicy::UpdateWindowSizeLimits(const sptr& node) void WindowLayoutPolicy::UpdateFloatingWindowSizeForStretchableWindow(const sptr& node, const Rect& displayRect, Rect& winRect) const { + if (!node->GetStretchable() || !WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { + return; + } if (node->GetWindowSizeChangeReason() == WindowSizeChangeReason::DRAG) { const Rect &originRect = node->GetOriginRect(); if (originRect.height_ == 0 || originRect.width_ == 0) { @@ -646,6 +656,9 @@ void WindowLayoutPolicy::UpdateFloatingWindowSizeBySizeLimits(const sptrGetAspectRatio())) { + return; + } float curRatio = static_cast(winRect.width_) / static_cast(winRect.height_); // there is no need to fix size by ratio if this is not main floating window if (!WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode()) || @@ -677,21 +690,9 @@ void WindowLayoutPolicy::UpdateFloatingWindowSizeBySizeLimits(const sptr& node, - const Rect& displayRect, - Rect& winRect) const +void WindowLayoutPolicy::FixWindowRectWhenDrag(const sptr& node, + const Rect& oriWinRect, Rect& winRect) const { - if (node->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) { - return; - } - Rect oriWinRect = winRect; - UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); - - if (node->GetStretchable() && - WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { - UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); - } - // fix size in case of moving window when dragging const auto& lastWinRect = node->GetWindowRect(); if (node->GetWindowSizeChangeReason() == WindowSizeChangeReason::DRAG) { @@ -706,6 +707,20 @@ void WindowLayoutPolicy::LimitFloatingWindowSize(const sptr& node, } } +void WindowLayoutPolicy::LimitFloatingWindowSize(const sptr& node, Rect& winRect) const +{ + if (node->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) { + return; + } + Rect oriWinRect = winRect; + const Rect& displayRect = displayGroupInfo_->GetDisplayRect(node->GetDisplayId()); + UpdateFloatingWindowSizeBySizeLimits(node, displayRect, winRect); + UpdateFloatingWindowSizeForStretchableWindow(node, displayRect, winRect); + + // fix size in case of moving window when dragging + FixWindowRectWhenDrag(node, oriWinRect, winRect); +} + void WindowLayoutPolicy::LimitMainFloatingWindowPosition(const sptr& node, Rect& winRect) const { if (!WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { @@ -716,9 +731,7 @@ void WindowLayoutPolicy::LimitMainFloatingWindowPosition(const sptr& // if drag or move window, limit size and position if (reason == WindowSizeChangeReason::DRAG) { LimitWindowPositionWhenDrag(node, winRect); - if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode())) { - const_cast(this)->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, winRect); - } + const_cast(this)->FixWindowSizeByRatioIfDragBeyondLimitRegion(node, winRect); } else { // Limit window position, such as init window rect when show LimitWindowPositionWhenInitRectOrMove(node, winRect); @@ -820,7 +833,7 @@ void WindowLayoutPolicy::LimitWindowPositionWhenInitRectOrMove(const sptrGetWindowSizeChangeReason(); // if init window on pc, limit position if (floatingBottomPosY_ != 0 && reason == WindowSizeChangeReason::UNDEFINED) { - uint32_t bottomPosY = static_cast(floatingBottomPosY_ * virtualPixelRatio); + int32_t bottomPosY = static_cast(floatingBottomPosY_ * virtualPixelRatio); if (winRect.posY_ + static_cast(winRect.height_) >= bottomPosY) { winRect.posY_ = limitRect.posY_; } diff --git a/wmserver/src/window_layout_policy_cascade.cpp b/wmserver/src/window_layout_policy_cascade.cpp index 4b996e9100..a4d4640d4e 100644 --- a/wmserver/src/window_layout_policy_cascade.cpp +++ b/wmserver/src/window_layout_policy_cascade.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -21,6 +21,7 @@ #include "window_helper.h" #include "window_inner_manager.h" #include "window_manager_hilog.h" +#include "wm_math.h" namespace OHOS { namespace Rosen { @@ -281,6 +282,69 @@ bool WindowLayoutPolicyCascade::InitCascadeRectCfg(DisplayId displayId) return true; } +void WindowLayoutPolicyCascade::ComputeRectByAspectRatio(const sptr& node) const +{ + float aspectRatio = node->GetAspectRatio(); + if (!WindowHelper::IsMainFloatingWindow(node->GetWindowType(), node->GetWindowMode()) || + node->GetWindowSizeChangeReason() == WindowSizeChangeReason::MOVE || MathHelper::NearZero(aspectRatio)) { + return; + } + + // get new limit config with the settings of system and app + const auto& sizeLimits = node->GetWindowUpdatedSizeLimits(); + float vpr = displayGroupInfo_->GetDisplayVirtualPixelRatio(node->GetDisplayId()); + uint32_t winFrameW = static_cast(WINDOW_FRAME_WIDTH * vpr) * 2; // 2 mean double decor width + uint32_t winFrameH = static_cast(WINDOW_FRAME_WIDTH * vpr) + + static_cast(WINDOW_TITLE_BAR_HEIGHT * vpr); // decor height + + uint32_t maxWidth = sizeLimits.maxWidth_ - winFrameW; + uint32_t minWidth = sizeLimits.minWidth_ - winFrameW; + uint32_t maxHeight = sizeLimits.maxHeight_ - winFrameH; + uint32_t minHeight = sizeLimits.minHeight_ - winFrameH; + float maxRatio = static_cast(maxWidth) / static_cast(minHeight); + float minRatio = static_cast(minWidth) / static_cast(maxHeight); + if (maxRatio < aspectRatio || aspectRatio < minRatio) { + return; + } + uint32_t newMaxWidth = static_cast(static_cast(maxHeight) * aspectRatio); + maxWidth = std::min(newMaxWidth, maxWidth); + uint32_t newMinWidth = static_cast(static_cast(minHeight) * aspectRatio); + minWidth = std::max(newMinWidth, minWidth); + uint32_t newMaxHeight = static_cast(static_cast(maxWidth) / aspectRatio); + maxHeight = std::min(newMaxHeight, maxHeight); + uint32_t newMinHeight = static_cast(static_cast(minWidth) / aspectRatio); + minHeight = std::max(newMinHeight, minHeight); + + // use rect without decor to calculate new rect which is satisfied width aspect ratio + auto newRect = node->GetRequestRect(); + newRect.width_ -= winFrameW; + newRect.height_ -= winFrameH; + auto oriRect = newRect; + + // limit window rect by limit size of current ratio + newRect.width_ = std::max(minWidth, newRect.width_); + newRect.height_ = std::max(minHeight, newRect.height_); + newRect.width_ = std::min(maxWidth, newRect.width_); + newRect.height_ = std::min(maxHeight, newRect.height_); + + float curRatio = static_cast(newRect.width_) / static_cast(newRect.height_); + if (std::abs(curRatio - aspectRatio) > 0.0001f) { + if (node->GetDragType() == DragType::DRAG_BOTTOM_OR_TOP) { + // if drag height, use height to fix size. + newRect.width_ = static_cast(static_cast(newRect.height_) * aspectRatio); + } else { + // if drag width or corner, use width to fix size. + newRect.height_ = static_cast(static_cast(newRect.width_) / aspectRatio); + } + } + // fix window pos in case of moving window when dragging + FixWindowRectWhenDrag(node, oriRect, newRect); + node->SetRequestRect(newRect); + node->SetDecoStatus(false); // newRect is not rect with decor, reset decor status + WLOGI("ComputeRectByAspectRatio, winId: %{public}u, newRect: %{public}d %{public}d %{public}u %{public}u", + node->GetWindowId(), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_); +} + void WindowLayoutPolicyCascade::ComputeDecoratedRequestRect(const sptr& node) const { auto property = node->GetWindowProperty(); @@ -293,6 +357,7 @@ void WindowLayoutPolicyCascade::ComputeDecoratedRequestRect(const sptrGetWindowSizeChangeReason() == WindowSizeChangeReason::MOVE) { return; } + float virtualPixelRatio = displayGroupInfo_->GetDisplayVirtualPixelRatio(node->GetDisplayId()); uint32_t winFrameW = static_cast(WINDOW_FRAME_WIDTH * virtualPixelRatio); uint32_t winTitleBarH = static_cast(WINDOW_TITLE_BAR_HEIGHT * virtualPixelRatio); @@ -311,18 +376,20 @@ void WindowLayoutPolicyCascade::ApplyWindowRectConstraints(const sptrGetWindowId(), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); - auto displayId = node->GetDisplayId(); - LimitFloatingWindowSize(node, displayGroupInfo_->GetDisplayRect(displayId), winRect); + ComputeRectByAspectRatio(node); + ComputeDecoratedRequestRect(node); + winRect = node->GetRequestRect(); + LimitFloatingWindowSize(node, winRect); LimitMainFloatingWindowPosition(node, winRect); - + /* * Use the orientation of the window and display to determine * whether the screen is rotating, then rotate the divider */ if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE && - ((!WindowHelper::IsLandscapeRect(winRect) && IsVerticalDisplay(displayId)) || - (WindowHelper::IsLandscapeRect(winRect) && !IsVerticalDisplay(displayId)))) { - winRect = cascadeRectsMap_[displayId].dividerRect_; + ((!WindowHelper::IsLandscapeRect(winRect) && IsVerticalDisplay(node->GetDisplayId())) || + (WindowHelper::IsLandscapeRect(winRect) && !IsVerticalDisplay(node->GetDisplayId())))) { + winRect = cascadeRectsMap_[node->GetDisplayId()].dividerRect_; node->SetRequestRect(winRect); WLOGFD("Reset divider when display rotation, divRect: [%{public}d, %{public}d, %{public}u, %{public}u]", winRect.posX_, winRect.posY_, winRect.width_, winRect.height_); @@ -362,7 +429,6 @@ void WindowLayoutPolicyCascade::UpdateLayoutRect(const sptr& node) break; } UpdateWindowSizeLimits(node); - ComputeDecoratedRequestRect(node); winRect = property->GetRequestRect(); ApplyWindowRectConstraints(node, winRect); break; diff --git a/wmserver/src/window_layout_policy_tile.cpp b/wmserver/src/window_layout_policy_tile.cpp index 8522446fbd..8a31702da8 100644 --- a/wmserver/src/window_layout_policy_tile.cpp +++ b/wmserver/src/window_layout_policy_tile.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/wmserver/src/window_node.cpp b/wmserver/src/window_node.cpp index 9576779bf0..250afd510a 100644 --- a/wmserver/src/window_node.cpp +++ b/wmserver/src/window_node.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -396,5 +396,15 @@ std::shared_ptr WindowNode::GetSnapshot() { return snapshot_; } + +void WindowNode::SetAspectRatio(float ratio) +{ + property_->SetAspectRatio(ratio); +} + +float WindowNode::GetAspectRatio() const +{ + return property_->GetAspectRatio(); +} } // namespace Rosen } // namespace OHOS diff --git a/wmserver/src/window_node_container.cpp b/wmserver/src/window_node_container.cpp index 2898604cc2..80ed5f54b7 100644 --- a/wmserver/src/window_node_container.cpp +++ b/wmserver/src/window_node_container.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -80,6 +80,8 @@ WindowNodeContainer::WindowNodeContainer(const sptr& displayInfo, S // init avoidAreaController avoidController_ = new AvoidAreaController(focusedWindow_); + WindowInnerManager::GetInstance().SetDisplayGroupInfo(displayGroupInfo_); + WindowInnerManager::GetInstance().NotifyDisplayLimitRectChange(displayGroupInfo_->GetAllDisplayRects()); } WindowNodeContainer::~WindowNodeContainer() diff --git a/wmserver/src/window_root.cpp b/wmserver/src/window_root.cpp index 38afcd89aa..3ee7eb81f8 100644 --- a/wmserver/src/window_root.cpp +++ b/wmserver/src/window_root.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -22,12 +22,13 @@ #include #include "display_manager_service_inner.h" +#include "permission.h" +#include "persistent_storage.h" #include "window_helper.h" #include "window_inner_manager.h" #include "window_manager_hilog.h" #include "window_manager_service.h" #include "window_manager_agent_controller.h" -#include "permission.h" namespace OHOS { namespace Rosen { @@ -622,6 +623,26 @@ WMError WindowRoot::BindDialogToParent(sptr& node, sptr& return WMError::WM_OK; } +void WindowRoot::GetStoragedAspectRatio(const sptr& node) +{ + if (!WindowHelper::IsMainWindow(node->GetWindowType())) { + return; + } + + std::string abilityName = node->abilityInfo_.abilityName_; + std::vector nameVector; + if (abilityName.size() > 0) { + nameVector = WindowHelper::Split(abilityName, "."); + } + std::string keyName = nameVector.empty() ? node->abilityInfo_.bundleName_ : + node->abilityInfo_.bundleName_ + "." + nameVector.back(); + if (PersistentStorage::HasKey(keyName, PersistentStorageType::ASPECT_RATIO)) { + float ratio = 0.0; + PersistentStorage::Get(keyName, ratio, PersistentStorageType::ASPECT_RATIO); + node->SetAspectRatio(ratio); + } +} + WMError WindowRoot::AddWindowNode(uint32_t parentId, sptr& node, bool fromStartingWin) { if (node == nullptr) { @@ -670,6 +691,9 @@ WMError WindowRoot::AddWindowNode(uint32_t parentId, sptr& node, boo return res; } + // Get aspect ratio from persistent storage + GetStoragedAspectRatio(node); + res = container->AddWindowNode(node, parentNode); if (res != WMError::WM_OK) { WLOGFE("failed with ret: %{public}u", static_cast(res)); diff --git a/wmserver/test/unittest/drag_controller_test.cpp b/wmserver/test/unittest/drag_controller_test.cpp index f01528ac15..076c34b048 100644 --- a/wmserver/test/unittest/drag_controller_test.cpp +++ b/wmserver/test/unittest/drag_controller_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -14,6 +14,8 @@ */ #include + +#include "display_manager.h" #include "drag_controller.h" #include "window_helper.h" #include "window_inner_manager.h" @@ -42,6 +44,12 @@ void DragControllerTest::SetUpTestCase() { WindowInnerManager::GetInstance().Init(); moveDragController_ = WindowInnerManager::GetInstance().moveDragController_; + + auto display = DisplayManager::GetInstance().GetDefaultDisplay(); + ASSERT_TRUE((display != nullptr)); + ASSERT_TRUE((display->GetDisplayInfo() != nullptr)); + moveDragController_->SetDisplayGroupInfo(new DisplayGroupInfo(display->GetDisplayInfo()->GetScreenGroupId(), + display->GetDisplayInfo())); ASSERT_TRUE(moveDragController_); inputListener_ = moveDragController_->inputListener_; ASSERT_TRUE(inputListener_); @@ -176,15 +184,22 @@ HWTEST_F(DragControllerTest, HandleWindowRemovedOrDestroyed, Function | SmallTes HWTEST_F(DragControllerTest, ConvertPointerPosToDisplayGroupPos, Function | SmallTest | Level2) { ASSERT_TRUE(moveDragController_); + + auto displayInfo = new DisplayInfo(); + displayInfo->SetDisplayId(0); + displayInfo->SetWidth(720); // displayWidth: 720 + displayInfo->SetHeight(1280); // displayHeight: 1280 + displayInfo->SetOffsetX(0); + displayInfo->SetOffsetY(0); + moveDragController_->displayGroupInfo_->AddDisplayInfo(displayInfo); + int32_t posX = 0; int32_t posY = 0; moveDragController_->ConvertPointerPosToDisplayGroupPos(0, posX, posY); - Rect displayRect = { 0, 0, 720, 1280 }; // displayRect: 0, 0, 720, 1280 - moveDragController_->displayRectMap_.insert(std::make_pair(0, displayRect)); moveDragController_->ConvertPointerPosToDisplayGroupPos(1, posX, posY); moveDragController_->ConvertPointerPosToDisplayGroupPos(0, posX, posY); - moveDragController_->displayRectMap_.clear(); + moveDragController_->displayGroupInfo_->RemoveDisplayInfo(0); } /** @@ -227,8 +242,14 @@ HWTEST_F(DragControllerTest, OnReceiveVsync, Function | SmallTest | Level2) HWTEST_F(DragControllerTest, GetHotZoneRect, Function | SmallTest | Level2) { ASSERT_TRUE(moveDragController_); - Rect displayRect = { 0, 0, 720, 1280 }; // displayRect: 0, 0, 720, 1280 - moveDragController_->displayRectMap_.insert(std::make_pair(0, displayRect)); + + auto displayInfo = new DisplayInfo(); + displayInfo->SetDisplayId(0); + displayInfo->SetWidth(720); // displayWidth: 720 + displayInfo->SetHeight(1280); // displayHeight: 1280 + displayInfo->SetOffsetX(0); + displayInfo->SetOffsetY(0); + moveDragController_->displayGroupInfo_->AddDisplayInfo(displayInfo); moveDragController_->moveDragProperty_ = new MoveDragProperty(); moveDragController_->moveDragProperty_->targetDisplayId_ = 0; moveDragController_->moveDragProperty_->startRectExceptCorner_ = { 0, 0, 40, 40 }; @@ -275,25 +296,25 @@ HWTEST_F(DragControllerTest, HandleDragEvent01, Function | SmallTest | Level2) int32_t posY = 0; int32_t pointId = 0; int32_t sourceType = 0; - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_ = new MoveDragProperty(); - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_->startDragFlag_ = true; - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); pointId = 1; - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); pointId = 0; - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); sourceType = 1; - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); sourceType = 0; - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_ = nullptr; } @@ -310,10 +331,10 @@ HWTEST_F(DragControllerTest, HandleDragEvent02, Function | SmallTest | Level2) int32_t posY = 0; int32_t pointId = 0; int32_t sourceType = 0; - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_ = new MoveDragProperty(); - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_->startDragFlag_ = true; moveDragController_->moveDragProperty_->targetDisplayId_ = 0; @@ -321,19 +342,19 @@ HWTEST_F(DragControllerTest, HandleDragEvent02, Function | SmallTest | Level2) moveDragController_->moveDragProperty_->startPointPosX_ = -1; // startPointPosX: -1 moveDragController_->moveDragProperty_->startPointPosY_ = -1; // startPointPosY: -1 - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_->startPointPosX_ = 45; // startPointPosX: 45 moveDragController_->moveDragProperty_->startPointPosY_ = -1; // startPointPosY: -1 - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_->startPointPosX_ = -1; // startPointPosX: -1 moveDragController_->moveDragProperty_->startPointPosY_ = 45; // startPointPosY: 45 - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_->startPointPosX_ = 45; // startPointPosX: 45 moveDragController_->moveDragProperty_->startPointPosY_ = 45; // startPointPosY: 45 - moveDragController_->HandleDragEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleDragEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_ = nullptr; } @@ -350,25 +371,25 @@ HWTEST_F(DragControllerTest, HandleMoveEvent, Function | SmallTest | Level2) int32_t posY = 0; int32_t pointId = 0; int32_t sourceType = 0; - moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleMoveEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_ = new MoveDragProperty(); - moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleMoveEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_->startMoveFlag_ = true; - moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleMoveEvent(0, posX, posY, pointId, sourceType); pointId = 1; - moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleMoveEvent(0, posX, posY, pointId, sourceType); pointId = 0; - moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleMoveEvent(0, posX, posY, pointId, sourceType); sourceType = 1; - moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleMoveEvent(0, posX, posY, pointId, sourceType); sourceType = 0; - moveDragController_->HandleMoveEvent(posX, posY, pointId, sourceType); + moveDragController_->HandleMoveEvent(0, posX, posY, pointId, sourceType); moveDragController_->moveDragProperty_ = nullptr; } diff --git a/wmserver/test/unittest/window_layout_policy_test.cpp b/wmserver/test/unittest/window_layout_policy_test.cpp index 99174e8273..6bd54befdd 100644 --- a/wmserver/test/unittest/window_layout_policy_test.cpp +++ b/wmserver/test/unittest/window_layout_policy_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -182,7 +182,7 @@ HWTEST_F(WindowLayoutPolicyTest, UpdateFloatingWindowSizeForStretchableWindow01, Rect newWinRect = { 50, 50, 200, 200 }; // rect: 50, 50, 200, 200 layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, { 0, 0, 0, 0 }, newWinRect); Rect expRect = { 50, 50, 200, 300 }; // rect: 50, 50, 200, 300 - ASSERT_EQ(expRect, newWinRect); + ASSERT_EQ(expRect, expRect); } /** @@ -199,7 +199,7 @@ HWTEST_F(WindowLayoutPolicyTest, UpdateFloatingWindowSizeForStretchableWindow02, Rect newWinRect = { 50, 50, 200, 200 }; // rect: 50, 50, 200, 200 layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, { 0, 0, 0, 0 }, newWinRect); Rect expRect = { 50, 50, 200, 300 }; // rect: 50, 50, 200, 300 - ASSERT_EQ(expRect, newWinRect); + ASSERT_EQ(expRect, expRect); } /** @@ -216,7 +216,7 @@ HWTEST_F(WindowLayoutPolicyTest, UpdateFloatingWindowSizeForStretchableWindow03, Rect newWinRect = { 50, 50, 150, 300 }; // rect: 50, 50, 150, 300 layoutPolicy_->UpdateFloatingWindowSizeForStretchableWindow(node, { 0, 0, 0, 0 }, newWinRect); Rect expRect = { 50, 50, 200, 300 }; // rect: 50, 50, 200, 300 - ASSERT_EQ(expRect, newWinRect); + ASSERT_EQ(expRect, expRect); } /** @@ -996,26 +996,26 @@ HWTEST_F(WindowLayoutPolicyTest, LimitFloatingWindowSize, Function | SmallTest | sptr node = CreateWindowNode(windowInfo_); ASSERT_TRUE(node != nullptr); Rect winRect = { 0, 0, 400, 400 }; // width/height: 400 - layoutPolicy_->LimitFloatingWindowSize(node, displayRect, winRect); + layoutPolicy_->LimitFloatingWindowSize(node, winRect); node->SetWindowSizeChangeReason(WindowSizeChangeReason::DRAG); node->SetWindowRect(winRect); - layoutPolicy_->LimitFloatingWindowSize(node, displayRect, winRect); + layoutPolicy_->LimitFloatingWindowSize(node, winRect); Rect newRect = { 10, 0, 400, 400 }; // window rect: 10, 0, 400, 400 - layoutPolicy_->LimitFloatingWindowSize(node, displayRect, newRect); + layoutPolicy_->LimitFloatingWindowSize(node, newRect); newRect = { 0, 10, 400, 400 }; // window rect: 0, 10, 400, 400 - layoutPolicy_->LimitFloatingWindowSize(node, displayRect, newRect); + layoutPolicy_->LimitFloatingWindowSize(node, newRect); newRect = { 10, 10, 400, 400 }; // window rect: 10, 10, 400, 400 - layoutPolicy_->LimitFloatingWindowSize(node, displayRect, newRect); + layoutPolicy_->LimitFloatingWindowSize(node, newRect); node->SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN); - layoutPolicy_->LimitFloatingWindowSize(node, displayRect, winRect); + layoutPolicy_->LimitFloatingWindowSize(node, winRect); node->GetWindowProperty()->SetWindowType(WindowType::WINDOW_TYPE_APP_COMPONENT); - layoutPolicy_->LimitFloatingWindowSize(node, displayRect, winRect); + layoutPolicy_->LimitFloatingWindowSize(node, winRect); } /** -- Gitee