From 20c28b4da40e76702dc88a2d25f4029b78a42ab5 Mon Sep 17 00:00:00 2001 From: w00574628 Date: Mon, 22 Apr 2024 20:45:54 +0800 Subject: [PATCH] Avoid keyboard panel rect and Notify Keyboard panel rect change Signed-off-by: wulehui --- interfaces/innerkits/wm/window.h | 37 ++++ interfaces/innerkits/wm/wm_common.h | 39 ++++ .../include/zidl/session_stage_interface.h | 1 + .../zidl/session_stage_ipc_interface_code.h | 1 + .../include/zidl/session_stage_proxy.h | 1 + .../include/zidl/session_stage_stub.h | 1 + .../src/zidl/session_stage_proxy.cpp | 21 ++ .../container/src/zidl/session_stage_stub.cpp | 16 ++ .../session/host/include/keyboard_session.h | 10 +- .../session/host/include/scb_system_session.h | 5 + .../session/host/include/scene_session.h | 5 +- .../session/host/src/keyboard_session.cpp | 185 +++++++++++------- .../session/host/src/scb_system_session.cpp | 14 ++ .../session/host/src/scene_session.cpp | 27 ++- .../test/unittest/keyboard_session_test.cpp | 74 ------- wm/include/window_scene_session_impl.h | 7 + wm/src/window_scene_session_impl.cpp | 46 +++++ wm/test/unittest/window_test.cpp | 30 +++ 18 files changed, 368 insertions(+), 152 deletions(-) diff --git a/interfaces/innerkits/wm/window.h b/interfaces/innerkits/wm/window.h index 372b978342..0dad880268 100644 --- a/interfaces/innerkits/wm/window.h +++ b/interfaces/innerkits/wm/window.h @@ -445,6 +445,21 @@ public: virtual void OnRectChange(Rect rect, WindowSizeChangeReason reason) {} }; +/** + * @class IKeyboardPanelInfoChangeListener + * + * @brief IKeyboardPanelInfoChangeListener is used to observe the keyboard panel info. + */ +class IKeyboardPanelInfoChangeListener : virtual public RefBase { +public: + /** + * @brief Notify caller when keyboard info changed. + * + * @param KeyboardPanelInfo keyboardPanelInfo of the keyboard panel; + */ + virtual void OnKeyboardPanelInfoChanged(const KeyboardPanelInfo& keyboardPanelInfo) {} +}; + static WMError DefaultCreateErrCode = WMError::WM_OK; class Window : virtual public RefBase { public: @@ -1877,6 +1892,28 @@ public: return WMError::WM_ERROR_DEVICE_NOT_SUPPORT; } + /** + * @brief Register keyboard panel info change listener. + * + * @param listener IKeyboardPanelInfoChangeListener. + * @return WM_OK means register success, others means register failed. + */ + virtual WMError RegisterKeyboardPanelInfoChangeListener(const sptr& listener) + { + return WMError::WM_OK; + } + + /** + * @brief Unregister keyboard panel info change listener. + * + * @param listener IKeyboardPanelInfoChangeListener. + * @return WM_OK means unregister success, others means unregister failed. + */ + virtual WMError UnregisterKeyboardPanelInfoChangeListener(const sptr& listener) + { + return WMError::WM_OK; + } + /** * @brief Get window by id * diff --git a/interfaces/innerkits/wm/wm_common.h b/interfaces/innerkits/wm/wm_common.h index ade0d59117..8606e8bdfa 100644 --- a/interfaces/innerkits/wm/wm_common.h +++ b/interfaces/innerkits/wm/wm_common.h @@ -373,6 +373,7 @@ enum class WindowSessionType : uint32_t { enum class WindowGravity : uint32_t { WINDOW_GRAVITY_FLOAT = 0, WINDOW_GRAVITY_BOTTOM, + WINDOW_GRAVITY_DEFAULT, }; /** @@ -558,6 +559,44 @@ struct Rect { } }; +/** + * @struct KeyboardPanelInfo + * + * @brief Info of keyboard panel + */ +struct KeyboardPanelInfo : public Parcelable { + Rect rect_ = {0, 0, 0, 0}; + WindowGravity gravity_ = WindowGravity::WINDOW_GRAVITY_BOTTOM; + bool isShowing_ = false; + + bool Marshalling(Parcel& parcel) const + { + return parcel.WriteInt32(rect_.posX_) && parcel.WriteInt32(rect_.posY_) && + parcel.WriteUint32(rect_.width_) && parcel.WriteUint32(rect_.height_) && + parcel.WriteUint32(static_cast(gravity_)) && + parcel.WriteBool(isShowing_); + } + + static KeyboardPanelInfo* Unmarshalling(Parcel& parcel) + { + KeyboardPanelInfo* keyboardPanelInfo = new(std::nothrow)KeyboardPanelInfo; + if (keyboardPanelInfo == nullptr) { + return nullptr; + } + bool res = parcel.ReadInt32(keyboardPanelInfo->rect_.posX_) && + parcel.ReadInt32(keyboardPanelInfo->rect_.posY_) && parcel.ReadUint32(keyboardPanelInfo->rect_.width_) && + parcel.ReadUint32(keyboardPanelInfo->rect_.height_); + if (!res) { + delete keyboardPanelInfo; + return nullptr; + } + keyboardPanelInfo->gravity_ = static_cast(parcel.ReadUint32()); + keyboardPanelInfo->isShowing_ = parcel.ReadBool(); + + return keyboardPanelInfo; + } +}; + /** * @brief Enumerates avoid area type. */ diff --git a/window_scene/session/container/include/zidl/session_stage_interface.h b/window_scene/session/container/include/zidl/session_stage_interface.h index a25ab9c064..87f24d7f7c 100644 --- a/window_scene/session/container/include/zidl/session_stage_interface.h +++ b/window_scene/session/container/include/zidl/session_stage_interface.h @@ -113,6 +113,7 @@ public: { return WSError::WS_OK; } + virtual void NotifyKeyboardPanelInfoChange(const KeyboardPanelInfo& keyboardPanelInfo) {} }; } // namespace OHOS::Rosen #endif // OHOS_WINDOW_SCENE_SESSION_STAGE_INTERFACE_H diff --git a/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h b/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h index 42a2f7e329..7050e97c56 100644 --- a/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h +++ b/window_scene/session/container/include/zidl/session_stage_ipc_interface_code.h @@ -49,6 +49,7 @@ enum class SessionStageInterfaceCode { TRANS_ID_NOTIFY_DISPLAYID_CHANGE, TRANS_ID_NOTIFY_DISPLAY_MOVE, TRANS_ID_NOTIFY_SWITCH_FREEMULTIWINDOW, + TRANS_ID_NOTIFY_KEYBOARD_INFO_CHANGE, }; } // namespace Rosen } // namespace OHOS diff --git a/window_scene/session/container/include/zidl/session_stage_proxy.h b/window_scene/session/container/include/zidl/session_stage_proxy.h index 1b839f6caa..69b7686eca 100644 --- a/window_scene/session/container/include/zidl/session_stage_proxy.h +++ b/window_scene/session/container/include/zidl/session_stage_proxy.h @@ -59,6 +59,7 @@ public: WSError UpdateDisplayId(uint64_t displayId) override; void NotifyDisplayMove(DisplayId from, DisplayId to) override; WSError SwitchFreeMultiWindow(bool enable) override; + void NotifyKeyboardPanelInfoChange(const KeyboardPanelInfo& keyboardPanelInfo) override; private: static inline BrokerDelegator delegator_; diff --git a/window_scene/session/container/include/zidl/session_stage_stub.h b/window_scene/session/container/include/zidl/session_stage_stub.h index 7d67d0a40a..d76d33e039 100644 --- a/window_scene/session/container/include/zidl/session_stage_stub.h +++ b/window_scene/session/container/include/zidl/session_stage_stub.h @@ -64,6 +64,7 @@ private: int HandleUpdateDisplayId(MessageParcel& data, MessageParcel& reply); int HandleNotifyDisplayMove(MessageParcel& data, MessageParcel& reply); int HandleSwitchFreeMultiWindow(MessageParcel& data, MessageParcel& reply); + int HandleNotifyKeyboardPanelInfoChange(MessageParcel& data, MessageParcel& reply); }; } // namespace OHOS::Rosen #endif // OHOS_WINDOW_SCENE_SESSION_STAGE_STUB_H diff --git a/window_scene/session/container/src/zidl/session_stage_proxy.cpp b/window_scene/session/container/src/zidl/session_stage_proxy.cpp index af0e4eab2c..b1f312dd25 100644 --- a/window_scene/session/container/src/zidl/session_stage_proxy.cpp +++ b/window_scene/session/container/src/zidl/session_stage_proxy.cpp @@ -681,4 +681,25 @@ void SessionStageProxy::NotifyDisplayMove(DisplayId from, DisplayId to) } } +void SessionStageProxy::NotifyKeyboardPanelInfoChange(const KeyboardPanelInfo& keyboardPanelInfo) +{ + MessageParcel data; + MessageParcel reply; + MessageOption option(MessageOption::TF_ASYNC); + if (!data.WriteInterfaceToken(GetDescriptor())) { + TLOGE(WmsLogTag::WMS_KEYBOARD, "WriteInterfaceToken failed"); + return; + } + + if (!data.WriteParcelable(&keyboardPanelInfo)) { + TLOGE(WmsLogTag::WMS_KEYBOARD, "KeyboardPanelInfo marshalling failed"); + return; + } + + if (Remote()->SendRequest(static_cast(SessionStageInterfaceCode::TRANS_ID_NOTIFY_KEYBOARD_INFO_CHANGE), + data, reply, option) != ERR_NONE) { + TLOGE(WmsLogTag::WMS_KEYBOARD, "SendRequest notify keyboard panel info change failed"); + return; + } +} } // namespace OHOS::Rosen diff --git a/window_scene/session/container/src/zidl/session_stage_stub.cpp b/window_scene/session/container/src/zidl/session_stage_stub.cpp index fe231769b1..31f6e88802 100644 --- a/window_scene/session/container/src/zidl/session_stage_stub.cpp +++ b/window_scene/session/container/src/zidl/session_stage_stub.cpp @@ -81,6 +81,8 @@ const std::map SessionStageStub::stubFuncMap_{ &SessionStageStub::HandleNotifyDisplayMove), std::make_pair(static_cast(SessionStageInterfaceCode::TRANS_ID_NOTIFY_SWITCH_FREEMULTIWINDOW), &SessionStageStub::HandleSwitchFreeMultiWindow), + std::make_pair(static_cast(SessionStageInterfaceCode::TRANS_ID_NOTIFY_KEYBOARD_INFO_CHANGE), + &SessionStageStub::HandleNotifyKeyboardPanelInfoChange), }; int SessionStageStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) @@ -376,6 +378,20 @@ int SessionStageStub::HandleSwitchFreeMultiWindow(MessageParcel& data, MessagePa bool enable = data.ReadBool(); WSError errCode = SwitchFreeMultiWindow(enable); reply.WriteInt32(static_cast(errCode)); + + return ERR_NONE; +} + +int SessionStageStub::HandleNotifyKeyboardPanelInfoChange(MessageParcel& data, MessageParcel& reply) +{ + TLOGD(WmsLogTag::WMS_KEYBOARD, "HandleNotifyKeyboardPanelInfoChange!"); + sptr keyboardPanelInfo = data.ReadParcelable(); + if (keyboardPanelInfo == nullptr) { + TLOGE(WmsLogTag::WMS_KEYBOARD, "keyboardPanelInfo is nullptr!"); + return ERR_INVALID_VALUE; + } + NotifyKeyboardPanelInfoChange(*keyboardPanelInfo); + return ERR_NONE; } } // namespace OHOS::Rosen diff --git a/window_scene/session/host/include/keyboard_session.h b/window_scene/session/host/include/keyboard_session.h index 9c79fd626d..ccb58e1dac 100644 --- a/window_scene/session/host/include/keyboard_session.h +++ b/window_scene/session/host/include/keyboard_session.h @@ -42,6 +42,7 @@ public: void BindKeyboardPanelSession(sptr panelSession) override; sptr GetKeyboardPanelSession() const override; SessionGravity GetKeyboardGravity() const override; + void OnKeyboardPanelUpdated() override; private: sptr GetSceneSession(uint32_t persistentId); @@ -49,22 +50,21 @@ private: WSError SetKeyboardSessionGravity(SessionGravity gravity, uint32_t percent) override; void SetCallingSessionId(uint32_t callingSessionId) override; - sptr GetCallingSession(); + uint32_t GetCallingSessionId(); bool IsStatusBarVisible(const sptr& session); int32_t GetStatusBarHeight(); void NotifyOccupiedAreaChangeInfo(const sptr& callingSession, const WSRect& rect, const WSRect& occupiedArea); - void RaiseCallingSession(bool isKeyboardUpdated = false); + void RaiseCallingSession(); void RestoreCallingSession(); void UseFocusIdIfCallingSessionIdInvalid(); - void OnKeyboardSessionShown(); void UpdateCallingSessionIdAndPosition(uint32_t callingSessionId); void RelayoutKeyBoard(); + void NotifyKeyboardPanelInfoChange(WSRect rect, bool isKeyboardPanelShow); + bool CheckIfNeedRaiseCallingSession(sptr callingSession, bool isCallingSessionFloating); sptr keyboardCallback_ = nullptr; - WSRect callingSessionRestoringRect_ = {0, 0, 0, 0}; - WSRect callingSessionRaisedRect_ = {0, 0, 0, 0}; }; } // namespace OHOS::Rosen #endif // OHOS_ROSEN_WINDOW_SCENE_KEYBOARD_SESSION_H \ No newline at end of file diff --git a/window_scene/session/host/include/scb_system_session.h b/window_scene/session/host/include/scb_system_session.h index 614f08ceac..0a12b4e0f3 100644 --- a/window_scene/session/host/include/scb_system_session.h +++ b/window_scene/session/host/include/scb_system_session.h @@ -19,6 +19,7 @@ #include "session/host/include/scene_session.h" namespace OHOS::Rosen { +using KeyboardPanelRectUpdateCallback = std::function; class SCBSystemSession : public SceneSession { public: SCBSystemSession(const SessionInfo& info, const sptr& specificCallback); @@ -34,9 +35,13 @@ public: WSError SetSystemSceneBlockingFocus(bool blocking) override; void BindKeyboardSession(sptr session) override; sptr GetKeyboardSession() const override; + void SetKeyboardPanelRectUpdateCallback(const KeyboardPanelRectUpdateCallback& func); protected: void UpdatePointerArea(const WSRect& rect) override; + +private: + KeyboardPanelRectUpdateCallback keyboardPanelRectUpdateCallback_; }; } // namespace OHOS::Rosen #endif // OHOS_ROSEN_WINDOW_SCENE_SCB_SYSTEM_SESSION_H diff --git a/window_scene/session/host/include/scene_session.h b/window_scene/session/host/include/scene_session.h index 4e82f5cad5..cb6ef2aceb 100644 --- a/window_scene/session/host/include/scene_session.h +++ b/window_scene/session/host/include/scene_session.h @@ -130,6 +130,7 @@ public: virtual void BindKeyboardSession(sptr session) {}; virtual sptr GetKeyboardSession() const { return nullptr; }; virtual SessionGravity GetKeyboardGravity() const { return SessionGravity::SESSION_GRAVITY_DEFAULT; }; + virtual void OnKeyboardPanelUpdated() {}; WSError UpdateActiveStatus(bool isActive) override; WSError OnSessionEvent(SessionEvent event) override; @@ -185,6 +186,7 @@ public: void SetAbilitySessionInfo(std::shared_ptr abilityInfo); void SetWindowDragHotAreaListener(const NotifyWindowDragHotAreaFunc& func); void SetSessionRectChangeCallback(const NotifySessionRectChangeFunc& func); + void SetRestoringRectForKeyboard(WSRect rect); int32_t GetCollaboratorType() const; sptr GetSelfToken() const; @@ -199,6 +201,7 @@ public: std::shared_ptr GetAbilityInfo() const; const std::string& GetWindowNameAllType() const; PiPTemplateInfo GetPiPTemplateInfo() const; + WSRect GetRestoringRectForKeyboard() const; bool IsVisible() const; bool IsDecorEnable() const; @@ -256,7 +259,6 @@ public: WSError UpdateRectChangeListenerRegistered(bool isRegister) override; void SetForceHideState(bool hideFlag); bool GetForceHideState() const; - int32_t GetCustomDecorHeight() override { return customDecorHeight_; @@ -328,6 +330,7 @@ private: std::map extWindowFlagsMap_; bool forceHideState_ = false; int32_t customDecorHeight_ = 0; + WSRect restoringRectForKeyboard_ = {0, 0, 0, 0}; }; } // namespace OHOS::Rosen #endif // OHOS_ROSEN_WINDOW_SCENE_SCENE_SESSION_H \ No newline at end of file diff --git a/window_scene/session/host/src/keyboard_session.cpp b/window_scene/session/host/src/keyboard_session.cpp index d41c396846..b4abf71560 100644 --- a/window_scene/session/host/src/keyboard_session.cpp +++ b/window_scene/session/host/src/keyboard_session.cpp @@ -73,9 +73,13 @@ WSError KeyboardSession::Show(sptr property) return WSError::WS_ERROR_DESTROYED_OBJECT; } - TLOGI(WmsLogTag::WMS_KEYBOARD, "Show keyboard session, id: %{public}d", session->GetPersistentId()); auto ret = session->SceneSession::Foreground(property); - session->OnKeyboardSessionShown(); + session->UseFocusIdIfCallingSessionIdInvalid(); + TLOGI(WmsLogTag::WMS_KEYBOARD, "Show keyboard session, id: %{public}d, calling session id: %{public}d", + session->GetPersistentId(), session->GetCallingSessionId()); + if (!session->isKeyboardPanelEnabled_) { + session->RaiseCallingSession(); + } return ret; }; PostTask(task, "Show"); @@ -99,6 +103,8 @@ WSError KeyboardSession::Hide() return ret; } ret = session->SceneSession::Background(); + WSRect rect = {0, 0, 0, 0}; + session->NotifyKeyboardPanelInfoChange(rect, false); session->RestoreCallingSession(); if (session->GetSessionProperty()) { session->GetSessionProperty()->SetCallingSessionId(INVALID_WINDOW_ID); @@ -120,6 +126,8 @@ WSError KeyboardSession::Disconnect(bool isFromClient) TLOGI(WmsLogTag::WMS_KEYBOARD, "Disconnect keyboard session, id: %{public}d, isFromClient: %{public}d", session->GetPersistentId(), isFromClient); session->SceneSession::Disconnect(isFromClient); + WSRect rect = {0, 0, 0, 0}; + session->NotifyKeyboardPanelInfoChange(rect, false); session->RestoreCallingSession(); if (session->GetSessionProperty()) { session->GetSessionProperty()->SetCallingSessionId(INVALID_WINDOW_ID); @@ -138,9 +146,11 @@ WSError KeyboardSession::NotifyClientToUpdateRect(std::shared_ptr if (ret != WSError::WS_OK) { return ret; } - session->RaiseCallingSession(true); - if (session->specificCallback_ != nullptr && session->specificCallback_->onUpdateAvoidArea_ != nullptr) { - session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId()); + if (!session->isKeyboardPanelEnabled_) { + session->RaiseCallingSession(); + if (session->specificCallback_ != nullptr && session->specificCallback_->onUpdateAvoidArea_ != nullptr) { + session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId()); + } } if (session->reason_ != SizeChangeReason::DRAG) { session->reason_ = SizeChangeReason::UNDEFINED; @@ -152,6 +162,19 @@ WSError KeyboardSession::NotifyClientToUpdateRect(std::shared_ptr return WSError::WS_OK; } +void KeyboardSession::OnKeyboardPanelUpdated() +{ + if (!isKeyboardPanelEnabled_) { + TLOGI(WmsLogTag::WMS_KEYBOARD, "KeyboardPanel is not enabled"); + return; + } + TLOGI(WmsLogTag::WMS_KEYBOARD, "id: %{public}d", GetPersistentId()); + RaiseCallingSession(); + if (specificCallback_ != nullptr && specificCallback_->onUpdateAvoidArea_ != nullptr) { + specificCallback_->onUpdateAvoidArea_(GetPersistentId()); + } +} + WSError KeyboardSession::SetKeyboardSessionGravity(SessionGravity gravity, uint32_t percent) { auto task = [weakThis = wptr(this), gravity, percent]() -> WSError { @@ -177,7 +200,7 @@ WSError KeyboardSession::SetKeyboardSessionGravity(SessionGravity gravity, uint3 } } else { session->SetWindowAnimationFlag(true); - if (session->IsSessionForeground()) { + if (session->IsSessionForeground() && !session->isKeyboardPanelEnabled_) { session->RaiseCallingSession(); } } @@ -191,13 +214,21 @@ void KeyboardSession::SetCallingSessionId(uint32_t callingSessionId) { TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session id: %{public}d", callingSessionId); UpdateCallingSessionIdAndPosition(callingSessionId); - if (keyboardCallback_ == nullptr || keyboardCallback_->onCallingSessionIdChange_ == nullptr || - GetSessionProperty() == nullptr) { - TLOGE(WmsLogTag::WMS_KEYBOARD, "KeyboardCallback_ or sessionProperty is null, callingSessionId: %{public}d", + if (keyboardCallback_ == nullptr || keyboardCallback_->onCallingSessionIdChange_ == nullptr) { + TLOGE(WmsLogTag::WMS_KEYBOARD, "KeyboardCallback_, callingSessionId: %{public}d", callingSessionId); return; } - keyboardCallback_->onCallingSessionIdChange_(GetSessionProperty()->GetCallingSessionId()); + keyboardCallback_->onCallingSessionIdChange_(GetCallingSessionId()); +} + +uint32_t KeyboardSession::GetCallingSessionId() +{ + if (GetSessionProperty() == nullptr) { + TLOGE(WmsLogTag::WMS_KEYBOARD, "Session property is null"); + return INVALID_SESSION_ID; + } + return GetSessionProperty()->GetCallingSessionId(); } sptr KeyboardSession::GetSceneSession(uint32_t persistentId) @@ -279,100 +310,126 @@ void KeyboardSession::NotifyOccupiedAreaChangeInfo(const sptr& cal callingSession->NotifyOccupiedAreaChangeInfo(info); } -sptr KeyboardSession::GetCallingSession() +void KeyboardSession::NotifyKeyboardPanelInfoChange(WSRect rect, bool isKeyboardPanelShow) { - sptr callingSession = nullptr; - if (GetSessionProperty() != nullptr) { - callingSession = GetSceneSession(GetSessionProperty()->GetCallingSessionId()); + if (!isKeyboardPanelEnabled_) { + TLOGI(WmsLogTag::WMS_KEYBOARD, "KeyboardPanel is not enabled"); + return; } + if (!sessionStage_) { + TLOGE(WmsLogTag::WMS_KEYBOARD, "sessionStage_ is nullptr, notify keyboard panel rect change failed"); + return; + } + KeyboardPanelInfo keyboardPanelInfo; + keyboardPanelInfo.rect_ = SessionHelper::TransferToRect(rect); + keyboardPanelInfo.gravity_ = static_cast(GetKeyboardGravity()); + keyboardPanelInfo.isShowing_ = isKeyboardPanelShow; - return callingSession; + sessionStage_->NotifyKeyboardPanelInfoChange(keyboardPanelInfo); } -void KeyboardSession::RaiseCallingSession(bool isKeyboardUpdated) +bool KeyboardSession::CheckIfNeedRaiseCallingSession(sptr callingSession, bool isCallingSessionFloating) { - sptr callingSession = GetCallingSession(); if (callingSession == nullptr) { TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session is nullptr"); - return; + return false; } - SessionGravity gravity = SessionGravity::SESSION_GRAVITY_DEFAULT; - uint32_t percent = 0; - GetSessionProperty()->GetSessionGravity(gravity, percent); + + SessionGravity gravity = GetKeyboardGravity(); if (gravity == SessionGravity::SESSION_GRAVITY_FLOAT) { TLOGI(WmsLogTag::WMS_KEYBOARD, "No need to raise calling session, gravity: %{public}d", gravity); - return; + return false; } - - WSRect callingSessionRect = callingSession->GetSessionRect(); - bool isCallingSessionFloating = (callingSession->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING); bool isMainOrParentFloating = WindowHelper::IsMainWindow(callingSession->GetWindowType()) || (WindowHelper::IsSubWindow(callingSession->GetWindowType()) && callingSession->GetParentSession() != nullptr && callingSession->GetParentSession()->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING); if (isCallingSessionFloating && isMainOrParentFloating && (system::GetParameter("const.product.devicetype", "unknown") == "phone" || system::GetParameter("const.product.devicetype", "unknown") == "tablet")) { - return; + TLOGI(WmsLogTag::WMS_KEYBOARD, "No need to raise calling session in float window."); + return false; } - if (isKeyboardUpdated && isCallingSessionFloating) { - callingSessionRect = callingSessionRestoringRect_; + return true; +} + +void KeyboardSession::RaiseCallingSession() +{ + sptr callingSession = GetSceneSession(GetCallingSessionId()); + if (callingSession == nullptr) { + TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session is nullptr"); + return; } - const WSRect& keyboardSessionRect = (GetSessionRect().height_ != 0) ? GetSessionRect() : GetSessionRequestRect(); - if (SessionHelper::IsEmptyRect(SessionHelper::GetOverlap(keyboardSessionRect, callingSessionRect, 0, 0))) { - TLOGI(WmsLogTag::WMS_KEYBOARD, "No overlap area, keyboardRect: %{public}s, callingSessionRect: %{public}s", - keyboardSessionRect.ToString().c_str(), callingSessionRect.ToString().c_str()); + WSRect keyboardPanelRect = {0, 0, 0, 0}; + if (!isKeyboardPanelEnabled_) { + keyboardPanelRect = (GetSessionRect().height_ != 0) ? GetSessionRect() : GetSessionRequestRect(); + } else if (keyboardPanelSession_ != nullptr) { + keyboardPanelRect = keyboardPanelSession_->GetSessionRect(); + NotifyKeyboardPanelInfoChange(keyboardPanelRect, true); + } + + bool isCallingSessionFloating = (callingSession->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING); + if (!CheckIfNeedRaiseCallingSession(callingSession, isCallingSessionFloating)) { return; } - if (!isKeyboardUpdated) { - callingSessionRestoringRect_ = callingSessionRect; + WSRect callingSessionRect = callingSession->GetSessionRect(); + WSRect callingSessionRestoringRect = callingSession->GetRestoringRectForKeyboard(); + if (!SessionHelper::IsEmptyRect(callingSessionRestoringRect) && isCallingSessionFloating) { + callingSessionRect = callingSessionRestoringRect; + } + if (SessionHelper::IsEmptyRect(SessionHelper::GetOverlap(keyboardPanelRect, callingSessionRect, 0, 0)) && + SessionHelper::IsEmptyRect(callingSessionRestoringRect)) { + TLOGI(WmsLogTag::WMS_KEYBOARD, "No overlap area, keyboardRect: %{public}s, callingRect: %{public}s", + keyboardPanelRect.ToString().c_str(), callingSessionRect.ToString().c_str()); + return; + } + if (SessionHelper::IsEmptyRect(callingSessionRestoringRect)) { + callingSessionRestoringRect = callingSessionRect; + callingSession->SetRestoringRectForKeyboard(callingSessionRect); } WSRect newRect = callingSessionRect; int32_t statusHeight = GetStatusBarHeight(); if (isCallingSessionFloating && callingSessionRect.posY_ > statusHeight) { - // calculate new rect of calling window - newRect.posY_ = std::max(keyboardSessionRect.posY_ - static_cast(newRect.height_), statusHeight); - NotifyOccupiedAreaChangeInfo(callingSession, newRect, keyboardSessionRect); + // calculate new rect of calling session + newRect.posY_ = std::max(keyboardPanelRect.posY_ - static_cast(newRect.height_), statusHeight); + newRect.posY_ = std::min(callingSessionRestoringRect.posY_, newRect.posY_); + NotifyOccupiedAreaChangeInfo(callingSession, newRect, keyboardPanelRect); callingSession->UpdateSessionRect(newRect, SizeChangeReason::UNDEFINED); - callingSessionRaisedRect_ = newRect; } else { - NotifyOccupiedAreaChangeInfo(callingSession, newRect, keyboardSessionRect); + NotifyOccupiedAreaChangeInfo(callingSession, newRect, keyboardPanelRect); } - TLOGI(WmsLogTag::WMS_KEYBOARD, "keyboardRect: %{public}s, OriCallingRect: %{public}s, NewCallingRect: %{public}s" - ", callingRestoreRect_: %{public}s, isCallingSessionFloating: %{public}d, isKeyboardUpdated: %{public}d", - keyboardSessionRect.ToString().c_str(), callingSessionRect.ToString().c_str(), newRect.ToString().c_str(), - callingSessionRestoringRect_.ToString().c_str(), isCallingSessionFloating, isKeyboardUpdated); + + TLOGI(WmsLogTag::WMS_KEYBOARD, "keyboardRect: %{public}s, CallSession OriRect: %{public}s, NewRect: %{public}s" + ", RestoreRect_: %{public}s, isCallingSessionFloating: %{public}d", + keyboardPanelRect.ToString().c_str(), callingSessionRect.ToString().c_str(), newRect.ToString().c_str(), + callingSessionRestoringRect.ToString().c_str(), isCallingSessionFloating); } void KeyboardSession::RestoreCallingSession() { - sptr callingSession = GetCallingSession(); + sptr callingSession = GetSceneSession(GetCallingSessionId()); if (callingSession == nullptr) { TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session is nullptr"); return; } - - TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session, RestoringRect_: %{public}s, RaisedRect_: %{public}s" - ", curRect_: %{public}s, sessionMode: %{public}d", callingSessionRestoringRect_.ToString().c_str(), - callingSessionRaisedRect_.ToString().c_str(), callingSession->GetSessionRect().ToString().c_str(), - callingSession->GetWindowMode()); - WSRect overlapRect = { 0, 0, 0, 0 }; - NotifyOccupiedAreaChangeInfo(callingSession, callingSessionRestoringRect_, overlapRect); - if (!SessionHelper::IsEmptyRect(callingSessionRestoringRect_) && - callingSession->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && - callingSession->GetSessionRect() == callingSessionRaisedRect_) { - callingSession->UpdateSessionRect(callingSessionRestoringRect_, SizeChangeReason::UNDEFINED); + WSRect callingSessionRestoringRect = callingSession->GetRestoringRectForKeyboard(); + TLOGI(WmsLogTag::WMS_KEYBOARD, "callingSessionRestoringRect: %{public}s, sessionMode: %{public}d", + callingSessionRestoringRect.ToString().c_str(), callingSession->GetWindowMode()); + WSRect keyboardRect = { 0, 0, 0, 0 }; + NotifyOccupiedAreaChangeInfo(callingSession, callingSessionRestoringRect, keyboardRect); + if (!SessionHelper::IsEmptyRect(callingSessionRestoringRect) && + callingSession->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) { + callingSession->UpdateSessionRect(callingSessionRestoringRect, SizeChangeReason::UNDEFINED); } - callingSessionRestoringRect_ = { 0, 0, 0, 0 }; - callingSessionRaisedRect_ = { 0, 0, 0, 0 }; + callingSession->SetRestoringRectForKeyboard(keyboardRect); } // Use focused session id when calling session id is invalid. void KeyboardSession::UseFocusIdIfCallingSessionIdInvalid() { - if (GetCallingSession() != nullptr) { + if (GetSceneSession(GetCallingSessionId()) != nullptr) { return; } int32_t focusedSessionId = GetFocusedSessionId(); @@ -384,18 +441,6 @@ void KeyboardSession::UseFocusIdIfCallingSessionIdInvalid() } } -void KeyboardSession::OnKeyboardSessionShown() -{ - if (GetSessionProperty() == nullptr) { - TLOGE(WmsLogTag::WMS_KEYBOARD, "Keyboard session property is nullptr, raise calling session failed."); - return; - } - UseFocusIdIfCallingSessionIdInvalid(); - TLOGI(WmsLogTag::WMS_KEYBOARD, "Raise keyboard session, persistentId: %{public}d, callingSessionId: %{public}d", - GetPersistentId(), GetSessionProperty()->GetCallingSessionId()); - RaiseCallingSession(); -} - void KeyboardSession::UpdateCallingSessionIdAndPosition(uint32_t callingSessionId) { if (GetSessionProperty() == nullptr) { diff --git a/window_scene/session/host/src/scb_system_session.cpp b/window_scene/session/host/src/scb_system_session.cpp index c8d05f83d9..4b4e3ae42b 100644 --- a/window_scene/session/host/src/scb_system_session.cpp +++ b/window_scene/session/host/src/scb_system_session.cpp @@ -62,6 +62,10 @@ WSError SCBSystemSession::NotifyClientToUpdateRect(std::shared_ptrspecificCallback_ != nullptr && session->specificCallback_->onUpdateAvoidArea_ != nullptr) { session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId()); } + if (session->GetWindowType() == WindowType::WINDOW_TYPE_KEYBOARD_PANEL && + session->keyboardPanelRectUpdateCallback_ && session->isKeyboardPanelEnabled_) { + session->keyboardPanelRectUpdateCallback_(); + } // clear after use if (session->reason_ != SizeChangeReason::DRAG) { session->reason_ = SizeChangeReason::UNDEFINED; @@ -73,6 +77,10 @@ WSError SCBSystemSession::NotifyClientToUpdateRect(std::shared_ptr session) { @@ -81,6 +89,12 @@ void SCBSystemSession::BindKeyboardSession(sptr session) return; } keyboardSession_ = session; + KeyboardPanelRectUpdateCallback onKeyboardPanelRectUpdate = [this]() { + if (this->keyboardSession_ != nullptr) { + this->keyboardSession_->OnKeyboardPanelUpdated(); + } + }; + SetKeyboardPanelRectUpdateCallback(onKeyboardPanelRectUpdate); TLOGI(WmsLogTag::WMS_KEYBOARD, "Success, id: %{public}d", keyboardSession_->GetPersistentId()); } diff --git a/window_scene/session/host/src/scene_session.cpp b/window_scene/session/host/src/scene_session.cpp index 41e471ce55..d17a58d5a1 100644 --- a/window_scene/session/host/src/scene_session.cpp +++ b/window_scene/session/host/src/scene_session.cpp @@ -911,8 +911,16 @@ void SceneSession::GetKeyboardAvoidArea(WSRect& rect, AvoidArea& avoidArea) if (gravity == SessionGravity::SESSION_GRAVITY_FLOAT) { continue; } - WSRect inputMethodRect = inputMethod->GetSessionRect(); - CalculateAvoidAreaRect(rect, inputMethodRect, avoidArea); + if (isKeyboardPanelEnabled_) { + WSRect keyboardRect = {0, 0, 0, 0}; + if (inputMethod && inputMethod->GetKeyboardPanelSession()) { + keyboardRect = inputMethod->GetKeyboardPanelSession()->GetSessionRect(); + } + CalculateAvoidAreaRect(rect, keyboardRect, avoidArea); + } else { + WSRect inputMethodRect = inputMethod->GetSessionRect(); + CalculateAvoidAreaRect(rect, inputMethodRect, avoidArea); + } } return; @@ -1476,6 +1484,11 @@ void SceneSession::OnMoveDragCallback(const SizeChangeReason& reason) UpdateRect(rect, reason); } if (reason == SizeChangeReason::DRAG_END) { + if (!SessionHelper::IsEmptyRect(GetRestoringRectForKeyboard())) { + TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session is moved and reset restoringRectForKeyboard_"); + WSRect restoringRect = {0, 0, 0, 0}; + SetRestoringRectForKeyboard(restoringRect); + } NotifySessionRectChange(rect, reason); OnSessionEvent(SessionEvent::EVENT_END_MOVE); } @@ -2257,6 +2270,16 @@ void SceneSession::SetLastSafeRect(WSRect rect) return; } +WSRect SceneSession::GetRestoringRectForKeyboard() const +{ + return restoringRectForKeyboard_; +} + +void SceneSession::SetRestoringRectForKeyboard(WSRect rect) +{ + restoringRectForKeyboard_ = rect; +} + bool SceneSession::AddSubSession(const sptr& subSession) { if (subSession == nullptr) { diff --git a/window_scene/test/unittest/keyboard_session_test.cpp b/window_scene/test/unittest/keyboard_session_test.cpp index 9f5ffa9c87..7c26054e23 100644 --- a/window_scene/test/unittest/keyboard_session_test.cpp +++ b/window_scene/test/unittest/keyboard_session_test.cpp @@ -216,35 +216,6 @@ HWTEST_F(KeyboardSessionTest, NotifyOccupiedAreaChangeInfo, Function | SmallTest keyboardSession->NotifyOccupiedAreaChangeInfo(callingSession, rect, occupiedArea); } -/** - * @tc.name: RaiseCallingSession - * @tc.desc: RaiseCallingSession - * @tc.type: FUNC - */ -HWTEST_F(KeyboardSessionTest, RaiseCallingSession, Function | SmallTest | Level1) -{ - SessionInfo info; - info.abilityName_ = "RaiseCallingSession"; - info.bundleName_ = "RaiseCallingSession"; - sptr specificCb = - new (std::nothrow) SceneSession::SpecificSessionCallback(); - EXPECT_NE(specificCb, nullptr); - sptr keyboardCb = - new (std::nothrow) KeyboardSession::KeyboardSessionCallback(); - EXPECT_NE(keyboardCb, nullptr); - sptr keyboardSession = new (std::nothrow) KeyboardSession(info, specificCb, keyboardCb); - EXPECT_NE(keyboardSession, nullptr); - - info.windowType_ = 1; - sptr sceneSession = new (std::nothrow) SceneSession(info, specificCb); - EXPECT_NE(sceneSession, nullptr); - auto id = sceneSession->GetPersistentId(); - EXPECT_NE(id, 0); - - keyboardSession->GetSessionProperty()->SetCallingSessionId(id); - keyboardSession->RaiseCallingSession(); -} - /** * @tc.name: RestoreCallingSession * @tc.desc: RestoreCallingSession @@ -303,35 +274,6 @@ HWTEST_F(KeyboardSessionTest, UseFocusIdIfCallingSessionIdInvalid, Function | Sm keyboardSession->UseFocusIdIfCallingSessionIdInvalid(); } -/** - * @tc.name: OnKeyboardSessionShown - * @tc.desc: OnKeyboardSessionShown - * @tc.type: FUNC - */ -HWTEST_F(KeyboardSessionTest, OnKeyboardSessionShown, Function | SmallTest | Level1) -{ - SessionInfo info; - info.abilityName_ = "OnKeyboardSessionShown"; - info.bundleName_ = "OnKeyboardSessionShown"; - sptr specificCb = - new (std::nothrow) SceneSession::SpecificSessionCallback(); - EXPECT_NE(specificCb, nullptr); - sptr keyboardCb = - new (std::nothrow) KeyboardSession::KeyboardSessionCallback(); - EXPECT_NE(keyboardCb, nullptr); - sptr keyboardSession = new (std::nothrow) KeyboardSession(info, specificCb, keyboardCb); - EXPECT_NE(keyboardSession, nullptr); - - info.windowType_ = 1; - sptr sceneSession = new (std::nothrow) SceneSession(info, specificCb); - EXPECT_NE(sceneSession, nullptr); - auto id = sceneSession->GetPersistentId(); - EXPECT_NE(id, 0); - - keyboardSession->GetSessionProperty()->SetCallingSessionId(id); - keyboardSession->OnKeyboardSessionShown(); -} - /** * @tc.name: UpdateCallingSessionIdAndPosition * @tc.desc: UpdateCallingSessionIdAndPosition @@ -432,22 +374,6 @@ HWTEST_F(KeyboardSessionTest, GetStatusBarHeight, Function | SmallTest | Level1) ASSERT_EQ(statusBarHeight, 0); } -/** - * @tc.name: GetCallingSession - * @tc.desc: GetCallingSession - * @tc.type: FUNC - */ -HWTEST_F(KeyboardSessionTest, GetCallingSession, Function | SmallTest | Level1) -{ - SessionInfo info; - info.abilityName_ = "RelayoutKeyBoard"; - info.bundleName_ = "RelayoutKeyBoard"; - sptr keyboardSession = new (std::nothrow) KeyboardSession(info, nullptr, nullptr); - EXPECT_NE(keyboardSession, nullptr); - - sptr callingSession = keyboardSession->GetCallingSession(); - ASSERT_EQ(callingSession, nullptr); -} } } } diff --git a/wm/include/window_scene_session_impl.h b/wm/include/window_scene_session_impl.h index 2e591d5c96..d5977fc2ff 100644 --- a/wm/include/window_scene_session_impl.h +++ b/wm/include/window_scene_session_impl.h @@ -146,6 +146,8 @@ public: WMError HideNonSecureWindows(bool shouldHide) override; virtual WMError SetWindowMask(const std::vector>& windowMask) override; WSError SwitchFreeMultiWindow(bool enable) override; + void NotifyKeyboardPanelInfoChange(const KeyboardPanelInfo& keyboardPanelInfo) override; + protected: void DestroySubWindow(); WMError CreateAndConnectSpecificSession(); @@ -195,6 +197,11 @@ private: uint32_t setSameSystembarPropertyCnt_ = 0; std::atomic isDefaultDensityEnabled_ = false; uint32_t getAvoidAreaCnt_ = 0; + + WMError RegisterKeyboardPanelInfoChangeListener(const sptr& listener) override; + WMError UnregisterKeyboardPanelInfoChangeListener(const sptr& listener) override; + static std::mutex keyboardPanelInfoChangeListenerMutex_; + sptr keyboardPanelInfoChangeListeners_ = nullptr; }; } // namespace Rosen } // namespace OHOS diff --git a/wm/src/window_scene_session_impl.cpp b/wm/src/window_scene_session_impl.cpp index 779b7e4be6..c657f8ec9e 100644 --- a/wm/src/window_scene_session_impl.cpp +++ b/wm/src/window_scene_session_impl.cpp @@ -76,6 +76,7 @@ constexpr float MIN_GRAY_SCALE = 0.0f; constexpr float MAX_GRAY_SCALE = 1.0f; } uint32_t WindowSceneSessionImpl::maxFloatingWindowSize_ = 1920; +std::mutex WindowSceneSessionImpl::keyboardPanelInfoChangeListenerMutex_; WindowSceneSessionImpl::WindowSceneSessionImpl(const sptr& option) : WindowSessionImpl(option) { @@ -3170,5 +3171,50 @@ bool WindowSceneSessionImpl::IfNotNeedAvoidKeyBoardForSplit() } return true; } + +WMError WindowSceneSessionImpl::RegisterKeyboardPanelInfoChangeListener( + const sptr& listener) +{ + if (!SessionPermission::IsStartedByInputMethod()) { + TLOGI(WmsLogTag::WMS_KEYBOARD, "Listeners_ not registered by inputMethod id: %{public}d", + GetPersistentId()); + return WMError::WM_ERROR_INVALID_PERMISSION; + } + std::lock_guard lockListener(keyboardPanelInfoChangeListenerMutex_); + if (keyboardPanelInfoChangeListeners_ == nullptr) { + TLOGI(WmsLogTag::WMS_KEYBOARD, "Register keyboard Panel info change listener id: %{public}d", + GetPersistentId()); + keyboardPanelInfoChangeListeners_ = listener; + } else { + TLOGE(WmsLogTag::WMS_KEYBOARD, "Keyboard Panel info change, listener already registered"); + return WMError::WM_ERROR_INVALID_OPERATION; + } + + return WMError::WM_OK; +} + +WMError WindowSceneSessionImpl::UnregisterKeyboardPanelInfoChangeListener( + const sptr& listener) +{ + std::lock_guard lockListener(keyboardPanelInfoChangeListenerMutex_); + keyboardPanelInfoChangeListeners_ = nullptr; + TLOGI(WmsLogTag::WMS_KEYBOARD, "UnRegister keyboard Panel info change listener id: %{public}d", GetPersistentId()); + + return WMError::WM_OK; +} + +void WindowSceneSessionImpl::NotifyKeyboardPanelInfoChange(const KeyboardPanelInfo& keyboardPanelInfo) +{ + TLOGI(WmsLogTag::WMS_KEYBOARD, "isKeyboardPanelShown: %{public}d, gravity: %{public}d" + ", rect_: [%{public}d, %{public}d, %{public}d, %{public}d]", keyboardPanelInfo.isShowing_, + keyboardPanelInfo.gravity_, keyboardPanelInfo.rect_.posX_, keyboardPanelInfo.rect_.posY_, + keyboardPanelInfo.rect_.width_, keyboardPanelInfo.rect_.height_); + std::lock_guard lockListener(keyboardPanelInfoChangeListenerMutex_); + if (keyboardPanelInfoChangeListeners_ && keyboardPanelInfoChangeListeners_.GetRefPtr()) { + keyboardPanelInfoChangeListeners_.GetRefPtr()->OnKeyboardPanelInfoChanged(keyboardPanelInfo); + } else { + TLOGI(WmsLogTag::WMS_KEYBOARD, "keyboardPanelInfoChangeListeners_ is unRegistered"); + } +} } // namespace Rosen } // namespace OHOS diff --git a/wm/test/unittest/window_test.cpp b/wm/test/unittest/window_test.cpp index 265b776b3a..a5dcb26981 100644 --- a/wm/test/unittest/window_test.cpp +++ b/wm/test/unittest/window_test.cpp @@ -2336,6 +2336,36 @@ HWTEST_F(WindowTest, UnregisterWindowRectChangeListener, Function | SmallTest | ASSERT_EQ(WMError::WM_OK, window->Destroy()); } +/** + * @tc.name: RegisterKeyboardPanelInfoChangeListener + * @tc.desc: get + * @tc.type: FUNC + */ +HWTEST_F(WindowTest, RegisterKeyboardPanelInfoChangeListener, Function | SmallTest | Level2) +{ + sptr window = new Window(); + ASSERT_NE(nullptr, window); + sptr listener = nullptr; + auto ret = window->RegisterKeyboardPanelInfoChangeListener(listener); + ASSERT_EQ(WMError::WM_OK, ret); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + +/** + * @tc.name: UnregisterKeyboardPanelInfoChangeListener + * @tc.desc: get + * @tc.type: FUNC + */ +HWTEST_F(WindowTest, UnregisterKeyboardPanelInfoChangeListener, Function | SmallTest | Level2) +{ + sptr window = new Window(); + ASSERT_NE(nullptr, window); + sptr listener = nullptr; + auto ret = window->UnregisterKeyboardPanelInfoChangeListener(listener); + ASSERT_EQ(WMError::WM_OK, ret); + ASSERT_EQ(WMError::WM_OK, window->Destroy()); +} + /** * @tc.name: GetTopWindowWithContext * @tc.desc: get -- Gitee