waterfall mode

Signed-off-by: yu <zhangyusi3@huawei.com>
Change-Id: I913c4d67fb902eaae70795adcb311c5bbe3e5010
This commit is contained in:
yu 2024-11-20 02:13:39 +00:00
parent f79d11b6da
commit 42ff5330a7
9 changed files with 266 additions and 9 deletions

View File

@ -441,6 +441,8 @@ enum class SessionEvent : uint32_t {
EVENT_DRAG_START,
EVENT_DRAG,
EVENT_MAXIMIZE_WITHOUT_ANIMATION,
EVENT_MAXIMIZE_WATERFALL,
EVENT_END
};
enum class BrokerStates: uint32_t {

View File

@ -44,6 +44,7 @@ const std::string SESSION_TOUCHABLE_CHANGE_CB = "sessionTouchableChange";
const std::string SESSION_TOP_MOST_CHANGE_CB = "sessionTopmostChange";
const std::string SESSION_MODAL_TYPE_CHANGE_CB = "sessionModalTypeChange";
const std::string MAIN_SESSION_MODAL_TYPE_CHANGE_CB = "mainSessionModalTypeChange";
const std::string SESSION_FULLSCREEN_WATERFALL_MODE_CHANGE_CB = "sessionFullScreenWaterfallModeChange";
const std::string CLICK_CB = "click";
const std::string TERMINATE_SESSION_CB = "terminateSession";
const std::string TERMINATE_SESSION_CB_NEW = "terminateSessionNew";
@ -105,6 +106,8 @@ const std::map<std::string, ListenerFuncType> ListenerFuncMap {
{SESSION_TOP_MOST_CHANGE_CB, ListenerFuncType::SESSION_TOP_MOST_CHANGE_CB},
{SESSION_MODAL_TYPE_CHANGE_CB, ListenerFuncType::SESSION_MODAL_TYPE_CHANGE_CB},
{MAIN_SESSION_MODAL_TYPE_CHANGE_CB, ListenerFuncType::MAIN_SESSION_MODAL_TYPE_CHANGE_CB},
{SESSION_FULLSCREEN_WATERFALL_MODE_CHANGE_CB,
ListenerFuncType::SESSION_FULLSCREEN_WATERFALL_MODE_CHANGE_CB},
{CLICK_CB, ListenerFuncType::CLICK_CB},
{TERMINATE_SESSION_CB, ListenerFuncType::TERMINATE_SESSION_CB},
{TERMINATE_SESSION_CB_NEW, ListenerFuncType::TERMINATE_SESSION_CB_NEW},
@ -1395,6 +1398,25 @@ void JsSceneSession::ProcessMainSessionModalTypeChangeRegister()
TLOGD(WmsLogTag::WMS_HIERARCHY, "register success, persistent id:%{public}d", persistentId_);
}
void JsSceneSession::ProcessSessionFullScreenWaterfallModeChangeRegister()
{
auto session = weakSession_.promote();
if (session == nullptr) {
TLOGE(WmsLogTag::WMS_LAYOUT, "session is nullptr, persistent id: %{public}d", persistentId_);
return;
}
const char* const where = __func__;
session->RegisterFullScreenWaterfallModeChangeCallback([weakThis = wptr(this), where](bool state) {
auto jsSceneSession = weakThis.promote();
if (!jsSceneSession) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "%{public}s jsSceneSession is null", where);
return;
}
jsSceneSession->OnSessionFullScreenWaterfallModeChange(state);
});
TLOGD(WmsLogTag::WMS_LAYOUT, "register success, persistent id: %{public}d", persistentId_);
}
void JsSceneSession::ProcessSessionFocusableChangeRegister()
{
NotifySessionFocusableChangeFunc func = [weakThis = wptr(this)](bool isFocusable) {
@ -2283,6 +2305,9 @@ void JsSceneSession::ProcessRegisterCallback(ListenerFuncType listenerFuncType)
case static_cast<uint32_t>(ListenerFuncType::MAIN_SESSION_MODAL_TYPE_CHANGE_CB):
ProcessMainSessionModalTypeChangeRegister();
break;
case static_cast<uint32_t>(ListenerFuncType::SESSION_FULLSCREEN_WATERFALL_MODE_CHANGE_CB):
ProcessSessionFullScreenWaterfallModeChangeRegister();
break;
case static_cast<uint32_t>(ListenerFuncType::CLICK_CB):
ProcessClickRegister();
break;
@ -3200,6 +3225,28 @@ void JsSceneSession::OnMainSessionModalTypeChange(bool isModal)
taskScheduler_->PostMainThreadTask(task, "OnMainSessionModalTypeChange: " + std::to_string(isModal));
}
void JsSceneSession::OnSessionFullScreenWaterfallModeChange(bool state)
{
const char* const where = __func__;
auto task = [weakThis = wptr(this), persistentId = persistentId_, state, env = env_, where] {
auto jsSceneSession = weakThis.promote();
if (!jsSceneSession || jsSceneSessionMap_.find(persistentId) == jsSceneSessionMap_.end()) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "%{public}s jsSceneSession id: %{public}d has been destroyed",
where, persistentId);
return;
}
auto jsCallBack = jsSceneSession->GetJSCallback(SESSION_FULLSCREEN_WATERFALL_MODE_CHANGE_CB);
if (!jsCallBack) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "%{public}s jsCallBack is nullptr", where);
return;
}
napi_value jsState = CreateJsValue(env, state);
napi_value argv[] = { jsState };
napi_call_function(env, NapiGetUndefined(env), jsCallBack->GetNapiValue(), ArraySize(argv), argv, nullptr);
};
taskScheduler_->PostMainThreadTask(task, __func__);
}
void JsSceneSession::OnClick(bool requestFocus, bool isClick)
{
TLOGD(WmsLogTag::WMS_FOCUS, "[NAPI] id: %{public}d, requestFocus: %{public}u, isClick: %{public}u",

View File

@ -47,6 +47,7 @@ enum class ListenerFuncType : uint32_t {
SESSION_TOP_MOST_CHANGE_CB,
SESSION_MODAL_TYPE_CHANGE_CB,
MAIN_SESSION_MODAL_TYPE_CHANGE_CB,
SESSION_FULLSCREEN_WATERFALL_MODE_CHANGE_CB,
CLICK_CB,
TERMINATE_SESSION_CB,
TERMINATE_SESSION_CB_NEW,
@ -239,6 +240,7 @@ private:
void ProcessMainWindowTopmostChangeRegister();
void ProcessSessionModalTypeChangeRegister();
void ProcessMainSessionModalTypeChangeRegister();
void ProcessSessionFullScreenWaterfallModeChangeRegister();
void ProcessClickRegister();
void ProcessTerminateSessionRegister();
void ProcessTerminateSessionRegisterNew();
@ -297,6 +299,7 @@ private:
void OnMainWindowTopmostChange(bool isTopmost);
void OnSessionModalTypeChange(SubWindowModalType subWindowModalType);
void OnMainSessionModalTypeChange(bool isModal);
void OnSessionFullScreenWaterfallModeChange(bool state);
void OnClick(bool requestFocus, bool isClick);
void TerminateSession(const SessionInfo& info);
void TerminateSessionNew(const SessionInfo& info, bool needStartCaller, bool isFromBroker);

View File

@ -20,6 +20,7 @@
#include <mutex>
#include <shared_mutex>
#include <tuple>
#include <unordered_map>
#include "animation/rs_animation_timing_curve.h"
#include "animation/rs_animation_timing_protocol.h"
@ -33,6 +34,8 @@ namespace OHOS::Rosen {
class SceneSession;
using RectRecordsVector =
std::vector<std::pair<std::chrono::time_point<std::chrono::high_resolution_clock>, WSRect>>;
using FoldScreenStatusChangeCallback = std::function<void(DisplayId displayId,
SuperFoldStatus status, SuperFoldStatus prevStatus)>;
enum class ScreenSide : uint8_t {
EXPAND = 0,
@ -76,6 +79,12 @@ public:
void ApplyArrangeRule(WSRect& rect, WSRect& lastArrangedRect,
const WSRect& limitRect, int32_t titleHeight);
/**
* Fold Screen Status Callback
*/
void RegisterFoldScreenStatusChangeCallback(int32_t persistentId, const std::weak_ptr<FoldScreenStatusChangeCallback>& func);
void UnregisterFoldScreenStatusChangeCallback(int32_t persistentId);
private:
void SetDisplayInfo(DisplayId displayId, SuperFoldStatus status);
void SetDisplayRects(
@ -89,6 +98,7 @@ private:
std::shared_mutex displayInfoMutex_; // protect display infos
DisplayId displayId_ { SCREEN_ID_INVALID };
float vpr_ { 1.5f }; // display vp ratio
SuperFoldStatus prevScreenFoldStatus_ { SuperFoldStatus::UNKNOWN };
SuperFoldStatus screenFoldStatus_ { SuperFoldStatus::UNKNOWN };
std::shared_mutex rectsMutex_; // protect rects
WSRect defaultDisplayRect_;
@ -103,11 +113,19 @@ private:
std::mutex arrangedRectsMutex_;
WSRect defaultArrangedRect_;
WSRect virtualArrangedRect_;
/**
* Fold Screen Status Callback
*/
void ExecuteFoldScreenStatusChangeCallbacks(DisplayId displayId, SuperFoldStatus status, SuperFoldStatus prevStatus);
std::mutex callbackMutex_;
std::unordered_map<int32_t, std::weak_ptr<FoldScreenStatusChangeCallback>> foldScreenStatusChangeCallbacks_;
};
class PcFoldScreenController : public RefBase {
public:
explicit PcFoldScreenController(wptr<SceneSession> weakSession);
explicit PcFoldScreenController(wptr<SceneSession> weakSession, int32_t persistentId);
~PcFoldScreenController();
bool IsHalfFolded(DisplayId displayId);
bool NeedFollowHandAnimation();
void RecordStartMoveRect(const WSRect& rect, bool isStartFullScreen);
@ -122,18 +140,34 @@ public:
RSAnimationTimingProtocol GetThrowSlipTimingProtocol();
RSAnimationTimingCurve GetThrowSlipTimingCurve();
void UpdateFullScreenWaterfallMode(bool state);
inline bool IsFullScreenWaterfallMode() { return isFullScreenWaterfallMode_; }
void RegisterFullScreenWaterfallModeChangeCallback(const std::function<void(bool state)>& func);
void UnregisterFullScreenWaterfallModeChangeCallback();
private:
int32_t GetPersistentId() const;
int32_t GetTitleHeight() const;
WSRectF CalculateMovingVelocity();
wptr<SceneSession> weakSceneSession_ = nullptr;
int32_t persistentId_;
// use queue to calculate velocity
std::mutex moveMutex_;
WSRect startMoveRect_;
bool isStartFullScreen_ { false };
RectRecordsVector movingRectRecords_;
std::shared_ptr<FoldScreenStatusChangeCallback> onFoldScreenStatusChangeCallback_;
/**
* Waterfall Mode
* accessed on SSM thread
*/
void ExecuteFullScreenWaterfallModeChangeCallback();
bool isFullScreenWaterfallMode_ { false };
std::function<void(bool state)> fullScreenWaterfallModeChangeCallback_ { nullptr };
};
} // namespace OHOS::Rosen

View File

@ -105,6 +105,7 @@ struct UIExtensionTokenInfo {
class SceneSession : public Session {
public:
friend class HidumpController;
friend class PcFoldScreenController;
// callback for notify SceneSessionManager
struct SpecificSessionCallback : public RefBase {
SpecificSessionCreateCallback onCreate_;
@ -544,6 +545,12 @@ public:
bool GetGestureBackEnabled();
bool GetEnableGestureBackHadSet();
/**
* PC Fold Screen
*/
void UpdateFullScreenWaterfallMode(bool state);
void RegisterFullScreenWaterfallModeChangeCallback(const std::function<void(bool state)>& func);
/**
* PC Window
*/
@ -626,6 +633,7 @@ protected:
/**
* PC Fold Screen
*/
bool IsFullScreenWaterfallMode();
sptr<PcFoldScreenController> pcFoldScreenController_ = nullptr;
std::atomic_bool throwSlipFullScreenFlag_ = false;

View File

@ -32,7 +32,7 @@ MainSession::MainSession(const SessionInfo& info, const sptr<SpecificSessionCall
// persistentId changed due to id conflicts. Need to rename the old snapshot if exists
scenePersistence_->RenameSnapshotFromOldPersistentId(info.persistentId_);
}
pcFoldScreenController_ = sptr<PcFoldScreenController>::MakeSptr(wptr(this));
pcFoldScreenController_ = sptr<PcFoldScreenController>::MakeSptr(wptr(this), GetPersistentId());
moveDragController_ = sptr<MoveDragController>::MakeSptr(GetPersistentId(), GetWindowType());
if (specificCallback != nullptr &&
specificCallback->onWindowInputPidChangeCallback_ != nullptr) {

View File

@ -66,9 +66,11 @@ void PcFoldScreenManager::SetDisplayInfo(DisplayId displayId, SuperFoldStatus st
}
TLOGI(WmsLogTag::WMS_MAIN, "display: %{public}" PRIu64", fold status: %{public}d",
displayId, static_cast<int32_t>(status));
prevScreenFoldStatus_ = screenFoldStatus_;
screenFoldStatus_ = status;
ResetArrangeRule();
displayId_ = displayId;
ExecuteFoldScreenStatusChangeCallbacks(displayId_, screenFoldStatus_, prevScreenFoldStatus_);
auto display = DisplayManager::GetInstance().GetDisplayById(displayId);
if (display == nullptr) {
TLOGE(WmsLogTag::WMS_MAIN, "Failed to get display");
@ -341,8 +343,71 @@ void PcFoldScreenManager::ApplyArrangeRule(WSRect& rect, WSRect& lastArrangedRec
lastArrangedRect = { rect.posX_, rect.posY_, RULE_TRANS_X * vpr, titleHeight * vpr};
}
PcFoldScreenController::PcFoldScreenController(wptr<SceneSession> weakSession)
: weakSceneSession_(std::move(weakSession)) {}
void PcFoldScreenManager::RegisterFoldScreenStatusChangeCallback(int32_t persistentId,
const std::weak_ptr<FoldScreenStatusChangeCallback>& func)
{
std::unique_lock<std::mutex> lock(callbackMutex_);
TLOGI(WmsLogTag::WMS_LAYOUT, "id: %{public}d", persistentId);
auto iter = foldScreenStatusChangeCallbacks_.find(persistentId);
if (iter != foldScreenStatusChangeCallbacks_.end()) {
TLOGW(WmsLogTag::WMS_LAYOUT, "callback has registered");
foldScreenStatusChangeCallbacks_[persistentId] = func;
return;
}
foldScreenStatusChangeCallbacks_.insert({ persistentId, func });
}
void PcFoldScreenManager::UnregisterFoldScreenStatusChangeCallback(int32_t persistentId)
{
std::unique_lock<std::mutex> lock(callbackMutex_);
TLOGI(WmsLogTag::WMS_LAYOUT, "id: %{public}d", persistentId);
auto iter = foldScreenStatusChangeCallbacks_.find(persistentId);
if (iter == foldScreenStatusChangeCallbacks_.end()) {
TLOGW(WmsLogTag::WMS_LAYOUT, "callback not registered");
return;
}
foldScreenStatusChangeCallbacks_.erase(iter);
}
void PcFoldScreenManager::ExecuteFoldScreenStatusChangeCallbacks(DisplayId displayId, SuperFoldStatus status, SuperFoldStatus prevStatus)
{
std::unique_lock<std::mutex> lock(callbackMutex_);
for (const auto& iter : foldScreenStatusChangeCallbacks_) {
auto callback = iter.second.lock();
if (callback == nullptr) {
TLOGW(WmsLogTag::WMS_LAYOUT, "callback invalid, id: %{public}d", iter.first);
foldScreenStatusChangeCallbacks_.erase(iter.first);
continue;
}
(*callback)(displayId, status, prevStatus);
}
}
PcFoldScreenController::PcFoldScreenController(wptr<SceneSession> weakSession, int32_t persistentId)
: weakSceneSession_(std::move(weakSession)), persistentId_(persistentId)
{
onFoldScreenStatusChangeCallback_ = std::make_shared<FoldScreenStatusChangeCallback>(
[weakThis = wptr(this)](DisplayId displayId, SuperFoldStatus status, SuperFoldStatus prevStatus) {
auto controller = weakThis.promote();
if (controller == nullptr) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "controller is nullptr");
return;
}
if ((prevStatus == SuperFoldStatus::HALF_FOLDED && status == SuperFoldStatus::FOLDED) ||
(prevStatus == SuperFoldStatus::FOLDED && status == SuperFoldStatus::HALF_FOLDED)) {
return;
}
controller->UpdateFullScreenWaterfallMode(false);
}
);
PcFoldScreenManager::GetInstance().RegisterFoldScreenStatusChangeCallback(GetPersistentId(),
static_cast<std::weak_ptr<FoldScreenStatusChangeCallback>>(onFoldScreenStatusChangeCallback_));
}
PcFoldScreenController::~PcFoldScreenController()
{
PcFoldScreenManager::GetInstance().UnregisterFoldScreenStatusChangeCallback(GetPersistentId());
}
bool PcFoldScreenController::IsHalfFolded(DisplayId displayId)
{
@ -448,13 +513,50 @@ RSAnimationTimingCurve PcFoldScreenController::GetThrowSlipTimingCurve()
return PcFoldScreenManager::GetInstance().GetThrowSlipTimingCurve();
}
int32_t PcFoldScreenController::GetPersistentId() const
void PcFoldScreenController::UpdateFullScreenWaterfallMode(bool state)
{
auto task = [weakThis = wptr(this), state] {
auto controller = weakThis.promote();
if (controller == nullptr) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "controller is nullptr");
return;
}
if (controller->isFullScreenWaterfallMode_ == state) {
return;
}
controller->isFullScreenWaterfallMode_ = state;
controller->ExecuteFullScreenWaterfallModeChangeCallback();
};
auto sceneSession = weakSceneSession_.promote();
if (sceneSession == nullptr) {
return INVALID_SESSION_ID;
TLOGE(WmsLogTag::WMS_LAYOUT, "session is nullptr, id: %{public}d", GetPersistentId());
return;
}
return sceneSession->GetPersistentId();
sceneSession->PostTask(task, __func__);
}
void PcFoldScreenController::RegisterFullScreenWaterfallModeChangeCallback(const std::function<void(bool state)>& func)
{
fullScreenWaterfallModeChangeCallback_ = std::move(func);
ExecuteFullScreenWaterfallModeChangeCallback();
}
void PcFoldScreenController::UnregisterFullScreenWaterfallModeChangeCallback()
{
fullScreenWaterfallModeChangeCallback_ = nullptr;
}
void PcFoldScreenController::ExecuteFullScreenWaterfallModeChangeCallback()
{
if (fullScreenWaterfallModeChangeCallback_ == nullptr) {
return;
}
fullScreenWaterfallModeChangeCallback_(isFullScreenWaterfallMode_);
}
int32_t PcFoldScreenController::GetPersistentId() const
{
return persistentId_;
}
/**

View File

@ -621,6 +621,23 @@ WSError SceneSession::OnSessionEvent(SessionEvent event)
return WSError::WS_ERROR_DESTROYED_OBJECT;
}
WLOGFI("[WMSCom] event: %{public}d", static_cast<int32_t>(event));
// update waterfall mode
if (session->pcFoldScreenController_) {
switch (event) {
case SessionEvent::EVENT_MAXIMIZE_WATERFALL:
session->UpdateFullScreenWaterfallMode(
session->pcFoldScreenController_->IsHalfFolded(session->GetScreenId()));
break;
case SessionEvent::EVENT_MAXIMIZE:
case SessionEvent::EVENT_RECOVER:
case SessionEvent::EVENT_SPLIT_PRIMARY:
case SessionEvent::EVENT_SPLIT_SECONDARY:
session->UpdateFullScreenWaterfallMode(false);
break;
default:
break;
}
}
if (event == SessionEvent::EVENT_START_MOVE) {
if (!session->IsMovable()) {
return WSError::WS_OK;
@ -2340,7 +2357,8 @@ bool SceneSession::IsFullScreenMovable()
return false;
}
return property->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN &&
WindowHelper::IsWindowModeSupported(property->GetWindowModeSupportType(), WindowMode::WINDOW_MODE_FLOATING);
WindowHelper::IsWindowModeSupported(property->GetWindowModeSupportType(), WindowMode::WINDOW_MODE_FLOATING) &&
!IsFullScreenWaterfallMode();
}
bool SceneSession::IsMovable()
@ -3994,6 +4012,46 @@ bool SceneSession::GetEnableGestureBackHadSet()
return isEnableGestureBackHadSet_;
}
void SceneSession::UpdateFullScreenWaterfallMode(bool state)
{
auto task = [weakThis = wptr(this), state] {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "session is nullptr");
return;
}
if (session->pcFoldScreenController_ == nullptr) {
return;
}
session->pcFoldScreenController_->UpdateFullScreenWaterfallMode(state);
};
PostTask(task, __func__);
}
bool SceneSession::IsFullScreenWaterfallMode()
{
if (pcFoldScreenController_ == nullptr) {
return false;
}
return pcFoldScreenController_->IsFullScreenWaterfallMode();
}
void SceneSession::RegisterFullScreenWaterfallModeChangeCallback(const std::function<void(bool state)>& func)
{
auto task = [weakThis = wptr(this), func = std::move(func)] {
auto session = weakThis.promote();
if (session == nullptr) {
TLOGNE(WmsLogTag::WMS_LAYOUT, "session is nullptr");
return;
}
if (session->pcFoldScreenController_ == nullptr) {
return;
}
session->pcFoldScreenController_->RegisterFullScreenWaterfallModeChangeCallback(std::move(func));
};
PostTask(task, __func__);
}
void SceneSession::SetSessionChangeByActionNotifyManagerListener(const SessionChangeByActionNotifyManagerFunc& func)
{
TLOGD(WmsLogTag::DEFAULT, "setListener success");
@ -5643,6 +5701,9 @@ void SceneSession::UnregisterSessionChangeListeners()
session->sessionChangeCallback_->onRaiseAboveTarget_ = nullptr;
session->sessionChangeCallback_->onSetLandscapeMultiWindowFunc_ = nullptr;
}
if (session->pcFoldScreenController_) {
session->pcFoldScreenController_->UnregisterFullScreenWaterfallModeChangeCallback();
}
session->Session::UnregisterSessionChangeListeners();
};
PostTask(task, "UnregisterSessionChangeListeners");

View File

@ -433,7 +433,7 @@ int SessionStub::HandleSessionEvent(MessageParcel& data, MessageParcel& reply)
}
TLOGD(WmsLogTag::WMS_EVENT, "eventId: %{public}d", eventId);
if (eventId < static_cast<uint32_t>(SessionEvent::EVENT_MAXIMIZE) ||
eventId > static_cast<uint32_t>(SessionEvent::EVENT_DRAG)) {
eventId >= static_cast<uint32_t>(SessionEvent::EVENT_END)) {
TLOGE(WmsLogTag::WMS_EVENT, "Invalid eventId: %{public}d", eventId);
return ERR_INVALID_DATA;
}