1 /*
2 * Copyright (c) 2023 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/sub_session.h"
17
18 #include "rs_adapter.h"
19 #include "screen_session_manager_client/include/screen_session_manager_client.h"
20 #include "session/screen/include/screen_session.h"
21 #include <transaction/rs_sync_transaction_controller.h>
22 #include <transaction/rs_transaction.h>
23 #include <ui/rs_surface_node.h>
24 #include "window_helper.h"
25 #include "pointer_event.h"
26 #include "window_manager_hilog.h"
27
28
29 namespace OHOS::Rosen {
30 namespace {
31 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "SubSession" };
32 constexpr int32_t SUFFIX_INDEX = -1;
33 } // namespace
34
SubSession(const SessionInfo & info,const sptr<SpecificSessionCallback> & specificCallback)35 SubSession::SubSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)
36 : SceneSession(info, specificCallback)
37 {
38 pcFoldScreenController_ = sptr<PcFoldScreenController>::MakeSptr(wptr(this), GetPersistentId());
39 moveDragController_ = sptr<MoveDragController>::MakeSptr(GetPersistentId(), GetWindowType());
40 if (specificCallback != nullptr &&
41 specificCallback->onWindowInputPidChangeCallback_ != nullptr) {
42 moveDragController_->SetNotifyWindowPidChangeCallback(specificCallback->onWindowInputPidChangeCallback_);
43 }
44 SetMoveDragCallback();
45 TLOGD(WmsLogTag::WMS_LIFE, "Create");
46 }
47
~SubSession()48 SubSession::~SubSession()
49 {
50 TLOGD(WmsLogTag::WMS_LIFE, "id: %{public}d", GetPersistentId());
51 }
52
Show(sptr<WindowSessionProperty> property)53 WSError SubSession::Show(sptr<WindowSessionProperty> property)
54 {
55 if (!CheckPermissionWithPropertyAnimation(property)) {
56 return WSError::WS_ERROR_NOT_SYSTEM_APP;
57 }
58 if (property->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_IS_TEXT_MENU) &&
59 GetForceHideState() != ForceHideState::NOT_HIDDEN) {
60 TLOGI(WmsLogTag::WMS_SUB, "UEC force hide, id: %{public}d forceHideState: %{public}d",
61 GetPersistentId(), GetForceHideState());
62 return WSError::WS_ERROR_INVALID_OPERATION;
63 }
64 PostTask([weakThis = wptr(this), property]() {
65 auto session = weakThis.promote();
66 if (!session) {
67 TLOGE(WmsLogTag::WMS_SUB, "session is null");
68 return WSError::WS_ERROR_DESTROYED_OBJECT;
69 }
70 TLOGI(WmsLogTag::WMS_LIFE, "Show session, id: %{public}d", session->GetPersistentId());
71
72 auto parentSession = session->GetParentSession();
73 if (parentSession && session->GetShouldFollowParentWhenShow()) {
74 session->CheckAndMoveDisplayIdRecursively(parentSession->GetSessionProperty()->GetDisplayId());
75 } else {
76 TLOGNE(WmsLogTag::WMS_SUB, "session has no parent, id: %{public}d", session->GetPersistentId());
77 }
78 // use property from client
79 auto sessionProperty = session->GetSessionProperty();
80 if (property && property->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM) &&
81 sessionProperty) {
82 sessionProperty->SetAnimationFlag(static_cast<uint32_t>(WindowAnimation::CUSTOM));
83 session->NotifyIsCustomAnimationPlaying(true);
84 }
85 auto ret = session->SceneSession::Foreground(property);
86 return ret;
87 }, "Show");
88 return WSError::WS_OK;
89 }
90
NotifySessionRectChange(const WSRect & rect,SizeChangeReason reason,DisplayId displayId,const RectAnimationConfig & rectAnimationConfig)91 void SubSession::NotifySessionRectChange(const WSRect& rect, SizeChangeReason reason, DisplayId displayId,
92 const RectAnimationConfig& rectAnimationConfig)
93 {
94 if (reason == SizeChangeReason::DRAG_END) {
95 SetShouldFollowParentWhenShow(false);
96 }
97 SceneSession::NotifySessionRectChange(rect, reason, displayId, rectAnimationConfig);
98 }
99
IsNeedCrossDisplayRendering() const100 bool SubSession::IsNeedCrossDisplayRendering() const
101 {
102 return IsFollowParentMultiScreenPolicy() && (IsAnyParentSessionDragMoving() || IsAnyParentSessionDragZooming());
103 }
104
UpdateSessionRectInner(const WSRect & rect,SizeChangeReason reason,const MoveConfiguration & moveConfiguration,const RectAnimationConfig & rectAnimationConfig)105 void SubSession::UpdateSessionRectInner(const WSRect& rect, SizeChangeReason reason,
106 const MoveConfiguration& moveConfiguration, const RectAnimationConfig& rectAnimationConfig)
107 {
108 if (moveConfiguration.displayId != DISPLAY_ID_INVALID) {
109 SetShouldFollowParentWhenShow(false);
110 }
111 if (IsNeedCrossDisplayRendering()) {
112 auto newRequestRect = GetSessionRequestRect();
113 if (reason == SizeChangeReason::MOVE) {
114 newRequestRect.posX_ = rect.posX_;
115 newRequestRect.posY_ = rect.posY_;
116 } else if (reason == SizeChangeReason::RESIZE && rect.width_ > 0 && rect.height_ > 0) {
117 newRequestRect.width_ = rect.width_;
118 newRequestRect.height_ = rect.height_;
119 }
120 SetSessionRequestRect(newRequestRect);
121 SetRequestRectWhenFollowParent(newRequestRect);
122 WSRect globaleRect =
123 layoutController_->ConvertRelativeRectToGlobal(newRequestRect, moveConfiguration.displayId);
124 UpdateSizeChangeReason(reason);
125 TLOGI(WmsLogTag::WMS_LAYOUT, "need show cross window, id:%{public}d, globalRect:%{public}s",
126 GetPersistentId(), globaleRect.ToString().c_str());
127 HandleCrossMoveTo(globaleRect);
128 return;
129 }
130
131 if (IsSessionForeground() && (reason == SizeChangeReason::MOVE || reason == SizeChangeReason::RESIZE)) {
132 SetOriPosYBeforeRaisedByKeyboard(0);
133 const WSRect& winRect = GetSessionRect();
134 if (reason == SizeChangeReason::MOVE && (rect.posX_ != winRect.posX_ || rect.posY_ != winRect.posY_)) {
135 isSubWindowResizingOrMoving_ = true;
136 }
137 if (reason == SizeChangeReason::RESIZE && (rect.width_ != winRect.width_ || rect.height_ != winRect.height_)) {
138 isSubWindowResizingOrMoving_ = true;
139 }
140 }
141
142 SceneSession::UpdateSessionRectInner(rect, reason, moveConfiguration, rectAnimationConfig);
143 }
144
Hide()145 WSError SubSession::Hide()
146 {
147 return Hide(false); // async mode
148 }
149
HideSync()150 WSError SubSession::HideSync()
151 {
152 return Hide(true); // sync mode
153 }
154
Hide(bool needSyncHide)155 WSError SubSession::Hide(bool needSyncHide)
156 {
157 if (!CheckPermissionWithPropertyAnimation(GetSessionProperty())) {
158 return WSError::WS_ERROR_NOT_SYSTEM_APP;
159 }
160 auto task = [weakThis = wptr(this)]() {
161 auto session = weakThis.promote();
162 if (!session) {
163 TLOGNE(WmsLogTag::WMS_SUB, "session is null");
164 return WSError::WS_ERROR_DESTROYED_OBJECT;
165 }
166 session->isSubWindowResizingOrMoving_ = false;
167 TLOGNI(WmsLogTag::WMS_LIFE, "Hide session, id: %{public}d", session->GetPersistentId());
168 auto ret = session->SetActive(false);
169 if (ret != WSError::WS_OK) {
170 return ret;
171 }
172 // background will remove surfaceNode, custom not execute
173 // not animation playing when already background; inactive may be animation playing
174 auto sessionProperty = session->GetSessionProperty();
175 if (sessionProperty &&
176 sessionProperty->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM)) {
177 session->NotifyIsCustomAnimationPlaying(true);
178 return WSError::WS_OK;
179 }
180 ret = session->SceneSession::Background();
181 return ret;
182 };
183
184 if (needSyncHide) {
185 return PostSyncTask(task, "HideSync");
186 }
187
188 PostTask(task, "HideAsync");
189 return WSError::WS_OK;
190 }
191
ProcessPointDownSession(int32_t posX,int32_t posY)192 WSError SubSession::ProcessPointDownSession(int32_t posX, int32_t posY)
193 {
194 const auto& id = GetPersistentId();
195 TLOGD(WmsLogTag::WMS_INPUT_KEY_FLOW, "id:%{public}d, type:%{public}d", id, GetWindowType());
196 auto isModal = IsModal();
197 auto parentSession = GetParentSession();
198 if (!isModal && parentSession && parentSession->CheckDialogOnForeground()) {
199 WLOGFI("Has dialog foreground, id: %{public}d, type: %{public}d", id, GetWindowType());
200 return WSError::WS_OK;
201 }
202 if (isModal) {
203 Session::ProcessClickModalWindowOutside(posX, posY);
204 }
205 auto sessionProperty = GetSessionProperty();
206 if (sessionProperty && sessionProperty->GetRaiseEnabled()) {
207 RaiseToAppTopForPointDown();
208 }
209 auto ret = SceneSession::ProcessPointDownSession(posX, posY);
210 PresentFocusIfPointDown();
211 return ret;
212 }
213
GetMissionId() const214 int32_t SubSession::GetMissionId() const
215 {
216 auto parentSession = GetParentSession();
217 return parentSession != nullptr ? parentSession->GetPersistentId() : SceneSession::GetMissionId();
218 }
219
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)220 WSError SubSession::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
221 {
222 if (!IsSessionValid()) {
223 return WSError::WS_ERROR_INVALID_SESSION;
224 }
225 if (keyEvent == nullptr) {
226 WLOGFE("KeyEvent is nullptr");
227 return WSError::WS_ERROR_NULLPTR;
228 }
229 auto parentSession = GetParentSession();
230 if (parentSession && parentSession->CheckDialogOnForeground()) {
231 TLOGD(WmsLogTag::WMS_DIALOG, "Its main window has dialog on foreground, not transfer pointer event");
232 return WSError::WS_ERROR_INVALID_PERMISSION;
233 }
234
235 WSError ret = Session::TransferKeyEvent(keyEvent);
236 return ret;
237 }
238
UpdatePointerArea(const WSRect & rect)239 void SubSession::UpdatePointerArea(const WSRect& rect)
240 {
241 auto property = GetSessionProperty();
242 if (!(property->IsDecorEnable() && GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING)) {
243 return;
244 }
245 Session::UpdatePointerArea(rect);
246 }
247
CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent> & pointerEvent) const248 bool SubSession::CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) const
249 {
250 auto sessionState = GetSessionState();
251 int32_t action = pointerEvent->GetPointerAction();
252 auto isPC = systemConfig_.IsPcWindow();
253 if (isPC && sessionState != SessionState::STATE_FOREGROUND &&
254 sessionState != SessionState::STATE_ACTIVE &&
255 action != MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW) {
256 WLOGFW("Current Session Info: [persistentId: %{public}d, "
257 "state: %{public}d, action:%{public}d]", GetPersistentId(), GetSessionState(), action);
258 return false;
259 }
260 return true;
261 }
262
RectCheck(uint32_t curWidth,uint32_t curHeight)263 void SubSession::RectCheck(uint32_t curWidth, uint32_t curHeight)
264 {
265 uint32_t minWidth = GetSystemConfig().miniWidthOfSubWindow_;
266 uint32_t minHeight = GetSystemConfig().miniHeightOfSubWindow_;
267 uint32_t maxFloatingWindowSize = GetSystemConfig().maxFloatingWindowSize_;
268 RectSizeCheckProcess(curWidth, curHeight, minWidth, minHeight, maxFloatingWindowSize);
269 }
270
IsTopmost() const271 bool SubSession::IsTopmost() const
272 {
273 bool isTopmost = false;
274 auto sessionProperty = GetSessionProperty();
275 if (sessionProperty) {
276 isTopmost = sessionProperty->IsTopmost();
277 }
278 TLOGI(WmsLogTag::WMS_SUB, "isTopmost: %{public}d", isTopmost);
279 return isTopmost;
280 }
281
IsModal() const282 bool SubSession::IsModal() const
283 {
284 return WindowHelper::IsModalSubWindow(GetSessionProperty()->GetWindowType(),
285 GetSessionProperty()->GetWindowFlags());
286 }
287
IsApplicationModal() const288 bool SubSession::IsApplicationModal() const
289 {
290 return WindowHelper::IsApplicationModalSubWindow(GetSessionProperty()->GetWindowType(),
291 GetSessionProperty()->GetWindowFlags());
292 }
293
IsVisibleForeground() const294 bool SubSession::IsVisibleForeground() const
295 {
296 const auto& mainOrFloatSession = GetMainOrFloatSession();
297 if (mainOrFloatSession) {
298 return mainOrFloatSession->IsVisibleForeground() && Session::IsVisibleForeground();
299 }
300 return Session::IsVisibleForeground();
301 }
302
IsVisibleNotBackground() const303 bool SubSession::IsVisibleNotBackground() const
304 {
305 const auto& mainOrFloatSession = GetMainOrFloatSession();
306 if (mainOrFloatSession) {
307 return mainOrFloatSession->IsVisibleNotBackground() && Session::IsVisibleNotBackground();
308 }
309 return Session::IsVisibleNotBackground();
310 }
311
NotifyFollowParentMultiScreenPolicy(bool enabled)312 WSError SubSession::NotifyFollowParentMultiScreenPolicy(bool enabled)
313 {
314 PostTask([weakThis = wptr(this), enabled, funcName = __func__] {
315 auto session = weakThis.promote();
316 if (!session) {
317 TLOGNE(WmsLogTag::WMS_SUB, "%{public}s: session is null", funcName);
318 return;
319 }
320 TLOGNI(WmsLogTag::WMS_SUB, "%{public}s: enabled:%{public}d", funcName, enabled);
321 session->isFollowParentMultiScreenPolicy_ = enabled;
322 }, __func__);
323 return WSError::WS_OK;
324 }
325
IsFollowParentMultiScreenPolicy() const326 bool SubSession::IsFollowParentMultiScreenPolicy() const
327 {
328 return isFollowParentMultiScreenPolicy_;
329 }
330
SetParentSessionCallback(NotifySetParentSessionFunc && func)331 void SubSession::SetParentSessionCallback(NotifySetParentSessionFunc&& func)
332 {
333 const char* const where = __func__;
334 PostTask([weakThis = wptr(this), where, func = std::move(func)] {
335 auto session = weakThis.promote();
336 if (!session || !func) {
337 TLOGNE(WmsLogTag::WMS_SUB, "%{public}s session or func is nullptr", where);
338 return;
339 }
340 session->setParentSessionFunc_ = std::move(func);
341 TLOGND(WmsLogTag::WMS_SUB, "%{public}s id: %{public}d", where,
342 session->GetPersistentId());
343 }, __func__);
344 }
345
NotifySetParentSession(int32_t oldParentWindowId,int32_t newParentWindowId)346 WMError SubSession::NotifySetParentSession(int32_t oldParentWindowId, int32_t newParentWindowId)
347 {
348 return PostSyncTask([weakThis = wptr(this), oldParentWindowId, newParentWindowId, where = __func__] {
349 auto session = weakThis.promote();
350 if (!session) {
351 TLOGNE(WmsLogTag::WMS_SUB, "%{public}s session is nullptr", where);
352 return WMError::WM_ERROR_INVALID_WINDOW;
353 }
354 if (session->setParentSessionFunc_) {
355 session->setParentSessionFunc_(oldParentWindowId, newParentWindowId);
356 TLOGND(WmsLogTag::WMS_SUB, "%{public}s id: %{public}d oldParentWindowId: %{public}d "
357 "newParentWindowId: %{public}d", where, session->GetPersistentId(), oldParentWindowId,
358 newParentWindowId);
359 }
360 return WMError::WM_OK;
361 }, __func__);
362 }
363
HandleCrossSurfaceNodeByWindowAnchor(SizeChangeReason reason,const sptr<ScreenSession> & screenSession)364 void SubSession::HandleCrossSurfaceNodeByWindowAnchor(SizeChangeReason reason, const sptr<ScreenSession>& screenSession)
365 {
366 if (!screenSession) {
367 TLOGE(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, ScreenSession is null", GetPersistentId());
368 return;
369 }
370 auto surfaceNode = GetSurfaceNodeForMoveDrag();
371 if (!surfaceNode) {
372 TLOGE(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, SurfaceNode is null", GetPersistentId());
373 return;
374 }
375 DisplayId displayId = screenSession->GetDisplayId();
376 if (reason == SizeChangeReason::DRAG || reason == SizeChangeReason::DRAG_MOVE) {
377 {
378 AutoRSTransaction trans(surfaceNode->GetRSUIContext());
379 surfaceNode->SetPositionZ(GetZOrder());
380 surfaceNode->SetIsCrossNode(true);
381 }
382 {
383 AutoRSTransaction trans(screenSession->GetRSUIContext());
384 screenSession->GetDisplayNode()->AddCrossScreenChild(surfaceNode, SUFFIX_INDEX, true);
385 }
386 cloneNodeCountDuringCross_.fetch_add(1);
387 TLOGI(WmsLogTag::WMS_LAYOUT, "Add sub window to display:%{public}" PRIu64 " persistentId:%{public}d, "
388 "cloneNodeCountDuringCross:%{public}d", displayId, GetPersistentId(), cloneNodeCountDuringCross_.load());
389 } else if (reason == SizeChangeReason::DRAG_END) {
390 surfaceNode->SetPositionZ(moveDragController_->GetOriginalPositionZ());
391 screenSession->GetDisplayNode()->RemoveCrossScreenChild(surfaceNode);
392 surfaceNode->SetIsCrossNode(false);
393 cloneNodeCountDuringCross_.fetch_sub(1);
394 TLOGI(WmsLogTag::WMS_LAYOUT, "Remove sub window from display:%{public}" PRIu64 " persistentId:%{public}d, "
395 "cloneNodeCountDuringCross:%{public}d", displayId, GetPersistentId(), cloneNodeCountDuringCross_.load());
396 }
397 }
398
SetSubWindowZLevel(int32_t zLevel)399 WSError SubSession::SetSubWindowZLevel(int32_t zLevel)
400 {
401 PostTask([weakThis = wptr(this), zLevel]() {
402 auto session = weakThis.promote();
403 if (!session) {
404 TLOGE(WmsLogTag::WMS_HIERARCHY, "session is null");
405 return;
406 }
407 auto property = session->GetSessionProperty();
408 TLOGI(WmsLogTag::WMS_HIERARCHY, "Notify session zLevel change, id: %{public}d, zLevel: %{public}d",
409 session->GetPersistentId(), zLevel);
410 property->SetSubWindowZLevel(zLevel);
411 if (session->onSubSessionZLevelChange_) {
412 session->onSubSessionZLevelChange_(zLevel);
413 }
414 }, "SetSubWindowZLevel");
415 return WSError::WS_OK;
416 }
417
GetSubWindowZLevel() const418 int32_t SubSession::GetSubWindowZLevel() const
419 {
420 int32_t zLevel = 0;
421 auto sessionProperty = GetSessionProperty();
422 zLevel = sessionProperty->GetSubWindowZLevel();
423 TLOGI(WmsLogTag::WMS_HIERARCHY, "zLevel: %{public}d", zLevel);
424 return zLevel;
425 }
426
HandleCrossMoveToSurfaceNode(WSRect & globalRect)427 void SubSession::HandleCrossMoveToSurfaceNode(WSRect& globalRect)
428 {
429 auto movedSurfaceNode = GetSurfaceNodeForMoveDrag();
430 if (movedSurfaceNode == nullptr) {
431 TLOGE(WmsLogTag::WMS_LAYOUT, "SurfaceNode is null");
432 return;
433 }
434
435 TLOGI(WmsLogTag::WMS_LAYOUT, "displayId:%{public}" PRIu64 ", persistentId:%{public}d, globalRect:%{public}s",
436 GetScreenId(), GetPersistentId(), globalRect.ToString().c_str());
437 for (const auto displayId : GetNewDisplayIdsDuringMoveTo(globalRect)) {
438 if (displayId == GetScreenId()) {
439 continue;
440 }
441 auto screenSession = ScreenSessionManagerClient::GetInstance().GetScreenSessionById(displayId);
442 if (screenSession == nullptr) {
443 TLOGE(WmsLogTag::WMS_LAYOUT, "ScreenSession is null");
444 continue;
445 }
446 if (screenSession->GetDisplayNode() == nullptr) {
447 TLOGE(WmsLogTag::WMS_LAYOUT, "DisplayNode is null");
448 continue;
449 }
450 if (screenSession->GetScreenProperty().GetScreenType() == ScreenType::VIRTUAL) {
451 TLOGD(WmsLogTag::WMS_LAYOUT, "virtual screen, no need to add cross parent child");
452 continue;
453 }
454 movedSurfaceNode->SetPositionZ(GetZOrder());
455 {
456 AutoRSTransaction trans(screenSession->GetRSUIContext());
457 screenSession->GetDisplayNode()->AddCrossScreenChild(movedSurfaceNode, SUFFIX_INDEX, true);
458 }
459 cloneNodeCount_++;
460 movedSurfaceNode->SetIsCrossNode(true);
461 TLOGI(WmsLogTag::WMS_LAYOUT, "Add sub window to display:%{public}" PRIu64 " persistentId:%{public}d",
462 displayId, GetPersistentId());
463 }
464 RSTransactionAdapter::FlushImplicitTransaction(movedSurfaceNode->GetRSUIContext());
465 }
466
GetNewDisplayIdsDuringMoveTo(WSRect & newRect)467 std::set<uint64_t> SubSession::GetNewDisplayIdsDuringMoveTo(WSRect& newRect)
468 {
469 std::set<uint64_t> newAddedDisplayIdSet;
470 WSRect windowRect = newRect;
471 std::map<ScreenId, ScreenProperty> screenProperties =
472 ScreenSessionManagerClient::GetInstance().GetAllScreensProperties();
473 std::lock_guard<std::mutex> lock(displayIdSetDuringMoveToMutex_);
474 for (const auto& [screenId, screenProperty] : screenProperties) {
475 if (displayIdSetDuringMoveTo_.find(screenId) != displayIdSetDuringMoveTo_.end()) {
476 continue;
477 }
478 WSRect screenRect = {
479 screenProperty.GetStartX(),
480 screenProperty.GetStartY(),
481 screenProperty.GetBounds().rect_.GetWidth(),
482 screenProperty.GetBounds().rect_.GetHeight(),
483 };
484 if (windowRect.IsOverlap(screenRect)) {
485 TLOGI(WmsLogTag::WMS_LAYOUT, "Overlap with new screen:%{public}" PRIu64 " persistentId:%{public}d",
486 screenId, GetPersistentId());
487 displayIdSetDuringMoveTo_.insert(screenId);
488 newAddedDisplayIdSet.insert(screenId);
489 }
490 }
491 return newAddedDisplayIdSet;
492 }
493
AddSurfaceNodeToScreen(DisplayId draggingOrMovingParentDisplayId)494 void SubSession::AddSurfaceNodeToScreen(DisplayId draggingOrMovingParentDisplayId)
495 {
496 auto currSurfacedNode = GetSurfaceNodeForMoveDrag();
497 if (currSurfacedNode == nullptr) {
498 TLOGE(WmsLogTag::WMS_LAYOUT, "SurfaceNode is null");
499 return;
500 }
501 DisplayId currDisplayId = GetDisplayId();
502 WSRect targetRect = GetLayoutController()->ConvertRelativeRectToGlobal(GetSessionRect(), currDisplayId);
503 TLOGI(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, currDisplayId:%{public}" PRIu64 ", winRect:%{public}s",
504 GetPersistentId(), currDisplayId, GetSessionRect().ToString().c_str());
505 for (const auto displayId : GetNewDisplayIdsDuringMoveTo(targetRect)) {
506 if (displayId == currDisplayId && currDisplayId == draggingOrMovingParentDisplayId) {
507 continue;
508 }
509 auto screenSession = ScreenSessionManagerClient::GetInstance().GetScreenSessionById(displayId);
510 if (screenSession == nullptr) {
511 TLOGE(WmsLogTag::WMS_LAYOUT, "ScreenSession is null");
512 continue;
513 }
514 if (screenSession->GetDisplayNode() == nullptr) {
515 TLOGE(WmsLogTag::WMS_LAYOUT, "DisplayNode is null");
516 continue;
517 }
518 if (screenSession->GetScreenProperty().GetScreenType() == ScreenType::VIRTUAL) {
519 TLOGD(WmsLogTag::WMS_LAYOUT, "virtual screen, no need to add cross parent child");
520 continue;
521 }
522 currSurfacedNode->SetPositionZ(GetZOrder());
523 {
524 AutoRSTransaction trans(screenSession->GetRSUIContext());
525 screenSession->GetDisplayNode()->AddCrossScreenChild(currSurfacedNode, SUFFIX_INDEX, true);
526 }
527 cloneNodeCount_++;
528 currSurfacedNode->SetIsCrossNode(true);
529 TLOGI(WmsLogTag::WMS_LAYOUT, "Add sub window to display:%{public}" PRIu64 " persistentId:%{public}d, "
530 "cloneNodeCount:%{public}d", displayId, GetPersistentId(), cloneNodeCount_);
531 }
532 RSTransactionAdapter::FlushImplicitTransaction(currSurfacedNode->GetRSUIContext());
533 }
534
RemoveSurfaceNodeFromScreen()535 void SubSession::RemoveSurfaceNodeFromScreen()
536 {
537 auto currSurfacedNode = GetSurfaceNodeForMoveDrag();
538 if (currSurfacedNode == nullptr) {
539 TLOGE(WmsLogTag::WMS_LAYOUT, "SurfaceNode is null");
540 return;
541 }
542 std::lock_guard<std::mutex> lock(displayIdSetDuringMoveToMutex_);
543 for (const auto displayId : displayIdSetDuringMoveTo_) {
544 auto screenSession = ScreenSessionManagerClient::GetInstance().GetScreenSessionById(displayId);
545 if (screenSession == nullptr) {
546 TLOGE(WmsLogTag::WMS_LAYOUT, "ScreenSession is null");
547 continue;
548 }
549 if (screenSession->GetDisplayNode() == nullptr) {
550 TLOGE(WmsLogTag::WMS_LAYOUT, "DisplayNode is null");
551 continue;
552 }
553 if (screenSession->GetScreenProperty().GetScreenType() == ScreenType::VIRTUAL) {
554 TLOGD(WmsLogTag::WMS_LAYOUT, "virtual screen, no need to remove cross parent child");
555 continue;
556 }
557 currSurfacedNode->SetPositionZ(moveDragController_->GetOriginalPositionZ());
558 screenSession->GetDisplayNode()->RemoveCrossScreenChild(currSurfacedNode);
559 cloneNodeCount_--;
560 currSurfacedNode->SetIsCrossNode(false);
561 TLOGI(WmsLogTag::WMS_LAYOUT, "Remove sub window from display:%{public}" PRIu64 " persistentId:%{public}d, "
562 "cloneNodeCount:%{public}d", displayId, GetPersistentId(), cloneNodeCount_);
563 }
564 }
565 } // namespace OHOS::Rosen
566