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