1 /*
2 * Copyright (c) 2022 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 "window_pair.h"
17
18 #include <ability_manager_client.h>
19 #include "common_event_manager.h"
20 #include "minimize_app.h"
21 #include "window_inner_manager.h"
22 #include "window_manager_hilog.h"
23 #include "window_helper.h"
24 #include "window_system_effect.h"
25 #include "surface_draw.h"
26
27 namespace OHOS {
28 namespace Rosen {
29 namespace {
30 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "Pair"};
31 const std::string SPLIT_SCREEN_EVENT_NAME = "common.event.SPLIT_SCREEN";
32 const std::map<SplitEventMsgType, std::string> splitEventDataMap {
33 {SplitEventMsgType::MSG_SHOW_PRIMARY, "Primary"},
34 {SplitEventMsgType::MSG_SHOW_SECONDARY, "Secondary"},
35 {SplitEventMsgType::MSG_SHOW_DIVIDER, "common.event.SPLIT_SCREEN.data.show.divider"},
36 {SplitEventMsgType::MSG_DESTROY_DIVIDER, "common.event.SPLIT_SCREEN.data.destroy.divider"}
37 };
38 }
39
~WindowPair()40 WindowPair::~WindowPair()
41 {
42 WLOGD("~WindowPair");
43 Clear();
44 }
45
SendSplitScreenCommonEvent(SplitEventMsgType msgType,int32_t missionId)46 void WindowPair::SendSplitScreenCommonEvent(SplitEventMsgType msgType, int32_t missionId)
47 {
48 std::string data = splitEventDataMap.at(msgType);
49 std::string identity = IPCSkeleton::ResetCallingIdentity();
50 AAFwk::Want want;
51 want.SetAction(SPLIT_SCREEN_EVENT_NAME);
52 want.SetParam("windowMode", data);
53 want.SetParam("missionId", missionId);
54 EventFwk::CommonEventData commonEventData;
55 commonEventData.SetWant(want);
56 EventFwk::CommonEventManager::PublishCommonEvent(commonEventData);
57 // set ipc identity to raw
58 IPCSkeleton::SetCallingIdentity(identity);
59 WLOGD("Send split screen event: %{public}s", data.c_str());
60 }
61
NotifyShowRecent(sptr<WindowNode> node)62 void WindowPair::NotifyShowRecent(sptr<WindowNode> node)
63 {
64 if (node == nullptr) {
65 return;
66 }
67 auto msgType = (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) ?
68 SplitEventMsgType::MSG_SHOW_PRIMARY : SplitEventMsgType::MSG_SHOW_SECONDARY;
69 SendSplitScreenCommonEvent(msgType, node->abilityInfo_.missionId_);
70 }
71
NotifyCreateOrDestroyDivider(sptr<WindowNode> node,bool isDestroy)72 void WindowPair::NotifyCreateOrDestroyDivider(sptr<WindowNode> node, bool isDestroy)
73 {
74 if (node == nullptr) {
75 return;
76 }
77 auto msgType = isDestroy ? SplitEventMsgType::MSG_DESTROY_DIVIDER : SplitEventMsgType::MSG_SHOW_DIVIDER;
78 SendSplitScreenCommonEvent(msgType, node->abilityInfo_.missionId_);
79 }
80
Find(sptr<WindowNode> & node)81 sptr<WindowNode> WindowPair::Find(sptr<WindowNode>& node)
82 {
83 if (node == nullptr) {
84 return nullptr;
85 }
86 if (primary_ != nullptr && primary_->GetWindowId() == node->GetWindowId()) {
87 return primary_;
88 } else if (secondary_ != nullptr && secondary_->GetWindowId() == node->GetWindowId()) {
89 return secondary_;
90 } else if (divider_ != nullptr && divider_->GetWindowId() == node->GetWindowId()) {
91 return divider_;
92 }
93 return nullptr;
94 }
95
IsPaired() const96 bool WindowPair::IsPaired() const
97 {
98 if (primary_ == nullptr || secondary_ == nullptr) {
99 return false;
100 }
101 if (primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY &&
102 secondary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY &&
103 divider_ != nullptr) {
104 return true;
105 }
106 return false;
107 }
108
IsAbnormalStatus() const109 bool WindowPair::IsAbnormalStatus() const
110 {
111 if (status_ == WindowPairStatus::SINGLE_SPLIT || status_ == WindowPairStatus::PRIMARY_AND_DIVIDER ||
112 status_ == WindowPairStatus::SECONDARY_AND_DIVIDER) {
113 return true;
114 } else {
115 return false;
116 }
117 }
118
SetSplitRatio(float ratio)119 void WindowPair::SetSplitRatio(float ratio)
120 {
121 ratio_ = ratio;
122 }
123
GetSplitRatio() const124 float WindowPair::GetSplitRatio() const
125 {
126 return ratio_;
127 }
128
GetPairStatus() const129 WindowPairStatus WindowPair::GetPairStatus() const
130 {
131 return status_;
132 }
133
GetDividerWindow() const134 sptr<WindowNode> WindowPair::GetDividerWindow() const
135 {
136 return divider_;
137 }
138
IsForbidDockSliceMove() const139 bool WindowPair::IsForbidDockSliceMove() const
140 {
141 if (status_ != WindowPairStatus::PAIRED_DONE) {
142 return false;
143 }
144 uint32_t flag = static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE);
145 if (primary_ != nullptr && !(primary_->GetWindowFlags() & flag) && secondary_ != nullptr &&
146 !(secondary_->GetWindowFlags() & flag)) {
147 return false;
148 }
149 return true;
150 }
151
IsDockSliceInExitSplitModeArea(const std::vector<int32_t> & exitSplitPoints)152 bool WindowPair::IsDockSliceInExitSplitModeArea(const std::vector<int32_t>& exitSplitPoints)
153 {
154 if (!IsPaired()) {
155 return false;
156 }
157 int32_t dividerOrigin;
158 Rect rect = divider_->GetWindowRect();
159 if (rect.width_ < rect.height_) {
160 dividerOrigin = rect.posX_;
161 } else {
162 dividerOrigin = rect.posY_; // vertical display
163 }
164 if (dividerOrigin < exitSplitPoints[0] || dividerOrigin > exitSplitPoints[1]) {
165 return true;
166 }
167 return false;
168 }
169
ExitSplitMode()170 void WindowPair::ExitSplitMode()
171 {
172 if (!IsPaired()) {
173 return;
174 }
175 Rect dividerRect = divider_->GetWindowRect();
176 sptr<WindowNode> hideNode, recoveryNode;
177 bool isVertical = (dividerRect.height_ < dividerRect.width_) ? true : false;
178 if ((isVertical && (primary_->GetWindowRect().height_ < secondary_->GetWindowRect().height_)) ||
179 (!isVertical && (primary_->GetWindowRect().width_ < secondary_->GetWindowRect().width_))) {
180 hideNode = primary_;
181 recoveryNode = secondary_;
182 } else {
183 hideNode = secondary_;
184 recoveryNode = primary_;
185 }
186 if (recoveryNode != nullptr) {
187 recoveryNode->SetSnapshot(nullptr);
188 }
189 MinimizeApp::AddNeedMinimizeApp(hideNode, MinimizeReason::SPLIT_QUIT);
190 MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::SPLIT_QUIT);
191 WLOGI("Exit Split Mode, Minimize Window %{public}u", hideNode->GetWindowId());
192 }
193
Clear()194 void WindowPair::Clear()
195 {
196 WLOGI("Clear window pair.");
197 DumpPairInfo();
198 auto splitMode = (WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY |
199 WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_SECONDARY);
200 if (primary_ != nullptr && primary_->GetWindowProperty() != nullptr &&
201 primary_->GetWindowToken() != nullptr) {
202 if (primary_->GetWindowModeSupportType() == splitMode) {
203 MinimizeApp::AddNeedMinimizeApp(primary_, MinimizeReason::SPLIT_QUIT);
204 MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::SPLIT_QUIT);
205 } else {
206 if (WindowHelper::IsFullScreenWindow(primary_->GetWindowProperty()->GetLastWindowMode()) &&
207 WindowHelper::IsSplitWindowMode(primary_->GetWindowProperty()->GetWindowMode()) &&
208 primary_->GetWindowType() != WindowType::WINDOW_TYPE_LAUNCHER_RECENT) {
209 primary_->SetWindowSizeChangeReason(WindowSizeChangeReason::SPLIT_TO_FULL);
210 }
211 primary_->GetWindowProperty()->ResumeLastWindowMode();
212 // when change mode, need to reset shadow and radius
213 WindowSystemEffect::SetWindowEffect(primary_);
214 primary_->GetWindowToken()->UpdateWindowMode(primary_->GetWindowMode());
215 }
216 }
217 if (secondary_ != nullptr && secondary_->GetWindowProperty() != nullptr &&
218 secondary_->GetWindowToken() != nullptr) {
219 if (secondary_->GetWindowModeSupportType() == splitMode) {
220 MinimizeApp::AddNeedMinimizeApp(secondary_, MinimizeReason::SPLIT_QUIT);
221 MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::SPLIT_QUIT);
222 } else {
223 if (WindowHelper::IsFullScreenWindow(secondary_->GetWindowProperty()->GetLastWindowMode()) &&
224 WindowHelper::IsSplitWindowMode(secondary_->GetWindowProperty()->GetWindowMode()) &&
225 secondary_->GetWindowType() != WindowType::WINDOW_TYPE_LAUNCHER_RECENT) {
226 secondary_->SetWindowSizeChangeReason(WindowSizeChangeReason::SPLIT_TO_FULL);
227 }
228 secondary_->GetWindowProperty()->ResumeLastWindowMode();
229 // when change mode, need to reset shadow and radius
230 WindowSystemEffect::SetWindowEffect(secondary_);
231 secondary_->GetWindowToken()->UpdateWindowMode(secondary_->GetWindowMode());
232 }
233 }
234
235 primary_ = nullptr;
236 secondary_ = nullptr;
237 if (divider_ != nullptr) {
238 NotifyCreateOrDestroyDivider(divider_, true);
239 divider_ = nullptr;
240 }
241 status_ = WindowPairStatus::EMPTY;
242 }
243
IsSplitRelated(sptr<WindowNode> & node) const244 bool WindowPair::IsSplitRelated(sptr<WindowNode>& node) const
245 {
246 if (node == nullptr) {
247 return false;
248 }
249 return WindowHelper::IsSplitWindowMode((node->GetWindowMode())) ||
250 (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE);
251 }
252
CheckOrderedPairZorder(sptr<WindowNode> & node,bool & hasPrimaryDialog,bool & hasSecondaryDialog,bool & isPrimaryAbove)253 void WindowPair::CheckOrderedPairZorder(
254 sptr<WindowNode>& node, bool& hasPrimaryDialog, bool& hasSecondaryDialog, bool& isPrimaryAbove)
255 {
256 if (primary_ != nullptr) {
257 for (auto& child : primary_->children_) {
258 if (child->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
259 // secondary divider primary
260 hasPrimaryDialog = true;
261 isPrimaryAbove = true;
262 break;
263 }
264 }
265 }
266 if (secondary_ != nullptr) {
267 for (auto& child : secondary_->children_) {
268 if (child->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
269 // primary divider secondary
270 hasSecondaryDialog = true;
271 isPrimaryAbove = false;
272 break;
273 }
274 }
275 }
276 if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY ||
277 node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
278 // primary secondary divider
279 isPrimaryAbove = false;
280 } else if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
281 // secondary primary divider
282 isPrimaryAbove = true;
283 }
284
285 return;
286 }
287
CreateOrderedPair(sptr<WindowNode> & bottom,sptr<WindowNode> & mid,sptr<WindowNode> & top)288 std::vector<sptr<WindowNode>> WindowPair::CreateOrderedPair(
289 sptr<WindowNode>& bottom, sptr<WindowNode>& mid, sptr<WindowNode>& top)
290 {
291 std::vector<sptr<WindowNode>> orderedPair;
292
293 if (bottom != nullptr) {
294 orderedPair.push_back(bottom);
295 }
296 if (mid != nullptr) {
297 orderedPair.push_back(mid);
298 }
299 if (top != nullptr) {
300 orderedPair.push_back(top);
301 }
302
303 return orderedPair;
304 }
305
GetOrderedPair(sptr<WindowNode> & node)306 std::vector<sptr<WindowNode>> WindowPair::GetOrderedPair(sptr<WindowNode>& node)
307 {
308 WLOGI("Get paired node in Z order");
309 std::vector<sptr<WindowNode>> orderedPair;
310 bool hasPrimaryDialog_ = false;
311 bool hasSecondaryDialog_ = false;
312 bool isPrimaryAbove_ = false;
313
314 if (node == nullptr || Find(node) == nullptr) {
315 return orderedPair;
316 }
317
318 CheckOrderedPairZorder(node, hasPrimaryDialog_, hasSecondaryDialog_, isPrimaryAbove_);
319
320 if (hasPrimaryDialog_ && hasSecondaryDialog_) {
321 return CreateOrderedPair(divider_, primary_, secondary_);
322 }
323 if (hasPrimaryDialog_ || hasSecondaryDialog_) {
324 if (isPrimaryAbove_) {
325 return CreateOrderedPair(secondary_, divider_, primary_);
326 } else {
327 return CreateOrderedPair(primary_, divider_, secondary_);
328 }
329 } else {
330 if (isPrimaryAbove_) {
331 return CreateOrderedPair(secondary_, primary_, divider_);
332 } else {
333 return CreateOrderedPair(primary_, secondary_, divider_);
334 }
335 }
336 }
337
GetPairedWindows()338 std::vector<sptr<WindowNode>> WindowPair::GetPairedWindows()
339 {
340 WLOGD("Get primary and secondary of window pair");
341 std::vector<sptr<WindowNode>> pairWindows;
342 if (status_ == WindowPairStatus::PAIRED_DONE && primary_ != nullptr && secondary_ != nullptr) {
343 pairWindows = {primary_, secondary_};
344 }
345 return pairWindows;
346 }
347
StatusSupprtedWhenRecentUpdate(sptr<WindowNode> & node)348 bool WindowPair::StatusSupprtedWhenRecentUpdate(sptr<WindowNode>& node)
349 {
350 WindowMode recentMode_ = node->GetWindowMode();
351 if (recentMode_ == WindowMode::WINDOW_MODE_SPLIT_PRIMARY &&
352 (status_ == WindowPairStatus::SINGLE_SECONDARY || status_ == WindowPairStatus::SECONDARY_AND_DIVIDER)) {
353 return true;
354 } else if (recentMode_ == WindowMode::WINDOW_MODE_SPLIT_SECONDARY &&
355 (status_ == WindowPairStatus::SINGLE_PRIMARY || status_ == WindowPairStatus::PRIMARY_AND_DIVIDER)) {
356 return true;
357 }
358 return false;
359 }
360
UpdateIfSplitRelated(sptr<WindowNode> & node)361 void WindowPair::UpdateIfSplitRelated(sptr<WindowNode>& node)
362 {
363 if (node == nullptr) {
364 return;
365 }
366 if (Find(node) == nullptr && !IsSplitRelated(node)) {
367 WLOGFD("Window id: %{public}u is not split related and paired.", node->GetWindowId());
368 return;
369 }
370 if ((node->GetWindowType() == WindowType::WINDOW_TYPE_PLACEHOLDER) &&
371 ((primary_ != nullptr && primary_->GetWindowMode() == node->GetWindowMode()) ||
372 (secondary_ != nullptr && secondary_->GetWindowMode() == node->GetWindowMode()))) {
373 WindowInnerManager::GetInstance().DestroyInnerWindow(displayId_, WindowType::WINDOW_TYPE_PLACEHOLDER);
374 return;
375 }
376 WLOGI("Current status: %{public}u, window id: %{public}u mode: %{public}u",
377 status_, node->GetWindowId(), node->GetWindowMode());
378 // when status not support to start recent, clear split node and return
379 if (node->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT && node->IsSplitMode() &&
380 !StatusSupprtedWhenRecentUpdate(node)) {
381 Clear();
382 return;
383 }
384 if (status_ == WindowPairStatus::EMPTY) {
385 Insert(node);
386 if (!isAllSplitAppWindowsRestoring_) {
387 WindowMode holderMode = node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ?
388 WindowMode::WINDOW_MODE_SPLIT_SECONDARY : WindowMode::WINDOW_MODE_SPLIT_PRIMARY;
389 WindowInnerManager::GetInstance().CreateInnerWindow("place_holder", displayId_, DEFAULT_PLACE_HOLDER_RECT,
390 WindowType::WINDOW_TYPE_PLACEHOLDER, holderMode);
391 // notity systemui to create divider window
392 NotifyShowRecent(node);
393 }
394 } else {
395 if (Find(node) == nullptr) {
396 // add new split related node to pair
397 Insert(node);
398 } else {
399 // handle paired nodes change
400 HandlePairedNodesChange();
401 }
402 }
403 }
404
UpdateWindowPairStatus()405 void WindowPair::UpdateWindowPairStatus()
406 {
407 WLOGI("Update window pair status.");
408 WindowPairStatus prevStatus = status_;
409 if (primary_ != nullptr && secondary_ != nullptr && divider_ != nullptr) {
410 status_ = WindowPairStatus::PAIRED_DONE;
411 } else if (primary_ != nullptr && secondary_ != nullptr && divider_ == nullptr) {
412 status_ = WindowPairStatus::PRIMARY_AND_SECONDARY;
413 } else if (primary_ != nullptr && secondary_ == nullptr && divider_ == nullptr) {
414 status_ = WindowPairStatus::SINGLE_PRIMARY;
415 } else if (primary_ != nullptr && secondary_ == nullptr && divider_ != nullptr) {
416 status_ = WindowPairStatus::PRIMARY_AND_DIVIDER;
417 } else if (primary_ == nullptr && secondary_ != nullptr && divider_ == nullptr) {
418 status_ = WindowPairStatus::SINGLE_SECONDARY;
419 } else if (primary_ == nullptr && secondary_ != nullptr && divider_ != nullptr) {
420 status_ = WindowPairStatus::SECONDARY_AND_DIVIDER;
421 } else if (primary_ == nullptr && secondary_ == nullptr && divider_ != nullptr) {
422 status_ = WindowPairStatus::SINGLE_SPLIT;
423 } else {
424 status_ = WindowPairStatus::EMPTY;
425 }
426 if ((prevStatus == WindowPairStatus::SINGLE_PRIMARY ||
427 prevStatus == WindowPairStatus::SINGLE_SECONDARY || prevStatus == WindowPairStatus::EMPTY) &&
428 status_ == WindowPairStatus::PRIMARY_AND_SECONDARY) {
429 // notify systemui to create divider
430 NotifyCreateOrDestroyDivider(primary_, false);
431 } else if ((prevStatus == WindowPairStatus::PAIRED_DONE || prevStatus == WindowPairStatus::PRIMARY_AND_SECONDARY) &&
432 (status_ != WindowPairStatus::PAIRED_DONE && status_ != WindowPairStatus::PRIMARY_AND_SECONDARY)) {
433 Clear();
434 }
435 DumpPairInfo();
436 }
437
SwitchPosition()438 void WindowPair::SwitchPosition()
439 {
440 if (primary_ == nullptr || secondary_ == nullptr) {
441 return;
442 }
443 WLOGI("Switch the pair pos, pri: %{public}u pri-mode: %{public}u, sec: %{public}u sec-mode: %{public}u,",
444 primary_->GetWindowId(), primary_->GetWindowMode(), secondary_->GetWindowId(), secondary_->GetWindowMode());
445 if (primary_->GetWindowMode() == secondary_->GetWindowMode() &&
446 primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
447 primary_->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY);
448 // when change mode, need to reset shadow and radius
449 WindowSystemEffect::SetWindowEffect(primary_);
450 if (primary_->GetWindowToken() != nullptr) {
451 primary_->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_SPLIT_SECONDARY);
452 }
453 std::swap(primary_, secondary_);
454 } else if (primary_->GetWindowMode() == secondary_->GetWindowMode() &&
455 primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
456 secondary_->SetWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
457 // when change mode, need to reset shadow and radius
458 WindowSystemEffect::SetWindowEffect(secondary_);
459 if (secondary_->GetWindowToken() != nullptr) {
460 secondary_->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_SPLIT_PRIMARY);
461 }
462 std::swap(primary_, secondary_);
463 }
464 }
465
HandlePairedNodesChange()466 void WindowPair::HandlePairedNodesChange()
467 {
468 WLOGI("Update pair node.");
469 if (primary_ != nullptr && !primary_->IsSplitMode()) {
470 primary_ = nullptr;
471 }
472 if (secondary_ != nullptr && !secondary_->IsSplitMode()) {
473 secondary_ = nullptr;
474 }
475 // paired node mode change
476 if (primary_ != nullptr && secondary_ == nullptr &&
477 primary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
478 std::swap(primary_, secondary_);
479 } else if (primary_ == nullptr && secondary_ != nullptr &&
480 secondary_->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
481 std::swap(primary_, secondary_);
482 } else if (primary_ != nullptr && secondary_ != nullptr &&
483 primary_->GetWindowMode() == secondary_->GetWindowMode()) {
484 // switch position
485 SwitchPosition();
486 }
487 UpdateWindowPairStatus();
488 if (IsAbnormalStatus()) {
489 Clear();
490 }
491 }
492
Insert(sptr<WindowNode> & node)493 void WindowPair::Insert(sptr<WindowNode>& node)
494 {
495 if (node == nullptr) {
496 return;
497 }
498 WLOGI("Insert a window to pair id: %{public}u", node->GetWindowId());
499 sptr<WindowNode> pairedNode;
500 if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_PRIMARY) {
501 pairedNode = primary_;
502 primary_ = node;
503 } else if (node->GetWindowMode() == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
504 pairedNode = secondary_;
505 secondary_ = node;
506 } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
507 pairedNode = divider_;
508 divider_ = node;
509 }
510 // minimize invalid paired window
511 if (pairedNode != nullptr && pairedNode->abilityToken_ != nullptr) {
512 MinimizeApp::AddNeedMinimizeApp(pairedNode, MinimizeReason::SPLIT_REPLACE);
513 }
514 UpdateWindowPairStatus();
515 if (IsAbnormalStatus()) {
516 Clear();
517 }
518 }
519
DumpPairInfo()520 void WindowPair::DumpPairInfo()
521 {
522 if (primary_ != nullptr) {
523 WLOGI("[DumpPairInfo] primary id: %{public}u mode: %{public}u", primary_->GetWindowId(),
524 primary_->GetWindowMode());
525 }
526 if (secondary_ != nullptr) {
527 WLOGI("[DumpPairInfo] secondary id: %{public}u mode: %{public}u", secondary_->GetWindowId(),
528 secondary_->GetWindowMode());
529 }
530 if (divider_ != nullptr) {
531 WLOGI("[DumpPairInfo] divider id: %{public}u mode: %{public}u", divider_->GetWindowId(),
532 divider_->GetWindowMode());
533 }
534 WLOGI("[DumpPairInfo] pair status %{public}u", status_);
535 }
536
HandleRemoveWindow(sptr<WindowNode> & node)537 void WindowPair::HandleRemoveWindow(sptr<WindowNode>& node)
538 {
539 if (node == nullptr) {
540 return;
541 }
542 if (Find(node) == nullptr && node->IsSplitMode()) {
543 WLOGI("Resume unpaired split related window id: %{public}u", node->GetWindowId());
544 if (node->GetWindowProperty() != nullptr && node->GetWindowToken() != nullptr) {
545 node->GetWindowProperty()->ResumeLastWindowMode();
546 // when change mode, need to reset shadow and radius
547 WindowSystemEffect::SetWindowEffect(node);
548 node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode());
549 }
550 // target node is not in window pair, need resume mode when remove
551 return;
552 } else if (Find(node) != nullptr) {
553 WLOGI("Pairing window id: %{public}u is remove, clear window pair", node->GetWindowId());
554 Clear();
555 }
556 }
557
RotateDividerWindow(const Rect & rect)558 void WindowPair::RotateDividerWindow(const Rect& rect)
559 {
560 dividerRect_ = rect;
561 // rotate divider when display orientation changed
562 if (divider_ == nullptr) {
563 WLOGE("Rotate divider failed because divider is null");
564 return;
565 }
566 WLOGFD("Rotate divider when display rotate rect:[%{public}d, %{public}d, %{public}u, %{public}u]",
567 rect.posX_, rect.posY_, rect.width_, rect.height_);
568 }
569
SetDividerRect(const Rect & rect)570 void WindowPair::SetDividerRect(const Rect& rect)
571 {
572 dividerRect_ = rect;
573 }
574
TakePairSnapshot()575 bool WindowPair::TakePairSnapshot()
576 {
577 if (status_ == WindowPairStatus::PAIRED_DONE && primary_ != nullptr && secondary_ != nullptr) {
578 WLOGD("Take pair snapshot id:[%{public}u, %{public}u]", primary_->GetWindowId(), secondary_->GetWindowId());
579 std::shared_ptr<Media::PixelMap> pixelMap;
580 // get pixelmap time out 2000ms
581 if (SurfaceDraw::GetSurfaceSnapshot(primary_->surfaceNode_, pixelMap, SNAPSHOT_TIMEOUT_MS)) {
582 primary_->SetSnapshot(pixelMap);
583 }
584 // get pixelmap time out 2000ms
585 if (SurfaceDraw::GetSurfaceSnapshot(secondary_->surfaceNode_, pixelMap, SNAPSHOT_TIMEOUT_MS)) {
586 secondary_->SetSnapshot(pixelMap);
587 }
588 return true;
589 }
590 return false;
591 }
592
ClearPairSnapshot()593 void WindowPair::ClearPairSnapshot()
594 {
595 WLOGD("Clear window pair snapshot");
596 if (primary_ != nullptr) {
597 primary_->SetSnapshot(nullptr);
598 }
599 if (secondary_ != nullptr) {
600 secondary_->SetSnapshot(nullptr);
601 }
602 }
603
GetSplitRatioPoint(float ratio,const Rect & displayRect)604 int32_t WindowPair::GetSplitRatioPoint(float ratio, const Rect& displayRect)
605 {
606 if (displayRect.width_ > displayRect.height_) {
607 return displayRect.posX_ +
608 static_cast<uint32_t>((displayRect.width_ - dividerRect_.width_) * ratio);
609 } else {
610 return displayRect.posY_ +
611 static_cast<uint32_t>((displayRect.height_ - dividerRect_.height_) * ratio);
612 }
613 }
614
CalculateSplitRatioPoints(const Rect & displayRect)615 void WindowPair::CalculateSplitRatioPoints(const Rect& displayRect)
616 {
617 exitSplitPoints_.clear();
618 splitRatioPoints_.clear();
619 exitSplitPoints_.push_back(GetSplitRatioPoint(splitRatioConfig_.exitSplitStartRatio, displayRect));
620 exitSplitPoints_.push_back(GetSplitRatioPoint(splitRatioConfig_.exitSplitEndRatio, displayRect));
621 for (const auto& ratio : splitRatioConfig_.splitRatios) {
622 splitRatioPoints_.push_back(GetSplitRatioPoint(ratio, displayRect));
623 }
624 }
625
SetSplitRatioConfig(const SplitRatioConfig & splitRatioConfig)626 void WindowPair::SetSplitRatioConfig(const SplitRatioConfig& splitRatioConfig)
627 {
628 splitRatioConfig_ = splitRatioConfig;
629 }
630
GetExitSplitPoints()631 std::vector<int32_t> WindowPair::GetExitSplitPoints()
632 {
633 return exitSplitPoints_;
634 }
635
GetSplitRatioPoints()636 std::vector<int32_t> WindowPair::GetSplitRatioPoints()
637 {
638 return splitRatioPoints_;
639 }
640
IsDuringSplit()641 bool WindowPair::IsDuringSplit()
642 {
643 if (status_ == WindowPairStatus::EMPTY) {
644 return false;
645 }
646
647 if (status_ != WindowPairStatus::PAIRED_DONE || primary_ == nullptr || secondary_ == nullptr) {
648 WLOGFD("missing pairWindows or split status is %{public}u not done", status_);
649 return true;
650 }
651
652 if (primary_->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT ||
653 secondary_->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT) {
654 WLOGFD("split is done, but there is recent");
655 return true;
656 }
657
658 return false;
659 }
660 } // namespace Rosen
661 } // namespace OHOS