1/*
2 * Copyright (c) 2021-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 "window_controller.h"
17#include <ability_manager_client.h>
18#include <chrono>
19#include <cstdint>
20#include <hisysevent.h>
21#include <hitrace_meter.h>
22#include <parameters.h>
23#include <rs_window_animation_finished_callback.h>
24#include <transaction/rs_transaction.h>
25#include <transaction/rs_sync_transaction_controller.h>
26#include <sstream>
27
28#ifdef POWER_MANAGER_ENABLE
29#include <power_mgr_client.h>
30#endif
31
32#include "display_group_info.h"
33#include "display_manager_service_inner.h"
34#include "minimize_app.h"
35#include "persistent_storage.h"
36#include "surface_capture_future.h"
37#include "remote_animation.h"
38#include "starting_window.h"
39#include "window_inner_manager.h"
40#include "window_manager_hilog.h"
41#include "window_helper.h"
42#include "window_system_effect.h"
43#include "wm_common.h"
44#include "wm_math.h"
45#include "permission.h"
46
47namespace OHOS {
48namespace Rosen {
49namespace {
50constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "Controller"};
51constexpr uint32_t TOUCH_HOT_AREA_MAX_NUM = 50;
52constexpr float MASKING_SURFACE_NODE_Z_ORDER = 9999;
53}
54
55uint32_t WindowController::GenWindowId()
56{
57    return ++windowId_;
58}
59
60void WindowController::StartingWindow(sptr<WindowTransitionInfo> info, std::shared_ptr<Media::PixelMap> pixelMap,
61    uint32_t bkgColor, bool isColdStart)
62{
63    if (!info || info->GetAbilityToken() == nullptr) {
64        WLOGFE("info or AbilityToken is nullptr!");
65        return;
66    }
67    StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::STARTING_WINDOW),
68        "wms:async:ShowStartingWindow");
69    auto node = windowRoot_->FindWindowNodeWithToken(info->GetAbilityToken());
70    if (node == nullptr) {
71        if (!isColdStart) {
72            WLOGFE("no windowNode exists but is hot start!");
73            return;
74        }
75        node = StartingWindow::CreateWindowNode(info, GenWindowId());
76        if (node == nullptr) {
77            return;
78        }
79        if (windowRoot_->SaveWindow(node) != WMError::WM_OK) {
80            return;
81        }
82        if (!RemoteAnimation::CheckAnimationController()) {
83            UpdateWindowAnimation(node);
84        }
85    } else {
86        if (node->stateMachine_.IsWindowNodeShownOrShowing()) {
87            WLOGFI("WindowId:%{public}u state:%{public}u!",
88                node->GetWindowId(), static_cast<uint32_t>(node->stateMachine_.GetCurrentState()));
89            return;
90        }
91        if (WindowHelper::IsValidWindowMode(info->GetWindowMode()) &&
92            (node->GetWindowMode() != info->GetWindowMode())) {
93            WLOGFW("set starting window mode. starting mode is: %{public}u, window mode is:%{public}u.",
94                node->GetWindowMode(), info->GetWindowMode());
95            node->SetWindowMode(info->GetWindowMode());
96        }
97    }
98
99    if (!WindowHelper::CheckSupportWindowMode(node->GetWindowMode(), node->GetModeSupportInfo(), info)) {
100        WLOGFE("need to cancel starting window");
101        return;
102    }
103
104    if (windowRoot_->AddWindowNode(0, node, true) != WMError::WM_OK) {
105        return;
106    }
107    StartingWindow::DrawStartingWindow(node, pixelMap, bkgColor, isColdStart);
108    FlushWindowInfo(node->GetWindowId());
109    node->startingWindowShown_ = true;
110    WLOGFI("Show success, id:%{public}u!", node->GetWindowId());
111}
112
113void WindowController::CancelStartingWindow(sptr<IRemoteObject> abilityToken)
114{
115    auto node = windowRoot_->FindWindowNodeWithToken(abilityToken);
116    if (node == nullptr) {
117        WLOGFE("Node is nullptr");
118        return;
119    }
120    if (!node->startingWindowShown_) {
121        WLOGFE("CancelStartingWindow failed because client window has shown id:%{public}u", node->GetWindowId());
122        return;
123    }
124    HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "wms:CancelStartingWindow(%u)", node->GetWindowId());
125    FinishAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::STARTING_WINDOW),
126        "wms:async:ShowStartingWindow");
127    WLOGFI("Id:%{public}u!", node->GetWindowId());
128    node->isAppCrash_ = true;
129    WMError res = DestroyWindow(node->GetWindowId(), false);
130    if (res != WMError::WM_OK) {
131        WLOGFE("DestroyWindow failed!");
132    }
133}
134
135WMError WindowController::NotifyWindowTransition(sptr<WindowTransitionInfo>& srcInfo,
136    sptr<WindowTransitionInfo>& dstInfo)
137{
138    WLOGI("NotifyWindowTransition begin!");
139    sptr<WindowNode> dstNode = nullptr;
140    sptr<WindowNode> srcNode = nullptr;
141    if (srcInfo) {
142        srcNode = windowRoot_->FindWindowNodeWithToken(srcInfo->GetAbilityToken());
143    }
144    if (dstInfo) {
145        dstNode = windowRoot_->FindWindowNodeWithToken(dstInfo->GetAbilityToken());
146    }
147    if (!RemoteAnimation::CheckTransition(srcInfo, srcNode, dstInfo, dstNode)) {
148        return WMError::WM_ERROR_NO_REMOTE_ANIMATION;
149    }
150    StartAsyncTraceArgs(HITRACE_TAG_WINDOW_MANAGER, static_cast<int32_t>(TraceTaskId::REMOTE_ANIMATION),
151        "wms:async:ShowRemoteAnimation");
152    auto transitionEvent = RemoteAnimation::GetTransitionEvent(srcInfo, dstInfo, srcNode, dstNode);
153    switch (transitionEvent) {
154        case TransitionEvent::APP_TRANSITION: {
155            return RemoteAnimation::NotifyAnimationTransition(srcInfo, dstInfo, srcNode, dstNode);
156        }
157        case TransitionEvent::MINIMIZE:
158            return RemoteAnimation::NotifyAnimationMinimize(srcInfo, srcNode);
159        case TransitionEvent::CLOSE:
160        case TransitionEvent::CLOSE_BUTTON:
161            return RemoteAnimation::NotifyAnimationClose(srcInfo, srcNode, transitionEvent);
162        case TransitionEvent::BACK_TRANSITION:
163        case TransitionEvent::BACKGROUND_TRANSITION:
164            return RemoteAnimation::NotifyAnimationBackTransition(srcInfo, dstInfo, srcNode, dstNode, transitionEvent);
165        default:
166            return WMError::WM_ERROR_NO_REMOTE_ANIMATION;
167    }
168    return WMError::WM_OK;
169}
170
171WMError WindowController::GetFocusWindowNode(DisplayId displayId, sptr<WindowNode>& windowNode)
172{
173    auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
174    if (windowNodeContainer == nullptr) {
175        WLOGFE("Container is null, displayId: %{public}" PRIu64"", displayId);
176        return WMError::WM_ERROR_NULLPTR;
177    }
178    uint32_t focusWindowId = windowNodeContainer->GetFocusWindow();
179    WLOGFD("Now focusId: %{public}u", focusWindowId);
180    auto thisWindowNode = windowRoot_->GetWindowNode(focusWindowId);
181    if (thisWindowNode == nullptr || !thisWindowNode->currentVisibility_) {
182        WLOGFE("Node is null or invisible, id: %{public}u", focusWindowId);
183        return WMError::WM_ERROR_INVALID_WINDOW;
184    }
185    windowNode = thisWindowNode;
186    return WMError::WM_OK;
187}
188
189WMError WindowController::GetFocusWindowInfo(sptr<IRemoteObject>& abilityToken)
190{
191    DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
192    sptr<WindowNode> windowNode;
193    WMError res = GetFocusWindowNode(displayId, windowNode);
194    if (res == WMError::WM_OK) {
195        abilityToken = windowNode->abilityToken_;
196    }
197    return res;
198}
199
200WMError WindowController::GetFocusWindowInfo(FocusChangeInfo& focusInfo)
201{
202    DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
203    sptr<WindowNode> windowNode;
204    WMError res = GetFocusWindowNode(displayId, windowNode);
205    if (res == WMError::WM_OK) {
206        WLOGFD("Get focus window info success");
207        focusInfo.windowId_ = static_cast<int32_t>(windowNode->GetWindowId());
208        focusInfo.displayId_ = windowNode->GetDisplayId();
209        focusInfo.pid_ = windowNode->GetCallingPid();
210        focusInfo.uid_ = windowNode->GetCallingUid();
211        focusInfo.windowType_ = windowNode->GetWindowType();
212        focusInfo.abilityToken_ = windowNode->abilityToken_;
213    }
214    return res;
215}
216
217bool WindowController::CheckParentWindowValid(const sptr<WindowProperty>& property)
218{
219    if (WindowHelper::IsSubWindow(property->GetWindowType())) {
220        if (property->GetParentId() == INVALID_WINDOW_ID) {
221            WLOGFE("failed, sub window parent type is invalid");
222            return false;
223        }
224        sptr<WindowNode> parentWindow = windowRoot_->GetWindowNode(property->GetParentId());
225        if (parentWindow == nullptr) {
226            WLOGFE("failed, sub window parent type is error");
227            return false;
228        }
229    } else if (WindowHelper::IsSystemSubWindow(property->GetWindowType())) {
230        if (property->GetParentId() == INVALID_WINDOW_ID) {
231            WLOGFE("failed, sub system window parent type is invalid");
232            return false;
233        }
234        sptr<WindowNode> parentWindow = windowRoot_->GetWindowNode(property->GetParentId());
235        if (parentWindow == nullptr || !WindowHelper::IsSystemWindow(parentWindow->GetWindowType())) {
236            WLOGFE("failed, sub system window parent type is error");
237            return false;
238        }
239    } else {
240        if (property->GetParentId() != INVALID_WINDOW_ID) {
241            WLOGFE("failed, type is error");
242            return false;
243        }
244    }
245    return true;
246}
247
248WMError WindowController::CreateWindow(sptr<IWindow>& window, sptr<WindowProperty>& property,
249    const std::shared_ptr<RSSurfaceNode>& surfaceNode, uint32_t& windowId, sptr<IRemoteObject> token,
250    int32_t pid, int32_t uid)
251{
252    if (!CheckParentWindowValid(property)) {
253        return WMError::WM_ERROR_INVALID_PARENT;
254    }
255
256    if (!surfaceNode) {
257        return WMError::WM_ERROR_NULLPTR;
258    }
259
260    if (property->GetWindowType() != WindowType::WINDOW_TYPE_BOOT_ANIMATION) {
261        surfaceNode->SetFrameGravity(Gravity::RESIZE);
262    }
263
264    sptr<WindowNode> node = windowRoot_->FindWindowNodeWithToken(token);
265    if (node != nullptr && WindowHelper::IsMainWindow(property->GetWindowType()) && node->startingWindowShown_) {
266        StartingWindow::HandleClientWindowCreate(node, window, windowId, surfaceNode, property, pid, uid);
267        windowRoot_->AddDeathRecipient(node);
268        windowRoot_->AddSurfaceNodeIdWindowNodePair(surfaceNode->GetId(), node);
269        WLOGFD("Flags: %{public}u, API version: %{public}u", property->GetWindowFlags(),
270            node->GetWindowProperty()->GetApiCompatibleVersion());
271        if (property->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED) &&
272            node->GetWindowProperty()->GetApiCompatibleVersion() >= 9 && !property->isSystemCalling_) { // 9: API ver.
273            property->SetWindowFlags(property->GetWindowFlags() &
274                ~static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED));
275        }
276        property->SetApiCompatibleVersion(node->GetWindowProperty()->GetApiCompatibleVersion());
277        return WMError::WM_OK;
278    }
279
280    windowId = GenWindowId();
281    sptr<WindowProperty> windowProperty = new WindowProperty(property);
282    windowProperty->SetWindowId(windowId);
283    node = new WindowNode(windowProperty, window, surfaceNode, pid, uid);
284    node->abilityToken_ = token;
285    node->dialogTargetToken_ = token;
286    UpdateWindowAnimation(node);
287    // for system and subwindow
288    WindowSystemEffect::SetWindowEffect(node);
289    WLOGFD("createWindow id:%{public}u", windowId);
290
291    node->stateMachine_.SetWindowId(windowId);
292    node->stateMachine_.SetWindowType(property->GetWindowType());
293    return windowRoot_->SaveWindow(node);
294}
295
296void WindowController::NotifyAfterAddWindow(sptr<WindowNode>& node)
297{
298    std::vector<sptr<WindowNode>> nodes;
299    nodes.emplace_back(node);
300    for (auto& child : node->children_) {
301        if (child->currentVisibility_) {
302            nodes.emplace_back(child);
303        }
304    }
305    for (auto& iter : nodes) {
306        if ((iter->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) &&
307            (node->abilityToken_ != iter->abilityToken_)) {
308            iter->GetWindowToken()->NotifyForeground();
309        }
310    }
311    accessibilityConnection_->NotifyAccessibilityWindowInfo(node->GetDisplayId(), nodes,
312        WindowUpdateType::WINDOW_UPDATE_ADDED);
313}
314
315WMError WindowController::AddWindowNode(sptr<WindowProperty>& property)
316{
317    auto node = windowRoot_->GetWindowNode(property->GetWindowId());
318    if (node == nullptr) {
319        WLOGFE("could not find window");
320        return WMError::WM_ERROR_NULLPTR;
321    }
322
323    if (node->currentVisibility_ && !node->startingWindowShown_) {
324        WLOGFE("Current window is visible, windowId: %{public}u", node->GetWindowId());
325        return WMError::WM_ERROR_INVALID_OPERATION;
326    }
327
328    // using starting window rect if client rect is empty
329    if (WindowHelper::IsEmptyRect(property->GetRequestRect()) && node->startingWindowShown_) { // for tile and cascade
330        property->SetRequestRect(node->GetRequestRect());
331        property->SetWindowRect(node->GetWindowRect());
332        property->SetDecoStatus(true);
333    }
334    node->GetWindowProperty()->CopyFrom(property);
335    UpdateWindowAnimation(node);
336
337    RelayoutKeyboard(node);
338    WMError res = windowRoot_->AddWindowNode(property->GetParentId(), node);
339    if (res != WMError::WM_OK) {
340        MinimizeApp::ClearNodesWithReason(MinimizeReason::OTHER_WINDOW);
341        return res;
342    }
343    windowRoot_->FocusFaultDetection();
344
345    FlushWindowInfo(property->GetWindowId());
346    NotifyAfterAddWindow(node);
347    HandleTurnScreenOn(node);
348
349    if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
350        sysBarWinId_[node->GetWindowType()] = node->GetWindowId();
351    }
352    if (node->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
353        ResizeSoftInputCallingWindowIfNeed(node);
354    }
355    StopBootAnimationIfNeed(node);
356    // when hide with remote animation first and show with default animation, need transform state
357    // minimize should execute in finish callback when remote animation enabled
358    if (!node->stateMachine_.IsShowAnimationPlaying()) {
359        if (WindowHelper::IsMainWindow(node->GetWindowType())) {
360            MinimizeApp::ExecuteMinimizeAll();
361            WLOGI("Id:%{public}u execute minimize all", node->GetWindowId());
362        }
363        node->stateMachine_.TransitionTo(WindowNodeState::SHOWN); // for normal show which not use remote animation
364    } else if (WindowHelper::IsMainWindow(node->GetWindowType())) {
365        MinimizeApp::ExecuteMinimizeTargetReasons(~MinimizeReason::OTHER_WINDOW);
366    }
367
368    return WMError::WM_OK;
369}
370
371bool WindowController::GetNavigationBarHeight(DisplayId displayId, uint32_t& navigationBarHeight)
372{
373    auto container = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
374    if (container == nullptr) {
375        WLOGFE("Node container is null");
376        return false;
377    }
378
379    bool hasFullScreenKeyGuardWindow = false;
380    WindowNodeOperationFunc func = [&navigationBarHeight, &hasFullScreenKeyGuardWindow](sptr<WindowNode> windowNode) {
381        if (!windowNode) {
382            WLOGFE("The window node is nullptr.");
383            return false;
384        }
385        if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD &&
386            windowNode->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN) {
387                hasFullScreenKeyGuardWindow = true;
388        }
389        if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_NAVIGATION_BAR &&
390            windowNode->GetVisibilityState() < WINDOW_VISIBILITY_STATE_TOTALLY_OCCUSION) {
391            navigationBarHeight = windowNode->GetWindowRect().height_;
392            if (hasFullScreenKeyGuardWindow) {
393                WLOGFW("The navigation bar is overlaid by the keyguard window and is invisible");
394                navigationBarHeight = 0;
395            }
396            return true;
397        }
398        return false;
399    };
400    container->TraverseWindowTree(func, true); // FromTopToBottom
401
402    return true;
403}
404
405void WindowController::RelayoutKeyboard(const sptr<WindowNode>& node)
406{
407    if (node == nullptr) {
408        WLOGFE("Node is nullptr");
409        return;
410    }
411    WindowGravity gravity;
412    uint32_t percent = 0;
413    node->GetWindowGravity(gravity, percent);
414    if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT ||
415        gravity == WindowGravity::WINDOW_GRAVITY_FLOAT) {
416        return;
417    }
418
419    auto container = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId());
420    if (container == nullptr) {
421        WLOGFE("Node container is null");
422        return;
423    }
424
425    uint32_t navigationBarHeight = 0;
426    bool res = GetNavigationBarHeight(node->GetDisplayId(), navigationBarHeight);
427    if (res == false) {
428        return;
429    }
430
431    sptr<DisplayInfo> defaultDisplayInfo = DisplayGroupInfo::GetInstance().GetDefaultDisplayInfo();
432    if (defaultDisplayInfo == nullptr) {
433        WLOGFE("defaultDisplayInfo is null");
434        return;
435    }
436
437    auto requestRect = node->GetRequestRect();
438    if (gravity == WindowGravity::WINDOW_GRAVITY_BOTTOM) {
439        if (percent != 0) {
440            requestRect.width_ = static_cast<uint32_t>(defaultDisplayInfo->GetWidth());
441            requestRect.height_ =
442                static_cast<uint32_t>(defaultDisplayInfo->GetHeight()) * percent / 100u; // 100: for calc percent.
443            requestRect.posX_ = 0;
444        }
445    }
446    requestRect.posY_ = defaultDisplayInfo->GetHeight() -
447        static_cast<int32_t>(requestRect.height_ + navigationBarHeight);
448    node->SetRequestRect(requestRect);
449}
450
451void WindowController::NotifyInputCallingWindowRectAndOccupiedAreaChange(const sptr<WindowNode>& callingWindow,
452    const Rect& rect, const Rect& occupiedArea)
453{
454    if (callingWindow->GetWindowType() != WindowType::WINDOW_TYPE_APP_COMPONENT) {
455        // update calling window rect
456        callingWindow->SetWindowRect(rect);
457        WindowLayoutPolicy::CalcAndSetNodeHotZone(rect, callingWindow);
458
459        // set bounds and do animation for calling window
460        wptr<WindowNode> weakNode = callingWindow;
461        auto setBoundsFun = [weakNode, rect]() {
462            auto winNode = weakNode.promote();
463            if (winNode == nullptr) {
464                WLOGFW("Window node is nullptr");
465                return;
466            }
467            if (winNode->leashWinSurfaceNode_) {
468                winNode->leashWinSurfaceNode_->SetBounds(rect.posX_, rect.posY_, rect.width_, rect.height_);
469                if (winNode->startingWinSurfaceNode_) {
470                    winNode->startingWinSurfaceNode_->SetBounds(0, 0, rect.width_, rect.height_);
471                }
472                if (winNode->surfaceNode_) {
473                    winNode->surfaceNode_->SetBounds(0, 0, rect.width_, rect.height_);
474                }
475            } else {
476                if (winNode->surfaceNode_) {
477                    winNode->surfaceNode_->SetBounds(rect.posX_, rect.posY_, rect.width_, rect.height_);
478                }
479            }
480        };
481
482        const AnimationConfig::KeyboardAnimation& animation = WindowHelper::IsEmptyRect(occupiedArea) ?
483            WindowNodeContainer::GetAnimationConfigRef().keyboardAnimationOut_ :
484            WindowNodeContainer::GetAnimationConfigRef().keyboardAnimationIn_;
485        RSNode::Animate(animation.duration_, animation.curve_, setBoundsFun);
486    }
487
488    // if keyboard will occupy calling, notify calling window the occupied area and safe height
489    const Rect& safeRect = WindowHelper::GetOverlap(occupiedArea, rect, 0, 0);
490    sptr<OccupiedAreaChangeInfo> info = new OccupiedAreaChangeInfo(OccupiedAreaType::TYPE_INPUT,
491        safeRect, safeRect.height_);
492
493    if (WindowNodeContainer::GetAnimateTransactionEnabled()) {
494        auto syncTransactionController = RSSyncTransactionController::GetInstance();
495        if (syncTransactionController) {
496            callingWindow->GetWindowToken()->UpdateOccupiedAreaAndRect(info, rect,
497                syncTransactionController->GetRSTransaction());
498        }
499    } else {
500        callingWindow->GetWindowToken()->UpdateOccupiedAreaAndRect(info, rect);
501    }
502
503    FlushWindowInfo(callingWindow->GetWindowId());
504    accessibilityConnection_->NotifyAccessibilityWindowInfo(callingWindow, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
505    WLOGFD("Calling windowId: %{public}u, calling winRect: [%{public}d, %{public}d, %{public}u, %{public}u], "
506        "occupiedArea: [%{public}d, %{public}d, %{public}u, %{public}u], safeHeight: %{public}u",
507        callingWindow->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_,
508        occupiedArea.posX_, occupiedArea.posY_, occupiedArea.width_, occupiedArea.height_, safeRect.height_);
509}
510
511void WindowController::ResizeSoftInputCallingWindowIfNeed(const sptr<WindowNode>& node)
512{
513    auto callingWindowId = node->GetCallingWindow();
514    auto callingWindow = windowRoot_->GetWindowNode(callingWindowId);
515    if (callingWindow == nullptr) {
516        auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId());
517        if (windowNodeContainer == nullptr) {
518            WLOGFE("NodeContainer is null, displayId:%{public}" PRIu64"", node->GetDisplayId());
519            return;
520        }
521        callingWindowId = windowNodeContainer->GetFocusWindow();
522        callingWindow = windowRoot_->GetWindowNode(callingWindowId);
523    }
524    if (callingWindow == nullptr || !callingWindow->currentVisibility_ ||
525        callingWindow->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) {
526        WLOGFE("callingWindow is null or invisible or not float window, callingWindowId:%{public}u", callingWindowId);
527        return;
528    }
529    WindowGravity gravity;
530    uint32_t percent = 0;
531    node->GetWindowGravity(gravity, percent);
532    if (gravity != WindowGravity::WINDOW_GRAVITY_BOTTOM) {
533        WLOGFI("input method window gravity is not bottom, no need to raise calling window");
534        return;
535    }
536
537    const Rect& softInputWindowRect = node->GetWindowRect();
538    const Rect& callingWindowRect = callingWindow->GetWindowRect();
539    if (WindowHelper::IsEmptyRect(WindowHelper::GetOverlap(softInputWindowRect, callingWindowRect, 0, 0))) {
540        WLOGFD("There is no overlap area");
541        return;
542    }
543
544    // calculate new rect of calling window
545    Rect newRect = callingWindowRect;
546    if (callingWindow->GetWindowType() != WindowType::WINDOW_TYPE_APP_COMPONENT) {
547        newRect.posY_ = softInputWindowRect.posY_ - static_cast<int32_t>(newRect.height_);
548        Rect statusBarWindowRect = { 0, 0, 0, 0 };
549        auto statusbarWindow = windowRoot_->GetWindowNode(sysBarWinId_[WindowType::WINDOW_TYPE_STATUS_BAR]);
550        if (statusbarWindow != nullptr && statusbarWindow->parent_ != nullptr) {
551            statusBarWindowRect = statusbarWindow->GetWindowRect();
552        }
553        newRect.posY_ = std::max(newRect.posY_,
554            statusBarWindowRect.posY_ + static_cast<int32_t>(statusBarWindowRect.height_));
555
556        callingWindowRestoringRect_ = callingWindowRect;
557        callingWindowId_ = callingWindow->GetWindowId();
558    }
559
560    NotifyInputCallingWindowRectAndOccupiedAreaChange(callingWindow, newRect, softInputWindowRect);
561}
562
563void WindowController::RestoreCallingWindowSizeIfNeed()
564{
565    auto callingWindow = windowRoot_->GetWindowNode(callingWindowId_);
566    if (!WindowHelper::IsEmptyRect(callingWindowRestoringRect_) && callingWindow != nullptr &&
567        callingWindow->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
568        Rect overlapRect = { 0, 0, 0, 0 };
569        NotifyInputCallingWindowRectAndOccupiedAreaChange(callingWindow, callingWindowRestoringRect_, overlapRect);
570    }
571    callingWindowRestoringRect_ = { 0, 0, 0, 0 };
572    callingWindowId_ = 0u;
573}
574
575void WindowController::HandleTurnScreenOn(const sptr<WindowNode>& node)
576{
577    if (node == nullptr) {
578        WLOGFE("Node is nullptr");
579        return;
580    }
581    WLOGFD("Win: %{public}s, is turn on%{public}d", node->GetWindowName().c_str(), node->IsTurnScreenOn());
582#ifdef POWER_MANAGER_ENABLE
583    // reset ipc identity
584    std::string identity = IPCSkeleton::ResetCallingIdentity();
585    if (node->IsTurnScreenOn() && !PowerMgr::PowerMgrClient::GetInstance().IsScreenOn()) {
586        WLOGI("turn screen on");
587        PowerMgr::PowerMgrClient::GetInstance().WakeupDevice();
588    }
589    // set ipc identity to raw
590    IPCSkeleton::SetCallingIdentity(identity);
591#endif
592}
593
594WMError WindowController::RemoveWindowNode(uint32_t windowId, bool fromAnimation)
595{
596    auto windowNode = windowRoot_->GetWindowNode(windowId);
597    if (windowNode == nullptr) {
598        WLOGFE("Could not find window");
599        return WMError::WM_ERROR_NULLPTR;
600    }
601    auto removeFunc = [this, windowId, windowNode, fromAnimation]() {
602        WMError res = windowRoot_->RemoveWindowNode(windowId, fromAnimation);
603        if (res != WMError::WM_OK) {
604            WLOGFE("RemoveWindowNode failed");
605            return res;
606        }
607        windowRoot_->FocusFaultDetection();
608        FlushWindowInfo(windowId);
609        std::vector<sptr<WindowNode>> nodes;
610        nodes.emplace_back(windowNode);
611        for (auto& child : windowNode->children_) {
612            nodes.emplace_back(child);
613        }
614        for (auto& iter : nodes) {
615            if ((iter->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) &&
616                (windowNode->abilityToken_ != iter->abilityToken_)) {
617                iter->GetWindowToken()->NotifyBackground();
618            }
619        }
620        displayZoomController_->ClearZoomTransform(nodes);
621        accessibilityConnection_->NotifyAccessibilityWindowInfo(windowNode->GetDisplayId(), nodes,
622            WindowUpdateType::WINDOW_UPDATE_REMOVED);
623        return res;
624    };
625    WMError res = WMError::WM_ERROR_NO_REMOTE_ANIMATION;
626    if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
627        // if has main full screen window, no need to do remote unlock animation
628        if (windowRoot_->NotifyDesktopUnfrozen() == WMError::WM_OK &&
629            !windowRoot_->HasMainFullScreenWindowShown(windowNode->GetDisplayId())) {
630            res = RemoteAnimation::NotifyAnimationScreenUnlock(removeFunc, windowNode);
631            WLOGI("NotifyAnimationScreenUnlock with remote animation");
632        }
633    }
634    if (res != WMError::WM_OK) {
635        res = removeFunc();
636    }
637    if (windowNode->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
638        RestoreCallingWindowSizeIfNeed();
639    }
640    if (!windowNode->stateMachine_.IsHideAnimationPlaying()) {
641        windowNode->stateMachine_.TransitionTo(WindowNodeState::HIDDEN);
642    }
643    return res;
644}
645
646WMError WindowController::DestroyWindow(uint32_t windowId, bool onlySelf)
647{
648    DisplayId displayId = DISPLAY_ID_INVALID;
649    auto node = windowRoot_->GetWindowNode(windowId);
650    if (node == nullptr) {
651        WLOGFE("Destroy window %{public}u failed.", windowId);
652        return WMError::WM_ERROR_NULLPTR;
653    }
654    sptr<WindowNode> parent = node->parent_;
655    displayId = node->GetDisplayId();
656    WMError res = windowRoot_->DestroyWindow(windowId, onlySelf);
657    if (res != WMError::WM_OK) {
658        return res;
659    }
660    if (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
661        if ((parent != nullptr) && WindowHelper::IsSplitWindowMode(parent->GetWindowMode())) {
662            auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
663            windowNodeContainer->RaiseSplitRelatedWindowToTop(parent);
664        }
665    }
666    windowRoot_->FocusFaultDetection();
667    FlushWindowInfoWithDisplayId(displayId);
668    std::vector<sptr<WindowNode>> nodes;
669    nodes.emplace_back(node);
670    for (auto& child : node->children_) {
671        nodes.emplace_back(child);
672    }
673    accessibilityConnection_->NotifyAccessibilityWindowInfo(node->GetDisplayId(), nodes,
674        WindowUpdateType::WINDOW_UPDATE_REMOVED);
675    node->stateMachine_.TransitionTo(WindowNodeState::DESTROYED);
676    return res;
677}
678
679WMError WindowController::ResizeRect(uint32_t windowId, const Rect& rect, WindowSizeChangeReason reason)
680{
681    auto node = windowRoot_->GetWindowNode(windowId);
682    if (node == nullptr) {
683        WLOGFE("could not find window");
684        return WMError::WM_ERROR_NULLPTR;
685    }
686    if (node->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) {
687        WLOGFE("fullscreen window could not resize");
688        return WMError::WM_ERROR_INVALID_OPERATION;
689    }
690    /*
691     *  if requestRect of systemBar equals to winRect, not need to resize. This may happen when rotate display
692     */
693    if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
694        if ((reason== WindowSizeChangeReason::MOVE || reason == WindowSizeChangeReason::RESIZE) &&
695            rect == node->GetWindowRect()) {
696            return WMError::WM_OK;
697        }
698    }
699    auto property = node->GetWindowProperty();
700    node->SetWindowSizeChangeReason(reason);
701    Rect lastRect = property->GetWindowRect();
702    Rect newRect;
703    if (reason == WindowSizeChangeReason::MOVE) {
704        newRect = { rect.posX_, rect.posY_, lastRect.width_, lastRect.height_ };
705        if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
706            if (windowRoot_->IsForbidDockSliceMove(node->GetDisplayId())) {
707                WLOGI("dock slice is forbidden to move");
708                newRect = lastRect;
709            } else if (windowRoot_->IsVerticalDisplay(node)) {
710                newRect.posX_ = lastRect.posX_;
711            } else {
712                newRect.posY_ = lastRect.posY_;
713            }
714        }
715    } else if (reason == WindowSizeChangeReason::RESIZE) {
716        newRect = { lastRect.posX_, lastRect.posY_, rect.width_, rect.height_ };
717    } else if (reason == WindowSizeChangeReason::DRAG || reason == WindowSizeChangeReason::MAXIMIZE) {
718        newRect = rect;
719    }
720    property->SetRequestRect(newRect);
721    if (node->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT &&
722        (reason == WindowSizeChangeReason::RESIZE || reason == WindowSizeChangeReason::MOVE)) {
723        RelayoutKeyboard(node);
724        ResizeSoftInputCallingWindowIfNeed(node);
725    }
726    WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_RECT);
727    if (res != WMError::WM_OK) {
728        return res;
729    }
730    accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
731    return WMError::WM_OK;
732}
733
734WMError WindowController::ResizeRectAndFlush(uint32_t windowId, const Rect& rect, WindowSizeChangeReason reason)
735{
736    WMError res = ResizeRect(windowId, rect, reason);
737    if (res != WMError::WM_OK) {
738        return res;
739    } else {
740        FlushWindowInfo(windowId);
741        return WMError::WM_OK;
742    }
743}
744
745WMError WindowController::RequestFocus(uint32_t windowId)
746{
747    if (windowRoot_ == nullptr) {
748        return WMError::WM_ERROR_NULLPTR;
749    }
750    WMError res = windowRoot_->RequestFocus(windowId);
751    FlushWindowInfo(windowId);
752    accessibilityConnection_->NotifyAccessibilityWindowInfo(windowRoot_->GetWindowNode(windowId),
753        WindowUpdateType::WINDOW_UPDATE_FOCUSED);
754    return res;
755}
756
757WMError WindowController::SetWindowMode(uint32_t windowId, WindowMode dstMode)
758{
759    HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
760    auto node = windowRoot_->GetWindowNode(windowId);
761    if (node == nullptr) {
762        WLOGFE("could not find window");
763        return WMError::WM_ERROR_NULLPTR;
764    }
765    WMError ret = windowRoot_->SetWindowMode(node, dstMode);
766    if (ret != WMError::WM_OK) {
767        return ret;
768    }
769    FlushWindowInfo(windowId);
770    accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
771    if (!node->stateMachine_.IsShowAnimationPlaying()) {
772        if (WindowHelper::IsMainWindow(node->GetWindowType())) {
773            MinimizeApp::ExecuteMinimizeAll();
774            WLOGI("id:%{public}u execute minimize all", node->GetWindowId());
775        }
776    }
777    return WMError::WM_OK;
778}
779
780void WindowController::NotifyDisplayStateChange(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
781    const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap, DisplayStateChangeType type)
782{
783    WLOGFD("NotifyDisplayStateChange start: %{public}u", type);
784    switch (type) {
785        case DisplayStateChangeType::BEFORE_SUSPEND: {
786            isScreenLocked_ = true;
787            windowRoot_->ProcessWindowStateChange(WindowState::STATE_FROZEN, WindowStateChangeReason::KEYGUARD);
788            break;
789        }
790        case DisplayStateChangeType::BEFORE_UNLOCK: {
791            windowRoot_->ProcessWindowStateChange(WindowState::STATE_UNFROZEN, WindowStateChangeReason::KEYGUARD);
792            isScreenLocked_ = false;
793            break;
794        }
795        case DisplayStateChangeType::CREATE: {
796            SetDefaultDisplayInfo(defaultDisplayId, displayInfo);
797            windowRoot_->ProcessDisplayCreate(defaultDisplayId, displayInfo, displayInfoMap);
798            FlushWindowInfoWithDisplayId(displayInfo->GetDisplayId());
799            break;
800        }
801        case DisplayStateChangeType::DESTROY: {
802            windowRoot_->ProcessDisplayDestroy(defaultDisplayId, displayInfo, displayInfoMap);
803            FlushWindowInfoWithDisplayId(defaultDisplayId);
804            break;
805        }
806        case DisplayStateChangeType::DISPLAY_COMPRESS:
807        case DisplayStateChangeType::SIZE_CHANGE:
808        case DisplayStateChangeType::UPDATE_ROTATION:
809        case DisplayStateChangeType::UPDATE_ROTATION_FROM_WINDOW:
810        case DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE: {
811            ProcessDisplayChange(defaultDisplayId, displayInfo, displayInfoMap, type);
812            /*
813             * Window tile num may change when display rotate or change size, need to execute minimize
814             */
815            MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::LAYOUT_TILE);
816            break;
817        }
818        default: {
819            WLOGFE("unknown DisplayStateChangeType:%{public}u", type);
820            return;
821        }
822    }
823    WLOGFD("NotifyDisplayStateChange end, type: %{public}u", type);
824}
825
826void WindowController::SetDefaultDisplayInfo(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo)
827{
828    if (displayInfo == nullptr) {
829        WLOGFE("display is null");
830        return;
831    }
832    if (displayInfo->GetDisplayId() != defaultDisplayId) {
833        return;
834    }
835    WLOGI("Set defaultDisplayInfo");
836    auto displayWidth = static_cast<uint32_t>(displayInfo->GetWidth());
837    auto displayHeight = static_cast<uint32_t>(displayInfo->GetHeight());
838    defaultDisplayRect_ = { 0, 0, displayWidth, displayHeight };
839}
840
841void WindowController::ProcessDisplayChange(DisplayId defaultDisplayId, sptr<DisplayInfo> displayInfo,
842    const std::map<DisplayId, sptr<DisplayInfo>>& displayInfoMap, DisplayStateChangeType type)
843{
844    if (displayInfo == nullptr) {
845        WLOGFE("get display failed");
846        return;
847    }
848    auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayInfo->GetDisplayId());
849    if (windowNodeContainer != nullptr) {
850        windowNodeContainer->BeforeProcessWindowAvoidAreaChangeWhenDisplayChange();
851        DisplayGroupInfo::GetInstance().UpdateDisplayInfo(displayInfo);
852    }
853    switch (type) {
854        case DisplayStateChangeType::DISPLAY_COMPRESS:
855            ProcessDisplayCompression(defaultDisplayId, displayInfo);
856            [[fallthrough]];
857        case DisplayStateChangeType::SIZE_CHANGE:
858        case DisplayStateChangeType::UPDATE_ROTATION:
859        case DisplayStateChangeType::UPDATE_ROTATION_FROM_WINDOW:
860        case DisplayStateChangeType::VIRTUAL_PIXEL_RATIO_CHANGE: {
861            windowRoot_->ProcessDisplayChange(defaultDisplayId, displayInfo, displayInfoMap, type);
862            break;
863        }
864        default: {
865            WLOGFE("unknown DisplayStateChangeType:%{public}u", type);
866            return;
867        }
868    }
869    auto displayId = displayInfo->GetDisplayId();
870    displayZoomController_->UpdateAllWindowsZoomInfo(displayId);
871    FlushWindowInfoWithDisplayId(displayId);
872    accessibilityConnection_->NotifyAccessibilityWindowInfo(displayId, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
873    if (windowNodeContainer != nullptr) {
874        windowNodeContainer->ProcessWindowAvoidAreaChangeWhenDisplayChange();
875    }
876}
877
878void WindowController::ProcessDisplayCompression(DisplayId defaultDisplayId, const sptr<DisplayInfo>& displayInfo)
879{
880    WLOGI("Enter processDisplayCompress");
881    DisplayId displayId = displayInfo->GetDisplayId();
882    if (displayId != defaultDisplayId) {
883        WLOGI("Not default display");
884        return;
885    }
886    auto& dms = DisplayManagerServiceInner::GetInstance();
887    if (!displayInfo->GetWaterfallDisplayCompressionStatus()) {
888        if (maskingSurfaceNode_ == nullptr) {
889            WLOGFD("MaskingSurfaceNode is not created");
890            return;
891        } else {
892            WLOGFD("Remove maskingSurfaceNode");
893            dms.UpdateRSTree(displayId, displayId, maskingSurfaceNode_, false, false);
894            maskingSurfaceNode_ = nullptr;
895            return;
896        }
897    }
898    WLOGFD("Add maskingSurfaceNode");
899    struct RSSurfaceNodeConfig rsSurfaceNodeConfig;
900    rsSurfaceNodeConfig.SurfaceNodeName = "maskingSurface";
901    maskingSurfaceNode_ = RSSurfaceNode::Create(rsSurfaceNodeConfig);
902    if (maskingSurfaceNode_ == nullptr) {
903        WLOGFE("Create maskingSurfaceNode failed");
904        return;
905    }
906    auto displayWidth = displayInfo->GetWidth();
907    auto displayHeight = displayInfo->GetHeight();
908    auto maskingSizeX = displayInfo->GetOffsetX();
909    auto maskingSizeY = displayInfo->GetOffsetY();
910    auto fullDisplayWidth = displayWidth + maskingSizeX * 2; // *2: Get full width.
911    auto fullDisplayHeight = displayHeight + maskingSizeY * 2; // *2: Get full height.
912
913    Rect screenRect = Rect {0, 0, fullDisplayWidth, fullDisplayHeight};
914    Rect transparentRect = Rect {maskingSizeX, maskingSizeY, displayWidth, displayHeight};
915    WLOGFD("ScreenRect: fullDisplayWidth: %{public}d, fullDisplayHeight: %{public}d",
916        fullDisplayWidth, fullDisplayHeight);
917    WLOGFD("TransparentRect: X: %{public}u, Y: %{public}u, Width: %{public}d, Height: %{public}d",
918        maskingSizeX, maskingSizeY, displayWidth, displayHeight);
919
920    maskingSurfaceNode_->SetPositionZ(MASKING_SURFACE_NODE_Z_ORDER);
921
922    if (!SurfaceDraw::DrawMasking(maskingSurfaceNode_, screenRect, transparentRect)) {
923        WLOGFE("Draw masking surface failed");
924        return;
925    }
926    maskingSurfaceNode_->SetBounds(0, 0, fullDisplayWidth, fullDisplayHeight);
927    dms.UpdateRSTree(displayId, displayId, maskingSurfaceNode_, true, false);
928}
929
930void WindowController::StopBootAnimationIfNeed(const sptr<WindowNode>& node)
931{
932    if (isBootAnimationStopped_) {
933        return;
934    }
935    if (node == nullptr) {
936        WLOGFE("Node is nullptr");
937        return;
938    }
939    if (node->GetDisplayId() != DisplayGroupInfo::GetInstance().GetDefaultDisplayId()) {
940        return;
941    }
942    auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId());
943    if (windowNodeContainer == nullptr) {
944        WLOGFE("Node container is nullptr");
945        return;
946    }
947    std::vector<sptr<WindowNode>> windowNodes;
948    windowNodeContainer->TraverseContainer(windowNodes);
949    WmOcclusion::Rect defaultDisplayRect = { defaultDisplayRect_.posX_, defaultDisplayRect_.posY_,
950        defaultDisplayRect_.posX_ + static_cast<int32_t>(defaultDisplayRect_.width_),
951        defaultDisplayRect_.posY_ + static_cast<int32_t>(defaultDisplayRect_.height_)};
952    WmOcclusion::Region defaultDisplayRegion(defaultDisplayRect);
953    WmOcclusion::Region allRegion; // Counts the area of all shown windows
954    for (auto& node : windowNodes) {
955        if (node->GetWindowType() == WindowType::WINDOW_TYPE_BOOT_ANIMATION) {
956            continue;
957        }
958        auto windowRect = node->GetWindowRect();
959        WmOcclusion::Rect curRect = { windowRect.posX_, windowRect.posY_,
960            windowRect.posX_ + static_cast<int32_t>(windowRect.width_),
961            windowRect.posY_ + static_cast<int32_t>(windowRect.height_)};
962        WmOcclusion::Region curRegion(curRect);
963        allRegion = curRegion.Or(allRegion);
964        WmOcclusion::Region subResult = defaultDisplayRegion.Sub(allRegion);
965        if (subResult.GetSize() == 0) {
966            WLOGI("stop boot animation");
967            system::SetParameter("bootevent.wms.fullscreen.ready", "true");
968            isBootAnimationStopped_ = true;
969            RecordBootAnimationEvent();
970            DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled();
971        }
972    }
973}
974
975void WindowController::RecordBootAnimationEvent() const
976{
977    uint64_t time = static_cast<uint64_t>(std::chrono::time_point_cast<std::chrono::seconds>
978        (std::chrono::steady_clock::now()).time_since_epoch().count());
979    WLOGI("boot animation done duration(s): %{public}" PRIu64"", time);
980    std::ostringstream os;
981    os << "boot animation done duration(s): " << time <<";";
982    int32_t ret = HiSysEventWrite(
983        OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
984        "WINDOW_BOOT_ANIMATION_DONE",
985        OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
986        "MSG", os.str());
987    if (ret != 0) {
988        WLOGFE("Write HiSysEvent error, ret:%{public}d", ret);
989    }
990}
991
992std::shared_ptr<Media::PixelMap> WindowController::GetSnapshot(int32_t windowId)
993{
994    auto node = windowRoot_->GetWindowNode(windowId);
995    if (node == nullptr) {
996        WLOGFE("could not find window");
997        return nullptr;
998    }
999    auto callback = std::make_shared<SurfaceCaptureFuture>();
1000    bool ret = RSInterfaces::GetInstance().TakeSurfaceCapture(node->surfaceNode_, callback);
1001    if (!ret) {
1002        WLOGFE("takeSurfaceCapture failed");
1003        return nullptr;
1004    }
1005    return callback->GetResult(SNAPSHOT_TIMEOUT_MS);
1006}
1007
1008WMError WindowController::SetWindowType(uint32_t windowId, WindowType type)
1009{
1010    auto node = windowRoot_->GetWindowNode(windowId);
1011    if (node == nullptr) {
1012        WLOGFE("could not find window");
1013        return WMError::WM_ERROR_NULLPTR;
1014    }
1015    auto property = node->GetWindowProperty();
1016    property->SetWindowType(type);
1017    UpdateWindowAnimation(node);
1018    WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_TYPE);
1019    if (res != WMError::WM_OK) {
1020        return res;
1021    }
1022    FlushWindowInfo(windowId);
1023    accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
1024    WLOGI("SetWindowType end");
1025    return res;
1026}
1027
1028WMError WindowController::SetWindowFlags(uint32_t windowId, uint32_t flags, bool isSystemCalling)
1029{
1030    auto node = windowRoot_->GetWindowNode(windowId);
1031    if (node == nullptr) {
1032        WLOGFE("could not find window");
1033        return WMError::WM_ERROR_NULLPTR;
1034    }
1035    auto property = node->GetWindowProperty();
1036    uint32_t oldFlags = property->GetWindowFlags();
1037    if (property->GetApiCompatibleVersion() >= 9 && !isSystemCalling && // 9: api version.
1038        (oldFlags ^ flags) == static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) {
1039        WLOGFW("Only API 9- or system calling support showing when locked.");
1040        return WMError::WM_ERROR_INVALID_PERMISSION;
1041    }
1042    property->SetWindowFlags(flags);
1043    // only forbid_split_move flag change, just set property
1044    if ((oldFlags ^ flags) == static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_FORBID_SPLIT_MOVE)) {
1045        return WMError::WM_OK;
1046    }
1047    WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_FLAGS);
1048    if (res != WMError::WM_OK) {
1049        return res;
1050    }
1051    FlushWindowInfo(windowId);
1052    accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
1053    WLOGI("SetWindowFlags end");
1054    return res;
1055}
1056
1057WMError WindowController::SetSystemBarProperty(uint32_t windowId, WindowType type, const SystemBarProperty& property)
1058{
1059    auto node = windowRoot_->GetWindowNode(windowId);
1060    if (node == nullptr) {
1061        WLOGFE("could not find window");
1062        return WMError::WM_ERROR_NULLPTR;
1063    }
1064    node->SetSystemBarProperty(type, property);
1065    WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_OTHER_PROPS);
1066    if (res != WMError::WM_OK) {
1067        return res;
1068    }
1069    FlushWindowInfo(windowId);
1070    accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
1071    WLOGI("SetSystemBarProperty end");
1072    return res;
1073}
1074
1075void WindowController::NotifySystemBarTints()
1076{
1077    windowRoot_->NotifySystemBarTints();
1078}
1079
1080WMError WindowController::SetWindowAnimationController(const sptr<RSIWindowAnimationController>& controller)
1081{
1082    return RemoteAnimation::SetWindowAnimationController(controller);
1083}
1084
1085AvoidArea WindowController::GetAvoidAreaByType(uint32_t windowId, AvoidAreaType avoidAreaType) const
1086{
1087    return windowRoot_->GetAvoidAreaByType(windowId, avoidAreaType);
1088}
1089
1090WMError WindowController::ChangeMouseStyle(uint32_t windowId, sptr<MoveDragProperty>& moveDragProperty)
1091{
1092    auto node = windowRoot_->GetWindowNode(windowId);
1093    int32_t mouseStyle = 0;
1094    MMI::PointerStyle pointerStyle;
1095    if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
1096        if (node->GetWindowRect().width_ > node->GetWindowRect().height_) {
1097            mouseStyle = MMI::MOUSE_ICON::NORTH_SOUTH;
1098        } else {
1099            mouseStyle = MMI::MOUSE_ICON::WEST_EAST;
1100        }
1101        pointerStyle.id = mouseStyle;
1102        int32_t res = MMI::InputManager::GetInstance()->SetPointerStyle(windowId, pointerStyle);
1103        if (res != 0) {
1104            WLOGFE("set pointer style failed");
1105            return WMError::WM_ERROR_INVALID_OPERATION;
1106        }
1107        return WMError::WM_OK;
1108    }
1109    pointerStyle.id = STYLEID_MAP.at(moveDragProperty->dragType_);
1110    int32_t res = MMI::InputManager::GetInstance()->SetPointerStyle(windowId, pointerStyle);
1111    if (res != 0) {
1112        WLOGFE("set pointer style failed");
1113        return WMError::WM_ERROR_INVALID_OPERATION;
1114    }
1115    return WMError::WM_OK;
1116}
1117
1118WMError WindowController::NotifyServerReadyToMoveOrDrag(uint32_t windowId, sptr<MoveDragProperty>& moveDragProperty)
1119{
1120    auto node = windowRoot_->GetWindowNode(windowId);
1121    if (node == nullptr) {
1122        WLOGFW("could not find window");
1123        return WMError::WM_ERROR_NULLPTR;
1124    }
1125    if (!node->currentVisibility_) {
1126        WLOGFE("Window is invisible, windowId: %{public}u", windowId);
1127        return WMError::WM_ERROR_INVALID_OPERATION;
1128    }
1129
1130    if (node->GetWindowProperty()->GetMaximizeMode() == MaximizeMode::MODE_AVOID_SYSTEM_BAR) {
1131        return WMError::WM_OK;
1132    }
1133
1134    // if start dragging or start moving dock_slice, need to update size change reason
1135    if ((moveDragProperty->startMoveFlag_ && node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) ||
1136        moveDragProperty->startDragFlag_) {
1137        WMError res = windowRoot_->UpdateSizeChangeReason(windowId, WindowSizeChangeReason::DRAG_START);
1138        ChangeMouseStyle(windowId, moveDragProperty);
1139        if (node->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW && dragFrameGravity_ != INVALID_GRAVITY) {
1140            if (node->surfaceNode_) {
1141                node->surfaceNode_->SetFrameGravity(static_cast<Gravity>(dragFrameGravity_));
1142            }
1143        }
1144        return res;
1145    }
1146    return WMError::WM_OK;
1147}
1148
1149WMError WindowController::ProcessPointDown(uint32_t windowId, bool isPointDown)
1150{
1151    auto node = windowRoot_->GetWindowNode(windowId);
1152    if (node == nullptr) {
1153        WLOGFW("could not find window");
1154        return WMError::WM_ERROR_NULLPTR;
1155    }
1156    if (!node->currentVisibility_) {
1157        WLOGFE("Window is invisible, windowId: %{public}u", windowId);
1158        return WMError::WM_ERROR_INVALID_OPERATION;
1159    }
1160
1161    /*
1162     * If not point down, no need to notify touch outside
1163     */
1164    if (isPointDown) {
1165        NotifyTouchOutside(node);
1166        if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
1167            windowRoot_->TakeWindowPairSnapshot(node->GetDisplayId());
1168        }
1169    }
1170
1171    WLOGFD("WindowId: %{public}u", windowId);
1172    WMError zOrderRes = windowRoot_->RaiseZOrderForAppWindow(node);
1173    WMError focusRes = windowRoot_->RequestFocus(windowId);
1174    windowRoot_->RequestActiveWindow(windowId);
1175    windowRoot_->FocusFaultDetection();
1176    if (zOrderRes == WMError::WM_OK || focusRes == WMError::WM_OK) {
1177        FlushWindowInfo(windowId);
1178        accessibilityConnection_->NotifyAccessibilityWindowInfo(windowRoot_->GetWindowNode(windowId),
1179            WindowUpdateType::WINDOW_UPDATE_FOCUSED);
1180        WLOGI("ProcessPointDown end");
1181        return WMError::WM_OK;
1182    }
1183    return WMError::WM_ERROR_INVALID_OPERATION;
1184}
1185
1186WMError WindowController::ProcessPointUp(uint32_t windowId)
1187{
1188    auto node = windowRoot_->GetWindowNode(windowId);
1189    if (node == nullptr) {
1190        WLOGFW("could not find window");
1191        return WMError::WM_ERROR_NULLPTR;
1192    }
1193    if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
1194        DisplayId displayId = node->GetDisplayId();
1195        if (windowRoot_->IsDockSliceInExitSplitModeArea(displayId)) {
1196            windowRoot_->ExitSplitMode(displayId);
1197        } else {
1198            windowRoot_->ClearWindowPairSnapshot(node->GetDisplayId());
1199            auto property = node->GetWindowProperty();
1200            node->SetWindowSizeChangeReason(WindowSizeChangeReason::DRAG_END);
1201            property->SetRequestRect(property->GetWindowRect());
1202            WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_RECT);
1203            if (res == WMError::WM_OK) {
1204                FlushWindowInfo(windowId);
1205                accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
1206            }
1207        }
1208    }
1209    if (node->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW && dragFrameGravity_ != INVALID_GRAVITY) {
1210        if (node->surfaceNode_) {
1211            node->surfaceNode_->SetFrameGravity(Gravity::RESIZE);
1212        }
1213    }
1214    WMError res = windowRoot_->UpdateSizeChangeReason(windowId, WindowSizeChangeReason::DRAG_END);
1215    if (res != WMError::WM_OK) {
1216        return res;
1217    }
1218    return WMError::WM_OK;
1219}
1220
1221WMError WindowController::InterceptInputEventToServer(uint32_t windowId)
1222{
1223    auto node = windowRoot_->GetWindowNode(windowId);
1224    if (node == nullptr) {
1225        WLOGFW("could not find window");
1226        return WMError::WM_ERROR_NULLPTR;
1227    }
1228    auto inputPidInServer = WindowInnerManager::GetInstance().GetPid();
1229    WLOGI("InterceptInputEventToServer, windowId: %{public}u, inputPid: %{public}u", windowId, inputPidInServer);
1230    node->SetInputEventCallingPid(static_cast<int32_t>(inputPidInServer));
1231    FlushWindowInfo(windowId);
1232    return WMError::WM_OK;
1233}
1234
1235WMError WindowController::RecoverInputEventToClient(uint32_t windowId)
1236{
1237    auto node = windowRoot_->GetWindowNode(windowId);
1238    if (node == nullptr) {
1239        WLOGFW("could not find window");
1240        return WMError::WM_ERROR_NULLPTR;
1241    }
1242    if (node->GetInputEventCallingPid() == node->GetCallingPid()) {
1243        WLOGFD("There is no need to recover input event to client");
1244        return WMError::WM_OK;
1245    }
1246
1247    node->SetInputEventCallingPid(node->GetCallingPid());
1248    RecoverDefaultMouseStyle(windowId);
1249    FlushWindowInfo(windowId);
1250    return WMError::WM_OK;
1251}
1252
1253void WindowController::RecoverDefaultMouseStyle(uint32_t windowId)
1254{
1255    // asynchronously calls SetMouseStyle of MultiModalInput
1256    MMI::PointerStyle pointerStyle;
1257    pointerStyle.id = MMI::MOUSE_ICON::DEFAULT;
1258    auto task = [this, windowId, pointerStyle]() {
1259        int32_t res = MMI::InputManager::GetInstance()->SetPointerStyle(windowId, pointerStyle);
1260        if (res != 0) {
1261            WLOGFE("set pointer style failed");
1262        }
1263    };
1264    WindowInnerManager::GetInstance().PostTask(task, "RecoverDefaultMouseStyle");
1265}
1266
1267/** @note @window.hierarchy */
1268WMError WindowController::RaiseToAppTop(uint32_t windowId)
1269{
1270    auto node = windowRoot_->GetWindowNode(windowId);
1271    if (node == nullptr) {
1272        WLOGFW("could not find window");
1273        return WMError::WM_ERROR_NULLPTR;
1274    }
1275
1276    auto parentNode = node->parent_;
1277    if (parentNode == nullptr) {
1278        WLOGFW("could not find parent");
1279        return WMError::WM_ERROR_INVALID_PARENT;
1280    }
1281
1282    WMError zOrderRes = windowRoot_->RaiseZOrderForAppWindow(node);
1283    if (zOrderRes != WMError::WM_OK) {
1284        WLOGFE("Raise subwindow zorder fail, ret: %{public}d", zOrderRes);
1285        return  WMError::WM_DO_NOTHING;
1286    }
1287
1288    UpdateFocusIfNeededWhenRaiseWindow(node);
1289    FlushWindowInfo(windowId);
1290    return WMError::WM_OK;
1291}
1292
1293void WindowController::DispatchKeyEvent(uint32_t windowId, std::shared_ptr<MMI::KeyEvent> event)
1294{
1295    auto node = windowRoot_->GetWindowNode(windowId);
1296    if (node == nullptr) {
1297        WLOGFW("Could not find window");
1298        return;
1299    }
1300    if (node->GetWindowType() != WindowType::WINDOW_TYPE_APP_COMPONENT) {
1301        WLOGFI("Window type is not WINDOW_TYPE_APP_COMPONENT");
1302        return;
1303    }
1304    windowRoot_->DispatchKeyEvent(node, event);
1305}
1306
1307void WindowController::UpdateFocusIfNeededWhenRaiseWindow(const sptr<WindowNode>& node)
1308{
1309    auto property = node->GetWindowProperty();
1310    if (!property->GetFocusable()) {
1311        return;
1312    }
1313    uint32_t windowId = node->GetWindowId();
1314    sptr<WindowNode> focusWindow = nullptr;
1315    WMError res = GetFocusWindowNode(node->GetDisplayId(), focusWindow);
1316    if (res != WMError::WM_OK || focusWindow == nullptr) {
1317        return;
1318    }
1319    if (node->parent_->GetWindowId() == focusWindow->GetWindowId() ||
1320        node->parent_->GetWindowId() == focusWindow->GetParentId()) {
1321        windowRoot_->RequestFocus(windowId);
1322        windowRoot_->RequestActiveWindow(windowId);
1323        windowRoot_->FocusFaultDetection();
1324
1325        accessibilityConnection_->NotifyAccessibilityWindowInfo(windowRoot_->GetWindowNode(windowId),
1326            WindowUpdateType::WINDOW_UPDATE_FOCUSED);
1327    }
1328}
1329
1330WMError WindowController::NotifyWindowClientPointUp(uint32_t windowId,
1331    const std::shared_ptr<MMI::PointerEvent>& pointerEvent)
1332{
1333    auto node = windowRoot_->GetWindowNode(windowId);
1334    if (node == nullptr) {
1335        WLOGFW("could not find window");
1336        return WMError::WM_ERROR_NULLPTR;
1337    }
1338    if (node->GetWindowToken() != nullptr) {
1339        WLOGI("notify client when receive point_up event, windowId: %{public}u", windowId);
1340        node->GetWindowToken()->NotifyWindowClientPointUp(pointerEvent);
1341    }
1342    return WMError::WM_OK;
1343}
1344
1345void WindowController::MinimizeAllAppWindows(DisplayId displayId)
1346{
1347    windowRoot_->MinimizeAllAppWindows(displayId);
1348    if (RemoteAnimation::NotifyAnimationByHome() != WMError::WM_OK) {
1349        MinimizeApp::ExecuteMinimizeAll();
1350    }
1351}
1352
1353WMError WindowController::ToggleShownStateForAllAppWindows()
1354{
1355    if (isScreenLocked_) {
1356        return WMError::WM_DO_NOTHING;
1357    }
1358    return windowRoot_->ToggleShownStateForAllAppWindows();
1359}
1360
1361WMError WindowController::GetTopWindowId(uint32_t mainWinId, uint32_t& topWinId)
1362{
1363    return windowRoot_->GetTopWindowId(mainWinId, topWinId);
1364}
1365
1366void WindowController::FlushWindowInfo(uint32_t windowId)
1367{
1368    WLOGD("FlushWindowInfo");
1369    displayZoomController_->UpdateWindowZoomInfo(windowId);
1370    RSTransaction::FlushImplicitTransaction();
1371    inputWindowMonitor_->UpdateInputWindow(windowId);
1372}
1373
1374void WindowController::FlushWindowInfoWithDisplayId(DisplayId displayId)
1375{
1376    WLOGFD("DisplayId: %{public}" PRIu64"", displayId);
1377    RSTransaction::FlushImplicitTransaction();
1378    inputWindowMonitor_->UpdateInputWindowByDisplayId(displayId);
1379}
1380
1381void WindowController::UpdateWindowAnimation(const sptr<WindowNode>& node)
1382{
1383    if (node == nullptr || (node->leashWinSurfaceNode_ == nullptr && node->surfaceNode_ == nullptr)) {
1384        WLOGFE("windowNode or surfaceNode is nullptr");
1385        return;
1386    }
1387    const auto& windowAnimationConfig = WindowNodeContainer::GetAnimationConfigRef().windowAnimationConfig_;
1388
1389    uint32_t animationFlag = node->GetWindowProperty()->GetAnimationFlag();
1390    uint32_t windowId = node->GetWindowProperty()->GetWindowId();
1391    WLOGFD("Id: %{public}u, anim_Flag: %{public}u", windowId, animationFlag);
1392    std::shared_ptr<const RSTransitionEffect> effect = nullptr;
1393    if (animationFlag == static_cast<uint32_t>(WindowAnimation::DEFAULT)) {
1394        effect = RSTransitionEffect::Create()
1395            ->Scale(windowAnimationConfig.scale_)
1396            ->Rotate(windowAnimationConfig.rotation_)
1397            ->Translate(windowAnimationConfig.translate_)
1398            ->Opacity(windowAnimationConfig.opacity_);
1399    } else if (animationFlag == static_cast<uint32_t>(WindowAnimation::INPUTE)) {
1400        float translateY = static_cast<float>(node->GetWindowRect().height_);
1401        if (!node->GetWindowRect().height_) {
1402            translateY = static_cast<float>(node->GetRequestRect().height_);
1403        }
1404        effect = RSTransitionEffect::Create()->Translate(Vector3f(0, translateY, 0))->Opacity(1.0f);
1405    };
1406    if (node->leashWinSurfaceNode_) {
1407        node->leashWinSurfaceNode_->SetTransitionEffect(effect);
1408    }
1409    if (node->surfaceNode_) {
1410        node->surfaceNode_->SetTransitionEffect(effect);
1411    }
1412}
1413
1414WMError WindowController::SetWindowLayoutMode(WindowLayoutMode mode)
1415{
1416    WMError res = WMError::WM_OK;
1417    auto displayIds = windowRoot_->GetAllDisplayIds();
1418    for (auto displayId : displayIds) {
1419        res = windowRoot_->SetWindowLayoutMode(displayId, mode);
1420        if (res != WMError::WM_OK) {
1421            return res;
1422        }
1423        displayZoomController_->UpdateAllWindowsZoomInfo(displayId);
1424        FlushWindowInfoWithDisplayId(displayId);
1425        accessibilityConnection_->NotifyAccessibilityWindowInfo(displayId, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
1426    }
1427    MinimizeApp::ExecuteMinimizeAll();
1428    return res;
1429}
1430
1431WMError WindowController::UpdateProperty(sptr<WindowProperty>& property, PropertyChangeAction action)
1432{
1433    if (property == nullptr) {
1434        WLOGFE("property is invalid");
1435        return WMError::WM_ERROR_NULLPTR;
1436    }
1437
1438    uint32_t windowId = property->GetWindowId();
1439    auto node = windowRoot_->GetWindowNode(windowId);
1440    if (node == nullptr) {
1441        WLOGFE("window is invalid");
1442        return WMError::WM_ERROR_NULLPTR;
1443    }
1444    WLOGI("Id: %{public}u, action: %{public}u", node->GetWindowId(), static_cast<uint32_t>(action));
1445    WMError ret = WMError::WM_OK;
1446    switch (action) {
1447        case PropertyChangeAction::ACTION_UPDATE_RECT: {
1448            node->SetDecoStatus(property->GetDecoStatus());
1449            node->SetOriginRect(property->GetOriginRect());
1450            node->SetDragType(property->GetDragType());
1451            ret = ResizeRectAndFlush(windowId, property->GetRequestRect(), property->GetWindowSizeChangeReason());
1452            if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING && ret == WMError::WM_OK &&
1453                callingWindowId_ == windowId && !WindowHelper::IsEmptyRect(callingWindowRestoringRect_)) {
1454                if (property->GetWindowSizeChangeReason() != WindowSizeChangeReason::MOVE) {
1455                    callingWindowId_ = 0u;
1456                    callingWindowRestoringRect_ = { 0, 0, 0, 0 };
1457                } else {
1458                    auto windowRect = node->GetWindowRect();
1459                    callingWindowRestoringRect_.posX_ = windowRect.posX_;
1460                    callingWindowRestoringRect_.posY_ = windowRect.posY_;
1461                }
1462            }
1463            break;
1464        }
1465        case PropertyChangeAction::ACTION_UPDATE_MODE: {
1466            node->SetDecorEnable(property->GetDecorEnable());
1467            ret = SetWindowMode(windowId, property->GetWindowMode());
1468            break;
1469        }
1470        case PropertyChangeAction::ACTION_UPDATE_FLAGS: {
1471            ret = SetWindowFlags(windowId, property->GetWindowFlags(), property->isSystemCalling_);
1472            break;
1473        }
1474        case PropertyChangeAction::ACTION_UPDATE_OTHER_PROPS: {
1475            auto& props = property->GetSystemBarProperty();
1476            for (auto& iter : props) {
1477                SetSystemBarProperty(windowId, iter.first, iter.second);
1478            }
1479            break;
1480        }
1481        case PropertyChangeAction::ACTION_UPDATE_FOCUSABLE: {
1482            node->SetFocusable(property->GetFocusable());
1483            windowRoot_->UpdateFocusableProperty(windowId);
1484            FlushWindowInfo(windowId);
1485            accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
1486            break;
1487        }
1488        case PropertyChangeAction::ACTION_UPDATE_TOUCHABLE: {
1489            node->SetTouchable(property->GetTouchable());
1490            FlushWindowInfo(windowId);
1491            accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
1492            break;
1493        }
1494        case PropertyChangeAction::ACTION_UPDATE_CALLING_WINDOW: {
1495            node->SetCallingWindow(property->GetCallingWindow());
1496            break;
1497        }
1498        case PropertyChangeAction::ACTION_UPDATE_ORIENTATION: {
1499            node->SetRequestedOrientation(property->GetRequestedOrientation());
1500            if (WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) {
1501                DisplayManagerServiceInner::GetInstance().
1502                    SetOrientationFromWindow(node->GetDisplayId(), property->GetRequestedOrientation());
1503            }
1504            break;
1505        }
1506        case PropertyChangeAction::ACTION_UPDATE_TURN_SCREEN_ON: {
1507            node->SetTurnScreenOn(property->IsTurnScreenOn());
1508            HandleTurnScreenOn(node);
1509            break;
1510        }
1511        case PropertyChangeAction::ACTION_UPDATE_KEEP_SCREEN_ON: {
1512            node->SetKeepScreenOn(property->IsKeepScreenOn());
1513            windowRoot_->HandleKeepScreenOn(node->GetWindowId(), node->IsKeepScreenOn());
1514            break;
1515        }
1516        case PropertyChangeAction::ACTION_UPDATE_SET_BRIGHTNESS: {
1517            node->SetBrightness(property->GetBrightness());
1518            windowRoot_->SetBrightness(node->GetWindowId(), node->GetBrightness());
1519            break;
1520        }
1521        case PropertyChangeAction::ACTION_UPDATE_MODE_SUPPORT_INFO: {
1522            node->SetModeSupportInfo(property->GetModeSupportInfo());
1523            break;
1524        }
1525        case PropertyChangeAction::ACTION_UPDATE_TOUCH_HOT_AREA: {
1526            std::vector<Rect> rects;
1527            property->GetTouchHotAreas(rects);
1528            ret = UpdateTouchHotAreas(node, rects);
1529            break;
1530        }
1531        case PropertyChangeAction::ACTION_UPDATE_ANIMATION_FLAG: {
1532            node->GetWindowProperty()->SetAnimationFlag(property->GetAnimationFlag());
1533            UpdateWindowAnimation(node);
1534            break;
1535        }
1536        case PropertyChangeAction::ACTION_UPDATE_TRANSFORM_PROPERTY: {
1537            node->SetTransform(property->GetTransform());
1538            node->SetWindowSizeChangeReason(WindowSizeChangeReason::TRANSFORM);
1539            node->GetWindowProperty()->SetAnimateWindowFlag(true);
1540            ret = UpdateTransform(windowId);
1541            break;
1542        }
1543        case PropertyChangeAction::ACTION_UPDATE_PRIVACY_MODE: {
1544            bool isPrivacyMode = property->GetPrivacyMode() || property->GetSystemPrivacyMode();
1545            node->GetWindowProperty()->SetPrivacyMode(isPrivacyMode);
1546            node->GetWindowProperty()->SetSystemPrivacyMode(isPrivacyMode);
1547            node->surfaceNode_->SetSecurityLayer(isPrivacyMode);
1548            if (node->leashWinSurfaceNode_ != nullptr) {
1549                node->leashWinSurfaceNode_->SetSecurityLayer(isPrivacyMode);
1550            }
1551            RSTransaction::FlushImplicitTransaction();
1552            UpdatePrivateStateAndNotify(node);
1553            break;
1554        }
1555        case PropertyChangeAction::ACTION_UPDATE_SYSTEM_PRIVACY_MODE: {
1556            bool isPrivacyMode = property->GetPrivacyMode() || property->GetSystemPrivacyMode();
1557            node->GetWindowProperty()->SetPrivacyMode(isPrivacyMode);
1558            node->GetWindowProperty()->SetSystemPrivacyMode(isPrivacyMode);
1559            node->surfaceNode_->SetSecurityLayer(isPrivacyMode);
1560            if (node->leashWinSurfaceNode_ != nullptr) {
1561                node->leashWinSurfaceNode_->SetSecurityLayer(isPrivacyMode);
1562            }
1563            RSTransaction::FlushImplicitTransaction();
1564            UpdatePrivateStateAndNotify(node);
1565            break;
1566        }
1567        case PropertyChangeAction::ACTION_UPDATE_SNAPSHOT_SKIP: {
1568            bool isSnapshotSkip = property->GetSnapshotSkip() || property->GetSystemPrivacyMode();
1569            node->GetWindowProperty()->SetSnapshotSkip(isSnapshotSkip);
1570            node->GetWindowProperty()->SetSystemPrivacyMode(isSnapshotSkip);
1571            node->surfaceNode_->SetSkipLayer(isSnapshotSkip);
1572            if (node->leashWinSurfaceNode_ != nullptr) {
1573                node->leashWinSurfaceNode_->SetSkipLayer(isSnapshotSkip);
1574            }
1575            RSTransaction::FlushImplicitTransaction();
1576            break;
1577        }
1578        case PropertyChangeAction::ACTION_UPDATE_ASPECT_RATIO: {
1579            ret = SetAspectRatio(windowId, property->GetAspectRatio());
1580            break;
1581        }
1582        case PropertyChangeAction::ACTION_UPDATE_MAXIMIZE_STATE: {
1583            MaximizeMode mode = property->GetMaximizeMode();
1584            node->GetWindowProperty()->SetMaximizeMode(mode);
1585            Rect newRect = {0, 0, 0, 0};
1586            if (mode == MaximizeMode::MODE_AVOID_SYSTEM_BAR) {
1587                node->SetOriginRect(node->GetWindowRect());
1588                auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId());
1589                if (windowNodeContainer == nullptr) {
1590                    WLOGFE("window node container is null");
1591                    return WMError::WM_ERROR_NULLPTR;
1592                }
1593                windowNodeContainer->GetLayoutPolicy()->GetMaximizeRect(node, newRect);
1594            } else {
1595                newRect = node->GetOriginRect();
1596            }
1597            WLOGI("window %{public}d maximizeMode %{public}d rect %{public}d %{public}d %{public}d %{public}d",
1598                windowId, static_cast<uint32_t>(mode), newRect.posX_, newRect.posY_, newRect.width_, newRect.height_);
1599            ret = ResizeRectAndFlush(windowId, newRect, WindowSizeChangeReason::MAXIMIZE);
1600            break;
1601        }
1602        case PropertyChangeAction::ACTION_UPDATE_TEXTFIELD_AVOID_INFO: {
1603            node->GetWindowProperty()->SetTextFieldPositionY(property->GetTextFieldPositionY());
1604            node->GetWindowProperty()->SetTextFieldHeight(property->GetTextFieldHeight());
1605            break;
1606        }
1607        default:
1608            break;
1609    }
1610    return ret;
1611}
1612
1613WMError WindowController::SetWindowGravity(uint32_t windowId, WindowGravity gravity, uint32_t percent)
1614{
1615    sptr<WindowNode> node = windowRoot_->GetWindowNode(windowId);
1616    if (node == nullptr) {
1617        return WMError::WM_ERROR_NULLPTR;
1618    }
1619    if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
1620        return WMError::WM_ERROR_INVALID_TYPE;
1621    }
1622    node->SetWindowGravity(gravity, percent);
1623    RelayoutKeyboard(node);
1624    if (gravity == WindowGravity::WINDOW_GRAVITY_FLOAT) {
1625        RestoreCallingWindowSizeIfNeed();
1626    } else {
1627        ResizeSoftInputCallingWindowIfNeed(node);
1628    }
1629    WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_RECT);
1630    if (res != WMError::WM_OK) {
1631        return res;
1632    }
1633    FlushWindowInfo(windowId);
1634    return WMError::WM_OK;
1635}
1636
1637void WindowController::UpdatePrivateStateAndNotify(const sptr<WindowNode>& node)
1638{
1639    auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId());
1640    if (windowNodeContainer == nullptr) {
1641        WLOGFE("window node container is null");
1642        return;
1643    }
1644    windowNodeContainer->UpdatePrivateStateAndNotify();
1645}
1646
1647WMError WindowController::SetAspectRatio(uint32_t windowId, float ratio)
1648{
1649    WLOGI("SetAspectRatio, windowId: %{public}u, %{public}f", windowId, ratio);
1650    HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
1651    auto node = windowRoot_->GetWindowNode(windowId);
1652    if (node == nullptr) {
1653        WLOGFE("could not find window");
1654        return WMError::WM_OK;
1655    }
1656    if (!WindowHelper::IsAspectRatioSatisfiedWithSizeLimits(node->GetWindowUpdatedSizeLimits(), ratio,
1657        DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(node->GetDisplayId()))) {
1658        return WMError::WM_ERROR_INVALID_PARAM;
1659    }
1660
1661    node->SetAspectRatio(ratio);
1662
1663    // perserve aspect ratio
1664    std::vector<std::string> nameVector;
1665    if (node->abilityInfo_.abilityName_.size() > 0) {
1666        nameVector = WindowHelper::Split(node->abilityInfo_.abilityName_, ".");
1667    }
1668    std::string keyName = nameVector.empty() ? node->abilityInfo_.bundleName_ :
1669                                               node->abilityInfo_.bundleName_ + "." + nameVector.back();
1670    if (MathHelper::NearZero(ratio)) { // If ratio is 0.0, need to reset aspect and delete storage
1671        if (PersistentStorage::HasKey(keyName, PersistentStorageType::ASPECT_RATIO)) {
1672            PersistentStorage::Delete(keyName, PersistentStorageType::ASPECT_RATIO);
1673        }
1674        return WMError::WM_OK;
1675    }
1676    PersistentStorage::Insert(keyName, ratio, PersistentStorageType::ASPECT_RATIO);
1677
1678    WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_ASPECT_RATIO);
1679    if (res != WMError::WM_OK) {
1680        return res;
1681    }
1682    FlushWindowInfo(windowId);
1683    return WMError::WM_OK;
1684}
1685
1686WMError WindowController::GetAccessibilityWindowInfo(std::vector<sptr<AccessibilityWindowInfo>>& infos) const
1687{
1688    accessibilityConnection_->GetAccessibilityWindowInfo(infos);
1689    return WMError::WM_OK;
1690}
1691
1692WMError WindowController::GetUnreliableWindowInfo(int32_t windowId,
1693    std::vector<sptr<UnreliableWindowInfo>>& infos) const
1694{
1695    windowRoot_->GetUnreliableWindowInfo(windowId, infos);
1696    return WMError::WM_OK;
1697}
1698
1699WMError WindowController::GetVisibilityWindowInfo(std::vector<sptr<WindowVisibilityInfo>>& infos) const
1700{
1701    windowRoot_->GetVisibilityWindowInfo(infos);
1702    return WMError::WM_OK;
1703}
1704
1705WMError WindowController::GetModeChangeHotZones(DisplayId displayId,
1706    ModeChangeHotZones& hotZones, const ModeChangeHotZonesConfig& config)
1707{
1708    return windowRoot_->GetModeChangeHotZones(displayId, hotZones, config);
1709}
1710
1711WMError WindowController::UpdateTouchHotAreas(const sptr<WindowNode>& node, const std::vector<Rect>& rects)
1712{
1713    std::ostringstream oss;
1714    int index = 0;
1715    for (const auto& rect : rects) {
1716        oss << "[ " << rect.posX_ << ", " << rect.posY_ << ", " << rect.width_ << ", " << rect.height_ << " ]";
1717        index++;
1718        if (index < static_cast<int32_t>(rects.size())) {
1719            oss <<", ";
1720        }
1721    }
1722    WLOGI("windowId: %{public}u, size: %{public}d, rects: %{public}s",
1723        node->GetWindowId(), static_cast<int32_t>(rects.size()), oss.str().c_str());
1724    if (rects.size() > TOUCH_HOT_AREA_MAX_NUM) {
1725        WLOGFE("the number of touch hot areas exceeds the maximum");
1726        return WMError::WM_ERROR_INVALID_PARAM;
1727    }
1728
1729    std::vector<Rect> touchHotAreas;
1730    std::vector<Rect> pointerHotAreas;
1731    if (rects.empty()) {
1732        touchHotAreas.emplace_back(node->GetEntireWindowTouchHotArea());
1733        pointerHotAreas.emplace_back(node->GetEntireWindowPointerHotArea());
1734    } else {
1735        Rect windowRect = node->GetWindowRect();
1736        if (!WindowHelper::CalculateTouchHotAreas(windowRect, rects, touchHotAreas)) {
1737            WLOGFE("the requested touch hot areas are incorrect");
1738            return WMError::WM_ERROR_INVALID_PARAM;
1739        }
1740        pointerHotAreas = touchHotAreas;
1741    }
1742    node->GetWindowProperty()->SetTouchHotAreas(rects);
1743    node->SetTouchHotAreas(touchHotAreas);
1744    node->SetPointerHotAreas(pointerHotAreas);
1745    FlushWindowInfo(node->GetWindowId());
1746    accessibilityConnection_->NotifyAccessibilityWindowInfo(node, WindowUpdateType::WINDOW_UPDATE_PROPERTY);
1747    return WMError::WM_OK;
1748}
1749
1750WMError WindowController::UpdateTransform(uint32_t windowId)
1751{
1752    WMError res = windowRoot_->UpdateWindowNode(windowId, WindowUpdateReason::UPDATE_TRANSFORM);
1753    if (res != WMError::WM_OK) {
1754        return res;
1755    }
1756    FlushWindowInfo(windowId);
1757    accessibilityConnection_->NotifyAccessibilityWindowInfo(windowRoot_->GetWindowNode(windowId),
1758        WindowUpdateType::WINDOW_UPDATE_PROPERTY);
1759    return WMError::WM_OK;
1760}
1761
1762void WindowController::NotifyTouchOutside(const sptr<WindowNode>& node)
1763{
1764    auto windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(node->GetDisplayId());
1765    if (windowNodeContainer == nullptr) {
1766        WLOGFE("window node container is null");
1767        return;
1768    }
1769
1770    std::vector<sptr<WindowNode>> windowNodes;
1771    windowNodeContainer->TraverseContainer(windowNodes);
1772    uint32_t skipNodeId = GetEmbedNodeId(windowNodes, node);
1773    for (const auto& windowNode : windowNodes) {
1774        if (windowNode == nullptr || windowNode->GetWindowToken() == nullptr ||
1775            windowNode->GetWindowId() == skipNodeId ||
1776            windowNode->GetWindowId() == node->GetWindowId()) {
1777            WLOGFD("continue %{public}s", windowNode == nullptr ? "nullptr" : windowNode->GetWindowName().c_str());
1778            continue;
1779        }
1780        WLOGFD("notify %{public}s id %{public}d", windowNode->GetWindowName().c_str(), windowNode->GetWindowId());
1781        windowNode->GetWindowToken()->NotifyTouchOutside();
1782    }
1783}
1784
1785uint32_t WindowController::GetEmbedNodeId(const std::vector<sptr<WindowNode>>& windowNodes,
1786    const sptr<WindowNode>& node)
1787{
1788    if (node->GetWindowType() != WindowType::WINDOW_TYPE_APP_COMPONENT) {
1789        return 0;
1790    }
1791
1792    Rect nodeRect = node->GetWindowRect();
1793    bool isSkip = true;
1794    for (auto& windowNode : windowNodes) {
1795        if (windowNode == nullptr) {
1796            continue;
1797        }
1798        if (windowNode->GetWindowId() == node->GetWindowId()) {
1799            isSkip = false;
1800            continue;
1801        }
1802        if (isSkip) {
1803            continue;
1804        }
1805        if (nodeRect.IsInsideOf(windowNode->GetWindowRect())) {
1806            WLOGI("TouchOutside window type is component %{public}s windowNode %{public}d",
1807                windowNode->GetWindowName().c_str(), windowNode->GetWindowId());
1808            return windowNode->GetWindowId();
1809        }
1810    }
1811    return 0;
1812}
1813
1814void WindowController::MinimizeWindowsByLauncher(std::vector<uint32_t>& windowIds, bool isAnimated,
1815    sptr<RSIWindowAnimationFinishedCallback>& finishCallback)
1816{
1817    windowRoot_->MinimizeTargetWindows(windowIds);
1818    auto func = []() {
1819        MinimizeApp::ExecuteMinimizeTargetReasons(MinimizeReason::GESTURE_ANIMATION);
1820    };
1821    if (!isAnimated) {
1822        WLOGFD("no animation minimize size: %{public}u", static_cast<uint32_t>(windowIds.size()));
1823        func();
1824    } else {
1825        WLOGFD("animation minimize size: %{public}u", static_cast<uint32_t>(windowIds.size()));
1826        auto needMinimizeAppNodes = MinimizeApp::GetNeedMinimizeAppNodesWithReason(MinimizeReason::GESTURE_ANIMATION);
1827        for (auto& weakNode : needMinimizeAppNodes) {
1828            auto node = weakNode.promote();
1829            if (node) {
1830                // gesture animation no need to play default animation when minimize
1831                node->isPlayAnimationHide_ = true;
1832            }
1833        }
1834        finishCallback = RemoteAnimation::CreateAnimationFinishedCallback(func, nullptr);
1835        if (finishCallback == nullptr) {
1836            return;
1837        }
1838    }
1839}
1840
1841void WindowController::OnScreenshot(DisplayId displayId)
1842{
1843    std::vector<sptr<WindowNode>> windowNodes;
1844    windowRoot_->GetForegroundNodes(windowNodes);
1845    for (auto& windowNode : windowNodes) {
1846        auto windowToken = windowNode->GetWindowToken();
1847        if (windowToken != nullptr) {
1848            windowToken->NotifyScreenshot();
1849        }
1850    }
1851}
1852
1853void WindowController::SetAnchorOffset(int32_t deltaX, int32_t deltaY)
1854{
1855    displayZoomController_->SetAnchorOffset(deltaX, deltaY);
1856    DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
1857    FlushWindowInfoWithDisplayId(displayId);
1858}
1859
1860void WindowController::OffWindowZoom()
1861{
1862    displayZoomController_->OffWindowZoom();
1863    DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
1864    FlushWindowInfoWithDisplayId(displayId);
1865}
1866
1867void WindowController::SetAnchorAndScale(int32_t x, int32_t y, float scale)
1868{
1869    displayZoomController_->SetAnchorAndScale(x, y, scale);
1870    DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
1871    FlushWindowInfoWithDisplayId(displayId);
1872}
1873
1874WMError WindowController::BindDialogTarget(uint32_t& windowId, sptr<IRemoteObject> targetToken)
1875{
1876    auto node = windowRoot_->GetWindowNode(windowId);
1877    if (node == nullptr) {
1878        WLOGFE("could not find window");
1879        return WMError::WM_ERROR_NULLPTR;
1880    }
1881
1882    node->dialogTargetToken_ = targetToken;
1883
1884    return WMError::WM_OK;
1885}
1886
1887void WindowController::SetDragFrameGravity(int32_t dragGravity)
1888{
1889    dragFrameGravity_ = dragGravity;
1890}
1891} // namespace OHOS
1892} // namespace Rosen
1893