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