• 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->FoldStatusChangeForSupportEnterWaterfallMode(displayId, status, prevStatus);
73             });
74         }
75     );
76     PcFoldScreenManager::GetInstance().RegisterFoldScreenStatusChangeCallback(GetPersistentId(),
77         std::weak_ptr<FoldScreenStatusChangeCallback>(onFoldScreenStatusChangeCallback_));
78 
79     onSystemKeyboardStatusChangeCallback_ = std::make_shared<SystemKeyboardStatusChangeCallback>(
80         [weakThis = wptr(this)](DisplayId displayId, bool hasSystemKeyboard) {
81             auto controller = weakThis.promote();
82             if (controller == nullptr) {
83                 TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "controller is nullptr");
84                 return;
85             }
86             auto sceneSession = controller->weakSceneSession_.promote();
87             if (sceneSession == nullptr) {
88                 TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", controller->GetPersistentId());
89                 return;
90             }
91             sceneSession->PostTask([weakThis, displayId, hasSystemKeyboard] {
92                 auto controller = weakThis.promote();
93                 if (controller == nullptr) {
94                     TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "controller is nullptr");
95                     return;
96                 }
97                 controller->SystemKeyboardStatusChangeForSupportEnterWaterfallMode(displayId, hasSystemKeyboard);
98             });
99         }
100     );
101     PcFoldScreenManager::GetInstance().RegisterSystemKeyboardStatusChangeCallback(GetPersistentId(),
102         std::weak_ptr<SystemKeyboardStatusChangeCallback>(onSystemKeyboardStatusChangeCallback_));
103 
104     supportEnterWaterfallMode_ = IsSupportEnterWaterfallMode(
105         PcFoldScreenManager::GetInstance().GetScreenFoldStatus(GetDisplayId()),
106         PcFoldScreenManager::GetInstance().HasSystemKeyboard());
107     UpdateSupportEnterWaterfallMode();
108 }
109 
IsSupportEnterWaterfallMode(SuperFoldStatus status,bool hasSystemKeyboard) const110 bool PcFoldScreenController::IsSupportEnterWaterfallMode(SuperFoldStatus status, bool hasSystemKeyboard) const
111 {
112     return status == SuperFoldStatus::HALF_FOLDED && !hasSystemKeyboard && !isFullScreenWaterfallMode_;
113 }
114 
FoldStatusChangeForSupportEnterWaterfallMode(DisplayId displayId,SuperFoldStatus status,SuperFoldStatus prevStatus)115 void PcFoldScreenController::FoldStatusChangeForSupportEnterWaterfallMode(
116     DisplayId displayId, SuperFoldStatus status, SuperFoldStatus prevStatus)
117 {
118     lastSupportEnterWaterfallMode_ = supportEnterWaterfallMode_;
119     supportEnterWaterfallMode_ = IsSupportEnterWaterfallMode(status,
120         PcFoldScreenManager::GetInstance().HasSystemKeyboard());
121     auto sceneSession = weakSceneSession_.promote();
122     if (sceneSession == nullptr) {
123         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", GetPersistentId());
124         return;
125     }
126     if (!sceneSession->IsMissionHighlighted()) {
127         return;
128     }
129     UpdateSupportEnterWaterfallMode();
130 }
131 
SystemKeyboardStatusChangeForSupportEnterWaterfallMode(DisplayId displayId,bool hasSystemKeyboard)132 void PcFoldScreenController::SystemKeyboardStatusChangeForSupportEnterWaterfallMode(
133     DisplayId displayId, bool hasSystemKeyboard)
134 {
135     lastSupportEnterWaterfallMode_ = supportEnterWaterfallMode_;
136     supportEnterWaterfallMode_ = IsSupportEnterWaterfallMode(
137         PcFoldScreenManager::GetInstance().GetScreenFoldStatus(displayId), hasSystemKeyboard);
138     auto sceneSession = weakSceneSession_.promote();
139     if (sceneSession == nullptr) {
140         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", GetPersistentId());
141         return;
142     }
143     if (!sceneSession->IsMissionHighlighted()) {
144         return;
145     }
146     UpdateSupportEnterWaterfallMode();
147 }
148 
IsHalfFolded(DisplayId displayId)149 bool PcFoldScreenController::IsHalfFolded(DisplayId displayId)
150 {
151     return PcFoldScreenManager::GetInstance().IsHalfFolded(displayId);
152 }
153 
IsAllowThrowSlip(DisplayId displayId)154 bool PcFoldScreenController::IsAllowThrowSlip(DisplayId displayId)
155 {
156     auto sceneSession = weakSceneSession_.promote();
157     if (sceneSession == nullptr) {
158         return false;
159     }
160     bool sessionValid = WindowHelper::IsMainWindow(sceneSession->GetWindowType()) || sceneSession->IsDecorEnable();
161     return sessionValid && PcFoldScreenManager::GetInstance().IsHalfFolded(displayId) &&
162            !PcFoldScreenManager::GetInstance().HasSystemKeyboard();
163 }
164 
NeedFollowHandAnimation()165 bool PcFoldScreenController::NeedFollowHandAnimation()
166 {
167     static bool needFollowHandAnimation =
168         system::GetParameter("persist.window.throw_slip_follow_animation.enabled", "1") == "1";
169     std::unique_lock<std::mutex> lock(moveMutex_);
170     return needFollowHandAnimation && (!isStartFullScreen_ || movingRectRecords_.size() > 0);
171 }
172 
RecordStartMoveRect(const WSRect & rect,bool isStartFullScreen)173 void PcFoldScreenController::RecordStartMoveRect(const WSRect& rect, bool isStartFullScreen)
174 {
175     TLOGI(WmsLogTag::WMS_LAYOUT_PC, "rect: %{public}s, isStartFullScreen: %{public}d",
176         rect.ToString().c_str(), isStartFullScreen);
177     std::unique_lock<std::mutex> lock(moveMutex_);
178     startMoveRect_ = rect;
179     isStartFullScreen_ = isStartFullScreen;
180     isStartWaterfallMode_ = isFullScreenWaterfallMode_;
181     movingRectRecords_.clear();
182     startThrowSlipMode_ = ThrowSlipMode::MOVE;
183 }
184 
RecordStartMoveRectDirectly(const WSRect & rect,ThrowSlipMode throwSlipMode,const WSRectF & velocity,bool isStartFullScreen)185 void PcFoldScreenController::RecordStartMoveRectDirectly(const WSRect& rect, ThrowSlipMode throwSlipMode,
186     const WSRectF& velocity, bool isStartFullScreen)
187 {
188     TLOGI(WmsLogTag::WMS_LAYOUT_PC, "rect: %{public}s, isStartFullScreen: %{public}d, velocity: %{public}s",
189         rect.ToString().c_str(), isStartFullScreen, velocity.ToString().c_str());
190     RecordStartMoveRect(rect, isStartFullScreen);
191     std::unique_lock<std::mutex> lock(moveMutex_);
192     startThrowSlipMode_ = throwSlipMode;
193     startVelocity_ = velocity;
194     startVelocity_.posY_ *= MOVING_DIRECTLY_BUFF;
195 }
196 
ResetRecords()197 void PcFoldScreenController::ResetRecords()
198 {
199     TLOGD(WmsLogTag::WMS_LAYOUT_PC, "in");
200     std::unique_lock<std::mutex> lock(moveMutex_);
201     startMoveRect_ = ZERO_RECT;
202     isStartFullScreen_ = false;
203     isStartWaterfallMode_ = false;
204     movingRectRecords_.clear();
205     startThrowSlipMode_ = ThrowSlipMode::INVALID;
206     startVelocity_ = ZERO_RECTF;
207 }
208 
IsStartFullScreen()209 bool PcFoldScreenController::IsStartFullScreen()
210 {
211     std::unique_lock<std::mutex> lock(moveMutex_);
212     return isStartFullScreen_;
213 }
214 
RecordMoveRects(const WSRect & rect)215 void PcFoldScreenController::RecordMoveRects(const WSRect& rect)
216 {
217     auto time = std::chrono::high_resolution_clock::now();
218     std::unique_lock<std::mutex> lock(moveMutex_);
219     movingRectRecords_.push_back(std::make_pair(time, rect));
220     TLOGD(WmsLogTag::WMS_LAYOUT_PC, "id: %{public}d, rect: %{public}s", GetPersistentId(), rect.ToString().c_str());
221     // pop useless record
222     while (movingRectRecords_.size() > MOVING_RECORDS_SIZE_LIMIT ||
223            TimeHelper::GetDuration(movingRectRecords_[0].first, time) > MOVING_RECORDS_TIME_LIMIT) {
224         movingRectRecords_.erase(movingRectRecords_.begin());
225     }
226     TLOGD(WmsLogTag::WMS_LAYOUT_PC, "records size: %{public}zu, duration: %{public}f", movingRectRecords_.size(),
227         TimeHelper::GetDuration(movingRectRecords_[0].first, movingRectRecords_[movingRectRecords_.size() - 1].first));
228 }
229 
230 /**
231  * if move fast, window can be throwed to other side
232  * @param rect: current rect. if throwed, move it to other side
233  * @param topAvoidHeight: avoid status bar
234  * @param botAvoidHeight: avoid dock
235  */
ThrowSlip(DisplayId displayId,WSRect & rect,int32_t topAvoidHeight,int32_t botAvoidHeight)236 bool PcFoldScreenController::ThrowSlip(DisplayId displayId, WSRect& rect,
237     int32_t topAvoidHeight, int32_t botAvoidHeight)
238 {
239     auto& manager = PcFoldScreenManager::GetInstance();
240     if (!IsAllowThrowSlip(displayId)) {
241         manager.ResetArrangeRule();
242         return false;
243     }
244     WSRect startRect;
245     bool startFullScreen;
246     bool startWaterfallMode;
247     ThrowSlipMode startThrowSlipMode;
248     {
249         std::unique_lock<std::mutex> lock(moveMutex_);
250         manager.ResetArrangeRule(startMoveRect_);
251         startRect = startMoveRect_;
252         startFullScreen = isStartFullScreen_;
253         startWaterfallMode = isStartWaterfallMode_;
254         startThrowSlipMode = startThrowSlipMode_;
255     }
256     WSRect titleRect = { rect.posX_, rect.posY_, rect.width_,
257         IsThrowSlipModeDirectly(startThrowSlipMode) ? rect.height_ : GetTitleHeight() };
258     ScreenSide throwSide = manager.CalculateScreenSide(titleRect);
259     const WSRectF& velocity = CalculateMovingVelocity();
260     if (isFullScreenWaterfallMode_) {
261         throwSide = MathHelper::GreatNotEqual(velocity.posY_, 0.0f) ? ScreenSide::FOLD_B : ScreenSide::FOLD_C;
262     }
263     if ((!startFullScreen && !manager.NeedDoThrowSlip(titleRect, velocity, throwSide)) ||
264         (startFullScreen && !manager.NeedDoEasyThrowSlip(titleRect, startRect, velocity, throwSide))) {
265         manager.ResetArrangeRule(throwSide);
266         TLOGI(WmsLogTag::WMS_LAYOUT_PC, "no throw rect: %{public}s", rect.ToString().c_str());
267         return false;
268     }
269 
270     // correct to start rect and throw
271     if (!startFullScreen) {
272         rect.posX_ = startRect.posX_;
273         rect.posY_ = startRect.posY_;
274     }
275     manager.ThrowSlipToOppositeSide(throwSide, rect, topAvoidHeight, botAvoidHeight, GetTitleHeight());
276     manager.ResetArrangeRule(throwSide);
277 
278     // hisysevent
279     ThrowSlipWindowMode startWindowMode = ThrowSlipWindowMode::FLOAT;
280     if (startFullScreen) {
281         startWindowMode = startWaterfallMode ? ThrowSlipWindowMode::FULLSCREEN_WATERFALLMODE :
282                                                ThrowSlipWindowMode::FULLSCREEN;
283     }
284     auto sceneSession = weakSceneSession_.promote();
285     std::string bundleName = sceneSession == nullptr ? "" : sceneSession->GetSessionInfo().bundleName_;
286     ThrowSlipHiSysEvent(bundleName, throwSide, startWindowMode, startThrowSlipMode);
287     TLOGI(WmsLogTag::WMS_LAYOUT_PC, "throw to rect: %{public}s", rect.ToString().c_str());
288     return true;
289 }
290 
ThrowSlipHiSysEvent(const std::string & bundleName,ScreenSide startSide,ThrowSlipWindowMode startWindowMode,ThrowSlipMode throwMode) const291 void PcFoldScreenController::ThrowSlipHiSysEvent(const std::string& bundleName, ScreenSide startSide,
292     ThrowSlipWindowMode startWindowMode, ThrowSlipMode throwMode) const
293 {
294     int32_t ret = HiSysEventWrite(
295         HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
296         "THROW_SLIP",
297         HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
298         "BUNDLE_NAME", bundleName,
299         "START_SIDE", static_cast<int32_t>(startSide),
300         "START_WINDOW_MODE", static_cast<int32_t>(startWindowMode),
301         "THROW_MODE", static_cast<int32_t>(throwMode));
302     if (ret != 0) {
303         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "write hisysevent error, ret: %{public}d", ret);
304     }
305 }
306 
ThrowSlipFloatingRectDirectly(WSRect & rect,const WSRect & floatingRect,int32_t topAvoidHeight,int32_t botAvoidHeight)307 void PcFoldScreenController::ThrowSlipFloatingRectDirectly(WSRect& rect, const WSRect& floatingRect,
308     int32_t topAvoidHeight, int32_t botAvoidHeight)
309 {
310     TLOGD(WmsLogTag::WMS_LAYOUT_PC, "rect: %{public}s, floating rect: %{public}s",
311         rect.ToString().c_str(), floatingRect.ToString().c_str());
312     auto& manager = PcFoldScreenManager::GetInstance();
313     const ScreenSide side = manager.CalculateScreenSide(rect);
314     const ScreenSide floatingSide = manager.CalculateScreenSide(floatingRect.posY_);
315     rect = floatingRect;
316     if (side == floatingSide) {
317         return;
318     }
319     manager.ThrowSlipToOppositeSide(floatingSide,
320         rect, topAvoidHeight, botAvoidHeight, GetTitleHeight());
321 }
322 
IsThrowSlipDirectly() const323 bool PcFoldScreenController::IsThrowSlipDirectly() const
324 {
325     std::unique_lock<std::mutex> lock(moveMutex_);
326     return IsThrowSlipModeDirectly(startThrowSlipMode_);
327 }
328 
IsThrowSlipModeDirectly(ThrowSlipMode throwSlipMode) const329 bool PcFoldScreenController::IsThrowSlipModeDirectly(ThrowSlipMode throwSlipMode) const
330 {
331     return throwSlipMode == ThrowSlipMode::BUTTON ||
332         throwSlipMode == ThrowSlipMode::THREE_FINGERS_SWIPE ||
333         throwSlipMode == ThrowSlipMode::FOUR_FINGERS_SWIPE ||
334         throwSlipMode == ThrowSlipMode::FIVE_FINGERS_SWIPE;
335 }
336 
337 /**
338  * resize to fullscreen in one side considering avoid area
339  * @param rect: resize in its side
340  */
ResizeToFullScreen(WSRect & rect,int32_t topAvoidHeight,int32_t botAvoidHeight)341 void PcFoldScreenController::ResizeToFullScreen(WSRect& rect, int32_t topAvoidHeight, int32_t botAvoidHeight)
342 {
343     PcFoldScreenManager::GetInstance().ResizeToFullScreen(rect, topAvoidHeight, botAvoidHeight);
344 }
345 
GetMovingTimingProtocol()346 RSAnimationTimingProtocol PcFoldScreenController::GetMovingTimingProtocol()
347 {
348     return PcFoldScreenManager::GetInstance().GetMovingTimingProtocol();
349 }
350 
GetMovingTimingCurve()351 RSAnimationTimingCurve PcFoldScreenController::GetMovingTimingCurve()
352 {
353     return PcFoldScreenManager::GetInstance().GetMovingTimingCurve();
354 }
355 
GetThrowSlipTimingProtocol()356 RSAnimationTimingProtocol PcFoldScreenController::GetThrowSlipTimingProtocol()
357 {
358     return PcFoldScreenManager::GetInstance().GetThrowSlipTimingProtocol();
359 }
360 
GetThrowSlipTimingCurve()361 RSAnimationTimingCurve PcFoldScreenController::GetThrowSlipTimingCurve()
362 {
363     return PcFoldScreenManager::GetInstance().GetThrowSlipTimingCurve();
364 }
365 
UpdateFullScreenWaterfallMode(bool isWaterfallMode)366 void PcFoldScreenController::UpdateFullScreenWaterfallMode(bool isWaterfallMode)
367 {
368     auto sceneSession = weakSceneSession_.promote();
369     if (sceneSession == nullptr) {
370         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", GetPersistentId());
371         return;
372     }
373     sceneSession->PostTask([weakThis = wptr(this), isWaterfallMode, where = __func__] {
374         auto controller = weakThis.promote();
375         if (controller == nullptr) {
376             TLOGNE(WmsLogTag::WMS_LAYOUT_PC, "controller is nullptr");
377             return;
378         }
379         if (controller->isFullScreenWaterfallMode_ == isWaterfallMode) {
380             return;
381         }
382         if (isWaterfallMode && !controller->supportEnterWaterfallMode_) {
383             TLOGNW(WmsLogTag::WMS_LAYOUT_PC, "%{public}s not support waterfall mode!", where);
384         }
385         TLOGNI(WmsLogTag::WMS_LAYOUT_PC, "%{public}s id: %{public}d, mode: %{public}d",
386             where, controller->GetPersistentId(), isWaterfallMode);
387         controller->isFullScreenWaterfallMode_ = isWaterfallMode;
388         controller->ExecuteFullScreenWaterfallModeChangeCallback();
389         controller->supportEnterWaterfallMode_ = controller->IsSupportEnterWaterfallMode(
390             PcFoldScreenManager::GetInstance().GetScreenFoldStatus(controller->GetDisplayId()),
391             PcFoldScreenManager::GetInstance().HasSystemKeyboard());
392         controller->UpdateSupportEnterWaterfallMode();
393     }, __func__);
394 }
395 
SetFullScreenWaterfallMode(bool isFullScreenWaterfallMode)396 void PcFoldScreenController::SetFullScreenWaterfallMode(bool isFullScreenWaterfallMode)
397 {
398     isFullScreenWaterfallMode_ = isFullScreenWaterfallMode;
399 }
400 
RegisterFullScreenWaterfallModeChangeCallback(std::function<void (bool isWaterfallMode)> && func)401 void PcFoldScreenController::RegisterFullScreenWaterfallModeChangeCallback(
402     std::function<void(bool isWaterfallMode)>&& func)
403 {
404     fullScreenWaterfallModeChangeCallback_ = std::move(func);
405     ExecuteFullScreenWaterfallModeChangeCallback();
406 }
407 
UnregisterFullScreenWaterfallModeChangeCallback()408 void PcFoldScreenController::UnregisterFullScreenWaterfallModeChangeCallback()
409 {
410     fullScreenWaterfallModeChangeCallback_ = nullptr;
411 }
412 
MaskSupportEnterWaterfallMode()413 void PcFoldScreenController::MaskSupportEnterWaterfallMode()
414 {
415     maskSupportEnterWaterfallMode_ = true;
416     auto sceneSession = weakSceneSession_.promote();
417     if (sceneSession == nullptr) {
418         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session unavailable, id: %{public}d", GetPersistentId());
419         return;
420     }
421     sceneSession->SetSupportEnterWaterfallMode(false);
422 }
423 
UpdateSupportEnterWaterfallMode()424 void PcFoldScreenController::UpdateSupportEnterWaterfallMode()
425 {
426     TLOGD(WmsLogTag::WMS_LAYOUT_PC, "last: %{public}d, curr: %{public}d",
427         lastSupportEnterWaterfallMode_, supportEnterWaterfallMode_);
428     if (maskSupportEnterWaterfallMode_ || (lastSupportEnterWaterfallMode_ == supportEnterWaterfallMode_)) {
429         return;
430     }
431     auto sceneSession = weakSceneSession_.promote();
432     if (sceneSession == nullptr) {
433         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session unavailable, id: %{public}d", GetPersistentId());
434         return;
435     }
436     lastSupportEnterWaterfallMode_ = supportEnterWaterfallMode_;
437     sceneSession->SetSupportEnterWaterfallMode(supportEnterWaterfallMode_);
438 }
439 
ExecuteFullScreenWaterfallModeChangeCallback()440 void PcFoldScreenController::ExecuteFullScreenWaterfallModeChangeCallback()
441 {
442     if (fullScreenWaterfallModeChangeCallback_ == nullptr) {
443         return;
444     }
445     fullScreenWaterfallModeChangeCallback_(isFullScreenWaterfallMode_);
446     // notify client
447     auto sceneSession = weakSceneSession_.promote();
448     if (sceneSession == nullptr) {
449         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", GetPersistentId());
450         return;
451     }
452     if (sceneSession->sessionStage_ == nullptr) {
453         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "sessionStage is nullptr, id: %{public}d", GetPersistentId());
454         return;
455     }
456     sceneSession->sessionStage_->SetFullScreenWaterfallMode(isFullScreenWaterfallMode_);
457 
458     // notify subSession client
459     sceneSession->NotifySubSessionAcrossDisplaysChange(isFullScreenWaterfallMode_);
460     sceneSession->NotifyFollowedParentWindowAcrossDisplaysChange(isFullScreenWaterfallMode_);
461 }
462 
GetPersistentId() const463 int32_t PcFoldScreenController::GetPersistentId() const
464 {
465     return persistentId_;
466 }
467 
GetDisplayId()468 DisplayId PcFoldScreenController::GetDisplayId()
469 {
470     auto sceneSession = weakSceneSession_.promote();
471     if (sceneSession == nullptr) {
472         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", GetPersistentId());
473         return SCREEN_ID_INVALID;
474     }
475     return sceneSession->GetScreenId();
476 }
477 
478 /**
479  * get height of title bar
480  * @return: vp
481  */
GetTitleHeight() const482 int32_t PcFoldScreenController::GetTitleHeight() const
483 {
484     auto sceneSession = weakSceneSession_.promote();
485     if (sceneSession == nullptr) {
486         return MIN_DECOR_HEIGHT;
487     }
488     return std::clamp(sceneSession->GetCustomDecorHeight(), MIN_DECOR_HEIGHT, MAX_DECOR_HEIGHT);
489 }
490 
CalculateMovingVelocity()491 WSRectF PcFoldScreenController::CalculateMovingVelocity()
492 {
493     WSRectF velocity = { 0.0f, 0.0f, 0.0f, 0.0f };
494     std::unique_lock<std::mutex> lock(moveMutex_);
495     if (IsThrowSlipModeDirectly(startThrowSlipMode_)) {
496         return startVelocity_;
497     }
498     uint32_t recordsSize = static_cast<uint32_t>(movingRectRecords_.size());
499     if (recordsSize <= 1) {
500         return velocity;
501     }
502 
503     if (recordsSize >= 2) { // temp use 2 points
504         auto rect0 = movingRectRecords_[0].second;
505         auto rect1 = movingRectRecords_[recordsSize - 1].second;
506         float duration = MathHelper::NonZero(TimeHelper::GetDuration(movingRectRecords_[0].first,
507             movingRectRecords_[recordsSize - 1].first));
508         if (!MathHelper::GreatNotEqual(duration, 0.0f)) {
509             return velocity;
510         }
511         velocity.posX_ = static_cast<float>((rect1.posX_ - rect0.posX_) / static_cast<float>(duration));
512         velocity.posY_ = static_cast<float>((rect1.posY_ - rect0.posY_) / static_cast<float>(duration));
513         velocity.width_ = static_cast<float>((rect1.width_ - rect0.width_) / static_cast<float>(duration));
514         velocity.height_ = static_cast<float>((rect1.height_ - rect0.height_) / static_cast<float>(duration));
515         return velocity;
516     }
517     return velocity;
518 }
519 
520 /**
521  * The callback that is triggered when the screen fold status changes.
522  */
UpdateRect()523 void PcFoldScreenController::UpdateRect()
524 {
525     auto sceneSession = weakSceneSession_.promote();
526     if (sceneSession == nullptr) {
527         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "session is nullptr, id: %{public}d", GetPersistentId());
528         return;
529     }
530     auto ret = sceneSession->NotifyClientToUpdateRect("ScreenFoldStatusChanged", nullptr);
531     if (ret != WSError::WS_OK) {
532         TLOGE(WmsLogTag::WMS_LAYOUT_PC, "NotifyClientToUpdateRect Fail, id: %{public}d", GetPersistentId());
533     }
534 }
535 } // namespace OHOS::Rosen