• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "session/host/include/pc_fold_screen_controller.h"
17 #include <hisysevent.h>
18 #include <parameters.h>
19 #include "session/host/include/scene_session.h"
20 #include "window_helper.h"
21 #include "window_manager_hilog.h"
22 #include "wm_common_inner.h"
23 #include "wm_math.h"
24 
25 namespace OHOS::Rosen {
26 
27 namespace {
28 // moving
29 constexpr int32_t MOVING_RECORDS_SIZE_LIMIT = 5;
30 constexpr int32_t MOVING_RECORDS_TIME_LIMIT = 100;
31 constexpr float MOVING_DIRECTLY_BUFF = 2.0f;
32 constexpr WSRect ZERO_RECT = { 0, 0, 0, 0 };
33 constexpr WSRectF ZERO_RECTF = { 0.0f, 0.0f, 0.0f, 0.0f };
34 
35 // arrange rule
36 constexpr int32_t MIN_DECOR_HEIGHT = 37;
37 constexpr int32_t MAX_DECOR_HEIGHT = 112;
38 } // namespace
39 
PcFoldScreenController(wptr<SceneSession> weakSession,int32_t persistentId)40 PcFoldScreenController::PcFoldScreenController(wptr<SceneSession> weakSession, int32_t persistentId)
41     : weakSceneSession_(std::move(weakSession)), persistentId_(persistentId) {}
42 
~PcFoldScreenController()43 PcFoldScreenController::~PcFoldScreenController()
44 {
45     PcFoldScreenManager::GetInstance().UnregisterFoldScreenStatusChangeCallback(GetPersistentId());
46     PcFoldScreenManager::GetInstance().UnregisterSystemKeyboardStatusChangeCallback(GetPersistentId());
47 }
48 
OnConnect()49 void PcFoldScreenController::OnConnect()
50 {
51     onFoldScreenStatusChangeCallback_ = std::make_shared<FoldScreenStatusChangeCallback>(
52         [weakThis = wptr(this)](DisplayId displayId, SuperFoldStatus status, SuperFoldStatus prevStatus) {
53             auto controller = weakThis.promote();
54             if (controller == nullptr) {
55                 TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "controller is nullptr");
56                 return;
57             }
58             auto sceneSession = controller->weakSceneSession_.promote();
59             if (sceneSession == nullptr) {
60                 TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", controller->GetPersistentId());
61                 return;
62             }
63             sceneSession->PostTask([weakThis, displayId, status, prevStatus] {
64                 auto controller = weakThis.promote();
65                 if (controller == nullptr) {
66                     TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "controller is nullptr");
67                     return;
68                 }
69                 if (status != prevStatus) {
70                     controller->UpdateRect();
71                 }
72                 controller->FoldStatusChangeForFullScreenWaterfallMode(displayId, status, prevStatus);
73                 controller->FoldStatusChangeForSupportEnterWaterfallMode(displayId, status, prevStatus);
74             });
75         }
76     );
77     PcFoldScreenManager::GetInstance().RegisterFoldScreenStatusChangeCallback(GetPersistentId(),
78         std::weak_ptr<FoldScreenStatusChangeCallback>(onFoldScreenStatusChangeCallback_));
79 
80     onSystemKeyboardStatusChangeCallback_ = std::make_shared<SystemKeyboardStatusChangeCallback>(
81         [weakThis = wptr(this)](DisplayId displayId, bool hasSystemKeyboard) {
82             auto controller = weakThis.promote();
83             if (controller == nullptr) {
84                 TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "controller is nullptr");
85                 return;
86             }
87             auto sceneSession = controller->weakSceneSession_.promote();
88             if (sceneSession == nullptr) {
89                 TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", controller->GetPersistentId());
90                 return;
91             }
92             sceneSession->PostTask([weakThis, displayId, hasSystemKeyboard] {
93                 auto controller = weakThis.promote();
94                 if (controller == nullptr) {
95                     TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "controller is nullptr");
96                     return;
97                 }
98                 controller->SystemKeyboardStatusChangeForFullScreenWaterfallMode(displayId, hasSystemKeyboard);
99                 controller->SystemKeyboardStatusChangeForSupportEnterWaterfallMode(displayId, hasSystemKeyboard);
100             });
101         }
102     );
103     PcFoldScreenManager::GetInstance().RegisterSystemKeyboardStatusChangeCallback(GetPersistentId(),
104         std::weak_ptr<SystemKeyboardStatusChangeCallback>(onSystemKeyboardStatusChangeCallback_));
105 
106     supportEnterWaterfallMode_ = IsSupportEnterWaterfallMode(
107         PcFoldScreenManager::GetInstance().GetScreenFoldStatus(GetDisplayId()),
108         PcFoldScreenManager::GetInstance().HasSystemKeyboard());
109     UpdateSupportEnterWaterfallMode();
110 }
111 
IsSupportEnterWaterfallMode(SuperFoldStatus status,bool hasSystemKeyboard) const112 bool PcFoldScreenController::IsSupportEnterWaterfallMode(SuperFoldStatus status, bool hasSystemKeyboard) const
113 {
114     return status == SuperFoldStatus::HALF_FOLDED && !hasSystemKeyboard && !isFullScreenWaterfallMode_;
115 }
116 
FoldStatusChangeForFullScreenWaterfallMode(DisplayId displayId,SuperFoldStatus status,SuperFoldStatus prevStatus)117 void PcFoldScreenController::FoldStatusChangeForFullScreenWaterfallMode(
118     DisplayId displayId, SuperFoldStatus status, SuperFoldStatus prevStatus)
119 {
120     if ((prevStatus == SuperFoldStatus::HALF_FOLDED && status == SuperFoldStatus::FOLDED) ||
121         (prevStatus == SuperFoldStatus::FOLDED && status == SuperFoldStatus::HALF_FOLDED)) {
122         return;
123     }
124     UpdateFullScreenWaterfallMode(false);
125 }
126 
FoldStatusChangeForSupportEnterWaterfallMode(DisplayId displayId,SuperFoldStatus status,SuperFoldStatus prevStatus)127 void PcFoldScreenController::FoldStatusChangeForSupportEnterWaterfallMode(
128     DisplayId displayId, SuperFoldStatus status, SuperFoldStatus prevStatus)
129 {
130     lastSupportEnterWaterfallMode_ = supportEnterWaterfallMode_;
131     supportEnterWaterfallMode_ = IsSupportEnterWaterfallMode(status,
132         PcFoldScreenManager::GetInstance().HasSystemKeyboard());
133     auto sceneSession = weakSceneSession_.promote();
134     if (sceneSession == nullptr) {
135         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", GetPersistentId());
136         return;
137     }
138     if (!sceneSession->IsMissionHighlighted()) {
139         return;
140     }
141     UpdateSupportEnterWaterfallMode();
142 }
143 
SystemKeyboardStatusChangeForFullScreenWaterfallMode(DisplayId displayId,bool hasSystemKeyboard)144 void PcFoldScreenController::SystemKeyboardStatusChangeForFullScreenWaterfallMode(
145     DisplayId displayId, bool hasSystemKeyboard)
146 {
147     UpdateFullScreenWaterfallMode(false);
148 }
149 
SystemKeyboardStatusChangeForSupportEnterWaterfallMode(DisplayId displayId,bool hasSystemKeyboard)150 void PcFoldScreenController::SystemKeyboardStatusChangeForSupportEnterWaterfallMode(
151     DisplayId displayId, bool hasSystemKeyboard)
152 {
153     lastSupportEnterWaterfallMode_ = supportEnterWaterfallMode_;
154     supportEnterWaterfallMode_ = IsSupportEnterWaterfallMode(
155         PcFoldScreenManager::GetInstance().GetScreenFoldStatus(displayId), hasSystemKeyboard);
156     auto sceneSession = weakSceneSession_.promote();
157     if (sceneSession == nullptr) {
158         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", GetPersistentId());
159         return;
160     }
161     if (!sceneSession->IsMissionHighlighted()) {
162         return;
163     }
164     UpdateSupportEnterWaterfallMode();
165 }
166 
IsHalfFolded(DisplayId displayId)167 bool PcFoldScreenController::IsHalfFolded(DisplayId displayId)
168 {
169     return PcFoldScreenManager::GetInstance().IsHalfFolded(displayId);
170 }
171 
IsAllowThrowSlip(DisplayId displayId)172 bool PcFoldScreenController::IsAllowThrowSlip(DisplayId displayId)
173 {
174     auto sceneSession = weakSceneSession_.promote();
175     if (sceneSession == nullptr) {
176         return false;
177     }
178     bool sessionValid = WindowHelper::IsMainWindow(sceneSession->GetWindowType()) || sceneSession->IsDecorEnable();
179     return sessionValid && PcFoldScreenManager::GetInstance().IsHalfFolded(displayId) &&
180            !PcFoldScreenManager::GetInstance().HasSystemKeyboard();
181 }
182 
NeedFollowHandAnimation()183 bool PcFoldScreenController::NeedFollowHandAnimation()
184 {
185     static bool needFollowHandAnimation =
186         system::GetParameter("persist.window.throw_slip_follow_animation.enabled", "1") == "1";
187     std::unique_lock<std::mutex> lock(moveMutex_);
188     return needFollowHandAnimation && (!isStartFullScreen_ || movingRectRecords_.size() > 0);
189 }
190 
RecordStartMoveRect(const WSRect & rect,bool isStartFullScreen)191 void PcFoldScreenController::RecordStartMoveRect(const WSRect& rect, bool isStartFullScreen)
192 {
193     TLOGI(WmsLogTag::WMS_LAYOUT, "rect: %{public}s, isStartFullScreen: %{public}d",
194         rect.ToString().c_str(), isStartFullScreen);
195     std::unique_lock<std::mutex> lock(moveMutex_);
196     startMoveRect_ = rect;
197     isStartFullScreen_ = isStartFullScreen;
198     isStartWaterfallMode_ = isFullScreenWaterfallMode_;
199     movingRectRecords_.clear();
200     isStartDirectly_ = false;
201 }
202 
RecordStartMoveRectDirectly(const WSRect & rect,const WSRectF & velocity,bool isStartFullScreen)203 void PcFoldScreenController::RecordStartMoveRectDirectly(const WSRect& rect, const WSRectF& velocity,
204     bool isStartFullScreen)
205 {
206     TLOGI(WmsLogTag::WMS_LAYOUT_PC, "rect: %{public}s, isStartFullScreen: %{public}d, velocity: %{public}s",
207         rect.ToString().c_str(), isStartFullScreen, velocity.ToString().c_str());
208     RecordStartMoveRect(rect, isStartFullScreen);
209     std::unique_lock<std::mutex> lock(moveMutex_);
210     isStartDirectly_ = true;
211     startVelocity_ = velocity;
212     startVelocity_.posY_ *= MOVING_DIRECTLY_BUFF;
213 }
214 
ResetRecords()215 void PcFoldScreenController::ResetRecords()
216 {
217     TLOGD(WmsLogTag::WMS_LAYOUT_PC, "in");
218     std::unique_lock<std::mutex> lock(moveMutex_);
219     startMoveRect_ = ZERO_RECT;
220     isStartFullScreen_ = false;
221     isStartWaterfallMode_ = false;
222     movingRectRecords_.clear();
223     isStartDirectly_ = false;
224     startVelocity_ = ZERO_RECTF;
225 }
226 
IsStartFullScreen()227 bool PcFoldScreenController::IsStartFullScreen()
228 {
229     std::unique_lock<std::mutex> lock(moveMutex_);
230     return isStartFullScreen_;
231 }
232 
RecordMoveRects(const WSRect & rect)233 void PcFoldScreenController::RecordMoveRects(const WSRect& rect)
234 {
235     auto time = std::chrono::high_resolution_clock::now();
236     std::unique_lock<std::mutex> lock(moveMutex_);
237     movingRectRecords_.push_back(std::make_pair(time, rect));
238     TLOGD(WmsLogTag::WMS_LAYOUT, "id: %{public}d, rect: %{public}s", GetPersistentId(), rect.ToString().c_str());
239     // pop useless record
240     while (movingRectRecords_.size() > MOVING_RECORDS_SIZE_LIMIT ||
241            TimeHelper::GetDuration(movingRectRecords_[0].first, time) > MOVING_RECORDS_TIME_LIMIT) {
242         movingRectRecords_.erase(movingRectRecords_.begin());
243     }
244     TLOGD(WmsLogTag::WMS_LAYOUT, "records size: %{public}zu, duration: %{public}f", movingRectRecords_.size(),
245         TimeHelper::GetDuration(movingRectRecords_[0].first, movingRectRecords_[movingRectRecords_.size() - 1].first));
246 }
247 
248 /**
249  * if move fast, window can be throwed to other side
250  * @param rect: current rect. if throwed, move it to other side
251  * @param topAvoidHeight: avoid status bar
252  * @param botAvoidHeight: avoid dock
253  */
ThrowSlip(DisplayId displayId,WSRect & rect,int32_t topAvoidHeight,int32_t botAvoidHeight)254 bool PcFoldScreenController::ThrowSlip(DisplayId displayId, WSRect& rect,
255     int32_t topAvoidHeight, int32_t botAvoidHeight)
256 {
257     auto& manager = PcFoldScreenManager::GetInstance();
258     if (!IsAllowThrowSlip(displayId)) {
259         manager.ResetArrangeRule();
260         return false;
261     }
262     WSRect startRect;
263     bool startFullScreen;
264     bool startWaterfallMode;
265     bool startDirectly;
266     {
267         std::unique_lock<std::mutex> lock(moveMutex_);
268         manager.ResetArrangeRule(startMoveRect_);
269         startRect = startMoveRect_;
270         startFullScreen = isStartFullScreen_;
271         startWaterfallMode = isStartWaterfallMode_;
272         startDirectly = isStartDirectly_;
273     }
274     WSRect titleRect = { rect.posX_, rect.posY_, rect.width_, startDirectly ? rect.height_ : GetTitleHeight() };
275     ScreenSide throwSide = manager.CalculateScreenSide(titleRect);
276     const WSRectF& velocity = CalculateMovingVelocity();
277     if (isFullScreenWaterfallMode_) {
278         throwSide = MathHelper::GreatNotEqual(velocity.posY_, 0.0f) ? ScreenSide::FOLD_B : ScreenSide::FOLD_C;
279     }
280     if ((!startFullScreen && !manager.NeedDoThrowSlip(titleRect, velocity, throwSide)) ||
281         (startFullScreen && !manager.NeedDoEasyThrowSlip(titleRect, startRect, velocity, throwSide))) {
282         manager.ResetArrangeRule(throwSide);
283         TLOGI(WmsLogTag::WMS_LAYOUT_PC, "no throw rect: %{public}s", rect.ToString().c_str());
284         return false;
285     }
286 
287     // correct to start rect and throw
288     if (!startFullScreen) {
289         rect.posX_ = startRect.posX_;
290         rect.posY_ = startRect.posY_;
291     }
292     manager.ThrowSlipToOppositeSide(throwSide, rect, topAvoidHeight, botAvoidHeight, GetTitleHeight());
293     manager.ResetArrangeRule(throwSide);
294 
295     // hisysevent
296     ThrowSlipWindowMode startWindowMode = ThrowSlipWindowMode::FLOAT;
297     if (startFullScreen) {
298         startWindowMode = startWaterfallMode ? ThrowSlipWindowMode::FULLSCREEN_WATERFALLMODE :
299                                                ThrowSlipWindowMode::FULLSCREEN;
300     }
301     ThrowSlipMode throwMode = startDirectly ? ThrowSlipMode::GESTURE : ThrowSlipMode::MOVE;
302     auto sceneSession = weakSceneSession_.promote();
303     std::string bundleName = sceneSession == nullptr ? "" : sceneSession->GetSessionInfo().bundleName_;
304     ThrowSlipHiSysEvent(bundleName, throwSide, startWindowMode, throwMode);
305     TLOGI(WmsLogTag::WMS_LAYOUT_PC, "throw to rect: %{public}s", rect.ToString().c_str());
306     return true;
307 }
308 
ThrowSlipHiSysEvent(const std::string & bundleName,ScreenSide startSide,ThrowSlipWindowMode startWindowMode,ThrowSlipMode throwMode) const309 void PcFoldScreenController::ThrowSlipHiSysEvent(const std::string& bundleName, ScreenSide startSide,
310     ThrowSlipWindowMode startWindowMode, ThrowSlipMode throwMode) const
311 {
312     int32_t ret = HiSysEventWrite(
313         HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
314         "THROW_SLIP",
315         HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
316         "BUNDLE_NAME", bundleName,
317         "START_SIDE", static_cast<int32_t>(startSide),
318         "START_WINDOW_MODE", static_cast<int32_t>(startWindowMode),
319         "THROW_MODE", static_cast<int32_t>(throwMode));
320     if (ret != 0) {
321         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "write hisysevent error, ret: %{public}d", ret);
322     }
323 }
324 
ThrowSlipFloatingRectDirectly(WSRect & rect,const WSRect & floatingRect,int32_t topAvoidHeight,int32_t botAvoidHeight)325 void PcFoldScreenController::ThrowSlipFloatingRectDirectly(WSRect& rect, const WSRect& floatingRect,
326     int32_t topAvoidHeight, int32_t botAvoidHeight)
327 {
328     TLOGD(WmsLogTag::WMS_LAYOUT_PC, "rect: %{public}s, floating rect: %{public}s",
329         rect.ToString().c_str(), floatingRect.ToString().c_str());
330     auto& manager = PcFoldScreenManager::GetInstance();
331     const ScreenSide side = manager.CalculateScreenSide(rect);
332     const ScreenSide floatingSide = manager.CalculateScreenSide(floatingRect);
333     rect = floatingRect;
334     if (side == floatingSide) {
335         return;
336     }
337     manager.ThrowSlipToOppositeSide(floatingSide,
338         rect, topAvoidHeight, botAvoidHeight, GetTitleHeight());
339 }
340 
IsThrowSlipDirectly() const341 bool PcFoldScreenController::IsThrowSlipDirectly() const
342 {
343     std::unique_lock<std::mutex> lock(moveMutex_);
344     return isStartDirectly_;
345 }
346 
347 /**
348  * resize to fullscreen in one side considering avoid area
349  * @param rect: resize in its side
350  */
ResizeToFullScreen(WSRect & rect,int32_t topAvoidHeight,int32_t botAvoidHeight)351 void PcFoldScreenController::ResizeToFullScreen(WSRect& rect, int32_t topAvoidHeight, int32_t botAvoidHeight)
352 {
353     PcFoldScreenManager::GetInstance().ResizeToFullScreen(rect, topAvoidHeight, botAvoidHeight);
354 }
355 
GetMovingTimingProtocol()356 RSAnimationTimingProtocol PcFoldScreenController::GetMovingTimingProtocol()
357 {
358     return PcFoldScreenManager::GetInstance().GetMovingTimingProtocol();
359 }
360 
GetMovingTimingCurve()361 RSAnimationTimingCurve PcFoldScreenController::GetMovingTimingCurve()
362 {
363     return PcFoldScreenManager::GetInstance().GetMovingTimingCurve();
364 }
365 
GetThrowSlipTimingProtocol()366 RSAnimationTimingProtocol PcFoldScreenController::GetThrowSlipTimingProtocol()
367 {
368     return PcFoldScreenManager::GetInstance().GetThrowSlipTimingProtocol();
369 }
370 
GetThrowSlipTimingCurve()371 RSAnimationTimingCurve PcFoldScreenController::GetThrowSlipTimingCurve()
372 {
373     return PcFoldScreenManager::GetInstance().GetThrowSlipTimingCurve();
374 }
375 
UpdateFullScreenWaterfallMode(bool isWaterfallMode)376 void PcFoldScreenController::UpdateFullScreenWaterfallMode(bool isWaterfallMode)
377 {
378     auto sceneSession = weakSceneSession_.promote();
379     if (sceneSession == nullptr) {
380         TLOGE(WmsLogTag::WMS_PC, "session is nullptr, id: %{public}d", GetPersistentId());
381         return;
382     }
383     sceneSession->PostTask([weakThis = wptr(this), isWaterfallMode, where = __func__] {
384         auto controller = weakThis.promote();
385         if (controller == nullptr) {
386             TLOGNE(WmsLogTag::WMS_PC, "controller is nullptr");
387             return;
388         }
389         if (controller->isFullScreenWaterfallMode_ == isWaterfallMode) {
390             return;
391         }
392         if (isWaterfallMode && !controller->supportEnterWaterfallMode_) {
393             TLOGNW(WmsLogTag::WMS_LAYOUT_PC, "%{public}s not support waterfall mode!", where);
394         }
395         controller->isFullScreenWaterfallMode_ = isWaterfallMode;
396         controller->ExecuteFullScreenWaterfallModeChangeCallback();
397         controller->supportEnterWaterfallMode_ = controller->IsSupportEnterWaterfallMode(
398             PcFoldScreenManager::GetInstance().GetScreenFoldStatus(controller->GetDisplayId()),
399             PcFoldScreenManager::GetInstance().HasSystemKeyboard());
400         controller->UpdateSupportEnterWaterfallMode();
401     }, __func__);
402 }
403 
RegisterFullScreenWaterfallModeChangeCallback(std::function<void (bool isWaterfallMode)> && func)404 void PcFoldScreenController::RegisterFullScreenWaterfallModeChangeCallback(
405     std::function<void(bool isWaterfallMode)>&& func)
406 {
407     fullScreenWaterfallModeChangeCallback_ = std::move(func);
408     ExecuteFullScreenWaterfallModeChangeCallback();
409 }
410 
UnregisterFullScreenWaterfallModeChangeCallback()411 void PcFoldScreenController::UnregisterFullScreenWaterfallModeChangeCallback()
412 {
413     fullScreenWaterfallModeChangeCallback_ = nullptr;
414 }
415 
MaskSupportEnterWaterfallMode()416 void PcFoldScreenController::MaskSupportEnterWaterfallMode()
417 {
418     maskSupportEnterWaterfallMode_ = true;
419     auto sceneSession = weakSceneSession_.promote();
420     if (sceneSession == nullptr) {
421         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session unavailable, id: %{public}d", GetPersistentId());
422         return;
423     }
424     sceneSession->SetSupportEnterWaterfallMode(false);
425 }
426 
UpdateSupportEnterWaterfallMode()427 void PcFoldScreenController::UpdateSupportEnterWaterfallMode()
428 {
429     TLOGD(WmsLogTag::WMS_LAYOUT_PC, "last: %{public}d, curr: %{public}d",
430         lastSupportEnterWaterfallMode_, supportEnterWaterfallMode_);
431     if (maskSupportEnterWaterfallMode_ || (lastSupportEnterWaterfallMode_ == supportEnterWaterfallMode_)) {
432         return;
433     }
434     auto sceneSession = weakSceneSession_.promote();
435     if (sceneSession == nullptr) {
436         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session unavailable, id: %{public}d", GetPersistentId());
437         return;
438     }
439     lastSupportEnterWaterfallMode_ = supportEnterWaterfallMode_;
440     sceneSession->SetSupportEnterWaterfallMode(supportEnterWaterfallMode_);
441 }
442 
ExecuteFullScreenWaterfallModeChangeCallback()443 void PcFoldScreenController::ExecuteFullScreenWaterfallModeChangeCallback()
444 {
445     if (fullScreenWaterfallModeChangeCallback_ == nullptr) {
446         return;
447     }
448     fullScreenWaterfallModeChangeCallback_(isFullScreenWaterfallMode_);
449     // notify client
450     auto sceneSession = weakSceneSession_.promote();
451     if (sceneSession == nullptr) {
452         TLOGE(WmsLogTag::WMS_LAYOUT, "session is nullptr, id: %{public}d", GetPersistentId());
453         return;
454     }
455     if (sceneSession->sessionStage_ == nullptr) {
456         TLOGE(WmsLogTag::WMS_LAYOUT, "sessionStage is nullptr, id: %{public}d", GetPersistentId());
457         return;
458     }
459     sceneSession->sessionStage_->SetFullScreenWaterfallMode(isFullScreenWaterfallMode_);
460 }
461 
GetPersistentId() const462 int32_t PcFoldScreenController::GetPersistentId() const
463 {
464     return persistentId_;
465 }
466 
GetDisplayId()467 DisplayId PcFoldScreenController::GetDisplayId()
468 {
469     auto sceneSession = weakSceneSession_.promote();
470     if (sceneSession == nullptr) {
471         TLOGE(WmsLogTag::WMS_LAYOUT, "session is nullptr, id: %{public}d", GetPersistentId());
472         return SCREEN_ID_INVALID;
473     }
474     return sceneSession->GetScreenId();
475 }
476 
477 /**
478  * get height of title bar
479  * @return: vp
480  */
GetTitleHeight() const481 int32_t PcFoldScreenController::GetTitleHeight() const
482 {
483     auto sceneSession = weakSceneSession_.promote();
484     if (sceneSession == nullptr) {
485         return MIN_DECOR_HEIGHT;
486     }
487     return std::clamp(sceneSession->GetCustomDecorHeight(), MIN_DECOR_HEIGHT, MAX_DECOR_HEIGHT);
488 }
489 
CalculateMovingVelocity()490 WSRectF PcFoldScreenController::CalculateMovingVelocity()
491 {
492     WSRectF velocity = { 0.0f, 0.0f, 0.0f, 0.0f };
493     std::unique_lock<std::mutex> lock(moveMutex_);
494     if (isStartDirectly_) {
495         return startVelocity_;
496     }
497     uint32_t recordsSize = static_cast<uint32_t>(movingRectRecords_.size());
498     if (recordsSize <= 1) {
499         return velocity;
500     }
501 
502     if (recordsSize >= 2) { // temp use 2 points
503         auto rect0 = movingRectRecords_[0].second;
504         auto rect1 = movingRectRecords_[recordsSize - 1].second;
505         float duration = MathHelper::NonZero(TimeHelper::GetDuration(movingRectRecords_[0].first,
506             movingRectRecords_[recordsSize - 1].first));
507         if (!MathHelper::GreatNotEqual(duration, 0.0f)) {
508             return velocity;
509         }
510         velocity.posX_ = static_cast<float>((rect1.posX_ - rect0.posX_) / static_cast<float>(duration));
511         velocity.posY_ = static_cast<float>((rect1.posY_ - rect0.posY_) / static_cast<float>(duration));
512         velocity.width_ = static_cast<float>((rect1.width_ - rect0.width_) / static_cast<float>(duration));
513         velocity.height_ = static_cast<float>((rect1.height_ - rect0.height_) / static_cast<float>(duration));
514         return velocity;
515     }
516     return velocity;
517 }
518 
519 /**
520  * The callback that is triggered when the screen fold status changes.
521  */
UpdateRect()522 void PcFoldScreenController::UpdateRect()
523 {
524     auto sceneSession = weakSceneSession_.promote();
525     if (sceneSession == nullptr) {
526         TLOGE(WmsLogTag::WMS_LAYOUT, "session is nullptr, id: %{public}d", GetPersistentId());
527         return;
528     }
529     auto ret = sceneSession->NotifyClientToUpdateRect("ScreenFoldStatusChanged", nullptr);
530     if (ret != WSError::WS_OK) {
531         TLOGE(WmsLogTag::WMS_LAYOUT, "NotifyClientToUpdateRect Fail, id: %{public}d", GetPersistentId());
532     }
533 }
534 } // namespace OHOS::Rosen