• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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