/* * 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_session_impl.h" #include #include #include #include #include #include #include #include #ifdef IMF_ENABLE #include #endif // IMF_ENABLE #include #include #include "anr_handler.h" #include "color_parser.h" #include "display_info.h" #include "display_manager.h" #include "hitrace_meter.h" #include "session_permission.h" #include "key_event.h" #include "session/container/include/window_event_channel.h" #include "session_manager/include/session_manager.h" #include "vsync_station.h" #include "window_adapter.h" #include "window_manager_hilog.h" #include "window_helper.h" #include "color_parser.h" #include "singleton_container.h" #include "perform_reporter.h" #include "picture_in_picture_manager.h" #include "parameters.h" namespace OHOS::Accessibility { class AccessibilityEventInfo; } namespace OHOS { namespace Rosen { namespace { constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowSessionImpl"}; constexpr int32_t FULL_CIRCLE_DEGREE = 360; constexpr int32_t ONE_FOURTH_FULL_CIRCLE_DEGREE = 90; constexpr int32_t FORCE_SPLIT_MODE = 5; /** * DFX */ const std::string SET_UIEXTENSION_DESTROY_TIMEOUT_LISTENER_TASK_NAME = "SetUIExtDestroyTimeoutListener"; constexpr int64_t SET_UIEXTENSION_DESTROY_TIMEOUT_TIME_MS = 4000; bool CheckIfNeedCommitRsTransaction(WindowSizeChangeReason wmReason) { if (wmReason == WindowSizeChangeReason::FULL_TO_SPLIT || wmReason == WindowSizeChangeReason::FULL_TO_FLOATING || wmReason == WindowSizeChangeReason::RECOVER || wmReason == WindowSizeChangeReason::MAXIMIZE) { return false; } return true; } Ace::ViewportConfig FillViewportConfig(Rect rect, float density, int32_t orientation, uint32_t transformHint) { Ace::ViewportConfig config; config.SetSize(rect.width_, rect.height_); config.SetPosition(rect.posX_, rect.posY_); config.SetDensity(density); config.SetOrientation(orientation); config.SetTransformHint(transformHint); return config; } Ace::ContentInfoType GetAceContentInfoType(BackupAndRestoreType type) { auto contentInfoType = Ace::ContentInfoType::NONE; switch (type) { case BackupAndRestoreType::CONTINUATION: contentInfoType = Ace::ContentInfoType::CONTINUATION; break; case BackupAndRestoreType::APP_RECOVERY: contentInfoType = Ace::ContentInfoType::APP_RECOVERY; break; case BackupAndRestoreType::RESOURCESCHEDULE_RECOVERY: contentInfoType = Ace::ContentInfoType::RESOURCESCHEDULE_RECOVERY; break; case BackupAndRestoreType::NONE: [[fallthrough]]; default: break; } return contentInfoType; } } std::map>> WindowSessionImpl::lifecycleListeners_; std::map>> WindowSessionImpl::displayMoveListeners_; std::map>> WindowSessionImpl::windowChangeListeners_; std::map>> WindowSessionImpl::avoidAreaChangeListeners_; std::map>> WindowSessionImpl::dialogDeathRecipientListeners_; std::map>> WindowSessionImpl::dialogTargetTouchListener_; std::map>> WindowSessionImpl::occupiedAreaChangeListeners_; std::map>> WindowSessionImpl::screenshotListeners_; std::map>> WindowSessionImpl::touchOutsideListeners_; std::map> WindowSessionImpl::windowVisibilityChangeListeners_; std::mutex WindowSessionImpl::displayIdChangeListenerMutex_; std::map> WindowSessionImpl::displayIdChangeListeners_; std::map> WindowSessionImpl::windowNoInteractionListeners_; std::map>> WindowSessionImpl::windowTitleButtonRectChangeListeners_; std::map>> WindowSessionImpl::windowRectChangeListeners_; std::map> WindowSessionImpl::subWindowCloseListeners_; std::map> WindowSessionImpl::mainWindowCloseListeners_; std::map>> WindowSessionImpl::switchFreeMultiWindowListeners_; std::recursive_mutex WindowSessionImpl::lifeCycleListenerMutex_; std::recursive_mutex WindowSessionImpl::windowChangeListenerMutex_; std::recursive_mutex WindowSessionImpl::avoidAreaChangeListenerMutex_; std::recursive_mutex WindowSessionImpl::dialogDeathRecipientListenerMutex_; std::recursive_mutex WindowSessionImpl::dialogTargetTouchListenerMutex_; std::recursive_mutex WindowSessionImpl::occupiedAreaChangeListenerMutex_; std::recursive_mutex WindowSessionImpl::screenshotListenerMutex_; std::recursive_mutex WindowSessionImpl::touchOutsideListenerMutex_; std::recursive_mutex WindowSessionImpl::windowVisibilityChangeListenerMutex_; std::recursive_mutex WindowSessionImpl::windowNoInteractionListenerMutex_; std::recursive_mutex WindowSessionImpl::windowStatusChangeListenerMutex_; std::recursive_mutex WindowSessionImpl::windowTitleButtonRectChangeListenerMutex_; std::mutex WindowSessionImpl::displayMoveListenerMutex_; std::mutex WindowSessionImpl::windowRectChangeListenerMutex_; std::mutex WindowSessionImpl::subWindowCloseListenersMutex_; std::mutex WindowSessionImpl::mainWindowCloseListenersMutex_; std::mutex WindowSessionImpl::switchFreeMultiWindowListenerMutex_; std::map>> WindowSessionImpl::windowSessionMap_; std::shared_mutex WindowSessionImpl::windowSessionMutex_; std::set> WindowSessionImpl::windowExtensionSessionSet_; std::shared_mutex WindowSessionImpl::windowExtensionSessionMutex_; std::map>> WindowSessionImpl::subWindowSessionMap_; std::map>> WindowSessionImpl::windowStatusChangeListeners_; bool WindowSessionImpl::isUIExtensionAbilityProcess_ = false; #define CALL_LIFECYCLE_LISTENER(windowLifecycleCb, listeners) \ do { \ for (auto& listener : (listeners)) { \ if (listener != nullptr) { \ listener->windowLifecycleCb(); \ } \ } \ } while (0) #define CALL_LIFECYCLE_LISTENER_WITH_PARAM(windowLifecycleCb, listeners, param) \ do { \ for (auto& listener : (listeners)) { \ if (listener != nullptr) { \ listener->windowLifecycleCb(param); \ } \ } \ } while (0) #define CALL_UI_CONTENT(uiContentCb) \ do { \ std::shared_ptr uiContent = GetUIContentSharedPtr(); \ if (uiContent != nullptr) { \ uiContent->uiContentCb(); \ } \ } while (0) #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) WindowSessionImpl::WindowSessionImpl(const sptr& option) { WLOGFD("[WMSCom]WindowSessionImpl"); property_ = new (std::nothrow) WindowSessionProperty(); if (property_ == nullptr) { WLOGFE("[WMSCom]Property is null"); return; } WindowType optionWindowType = option->GetWindowType(); SessionInfo sessionInfo; sessionInfo.bundleName_ = option->GetBundleName(); property_->SetSessionInfo(sessionInfo); property_->SetWindowName(option->GetWindowName()); property_->SetRequestRect(option->GetWindowRect()); property_->SetWindowType(optionWindowType); property_->SetFocusable(option->GetFocusable()); property_->SetTouchable(option->GetTouchable()); property_->SetDisplayId(option->GetDisplayId()); property_->SetParentId(option->GetParentId()); property_->SetTurnScreenOn(option->IsTurnScreenOn()); property_->SetKeepScreenOn(option->IsKeepScreenOn()); property_->SetWindowMode(option->GetWindowMode()); property_->SetWindowFlags(option->GetWindowFlags()); property_->SetCallingSessionId(option->GetCallingWindow()); property_->SetExtensionFlag(option->GetExtensionTag()); property_->SetTopmost(option->GetWindowTopmost()); property_->SetRealParentId(option->GetRealParentId()); property_->SetParentWindowType(option->GetParentWindowType()); property_->SetUIExtensionUsage(static_cast(option->GetUIExtensionUsage())); layoutCallback_ = sptr::MakeSptr(); property_->SetIsUIExtensionSubWindowFlag(option->GetIsUIExtensionSubWindowFlag()); isMainHandlerAvailable_ = option->GetMainHandlerAvailable(); isIgnoreSafeArea_ = WindowHelper::IsSubWindow(optionWindowType); windowOption_ = option; surfaceNode_ = CreateSurfaceNode(property_->GetWindowName(), optionWindowType); handler_ = std::make_shared(AppExecFwk::EventRunner::GetMainEventRunner()); if (surfaceNode_ != nullptr) { vsyncStation_ = std::make_shared(surfaceNode_->GetId()); if (WindowHelper::IsSubWindow(GetType())) { surfaceNode_->SetFrameGravity(Gravity::TOP_LEFT); } } } bool WindowSessionImpl::IsPcWindow() const { return (windowSystemConfig_.uiType_ == UI_TYPE_PC); } bool WindowSessionImpl::IsPcOrPadCapabilityEnabled() const { return WindowSessionImpl::IsPcOrPadFreeMultiWindowMode() || property_->GetIsPcAppInPad(); } bool WindowSessionImpl::IsPcOrPadFreeMultiWindowMode() const { return windowSystemConfig_.uiType_ == UI_TYPE_PC || IsFreeMultiWindowMode(); } void WindowSessionImpl::MakeSubOrDialogWindowDragableAndMoveble() { TLOGI(WmsLogTag::WMS_LIFE, "Called %{public}d.", GetPersistentId()); if (IsPcOrPadCapabilityEnabled() && windowOption_ != nullptr) { if (WindowHelper::IsSubWindow(property_->GetWindowType())) { TLOGI(WmsLogTag::WMS_LIFE, "create subwindow, title: %{public}s, decorEnable: %{public}d", windowOption_->GetSubWindowTitle().c_str(), windowOption_->GetSubWindowDecorEnable()); property_->SetDecorEnable(windowOption_->GetSubWindowDecorEnable()); property_->SetDragEnabled(windowOption_->GetSubWindowDecorEnable()); subWindowTitle_ = windowOption_->GetSubWindowTitle(); } bool isDialog = WindowHelper::IsDialogWindow(property_->GetWindowType()); if (isDialog) { bool dialogDecorEnable = windowOption_->GetDialogDecorEnable(); property_->SetDecorEnable(dialogDecorEnable); property_->SetDragEnabled(dialogDecorEnable); dialogTitle_ = windowOption_->GetDialogTitle(); TLOGI(WmsLogTag::WMS_LIFE, "create dialogWindow, title: %{public}s, decorEnable: %{public}d", dialogTitle_.c_str(), dialogDecorEnable); } } } RSSurfaceNode::SharedPtr WindowSessionImpl::CreateSurfaceNode(std::string name, WindowType type) { struct RSSurfaceNodeConfig rsSurfaceNodeConfig; rsSurfaceNodeConfig.SurfaceNodeName = name; RSSurfaceNodeType rsSurfaceNodeType = RSSurfaceNodeType::DEFAULT; switch (type) { case WindowType::WINDOW_TYPE_BOOT_ANIMATION: case WindowType::WINDOW_TYPE_POINTER: rsSurfaceNodeType = RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE; break; case WindowType::WINDOW_TYPE_APP_MAIN_WINDOW: rsSurfaceNodeType = RSSurfaceNodeType::APP_WINDOW_NODE; break; case WindowType::WINDOW_TYPE_UI_EXTENSION: TLOGI(WmsLogTag::WMS_LIFE, "uiExtensionUsage = %{public}u", property_->GetUIExtensionUsage()); if (property_->GetUIExtensionUsage() == UIExtensionUsage::CONSTRAINED_EMBEDDED) { rsSurfaceNodeType = RSSurfaceNodeType::UI_EXTENSION_SECURE_NODE; } else { rsSurfaceNodeType = RSSurfaceNodeType::UI_EXTENSION_COMMON_NODE; } break; case WindowType::WINDOW_TYPE_PIP: rsSurfaceNodeType = RSSurfaceNodeType::APP_WINDOW_NODE; break; default: rsSurfaceNodeType = RSSurfaceNodeType::DEFAULT; break; } return RSSurfaceNode::Create(rsSurfaceNodeConfig, rsSurfaceNodeType); } WindowSessionImpl::~WindowSessionImpl() { WLOGFD("[WMSCom]~WindowSessionImpl, id: %{public}d", GetPersistentId()); Destroy(true, false); } uint32_t WindowSessionImpl::GetWindowId() const { return static_cast(GetPersistentId()) & 0xffffffff; // 0xffffffff: to get low 32 bits } uint64_t WindowSessionImpl::GetDisplayId() const { return property_->GetDisplayId(); } int32_t WindowSessionImpl::GetParentId() const { // 0xffffffff: to get low 32 bits uint32_t parentID = static_cast(property_->GetParentPersistentId()) & 0x7fffffff; return static_cast(parentID); } bool WindowSessionImpl::IsWindowSessionInvalid() const { bool res = ((GetHostSession() == nullptr) || (GetPersistentId() == INVALID_SESSION_ID) || (state_ == WindowState::STATE_DESTROYED)); if (res) { TLOGW(WmsLogTag::WMS_LIFE, "already destroyed or not created! id: %{public}d state_: %{public}u", GetPersistentId(), state_); } return res; } bool WindowSessionImpl::IsMainHandlerAvailable() const { TLOGI(WmsLogTag::DEFAULT, "id:%{public}d, isAvailable:%{public}u", GetPersistentId(), isMainHandlerAvailable_); return isMainHandlerAvailable_; } int32_t WindowSessionImpl::GetPersistentId() const { if (property_) { return property_->GetPersistentId(); } return INVALID_SESSION_ID; } sptr WindowSessionImpl::GetProperty() const { return property_; } SystemSessionConfig WindowSessionImpl::GetSystemSessionConfig() const { return windowSystemConfig_; } sptr WindowSessionImpl::GetHostSession() const { std::lock_guard lock(hostSessionMutex_); return hostSession_; } ColorSpace WindowSessionImpl::GetColorSpaceFromSurfaceGamut(GraphicColorGamut colorGamut) { if (colorGamut == GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB) { return ColorSpace::COLOR_SPACE_DEFAULT; } else if (colorGamut == GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DCI_P3) { return ColorSpace::COLOR_SPACE_WIDE_GAMUT; } else { WLOGFE("try to get not exist ColorSpace"); return ColorSpace::COLOR_SPACE_DEFAULT; } } GraphicColorGamut WindowSessionImpl::GetSurfaceGamutFromColorSpace(ColorSpace colorSpace) { if (colorSpace == ColorSpace::COLOR_SPACE_DEFAULT) { return GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB; } else if (colorSpace == ColorSpace::COLOR_SPACE_WIDE_GAMUT) { return GraphicColorGamut::GRAPHIC_COLOR_GAMUT_DCI_P3; } else { WLOGFE("try to get not exist colorGamut"); return GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB; } } bool WindowSessionImpl::IsSupportWideGamut() { return true; } void WindowSessionImpl::SetColorSpace(ColorSpace colorSpace) { if (IsWindowSessionInvalid() || surfaceNode_ == nullptr) { TLOGE(WmsLogTag::DEFAULT, "session is invalid"); return; } auto colorGamut = GetSurfaceGamutFromColorSpace(colorSpace); surfaceNode_->SetColorSpace(colorGamut); } ColorSpace WindowSessionImpl::GetColorSpace() { if (IsWindowSessionInvalid() || surfaceNode_ == nullptr) { TLOGE(WmsLogTag::DEFAULT, "session is invalid"); return ColorSpace::COLOR_SPACE_DEFAULT; } GraphicColorGamut colorGamut = surfaceNode_->GetColorSpace(); return GetColorSpaceFromSurfaceGamut(colorGamut); } WMError WindowSessionImpl::WindowSessionCreateCheck() { if (!property_ || vsyncStation_ == nullptr || !vsyncStation_->IsVsyncReceiverCreated()) { return WMError::WM_ERROR_NULLPTR; } const auto& name = property_->GetWindowName(); std::shared_lock lock(windowSessionMutex_); // check window name, same window names are forbidden if (windowSessionMap_.find(name) != windowSessionMap_.end()) { WLOGFE("WindowName(%{public}s) already exists.", name.c_str()); return WMError::WM_ERROR_REPEAT_OPERATION; } // check if camera floating window is already exists if (property_->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA || property_->GetWindowType() == WindowType::WINDOW_TYPE_PIP) { for (const auto& item : windowSessionMap_) { if (item.second.second && item.second.second->property_ && item.second.second->property_->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) { WLOGFE("Camera floating window is already exists."); return WMError::WM_ERROR_REPEAT_OPERATION; } } uint32_t accessTokenId = static_cast(IPCSkeleton::GetCallingTokenID()); property_->SetAccessTokenId(accessTokenId); TLOGI(WmsLogTag::DEFAULT, "Create camera float window, TokenId = %{private}u", accessTokenId); } return WMError::WM_OK; } void WindowSessionImpl::SetDefaultDisplayIdIfNeed() { TLOGI(WmsLogTag::WMS_LIFE, "Called"); auto displayId = property_->GetDisplayId(); if (displayId == DISPLAY_ID_INVALID) { auto defaultDisplayId = SingletonContainer::IsDestroyed() ? DISPLAY_ID_INVALID : SingletonContainer::Get().GetDefaultDisplayId(); defaultDisplayId = (defaultDisplayId == DISPLAY_ID_INVALID) ? 0 : defaultDisplayId; property_->SetDisplayId(defaultDisplayId); TLOGI(WmsLogTag::WMS_LIFE, "Reset displayId to %{public}" PRIu64, defaultDisplayId); } } WMError WindowSessionImpl::Create(const std::shared_ptr& context, const sptr& iSession, const std::string& identityToken) { return WMError::WM_OK; } WMError WindowSessionImpl::Connect() { TLOGI(WmsLogTag::WMS_LIFE, "Called"); auto hostSession = GetHostSession(); CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_NULLPTR); sptr iSessionStage(this); auto windowEventChannel = new (std::nothrow) WindowEventChannel(iSessionStage); if (windowEventChannel && property_) { windowEventChannel->SetIsUIExtension(property_->GetWindowType() == WindowType::WINDOW_TYPE_UI_EXTENSION); windowEventChannel->SetUIExtensionUsage(property_->GetUIExtensionUsage()); } sptr iWindowEventChannel(windowEventChannel); sptr token = context_ ? context_->GetToken() : nullptr; if (token) { property_->SetTokenState(true); } auto ret = hostSession->Connect( iSessionStage, iWindowEventChannel, surfaceNode_, windowSystemConfig_, property_, token, identityToken_); TLOGI(WmsLogTag::WMS_LIFE, "Window Connect [name:%{public}s, id:%{public}d, type:%{public}u], ret:%{public}u", property_->GetWindowName().c_str(), GetPersistentId(), property_->GetWindowType(), ret); return static_cast(ret); } void WindowSessionImpl::ConsumePointerEvent(const std::shared_ptr& pointerEvent) { NotifyPointerEvent(pointerEvent); } void WindowSessionImpl::ConsumeKeyEvent(std::shared_ptr& keyEvent) { bool isConsumed = false; NotifyKeyEvent(keyEvent, isConsumed, false); } bool WindowSessionImpl::PreNotifyKeyEvent(const std::shared_ptr& keyEvent) { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { return uiContent->ProcessKeyEvent(keyEvent, true); } return false; } bool WindowSessionImpl::NotifyOnKeyPreImeEvent(const std::shared_ptr& keyEvent) { return PreNotifyKeyEvent(keyEvent); } void WindowSessionImpl::UpdateSubWindowStateAndNotify(int32_t parentPersistentId, const WindowState newState) { auto iter = subWindowSessionMap_.find(parentPersistentId); if (iter == subWindowSessionMap_.end()) { TLOGD(WmsLogTag::WMS_SUB, "parent window: %{public}d has no child node", parentPersistentId); return; } const auto& subWindows = iter->second; if (subWindows.empty()) { TLOGD(WmsLogTag::WMS_SUB, "parent window: %{public}d, its subWindowMap is empty", parentPersistentId); return; } // when parent window hide and subwindow whose state is shown should hide and notify user if (newState == WindowState::STATE_HIDDEN) { for (auto subwindow : subWindows) { if (subwindow != nullptr && subwindow->GetWindowState() == WindowState::STATE_SHOWN) { subwindow->state_ = WindowState::STATE_HIDDEN; subwindow->NotifyAfterBackground(); TLOGD(WmsLogTag::WMS_SUB, "Notify subWindow background, id:%{public}d", subwindow->GetPersistentId()); UpdateSubWindowStateAndNotify(subwindow->GetPersistentId(), newState); } } // when parent window show and subwindow whose state is shown should show and notify user } else if (newState == WindowState::STATE_SHOWN) { for (auto subwindow : subWindows) { if (subwindow != nullptr && subwindow->GetWindowState() == WindowState::STATE_HIDDEN && subwindow->GetRequestWindowState() == WindowState::STATE_SHOWN) { subwindow->state_ = WindowState::STATE_SHOWN; subwindow->NotifyAfterForeground(); TLOGD(WmsLogTag::WMS_SUB, "Notify subWindow foreground, id:%{public}d", subwindow->GetPersistentId()); UpdateSubWindowStateAndNotify(subwindow->GetPersistentId(), newState); } } } } WMError WindowSessionImpl::Show(uint32_t reason, bool withAnimation, bool withFocus) { TLOGI(WmsLogTag::WMS_LIFE, "name:%{public}s, id:%{public}d, type:%{public}u, reason:%{public}u, state:%{public}u", property_->GetWindowName().c_str(), property_->GetPersistentId(), GetType(), reason, state_); if (IsWindowSessionInvalid()) { WLOGFE("session is invalid"); return WMError::WM_ERROR_INVALID_WINDOW; } if (state_ == WindowState::STATE_SHOWN) { TLOGD(WmsLogTag::WMS_LIFE, "window session is alreay shown [name:%{public}s, id:%{public}d, type: %{public}u]", property_->GetWindowName().c_str(), GetPersistentId(), property_->GetWindowType()); NotifyAfterForeground(true, false); return WMError::WM_OK; } auto hostSession = GetHostSession(); CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW); WSError ret = hostSession->Foreground(property_); // delete after replace WSError with WMError WMError res = static_cast(ret); if (res == WMError::WM_OK) { UpdateSubWindowStateAndNotify(GetPersistentId(), WindowState::STATE_SHOWN); state_ = WindowState::STATE_SHOWN; requestState_ = WindowState::STATE_SHOWN; NotifyAfterForeground(); } else { NotifyForegroundFailed(res); } return res; } WMError WindowSessionImpl::Hide(uint32_t reason, bool withAnimation, bool isFromInnerkits) { TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d Hide, reason:%{public}u, state:%{public}u", GetPersistentId(), reason, state_); if (IsWindowSessionInvalid()) { WLOGFE("session is invalid"); return WMError::WM_ERROR_INVALID_WINDOW; } if (state_ == WindowState::STATE_HIDDEN || state_ == WindowState::STATE_CREATED) { TLOGD(WmsLogTag::WMS_LIFE, "window session is alreay hidden [name:%{public}s, id:%{public}d, type: %{public}u]", property_->GetWindowName().c_str(), GetPersistentId(), property_->GetWindowType()); NotifyBackgroundFailed(WMError::WM_DO_NOTHING); return WMError::WM_OK; } UpdateSubWindowStateAndNotify(GetPersistentId(), WindowState::STATE_HIDDEN); state_ = WindowState::STATE_HIDDEN; requestState_ = WindowState::STATE_HIDDEN; NotifyAfterBackground(); return WMError::WM_OK; } void WindowSessionImpl::DestroySubWindow() { int32_t parentPersistentId = property_->GetParentPersistentId(); const int32_t persistentId = GetPersistentId(); if (property_->GetExtensionFlag() == true) { auto extensionWindow = FindExtensionWindowWithContext(); if (extensionWindow != nullptr) { parentPersistentId = extensionWindow->GetPersistentId(); } } TLOGI(WmsLogTag::WMS_SUB, "Id: %{public}d, parentId: %{public}d", persistentId, parentPersistentId); // remove from subWindowMap_ when destroy sub window auto subIter = subWindowSessionMap_.find(parentPersistentId); if (subIter != subWindowSessionMap_.end()) { auto& subWindows = subIter->second; for (auto iter = subWindows.begin(); iter != subWindows.end(); iter++) { auto subWindow = *iter; if (subWindow == nullptr) { continue; } if (subWindow->GetPersistentId() == persistentId) { TLOGD(WmsLogTag::WMS_SUB, "Destroy sub window, persistentId: %{public}d", persistentId); subWindows.erase(iter); break; } else { TLOGD(WmsLogTag::WMS_SUB, "Exists other sub window, persistentId: %{public}d", persistentId); } } if (property_->GetExtensionFlag() && subWindowSessionMap_.empty()) { auto extensionWindow = FindExtensionWindowWithContext(); if (extensionWindow != nullptr && extensionWindow->GetUIContentSharedPtr() == nullptr) { extensionWindow->AddSetUIExtensionDestroyTimeoutCheck(); } } } // remove from subWindowMap_ when destroy parent window auto mainIter = subWindowSessionMap_.find(persistentId); if (mainIter != subWindowSessionMap_.end()) { auto& subWindows = mainIter->second; for (auto iter = subWindows.begin(); iter != subWindows.end(); iter = subWindows.begin()) { auto subWindow = *iter; if (subWindow == nullptr) { TLOGW(WmsLogTag::WMS_SUB, "Destroy sub window which is nullptr"); subWindows.erase(iter); continue; } bool isExtDestroyed = subWindow->property_->GetExtensionFlag(); TLOGD(WmsLogTag::WMS_SUB, "Destroy sub window, persistentId: %{public}d, isExtDestroyed: %{public}d", subWindow->GetPersistentId(), isExtDestroyed); auto ret = subWindow->Destroy(isExtDestroyed); if (ret != WMError::WM_OK) { TLOGE(WmsLogTag::WMS_SUB, "Destroy failed. persistentId: %{public}d", subWindow->GetPersistentId()); subWindows.erase(iter); } } mainIter->second.clear(); subWindowSessionMap_.erase(mainIter); } } WMError WindowSessionImpl::Destroy(bool needNotifyServer, bool needClearListener) { TLOGI(WmsLogTag::WMS_LIFE, "Id: %{public}d Destroy, state_:%{public}u, needNotifyServer: %{public}d, " "needClearListener: %{public}d", GetPersistentId(), state_, needNotifyServer, needClearListener); if (IsWindowSessionInvalid()) { WLOGFW("[WMSLife]session is invalid"); return WMError::WM_ERROR_INVALID_WINDOW; } { auto hostSession = GetHostSession(); if (hostSession != nullptr) { hostSession->Disconnect(); } } NotifyBeforeDestroy(GetWindowName()); { std::lock_guard lock(mutex_); state_ = WindowState::STATE_DESTROYED; requestState_ = WindowState::STATE_DESTROYED; } DestroySubWindow(); { std::lock_guard lock(hostSessionMutex_); hostSession_ = nullptr; } { std::unique_lock lock(windowSessionMutex_); windowSessionMap_.erase(property_->GetWindowName()); } NotifyAfterDestroy(); if (needClearListener) { ClearListenersById(GetPersistentId()); } if (context_) { context_.reset(); } ClearVsyncStation(); return WMError::WM_OK; } WMError WindowSessionImpl::Destroy() { return Destroy(true); } WSError WindowSessionImpl::SetActive(bool active) { WLOGFD("active status: %{public}d", active); if (active) { NotifyAfterActive(); } else { NotifyAfterInactive(); } return WSError::WS_OK; } WSError WindowSessionImpl::UpdateRect(const WSRect& rect, SizeChangeReason reason, const SceneAnimationConfig& config) { // delete after replace ws_common.h with wm_common.h auto wmReason = static_cast(reason); Rect wmRect = { rect.posX_, rect.posY_, rect.width_, rect.height_ }; auto preRect = GetRect(); if (preRect.width_ != wmRect.width_ || preRect.height_ != wmRect.height_) { windowSizeChanged_ = true; } property_->SetWindowRect(wmRect); property_->SetRequestRect(wmRect); TLOGI(WmsLogTag::WMS_LAYOUT, "%{public}s, preRect:%{public}s, reason:%{public}u, hasRSTransaction:%{public}d" ",duration:%{public}d, [name:%{public}s, id:%{public}d]", rect.ToString().c_str(), preRect.ToString().c_str(), wmReason, config.rsTransaction_ != nullptr, config.animationDuration_, GetWindowName().c_str(), GetPersistentId()); HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "WindowSessionImpl::UpdateRect id: %d [%d, %d, %u, %u] reason: %u hasRSTransaction: %u", GetPersistentId(), wmRect.posX_, wmRect.posY_, wmRect.width_, wmRect.height_, wmReason, config.rsTransaction_ != nullptr); if (handler_ != nullptr && wmReason == WindowSizeChangeReason::ROTATION) { postTaskDone_ = false; UpdateRectForRotation(wmRect, preRect, wmReason, config); } else { UpdateRectForOtherReason(wmRect, preRect, wmReason, config.rsTransaction_); } if (wmReason == WindowSizeChangeReason::MOVE || wmReason == WindowSizeChangeReason::RESIZE) { layoutCallback_->OnUpdateSessionRect(wmRect, wmReason, GetPersistentId()); } return WSError::WS_OK; } /** @note @window.layout */ void WindowSessionImpl::UpdateVirtualPixelRatio(const sptr& display) { if (display == nullptr) { TLOGE(WmsLogTag::WMS_LAYOUT, "display is null when rotation!"); return; } sptr displayInfo = display->GetDisplayInfo(); if (displayInfo == nullptr) { TLOGE(WmsLogTag::WMS_LAYOUT, "displayInfo is null when rotation!"); return; } virtualPixelRatio_ = GetVirtualPixelRatio(displayInfo); TLOGD(WmsLogTag::WMS_LAYOUT, "virtualPixelRatio: %{public}f", virtualPixelRatio_); } void WindowSessionImpl::UpdateRectForRotation(const Rect& wmRect, const Rect& preRect, WindowSizeChangeReason wmReason, const SceneAnimationConfig& config) { handler_->PostTask([weak = wptr(this), wmReason, wmRect, preRect, config]() mutable { HITRACE_METER_NAME(HITRACE_TAG_WINDOW_MANAGER, "WindowSessionImpl::UpdateRectForRotation"); auto window = weak.promote(); if (!window) { return; } auto display = SingletonContainer::Get().GetDisplayById(window->property_->GetDisplayId()); sptr displayInfo = display ? display->GetDisplayInfo() : nullptr; window->UpdateVirtualPixelRatio(display); const std::shared_ptr& rsTransaction = config.rsTransaction_; if (rsTransaction) { RSTransaction::FlushImplicitTransaction(); rsTransaction->Begin(); } window->rotationAnimationCount_++; RSAnimationTimingProtocol protocol; protocol.SetDuration(config.animationDuration_); // animation curve: cubic [0.2, 0.0, 0.2, 1.0] auto curve = RSAnimationTimingCurve::CreateCubicCurve(0.2, 0.0, 0.2, 1.0); RSNode::OpenImplicitAnimation(protocol, curve, [weak]() { auto window = weak.promote(); if (!window) { return; } window->rotationAnimationCount_--; if (window->rotationAnimationCount_ == 0) { window->NotifyRotationAnimationEnd(); } }); if ((wmRect != preRect) || (wmReason != window->lastSizeChangeReason_)) { window->NotifySizeChange(wmRect, wmReason); window->lastSizeChangeReason_ = wmReason; } window->UpdateViewportConfig(wmRect, wmReason, rsTransaction, displayInfo); RSNode::CloseImplicitAnimation(); if (rsTransaction) { rsTransaction->Commit(); } else { RSTransaction::FlushImplicitTransaction(); } window->postTaskDone_ = true; }, "WMS_WindowSessionImpl_UpdateRectForRotation"); } void WindowSessionImpl::UpdateRectForOtherReasonTask(const Rect& wmRect, const Rect& preRect, WindowSizeChangeReason wmReason, const std::shared_ptr& rsTransaction) { if ((wmRect != preRect) || (wmReason != lastSizeChangeReason_) || !postTaskDone_) { NotifySizeChange(wmRect, wmReason); lastSizeChangeReason_ = wmReason; postTaskDone_ = true; } UpdateViewportConfig(wmRect, wmReason, rsTransaction); UpdateFrameLayoutCallbackIfNeeded(wmReason); } void WindowSessionImpl::UpdateRectForOtherReason(const Rect& wmRect, const Rect& preRect, WindowSizeChangeReason wmReason, const std::shared_ptr& rsTransaction) { if (handler_ == nullptr) { UpdateRectForOtherReasonTask(wmRect, preRect, wmReason, rsTransaction); return; } auto task = [weak = wptr(this), wmReason, wmRect, preRect, rsTransaction] { auto window = weak.promote(); if (!window) { TLOGE(WmsLogTag::WMS_LAYOUT, "window is null, updateViewPortConfig failed"); return; } bool ifNeedCommitRsTransaction = CheckIfNeedCommitRsTransaction(wmReason); if (rsTransaction && ifNeedCommitRsTransaction) { RSTransaction::FlushImplicitTransaction(); rsTransaction->Begin(); } window->UpdateRectForOtherReasonTask(wmRect, preRect, wmReason, rsTransaction); if (rsTransaction && ifNeedCommitRsTransaction) { rsTransaction->Commit(); } }; handler_->PostTask(task, "WMS_WindowSessionImpl_UpdateRectForOtherReason"); } void WindowSessionImpl::NotifyRotationAnimationEnd() { auto task = [weak = wptr(this)] { auto window = weak.promote(); if (!window) { TLOGE(WmsLogTag::WMS_LAYOUT, "window is null"); return; } std::shared_ptr uiContent = window->GetUIContentSharedPtr(); if (uiContent == nullptr) { WLOGFW("uiContent is null!"); return; } uiContent->NotifyRotationAnimationEnd(); }; if (handler_ == nullptr) { TLOGW(WmsLogTag::WMS_LAYOUT, "handler is null!"); task(); } else { handler_->PostTask(task, "WMS_WindowSessionImpl_NotifyRotationAnimationEnd"); } } void WindowSessionImpl::FlushLayoutSize(int32_t width, int32_t height) { if (!WindowHelper::IsMainWindow(GetType())) { return; } WSRect rect = { 0, 0, width, height }; bool windowSizeChanged = true; bool enableFrameLayoutFinishCb = true; if (windowSizeChanged_.compare_exchange_strong(windowSizeChanged, false) || enableFrameLayoutFinishCb_.compare_exchange_strong(enableFrameLayoutFinishCb, false) || layoutRect_ != rect) { HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "NotifyFrameLayoutFinishFromApp, id: %u, rect: %s, notifyListener: %d", GetWindowId(), rect.ToString().c_str(), enableFrameLayoutFinishCb_.load()); TLOGI(WmsLogTag::WMS_LAYOUT, "NotifyFrameLayoutFinishFromApp, id: %{public}u, rect: %{public}s, notifyListener: %{public}d", GetWindowId(), rect.ToString().c_str(), enableFrameLayoutFinishCb_.load()); if (auto session = GetHostSession()) { session->NotifyFrameLayoutFinishFromApp(enableFrameLayoutFinishCb_, rect); } layoutRect_ = rect; enableFrameLayoutFinishCb_ = false; } } void WindowSessionImpl::GetTitleButtonVisible(bool& hideMaximizeButton, bool& hideMinimizeButton, bool& hideSplitButton, bool& hideCloseButton) { if (!IsPcOrPadFreeMultiWindowMode()) { TLOGE(WmsLogTag::WMS_LAYOUT, "device not support"); return; } if (hideMaximizeButton > !windowTitleVisibleFlags_.isMaximizeVisible) { TLOGW(WmsLogTag::WMS_LAYOUT, "isMaximizeVisible param INVALID"); } hideMaximizeButton = hideMaximizeButton || (!windowTitleVisibleFlags_.isMaximizeVisible); if (hideMinimizeButton > !windowTitleVisibleFlags_.isMinimizeVisible) { TLOGW(WmsLogTag::WMS_LAYOUT, "isMinimizeVisible param INVALID"); } hideMinimizeButton = hideMinimizeButton || (!windowTitleVisibleFlags_.isMinimizeVisible); if (hideSplitButton > !windowTitleVisibleFlags_.isSplitVisible) { TLOGW(WmsLogTag::WMS_LAYOUT, "isSplitVisible param INVALID"); } hideSplitButton = hideSplitButton || (!windowTitleVisibleFlags_.isSplitVisible); if (hideCloseButton > !windowTitleVisibleFlags_.isCloseVisible) { TLOGW(WmsLogTag::WMS_LAYOUT, "isCloseVisible param INVALID"); } hideCloseButton = hideCloseButton || (!windowTitleVisibleFlags_.isCloseVisible); } void WindowSessionImpl::UpdateDensity() { auto preRect = GetRect(); UpdateViewportConfig(preRect, WindowSizeChangeReason::UNDEFINED); WLOGFI("WindowSessionImpl::UpdateDensity [%{public}d, %{public}d, %{public}u, %{public}u]", preRect.posX_, preRect.posY_, preRect.width_, preRect.height_); } void WindowSessionImpl::SetUniqueVirtualPixelRatio(bool useUniqueDensity, float virtualPixelRatio) { TLOGI(WmsLogTag::DEFAULT, "old {useUniqueDensity: %{public}d, virtualPixelRatio: %{public}f}, "\ "new {useUniqueDensity: %{public}d, virtualPixelRatio: %{public}f}", useUniqueDensity_, virtualPixelRatio_, useUniqueDensity, virtualPixelRatio); bool oldUseUniqueDensity = useUniqueDensity_; useUniqueDensity_ = useUniqueDensity; if (useUniqueDensity_) { float oldVirtualPixelRatio = virtualPixelRatio_; virtualPixelRatio_ = virtualPixelRatio; if (!MathHelper::NearZero(oldVirtualPixelRatio - virtualPixelRatio)) { UpdateDensity(); SetUniqueVirtualPixelRatioForSub(useUniqueDensity, virtualPixelRatio); } } else { if (oldUseUniqueDensity) { UpdateDensity(); SetUniqueVirtualPixelRatioForSub(useUniqueDensity, virtualPixelRatio); } } } void WindowSessionImpl::CopyUniqueDensityParameter(sptr parentWindow) { if (parentWindow) { useUniqueDensity_ = parentWindow->useUniqueDensity_; virtualPixelRatio_ = parentWindow->virtualPixelRatio_; } } sptr WindowSessionImpl::FindMainWindowWithContext() { if (context_ == nullptr) { return nullptr; } std::shared_lock lock(windowSessionMutex_); for (const auto& winPair : windowSessionMap_) { auto win = winPair.second.second; if (win && win->GetType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW && context_.get() == win->GetContext().get()) { return win; } } WLOGFW("Can not find main window, not app type"); return nullptr; } sptr WindowSessionImpl::FindExtensionWindowWithContext() { if (context_ == nullptr) { return nullptr; } std::shared_lock lock(windowExtensionSessionMutex_); for (const auto& window : windowExtensionSessionSet_) { if (window && context_.get() == window->GetContext().get()) { return window; } } return nullptr; } void WindowSessionImpl::SetUniqueVirtualPixelRatioForSub(bool useUniqueDensity, float virtualPixelRatio) { if (subWindowSessionMap_.count(GetPersistentId()) == 0) { return; } for (auto& subWindowSession : subWindowSessionMap_.at(GetPersistentId())) { subWindowSession->SetUniqueVirtualPixelRatio(useUniqueDensity, virtualPixelRatio); } } WSError WindowSessionImpl::UpdateOrientation() { TLOGD(WmsLogTag::DMS, "UpdateOrientation, wid: %{public}d", GetPersistentId()); return WSError::WS_OK; } WSError WindowSessionImpl::UpdateDisplayId(uint64_t displayId) { property_->SetDisplayId(displayId); return WSError::WS_OK; } WSError WindowSessionImpl::UpdateFocus(bool isFocused) { TLOGI(WmsLogTag::WMS_FOCUS, "Report update focus: %{public}u, id: %{public}d", isFocused, GetPersistentId()); isFocused_ = isFocused; if (isFocused) { HiSysEventWrite( OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER, "FOCUS_WINDOW", OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "PID", getpid(), "UID", getuid(), "BUNDLE_NAME", property_->GetSessionInfo().bundleName_); NotifyAfterFocused(); } else { NotifyAfterUnfocused(); } return WSError::WS_OK; } bool WindowSessionImpl::IsFocused() const { if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::DEFAULT, "Session is invalid"); return false; } TLOGD(WmsLogTag::WMS_FOCUS, "window id = %{public}d, isFocused = %{public}d", GetPersistentId(), isFocused_.load()); return isFocused_; } WMError WindowSessionImpl::RequestFocus() const { if (IsWindowSessionInvalid()) { WLOGFD("session is invalid"); return WMError::WM_ERROR_INVALID_WINDOW; } return SingletonContainer::Get().RequestFocusStatus(GetPersistentId(), true); } /** @note @window.focus */ WMError WindowSessionImpl::RequestFocusByClient(bool isFocused) const { if (!SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::WMS_FOCUS, "permission denied!"); return WMError::WM_ERROR_NOT_SYSTEM_APP; } if (IsWindowSessionInvalid()) { TLOGD(WmsLogTag::WMS_FOCUS, "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); auto ret = hostSession->RequestFocus(isFocused); return static_cast(ret); } bool WindowSessionImpl::IsNotifyInteractiveDuplicative(bool interactive) { if (interactive == interactive_ && hasFirstNotifyInteractive_) { return true; } hasFirstNotifyInteractive_ = true; if (interactive_ != interactive) { interactive_ = interactive; } return false; } void WindowSessionImpl::NotifyForegroundInteractiveStatus(bool interactive) { WLOGFI("NotifyForegroundInteractiveStatus %{public}d", interactive); if (IsWindowSessionInvalid() || state_ != WindowState::STATE_SHOWN) { return; } if (IsNotifyInteractiveDuplicative(interactive)) { return; } if (interactive) { NotifyAfterResumed(); } else { NotifyAfterPaused(); } } WSError WindowSessionImpl::UpdateWindowMode(WindowMode mode) { return WSError::WS_OK; } /** @note @window.layout */ float WindowSessionImpl::GetVirtualPixelRatio() { TLOGD(WmsLogTag::WMS_LAYOUT, "virtualPixelRatio: %{public}f", virtualPixelRatio_); return virtualPixelRatio_; } float WindowSessionImpl::GetVirtualPixelRatio(sptr displayInfo) { if (useUniqueDensity_) { return virtualPixelRatio_; } return displayInfo->GetVirtualPixelRatio(); } void WindowSessionImpl::UpdateViewportConfig(const Rect& rect, WindowSizeChangeReason reason, const std::shared_ptr& rsTransaction, const sptr& info, const std::map& avoidAreas) { sptr displayInfo; if (info == nullptr) { auto display = SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); if (display == nullptr) { WLOGFE("display is null!"); return; } displayInfo = display->GetDisplayInfo(); } else { displayInfo = info; } if (displayInfo == nullptr) { WLOGFE("displayInfo is null!"); return; } if (rect.width_ <= 0 || rect.height_ <= 0) { TLOGW(WmsLogTag::WMS_LAYOUT, "invalid width: %{public}d, height: %{public}d, id: %{public}d", rect.width_, rect.height_, GetPersistentId()); return; } auto rotation = ONE_FOURTH_FULL_CIRCLE_DEGREE * static_cast(displayInfo->GetRotation()); auto deviceRotation = static_cast(displayInfo->GetDefaultDeviceRotationOffset()); uint32_t transformHint = (rotation + deviceRotation) % FULL_CIRCLE_DEGREE; float density = GetVirtualPixelRatio(displayInfo); int32_t orientation = static_cast(displayInfo->GetDisplayOrientation()); virtualPixelRatio_ = density; TLOGI(WmsLogTag::WMS_LAYOUT, "[rotation,deviceRotation,transformHint,virtualPixelRatio]:[%{public}u," "%{public}u,%{public}u,%{public}f]", rotation, deviceRotation, transformHint, virtualPixelRatio_); auto config = FillViewportConfig(rect, density, orientation, transformHint); std::map avoidAreasToUpdate; if (reason == WindowSizeChangeReason::ROTATION) { if (auto hostSession = GetHostSession()) { hostSession->GetAllAvoidAreas(avoidAreasToUpdate); } } else { avoidAreasToUpdate = avoidAreas; } for (const auto& [type, avoidArea] : avoidAreasToUpdate) { TLOGD(WmsLogTag::WMS_IMMS, "avoid type %{public}u area %{public}s", type, avoidArea.ToString().c_str()); } { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { WLOGFW("uiContent is null!"); return; } uiContent->UpdateViewportConfig(config, reason, rsTransaction, avoidAreasToUpdate); } if (WindowHelper::IsUIExtensionWindow(GetType())) { TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d reason:%{public}d windowRect:[%{public}d,%{public}d," "%{public}u,%{public}u] displayOrientation:%{public}d", GetPersistentId(), reason, rect.posX_, rect.posY_, rect.width_, rect.height_, orientation); } else { TLOGI(WmsLogTag::WMS_LAYOUT, "Id:%{public}d reason:%{public}d windowRect:[%{public}d,%{public}d," "%{public}u,%{public}u] displayOrientation:%{public}d", GetPersistentId(), reason, rect.posX_, rect.posY_, rect.width_, rect.height_, orientation); } } int32_t WindowSessionImpl::GetFloatingWindowParentId() { if (context_.get() == nullptr) { return INVALID_SESSION_ID; } std::shared_lock lock(windowSessionMutex_); for (const auto& winPair : windowSessionMap_) { if (winPair.second.second && WindowHelper::IsMainWindow(winPair.second.second->GetType()) && winPair.second.second->GetProperty() && context_.get() == winPair.second.second->GetContext().get()) { WLOGFD("Find parent, [parentName: %{public}s, selfPersistentId: %{public}d]", winPair.second.second->GetProperty()->GetWindowName().c_str(), GetPersistentId()); return winPair.second.second->GetProperty()->GetPersistentId(); } } return INVALID_SESSION_ID; } Rect WindowSessionImpl::GetRect() const { return property_->GetWindowRect(); } void WindowSessionImpl::UpdateTitleButtonVisibility() { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr || !IsDecorEnable()) { return; } WindowType windowType = GetType(); bool isSubWindow = WindowHelper::IsSubWindow(windowType); bool isDialogWindow = WindowHelper::IsDialogWindow(windowType); if (IsPcOrPadCapabilityEnabled() && (isSubWindow || isDialogWindow)) { WLOGFD("hide other buttons except close"); uiContent->HideWindowTitleButton(true, true, true, false); return; } auto windowModeSupportType = property_->GetWindowModeSupportType(); bool hideSplitButton = !(windowModeSupportType & WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY); // not support fullscreen in split and floating mode, or not support float in fullscreen mode bool hideMaximizeButton = (!(windowModeSupportType & WindowModeSupport::WINDOW_MODE_SUPPORT_FULLSCREEN) && (GetMode() == WindowMode::WINDOW_MODE_FLOATING || WindowHelper::IsSplitWindowMode(GetMode()))) || (!(windowModeSupportType & WindowModeSupport::WINDOW_MODE_SUPPORT_FLOATING) && GetMode() == WindowMode::WINDOW_MODE_FULLSCREEN); bool hideMinimizeButton = false; bool hideCloseButton = false; GetTitleButtonVisible(hideMaximizeButton, hideMinimizeButton, hideSplitButton, hideCloseButton); TLOGI(WmsLogTag::WMS_LAYOUT, "[hideSplit, hideMaximize, hideMinimizeButton, hideCloseButton]:" "[%{public}d, %{public}d, %{public}d, %{public}d]", hideSplitButton, hideMaximizeButton, hideMinimizeButton, hideCloseButton); if (property_->GetCompatibleModeInPc()) { if (IsFreeMultiWindowMode()) { uiContent->HideWindowTitleButton(true, hideMaximizeButton, hideMinimizeButton, hideCloseButton); } else { uiContent->HideWindowTitleButton(hideSplitButton, true, hideMinimizeButton, hideCloseButton); } } else { uiContent->HideWindowTitleButton(hideSplitButton, hideMaximizeButton, hideMinimizeButton, hideCloseButton); } } WMError WindowSessionImpl::NapiSetUIContent(const std::string& contentInfo, napi_env env, napi_value storage, BackupAndRestoreType type, sptr token, AppExecFwk::Ability* ability) { return SetUIContentInner(contentInfo, env, storage, type == BackupAndRestoreType::NONE ? WindowSetUIContentType::DEFAULT : WindowSetUIContentType::RESTORE, type, ability); } WMError WindowSessionImpl::SetUIContentByName( const std::string& contentInfo, napi_env env, napi_value storage, AppExecFwk::Ability* ability) { return SetUIContentInner(contentInfo, env, storage, WindowSetUIContentType::BY_NAME, BackupAndRestoreType::NONE, ability); } WMError WindowSessionImpl::SetUIContentByAbc( const std::string& contentInfo, napi_env env, napi_value storage, AppExecFwk::Ability* ability) { return SetUIContentInner(contentInfo, env, storage, WindowSetUIContentType::BY_ABC, BackupAndRestoreType::NONE, ability); } void WindowSessionImpl::DestroyExistUIContent() { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent) { uiContent->Destroy(); } } WMError WindowSessionImpl::InitUIContent(const std::string& contentInfo, napi_env env, napi_value storage, WindowSetUIContentType setUIContentType, BackupAndRestoreType restoreType, AppExecFwk::Ability* ability, OHOS::Ace::UIContentErrorCode& aceRet) { DestroyExistUIContent(); std::unique_ptr uiContent = ability != nullptr ? Ace::UIContent::Create(ability) : Ace::UIContent::Create(context_.get(), reinterpret_cast(env)); if (uiContent == nullptr) { TLOGE(WmsLogTag::WMS_LIFE, "fail to NapiSetUIContent id: %{public}d", GetPersistentId()); return WMError::WM_ERROR_NULLPTR; } switch (setUIContentType) { default: case WindowSetUIContentType::DEFAULT: { if (isUIExtensionAbilityProcess_ && property_->GetExtensionFlag() == true) { // subWindow created by UIExtensionAbility uiContent->SetUIExtensionSubWindow(true); uiContent->SetUIExtensionAbilityProcess(true); } else { auto routerStack = GetRestoredRouterStack(); auto type = GetAceContentInfoType(BackupAndRestoreType::RESOURCESCHEDULE_RECOVERY); if (!routerStack.empty() && uiContent->Restore(this, routerStack, storage, type) == Ace::UIContentErrorCode::NO_ERRORS) { TLOGI(WmsLogTag::WMS_LIFE, "Restore router stack succeed."); break; } } aceRet = uiContent->Initialize(this, contentInfo, storage); break; } case WindowSetUIContentType::RESTORE: aceRet = uiContent->Restore(this, contentInfo, storage, GetAceContentInfoType(restoreType)); break; case WindowSetUIContentType::BY_NAME: aceRet = uiContent->InitializeByName(this, contentInfo, storage); break; case WindowSetUIContentType::BY_ABC: auto abcContent = GetAbcContent(contentInfo); aceRet = uiContent->Initialize(this, abcContent, storage, contentInfo); break; } // make uiContent available after Initialize/Restore { std::unique_lock lock(uiContentMutex_); uiContent_ = std::move(uiContent); WLOGFI("UIContent Initialize, isUIExtensionSubWindow:%{public}d, isUIExtensionAbilityProcess:%{public}d", uiContent_->IsUIExtensionSubWindow(), uiContent_->IsUIExtensionAbilityProcess()); } return WMError::WM_OK; } WMError WindowSessionImpl::SetUIContentInner(const std::string& contentInfo, napi_env env, napi_value storage, WindowSetUIContentType setUIContentType, BackupAndRestoreType restoreType, AppExecFwk::Ability* ability) { TLOGD(WmsLogTag::WMS_LIFE, "NapiSetUIContent: %{public}s state:%{public}u", contentInfo.c_str(), state_); if (IsWindowSessionInvalid()) { WLOGFE("[WMSLife]interrupt set uicontent because window is invalid! window state: %{public}d", state_); return WMError::WM_ERROR_INVALID_WINDOW; } NotifySetUIContentComplete(); OHOS::Ace::UIContentErrorCode aceRet = OHOS::Ace::UIContentErrorCode::NO_ERRORS; WMError initUIContentRet = InitUIContent(contentInfo, env, storage, setUIContentType, restoreType, ability, aceRet); if (initUIContentRet != WMError::WM_OK) { TLOGE(WmsLogTag::WMS_LIFE, "Init UIContent fail, ret:%{public}u", initUIContentRet); return initUIContentRet; } WindowType winType = GetType(); bool isSubWindow = WindowHelper::IsSubWindow(winType); bool isDialogWindow = WindowHelper::IsDialogWindow(winType); if (IsDecorEnable()) { if (isSubWindow) { SetAPPWindowLabel(subWindowTitle_); } else if (isDialogWindow) { SetAPPWindowLabel(dialogTitle_); } } AppForceLandscapeConfig config = {}; if (WindowHelper::IsMainWindow(winType) && GetAppForceLandscapeConfig(config) == WMError::WM_OK && config.mode_ == FORCE_SPLIT_MODE) { SetForceSplitEnable(true, config.homePage_); } uint32_t version = 0; if ((context_ != nullptr) && (context_->GetApplicationInfo() != nullptr)) { version = context_->GetApplicationInfo()->apiCompatibleVersion; } // 10 ArkUI new framework support after API10 if (version < 10) { SetLayoutFullScreenByApiVersion(isIgnoreSafeArea_); if (!isSystembarPropertiesSet_) { SetSystemBarProperty(WindowType::WINDOW_TYPE_STATUS_BAR, SystemBarProperty()); } } else if (isIgnoreSafeAreaNeedNotify_) { SetLayoutFullScreenByApiVersion(isIgnoreSafeArea_); } else if (isSubWindow) { SetLayoutFullScreenByApiVersion(isIgnoreSafeArea_); isIgnoreSafeAreaNeedNotify_ = false; } // UIContent may be nullptr on setting system bar properties, need to set menubar color on UIContent init. if (auto uiContent = GetUIContentSharedPtr()) { auto property = GetSystemBarPropertyByType(WindowType::WINDOW_TYPE_STATUS_BAR); uiContent->SetStatusBarItemColor(property.contentColor_); } UpdateDecorEnable(true); if (state_ == WindowState::STATE_SHOWN) { // UIContent may be nullptr when show window, need to notify again when window is shown { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { uiContent->Foreground(); } } UpdateTitleButtonVisibility(); } UpdateViewportConfig(GetRect(), WindowSizeChangeReason::UNDEFINED); if (shouldReNotifyFocus_) { // uiContent may be nullptr when notify focus status, need to notify again when uiContent is not empty. NotifyUIContentFocusStatus(); shouldReNotifyFocus_ = false; } if (aceRet != OHOS::Ace::UIContentErrorCode::NO_ERRORS) { WLOGFE("failed to init or restore uicontent with file %{public}s. errorCode: %{public}d", contentInfo.c_str(), static_cast(aceRet)); return WMError::WM_ERROR_INVALID_PARAM; } TLOGD(WmsLogTag::WMS_LIFE, "notify uiContent window size change end"); return WMError::WM_OK; } std::shared_ptr> WindowSessionImpl::GetAbcContent(const std::string& abcPath) { std::filesystem::path abcFile { abcPath }; if (abcFile.empty() || !abcFile.is_absolute() || !std::filesystem::exists(abcFile)) { WLOGFE("abc file path is not valid"); return nullptr; } int begin, end; std::fstream file(abcFile, std::ios::in | std::ios::binary); if (!file) { WLOGFE("abc file is not valid"); return nullptr; } begin = file.tellg(); file.seekg(0, std::ios::end); end = file.tellg(); int len = end - begin; WLOGFD("abc file: %{public}s, size: %{public}d", abcPath.c_str(), len); if (len <= 0) { WLOGFE("abc file size is 0"); return nullptr; } std::vector abcBytes(len); file.seekg(0, std::ios::beg); file.read(reinterpret_cast(abcBytes.data()), len); return std::make_shared>(abcBytes); } void WindowSessionImpl::UpdateDecorEnableToAce(bool isDecorEnable) { { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { WindowMode mode = GetMode(); bool decorVisible = mode == WindowMode::WINDOW_MODE_FLOATING || mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY || (mode == WindowMode::WINDOW_MODE_FULLSCREEN && !property_->IsLayoutFullScreen()); WLOGFD("[WSLayout]Notify uiContent window mode change end,decorVisible:%{public}d", decorVisible); if (windowSystemConfig_.freeMultiWindowSupport_) { auto isSubWindow = WindowHelper::IsSubWindow(GetType()); decorVisible = decorVisible && ((property_->GetIsPcAppInPad() && isSubWindow) || (windowSystemConfig_.freeMultiWindowEnable_ && mode != WindowMode::WINDOW_MODE_FULLSCREEN)); } uiContent->UpdateDecorVisible(decorVisible, isDecorEnable); return; } } std::lock_guard lockListener(windowChangeListenerMutex_); auto windowChangeListeners = GetListeners(); for (auto& listener : windowChangeListeners) { if (listener.GetRefPtr() != nullptr) { listener.GetRefPtr()->OnModeChange(GetMode(), isDecorEnable); } } } void WindowSessionImpl::UpdateDecorEnable(bool needNotify, WindowMode mode) { if (mode == WindowMode::WINDOW_MODE_UNDEFINED) { mode = GetMode(); } if (needNotify) { { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { bool decorVisible = mode == WindowMode::WINDOW_MODE_FLOATING || mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY || (mode == WindowMode::WINDOW_MODE_FULLSCREEN && !property_->IsLayoutFullScreen()); if (windowSystemConfig_.freeMultiWindowSupport_) { auto isSubWindow = WindowHelper::IsSubWindow(GetType()); decorVisible = decorVisible && ((property_->GetIsPcAppInPad() && isSubWindow) || (windowSystemConfig_.freeMultiWindowEnable_ && mode != WindowMode::WINDOW_MODE_FULLSCREEN)); } WLOGFD("[WSLayout]Notify uiContent window mode change end,decorVisible:%{public}d", decorVisible); uiContent->UpdateDecorVisible(decorVisible, IsDecorEnable()); } } NotifyModeChange(mode, IsDecorEnable()); } } void WindowSessionImpl::NotifyModeChange(WindowMode mode, bool hasDeco) { { std::lock_guard lockListener(windowChangeListenerMutex_); auto windowChangeListeners = GetListeners(); for (auto& listener : windowChangeListeners) { if (listener.GetRefPtr() != nullptr) { listener.GetRefPtr()->OnModeChange(mode, hasDeco); } } } if (GetHostSession()) { property_->SetWindowMode(mode); property_->SetDecorEnable(hasDeco); } UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_MODE); UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_DECOR_ENABLE); } std::shared_ptr WindowSessionImpl::GetSurfaceNode() const { TLOGI(WmsLogTag::DEFAULT, "name:%{public}s, id:%{public}d", property_->GetWindowName().c_str(), GetPersistentId()); return surfaceNode_; } const std::shared_ptr WindowSessionImpl::GetContext() const { TLOGI(WmsLogTag::DEFAULT, "name:%{public}s, id:%{public}d", property_->GetWindowName().c_str(), GetPersistentId()); return context_; } Rect WindowSessionImpl::GetRequestRect() const { return property_->GetRequestRect(); } WindowType WindowSessionImpl::GetType() const { return property_->GetWindowType(); } const std::string& WindowSessionImpl::GetWindowName() const { return property_->GetWindowName(); } WindowState WindowSessionImpl::GetWindowState() const { return state_; } WindowState WindowSessionImpl::GetRequestWindowState() const { return requestState_; } WMError WindowSessionImpl::SetFocusable(bool isFocusable) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } TLOGI(WmsLogTag::WMS_FOCUS, "set focusable: windowId = %{public}d, isFocusable = %{public}d", property_->GetPersistentId(), isFocusable); property_->SetFocusable(isFocusable); return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_FOCUSABLE); } bool WindowSessionImpl::GetFocusable() const { bool isFocusable = property_->GetFocusable(); TLOGD(WmsLogTag::WMS_FOCUS, "get focusable: windowId = %{public}d, isFocusable = %{public}d", property_->GetPersistentId(), isFocusable); return isFocusable; } WMError WindowSessionImpl::SetTouchable(bool isTouchable) { WLOGFD("set touchable"); if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } property_->SetTouchable(isTouchable); return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_TOUCHABLE); } /** @note @window.hierarchy */ WMError WindowSessionImpl::SetTopmost(bool topmost) { TLOGD(WmsLogTag::WMS_LAYOUT, "set topmost"); auto isPC = windowSystemConfig_.uiType_ == UI_TYPE_PC; if (!isPC) { return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } property_->SetTopmost(topmost); return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_TOPMOST); } /** @note @window.hierarchy */ bool WindowSessionImpl::IsTopmost() const { return property_->IsTopmost(); } /** @note @window.hierarchy */ WMError WindowSessionImpl::SetMainWindowTopmost(bool isTopmost) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } if (!IsPcOrPadFreeMultiWindowMode()) { TLOGE(WmsLogTag::WMS_HIERARCHY, "device not support"); return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } if (!WindowHelper::IsMainWindow(GetType())) { TLOGE(WmsLogTag::WMS_HIERARCHY, "window type is not supported"); return WMError::WM_ERROR_INVALID_CALLING; } property_->SetMainWindowTopmost(isTopmost); uint32_t accessTokenId = static_cast(IPCSkeleton::GetCallingTokenID()); property_->SetAccessTokenId(accessTokenId); TLOGD(WmsLogTag::WMS_HIERARCHY, "tokenId=%{private}u, isTopmost=%{public}d", accessTokenId, isTopmost); return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_MAIN_WINDOW_TOPMOST); } bool WindowSessionImpl::IsMainWindowTopmost() const { return property_->IsMainWindowTopmost(); } WMError WindowSessionImpl::SetResizeByDragEnabled(bool dragEnabled) { TLOGD(WmsLogTag::DEFAULT, "%{public}d", dragEnabled); if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::DEFAULT, "Session is invalid"); return WMError::WM_ERROR_INVALID_WINDOW; } if (WindowHelper::IsMainWindow(GetType()) || (WindowHelper::IsSubWindow(GetType()) && windowOption_->GetSubWindowDecorEnable())) { property_->SetDragEnabled(dragEnabled); } else { TLOGE(WmsLogTag::DEFAULT, "This is not main window or decor enabled sub window."); return WMError::WM_ERROR_INVALID_TYPE; } return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_DRAGENABLED); } /** @note @window.hierarchy */ WMError WindowSessionImpl::SetRaiseByClickEnabled(bool raiseEnabled) { WLOGFD("%{public}d", raiseEnabled); auto parentId = GetParentId(); if (parentId == INVALID_SESSION_ID) { TLOGE(WmsLogTag::WMS_HIERARCHY, "Window id: %{public}d Parent id is invalid!", GetPersistentId()); return WMError::WM_ERROR_INVALID_PARENT; } if (!WindowHelper::IsSubWindow(GetType())) { TLOGE(WmsLogTag::WMS_HIERARCHY, "Window id: %{public}d Must be app sub window!", GetPersistentId()); return WMError::WM_ERROR_INVALID_CALLING; } if (state_ != WindowState::STATE_SHOWN) { TLOGE(WmsLogTag::WMS_HIERARCHY, "Window id: %{public}d The sub window must be shown!", GetPersistentId()); return WMError::WM_DO_NOTHING; } if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } property_->SetRaiseEnabled(raiseEnabled); return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_RAISEENABLED); } WMError WindowSessionImpl::HideNonSystemFloatingWindows(bool shouldHide) { WLOGFD("hide non-system floating windows"); if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } property_->SetHideNonSystemFloatingWindows(shouldHide); return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_HIDE_NON_SYSTEM_FLOATING_WINDOWS); } WMError WindowSessionImpl::SetLandscapeMultiWindow(bool isLandscapeMultiWindow) { TLOGI(WmsLogTag::WMS_MULTI_WINDOW, "SetLandscapeMultiWindow, isLandscapeMultiWindow:%{public}d", isLandscapeMultiWindow); if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::WMS_MULTI_WINDOW, "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->SetLandscapeMultiWindow(isLandscapeMultiWindow); return WMError::WM_OK; } WMError WindowSessionImpl::SetSingleFrameComposerEnabled(bool enable) { WLOGFD("Set the enable flag of single frame composer."); if (IsWindowSessionInvalid()) { WLOGE("The window state is invalid "); return WMError::WM_ERROR_INVALID_WINDOW; } if (surfaceNode_ == nullptr) { WLOGE("The surface node is nullptr"); return WMError::WM_ERROR_INVALID_WINDOW; } surfaceNode_->MarkNodeSingleFrameComposer(enable); RSTransaction::FlushImplicitTransaction(); return WMError::WM_OK; } bool WindowSessionImpl::IsFloatingWindowAppType() const { if (IsWindowSessionInvalid()) { return false; } return property_ != nullptr && property_->IsFloatingWindowAppType(); } bool WindowSessionImpl::GetTouchable() const { return property_->GetTouchable(); } WMError WindowSessionImpl::SetWindowType(WindowType type) { TLOGD(WmsLogTag::DEFAULT, "SetWindowType %{public}u type %{public}u", GetWindowId(), static_cast(type)); if (type != WindowType::WINDOW_TYPE_SYSTEM_ALARM_WINDOW && !SessionPermission::IsSystemCalling()) { TLOGE(WmsLogTag::DEFAULT, "set window type permission denied!"); return WMError::WM_ERROR_NOT_SYSTEM_APP; } if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::DEFAULT, "Session is invalid"); return WMError::WM_ERROR_INVALID_WINDOW; } property_->SetWindowType(type); UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_OTHER_PROPS); return WMError::WM_OK; } WMError WindowSessionImpl::SetBrightness(float brightness) { if ((brightness < MINIMUM_BRIGHTNESS && std::fabs(brightness - UNDEFINED_BRIGHTNESS) >= std::numeric_limits::min()) || brightness > MAXIMUM_BRIGHTNESS) { TLOGE(WmsLogTag::DEFAULT, "invalid brightness value: %{public}f", brightness); return WMError::WM_ERROR_INVALID_PARAM; } if (!WindowHelper::IsAppWindow(GetType())) { TLOGE(WmsLogTag::DEFAULT, "non app window does not support set brightness, type: %{public}u", GetType()); return WMError::WM_ERROR_INVALID_TYPE; } if (!property_) { TLOGE(WmsLogTag::DEFAULT, "window property is not existed"); return WMError::WM_ERROR_NULLPTR; } property_->SetBrightness(brightness); return UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_SET_BRIGHTNESS); } float WindowSessionImpl::GetBrightness() const { return property_->GetBrightness(); } void WindowSessionImpl::SetRequestedOrientation(Orientation orientation) { if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::DEFAULT, "windowSession is invalid"); return; } TLOGI(WmsLogTag::WMS_MAIN, "id:%{public}u lastReqOrientation:%{public}u target:%{public}u state:%{public}u", GetPersistentId(), property_->GetRequestedOrientation(), orientation, state_); bool isUserOrientation = IsUserOrientation(orientation); if (property_->GetRequestedOrientation() == orientation && !isUserOrientation) { return; } property_->SetRequestedOrientation(orientation); UpdateProperty(WSPropertyChangeAction::ACTION_UPDATE_ORIENTATION); } Orientation WindowSessionImpl::GetRequestedOrientation() { if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::DEFAULT, "windowSession is invalid"); return Orientation::UNSPECIFIED; } return property_->GetRequestedOrientation(); } std::string WindowSessionImpl::GetContentInfo(BackupAndRestoreType type) { WLOGFD("GetContentInfo"); if (type == BackupAndRestoreType::NONE) { return ""; } std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { WLOGFE("fail to GetContentInfo id: %{public}d", GetPersistentId()); return ""; } return uiContent->GetContentInfo(GetAceContentInfoType(type)); } WMError WindowSessionImpl::SetRestoredRouterStack(const std::string& routerStack) { TLOGD(WmsLogTag::WMS_LIFE, "Set restored router stack."); restoredRouterStack_ = routerStack; return WMError::WM_OK; } std::string WindowSessionImpl::GetRestoredRouterStack() { TLOGD(WmsLogTag::WMS_LIFE, "Get restored router stack."); return std::move(restoredRouterStack_); } Ace::UIContent* WindowSessionImpl::GetUIContent() const { std::shared_lock lock(uiContentMutex_); return uiContent_.get(); } std::shared_ptr WindowSessionImpl::GetUIContentSharedPtr() const { std::shared_lock lock(uiContentMutex_); return uiContent_; } Ace::UIContent* WindowSessionImpl::GetUIContentWithId(uint32_t winId) const { sptr targetWindow = FindWindowById(winId); if (targetWindow == nullptr) { WLOGE("target window is null"); return nullptr; } return targetWindow->GetUIContent(); } void WindowSessionImpl::OnNewWant(const AAFwk::Want& want) { WLOGFI("Window [name:%{public}s, id:%{public}d]", property_->GetWindowName().c_str(), GetPersistentId()); std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { uiContent->OnNewWant(want); } } WMError WindowSessionImpl::SetAPPWindowLabel(const std::string& label) { TLOGI(WmsLogTag::DEFAULT, "Enter"); std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { WLOGFE("uicontent is empty"); return WMError::WM_ERROR_NULLPTR; } uiContent->SetAppWindowTitle(label); return WMError::WM_OK; } WMError WindowSessionImpl::SetAPPWindowIcon(const std::shared_ptr& icon) { if (icon == nullptr) { WLOGFE("window icon is empty"); return WMError::WM_ERROR_NULLPTR; } std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { WLOGFE("uicontent is empty"); return WMError::WM_ERROR_NULLPTR; } uiContent->SetAppWindowIcon(icon); WLOGI("Set app window icon success"); return WMError::WM_OK; } WMError WindowSessionImpl::RegisterLifeCycleListener(const sptr& listener) { WLOGFD("Start register"); std::lock_guard lockListener(lifeCycleListenerMutex_); return RegisterListener(lifecycleListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::RegisterDisplayMoveListener(sptr& listener) { WLOGFD("Start register"); std::lock_guard lockListener(displayMoveListenerMutex_); return RegisterListener(displayMoveListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::UnregisterDisplayMoveListener(sptr& listener) { WLOGFD("Start unregister"); std::lock_guard lockListener(displayMoveListenerMutex_); return UnregisterListener(displayMoveListeners_[GetPersistentId()], listener); } /** * Currently only supports system windows. */ WMError WindowSessionImpl::EnableDrag(bool enableDrag) { bool isPC = windowSystemConfig_.uiType_ == UI_TYPE_PC; if (!isPC && !IsFreeMultiWindowMode()) { TLOGE(WmsLogTag::WMS_LAYOUT, "The device is not supported"); return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } property_->SetDragEnabled(enableDrag); auto hostSession = GetHostSession(); CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW); WMError errorCode = hostSession->SetSystemWindowEnableDrag(enableDrag); TLOGI(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, enableDrag:%{public}d, errcode:%{public}d", GetPersistentId(), enableDrag, static_cast(errorCode)); return static_cast(errorCode); } WMError WindowSessionImpl::RegisterOccupiedAreaChangeListener(const sptr& listener) { WLOGFD("Start register"); std::lock_guard lockListener(occupiedAreaChangeListenerMutex_); return RegisterListener(occupiedAreaChangeListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::UnregisterOccupiedAreaChangeListener(const sptr& listener) { WLOGFD("Start unregister"); std::lock_guard lockListener(occupiedAreaChangeListenerMutex_); return UnregisterListener(occupiedAreaChangeListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::UnregisterLifeCycleListener(const sptr& listener) { WLOGFD("Start unregister"); std::lock_guard lockListener(lifeCycleListenerMutex_); return UnregisterListener(lifecycleListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::RegisterWindowChangeListener(const sptr& listener) { WLOGFD("Start register"); std::lock_guard lockListener(windowChangeListenerMutex_); return RegisterListener(windowChangeListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::UnregisterWindowChangeListener(const sptr& listener) { WLOGFD("Start register"); std::lock_guard lockListener(windowChangeListenerMutex_); return UnregisterListener(windowChangeListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::RegisterWindowStatusChangeListener(const sptr& listener) { WLOGFD("Start register"); std::lock_guard lockListener(windowStatusChangeListenerMutex_); return RegisterListener(windowStatusChangeListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::UnregisterWindowStatusChangeListener(const sptr& listener) { WLOGFD("Start register"); std::lock_guard lockListener(windowStatusChangeListenerMutex_); return UnregisterListener(windowStatusChangeListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::SetDecorVisible(bool isVisible) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { WLOGFE("uicontent is empty"); return WMError::WM_ERROR_NULLPTR; } uiContent->SetContainerModalTitleVisible(isVisible, true); WLOGI("Change the visibility of decor success"); return WMError::WM_OK; } WMError WindowSessionImpl::SetWindowTitleMoveEnabled(bool enable) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } if (!IsPcOrPadFreeMultiWindowMode()) { TLOGE(WmsLogTag::WMS_LAYOUT, "The device is not supported"); return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } if (!WindowHelper::IsMainWindow(GetType()) && !WindowHelper::IsSubWindow(GetType())) { TLOGE(WmsLogTag::WMS_LAYOUT, "called by invalid window type, type:%{public}d", GetType()); return WMError::WM_ERROR_INVALID_CALLING; } std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { TLOGE(WmsLogTag::WMS_LAYOUT, "uicontent is null"); return WMError::WM_ERROR_NULLPTR; } uiContent->EnableContainerModalGesture(enable); TLOGI(WmsLogTag::WMS_LAYOUT, "enable:%{public}d end", enable); return WMError::WM_OK; } WMError WindowSessionImpl::SetSubWindowModal(bool isModal, ModalityType modalityType) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } if (!WindowHelper::IsSubWindow(GetType())) { TLOGE(WmsLogTag::WMS_SUB, "called by invalid window type, type:%{public}d", GetType()); return WMError::WM_ERROR_INVALID_CALLING; } if (modalityType == ModalityType::APPLICATION_MODALITY && !IsPcOrPadFreeMultiWindowMode()) { TLOGE(WmsLogTag::WMS_SUB, "device not support"); return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } WMError modalRet = isModal ? AddWindowFlag(WindowFlag::WINDOW_FLAG_IS_MODAL) : RemoveWindowFlag(WindowFlag::WINDOW_FLAG_IS_MODAL); if (modalRet != WMError::WM_OK) { return modalRet; } modalRet = isModal && modalityType == ModalityType::APPLICATION_MODALITY ? AddWindowFlag(WindowFlag::WINDOW_FLAG_IS_APPLICATION_MODAL) : RemoveWindowFlag(WindowFlag::WINDOW_FLAG_IS_APPLICATION_MODAL); auto hostSession = GetHostSession(); CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_INVALID_WINDOW); SubWindowModalType subWindowModalType = SubWindowModalType::TYPE_NORMAL; if (isModal) { subWindowModalType = modalityType == ModalityType::WINDOW_MODALITY ? SubWindowModalType::TYPE_WINDOW_MODALITY : SubWindowModalType::TYPE_APPLICATION_MODALITY; } hostSession->NotifySubModalTypeChange(subWindowModalType); return modalRet; } WMError WindowSessionImpl::SetWindowModal(bool isModal) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } if (!IsPcOrPadFreeMultiWindowMode()) { TLOGE(WmsLogTag::WMS_MAIN, "device not support"); return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } if (!WindowHelper::IsMainWindow(GetType())) { TLOGE(WmsLogTag::WMS_MAIN, "called by invalid window type, type:%{public}d", GetType()); return WMError::WM_ERROR_INVALID_CALLING; } WMError modalRet = isModal ? AddWindowFlag(WindowFlag::WINDOW_FLAG_IS_MODAL) : RemoveWindowFlag(WindowFlag::WINDOW_FLAG_IS_MODAL); if (modalRet != WMError::WM_OK) { return modalRet; } auto hostSession = GetHostSession(); CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WMError::WM_ERROR_SYSTEM_ABNORMALLY); hostSession->NotifyMainModalTypeChange(isModal); return modalRet; } WMError WindowSessionImpl::SetDecorHeight(int32_t decorHeight) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } auto display = SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); if (display == nullptr) { WLOGFE("get display failed displayId:%{public}" PRIu64, property_->GetDisplayId()); return WMError::WM_ERROR_NULLPTR; } auto displayInfo = display->GetDisplayInfo(); if (displayInfo == nullptr) { WLOGFE("get display info failed displayId:%{public}" PRIu64, property_->GetDisplayId()); return WMError::WM_ERROR_NULLPTR; } float vpr = GetVirtualPixelRatio(displayInfo); int32_t decorHeightWithPx = static_cast(decorHeight * vpr); { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { WLOGFE("uicontent is empty"); return WMError::WM_ERROR_NULLPTR; } uiContent->SetContainerModalTitleHeight(decorHeightWithPx); } auto hostSession = GetHostSession(); if (hostSession != nullptr) { hostSession->SetCustomDecorHeight(decorHeight); } WLOGI("Set app window decor height success, height : %{public}d", decorHeight); return WMError::WM_OK; } WMError WindowSessionImpl::GetDecorHeight(int32_t& height) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { WLOGFE("uiContent is nullptr, windowId: %{public}u", GetWindowId()); return WMError::WM_ERROR_NULLPTR; } height = uiContent->GetContainerModalTitleHeight(); } if (height == -1) { height = 0; WLOGFE("Get app window decor height failed"); return WMError::WM_OK; } auto display = SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); if (display == nullptr) { WLOGFE("get display failed displayId:%{public}" PRIu64, property_->GetDisplayId()); return WMError::WM_ERROR_NULLPTR; } auto displayInfo = display->GetDisplayInfo(); if (displayInfo == nullptr) { WLOGFE("get display info failed displayId:%{public}" PRIu64, property_->GetDisplayId()); return WMError::WM_ERROR_NULLPTR; } float vpr = GetVirtualPixelRatio(displayInfo); if (MathHelper::NearZero(vpr)) { WLOGFE("get decor height failed, because of wrong vpr: %{public}f", vpr); return WMError::WM_ERROR_INVALID_WINDOW; } height = static_cast(height / vpr); WLOGI("Get app window decor height success, height : %{public}d", height); return WMError::WM_OK; } WMError WindowSessionImpl::GetTitleButtonArea(TitleButtonRect& titleButtonRect) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } Rect decorRect; Rect titleButtonLeftRect; bool res = false; { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { WLOGFE("uicontent is empty"); return WMError::WM_ERROR_NULLPTR; } res = uiContent->GetContainerModalButtonsRect(decorRect, titleButtonLeftRect); } if (!res) { WLOGFE("get window title buttons area failed"); titleButtonRect.IsUninitializedRect(); return WMError::WM_OK; } auto display = SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); if (display == nullptr) { WLOGFE("get display failed displayId:%{public}" PRIu64, property_->GetDisplayId()); return WMError::WM_ERROR_NULLPTR; } auto displayInfo = display->GetDisplayInfo(); if (displayInfo == nullptr) { WLOGFE("get display info failed displayId:%{public}" PRIu64, property_->GetDisplayId()); return WMError::WM_ERROR_NULLPTR; } float vpr = GetVirtualPixelRatio(displayInfo); if (MathHelper::NearZero(vpr)) { WLOGFE("get title buttons area failed, because of wrong vpr: %{public}f", vpr); return WMError::WM_ERROR_INVALID_WINDOW; } titleButtonRect.posX_ = static_cast(decorRect.width_) - static_cast(titleButtonLeftRect.width_) - titleButtonLeftRect.posX_; titleButtonRect.posX_ = static_cast(titleButtonRect.posX_ / vpr); titleButtonRect.posY_ = static_cast(titleButtonLeftRect.posY_ / vpr); titleButtonRect.width_ = static_cast(titleButtonLeftRect.width_ / vpr); titleButtonRect.height_ = static_cast(titleButtonLeftRect.height_ / vpr); return WMError::WM_OK; } WSError WindowSessionImpl::GetUIContentRemoteObj(sptr& uiContentRemoteObj) { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { TLOGE(WmsLogTag::DEFAULT, "uiContent is nullptr. Failed to get uiContentRemoteObj"); return WSError::WS_ERROR_NULLPTR; } uiContentRemoteObj = uiContent->GetRemoteObj(); return WSError::WS_OK; } WMError WindowSessionImpl::RegisterWindowTitleButtonRectChangeListener( const sptr& listener) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } auto persistentId = GetPersistentId(); WLOGFD("Start register windowTitleButtonRectChange listener, id:%{public}d", persistentId); if (listener == nullptr) { WLOGFE("listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } { std::lock_guard lockListener(windowTitleButtonRectChangeListenerMutex_); WMError ret = RegisterListener(windowTitleButtonRectChangeListeners_[persistentId], listener); if (ret != WMError::WM_OK) { WLOGFE("register the listener of window title button rect change failed"); return ret; } } auto display = SingletonContainer::Get().GetDisplayById(property_->GetDisplayId()); if (display == nullptr) { WLOGFE("get display failed displayId:%{public}" PRIu64, property_->GetDisplayId()); return WMError::WM_ERROR_NULLPTR; } auto displayInfo = display->GetDisplayInfo(); if (displayInfo == nullptr) { WLOGFE("get display info failed displayId:%{public}" PRIu64, property_->GetDisplayId()); return WMError::WM_ERROR_NULLPTR; } float vpr = GetVirtualPixelRatio(displayInfo); if (MathHelper::NearZero(vpr)) { WLOGFE("register title button rect change listener failed, because of wrong vpr: %{public}f", vpr); return WMError::WM_ERROR_INVALID_WINDOW; } if (auto uiContent = GetUIContentSharedPtr()) { uiContent->SubscribeContainerModalButtonsRectChange( [vpr, weakThis = wptr(this)](Rect& decorRect, Rect& titleButtonLeftRect) { auto window = weakThis.promote(); if (!window) { TLOGNE(WmsLogTag::WMS_LAYOUT, "window is null"); return; } TitleButtonRect titleButtonRect; titleButtonRect.posX_ = static_cast(decorRect.width_) - static_cast(titleButtonLeftRect.width_) - titleButtonLeftRect.posX_; titleButtonRect.posX_ = static_cast(titleButtonRect.posX_ / vpr); titleButtonRect.posY_ = static_cast(titleButtonLeftRect.posY_ / vpr); titleButtonRect.width_ = static_cast(titleButtonLeftRect.width_ / vpr); titleButtonRect.height_ = static_cast(titleButtonLeftRect.height_ / vpr); window->NotifyWindowTitleButtonRectChange(titleButtonRect); }); } return WMError::WM_OK; } WMError WindowSessionImpl::UnregisterWindowTitleButtonRectChangeListener( const sptr& listener) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } WMError ret = WMError::WM_OK; auto persistentId = GetPersistentId(); WLOGFD("Start unregister windowTitleButtonRectChange listener, id:%{public}d", persistentId); if (listener == nullptr) { WLOGFE("listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } { std::lock_guard lockListener(windowTitleButtonRectChangeListenerMutex_); ret = UnregisterListener(windowTitleButtonRectChangeListeners_[persistentId], listener); if (ret != WMError::WM_OK) { WLOGFE("unregister the listener of window title button rect change failed"); return ret; } } std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { uiContent->SubscribeContainerModalButtonsRectChange(nullptr); } return ret; } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> windowTitleButtonRectListeners; for (auto& listener : windowTitleButtonRectChangeListeners_[GetPersistentId()]) { windowTitleButtonRectListeners.push_back(listener); } return windowTitleButtonRectListeners; } void WindowSessionImpl::NotifyWindowTitleButtonRectChange(TitleButtonRect titleButtonRect) { std::lock_guard lockListener(windowTitleButtonRectChangeListenerMutex_); auto windowTitleButtonRectListeners = GetListeners(); for (auto& listener : windowTitleButtonRectListeners) { if (listener != nullptr) { listener->OnWindowTitleButtonRectChanged(titleButtonRect); } } } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> windowRectChangeListeners; for (auto& listener : windowRectChangeListeners_[GetPersistentId()]) { windowRectChangeListeners.push_back(listener); } return windowRectChangeListeners; } WMError WindowSessionImpl::RegisterWindowRectChangeListener(const sptr& listener) { WMError ret = WMError::WM_OK; { std::lock_guard lockListener(windowRectChangeListenerMutex_); ret = RegisterListener(windowRectChangeListeners_[GetPersistentId()], listener); } auto hostSession = GetHostSession(); if (hostSession != nullptr && ret == WMError::WM_OK) { hostSession->UpdateRectChangeListenerRegistered(true); } return ret; } WMError WindowSessionImpl::UnregisterWindowRectChangeListener(const sptr& listener) { WMError ret = WMError::WM_OK; bool windowRectChangeListenersEmpty = false; { std::lock_guard lockListener(windowRectChangeListenerMutex_); ret = UnregisterListener(windowRectChangeListeners_[GetPersistentId()], listener); windowRectChangeListenersEmpty = windowRectChangeListeners_.count(GetPersistentId()) == 0 || windowRectChangeListeners_[GetPersistentId()].empty(); } auto hostSession = GetHostSession(); if (hostSession != nullptr && windowRectChangeListenersEmpty) { hostSession->UpdateRectChangeListenerRegistered(false); } return ret; } template EnableIfSame> WindowSessionImpl::GetListeners() { sptr subWindowCloseListeners; subWindowCloseListeners = subWindowCloseListeners_[GetPersistentId()]; return subWindowCloseListeners; } WMError WindowSessionImpl::RegisterSubWindowCloseListeners(const sptr& listener) { if (listener == nullptr) { WLOGFE("listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } if (!WindowHelper::IsSubWindow(GetType()) && !WindowHelper::IsSystemSubWindow(GetType())) { WLOGFE("window type is not supported"); return WMError::WM_ERROR_INVALID_CALLING; } std::lock_guard lockListener(subWindowCloseListenersMutex_); subWindowCloseListeners_[GetPersistentId()] = listener; return WMError::WM_OK; } WMError WindowSessionImpl::UnregisterSubWindowCloseListeners(const sptr& listener) { if (listener == nullptr) { WLOGFE("listener could not be null"); return WMError::WM_ERROR_NULLPTR; } if (!WindowHelper::IsSubWindow(GetType()) && !WindowHelper::IsSystemSubWindow(GetType())) { WLOGFE("window type is not supported"); return WMError::WM_ERROR_INVALID_CALLING; } std::lock_guard lockListener(subWindowCloseListenersMutex_); subWindowCloseListeners_[GetPersistentId()] = nullptr; return WMError::WM_OK; } template EnableIfSame> WindowSessionImpl::GetListeners() { return mainWindowCloseListeners_[GetPersistentId()]; } WMError WindowSessionImpl::RegisterMainWindowCloseListeners(const sptr& listener) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } if (listener == nullptr) { TLOGE(WmsLogTag::DEFAULT, "listener is null"); return WMError::WM_ERROR_NULLPTR; } if (!WindowHelper::IsMainWindow(GetType())) { TLOGE(WmsLogTag::DEFAULT, "window type is not supported"); return WMError::WM_ERROR_INVALID_CALLING; } auto isPC = windowSystemConfig_.uiType_ == UI_TYPE_PC; if (!(isPC|| IsFreeMultiWindowMode())) { TLOGE(WmsLogTag::DEFAULT, "The device is not supported"); return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } std::lock_guard lockListener(mainWindowCloseListenersMutex_); mainWindowCloseListeners_[GetPersistentId()] = listener; return WMError::WM_OK; } WMError WindowSessionImpl::UnregisterMainWindowCloseListeners(const sptr& listener) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } if (listener == nullptr) { TLOGE(WmsLogTag::DEFAULT, "listener could not be null"); return WMError::WM_ERROR_NULLPTR; } auto isPC = windowSystemConfig_.uiType_ == UI_TYPE_PC; if (!(isPC|| IsFreeMultiWindowMode())) { TLOGE(WmsLogTag::DEFAULT, "The device is not supported"); return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } if (!WindowHelper::IsMainWindow(GetType())) { TLOGE(WmsLogTag::DEFAULT, "window type is not supported"); return WMError::WM_ERROR_INVALID_CALLING; } std::lock_guard lockListener(mainWindowCloseListenersMutex_); mainWindowCloseListeners_[GetPersistentId()] = nullptr; return WMError::WM_OK; } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> switchFreeMultiWindowListeners; for (auto& listener : switchFreeMultiWindowListeners_[GetPersistentId()]) { switchFreeMultiWindowListeners.push_back(listener); } return switchFreeMultiWindowListeners; } WMError WindowSessionImpl::RegisterSwitchFreeMultiWindowListener(const sptr& listener) { if (listener == nullptr) { WLOGFE("listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } if (!WindowHelper::IsMainWindow(GetType())) { WLOGFE("window type is not supported"); return WMError::WM_ERROR_INVALID_CALLING; } WLOGFD("Start register"); std::lock_guard lockListener(switchFreeMultiWindowListenerMutex_); return RegisterListener(switchFreeMultiWindowListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::UnregisterSwitchFreeMultiWindowListener(const sptr& listener) { if (listener == nullptr) { WLOGFE("listener could not be null"); return WMError::WM_ERROR_NULLPTR; } if (!WindowHelper::IsMainWindow(GetType())) { WLOGFE("window type is not supported"); return WMError::WM_ERROR_INVALID_CALLING; } WLOGFD("Start unregister"); std::lock_guard lockListener(switchFreeMultiWindowListenerMutex_); return UnregisterListener(switchFreeMultiWindowListeners_[GetPersistentId()], listener); } void WindowSessionImpl::RecoverSessionListener() { auto persistentId = GetPersistentId(); TLOGI(WmsLogTag::WMS_RECOVER, "with persistentId=%{public}d", persistentId); { std::lock_guard lockListener(avoidAreaChangeListenerMutex_); if (avoidAreaChangeListeners_.find(persistentId) != avoidAreaChangeListeners_.end() && !avoidAreaChangeListeners_[persistentId].empty()) { SingletonContainer::Get().UpdateSessionAvoidAreaListener(persistentId, true); } } { std::lock_guard lockListener(touchOutsideListenerMutex_); if (touchOutsideListeners_.find(persistentId) != touchOutsideListeners_.end() && !touchOutsideListeners_[persistentId].empty()) { SingletonContainer::Get().UpdateSessionTouchOutsideListener(persistentId, true); } } { std::lock_guard lockListener(windowVisibilityChangeListenerMutex_); if (windowVisibilityChangeListeners_.find(persistentId) != windowVisibilityChangeListeners_.end() && !windowVisibilityChangeListeners_[persistentId].empty()) { SingletonContainer::Get().UpdateSessionWindowVisibilityListener(persistentId, true); } } { std::lock_guard lockListener(windowRectChangeListenerMutex_); if (windowRectChangeListeners_.find(persistentId) != windowRectChangeListeners_.end() && !windowRectChangeListeners_[persistentId].empty()) { if (auto hostSession = GetHostSession()) { hostSession->UpdateRectChangeListenerRegistered(true); } } } } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> lifecycleListeners; for (auto& listener : lifecycleListeners_[GetPersistentId()]) { lifecycleListeners.push_back(listener); } return lifecycleListeners; } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> windowChangeListeners; for (auto& listener : windowChangeListeners_[GetPersistentId()]) { windowChangeListeners.push_back(listener); } return windowChangeListeners; } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> occupiedAreaChangeListeners; for (auto& listener : occupiedAreaChangeListeners_[GetPersistentId()]) { occupiedAreaChangeListeners.push_back(listener); } return occupiedAreaChangeListeners; } template WMError WindowSessionImpl::RegisterListener(std::vector>& holder, const sptr& listener) { if (listener == nullptr) { WLOGFE("listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } if (std::find(holder.begin(), holder.end(), listener) != holder.end()) { WLOGFE("Listener already registered"); return WMError::WM_OK; } holder.emplace_back(listener); return WMError::WM_OK; } template WMError WindowSessionImpl::UnregisterListener(std::vector>& holder, const sptr& listener) { if (listener == nullptr) { WLOGFE("listener could not be null"); return WMError::WM_ERROR_NULLPTR; } holder.erase(std::remove_if(holder.begin(), holder.end(), [listener](sptr registeredListener) { return registeredListener == listener; }), holder.end()); return WMError::WM_OK; } template void WindowSessionImpl::ClearUselessListeners(std::map& listeners, int32_t persistentId) { listeners.erase(persistentId); } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> windowStatusChangeListeners; for (auto& listener : windowStatusChangeListeners_[GetPersistentId()]) { windowStatusChangeListeners.push_back(listener); } return windowStatusChangeListeners; } void WindowSessionImpl::ClearListenersById(int32_t persistentId) { TLOGI(WmsLogTag::WMS_LIFE, "Called id: %{public}d.", GetPersistentId()); { std::lock_guard lockListener(displayMoveListenerMutex_); ClearUselessListeners(displayMoveListeners_, persistentId); } { std::lock_guard lockListener(lifeCycleListenerMutex_); ClearUselessListeners(lifecycleListeners_, persistentId); } { std::lock_guard lockListener(windowChangeListenerMutex_); ClearUselessListeners(windowChangeListeners_, persistentId); } { std::lock_guard lockListener(avoidAreaChangeListenerMutex_); ClearUselessListeners(avoidAreaChangeListeners_, persistentId); } { std::lock_guard lockListener(dialogDeathRecipientListenerMutex_); ClearUselessListeners(dialogDeathRecipientListeners_, persistentId); } { std::lock_guard lockListener(dialogTargetTouchListenerMutex_); ClearUselessListeners(dialogTargetTouchListener_, persistentId); } { std::lock_guard lockListener(screenshotListenerMutex_); ClearUselessListeners(screenshotListeners_, persistentId); } { std::lock_guard lockListener(windowStatusChangeListenerMutex_); ClearUselessListeners(windowStatusChangeListeners_, persistentId); } { std::lock_guard lockListener(windowTitleButtonRectChangeListenerMutex_); ClearUselessListeners(windowTitleButtonRectChangeListeners_, persistentId); } { std::lock_guard lockListener(displayIdChangeListenerMutex_); ClearUselessListeners(displayIdChangeListeners_, persistentId); } { std::lock_guard lockListener(windowNoInteractionListenerMutex_); ClearUselessListeners(windowNoInteractionListeners_, persistentId); } { std::lock_guard lockListener(windowRectChangeListenerMutex_); ClearUselessListeners(windowRectChangeListeners_, persistentId); } { std::lock_guard lockListener(subWindowCloseListenersMutex_); ClearUselessListeners(subWindowCloseListeners_, persistentId); } { std::lock_guard lockListener(mainWindowCloseListenersMutex_); ClearUselessListeners(mainWindowCloseListeners_, persistentId); } { std::lock_guard lockListener(occupiedAreaChangeListenerMutex_); ClearUselessListeners(occupiedAreaChangeListeners_, persistentId); } ClearSwitchFreeMultiWindowListenersById(persistentId); TLOGI(WmsLogTag::WMS_LIFE, "Clear success, id: %{public}d.", GetPersistentId()); } void WindowSessionImpl::ClearSwitchFreeMultiWindowListenersById(int32_t persistentId) { std::lock_guard lockListener(switchFreeMultiWindowListenerMutex_); ClearUselessListeners(switchFreeMultiWindowListeners_, persistentId); } void WindowSessionImpl::RegisterWindowDestroyedListener(const NotifyNativeWinDestroyFunc& func) { notifyNativeFunc_ = std::move(func); } void WindowSessionImpl::ClearVsyncStation() { std::lock_guard lock(mutex_); if (vsyncStation_ != nullptr) { vsyncStation_.reset(); } } void WindowSessionImpl::SetInputEventConsumer(const std::shared_ptr& inputEventConsumer) { TLOGI(WmsLogTag::WMS_EVENT, "called"); std::lock_guard lock(mutex_); inputEventConsumer_ = inputEventConsumer; } WMError WindowSessionImpl::SetTitleButtonVisible(bool isMaximizeVisible, bool isMinimizeVisible, bool isSplitVisible, bool isCloseVisible) { if (IsWindowSessionInvalid()) { return WMError::WM_ERROR_INVALID_WINDOW; } if (!WindowHelper::IsMainWindow(GetType())) { return WMError::WM_ERROR_INVALID_CALLING; } if (!IsPcOrPadCapabilityEnabled()) { return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } if (GetUIContentSharedPtr() == nullptr || !IsDecorEnable()) { return WMError::WM_ERROR_INVALID_WINDOW; } windowTitleVisibleFlags_ = { isMaximizeVisible, isMinimizeVisible, isSplitVisible, isCloseVisible }; UpdateTitleButtonVisibility(); return WMError::WM_OK; } void WindowSessionImpl::NotifyAfterForeground(bool needNotifyListeners, bool needNotifyUiContent) { if (needNotifyListeners) { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER(AfterForeground, lifecycleListeners); } if (needNotifyUiContent) { CALL_UI_CONTENT(Foreground); } if (vsyncStation_ == nullptr) { TLOGE(WmsLogTag::WMS_MAIN, "SetFrameRateLinkerEnable true failed, vsyncStation is nullptr"); return; } TLOGD(WmsLogTag::WMS_MAIN, "SetFrameRateLinkerEnable: true, linkerId = %{public}" PRIu64, vsyncStation_->GetFrameRateLinkerId()); vsyncStation_->SetFrameRateLinkerEnable(true); if (WindowHelper::IsMainWindow(GetType())) { TLOGD(WmsLogTag::WMS_MAIN, "IsMainWindow: %{public}d, WindowType: %{public}d", WindowHelper::IsMainWindow(GetType()), GetType()); vsyncStation_->SetDisplaySoloistFrameRateLinkerEnable(true); } } void WindowSessionImpl::NotifyAfterBackground(bool needNotifyListeners, bool needNotifyUiContent) { if (needNotifyListeners) { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER(AfterBackground, lifecycleListeners); } if (needNotifyUiContent) { CALL_UI_CONTENT(Background); } if (vsyncStation_ == nullptr) { TLOGE(WmsLogTag::WMS_MAIN, "SetFrameRateLinkerEnable false failed, vsyncStation is nullptr"); return; } TLOGD(WmsLogTag::WMS_MAIN, "SetFrameRateLinkerEnable: false, linkerId = %{public}" PRIu64, vsyncStation_->GetFrameRateLinkerId()); vsyncStation_->SetFrameRateLinkerEnable(false); if (WindowHelper::IsMainWindow(GetType())) { TLOGD(WmsLogTag::WMS_MAIN, "IsMainWindow: %{public}d, WindowType: %{public}d", WindowHelper::IsMainWindow(GetType()), GetType()); vsyncStation_->SetDisplaySoloistFrameRateLinkerEnable(false); } } static void RequestInputMethodCloseKeyboard(bool isNeedKeyboard, bool keepKeyboardFlag) { if (!isNeedKeyboard && !keepKeyboardFlag) { #ifdef IMF_ENABLE TLOGI(WmsLogTag::WMS_KEYBOARD, "Notify InputMethod framework close keyboard start."); if (MiscServices::InputMethodController::GetInstance()) { MiscServices::InputMethodController::GetInstance()->RequestHideInput(); TLOGI(WmsLogTag::WMS_KEYBOARD, "Notify InputMethod framework close keyboard end."); } #endif } } void WindowSessionImpl::NotifyUIContentFocusStatus() { if (!isFocused_) { CALL_UI_CONTENT(UnFocus); return; } CALL_UI_CONTENT(Focus); auto task = [weak = wptr(this)]() { auto window = weak.promote(); if (!window) { return; } bool isNeedKeyboard = false; { std::shared_ptr uiContent = window->GetUIContentSharedPtr(); if (uiContent != nullptr) { // isNeedKeyboard is set by arkui and indicates whether the window needs a keyboard or not. isNeedKeyboard = uiContent->NeedSoftKeyboard(); } } // whether keep the keyboard created by other windows, support system window and app subwindow. bool keepKeyboardFlag = (window->property_) ? window->property_->GetKeepKeyboardFlag() : false; TLOGI(WmsLogTag::WMS_KEYBOARD, "isNeedKeyboard: %{public}d, keepKeyboardFlag: %{public}d", isNeedKeyboard, keepKeyboardFlag); RequestInputMethodCloseKeyboard(isNeedKeyboard, keepKeyboardFlag); }; std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { uiContent->SetOnWindowFocused(task); } } void WindowSessionImpl::NotifyAfterFocused() { NotifyWindowAfterFocused(); if (GetUIContentSharedPtr() != nullptr) { NotifyUIContentFocusStatus(); } else { shouldReNotifyFocus_ = true; } } void WindowSessionImpl::NotifyAfterUnfocused(bool needNotifyUiContent) { NotifyWindowAfterUnfocused(); if (needNotifyUiContent) { if (GetUIContentSharedPtr() == nullptr) { shouldReNotifyFocus_ = true; } else { CALL_UI_CONTENT(UnFocus); } } } void WindowSessionImpl::NotifyWindowAfterFocused() { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER(AfterFocused, lifecycleListeners); } void WindowSessionImpl::NotifyWindowAfterUnfocused() { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); // use needNotifyUinContent to separate ui content callbacks CALL_LIFECYCLE_LISTENER(AfterUnfocused, lifecycleListeners); } void WindowSessionImpl::NotifyBeforeDestroy(std::string windowName) { auto task = [this]() { { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { uiContent->Destroy(); } } { std::unique_lock lock(uiContentMutex_); if (uiContent_ != nullptr) { uiContent_ = nullptr; TLOGD(WmsLogTag::WMS_LIFE, "NotifyBeforeDestroy: uiContent destroy success, persistentId:%{public}d", GetPersistentId()); } } }; if (handler_) { handler_->PostSyncTask(task, "wms:NotifyBeforeDestroy"); } else { task(); } TLOGI(WmsLogTag::WMS_LIFE, "Release uicontent successfully, id: %{public}d.", GetPersistentId()); if (notifyNativeFunc_) { notifyNativeFunc_(windowName); } TLOGI(WmsLogTag::WMS_LIFE, "successed with id: %{public}d.", GetPersistentId()); } void WindowSessionImpl::NotifyAfterDestroy() { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER(AfterDestroyed, lifecycleListeners); } void WindowSessionImpl::NotifyAfterActive() { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER(AfterActive, lifecycleListeners); } void WindowSessionImpl::NotifyAfterInactive() { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER(AfterInactive, lifecycleListeners); } void WindowSessionImpl::NotifyForegroundFailed(WMError ret) { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER_WITH_PARAM(ForegroundFailed, lifecycleListeners, static_cast(ret)); } void WindowSessionImpl::NotifyBackgroundFailed(WMError ret) { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER_WITH_PARAM(BackgroundFailed, lifecycleListeners, static_cast(ret)); } void WindowSessionImpl::NotifyAfterResumed() { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER(AfterResumed, lifecycleListeners); } void WindowSessionImpl::NotifyAfterPaused() { std::lock_guard lockListener(lifeCycleListenerMutex_); auto lifecycleListeners = GetListeners(); CALL_LIFECYCLE_LISTENER(AfterPaused, lifecycleListeners); } WSError WindowSessionImpl::MarkProcessed(int32_t eventId) { if (IsWindowSessionInvalid()) { WLOGFE("HostSession is invalid"); return WSError::WS_DO_NOTHING; } auto hostSession = GetHostSession(); CHECK_HOST_SESSION_RETURN_ERROR_IF_NULL(hostSession, WSError::WS_DO_NOTHING); return hostSession->MarkProcessed(eventId); } void WindowSessionImpl::RegisterDialogDeathRecipientListener(const sptr& listener) { TLOGI(WmsLogTag::WMS_DIALOG, "window %{public}s id %{public}d register DialogDeathRecipientListener", GetWindowName().c_str(), GetPersistentId()); if (listener == nullptr) { WLOGFE("listener is nullptr"); return; } std::lock_guard lockListener(dialogDeathRecipientListenerMutex_); RegisterListener(dialogDeathRecipientListeners_[GetPersistentId()], listener); } void WindowSessionImpl::UnregisterDialogDeathRecipientListener(const sptr& listener) { TLOGI(WmsLogTag::WMS_DIALOG, "window %{public}s id %{public}d unregister DialogDeathRecipientListener", GetWindowName().c_str(), GetPersistentId()); std::lock_guard lockListener(dialogDeathRecipientListenerMutex_); UnregisterListener(dialogDeathRecipientListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::RegisterDialogTargetTouchListener(const sptr& listener) { TLOGI(WmsLogTag::WMS_DIALOG, "window %{public}s id %{public}d register DialogTargetTouchListener", GetWindowName().c_str(), GetPersistentId()); if (listener == nullptr) { WLOGFE("listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } std::lock_guard lockListener(dialogTargetTouchListenerMutex_); return RegisterListener(dialogTargetTouchListener_[GetPersistentId()], listener); } WMError WindowSessionImpl::UnregisterDialogTargetTouchListener(const sptr& listener) { TLOGI(WmsLogTag::WMS_DIALOG, "window %{public}s id %{public}d unregister DialogTargetTouchListener", GetWindowName().c_str(), GetPersistentId()); std::lock_guard lockListener(dialogTargetTouchListenerMutex_); return UnregisterListener(dialogTargetTouchListener_[GetPersistentId()], listener); } WMError WindowSessionImpl::RegisterScreenshotListener(const sptr& listener) { WLOGFD("Start register ScreenshotListener"); std::lock_guard lockListener(screenshotListenerMutex_); return RegisterListener(screenshotListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::UnregisterScreenshotListener(const sptr& listener) { WLOGFD("Start unregister ScreenshotListener"); std::lock_guard lockListener(screenshotListenerMutex_); return UnregisterListener(screenshotListeners_[GetPersistentId()], listener); } template EnableIfSame>> WindowSessionImpl:: GetListeners() { std::vector> dialogDeathRecipientListener; for (auto& listener : dialogDeathRecipientListeners_[GetPersistentId()]) { dialogDeathRecipientListener.push_back(listener); } return dialogDeathRecipientListener; } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> dialogTargetTouchListener; for (auto& listener : dialogTargetTouchListener_[GetPersistentId()]) { dialogTargetTouchListener.push_back(listener); } return dialogTargetTouchListener; } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> screenshotListeners; for (auto& listener : screenshotListeners_[GetPersistentId()]) { screenshotListeners.push_back(listener); } return screenshotListeners; } WSError WindowSessionImpl::NotifyDestroy() { if (WindowHelper::IsDialogWindow(property_->GetWindowType())) { std::lock_guard lockListener(dialogDeathRecipientListenerMutex_); auto dialogDeathRecipientListener = GetListeners(); for (auto& listener : dialogDeathRecipientListener) { if (listener != nullptr) { listener->OnDialogDeathRecipient(); } } } else if (WindowHelper::IsSubWindow(property_->GetWindowType())) { if (property_->GetExtensionFlag() == true && !isUIExtensionAbilityProcess_) { Destroy(); } } return WSError::WS_OK; } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> displayMoveListeners; for (auto& listener : displayMoveListeners_[GetPersistentId()]) { displayMoveListeners.push_back(listener); } return displayMoveListeners; } void WindowSessionImpl::NotifyDisplayMove(DisplayId from, DisplayId to) { WLOGFD("Notify display move from %{public}" PRIu64 " to %{public}" PRIu64, from, to); std::lock_guard lockListener(displayMoveListenerMutex_); auto displayMoveListeners = GetListeners(); for (auto& listener : displayMoveListeners) { if (listener != nullptr) { listener->OnDisplayMove(from, to); } } } WSError WindowSessionImpl::NotifyCloseExistPipWindow() { TLOGI(WmsLogTag::WMS_PIP, "WindowSessionImpl::NotifyCloseExistPipWindow"); auto task = []() { PictureInPictureManager::DoClose(true, true); }; handler_->PostTask(task, "WMS_WindowSessionImpl_NotifyCloseExistPipWindow"); return WSError::WS_OK; } void WindowSessionImpl::NotifyTouchDialogTarget(int32_t posX, int32_t posY) { TLOGI(WmsLogTag::WMS_DIALOG, "window %{public}s id %{public}d", GetWindowName().c_str(), GetPersistentId()); auto hostSession = GetHostSession(); if (hostSession != nullptr) { hostSession->ProcessPointDownSession(posX, posY); } std::lock_guard lockListener(dialogTargetTouchListenerMutex_); auto dialogTargetTouchListener = GetListeners(); for (auto& listener : dialogTargetTouchListener) { if (listener != nullptr) { listener->OnDialogTargetTouch(); } } } void WindowSessionImpl::NotifyScreenshot() { std::lock_guard lockListener(screenshotListenerMutex_); auto screenshotListeners = GetListeners(); for (auto& listener : screenshotListeners) { if (listener != nullptr) { listener->OnScreenshot(); } } } void WindowSessionImpl::NotifySizeChange(Rect rect, WindowSizeChangeReason reason) { { std::lock_guard lockListener(windowChangeListenerMutex_); auto windowChangeListeners = GetListeners(); for (auto& listener : windowChangeListeners) { if (listener != nullptr) { listener->OnSizeChange(rect, reason); } } } { std::lock_guard lockRectListener(windowRectChangeListenerMutex_); auto windowRectChangeListeners = GetListeners(); for (auto& listener : windowRectChangeListeners) { if (listener != nullptr) { listener->OnRectChange(rect, reason); } } } } void WindowSessionImpl::NotifySubWindowClose(bool& terminateCloseProcess) { WLOGFD("WindowSessionImpl::NotifySubWindowClose"); std::lock_guard lockListener(subWindowCloseListenersMutex_); auto subWindowCloseListeners = GetListeners(); if (subWindowCloseListeners != nullptr) { subWindowCloseListeners->OnSubWindowClose(terminateCloseProcess); } } WMError WindowSessionImpl::NotifyMainWindowClose(bool& terminateCloseProcess) { std::lock_guard lockListener(mainWindowCloseListenersMutex_); auto mainWindowCloseListener = GetListeners(); if (mainWindowCloseListener != nullptr) { mainWindowCloseListener->OnMainWindowClose(terminateCloseProcess); return WMError::WM_OK; } return WMError::WM_ERROR_NULLPTR; } void WindowSessionImpl::NotifySwitchFreeMultiWindow(bool enable) { std::lock_guard lockListener(switchFreeMultiWindowListenerMutex_); auto switchFreeMultiWindowListeners = GetListeners(); for (auto& listener : switchFreeMultiWindowListeners) { if (listener != nullptr) { listener->OnSwitchFreeMultiWindow(enable); } } } WMError WindowSessionImpl::RegisterAvoidAreaChangeListener(sptr& listener) { bool isUpdate = false; WMError ret = WMError::WM_OK; auto persistentId = GetPersistentId(); TLOGI(WmsLogTag::WMS_IMMS, "Start register avoidAreaChange listener, id:%{public}d", persistentId); if (listener == nullptr) { TLOGE(WmsLogTag::WMS_IMMS, "listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } { std::lock_guard lockListener(avoidAreaChangeListenerMutex_); ret = RegisterListener(avoidAreaChangeListeners_[persistentId], listener); if (ret != WMError::WM_OK) { return ret; } if (avoidAreaChangeListeners_[persistentId].size() == 1) { isUpdate = true; } } if (isUpdate) { ret = SingletonContainer::Get().UpdateSessionAvoidAreaListener(persistentId, true); } return ret; } WMError WindowSessionImpl::UnregisterAvoidAreaChangeListener(sptr& listener) { bool isUpdate = false; WMError ret = WMError::WM_OK; auto persistentId = GetPersistentId(); TLOGI(WmsLogTag::WMS_IMMS, "Start unregister avoidAreaChange listener, id:%{public}d", persistentId); if (listener == nullptr) { WLOGFE("listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } { std::lock_guard lockListener(avoidAreaChangeListenerMutex_); ret = UnregisterListener(avoidAreaChangeListeners_[persistentId], listener); if (ret != WMError::WM_OK) { return ret; } if (avoidAreaChangeListeners_[persistentId].empty()) { isUpdate = true; } } if (isUpdate) { ret = SingletonContainer::Get().UpdateSessionAvoidAreaListener(persistentId, false); } return ret; } WMError WindowSessionImpl::RegisterExtensionAvoidAreaChangeListener(sptr& listener) { auto persistentId = GetPersistentId(); WLOGI("Start register extension avoidAreaChange listener, id:%{public}d", persistentId); std::lock_guard lockListener(avoidAreaChangeListenerMutex_); return RegisterListener(avoidAreaChangeListeners_[persistentId], listener); } WMError WindowSessionImpl::UnregisterExtensionAvoidAreaChangeListener(sptr& listener) { auto persistentId = GetPersistentId(); WLOGI("Start unregister extension avoidAreaChange listener, id:%{public}d", persistentId); std::lock_guard lockListener(avoidAreaChangeListenerMutex_); return UnregisterListener(avoidAreaChangeListeners_[persistentId], listener); } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> windowChangeListeners; for (auto& listener : avoidAreaChangeListeners_[GetPersistentId()]) { windowChangeListeners.push_back(listener); } return windowChangeListeners; } void WindowSessionImpl::NotifyAvoidAreaChange(const sptr& avoidArea, AvoidAreaType type) { TLOGI(WmsLogTag::WMS_IMMS, "window [%{public}d, %{public}s] type %{public}d area %{public}s", GetPersistentId(), GetWindowName().c_str(), type, avoidArea->ToString().c_str()); std::lock_guard lockListener(avoidAreaChangeListenerMutex_); auto avoidAreaChangeListeners = GetListeners(); for (auto& listener : avoidAreaChangeListeners) { if (listener != nullptr) { listener->OnAvoidAreaChanged(*avoidArea, type); } } } WSError WindowSessionImpl::NotifyTransferComponentData(const AAFwk::WantParams& wantParams) { return WSError::WS_OK; } WSErrorCode WindowSessionImpl::NotifyTransferComponentDataSync(const AAFwk::WantParams& wantParams, AAFwk::WantParams& reWantParams) { return WSErrorCode::WS_OK; } WSError WindowSessionImpl::UpdateAvoidArea(const sptr& avoidArea, AvoidAreaType type) { UpdateViewportConfig(GetRect(), WindowSizeChangeReason::UNDEFINED, nullptr, nullptr, {{type, *avoidArea}}); NotifyAvoidAreaChange(avoidArea, type); return WSError::WS_OK; } WSError WindowSessionImpl::SetPipActionEvent(const std::string& action, int32_t status) { TLOGI(WmsLogTag::WMS_PIP, "action: %{public}s, status: %{public}d", action.c_str(), status); auto task = [action, status]() { PictureInPictureManager::DoActionEvent(action, status); }; handler_->PostTask(task, "WMS_WindowSessionImpl_SetPipActionEvent"); return WSError::WS_OK; } WSError WindowSessionImpl::SetPiPControlEvent(WsPiPControlType controlType, WsPiPControlStatus status) { TLOGI(WmsLogTag::WMS_PIP, "controlType:%{public}u, enabled:%{public}d", controlType, status); auto task = [controlType, status]() { PictureInPictureManager::DoControlEvent(static_cast(controlType), static_cast(status)); }; handler_->PostTask(task, "WMS_WindowSessionImpl_SetPiPControlEvent"); return WSError::WS_OK; } WMError WindowSessionImpl::RegisterTouchOutsideListener(const sptr& listener) { bool isUpdate = false; WMError ret = WMError::WM_OK; auto persistentId = GetPersistentId(); TLOGI(WmsLogTag::WMS_EVENT, "Start register touchOutside listener, window: name=%{public}s, id=%{public}u", GetWindowName().c_str(), GetPersistentId()); if (listener == nullptr) { TLOGE(WmsLogTag::WMS_EVENT, "listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } { std::lock_guard lockListener(touchOutsideListenerMutex_); ret = RegisterListener(touchOutsideListeners_[persistentId], listener); if (ret != WMError::WM_OK) { TLOGE(WmsLogTag::WMS_EVENT, "Register touchOutside listener fail, ret:%{public}u", ret); return ret; } if (touchOutsideListeners_[persistentId].size() == 1) { isUpdate = true; } } if (isUpdate) { ret = SingletonContainer::Get().UpdateSessionTouchOutsideListener(persistentId, true); } return ret; } WMError WindowSessionImpl::UnregisterTouchOutsideListener(const sptr& listener) { bool isUpdate = false; WMError ret = WMError::WM_OK; auto persistentId = GetPersistentId(); TLOGI(WmsLogTag::WMS_EVENT, "Start unregister touchOutside listener, window: name=%{public}s, id=%{public}u", GetWindowName().c_str(), GetPersistentId()); if (listener == nullptr) { TLOGE(WmsLogTag::WMS_EVENT, "listener is nullptr"); return WMError::WM_ERROR_NULLPTR; } { std::lock_guard lockListener(touchOutsideListenerMutex_); ret = UnregisterListener(touchOutsideListeners_[persistentId], listener); if (ret != WMError::WM_OK) { TLOGE(WmsLogTag::WMS_EVENT, "Unregister touchOutside listener fail, ret:%{public}u", ret); return ret; } if (touchOutsideListeners_[persistentId].empty()) { isUpdate = true; } } if (isUpdate) { ret = SingletonContainer::Get().UpdateSessionTouchOutsideListener(persistentId, false); } return ret; } template EnableIfSame>> WindowSessionImpl::GetListeners() { std::vector> windowChangeListeners; for (auto& listener : touchOutsideListeners_[GetPersistentId()]) { windowChangeListeners.push_back(listener); } return windowChangeListeners; } WSError WindowSessionImpl::NotifyTouchOutside() { TLOGI(WmsLogTag::WMS_EVENT, "Notify touch outside, window: name=%{public}s, id=%{public}u", GetWindowName().c_str(), GetPersistentId()); std::lock_guard lockListener(touchOutsideListenerMutex_); auto touchOutsideListeners = GetListeners(); for (auto& listener : touchOutsideListeners) { if (listener != nullptr) { listener->OnTouchOutside(); } } return WSError::WS_OK; } WMError WindowSessionImpl::RegisterWindowVisibilityChangeListener(const IWindowVisibilityListenerSptr& listener) { auto persistentId = GetPersistentId(); WLOGFD("Start to register window visibility change listener, persistentId=%{public}d.", persistentId); WMError ret = WMError::WM_OK; bool isFirstRegister = false; { std::lock_guard lockListener(windowVisibilityChangeListenerMutex_); ret = RegisterListener(windowVisibilityChangeListeners_[persistentId], listener); if (ret != WMError::WM_OK) { return ret; } isFirstRegister = windowVisibilityChangeListeners_[persistentId].size() == 1; } if (isFirstRegister) { ret = SingletonContainer::Get().UpdateSessionWindowVisibilityListener(persistentId, true); } return ret; } WMError WindowSessionImpl::UnregisterWindowVisibilityChangeListener(const IWindowVisibilityListenerSptr& listener) { auto persistentId = GetPersistentId(); WLOGFD("Start to unregister window visibility change listener, persistentId=%{public}d.", persistentId); WMError ret = WMError::WM_OK; bool isLastUnregister = false; { std::lock_guard lockListener(windowVisibilityChangeListenerMutex_); ret = UnregisterListener(windowVisibilityChangeListeners_[persistentId], listener); if (ret != WMError::WM_OK) { return ret; } isLastUnregister = windowVisibilityChangeListeners_[persistentId].empty(); } if (isLastUnregister) { ret = SingletonContainer::Get().UpdateSessionWindowVisibilityListener(persistentId, false); } return ret; } WMError WindowSessionImpl::RegisterDisplayIdChangeListener(const IDisplayIdChangeListenerSptr& listener) { TLOGD(WmsLogTag::DEFAULT, "name=%{public}s, id=%{public}u", GetWindowName().c_str(), GetPersistentId()); std::lock_guard lockListener(displayIdChangeListenerMutex_); return RegisterListener(displayIdChangeListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::UnregisterDisplayIdChangeListener(const IDisplayIdChangeListenerSptr& listener) { TLOGD(WmsLogTag::DEFAULT, "name=%{public}s, id=%{public}u", GetWindowName().c_str(), GetPersistentId()); std::lock_guard lockListener(displayIdChangeListenerMutex_); return UnregisterListener(displayIdChangeListeners_[GetPersistentId()], listener); } WMError WindowSessionImpl::RegisterWindowNoInteractionListener(const IWindowNoInteractionListenerSptr& listener) { WLOGFD("Start to register window no interaction listener."); std::lock_guard lockListener(windowNoInteractionListenerMutex_); WMError ret = RegisterListener(windowNoInteractionListeners_[GetPersistentId()], listener); if (ret != WMError::WM_OK) { WLOGFE("register no interaction listener failed."); } else { SubmitNoInteractionMonitorTask(this->lastInteractionEventId_.load(), listener); } return ret; } WMError WindowSessionImpl::UnregisterWindowNoInteractionListener(const IWindowNoInteractionListenerSptr& listener) { WLOGFD("Start to unregister window no interaction listener."); std::lock_guard lockListener(windowNoInteractionListenerMutex_); WMError ret = UnregisterListener(windowNoInteractionListeners_[GetPersistentId()], listener); if (windowNoInteractionListeners_[GetPersistentId()].empty()) { lastInteractionEventId_.store(-1); } return ret; } template EnableIfSame> WindowSessionImpl::GetListeners() { std::vector windowVisibilityChangeListeners; for (auto& listener : windowVisibilityChangeListeners_[GetPersistentId()]) { windowVisibilityChangeListeners.push_back(listener); } return windowVisibilityChangeListeners; } template EnableIfSame> WindowSessionImpl::GetListeners() { return displayIdChangeListeners_[GetPersistentId()]; } template EnableIfSame> WindowSessionImpl::GetListeners() { std::vector noInteractionListeners; for (auto& listener : windowNoInteractionListeners_[GetPersistentId()]) { noInteractionListeners.push_back(listener); } return noInteractionListeners; } WSError WindowSessionImpl::NotifyDisplayIdChange(DisplayId displayId) { TLOGD(WmsLogTag::DEFAULT, "id=%{public}u, displayId=%{public}" PRIu64, GetPersistentId(), displayId); std::lock_guard lock(displayIdChangeListenerMutex_); auto displayIdChangeListeners = GetListeners(); for (auto& listener : displayIdChangeListeners) { if (listener != nullptr) { listener->OnDisplayIdChanged(displayId); } } return WSError::WS_OK; } WSError WindowSessionImpl::NotifyWindowVisibility(bool isVisible) { TLOGD(WmsLogTag::DEFAULT, "window: name=%{public}s, id=%{public}u, isVisible=%{public}d", GetWindowName().c_str(), GetPersistentId(), isVisible); std::lock_guard lockListener(windowVisibilityChangeListenerMutex_); auto windowVisibilityListeners = GetListeners(); for (auto& listener : windowVisibilityListeners) { if (listener != nullptr) { listener->OnWindowVisibilityChangedCallback(isVisible); } } return WSError::WS_OK; } WSError WindowSessionImpl::NotifyNoInteractionTimeout(const IWindowNoInteractionListenerSptr& listener) { if (listener == nullptr) { WLOGFE("invalid listener: nullptr"); return WSError::WS_ERROR_NULLPTR; } WLOGFD("Notify window no interaction timeout, window: name=%{public}s, id=%{public}u, timeout=%{public}" PRId64, GetWindowName().c_str(), GetPersistentId(), listener->GetTimeout()); listener->OnWindowNoInteractionCallback(); return WSError::WS_OK; } void WindowSessionImpl::NotifyPointerEvent(const std::shared_ptr& pointerEvent) { if (!pointerEvent) { TLOGE(WmsLogTag::WMS_INPUT_KEY_FLOW, "Pointer event is nullptr"); return; } std::shared_ptr inputEventConsumer; { std::lock_guard lock(mutex_); inputEventConsumer = inputEventConsumer_; } if (inputEventConsumer != nullptr) { WLOGFD("Transfer pointer event to inputEventConsumer"); if (pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_MOVE) { TLOGI(WmsLogTag::WMS_INPUT_KEY_FLOW, "Transfer pointer event to inputEventConsumer InputTracking id:%{public}d", pointerEvent->GetId()); } if (!(inputEventConsumer->OnInputEvent(pointerEvent))) { pointerEvent->MarkProcessed(); } return; } std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { if (pointerEvent->GetPointerAction() != MMI::PointerEvent::POINTER_ACTION_MOVE) { TLOGI(WmsLogTag::WMS_EVENT, "Input id:%{public}d", pointerEvent->GetId()); } if (!(uiContent->ProcessPointerEvent(pointerEvent))) { TLOGI(WmsLogTag::WMS_INPUT_KEY_FLOW, "UI content dose not consume this pointer event"); pointerEvent->MarkProcessed(); } } else { TLOGW(WmsLogTag::WMS_INPUT_KEY_FLOW, "pointerEvent is not consumed, windowId: %{public}u", GetWindowId()); pointerEvent->MarkProcessed(); } } WMError WindowSessionImpl::SetKeyEventFilter(KeyEventFilterFunc filter) { std::unique_lock lock(keyEventFilterMutex_); keyEventFilter_ = std::move(filter); return WMError::WM_OK; } WMError WindowSessionImpl::ClearKeyEventFilter() { std::unique_lock lock(keyEventFilterMutex_); keyEventFilter_ = nullptr; return WMError::WM_OK; } bool WindowSessionImpl::FilterKeyEvent(const std::shared_ptr& keyEvent) { std::shared_lock lock(keyEventFilterMutex_); if (keyEventFilter_ != nullptr) { bool isFilter = keyEventFilter_(*keyEvent.get()); TLOGE(WmsLogTag::WMS_SYSTEM, "keyCode:%{public}d isFilter:%{public}d", keyEvent->GetKeyCode(), isFilter); if (isFilter) { keyEvent->MarkProcessed(); return true; } } return false; } void WindowSessionImpl::DispatchKeyEventCallback(const std::shared_ptr& keyEvent, bool& isConsumed) { std::shared_ptr inputEventConsumer; { std::lock_guard lock(mutex_); inputEventConsumer = inputEventConsumer_; } int32_t keyCode = keyEvent->GetKeyCode(); int32_t keyAction = keyEvent->GetKeyAction(); if (keyCode == MMI::KeyEvent::KEYCODE_BACK && keyAction == MMI::KeyEvent::KEY_ACTION_UP) { WLOGFI("input event is consumed by back, return"); if (inputEventConsumer != nullptr) { WLOGFD("Transfer key event to inputEventConsumer"); if (inputEventConsumer->OnInputEvent(keyEvent)) { return; } PerformBack(); keyEvent->MarkProcessed(); return; } HandleBackEvent(); keyEvent->MarkProcessed(); return; } if (inputEventConsumer != nullptr) { WLOGD("Transfer key event to inputEventConsumer"); if (!(inputEventConsumer->OnInputEvent(keyEvent))) { keyEvent->MarkProcessed(); } return; } std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent) { if (FilterKeyEvent(keyEvent)) return; isConsumed = uiContent->ProcessKeyEvent(keyEvent); if (!isConsumed && keyEvent->GetKeyCode() == MMI::KeyEvent::KEYCODE_ESCAPE && property_->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && GetImmersiveModeEnabledState() && keyAction == MMI::KeyEvent::KEY_ACTION_DOWN && !escKeyEventTriggered_) { WLOGI("recover from fullscreen cause KEYCODE_ESCAPE"); Recover(); } if (!isConsumed) { keyEvent->MarkProcessed(); } if (keyEvent->GetKeyCode() == MMI::KeyEvent::KEYCODE_ESCAPE) { escKeyEventTriggered_ = (keyAction == MMI::KeyEvent::KEY_ACTION_UP) ? false : true; } } } WSError WindowSessionImpl::HandleBackEvent() { TLOGI(WmsLogTag::WMS_EVENT, "called"); bool isConsumed = false; std::shared_ptr inputEventConsumer; { std::lock_guard lock(mutex_); inputEventConsumer = inputEventConsumer_; } if (inputEventConsumer != nullptr) { WLOGFD("Transfer back event to inputEventConsumer"); std::shared_ptr backKeyEvent = MMI::KeyEvent::Create(); if (backKeyEvent == nullptr) { WLOGFE("backKeyEvent is null"); return WSError::WS_ERROR_NULLPTR; } backKeyEvent->SetKeyCode(MMI::KeyEvent::KEYCODE_BACK); backKeyEvent->SetKeyAction(MMI::KeyEvent::KEY_ACTION_UP); isConsumed = inputEventConsumer->OnInputEvent(backKeyEvent); } else { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { WLOGFD("Transfer back event to uiContent"); isConsumed = uiContent->ProcessBackPressed(); } else { WLOGFE("There is no back event consumer"); } } if (isConsumed) { WLOGD("Back key event is consumed"); return WSError::WS_OK; } WLOGFD("report Back"); SingletonContainer::Get().ReportBackButtonInfoImmediately(); if (handler_ == nullptr) { WLOGFE("HandleBackEvent handler_ is nullptr!"); return WSError::WS_ERROR_INVALID_PARAM; } // notify back event to host session wptr weak = this; auto task = [weak]() { auto weakSession = weak.promote(); if (weakSession == nullptr) { WLOGFE("HandleBackEvent session wptr is nullptr"); return; } weakSession->PerformBack(); }; if (!handler_->PostTask(task, "wms:PerformBack")) { WLOGFE("Failed to post PerformBack"); return WSError::WS_ERROR_INVALID_OPERATION; } return WSError::WS_OK; } void WindowSessionImpl::NotifyKeyEvent(const std::shared_ptr& keyEvent, bool& isConsumed, bool notifyInputMethod) { if (keyEvent == nullptr) { WLOGFE("keyEvent is nullptr"); return; } #ifdef IMF_ENABLE bool isKeyboardEvent = IsKeyboardEvent(keyEvent); if (isKeyboardEvent && notifyInputMethod) { WLOGD("Async dispatch keyEvent to input method"); auto callback = [weakThis = wptr(this)] (std::shared_ptr& keyEvent, bool consumed) { if (keyEvent == nullptr) { WLOGFW("keyEvent is null, consumed:%{public}" PRId32, consumed); return; } if (consumed) { WLOGD("Input method has processed key event, id:%{public}" PRId32, keyEvent->GetId()); return; } auto promoteThis = weakThis.promote(); if (promoteThis == nullptr) { WLOGFW("promoteThis is nullptr"); keyEvent->MarkProcessed(); return; } bool isConsumed = false; promoteThis->DispatchKeyEventCallback(keyEvent, isConsumed); }; auto ret = MiscServices::InputMethodController::GetInstance()->DispatchKeyEvent( const_cast&>(keyEvent), callback); if (ret != 0) { WLOGFE("DispatchKeyEvent failed, ret:%{public}" PRId32 ", id:%{public}" PRId32, ret, keyEvent->GetId()); DispatchKeyEventCallback(keyEvent, isConsumed); } return; } #endif // IMF_ENABLE DispatchKeyEventCallback(keyEvent, isConsumed); } bool WindowSessionImpl::IsKeyboardEvent(const std::shared_ptr& keyEvent) const { int32_t keyCode = keyEvent->GetKeyCode(); bool isKeyFN = (keyCode == MMI::KeyEvent::KEYCODE_FN); bool isKeyBack = (keyCode == MMI::KeyEvent::KEYCODE_BACK); bool isKeyboard = (keyCode >= MMI::KeyEvent::KEYCODE_0 && keyCode <= MMI::KeyEvent::KEYCODE_NUMPAD_RIGHT_PAREN); bool isKeySound = (keyCode == MMI::KeyEvent::KEYCODE_SOUND); WLOGD("isKeyFN: %{public}d, isKeyboard: %{public}d", isKeyFN, isKeyboard); return (isKeyFN || isKeyboard || isKeyBack || isKeySound); } void WindowSessionImpl::RequestVsync(const std::shared_ptr& vsyncCallback) { std::lock_guard lock(mutex_); if (state_ == WindowState::STATE_DESTROYED) { WLOGFE("Receive vsync request failed, window is destroyed"); return; } if (vsyncStation_ == nullptr) { TLOGE(WmsLogTag::WMS_MAIN, "Receive vsync request failed, vsyncStation is nullptr"); return; } vsyncStation_->RequestVsync(vsyncCallback); } int64_t WindowSessionImpl::GetVSyncPeriod() { std::lock_guard lock(mutex_); if (vsyncStation_ == nullptr) { TLOGE(WmsLogTag::WMS_MAIN, "Get vsync period failed, vsyncStation is nullptr"); return 0; } return vsyncStation_->GetVSyncPeriod(); } void WindowSessionImpl::FlushFrameRate(uint32_t rate, int32_t animatorExpectedFrameRate, uint32_t rateType) { std::lock_guard lock(mutex_); if (vsyncStation_ == nullptr) { TLOGE(WmsLogTag::WMS_MAIN, "FlushFrameRate failed, vsyncStation is nullptr"); return; } vsyncStation_->FlushFrameRate(rate, animatorExpectedFrameRate, rateType); } WMError WindowSessionImpl::UpdateProperty(WSPropertyChangeAction action) { TLOGD(WmsLogTag::DEFAULT, "action:%{public}u", action); if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::DEFAULT, "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 hostSession->UpdateSessionPropertyByAction(property_, action); } sptr WindowSessionImpl::Find(const std::string& name) { std::shared_lock lock(windowSessionMutex_); TLOGI(WmsLogTag::DEFAULT, "Try to find window %{public}s", name.c_str()); auto iter = windowSessionMap_.find(name); if (iter == windowSessionMap_.end()) { TLOGE(WmsLogTag::DEFAULT, "Can not find window %{public}s", name.c_str()); return nullptr; } return iter->second.second; } void WindowSessionImpl::SetAceAbilityHandler(const sptr& handler) { if (handler == nullptr) { WLOGE("ace ability handler is nullptr"); } std::lock_guard lock(mutex_); aceAbilityHandler_ = handler; } WMError WindowSessionImpl::SetBackgroundColor(const std::string& color) { if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::DEFAULT, "session is invalid"); return WMError::WM_ERROR_INVALID_WINDOW; } uint32_t colorValue; if (ColorParser::Parse(color, colorValue)) { TLOGD(WmsLogTag::DEFAULT, "SetBackgroundColor: window: %{public}s, value: [%{public}s, %{public}u]", GetWindowName().c_str(), color.c_str(), colorValue); return SetBackgroundColor(colorValue); } TLOGE(WmsLogTag::DEFAULT, "invalid color string: %{public}s", color.c_str()); return WMError::WM_ERROR_INVALID_PARAM; } WMError WindowSessionImpl::SetBackgroundColor(uint32_t color) { TLOGI(WmsLogTag::DEFAULT, "window: %{public}s, value:%{public}u", GetWindowName().c_str(), color); // 0xff000000: ARGB style, means Opaque color. const bool isAlphaZero = !(color & 0xff000000); std::string bundleName; std::string abilityName; if ((context_ != nullptr) && (context_->GetApplicationInfo() != nullptr)) { bundleName = context_->GetBundleName(); abilityName = context_->GetApplicationInfo()->name; } if (isAlphaZero && WindowHelper::IsMainWindow(GetType())) { auto& reportInstance = SingletonContainer::Get(); reportInstance.ReportZeroOpacityInfoImmediately(bundleName, abilityName); } { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { uiContent->SetBackgroundColor(color); return WMError::WM_OK; } } if (aceAbilityHandler_ != nullptr) { aceAbilityHandler_->SetBackgroundColor(color); return WMError::WM_OK; } TLOGD(WmsLogTag::DEFAULT, "FA mode could not set bg color: %{public}u", GetWindowId()); return WMError::WM_ERROR_INVALID_OPERATION; } sptr WindowSessionImpl::FindWindowById(uint32_t winId) { std::shared_lock lock(windowSessionMutex_); if (windowSessionMap_.empty()) { WLOGFE("Please create mainWindow First!"); return nullptr; } for (auto iter = windowSessionMap_.begin(); iter != windowSessionMap_.end(); iter++) { if (static_cast(winId) == iter->second.first) { WLOGD("FindWindow id: %{public}u", winId); return iter->second.second; } } WLOGFE("Cannot find Window, id: %{public}d", winId); return nullptr; } std::vector> WindowSessionImpl::GetSubWindow(int parentId) { auto iter = subWindowSessionMap_.find(parentId); if (iter == subWindowSessionMap_.end()) { return std::vector>(); } return std::vector>(subWindowSessionMap_[parentId].begin(), subWindowSessionMap_[parentId].end()); } uint32_t WindowSessionImpl::GetBackgroundColor() const { { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { return uiContent->GetBackgroundColor(); } } WLOGD("uiContent is nullptr, windowId: %{public}u, use FA mode", GetWindowId()); if (aceAbilityHandler_ != nullptr) { return aceAbilityHandler_->GetBackgroundColor(); } WLOGFD("FA mode does not get bg color: %{public}u", GetWindowId()); return 0xffffffff; // means no background color been set, default color is white } WMError WindowSessionImpl::SetLayoutFullScreenByApiVersion(bool status) { return WMError::WM_OK; } WMError WindowSessionImpl::SetSystemBarProperty(WindowType type, const SystemBarProperty& property) { return WMError::WM_OK; } WMError WindowSessionImpl::SetSpecificBarProperty(WindowType type, const SystemBarProperty& property) { return WMError::WM_OK; } void WindowSessionImpl::NotifyOccupiedAreaChangeInfoInner(sptr info) { std::lock_guard lockListener(occupiedAreaChangeListenerMutex_); auto occupiedAreaChangeListeners = GetListeners(); for (auto& listener : occupiedAreaChangeListeners) { if (listener != nullptr) { listener->OnSizeChange(info); } } } void WindowSessionImpl::NotifyOccupiedAreaChangeInfo(sptr info, const std::shared_ptr& rsTransaction) { TLOGI(WmsLogTag::WMS_KEYBOARD, "hasRSTransaction: %{public}d, safeHeight: %{public}u" ", occupied rect: x %{public}u, y %{public}u, w %{public}u, h %{public}u", rsTransaction != nullptr, info->safeHeight_, info->rect_.posX_, info->rect_.posY_, info->rect_.width_, info->rect_.height_); if (handler_ == nullptr) { TLOGE(WmsLogTag::WMS_KEYBOARD, "handler_ is nullptr, notify occupied area change info failed"); return; } auto task = [weak = wptr(this), info, rsTransaction]() { auto window = weak.promote(); if (!window) { TLOGE(WmsLogTag::WMS_KEYBOARD, "window is nullptr, notify occupied area change info failed"); return; } if (rsTransaction) { RSTransaction::FlushImplicitTransaction(); rsTransaction->Begin(); } window->NotifyOccupiedAreaChangeInfoInner(info); if (rsTransaction) { rsTransaction->Commit(); } }; handler_->PostTask(task, "WMS_WindowSessionImpl_NotifyOccupiedAreaChangeInfo"); } KeyboardAnimationConfig WindowSessionImpl::GetKeyboardAnimationConfig() { return { windowSystemConfig_.animationIn_, windowSystemConfig_.animationOut_ }; } void WindowSessionImpl::DumpSessionElementInfo(const std::vector& params) { WLOGFD("DumpSessionElementInfo"); } WSError WindowSessionImpl::UpdateMaximizeMode(MaximizeMode mode) { return WSError::WS_OK; } WMError WindowSessionImpl::TransferAccessibilityEvent(const Accessibility::AccessibilityEventInfo& info, int64_t uiExtensionIdLevel) { return WMError::WM_OK; } void WindowSessionImpl::NotifySessionForeground(uint32_t reason, bool withAnimation) { WLOGFD("NotifySessionForeground"); } void WindowSessionImpl::NotifySessionBackground(uint32_t reason, bool withAnimation, bool isFromInnerkits) { WLOGFD("NotifySessionBackground"); } WSError WindowSessionImpl::UpdateTitleInTargetPos(bool isShow, int32_t height) { return WSError::WS_OK; } WSError WindowSessionImpl::SwitchFreeMultiWindow(bool enable) { return WSError::WS_OK; } WSError WindowSessionImpl::NotifyDialogStateChange(bool isForeground) { return WSError::WS_OK; } void WindowSessionImpl::UpdatePiPRect(const Rect& rect, WindowSizeChangeReason reason) { if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::WMS_PIP, "HostSession is invalid"); return; } auto hostSession = GetHostSession(); CHECK_HOST_SESSION_RETURN_IF_NULL(hostSession); hostSession->UpdatePiPRect(rect, static_cast(reason)); } void WindowSessionImpl::UpdatePiPControlStatus(PiPControlType controlType, PiPControlStatus status) { TLOGI(WmsLogTag::WMS_PIP, "controlType:%{public}u, status:%{public}d", controlType, status); if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::WMS_PIP, "HostSession is invalid"); return; } auto hostSession = GetHostSession(); CHECK_HOST_SESSION_RETURN_IF_NULL(hostSession); hostSession->UpdatePiPControlStatus(static_cast(controlType), static_cast(status)); } void WindowSessionImpl::SetAutoStartPiP(bool isAutoStart, uint32_t priority) { if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::WMS_PIP, "session is invalid"); return; } if (auto hostSession = GetHostSession()) { hostSession->SetAutoStartPiP(isAutoStart, priority); } } WindowStatus WindowSessionImpl::GetWindowStatusInner(WindowMode mode) { auto windowStatus = WindowStatus::WINDOW_STATUS_UNDEFINED; if (mode == WindowMode::WINDOW_MODE_FLOATING) { windowStatus = WindowStatus::WINDOW_STATUS_FLOATING; if (property_->GetMaximizeMode() == MaximizeMode::MODE_AVOID_SYSTEM_BAR) { windowStatus = WindowStatus::WINDOW_STATUS_MAXIMIZE; } } else if (mode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY || mode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) { windowStatus = WindowStatus::WINDOW_STATUS_SPLITSCREEN; if (IsPcOrPadFreeMultiWindowMode() && GetTargetAPIVersion() >= 14) { // 14: isolated version windowStatus = GetImmersiveModeEnabledState() ? WindowStatus::WINDOW_STATUS_FULLSCREEN : WindowStatus::WINDOW_STATUS_MAXIMIZE; } else { windowStatus = WindowStatus::WINDOW_STATUS_FULLSCREEN; } } if (mode == WindowMode::WINDOW_MODE_FULLSCREEN) { windowStatus = WindowStatus::WINDOW_STATUS_FULLSCREEN; } if (state_ == WindowState::STATE_HIDDEN) { windowStatus = WindowStatus::WINDOW_STATUS_MINIMIZE; } return windowStatus; } void WindowSessionImpl::NotifyWindowStatusChange(WindowMode mode) { auto windowStatus = GetWindowStatusInner(mode); TLOGD(WmsLogTag::WMS_LAYOUT, "WindowMode: %{public}d, windowStatus: %{public}d", mode, windowStatus); std::lock_guard lockListener(windowStatusChangeListenerMutex_); auto windowStatusChangeListeners = GetListeners(); for (auto& listener : windowStatusChangeListeners) { if (listener != nullptr) { listener->OnWindowStatusChange(windowStatus); } } } void WindowSessionImpl::NotifyTransformChange(const Transform& transform) { WLOGFI("NotifyWindowStatusChange"); std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent != nullptr) { uiContent->UpdateTransform(transform); } } void WindowSessionImpl::SubmitNoInteractionMonitorTask(int32_t eventId, const IWindowNoInteractionListenerSptr& listener) { auto task = [sessionWptr = wptr(this), eventId, listenerWptr = wptr(listener)]() { auto session = sessionWptr.promote(); if (session == nullptr) { WLOGFE("windowInteractionMonitor task running failed, window session is null"); return; } if (eventId != session->lastInteractionEventId_.load()) { WLOGFD("event id of windowInteractionMonitor has been changed, need not notify!"); return; } if (session->state_ != WindowState::STATE_SHOWN) { WLOGFD("window state is not show, need not notify!"); return; } session->NotifyNoInteractionTimeout(listenerWptr.promote()); }; handler_->PostTask(task, listener->GetTimeout()); } void WindowSessionImpl::RefreshNoInteractionTimeoutMonitor() { std::lock_guard lockListener(windowNoInteractionListenerMutex_); if (windowNoInteractionListeners_[GetPersistentId()].empty()) { return; } this->lastInteractionEventId_.fetch_add(1); int32_t eventId = lastInteractionEventId_.load(); auto noInteractionListeners = GetListeners(); for (const auto& listenerItem : noInteractionListeners) { SubmitNoInteractionMonitorTask(eventId, listenerItem); } } bool WindowSessionImpl::IsUserOrientation(Orientation orientation) const { if (orientation == Orientation::USER_ROTATION_PORTRAIT || orientation == Orientation::USER_ROTATION_LANDSCAPE || orientation == Orientation::USER_ROTATION_PORTRAIT_INVERTED || orientation == Orientation::USER_ROTATION_LANDSCAPE_INVERTED) { return true; } return false; } WMError WindowSessionImpl::GetCallingWindowWindowStatus(WindowStatus& windowStatus) const { TLOGI(WmsLogTag::WMS_KEYBOARD, "id: %{public}d", GetPersistentId()); if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::WMS_KEYBOARD, "session is invalid"); return WMError::WM_ERROR_INVALID_WINDOW; } return SingletonContainer::Get().GetCallingWindowWindowStatus(GetPersistentId(), windowStatus); } WMError WindowSessionImpl::GetCallingWindowRect(Rect& rect) const { TLOGI(WmsLogTag::WMS_KEYBOARD, "Get CallingWindow Rect"); if (IsWindowSessionInvalid()) { TLOGE(WmsLogTag::WMS_KEYBOARD, "session is invalid"); return WMError::WM_ERROR_INVALID_WINDOW; } return SingletonContainer::Get().GetCallingWindowRect(GetPersistentId(), rect); } void WindowSessionImpl::SetUiDvsyncSwitch(bool dvsyncSwitch) { std::lock_guard lock(mutex_); if (vsyncStation_ == nullptr) { TLOGE(WmsLogTag::WMS_MAIN, "vsyncStation is nullptr"); return; } vsyncStation_->SetUiDvsyncSwitch(dvsyncSwitch); } WMError WindowSessionImpl::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); } void WindowSessionImpl::SetForceSplitEnable(bool isForceSplit, const std::string& homePage) { std::shared_ptr uiContent = GetUIContentSharedPtr(); if (uiContent == nullptr) { TLOGE(WmsLogTag::DEFAULT, "uiContent is null!"); return; } TLOGI(WmsLogTag::DEFAULT, "isForceSplit: %{public}u, homePage: %{public}s", isForceSplit, homePage.c_str()); uiContent->SetForceSplitEnable(isForceSplit, homePage); } void WindowSessionImpl::SetFrameLayoutCallbackEnable(bool enable) { enableFrameLayoutFinishCb_ = enable; } void WindowSessionImpl::UpdateFrameLayoutCallbackIfNeeded(WindowSizeChangeReason wmReason) { bool isDragInPcmode = IsFreeMultiWindowMode() && (wmReason == WindowSizeChangeReason::DRAG_END); if (wmReason == WindowSizeChangeReason::FULL_TO_SPLIT || wmReason == WindowSizeChangeReason::SPLIT_TO_FULL || wmReason == WindowSizeChangeReason::FULL_TO_FLOATING || wmReason == WindowSizeChangeReason::FLOATING_TO_FULL || isDragInPcmode) { TLOGI(WmsLogTag::WMS_MULTI_WINDOW, "enable framelayoutfinish callback reason:%{public}u", wmReason); SetFrameLayoutCallbackEnable(true); } } WMError WindowSessionImpl::SetContinueState(int32_t continueState) { if (continueState > ContinueState::CONTINUESTATE_MAX || continueState < ContinueState::CONTINUESTATE_UNKNOWN) { TLOGE(WmsLogTag::WMS_MAIN, "continueState is invalid: %{public}d", continueState); return WMError::WM_ERROR_INVALID_PARAM; } property_->EditSessionInfo().continueState = static_cast(continueState); return WMError::WM_OK; } void WindowSessionImpl::SetUIContentComplete() { bool setUIContentCompleted = false; if (setUIContentCompleted_.compare_exchange_strong(setUIContentCompleted, true)) { TLOGI(WmsLogTag::WMS_LIFE, "persistentId=%{public}d", GetPersistentId()); handler_->RemoveTask(SET_UICONTENT_TIMEOUT_LISTENER_TASK_NAME + std::to_string(GetPersistentId())); } else { TLOGI(WmsLogTag::WMS_LIFE, "already SetUIContent, persistentId=%{public}d", GetPersistentId()); } } void WindowSessionImpl::AddSetUIContentTimeoutCheck() { const auto checkBeginTime = std::chrono::time_point_cast(std::chrono::system_clock::now()) .time_since_epoch().count(); auto task = [weakThis = wptr(this), checkBeginTime] { auto window = weakThis.promote(); if (window == nullptr) { TLOGNI(WmsLogTag::WMS_LIFE, "window is nullptr"); return; } if (window->setUIContentCompleted_.load()) { TLOGNI(WmsLogTag::WMS_LIFE, "already SetUIContent, persistentId=%{public}d", window->GetPersistentId()); return; } const auto checkEndTime = std::chrono::time_point_cast(std::chrono::system_clock::now()) .time_since_epoch().count(); if (checkEndTime - checkBeginTime > SET_UICONTENT_TIMEOUT_TIME_AFTER_FREEZE_MS) { TLOGNI(WmsLogTag::WMS_LIFE, "will start re-check after freeze, persistentId=%{public}d", window->GetPersistentId()); window->AddSetUIContentTimeoutCheck(); return; } TLOGNI(WmsLogTag::WMS_LIFE, "SetUIContent timeout, persistentId=%{public}d", window->GetPersistentId()); std::ostringstream oss; oss << "SetUIContent timeout uid: " << getuid(); oss << ", windowName: " << window->GetWindowName(); if (window->context_) { oss << ", bundleName: " << window->context_->GetBundleName(); if (window->context_->GetApplicationInfo()) { oss << ", abilityName: " << window->context_->GetApplicationInfo()->name; } } SingletonContainer::Get().ReportWindowException( static_cast(WindowDFXHelperType::WINDOW_TRANSPARENT_CHECK), getpid(), oss.str()); if (WindowHelper::IsUIExtensionWindow(window->GetType())) { window->NotifyExtensionTimeout(TimeoutErrorCode::SET_UICONTENT_TIMEOUT); } }; handler_->PostTask(task, SET_UICONTENT_TIMEOUT_LISTENER_TASK_NAME + std::to_string(GetPersistentId()), SET_UICONTENT_TIMEOUT_TIME_MS, AppExecFwk::EventQueue::Priority::HIGH); } void WindowSessionImpl::NotifySetUIContentComplete() { if (WindowHelper::IsSubWindow(GetType()) || WindowHelper::IsSystemWindow(GetType())) { // created by UIExtension auto extWindow = FindExtensionWindowWithContext(); if (extWindow != nullptr) { extWindow->SetUIContentComplete(); } } SetUIContentComplete(); } void WindowSessionImpl::SetUIExtensionDestroyComplete() { bool setUIExtensionDestroyCompleted = false; if (setUIExtensionDestroyCompleted_.compare_exchange_strong(setUIExtensionDestroyCompleted, true)) { TLOGI(WmsLogTag::WMS_LIFE, "persistentId=%{public}d", GetPersistentId()); handler_->RemoveTask(SET_UIEXTENSION_DESTROY_TIMEOUT_LISTENER_TASK_NAME + std::to_string(GetPersistentId())); } else { TLOGI(WmsLogTag::WMS_LIFE, "already, persistentId=%{public}d", GetPersistentId()); } } void WindowSessionImpl::SetUIExtensionDestroyCompleteInSubWindow() { if (WindowHelper::IsSubWindow(GetType()) || WindowHelper::IsSystemWindow(GetType())) { bool startUIExtensionDestroyTimer = true; auto extensionWindow = FindExtensionWindowWithContext(); if (extensionWindow != nullptr && extensionWindow->startUIExtensionDestroyTimer_.compare_exchange_strong( startUIExtensionDestroyTimer, false)) { TLOGI(WmsLogTag::WMS_LIFE, "called"); extensionWindow->SetUIExtensionDestroyComplete(); extensionWindow->setUIExtensionDestroyCompleted_.store(false); } } } void WindowSessionImpl::AddSetUIExtensionDestroyTimeoutCheck() { const char* const where = __func__; auto task = [weakThis = wptr(this), where] { auto window = weakThis.promote(); if (window == nullptr) { TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s: window is nullptr", where); return; } if (window->setUIExtensionDestroyCompleted_.load()) { TLOGNI(WmsLogTag::WMS_LIFE, "%{public}s: already, persistentId=%{public}d", where, window->GetPersistentId()); return; } TLOGNI(WmsLogTag::WMS_LIFE, "%{public}s: timeout, persistentId=%{public}d", where, window->GetPersistentId()); std::ostringstream oss; oss << "SetUIExtDestroy timeout uid: " << getuid(); oss << ", windowName: " << window->GetWindowName(); if (window->context_) { oss << ", bundleName: " << window->context_->GetBundleName(); if (window->context_->GetApplicationInfo()) { oss << ", abilityName: " << window->context_->GetApplicationInfo()->name; } } SingletonContainer::Get().ReportWindowException( static_cast(WindowDFXHelperType::WINDOW_TRANSPARENT_CHECK), getpid(), oss.str()); if (WindowHelper::IsUIExtensionWindow(window->GetType())) { window->NotifyExtensionTimeout(TimeoutErrorCode::SET_UIEXTENSION_DESTROY_TIMEOUT); } }; handler_->PostTask(task, SET_UIEXTENSION_DESTROY_TIMEOUT_LISTENER_TASK_NAME + std::to_string(GetPersistentId()), SET_UIEXTENSION_DESTROY_TIMEOUT_TIME_MS, AppExecFwk::EventQueue::Priority::HIGH); startUIExtensionDestroyTimer_.store(true); } WSError WindowSessionImpl::SetEnableDragBySystem(bool enableDrag) { TLOGI(WmsLogTag::WMS_LAYOUT, "enableDrag:%{publlic}d", enableDrag); property_->SetDragEnabled(enableDrag); return WSError::WS_OK; } void WindowSessionImpl::SetTargetAPIVersion(uint32_t targetAPIVersion) { targetAPIVersion_ = targetAPIVersion; } uint32_t WindowSessionImpl::GetTargetAPIVersion() const { return targetAPIVersion_; } } // namespace Rosen } // namespace OHOS