* 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 "window_scene_session_impl.h"
#include <chrono>
#include <limits>
#include <ability_manager_client.h>
#include <algorithm>
#include <modifier/rs_property.h>
#include <modifier_ng/appearance/rs_behind_window_filter_modifier.h>
#include <parameters.h>
#include <sstream>
#include <string>
#include <transaction/rs_transaction.h>
#include <hitrace_meter.h>
#include <hisysevent.h>
#include <application_context.h>
#include "color_parser.h"
#include "common/include/fold_screen_state_internel.h"
#include "common/include/fold_screen_common.h"
#include "configuration.h"
#include "display_manager.h"
#include "display_manager_adapter.h"
#include "dm_common.h"
#include "extension/extension_business_info.h"
#include "fold_screen_controller/super_fold_state_manager.h"
#include "input_transfer_station.h"
#include "perform_reporter.h"
#include "rate_limited_logger.h"
#include "rs_adapter.h"
#include "session_helper.h"
#include "session_permission.h"
#include "session/container/include/window_event_channel.h"
#include "session_manager/include/session_manager.h"
#include "singleton_container.h"
#include "sys_cap_util.h"
#include "window_adapter.h"
#include "window_helper.h"
#include "window_inspector.h"
#include "window_manager_hilog.h"
#include "window_prepare_terminate.h"
#include "wm_common.h"
#include "wm_common_inner.h"
#include "wm_math.h"
#include "session_manager_agent_controller.h"
#include <transaction/rs_interfaces.h>
#include "surface_capture_future.h"
#include "pattern_detach_callback.h"
#include "picture_in_picture_manager.h"
#include "window_session_impl.h"
#include "sys_cap_util.h"
namespace OHOS {
namespace Rosen {
union WSColorParam {
#if defined(BIG_ENDIANNESS) && BIG_ENDIANNESS
struct {
uint8_t alpha;
uint8_t red;
uint8_t green;
uint8_t blue;
} argb;
#else
struct {
uint8_t blue;
uint8_t green;
uint8_t red;
uint8_t alpha;
} argb;
#endif
uint32_t value;
};
#define CHECK_HOST_SESSION_RETURN_IF_NULL(hostSession) \
do { \
if ((hostSession) == nullptr) { \
TLOGE(WmsLogTag::DEFAULT, "hostSession is null"); \
return; \
} \
} while (false)
#define CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, ret) \
do { \
if ((hostSession) == nullptr) { \
TLOGE(WmsLogTag::DEFAULT, "hostSession is null"); \
return ret; \
} \
} while (false)
namespace {
constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowSceneSessionImpl"};
constexpr int32_t WINDOW_DETACH_TIMEOUT = 1500;
constexpr int32_t WINDOW_LAYOUT_TIMEOUT = 30;
constexpr int32_t WINDOW_PAGE_ROTATION_TIMEOUT = 2000;
const std::string PARAM_DUMP_HELP = "-h";
constexpr float MIN_GRAY_SCALE = 0.0f;
constexpr float MAX_GRAY_SCALE = 1.0f;
constexpr int32_t DISPLAY_ID_C = 999;
constexpr int32_t MAX_POINTERS = 16;
constexpr int32_t TOUCH_SLOP_RATIO = 25;
constexpr int32_t COMBINED_COMPATIBLE_CONFIG_SIZE = 2;
const std::string WATERFALL_WINDOW_EVENT = "scb_waterfall_window_event";
const std::string BACK_WINDOW_EVENT = "scb_back_window_event";
const std::string COMPATIBLE_MAX_WINDOW_EVENT = "win_compatible_max_event";
const std::string COMPATIBLE_RECOVER_WINDOW_EVENT = "win_compatible_recover_event";
const std::string NAME_LANDSCAPE_2_3_CLICK = "win_change_to_2_3_landscape";
const std::string NAME_LANDSCAPE_1_1_CLICK = "win_change_to_1_1_landscape";
const std::string NAME_LANDSCAPE_18_9_CLICK = "win_change_to_18_9_landscape";
const std::string NAME_LANDSCAPE_SPLIT_CLICK = "win_change_to_split_landscape";
const std::string NAME_DEFAULT_LANDSCAPE_CLICK = "win_change_to_default_landscape";
const std::string EVENT_NAME_HOVER = "win_hover_event";
const std::string EVENT_NAME_MINIMIZE = "win_minimize_event";
const std::string EVENT_NAME_CLOSE = "win_close_event";
const std::string MOUSE_HOVER = "mouseHover";
const std::string TOUCH_HOVER = "touchHover";
const std::string EXIT_HOVER = "exitHover";
const std::string IS_ANCO_SUPPORT_FREE_WINDOW = "hmos_fusion.container.pc.freemode.captionbar";
constexpr char SCENE_BOARD_UE_DOMAIN[] = "SCENE_BOARD_UE";
constexpr char HOVER_MAXIMIZE_MENU[] = "PC_HOVER_MAXIMIZE_MENU";
constexpr char CLICK_TITLE_MINIMIZE[] = "PC_CLICK_TITLE_MINIMIZE";
constexpr char CLICK_TITLE_CLOSE[] = "PC_CLICK_TITLE_CLOSE";
constexpr char COMPATIBLE_TITLE_OPERATE[] = "PC_COMPATIBLE_TITLE_OPERATE";
const std::unordered_set<WindowType> INVALID_SYSTEM_WINDOW_TYPE = {
WindowType::WINDOW_TYPE_NEGATIVE_SCREEN,
WindowType::WINDOW_TYPE_THEME_EDITOR,
WindowType::WINDOW_TYPE_NAVIGATION_INDICATOR,
WindowType::WINDOW_TYPE_SCENE_BOARD,
WindowType::WINDOW_TYPE_KEYBOARD_PANEL,
WindowType::WINDOW_TYPE_APP_LAUNCHING,
WindowType::WINDOW_TYPE_INCOMING_CALL,
WindowType::WINDOW_TYPE_BOOT_ANIMATION,
WindowType::WINDOW_TYPE_FREEZE_DISPLAY,
WindowType::WINDOW_TYPE_PLACEHOLDER
};
const std::unordered_set<WindowType> INVALID_SCB_WINDOW_TYPE = {
WindowType::WINDOW_TYPE_WALLPAPER,
WindowType::WINDOW_TYPE_DESKTOP,
WindowType::WINDOW_TYPE_DOCK_SLICE,
WindowType::WINDOW_TYPE_STATUS_BAR,
WindowType::WINDOW_TYPE_KEYGUARD,
WindowType::WINDOW_TYPE_NAVIGATION_BAR,
WindowType::WINDOW_TYPE_LAUNCHER_RECENT,
WindowType::WINDOW_TYPE_LAUNCHER_DOCK
};
constexpr float INVALID_DEFAULT_DENSITY = 1.0f;
constexpr uint32_t FORCE_LIMIT_MIN_FLOATING_WIDTH = 40;
constexpr uint32_t FORCE_LIMIT_MIN_FLOATING_HEIGHT = 40;
constexpr int32_t API_VERSION_18 = 18;
constexpr uint32_t REASON_MAXIMIZE_MODE_CHANGE = 1;
constexpr int32_t SIDEBAR_BLUR_ANIMATION_DURATION = 150;
constexpr float NAG_NUM = -1.0f;
bool IsValueInRange(double value, double lowerBound, double upperBound)
{
return !MathHelper::GreatNotEqual(lowerBound, value) &&
!MathHelper::GreatNotEqual(value, upperBound);
}
void RecalculatePxLimitsByVp(const WindowLimits& RefreshLimitsVp, WindowLimits& RefreshLimitsPx, float vpr)
{
RefreshLimitsPx.maxWidth_ = static_cast<uint32_t>(RefreshLimitsVp.maxWidth_ * vpr);
RefreshLimitsPx.maxHeight_ = static_cast<uint32_t>(RefreshLimitsVp.maxHeight_ * vpr);
RefreshLimitsPx.minWidth_ = static_cast<uint32_t>(RefreshLimitsVp.minWidth_ * vpr);
RefreshLimitsPx.minHeight_ = static_cast<uint32_t>(RefreshLimitsVp.minHeight_ * vpr);
}
void RecalculateVpLimitsByPx(const WindowLimits& limits, WindowLimits& limitsVP, float vpr)
{
if (MathHelper::NearZero(vpr)) {
TLOGE(WmsLogTag::WMS_LAYOUT, "vpr is zero");
return;
}
limitsVP.maxWidth_ = static_cast<uint32_t>(std::round(limits.maxWidth_ / vpr));
limitsVP.maxHeight_ = static_cast<uint32_t>(std::round(limits.maxHeight_ / vpr));
limitsVP.minWidth_ = static_cast<uint32_t>(std::round(limits.minWidth_ / vpr));
limitsVP.minHeight_ = static_cast<uint32_t>(std::round(limits.minHeight_ / vpr));
}
uint32_t SafelyRoundToUint32(double value)
{
return (value > static_cast<double>(UINT32_MAX)) ? UINT32_MAX : std::round(value);
}
void RecalculateLimits(double maxRatio, double minRatio, WindowLimits& limits)
{
if (MathHelper::NearZero(maxRatio) || MathHelper::NearZero(minRatio)) {
TLOGE(WmsLogTag::WMS_LAYOUT, "ratio is zero");
return;
}
const uint32_t newMaxWidth = SafelyRoundToUint32(limits.maxHeight_ * maxRatio);
const uint32_t newMinWidth = SafelyRoundToUint32(limits.minHeight_ * minRatio);
const uint32_t newMaxHeight = MathHelper::NearZero(minRatio) ?
UINT32_MAX : SafelyRoundToUint32(limits.maxWidth_ / minRatio);
const uint32_t newMinHeight = MathHelper::NearZero(maxRatio) ?
UINT32_MAX : SafelyRoundToUint32(limits.minWidth_ / maxRatio);
limits.maxWidth_ = std::min(newMaxWidth, limits.maxWidth_);
limits.minWidth_ = std::max(newMinWidth, limits.minWidth_);
limits.maxHeight_ = std::min(newMaxHeight, limits.maxHeight_);
limits.minHeight_ = std::max(newMinHeight, limits.minHeight_);
}
* @brief Calculate intersection between current limits and attached limits.
* @param currentLimits Current window limits.
* @param attachedLimits Attached window limits.
* @param intersectHeight Whether to intersect height limits.
* @param intersectWidth Whether to intersect width limits.
* @return Intersected limits.
*/
WindowLimits CalculateLimitsIntersection(const WindowLimits& currentLimits,
const WindowLimits& attachedLimits, bool intersectHeight, bool intersectWidth)
{
WindowLimits result = currentLimits;
if (intersectHeight) {
result.minHeight_ = std::max(currentLimits.minHeight_, attachedLimits.minHeight_);
result.maxHeight_ = std::min(currentLimits.maxHeight_, attachedLimits.maxHeight_);
}
if (intersectWidth) {
result.minWidth_ = std::max(currentLimits.minWidth_, attachedLimits.minWidth_);
result.maxWidth_ = std::min(currentLimits.maxWidth_, attachedLimits.maxWidth_);
}
return result;
}
* @brief Check if limits intersection is valid (min <= max).
* @param limits Limits to validate.
* @param checkHeight Whether to check height limits.
* @param checkWidth Whether to check width limits.
* @return true if intersection is valid, false otherwise.
*/
bool IsLimitsIntersectionValid(const WindowLimits& limits, bool checkHeight, bool checkWidth)
{
if (checkWidth && limits.minWidth_ > limits.maxWidth_) {
return false;
}
if (checkHeight && limits.minHeight_ > limits.maxHeight_) {
return false;
}
return true;
}
* @brief Returns candidate if it lies within the inclusive range; otherwise returns fallback.
*
* Performs a range check against [lowerBound, upperBound]. Unlike std::clamp,
* this function does not adjust out-of-range values but instead returns fallback.
*
* @tparam T Type supporting comparison operators.
* @param candidate Value to evaluate.
* @param lowerBound Inclusive lower bound.
* @param upperBound Inclusive upper bound.
* @param fallback Value returned when candidate is out of range.
* @return candidate if within range; otherwise fallback.
*/
template<typename T>
static inline T SafeBoundAssign(T candidate, T lowerBound, T upperBound, T fallback)
{
return (candidate >= lowerBound && candidate <= upperBound) ? candidate : fallback;
}
}
std::mutex WindowSceneSessionImpl::keyboardPanelInfoChangeListenerMutex_;
using WindowSessionImplMap = std::map<std::string, std::pair<int32_t, sptr<WindowSessionImpl>>>;
std::mutex WindowSceneSessionImpl::windowAttachStateChangeListenerMutex_;
std::atomic<bool> WindowSceneSessionImpl::hasSentCombinedCompatibleConfig_ = false;
WindowSceneSessionImpl::WindowSceneSessionImpl(const sptr<WindowOption>& option,
const std::shared_ptr<RSUIContext>& rsUIContext) : WindowSessionImpl(option, rsUIContext)
{
WLOGFI("[WMSCom] Constructor %{public}s", GetWindowName().c_str());
}
WindowSceneSessionImpl::~WindowSceneSessionImpl()
{
WLOGFI("[WMSCom] Destructor %{public}d, %{public}s", GetPersistentId(), GetWindowName().c_str());
}
bool WindowSceneSessionImpl::IsValidSystemWindowType(const WindowType& type)
{
if (INVALID_SYSTEM_WINDOW_TYPE.find(type) != INVALID_SYSTEM_WINDOW_TYPE.end()) {
TLOGI(WmsLogTag::WMS_SYSTEM, "Invalid type: %{public}u", type);
return false;
}
TLOGI(WmsLogTag::WMS_SYSTEM, "Valid type: %{public}u", type);
return true;
}
sptr<WindowSessionImpl> WindowSceneSessionImpl::FindParentSessionByParentId(uint32_t parentId)
{
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
for (const auto& [_, pair] : windowSessionMap_) {
auto& window = pair.second;
if (window && window->GetWindowId() == parentId) {
if (WindowHelper::IsMainWindow(window->GetType()) || WindowHelper::IsSystemWindow(window->GetType())) {
TLOGD(WmsLogTag::WMS_SUB, "Find parent window [%{public}s, %{public}u, %{public}d]",
window->GetProperty()->GetWindowName().c_str(), parentId,
window->GetProperty()->GetPersistentId());
return window;
} else if (WindowHelper::IsSubWindow(window->GetType()) &&
(IsSessionMainWindow(window->GetParentId()) ||
window->GetProperty()->GetIsUIExtFirstSubWindow() ||
window->GetProperty()->GetSubWindowLevel() < MAX_SUB_WINDOW_LEVEL)) {
TLOGD(WmsLogTag::WMS_SUB, "Find parent window [%{public}s, %{public}u, %{public}d]",
window->GetProperty()->GetWindowName().c_str(), parentId,
window->GetProperty()->GetPersistentId());
return window;
}
}
}
TLOGD(WmsLogTag::WMS_SUB, "Can not find parent window, id: %{public}d", parentId);
return nullptr;
}
sptr<WindowSessionImpl> WindowSceneSessionImpl::FindParentMainSession(uint32_t parentId, const SessionMap& sessionMap)
{
if (parentId == INVALID_SESSION_ID) {
TLOGW(WmsLogTag::WMS_SUB, "invalid parent id");
return nullptr;
}
for (const auto& [_, pair] : sessionMap) {
auto& window = pair.second;
if (window && window->GetWindowId() == parentId) {
if (WindowHelper::IsMainWindow(window->GetType()) || window->IsLoosenedWithPcOrFreeMultiMode() ||
(WindowHelper::IsSystemWindow(window->GetType()) && window->GetParentId() == INVALID_SESSION_ID)) {
TLOGD(WmsLogTag::WMS_SUB, "find main session, id:%{public}u", window->GetWindowId());
return window;
}
return FindParentMainSession(window->GetParentId(), sessionMap);
}
}
TLOGW(WmsLogTag::WMS_SUB, "don't find main session, parentId:%{public}u", parentId);
return nullptr;
}
bool WindowSceneSessionImpl::IsSessionMainWindow(uint32_t parentId)
{
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
for (const auto& [_, pair] : windowSessionMap_) {
auto& window = pair.second;
if (window && window->GetWindowId() == parentId && WindowHelper::IsMainWindow(window->GetType())) {
return true;
}
}
return false;
}
void WindowSceneSessionImpl::AddSubWindowMapForExtensionWindow()
{
auto extensionWindow = FindExtensionWindowWithContext();
if (extensionWindow != nullptr) {
auto parentWindowId = extensionWindow->GetPersistentId();
std::lock_guard<std::recursive_mutex> lock(subWindowSessionMutex_);
subWindowSessionMap_[parentWindowId].push_back(this);
} else {
TLOGE(WmsLogTag::WMS_SUB, "name: %{public}s not found parent extension window",
property_->GetWindowName().c_str());
}
}
bool WindowSceneSessionImpl::hasAncestorFloatSession(uint32_t parentId, const SessionMap& sessionMap)
{
if (parentId == INVALID_SESSION_ID) {
TLOGW(WmsLogTag::WMS_SUB, "invalid parent id");
return false;
}
for (const auto& [_, pair] : sessionMap) {
auto& window = pair.second;
if (window && window->GetWindowId() == parentId) {
if (window->GetType() == WindowType::WINDOW_TYPE_FLOAT) {
TLOGD(WmsLogTag::WMS_SUB, "find float session, id:%{public}u", window->GetWindowId());
return true;
} else if (WindowHelper::IsSubWindow(window->GetType())) {
return hasAncestorFloatSession(window->GetParentId(), sessionMap);
}
return false;
}
}
TLOGD(WmsLogTag::WMS_SUB, "don't find float session, parentId:%{public}u", parentId);
return false;
}
WMError WindowSceneSessionImpl::GetParentSessionAndVerify(bool isToast, sptr<WindowSessionImpl>& parentSession)
{
if (isToast) {
auto parentWindow = GetWindowWithId(property_->GetParentId());
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
if (parentWindow && hasAncestorFloatSession(parentWindow->GetWindowId(), windowSessionMap_)) {
TLOGI(WmsLogTag::WMS_SUB, "parentId: %{public}u exist ancestor float window", property_->GetParentId());
parentSession = parentWindow;
} else {
parentSession = FindParentMainSession(property_->GetParentId(), windowSessionMap_);
}
} else {
parentSession = FindParentSessionByParentId(property_->GetParentId());
}
if (parentSession == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "parent of sub window is nullptr, name: %{public}s, type: %{public}d",
property_->GetWindowName().c_str(), GetType());
return WMError::WM_ERROR_NULLPTR;
}
return WindowSceneSessionImpl::VerifySubWindowLevel(isToast, parentSession);
}
WMError WindowSceneSessionImpl::VerifySubWindowLevel(bool isToast, const sptr<WindowSessionImpl>& parentSession)
{
if (parentSession == nullptr) {
TLOGE(WmsLogTag::WMS_SUB, "parent of sub window is nullptr");
return WMError::WM_ERROR_NULLPTR;
}
if (!isToast && !parentSession->GetIsUIExtFirstSubWindow() &&
parentSession->GetProperty()->GetSubWindowLevel() >= 1 &&
!parentSession->IsPcOrFreeMultiWindowCapabilityEnabled()) {
TLOGE(WmsLogTag::WMS_SUB, "device not support");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
return WMError::WM_OK;
}
static void AdjustPropertySessionInfo(const std::shared_ptr<AbilityRuntime::Context>& context, SessionInfo& info)
{
if (!context) {
TLOGE(WmsLogTag::WMS_LIFE, "context is null");
return;
}
info.moduleName_ = context->GetHapModuleInfo() ? context->GetHapModuleInfo()->moduleName : "";
auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
if (abilityContext && abilityContext->GetAbilityInfo()) {
info.abilityName_ = abilityContext->GetAbilityInfo()->name;
info.bundleName_ = abilityContext->GetAbilityInfo()->bundleName;
} else {
info.bundleName_ = context->GetBundleName();
}
}
WMError WindowSceneSessionImpl::CreateAndConnectSpecificSession()
{
sptr<ISessionStage> iSessionStage(this);
sptr<IWindowEventChannel> eventChannel = sptr<WindowEventChannel>::MakeSptr(iSessionStage);
auto persistentId = INVALID_SESSION_ID;
sptr<Rosen::ISession> session;
sptr<IRemoteObject> renderSession;
auto context = GetContext();
sptr<IRemoteObject> token = context ? context->GetToken() : nullptr;
if (token) {
property_->SetTokenState(true);
}
AdjustPropertySessionInfo(context, property_->EditSessionInfo());
const WindowType type = GetType();
bool hasToastFlag = property_->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_IS_TOAST);
WMErrorResult result;
if (WindowHelper::IsSubWindow(type) && (property_->GetIsUIExtFirstSubWindow() ||
(property_->GetIsUIExtAnySubWindow() && hasToastFlag))) {
property_->SetParentPersistentId(property_->GetParentId());
SetDefaultDisplayIdIfNeed();
property_->SetIsUIExtensionAbilityProcess(isUIExtensionAbilityProcess_);
result = SingletonContainer::Get<WindowAdapter>().CreateAndConnectSpecificSession(
iSessionStage, eventChannel, nodeId_,
property_, persistentId, session, windowSystemConfig_, renderSession, surfaceNode_, token);
if (!hasToastFlag) {
AddSubWindowMapForExtensionWindow();
}
} else if (WindowHelper::IsSubWindow(type)) {
if (property_->GetIsCrossProcessWindow()) {
CrossProcessWindowInfo crossProcessWindowInfo;
crossProcessWindowInfo.persistentId = property_->GetParentId();
WMError wmError = SingletonContainer::Get<WindowAdapter>()
.GetCrossProcessWindowInfo(crossProcessWindowInfo);
if (wmError != WMError::WM_OK) {
return wmError;
}
property_->SetParentPersistentId(crossProcessWindowInfo.persistentId);
property_->SetDisplayId(crossProcessWindowInfo.displayId);
property_->SetIsPcAppInPad(crossProcessWindowInfo.isPcAppInPad);
property_->SetPcAppInpadCompatibleMode(crossProcessWindowInfo.isPcAppInpadCompatibleMode);
result = SingletonContainer::Get<WindowAdapter>().CreateAndConnectSpecificSession(
iSessionStage, eventChannel,
nodeId_, property_, persistentId, session, windowSystemConfig_, renderSession, surfaceNode_, token);
} else {
sptr<WindowSessionImpl> parentSession = nullptr;
auto ret = WindowSceneSessionImpl::GetParentSessionAndVerify(hasToastFlag, parentSession);
if (ret != WMError::WM_OK) {
return ret;
}
property_->SetDisplayId(parentSession->GetDisplayId());
auto parentWindowId = parentSession->GetPersistentId();
property_->SetParentPersistentId(parentWindowId);
property_->SetIsPcAppInPad(parentSession->GetProperty()->GetIsPcAppInPad());
property_->SetPcAppInpadCompatibleMode(parentSession->GetProperty()->GetPcAppInpadCompatibleMode());
result = SingletonContainer::Get<WindowAdapter>().CreateAndConnectSpecificSession(
iSessionStage, eventChannel,
nodeId_, property_, persistentId, session, windowSystemConfig_, renderSession, surfaceNode_, token);
{
std::lock_guard<std::recursive_mutex> lock(subWindowSessionMutex_);
subWindowSessionMap_[parentWindowId].push_back(this);
}
SetTargetAPIVersion(parentSession->GetTargetAPIVersion());
}
} else {
WMError createSystemWindowRet = CreateSystemWindow(type);
if (createSystemWindowRet != WMError::WM_OK) {
return createSystemWindowRet;
}
auto parentSession = FindParentSessionByParentId(property_->GetParentPersistentId());
if (parentSession != nullptr) {
property_->SetIsPcAppInPad(parentSession->GetProperty()->GetIsPcAppInPad());
}
PreProcessCreate();
result = SingletonContainer::Get<WindowAdapter>().CreateAndConnectSpecificSession(
iSessionStage, eventChannel,
nodeId_, property_, persistentId, session, windowSystemConfig_, renderSession, surfaceNode_, token);
}
property_->SetPersistentId(persistentId);
if (session == nullptr) {
TLOGI(WmsLogTag::WMS_LIFE, "create specific failed, session is nullptr, name: %{public}s",
property_->GetWindowName().c_str());
RecordLifeCycleExceptionEvent(WMError::WM_ERROR_NULLPTR,
WMErrorReason::WM_REASON_SUB_WINDOW_IPC_CREATE_ERR, "sub window create failed when ipc");
return WMError::WM_ERROR_NULLPTR;
}
if (surfaceNode_ == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "create specific failed, surfaceNode is nullptr, name: %{public}s",
property_->GetWindowName().c_str());
return WMError::WM_ERROR_NULLPTR;
}
if (renderSession == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "create specific failed, renderSession is nullptr, name: %{public}s",
property_->GetWindowName().c_str());
return WMError::WM_ERROR_NULLPTR;
}
PostInitSurfaceNode(renderSession);
{
std::lock_guard<std::mutex> lock(hostSessionMutex_);
hostSession_ = session;
}
TLOGI(WmsLogTag::WMS_LIFE, "name:%{public}s,id:%{public}d,parentId:%{public}d,type:%{public}u,"
"touchable:%{public}d,displayId:%{public}" PRIu64 ", errCode: %{public}d, msg: %{public}s",
property_->GetWindowName().c_str(),
property_->GetPersistentId(), property_->GetParentPersistentId(), GetType(),
property_->GetTouchable(), property_->GetDisplayId(), result.errCode, result.errMsg.c_str());
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::CreateSystemWindow(WindowType type)
{
if (WindowHelper::IsAppFloatingWindow(type) || WindowHelper::IsPipWindow(type) ||
type == WindowType::WINDOW_TYPE_TOAST || WindowHelper::IsFbWindow(type) || WindowHelper::IsFvWindow(type)) {
property_->SetParentPersistentId(GetFloatingWindowParentId());
TLOGI(WmsLogTag::WMS_SYSTEM, "parentId: %{public}d, type: %{public}d",
property_->GetParentPersistentId(), type);
auto mainWindow = FindMainWindowWithContext();
property_->SetFloatingWindowAppType(mainWindow != nullptr ? true : false);
if (mainWindow != nullptr) {
if (property_->GetDisplayId() == DISPLAY_ID_INVALID) {
property_->SetDisplayId(mainWindow->GetDisplayId());
}
}
} else if (type == WindowType::WINDOW_TYPE_DIALOG) {
if (auto mainWindow = FindMainWindowWithContext()) {
property_->SetParentPersistentId(mainWindow->GetPersistentId());
property_->SetDisplayId(mainWindow->GetDisplayId());
TLOGI(WmsLogTag::WMS_DIALOG, "The parentId: %{public}d", mainWindow->GetPersistentId());
}
WLOGFD("Cannot find main window to bind");
} else if (WindowHelper::IsSystemSubWindow(type)) {
auto parentSession = FindParentSessionByParentId(property_->GetParentId());
if (parentSession == nullptr || parentSession->GetHostSession() == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "parent of system sub window, name: %{public}s, type: %{public}d",
property_->GetWindowName().c_str(), type);
return WMError::WM_ERROR_NULLPTR;
}
if (WindowHelper::IsSystemSubWindow(parentSession->GetType())) {
TLOGE(WmsLogTag::WMS_LIFE, "parent is system sub window, name: %{public}s, type: %{public}d",
property_->GetWindowName().c_str(), type);
return WMError::WM_ERROR_INVALID_TYPE;
}
property_->SetParentPersistentId(parentSession->GetPersistentId());
property_->SetDisplayId(parentSession->GetDisplayId());
} else if (WindowHelper::IsInputWindow(type)) {
TLOGD(WmsLogTag::WMS_LIFE, "input method need default displayId");
} else {
return WMError::WM_OK;
}
SetDefaultDisplayIdIfNeed();
return WMError::WM_OK;
}
void WindowSceneSessionImpl::RecoverSessionProperty()
{
if (auto hostSession = GetHostSession()) {
hostSession->OnUpdateColorMode(colorMode_, hasDarkRes_);
}
}
WMError WindowSceneSessionImpl::RecoverAndConnectSpecificSession()
{
TLOGI(WmsLogTag::WMS_RECOVER, "windowName=%{public}s, windowMode=%{public}u, windowType=%{public}u, "
"persistentId=%{public}d, windowState=%{public}d, requestWindowState=%{public}d, parentId=%{public}d",
GetWindowName().c_str(), property_->GetWindowMode(), property_->GetWindowType(), GetPersistentId(), state_,
requestState_, property_->GetParentId());
const WindowType type = GetType();
if (WindowHelper::IsSubWindow(type) && !property_->GetIsUIExtFirstSubWindow()) {
TLOGD(WmsLogTag::WMS_RECOVER, "SubWindow");
auto parentSession = FindParentSessionByParentId(property_->GetParentId());
if ((parentSession == nullptr || parentSession->GetHostSession() == nullptr) &&
!property_->GetIsCrossProcessWindow()) {
TLOGE(WmsLogTag::WMS_RECOVER, "parentSession is null");
return WMError::WM_ERROR_NULLPTR;
}
}
if (WindowHelper::IsPipWindow(type)) {
TLOGI(WmsLogTag::WMS_RECOVER, "pipWindow");
PictureInPictureManager::DoClose(GetWindowId(), true, true);
return WMError::WM_OK;
}
windowRecoverStateChangeFunc_(true, WindowRecoverState::WINDOW_START_RECONNECT);
sptr<ISessionStage> iSessionStage(this);
sptr<IWindowEventChannel> eventChannel = sptr<WindowEventChannel>::MakeSptr(iSessionStage);
sptr<Rosen::ISession> session = nullptr;
auto context = GetContext();
sptr<IRemoteObject> token = context ? context->GetToken() : nullptr;
windowRecoverStateChangeFunc_(true, WindowRecoverState::WINDOW_DOING_RECONNECT);
SingletonContainer::Get<WindowAdapter>().RecoverAndConnectSpecificSession(
iSessionStage, eventChannel, surfaceNode_, property_, session, token);
if (session == nullptr) {
TLOGE(WmsLogTag::WMS_RECOVER, "Recover failed, session is nullptr");
RecordLifeCycleExceptionEvent(WMError::WM_ERROR_NULLPTR,
WMErrorReason::WM_REASON_SUB_WINDOW_IPC_RECOVER_ERR, "sub window recover failed when ipc");
windowRecoverStateChangeFunc_(true, WindowRecoverState::WINDOW_NOT_RECONNECT);
return WMError::WM_ERROR_NULLPTR;
}
{
std::lock_guard<std::mutex> lock(hostSessionMutex_);
hostSession_ = session;
}
windowRecoverStateChangeFunc_(true, WindowRecoverState::WINDOW_FINISH_RECONNECT);
TLOGI(WmsLogTag::WMS_RECOVER,
"over, windowName=%{public}s, persistentId=%{public}d",
GetWindowName().c_str(), GetPersistentId());
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::RecoverAndReconnectSceneSession()
{
TLOGI(WmsLogTag::WMS_RECOVER, "windowName=%{public}s, windowMode=%{public}u, windowType=%{public}u, "
"persistentId=%{public}d, windowState=%{public}d, requestWindowState=%{public}d", GetWindowName().c_str(),
property_->GetWindowMode(), property_->GetWindowType(), GetPersistentId(), state_, requestState_);
auto context = GetContext();
auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
if (context && context->GetHapModuleInfo() && abilityContext && abilityContext->GetAbilityInfo()) {
if (!abilityContext->IsHook() || abilityContext->GetHookOff()) {
property_->EditSessionInfo().abilityName_ = abilityContext->GetAbilityInfo()->name;
property_->EditSessionInfo().moduleName_ = context->GetHapModuleInfo()->moduleName;
}
} else {
TLOGE(WmsLogTag::WMS_RECOVER, "context or abilityContext is null, recovered session failed");
return WMError::WM_ERROR_NULLPTR;
}
auto& info = property_->EditSessionInfo();
if (auto want = abilityContext->GetWant()) {
info.want = want;
} else {
TLOGE(WmsLogTag::WMS_RECOVER, "want is nullptr!");
}
property_->SetIsFullScreenInForceSplitMode(isFullScreenInForceSplit_.load());
windowRecoverStateChangeFunc_(false, WindowRecoverState::WINDOW_START_RECONNECT);
sptr<ISessionStage> iSessionStage(this);
sptr<IWindowEventChannel> iWindowEventChannel = sptr<WindowEventChannel>::MakeSptr(iSessionStage);
sptr<IRemoteObject> token = context ? context->GetToken() : nullptr;
sptr<Rosen::ISession> session = nullptr;
windowRecoverStateChangeFunc_(false, WindowRecoverState::WINDOW_DOING_RECONNECT);
auto ret = SingletonContainer::Get<WindowAdapter>().RecoverAndReconnectSceneSession(
iSessionStage, iWindowEventChannel, surfaceNode_, session, property_, token);
if (session == nullptr) {
TLOGE(WmsLogTag::WMS_RECOVER, "session is null, recovered session failed");
windowRecoverStateChangeFunc_(false, WindowRecoverState::WINDOW_NOT_RECONNECT);
return WMError::WM_ERROR_NULLPTR;
}
{
std::lock_guard<std::mutex> lock(hostSessionMutex_);
hostSession_ = session;
}
windowRecoverStateChangeFunc_(false, WindowRecoverState::WINDOW_FINISH_RECONNECT);
TLOGI(WmsLogTag::WMS_RECOVER, "Successful, persistentId=%{public}d", GetPersistentId());
return static_cast<WMError>(ret);
}
std::string WindowSceneSessionImpl::TransferLifeCycleEventToString(LifeCycleEvent type) const
{
std::string event;
switch (type) {
case LifeCycleEvent::CREATE_EVENT:
event = "CREATE";
break;
case LifeCycleEvent::SHOW_EVENT:
event = "SHOW";
break;
case LifeCycleEvent::HIDE_EVENT:
event = "HIDE";
break;
case LifeCycleEvent::DESTROY_EVENT:
event = "DESTROY";
break;
default:
event = "UNDEFINE";
break;
}
return event;
}
void WindowSceneSessionImpl::UpdateWindowState()
{
{
std::unique_lock<std::shared_mutex> lock(windowSessionMutex_);
windowSessionMap_.insert(std::make_pair(property_->GetWindowName(),
std::pair<uint64_t, sptr<WindowSessionImpl>>(property_->GetPersistentId(), this)));
}
state_ = WindowState::STATE_CREATED;
requestState_ = WindowState::STATE_CREATED;
WindowType windowType = GetType();
if (WindowHelper::IsMainWindow(windowType)) {
if (property_->GetIsNeedUpdateWindowMode()) {
WLOGFI("UpdateWindowMode %{public}u mode %{public}u",
GetWindowId(), static_cast<uint32_t>(property_->GetWindowMode()));
UpdateWindowModeImmediately(property_->GetWindowModeInfo());
property_->SetIsNeedUpdateWindowMode(false);
} else {
SetWindowMode(windowSystemConfig_.defaultWindowMode_);
}
NotifyWindowNeedAvoid(
(property_->GetWindowFlags()) & (static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_NEED_AVOID)));
GetConfigurationFromAbilityInfo();
} else {
bool isSubWindow = WindowHelper::IsSubWindow(windowType);
bool isDialogWindow = WindowHelper::IsDialogWindow(windowType);
bool isSysytemWindow = WindowHelper::IsSystemWindow(windowType);
UpdateWindowSizeLimits();
if ((isSubWindow || isDialogWindow || isSysytemWindow) && IsWindowDraggable()) {
WLOGFD("sync window limits to server side to make size limits work while resizing");
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_LIMITS);
}
}
}
WMError WindowSceneSessionImpl::Create(const std::shared_ptr<AbilityRuntime::Context>& context,
const sptr<Rosen::ISession>& iSession, const std::string& identityToken, bool isModuleAbilityHookEnd,
bool isBlockSubwindow)
{
TLOGI(WmsLogTag::WMS_LIFE, "Window Create name:%{public}s, state:%{public}u, mode:%{public}u",
property_->GetWindowName().c_str(), state_, GetWindowMode());
if (!context) {
TLOGW(WmsLogTag::WMS_LIFE, "context is nullptr");
}
WMError ret = WindowSessionCreateCheck();
if (ret != WMError::WM_OK) {
return ret;
}
hostSession_ = iSession;
SetContext(context);
identityToken_ = identityToken;
property_->SetIsAbilityHookOff(isModuleAbilityHookEnd);
TLOGI(WmsLogTag::WMS_LIFE, "SetIsAbilityHookOff %{public}d", isModuleAbilityHookEnd);
AdjustWindowAnimationFlag();
if (context && context->GetApplicationInfo() &&
context->GetApplicationInfo()->apiCompatibleVersion >= 9 &&
!SessionPermission::IsSystemCalling()) {
WLOGI("Remove window flag WINDOW_FLAG_SHOW_WHEN_LOCKED");
property_->SetWindowFlags(property_->GetWindowFlags() &
(~(static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))));
}
int32_t zLevel = GetSubWindowZLevelByFlags(GetType(), GetWindowFlags(), IsTopmost());
if (zLevel != NORMAL_SUB_WINDOW_Z_LEVEL) {
property_->SetSubWindowZLevel(zLevel);
}
if (IsSubWindowMaximizeSupported()) {
property_->SetDecorEnable(windowOption_->GetSubWindowDecorEnable());
}
bool isSpecificSession = false;
const auto& initRect = GetRequestRect();
if (GetHostSession()) {
SetDefaultDisplayIdIfNeed();
SetTargetAPIVersion(SysCapUtil::GetApiCompatibleVersion());
ret = Connect();
SendCombinedCompatibleConfigToArkUI();
TLOGD(WmsLogTag::WMS_PC, "targeAPItVersion: %{public}d", GetTargetAPIVersion());
} else {
TLOGI(WmsLogTag::WMS_LIFE, "Create system or sub window with type=%{public}d", GetType());
isSpecificSession = true;
const auto& type = GetType();
if (WindowHelper::IsSystemWindow(type)) {
if (!IsValidSystemWindowType(type)) {
return WMError::WM_ERROR_INVALID_CALLING;
}
if (INVALID_SCB_WINDOW_TYPE.find(type) != INVALID_SCB_WINDOW_TYPE.end()) {
TLOGI(WmsLogTag::WMS_SYSTEM, "Invalid SCB type: %{public}u", type);
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
InitSystemSessionDragEnable();
} else if (!WindowHelper::IsSubWindow(type)) {
TLOGI(WmsLogTag::WMS_LIFE, "create failed not system or sub type, type: %{public}d", type);
return WMError::WM_ERROR_INVALID_CALLING;
}
InitSubSessionDragEnable();
isEnableDefaultDensityWhenCreate_ = windowOption_->IsDefaultDensityEnabled();
ret = CreateAndConnectSpecificSession();
}
if (ret == WMError::WM_OK) {
MakeSubOrDialogWindowDragableAndMoveble();
UpdateWindowState();
RegisterWindowRecoverStateChangeListener();
RegisterSessionRecoverListener(isSpecificSession);
UpdateDefaultStatusBarColor();
AddSetUIContentTimeoutCheck();
SetUIExtensionDestroyCompleteInSubWindow();
SetSubWindowZLevelToProperty();
InputTransferStation::GetInstance().AddInputWindow(this);
if (WindowHelper::IsSubWindow(GetType()) && !initRect.IsUninitializedRect()) {
auto hostSession = GetHostSession();
if (IsFullScreenSizeWindow(initRect.width_, initRect.height_) && (hostSession != nullptr)) {
TLOGI(WmsLogTag::WMS_LIFE, "Full screen size sub window set isDefaultDensityEnabled true");
hostSession->OnDefaultDensityEnabled(true);
}
Resize(initRect.width_, initRect.height_);
}
RegisterWindowInspectorCallback();
UpdateColorMode();
SetPcAppInpadSpecificSystemBarInvisible();
SetPcAppInpadOrientationLandscape();
SetDefaultDensityEnabledValue(IsStageDefaultDensityEnabled());
RegisterListenerForKeyboard();
RecordWindowLifecycleChange("create");
}
RecordLifeCycleExceptionEvent(ret,
WMErrorReason::WM_REASON_WINDOW_CREATE_ERR, "window create failed");
UpdateAnimationSpeedIfEnabled();
TLOGI(WmsLogTag::WMS_LIFE, "Window Create success [name:%{public}s, id:%{public}d], state:%{public}u, "
"mode:%{public}u, enableDefaultDensity:%{public}d, displayId:%{public}" PRIu64,
property_->GetWindowName().c_str(), property_->GetPersistentId(), state_, GetWindowMode(),
isEnableDefaultDensityWhenCreate_, property_->GetDisplayId());
return ret;
}
void WindowSceneSessionImpl::RegisterListenerForKeyboard()
{
if (GetType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
return;
}
SingletonContainer::Get<ScreenManager>().RegisterScreenListener(sptr<WindowScreenListener>::MakeSptr());
}
void WindowSceneSessionImpl::UpdateAnimationSpeedIfEnabled()
{
if (!isEnableAnimationSpeed_.load()) {
return;
}
TLOGI(WmsLogTag::WMS_ANIMATION, "isEnableAnimationSpeed_ is true");
auto rsUIContext = WindowSessionImpl::GetRSUIContext();
auto implicitAnimator = rsUIContext ? rsUIContext->GetRSImplicitAnimator() : nullptr;
if (implicitAnimator != nullptr) {
implicitAnimator->ApplyAnimationSpeedMultiplier(animationSpeed_.load());
TLOGI(WmsLogTag::WMS_ANIMATION, "update animation speed success");
} else {
TLOGE(WmsLogTag::WMS_ANIMATION, "implicitAnimator is nullptr");
}
}
WMError WindowSceneSessionImpl::SetPcAppInpadSpecificSystemBarInvisible()
{
TLOGI(WmsLogTag::WMS_COMPAT, "isPcAppInpadSpecificSystemBarInvisible: %{public}d",
property_->GetPcAppInpadSpecificSystemBarInvisible());
if (WindowHelper::IsMainWindow(GetType()) && IsPadAndNotFreeMultiWindowCompatibleMode() &&
property_->GetPcAppInpadSpecificSystemBarInvisible()) {
SystemBarProperty statusProperty = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR);
UpdateSpecificSystemBarEnabled(false, false, statusProperty);
SetSpecificBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, statusProperty);
SystemBarProperty NavigationIndicatorPorperty =
GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_INDICATOR);
UpdateSpecificSystemBarEnabled(false, false, NavigationIndicatorPorperty);
SetSpecificBarProperty(WindowType::WINDOW_TYPE_NAVIGATION_INDICATOR, NavigationIndicatorPorperty);
return WMError::WM_OK;
}
return WMError::WM_ERROR_INVALID_CALLING;
}
WMError WindowSceneSessionImpl::SetPcAppInpadOrientationLandscape()
{
TLOGI(WmsLogTag::WMS_COMPAT, "isPcAppInpadOrientationLandscape: %{public}d",
property_->GetPcAppInpadOrientationLandscape());
if (WindowHelper::IsMainWindow(GetType()) && IsPadAndNotFreeMultiWindowCompatibleMode() &&
property_->GetPcAppInpadOrientationLandscape()) {
SetRequestedOrientation(Orientation::HORIZONTAL, false);
return WMError::WM_OK;
}
return WMError::WM_ERROR_INVALID_CALLING;
}
bool WindowSceneSessionImpl::IsFullScreenSizeWindow(uint32_t width, uint32_t height)
{
DisplayId displayId = property_->GetDisplayId();
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(displayId);
if (display == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT, "display is null");
return false;
}
auto displayInfo = display->GetDisplayInfo();
if (displayInfo == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT, "displayInfo is null");
return false;
}
uint32_t displayWidth = static_cast<uint32_t>(displayInfo->GetWidth());
uint32_t displayHeight = static_cast<uint32_t>(displayInfo->GetHeight());
if (displayWidth == width && displayHeight == height) {
return true;
}
if (!FoldScreenStateInternel::IsSuperFoldDisplayDevice() ||
DisplayManager::GetInstance().GetFoldStatus() != FoldStatus::HALF_FOLD) {
return false;
}
auto virtualDisplay = SingletonContainer::Get<DisplayManager>().GetDisplayById(DISPLAY_ID_C);
if (virtualDisplay == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT, "virtual display is null");
return false;
}
auto virtualDisplayInfo = virtualDisplay->GetDisplayInfo();
if (virtualDisplayInfo == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT, "virtual displayInfo is null");
return false;
}
displayWidth = static_cast<uint32_t>(virtualDisplayInfo->GetWidth());
displayHeight = static_cast<uint32_t>(virtualDisplayInfo->GetHeight());
if (displayWidth == width && displayHeight == height) {
return true;
}
return false;
}
WMError WindowSceneSessionImpl::SetParentWindowInner(int32_t oldParentWindowId,
const sptr<WindowSessionImpl>& newParentWindow)
{
auto newParentWindowId = newParentWindow->GetPersistentId();
auto subWindowId = GetPersistentId();
TLOGI(WmsLogTag::WMS_SUB, "subWindowId: %{public}d, oldParentWindowId: %{public}d, "
"newParentWindowId: %{public}d", subWindowId, oldParentWindowId, newParentWindowId);
WMError ret = SingletonContainer::Get<WindowAdapter>().SetParentWindow(subWindowId, newParentWindowId);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d set parent window failed errCode: %{public}d",
subWindowId, static_cast<int32_t>(ret));
return ret;
}
RemoveSubWindow(oldParentWindowId);
{
std::lock_guard<std::recursive_mutex> lock(subWindowSessionMutex_);
subWindowSessionMap_[newParentWindowId].push_back(this);
}
property_->SetParentPersistentId(newParentWindowId);
UpdateSubWindowInfo(newParentWindow->GetProperty()->GetSubWindowLevel() + 1, newParentWindow->GetContext());
if (!IsLoosenedWithPcOrFreeMultiMode() && state_ == WindowState::STATE_SHOWN &&
newParentWindow->GetWindowState() == WindowState::STATE_HIDDEN) {
UpdateSubWindowStateAndNotify(newParentWindowId, WindowState::STATE_HIDDEN);
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetParentWindow(int32_t newParentWindowId)
{
auto subWindowId = GetPersistentId();
if (property_->GetPcAppInpadCompatibleMode()) {
TLOGE(WmsLogTag::WMS_SUB, "This is PcAppInPad, not Supported");
return WMError::WM_OK;
}
if (!IsPcOrPadFreeMultiWindowMode()) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d device not support", subWindowId);
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsSubWindow(GetType())) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d called by invalid window type %{public}d",
subWindowId, GetType());
return WMError::WM_ERROR_INVALID_CALLING;
}
auto oldParentWindowId = property_->GetParentPersistentId();
if (oldParentWindowId == newParentWindowId || subWindowId == newParentWindowId) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d newParentWindowId is the same as "
"oldParentWindowId or subWindowId", subWindowId);
return WMError::WM_ERROR_INVALID_PARENT;
}
auto oldParentWindow = GetWindowWithId(oldParentWindowId);
if (oldParentWindow == nullptr) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d can not find old parent window By Id: %{public}d",
subWindowId, oldParentWindowId);
return WMError::WM_ERROR_INVALID_PARENT;
}
auto oldWindowType = oldParentWindow->GetType();
if (!WindowHelper::IsMainWindow(oldWindowType) && !WindowHelper::IsFloatOrSubWindow(oldWindowType)) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d old parent window type invalid", subWindowId);
return WMError::WM_ERROR_INVALID_PARENT;
}
auto newParentWindow = GetWindowWithId(newParentWindowId);
if (newParentWindow == nullptr) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d can not find new parent window By Id: %{public}d",
subWindowId, newParentWindowId);
return WMError::WM_ERROR_INVALID_PARENT;
}
auto newWindowType = newParentWindow->GetType();
if (!WindowHelper::IsMainWindow(newWindowType) && !WindowHelper::IsFloatOrSubWindow(newWindowType)) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d new parent window type invalid", subWindowId);
return WMError::WM_ERROR_INVALID_PARENT;
}
if (IsZLevelAboveParentLoosened() && !WindowHelper::IsMainWindow(newWindowType)) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d new parent window type invalid", subWindowId);
return WMError::WM_ERROR_INVALID_PARENT;
}
return SetParentWindowInner(oldParentWindowId, newParentWindow);
}
WMError WindowSceneSessionImpl::GetParentWindow(sptr<Window>& parentWindow)
{
if (property_->GetPcAppInpadCompatibleMode()) {
TLOGE(WmsLogTag::WMS_SUB, "This is PcAppInPad, not Supported");
return WMError::WM_OK;
}
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsSubWindow(GetType())) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d called by invalid window type %{public}d",
GetPersistentId(), GetType());
return WMError::WM_ERROR_INVALID_CALLING;
}
if (property_->GetIsUIExtFirstSubWindow()) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d UIExtension sub window not get parent window",
GetPersistentId());
return WMError::WM_ERROR_INVALID_CALLING;
}
parentWindow = FindWindowById(property_->GetParentPersistentId());
if (parentWindow == nullptr) {
TLOGE(WmsLogTag::WMS_SUB, "winId: %{public}d parentWindow is nullptr", GetPersistentId());
return WMError::WM_ERROR_INVALID_PARENT;
}
return WMError::WM_OK;
}
void WindowSceneSessionImpl::UpdateDefaultStatusBarColor()
{
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGD(WmsLogTag::WMS_IMMS, "win %{public}u not main window", GetPersistentId());
return;
}
uint32_t contentColor = 0;
auto ret = UpdateStatusBarColorByColorMode(contentColor);
if (ret != WMError::WM_OK) {
TLOGD(WmsLogTag::WMS_IMMS, "win %{public}u no need update", GetPersistentId());
return;
}
auto type = WindowType::WINDOW_TYPE_STATUS_BAR;
SystemBarProperty statusBarProp = GetSystemBarPropertyByType(type);
statusBarProp.contentColor_ = contentColor;
statusBarProp.settingFlag_ = static_cast<SystemBarSettingFlag>(
static_cast<uint32_t>(statusBarProp.settingFlag_) |
static_cast<uint32_t>(SystemBarSettingFlag::FOLLOW_SETTING));
property_->SetSystemBarProperty(type, statusBarProp);
auto prop = GetCurrentActiveSystemBarProperty(type);
if ((static_cast<uint32_t>(prop.settingFlag_) &
static_cast<uint32_t>(SystemBarSettingFlag::COLOR_SETTING)) == 0u) {
SetSpecificBarProperty(type, statusBarProp);
}
}
void WindowSceneSessionImpl::InitSubSessionDragEnable()
{
if (WindowHelper::IsSubWindow(GetType()) && !IsPcOrPadFreeMultiWindowMode()) {
TLOGI(WmsLogTag::WMS_LAYOUT, "windId: %{public}d init subWindow dragEnable false",
property_->GetPersistentId());
property_->SetDragEnabled(false);
}
}
void WindowSceneSessionImpl::InitSystemSessionDragEnable()
{
if (WindowHelper::IsDialogWindow(GetType()) && IsPcOrPadFreeMultiWindowMode()) {
TLOGI(WmsLogTag::WMS_LAYOUT, "dialogWindow default draggable, should not init false, id: %{public}d",
GetPersistentId());
return;
}
TLOGI(WmsLogTag::WMS_LAYOUT, "windId: %{public}d init dragEnable false",
GetPersistentId());
property_->SetDragEnabled(false);
}
void WindowSceneSessionImpl::RegisterSessionRecoverListener(bool isSpecificSession)
{
TLOGD(WmsLogTag::WMS_RECOVER, "Id=%{public}d, isSpecificSession=%{public}s",
GetPersistentId(), isSpecificSession ? "true" : "false");
if (GetType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
TLOGI(WmsLogTag::WMS_RECOVER, "input method window does not need to recover");
return;
}
if (property_->GetCollaboratorType() != CollaboratorType::DEFAULT_TYPE) {
TLOGI(WmsLogTag::WMS_RECOVER, "collaboratorType is %{public}" PRId32 ", not need to recover",
property_->GetCollaboratorType());
return;
}
wptr<WindowSceneSessionImpl> weakThis = this;
auto callbackFunc = [weakThis, isSpecificSession] {
auto promoteThis = weakThis.promote();
if (promoteThis == nullptr) {
TLOGW(WmsLogTag::WMS_RECOVER, "promoteThis is nullptr");
return WMError::WM_ERROR_NULLPTR;
}
if (promoteThis->state_ == WindowState::STATE_DESTROYED) {
TLOGW(WmsLogTag::WMS_RECOVER, "windowState is STATE_DESTROYED, no need to recover");
return WMError::WM_ERROR_DESTROYED_OBJECT;
}
if (promoteThis->windowRecoverStateChangeFunc_ == nullptr) {
TLOGW(WmsLogTag::WMS_RECOVER, "windowRecoverStateChangeFunc_ is nullptr");
return WMError::WM_ERROR_NULLPTR;
}
auto ret = isSpecificSession ? promoteThis->RecoverAndConnectSpecificSession() :
promoteThis->RecoverAndReconnectSceneSession();
TLOGD(WmsLogTag::WMS_RECOVER, "Recover session over, ret=%{public}d", ret);
return ret;
};
SingletonContainer::Get<WindowAdapter>().RegisterSessionRecoverCallbackFunc(GetPersistentId(), callbackFunc);
}
void WindowSceneSessionImpl::RegisterWindowRecoverStateChangeListener()
{
windowRecoverStateChangeFunc_ = [weakThis = wptr(this)](bool isSpecificSession,
const WindowRecoverState& state) THREAD_SAFETY_GUARD(SCENE_GUARD) {
auto window = weakThis.promote();
if (window == nullptr) {
TLOGNE(WmsLogTag::WMS_RECOVER, "window is null");
return;
}
window->OnWindowRecoverStateChange(isSpecificSession, state);
};
}
void WindowSceneSessionImpl::RecoverExtension()
{
TLOGI(WmsLogTag::WMS_UIEXT, "hostWindowId: %{public}d", GetPersistentId());
if (auto uiContent = GetUIContentSharedPtr()) {
AAFwk::Want want;
Ace::UIExtOptions uiExtOptions;
uiExtOptions.isSendBackground = true;
uiContent->SendUIExtProprty(static_cast<uint32_t>(Extension::Businesscode::RECOVER_EXTENSION), want,
static_cast<uint8_t>(SubSystemId::WM_UIEXT), uiExtOptions);
}
}
void WindowSceneSessionImpl::OnWindowRecoverStateChange(bool isSpecificSession, const WindowRecoverState& state)
{
TLOGI(WmsLogTag::WMS_RECOVER, "id: %{public}d, state:%{public}u", GetPersistentId(), state);
switch (state) {
case WindowRecoverState::WINDOW_START_RECONNECT:
UpdateStartRecoverProperty(isSpecificSession);
UpdateStartRecoverEventFlag();
if (isFocused_) {
UpdateFocusState(false);
}
if (isHighlighted_) {
NotifyHighlightChange(false);
}
SetIsStartMoving(false);
break;
case WindowRecoverState::WINDOW_FINISH_RECONNECT:
UpdateFinishRecoverProperty(isSpecificSession);
RecoverSessionListener();
RecoverSessionProperty();
RecoverExtension();
break;
default:
break;
}
}
void WindowSceneSessionImpl::UpdateStartRecoverEventFlag()
{
std::unique_lock<std::shared_mutex> lock(windowSessionMutex_);
property_->EditSessionInfo().isReceiveDragEventEnabled_ = isReceiveDragEventEnabled_;
property_->EditSessionInfo().isSeparationTouchEnabled_ = isSeparationTouchEnabled_;
}
void WindowSceneSessionImpl::UpdateStartRecoverProperty(bool isSpecificSession)
{
if (isSpecificSession) {
property_->SetWindowState(requestState_);
if (GetContext() && GetContext()->GetToken()) {
property_->SetTokenState(true);
}
} else {
property_->SetWindowState(state_);
property_->SetIsFullScreenWaterfallMode(isFullScreenWaterfallMode_.load());
}
}
void WindowSceneSessionImpl::UpdateFinishRecoverProperty(bool isSpecificSession)
{
property_->SetWindowState(state_);
}
bool WindowSceneSessionImpl::HandlePointDownEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
const MMI::PointerEvent::PointerItem& pointerItem)
{
bool needNotifyEvent = true;
WindowType windowType = property_->GetWindowType();
AreaType dragType = GetDragAreaByDownEvent(pointerEvent, pointerItem);
TLOGD(WmsLogTag::WMS_EVENT, "dragType: %{public}d", dragType);
bool isDecorDialog = windowType == WindowType::WINDOW_TYPE_DIALOG && property_->IsDecorEnable();
bool isFixedSubWin = WindowHelper::IsSubWindow(windowType) && !IsWindowDraggable();
bool isFixedSystemWin = WindowHelper::IsSystemWindow(windowType) && !IsWindowDraggable();
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, needNotifyEvent);
TLOGD(WmsLogTag::WMS_EVENT, "isFixedSystemWin %{public}d, isFixedSubWin %{public}d, isDecorDialog %{public}d",
isFixedSystemWin, isFixedSubWin, isDecorDialog);
if ((isFixedSystemWin || isFixedSubWin) && !isDecorDialog) {
hostSession->SendPointEventForMoveDrag(pointerEvent, isExecuteDelayRaise_);
} else {
if (dragType != AreaType::UNDEFINED) {
hostSession->SendPointEventForMoveDrag(pointerEvent, isExecuteDelayRaise_);
needNotifyEvent = false;
} else if (WindowHelper::IsMainWindow(windowType) ||
WindowHelper::IsSubWindow(windowType) ||
WindowHelper::IsSystemWindow(windowType)) {
hostSession->SendPointEventForMoveDrag(pointerEvent, isExecuteDelayRaise_);
} else {
hostSession->ProcessPointDownSession(pointerItem.GetDisplayX(), pointerItem.GetDisplayY());
}
}
return needNotifyEvent;
}
AreaType WindowSceneSessionImpl::GetDragAreaByDownEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
const MMI::PointerEvent::PointerItem& pointerItem)
{
AreaType dragType = AreaType::UNDEFINED;
float vpr = WindowSessionImpl::GetVirtualPixelRatio();
if (MathHelper::NearZero(vpr)) {
return dragType;
}
const auto& sourceType = pointerEvent->GetSourceType();
int outside = (sourceType == MMI::PointerEvent::SOURCE_TYPE_MOUSE) ? static_cast<int>(HOTZONE_POINTER * vpr) :
static_cast<int>(HOTZONE_TOUCH * vpr);
int32_t winX = pointerItem.GetWindowX();
int32_t winY = pointerItem.GetWindowY();
WindowType windowType = property_->GetWindowType();
bool isSystemDraggableType = WindowHelper::IsSystemWindow(windowType) && IsWindowDraggable();
bool isFloatingDraggableType =
property_->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && IsWindowDraggable();
const auto& rect = SessionHelper::TransferToWSRect(GetRect());
auto limits = property_->GetWindowLimits();
TLOGD(WmsLogTag::WMS_EVENT, "%{public}s [minWidth,maxWidth,minHeight,maxHeight]: %{public}d,"
" %{public}d, %{public}d, %{public}d", GetWindowName().c_str(), limits.minWidth_,
limits.maxWidth_, limits.minHeight_, limits.maxHeight_);
if (isFloatingDraggableType || isSystemDraggableType) {
dragType = SessionHelper::GetAreaType(winX, winY, sourceType, outside, vpr, rect, limits);
}
return dragType;
}
void WindowSceneSessionImpl::ResetSuperFoldDisplayY(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
{
if (superFoldOffsetY_ == -1) {
auto foldCreaseRegion = DisplayManager::GetInstance().GetCurrentFoldCreaseRegion();
if (foldCreaseRegion == nullptr) {
TLOGE(WmsLogTag::WMS_INPUT_KEY_FLOW, "foldCreaseRegion is nullptr");
return;
}
const auto& creaseRects = foldCreaseRegion->GetCreaseRects();
if (creaseRects.empty()) {
TLOGE(WmsLogTag::WMS_INPUT_KEY_FLOW, "creaseRects is empty");
return;
}
const auto& rect = creaseRects.front();
superFoldOffsetY_ = rect.height_ + rect.posY_;
TLOGI(WmsLogTag::WMS_EVENT, "height: %{public}d, posY: %{public}d", rect.height_, rect.posY_);
}
std::vector<int32_t> pointerIds = pointerEvent->GetPointerIds();
for (int32_t pointerId : pointerIds) {
MMI::PointerEvent::PointerItem pointerItem;
if (!pointerEvent->GetPointerItem(pointerId, pointerItem)) {
TLOGE(WmsLogTag::WMS_INPUT_KEY_FLOW, "Get pointerItem failed");
return;
}
if (auto displayYPos = pointerItem.GetDisplayYPos();
!MathHelper::LessNotEqual(displayYPos, superFoldOffsetY_)) {
pointerItem.SetDisplayYPos(displayYPos - superFoldOffsetY_);
pointerEvent->UpdatePointerItem(pointerId, pointerItem);
pointerEvent->SetTargetDisplayId(DISPLAY_ID_C);
TLOGD(WmsLogTag::WMS_EVENT, "Calculated superFoldOffsetY:%{public}d,displayId:%{public}d,"
"InputId:%{public}d,pointerId:%{public}d,displayXPos:%{private}f,displayYPos:%{private}f,",
superFoldOffsetY_, pointerEvent->GetTargetDisplayId(), pointerEvent->GetId(),
pointerId, pointerItem.GetDisplayXPos(), pointerItem.GetDisplayYPos());
}
}
if (MMI::PointerEvent::POINTER_ACTION_AXIS_UPDATE == pointerEvent->GetPointerAction()) {
pointerEvent->SetTargetDisplayId(DISPLAY_ID_C);
TLOGD(WmsLogTag::WMS_EVENT, "Reset targetDisplayId, InputId:%{public}d, ac:%{public}d", pointerEvent->GetId(),
pointerEvent->GetPointerAction());
}
}
void WindowSceneSessionImpl::ConsumePointerEventInner(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
MMI::PointerEvent::PointerItem& pointerItem, bool isHitTargetDraggable)
{
const int32_t& action = pointerEvent->GetPointerAction();
bool isPointDown = (action == MMI::PointerEvent::POINTER_ACTION_DOWN ||
action == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN);
bool needNotifyEvent = true;
if (property_->IsAdaptToEventMapping()) {
HandleEventForCompatibleMode(pointerEvent, pointerItem);
}
lastPointerEvent_ = pointerEvent;
if (isPointDown) {
float vpr = WindowSessionImpl::GetVirtualPixelRatio();
if (MathHelper::NearZero(vpr)) {
WLOGFW("vpr is zero");
pointerEvent->MarkProcessed();
return;
}
if (IsWindowDelayRaiseEnabled() && isHitTargetDraggable) {
isExecuteDelayRaise_ = true;
}
needNotifyEvent = HandlePointDownEvent(pointerEvent, pointerItem);
RefreshNoInteractionTimeoutMonitor();
}
bool isPointUp = (action == MMI::PointerEvent::POINTER_ACTION_UP ||
action == MMI::PointerEvent::POINTER_ACTION_BUTTON_UP ||
action == MMI::PointerEvent::POINTER_ACTION_CANCEL);
bool needForwardMoveEvent = (action == MMI::PointerEvent::POINTER_ACTION_MOVE && IsStartMoving());
if (isPointUp || needForwardMoveEvent) {
if (auto hostSession = GetHostSession()) {
hostSession->SendPointEventForMoveDrag(pointerEvent, isExecuteDelayRaise_);
}
}
bool isPointPullUp = action == MMI::PointerEvent::POINTER_ACTION_PULL_UP;
if (isExecuteDelayRaise_ && (isPointUp || isPointPullUp)) {
isExecuteDelayRaise_ = false;
}
if (FoldScreenStateInternel::IsSuperFoldDisplayDevice() &&
property_->GetDisplayId() == DISPLAY_ID_C &&
DisplayManager::GetInstance().GetFoldStatus() == FoldStatus::HALF_FOLD) {
ResetSuperFoldDisplayY(pointerEvent);
}
if (needNotifyEvent) {
NotifyPointerEvent(pointerEvent);
} else {
pointerEvent->MarkProcessed();
}
if (isPointDown || isPointUp) {
TLOGNI(WmsLogTag::WMS_INPUT_KEY_FLOW, "ConsumePointerEvent InputId:%{public}d,notify:%{public}d",
pointerEvent->GetId(), needNotifyEvent);
}
}
void WindowSceneSessionImpl::ConsumePointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
{
if (pointerEvent == nullptr) {
WLOGFE("PointerEvent is nullptr, windowId: %{public}d", GetWindowId());
return;
}
if (GetHostSession() == nullptr) {
TLOGE(WmsLogTag::WMS_INPUT_KEY_FLOW, "hostSession is nullptr, windowId: %{public}d", GetWindowId());
pointerEvent->MarkProcessed();
return;
}
MMI::PointerEvent::PointerItem pointerItem;
if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) {
TLOGW(WmsLogTag::WMS_INPUT_KEY_FLOW, "invalid pointerEvent, windowId: %{public}d", GetWindowId());
pointerEvent->MarkProcessed();
return;
}
bool isPointDown = pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN ||
pointerEvent->GetPointerAction() == MMI::PointerEvent::POINTER_ACTION_DOWN;
AreaType dragType = AreaType::UNDEFINED;
if (isPointDown) {
dragType = GetDragAreaByDownEvent(pointerEvent, pointerItem);
}
if (!IsWindowDelayRaiseEnabled() || dragType != AreaType::UNDEFINED) {
ConsumePointerEventInner(pointerEvent, pointerItem, false);
return;
}
if (auto uiContent = GetUIContentSharedPtr()) {
uiContent->ProcessPointerEvent(pointerEvent,
[weakThis = wptr(this), pointerEvent, pointerItem](bool isHitTargetDraggable) mutable {
auto window = weakThis.promote();
if (window == nullptr) {
TLOGNE(WmsLogTag::WMS_FOCUS, "window is null");
return;
}
window->ConsumePointerEventInner(pointerEvent, pointerItem, isHitTargetDraggable);
});
} else {
TLOGE(WmsLogTag::WMS_FOCUS, "uiContent is nullptr, windowId: %{public}u", GetWindowId());
pointerEvent->MarkProcessed();
}
}
bool WindowSceneSessionImpl::PreNotifyKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
{
if (FoldScreenStateInternel::IsSuperFoldDisplayDevice() &&
property_->GetDisplayId() == DISPLAY_ID_C &&
DisplayManager::GetInstance().GetFoldStatus() == FoldStatus::HALF_FOLD) {
keyEvent->SetTargetDisplayId(DISPLAY_ID_C);
}
bool isConsumed = false;
if (auto uiContent = GetUIContentSharedPtr()) {
isConsumed = uiContent->ProcessKeyEvent(keyEvent, true);
}
RefreshNoInteractionTimeoutMonitor();
if ((keyEvent->GetKeyCode() == MMI::KeyEvent::KEYCODE_TAB ||
keyEvent->GetKeyCode() == MMI::KeyEvent::KEYCODE_ENTER) && isConsumed &&
keyEvent->GetKeyAction() == MMI::KeyEvent::KEY_ACTION_DOWN) {
TLOGD(WmsLogTag::WMS_EVENT, "wid:%{public}u, isConsumed:%{public}d", GetWindowId(), isConsumed);
NotifyWatchGestureConsumeResult(keyEvent->GetKeyCode(), isConsumed);
}
SetWatchGestureConsumed(isConsumed);
return isConsumed;
}
static void GetWindowSizeLimits(std::shared_ptr<AppExecFwk::AbilityInfo> abilityInfo,
WindowSizeLimits& windowSizeLimits)
{
windowSizeLimits.maxWindowWidth = windowSizeLimits.maxWindowWidth > 0 ?
windowSizeLimits.maxWindowWidth : abilityInfo->maxWindowWidth;
windowSizeLimits.maxWindowHeight = windowSizeLimits.maxWindowHeight > 0 ?
windowSizeLimits.maxWindowHeight : abilityInfo->maxWindowHeight;
windowSizeLimits.minWindowWidth = windowSizeLimits.minWindowWidth > 0 ?
windowSizeLimits.minWindowWidth : abilityInfo->minWindowWidth;
windowSizeLimits.minWindowHeight = windowSizeLimits.minWindowHeight > 0 ?
windowSizeLimits.minWindowHeight : abilityInfo->minWindowHeight;
}
std::vector<AppExecFwk::SupportWindowMode> WindowSceneSessionImpl::ExtractSupportWindowModeFromMetaData(
const std::shared_ptr<AppExecFwk::AbilityInfo>& abilityInfo)
{
std::vector<AppExecFwk::SupportWindowMode> updateWindowModes = {};
if (windowSystemConfig_.IsPcWindow() || IsFreeMultiWindowMode()) {
auto metadata = abilityInfo->metadata;
for (const auto& item : metadata) {
if (item.name == "ohos.ability.window.supportWindowModeInFreeMultiWindow") {
updateWindowModes = ParseWindowModeFromMetaData(item.value);
}
}
}
if (updateWindowModes.empty()) {
updateWindowModes = abilityInfo->windowModes;
}
return updateWindowModes;
}
std::vector<AppExecFwk::SupportWindowMode> WindowSceneSessionImpl::ParseWindowModeFromMetaData(
const std::string& supportModesInFreeMultiWindow)
{
std::vector<AppExecFwk::SupportWindowMode> updateWindowModes = {};
std::stringstream supportModes(supportModesInFreeMultiWindow);
std::string supportWindowMode;
while (getline(supportModes, supportWindowMode, ',')) {
if (supportWindowMode == "fullscreen") {
updateWindowModes.push_back(AppExecFwk::SupportWindowMode::FULLSCREEN);
} else if (supportWindowMode == "split") {
updateWindowModes.push_back(AppExecFwk::SupportWindowMode::SPLIT);
} else if (supportWindowMode == "floating") {
updateWindowModes.push_back(AppExecFwk::SupportWindowMode::FLOATING);
} else {
TLOGW(WmsLogTag::WMS_LAYOUT, "invalid input");
}
}
return updateWindowModes;
}
uint32_t WindowSceneSessionImpl::GetSupportedWindowModesConfiguration(
const std::shared_ptr<AppExecFwk::AbilityInfo>& abilityInfo)
{
uint32_t windowModeSupportType = 0;
std::vector<AppExecFwk::SupportWindowMode> supportedWindowModes;
auto size = supportedWindowModes.size();
if (size > 0 && size <= WINDOW_SUPPORT_MODE_MAX_SIZE) {
windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(supportedWindowModes);
if (auto hostSession = GetHostSession()) {
hostSession->NotifySupportWindowModesChange(supportedWindowModes);
};
} else {
std::vector<AppExecFwk::SupportWindowMode> updateWindowModes =
ExtractSupportWindowModeFromMetaData(abilityInfo);
windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(updateWindowModes);
}
if (windowModeSupportType == 0) {
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "mode config param is 0, all modes is supported");
} else {
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "winId: %{public}u, windowModeSupportType: %{public}u",
GetWindowId(), windowModeSupportType);
}
return windowModeSupportType;
}
void WindowSceneSessionImpl::GetConfigurationFromAbilityInfo()
{
auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(GetContext());
if (abilityContext == nullptr) {
WLOGFE("abilityContext is nullptr");
return;
}
auto abilityInfo = abilityContext->GetAbilityInfo();
if (abilityInfo != nullptr) {
WindowSizeLimits windowSizeLimits = property_->GetWindowSizeLimits();
GetWindowSizeLimits(abilityInfo, windowSizeLimits);
property_->SetConfigWindowLimitsVP({
windowSizeLimits.maxWindowWidth, windowSizeLimits.maxWindowHeight,
windowSizeLimits.minWindowWidth, windowSizeLimits.minWindowHeight,
static_cast<float>(abilityInfo->maxWindowRatio), static_cast<float>(abilityInfo->minWindowRatio),
1.0f, PixelUnit::VP
});
UpdateWindowSizeLimits();
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_LIMITS);
uint32_t windowModeSupportType = GetSupportedWindowModesConfiguration(abilityInfo);
windowModeSupportType = SetSupportedWindowModesForAncoInFreeWindow(windowModeSupportType);
property_->SetWindowModeSupportType(windowModeSupportType);
TLOGI(WmsLogTag::WMS_LAYOUT, "windowId: %{public}u, windowModeSupportType: %{public}u, "
"isAncoSupportFreeWindow: %{public}d", GetWindowId(), windowModeSupportType, IsAncoSupportFreeWindow());
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO);
bool isWindowModeSupportFullscreen = GetTargetAPIVersion() < 15 ?
(windowModeSupportType == WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN) :
(WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FULLSCREEN) &&
!WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FLOATING));
bool isAncoInPhoneFreeMultiWindowMode = IsAnco() && IsFreeMultiWindowMode() &&
windowSystemConfig_.IsPhoneWindow();
bool onlySupportFullScreen = isWindowModeSupportFullscreen || isAncoInPhoneFreeMultiWindowMode ||
(IsAnco() && !IsAncoSupportFreeWindow());
bool compatibleDisableFullScreen = property_->IsFullScreenDisabled();
if ((onlySupportFullScreen || property_->GetFullScreenStart()) && !compatibleDisableFullScreen) {
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "onlySupportFullScreen:%{public}d fullScreenStart:%{public}d",
onlySupportFullScreen, property_->GetFullScreenStart());
Maximize(MaximizePresentation::ENTER_IMMERSIVE);
}
const bool isPcMode = system::GetBoolParameter("persist.sceneboard.ispcmode", false);
if (!onlySupportFullScreen && IsAnco() && IsFreeMultiWindowMode() &&
(!windowSystemConfig_.IsPcWindow() || isPcMode) && IsAncoSupportFreeWindow()) {
MaximizeForCompatibleMode();
}
}
}
uint32_t WindowSceneSessionImpl::UpdateConfigVal(uint32_t minVal, uint32_t maxVal, uint32_t configVal,
uint32_t defaultVal, float vpr)
{
bool validConfig = minVal < (configVal * vpr) && (configVal * vpr) < maxVal;
return validConfig ? static_cast<uint32_t>(configVal * vpr) : static_cast<uint32_t>(defaultVal * vpr);
}
uint32_t WindowSceneSessionImpl::UpdateConfigValInVP(uint32_t minVal, uint32_t maxVal, uint32_t configVal,
uint32_t defaultVal, float vpr)
{
bool validConfig = minVal < (configVal * vpr) && (configVal * vpr) < maxVal;
return validConfig ? configVal : defaultVal;
}
void WindowSceneSessionImpl::ApplyForcibleLimits(
WindowLimits& sysLimitsPX, WindowLimits& sysLimitsVP, float vpr, SystemPermissionChecker systemPermChecker)
{
bool isWindowLimitsForcible = property_->GetIsWindowLimitsForcible();
if (!isWindowLimitsForcible) {
TLOGD(WmsLogTag::WMS_LAYOUT,
"The window limits are not forcible, no need to break system constraints.");
return;
}
if (!systemPermChecker()) {
TLOGW(WmsLogTag::WMS_LAYOUT,
"The caller doesn't have system permissions, cannot to break system constraints.");
return;
}
constexpr uint32_t FORCIBLE_MAX = static_cast<uint32_t>(INT32_MAX);
constexpr uint32_t FORCIBLE_MIN = 1;
sysLimitsPX.maxWidth_ = FORCIBLE_MAX;
sysLimitsPX.maxHeight_ = FORCIBLE_MAX;
sysLimitsPX.minWidth_ = std::min(sysLimitsPX.minWidth_, FORCIBLE_MIN);
sysLimitsPX.minHeight_ = std::min(sysLimitsPX.minHeight_, FORCIBLE_MIN);
sysLimitsVP.maxWidth_ = FORCIBLE_MAX;
sysLimitsVP.maxHeight_ = FORCIBLE_MAX;
sysLimitsVP.minWidth_ = std::min(sysLimitsVP.minWidth_, FORCIBLE_MIN);
sysLimitsVP.minHeight_ = std::min(sysLimitsVP.minHeight_, FORCIBLE_MIN);
}
std::pair<WindowLimits, WindowLimits> WindowSceneSessionImpl::GetSystemSizeLimits(uint32_t displayWidth,
uint32_t displayHeight,
float vpr)
{
WindowLimits systemLimits;
WindowLimits systemLimitsVP = WindowLimits::DEFAULT_VP_LIMITS();
const uint32_t configMaxSize = windowSystemConfig_.maxFloatingWindowSize_;
systemLimits.maxWidth_ = static_cast<uint32_t>(configMaxSize * vpr);
systemLimits.maxHeight_ = static_cast<uint32_t>(configMaxSize * vpr);
systemLimitsVP.maxWidth_ = configMaxSize;
systemLimitsVP.maxHeight_ = configMaxSize;
SetMinimumDimensions(systemLimits, systemLimitsVP, displayWidth, displayHeight, vpr);
ApplyForcibleLimits(systemLimits, systemLimitsVP, vpr, SessionPermission::IsSystemCalling);
TLOGI(WmsLogTag::WMS_LAYOUT,
"systemLimitsPX: %{public}s, systemLimitsVP: %{public}s, configMaxSize: %{public}u, "
"vpr: %{public}f, winType: %{public}u",
systemLimits.ToString().c_str(), systemLimitsVP.ToString().c_str(),
configMaxSize, vpr, GetType());
return std::make_pair(systemLimits, systemLimitsVP);
}
void WindowSceneSessionImpl::SetMinimumDimensions(WindowLimits& systemLimits, WindowLimits& systemLimitsVP,
uint32_t displayWidth, uint32_t displayHeight, float vpr)
{
const WindowType windowType = GetType();
if (WindowHelper::IsMainWindow(windowType)) {
ApplyConfiguredMinSizeToLimits(systemLimits, systemLimitsVP, displayWidth, displayHeight, vpr,
windowSystemConfig_.miniWidthOfMainWindow_,
windowSystemConfig_.miniHeightOfMainWindow_);
} else if (WindowHelper::IsSubWindow(windowType)) {
ApplyConfiguredMinSizeToLimits(systemLimits, systemLimitsVP, displayWidth, displayHeight, vpr,
windowSystemConfig_.miniWidthOfSubWindow_,
windowSystemConfig_.miniHeightOfSubWindow_);
} else if (WindowHelper::IsDialogWindow(windowType)) {
ApplyConfiguredMinSizeToLimits(systemLimits, systemLimitsVP, displayWidth, displayHeight, vpr,
windowSystemConfig_.miniWidthOfDialogWindow_,
windowSystemConfig_.miniHeightOfDialogWindow_);
} else if (WindowHelper::IsSystemWindow(windowType)) {
systemLimits.minWidth_ = 0;
systemLimits.minHeight_ = 0;
systemLimitsVP.minWidth_ = 0;
systemLimitsVP.minHeight_ = 0;
} else {
systemLimits.minWidth_ = static_cast<uint32_t>(MIN_FLOATING_WIDTH * vpr);
systemLimits.minHeight_ = static_cast<uint32_t>(MIN_FLOATING_HEIGHT * vpr);
systemLimitsVP.minWidth_ = MIN_FLOATING_WIDTH;
systemLimitsVP.minHeight_ = MIN_FLOATING_HEIGHT;
}
}
void WindowSceneSessionImpl::ApplyConfiguredMinSizeToLimits(WindowLimits& systemLimits, WindowLimits& systemLimitsVP,
uint32_t displayWidth, uint32_t displayHeight, float vpr,
uint32_t configMinWidth, uint32_t configMinHeight)
{
systemLimits.minWidth_ = UpdateConfigVal(0, displayWidth, configMinWidth, MIN_FLOATING_WIDTH, vpr);
systemLimits.minHeight_ = UpdateConfigVal(0, displayHeight, configMinHeight, MIN_FLOATING_HEIGHT, vpr);
systemLimitsVP.minWidth_ = UpdateConfigValInVP(0, displayWidth, configMinWidth, MIN_FLOATING_WIDTH, vpr);
systemLimitsVP.minHeight_ = UpdateConfigValInVP(0, displayHeight, configMinHeight, MIN_FLOATING_HEIGHT, vpr);
}
void WindowSceneSessionImpl::CalculateNewLimitsByLimits(WindowLimits& newLimits,
WindowLimits& newLimitsVP,
WindowLimits& customizedLimits,
float& virtualPixelRatio)
{
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT, "display is null");
return;
}
auto displayInfo = display->GetDisplayInfo();
if (displayInfo == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT, "displayInfo is null");
return;
}
uint32_t displayWidth = static_cast<uint32_t>(displayInfo->GetWidth());
uint32_t displayHeight = static_cast<uint32_t>(displayInfo->GetHeight());
if (displayWidth == 0 || displayHeight == 0) {
TLOGE(WmsLogTag::WMS_LAYOUT, "displayWidth or displayHeight is zero, displayId: %{public}" PRIu64,
property_->GetDisplayId());
return;
}
virtualPixelRatio = GetVirtualPixelRatio(displayInfo);
if (MathHelper::NearZero(virtualPixelRatio)) {
return;
}
const auto& [systemLimits, systemLimitsVP] = GetSystemSizeLimits(displayWidth, displayHeight, virtualPixelRatio);
customizedLimits = userLimitsSet_ ? property_->GetUserWindowLimits() : property_->GetConfigWindowLimitsVP();
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] CalcByLimits id:%{public}d, display=%{public}ux%{public}u vpr=%{public}f, "
"sys[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u], "
"user[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] unit:%{public}u userSet:%{public}d",
GetPersistentId(), displayWidth, displayHeight, virtualPixelRatio,
systemLimits.minWidth_, systemLimits.minHeight_, systemLimits.maxWidth_, systemLimits.maxHeight_,
customizedLimits.minWidth_, customizedLimits.minHeight_,
customizedLimits.maxWidth_, customizedLimits.maxHeight_,
customizedLimits.pixelUnit_, userLimitsSet_.load());
newLimits = systemLimits;
newLimitsVP = systemLimitsVP;
if (customizedLimits.pixelUnit_ == PixelUnit::VP) {
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] id:%{public}d, process VP path", GetPersistentId());
ProcessVirtualPixelLimits(newLimits, newLimitsVP, customizedLimits, systemLimitsVP, virtualPixelRatio);
} else {
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] id:%{public}d, process PX path", GetPersistentId());
ProcessPhysicalPixelLimits(newLimits, newLimitsVP, customizedLimits, systemLimits, virtualPixelRatio);
}
}
void WindowSceneSessionImpl::ProcessVirtualPixelLimits(WindowLimits& newLimits, WindowLimits& newLimitsVP,
const WindowLimits& customizedLimits,
const WindowLimits& systemLimitsVP, float virtualPixelRatio)
{
const uint32_t sysMinW = systemLimitsVP.minWidth_;
const uint32_t sysMinH = systemLimitsVP.minHeight_;
const uint32_t sysMaxW = systemLimitsVP.maxWidth_;
const uint32_t sysMaxH = systemLimitsVP.maxHeight_;
newLimitsVP.maxWidth_ = SafeBoundAssign(customizedLimits.maxWidth_, sysMinW, sysMaxW, sysMaxW);
newLimitsVP.maxHeight_ = SafeBoundAssign(customizedLimits.maxHeight_, sysMinH, sysMaxH, sysMaxH);
newLimitsVP.minWidth_ = SafeBoundAssign(customizedLimits.minWidth_, sysMinW, newLimitsVP.maxWidth_, sysMinW);
newLimitsVP.minHeight_ = SafeBoundAssign(customizedLimits.minHeight_, sysMinH, newLimitsVP.maxHeight_, sysMinH);
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] ProcessVP id:%{public}d, "
"result[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u]",
GetPersistentId(), newLimitsVP.minWidth_, newLimitsVP.minHeight_,
newLimitsVP.maxWidth_, newLimitsVP.maxHeight_);
RecalculatePxLimitsByVp(newLimitsVP, newLimits, virtualPixelRatio);
}
void WindowSceneSessionImpl::ProcessPhysicalPixelLimits(WindowLimits& newLimits, WindowLimits& newLimitsVP,
const WindowLimits& customizedLimits,
const WindowLimits& systemLimits, float virtualPixelRatio)
{
bool needAdjustMinBound = forceLimits_ && IsPcOrFreeMultiWindowCapabilityEnabled();
const uint32_t sysMinW = needAdjustMinBound ?
std::min(static_cast<uint32_t>(FORCE_LIMIT_MIN_FLOATING_WIDTH * virtualPixelRatio), systemLimits.minWidth_) :
systemLimits.minWidth_;
const uint32_t sysMinH = needAdjustMinBound ?
std::min(static_cast<uint32_t>(FORCE_LIMIT_MIN_FLOATING_HEIGHT * virtualPixelRatio), systemLimits.minHeight_) :
systemLimits.minHeight_;
const uint32_t sysMaxW = systemLimits.maxWidth_;
const uint32_t sysMaxH = systemLimits.maxHeight_;
newLimits.maxWidth_ = SafeBoundAssign(customizedLimits.maxWidth_, sysMinW, sysMaxW, sysMaxW);
newLimits.maxHeight_ = SafeBoundAssign(customizedLimits.maxHeight_, sysMinH, sysMaxH, sysMaxH);
newLimits.minWidth_ = SafeBoundAssign(customizedLimits.minWidth_, sysMinW, newLimits.maxWidth_, sysMinW);
newLimits.minHeight_ = SafeBoundAssign(customizedLimits.minHeight_, sysMinH, newLimits.maxHeight_, sysMinH);
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] ProcessPX id:%{public}d, "
"result[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] forceAdjust:%{public}d",
GetPersistentId(), newLimits.minWidth_, newLimits.minHeight_,
newLimits.maxWidth_, newLimits.maxHeight_, needAdjustMinBound);
RecalculateVpLimitsByPx(newLimits, newLimitsVP, virtualPixelRatio);
}
void WindowSceneSessionImpl::CalculateNewLimitsByRatio(WindowLimits& newLimits,
WindowLimits& newLimitsVP,
const WindowLimits& customizedLimits)
{
newLimits.maxRatio_ = customizedLimits.maxRatio_;
newLimits.minRatio_ = customizedLimits.minRatio_;
newLimitsVP.maxRatio_ = customizedLimits.maxRatio_;
newLimitsVP.minRatio_ = customizedLimits.minRatio_;
double maxRatio = FLT_MAX;
double minRatio = 0.0;
CalculateInitialRatioBounds(newLimits, maxRatio, minRatio);
ApplyCustomRatioConstraints(customizedLimits, maxRatio, minRatio);
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] CalcByRatio id:%{public}d, "
"maxRatio=%{public}f minRatio=%{public}f customMaxRatio=%{public}f customMinRatio=%{public}f",
GetPersistentId(), maxRatio, minRatio,
customizedLimits.maxRatio_, customizedLimits.minRatio_);
RecalculateSizeLimitsWithRatios(newLimits, newLimitsVP, maxRatio, minRatio, customizedLimits.pixelUnit_);
}
void WindowSceneSessionImpl::CalculateInitialRatioBounds(const WindowLimits& currentLimits,
double& maxRatio, double& minRatio)
{
if (currentLimits.minHeight_ != 0) {
maxRatio = static_cast<double>(currentLimits.maxWidth_) /
static_cast<double>(currentLimits.minHeight_);
}
if (currentLimits.maxHeight_ != 0) {
minRatio = static_cast<double>(currentLimits.minWidth_) /
static_cast<double>(currentLimits.maxHeight_);
}
}
void WindowSceneSessionImpl::ApplyCustomRatioConstraints(const WindowLimits& customizedLimits,
double& maxRatio, double& minRatio)
{
if (IsValueInRange(customizedLimits.maxRatio_, minRatio, maxRatio)) {
maxRatio = customizedLimits.maxRatio_;
}
if (IsValueInRange(customizedLimits.minRatio_, minRatio, maxRatio)) {
minRatio = customizedLimits.minRatio_;
}
}
void WindowSceneSessionImpl::RecalculateSizeLimitsWithRatios(WindowLimits& limits,
WindowLimits& limitsVP,
double maxRatio,
double minRatio,
PixelUnit pixelUnit)
{
const float vpr = limits.vpRatio_;
if (pixelUnit == PixelUnit::VP) {
RecalculateLimits(maxRatio, minRatio, limitsVP);
RecalculatePxLimitsByVp(limitsVP, limits, vpr);
} else {
RecalculateLimits(maxRatio, minRatio, limits);
RecalculateVpLimitsByPx(limits, limitsVP, vpr);
}
}
void WindowSceneSessionImpl::UpdateWindowSizeLimits(bool needNotifySession)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"WMS::WindowLimitsUpdate::CalcLimits id=%d", GetPersistentId());
WindowLimits customizedLimits;
WindowLimits newLimits;
WindowLimits newLimitsVP = WindowLimits::DEFAULT_VP_LIMITS();
float virtualPixelRatio = 0.0f;
CalculateNewLimitsByLimits(newLimits, newLimitsVP, customizedLimits, virtualPixelRatio);
if (MathHelper::NearZero(virtualPixelRatio)) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] vpr is zero, id:%{public}u", GetWindowId());
return;
}
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] AfterByLimits id:%{public}d, "
"px[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] "
"vp[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] vpr=%{public}f",
GetPersistentId(), newLimits.minWidth_, newLimits.minHeight_,
newLimits.maxWidth_, newLimits.maxHeight_,
newLimitsVP.minWidth_, newLimitsVP.minHeight_,
newLimitsVP.maxWidth_, newLimitsVP.maxHeight_, virtualPixelRatio);
newLimits.vpRatio_ = virtualPixelRatio;
newLimitsVP.vpRatio_ = virtualPixelRatio;
CalculateNewLimitsByRatio(newLimits, newLimitsVP, customizedLimits);
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] AfterByRatio id:%{public}d, "
"px[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] "
"vp[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u]",
GetPersistentId(), newLimits.minWidth_, newLimits.minHeight_,
newLimits.maxWidth_, newLimits.maxHeight_,
newLimitsVP.minWidth_, newLimitsVP.minHeight_,
newLimitsVP.maxWidth_, newLimitsVP.maxHeight_);
if (WindowHelper::IsSystemWindowButNotDialog(GetType()) && !userLimitsSet_) {
TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, set min limits to 1 px, preMinW:%{public}u, preMinH:%{public}u",
GetPersistentId(), newLimits.minWidth_, newLimits.minHeight_);
newLimits.minWidth_ = 1;
newLimits.minHeight_ = 1;
}
const WindowLimits& limitsToNotify =
(property_->GetUserWindowLimits().pixelUnit_ == PixelUnit::VP) ? newLimitsVP : newLimits;
property_->SetLimitsForAttachedWindows(limitsToNotify);
if (needNotifySession) {
NotifySessionSideLimitsChanged(limitsToNotify);
}
CalculateAttachedWindowLimitsIntersection(newLimits, newLimitsVP, virtualPixelRatio);
TLOGI_LMTBYID(TEN_SECONDS, RECORD_100_TIMES, GetPersistentId(), WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:CalcLimits] SaveLimits id:%{public}d, "
"px[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] "
"vp[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] vpr=%{public}f",
GetPersistentId(), newLimits.minWidth_, newLimits.minHeight_,
newLimits.maxWidth_, newLimits.maxHeight_,
newLimitsVP.minWidth_, newLimitsVP.minHeight_,
newLimitsVP.maxWidth_, newLimitsVP.maxHeight_, virtualPixelRatio);
property_->SetWindowLimits(newLimits);
property_->SetWindowLimitsVP(newLimitsVP);
property_->SetLastLimitsVpr(virtualPixelRatio);
}
void WindowSceneSessionImpl::CalculateAttachedWindowLimitsIntersection(
WindowLimits& newLimits, WindowLimits& newLimitsVP, float virtualPixelRatio)
{
if (!IsPcOrPadFreeMultiWindowMode()) {
TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, not in PC or free multi-window mode",
GetPersistentId());
return;
}
if (MathHelper::NearZero(virtualPixelRatio)) {
TLOGE(WmsLogTag::WMS_LAYOUT, "windowId:%{public}u, virtual pixel ratio is zero", GetWindowId());
return;
}
auto attachedLimitsList = property_->GetAttachedWindowLimitsList();
if (attachedLimitsList.empty()) {
TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, no attached limits", GetPersistentId());
return;
}
const bool isMainWindow = WindowHelper::IsMainWindow(GetType());
TLOGI(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, calc with %{public}zu wins, type=%{public}u",
GetPersistentId(), attachedLimitsList.size(), static_cast<uint32_t>(GetType()));
for (const auto& [sourceId, attachedLimits] : attachedLimitsList) {
AttachLimitOptions limitOptions = isMainWindow ? property_->GetAttachedLimitOptions(sourceId) :
AttachLimitOptions { property_->GetWindowAnchorInfo().attachOptions.isIntersectedHeightLimit,
property_->GetWindowAnchorInfo().attachOptions.isIntersectedWidthLimit };
if (!limitOptions.isIntersectedHeightLimit && !limitOptions.isIntersectedWidthLimit) {
continue;
}
auto result = CalcSingleWinIntersect(
newLimits, newLimitsVP, attachedLimits, limitOptions, virtualPixelRatio);
if (!result.pxValid || !result.vpValid) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, no intersect srcId=%{public}d (%{public}s)",
GetPersistentId(), sourceId, !result.pxValid ? "PX" : "VP");
continue;
}
newLimits = result.pxLimits;
newLimitsVP = result.vpLimits;
TLOGI(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, intersect srcId=%{public}d "
"PX[%{public}u,%{public}u,%{public}u,%{public}u] VP[%{public}u,%{public}u,%{public}u,%{public}u]",
GetPersistentId(), sourceId, newLimits.minWidth_, newLimits.maxWidth_,
newLimits.minHeight_, newLimits.maxHeight_, newLimitsVP.minWidth_,
newLimitsVP.maxWidth_, newLimitsVP.minHeight_, newLimitsVP.maxHeight_);
}
}
WindowSceneSessionImpl::WinIntersectResult WindowSceneSessionImpl::CalcSingleWinIntersect(
const WindowLimits& currentLimits,
const WindowLimits& currentLimitsVP,
const WindowLimits& attachedLimits,
const AttachLimitOptions& limitOptions,
float virtualPixelRatio)
{
WinIntersectResult result;
const bool intersectHeight = limitOptions.isIntersectedHeightLimit;
const bool intersectWidth = limitOptions.isIntersectedWidthLimit;
WindowLimits attachedLimitsPX;
if (attachedLimits.pixelUnit_ == PixelUnit::VP) {
RecalculatePxLimitsByVp(attachedLimits, attachedLimitsPX, virtualPixelRatio);
} else {
attachedLimitsPX = attachedLimits;
}
result.pxLimits = CalculateLimitsIntersection(currentLimits, attachedLimitsPX, intersectHeight,
intersectWidth);
result.pxValid = IsLimitsIntersectionValid(result.pxLimits, intersectHeight, intersectWidth);
WindowLimits attachedLimitsVP;
if (attachedLimits.pixelUnit_ == PixelUnit::PX) {
RecalculateVpLimitsByPx(attachedLimits, attachedLimitsVP, virtualPixelRatio);
} else {
attachedLimitsVP = attachedLimits;
}
result.vpLimits = CalculateLimitsIntersection(currentLimitsVP, attachedLimitsVP, intersectHeight,
intersectWidth);
result.vpValid = IsLimitsIntersectionValid(result.vpLimits, intersectHeight, intersectWidth);
return result;
}
void WindowSceneSessionImpl::NotifySessionSideLimitsChanged(const WindowLimits& limitsToNotify)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"WMS::WindowLimitsUpdate::NotifySession id=%d", GetPersistentId());
if (GetHostSession() == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:NotifySession] hostSession is null, id:%{public}u", GetWindowId());
return;
}
WindowType windowType = GetType();
bool shouldNotify = false;
if (WindowHelper::IsMainWindow(windowType)) {
auto attachedLimitOptionsList = property_->GetAttachedLimitOptionsList();
shouldNotify = !attachedLimitOptionsList.empty();
TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d is main window, has %{public}zu attached windows with limits",
GetWindowId(), attachedLimitOptionsList.size());
} else if (WindowHelper::IsSubWindow(windowType)) {
WindowAnchorInfo anchorInfo = property_->GetWindowAnchorInfo();
shouldNotify = anchorInfo.isAnchoredByAttach_ &&
(anchorInfo.attachOptions.isIntersectedWidthLimit ||
anchorInfo.attachOptions.isIntersectedHeightLimit);
TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d is sub window, isAnchoredByAttach=%{public}d, "
"isIntersectedWidthLimit=%{public}d, isIntersectedHeightLimit=%{public}d",
GetWindowId(), anchorInfo.isAnchoredByAttach_,
anchorInfo.attachOptions.isIntersectedWidthLimit,
anchorInfo.attachOptions.isIntersectedHeightLimit);
}
if (!shouldNotify) {
TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, no need to notify session side", GetWindowId());
return;
}
GetHostSession()->NotifyAttachedWindowsLimitsChanged(limitsToNotify);
TLOGI(WmsLogTag::WMS_LAYOUT, "Notified session side about window limits change for window "
"id=%{public}u, limitsToNotify: maxW=%{public}u, maxH=%{public}u, minW=%{public}u, minH=%{public}u, "
"pixelUnit=%{public}u", GetWindowId(), limitsToNotify.maxWidth_, limitsToNotify.maxHeight_,
limitsToNotify.minWidth_, limitsToNotify.minHeight_,
static_cast<uint32_t>(limitsToNotify.pixelUnit_));
}
void WindowSceneSessionImpl::PreLayoutOnShow(WindowType type, const sptr<DisplayInfo>& info)
{
std::shared_ptr<Ace::UIContent> uiContent = GetUIContentSharedPtr();
if (uiContent == nullptr) {
TLOGW(WmsLogTag::WMS_LIFE, "uiContent is null");
return;
}
if (type == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT && info != nullptr) {
uint64_t screenId = info->GetScreenId();
KeyboardLayoutParams params;
property_->GetKeyboardLayoutParamsByScreenId(screenId, params);
if (params.isEmpty()) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "Update prelayout failed, %{public}" PRIu64, screenId);
} else {
std::string dispName = info->GetName();
Rect newRect = (info->GetWidth() > info->GetHeight()) ?
params.LandscapeKeyboardRect_ : params.PortraitKeyboardRect_;
property_->SetRequestRect(newRect);
}
}
const auto& requestRect = GetRequestRect();
TLOGI(WmsLogTag::WMS_LIFE, "name: %{public}s, id: %{public}d, type: %{public}u, requestRect:%{public}s",
property_->GetWindowName().c_str(), GetPersistentId(), type, requestRect.ToString().c_str());
if (requestRect.width_ != 0 && requestRect.height_ != 0) {
UpdateViewportConfig(requestRect, WindowSizeChangeReason::RESIZE, nullptr, info);
if (auto hostSession = GetHostSession()) {
WSRect wsRect = { requestRect.posX_, requestRect.posY_, requestRect.width_, requestRect.height_ };
SetNotifySizeChangeFlag(true);
property_->SetWindowRect(requestRect);
hostSession->UpdateClientRect(wsRect);
} else {
TLOGE(WmsLogTag::WMS_LAYOUT, "hostSession is null");
}
}
uiContent->PreLayout();
}
WMError WindowSceneSessionImpl::Show(uint32_t reason, bool withAnimation, bool withFocus,
int32_t requestId, int32_t scbRequestId)
{
return Show(reason, withAnimation, withFocus, false, requestId, scbRequestId);
}
bool WindowSceneSessionImpl::isNeedWindowShow(uint32_t reason)
{
if (reason == static_cast<uint32_t>(WindowStateChangeReason::USER_SWITCH)) {
TLOGI(WmsLogTag::WMS_MULTI_USER, "Switch to current user, NotifyAfterForeground");
NotifyAfterForeground(true, false);
NotifyAfterDidForeground(reason);
RecordWindowLifecycleChange("user switch show");
return true;
}
if (reason == static_cast<uint32_t>(WindowStateChangeReason::PC_APP_IN_PAD)) {
TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d, PcAppInPad when unlock.", GetPersistentId());
NotifyAfterForeground(true, false);
NotifyAfterDidForeground(reason);
RecordWindowLifecycleChange("PcAppInPad when unlock");
return true;
}
return false;
}
WMError WindowSceneSessionImpl::Show(uint32_t reason, bool withAnimation, bool withFocus, bool waitAttach,
int32_t requestId, int32_t scbRequestId)
{
if (isNeedWindowShow(reason)) {
return WMError::WM_OK;
}
const auto type = GetType();
if (IsWindowSessionInvalid()) {
TLOGI(WmsLogTag::WMS_LIFE, "Window show failed, session is invalid, name: %{public}s, id: %{public}d",
property_->GetWindowName().c_str(), GetPersistentId());
RecordLifeCycleExceptionEvent(WMError::WM_ERROR_INVALID_WINDOW,
WMErrorReason::WM_REASON_WINDOW_SHOW_ERR, "window is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
TLOGI(WmsLogTag::WMS_LIFE, "[requestId: %{public}d][scbRequestId: %{public}d]Window show [name: %{public}s, "
"id: %{public}d, type: %{public}u], reason: %{public}u, state:%{public}u, requestState:%{public}u",
requestId, scbRequestId, property_->GetWindowName().c_str(),
property_->GetPersistentId(), type, reason, state_, requestState_);
auto isDecorEnable = IsDecorEnable();
UpdateDecorEnableToAce(isDecorEnable);
property_->SetDecorEnable(isDecorEnable);
if (state_ == WindowState::STATE_SHOWN) {
TLOGI(WmsLogTag::WMS_LIFE, "window is already shown [name:%{public}s, id:%{public}d, type: %{public}u]",
property_->GetWindowName().c_str(), property_->GetPersistentId(), type);
if (WindowHelper::IsMainWindow(type) ||
(WindowHelper::IsSubWindow(type) && IsLoosenedWithPcOrFreeMultiMode())) {
hostSession->RaiseAppMainWindowToTop();
}
NotifyAfterForeground(true, false);
NotifyAfterDidForeground(reason);
RefreshNoInteractionTimeoutMonitor();
RecordWindowLifecycleChange("already show");
return WMError::WM_OK;
}
auto displayInfo = GetDisplayInfo();
if (displayInfo == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "Window show failed, displayInfo is null, name: %{public}s, id: %{public}d",
property_->GetWindowName().c_str(), GetPersistentId());
return WMError::WM_ERROR_NULLPTR;
}
float density = GetVirtualPixelRatio(displayInfo);
if (!MathHelper::NearZero(virtualPixelRatio_ - density) ||
!MathHelper::NearZero(property_->GetLastLimitsVpr() - density)) {
UpdateDensityInner(displayInfo);
}
WMError ret = UpdateAnimationFlagProperty(withAnimation);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LIFE, "Window show failed, UpdateProperty failed, ret: %{public}d, name: %{public}s"
", id: %{public}d", static_cast<int32_t>(ret), property_->GetWindowName().c_str(), GetPersistentId());
return ret;
}
UpdateTitleButtonVisibility();
property_->SetFocusableOnShow(withFocus);
if (WindowHelper::IsMainWindow(type)) {
ret = static_cast<WMError>(hostSession->Foreground(property_, true, identityToken_));
} else if (WindowHelper::IsSystemOrSubWindow(type)) {
if (waitAttach && !lifecycleCallback_ && !WindowHelper::IsKeyboardWindow(type) &&
SysCapUtil::GetBundleName() != AppExecFwk::Constants::SCENE_BOARD_BUNDLE_NAME) {
lifecycleCallback_ = sptr<LifecycleFutureCallback>::MakeSptr();
TLOGI(WmsLogTag::WMS_LIFE, "init lifecycleCallback, id:%{public}d", GetPersistentId());
}
if (waitAttach && lifecycleCallback_) {
lifecycleCallback_->ResetAttachLock();
}
PreLayoutOnShow(type, displayInfo);
TLOGD(WmsLogTag::WMS_LIFE, "Show session [name: %{public}s, id: %{public}d]",
property_->GetWindowName().c_str(), GetPersistentId());
ret = static_cast<WMError>(hostSession->Show(property_));
} else {
ret = WMError::WM_ERROR_INVALID_WINDOW;
}
if (ret == WMError::WM_OK) {
UpdateSubWindowStateAndNotify(GetPersistentId(), WindowState::STATE_SHOWN);
state_ = WindowState::STATE_SHOWN;
requestState_ = WindowState::STATE_SHOWN;
NotifyAfterForeground(true, true, waitAttach);
NotifyAfterDidForeground(reason);
NotifyFreeMultiWindowModeResume();
RefreshNoInteractionTimeoutMonitor();
TLOGI(WmsLogTag::WMS_LIFE, "[requestId: %{public}d][scbRequestId: %{public}d]Window show success "
"[name:%{public}s, id:%{public}d, type:%{public}u]",
requestId, scbRequestId, property_->GetWindowName().c_str(), GetPersistentId(), type);
RecordWindowLifecycleChange("show");
} else {
RecordLifeCycleExceptionEvent(ret, WMErrorReason::WM_REASON_WINDOW_SHOW_ERR, "window show failed");
NotifyForegroundFailed(ret);
TLOGI(WmsLogTag::WMS_LIFE, "[requestId: %{public}d][scbRequestId: %{public}d]Window show failed with "
"errcode: %{public}d, name:%{public}s, id:%{public}d",
requestId, scbRequestId, static_cast<int32_t>(ret), property_->GetWindowName().c_str(), GetPersistentId());
}
NotifyWindowStatusChange(GetWindowMode());
NotifyWindowStatusDidChangeAfterShowWindow();
NotifyDisplayInfoChange(displayInfo);
return ret;
}
void WindowSceneSessionImpl::NotifyWindowStatusDidChangeAfterShowWindow()
{
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_IF_NULL(hostSession);
hostSession->NotifyWindowStatusDidChangeAfterShowWindow();
}
sptr<DisplayInfo> WindowSceneSessionImpl::GetDisplayInfo() const
{
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "not find, displayId: %{public}" PRIu64 ", persistentId: %{public}d",
property_->GetDisplayId(), GetPersistentId());
display = SingletonContainer::Get<DisplayManager>().GetDefaultDisplay();
if (display != nullptr) {
property_->SetDisplayId(display->GetId());
TLOGI(WmsLogTag::WMS_LIFE, "use default display id: %{public}" PRIu64, display->GetId());
} else {
TLOGE(WmsLogTag::WMS_LIFE, "failed, display is null, name: %{public}s, id: %{public}d",
property_->GetWindowName().c_str(), GetPersistentId());
return nullptr;
}
}
return display->GetDisplayInfo();
}
WMError WindowSceneSessionImpl::ShowKeyboard(
uint32_t callingWindowId, uint64_t tgtDisplayId, KeyboardEffectOption effectOption)
{
TLOGI(WmsLogTag::WMS_KEYBOARD, "CallingWindowId: %{public}d, effect option: %{public}s, %{public}" PRIu64,
callingWindowId, effectOption.ToString().c_str(), tgtDisplayId);
if (effectOption.viewMode_ >= KeyboardViewMode::VIEW_MODE_END) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "Invalid view mode: %{public}u. Use default mode",
static_cast<uint32_t>(effectOption.viewMode_));
effectOption.viewMode_ = KeyboardViewMode::NON_IMMERSIVE_MODE;
}
if (effectOption.flowLightMode_ >= KeyboardFlowLightMode::END) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "Invalid flow light mode: %{public}u. Use default mode",
static_cast<uint32_t>(effectOption.flowLightMode_));
effectOption.flowLightMode_ = KeyboardFlowLightMode::NONE;
}
if (effectOption.gradientMode_ >= KeyboardGradientMode::END) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "Invalid gradient mode: %{public}u. Use default mode",
static_cast<uint32_t>(effectOption.gradientMode_));
effectOption.gradientMode_ = KeyboardGradientMode::NONE;
}
property_->SetKeyboardEffectOption(effectOption);
if (property_->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_STATUS_BAR) {
property_->SetCallingSessionId(callingWindowId);
property_->SetKeyboardTargetDisplayId(tgtDisplayId);
}
return Show();
}
void WindowSceneSessionImpl::NotifyFreeMultiWindowModeResume()
{
TLOGI(WmsLogTag::WMS_MAIN, "IsPcMode %{public}d, isColdStart %{public}d", IsPcOrFreeMultiWindowCapabilityEnabled(),
isColdStart_);
if (IsPcOrFreeMultiWindowCapabilityEnabled() && !isColdStart_) {
isDidForeground_ = true;
NotifyAfterLifecycleResumed();
}
}
void WindowSceneSessionImpl::Resume(bool isGamePreLaunch)
{
TLOGI(WmsLogTag::WMS_LIFE, "isColdStart: %{public}d, isDidForeground: %{public}d, isGamePreLaunch:%{public}d",
isColdStart_, isDidForeground_, isGamePreLaunch);
isDidForeground_ = true;
isColdStart_ = false;
NotifyAfterLifecycleResumed(isGamePreLaunch);
}
void WindowSceneSessionImpl::Pause(bool isGamePreLaunch)
{
TLOGI(WmsLogTag::WMS_LIFE, "isColdStart: %{public}d isGamePreLaunch: %{public}d",
isColdStart_, isGamePreLaunch);
isColdStart_ = false;
NotifyAfterLifecyclePaused();
auto hostSession = GetHostSession();
if (isGamePreLaunch && hostSession) {
hostSession->OnSessionEvent(SessionEvent::EVENT_CLEAR_GAME_PRELAUNCH_FLAG);
}
}
WMError WindowSceneSessionImpl::Hide(uint32_t reason, bool withAnimation, bool isFromInnerkits)
{
return Hide(reason, withAnimation, isFromInnerkits, false);
}
WMError WindowSceneSessionImpl::Hide(uint32_t reason, bool withAnimation, bool isFromInnerkits, bool waitDetach)
{
if (reason == static_cast<uint32_t>(WindowStateChangeReason::USER_SWITCH)) {
TLOGI(WmsLogTag::WMS_MULTI_USER, "Switch to another user, NotifyAfterBackground");
NotifyAfterBackground(true, false);
NotifyAfterDidBackground(reason);
return WMError::WM_OK;
}
const auto type = GetType();
TLOGI(WmsLogTag::WMS_LIFE, "Window hide [id:%{public}d, type: %{public}d, reason:%{public}u, state:%{public}u, "
"requestState:%{public}u, isFromInnerkits:%{public}d",
GetPersistentId(), type, reason, state_, requestState_, isFromInnerkits);
if (IsWindowSessionInvalid()) {
TLOGI(WmsLogTag::WMS_LIFE, "session is invalid, id:%{public}d", GetPersistentId());
RecordLifeCycleExceptionEvent(WMError::WM_ERROR_INVALID_WINDOW,
WMErrorReason::WM_REASON_WINDOW_HIDE_ERR, "window is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
WindowState validState = state_;
if (WindowHelper::IsSubWindow(type) || WindowHelper::IsDialogWindow(type)) {
validState = requestState_;
}
if (validState == WindowState::STATE_HIDDEN || state_ == WindowState::STATE_CREATED) {
TLOGD(WmsLogTag::WMS_LIFE, "window is alreay hidden, id:%{public}d", property_->GetPersistentId());
NotifyBackgroundFailed(WMError::WM_DO_NOTHING);
RecordWindowLifecycleChange("already hide");
return WMError::WM_OK;
}
WMError res = UpdateAnimationFlagProperty(withAnimation);
if (res != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LIFE, "UpdateProperty failed with errCode:%{public}d", static_cast<int32_t>(res));
return res;
}
* main window no need to notify host, since host knows hide first
* main window notify host temporarily, since host background may failed
* need to SetActive(false) for host session before background
*/
if (WindowHelper::IsMainWindow(type)) {
res = static_cast<WMError>(SetActive(false));
if (res != WMError::WM_OK) {
return res;
}
res = static_cast<WMError>(hostSession->Background(true, identityToken_, isFromInnerkits));
} else if (WindowHelper::IsSystemOrSubWindow(type)) {
if (waitDetach && !lifecycleCallback_ && !WindowHelper::IsKeyboardWindow(type) &&
SysCapUtil::GetBundleName() != AppExecFwk::Constants::SCENE_BOARD_BUNDLE_NAME) {
lifecycleCallback_ = sptr<LifecycleFutureCallback>::MakeSptr();
TLOGI(WmsLogTag::WMS_LIFE, "init lifecycleCallback, id:%{public}d", GetPersistentId());
}
if (waitDetach && lifecycleCallback_) {
lifecycleCallback_->ResetDetachLock();
}
res = static_cast<WMError>(hostSession->Hide());
} else {
res = WMError::WM_ERROR_INVALID_WINDOW;
}
if (res == WMError::WM_OK) {
GetAttachStateSyncResult(waitDetach, false);
UpdateSubWindowState(type);
NotifyAfterDidBackground(reason);
state_ = WindowState::STATE_HIDDEN;
requestState_ = WindowState::STATE_HIDDEN;
isDidForeground_ = false;
if (!interactive_) {
hasFirstNotifyInteractive_ = false;
}
RecordWindowLifecycleChange("hide");
} else {
RecordLifeCycleExceptionEvent(res, WMErrorReason::WM_REASON_WINDOW_HIDE_ERR, "window hide failed");
TLOGI(WmsLogTag::WMS_LIFE, "Window hide failed, id:%{public}d, name:%{public}s, res:%{public}d",
GetPersistentId(), property_->GetWindowName().c_str(), static_cast<int32_t>(res));
NotifyBackgroundFailed(WMError::WM_DO_NOTHING);
}
CustomHideAnimation();
NotifyWindowStatusChange(GetWindowMode());
NotifyWindowStatusDidChange(GetWindowMode());
escKeyEventTriggered_ = false;
TLOGI(WmsLogTag::WMS_LIFE, "Window hide end, id:%{public}d, type: %{public}d",
property_->GetPersistentId(), type);
return res;
}
void WindowSceneSessionImpl::CustomHideAnimation()
{
uint32_t animationFlag = property_->GetAnimationFlag();
if (animationFlag == static_cast<uint32_t>(WindowAnimation::CUSTOM)) {
std::vector<sptr<IAnimationTransitionController>> animationTransitionControllers;
{
std::lock_guard<std::mutex> lockListener(transitionControllerMutex_);
animationTransitionControllers = animationTransitionControllers_;
}
for (auto animationTransitionController : animationTransitionControllers) {
if (animationTransitionController != nullptr) {
animationTransitionController->AnimationForHidden();
}
}
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
}
}
WMError WindowSceneSessionImpl::NotifyDrawingCompleted()
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LIFE, "session is invalid, id:%{public}d", GetPersistentId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
const auto type = GetType();
WMError res = WindowHelper::IsMainWindow(type) ?
static_cast<WMError>(hostSession_->DrawingCompleted()) :
WMError::WM_ERROR_INVALID_WINDOW;
if (res == WMError::WM_OK) {
TLOGI(WmsLogTag::WMS_LIFE, "success id:%{public}d, type:%{public}d",
GetPersistentId(), type);
}
return res;
}
WMError WindowSceneSessionImpl::NotifyRemoveStartingWindow()
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_STARTUP_PAGE, "session is invalid, id:%{public}d", GetPersistentId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
WMError res = WindowHelper::IsMainWindow(GetType()) ?
static_cast<WMError>(hostSession->RemoveStartingWindow()) :
WMError::WM_ERROR_INVALID_WINDOW;
if (res == WMError::WM_OK) {
property_->SetAppBufferReady(true);
TLOGI(WmsLogTag::WMS_STARTUP_PAGE, "success id:%{public}d", GetPersistentId());
}
return res;
}
void WindowSceneSessionImpl::UpdateSubWindowState(const WindowType& type)
{
UpdateSubWindowStateAndNotify(GetPersistentId(), WindowState::STATE_HIDDEN);
if (WindowHelper::IsSubWindow(type)) {
if (state_ == WindowState::STATE_SHOWN) {
NotifyAfterBackground(true, true);
}
} else {
NotifyAfterBackground(true, true);
}
}
void WindowSceneSessionImpl::PreProcessCreate()
{
SetDefaultProperty();
}
void WindowSceneSessionImpl::SetDefaultProperty()
{
switch (property_->GetWindowType()) {
case WindowType::WINDOW_TYPE_TOAST:
case WindowType::WINDOW_TYPE_FLOAT:
case WindowType::WINDOW_TYPE_SYSTEM_FLOAT:
case WindowType::WINDOW_TYPE_FLOAT_CAMERA:
case WindowType::WINDOW_TYPE_VOICE_INTERACTION:
case WindowType::WINDOW_TYPE_SEARCHING_BAR:
case WindowType::WINDOW_TYPE_SCREENSHOT:
case WindowType::WINDOW_TYPE_GLOBAL_SEARCH:
case WindowType::WINDOW_TYPE_DIALOG:
case WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW:
case WindowType::WINDOW_TYPE_PANEL:
case WindowType::WINDOW_TYPE_LAUNCHER_DOCK:
case WindowType::WINDOW_TYPE_WALLET_SWIPE_CARD:
case WindowType::WINDOW_TYPE_MUTISCREEN_COLLABORATION:
case WindowType::WINDOW_TYPE_MAGNIFICATION:
case WindowType::WINDOW_TYPE_MAGNIFICATION_MENU:
case WindowType::WINDOW_TYPE_SELECTION:
case WindowType::WINDOW_TYPE_DYNAMIC: {
property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
break;
}
case WindowType::WINDOW_TYPE_VOLUME_OVERLAY:
case WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT:
case WindowType::WINDOW_TYPE_INPUT_METHOD_STATUS_BAR:
case WindowType::WINDOW_TYPE_DOCK_SLICE:
case WindowType::WINDOW_TYPE_STATUS_BAR:
case WindowType::WINDOW_TYPE_NAVIGATION_BAR:
case WindowType::WINDOW_TYPE_FLOAT_NAVIGATION: {
property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
property_->SetFocusable(false);
break;
}
case WindowType::WINDOW_TYPE_SYSTEM_TOAST: {
property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
property_->SetTouchable(false);
property_->SetFocusable(false);
break;
}
case WindowType::WINDOW_TYPE_POINTER: {
property_->SetFocusable(false);
break;
}
case WindowType::WINDOW_TYPE_SCREEN_CONTROL: {
property_->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
property_->SetTouchable(false);
property_->SetFocusable(false);
SetAlpha(0);
break;
}
default:
break;
}
}
WMError WindowSceneSessionImpl::DestroyInner(bool needNotifyServer, bool isFromInnerkits)
{
WMError ret = WMError::WM_OK;
if (!WindowHelper::IsMainWindow(GetType()) && needNotifyServer) {
if (WindowHelper::IsSystemWindow(GetType())) {
ret = SyncDestroyAndDisconnectSpecificSession(property_->GetPersistentId());
} else if (WindowHelper::IsSubWindow(GetType()) && !property_->GetIsUIExtFirstSubWindow()) {
auto parentSession = FindParentSessionByParentId(GetParentId());
if ((parentSession == nullptr || parentSession->GetHostSession() == nullptr) &&
!property_->GetIsCrossProcessWindow()) {
return WMError::WM_ERROR_NULLPTR;
}
ret = SyncDestroyAndDisconnectSpecificSession(property_->GetPersistentId());
} else if (property_->GetIsUIExtFirstSubWindow()) {
ret = SyncDestroyAndDisconnectSpecificSession(property_->GetPersistentId());
}
}
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LIFE, "DestroyInner fail, ret:%{public}d", ret);
RecordLifeCycleExceptionEvent(ret, WMErrorReason::WM_REASON_WINDOW_DESTROY_ERR, "window destroy failed");
return ret;
}
if (WindowHelper::IsMainWindow(GetType())) {
if (auto hostSession = GetHostSession()) {
ret = static_cast<WMError>(hostSession->Disconnect(true, identityToken_, isFromInnerkits));
RecordLifeCycleExceptionEvent(ret, WMErrorReason::WM_REASON_WINDOW_DESTROY_ERR, "window disconnect failed");
}
}
return ret;
}
WMError WindowSceneSessionImpl::SyncDestroyAndDisconnectSpecificSession(int32_t persistentId)
{
WMError ret = WMError::WM_OK;
if (SysCapUtil::GetBundleName() == AppExecFwk::Constants::SCENE_BOARD_BUNDLE_NAME) {
TLOGI(WmsLogTag::WMS_LIFE, "Destroy window is scb window");
WMErrorResult result =
SingletonContainer::Get<WindowAdapter>().DestroyAndDisconnectSpecificSession(persistentId);
ret = result.errCode;
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LIFE,
"DestroyAndDisconnectSpecificSession failed, errCode: %{public}d, msg: %{public}s",
result.errCode, result.errMsg.c_str());
}
return ret;
}
sptr<PatternDetachCallback> callback = sptr<PatternDetachCallback>::MakeSptr();
WMErrorResult result =
SingletonContainer::Get<WindowAdapter>().DestroyAndDisconnectSpecificSessionWithDetachCallback(persistentId,
callback->AsObject());
ret = result.errCode;
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LIFE,
"DestroyAndDisconnectSpecificSessionWithDetachCallback failed, errCode: %{public}d, msg: %{public}s",
result.errCode, result.errMsg.c_str());
return ret;
}
auto startTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
if (!WindowHelper::IsSubWindow(GetType())) {
callback->GetResult(WINDOW_DETACH_TIMEOUT);
}
auto endTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
auto waitTime = endTime - startTime;
if (waitTime >= WINDOW_DETACH_TIMEOUT) {
TLOGW(WmsLogTag::WMS_LIFE, "Destroy window timeout, persistentId:%{public}d", persistentId);
RecordLifeCycleExceptionEvent(ret, WMErrorReason::WM_REASON_WINDOW_DESTROY_ERR, "window detach timeout");
}
TLOGI(WmsLogTag::WMS_LIFE, "Destroy window persistentId:%{public}d waitTime:%{public}lld", persistentId, waitTime);
return ret;
}
WMError WindowSceneSessionImpl::DestroyHookWindow()
{
TLOGI(WmsLogTag::WMS_LIFE, "in");
InputTransferStation::GetInstance().RemoveInputWindow(GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LIFE, "session invalid, id: %{public}d", GetPersistentId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
state_ = WindowState::STATE_DESTROYED;
requestState_ = WindowState::STATE_DESTROYED;
}
DestroySubWindow();
{
std::unique_lock<std::shared_mutex> lock(windowSessionMutex_);
windowSessionMap_.erase(property_->GetWindowName());
}
{
std::lock_guard<std::mutex> lock(hostSessionMutex_);
hostSession_ = nullptr;
}
NotifyAfterDestroy();
ClearListenersById(GetPersistentId());
ClearVsyncStation();
SetUIContentComplete();
TLOGI(WmsLogTag::WMS_LIFE, "Destroy hook window success, id: %{public}d", property_->GetPersistentId());
return WMError::WM_OK;
}
WindowLifeCycleInfo WindowSceneSessionImpl::GetWindowLifecycleInfo() const
{
WindowLifeCycleInfo lifeCycleInfo;
lifeCycleInfo.windowId = GetPersistentId();
lifeCycleInfo.windowType = GetType();
lifeCycleInfo.windowName = GetWindowName();
return lifeCycleInfo;
}
WMError WindowSceneSessionImpl::Destroy(bool needNotifyServer, bool needClearListener, uint32_t reason,
bool isFromInnerkits)
{
TLOGI(WmsLogTag::WMS_LIFE, "Destroy start, id:%{public}d, state:%{public}u, needNotifyServer:%{public}d, "
"needClearListener:%{public}d, reason:%{public}u, isFromInnerkits:%{public}d", GetPersistentId(), state_,
needNotifyServer, needClearListener, reason, isFromInnerkits);
if (reason == static_cast<uint32_t>(WindowStateChangeReason::ABILITY_HOOK)) {
return DestroyHookWindow();
}
InputTransferStation::GetInstance().RemoveInputWindow(GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LIFE, "session invalid, id: %{public}d", GetPersistentId());
RecordLifeCycleExceptionEvent(WMError::WM_ERROR_INVALID_WINDOW,
WMErrorReason::WM_REASON_WINDOW_DESTROY_ERR, "window is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
WindowInspector::GetInstance().UnregisterGetWMSWindowListCallback(GetWindowId());
SingletonContainer::Get<WindowAdapter>().UnregisterSessionRecoverCallbackFunc(property_->GetPersistentId());
auto ret = DestroyInner(needNotifyServer, isFromInnerkits);
if (ret != WMError::WM_OK && ret != WMError::WM_ERROR_NULLPTR &&
!(WindowHelper::IsMainWindow(GetType()) && ret == WMError::WM_ERROR_IPC_FAILED)) {
WLOGFW("Destroy window failed, id: %{public}d", GetPersistentId());
return ret;
}
RecordWindowLifecycleChange("destroy");
WindowLifeCycleInfo windowLifeCycleInfo = GetWindowLifecycleInfo();
SingletonContainer::Get<WindowManager>().NotifyWMSWindowDestroyed(windowLifeCycleInfo);
NotifyBeforeDestroy(GetWindowName());
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
state_ = WindowState::STATE_DESTROYED;
requestState_ = WindowState::STATE_DESTROYED;
}
DestroySubWindow();
{
std::unique_lock<std::shared_mutex> lock(windowSessionMutex_);
windowSessionMap_.erase(property_->GetWindowName());
}
{
std::lock_guard<std::mutex> lock(hostSessionMutex_);
hostSession_ = nullptr;
}
NotifyAfterDestroy();
if (needClearListener) {
ClearListenersById(GetPersistentId());
}
auto context = GetContext();
if (context) {
context.reset();
}
ClearVsyncStation();
SetUIContentComplete();
surfaceNode_ = nullptr;
RSTransactionAdapter::FlushImplicitTransaction(GetRSUIContext());
TLOGI(WmsLogTag::WMS_LIFE, "Destroy success, id: %{public}d", property_->GetPersistentId());
return WMError::WM_OK;
}
void WindowSceneSessionImpl::CheckMoveConfiguration(MoveConfiguration& moveConfiguration)
{
std::vector<DisplayId> displayIds = SingletonContainer::Get<DisplayManagerAdapter>().GetAllDisplayIds();
if (std::find(displayIds.begin(), displayIds.end(), moveConfiguration.displayId) ==
displayIds.end()) {
TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d not find displayId moveConfiguration %{public}s",
property_->GetPersistentId(), moveConfiguration.ToString().c_str());
moveConfiguration.displayId = DISPLAY_ID_INVALID;
}
}
WMError WindowSceneSessionImpl::MoveTo(int32_t x, int32_t y, bool isMoveToGlobal, MoveConfiguration moveConfiguration)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"CUSTOM_ANIMATOR_WMS::WindowRectUpdate::ClientReq::MoveTo id=%d [%d,%d]", property_->GetPersistentId(), x, y);
TLOGI_LMT(TEN_SECONDS, RECORD_100_TIMES, WmsLogTag::WMS_LAYOUT,
"Id:%{public}d MoveTo:(%{public}d %{public}d) global:%{public}d cfg:%{public}s",
property_->GetPersistentId(), x, y, isMoveToGlobal, moveConfiguration.ToString().c_str());
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (property_->GetWindowType() == WindowType::WINDOW_TYPE_PIP) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Unsupported operation for pip window");
return WMError::WM_ERROR_INVALID_OPERATION;
}
const auto& windowRect = GetRect();
const auto& requestRect = GetRequestRect();
Rect newRect = { x, y, requestRect.width_, requestRect.height_ };
TLOGI_LMT(TEN_SECONDS, RECORD_100_TIMES, WmsLogTag::WMS_LAYOUT,
"Id:%{public}d state:%{public}d type:%{public}d mode:%{public}d rect:"
"%{public}s->%{public}s req=%{public}s", property_->GetPersistentId(), state_, GetType(), GetWindowMode(),
windowRect.ToString().c_str(), newRect.ToString().c_str(), requestRect.ToString().c_str());
property_->SetRequestRect(newRect);
CheckMoveConfiguration(moveConfiguration);
WSRect wsRect = { newRect.posX_, newRect.posY_, newRect.width_, newRect.height_ };
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
auto ret = hostSession->UpdateSessionRect(wsRect, SizeChangeReason::MOVE, isMoveToGlobal, false, moveConfiguration);
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::MoveToAsync(int32_t x, int32_t y, MoveConfiguration moveConfiguration)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::MoveToAsync");
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) {
TLOGW(WmsLogTag::WMS_LAYOUT, "window should not move, winId:%{public}u, mode:%{public}u",
GetWindowId(), GetWindowMode());
return WMError::WM_ERROR_INVALID_OP_IN_CUR_STATUS;
}
auto ret = MoveTo(x, y, false, moveConfiguration);
if (state_ == WindowState::STATE_SHOWN) {
layoutCallback_->ResetMoveToLock();
auto startTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
layoutCallback_->GetMoveToAsyncResult(WINDOW_LAYOUT_TIMEOUT);
auto endTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
auto waitTime = endTime - startTime;
if (waitTime >= WINDOW_LAYOUT_TIMEOUT) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Layout timeout, Id:%{public}d", property_->GetPersistentId());
layoutCallback_->GetMoveToAsyncResult(WINDOW_LAYOUT_TIMEOUT);
}
}
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::MoveWindowToGlobal(int32_t x, int32_t y, MoveConfiguration moveConfiguration)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::MoveWindowToGlobal");
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"[WindowRectUpdate:ClientReq] MoveWindowToGlobal skip: session invalid, id:%{public}d",
property_->GetPersistentId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) {
TLOGW(WmsLogTag::WMS_LAYOUT,
"[WindowRectUpdate:ClientReq] MoveWindowToGlobal skip: not floating, id:%{public}d, mode:%{public}u",
GetWindowId(), static_cast<uint32_t>(GetWindowMode()));
return WMError::WM_ERROR_INVALID_OP_IN_CUR_STATUS;
}
if (property_->GetWindowType() == WindowType::WINDOW_TYPE_PIP) {
TLOGW(WmsLogTag::WMS_LAYOUT, "[WindowRectUpdate:ClientReq] MoveWindowToGlobal skip: pip window, id:%{public}d",
property_->GetPersistentId());
return WMError::WM_ERROR_INVALID_OPERATION;
}
const auto& windowRect = GetRect();
const auto& requestRect = GetRequestRect();
Rect newRect = { x, y, requestRect.width_, requestRect.height_ };
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowRectUpdate:ClientReq] MoveWindowToGlobal id:%{public}d, curRect=%{public}s, newRect=%{public}s, "
"moveConfig=%{public}s",
property_->GetPersistentId(), windowRect.ToString().c_str(), newRect.ToString().c_str(),
moveConfiguration.ToString().c_str());
property_->SetRequestRect(newRect);
CheckMoveConfiguration(moveConfiguration);
WSRect wsRect = { newRect.posX_, newRect.posY_, newRect.width_, newRect.height_ };
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
auto ret = hostSession->UpdateSessionRect(wsRect, SizeChangeReason::MOVE, false, true, moveConfiguration);
if (state_ == WindowState::STATE_SHOWN) {
layoutCallback_->ResetMoveToLock();
auto startTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
layoutCallback_->GetMoveToAsyncResult(WINDOW_LAYOUT_TIMEOUT);
auto endTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
auto waitTime = endTime - startTime;
if (waitTime >= WINDOW_LAYOUT_TIMEOUT) {
TLOGW(WmsLogTag::WMS_LAYOUT,
"[WindowRectUpdate:ClientReq] MoveWindowToGlobal layout timeout, id:%{public}d, waitTime:%{public}lld",
property_->GetPersistentId(), static_cast<long long>(waitTime));
layoutCallback_->GetMoveToAsyncResult(WINDOW_LAYOUT_TIMEOUT);
}
}
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::MoveWindowToGlobalDisplay(
int32_t x, int32_t y, MoveConfiguration )
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER,
"CUSTOM_ANIMATOR_WindowSceneSessionImpl::MoveWindowToGlobalDisplay");
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid session");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto mode = GetWindowMode();
if (mode != WindowMode::WINDOW_MODE_FLOATING) {
TLOGW(WmsLogTag::WMS_LAYOUT, "window should not move, windowId: %{public}u, mode: %{public}u",
GetWindowId(), mode);
return WMError::WM_ERROR_INVALID_OP_IN_CUR_STATUS;
}
auto winId = GetPersistentId();
const auto curGlobalDisplayRect = GetGlobalDisplayRect();
if (curGlobalDisplayRect.IsSamePosition(x, y)) {
TLOGW(WmsLogTag::WMS_LAYOUT, "windowId: %{public}u, request same position: [%{public}d, %{public}d]",
winId, x, y);
return WMError::WM_OK;
}
const auto requestRect = GetRequestRect();
if (Rect::IsRightBottomOverflow(x, y, requestRect.width_, requestRect.height_)) {
TLOGE(WmsLogTag::WMS_LAYOUT, "windowId: %{public}d, illegal position: [%{public}d, %{public}d]", winId, x, y);
return WMError::WM_ERROR_ILLEGAL_PARAM;
}
WSRect newGlobalDisplayRect = { x, y, requestRect.width_, requestRect.height_ };
TLOGI(WmsLogTag::WMS_LAYOUT, "windowId: %{public}d, newGlobalDisplayRect: %{public}s",
winId, newGlobalDisplayRect.ToString().c_str());
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
auto ret = hostSession->UpdateGlobalDisplayRectFromClient(newGlobalDisplayRect, SizeChangeReason::MOVE);
if (state_ == WindowState::STATE_SHOWN) {
layoutCallback_->ResetMoveWindowToGlobalDisplayLock();
const auto now = [] {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
};
const auto startTime = now();
layoutCallback_->GetMoveWindowToGlobalDisplayAsyncResult(WINDOW_LAYOUT_TIMEOUT);
const auto waitDuration = now() - startTime;
if (waitDuration >= WINDOW_LAYOUT_TIMEOUT) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Window layout timeout, windowId: %{public}d", winId);
layoutCallback_->GetMoveWindowToGlobalDisplayAsyncResult(WINDOW_LAYOUT_TIMEOUT);
}
}
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::GetGlobalScaledRect(Rect& globalScaledRect, bool useHookedSize)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::GetGlobalScaledRect");
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
auto ret = hostSession->GetGlobalScaledRect(globalScaledRect);
TLOGI(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, globalScaledRect:%{public}s, ret:%{public}d",
GetPersistentId(), globalScaledRect.ToString().c_str(), ret);
if (WMError::WM_OK == static_cast<WMError>(ret)) {
Rect realRect = globalScaledRect;
Rect hookedRect = globalScaledRect;
HookWindowSizeByHookWindowInfo(hookedRect);
TLOGD(WmsLogTag::WMS_LAYOUT,
"HookWindowSize[GetGlobalScaledRect], id:%{public}d, realRect:%{public}s, hookedRect:%{public}s, "
"useHookedSize:%{public}d",
GetPersistentId(), realRect.ToString().c_str(), hookedRect.ToString().c_str(), useHookedSize);
if (useHookedSize) {
globalScaledRect = hookedRect;
}
}
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::GetEventOriginalPosition(const EventPositionInfo& eventPositionInfo,
EventPositionInfo& originalEventPositionInfo) const
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_EVENT, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
originalEventPositionInfo = eventPositionInfo;
if (FoldScreenStateInternel::IsSuperFoldDisplayDevice() &&
property_->GetDisplayId() == DISPLAY_ID_C &&
DisplayManager::GetInstance().GetFoldStatus() == FoldStatus::HALF_FOLD &&
superFoldOffsetY_ != -1 && !IsWindowDelayRaiseEnabled()) {
if (originalEventPositionInfo.displayY != EventPositionInfo::INVALID_INT32) {
originalEventPositionInfo.displayY += superFoldOffsetY_;
}
if (originalEventPositionInfo.displayYPos != EventPositionInfo::INVALID_DOUBLE) {
originalEventPositionInfo.displayYPos += superFoldOffsetY_;
}
TLOGD(WmsLogTag::WMS_EVENT, "displayY:%{private}d, displayYPos:%{private}f",
originalEventPositionInfo.displayY, originalEventPositionInfo.displayYPos);
}
return WMError::WM_OK;
}
void WindowSceneSessionImpl::LimitCameraFloatWindowMininumSize(uint32_t& width, uint32_t& height, float& vpr)
{
if (GetType() != WindowType::WINDOW_TYPE_FLOAT_CAMERA) {
return;
}
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display == nullptr) {
WLOGFE("get display failed displayId:%{public}" PRIu64, property_->GetDisplayId());
return;
}
auto displayInfo = display->GetDisplayInfo();
if (displayInfo == nullptr) {
WLOGFE("get displayInfo failed displayId:%{public}" PRIu64, property_->GetDisplayId());
return;
}
uint32_t displayWidth = static_cast<uint32_t>(display->GetWidth());
uint32_t displayHeight = static_cast<uint32_t>(display->GetHeight());
if (displayWidth == 0 || displayHeight == 0) {
return;
}
vpr = GetVirtualPixelRatio(displayInfo);
uint32_t smallWidth = displayHeight <= displayWidth ? displayHeight : displayWidth;
float hwRatio = static_cast<float>(displayHeight) / static_cast<float>(displayWidth);
uint32_t minWidth;
if (smallWidth <= static_cast<uint32_t>(600 * vpr)) {
if (displayWidth <= displayHeight) {
minWidth = static_cast<uint32_t>(smallWidth * 0.3);
} else {
minWidth = static_cast<uint32_t>(smallWidth * 0.5);
}
} else {
if (displayWidth <= displayHeight) {
minWidth = static_cast<uint32_t>(smallWidth * 0.12);
} else {
minWidth = static_cast<uint32_t>(smallWidth * 0.3);
}
}
width = (width < minWidth) ? minWidth : width;
height = static_cast<uint32_t>(width * hwRatio);
}
void WindowSceneSessionImpl::UpdateFloatingWindowSizeBySizeLimits(uint32_t& width, uint32_t& height) const
{
if (property_->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) {
TLOGD(WmsLogTag::WMS_LAYOUT, "float camera type window");
return;
}
const auto& sizeLimits = property_->GetWindowLimits();
if (!WindowHelper::IsSystemWindow(property_->GetWindowType()) ||
property_->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
width = std::max(sizeLimits.minWidth_, width);
height = std::max(sizeLimits.minHeight_, height);
}
width = std::min(sizeLimits.maxWidth_, width);
height = std::min(sizeLimits.maxHeight_, height);
if (height == 0) {
return;
}
float curRatio = static_cast<float>(width) / static_cast<float>(height);
if (!WindowHelper::IsMainFloatingWindow(property_->GetWindowType(), GetWindowMode()) ||
(!MathHelper::GreatNotEqual(sizeLimits.minRatio_, curRatio) &&
!MathHelper::GreatNotEqual(curRatio, sizeLimits.maxRatio_))) {
return;
}
float newRatio = curRatio < sizeLimits.minRatio_ ? sizeLimits.minRatio_ : sizeLimits.maxRatio_;
if (MathHelper::NearZero(newRatio)) {
return;
}
if (sizeLimits.maxWidth_ == sizeLimits.minWidth_) {
height = static_cast<uint32_t>(static_cast<float>(width) / newRatio);
return;
}
if (sizeLimits.maxHeight_ == sizeLimits.minHeight_) {
width = static_cast<uint32_t>(static_cast<float>(height) * newRatio);
return;
}
WLOGFD("After limit by customize config: %{public}u %{public}u", width, height);
}
void WindowSceneSessionImpl::LimitWindowSize(uint32_t& width, uint32_t& height)
{
float vpr = 0.0f;
LimitCameraFloatWindowMininumSize(width, height, vpr);
if (!MathHelper::NearZero(vpr) || !MathHelper::NearZero(property_->GetLastLimitsVpr() - vpr)) {
UpdateWindowSizeLimits();
}
UpdateFloatingWindowSizeBySizeLimits(width, height);
}
WMError WindowSceneSessionImpl::CheckAndModifyWindowRect(uint32_t& width, uint32_t& height)
{
if (width == 0 || height == 0) {
TLOGE(WmsLogTag::WMS_LAYOUT, "width or height should greater than 0!");
return WMError::WM_ERROR_INVALID_PARAM;
}
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (property_->GetWindowType() == WindowType::WINDOW_TYPE_PIP) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Unsupported operation for pip window");
return WMError::WM_ERROR_INVALID_OPERATION;
}
if (GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING && !IsFullScreenPcAppInPadMode()) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Fullscreen window could not resize, winId: %{public}u", GetWindowId());
return WMError::WM_ERROR_INVALID_OPERATION;
}
if (IsFullScreenPcAppInPadMode() && IsFullScreenEnable()) {
NotifyClientWindowSize();
return WMError::WM_ERROR_INVALID_OPERATION;
}
LimitWindowSize(width, height);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::Resize(uint32_t width, uint32_t height)
{
auto reason = SizeChangeReason::RESIZE;
if (isResizedByLimit_) {
reason = SizeChangeReason::RESIZE_BY_LIMIT;
isResizedByLimit_ = false;
}
const auto& preRect = GetRect();
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"CUSTOM_ANIMATOR_WMS::WindowRectUpdate::ClientReq::Resize id=%d [%u,%u]",
property_->GetPersistentId(), width, height);
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowRectUpdate:ClientReq] Resize id:%{public}d, preRect=%{public}s, size=%{public}ux%{public}u",
property_->GetPersistentId(), preRect.ToString().c_str(), width, height);
if (CheckAndModifyWindowRect(width, height) != WMError::WM_OK) {
return WMError::WM_ERROR_INVALID_OPERATION;
}
const auto& windowRect = GetRect();
const auto& requestRect = GetRequestRect();
Rect newRect = { requestRect.posX_, requestRect.posY_, width, height };
TLOGI(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, state: %{public}d, type: %{public}d, mode: %{public}d, requestRect: "
"%{public}s, windowRect: %{public}s, newRect: %{public}s",
property_->GetPersistentId(), state_, GetType(), GetWindowMode(), requestRect.ToString().c_str(),
windowRect.ToString().c_str(), newRect.ToString().c_str());
property_->SetRequestRect(newRect);
WSRect wsRect = { newRect.posX_, newRect.posY_, newRect.width_, newRect.height_ };
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
auto ret = hostSession->UpdateSessionRect(wsRect, reason);
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::ResizeAsync(uint32_t width, uint32_t height)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::ResizeAsync");
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING && !property_->GetIsPcAppInPad()) {
TLOGW(WmsLogTag::WMS_LAYOUT, "window should not resize, winId:%{public}u, mode:%{public}u",
GetWindowId(), GetWindowMode());
return WMError::WM_ERROR_INVALID_OP_IN_CUR_STATUS;
}
auto ret = Resize(width, height);
if (state_ == WindowState::STATE_SHOWN) {
layoutCallback_->ResetResizeLock();
auto startTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
layoutCallback_->GetResizeAsyncResult(WINDOW_LAYOUT_TIMEOUT);
auto endTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()).count();
auto waitTime = endTime - startTime;
if (waitTime >= WINDOW_LAYOUT_TIMEOUT) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Layout timeout, Id:%{public}d", property_->GetPersistentId());
layoutCallback_->GetResizeAsyncResult(WINDOW_LAYOUT_TIMEOUT);
}
}
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::SetFrameRectForPartialZoomIn(const Rect& frameRect)
{
TLOGI(WmsLogTag::WMS_ANIMATION, "set frame rect start, rect: %{public}s", frameRect.ToString().c_str());
if (GetType() != WindowType::WINDOW_TYPE_MAGNIFICATION) {
TLOGE(WmsLogTag::WMS_ANIMATION, "window type is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
return static_cast<WMError>(hostSession->SetFrameRectForPartialZoomIn(frameRect));
}
WMError WindowSceneSessionImpl::UpdateWindowModeForUITest(int32_t updateMode)
{
TLOGI(WmsLogTag::WMS_LAYOUT, "windowId: %{public}d, updateMode: %{public}d", GetPersistentId(), updateMode);
switch (updateMode) {
case static_cast<int32_t>(WindowMode::WINDOW_MODE_FULLSCREEN):
return Maximize();
case static_cast<int32_t>(WindowMode::WINDOW_MODE_FLOATING):
return Recover();
case static_cast<int32_t>(WindowMode::WINDOW_MODE_SPLIT_PRIMARY):
return SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
case static_cast<int32_t>(WindowMode::WINDOW_MODE_SPLIT_SECONDARY):
return SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY);
case static_cast<int32_t>(WindowMode::WINDOW_MODE_SPLIT):
return SetWindowMode(WindowMode::WINDOW_MODE_SPLIT);
default:
break;
}
return WMError::WM_DO_NOTHING;
}
WMError WindowSceneSessionImpl::GetTargetOrientationConfigInfo(Orientation targetOrientation,
const std::map<WindowType, SystemBarProperty>& targetProperties,
const std::map<WindowType, SystemBarProperty>& currentProperties,
ViewportConfigAndAvoidArea& targetViewportConfigAndAvoidArea,
ViewportConfigAndAvoidArea& currentViewportConfigAndAvoidArea)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_ROTATION, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
std::map<WindowType, SystemBarProperty> targetPageProperties;
std::map<WindowType, SystemBarProperty> currentPageProperties;
GetSystemBarPropertyForPage(targetProperties, targetPageProperties);
GetSystemBarPropertyForPage(currentProperties, currentPageProperties);
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display == nullptr) {
TLOGE(WmsLogTag::WMS_ROTATION, "display is null, winId=%{public}u", GetWindowId());
return WMError::WM_ERROR_NULLPTR;
}
sptr<DisplayInfo> displayInfo = display ? display->GetDisplayInfo() : nullptr;
if (displayInfo == nullptr) {
TLOGE(WmsLogTag::WMS_ROTATION, "displayInfo is null!");
return WMError::WM_ERROR_NULLPTR;
}
WSError ret;
if (targetOrientation == Orientation::INVALID) {
Orientation requestedOrientation = ConvertInvalidOrientation();
ret = hostSession->GetTargetOrientationConfigInfo(requestedOrientation,
targetPageProperties, currentPageProperties);
} else {
ret = hostSession->GetTargetOrientationConfigInfo(targetOrientation,
targetPageProperties, currentPageProperties);
}
getTargetInfoCallback_->ResetGetTargetRotationLock();
std::pair<OrientationInfo, OrientationInfo> infoResult =
getTargetInfoCallback_->GetTargetOrientationResult(WINDOW_PAGE_ROTATION_TIMEOUT);
OrientationInfo info = infoResult.first;
OrientationInfo currentInfo = infoResult.second;
if (info.rect.IsUninitializedRect() && displayInfo !=nullptr) {
TLOGW(WmsLogTag::WMS_ROTATION, "GetTargetOrientationResult timeout, using display size as fallback");
info.rect.posX_ = 0;
info.rect.posY_ = 0;
info.rect.width_ = displayInfo->GetWidth();
info.rect.height_ = displayInfo->GetHeight();
info.rotation = static_cast<int32_t>(displayInfo->GetRotation());
}
Ace::ViewportConfig config = FillTargetOrientationConfig(info, displayInfo, GetDisplayId());
targetViewportConfigAndAvoidArea.config = std::make_shared<Ace::ViewportConfig>(config);
targetViewportConfigAndAvoidArea.avoidAreas = info.avoidAreas;
Ace::ViewportConfig currentConfig = FillTargetOrientationConfig(currentInfo, displayInfo, GetDisplayId());
currentViewportConfigAndAvoidArea.config = std::make_shared<Ace::ViewportConfig>(currentConfig);
currentViewportConfigAndAvoidArea.avoidAreas = currentInfo.avoidAreas;
TLOGI(WmsLogTag::WMS_ROTATION,
"win:%{public}u, rotate:%{public}d, rect:%{public}s, avoidAreas:%{public}s,%{public}s,%{public}s,%{public}s",
GetWindowId(), info.rotation, info.rect.ToString().c_str(),
info.avoidAreas[AvoidAreaType::TYPE_SYSTEM].ToString().c_str(),
info.avoidAreas[AvoidAreaType::TYPE_CUTOUT].ToString().c_str(),
info.avoidAreas[AvoidAreaType::TYPE_KEYBOARD].ToString().c_str(),
info.avoidAreas[AvoidAreaType::TYPE_NAVIGATION_INDICATOR].ToString().c_str());
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"GetTargetOrientationConfigInfo: targetOrientation:%u, rotation:%d, rect:%s",
static_cast<uint32_t>(targetOrientation), info.rotation, info.rect.ToString().c_str());
return static_cast<WMError>(ret);
}
Ace::ViewportConfig WindowSceneSessionImpl::FillTargetOrientationConfig(
const OrientationInfo& info, const sptr<DisplayInfo>& displayInfo, uint64_t displayId)
{
Ace::ViewportConfig config;
Rect targetRect = info.rect;
uint32_t targetRotation = info.rotation;
if (displayInfo == nullptr) {
TLOGE(WmsLogTag::WMS_ROTATION, "displayInfo is null!");
return config;
}
auto deviceRotation = static_cast<uint32_t>(displayInfo->GetDefaultDeviceRotationOffset());
uint32_t transformHint = (targetRotation * ONE_FOURTH_FULL_CIRCLE_DEGREE + deviceRotation) % FULL_CIRCLE_DEGREE;
float density = GetVirtualPixelRatio(displayInfo);
{
std::lock_guard<std::mutex> lock(virtualPixelRatioMutex_);
virtualPixelRatio_ = density;
}
config.SetSize(targetRect.width_, targetRect.height_);
config.SetPosition(targetRect.posX_, targetRect.posY_);
config.SetDensity(density);
config.SetOrientation(targetRotation);
config.SetTransformHint(transformHint);
config.SetDisplayId(displayId);
return config;
}
WSError WindowSceneSessionImpl::NotifyTargetRotationInfo(OrientationInfo& info, OrientationInfo& cuurentInfo)
{
WSError ret = WSError::WS_OK;
if (getTargetInfoCallback_) {
ret = getTargetInfoCallback_->OnUpdateTargetOrientationInfo(info, cuurentInfo);
}
return ret;
}
WMError WindowSceneSessionImpl::SetAspectRatio(float ratio)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::SetAspectRatio");
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::DEFAULT, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsAdaptToProportionalScale()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Window is in compatibility mode, windowId: %{public}u", GetWindowId());
return WMError::WM_OK;
}
auto hostSession = GetHostSession();
if (hostSession == nullptr) {
WLOGFE("failed, because of nullptr");
return WMError::WM_ERROR_NULLPTR;
}
if (ratio == MathHelper::INF || ratio == MathHelper::NAG_INF || std::isnan(ratio) || MathHelper::NearZero(ratio)) {
WLOGFE("failed, because of wrong value: %{public}f", ratio);
return WMError::WM_ERROR_INVALID_PARAM;
}
if (hostSession->SetAspectRatio(ratio) != WSError::WS_OK) {
return WMError::WM_ERROR_INVALID_PARAM;
}
property_->SetAspectRatio(ratio);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::ResetAspectRatio()
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::ResetAspectRatio");
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
WSError ret = hostSession->SetAspectRatio(0.0f);
if (ret != WSError::WS_OK) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Failed, windowId: %{public}u, ret: %{public}d",
GetWindowId(), static_cast<int32_t>(ret));
return WMError::WM_ERROR_INVALID_OPERATION;
}
property_->SetAspectRatio(0.0f);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetContentAspectRatio(float ratio, bool isPersistent, bool needUpdateRect)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::SetContentAspectRatio");
auto windowId = GetWindowId();
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Only allowed for the main window, windowId: %{public}u", windowId);
return WMError::WM_ERROR_INVALID_CALLING;
}
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid session, windowId: %{public}u", windowId);
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsAdaptToProportionalScale()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Window is in compatibility mode, windowId: %{public}u", windowId);
return WMError::WM_OK;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
if (ratio == MathHelper::INF || ratio == MathHelper::NAG_INF || std::isnan(ratio) || MathHelper::NearZero(ratio)) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid ratio: %{public}f, windowId: %{public}u", ratio, windowId);
return WMError::WM_ERROR_ILLEGAL_PARAM;
}
TLOGI(WmsLogTag::WMS_LAYOUT,
"windowId: %{public}u, ratio: %{public}f, isPersistent: %{public}d, needUpdateRect: %{public}d",
windowId, ratio, isPersistent, needUpdateRect);
if (hostSession->SetContentAspectRatio(ratio, isPersistent, needUpdateRect) != WSError::WS_OK) {
return WMError::WM_ERROR_ILLEGAL_PARAM;
}
property_->SetAspectRatio(ratio);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::RaiseToAppTop()
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
WLOGFI("id: %{public}d", GetPersistentId());
if (IsLoosenedWithPcOrFreeMultiMode()) {
TLOGI(WmsLogTag::WMS_HIERARCHY, "id: %{public}u is loosened", GetPersistentId());
return WMError::WM_OK;
}
auto parentId = GetParentId();
if (parentId == INVALID_SESSION_ID) {
WLOGFE("Only the children of the main window can be raised!");
return WMError::WM_ERROR_INVALID_PARENT;
}
if (!WindowHelper::IsSubWindow(GetType())) {
WLOGFE("Must be app sub window window!");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (state_ != WindowState::STATE_SHOWN) {
WLOGFE("The sub window must be shown!");
return WMError::WM_DO_NOTHING;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
WSError ret = hostSession->RaiseToAppTop();
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::RaiseAboveTarget(int32_t subWindowId)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto parentId = GetParentId();
auto currentWindowId = GetWindowId();
if (parentId == INVALID_SESSION_ID) {
WLOGFE("Only the children of the main window can be raised!");
return WMError::WM_ERROR_INVALID_PARENT;
}
auto subWindows = Window::GetSubWindow(parentId);
auto targetWindow = find_if(subWindows.begin(), subWindows.end(), [subWindowId](sptr<Window>& window) {
return static_cast<uint32_t>(subWindowId) == window->GetWindowId();
});
if (targetWindow == subWindows.end()) {
return WMError::WM_ERROR_INVALID_PARAM;
}
if (!WindowHelper::IsSubWindow(GetType())) {
WLOGFE("Must be app sub window window!");
return WMError::WM_ERROR_INVALID_CALLING;
}
if ((state_ != WindowState::STATE_SHOWN) ||
((*targetWindow)->GetWindowState() != WindowState::STATE_SHOWN)) {
WLOGFE("The sub window must be shown!");
return WMError::WM_DO_NOTHING;
}
if (currentWindowId == static_cast<uint32_t>(subWindowId)) {
return WMError::WM_OK;
}
if (IsLoosenedWithPcOrFreeMultiMode() ||
(*targetWindow)->IsZLevelAboveParentLoosened()) {
TLOGI(WmsLogTag::WMS_HIERARCHY, "source window or target window is loosened");
return WMError::WM_OK;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
WSError ret = hostSession->RaiseAboveTarget(subWindowId);
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::RaiseMainWindowAboveTarget(int32_t targetId)
{
TLOGI(WmsLogTag::WMS_HIERARCHY, "source id: %{public}u, target id: %{public}u", GetWindowId(), targetId);
if (!IsPcOrPadFreeMultiWindowMode()) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "device type not supported");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
auto targetIter = std::find_if(windowSessionMap_.begin(), windowSessionMap_.end(),
[targetId](const auto& windowInfoPair) {return windowInfoPair.second.first == targetId; });
if (targetIter == windowSessionMap_.end()) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "target not found, id invalid or pid inconsistent with source window pid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto targetSessionImpl = targetIter->second.second;
if (IsWindowSessionInvalid() || targetSessionImpl == nullptr || targetSessionImpl->GetHostSession() == nullptr ||
targetSessionImpl->state_ == WindowState::STATE_DESTROYED) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "source window or target window is null or destroyed");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (state_ != WindowState::STATE_SHOWN || targetSessionImpl->state_ != WindowState::STATE_SHOWN) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "both source window and target window must be shown");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType()) || !WindowHelper::IsMainWindow(targetSessionImpl->GetType())) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "window type not supported");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (WindowHelper::IsModalMainWindow(GetType(), GetWindowFlags()) ||
WindowHelper::IsModalMainWindow(targetSessionImpl->GetType(), targetSessionImpl->GetWindowFlags())) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "both source window and target window must be not modal");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (IsApplicationModalSubWindowShowing(GetWindowId()) || IsApplicationModalSubWindowShowing(targetId)) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "application sub window is not allowed");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (IsMainWindowTopmost() || targetSessionImpl->IsMainWindowTopmost() || IsTopmost() ||
targetSessionImpl->IsTopmost()) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "both source window and target window must be not topmost");
return WMError::WM_ERROR_INVALID_CALLING;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
WSError ret = hostSession->RaiseMainWindowAboveTarget(targetId);
return static_cast<WMError>(ret);
}
WMError WindowSceneSessionImpl::SetSubWindowZLevel(int32_t zLevel)
{
TLOGD(WmsLogTag::WMS_HIERARCHY, "%{public}d", zLevel);
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsLoosenedWithPcOrFreeMultiMode()) {
TLOGI(WmsLogTag::WMS_HIERARCHY, "id: %{public}u is loosened", GetPersistentId());
return WMError::WM_OK;
}
if (!windowSystemConfig_.supportZLevel_) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "The device is not supported");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!WindowHelper::IsNormalSubWindow(GetType(), property_->GetWindowFlags())) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "must be normal app sub window");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (GetParentId() == INVALID_SESSION_ID) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "only the children of the main window can be raised");
return WMError::WM_ERROR_INVALID_PARENT;
}
if (zLevel > MAXIMUM_Z_LEVEL || zLevel < MINIMUM_Z_LEVEL) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "zLevel value %{public}d exceeds valid range [-10000, 10000]!", zLevel);
return WMError::WM_ERROR_INVALID_PARAM;
}
auto currentZLevel = property_->GetSubWindowZLevel();
if (currentZLevel == static_cast<int32_t>(zLevel)) {
return WMError::WM_OK;
}
property_->SetSubWindowZLevel(zLevel);
return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_SUB_WINDOW_Z_LEVEL);
}
WMError WindowSceneSessionImpl::GetSubWindowZLevel(int32_t& zLevel)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsLoosenedWithPcOrFreeMultiMode()) {
TLOGI(WmsLogTag::WMS_HIERARCHY, "id: %{public}u is loosened", GetPersistentId());
return WMError::WM_OK;
}
if (!windowSystemConfig_.supportZLevel_) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "The device is not supported");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!WindowHelper::IsSubWindow(GetType()) && !WindowHelper::IsDialogWindow(GetType())) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "must be app sub window!");
return WMError::WM_ERROR_INVALID_CALLING;
}
zLevel = property_->GetSubWindowZLevel();
TLOGI(WmsLogTag::WMS_HIERARCHY, "Id:%{public}u, zLevel:%{public}d", GetWindowId(), zLevel);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::GetAvoidAreaByType(AvoidAreaType type, AvoidArea& avoidArea,
const Rect& rect, int32_t apiVersion)
{
uint32_t currentApiVersion = GetTargetAPIVersionByApplicationInfo();
apiVersion = (apiVersion == API_VERSION_INVALID) ? static_cast<int32_t>(currentApiVersion) : apiVersion;
if (apiVersion < API_VERSION_18 && WindowHelper::IsSystemWindow(property_->GetWindowType())) {
TLOGI(WmsLogTag::WMS_IMMS, "win %{public}u type %{public}d api %{public}u not supported",
GetWindowId(), type, apiVersion);
return WMError::WM_OK;
}
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!IsFloatNavigationAvoidAreaEnabled(type)) {
TLOGI(WmsLogTag::WMS_IMMS, "win %{public}u type not supported", GetWindowId());
return WMError::WM_DO_NOTHING;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
WSRect sessionRect = { rect.posX_, rect.posY_, rect.width_, rect.height_ };
avoidArea = hostSession->GetAvoidAreaByType(type, sessionRect, apiVersion);
getAvoidAreaCnt_++;
TLOGI_LMT(TEN_SECONDS, RECORD_100_TIMES, WmsLogTag::WMS_IMMS,
"win %{public}u type %{public}d times %{public}u area %{public}s",
GetWindowId(), type, getAvoidAreaCnt_.load(), avoidArea.ToString().c_str());
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::GetAvoidAreaByTypeIgnoringVisibility(AvoidAreaType type,
AvoidArea& avoidArea, const Rect& rect)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (type == AvoidAreaType::TYPE_KEYBOARD) {
return WMError::WM_ERROR_ILLEGAL_PARAM;
}
if (!IsFloatNavigationAvoidAreaEnabled(type)) {
TLOGI(WmsLogTag::WMS_IMMS, "win %{public}u type not supported", GetWindowId());
return WMError::WM_DO_NOTHING;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_SYSTEM_ABNORMALLY);
WSRect sessionRect = {
rect.posX_, rect.posY_, static_cast<int32_t>(rect.width_), static_cast<int32_t>(rect.height_)
};
avoidArea = hostSession->GetAvoidAreaByTypeIgnoringVisibility(type, sessionRect);
TLOGI(WmsLogTag::WMS_IMMS, "win [%{public}u %{public}s] type %{public}d area %{public}s",
GetWindowId(), GetWindowName().c_str(), type, avoidArea.ToString().c_str());
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::NotifyWindowNeedAvoid(bool status)
{
TLOGD(WmsLogTag::WMS_IMMS, "win %{public}u status %{public}d",
GetWindowId(), static_cast<int32_t>(status));
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_IMMS, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
hostSession->OnNeedAvoid(status);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetIgnoreSafeArea(bool isIgnoreSafeArea)
{
return SetLayoutFullScreenByApiVersion(isIgnoreSafeArea);
}
WMError WindowSceneSessionImpl::SetLayoutFullScreenByApiVersion(bool status)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_IMMS, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
uint32_t version = 0;
auto context = GetContext();
if ((context != nullptr) && (context->GetApplicationInfo() != nullptr)) {
version = context->GetApplicationInfo()->apiCompatibleVersion;
}
isIgnoreSafeArea_ = status;
isIgnoreSafeAreaNeedNotify_ = true;
if (isIgnoreSafeArea_) {
maximizeLayoutFullScreen_.store(false);
}
if (version >= 10) {
TLOGI(WmsLogTag::WMS_IMMS, "win %{public}u status %{public}d",
GetWindowId(), static_cast<int32_t>(status));
if (auto uiContent = GetUIContentSharedPtr()) {
uiContent->SetIgnoreViewSafeArea(status);
}
} else {
TLOGI(WmsLogTag::WMS_IMMS, "win %{public}u status %{public}d",
GetWindowId(), static_cast<int32_t>(status));
WMError ret = WMError::WM_OK;
if (status) {
ret = RemoveWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_IMMS, "remove window flag, win %{public}u errCode %{public}d",
GetWindowId(), static_cast<int32_t>(ret));
return ret;
}
} else {
ret = AddWindowFlag(WindowFlag::WINDOW_FLAG_NEED_AVOID);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_IMMS, "add window flag, win %{public}u errCode %{public}d",
GetWindowId(), static_cast<int32_t>(ret));
return ret;
}
}
ret = NotifyWindowNeedAvoid(!status);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_IMMS, "notify window need avoid, win %{public}u errCode %{public}d",
GetWindowId(), static_cast<int32_t>(ret));
return ret;
}
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetLayoutFullScreen(bool status)
{
TLOGD(WmsLogTag::WMS_IMMS, "win [%{public}u %{public}s] status %{public}d",
GetWindowId(), GetWindowName().c_str(), static_cast<int32_t>(status));
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (WindowHelper::IsSystemWindow(GetType())) {
TLOGI(WmsLogTag::WMS_IMMS, "system window not supported");
return WMError::WM_OK;
}
if (IsPcOrPadFreeMultiWindowMode() && property_->IsAdaptToImmersive()) {
SetLayoutFullScreenByApiVersion(status);
auto systemBarProperties = property_->GetSystemBarProperty();
if (status && systemBarProperties.find(WindowType::WINDOW_TYPE_STATUS_BAR) != systemBarProperties.end()) {
auto statusBarProperty = systemBarProperties[WindowType::WINDOW_TYPE_STATUS_BAR];
HookDecorButtonStyleInCompatibleMode(statusBarProperty.contentColor_);
}
return WMError::WM_OK;
}
bool preStatus = property_->IsLayoutFullScreen();
property_->SetIsLayoutFullScreen(status);
auto hostSession = GetHostSession();
if (hostSession != nullptr) {
hostSession->OnLayoutFullScreenChange(status);
}
if (WindowHelper::IsMainWindow(GetType()) &&
!windowSystemConfig_.IsPhoneWindow() &&
!windowSystemConfig_.IsPadWindow()) {
if (!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(),
WindowMode::WINDOW_MODE_FULLSCREEN)) {
TLOGE(WmsLogTag::WMS_IMMS, "fullscreen window mode not supported");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (property_->IsFullScreenDisabled()) {
TLOGE(WmsLogTag::WMS_IMMS, "compatible mode disable fullscreen");
return WMError::WM_OK;
}
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
auto event = GetSessionEvent();
hostSession->OnSessionEvent(event);
SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN);
}
WMError ret = SetLayoutFullScreenByApiVersion(status);
if (ret != WMError::WM_OK) {
property_->SetIsLayoutFullScreen(preStatus);
TLOGE(WmsLogTag::WMS_IMMS, "failed, win %{public}u errCode %{public}d",
GetWindowId(), static_cast<int32_t>(ret));
}
enableImmersiveMode_ = status;
return ret;
}
SessionEvent WindowSceneSessionImpl::GetSessionEvent()
{
auto event = SessionEvent::EVENT_MAXIMIZE;
if (isFullScreenWaterfallMode_.load()) {
event = SessionEvent::EVENT_MAXIMIZE_WATERFALL;
} else if (isWaterfallToMaximize_.load()) {
event = SessionEvent::EVENT_WATERFALL_TO_MAXIMIZE;
isWaterfallToMaximize_.store(false);
}
return event;
}
WMError WindowSceneSessionImpl::SetTitleAndDockHoverShown(
bool isTitleHoverShown, bool isDockHoverShown)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "winId:%{public}u %{public}s isTitleHoverShown:%{public}d, "
"isDockHoverShown:%{public}d", GetWindowId(), GetWindowName().c_str(), isTitleHoverShown, isDockHoverShown);
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "window is not main window");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (IsPadAndNotFreeMultiWindowCompatibleMode()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "This is PcAppInPad, not supported");
return WMError::WM_OK;
}
if (!IsPcOrPadFreeMultiWindowMode()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "The device is not supported");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
titleHoverShowEnabled_ = isTitleHoverShown;
dockHoverShowEnabled_ = isDockHoverShown;
if (auto hostSession = GetHostSession()) {
hostSession->OnTitleAndDockHoverShowChange(isTitleHoverShown, isDockHoverShown);
}
return WMError::WM_OK;
}
bool WindowSceneSessionImpl::IsLayoutFullScreen() const
{
if (IsWindowSessionInvalid()) {
return false;
}
WindowType winType = property_->GetWindowType();
if (WindowHelper::IsMainWindow(winType)) {
return (GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && isIgnoreSafeArea_);
}
if (WindowHelper::IsSubWindow(winType)) {
return isIgnoreSafeAreaNeedNotify_ && isIgnoreSafeArea_;
}
return false;
}
SystemBarProperty WindowSceneSessionImpl::GetSystemBarPropertyByType(WindowType type) const
{
auto curProperties = property_->GetSystemBarProperty();
return curProperties[type];
}
WMError WindowSceneSessionImpl::NotifyWindowSessionProperty()
{
TLOGD(WmsLogTag::WMS_IMMS, "windowId:%{public}u", GetWindowId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_IMMS, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_OTHER_PROPS);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::NotifySpecificWindowSessionProperty(WindowType type, const SystemBarProperty& property)
{
TLOGD(WmsLogTag::WMS_IMMS, "windowId:%{public}u", GetWindowId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_IMMS, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (type == WindowType::WINDOW_TYPE_STATUS_BAR) {
TLOGI_LMT(TEN_SECONDS, RECORD_100_TIMES, WmsLogTag::WMS_IMMS,
"win %{public}u statusBar: %{public}u %{public}x %{public}x %{public}u %{public}u",
GetWindowId(), property.enable_, property.backgroundColor_, property.contentColor_,
property.enableAnimation_, property.settingFlag_);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_STATUS_PROPS);
if (auto uiContent = GetUIContentSharedPtr()) {
uiContent->SetStatusBarItemColor(property.contentColor_);
AAFwk::Want want;
want.SetParam(Extension::HOST_STATUS_BAR_CONTENT_COLOR, static_cast<int32_t>(property.contentColor_));
uiContent->SendUIExtProprty(
static_cast<uint32_t>(Extension::Businesscode::SYNC_HOST_STATUS_BAR_CONTENT_COLOR), want,
static_cast<uint8_t>(SubSystemId::WM_UIEXT));
}
if (property_->IsAdaptToImmersive() && isIgnoreSafeArea_) {
HookDecorButtonStyleInCompatibleMode(property.contentColor_);
}
bool isCompatibleFullScreen = GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN &&
property_->IsSupportRotateFullScreen() && !IsAnco() && windowSystemConfig_.IsPcWindow();
if (isCompatibleFullScreen) {
UpdateDecorEnable(true);
}
} else if (type == WindowType::WINDOW_TYPE_NAVIGATION_BAR) {
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_NAVIGATION_PROPS);
} else if (type == WindowType::WINDOW_TYPE_NAVIGATION_INDICATOR) {
TLOGI_LMT(TEN_SECONDS, RECORD_100_TIMES, WmsLogTag::WMS_IMMS, "win %{public}u aiBar: %{public}u %{public}u",
GetWindowId(), property.enable_, property.enableAnimation_);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_NAVIGATION_INDICATOR_PROPS);
}
return WMError::WM_OK;
}
void WindowSceneSessionImpl::HookDecorButtonStyleInCompatibleMode(uint32_t color)
{
if (!property_->IsAdaptToImmersive()) {
return;
}
if (IsAnco()) {
TLOGI(WmsLogTag::WMS_DECOR, "anco window need not hook decor.");
return;
}
auto alpha = (color >> 24) & 0xFF;
auto red = (color >> 16) & 0xFF;
auto green = (color >> 8) & 0xFF;
auto blue = color & 0xFF;
double luminance = 0.299 * red + 0.587 * green + 0.114 * blue;
DecorButtonStyle style;
style.colorMode = ((luminance > (0xFF>>1)) || (alpha == 0x00)) ? LIGHT_COLOR_MODE : DARK_COLOR_MODE;
TLOGI(WmsLogTag::WMS_DECOR, "contentColor:%{public}d luminance:%{public}f colorMode:%{public}d",
color, luminance, style.colorMode);
SetDecorButtonStyle(style);
}
WMError WindowSceneSessionImpl::SetSpecificBarProperty(WindowType type, const SystemBarProperty& property)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGI(WmsLogTag::WMS_IMMS, "only main window support");
return WMError::WM_OK;
}
if (!(state_ > WindowState::STATE_INITIAL && state_ < WindowState::STATE_BOTTOM)) {
TLOGE(WmsLogTag::WMS_IMMS, "win %{public}u invalid state", GetWindowId());
return WMError::WM_ERROR_INVALID_WINDOW;
} else if (GetSystemBarPropertyByType(type) == property &&
property.settingFlag_ == SystemBarSettingFlag::DEFAULT_SETTING) {
setSameSystembarPropertyCnt_++;
TLOGI(WmsLogTag::WMS_IMMS, "win [%{public}u %{public}s] set "
"%{public}u %{public}u %{public}x %{public}x %{public}u, for %{public}u times",
GetWindowId(), GetWindowName().c_str(), static_cast<uint32_t>(type), property.enable_,
property.backgroundColor_, property.contentColor_, property.enableAnimation_,
setSameSystembarPropertyCnt_);
return WMError::WM_OK;
}
setSameSystembarPropertyCnt_ = 0;
isSystembarPropertiesSet_ = true;
property_->SetSystemBarProperty(type, property);
WMError ret = NotifySpecificWindowSessionProperty(type, property);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_IMMS, "win %{public}u errCode %{public}d",
GetWindowId(), static_cast<int32_t>(ret));
}
return ret;
}
WMError WindowSceneSessionImpl::UpdateSystemBarProperties(
const std::unordered_map<WindowType, SystemBarProperty>& systemBarProperties,
const std::unordered_map<WindowType, SystemBarPropertyFlag>& systemBarPropertyFlags)
{
for (auto [systemBarType, systemBarPropertyFlag] : systemBarPropertyFlags) {
if (systemBarProperties.find(systemBarType) == systemBarProperties.end()) {
TLOGE(WmsLogTag::WMS_IMMS, "system bar type is invalid");
return WMError::WM_DO_NOTHING;
}
auto property = GetSystemBarPropertyByType(systemBarType);
property.enable_ = systemBarPropertyFlag.enableFlag ?
systemBarProperties.at(systemBarType).enable_ : property.enable_;
property.settingFlag_ |= systemBarPropertyFlag.enableFlag ?
SystemBarSettingFlag::ENABLE_SETTING : SystemBarSettingFlag::DEFAULT_SETTING;
property.backgroundColor_ = systemBarPropertyFlag.backgroundColorFlag ?
systemBarProperties.at(systemBarType).backgroundColor_ : property.backgroundColor_;
property.contentColor_ = systemBarPropertyFlag.contentColorFlag ?
systemBarProperties.at(systemBarType).contentColor_ : property.contentColor_;
property.settingFlag_ |=
(systemBarPropertyFlag.backgroundColorFlag || systemBarPropertyFlag.contentColorFlag) ?
SystemBarSettingFlag::COLOR_SETTING : SystemBarSettingFlag::DEFAULT_SETTING;
property.enableAnimation_ = systemBarPropertyFlag.enableAnimationFlag ?
systemBarProperties.at(systemBarType).enableAnimation_ : property.enableAnimation_;
if (systemBarPropertyFlag.enableFlag || systemBarPropertyFlag.backgroundColorFlag ||
systemBarPropertyFlag.contentColorFlag || systemBarPropertyFlag.enableAnimationFlag) {
auto ret = UpdateSystemBarPropertyForPage(systemBarType, property, systemBarPropertyFlag);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_IMMS, "set failed");
return ret;
}
}
}
SystemBarProperty statusProperty = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR);
SystemBarProperty navigationIndicatorProperty =
GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_INDICATOR);
MobileAppInPadLayoutFullScreenChange(statusProperty.enable_, navigationIndicatorProperty.enable_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::UpdateSystemBarPropertyForPage(WindowType type,
const SystemBarProperty& systemBarProperty, const SystemBarPropertyFlag& systemBarPropertyFlag)
{
bool hasEnableSetting = static_cast<uint32_t>(systemBarProperty.settingFlag_) &
static_cast<uint32_t>(SystemBarSettingFlag::ENABLE_SETTING);
PartialSystemBarProperty prop = {
.enable_ = systemBarProperty.enable_,
.backgroundColor_ = systemBarProperty.backgroundColor_,
.contentColor_ = systemBarProperty.contentColor_,
.enableAnimation_ = systemBarProperty.enableAnimation_,
.flag_ = systemBarPropertyFlag,
.isolate_ = systemBarPropertyFlag.enableFlag && !hasEnableSetting
};
auto ret = SetOwnSystemBarProperty(type, prop, SystemBarPropertyOwner::APPLICATION);
if (ret == WMError::WM_OK) {
property_->SetSystemBarProperty(type, systemBarProperty);
}
return ret;
}
void WindowSceneSessionImpl::MobileAppInPadLayoutFullScreenChange(bool statusBarEnable, bool navigationEnable)
{
TLOGI(WmsLogTag::WMS_COMPAT, "isMobileAppInPadLayoutFullScreen %{public}d",
property_->GetMobileAppInPadLayoutFullScreen());
if (property_->GetMobileAppInPadLayoutFullScreen() && GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) {
TLOGI(WmsLogTag::WMS_COMPAT, "statusProperty %{public}d, navigationIndicatorPorperty %{public}d",
statusBarEnable, navigationEnable);
if (!statusBarEnable && !navigationEnable && !enableImmersiveMode_) {
Maximize(MaximizePresentation::ENTER_IMMERSIVE);
}
if (statusBarEnable && navigationEnable && enableImmersiveMode_) {
Maximize(MaximizePresentation::EXIT_IMMERSIVE);
}
}
}
WMError WindowSceneSessionImpl::SetSystemBarProperty(WindowType type, const SystemBarProperty& property)
{
return SetSpecificBarProperty(type, property);
}
WMError WindowSceneSessionImpl::SetStatusBarColorForNavigation(const std::optional<uint32_t> color)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_IMMS, "win %{public}u invalid state", GetWindowId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGI(WmsLogTag::WMS_IMMS, "only main window support, win %{public}u", GetWindowId());
return WMError::WM_DO_NOTHING;
}
auto type = WindowType::WINDOW_TYPE_STATUS_BAR;
if (color != std::nullopt) {
PartialSystemBarProperty prop;
prop.contentColor_ = color.value();
prop.flag_.contentColorFlag = true;
TLOGI(WmsLogTag::WMS_IMMS, "color:%{public}x", prop.contentColor_);
return SetOwnSystemBarProperty(type, prop, SystemBarPropertyOwner::ARKUI_NAVIGATION);
} else {
TLOGI(WmsLogTag::WMS_IMMS, "clear");
SystemBarPropertyFlag mask = { .contentColorFlag = true };
return RemoveOwnSystemBarProperty(type, mask, SystemBarPropertyOwner::ARKUI_NAVIGATION);
}
}
WMError WindowSceneSessionImpl::GetSystemBarProperties(std::map<WindowType, SystemBarProperty>& properties)
{
auto type = WindowType::WINDOW_TYPE_STATUS_BAR;
properties[type] = GetCurrentActiveSystemBarProperty(type);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetSystemBarPropertyForPage(WindowType type, std::optional<SystemBarProperty> property)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_IMMS, "win %{public}u invalid state", GetWindowId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGI(WmsLogTag::WMS_IMMS, "only main window support, win %{public}u", GetWindowId());
return WMError::WM_DO_NOTHING;
}
if (property != std::nullopt) {
PartialSystemBarProperty prop;
prop.enable_ = property.value().enable_;
prop.enableAnimation_ = property.value().enableAnimation_;
prop.flag_.enableFlag = true;
prop.flag_.enableAnimationFlag = true;
TLOGI_LMT(TEN_SECONDS, RECORD_100_TIMES, WmsLogTag::WMS_IMMS,
"enable:%{public}d, enableAnimation:%{public}d", prop.enable_, prop.enableAnimation_);
return SetOwnSystemBarProperty(type, prop, SystemBarPropertyOwner::ARKUI_NAVIGATION);
} else {
TLOGI_LMT(TEN_SECONDS, RECORD_100_TIMES, WmsLogTag::WMS_IMMS, "clear");
SystemBarPropertyFlag mask = { .enableFlag = true, .enableAnimationFlag = true };
return RemoveOwnSystemBarProperty(type, mask, SystemBarPropertyOwner::ARKUI_NAVIGATION);
}
}
WMError WindowSceneSessionImpl::SetStatusBarColorForPage(const std::optional<uint32_t> color)
{
auto type = WindowType::WINDOW_TYPE_STATUS_BAR;
if (color != std::nullopt) {
PartialSystemBarProperty prop;
prop.contentColor_ = color.value();
prop.flag_.contentColorFlag = true;
TLOGI(WmsLogTag::WMS_IMMS, "color:%{public}x", prop.contentColor_);
return SetOwnSystemBarProperty(type, prop, SystemBarPropertyOwner::ATOMIC_SERVICE);
} else {
TLOGI(WmsLogTag::WMS_IMMS, "clear");
SystemBarPropertyFlag mask = { .contentColorFlag = true };
return RemoveOwnSystemBarProperty(type, mask, SystemBarPropertyOwner::ATOMIC_SERVICE);
}
}
WMError WindowSceneSessionImpl::UpdateSystemBarProperty(WindowType type, const SystemBarProperty& systemBarProperty)
{
auto winProperty = GetSystemBarPropertyByType(type);
property_->SetSystemBarProperty(type, systemBarProperty);
auto ret = NotifySpecificWindowSessionProperty(type, systemBarProperty);
property_->SetSystemBarProperty(type, winProperty);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_IMMS, "update prop fail, ret %{public}u", ret);
return ret;
}
return WMError::WM_OK;
}
void WindowSceneSessionImpl::GetSystemBarPropertyForPage(const std::map<WindowType, SystemBarProperty>& properties,
std::map<WindowType, SystemBarProperty>& pageProperties)
{
for (auto type : { WindowType::WINDOW_TYPE_STATUS_BAR, WindowType::WINDOW_TYPE_NAVIGATION_INDICATOR }) {
if (properties.find(type) != properties.end()) {
pageProperties[type] = properties.at(type);
} else {
pageProperties[type] = GetSystemBarPropertyByType(type);
}
TLOGI(WmsLogTag::WMS_IMMS, "win [%{public}u %{public}s] type %{public}u "
"%{public}u %{public}x %{public}x %{public}u %{public}u",
GetWindowId(), GetWindowName().c_str(), static_cast<uint32_t>(type),
pageProperties[type].enable_, pageProperties[type].backgroundColor_,
pageProperties[type].contentColor_, pageProperties[type].enableAnimation_,
pageProperties[type].settingFlag_);
}
}
WMError WindowSceneSessionImpl::SetOwnSystemBarProperty(WindowType type, const PartialSystemBarProperty& prop,
SystemBarPropertyOwner owner)
{
{
std::lock_guard<std::mutex> lock(ownSystemBarPropertyMapMutex_);
if (ownSystemBarPropertyMap_.find(type) == ownSystemBarPropertyMap_.end()) {
ownSystemBarPropertyMap_[type] = std::list<OwnSystemBarPropertyPair>();
}
auto& ownPropList = ownSystemBarPropertyMap_[type];
auto it = std::find_if(ownPropList.begin(), ownPropList.end(), [owner, &prop](OwnSystemBarPropertyPair& pair) {
return pair.first == owner && pair.second.flag_ == prop.flag_;
});
if (it != ownPropList.end()) {
ownPropList.erase(it);
}
auto insertPair = OwnSystemBarPropertyPair(owner, prop);
auto insertIt = ownPropList.begin();
if (owner != SystemBarPropertyOwner::ABILITY_RUNTIME) {
while (insertIt != ownPropList.end() && insertIt->first == SystemBarPropertyOwner::ABILITY_RUNTIME) {
insertIt++;
}
}
ownPropList.insert(insertIt, insertPair);
TLOGD(WmsLogTag::WMS_IMMS, "win [%{public}u %{public}s] type %{public}u owner %{public}u "
"prop [%{public}u %{public}x %{public}x %{public}u, %{public}u] "
"flag [%{public}u%{public}u%{public}u%{public}u] size %{public}u",
GetWindowId(), GetWindowName().c_str(), static_cast<uint32_t>(type), static_cast<uint32_t>(owner),
prop.enable_, prop.backgroundColor_, prop.contentColor_, prop.enableAnimation_, prop.isolate_,
prop.flag_.enableFlag, prop.flag_.backgroundColorFlag,
prop.flag_.contentColorFlag, prop.flag_.enableAnimationFlag, static_cast<uint32_t>(ownPropList.size()));
}
return UpdateSystemBarProperty(type, GetCurrentActiveSystemBarProperty(type));
}
WMError WindowSceneSessionImpl::RemoveOwnSystemBarProperty(WindowType type, const SystemBarPropertyFlag& flag,
SystemBarPropertyOwner owner)
{
{
std::lock_guard<std::mutex> lock(ownSystemBarPropertyMapMutex_);
if (ownSystemBarPropertyMap_.find(type) == ownSystemBarPropertyMap_.end()) {
return WMError::WM_OK;
}
auto& ownPropList = ownSystemBarPropertyMap_[type];
for (auto it = ownPropList.begin(); it != ownPropList.end();) {
if (it->first == owner && flag.Contains(it->second.flag_)) {
it = ownPropList.erase(it);
} else {
it++;
}
}
if (ownPropList.empty()) {
ownSystemBarPropertyMap_.erase(type);
}
TLOGD(WmsLogTag::WMS_IMMS, "win [%{public}u %{public}s] type %{public}u owner %{public}u "
"flag [%{public}u%{public}u%{public}u%{public}u]",
GetWindowId(), GetWindowName().c_str(), static_cast<uint32_t>(type), static_cast<uint32_t>(owner),
flag.enableFlag, flag.backgroundColorFlag,
flag.contentColorFlag, flag.enableAnimationFlag);
}
return UpdateSystemBarProperty(type, GetCurrentActiveSystemBarProperty(type));
}
SystemBarProperty WindowSceneSessionImpl::GetCurrentActiveSystemBarProperty(WindowType type)
{
auto prop = GetSystemBarPropertyByType(type);
prop.settingFlag_ = SystemBarSettingFlag::FOLLOW_SETTING;
{
std::lock_guard<std::mutex> lock(ownSystemBarPropertyMapMutex_);
if (ownSystemBarPropertyMap_.find(type) == ownSystemBarPropertyMap_.end()) {
return prop;
}
bool isUseNavigationColor = false;
auto& ownPropList = ownSystemBarPropertyMap_[type];
SystemBarPropertyFlag flag;
for (auto& pair : ownPropList) {
if (!flag.backgroundColorFlag && pair.second.flag_.backgroundColorFlag) {
prop.backgroundColor_ = pair.second.backgroundColor_;
flag.backgroundColorFlag = true;
prop.settingFlag_ |= SystemBarSettingFlag::COLOR_SETTING;
}
if (!flag.contentColorFlag && pair.second.flag_.contentColorFlag) {
prop.contentColor_ = pair.second.contentColor_;
flag.contentColorFlag = true;
prop.settingFlag_ |= SystemBarSettingFlag::COLOR_SETTING;
isUseNavigationColor = !(static_cast<uint32_t>(prop.settingFlag_) &
static_cast<uint32_t>(SystemBarSettingFlag::ENABLE_SETTING)) &&
(pair.first == SystemBarPropertyOwner::ARKUI_NAVIGATION);
}
if (!flag.enableFlag && pair.second.flag_.enableFlag) {
prop.enable_ = pair.second.enable_;
flag.enableFlag = true;
prop.settingFlag_ = pair.second.isolate_ ?
prop.settingFlag_ : (prop.settingFlag_ | SystemBarSettingFlag::ENABLE_SETTING);
}
if (!flag.enableAnimationFlag && pair.second.flag_.enableAnimationFlag) {
prop.enableAnimation_= pair.second.enableAnimation_;
flag.enableAnimationFlag = true;
}
if (flag.backgroundColorFlag && flag.contentColorFlag && flag.enableFlag && flag.enableAnimationFlag) {
break;
}
}
prop.settingFlag_ = isUseNavigationColor ? SystemBarSettingFlag::COLOR_SETTING : prop.settingFlag_;
}
TLOGD(WmsLogTag::WMS_IMMS, "win [%{public}u %{public}s] type %{public}u "
"prop [%{public}u %{public}x %{public}x %{public}u %{public}u]",
GetWindowId(), GetWindowName().c_str(), static_cast<uint32_t>(type),
prop.enable_, prop.backgroundColor_, prop.contentColor_, prop.enableAnimation_, prop.settingFlag_);
return prop;
}
WMError WindowSceneSessionImpl::SetFullScreen(bool status)
{
TLOGI(WmsLogTag::WMS_IMMS, "win [%{public}u %{public}s] status %{public}d",
GetWindowId(), GetWindowName().c_str(), static_cast<int32_t>(status));
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (WindowHelper::IsSystemWindow(GetType())) {
TLOGI(WmsLogTag::WMS_IMMS, "system window not supported");
return WMError::WM_OK;
}
if (WindowHelper::IsMainWindow(GetType()) && IsPcOrPadFreeMultiWindowMode()) {
if (!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(),
WindowMode::WINDOW_MODE_FULLSCREEN)) {
TLOGE(WmsLogTag::WMS_IMMS, "fullscreen window not supported");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (property_->IsFullScreenDisabled()) {
TLOGE(WmsLogTag::WMS_IMMS, "compatible mode disable fullscreen");
return WMError::WM_OK;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
hostSession->OnSessionEvent(SessionEvent::EVENT_MAXIMIZE);
SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN);
};
WMError ret = SetLayoutFullScreenByApiVersion(status);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_IMMS, "failed, win %{public}u errCode %{public}d",
GetWindowId(), static_cast<int32_t>(ret));
}
UpdateDecorEnable(true);
SystemBarProperty statusProperty = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR);
statusProperty.enable_ = !status;
ret = SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, statusProperty);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_IMMS, "SetSystemBarProperty win %{public}u errCode %{public}d",
GetWindowId(), static_cast<int32_t>(ret));
}
return ret;
}
bool WindowSceneSessionImpl::IsFullScreen() const
{
SystemBarProperty statusProperty = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR);
return (IsLayoutFullScreen() && !statusProperty.enable_);
}
bool WindowSceneSessionImpl::IsDecorEnable() const
{
WindowType windowType = GetType();
bool isMainWindow = WindowHelper::IsMainWindow(windowType);
bool isSubWindow = WindowHelper::IsSubWindow(windowType);
bool isDialogWindow = WindowHelper::IsDialogWindow(windowType);
bool isValidWindow = isMainWindow ||
((isSubWindow || isDialogWindow || IsSubWindowMaximizeSupported()) && property_->IsDecorEnable());
bool isWindowModeSupported = WindowHelper::IsWindowModeSupported(
windowSystemConfig_.decorWindowModeSupportType_, GetWindowMode());
if (windowSystemConfig_.freeMultiWindowSupport_) {
return isValidWindow && windowSystemConfig_.isSystemDecorEnable_;
}
bool enable = isValidWindow && windowSystemConfig_.isSystemDecorEnable_ &&
isWindowModeSupported;
if ((isSubWindow || isDialogWindow) && property_->GetIsPcAppInPad() && property_->IsDecorEnable()) {
enable = true;
}
TLOGD(WmsLogTag::WMS_DECOR, "get decor enable %{public}d", enable);
return enable;
}
WMError WindowSceneSessionImpl::SetWindowTitle(const std::string& title)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_DECOR, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (property_->GetPcAppInpadCompatibleMode() && !IsDecorEnable()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "This is PcAppInPad, not supported");
return WMError::WM_OK;
}
if (!(windowSystemConfig_.IsPcWindow() || windowSystemConfig_.IsPadWindow() ||
windowSystemConfig_.IsPhoneWindow() || IsDeviceFeatureCapableForFreeMultiWindow())) {
TLOGE(WmsLogTag::WMS_DECOR, "device not support");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (GetUIContentSharedPtr() == nullptr) {
TLOGE(WmsLogTag::WMS_DECOR, "uicontent is empty");
return WMError::WM_OK;
}
if (!IsDecorEnable()) {
TLOGE(WmsLogTag::WMS_DECOR, "DecorEnable is false");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (WindowHelper::IsMainWindow(GetType())) {
auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(GetContext());
if (abilityContext == nullptr) {
return WMError::WM_ERROR_NULLPTR;
}
abilityContext->SetMissionLabel(title);
} else {
return SetAPPWindowLabel(title);
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::Minimize()
{
WLOGFI("id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
WLOGFE("session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsPcOrPadFreeMultiWindowMode() && IsZLevelAboveParentLoosened()) {
return Hide(0, true, true);
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
if (WindowHelper::IsMainWindow(GetType())) {
hostSession->OnSessionEvent(SessionEvent::EVENT_MINIMIZE);
} else {
WLOGFE("This window state is abnormal.");
return WMError::WM_DO_NOTHING;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::MaximizeForCompatibleMode()
{
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "maximize fail, not main");
return WMError::WM_ERROR_INVALID_CALLING;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
hostSession->OnSessionEvent(SessionEvent::EVENT_COMPATIBLE_TO_MAXIMIZE);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::RecoverForCompatibleMode()
{
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "recover fail, not main");
return WMError::WM_ERROR_INVALID_CALLING;
}
isTitleShowInFullScreen_ = false;
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
hostSession->OnSessionEvent(SessionEvent::EVENT_COMPATIBLE_TO_RECOVER);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SwitchCompatibleMode(CompatibleStyleMode styleMode)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "switch compatible style fail, not main");
return WMError::WM_ERROR_INVALID_CALLING;
}
SessionEventParam param;
param.compatibleStyleMode = static_cast<uint32_t>(styleMode);
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
hostSession->OnSessionEvent(SessionEvent::EVENT_SWITCH_COMPATIBLE_MODE, param);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::Maximize()
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::Maximize");
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "Maximize id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (WindowHelper::IsMainWindow(GetType()) || IsSubWindowMaximizeSupported()) {
UpdateIsShowDecorInFreeMultiWindow(true);
isMaximizeInvoked_ = !enableImmersiveMode_;
SetLayoutFullScreen(enableImmersiveMode_);
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::Maximize(MaximizePresentation presentation)
{
return MaximizeWithOptions(presentation, AcrossDisplayPresentation::UNSPECIFIED,
{ SnapshotAnimationConfig::UNSET, SnapshotAnimationConfig::UNSET });
}
bool WindowSceneSessionImpl::CheckAcrossDisplayPresentation(AcrossDisplayPresentation state) const
{
if (!WindowHelper::IsSubWindow(GetType())) {
return true;
}
return state == AcrossDisplayPresentation::UNSPECIFIED ||
state == AcrossDisplayPresentation::FOLLOW_ACROSS_DISPLAY_SETTING;
}
void WindowSceneSessionImpl::ApplyMaximizePresentation(MaximizePresentation presentation)
{
titleHoverShowEnabled_ = true;
dockHoverShowEnabled_ = true;
switch (presentation) {
case MaximizePresentation::ENTER_IMMERSIVE:
enableImmersiveMode_ = true;
break;
case MaximizePresentation::EXIT_IMMERSIVE:
enableImmersiveMode_ = false;
break;
case MaximizePresentation::ENTER_IMMERSIVE_DISABLE_TITLE_AND_DOCK_HOVER:
enableImmersiveMode_ = true;
titleHoverShowEnabled_ = false;
dockHoverShowEnabled_ = false;
break;
case MaximizePresentation::FOLLOW_APP_IMMERSIVE_SETTING:
break;
default:
TLOGE(WmsLogTag::WMS_LAYOUT_PC,
"Invalid presentation. windowId: %{public}u, presentation: %{public}u",
GetWindowId(), static_cast<uint32_t>(presentation));
break;
}
}
WMError WindowSceneSessionImpl::Maximize(MaximizePresentation presentation, WaterfallResidentState state)
{
auto acrossDisplay = (state == WaterfallResidentState::UNCHANGED)
? AcrossDisplayPresentation::UNSPECIFIED
: static_cast<AcrossDisplayPresentation>(static_cast<uint32_t>(state));
return MaximizeWithOptions(presentation, acrossDisplay,
{ SnapshotAnimationConfig::UNSET, SnapshotAnimationConfig::UNSET });
}
WMError WindowSceneSessionImpl::ValidateSnapshotAnimationConfig(const SnapshotAnimationConfig& config)
{
constexpr int64_t MAX_DURATION = 400;
constexpr int64_t MAX_DELAY = 350;
constexpr int64_t USE_DEFAULT = -1;
if (WindowHelper::IsSubWindow(GetType())) {
auto isUnsetOrZero = [USE_DEFAULT](int64_t value) {
return value == USE_DEFAULT || value == 0;
};
if (!isUnsetOrZero(config.duration) || !isUnsetOrZero(config.delay)) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Sub-window does not support setting snapshot animation config: "
"duration=%{public}" PRId64 ", delay=%{public}" PRId64,
config.duration, config.delay);
return WMError::WM_ERROR_INVALID_CALLING;
}
return WMError::WM_OK;
}
auto isValid = [](int64_t value, int64_t max) {
return value == USE_DEFAULT || (value >= 0 && value <= max);
};
if (!isValid(config.duration, MAX_DURATION) || !isValid(config.delay, MAX_DELAY)) {
TLOGW(WmsLogTag::WMS_LAYOUT, "Invalid animation config: duration=%{public}" PRId64 ", delay=%{public}" PRId64
" (valid: duration [0,%{public}" PRId64 "], delay [0,%{public}" PRId64 "] )",
config.duration, config.delay, MAX_DURATION, MAX_DELAY);
return WMError::WM_ERROR_ILLEGAL_PARAM;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::CheckMaximizePreConditions(AcrossDisplayPresentation state)
{
if (!CheckAcrossDisplayPresentation(state)) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "Invalid acrossDisplayPresentation. windowId: %{public}u, state: %{public}u",
GetWindowId(), static_cast<uint32_t>(state));
return WMError::WM_ERROR_INVALID_CALLING;
}
if (!WindowHelper::IsMainWindow(GetType()) && !IsSubWindowMaximizeSupported()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "maximize fail, not main or sub window");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(),
WindowMode::WINDOW_MODE_FULLSCREEN)) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::ExecuteMaximizeWithOptions(MaximizePresentation presentation,
AcrossDisplayPresentation state, const SnapshotAnimationConfig& snapshotAnimationConfig)
{
ApplyMaximizePresentation(presentation);
UpdateIsShowDecorInFreeMultiWindow(true);
isMaximizeInvoked_ = !enableImmersiveMode_;
property_->SetIsLayoutFullScreen(enableImmersiveMode_);
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
hostSession->OnLayoutFullScreenChange(enableImmersiveMode_);
hostSession->OnTitleAndDockHoverShowChange(titleHoverShowEnabled_, dockHoverShowEnabled_);
SetLayoutFullScreenByApiVersion(enableImmersiveMode_);
maximizeLayoutFullScreen_.store(presentation == MaximizePresentation::ENTER_IMMERSIVE ||
presentation == MaximizePresentation::ENTER_IMMERSIVE_DISABLE_TITLE_AND_DOCK_HOVER);
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "present: %{public}d, enableImmersiveMode_:%{public}d!",
presentation, enableImmersiveMode_.load());
SessionEventParam param;
param.waterfallResidentState = (state == AcrossDisplayPresentation::UNSPECIFIED)
? static_cast<uint32_t>(AcrossDisplayPresentation::FOLLOW_ACROSS_DISPLAY_SETTING)
: static_cast<uint32_t>(state);
param.snapshotAnimationConfig_ = snapshotAnimationConfig;
hostSession->OnSessionEvent(SessionEvent::EVENT_MAXIMIZE, param);
return SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN);
}
WMError WindowSceneSessionImpl::MaximizeWithOptions(MaximizePresentation presentation,
AcrossDisplayPresentation state, const SnapshotAnimationConfig& snapshotAnimationConfig)
{
TLOGI(WmsLogTag::WMS_LAYOUT, "id: %{public}d, presentation: %{public}u, state: %{public}u, "
"duration: %{public}" PRId64 ", delay: %{public}" PRId64, GetPersistentId(),
static_cast<uint32_t>(presentation), static_cast<uint32_t>(state),
snapshotAnimationConfig.duration, snapshotAnimationConfig.delay);
WMError validateRet = ValidateSnapshotAnimationConfig(snapshotAnimationConfig);
if (validateRet != WMError::WM_OK) {
return validateRet;
}
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (property_->GetWindowAnchorInfo().isFromAttachOrDetach_ &&
property_->GetWindowAnchorInfo().isAnchoredByAttach_) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Cannot maximize due to in anchor enabled mode.");
return WMError::WM_OK;
}
WMError checkRet = CheckMaximizePreConditions(state);
if (checkRet != WMError::WM_OK) {
return checkRet;
}
if (!IsPcOrPadFreeMultiWindowMode() || property_->IsFullScreenDisabled()) {
TLOGW(WmsLogTag::WMS_LAYOUT_PC, "The device is not supported");
return WMError::WM_OK;
}
return ExecuteMaximizeWithOptions(presentation, state, snapshotAnimationConfig);
}
WMError WindowSceneSessionImpl::MaximizeFloating()
{
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
if (!WindowHelper::IsMainWindow(property_->GetWindowType()) && !IsSubWindowMaximizeSupported()) {
TLOGW(WmsLogTag::WMS_LAYOUT_PC,
"SetGlobalMaximizeMode fail, not main or sub window, id %{public}d",
GetPersistentId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(),
WindowMode::WINDOW_MODE_FULLSCREEN)) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (property_->IsFullScreenDisabled()) {
TLOGW(WmsLogTag::WMS_COMPAT, "diable fullScreen in compatibleMode window ,id:%{public}d", GetPersistentId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (property_->GetMobileAppInPadLayoutFullScreen()) {
SystemBarProperty statusProperty = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR);
SystemBarProperty navigationIndicatorPorperty =
GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_NAVIGATION_INDICATOR);
TLOGI(WmsLogTag::WMS_COMPAT, "statusProperty %{public}d, navigationIndicatorPorperty %{public}d",
statusProperty.enable_, navigationIndicatorPorperty.enable_);
if (!statusProperty.enable_ && !navigationIndicatorPorperty.enable_) {
Maximize(MaximizePresentation::ENTER_IMMERSIVE);
return WMError::WM_OK;
}
}
MaximizeEvent(hostSession);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_MAXIMIZE_STATE);
return WMError::WM_OK;
}
void WindowSceneSessionImpl::MaximizeEvent(const sptr<ISession> &hostSession)
{
if (hostSession == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "hostSession is nullptr");
return;
}
if (GetGlobalMaximizeMode() != MaximizeMode::MODE_AVOID_SYSTEM_BAR) {
const bool isPcMode = system::GetBoolParameter("persist.sceneboard.ispcmode", false);
if (IsFreeMultiWindowMode() && !isPcMode && !windowSystemConfig_.IsPcWindow() &&
!property_->GetIsPcAppInPad() && WindowHelper::IsMainWindow(GetType())) {
UpdateIsShowDecorInFreeMultiWindow(false);
hostSession->OnSessionEvent(SessionEvent::EVENT_MAXIMIZE_FULLSCREEN);
} else {
SessionEventParam param;
param.titleButtonEventType_ = static_cast<uint32_t>(TitleButtonEventType::EVENT_TYPE_MAXIMIZE);
hostSession->OnSessionEvent(SessionEvent::EVENT_MAXIMIZE, param);
}
SetWindowMode(WindowMode::WINDOW_MODE_FULLSCREEN);
UpdateDecorEnable(true);
property_->SetMaximizeMode(MaximizeMode::MODE_FULL_FILL);
} else {
hostSession->OnSessionEvent(SessionEvent::EVENT_MAXIMIZE_FLOATING);
SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
property_->SetMaximizeMode(MaximizeMode::MODE_AVOID_SYSTEM_BAR);
UpdateDecorEnable(true);
NotifyWindowStatusChange(GetWindowMode());
}
}
WMError WindowSceneSessionImpl::Recover()
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::Recover");
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "id: %{public}d", GetPersistentId());
if (FoldScreenStateInternel::IsSuperFoldDisplayDevice() && isFullScreenWaterfallMode_.load() &&
lastWindowModeBeforeWaterfall_.load() == WindowMode::WINDOW_MODE_FULLSCREEN) {
isWaterfallToMaximize_.store(true);
SetFullScreenWaterfallMode(false);
WMError ret = Maximize();
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "recover to fullscreen failed");
isWaterfallToMaximize_.store(false);
SetFullScreenWaterfallMode(true);
}
return ret;
}
if (IsWindowSessionInvalid() || property_->IsFullScreenDisabled()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC,
"recover failed, session invalid or fullscreen disabled in compatibleMode, id:%{public}d",
GetPersistentId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(), WindowMode::WINDOW_MODE_FLOATING)) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "not support floating, can not Recover");
return WMError::WM_ERROR_INVALID_OPERATION;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
if (WindowHelper::IsMainWindow(GetType()) || IsSubWindowMaximizeSupported()) {
if (property_->GetMaximizeMode() == MaximizeMode::MODE_RECOVER &&
property_->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
TLOGW(WmsLogTag::WMS_LAYOUT_PC, "Recover fail, already MODE_RECOVER");
return WMError::WM_ERROR_REPEAT_OPERATION;
}
if (enableImmersiveMode_) {
enableImmersiveMode_ = false;
property_->SetIsLayoutFullScreen(enableImmersiveMode_);
hostSession->OnLayoutFullScreenChange(enableImmersiveMode_);
}
hostSession->OnSessionEvent(SessionEvent::EVENT_RECOVER);
SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
isMaximizeInvoked_ = false;
property_->SetMaximizeMode(MaximizeMode::MODE_RECOVER);
UpdateDecorEnable(true);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_MAXIMIZE_STATE);
NotifyWindowStatusChange(GetWindowMode());
} else {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "recovery is invalid, window id: %{public}d", GetPersistentId());
return WMError::WM_ERROR_INVALID_OPERATION;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::Restore()
{
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "Restore fail, not main window");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (!(windowSystemConfig_.IsPcWindow() || property_->GetIsPcAppInPad())) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "This is not PC or PcAppInPad, not supported");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_SYSTEM_ABNORMALLY);
WSError ret = hostSession->OnRestoreMainWindow();
if (ret != WSError::WS_OK) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "OnRestoreMainWindow result is: %{public}d", static_cast<int32_t>(ret));
return WMError::WM_ERROR_INVALID_CALLING;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::Recover(uint32_t reason)
{
return Recover(reason, { SnapshotAnimationConfig::UNSET, SnapshotAnimationConfig::UNSET });
}
WMError WindowSceneSessionImpl::CheckRecoverPreConditions()
{
if (!IsPcOrPadFreeMultiWindowMode()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "The device is not supported");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(), WindowMode::WINDOW_MODE_FLOATING)) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "not support floating, can not Recover");
return WMError::WM_ERROR_INVALID_OPERATION;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::ExecuteRecover(uint32_t reason, const SnapshotAnimationConfig& snapshotAnimationConfig)
{
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
bool onlySupportFloating = WindowHelper::IsSubWindow(GetType()) &&
WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(), WindowMode::WINDOW_MODE_FLOATING) &&
!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(), WindowMode::WINDOW_MODE_FULLSCREEN);
bool isSubWindowMaxSupported = IsSubWindowMaximizeSupported();
TLOGI(WmsLogTag::WMS_LAYOUT, "ExecuteRecover: onlySupportFloating=%{public}d, isSubWindowMaxSupported=%{public}d",
onlySupportFloating, isSubWindowMaxSupported);
if (!onlySupportFloating && !WindowHelper::IsMainWindow(GetType()) && !IsSubWindowMaximizeSupported()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "recovery is invalid on sub window");
return WMError::WM_ERROR_INVALID_OPERATION;
}
if (property_->GetMaximizeMode() == MaximizeMode::MODE_RECOVER &&
property_->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
TLOGW(WmsLogTag::WMS_LAYOUT_PC, "Recover fail, already MODE_RECOVER");
return WMError::WM_ERROR_REPEAT_OPERATION;
}
if (enableImmersiveMode_) {
enableImmersiveMode_ = false;
property_->SetIsLayoutFullScreen(enableImmersiveMode_);
hostSession->OnLayoutFullScreenChange(enableImmersiveMode_);
}
SessionEventParam param;
param.snapshotAnimationConfig_ = snapshotAnimationConfig;
hostSession->OnSessionEvent(SessionEvent::EVENT_RECOVER, param);
if (reason == REASON_MAXIMIZE_MODE_CHANGE &&
property_->GetMaximizeMode() == MaximizeMode::MODE_AVOID_SYSTEM_BAR) {
UpdateMaximizeMode(MaximizeMode::MODE_RECOVER);
}
SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
isMaximizeInvoked_ = false;
property_->SetMaximizeMode(MaximizeMode::MODE_RECOVER);
UpdateDecorEnable(true);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_MAXIMIZE_STATE);
NotifyWindowStatusChange(GetWindowMode());
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::Recover(uint32_t reason, const SnapshotAnimationConfig& snapshotAnimationConfig)
{
TLOGI(WmsLogTag::WMS_LAYOUT, "id: %{public}d, reason: %{public}u, duration: %{public}" PRId64
", delay: %{public}" PRId64, GetPersistentId(), reason,
snapshotAnimationConfig.duration, snapshotAnimationConfig.delay);
WMError validateRet = ValidateSnapshotAnimationConfig(snapshotAnimationConfig);
if (validateRet != WMError::WM_OK) {
return validateRet;
}
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsPadAndNotFreeMultiWindowCompatibleMode()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "The device is not supported");
return WMError::WM_OK;
}
WMError checkRet = CheckRecoverPreConditions();
if (checkRet != WMError::WM_OK) {
return checkRet;
}
return ExecuteRecover(reason, snapshotAnimationConfig);
}
WMError WindowSceneSessionImpl::SetWindowRectAutoSave(bool enabled, bool isSaveBySpecifiedFlag)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "WindowSceneSessionImpl::SetWindowRectAutoSave");
TLOGI(WmsLogTag::WMS_MAIN, "id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_MAIN, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_MAIN, "This is not main window, not supported");
return WMError::WM_ERROR_INVALID_CALLING;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_SYSTEM_ABNORMALLY);
hostSession->OnSetWindowRectAutoSave(enabled, isSaveBySpecifiedFlag);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::IsWindowRectAutoSave(bool& enabled)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_MAIN, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_MAIN, "This is not main window, not supported");
return WMError::WM_ERROR_INVALID_CALLING;
}
auto context = GetContext();
if (context == nullptr) {
TLOGE(WmsLogTag::WMS_MAIN, "context is nullptr");
return WMError::WM_ERROR_NULLPTR;
}
auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
std::string bundleName = property_->GetSessionInfo().bundleName_;
std::string moduleName = property_->GetSessionInfo().moduleName_;
std::string abilityName = property_->GetSessionInfo().abilityName_;
if (abilityContext && abilityContext->GetAbilityInfo()) {
abilityName = abilityContext->GetAbilityInfo()->name;
moduleName = context->GetHapModuleInfo() ? context->GetHapModuleInfo()->moduleName : "";
bundleName = abilityContext->GetAbilityInfo()->bundleName;
} else if (context) {
moduleName = context->GetHapModuleInfo() ? context->GetHapModuleInfo()->moduleName : "";
bundleName = context->GetBundleName();
}
std::string key = bundleName + moduleName + abilityName;
int persistentId = GetPersistentId();
auto ret = SingletonContainer::Get<WindowAdapter>().IsWindowRectAutoSave(key, enabled, persistentId);
return ret;
}
WMError WindowSceneSessionImpl::SetSupportedWindowModes(
const std::vector<AppExecFwk::SupportWindowMode>& supportedWindowModes, bool grayOutMaximizeButton)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"CUSTOM_ANIMATOR_WMS::WindowSupportModes::ClientReq::SetSupportedWindowModes id=%d modes=%zu",
GetPersistentId(), supportedWindowModes.size());
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowSupportModes:ClientReq] SetSupportedWindowModes id:%{public}u, "
"modes=%{public}zu grayOut:%{public}d",
GetWindowId(), supportedWindowModes.size(), grayOutMaximizeButton);
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsPadAndNotFreeMultiWindowCompatibleMode()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "This is PcAppInpad, not supported");
return WMError::WM_OK;
}
if (!(windowSystemConfig_.IsPcWindow() || windowSystemConfig_.freeMultiWindowSupport_)) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "Neither is Pc nor support free multi window, invalid calling");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
bool isMainWindow = WindowHelper::IsMainWindow(GetType());
bool isSubWindow = WindowHelper::IsSubWindow(GetType());
if ((!isMainWindow && !isSubWindow) ||
(isSubWindow && (property_->GetWindowAnchorInfo().isAnchorEnabled_ || property_->IsFollowParentLayout()))) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "Only support main window and sub window not following parent");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (isSubWindow && std::find(supportedWindowModes.begin(), supportedWindowModes.end(),
AppExecFwk::SupportWindowMode::SPLIT) != supportedWindowModes.end()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "Sub window does not support split mode");
return WMError::WM_ERROR_ILLEGAL_PARAM;
}
if (isMainWindow && grayOutMaximizeButton) {
size_t size = supportedWindowModes.size();
if (size == 0 || size > WINDOW_SUPPORT_MODE_MAX_SIZE) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "mode param is invalid");
return WMError::WM_ERROR_ILLEGAL_PARAM;
}
if (std::find(supportedWindowModes.begin(), supportedWindowModes.end(),
AppExecFwk::SupportWindowMode::FULLSCREEN) != supportedWindowModes.end()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "Supports full screen cannot be grayed out");
return WMError::WM_ERROR_ILLEGAL_PARAM;
}
GrayOutMaximizeButton(true);
} else if (isMainWindow && grayOutMaximizeButton_) {
GrayOutMaximizeButton(false);
}
return SetSupportedWindowModesInner(supportedWindowModes);
}
WMError WindowSceneSessionImpl::GrayOutMaximizeButton(bool isGrayOut)
{
if (grayOutMaximizeButton_ == isGrayOut) {
TLOGW(WmsLogTag::WMS_LAYOUT_PC, "Duplicate settings are gray out: %{public}d", isGrayOut);
return WMError::WM_DO_NOTHING;
}
std::shared_ptr<Ace::UIContent> uiContent = GetUIContentSharedPtr();
if (uiContent == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "uicontent is empty");
return WMError::WM_ERROR_NULLPTR;
}
grayOutMaximizeButton_ = isGrayOut;
uiContent->OnContainerModalEvent(WINDOW_GRAY_OUT_MAXIMIZE_EVENT, isGrayOut ? "true" : "false");
TLOGI(WmsLogTag::WMS_LAYOUT_PC,
"[WindowSupportModes:GrayOut] GrayOutMaximizeButton id:%{public}u, isGrayOut:%{public}d",
GetWindowId(), isGrayOut);
return WMError::WM_OK;
}
void WindowSceneSessionImpl::UpdateWindowModeWhenSupportTypeChange(uint32_t windowModeSupportType)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"WMS::WindowSupportModes::ModeChange id=%d type=%u", GetPersistentId(), windowModeSupportType);
bool onlySupportFullScreen =
WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FULLSCREEN) &&
!WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FLOATING);
bool onlySupportFloating =
!WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FULLSCREEN) &&
WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FLOATING);
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowSupportModes:ModeChange] id:%{public}d, type:0x%{public}x, "
"onlyFullScreen:%{public}d onlyFloating:%{public}d",
GetPersistentId(), windowModeSupportType, onlySupportFullScreen, onlySupportFloating);
bool disableFullScreen = property_->IsFullScreenDisabled();
if (onlySupportFullScreen && !disableFullScreen) {
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "onlySupportFullScreen:%{public}d disableFullScreen:%{public}d",
onlySupportFullScreen, disableFullScreen);
Maximize(MaximizePresentation::ENTER_IMMERSIVE);
return;
}
if (onlySupportFloating) {
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "onlySupportFloating:%{public}d", onlySupportFloating);
Recover(REASON_MAXIMIZE_MODE_CHANGE);
}
}
WMError WindowSceneSessionImpl::SetSupportedWindowModesInner(
const std::vector<AppExecFwk::SupportWindowMode>& supportedWindowModes)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"WMS::WindowSupportModes::SetInner id=%d", GetPersistentId());
auto size = supportedWindowModes.size();
if (size <= 0 || size > WINDOW_SUPPORT_MODE_MAX_SIZE) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "mode param is invalid");
return WMError::WM_ERROR_INVALID_PARAM;
}
uint32_t windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(supportedWindowModes);
if (windowModeSupportType == 0) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "mode param is 0");
return WMError::WM_ERROR_INVALID_PARAM;
}
uint32_t allSplitSupport = WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY |
WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY |
WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT;
bool onlySupportSplit = (windowModeSupportType & ~allSplitSupport) == 0;
if (onlySupportSplit) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "mode param is only support split");
return WMError::WM_ERROR_INVALID_PARAM;
}
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "winId: %{public}u, windowModeSupportType: %{public}u",
GetWindowId(), windowModeSupportType);
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowSupportModes:SetInner] supportType=0x%{public}x, id:%{public}u",
windowModeSupportType, GetWindowId());
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_SYSTEM_ABNORMALLY);
hostSession->NotifySupportWindowModesChange(supportedWindowModes);
property_->SetSupportedWindowModes(supportedWindowModes);
haveSetSupportedWindowModes_ = true;
if (!IsPcOrPadFreeMultiWindowMode()) {
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowSupportModes:SetInner] not free multi window, cached for later, id:%{public}u, type:%{public}u",
GetWindowId(), windowModeSupportType);
return WMError::WM_OK;
}
property_->SetWindowModeSupportType(windowModeSupportType);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO);
UpdateTitleButtonVisibility();
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowSupportModes:SetInner] saved id:%{public}u, type:%{public}u, updateModeChange",
GetWindowId(), windowModeSupportType);
UpdateWindowModeWhenSupportTypeChange(windowModeSupportType);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetImageForRecent(uint32_t imgResourceId, ImageFit imageFit)
{
int32_t persistentId = GetPersistentId();
return SingletonContainer::Get<WindowAdapter>().SetImageForRecent(imgResourceId, imageFit, persistentId);
}
WMError WindowSceneSessionImpl::SetImageForRecentPixelMap(const std::shared_ptr<Media::PixelMap>& pixelMap,
ImageFit imageFit)
{
int32_t persistentId = GetPersistentId();
TLOGI(WmsLogTag::WMS_PATTERN,
"set imageForRecent, persistentId=%{public}d", persistentId);
WMError ret = SingletonContainer::Get<WindowAdapter>().SetImageForRecentPixelMap(pixelMap, imageFit, persistentId);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_PATTERN, "set imageForRecent failed, ret=%{public}d", ret);
}
return ret;
}
WMError WindowSceneSessionImpl::RemoveImageForRecent()
{
int32_t persistentId = GetPersistentId();
TLOGI(WmsLogTag::WMS_PATTERN,
"remove imageForRecent, persistentId=%{public}d", persistentId);
WMError ret = SingletonContainer::Get<WindowAdapter>().RemoveImageForRecent(persistentId);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_PATTERN, "remove imageForRecent failed, ret=%{public}d", ret);
}
return ret;
}
void WindowSceneSessionImpl::NotifyWindowStageCreateFinished()
{
TLOGI(WmsLogTag::WMS_LIFE, "id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LIFE, "session is invalid");
return;
}
auto hostSession = GetHostSession();
if (hostSession) {
hostSession->OnSessionEvent(SessionEvent::EVENT_NOTIFY_WINDOW_STAGE_CREATE_FINISHED);
}
}
void WindowSceneSessionImpl::StartMove()
{
WLOGFI("id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
WLOGFE("session is invalid");
return;
}
WindowType windowType = GetType();
bool isMainWindow = WindowHelper::IsMainWindow(windowType);
bool isSubWindow = WindowHelper::IsSubWindow(windowType);
bool isDialogWindow = WindowHelper::IsDialogWindow(windowType);
bool isDecorDialog = isDialogWindow && property_->IsDecorEnable();
bool isValidWindow = isMainWindow || (IsPcOrFreeMultiWindowCapabilityEnabled() && (isSubWindow || isDecorDialog));
auto hostSession = GetHostSession();
if (isValidWindow && hostSession) {
hostSession->OnSessionEvent(SessionEvent::EVENT_START_MOVE);
}
}
bool WindowSceneSessionImpl::CheckCanMoveWindowType()
{
WindowType windowType = GetType();
if (!WindowHelper::IsSystemWindow(windowType) &&
!WindowHelper::IsMainWindow(windowType) &&
!WindowHelper::IsSubWindow(windowType)) {
return false;
}
return true;
}
bool WindowSceneSessionImpl::CheckIsPcAppInPadFullScreenOnMobileWindowMode()
{
auto mode = property_->GetWindowMode();
if (property_->GetIsPcAppInPad() &&
(mode == WindowMode::WINDOW_MODE_FULLSCREEN ||
WindowHelper::IsSplitWindowMode(mode)) &&
!IsFreeMultiWindowMode()) {
return true;
}
return false;
}
bool WindowSceneSessionImpl::CheckCanStartMoveWindowByWindowType()
{
if (IsPcOrFreeMultiWindowCapabilityEnabled()) {
return true;
}
WindowType windowType = GetType();
return WindowHelper::IsSystemWindow(windowType) || WindowHelper::IsSubWindow(windowType);
}
WmErrorCode WindowSceneSessionImpl::StartMoveWindow()
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::StartMoveWindow");
if (!CheckCanStartMoveWindowByWindowType()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid window type:%{public}u", GetType());
return WmErrorCode::WM_ERROR_INVALID_CALLING;
}
if (CheckIsPcAppInPadFullScreenOnMobileWindowMode()) {
return WmErrorCode::WM_OK;
}
auto hostSession = GetHostSession();
if (!hostSession) {
TLOGE(WmsLogTag::WMS_LAYOUT, "hostSession is nullptr");
return WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY;
}
WSError errorCode = hostSession->SyncSessionEvent(SessionEvent::EVENT_START_MOVE);
TLOGD(WmsLogTag::WMS_LAYOUT, "id:%{public}d, errorCode:%{public}d",
GetPersistentId(), static_cast<int>(errorCode));
if (errorCode == WSError::WS_ERROR_REPEAT_OPERATION) {
return WmErrorCode::WM_ERROR_REPEAT_OPERATION;
}
if (errorCode == WSError::WS_ERROR_NULLPTR) {
return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
}
return WmErrorCode::WM_OK;
}
WMError WindowSceneSessionImpl::StartMovingWithOptions(const StartMovingOptions& options)
{
auto windowId = GetPersistentId();
if (!CheckCanStartMoveWindowByWindowType()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Invalid window type: %{public}u, id: %{public}d", GetType(), windowId);
return WMError::WM_ERROR_INVALID_CALLING;
}
if (CheckIsPcAppInPadFullScreenOnMobileWindowMode()) {
return WMError::WM_OK;
}
if (options.avoidRect.IsRightBottomOverflow()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "avoidRect is invalid: %{public}s", options.avoidRect.ToString().c_str());
return WMError::WM_ERROR_ILLEGAL_PARAM;
}
auto hostSession = GetHostSession();
if (!hostSession) {
TLOGE(WmsLogTag::WMS_LAYOUT, "hostSession is nullptr");
return WMError::WM_ERROR_SYSTEM_ABNORMALLY;
}
auto ret = hostSession->StartMovingWithOptions(options);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"Failed to start moving with options. id: %{public}d, options: %{public}s, ret: %{public}d",
windowId, options.ToString().c_str(), static_cast<int>(ret));
}
return ret;
}
WmErrorCode WindowSceneSessionImpl::StartMoveWindowWithCoordinate(int32_t offsetX, int32_t offsetY)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WMS::StartMoveWindowWithCoordinate");
if (!CheckCanMoveWindowType()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "invalid window type:%{public}u", GetType());
return WmErrorCode::WM_ERROR_INVALID_CALLING;
}
if (!IsPcOrFreeMultiWindowCapabilityEnabled()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "The device is not supported");
return WmErrorCode::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (CheckIsPcAppInPadFullScreenOnMobileWindowMode()) {
return WmErrorCode::WM_OK;
}
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
}
const auto& windowRect = GetRect();
if (offsetX < 0 || offsetX > static_cast<int32_t>(windowRect.width_) ||
offsetY < 0 || offsetY > static_cast<int32_t>(windowRect.height_)) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "offset not in window");
return WmErrorCode::WM_ERROR_INVALID_PARAM;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY);
WSError errorCode;
MMI::PointerEvent::PointerItem pointerItem;
if (lastPointerEvent_ != nullptr &&
lastPointerEvent_->GetPointerItem(lastPointerEvent_->GetPointerId(), pointerItem)) {
int32_t lastDisplayX = pointerItem.GetDisplayX();
int32_t lastDisplayY = pointerItem.GetDisplayY();
int32_t lastDisplayId = lastPointerEvent_->GetTargetDisplayId();
TLOGD(WmsLogTag::WMS_LAYOUT_PC, "offset:[%{public}d,%{public}d] lastEvent:[%{private}d,%{private}d]"
" lastDisplayId:%{public}d", offsetX, offsetY, lastDisplayX, lastDisplayY, lastDisplayId);
errorCode = hostSession->StartMovingWithCoordinate(offsetX, offsetY, lastDisplayX, lastDisplayY, lastDisplayId);
} else {
errorCode = hostSession->SyncSessionEvent(SessionEvent::EVENT_START_MOVE);
}
TLOGD(WmsLogTag::WMS_LAYOUT_PC, "id:%{public}d, errorCode:%{public}d",
GetPersistentId(), static_cast<int>(errorCode));
switch (errorCode) {
case WSError::WS_ERROR_REPEAT_OPERATION: {
return WmErrorCode::WM_ERROR_REPEAT_OPERATION;
}
case WSError::WS_ERROR_NULLPTR: {
return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
}
default: {
return WmErrorCode::WM_OK;
}
}
}
WmErrorCode WindowSceneSessionImpl::StopMoveWindow()
{
if (!CheckCanMoveWindowType()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "invalid window type:%{public}u", GetType());
return WmErrorCode::WM_ERROR_INVALID_CALLING;
}
if (!IsPcOrFreeMultiWindowCapabilityEnabled()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "The device is not supported");
return WmErrorCode::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WmErrorCode::WM_ERROR_STATE_ABNORMALLY;
}
auto hostSession = GetHostSession();
if (!hostSession) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "hostSession is nullptr");
return WmErrorCode::WM_ERROR_SYSTEM_ABNORMALLY;
}
WSError errorCode = hostSession->SyncSessionEvent(SessionEvent::EVENT_END_MOVE);
TLOGD(WmsLogTag::WMS_LAYOUT_PC, "id:%{public}d, errorCode:%{public}d",
GetPersistentId(), static_cast<int>(errorCode));
return errorCode == WSError::WS_ERROR_NULLPTR ? WmErrorCode::WM_ERROR_STATE_ABNORMALLY : WmErrorCode::WM_OK;
}
WMError WindowSceneSessionImpl::MainWindowCloseInner()
{
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(GetContext());
if (!abilityContext) {
return Destroy(true);
}
bool terminateCloseProcess = false;
WMError res = NotifyMainWindowClose(terminateCloseProcess);
if (res == WMError::WM_OK) {
TLOGI(WmsLogTag::WMS_DECOR, "id: %{public}d, not close: %{public}d", GetPersistentId(),
terminateCloseProcess);
if (!terminateCloseProcess) {
hostSession->OnSessionEvent(SessionEvent::EVENT_CLOSE);
}
return res;
}
auto handler = sptr<WindowPrepareTerminateHandler>::MakeSptr();
PrepareTerminateFunc func = [hostSessionWptr = wptr<ISession>(hostSession)] {
auto hostSession = hostSessionWptr.promote();
if (hostSession == nullptr) {
TLOGNE(WmsLogTag::WMS_LIFE, "this session is nullptr");
return;
}
hostSession->OnSessionEvent(SessionEvent::EVENT_CLOSE);
};
handler->SetPrepareTerminateFun(func);
if (AAFwk::AbilityManagerClient::GetInstance()->PrepareTerminateAbility(abilityContext->GetToken(),
handler) != ERR_OK) {
TLOGE(WmsLogTag::WMS_LIFE, "PrepareTerminateAbility failed, do close window");
hostSession->OnSessionEvent(SessionEvent::EVENT_CLOSE);
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::Close()
{
TLOGI(WmsLogTag::WMS_DECOR, "id: %{public}d", GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_DECOR, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
WindowType windowType = GetType();
bool isSubWindow = WindowHelper::IsSubWindow(windowType);
bool isSystemSubWindow = WindowHelper::IsSystemSubWindow(windowType);
bool isDialogWindow = WindowHelper::IsDialogWindow(windowType);
if (WindowHelper::IsMainWindow(windowType) || isSubWindow) {
WMError res = NotifyWindowWillClose(this);
if (res == WMError::WM_OK) {
TLOGI(WmsLogTag::WMS_DECOR, "id: %{public}d will close", GetPersistentId());
return res;
}
}
if (WindowHelper::IsMainWindow(windowType)) {
return MainWindowCloseInner();
} else if (isSubWindow || isSystemSubWindow || isDialogWindow) {
TLOGI(WmsLogTag::WMS_DECOR, "subwindow or dialog");
bool terminateCloseProcess = false;
NotifySubWindowClose(terminateCloseProcess);
if (!terminateCloseProcess || isDialogWindow) {
return Destroy(true);
}
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::CloseDirectly()
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_DECOR, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
TLOGI(WmsLogTag::WMS_DECOR, "id: %{public}d", GetPersistentId());
if (WindowHelper::IsMainWindow(GetType())) {
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_SYSTEM_ABNORMALLY);
hostSession->OnSessionEvent(SessionEvent::EVENT_CLOSE);
return WMError::WM_OK;
}
return Destroy(true);
}
WMError WindowSceneSessionImpl::DisableAppWindowDecor()
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) {
TLOGE(WmsLogTag::WMS_DECOR, "disable app window decor permission denied!");
return WMError::WM_ERROR_NOT_SYSTEM_APP;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_DECOR, "window decoration is invalid on sub window");
return WMError::WM_ERROR_INVALID_OPERATION;
}
TLOGI(WmsLogTag::WMS_DECOR, "disable app window decoration.");
windowSystemConfig_.isSystemDecorEnable_ = false;
UpdateDecorEnable(true);
return WMError::WM_OK;
}
void WindowSceneSessionImpl::PerformBack()
{
if (!WindowHelper::IsMainWindow(GetType())) {
WLOGFI("PerformBack is not MainWindow, return");
return;
}
if (auto hostSession = GetHostSession()) {
bool needMoveToBackground = false;
auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(GetContext());
if (abilityContext != nullptr) {
abilityContext->OnBackPressedCallBack(needMoveToBackground);
}
TLOGI(WmsLogTag::DEFAULT, "%{public}d", needMoveToBackground);
hostSession->RequestSessionBack(needMoveToBackground);
}
}
WMError WindowSceneSessionImpl::SetGlobalMaximizeMode(MaximizeMode mode)
{
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "mode %{public}u", static_cast<uint32_t>(mode));
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
if (WindowHelper::IsMainWindow(GetType())) {
hostSession->SetGlobalMaximizeMode(mode);
return WMError::WM_OK;
} else {
TLOGW(WmsLogTag::WMS_LAYOUT_PC, "fail, not main window");
return WMError::WM_ERROR_INVALID_PARAM;
}
}
MaximizeMode WindowSceneSessionImpl::GetGlobalMaximizeMode() const
{
TLOGD(WmsLogTag::WMS_LAYOUT_PC, "in");
MaximizeMode mode = MaximizeMode::MODE_RECOVER;
if (auto hostSession = GetHostSession()) {
hostSession->GetGlobalMaximizeMode(mode);
}
return mode;
}
WMError WindowSceneSessionImpl::SetWindowMode(WindowMode mode)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::SetWindowMode");
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
TLOGI(WmsLogTag::WMS_LAYOUT, "windowId: %{public}u, windowModeSupportType: %{public}u, mode: %{public}u",
GetWindowId(), property_->GetWindowModeSupportType(), static_cast<uint32_t>(mode));
if (!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(), mode)) {
TLOGE(WmsLogTag::WMS_LAYOUT, "window %{public}u do not support mode: %{public}u",
GetWindowId(), static_cast<uint32_t>(mode));
return WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE;
}
WMError ret = UpdateWindowModeImmediately(WindowModeInfo{ mode });
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Update window mode fail, ret:%{public}u", ret);
return ret;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
hostSession->OnSessionEvent(SessionEvent::EVENT_SPLIT_PRIMARY);
} else if (mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
hostSession->OnSessionEvent(SessionEvent::EVENT_SPLIT_SECONDARY);
} else if (mode == WindowMode::WINDOW_MODE_SPLIT) {
hostSession->OnSessionEvent(SessionEvent::EVENT_SPLIT_PRIMARY);
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetGrayScale(float grayScale)
{
if (IsWindowSessionInvalid()) {
WLOGFE("session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
constexpr float eps = 1e-6f;
if (grayScale < (MIN_GRAY_SCALE - eps) || grayScale > (MAX_GRAY_SCALE + eps)) {
WLOGFE("invalid grayScale value: %{public}f", grayScale);
return WMError::WM_ERROR_INVALID_PARAM;
}
std::shared_ptr<Ace::UIContent> uiContent = GetUIContentSharedPtr();
if (uiContent == nullptr) {
WLOGFE("uicontent is empty");
return WMError::WM_ERROR_NULLPTR;
}
uiContent->SetContentNodeGrayScale(grayScale);
WLOGI("Set window gray scale success, grayScale: %{public}f", grayScale);
return WMError::WM_OK;
}
WindowMode WindowSceneSessionImpl::GetWindowMode() const
{
return property_->GetWindowMode();
}
WindowMode WindowSceneSessionImpl::GetWindowModeCompat() const
{
return property_->GetWindowModeCompat();
}
WindowModeInfo WindowSceneSessionImpl::GetWindowModeInfo() const
{
return windowModeInfo_;
}
bool WindowSceneSessionImpl::IsTransparent() const
{
if (IsWindowSessionInvalid()) {
return false;
}
WSColorParam backgroundColor;
backgroundColor.value = GetBackgroundColor();
WLOGFD("color: %{public}u, alpha: %{public}u", backgroundColor.value, backgroundColor.argb.alpha);
return backgroundColor.argb.alpha == 0x00;
}
WMError WindowSceneSessionImpl::SetTransparent(bool isTransparent)
{
if (IsWindowSessionInvalid()) {
WLOGFE("session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
WSColorParam backgroundColor;
backgroundColor.value = GetBackgroundColor();
if (isTransparent) {
backgroundColor.argb.alpha = 0x00;
return SetBackgroundColor(backgroundColor.value);
} else {
backgroundColor.value = GetBackgroundColor();
if (backgroundColor.argb.alpha == 0x00) {
backgroundColor.argb.alpha = 0xff;
return SetBackgroundColor(backgroundColor.value);
}
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::AddWindowFlag(WindowFlag flag)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto context = GetContext();
if (flag == WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED && context && context->GetApplicationInfo() &&
context->GetApplicationInfo()->apiCompatibleVersion >= 9 &&
!SessionPermission::IsSystemCalling()) {
TLOGI(WmsLogTag::DEFAULT, "Can not set show when locked, PersistentId: %{public}u", GetPersistentId());
return WMError::WM_ERROR_INVALID_PERMISSION;
}
if (flag == WindowFlag::WINDOW_FLAG_HANDWRITING && !SessionPermission::IsSystemCalling()) {
TLOGI(WmsLogTag::DEFAULT, "Can not set handwritting, PersistentId: %{public}u", GetPersistentId());
return WMError::WM_ERROR_NOT_SYSTEM_APP;
}
if (flag == WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE && !SessionPermission::IsSystemCalling()) {
TLOGI(WmsLogTag::DEFAULT, "Can not set forbid split move, PersistentId: %{public}u", GetPersistentId());
return WMError::WM_ERROR_NOT_SYSTEM_APP;
}
uint32_t updateFlags = property_->GetWindowFlags() | (static_cast<uint32_t>(flag));
return SetWindowFlags(updateFlags);
}
WMError WindowSceneSessionImpl::RemoveWindowFlag(WindowFlag flag)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
uint32_t updateFlags = property_->GetWindowFlags() & (~(static_cast<uint32_t>(flag)));
return SetWindowFlags(updateFlags);
}
WMError WindowSceneSessionImpl::SetWindowFlags(uint32_t flags)
{
TLOGI(WmsLogTag::DEFAULT, "Session %{public}u flags %{public}u", GetWindowId(), flags);
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::DEFAULT, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (property_->GetWindowFlags() == flags) {
TLOGI(WmsLogTag::DEFAULT, "Session %{public}u set same flags %{public}u", GetWindowId(), flags);
return WMError::WM_OK;
}
auto oriFlags = property_->GetWindowFlags();
property_->SetWindowFlags(flags);
WMError ret = UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_FLAGS);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::DEFAULT, "SetWindowFlags errCode:%{public}d winId:%{public}u",
static_cast<int32_t>(ret), GetWindowId());
property_->SetWindowFlags(oriFlags);
}
return ret;
}
uint32_t WindowSceneSessionImpl::GetWindowFlags() const
{
return property_->GetWindowFlags();
}
bool WindowSceneSessionImpl::IsApplicationModalSubWindowShowing(int32_t parentId)
{
auto subMap = GetSubWindow(parentId);
auto applicationModalIndex = std::find_if(subMap.begin(), subMap.end(),
[](const auto& subWindow) {
return WindowHelper::IsApplicationModalSubWindow(subWindow->GetType(), subWindow->GetWindowFlags()) &&
subWindow->GetWindowState() != WindowState::STATE_SHOWN;
});
return applicationModalIndex != subMap.end();
}
void WindowSceneSessionImpl::UpdateConfiguration(const std::shared_ptr<AppExecFwk::Configuration>& configuration)
{
if (auto uiContent = GetUIContentSharedPtr()) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "notify ace scene win=%{public}u, display=%{public}" PRIu64,
GetWindowId(), GetDisplayId());
uiContent->UpdateConfiguration(configuration);
UpdateColorMode();
} else {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "uiContent null, scene win=%{public}u, display=%{public}" PRIu64,
GetWindowId(), GetDisplayId());
}
UpdateDefaultStatusBarColor();
std::vector<sptr<WindowSessionImpl>> subWindows;
GetSubWindows(GetPersistentId(), subWindows);
for (auto& subWindowSession : subWindows) {
if (subWindowSession != nullptr) {
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "scene subWin=%{public}u, display=%{public}" PRIu64,
subWindowSession->GetWindowId(), subWindowSession->GetDisplayId());
subWindowSession->UpdateConfiguration(configuration);
}
}
}
WMError WindowSceneSessionImpl::UpdateColorMode(const std::shared_ptr<AppExecFwk::Configuration>& configuration)
{
std::string colorMode;
if (configuration != nullptr) {
colorMode = configuration->GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE);
}
auto appContext = AbilityRuntime::Context::GetApplicationContext();
if (appContext == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "winId: %{public}d app context is null", GetPersistentId());
return WMError::WM_ERROR_NULLPTR;
}
if (colorMode.empty()) {
std::shared_ptr<AppExecFwk::Configuration> config = appContext->GetConfiguration();
if (config == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "config is null, winId: %{public}d", GetPersistentId());
return WMError::WM_ERROR_NULLPTR;
}
colorMode = config->GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE);
}
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "winId: %{public}d, colorMode: %{public}s", GetPersistentId(), colorMode.c_str());
if (colorMode_ == colorMode) {
return WMError::WM_DO_NOTHING;
}
colorMode_ = colorMode;
UpdateSidebarBlurStyleWhenColorModeChange();
bool hasDarkRes = false;
appContext->AppHasDarkRes(hasDarkRes);
hasDarkRes_ = hasDarkRes;
if (auto hostSession = GetHostSession()) {
hostSession->OnUpdateColorMode(colorMode, hasDarkRes);
} else {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "winId: %{public}d hostSession is null", GetPersistentId());
}
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "winId: %{public}d, colorMode: %{public}s, hasDarkRes: %{public}u",
GetPersistentId(), colorMode.c_str(), hasDarkRes);
return WMError::WM_OK;
}
void WindowSceneSessionImpl::UpdateConfigurationForSpecified(
const std::shared_ptr<AppExecFwk::Configuration>& configuration,
const std::shared_ptr<Global::Resource::ResourceManager>& resourceManager)
{
if (auto uiContent = GetUIContentSharedPtr()) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "notify ace scene win=%{public}u, display=%{public}" PRIu64,
GetWindowId(), GetDisplayId());
uiContent->UpdateConfiguration(configuration, resourceManager);
} else {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "uiContent null, scene win=%{public}u, display=%{public}" PRIu64,
GetWindowId(), GetDisplayId());
}
if (configuration != nullptr) {
specifiedColorMode_ = configuration->GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE);
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "scene win=%{public}u, colorMode=%{public}s, display=%{public}" PRIu64,
GetWindowId(), specifiedColorMode_.c_str(), GetDisplayId());
}
UpdateDefaultStatusBarColor();
std::vector<sptr<WindowSessionImpl>> subWindows;
GetSubWindows(GetPersistentId(), subWindows);
if (subWindows.empty()) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "no subSession, scene win=%{public}u, display=%{public}" PRIu64,
GetWindowId(), GetDisplayId());
return;
}
for (auto& subWindowSession : subWindows) {
if (subWindowSession != nullptr) {
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "scene subWin=%{public}u, display=%{public}" PRIu64,
subWindowSession->GetWindowId(), subWindowSession->GetDisplayId());
subWindowSession->UpdateConfigurationForSpecified(configuration, resourceManager);
}
}
}
void WindowSceneSessionImpl::UpdateConfigurationForAll(const std::shared_ptr<AppExecFwk::Configuration>& configuration,
const std::vector<std::shared_ptr<AbilityRuntime::Context>>& ignoreWindowContexts)
{
std::unordered_set<std::shared_ptr<AbilityRuntime::Context>> ignoreWindowCtxSet(
ignoreWindowContexts.begin(), ignoreWindowContexts.end());
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "scene map size: %{public}u", static_cast<uint32_t>(windowSessionMap_.size()));
for (const auto& winPair : windowSessionMap_) {
auto window = winPair.second.second;
if (window == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "scene window is null");
continue;
}
if (ignoreWindowCtxSet.count(window->GetContext()) == 0) {
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "scene win=%{public}u, display=%{public}" PRIu64,
window->GetWindowId(), window->GetDisplayId());
window->UpdateConfiguration(configuration);
} else {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "skip scene win=%{public}u, display=%{public}" PRIu64,
window->GetWindowId(), window->GetDisplayId());
}
}
}
void WindowSceneSessionImpl::UpdateConfigurationSync(const std::shared_ptr<AppExecFwk::Configuration>& configuration)
{
if (auto uiContent = GetUIContentSharedPtr()) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "notify ace scene win=%{public}u, display=%{public}" PRIu64,
GetWindowId(), GetDisplayId());
uiContent->UpdateConfigurationSyncForAll(configuration);
UpdateColorMode();
} else {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "uiContent null, scene win=%{public}u, display=%{public}" PRIu64,
GetWindowId(), GetDisplayId());
}
std::vector<sptr<WindowSessionImpl>> subWindows;
GetSubWindows(GetPersistentId(), subWindows);
if (subWindows.empty()) {
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "no subSession, scene win=%{public}u, display=%{public}" PRIu64,
GetWindowId(), GetDisplayId());
return;
}
for (auto& subWindowSession : subWindows) {
if (subWindowSession != nullptr) {
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "scene subWin=%{public}u, display=%{public}" PRIu64,
subWindowSession->GetWindowId(), subWindowSession->GetDisplayId());
subWindowSession->UpdateConfigurationSync(configuration);
}
}
}
void WindowSceneSessionImpl::UpdateConfigurationSyncForAll(
const std::shared_ptr<AppExecFwk::Configuration>& configuration)
{
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "scene map size: %{public}u", static_cast<uint32_t>(windowSessionMap_.size()));
for (const auto& winPair : windowSessionMap_) {
if (auto window = winPair.second.second) {
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "scene win=%{public}u, display=%{public}" PRIu64,
window->GetWindowId(), window->GetDisplayId());
window->UpdateConfigurationSync(configuration);
}
}
}
sptr<Window> WindowSceneSessionImpl::GetTopWindowWithContext(const std::shared_ptr<AbilityRuntime::Context>& context)
{
uint32_t mainWinId = INVALID_WINDOW_ID;
{
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
if (windowSessionMap_.empty()) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "Please create mainWindow First!");
return nullptr;
}
for (const auto& winPair : windowSessionMap_) {
auto win = winPair.second.second;
if (win && WindowHelper::IsMainWindow(win->GetType()) && context.get() == win->GetContext().get()) {
mainWinId = win->GetWindowId();
TLOGD(WmsLogTag::WMS_HIERARCHY, "Find MainWinId:%{public}u.", mainWinId);
break;
}
}
}
TLOGI(WmsLogTag::WMS_HIERARCHY, "mainId:%{public}u!", mainWinId);
if (mainWinId == INVALID_WINDOW_ID) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "Cannot find topWindow!");
return nullptr;
}
uint32_t topWinId = INVALID_WINDOW_ID;
WMError ret = SingletonContainer::Get<WindowAdapter>().GetTopWindowId(mainWinId, topWinId);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_HIERARCHY, "failed with errCode:%{public}d", static_cast<int32_t>(ret));
return nullptr;
}
return FindWindowById(topWinId);
}
sptr<Window> WindowSceneSessionImpl::GetTopWindowWithId(uint32_t mainWinId)
{
TLOGI(WmsLogTag::WMS_HIERARCHY, "mainId:%{public}u", mainWinId);
uint32_t topWinId = INVALID_WINDOW_ID;
WMError ret = SingletonContainer::Get<WindowAdapter>().GetTopWindowId(mainWinId, topWinId);
if (ret != WMError::WM_OK) {
WLOGFE("[GetTopWin] failed with errCode:%{public}d", static_cast<int32_t>(ret));
return nullptr;
}
return FindWindowById(topWinId);
}
sptr<Window> WindowSceneSessionImpl::GetMainWindowWithContext(const std::shared_ptr<AbilityRuntime::Context>& context)
{
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
if (windowSessionMap_.empty()) {
TLOGE(WmsLogTag::WMS_MAIN, "Please create mainWindow First!");
return nullptr;
}
for (const auto& winPair : windowSessionMap_) {
auto win = winPair.second.second;
if (win && WindowHelper::IsMainWindow(win->GetType()) && context.get() == win->GetContext().get()) {
TLOGI(WmsLogTag::WMS_MAIN, "Find MainWinId:%{public}u.", win->GetWindowId());
return win;
}
}
TLOGE(WmsLogTag::WMS_MAIN, "Cannot find Window!");
return nullptr;
}
sptr<WindowSessionImpl> WindowSceneSessionImpl::GetMainWindowWithId(uint32_t mainWinId)
{
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
if (windowSessionMap_.empty()) {
WLOGFE("Please create mainWindow First!");
return nullptr;
}
for (const auto& winPair : windowSessionMap_) {
auto win = winPair.second.second;
if (win && WindowHelper::IsMainWindow(win->GetType()) && mainWinId == win->GetWindowId()) {
WLOGI("GetTopWindow Find MainWinId:%{public}u.", mainWinId);
return win;
}
}
WLOGFE("Cannot find Window!");
return nullptr;
}
static WMError GetParentMainWindowIdInner(WindowSessionImplMap& sessionMap, int32_t windowId, int32_t& mainWindowId)
{
for (const auto& [_, pair] : sessionMap) {
const auto& window = pair.second;
if (window == nullptr) {
return WMError::WM_ERROR_NULLPTR;
}
if (window->GetPersistentId() != windowId) {
continue;
}
if (WindowHelper::IsMainWindow(window->GetType()) || window->IsLoosenedWithPcOrFreeMultiMode()) {
TLOGI(WmsLogTag::WMS_SUB, "find main window, id:%{public}u", window->GetPersistentId());
mainWindowId = window->GetPersistentId();
return WMError::WM_OK;
}
if (WindowHelper::IsSubWindow(window->GetType()) || WindowHelper::IsDialogWindow(window->GetType())) {
return GetParentMainWindowIdInner(sessionMap, window->GetParentId(), mainWindowId);
}
mainWindowId = INVALID_SESSION_ID;
return WMError::WM_OK;
}
return WMError::WM_ERROR_INVALID_PARENT;
}
int32_t WindowSceneSessionImpl::GetParentMainWindowId(int32_t windowId)
{
if (windowId == INVALID_SESSION_ID) {
TLOGW(WmsLogTag::WMS_SUB, "invalid windowId id");
return INVALID_SESSION_ID;
}
int32_t mainWindowId = INVALID_SESSION_ID;
{
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
WMError findRet = GetParentMainWindowIdInner(windowSessionMap_, windowId, mainWindowId);
if (findRet == WMError::WM_OK) {
return mainWindowId;
}
}
WMError ret = SingletonContainer::Get<WindowAdapter>().GetParentMainWindowId(windowId, mainWindowId);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SUB, "cant't find main window id, err:%{public}d", static_cast<uint32_t>(ret));
return INVALID_SESSION_ID;
}
return mainWindowId;
}
WMError WindowSceneSessionImpl::GetAndVerifyWindowTypeForArkUI(uint32_t parentId, const std::string& windowName,
WindowType parentWindowType, WindowType& windowType)
{
auto window = WindowSceneSessionImpl::Find(windowName);
if (window != nullptr) {
TLOGE(WmsLogTag::WMS_SUB, "WindowName(%{public}s) already exists.", windowName.c_str());
return WMError::WM_ERROR_REPEAT_OPERATION;
}
TLOGI(WmsLogTag::WMS_SUB, "parentWindowId:%{public}d, parentWindowType:%{public}d", parentId, parentWindowType);
if (parentWindowType == WindowType::WINDOW_TYPE_SCENE_BOARD ||
parentWindowType == WindowType::WINDOW_TYPE_DESKTOP) {
windowType = WindowType::WINDOW_TYPE_SYSTEM_FLOAT;
} else if (WindowHelper::IsUIExtensionWindow(parentWindowType)) {
windowType = WindowType::WINDOW_TYPE_APP_SUB_WINDOW;
} else if (WindowHelper::IsSystemSubWindow(parentWindowType)) {
TLOGE(WmsLogTag::WMS_SUB, "parent is system sub window, id: %{public}d, type: %{public}d",
parentId, parentWindowType);
return WMError::WM_ERROR_INVALID_TYPE;
} else if (WindowHelper::IsSystemWindow(parentWindowType)) {
windowType = WindowType::WINDOW_TYPE_SYSTEM_SUB_WINDOW;
} else {
auto parentWindow = WindowSceneSessionImpl::GetWindowWithId(parentId);
if (parentWindow == nullptr) {
TLOGE(WmsLogTag::WMS_SUB, "parentWindow is null, windowId:%{public}d", parentId);
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (parentWindowType != parentWindow->GetType()) {
TLOGE(WmsLogTag::WMS_SUB, "parentWindow does match type");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto ret = WindowSceneSessionImpl::VerifySubWindowLevel(false, parentWindow);
if (ret != WMError::WM_OK) {
return ret;
}
windowType = WindowType::WINDOW_TYPE_APP_SUB_WINDOW;
}
return WMError::WM_OK;
}
void WindowSceneSessionImpl::SetNeedDefaultAnimation(bool needDefaultAnimation)
{
{
std::lock_guard<std::mutex> lockListener(transitionControllerMutex_);
enableDefaultAnimation_ = needDefaultAnimation;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_IF_NULL(hostSession);
hostSession->UpdateWindowAnimationFlag(needDefaultAnimation);
}
static float ConvertRadiusToSigma(float radius)
{
return radius > 0.0f ? 0.57735f * radius + SK_ScalarHalf : 0.0f;
}
WMError WindowSceneSessionImpl::CheckParmAndPermission()
{
if (surfaceNode_ == nullptr) {
WLOGFE("RSSurface node is null");
return WMError::WM_ERROR_NULLPTR;
}
if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) {
WLOGFE("Check failed, permission denied");
return WMError::WM_ERROR_NOT_SYSTEM_APP;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetCornerRadius(float cornerRadius)
{
if (surfaceNode_ == nullptr) {
WLOGFE("RSSurface node is null");
return WMError::WM_ERROR_NULLPTR;
}
WLOGFI("Set window %{public}s corner radius %{public}f", GetWindowName().c_str(), cornerRadius);
surfaceNode_->SetCornerRadius(cornerRadius);
rsCornerRadius_ = cornerRadius;
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetWindowCornerRadius(float cornerRadius)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!windowSystemConfig_.IsPcWindow() && !windowSystemConfig_.IsPadWindow() &&
!windowSystemConfig_.IsPhoneWindow()) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "This is not pc, pad or phone, not supported.");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!WindowHelper::IsFloatOrSubWindow(GetType())) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "This is not sub window or float window.");
return WMError::WM_ERROR_INVALID_CALLING;
}
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "Set id %{public}u corner radius %{public}f.", GetWindowId(), cornerRadius);
if (MathHelper::LessNotEqual(cornerRadius, 0.0f)) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "The corner radius is less than zero.");
return WMError::WM_ERROR_INVALID_PARAM;
}
property_->SetWindowCornerRadius(cornerRadius);
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_SYSTEM_ABNORMALLY);
hostSession->SetWindowCornerRadius(cornerRadius);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::GetWindowCornerRadius(float& cornerRadius)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!windowSystemConfig_.IsPcWindow() && !windowSystemConfig_.IsPadWindow() &&
!windowSystemConfig_.IsPhoneWindow()) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "This is not PC, pad or phone, not supported.");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!WindowHelper::IsFloatOrSubWindow(GetType())) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "This is not sub window or float window.");
return WMError::WM_ERROR_INVALID_CALLING;
}
cornerRadius = property_->GetWindowCornerRadius();
if (MathHelper::LessNotEqual(cornerRadius, 0.0f)) {
TLOGI(WmsLogTag::WMS_ANIMATION, "System config radius: %{public}f, property radius: %{public}f, id: %{public}d",
windowSystemConfig_.defaultCornerRadius_, cornerRadius, GetPersistentId());
cornerRadius = MathHelper::LessNotEqual(windowSystemConfig_.defaultCornerRadius_, 0.0f) ?
0.0f : windowSystemConfig_.defaultCornerRadius_;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetShadowRadius(float radius)
{
WMError ret = CheckParmAndPermission();
if (ret != WMError::WM_OK) {
return ret;
}
WLOGFI("Set window %{public}s shadow radius %{public}f", GetWindowName().c_str(), radius);
if (MathHelper::LessNotEqual(radius, 0.0)) {
return WMError::WM_ERROR_INVALID_PARAM;
}
surfaceNode_->SetShadowRadius(MathHelper::Equal(radius, 0.0) ? NAG_NUM : ConvertRadiusToSigma(radius));
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SyncShadowsToComponent(const ShadowsInfo& shadowsInfo)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
TLOGI(WmsLogTag::WMS_ANIMATION, "Sync Shadows To Component %{public}s shadow radius: %{public}f,"
" color: %{public}s, offsetX: %{public}f, offsetY: %{public}f", GetWindowName().c_str(),
shadowsInfo.radius_, shadowsInfo.color_.c_str(), shadowsInfo.offsetX_, shadowsInfo.offsetY_);
if (MathHelper::LessNotEqual(shadowsInfo.radius_, 0.0)) {
return WMError::WM_ERROR_INVALID_PARAM;
}
property_->SetWindowShadows(shadowsInfo);
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_SYSTEM_ABNORMALLY);
hostSession->SetWindowShadows(shadowsInfo);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetWindowShadowRadius(float radius)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!windowSystemConfig_.IsPcWindow() && !windowSystemConfig_.IsPadWindow() &&
!windowSystemConfig_.IsPhoneWindow() && !IsDeviceFeatureCapableForFreeMultiWindow()) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "device not support.");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!WindowHelper::IsFloatOrSubWindow(GetType())) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "This is not sub window or float window.");
return WMError::WM_ERROR_INVALID_CALLING;
}
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "Set id %{public}u shadow radius %{public}f.", GetWindowId(), radius);
if (MathHelper::LessNotEqual(radius, 0.0f)) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "The shadow radius is less than zero.");
return WMError::WM_ERROR_INVALID_PARAM;
}
if (surfaceNode_ == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "RSSurface node is nullptr.");
return WMError::WM_ERROR_NULLPTR;
}
surfaceNode_->SetShadowRadius(MathHelper::Equal(radius, 0.0) ? NAG_NUM : ConvertRadiusToSigma(radius));
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetShadowColor(std::string color)
{
WMError ret = CheckParmAndPermission();
if (ret != WMError::WM_OK) {
return ret;
}
WLOGFI("Set window %{public}s shadow color %{public}s", GetWindowName().c_str(), color.c_str());
uint32_t colorValue = 0;
if (!ColorParser::Parse(color, colorValue)) {
return WMError::WM_ERROR_INVALID_PARAM;
}
surfaceNode_->SetShadowColor(colorValue);
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetShadowOffsetX(float offsetX)
{
WMError ret = CheckParmAndPermission();
if (ret != WMError::WM_OK) {
return ret;
}
WLOGFI("Set window %{public}s shadow offsetX %{public}f", GetWindowName().c_str(), offsetX);
surfaceNode_->SetShadowOffsetX(offsetX);
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetShadowOffsetY(float offsetY)
{
WMError ret = CheckParmAndPermission();
if (ret != WMError::WM_OK) {
return ret;
}
WLOGFI("Set window %{public}s shadow offsetY %{public}f", GetWindowName().c_str(), offsetY);
surfaceNode_->SetShadowOffsetY(offsetY);
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetBlur(float radius)
{
WMError ret = CheckParmAndPermission();
if (ret != WMError::WM_OK) {
return ret;
}
WLOGFI("Set window %{public}s blur radius %{public}f", GetWindowName().c_str(), radius);
if (MathHelper::LessNotEqual(radius, 0.0)) {
return WMError::WM_ERROR_INVALID_PARAM;
}
radius = ConvertRadiusToSigma(radius);
WLOGFI("Set window %{public}s blur radius after conversion %{public}f", GetWindowName().c_str(), radius);
surfaceNode_->SetFilter(RSFilter::CreateBlurFilter(radius, radius));
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetBackdropBlur(float radius)
{
WMError ret = CheckParmAndPermission();
if (ret != WMError::WM_OK) {
return ret;
}
WLOGFI("Set window %{public}s backdrop blur radius %{public}f", GetWindowName().c_str(), radius);
if (MathHelper::LessNotEqual(radius, 0.0)) {
return WMError::WM_ERROR_INVALID_PARAM;
}
radius = ConvertRadiusToSigma(radius);
WLOGFI("Set window %{public}s backdrop blur radius after conversion %{public}f", GetWindowName().c_str(), radius);
surfaceNode_->SetBackgroundFilter(RSFilter::CreateBlurFilter(radius, radius));
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetBackdropBlurStyle(WindowBlurStyle blurStyle)
{
WMError ret = CheckParmAndPermission();
if (ret != WMError::WM_OK) {
return ret;
}
WLOGFI("Set window %{public}s backdrop blur style %{public}u", GetWindowName().c_str(), blurStyle);
if (blurStyle < WindowBlurStyle::WINDOW_BLUR_OFF || blurStyle > WindowBlurStyle::WINDOW_BLUR_THICK) {
return WMError::WM_ERROR_INVALID_PARAM;
}
if (blurStyle == WindowBlurStyle::WINDOW_BLUR_OFF) {
surfaceNode_->SetBackgroundFilter(nullptr);
} else {
auto display = SingletonContainer::IsDestroyed() ? nullptr :
SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display == nullptr) {
WLOGFE("get display failed displayId:%{public}" PRIu64, property_->GetDisplayId());
return WMError::WM_ERROR_INVALID_PARAM;
}
auto displayInfo = display->GetDisplayInfo();
if (displayInfo == nullptr) {
WLOGFE("get displayInfo failed displayId:%{public}" PRIu64, property_->GetDisplayId());
return WMError::WM_ERROR_INVALID_PARAM;
}
surfaceNode_->SetBackgroundFilter(RSFilter::CreateMaterialFilter(
static_cast<int>(blurStyle), GetVirtualPixelRatio(displayInfo)));
}
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetPrivacyMode(bool isPrivacyMode)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
WLOGFD("id : %{public}u, %{public}u", GetWindowId(), isPrivacyMode);
property_->SetPrivacyMode(isPrivacyMode);
return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_PRIVACY_MODE);
}
bool WindowSceneSessionImpl::IsPrivacyMode() const
{
if (IsWindowSessionInvalid()) {
return false;
}
return property_->GetPrivacyMode();
}
void WindowSceneSessionImpl::SetSystemPrivacyMode(bool isSystemPrivacyMode)
{
WLOGFD("id : %{public}u, %{public}u", GetWindowId(), isSystemPrivacyMode);
property_->SetSystemPrivacyMode(isSystemPrivacyMode);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_SYSTEM_PRIVACY_MODE);
}
WMError WindowSceneSessionImpl::SetSnapshotSkip(bool isSkip)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
bool oldSkipValue = property_->GetSnapshotSkip();
property_->SetSnapshotSkip(isSkip);
auto resError = UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_SNAPSHOT_SKIP);
if (resError != WMError::WM_OK) {
property_->SetSnapshotSkip(oldSkipValue);
}
return resError;
}
WMError WindowSceneSessionImpl::NotifyMemoryLevel(int32_t level)
{
TLOGI(WmsLogTag::DEFAULT, "id: %{public}u, level: %{public}d", GetWindowId(), level);
std::shared_ptr<Ace::UIContent> uiContent = GetUIContentSharedPtr();
if (uiContent == nullptr) {
WLOGFE("Window %{public}s notify failed, uiContent is null.", GetWindowName().c_str());
return WMError::WM_ERROR_NULLPTR;
}
uiContent->NotifyMemoryLevel(level);
WLOGFD("End!");
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetTurnScreenOn(bool turnScreenOn)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
property_->SetTurnScreenOn(turnScreenOn);
return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_TURN_SCREEN_ON);
}
bool WindowSceneSessionImpl::IsTurnScreenOn() const
{
return property_->IsTurnScreenOn();
}
WMError WindowSceneSessionImpl::SetKeepScreenOn(bool keepScreenOn)
{
if (IsWindowSessionInvalid()) {
WLOGFE("session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
property_->SetKeepScreenOn(keepScreenOn);
return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_KEEP_SCREEN_ON);
}
bool WindowSceneSessionImpl::IsKeepScreenOn() const
{
return property_->IsKeepScreenOn();
}
WMError WindowSceneSessionImpl::SetViewKeepScreenOn(bool keepScreenOn)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "id: %{public}d, enabled: %{public}u", GetPersistentId(), keepScreenOn);
property_->SetViewKeepScreenOn(keepScreenOn);
return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_VIEW_KEEP_SCREEN_ON);
}
bool WindowSceneSessionImpl::IsViewKeepScreenOn() const
{
return property_->IsViewKeepScreenOn();
}
WMError WindowSceneSessionImpl::SetWindowShadowEnabled(bool isEnabled)
{
if (property_->GetPcAppInpadCompatibleMode()) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "This is PcAppInPad, not supported");
return WMError::WM_OK;
}
if (!windowSystemConfig_.IsPcWindow() && !windowSystemConfig_.IsPadWindow()) {
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
property_->SetWindowShadowEnabled(isEnabled);
return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_SHADOW_ENABLED);
}
bool WindowSceneSessionImpl::GetWindowShadowEnabled() const
{
return property_->GetWindowShadowEnabled();
}
WMError WindowSceneSessionImpl::SetTransform(const Transform& trans)
{
TLOGI(WmsLogTag::DEFAULT, "Id: %{public}d", property_->GetPersistentId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::DEFAULT, "Session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
Transform oriTrans = property_->GetTransform();
property_->SetTransform(trans);
TransformSurfaceNode(trans);
return WMError::WM_OK;
}
const Transform& WindowSceneSessionImpl::GetTransform() const
{
return property_->GetTransform();
}
void WindowSceneSessionImpl::TransformSurfaceNode(const Transform& trans)
{
if (surfaceNode_ == nullptr) {
return;
}
surfaceNode_->SetPivotX(trans.pivotX_);
surfaceNode_->SetPivotY(trans.pivotY_);
surfaceNode_->SetScaleX(trans.scaleX_);
surfaceNode_->SetScaleY(trans.scaleY_);
surfaceNode_->SetTranslateX(trans.translateX_);
surfaceNode_->SetTranslateY(trans.translateY_);
surfaceNode_->SetTranslateZ(trans.translateZ_);
surfaceNode_->SetRotationX(trans.rotationX_);
surfaceNode_->SetRotationY(trans.rotationY_);
surfaceNode_->SetRotation(trans.rotationZ_);
uint32_t animationFlag = property_->GetAnimationFlag();
if (animationFlag != static_cast<uint32_t>(WindowAnimation::CUSTOM)) {
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
}
}
WMError WindowSceneSessionImpl::RegisterAnimationTransitionController(
const sptr<IAnimationTransitionController>& listener)
{
if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) {
TLOGE(WmsLogTag::WMS_SYSTEM, "permission denied!");
return WMError::WM_ERROR_NOT_SYSTEM_APP;
}
if (listener == nullptr) {
TLOGE(WmsLogTag::WMS_SYSTEM, "listener is nullptr");
return WMError::WM_ERROR_NULLPTR;
}
{
std::lock_guard<std::mutex> lockListener(transitionControllerMutex_);
if (std::find(animationTransitionControllers_.begin(), animationTransitionControllers_.end(), listener) ==
animationTransitionControllers_.end()) {
animationTransitionControllers_.push_back(listener);
}
}
wptr<WindowSessionProperty> propertyWeak(property_);
wptr<IAnimationTransitionController> animationTransitionControllerWeak(listener);
if (auto uiContent = GetUIContentSharedPtr()) {
uiContent->SetNextFrameLayoutCallback([propertyWeak, animationTransitionControllerWeak]() {
auto property = propertyWeak.promote();
auto animationTransitionController = animationTransitionControllerWeak.promote();
if (!property || !animationTransitionController) {
TLOGE(WmsLogTag::WMS_SYSTEM, "property or animation transition controller is nullptr");
return;
}
uint32_t animationFlag = property->GetAnimationFlag();
if (animationFlag == static_cast<uint32_t>(WindowAnimation::CUSTOM)) {
animationTransitionController->AnimationForShown();
}
TLOGI(WmsLogTag::WMS_SYSTEM, "AnimationForShown excute sucess %{public}d!", property->GetPersistentId());
});
}
TLOGI(WmsLogTag::WMS_SYSTEM, "%{public}d!", property_->GetPersistentId());
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::UpdateSurfaceNodeAfterCustomAnimation(bool isAdd)
{
TLOGI(WmsLogTag::WMS_SYSTEM, "id:%{public}d, isAdd:%{public}u", property_->GetPersistentId(), isAdd);
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsSystemWindow(property_->GetWindowType())) {
TLOGE(WmsLogTag::WMS_SYSTEM, "only system window can set");
return WMError::WM_ERROR_INVALID_OPERATION;
}
WMError ret = UpdateAnimationFlagProperty(false);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_SYSTEM, "UpdateAnimationFlagProperty failed!");
return ret;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
ret = static_cast<WMError>(hostSession->UpdateWindowSceneAfterCustomAnimation(isAdd));
return ret;
}
void WindowSceneSessionImpl::AdjustWindowAnimationFlag(bool withAnimation)
{
if (IsWindowSessionInvalid()) {
WLOGFW("session invalid!");
return;
}
WindowType winType = property_->GetWindowType();
bool isAppWindow = WindowHelper::IsAppWindow(winType);
bool hasTransitionController = false;
bool enableDefaultAnimation = false;
{
std::lock_guard<std::mutex> lockListener(transitionControllerMutex_);
hasTransitionController = !animationTransitionControllers_.empty();
enableDefaultAnimation = enableDefaultAnimation_;
}
if (withAnimation && !isAppWindow && hasTransitionController) {
property_->SetAnimationFlag(static_cast<uint32_t>(WindowAnimation::CUSTOM));
} else if ((isAppWindow && enableDefaultAnimation) || (withAnimation && !hasTransitionController)) {
property_->SetAnimationFlag(static_cast<uint32_t>(WindowAnimation::DEFAULT));
} else {
property_->SetAnimationFlag(static_cast<uint32_t>(WindowAnimation::NONE));
}
}
WMError WindowSceneSessionImpl::UpdateAnimationFlagProperty(bool withAnimation)
{
if (!WindowHelper::IsSystemWindow(GetType())) {
return WMError::WM_OK;
}
AdjustWindowAnimationFlag(withAnimation);
return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG);
}
WMError WindowSceneSessionImpl::SetAlpha(float alpha)
{
WLOGFI("%{public}d alpha %{public}f", property_->GetPersistentId(), alpha);
if (!SessionPermission::IsSystemCalling() && !SessionPermission::IsStartByHdcd()) {
WLOGFE("permission denied!");
return WMError::WM_ERROR_NOT_SYSTEM_APP;
}
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
surfaceNode_->SetAlpha(alpha);
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::BindDialogTarget(sptr<IRemoteObject> targetToken)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_DIALOG, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto persistentId = property_->GetPersistentId();
TLOGI(WmsLogTag::WMS_DIALOG, "id: %{public}d", persistentId);
WMError ret = SingletonContainer::Get<WindowAdapter>().BindDialogSessionTarget(persistentId, targetToken);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_DIALOG, "bind window failed with errCode:%{public}d", static_cast<int32_t>(ret));
RecordLifeCycleExceptionEvent(ret,
WMErrorReason::WM_REASON_SUB_WINDOW_IPC_BIND_DIALOG_TARGET_ERR,
"sub window bind dialog target failed when ipc");
}
return ret;
}
WMError WindowSceneSessionImpl::SetDialogBackGestureEnabled(bool isEnabled)
{
WindowType windowType = GetType();
if (windowType != WindowType::WINDOW_TYPE_DIALOG) {
TLOGE(WmsLogTag::WMS_DIALOG, "windowType not support. WinId:%{public}u, WindowType:%{public}u",
GetWindowId(), static_cast<uint32_t>(windowType));
return WMError::WM_ERROR_INVALID_CALLING;
}
auto hostSession = GetHostSession();
if (hostSession == nullptr) {
TLOGE(WmsLogTag::WMS_DIALOG, "set window failed because of nullptr");
return WMError::WM_ERROR_NULLPTR;
}
WMError ret = static_cast<WMError>(hostSession->SetDialogSessionBackGestureEnabled(isEnabled));
dialogSessionBackGestureEnabled_ = isEnabled;
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_DIALOG, "set window failed with errCode:%{public}d", static_cast<int32_t>(ret));
}
return ret;
}
WMError WindowSceneSessionImpl::SetTouchHotAreas(const std::vector<Rect>& rects)
{
std::vector<Rect> lastTouchHotAreas;
property_->GetTouchHotAreas(lastTouchHotAreas);
property_->SetTouchHotAreas(rects);
WMError result = UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_TOUCH_HOT_AREA);
if (result != WMError::WM_OK) {
property_->SetTouchHotAreas(lastTouchHotAreas);
WLOGFE("errCode:%{public}d", static_cast<int32_t>(result));
return result;
}
for (uint32_t i = 0; i < rects.size(); i++) {
TLOGD(WmsLogTag::WMS_EVENT, "id:%{public}u xywh:[%{public}d %{public}d %{public}u %{public}u]",
i, rects[i].posX_, rects[i].posY_, rects[i].width_, rects[i].height_);
}
return result;
}
WMError WindowSceneSessionImpl::SetKeyboardTouchHotAreas(const KeyboardTouchHotAreas& hotAreas)
{
if (GetType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
return WMError::WM_ERROR_INVALID_TYPE;
}
std::vector<Rect> lastTouchHotAreas;
property_->GetTouchHotAreas(lastTouchHotAreas);
KeyboardTouchHotAreas lastKeyboardTouchHotAreas = property_->GetKeyboardTouchHotAreas();
if (IsLandscape(hotAreas.displayId_)) {
property_->SetTouchHotAreas(hotAreas.landscapeKeyboardHotAreas_);
} else {
property_->SetTouchHotAreas(hotAreas.portraitKeyboardHotAreas_);
}
property_->SetKeyboardTouchHotAreas(hotAreas);
WMError result = UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_KEYBOARD_TOUCH_HOT_AREA);
if (result != WMError::WM_OK) {
property_->SetTouchHotAreas(lastTouchHotAreas);
property_->SetKeyboardTouchHotAreas(lastKeyboardTouchHotAreas);
TLOGE(WmsLogTag::WMS_EVENT, "errCode:%{public}d", static_cast<int32_t>(result));
}
return result;
}
WmErrorCode WindowSceneSessionImpl::KeepKeyboardOnFocus(bool keepKeyboardFlag)
{
property_->KeepKeyboardOnFocus(keepKeyboardFlag);
return WmErrorCode::WM_OK;
}
WMError WindowSceneSessionImpl::ChangeCallingWindowId(uint32_t callingSessionId)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "session is invalid!");
return WMError::WM_ERROR_INVALID_WINDOW;
}
WindowType type = GetType();
uint32_t curCallingSessionId = property_->GetCallingSessionId();
if (type != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT || callingSessionId == curCallingSessionId ||
state_ != WindowState::STATE_SHOWN) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "set calling window id failed, type: %{public}d, newId: %{public}u,"
" state: %{public}d", type, callingSessionId, state_);
return WMError::WM_ERROR_INVALID_OPERATION;
}
TLOGI(WmsLogTag::WMS_KEYBOARD, "id: %{public}d, curId: %{public}u, newId: %{public}u",
property_->GetPersistentId(), curCallingSessionId, callingSessionId);
if (auto hostSession = GetHostSession()) {
hostSession->SetCallingSessionId(callingSessionId);
}
property_->SetCallingSessionId(callingSessionId);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::ChangeKeyboardEffectOption(KeyboardEffectOption effectOption)
{
TLOGI(WmsLogTag::WMS_KEYBOARD, "effect option: %{public}s",
effectOption.ToString().c_str());
if (effectOption.viewMode_ >= KeyboardViewMode::VIEW_MODE_END ||
effectOption.flowLightMode_ >= KeyboardFlowLightMode::END ||
effectOption.gradientMode_ >= KeyboardGradientMode::END) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "Invalid view or effect mode! effectOption: %{public}s",
effectOption.ToString().c_str());
return WMError::WM_ERROR_INVALID_PARAM;
}
auto lastOption = property_->GetKeyboardEffectOption();
if (effectOption == lastOption) {
TLOGI(WmsLogTag::WMS_KEYBOARD, "Is same option: %{public}s", lastOption.ToString().c_str());
return WMError::WM_DO_NOTHING;
}
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "Session is invalid!");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (state_ != WindowState::STATE_SHOWN) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "The keyboard is not show status.");
return WMError::WM_ERROR_INVALID_WINDOW;
}
property_->SetKeyboardEffectOption(effectOption);
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
return static_cast<WMError>(hostSession->ChangeKeyboardEffectOption(effectOption));
}
void WindowSceneSessionImpl::DumpSessionElementInfo(const std::vector<std::string>& params)
{
WLOGFD("in");
std::vector<std::string> info;
if (params.size() == 1 && params[0] == PARAM_DUMP_HELP) {
WLOGFD("Dump ArkUI help Info");
Ace::UIContent::ShowDumpHelp(info);
SingletonContainer::Get<WindowAdapter>().NotifyDumpInfoResult(info);
return;
}
WLOGFD("ArkUI:DumpInfo");
if (auto uiContent = GetUIContentSharedPtr()) {
uiContent->DumpInfo(params, info);
}
for (auto iter = info.begin(); iter != info.end();) {
if ((*iter).size() == 0) {
iter = info.erase(iter);
continue;
}
WLOGFD("ElementInfo size: %{public}u", static_cast<uint32_t>((*iter).size()));
iter++;
}
if (info.size() == 0) {
WLOGFD("ElementInfo is empty");
return;
}
SingletonContainer::Get<WindowAdapter>().NotifyDumpInfoResult(info);
}
WSError WindowSceneSessionImpl::NotifyLayoutFinishAfterWindowModeChange(WindowMode mode)
{
NotifyWindowStatusDidChange(mode);
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::NotifySubWindowAfterParentWindowSizeChange(Rect rect)
{
NotifyParentWindowSizeChange(rect);
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::NotifySubWindowAfterParentWindowStatusChange(WindowMode mode, MaximizeMode maximizeMode,
bool isLayoutFullScreen)
{
NotifyParentWindowStatusChange(mode, maximizeMode, isLayoutFullScreen);
return WSError::WS_OK;
}
bool WindowSceneSessionImpl::ShouldSkipSupportWindowModeCheck(uint32_t windowModeSupportType, WindowMode mode)
{
bool isFreeMultiWindowMode = IsFreeMultiWindowMode();
bool onlySupportSplitInFreeMultiWindow =
isFreeMultiWindowMode && mode == WindowMode::WINDOW_MODE_FLOATING &&
(WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_SPLIT_PRIMARY) ||
WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_SPLIT_SECONDARY) ||
WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_SPLIT)) &&
!WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FULLSCREEN);
if (onlySupportSplitInFreeMultiWindow) {
return true;
}
bool isMultiWindowMode = mode == WindowMode::WINDOW_MODE_FLOATING ||
WindowHelper::IsSplitWindowMode(mode);
bool isAvailableDevice =
(windowSystemConfig_.IsPhoneWindow() || windowSystemConfig_.IsPadWindow()) && !isFreeMultiWindowMode;
if (isAvailableDevice && isMultiWindowMode) {
return true;
}
bool isCompatibleWindow = mode == WindowMode::WINDOW_MODE_FLOATING ||
mode == WindowMode::WINDOW_MODE_FULLSCREEN;
bool isDragScale = property_->IsAdaptToDragScale();
if (windowSystemConfig_.IsPcOrPcMode() && isCompatibleWindow && isDragScale) {
return true;
}
bool isSupportedFullScreen = !windowSystemConfig_.IsPcWindow() && !isFreeMultiWindowMode &&
mode == WindowMode::WINDOW_MODE_FULLSCREEN;
if (isSupportedFullScreen) {
return true;
}
return false;
}
WSError WindowSceneSessionImpl::UpdateWindowMode(const WindowModeInfo& windowModeInfo)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::UpdateWindowMode");
windowModeInfo_ = windowModeInfo;
WindowMode mode = windowModeInfo.windowMode;
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"WMS::WindowModeUpdate::ClientRecv::UpdateWindowMode id=%u mode=%d splitStyle=%d splitIndex=%d",
GetWindowId(), static_cast<int32_t>(mode),
static_cast<int32_t>(windowModeInfo.splitStyle), windowModeInfo.splitIndex);
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ClientRecv] skip: session invalid, id:%{public}u, mode:%{public}u",
GetWindowId(), static_cast<uint32_t>(mode));
return WSError::WS_ERROR_INVALID_WINDOW;
}
uint32_t windowModeSupportType = property_->GetWindowModeSupportType();
auto preMode = GetWindowMode();
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ClientRecv] id:%{public}u, preMode:%{public}u, mode:%{public}u, "
"splitStyle:%{public}d, splitIndex:%{public}d, supportType:%{public}u",
GetWindowId(), static_cast<uint32_t>(preMode), static_cast<uint32_t>(mode),
static_cast<int32_t>(windowModeInfo.splitStyle), windowModeInfo.splitIndex, windowModeSupportType);
if (!WindowHelper::IsWindowModeSupported(windowModeSupportType, mode) &&
!ShouldSkipSupportWindowModeCheck(windowModeSupportType, mode)) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ClientRecv] skip: mode not supported, id:%{public}u, mode:%{public}u, "
"supportType:%{public}u", GetWindowId(), static_cast<uint32_t>(mode), windowModeSupportType);
return WSError::WS_ERROR_INVALID_WINDOW_MODE_OR_SIZE;
}
if (mode != WindowMode::WINDOW_MODE_FULLSCREEN) {
UpdateIsShowDecorInFreeMultiWindow(true);
isMaximizeInvoked_ = false;
}
WMError ret = UpdateWindowModeImmediately(windowModeInfo);
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:ClientRecv] done, id:%{public}u, mode:%{public}u, ret:%{public}d",
GetWindowId(), static_cast<uint32_t>(mode), static_cast<int32_t>(ret));
return static_cast<WSError>(ret);
}
WSError WindowSceneSessionImpl::GetTopNavDestinationName(std::string& topNavDestName)
{
auto uiContent = GetUIContentSharedPtr();
if (uiContent == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "uiContent is null: winId=%{public}u", GetWindowId());
return WSError::WS_DO_NOTHING;
}
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "call uicontent: winId=%{public}u", GetWindowId());
std::string navDestInfoJsonStr = uiContent->GetTopNavDestinationInfo(false, false);
if (navDestInfoJsonStr.empty()) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "winId=%{public}u, empty navDestInfoJsonStr", GetWindowId());
return WSError::WS_OK;
}
nlohmann::json navDestInfoJson = nlohmann::json::parse(navDestInfoJsonStr, nullptr, false);
if (navDestInfoJson.is_discarded()) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "parse json error: winId=%{public}u, navDestInfoJsonStr=%{public}s",
GetWindowId(), navDestInfoJsonStr.c_str());
return WSError::WS_DO_NOTHING;
}
if (navDestInfoJson.contains("name") && navDestInfoJson["name"].is_string()) {
navDestInfoJson["name"].get_to(topNavDestName);
}
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "winId=%{public}u, navDestInfoJsonStr=%{public}s, topNavDestName=%{public}s",
GetWindowId(), navDestInfoJsonStr.c_str(), topNavDestName.c_str());
return WSError::WS_OK;
}
WMError WindowSceneSessionImpl::UpdateWindowModeImmediately(const WindowModeInfo& windowModeInfo)
{
WindowMode mode = windowModeInfo.windowMode;
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowModeUpdate:Inner] UpdateWindowModeImmediately id:%{public}u, mode:%{public}u, "
"splitStyle:%{public}d, splitIndex:%{public}d, state:%{public}u",
GetWindowId(), static_cast<uint32_t>(mode),
static_cast<int32_t>(windowModeInfo.splitStyle), windowModeInfo.splitIndex,
static_cast<uint32_t>(state_));
if (state_ == WindowState::STATE_CREATED || state_ == WindowState::STATE_HIDDEN) {
property_->SetWindowModeInfo(windowModeInfo);
UpdateTitleButtonVisibility();
UpdateDecorEnable(true);
} else if (state_ == WindowState::STATE_SHOWN) {
property_->SetWindowModeInfo(windowModeInfo);
UpdateTitleButtonVisibility();
UpdateDecorEnable(true, mode);
if (WindowHelper::IsSplitWindowMode(mode)) {
property_->SetMaximizeMode(MaximizeMode::MODE_RECOVER);
}
}
NotifyWindowStatusChange(mode);
return WMError::WM_OK;
}
WSError WindowSceneSessionImpl::UpdateMaximizeMode(MaximizeMode mode)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::UpdateMaximizeMode");
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "%{public}u mode %{public}u", GetWindowId(), static_cast<uint32_t>(mode));
std::shared_ptr<Ace::UIContent> uiContent = GetUIContentSharedPtr();
if (uiContent == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT_PC, "uiContent is null");
return WSError::WS_ERROR_INVALID_PARAM;
}
uiContent->UpdateMaximizeMode(mode);
property_->SetMaximizeMode(mode);
if (mode == MaximizeMode::MODE_RECOVER && enableImmersiveMode_.load()) {
enableImmersiveMode_.store(false);
property_->SetIsLayoutFullScreen(false);
if (auto hostSession = GetHostSession()) {
hostSession->OnLayoutFullScreenChange(false);
}
}
return WSError::WS_OK;
}
void WindowSceneSessionImpl::NotifySessionFullScreen(bool fullScreen)
{
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "winId: %{public}u", GetWindowId());
Maximize(fullScreen ? MaximizePresentation::ENTER_IMMERSIVE : MaximizePresentation::EXIT_IMMERSIVE);
}
WSError WindowSceneSessionImpl::UpdateTitleInTargetPos(bool isShow, int32_t height)
{
TLOGI(WmsLogTag::WMS_DECOR, "%{public}u isShow %{public}u, height %{public}u", GetWindowId(), isShow, height);
if (IsWindowSessionInvalid()) {
return WSError::WS_ERROR_INVALID_WINDOW;
}
std::shared_ptr<Ace::UIContent> uiContent = GetUIContentSharedPtr();
if (uiContent == nullptr) {
TLOGE(WmsLogTag::WMS_DECOR, "uiContent is null");
return WSError::WS_ERROR_INVALID_PARAM;
}
const bool isPcMode = system::GetBoolParameter("persist.sceneboard.ispcmode", false);
if (isPcMode && windowSystemConfig_.isDockAutoHide_ && (isDecorHiddenByApp_ || isMaximizeInvoked_ ||
property_->IsAdaptToImmersive()) && !IsAnco() && GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) {
TLOGI(WmsLogTag::WMS_DECOR, "dock auto hide skip updateTitleInTargetPos");
return WSError::WS_OK;
}
isTitleShowInFullScreen_ = isShow && height >= 0 && GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN;
NotifyTitleChange(isShow, height);
uiContent->UpdateTitleInTargetPos(isShow, height);
return WSError::WS_OK;
}
void WindowSceneSessionImpl::UpdateSupportWindowModesWhenSwitchFreeMultiWindow()
{
auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context_);
if (abilityContext == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT, "abilityContext is nullptr");
return;
}
auto abilityInfo = abilityContext->GetAbilityInfo();
if (abilityInfo == nullptr) {
TLOGE(WmsLogTag::DEFAULT, "abilityInfo is nullptr!");
return;
}
uint32_t windowModeSupportType = 0;
std::vector<AppExecFwk::SupportWindowMode> supportedWindowModes;
property_->GetSupportedWindowModes(supportedWindowModes);
auto size = supportedWindowModes.size();
if (windowSystemConfig_.freeMultiWindowEnable_ && size > 0 && size <= WINDOW_SUPPORT_MODE_MAX_SIZE) {
windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(supportedWindowModes);
} else {
std::vector<AppExecFwk::SupportWindowMode> updateWindowModes =
ExtractSupportWindowModeFromMetaData(abilityInfo);
windowModeSupportType = WindowHelper::ConvertSupportModesToSupportType(updateWindowModes);
}
property_->SetWindowModeSupportType(windowModeSupportType);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO);
if (windowSystemConfig_.freeMultiWindowEnable_) {
if (haveSetSupportedWindowModes_) {
UpdateTitleButtonVisibility();
}
maximizeWhenSwitchMultiWindowIfOnlySupportFullScreen();
}
}
void WindowSceneSessionImpl::UpdateEnableDragWhenSwitchMultiWindow(bool enable)
{
if (hasSetEnableDrag_.load() || property_->IsDragResizeDisabled()) {
TLOGI(WmsLogTag::WMS_LAYOUT, "EnableDrag is already set, id: %{public}d", GetPersistentId());
return;
}
auto isSystemWindow = WindowHelper::IsSystemWindow(property_->GetWindowType());
bool isDialog = WindowHelper::IsDialogWindow(property_->GetWindowType());
bool isSystemCalling = property_->GetSystemCalling();
TLOGI(WmsLogTag::WMS_LAYOUT, "windId: %{public}d, isSystemWindow: %{public}d, isDialog: %{public}d, "
"isSystemCalling: %{public}d", GetPersistentId(), isSystemWindow, isDialog, isSystemCalling);
if (!enable || (isSystemWindow && !isDialog && !isSystemCalling)) {
property_->SetDragEnabled(false);
} else {
property_->SetDragEnabled(true);
}
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_DRAGENABLED);
}
void WindowSceneSessionImpl::UpdateSubWindowDragEnabledByDecorVisible()
{
if (hasSetEnableDrag_.load() || property_->IsDragResizeDisabled()) {
return;
}
if (!WindowHelper::IsSubWindow(GetType())) {
return;
}
bool decorVisible = false;
GetDecorVisible(decorVisible);
property_->SetDragEnabled(decorVisible);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_DRAGENABLED);
TLOGI(WmsLogTag::WMS_LAYOUT, "id: %{public}d, decorVisible: %{public}d", GetPersistentId(), decorVisible);
}
WSError WindowSceneSessionImpl::SwitchFreeMultiWindow(bool enable,
const std::set<ScreenId>& supportMultiWindowScreenSet)
{
if (IsWindowSessionInvalid()) {
return WSError::WS_ERROR_INVALID_WINDOW;
}
windowSystemConfig_.supportMultiWindowScreenSet_ = supportMultiWindowScreenSet;
bool isUiExtSubWindow = WindowHelper::IsSubWindow(property_->GetWindowType()) &&
property_->GetIsUIExtFirstSubWindow();
if (!WindowHelper::IsMainWindow(property_->GetWindowType()) && !isUiExtSubWindow) {
return WSError::WS_ERROR_INVALID_WINDOW;
}
if (windowSystemConfig_.freeMultiWindowEnable_ == enable) {
UpdateSupportWindowModesWhenSwitchFreeMultiWindow();
return WSError::WS_ERROR_REPEAT_OPERATION;
}
SetFreeMultiWindowMode(enable);
NotifySwitchFreeMultiWindow(enable);
NotifyFreeWindowModeChange(enable);
if (IsAnco() && windowSystemConfig_.IsPadWindow()) {
if (!IsAncoSupportFreeWindow()) {
uint32_t tempWindowModeSupportType = property_->GetWindowModeSupportType();
property_->SetWindowModeSupportType(lastWindowModeSupportType_);
lastWindowModeSupportType_ = tempWindowModeSupportType;
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO);
}
} else {
UpdateSupportWindowModesWhenSwitchFreeMultiWindow();
}
if (enable && IsAnco() && windowSystemConfig_.IsPadWindow()) {
uiContent_->SetContainerModalTitleVisible(false, true);
uiContent_->EnableContainerModalCustomGesture(true);
}
UpdateEnableDragWhenSwitchMultiWindow(enable);
if (!enable && !WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(),
WindowMode::WINDOW_MODE_FULLSCREEN)) {
UpdateDecorEnable(true);
}
if (!IsAnco()) {
UpdateImmersiveBySwitchMode(enable);
}
SwitchSubWindow(enable, GetPersistentId());
SwitchSystemWindow(enable, GetPersistentId());
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::ConfigDockAutoHide(bool isDockAutoHide)
{
windowSystemConfig_.isDockAutoHide_ = isDockAutoHide;
UpdateDecorEnable(true);
std::vector<sptr<WindowSessionImpl>> subWindows;
GetSubWindows(GetPersistentId(), subWindows);
for (auto& subWindowSession : subWindows) {
if (subWindowSession != nullptr) {
subWindowSession->SetDockAutoHide(isDockAutoHide);
subWindowSession->UpdateDecorEnable(true);
}
}
return WSError::WS_OK;
}
void WindowSceneSessionImpl::maximizeWhenSwitchMultiWindowIfOnlySupportFullScreen()
{
uint32_t windowModeSupportType = property_->GetWindowModeSupportType();
bool onlySupportFullScreen =
WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FULLSCREEN) &&
!WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FLOATING);
bool disableFullScreen = property_->IsFullScreenDisabled();
if (onlySupportFullScreen && !disableFullScreen) {
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "only support fullscreen, enter immersive");
Maximize(MaximizePresentation::ENTER_IMMERSIVE);
}
bool onlySupportFloating =
!WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FULLSCREEN) &&
WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FLOATING);
if (onlySupportFloating && GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) {
TLOGI(WmsLogTag::WMS_LAYOUT_PC, "only support floating, switch to floating, id: %{public}d",
GetPersistentId());
Recover(REASON_MAXIMIZE_MODE_CHANGE);
}
}
void WindowSceneSessionImpl::UpdateImmersiveBySwitchMode(bool freeMultiWindowEnable)
{
uint32_t windowModeSupportType = property_->GetWindowModeSupportType();
if (freeMultiWindowEnable) {
cacheEnableImmersiveMode_.store(enableImmersiveMode_);
if (enableImmersiveMode_ &&
WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FLOATING) &&
!(IsAnco() && windowSystemConfig_.IsPhoneWindow())) {
maximizeLayoutFullScreen_.store(false);
enableImmersiveMode_.store(false);
property_->SetIsLayoutFullScreen(enableImmersiveMode_);
if (auto hostSession = GetHostSession()) {
hostSession->OnLayoutFullScreenChange(enableImmersiveMode_);
} else {
TLOGE(WmsLogTag::WMS_LAYOUT, "host session is nullptr, id: %{public}d", GetPersistentId());
}
}
}
if (!freeMultiWindowEnable) {
bool isNeedRemoveMaximizeLayout = maximizeLayoutFullScreen_.load() && !cacheEnableImmersiveMode_;
bool isNeedRecoverLayout = cacheEnableImmersiveMode_ &&
WindowHelper::IsWindowModeSupported(windowModeSupportType, WindowMode::WINDOW_MODE_FLOATING) &&
!(IsAnco() && windowSystemConfig_.IsPhoneWindow());
if (isNeedRemoveMaximizeLayout) {
maximizeLayoutFullScreen_.store(false);
enableImmersiveMode_.store(false);
}
if (isNeedRecoverLayout) {
enableImmersiveMode_.store(true);
cacheEnableImmersiveMode_.store(false);
}
if (isNeedRemoveMaximizeLayout || isNeedRecoverLayout) {
property_->SetIsLayoutFullScreen(enableImmersiveMode_);
SetLayoutFullScreenByApiVersion(enableImmersiveMode_);
if (auto hostSession = GetHostSession()) {
hostSession->OnLayoutFullScreenChange(enableImmersiveMode_);
} else {
TLOGE(WmsLogTag::WMS_LAYOUT, "host session is nullptr, id: %{public}d", GetPersistentId());
}
}
}
}
bool WindowSceneSessionImpl::GetFreeMultiWindowModeEnabledState()
{
return windowSystemConfig_.freeMultiWindowEnable_ &&
windowSystemConfig_.freeMultiWindowSupport_;
}
WSError WindowSceneSessionImpl::PcAppInPadNormalClose()
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_COMPAT, "window session invalid!");
return WSError::WS_ERROR_INVALID_WINDOW;
}
if (!property_->GetIsPcAppInPad()) {
TLOGE(WmsLogTag::WMS_COMPAT, "is not pcAppInPad, can not Close");
return WSError::WS_ERROR_INVALID_WINDOW;
}
Close();
return WSError::WS_OK;
}
void WindowSceneSessionImpl::NotifyIsFullScreenInForceSplitMode(bool isFullScreen)
{
TLOGI(WmsLogTag::WMS_COMPAT, "isFullScreen: %{public}u", isFullScreen);
if (isFullScreenInForceSplit_.load() == isFullScreen) {
TLOGI(WmsLogTag::WMS_COMPAT, "status has not changed");
return;
}
isFullScreenInForceSplit_.store(isFullScreen);
const auto& windowRect = GetRect();
NotifySizeChange(windowRect, WindowSizeChangeReason::FULL_SCREEN_IN_FORCE_SPLIT);
NotifyGlobalDisplayRectChange(windowRect, WindowSizeChangeReason::FULL_SCREEN_IN_FORCE_SPLIT);
auto hostSession = GetHostSession();
if (hostSession) {
hostSession->NotifyIsFullScreenInForceSplitMode(isFullScreen);
} else {
TLOGW(WmsLogTag::WMS_COMPAT, "hostSession is nullptr");
}
}
WMError WindowSceneSessionImpl::NotifySplitRatioChanged(float newRatio)
{
TLOGI(WmsLogTag::WMS_COMPAT, "windowId: %{public}u, new ratio is: %{public}f", GetWindowId(), newRatio);
auto hookWindowInfo = GetProperty()->GetHookWindowInfo();
if (!hookWindowInfo.enableHookWindow || !WindowHelper::IsMainWindow(GetType())
|| MathHelper::NearEqual(hookWindowInfo.widthHookRatio, newRatio)) {
TLOGW(WmsLogTag::WMS_COMPAT, "windowId: %{public}u, enableHookWindow: %{public}u, widthHookRatio: %{public}f, "
"no need to update hook info", GetWindowId(), static_cast<uint32_t>(hookWindowInfo.enableHookWindow),
hookWindowInfo.widthHookRatio);
return WMError::WM_DO_NOTHING;
}
bool isValid = std::any_of(VALID_SPLIT_RATIOS.begin(), VALID_SPLIT_RATIOS.end(),
[newRatio](float ratio) { return MathHelper::NearEqual(newRatio, ratio); });
if (!isValid) {
TLOGE(WmsLogTag::WMS_COMPAT, "invalid split ratio: %{public}f", newRatio);
return WMError::WM_ERROR_INVALID_PARAM;
}
auto hostSession = GetHostSession();
if (!hostSession) {
TLOGW(WmsLogTag::WMS_COMPAT, "hostSession is nullptr");
return WMError::WM_ERROR_NULLPTR;
}
WMError ret = hostSession->NotifySplitRatioChanged(newRatio);
if (ret == WMError::WM_OK) {
hookWindowInfo.widthHookRatio = newRatio;
SetAppHookWindowInfo(hookWindowInfo);
}
return ret;
}
WSError WindowSceneSessionImpl::NotifyCompatibleModePropertyChange(const sptr<CompatibleModeProperty> property)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_COMPAT, "window session invalid!");
return WSError::WS_ERROR_INVALID_WINDOW;
}
property_->SetCompatibleModeProperty(property);
return WSError::WS_OK;
}
WMError WindowSceneSessionImpl::NotifyPageEnable(const std::string& action, const std::string& message)
{
TLOGI(WmsLogTag::WMS_COMPAT, "action:%{public}zu, message:%{public}zu", action.length(), message.length());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_COMPAT, "window session invalid!");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
WSError ret = hostSession->NotifyPageEnable(action, message);
if (ret != WSError::WS_OK) {
TLOGE(WmsLogTag::WMS_COMPAT, "NotifyPageEnable failed, ret: %{public}d", static_cast<int32_t>(ret));
return static_cast<WMError>(ret);
}
return WMError::WM_OK;
}
void WindowSceneSessionImpl::NotifySessionForeground(uint32_t reason, bool withAnimation)
{
TLOGI(WmsLogTag::WMS_LIFE, "in");
if (!handler_) {
TLOGE(WmsLogTag::WMS_LIFE, "handler is nullptr");
return;
}
handler_->PostTask([weakThis = wptr(this), reason, withAnimation] {
auto window = weakThis.promote();
if (!window) {
TLOGNE(WmsLogTag::WMS_LIFE, "window is nullptr");
return;
}
window->Show(reason, withAnimation);
}, __func__);
}
void WindowSceneSessionImpl::NotifySessionBackground(uint32_t reason, bool withAnimation, bool isFromInnerkits)
{
TLOGI(WmsLogTag::WMS_LIFE, "in");
if (!handler_) {
TLOGE(WmsLogTag::WMS_LIFE, "handler is nullptr");
return;
}
handler_->PostTask([weakThis = wptr(this), reason, withAnimation, isFromInnerkits] {
auto window = weakThis.promote();
if (!window) {
TLOGNE(WmsLogTag::WMS_LIFE, "window is nullptr");
return;
}
window->Hide(reason, withAnimation, isFromInnerkits);
}, __func__);
}
WMError WindowSceneSessionImpl::NotifyPrepareClosePiPWindow(const bool isWeb)
{
TLOGI(WmsLogTag::WMS_PIP, "type: %{public}u", GetType());
if (!WindowHelper::IsPipWindow(GetType())) {
return WMError::WM_DO_NOTHING;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
if (isWeb && surfaceNode_ != nullptr) {
surfaceNode_->SetAlpha(0);
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
}
hostSession->NotifyPiPWindowPrepareClose();
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::GetWindowLimits(WindowLimits& windowLimits, bool getVirtualPixel)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::GetWindowLimits");
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
WindowLimits customizedLimits;
if (getVirtualPixel) {
customizedLimits = property_->GetWindowLimitsVP();
} else {
customizedLimits = property_->GetWindowLimits();
}
windowLimits.minWidth_ = customizedLimits.minWidth_;
windowLimits.minHeight_ = customizedLimits.minHeight_;
windowLimits.maxWidth_ = customizedLimits.maxWidth_;
windowLimits.maxHeight_ = customizedLimits.maxHeight_;
windowLimits.vpRatio_ = customizedLimits.vpRatio_;
windowLimits.pixelUnit_ = customizedLimits.pixelUnit_;
TLOGI(WmsLogTag::WMS_LAYOUT, "Id:%{public}u, minW:%{public}u, minH:%{public}u, "
"maxW:%{public}u, maxH:%{public}u, vpRatio:%{public}f, pixelUnit:%{public}u", GetWindowId(),
windowLimits.minWidth_, windowLimits.minHeight_, windowLimits.maxWidth_, windowLimits.maxHeight_,
windowLimits.vpRatio_, windowLimits.pixelUnit_);
return WMError::WM_OK;
}
void WindowSceneSessionImpl::UpdateNewSize()
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"WMS::WindowLimitsUpdate::UpdateSize id=%d", GetPersistentId());
if (GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING || property_->IsWindowLimitDisabled()) {
TLOGD(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:UpdateSize] skip: not floating or limit disabled, id:%{public}d",
GetPersistentId());
return;
}
bool needResize = false;
Rect windowRect = GetRequestRect();
if (windowRect.IsUninitializedSize()) {
windowRect = GetRect();
if (windowRect.IsUninitializedSize()) {
TLOGW(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:UpdateSize] skip: uninitialized size, id:%{public}u", GetWindowId());
return;
}
}
if (GetType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
return;
}
uint32_t width = windowRect.width_;
uint32_t height = windowRect.height_;
const auto& newLimits = property_->GetWindowLimits();
if (width < newLimits.minWidth_) {
width = newLimits.minWidth_;
needResize = true;
}
if (height < newLimits.minHeight_) {
height = newLimits.minHeight_;
needResize = true;
}
if (width > newLimits.maxWidth_) {
width = newLimits.maxWidth_;
needResize = true;
}
if (height > newLimits.maxHeight_) {
height = newLimits.maxHeight_;
needResize = true;
}
if (needResize) {
if (IsPcOrPadFreeMultiWindowMode()) {
isResizedByLimit_ = true;
}
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:UpdateSize] ResizeByLimits id:%{public}u, "
"preSize=%{public}ux%{public}u, newSize=%{public}ux%{public}u, "
"limits[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u]",
GetWindowId(), windowRect.width_, windowRect.height_, width, height,
newLimits.minWidth_, newLimits.minHeight_, newLimits.maxWidth_, newLimits.maxHeight_);
Resize(width, height);
}
}
bool WindowSceneSessionImpl::HasIntersectedAttachLimits() const
{
auto anchorInfo = property_->GetWindowAnchorInfo();
if (anchorInfo.isAnchoredByAttach_) {
if (anchorInfo.attachOptions.isIntersectedWidthLimit ||
anchorInfo.attachOptions.isIntersectedHeightLimit) {
return true;
}
}
for (const auto& [id, options] : property_->GetAttachedLimitOptionsList()) {
if (options.isIntersectedWidthLimit || options.isIntersectedHeightLimit) {
return true;
}
}
return false;
}
WindowLimits WindowSceneSessionImpl::ConvertBaseLimitsToTargetUnit(
const WindowLimits& srcLimits, PixelUnit targetPixelUnit)
{
float vpr = 1.0f;
WMError ret = GetVirtualPixelRatio(vpr);
if (ret != WMError::WM_OK || MathHelper::NearZero(vpr)) {
return (targetPixelUnit == PixelUnit::VP) ?
property_->GetWindowLimitsVP() : property_->GetWindowLimits();
}
WindowLimits result;
if (targetPixelUnit == PixelUnit::VP) {
RecalculateVpLimitsByPx(srcLimits, result, vpr);
} else {
RecalculatePxLimitsByVp(srcLimits, result, vpr);
}
result.maxRatio_ = srcLimits.maxRatio_;
result.minRatio_ = srcLimits.minRatio_;
result.vpRatio_ = vpr;
result.pixelUnit_ = targetPixelUnit;
return result;
}
WindowLimits WindowSceneSessionImpl::GetCustomizedLimitsForSetWindowLimits(
const WindowLimits& windowLimits)
{
if (HasIntersectedAttachLimits()) {
WindowLimits baseLimits = property_->GetLimitsForAttachedWindows();
if (baseLimits.pixelUnit_ == windowLimits.pixelUnit_) {
return baseLimits;
}
return ConvertBaseLimitsToTargetUnit(baseLimits, windowLimits.pixelUnit_);
}
if (windowLimits.pixelUnit_ == PixelUnit::VP) {
return property_->GetWindowLimitsVP();
}
return property_->GetWindowLimits();
}
WMError WindowSceneSessionImpl::SetWindowLimits(WindowLimits& windowLimits, bool isForcible)
{
HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER,
"WMS::WindowLimitsUpdate::ClientReq::SetWindowLimits id=%d", GetPersistentId());
auto preLimits = property_->GetWindowLimits();
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:ClientReq] SetWindowLimits id:%{public}u, "
"req[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] "
"pre[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] "
"unit:%{public}u forcible:%{public}u",
GetWindowId(), windowLimits.minWidth_, windowLimits.minHeight_,
windowLimits.maxWidth_, windowLimits.maxHeight_,
preLimits.minWidth_, preLimits.minHeight_, preLimits.maxWidth_, preLimits.maxHeight_,
windowLimits.pixelUnit_, isForcible);
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
WindowType windowType = GetType();
bool isDraggableSystemWin = WindowHelper::IsSystemWindow(windowType) && IsWindowDraggable();
if (!WindowHelper::IsMainWindow(windowType) && !WindowHelper::IsSubWindow(windowType) &&
windowType != WindowType::WINDOW_TYPE_DIALOG && !isDraggableSystemWin) {
TLOGE(WmsLogTag::WMS_LAYOUT, "type not support. Id:%{public}u, type:%{public}u",
GetWindowId(), static_cast<uint32_t>(windowType));
return WMError::WM_ERROR_INVALID_CALLING;
}
WindowLimits customizedLimits = GetCustomizedLimitsForSetWindowLimits(windowLimits);
forceLimits_ = (windowLimits.pixelUnit_ != PixelUnit::VP) ? isForcible : false;
userLimitsSet_ = true;
uint32_t minWidth = windowLimits.minWidth_ ? windowLimits.minWidth_ : customizedLimits.minWidth_;
uint32_t minHeight = windowLimits.minHeight_ ? windowLimits.minHeight_ : customizedLimits.minHeight_;
uint32_t maxWidth = windowLimits.maxWidth_ ? windowLimits.maxWidth_ : customizedLimits.maxWidth_;
uint32_t maxHeight = windowLimits.maxHeight_ ? windowLimits.maxHeight_ : customizedLimits.maxHeight_;
property_->SetUserWindowLimits({
maxWidth, maxHeight, minWidth, minHeight, customizedLimits.maxRatio_, customizedLimits.minRatio_,
customizedLimits.vpRatio_, windowLimits.pixelUnit_
});
UpdateWindowSizeLimits(true);
WMError ret = UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_LIMITS);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LAYOUT, "update window proeprty failed! id: %{public}u.", GetWindowId());
return ret;
}
UpdateNewSize();
FillWindowLimits(windowLimits, windowLimits.pixelUnit_);
return WMError::WM_OK;
}
void WindowSceneSessionImpl::FillWindowLimits(WindowLimits& windowLimits, PixelUnit pixelUnit)
{
WindowLimits newLimits;
if (pixelUnit == PixelUnit::VP) {
newLimits = property_->GetWindowLimitsVP();
} else {
newLimits = property_->GetWindowLimits();
}
windowLimits.minWidth_ = newLimits.minWidth_;
windowLimits.minHeight_ = newLimits.minHeight_;
windowLimits.maxWidth_ = newLimits.maxWidth_;
windowLimits.maxHeight_ = newLimits.maxHeight_;
windowLimits.pixelUnit_ = newLimits.pixelUnit_;
TLOGI(WmsLogTag::WMS_LAYOUT,
"[WindowLimitsUpdate:Result] FillWindowLimits id:%{public}u, "
"final[minW:%{public}u,minH:%{public}u,maxW:%{public}u,maxH:%{public}u] unit:%{public}u",
GetWindowId(), windowLimits.minWidth_, windowLimits.minHeight_,
windowLimits.maxWidth_, windowLimits.maxHeight_, windowLimits.pixelUnit_);
}
WSError WindowSceneSessionImpl::NotifyDialogStateChange(bool isForeground)
{
const auto type = GetType();
TLOGI(WmsLogTag::WMS_DIALOG, "state change [name:%{public}s, id:%{public}d, type:%{public}u], state:%{public}u,"
" requestState:%{public}u, isForeground:%{public}d", property_->GetWindowName().c_str(), GetPersistentId(),
type, state_, requestState_, static_cast<int32_t>(isForeground));
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_DIALOG, "session is invalid, id:%{public}d", GetPersistentId());
return WSError::WS_ERROR_INVALID_WINDOW;
}
if (isForeground) {
if (state_ == WindowState::STATE_SHOWN) {
return WSError::WS_OK;
}
if (state_ == WindowState::STATE_HIDDEN && requestState_ == WindowState::STATE_SHOWN) {
state_ = WindowState::STATE_SHOWN;
NotifyAfterForeground();
}
} else {
if (state_ == WindowState::STATE_HIDDEN) {
return WSError::WS_OK;
}
if (state_ == WindowState::STATE_SHOWN) {
state_ = WindowState::STATE_HIDDEN;
NotifyAfterBackground();
}
}
TLOGI(WmsLogTag::WMS_DIALOG, "success [name:%{public}s, id:%{public}d, type:%{public}u],"
" state:%{public}u, requestState:%{public}u", property_->GetWindowName().c_str(), property_->GetPersistentId(),
type, state_, requestState_);
return WSError::WS_OK;
}
WMError WindowSceneSessionImpl::SetDefaultDensityEnabled(bool enabled)
{
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "Id=%{public}d, enabled=%{public}d", GetWindowId(), enabled);
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "window is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "must be app main window");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (IsStageDefaultDensityEnabled() == enabled) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "defaultDensityEnabledGlobalConfig not change");
return WMError::WM_OK;
}
if (property_->IsAdaptToSimulationScale()) {
TLOGI(WmsLogTag::WMS_COMPAT, "compat mode not use default density");
return WMError::WM_OK;
}
if (auto hostSession = GetHostSession()) {
hostSession->OnDefaultDensityEnabled(enabled);
}
defaultDensityEnabledStageConfig_.store(enabled);
SetDefaultDensityEnabledValue(enabled);
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
for (const auto& winPair : windowSessionMap_) {
auto window = winPair.second.second;
if (window == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "window is nullptr");
continue;
}
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "Id=%{public}u set=%{public}u",
window->GetWindowId(), window->IsStageDefaultDensityEnabled());
window->SetDefaultDensityEnabledValue(window->IsStageDefaultDensityEnabled());
window->UpdateDensity();
}
return WMError::WM_OK;
}
bool WindowSceneSessionImpl::GetDefaultDensityEnabled()
{
return isDefaultDensityEnabled_.load();
}
float WindowSceneSessionImpl::GetVirtualPixelRatio(const sptr<DisplayInfo>& displayInfo)
{
if (displayInfo == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "displayInfo is nullptr");
return INVALID_DEFAULT_DENSITY;
}
if (IsDefaultDensityEnabled()) {
return displayInfo->GetDefaultVirtualPixelRatio();
}
if (useUniqueDensity_) {
return virtualPixelRatio_;
}
auto vpr = GetMainWindowCustomDensity();
return vpr >= MINIMUM_CUSTOM_DENSITY && vpr <= MAXIMUM_CUSTOM_DENSITY ? vpr : displayInfo->GetVirtualPixelRatio();
}
WMError WindowSceneSessionImpl::HideNonSecureWindows(bool shouldHide)
{
return SingletonContainer::Get<WindowAdapter>().AddOrRemoveSecureSession(property_->GetPersistentId(), shouldHide);
}
WMError WindowSceneSessionImpl::SetTextFieldAvoidInfo(double textFieldPositionY, double textFieldHeight)
{
TLOGI(WmsLogTag::WMS_KEYBOARD, "textFieldPositionY: %{public}f, textFieldHeight:%{public}f",
textFieldPositionY, textFieldHeight);
property_->SetTextFieldPositionY(textFieldPositionY);
property_->SetTextFieldHeight(textFieldHeight);
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_TEXTFIELD_AVOID_INFO);
return WMError::WM_OK;
}
std::unique_ptr<Media::PixelMap> WindowSceneSessionImpl::HandleWindowMask(
const std::vector<std::vector<uint32_t>>& windowMask)
{
const Rect& windowRect = GetRequestRect();
uint32_t maskHeight = windowMask.size();
if (maskHeight == 0) {
WLOGFE("WindowMask is invalid");
return nullptr;
}
uint32_t maskWidth = windowMask[0].size();
if ((windowRect.height_ > 0 && windowRect.height_ != maskHeight) ||
(windowRect.width_ > 0 && windowRect.width_ != maskWidth)) {
WLOGFE("WindowMask is invalid");
return nullptr;
}
constexpr uint32_t bgraChannel = 4;
Media::InitializationOptions opts;
opts.size.width = static_cast<int32_t>(maskWidth);
opts.size.height = static_cast<int32_t>(maskHeight);
uint32_t length = maskWidth * maskHeight * bgraChannel;
uint8_t* data = static_cast<uint8_t*>(malloc(length));
if (data == nullptr) {
WLOGFE("data is nullptr");
return nullptr;
}
constexpr uint32_t fullChannel = 255;
constexpr uint32_t greenChannel = 1;
constexpr uint32_t redChannel = 2;
constexpr uint32_t alphaChannel = 3;
for (uint32_t i = 0; i < maskHeight; i++) {
for (uint32_t j = 0; j < maskWidth; j++) {
uint32_t idx = i * maskWidth + j;
uint32_t value = (j < windowMask[i].size()) ? windowMask[i][j] : 1;
uint32_t channel = value > 0 ? fullChannel : 0;
uint32_t channelIndex = idx * bgraChannel;
data[channelIndex] = channel;
data[channelIndex + greenChannel] = channel;
data[channelIndex + redChannel] = fullChannel;
data[channelIndex + alphaChannel] = channel;
}
}
std::unique_ptr<Media::PixelMap> mask = Media::PixelMap::Create(reinterpret_cast<uint32_t*>(data), length, opts);
free(data);
return mask;
}
std::shared_ptr<Media::PixelMap> WindowSceneSessionImpl::HandleWindowMaskWithAlpha(
const uint8_t* windowMask, uint32_t maskWidth, uint32_t maskHeight)
{
if (windowMask == nullptr) {
TLOGE(WmsLogTag::WMS_EVENT, "windowMask is nullptr");
return nullptr;
}
constexpr uint32_t bgraChannel = 4;
Media::InitializationOptions opts;
opts.size.width = static_cast<int32_t>(maskWidth);
opts.size.height = static_cast<int32_t>(maskHeight);
size_t length = static_cast<size_t>(maskWidth) * static_cast<size_t>(maskHeight) * bgraChannel;
uint8_t* data = static_cast<uint8_t*>(malloc(length));
if (data == nullptr) {
TLOGE(WmsLogTag::WMS_EVENT, "data is nullptr");
return nullptr;
}
constexpr uint32_t fullChannel = 255;
constexpr uint32_t greenChannel = 1;
constexpr uint32_t redChannel = 2;
constexpr uint32_t alphaChannel = 3;
size_t totalPixels = static_cast<size_t>(maskWidth) * static_cast<size_t>(maskHeight);
for (size_t idx = 0; idx < totalPixels; idx++) {
size_t channelIndex = idx * bgraChannel;
data[channelIndex] = fullChannel;
data[channelIndex + greenChannel] = fullChannel;
data[channelIndex + redChannel] = fullChannel;
data[channelIndex + alphaChannel] = windowMask[idx];
}
std::shared_ptr<Media::PixelMap> mask = Media::PixelMap::Create(reinterpret_cast<uint32_t*>(data), length, opts);
free(data);
return mask;
}
WMError WindowSceneSessionImpl::ApplyWindowMask(const std::shared_ptr<Media::PixelMap>& mask)
{
auto rsMask = RSMask::CreatePixelMapMask(mask);
surfaceNode_->SetCornerRadius(0.0f);
if (property_->GetWindowShadows().hasRadiusValue_) {
surfaceNode_->SetShadowRadius(WINDOW_SHADOW_RADIUS_INVALID);
}
surfaceNode_->SetAbilityBGAlpha(0);
surfaceNode_->SetMask(rsMask);
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
hostSession->SetWindowCornerRadius(0);
ShadowsInfo shadowsInfo;
shadowsInfo.hasRadiusValue_ = true;
hostSession->SetWindowShadows(shadowsInfo);
property_->SetWindowMask(mask);
property_->SetIsShaped(true);
return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_MASK);
}
WMError WindowSceneSessionImpl::SetWindowMask(const std::vector<std::vector<uint32_t>>& windowMask)
{
TLOGI(WmsLogTag::WMS_PC, "WindowId: %{public}u", GetWindowId());
if (IsWindowSessionInvalid()) {
WLOGFE("session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
std::shared_ptr<Media::PixelMap> mask = HandleWindowMask(windowMask);
if (mask == nullptr) {
TLOGE(WmsLogTag::WMS_PC, "Failed to create pixelMap of window mask");
return WMError::WM_ERROR_INVALID_WINDOW;
}
return ApplyWindowMask(mask);
}
WMError WindowSceneSessionImpl::SetWindowMaskWithAlpha(const uint8_t* windowMask, uint32_t maskWidth,
uint32_t maskHeight)
{
TLOGI(WmsLogTag::WMS_EVENT, "WindowId: %{public}u, maskWidth: %{public}u, maskHeight: %{public}u",
GetWindowId(), maskWidth, maskHeight);
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_EVENT, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
std::shared_ptr<Media::PixelMap> mask = HandleWindowMaskWithAlpha(windowMask, maskWidth, maskHeight);
if (mask == nullptr) {
TLOGE(WmsLogTag::WMS_EVENT, "Failed to create pixelMap of window mask");
return WMError::WM_ERROR_INVALID_WINDOW;
}
return ApplyWindowMask(mask);
}
WMError WindowSceneSessionImpl::ClearWindowMask()
{
TLOGI(WmsLogTag::WMS_PC, "WindowId: %{public}u", GetWindowId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!property_->GetIsShaped()) {
TLOGE(WmsLogTag::WMS_PC, "The window is not shaped");
return WMError::WM_ERROR_INVALID_OPERATION;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
bool hasCornerRadius = property_->GetWindowCornerRadius() != WINDOW_CORNER_RADIUS_INVALID;
if (hasCornerRadius) {
hostSession->SetWindowCornerRadius(property_->GetWindowCornerRadius());
}
ShadowsInfo shadowsInfo = property_->GetWindowShadows();
bool hasShadowRadius = shadowsInfo.hasRadiusValue_;
if (hasShadowRadius) {
hostSession->SetWindowShadows(shadowsInfo);
surfaceNode_->SetShadowRadius(MathHelper::NearEqual(shadowsInfo.radius_, 0.0f) ?
WINDOW_SHADOW_RADIUS_INVALID : ConvertRadiusToSigma(shadowsInfo.radius_));
}
if (!(hasCornerRadius && hasShadowRadius)) {
hostSession->RecoverWindowEffect(!hasCornerRadius, !hasShadowRadius);
}
surfaceNode_->SetCornerRadius(rsCornerRadius_);
surfaceNode_->SetMask(nullptr);
RSTransactionAdapter::FlushImplicitTransaction(surfaceNode_);
property_->SetIsShaped(false);
WMError ret = UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_MASK);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_PC, "UpdateProperty failed, id:%{public}u", GetWindowId());
}
return ret;
}
WMError WindowSceneSessionImpl::SetIsGamePreLaunch(bool isGamePreLaunch)
{
isGamePreLaunch_ = isGamePreLaunch;
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::ClearIsGamePreLaunch()
{
isGamePreLaunch_ = false;
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetFollowParentMultiScreenPolicy(bool enabled)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsPadAndNotFreeMultiWindowCompatibleMode()) {
TLOGE(WmsLogTag::WMS_SUB, "This is PcAppInpad, not Suppored");
return WMError::WM_OK;
}
if (!IsPhonePadOrPcWindow()) {
TLOGE(WmsLogTag::WMS_SUB, "device not support");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!WindowHelper::IsSubWindow(GetType())) {
TLOGE(WmsLogTag::WMS_SUB, "called by invalid window type, type:%{public}d", GetType());
return WMError::WM_ERROR_INVALID_CALLING;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
hostSession->NotifyFollowParentMultiScreenPolicy(enabled);
property_->EditSessionInfo().isFollowParentMultiScreenPolicy = enabled;
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::UseImplicitAnimation(bool useImplicit)
{
TLOGI(WmsLogTag::WMS_PC, "WindowId: %{public}u", GetWindowId());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
return static_cast<WMError>(hostSession->UseImplicitAnimation(useImplicit));
}
WSError WindowSceneSessionImpl::UpdateBrightness(float brightness)
{
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "Wid: %{public}d, brightness: %{public}f", GetWindowId(), brightness);
property_->SetBrightness(brightness);
return WSError::WS_OK;
}
void WindowSceneSessionImpl::UpdateDensity()
{
UpdateDensityInner(nullptr);
}
void WindowSceneSessionImpl::UpdateDensityInner(const sptr<DisplayInfo>& info)
{
if (property_->GetUserWindowLimits().pixelUnit_ == PixelUnit::VP) {
UpdateWindowSizeLimits();
UpdateNewSize();
} else {
float vpr = 1.0f;
WMError ret = GetVirtualPixelRatio(vpr);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::DEFAULT, "Id:%{public}d, get vpr failed", GetPersistentId());
return;
}
bool hasIntersectedLimits = HasIntersectedAttachLimits();
WindowLimits limitsPx = hasIntersectedLimits ?
property_->GetLimitsForAttachedWindows() : property_->GetWindowLimits();
WindowLimits limitsVp = WindowLimits::DEFAULT_VP_LIMITS();
RecalculateVpLimitsByPx(limitsPx, limitsVp, vpr);
limitsPx.vpRatio_ = vpr;
limitsVp.vpRatio_ = vpr;
if (hasIntersectedLimits) {
CalculateAttachedWindowLimitsIntersection(limitsPx, limitsVp, vpr);
}
property_->SetWindowLimits(limitsPx);
property_->SetWindowLimitsVP(limitsVp);
property_->SetLastLimitsVpr(vpr);
if (hasIntersectedLimits) {
UpdateNewSize();
}
}
WMError ret = UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_LIMITS);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::DEFAULT, "update window property failed! id: %{public}u.", GetWindowId());
return;
}
NotifyDisplayInfoChange(info);
auto preRect = GetRect();
UpdateViewportConfig(preRect, WindowSizeChangeReason::UNDEFINED, nullptr, info);
TLOGD(WmsLogTag::DEFAULT, "[%{public}d, %{public}d, %{public}u, %{public}u]",
preRect.posX_, preRect.posY_, preRect.width_, preRect.height_);
}
WMError WindowSceneSessionImpl::RegisterKeyboardPanelInfoChangeListener(
const sptr<IKeyboardPanelInfoChangeListener>& listener)
{
std::lock_guard<std::mutex> lockListener(keyboardPanelInfoChangeListenerMutex_);
if (keyboardPanelInfoChangeListeners_ == nullptr) {
TLOGI(WmsLogTag::WMS_KEYBOARD, "id: %{public}d",
GetPersistentId());
keyboardPanelInfoChangeListeners_ = listener;
} else {
TLOGE(WmsLogTag::WMS_KEYBOARD, "listener already registered");
return WMError::WM_ERROR_INVALID_OPERATION;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::RegisterWindowAttachStateChangeListener(
const sptr<IWindowAttachStateChangeListner>& listener)
{
if (listener == nullptr) {
TLOGE(WmsLogTag::WMS_SUB, "id: %{public}d, listener is null", GetPersistentId());
return WMError::WM_ERROR_NULLPTR;
}
{
std::lock_guard<std::mutex> lockListener(windowAttachStateChangeListenerMutex_);
windowAttachStateChangeListener_ = listener;
}
TLOGD(WmsLogTag::WMS_SUB, "id: %{public}d listener registered", GetPersistentId());
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
hostSession->NotifyWindowAttachStateListenerRegistered(true);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::UnregisterWindowAttachStateChangeListener()
{
{
std::lock_guard<std::mutex> lockListener(windowAttachStateChangeListenerMutex_);
windowAttachStateChangeListener_ = nullptr;
}
TLOGD(WmsLogTag::WMS_SUB, "id: %{public}d listener unregistered", GetPersistentId());
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
hostSession->NotifyWindowAttachStateListenerRegistered(false);
return WMError::WM_OK;
}
WSError WindowSceneSessionImpl::NotifyWindowAttachStateChange(bool isAttach)
{
TLOGI(WmsLogTag::WMS_SUB, "id: %{public}d, isAttach:%{public}u.", GetPersistentId(), isAttach);
{
std::unique_lock<std::shared_mutex> lock(uiContentMutex_);
if (uiContent_ != nullptr) {
uiContent_->NotifyWindowAttachStateChange(isAttach);
}
}
if (handler_) {
handler_->PostTask(
[weakThis = wptr(this), isAttach] {
auto window = weakThis.promote();
if (!window) {
return;
}
window->attachState_ = static_cast<AttachState>(isAttach);
if (!isAttach && window->isNeedReleaseUIContent_) {
window->DestroyExistUIContent();
window->isNeedReleaseUIContent_ = false;
}
}, __func__);
}
if (lifecycleCallback_) {
TLOGI(WmsLogTag::WMS_SUB, "notifyAttachState id: %{public}d", GetPersistentId());
lifecycleCallback_->OnNotifyAttachState(isAttach);
}
std::lock_guard<std::mutex> lockListener(windowAttachStateChangeListenerMutex_);
if (!windowAttachStateChangeListener_) {
TLOGW(WmsLogTag::WMS_SUB, "listener is null");
return WSError::WS_ERROR_NULLPTR;
}
if (isAttach) {
windowAttachStateChangeListener_->AfterAttached();
} else {
windowAttachStateChangeListener_->AfterDetached();
}
return WSError::WS_OK;
}
WMError WindowSceneSessionImpl::UnregisterKeyboardPanelInfoChangeListener(
const sptr<IKeyboardPanelInfoChangeListener>& listener)
{
std::lock_guard<std::mutex> lockListener(keyboardPanelInfoChangeListenerMutex_);
keyboardPanelInfoChangeListeners_ = nullptr;
TLOGI(WmsLogTag::WMS_KEYBOARD, "id: %{public}d", GetPersistentId());
return WMError::WM_OK;
}
void WindowSceneSessionImpl::NotifyKeyboardPanelInfoChange(const KeyboardPanelInfo& keyboardPanelInfo)
{
TLOGI(WmsLogTag::WMS_KEYBOARD, "isShown: %{public}d, gravity: %{public}d"
", rect_: [%{public}d, %{public}d, %{public}d, %{public}d]", keyboardPanelInfo.isShowing_,
keyboardPanelInfo.gravity_, keyboardPanelInfo.rect_.posX_, keyboardPanelInfo.rect_.posY_,
keyboardPanelInfo.rect_.width_, keyboardPanelInfo.rect_.height_);
std::lock_guard<std::mutex> lockListener(keyboardPanelInfoChangeListenerMutex_);
if (keyboardPanelInfoChangeListeners_ && keyboardPanelInfoChangeListeners_.GetRefPtr()) {
keyboardPanelInfoChangeListeners_.GetRefPtr()->OnKeyboardPanelInfoChanged(keyboardPanelInfo);
} else {
TLOGI(WmsLogTag::WMS_KEYBOARD, "listener is unRegistered");
}
}
WSError WindowSceneSessionImpl::UpdateDisplayId(DisplayId displayId)
{
bool displayIdChanged = property_->GetDisplayId() != displayId;
property_->SetDisplayId(displayId);
NotifyDisplayInfoChange();
if (displayIdChanged) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "wid: %{public}d, displayId: %{public}" PRIu64, GetPersistentId(), displayId);
NotifyDisplayIdChange(displayId);
}
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::UpdateOrientation()
{
TLOGD(WmsLogTag::DMS, "id: %{public}d", GetPersistentId());
NotifyDisplayInfoChange();
return WSError::WS_OK;
}
void WindowSceneSessionImpl::NotifyDisplayInfoChange(const sptr<DisplayInfo>& info)
{
TLOGD(WmsLogTag::DMS, "wid: %{public}d", GetPersistentId());
sptr<DisplayInfo> displayInfo = nullptr;
DisplayId displayId = 0;
if (info == nullptr) {
displayId = property_->GetDisplayId();
auto display = SingletonContainer::IsDestroyed() ? nullptr :
SingletonContainer::Get<DisplayManager>().GetDisplayById(displayId);
if (display == nullptr) {
TLOGE(WmsLogTag::DMS, "get display by displayId %{public}" PRIu64 " failed.", displayId);
return;
}
displayInfo = display->GetDisplayInfo();
} else {
displayInfo = info;
}
if (displayInfo == nullptr) {
TLOGE(WmsLogTag::DMS, "get display info %{public}" PRIu64 " failed.", displayId);
return;
}
if (IsSystemDensityChanged(displayInfo)) {
lastSystemDensity_ = displayInfo->GetVirtualPixelRatio();
NotifySystemDensityChange(displayInfo->GetVirtualPixelRatio());
}
float density = GetVirtualPixelRatio(displayInfo);
DisplayOrientation orientation = displayInfo->GetDisplayOrientation();
auto context = GetContext();
if (context == nullptr || context->GetBundleName() == AppExecFwk::Constants::SCENE_BOARD_BUNDLE_NAME) {
TLOGE(WmsLogTag::DMS, "id:%{public}d failed, context is null.", GetPersistentId());
return;
}
auto token = context->GetToken();
if (token == nullptr) {
TLOGE(WmsLogTag::DMS, "get token window:%{public}d failed.", GetPersistentId());
return;
}
SingletonContainer::Get<WindowManager>().NotifyDisplayInfoChange(token, displayId, density, orientation);
}
bool WindowSceneSessionImpl::IsLandscape(uint64_t displayId)
{
int32_t displayWidth = 0;
int32_t displayHeight = 0;
displayId = (displayId == DISPLAY_ID_INVALID) ? property_->GetDisplayId() : displayId;
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(displayId);
if (display != nullptr) {
displayWidth = display->GetWidth();
displayHeight = display->GetHeight();
} else {
auto defaultDisplayInfo = DisplayManager::GetInstance().GetDefaultDisplay();
if (defaultDisplayInfo != nullptr) {
displayWidth = defaultDisplayInfo->GetWidth();
displayHeight = defaultDisplayInfo->GetHeight();
}
WindowInfoReporter::GetInstance().ReportKeyboardLifeCycleException(GetPersistentId(),
KeyboardLifeCycleException::HOT_AREA_EXCEPTION,
"IsLandscape: use default display, displayWidth=" + std::to_string(displayWidth) +
", displayHeight=" + std::to_string(displayHeight));
}
bool isLandscape = displayWidth > displayHeight;
if (displayWidth == displayHeight && display != nullptr) {
sptr<DisplayInfo> displayInfo = display->GetDisplayInfo();
if (displayInfo == nullptr) {
TLOGE(WmsLogTag::DMS, "displayInfo is nullptr");
return false;
}
DisplayOrientation orientation = displayInfo->GetDisplayOrientation();
if (orientation == DisplayOrientation::UNKNOWN) {
TLOGW(WmsLogTag::WMS_KEYBOARD, "Display orientation is UNKNOWN");
}
isLandscape = (orientation == DisplayOrientation::LANDSCAPE ||
orientation == DisplayOrientation::LANDSCAPE_INVERTED);
}
TLOGI(WmsLogTag::WMS_KEYBOARD, "c-displayInfo: %{public}" PRIu64 ", %{public}d|%{public}d|%{public}d",
displayId, displayWidth, displayHeight, isLandscape);
return isLandscape;
}
WMError WindowSceneSessionImpl::MoveAndResizeKeyboard(const KeyboardLayoutParams& params)
{
bool isLandscape = IsLandscape(params.displayId_);
Rect newRect = isLandscape ? params.LandscapeKeyboardRect_ : params.PortraitKeyboardRect_;
property_->SetRequestRect(newRect);
TLOGI(WmsLogTag::WMS_KEYBOARD, "Id: %{public}d, newRect: %{public}s, isLandscape: %{public}d",
GetPersistentId(), newRect.ToString().c_str(), isLandscape);
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::AdjustKeyboardLayout(const KeyboardLayoutParams params)
{
TLOGI(WmsLogTag::WMS_KEYBOARD, "g: %{public}u, "
"LAvoid: %{public}d, PAvoid: %{public}d, "
"LRect: %{public}s, PRect: %{public}s, "
"LPRect: %{public}s, PPRect: %{public}s, dispId: %{public}" PRIu64,
static_cast<uint32_t>(params.gravity_), params.landscapeAvoidHeight_, params.portraitAvoidHeight_,
params.LandscapeKeyboardRect_.ToString().c_str(), params.PortraitKeyboardRect_.ToString().c_str(),
params.LandscapePanelRect_.ToString().c_str(), params.PortraitPanelRect_.ToString().c_str(), params.displayId_);
property_->SetKeyboardLayoutParams(params);
property_->AddKeyboardLayoutParams(params.displayId_, params);
auto ret = MoveAndResizeKeyboard(params);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_KEYBOARD, "keyboard move and resize failed");
return ret;
}
if (auto hostSession = GetHostSession()) {
return static_cast<WMError>(hostSession->AdjustKeyboardLayout(params));
}
return WMError::WM_OK;
}
void WindowSceneSessionImpl::WindowScreenListener::OnDisconnect(ScreenId screenId)
{
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
for (const auto& [_, windPair] : windowSessionMap_) {
if (windPair.second->GetType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
auto& window = windPair.second;
window->GetProperty()->ClearCachedKeyboardParamsOnScreenDisconnected(screenId);
TLOGI(WmsLogTag::WMS_KEYBOARD, "Clear cached keyboardParams: %{public}d, dispId: %{public}" PRIu64,
window->GetProperty()->GetPersistentId(), screenId);
}
}
}
WMError WindowSceneSessionImpl::SetImmersiveModeEnabledState(bool enable)
{
TLOGD(WmsLogTag::WMS_IMMS, "id: %{public}u, enable: %{public}u", GetWindowId(), enable);
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
if (!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(),
WindowMode::WINDOW_MODE_FULLSCREEN)) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
const WindowType curWindowType = GetType();
if (!WindowHelper::IsMainWindow(curWindowType) && !WindowHelper::IsSubWindow(curWindowType)) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
enableImmersiveMode_ = enable;
hostSession->OnLayoutFullScreenChange(enableImmersiveMode_);
WindowMode mode = GetWindowMode();
if (!windowSystemConfig_.IsPcWindow() || mode == WindowMode::WINDOW_MODE_FULLSCREEN) {
return SetLayoutFullScreen(enableImmersiveMode_);
}
return WMError::WM_OK;
}
bool WindowSceneSessionImpl::GetImmersiveModeEnabledState() const
{
TLOGD(WmsLogTag::WMS_IMMS, "id: %{public}u, enableImmersiveMode=%{public}u",
GetWindowId(), enableImmersiveMode_.load());
if (IsWindowSessionInvalid()) {
return false;
}
return enableImmersiveMode_;
}
WMError WindowSceneSessionImpl::IsImmersiveLayout(bool& isImmersiveLayout) const
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (IsPcOrPadFreeMultiWindowMode()) {
auto uiContent = GetUIContentSharedPtr();
if (uiContent == nullptr) {
TLOGE(WmsLogTag::WMS_IMMS, "uicontent is null");
return WMError::WM_ERROR_INVALID_WINDOW;
}
Rect drawableRect;
uiContent->GetWindowPaintSize(drawableRect);
isImmersiveLayout = drawableRect == GetRect();
} else {
isImmersiveLayout = isIgnoreSafeArea_;
}
return WMError::WM_OK;
}
template <typename K, typename V>
static V GetValueByKey(const std::unordered_map<K, V>& map, K key)
{
auto it = map.find(key);
return it != map.end() ? it->second : V{};
}
void WindowSceneSessionImpl::HandleEventForCompatibleMode(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
MMI::PointerEvent::PointerItem& pointerItem)
{
int32_t action = pointerEvent->GetPointerAction();
switch (action) {
case MMI::PointerEvent::POINTER_ACTION_DOWN:
HandleDownForCompatibleMode(pointerEvent, pointerItem);
break;
case MMI::PointerEvent::POINTER_ACTION_MOVE:
HandleMoveForCompatibleMode(pointerEvent, pointerItem);
break;
case MMI::PointerEvent::POINTER_ACTION_UP:
HandleUpForCompatibleMode(pointerEvent, pointerItem);
break;
default:
break;
}
}
void WindowSceneSessionImpl::HandleDownForCompatibleMode(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
MMI::PointerEvent::PointerItem& pointerItem)
{
int32_t displayX = pointerItem.GetDisplayX();
int32_t displayY = pointerItem.GetDisplayY();
int32_t displayId = property_->GetDisplayId();
int32_t pointerCount = pointerEvent->GetPointerCount();
if (pointerCount == 1) {
eventMapTriggerByDisplay_[displayId] = std::vector<bool>(MAX_POINTERS);
eventMapDeltaXByDisplay_[displayId] = std::vector<int32_t>(MAX_POINTERS);
downPointerByDisplay_[displayId] = std::vector<PointInfo>(MAX_POINTERS);
isOverTouchSlop_ = false;
isDown_ = true;
}
if (IsInMappingRegionForCompatibleMode(displayX, displayY)) {
int32_t pointerId = pointerEvent->GetPointerId();
if (pointerId >= GetValueByKey(eventMapTriggerByDisplay_, displayId).size() ||
pointerId >= GetValueByKey(eventMapDeltaXByDisplay_, displayId).size() ||
pointerId >= GetValueByKey(downPointerByDisplay_, displayId).size()) {
TLOGE(WmsLogTag::DEFAULT, "pointerId: %{public}d out of range", pointerId);
return;
}
eventMapTriggerByDisplay_[displayId][pointerId] = true;
downPointerByDisplay_[displayId][pointerId] = {displayX, displayY};
const auto& windowRect = GetGlobalScaledRectLocal();
const auto& windowRectNoScaled = GetRect();
bool isForceSplitEnabled = property_->GetForceSplitEnable();
float xMappingScale = 1.0f;
int32_t xMappingWidth = isForceSplitEnabled ? windowRect.width_ / 2 : windowRect.width_;
if (windowRect.posX_ != 0) {
xMappingScale = static_cast<float>(xMappingWidth) / windowRect.posX_;
}
int32_t windowLeft = windowRect.posX_;
int32_t windowRight = windowRect.posX_ + windowRect.width_;
int32_t windowMidNoScaled = windowRectNoScaled.posX_ + windowRectNoScaled.width_ / 2;
int32_t xMappingLeft = isForceSplitEnabled ? windowMidNoScaled : windowLeft;
int32_t xMappingRight = isForceSplitEnabled ? windowMidNoScaled : windowRight;
int32_t transferX;
if (displayX <= windowLeft) {
transferX = xMappingRight - xMappingScale * (windowLeft - displayX);
} else {
transferX = xMappingLeft + xMappingScale * (displayX - windowRight);
}
if (transferX < 0) {
transferX = 0;
}
TLOGD(WmsLogTag::DEFAULT, "DOWN in mapping region, displayX: %{private}d, transferX: %{public}d, "
"pointerId: %{public}d", displayX, transferX, pointerId);
eventMapDeltaXByDisplay_[displayId][pointerId] = transferX - displayX;
ConvertPointForCompatibleMode(pointerEvent, pointerItem, transferX);
}
}
void WindowSceneSessionImpl::HandleMoveForCompatibleMode(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
MMI::PointerEvent::PointerItem& pointerItem)
{
if (!isDown_) {
TLOGW(WmsLogTag::WMS_COMPAT, "receive move before down, skip");
return;
}
int32_t displayId = property_->GetDisplayId();
int32_t pointerId = pointerEvent->GetPointerId();
if (pointerId >= GetValueByKey(eventMapTriggerByDisplay_, displayId).size() ||
pointerId >= GetValueByKey(eventMapDeltaXByDisplay_, displayId).size() ||
!GetValueByKey(eventMapTriggerByDisplay_, displayId)[pointerId]) {
return;
}
int32_t displayX = pointerItem.GetDisplayX();
int32_t displayY = pointerItem.GetDisplayY();
const auto& windowRect = GetGlobalScaledRectLocal();
if (!isOverTouchSlop_ && CheckTouchSlop(pointerId, displayX, displayY, windowRect.width_ / TOUCH_SLOP_RATIO)) {
TLOGD(WmsLogTag::WMS_COMPAT, "reach touch slop, threshold: %{public}d", windowRect.width_ / TOUCH_SLOP_RATIO);
isOverTouchSlop_ = true;
}
int32_t transferX = displayX + GetValueByKey(eventMapDeltaXByDisplay_, displayId)[pointerId];
TLOGD(WmsLogTag::WMS_COMPAT, "MOVE, displayX: %{private}d, transferX: %{public}d, pointerId: %{public}d",
displayX, transferX, pointerId);
ConvertPointForCompatibleMode(pointerEvent, pointerItem, transferX);
}
void WindowSceneSessionImpl::HandleUpForCompatibleMode(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
MMI::PointerEvent::PointerItem& pointerItem)
{
if (!isDown_) {
TLOGW(WmsLogTag::WMS_COMPAT, "receive up before down, skip");
return;
}
int32_t displayId = property_->GetDisplayId();
int32_t pointerId = pointerEvent->GetPointerId();
if (pointerId >= GetValueByKey(eventMapTriggerByDisplay_, displayId).size() ||
pointerId >= GetValueByKey(eventMapDeltaXByDisplay_, displayId).size()) {
return;
}
if (GetValueByKey(eventMapTriggerByDisplay_, displayId)[pointerId]) {
int32_t displayX = pointerItem.GetDisplayX();
int32_t transferX = displayX + GetValueByKey(eventMapDeltaXByDisplay_, displayId)[pointerId];
ConvertPointForCompatibleMode(pointerEvent, pointerItem, transferX);
TLOGD(WmsLogTag::WMS_COMPAT, "UP, displayX: %{private}d, transferX: %{public}d, pointerId: %{public}d",
displayX, transferX, pointerId);
GetValueByKey(eventMapDeltaXByDisplay_, displayId)[pointerId] = 0;
GetValueByKey(eventMapTriggerByDisplay_, displayId)[pointerId] = false;
IgnoreClickEvent(pointerEvent);
}
int32_t pointerCount = pointerEvent->GetPointerCount();
if (pointerCount == 1) {
eventMapDeltaXByDisplay_.erase(displayId);
eventMapTriggerByDisplay_.erase(displayId);
downPointerByDisplay_.erase(displayId);
isDown_ = false;
}
}
void WindowSceneSessionImpl::ConvertPointForCompatibleMode(const std::shared_ptr<MMI::PointerEvent>& pointerEvent,
MMI::PointerEvent::PointerItem& pointerItem, int32_t transferX)
{
const auto& windowRect = GetGlobalScaledRectLocal();
int32_t pointerId = pointerEvent->GetPointerId();
pointerItem.SetDisplayX(transferX);
pointerItem.SetDisplayXPos(static_cast<double>(transferX));
pointerItem.SetWindowX(transferX - windowRect.posX_);
pointerItem.SetWindowXPos(static_cast<double>(transferX - windowRect.posX_));
pointerEvent->UpdatePointerItem(pointerId, pointerItem);
}
bool WindowSceneSessionImpl::IsInMappingRegionForCompatibleMode(int32_t displayX, int32_t displayY)
{
const auto& windowRect = GetGlobalScaledRectLocal();
Rect pointerRect = { displayX, displayY, 0, 0 };
return !pointerRect.IsInsideOf(windowRect);
}
bool WindowSceneSessionImpl::CheckTouchSlop(int32_t pointerId, int32_t displayX, int32_t displayY, int32_t threshold)
{
int32_t displayId = property_->GetDisplayId();
if (downPointerByDisplay_.find(displayId) == downPointerByDisplay_.end()) {
return false;
}
std::vector<PointInfo> downPointers = downPointerByDisplay_[displayId];
return pointerId < downPointers.size() &&
(std::abs(displayX - downPointers[pointerId].x) >= threshold ||
std::abs(displayY - downPointers[pointerId].y) >= threshold);
}
void WindowSceneSessionImpl::IgnoreClickEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
{
int32_t action = pointerEvent->GetPointerAction();
if (action != MMI::PointerEvent::POINTER_ACTION_UP) {
return;
}
if (isOverTouchSlop_) {
if (pointerEvent->GetPointerCount() == 1) {
isOverTouchSlop_ = false;
}
} else {
pointerEvent->SetPointerAction(MMI::PointerEvent::POINTER_ACTION_CANCEL);
TLOGI(WmsLogTag::DEFAULT, "transfer UP to CANCEL for not over touch slop");
}
}
WMError WindowSceneSessionImpl::GetWindowStatus(WindowStatus& windowStatus)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_PC, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
windowStatus = GetOwnWindowStatus(GetWindowMode());
TLOGD(WmsLogTag::WMS_PC, "Id:%{public}u, WindowStatus:%{public}u", GetWindowId(), windowStatus);
return WMError::WM_OK;
}
bool WindowSceneSessionImpl::GetIsUIExtFirstSubWindow() const
{
return property_->GetIsUIExtFirstSubWindow();
}
bool WindowSceneSessionImpl::GetIsUIExtAnySubWindow() const
{
return property_->GetIsUIExtAnySubWindow();
}
WMError WindowSceneSessionImpl::SetGestureBackEnabled(bool enable)
{
if (windowSystemConfig_.IsPcWindow()) {
if (property_->IsAdaptToCompatibleDevice()) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "phone app in pc compatible mode, enable=%{public}d", enable);
return WMError::WM_OK;
}
TLOGI(WmsLogTag::WMS_IMMS, "device is not support");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
TLOGI(WmsLogTag::WMS_IMMS, "win %{public}u, enable %{public}u", GetWindowId(), enable);
gestureBackEnabled_ = enable;
AAFwk::Want want;
want.SetParam(Extension::GESTURE_BACK_ENABLED, enable);
if (auto uiContent = GetUIContentSharedPtr()) {
uiContent->SendUIExtProprty(static_cast<uint32_t>(Extension::Businesscode::SYNC_HOST_GESTURE_BACK_ENABLED),
want, static_cast<uint8_t>(SubSystemId::WM_UIEXT));
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
return hostSession->SetGestureBackEnabled(enable);
}
WMError WindowSceneSessionImpl::GetGestureBackEnabled(bool& enable) const
{
if (windowSystemConfig_.IsPcWindow()) {
enable = false;
if (property_->IsAdaptToCompatibleDevice()) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "phone app in pc compatible mode, enable=%{public}d", enable);
return WMError::WM_OK;
}
TLOGI(WmsLogTag::WMS_IMMS, "device not support");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
enable = gestureBackEnabled_;
TLOGI(WmsLogTag::WMS_IMMS, "win %{public}u enable %{public}u", GetWindowId(), enable);
return WMError::WM_OK;
}
WSError WindowSceneSessionImpl::SetFullScreenWaterfallMode(bool isWaterfallMode)
{
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "prev: %{public}d, curr: %{public}d, winId: %{public}u",
isFullScreenWaterfallMode_.load(), isWaterfallMode, GetWindowId());
NotifyAcrossDisplaysChange(isWaterfallMode);
if (isValidWaterfallMode_.load() && isFullScreenWaterfallMode_.load() == isWaterfallMode) {
return WSError::WS_DO_NOTHING;
}
isFullScreenWaterfallMode_.store(isWaterfallMode);
if (isWaterfallMode) {
lastWindowModeBeforeWaterfall_.store(property_->GetWindowMode());
} else {
lastWindowModeBeforeWaterfall_.store(WindowMode::WINDOW_MODE_UNDEFINED);
}
isValidWaterfallMode_.store(true);
NotifyWaterfallModeChange(isWaterfallMode);
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::SetSupportEnterWaterfallMode(bool isSupportEnter)
{
handler_->PostTask([weakThis = wptr(this), isSupportEnter, where = __func__] {
auto window = weakThis.promote();
if (!window) {
TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "%{public}s window is null", where);
return;
}
if (window->supportEnterWaterfallMode_ == isSupportEnter) {
return;
}
TLOGNI(WmsLogTag::WMS_LAYOUT_PC, "%{public}s prev: %{public}d, curr: %{public}d",
where, window->supportEnterWaterfallMode_, isSupportEnter);
window->supportEnterWaterfallMode_ = isSupportEnter;
std::shared_ptr<Ace::UIContent> uiContent = window->GetUIContentSharedPtr();
if (uiContent == nullptr || !window->IsDecorEnable()) {
TLOGND(WmsLogTag::WMS_LAYOUT_PC, "%{public}s uiContent unavailable", where);
return;
}
uiContent->OnContainerModalEvent(WINDOW_WATERFALL_VISIBILITY_EVENT, isSupportEnter ? "true" : "false");
}, __func__);
return WSError::WS_OK;
}
WMError WindowSceneSessionImpl::OnContainerModalEvent(const std::string& eventName, const std::string& value)
{
TLOGI(WmsLogTag::WMS_LAYOUT, "windowId: %{public}d, name: %{public}s, value: %{public}s",
GetPersistentId(), eventName.c_str(), value.c_str());
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
hostSession->OnContainerModalEvent(eventName, value);
std::string bundleName = property_->GetSessionInfo().bundleName_;
if (eventName == WINDOW_WATERFALL_EVENT) {
bool lastFullScreenWaterfallMode = isFullScreenWaterfallMode_.load();
SetFullScreenWaterfallMode(true);
auto ret = Maximize();
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LAYOUT, "maximize failed");
SetFullScreenWaterfallMode(lastFullScreenWaterfallMode);
}
return ret;
} else if (eventName == BACK_WINDOW_EVENT) {
HandleBackEvent();
ReportCompatibleTitleOperate(bundleName, BACK_WINDOW_EVENT);
return WMError::WM_OK;
} else if (eventName == EVENT_NAME_HOVER) {
ReportHoverMaximizeMenu(bundleName, value);
return WMError::WM_OK;
} else if (eventName == EVENT_NAME_MINIMIZE) {
ReportClickTitleMinimize(bundleName);
return WMError::WM_OK;
} else if (eventName == EVENT_NAME_CLOSE) {
ReportClickTitleClose(bundleName);
return WMError::WM_OK;
} else if (eventName == COMPATIBLE_MAX_WINDOW_EVENT) {
MaximizeForCompatibleMode();
ReportCompatibleTitleOperate(bundleName, COMPATIBLE_MAX_WINDOW_EVENT);
return WMError::WM_OK;
} else if (eventName == COMPATIBLE_RECOVER_WINDOW_EVENT) {
RecoverForCompatibleMode();
ReportCompatibleTitleOperate(bundleName, COMPATIBLE_RECOVER_WINDOW_EVENT);
return WMError::WM_OK;
} else if (eventName == NAME_LANDSCAPE_18_9_CLICK) {
SwitchCompatibleMode(CompatibleStyleMode::LANDSCAPE_18_9);
return WMError::WM_OK;
} else if (eventName == NAME_LANDSCAPE_1_1_CLICK) {
SwitchCompatibleMode(CompatibleStyleMode::LANDSCAPE_1_1);
return WMError::WM_OK;
} else if (eventName == NAME_LANDSCAPE_2_3_CLICK) {
SwitchCompatibleMode(CompatibleStyleMode::LANDSCAPE_2_3);
return WMError::WM_OK;
} else if (eventName == NAME_DEFAULT_LANDSCAPE_CLICK) {
SwitchCompatibleMode(CompatibleStyleMode::LANDSCAPE_DEFAULT);
return WMError::WM_OK;
} else if (eventName == NAME_LANDSCAPE_SPLIT_CLICK) {
SwitchCompatibleMode(CompatibleStyleMode::LANDSCAPE_SPLIT);
return WMError::WM_OK;
}
return WMError::WM_DO_NOTHING;
}
void WindowSceneSessionImpl::ReportHoverMaximizeMenu(const std::string& bundleName, const std::string& hoverType)
{
HiSysEventWrite(SCENE_BOARD_UE_DOMAIN, HOVER_MAXIMIZE_MENU,
OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
"BUNDLENAME", bundleName,
"HOVERTYPE", hoverType);
}
void WindowSceneSessionImpl::ReportClickTitleMinimize(const std::string& bundleName)
{
HiSysEventWrite(SCENE_BOARD_UE_DOMAIN, CLICK_TITLE_MINIMIZE,
OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
"BUNDLENAME", bundleName);
}
void WindowSceneSessionImpl::ReportClickTitleClose(const std::string& bundleName)
{
HiSysEventWrite(SCENE_BOARD_UE_DOMAIN, CLICK_TITLE_CLOSE,
OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
"BUNDLENAME", bundleName);
}
void WindowSceneSessionImpl::ReportCompatibleTitleOperate(const std::string& bundleName, const std::string& operateType)
{
HiSysEventWrite(SCENE_BOARD_UE_DOMAIN, COMPATIBLE_TITLE_OPERATE,
OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
"BUNDLENAME", bundleName,
"OPERATETYPE", operateType);
}
bool WindowSceneSessionImpl::IsSystemDensityChanged(const sptr<DisplayInfo>& displayInfo)
{
if (MathHelper::NearZero(lastSystemDensity_ - displayInfo->GetVirtualPixelRatio())) {
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "System density not change");
return false;
}
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "windowId: %{public}d, lastDensity: %{public}f, currDensity: %{public}f",
GetPersistentId(), lastSystemDensity_, displayInfo->GetVirtualPixelRatio());
return true;
}
bool WindowSceneSessionImpl::IsDefaultDensityEnabled()
{
if (WindowHelper::IsMainWindow(GetType())) {
return GetDefaultDensityEnabled();
}
if (isEnableDefaultDensityWhenCreate_) {
return true;
}
if (auto mainWindow = FindMainWindowWithContext()) {
CopyUniqueDensityParameter(mainWindow);
}
return GetDefaultDensityEnabled();
}
float WindowSceneSessionImpl::GetMainWindowCustomDensity()
{
if (WindowHelper::IsMainWindow(GetType())) {
return GetCustomDensity();
}
auto mainWindow = FindMainWindowWithContext();
return mainWindow ? mainWindow->GetCustomDensity() : UNDEFINED_DENSITY;
}
float WindowSceneSessionImpl::GetCustomDensity() const
{
return customDensity_;
}
WMError WindowSceneSessionImpl::ValidateWindowAnchorInfo(const WindowAnchorInfo& windowAnchorInfo)
{
const auto& property = GetProperty();
if (windowAnchorInfo.isFromAttachOrDetach_ && (!(windowSystemConfig_.IsPcWindow() ||
windowSystemConfig_.freeMultiWindowSupport_) || property_->IsAdaptToCompatibleDevice())) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"isPcWindow: %{public}d , freeMultiWindowSupport: %{public}d, IsAdaptToCompatibleDevice: %{public}d",
windowSystemConfig_.IsPcWindow(), windowSystemConfig_.freeMultiWindowSupport_,
property_->IsAdaptToCompatibleDevice());
return WMError::WM_OK;
}
if (!WindowHelper::IsSubWindow(property->GetWindowType()) || property->GetSubWindowLevel() > 1 ||
IsZLevelAboveParentLoosened()) {
TLOGE(WmsLogTag::WMS_LAYOUT,
"only 1 level sub window is valid, windowType: %{public}d, IsZLevelAboveParentLoosened: %{public}d, "
"subWindowLevel: %{public}d",
property->GetWindowType(), IsZLevelAboveParentLoosened(), property->GetSubWindowLevel());
return WMError::WM_ERROR_INVALID_CALLING;
}
if (windowAnchorInfo.isFromAttachOrDetach_ && (!windowAnchorInfo.isAnchoredByAttach_ &&
!property->GetWindowAnchorInfo().isAnchoredByAttach_)) {
TLOGE(WmsLogTag::WMS_LAYOUT, "Repeated invoking");
return WMError::WM_ERROR_INVALID_OP_IN_CUR_STATUS;
}
if (windowAnchorInfo.isFromAttachOrDetach_ && (WindowHelper::IsFullScreenWindow(property->GetWindowMode()) ||
property->IsFollowParentLayout())) {
TLOGE(WmsLogTag::WMS_LAYOUT, "The subwindow is maximized or is following its parent window's layout.");
return WMError::WM_ERROR_INVALID_OP_IN_CUR_STATUS;
}
if (WindowHelper::IsFullScreenWindow(property->GetWindowMode()) || property->GetSubWindowLevel() > 1) {
TLOGE(WmsLogTag::WMS_LAYOUT, "not support fullscreen sub window or more than 1 level window");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (!windowAnchorInfo.isFromAttachOrDetach_ && !windowSystemConfig_.supportFollowRelativePositionToParent_) {
TLOGI(WmsLogTag::WMS_LAYOUT, "not support device");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
return WMError::WM_DO_NOTHING;
}
WMError WindowSceneSessionImpl::SetWindowAnchorInfo(const WindowAnchorInfo& windowAnchorInfo)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "CUSTOM_ANIMATOR_WindowSceneSessionImpl::SetWindowAnchorInfo");
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
WMError retValide = ValidateWindowAnchorInfo(windowAnchorInfo);
if (retValide != WMError::WM_DO_NOTHING) {
return retValide;
}
auto hostSession = GetHostSession();
if (!hostSession) {
TLOGI(WmsLogTag::WMS_SUB, "session is nullptr");
return WMError::WM_ERROR_INVALID_SESSION;
}
const auto& property = GetProperty();
WSError wsRet = hostSession->SetWindowAnchorInfo(windowAnchorInfo);
if (wsRet == WSError::WS_ERROR_DEVICE_NOT_SUPPORT) {
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (wsRet == WSError::WS_ERROR_NOT_SYSTEM_APP) {
return WMError::WM_ERROR_NOT_SYSTEM_APP;
}
if (wsRet == WSError::WS_OK) {
const auto& property = GetProperty();
property->SetWindowAnchorInfo(windowAnchorInfo);
}
return wsRet != WSError::WS_OK ? WMError::WM_ERROR_SYSTEM_ABNORMALLY : WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetFollowParentWindowLayoutEnabled(bool isFollow)
{
HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER,
"CUSTOM_ANIMATOR_WindowSceneSessionImpl::SetFollowParentWindowLayoutEnabled");
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LAYOUT, "windowId: %{public}u, window session is invalid", GetWindowId());
return WMError::WM_ERROR_INVALID_WINDOW;
}
const auto& property = GetProperty();
if (!WindowHelper::IsSubWindow(property->GetWindowType()) &&
!WindowHelper::IsDialogWindow(property->GetWindowType())) {
TLOGE(WmsLogTag::WMS_SUB, "only sub window and dialog is valid");
return WMError::WM_ERROR_INVALID_OPERATION;
}
if (IsZLevelAboveParentLoosened()) {
TLOGE(WmsLogTag::WMS_SUB, "No parent sub window is invalid");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (property->GetSubWindowLevel() > 1) {
TLOGI(WmsLogTag::WMS_SUB, "not support more than 1 level window");
return WMError::WM_ERROR_INVALID_OPERATION;
}
if (!windowSystemConfig_.supportFollowParentWindowLayout_) {
TLOGI(WmsLogTag::WMS_SUB, "not support device");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!GetHostSession()) {
TLOGI(WmsLogTag::WMS_SUB, "session is nullptr");
return WMError::WM_ERROR_INVALID_SESSION;
}
WSError ret = GetHostSession()->SetFollowParentWindowLayoutEnabled(isFollow);
TLOGI(WmsLogTag::WMS_SUB, "id:%{public}d, isFollow:%{public}d", GetPersistentId(), isFollow);
if (ret == WSError::WS_ERROR_DEVICE_NOT_SUPPORT) {
TLOGE(WmsLogTag::WMS_LAYOUT, "windowId: %{public}u, device not support", GetWindowId());
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (ret == WSError::WS_OK) {
property->SetFollowParentLayout(isFollow);
}
return ret != WSError::WS_OK ? WMError::WM_ERROR_SYSTEM_ABNORMALLY : WMError::WM_OK;
}
WMError WindowSceneSessionImpl::IsTransitionAnimationSupported() const
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!(IsPcOrPadFreeMultiWindowMode() || property_->GetIsPcAppInPad())) {
TLOGE(WmsLogTag::WMS_ANIMATION, "Device is invalid");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_ANIMATION, "Window type is invalid");
return WMError::WM_ERROR_INVALID_CALLING;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetWindowTransitionAnimation(WindowTransitionType transitionType,
const TransitionAnimation& animation)
{
WMError errorCode = IsTransitionAnimationSupported();
if (errorCode != WMError::WM_OK) {
return errorCode;
}
auto hostSession = GetHostSession();
if (!hostSession) {
TLOGI(WmsLogTag::WMS_ANIMATION, "session is nullptr");
return WMError::WM_ERROR_INVALID_SESSION;
}
WSError ret = hostSession->SetWindowTransitionAnimation(transitionType, animation);
if (ret == WSError::WS_OK) {
std::lock_guard<std::mutex> lockListener(transitionAnimationConfigMutex_);
property_->SetTransitionAnimationConfig(transitionType, animation);
}
return ret != WSError::WS_OK ? WMError::WM_ERROR_SYSTEM_ABNORMALLY : WMError::WM_OK;
}
std::shared_ptr<TransitionAnimation> WindowSceneSessionImpl::GetWindowTransitionAnimation(WindowTransitionType
transitionType)
{
if (IsTransitionAnimationSupported() != WMError::WM_OK) {
return nullptr;
}
std::lock_guard<std::mutex> lockListener(transitionAnimationConfigMutex_);
auto transitionAnimationConfig = property_->GetTransitionAnimationConfig();
if (transitionAnimationConfig.find(transitionType) != transitionAnimationConfig.end()) {
return transitionAnimationConfig[transitionType];
} else {
return nullptr;
}
}
WMError WindowSceneSessionImpl::SetCustomDensity(float density, bool applyToSubWindow)
{
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "winId=%{public}u, density=%{public}f", GetWindowId(), density);
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if ((density < MINIMUM_CUSTOM_DENSITY && !MathHelper::NearZero(density - UNDEFINED_DENSITY)) ||
density > MAXIMUM_CUSTOM_DENSITY) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "winId=%{public}u set invalid density=%{public}f", GetWindowId(), density);
return WMError::WM_ERROR_INVALID_PARAM;
}
if (!WindowHelper::IsMainWindow(GetType())) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "winId=%{public}u, must be app main window", GetWindowId());
return WMError::WM_ERROR_INVALID_CALLING;
}
if (MathHelper::NearZero(customDensity_ - density) && !applyToSubWindow) {
TLOGI(WmsLogTag::WMS_ATTRIBUTE, "winId=%{public}u set density not change", GetWindowId());
return WMError::WM_OK;
}
defaultDensityEnabledStageConfig_.store(false);
SetDefaultDensityEnabledValue(false);
customDensity_ = density;
UpdateDensity();
std::shared_lock<std::shared_mutex> lock(windowSessionMutex_);
for (const auto& winPair : windowSessionMap_) {
auto window = winPair.second.second;
if (window == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "window is nullptr");
continue;
}
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "Id=%{public}d UpdateDensity", window->GetWindowId());
window->SetDefaultDensityEnabledValue(false);
if (applyToSubWindow) {
window->UpdateDensity();
}
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::GetWindowDensityInfo(WindowDensityInfo& densityInfo)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "display is null, winId=%{public}u", GetWindowId());
return WMError::WM_ERROR_NULLPTR;
}
auto displayInfo = display->GetDisplayInfo();
if (displayInfo == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "displayInfo is null, winId=%{public}u", GetWindowId());
return WMError::WM_ERROR_NULLPTR;
}
densityInfo.systemDensity = displayInfo->GetVirtualPixelRatio();
densityInfo.defaultDensity = displayInfo->GetDefaultVirtualPixelRatio();
auto customDensity = UNDEFINED_DENSITY;
if (IsDefaultDensityEnabled()) {
customDensity = displayInfo->GetDefaultVirtualPixelRatio();
} else {
customDensity = GetCustomDensity();
customDensity = MathHelper::NearZero(customDensity - UNDEFINED_DENSITY) ? displayInfo->GetVirtualPixelRatio()
: customDensity;
}
densityInfo.customDensity = customDensity;
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::IsMainWindowFullScreenAcrossDisplays(bool& isAcrossDisplays)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
return hostSession->IsMainWindowFullScreenAcrossDisplays(isAcrossDisplays);
}
bool WindowSceneSessionImpl::IsFullScreenEnable() const
{
if (!WindowHelper::IsWindowModeSupported(property_->GetWindowModeSupportType(),
WindowMode::WINDOW_MODE_FULLSCREEN)) {
return false;
}
const auto& sizeLimits = property_->GetWindowLimits();
uint32_t displayWidth = 0;
uint32_t displayHeight = 0;
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display == nullptr) {
TLOGE(WmsLogTag::WMS_PC, "display is null, winId=%{public}u", GetWindowId());
return false;
}
displayWidth = static_cast<uint32_t>(display->GetWidth());
displayHeight = static_cast<uint32_t>(display->GetHeight());
if (property_->GetDragEnabled() && (sizeLimits.maxWidth_ < displayWidth || sizeLimits.maxHeight_ < displayHeight)) {
return false;
}
return true;
}
WMError WindowSceneSessionImpl::GetWindowPropertyInfo(WindowPropertyInfo& windowPropertyInfo, bool useHookedSize)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
windowPropertyInfo.windowRect = property_->GetWindowRect();
auto uicontent = GetUIContentSharedPtr();
if (uicontent == nullptr) {
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "uicontent is nullptr");
} else {
uicontent->GetWindowPaintSize(windowPropertyInfo.drawableRect);
}
windowPropertyInfo.globalDisplayRect = property_->GetGlobalDisplayRect();
windowPropertyInfo.type = GetType();
windowPropertyInfo.isLayoutFullScreen = IsLayoutFullScreen();
windowPropertyInfo.isFullScreen = IsFullScreen();
windowPropertyInfo.isTouchable = GetTouchable();
windowPropertyInfo.isFocusable = GetFocusable();
windowPropertyInfo.name = GetWindowName();
windowPropertyInfo.isPrivacyMode = IsPrivacyMode();
windowPropertyInfo.isKeepScreenOn = IsKeepScreenOn();
windowPropertyInfo.brightness = GetBrightness();
windowPropertyInfo.isTransparent = IsTransparent();
windowPropertyInfo.id = GetWindowId();
windowPropertyInfo.displayId = GetDisplayId();
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "winId=%{public}u, globalDisplayRect=%{public}s", windowPropertyInfo.id,
windowPropertyInfo.globalDisplayRect.ToString().c_str());
if (WindowHelper::IsMainWindow(windowPropertyInfo.type) && useHookedSize) {
Rect realWindowRect = windowPropertyInfo.windowRect;
Rect realGlobalDisplayRect = windowPropertyInfo.globalDisplayRect;
Rect realDrawableRect = windowPropertyInfo.drawableRect;
Rect hookedWindowRect = windowPropertyInfo.windowRect;
Rect hookedGlobalDisplayRect = windowPropertyInfo.globalDisplayRect;
Rect hookedDrawableRect = windowPropertyInfo.drawableRect;
HookWindowSizeByHookWindowInfo(hookedWindowRect);
HookWindowSizeByHookWindowInfo(hookedGlobalDisplayRect);
auto hookWindowInfo = GetProperty()->GetHookWindowInfo();
if (hookWindowInfo.drawableRectHook) {
HookWindowSizeByHookWindowInfo(hookedDrawableRect);
}
TLOGD(WmsLogTag::WMS_LAYOUT,
"HookWindowSize[GetWindowPropertyInfo], id:%{public}d, "
"realWindowRect:%{public}s, hookedWindowRect:%{public}s, "
"realGlobalDisplayRect:%{public}s, hookedGlobalDisplayRect:%{public}s, "
"realDrawableRect:%{public}s, hookedDrawableRect:%{public}s, useHookedSize:%{public}d",
GetPersistentId(),
realWindowRect.ToString().c_str(), hookedWindowRect.ToString().c_str(),
realGlobalDisplayRect.ToString().c_str(), hookedGlobalDisplayRect.ToString().c_str(),
realDrawableRect.ToString().c_str(), hookedDrawableRect.ToString().c_str(), useHookedSize);
windowPropertyInfo.windowRect = hookedWindowRect;
windowPropertyInfo.globalDisplayRect = hookedGlobalDisplayRect;
windowPropertyInfo.drawableRect = hookedDrawableRect;
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::GetWindowStateSnapshot(std::string& winStateSnapshotJsonStr)
{
auto persistentId = GetPersistentId();
nlohmann::json winStateSnapshotJson = {
{"isPcMode", system::GetBoolParameter("persist.sceneboard.ispcmode", false)},
{"isSupportFreeWindowMode", windowSystemConfig_.freeMultiWindowSupport_ || windowSystemConfig_.IsPcWindow()},
};
winStateSnapshotJsonStr = winStateSnapshotJson.dump();
auto errCode = SingletonContainer::Get<WindowAdapter>().GetWindowStateSnapshot(persistentId,
winStateSnapshotJsonStr);
if (errCode != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "ipc failed: winId=%{public}d, retCode=%{public}d",
persistentId, static_cast<int32_t>(errCode));
return WMError::WM_ERROR_SYSTEM_ABNORMALLY;
}
TLOGD(WmsLogTag::WMS_ATTRIBUTE, "winId=%{public}d, winStateSnapshot=%{public}s",
persistentId, winStateSnapshotJsonStr.c_str());
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SetRotationLocked(bool locked)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!windowSystemConfig_.IsPcWindow() && !windowSystemConfig_.IsPadWindow() &&
!windowSystemConfig_.IsPhoneWindow()) {
TLOGE(WmsLogTag::WMS_ROTATION, "window is not pc, pad or phone, not supported.");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!(WindowHelper::IsSystemWindow(GetType()) && !WindowHelper::IsWindowInApp(GetType()))) {
TLOGE(WmsLogTag::WMS_ROTATION, "is not system window.");
return WMError::WM_ERROR_INVALID_WINDOW_TYPE;
}
TLOGI(WmsLogTag::WMS_ROTATION, "set id %{public}u rotation lock %{public}d.", GetWindowId(), locked);
property_->SetRotationLocked(locked);
return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_ROTATION_LOCK_CHANGE);
}
WMError WindowSceneSessionImpl::GetRotationLocked(bool& locked)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (!windowSystemConfig_.IsPcWindow() && !windowSystemConfig_.IsPadWindow() &&
!windowSystemConfig_.IsPhoneWindow()) {
TLOGE(WmsLogTag::WMS_ROTATION, "window is not pc, pad or phone, not supported.");
return WMError::WM_ERROR_DEVICE_NOT_SUPPORT;
}
if (!(WindowHelper::IsSystemWindow(GetType()) && !WindowHelper::IsWindowInApp(GetType()))) {
TLOGE(WmsLogTag::WMS_ROTATION, "is not system window.");
return WMError::WM_ERROR_INVALID_WINDOW_TYPE;
}
locked = property_->GetRotationLocked();
TLOGI(WmsLogTag::WMS_ROTATION, "get id %{public}u rotation lock %{public}d.", GetWindowId(), locked);
return WMError::WM_OK;
}
WSError WindowSceneSessionImpl::UpdatePropertyWhenTriggerMode(const sptr<WindowSessionProperty>& property)
{
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_ATTRIBUTE, "property invalid!");
return WSError::WS_ERROR_INVALID_PARAM;
}
property_->SetMobileAppInPadLayoutFullScreen(property->GetMobileAppInPadLayoutFullScreen());
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::UpdateAttachedWindowLimits(int32_t sourcePersistentId,
const WindowLimits& attachedWindowLimits, bool isIntersectedHeightLimit,
bool isIntersectedWidthLimit)
{
TLOGI(WmsLogTag::WMS_LAYOUT, "called for window id=%{public}u, sourcePersistentId=%{public}d, "
"isIntersectedHeightLimit=%{public}d, isIntersectedWidthLimit=%{public}d",
GetWindowId(), sourcePersistentId, isIntersectedHeightLimit, isIntersectedWidthLimit);
const auto& property = GetProperty();
property->SetAttachedWindowLimits(sourcePersistentId, attachedWindowLimits);
AttachLimitOptions limitOptions{ isIntersectedHeightLimit, isIntersectedWidthLimit };
property->SetAttachedLimitOptions(sourcePersistentId, limitOptions);
UpdateWindowSizeLimits();
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_LIMITS);
UpdateNewSize();
TLOGI(WmsLogTag::WMS_LAYOUT, "completed for window id=%{public}u", GetWindowId());
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::SyncAllAttachedLimitsToChild(
const std::vector<std::pair<int32_t, WindowLimits>>& limitsList,
const std::vector<std::pair<int32_t, AttachLimitOptions>>& optionsList)
{
TLOGI(WmsLogTag::WMS_LAYOUT, "called for window id=%{public}u, limitsList size=%{public}zu, "
"optionsList size=%{public}zu", GetWindowId(), limitsList.size(), optionsList.size());
const auto& property = GetProperty();
property->ClearAttachedWindowLimitsList();
property->ClearAttachedLimitOptionsList();
for (const auto& [sourceId, limits] : limitsList) {
property->SetAttachedWindowLimits(sourceId, limits);
}
for (const auto& [sourceId, options] : optionsList) {
property->SetAttachedLimitOptions(sourceId, options);
}
UpdateWindowSizeLimits();
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_LIMITS);
UpdateNewSize();
TLOGI(WmsLogTag::WMS_LAYOUT, "completed for window id=%{public}u", GetWindowId());
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::NotifyRebindAttachAfterParentChange(int32_t newParentWindowId)
{
TLOGI(WmsLogTag::WMS_LAYOUT, "window id=%{public}u, newParentWindowId=%{public}d",
GetWindowId(), newParentWindowId);
const auto& property = GetProperty();
WindowAnchorInfo anchorInfo = property->GetWindowAnchorInfo();
if (!anchorInfo.isAnchorEnabled_) {
TLOGI(WmsLogTag::WMS_LAYOUT, "id=%{public}u no anchor binding, skip", GetWindowId());
return WSError::WS_OK;
}
property->ClearAttachedWindowLimitsList();
property->ClearAttachedLimitOptionsList();
UpdateWindowSizeLimits();
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_LIMITS);
UpdateNewSize();
auto newParentWindow = GetWindowWithId(newParentWindowId);
if (newParentWindow && WindowHelper::IsMainWindow(newParentWindow->GetType())) {
SetWindowAnchorInfo(anchorInfo);
} else {
WindowAnchorInfo clearedInfo = {false, false, WindowAnchor::TOP_START, 0, 0};
clearedInfo.isFromAttachOrDetach_ = true;
clearedInfo.attachOptions.currentLayoutMode = "";
property->SetWindowAnchorInfo(clearedInfo);
ClearParentWindowListeners(GetPersistentId());
}
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::RemoveAttachedWindowLimits(int32_t sourcePersistentId)
{
TLOGI(WmsLogTag::WMS_LAYOUT, "called for window id=%{public}u, "
"sourcePersistentId=%{public}d", GetWindowId(), sourcePersistentId);
const auto& property = GetProperty();
if (sourcePersistentId == GetPersistentId()) {
TLOGI(WmsLogTag::WMS_LAYOUT, "Window id=%{public}u is detaching, clearing all attached limits",
GetWindowId());
property->ClearAttachedWindowLimitsList();
property->ClearAttachedLimitOptionsList();
} else {
property->RemoveAttachedWindowLimits(sourcePersistentId);
property->RemoveAttachedLimitOptions(sourcePersistentId);
}
UpdateWindowSizeLimits();
UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_WINDOW_LIMITS);
UpdateNewSize();
TLOGI(WmsLogTag::WMS_LAYOUT, "completed for window id=%{public}u", GetWindowId());
return WSError::WS_OK;
}
WMError WindowSceneSessionImpl::SetHookTargetElementInfo(const AppExecFwk::ElementName& elementName)
{
auto context = GetContext();
auto abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(context);
if (!abilityContext) {
TLOGE(WmsLogTag::WMS_LIFE, "abilityContext is nullptr");
return WMError::WM_ERROR_NULLPTR;
}
if (abilityContext->IsHook() && !abilityContext->GetHookOff()) {
property_->EditSessionInfo().bundleName_ = elementName.GetBundleName();
property_->EditSessionInfo().moduleName_ = elementName.GetModuleName();
property_->EditSessionInfo().abilityName_ = elementName.GetAbilityName();
}
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::GetAppForceLandscapeConfig(AppForceLandscapeConfig& config)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::DEFAULT, "HostSession is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
return hostSession->GetAppForceLandscapeConfig(config);
}
WSError WindowSceneSessionImpl::NotifyAppForceLandscapeConfigUpdated()
{
TLOGI(WmsLogTag::DEFAULT, "in");
WindowType winType = GetType();
AppForceLandscapeConfig config = {};
if (WindowHelper::IsMainWindow(winType) && GetAppForceLandscapeConfig(config) == WMError::WM_OK &&
config.containsConfig_) {
SetForceSplitConfig(config);
return WSError::WS_OK;
}
return WSError::WS_DO_NOTHING;
}
void WindowSceneSessionImpl::SetForceSplitConfigEnable(bool needUpdateViewport)
{
WindowType winType = GetType();
if (!WindowHelper::IsMainWindow(winType)) {
return;
}
std::shared_ptr<Ace::UIContent> uiContent = GetUIContentSharedPtr();
if (uiContent == nullptr) {
TLOGE(WmsLogTag::WMS_COMPAT, "uiContent is null!");
return;
}
const auto& property = GetProperty();
if (property == nullptr) {
TLOGE(WmsLogTag::WMS_COMPAT, "property is null!");
return;
}
TLOGI(WmsLogTag::WMS_COMPAT, "enableForceSplit: %{public}u, needUpdateViewport: %{public}u, "
"selectMode: %{public}u", property->GetForceSplitEnable(), needUpdateViewport,
static_cast<uint32_t>(property->GetSelectMode()));
if (!needUpdateViewport) {
UpdateViewportConfig(GetRect(), WindowSizeChangeReason::SPLIT_ENABLE_CHANGE);
}
}
void WindowSceneSessionImpl::SendCombinedCompatibleConfigToArkUI()
{
const auto& combinedCompatibleConfig = property_->GetCombinedCompatibleConfig();
TLOGI(WmsLogTag::WMS_COMPAT, "bundleName: %{public}s, combinedCompatibleConfig size: %{public}zu",
property_->GetSessionInfo().bundleName_.c_str(), combinedCompatibleConfig.size());
if (combinedCompatibleConfig.size() < COMBINED_COMPATIBLE_CONFIG_SIZE) {
TLOGE(WmsLogTag::WMS_COMPAT, "Combined compatible config size is less than %{public}u!",
COMBINED_COMPATIBLE_CONFIG_SIZE);
return;
}
if (WindowSceneSessionImpl::hasSentCombinedCompatibleConfig_) {
TLOGI(WmsLogTag::WMS_COMPAT, "Combined compatible config has already sent");
return;
}
const auto& logicalDeviceConfig = combinedCompatibleConfig[0];
const auto& arkUIAndWebConfig = combinedCompatibleConfig[1];
TLOGI(WmsLogTag::WMS_COMPAT, "bundleName:%{public}s, logicalDeviceConfig size:%{public}zu, arkUIAndWebConfig size:"
"%{public}zu", property_->GetSessionInfo().bundleName_.c_str(), logicalDeviceConfig.size(),
arkUIAndWebConfig.size());
Ace::UIContent::SetXComponentCompensationAngle(logicalDeviceConfig);
Ace::UIContent::SetUICorrectionConfig(arkUIAndWebConfig);
WindowSceneSessionImpl::hasSentCombinedCompatibleConfig_ = true;
if (logicalDeviceConfig == "") {
TLOGI(WmsLogTag::WMS_COMPAT, "Send default logical device config to arkui");
} else if (logicalDeviceConfig == "{}") {
TLOGI(WmsLogTag::WMS_COMPAT, "Send null logical device config to arkui");
} else {
TLOGI(WmsLogTag::WMS_COMPAT, "Send logical device config to arkui successfully!");
}
TLOGI(WmsLogTag::WMS_COMPAT, "Send combined compatible config to arkui successfully!");
}
WMError WindowSceneSessionImpl::GetSelectMode(SelectMode& selectMode)
{
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
WMError ret = hostSession->GetSelectMode(selectMode);
if (ret == WMError::WM_OK) {
property_->SetSelectMode(selectMode);
}
return ret;
}
WMError WindowSceneSessionImpl::GetForceSplitEnable(bool& enable)
{
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR);
return hostSession->GetForceSplitEnable(enable);
}
WSError WindowSceneSessionImpl::UpdateAppHookWindowInfo(const HookWindowInfo& hookWindowInfo)
{
TLOGI(WmsLogTag::WMS_LAYOUT, "in");
const WindowType windowType = GetType();
if (!WindowHelper::IsMainWindow(windowType)) {
return WSError::WS_DO_NOTHING;
}
SetAppHookWindowInfo(hookWindowInfo);
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::SetForceSplitEnable(bool isForceSplitEnabled, bool needUpdateViewport,
SelectMode selectMode)
{
TLOGI(WmsLogTag::WMS_COMPAT, "in");
const WindowType windowType = GetType();
if (!WindowHelper::IsMainWindow(windowType)) {
return WSError::WS_DO_NOTHING;
}
const auto& property = GetProperty();
if (property) {
property->SetForceSplitEnable(isForceSplitEnabled);
property->SetSelectMode(selectMode);
}
SetForceSplitConfigEnable(needUpdateViewport);
return WSError::WS_OK;
}
WMError WindowSceneSessionImpl::SetSubWindowSource(SubWindowSource source)
{
if (IsWindowSessionInvalid()) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
const auto& property = GetProperty();
if (!WindowHelper::IsSubWindow(property->GetWindowType()) &&
!WindowHelper::IsDialogWindow(property->GetWindowType())) {
TLOGE(WmsLogTag::WMS_SUB, "only sub window and dialog is valid");
return WMError::WM_ERROR_INVALID_OPERATION;
}
auto hostSession = GetHostSession();
if (!hostSession) {
TLOGI(WmsLogTag::WMS_SUB, "session is nullptr");
return WMError::WM_ERROR_INVALID_SESSION;
}
WSError ret = hostSession->SetSubWindowSource(source);
if (ret == WSError::WS_ERROR_INVALID_WINDOW) {
return WMError::WM_ERROR_INVALID_WINDOW;
}
return ret != WSError::WS_OK ? WMError::WM_ERROR_SYSTEM_ABNORMALLY : WMError::WM_OK;
}
WMError WindowSceneSessionImpl::RestoreMainWindow(const std::shared_ptr<AAFwk::WantParams>& wantParams)
{
TLOGI(WmsLogTag::WMS_LIFE, "restore float main window id: %{public}d", GetPersistentId());
if (GetType() != WindowType::WINDOW_TYPE_FLOAT) {
TLOGE(WmsLogTag::WMS_LIFE, "only TYPE_FLOAT can use interface, type:%{public}u", GetType());
return WMError::WM_ERROR_INVALID_CALLING;
}
auto parentWindow = FindWindowById(property_->GetParentPersistentId());
if (parentWindow == nullptr) {
TLOGE(WmsLogTag::WMS_LIFE, "parentWindow is invalid");
return WMError::WM_ERROR_INVALID_CALLING;
}
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_LIFE, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
if (state_ != WindowState::STATE_SHOWN) {
TLOGE(WmsLogTag::WMS_LIFE, "window is not foreground showing");
return WMError::WM_ERROR_INVALID_CALLING;
}
auto hostSession = GetHostSession();
if (!hostSession) {
TLOGE(WmsLogTag::WMS_LIFE, "session is nullptr");
return WMError::WM_ERROR_INVALID_WINDOW;
}
WMError ret = hostSession->RestoreFloatMainWindow(wantParams);
if (ret != WMError::WM_OK) {
TLOGE(WmsLogTag::WMS_LIFE, "RestoreFloatMainWindow result is: %{public}d", static_cast<int32_t>(ret));
return ret;
}
return WMError::WM_OK;
}
WSError WindowSceneSessionImpl::CloseSpecificScene()
{
if (!property_->IsDecorEnable()) {
TLOGW(WmsLogTag::WMS_SUB, "specific scene can not close id: %{public}d, decor is not enable.",
GetPersistentId());
return WSError::WS_ERROR_INVALID_OPERATION;
}
TLOGI(WmsLogTag::WMS_SUB, "close specific scene id: %{public}d", GetPersistentId());
handler_->PostTask([weakThis = wptr(this)] {
auto window = weakThis.promote();
if (!window) {
TLOGNE(WmsLogTag::WMS_SUB, "window is nullptr");
return;
}
window->Close();
}, __func__);
return WSError::WS_OK;
}
* Window Event
*/
WMError WindowSceneSessionImpl::LockCursor(int32_t windowId, bool isCursorFollowMovement)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_EVENT, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
std::vector<int32_t> parameters;
parameters.emplace_back(LOCK_CURSOR_LENGTH);
parameters.emplace_back(windowId);
parameters.emplace_back(static_cast<int32_t>(isCursorFollowMovement));
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
return hostSession->SendCommonEvent(static_cast<int32_t>(CommonEventCommand::LOCK_CURSOR), parameters);
}
WMError WindowSceneSessionImpl::UnlockCursor(int32_t windowId)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_EVENT, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
std::vector<int32_t> parameters;
parameters.emplace_back(UNLOCK_CURSOR_LENGTH);
parameters.emplace_back(windowId);
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
return hostSession->SendCommonEvent(static_cast<int32_t>(CommonEventCommand::UNLOCK_CURSOR), parameters);
}
WMError WindowSceneSessionImpl::SetReceiveDragEventEnabled(bool enabled)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_EVENT, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
std::vector<int32_t> parameters;
parameters.emplace_back(SET_RECEIVE_DRAG_EVENT_LENGTH);
parameters.emplace_back(static_cast<int32_t>(enabled));
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
auto result = hostSession->SendCommonEvent(static_cast<int32_t>(CommonEventCommand::SET_RECEIVE_DRAG_EVENT),
parameters);
if (result == WMError::WM_OK) {
isReceiveDragEventEnabled_ = enabled;
}
return result;
}
bool WindowSceneSessionImpl::IsReceiveDragEventEnabled()
{
return isReceiveDragEventEnabled_;
}
WMError WindowSceneSessionImpl::SetSeparationTouchEnabled(bool enabled)
{
if (IsWindowSessionInvalid()) {
TLOGE(WmsLogTag::WMS_EVENT, "session is invalid");
return WMError::WM_ERROR_INVALID_WINDOW;
}
std::vector<int32_t> parameters;
parameters.emplace_back(WINDOW_SEPARATION_TOUCH_ENABLED_LENGTH);
parameters.emplace_back(static_cast<int32_t>(enabled));
auto hostSession = GetHostSession();
CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW);
auto result = hostSession->SendCommonEvent(
static_cast<int32_t>(CommonEventCommand::SET_WINDOW_SEPARATION_TOUCH_ENABLED), parameters);
if (result == WMError::WM_OK) {
TLOGI(WmsLogTag::WMS_EVENT, "set window separation successfully WId:%{public}u", GetWindowId());
isSeparationTouchEnabled_ = enabled;
}
return result;
}
bool WindowSceneSessionImpl::IsSeparationTouchEnabled()
{
return isSeparationTouchEnabled_;
}
bool WindowSceneSessionImpl::IsHitHotAreas(std::shared_ptr<MMI::PointerEvent>& pointerEvent)
{
std::shared_ptr<Ace::UIContent> uiContent = GetUIContentSharedPtr();
std::lock_guard<std::mutex> lockListener(compatScaleListenerMutex_);
if (!IsPcOrPadFreeMultiWindowMode()) {
return false;
}
if (uiContent == nullptr) {
TLOGE(WmsLogTag::WMS_DECOR, "uiContent is null, windowId: %{public}u", GetWindowId());
return false;
}
Rect windowRect = property_->GetWindowRect();
MMI::PointerEvent::PointerItem pointerItem;
int32_t foldCreaseRegionHeight = 0;
int32_t displayHeight = 0;
bool isValidPointItem = pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem);
auto foldCreaseRegion = DisplayManager::GetInstance().GetCurrentFoldCreaseRegion();
if (foldCreaseRegion != nullptr) {
const auto& creaseRects = foldCreaseRegion->GetCreaseRects();
if (!creaseRects.empty()) {
foldCreaseRegionHeight = creaseRects.front().height_;
}
}
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display != nullptr) {
displayHeight = display->GetHeight();
}
int32_t displayX = pointerItem.GetDisplayX();
int32_t displayY = pointerItem.GetDisplayY();
if (property_->GetDisplayId() == DISPLAY_ID_C) {
displayY -= (displayHeight + foldCreaseRegionHeight);
}
int32_t width = static_cast<int32_t>(windowRect.width_);
int32_t height = static_cast<int32_t>(windowRect.height_);
int32_t posX = windowRect.posX_;
int32_t posY = windowRect.posY_;
float vpr = WindowSessionImpl::GetVirtualPixelRatio();
float scaleX = compatScaleX_;
float scaleY = compatScaleY_;
float outsideArea = HOTZONE_TOUCH * vpr;
float insideArea = WINDOW_FRAME_WIDTH * vpr;
float cornerArea = WINDOW_FRAME_CORNER_TOUCH_WIDTH * vpr;
bool isHitTopHotArea = displayX > posX - outsideArea * scaleX &&
displayX < posX + (width + outsideArea) * scaleX &&
displayY > posY - outsideArea * scaleY &&
displayY < posY + (insideArea + outsideArea) * scaleY;
bool isHitLeftHotArea = displayX > posX - outsideArea * scaleX &&
displayX < posX + (insideArea + outsideArea) * scaleX &&
displayY > posY - outsideArea * scaleY &&
displayY < posY + (height + outsideArea) * scaleY;
bool isHitRightHotArea = displayX > posX + (width - insideArea) * scaleX &&
displayX < posX + (width + outsideArea) * scaleX &&
displayY > posY - outsideArea * scaleY &&
displayY < posY + (height + outsideArea) * scaleY;
bool isHitBottomHotArea = displayX > posX - outsideArea * scaleX &&
displayX < posX + (width + outsideArea) * scaleX &&
displayY > posY + (height - insideArea) * scaleY &&
displayY < posY + (height + outsideArea) * scaleY;
bool isHitLeftBottomHotArea = displayX > posX &&
displayX < posX + cornerArea * scaleX &&
displayY > posY + (height - cornerArea) * scaleY &&
displayY < posY + height * scaleY;
bool isHitRightBottomHotArea = displayX > posX + (width - cornerArea) * scaleX &&
displayX < posX + width * scaleX &&
displayY > posY + (height - cornerArea) * scaleY &&
displayY < posY + height * scaleY;
bool isHitHotAreas = isHitTopHotArea || isHitLeftHotArea || isHitRightHotArea || isHitBottomHotArea ||
isHitLeftBottomHotArea || isHitRightBottomHotArea;
if (isValidPointItem && isHitHotAreas) {
TLOGI(WmsLogTag::WMS_DECOR, "hitHotAreas success");
return true;
}
return false;
}
WSError WindowSceneSessionImpl::AddSidebarBlur()
{
TLOGI(WmsLogTag::WMS_PC, "in, persistentId=%{public}d", GetPersistentId());
if (handler_ == nullptr) {
TLOGE(WmsLogTag::WMS_PC, "handler is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
handler_->PostTask(
[weakThis = wptr(this), where = __func__] {
auto window = weakThis.promote();
if (!window) {
TLOGNE(WmsLogTag::WMS_PC, "%{public}s: window is nullptr", where);
return;
}
if (!window->surfaceNode_) {
TLOGNE(WmsLogTag::WMS_PC, "%{public}s: surfaceNode is null", where);
return;
}
auto rsNodeTemp = RSAdapterUtil::GetRSNode(window->GetRSUIContext(), window->surfaceNode_->GetId());
if (rsNodeTemp) {
bool isDark = (window->colorMode_ == AppExecFwk::ConfigurationInner::COLOR_MODE_DARK);
window->AddRSNodeModifier(isDark, rsNodeTemp);
}
}, __func__);
return WSError::WS_OK;
}
void WindowSceneSessionImpl::AddRSNodeModifier(bool isDark, const std::shared_ptr<RSBaseNode>& rsNode)
{
TLOGI(WmsLogTag::WMS_PC, "persistentId=%{public}d, isDark=%{public}d", GetPersistentId(), isDark);
if (blurRadiusValue_ && blurSaturationValue_ && blurBrightnessValue_ && blurMaskColorValue_) {
TLOGE(WmsLogTag::WMS_PC, "RSAnimatableProperty has value");
return;
}
if (!rsNode) {
TLOGE(WmsLogTag::WMS_PC, "rsNode is nullptr");
return;
}
blurRadiusValue_ = std::make_shared<Rosen::RSAnimatableProperty<float>>(
isDark ? SIDEBAR_DEFAULT_RADIUS_DARK : SIDEBAR_DEFAULT_RADIUS_LIGHT);
blurSaturationValue_ = std::make_shared<Rosen::RSAnimatableProperty<float>>(
isDark ? SIDEBAR_DEFAULT_SATURATION_DARK : SIDEBAR_DEFAULT_SATURATION_LIGHT);
blurBrightnessValue_ = std::make_shared<Rosen::RSAnimatableProperty<float>>(
isDark ? SIDEBAR_DEFAULT_BRIGHTNESS_DARK : SIDEBAR_DEFAULT_BRIGHTNESS_LIGHT);
blurMaskColorValue_ = std::make_shared<RSAnimatableProperty<Rosen::RSColor>>(
Rosen::RSColor::FromArgbInt(isDark ? SIDEBAR_DEFAULT_MASKCOLOR_DARK : SIDEBAR_DEFAULT_MASKCOLOR_LIGHT));
auto modifier = std::make_shared<Rosen::ModifierNG::RSBehindWindowFilterModifier>();
modifier->AttachProperty(ModifierNG::RSPropertyType::BEHIND_WINDOW_FILTER_RADIUS, blurRadiusValue_);
modifier->AttachProperty(ModifierNG::RSPropertyType::BEHIND_WINDOW_FILTER_SATURATION, blurSaturationValue_);
modifier->AttachProperty(ModifierNG::RSPropertyType::BEHIND_WINDOW_FILTER_BRIGHTNESS, blurBrightnessValue_);
modifier->AttachProperty(ModifierNG::RSPropertyType::BEHIND_WINDOW_FILTER_MASK_COLOR, blurMaskColorValue_);
rsNode->AddModifier(modifier);
}
WSError WindowSceneSessionImpl::SetSidebarBlurStyleWithType(SidebarBlurType type)
{
TLOGI(WmsLogTag::WMS_PC, "in, persistentId=%{public}d, type: %{public}u", GetPersistentId(),
static_cast<uint32_t>(type));
if (handler_ == nullptr) {
TLOGE(WmsLogTag::WMS_PC, "handler is nullptr");
return WSError::WS_ERROR_NULLPTR;
}
handler_->PostTask(
[weakThis = wptr(this), type, where = __func__] {
auto window = weakThis.promote();
if (!window) {
TLOGNE(WmsLogTag::WMS_PC, "%{public}s: window is nullptr", where);
return;
}
if (!window->blurRadiusValue_ || !window->blurSaturationValue_ || !window->blurBrightnessValue_ ||
!window->blurMaskColorValue_) {
TLOGNW(WmsLogTag::WMS_PC, "%{public}s: RSAnimatableProperty is null", where);
return;
}
bool isDark = (window->colorMode_ == AppExecFwk::ConfigurationInner::COLOR_MODE_DARK);
window->ModifySidebarBlurProperty(isDark, type);
}, __func__);
return WSError::WS_OK;
}
void WindowSceneSessionImpl::UpdateSidebarBlurStyleWhenColorModeChange()
{
TLOGI(WmsLogTag::WMS_PC, "in, persistentId=%{public}d", GetPersistentId());
if (!blurRadiusValue_ || !blurSaturationValue_ || !blurBrightnessValue_ || !blurMaskColorValue_) {
TLOGW(WmsLogTag::WMS_PC, "RSAnimatableProperty is null");
return;
}
bool isDark = (colorMode_ == AppExecFwk::ConfigurationInner::COLOR_MODE_DARK);
SidebarBlurType type = (GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) ?
SidebarBlurType::DEFAULT_MAXIMIZE : SidebarBlurType::DEFAULT_FLOAT;
ModifySidebarBlurProperty(isDark, type);
}
void WindowSceneSessionImpl::ModifySidebarBlurProperty(bool isDark, SidebarBlurType type)
{
TLOGI(WmsLogTag::WMS_PC, "persistentId=%{public}d, isDark: %{public}d, type: %{public}u", GetPersistentId(),
isDark, static_cast<uint32_t>(type));
auto rsUIContext = GetRSUIContext();
AutoRSTransaction trans(rsUIContext);
if (type == SidebarBlurType::DEFAULT_FLOAT || type == SidebarBlurType::DEFAULT_MAXIMIZE) {
Rosen::RSAnimationTimingProtocol timingProtocol;
timingProtocol.SetDuration(SIDEBAR_BLUR_ANIMATION_DURATION);
timingProtocol.SetDirection(true);
timingProtocol.SetFillMode(Rosen::FillMode::FORWARDS);
timingProtocol.SetFinishCallbackType(Rosen::FinishCallbackType::LOGICALLY);
RSNode::OpenImplicitAnimation(rsUIContext, timingProtocol, Rosen::RSAnimationTimingCurve::LINEAR, nullptr);
}
switch (type) {
case SidebarBlurType::NONE:
blurRadiusValue_->Set(SIDEBAR_BLUR_NUMBER_ZERO);
blurSaturationValue_->Set(SIDEBAR_BLUR_NUMBER_ZERO);
blurBrightnessValue_->Set(SIDEBAR_BLUR_NUMBER_ZERO);
blurMaskColorValue_->Set(Rosen::RSColor::FromArgbInt(
isDark ? SIDEBAR_SNAPSHOT_MASKCOLOR_DARK : SIDEBAR_SNAPSHOT_MASKCOLOR_LIGHT));
break;
case SidebarBlurType::INITIAL:
case SidebarBlurType::DEFAULT_FLOAT: {
blurRadiusValue_->Set(isDark ? SIDEBAR_DEFAULT_RADIUS_DARK : SIDEBAR_DEFAULT_RADIUS_LIGHT);
blurSaturationValue_->Set(isDark ? SIDEBAR_DEFAULT_SATURATION_DARK : SIDEBAR_DEFAULT_SATURATION_LIGHT);
blurBrightnessValue_->Set(isDark ? SIDEBAR_DEFAULT_BRIGHTNESS_DARK : SIDEBAR_DEFAULT_BRIGHTNESS_LIGHT);
blurMaskColorValue_->Set(Rosen::RSColor::FromArgbInt(
isDark ? SIDEBAR_DEFAULT_MASKCOLOR_DARK : SIDEBAR_DEFAULT_MASKCOLOR_LIGHT));
break;
}
case SidebarBlurType::DEFAULT_MAXIMIZE: {
blurRadiusValue_->Set(isDark ? SIDEBAR_MAXIMIZE_RADIUS_DARK : SIDEBAR_MAXIMIZE_RADIUS_LIGHT);
blurSaturationValue_->Set(isDark ? SIDEBAR_MAXIMIZE_SATURATION_DARK : SIDEBAR_MAXIMIZE_SATURATION_LIGHT);
blurBrightnessValue_->Set(isDark ? SIDEBAR_MAXIMIZE_BRIGHTNESS_DARK : SIDEBAR_MAXIMIZE_BRIGHTNESS_LIGHT);
blurMaskColorValue_->Set(Rosen::RSColor::FromArgbInt(
isDark ? SIDEBAR_MAXIMIZE_MASKCOLOR_DARK : SIDEBAR_MAXIMIZE_MASKCOLOR_LIGHT));
break;
}
default:
break;
}
if (type == SidebarBlurType::DEFAULT_FLOAT || type == SidebarBlurType::DEFAULT_MAXIMIZE) {
RSNode::CloseImplicitAnimation(rsUIContext);
}
}
bool WindowSceneSessionImpl::IsInFreeWindowMode() const
{
return IsPcOrPadFreeMultiWindowMode();
}
bool WindowSceneSessionImpl::IsAncoSupportFreeWindow() const
{
static const bool isAncoSupportFreeWindow = system::GetIntParameter(IS_ANCO_SUPPORT_FREE_WINDOW, 0) == 1;
return isAncoSupportFreeWindow && (windowSystemConfig_.IsPcWindow() || windowSystemConfig_.IsPadWindow());
}
uint32_t WindowSceneSessionImpl::SetSupportedWindowModesForAncoInFreeWindow(uint32_t windowModeSupportType)
{
if (!IsAnco() || !(windowSystemConfig_.IsPcWindow() || windowSystemConfig_.IsPadWindow())) {
TLOGI(WmsLogTag::WMS_MAIN, "is not anco app, need not update support window mode.");
return windowModeSupportType;
}
if (IsAncoSupportFreeWindow()) {
TLOGI(WmsLogTag::WMS_MAIN, "anco app support free window, need not update support window mode.");
return windowModeSupportType;
}
if (windowSystemConfig_.IsPcOrPcMode()) {
lastWindowModeSupportType_ = windowModeSupportType;
windowModeSupportType = windowModeSupportType & (~WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING);
return windowModeSupportType;
}
lastWindowModeSupportType_ = windowModeSupportType & (~WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING);
return windowModeSupportType;
}
WSError WindowSceneSessionImpl::HideSubWindowZLevelAboveParentLoosened()
{
TLOGI(WmsLogTag::WMS_SUB, "persistentId: %{public}d", GetPersistentId());
Hide(0, false, false, true);
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::ShowSubWindowZLevelAboveParentLoosened()
{
TLOGI(WmsLogTag::WMS_SUB, "persistentId: %{public}d", GetPersistentId());
Show(0, false, true);
return WSError::WS_OK;
}
WSError WindowSceneSessionImpl::DestroySubWindowZLevelAboveParentLoosened()
{
TLOGI(WmsLogTag::WMS_SUB, "persistentId: %{public}d", GetPersistentId());
handler_->PostTask([weakThis = wptr(this)] {
auto window = weakThis.promote();
if (!window) {
TLOGNE(WmsLogTag::WMS_LIFE, "window is nullptr");
return;
}
window->Close();
}, __func__);
return WSError::WS_OK;
}
WMError WindowSceneSessionImpl::SaveNativeKeyEventFilter(NativeKeyEventFilter nativeFilter)
{
std::unique_lock<std::shared_mutex> lock(nativeKeyEventFilterMutex_);
nativeKeyEventFilter_ = nativeFilter;
return WMError::WM_OK;
}
NativeKeyEventFilter WindowSceneSessionImpl::GetNativeKeyEventFilter() const
{
std::shared_lock<std::shared_mutex> lock(nativeKeyEventFilterMutex_);
return nativeKeyEventFilter_;
}
WMError WindowSceneSessionImpl::ClearNativeKeyEventFilter()
{
std::unique_lock<std::shared_mutex> lock(nativeKeyEventFilterMutex_);
nativeKeyEventFilter_ = nullptr;
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SaveNativeMouseEventFilter(NativeMouseEventFilter nativeFilter)
{
std::unique_lock<std::shared_mutex> lock(nativeMouseEventFilterMutex_);
nativeMouseEventFilter_ = nativeFilter;
return WMError::WM_OK;
}
NativeMouseEventFilter WindowSceneSessionImpl::GetNativeMouseEventFilter() const
{
std::shared_lock<std::shared_mutex> lock(nativeMouseEventFilterMutex_);
return nativeMouseEventFilter_;
}
WMError WindowSceneSessionImpl::ClearNativeMouseEventFilter()
{
std::unique_lock<std::shared_mutex> lock(nativeMouseEventFilterMutex_);
nativeMouseEventFilter_ = nullptr;
return WMError::WM_OK;
}
WMError WindowSceneSessionImpl::SaveNativeTouchEventFilter(NativeTouchEventFilter nativeFilter)
{
std::unique_lock<std::shared_mutex> lock(nativeTouchEventFilterMutex_);
nativeTouchEventFilter_ = nativeFilter;
return WMError::WM_OK;
}
NativeTouchEventFilter WindowSceneSessionImpl::GetNativeTouchEventFilter() const
{
std::shared_lock<std::shared_mutex> lock(nativeTouchEventFilterMutex_);
return nativeTouchEventFilter_;
}
WMError WindowSceneSessionImpl::ClearNativeTouchEventFilter()
{
std::unique_lock<std::shared_mutex> lock(nativeTouchEventFilterMutex_);
nativeTouchEventFilter_ = nullptr;
return WMError::WM_OK;
}
bool WindowSceneSessionImpl::CheckWindowCanInHoverState(const Rect& windowRect)
{
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display == nullptr) {
TLOGE(WmsLogTag::DEFAULT, "display is null!");
return false;
}
bool isFullScreen = false;
if (FoldScreenStateInternel::IsSuperFoldDisplayDevice()) {
auto displayInfo = display->GetDisplayInfo();
if (displayInfo &&
windowRect.width_ == static_cast<uint32_t>(displayInfo->GetWidth()) &&
windowRect.height_ >= static_cast<uint32_t>(displayInfo->GetHeight())) {
isFullScreen = true;
}
} else {
isFullScreen = IsFullScreenSizeWindow(windowRect.width_, windowRect.height_);
}
Transform transform = property_->GetTransform();
if (!isFullScreen || GetWindowMode() != WindowMode::WINDOW_MODE_FULLSCREEN ||
(transform.scaleX_ != 1 || transform.scaleY_ != 1) || WindowSessionImpl::GetLSState()) {
return false;
}
return CheckCreaseRegionCanInHoverState(windowRect);
}
bool WindowSceneSessionImpl::CheckCreaseRegionCanInHoverState(const Rect& windowRect)
{
auto display = SingletonContainer::Get<DisplayManager>().GetDisplayById(property_->GetDisplayId());
if (display == nullptr) {
TLOGE(WmsLogTag::DEFAULT, "display is null!");
return false;
}
FoldCreaseRegion foldCreaseRegion;
DMError res = display->GetLiveCreaseRegion(foldCreaseRegion);
if (res != DMError::DM_OK) {
TLOGE(WmsLogTag::DEFAULT, "foldCreaseRegion is null!");
return false;
}
const auto& creaseRects = foldCreaseRegion.GetCreaseRects();
if (creaseRects.empty()) {
TLOGE(WmsLogTag::DEFAULT, "creaseRects is empty!");
return false;
}
const DMRect& creaseRect = creaseRects.front();
if (creaseRect.width_ < creaseRect.height_) {
return false;
}
if ((creaseRect.posX_ < windowRect.posX_ || creaseRect.posY_ < windowRect.posY_) ||
(creaseRect.posX_ + creaseRect.width_ > windowRect.posX_ + windowRect.width_ ||
creaseRect.posY_ + creaseRect.height_ > windowRect.posY_ + windowRect.height_)) {
return false;
}
return true;
}
}
}