1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "window_system_effect.h"
17 
18 #include <common/rs_common_def.h>
19 #include "color_parser.h"
20 #include "display_group_info.h"
21 #include "remote_animation.h"
22 #include "window_helper.h"
23 #include "window_inner_manager.h"
24 #include "window_manager_hilog.h"
25 
26 namespace OHOS {
27 namespace Rosen {
28 namespace {
29 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowSystemEffect"};
30 }
31 
32 AppWindowEffectConfig WindowSystemEffect::windowSystemEffectConfig_;
33 wptr<WindowRoot> WindowSystemEffect::windowRoot_;
34 
SetWindowSystemEffectConfig(AppWindowEffectConfig config)35 void WindowSystemEffect::SetWindowSystemEffectConfig(AppWindowEffectConfig config)
36 {
37     windowSystemEffectConfig_ = config;
38 }
39 
SetWindowRoot(const sptr<WindowRoot> & windowRoot)40 void WindowSystemEffect::SetWindowRoot(const sptr<WindowRoot>& windowRoot)
41 {
42     windowRoot_ = windowRoot;
43 }
44 
SetCornerRadius(const sptr<WindowNode> & node,bool needCheckAnimation)45 WMError WindowSystemEffect::SetCornerRadius(const sptr<WindowNode>& node, bool needCheckAnimation)
46 {
47     auto winRoot = windowRoot_.promote();
48     if (winRoot == nullptr || node == nullptr) {
49         WLOGFE("window root is null");
50         return WMError::WM_ERROR_NULLPTR;
51     }
52     // if change mode during animation, not set radius until animationFinish
53     if (needCheckAnimation && RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) &&
54         node->stateMachine_.IsShowAnimationPlaying()) {
55         WLOGFW("not set radius during animation");
56         return WMError::WM_DO_NOTHING;
57     }
58 
59     if (!IsAppMainOrSubOrFloatingWindow(node)) {
60         return WMError::WM_DO_NOTHING;
61     }
62     auto vpr = DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(node->GetDisplayId());
63     auto fullscreenRadius = windowSystemEffectConfig_.fullScreenCornerRadius_ * vpr;
64     auto splitRadius = windowSystemEffectConfig_.splitCornerRadius_ * vpr;
65     auto floatRadius = windowSystemEffectConfig_.floatCornerRadius_ * vpr;
66 
67     WLOGFD("[WEffect] [id:%{public}d] mode: %{public}u, vpr: %{public}f, [%{public}f, %{public}f, %{public}f]",
68         node->GetWindowId(), node->GetWindowMode(), vpr, fullscreenRadius, splitRadius, floatRadius);
69     if (MathHelper::NearZero(fullscreenRadius) && MathHelper::NearZero(splitRadius) &&
70         MathHelper::NearZero(floatRadius)) {
71         return WMError::WM_DO_NOTHING;
72     }
73     auto surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_;
74     if (surfaceNode == nullptr) {
75         WLOGFE("window surfaceNode is null");
76         return WMError::WM_ERROR_NULLPTR;
77     }
78     if (WindowHelper::IsFullScreenWindow(node->GetWindowMode())) {
79         surfaceNode->SetCornerRadius(fullscreenRadius);
80     } else if (WindowHelper::IsSplitWindowMode(node->GetWindowMode())) {
81         surfaceNode->SetCornerRadius(splitRadius);
82     } else if (WindowHelper::IsFloatingWindow(node->GetWindowMode())) {
83         surfaceNode->SetCornerRadius(floatRadius);
84     }
85     return WMError::WM_OK;
86 }
87 
IsAppMainOrSubOrFloatingWindow(const sptr<WindowNode> & node)88 bool WindowSystemEffect::IsAppMainOrSubOrFloatingWindow(const sptr<WindowNode>& node)
89 {
90     if (WindowHelper::IsAppWindow(node->GetWindowType())) {
91         return true;
92     }
93     auto winRoot = windowRoot_.promote();
94     if (winRoot == nullptr) {
95         return false;
96     }
97     // Type float has main window
98     if (WindowHelper::IsAppFloatingWindow(node->GetWindowType()) &&
99         winRoot->FindMainWindowWithToken(node->abilityToken_)) {
100         return true;
101     }
102     WLOGFD("not appWindow or app floating window, id: %{public}u!", node->GetWindowId());
103     return false;
104 }
105 
SetWindowShadow(const sptr<WindowNode> & node)106 WMError WindowSystemEffect::SetWindowShadow(const sptr<WindowNode>& node)
107 {
108     auto winRoot = windowRoot_.promote();
109     if (winRoot == nullptr || node == nullptr) {
110         return WMError::WM_ERROR_NULLPTR;
111     }
112 
113     if (!IsAppMainOrSubOrFloatingWindow(node)) {
114         return WMError::WM_DO_NOTHING;
115     }
116 
117     if (MathHelper::NearZero(windowSystemEffectConfig_.focusedShadow_.elevation_) &&
118         MathHelper::NearZero(windowSystemEffectConfig_.unfocusedShadow_.elevation_) &&
119         MathHelper::NearZero(windowSystemEffectConfig_.focusedShadow_.radius_) &&
120         MathHelper::NearZero(windowSystemEffectConfig_.unfocusedShadow_.radius_)) {
121         WLOGFD("shadow elevation and radius are both 0.0, id: %{public}u", node->GetWindowId());
122         return WMError::WM_DO_NOTHING;
123     }
124 
125     auto surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_;
126     if (surfaceNode == nullptr) {
127         WLOGFE("window surfaceNode is null");
128         return WMError::WM_ERROR_NULLPTR;
129     }
130 
131     auto& shadow = node->isFocused_ ? windowSystemEffectConfig_.focusedShadow_ :
132         windowSystemEffectConfig_.unfocusedShadow_;
133 
134     // when float mode change to fullscreen/split mode
135     if (!WindowHelper::IsFloatingWindow(node->GetWindowMode())) {
136         if (MathHelper::GreatNotEqual(shadow.elevation_, 0.f)) {
137             surfaceNode->SetShadowElevation(0.f);
138         } else {
139             surfaceNode->SetShadowRadius(0.f);
140         }
141         surfaceNode->SetShadowAlpha(0.f);
142         WLOGFD("[WEffect]close shadow id: %{public}u", node->GetWindowId());
143         return WMError::WM_OK;
144     }
145 
146     uint32_t colorValue;
147     if (!ColorParser::Parse(shadow.color_, colorValue)) {
148         WLOGFE("[WEffect]invalid color string: %{public}s", shadow.color_.c_str());
149         return WMError::WM_ERROR_INVALID_PARAM;
150     }
151 
152     WLOGFI("[WEffect]id: %{public}u focused: %{public}d elevation: %{public}f",
153         node->GetWindowId(), static_cast<int32_t>(node->isFocused_), shadow.elevation_);
154     WLOGFI("[WEffect]color: %{public}s offsetX: %{public}f offsetY: %{public}f alpha: %{public}f radius: %{public}f",
155         shadow.color_.c_str(), shadow.offsetX_, shadow.offsetY_, shadow.alpha_, shadow.radius_);
156     auto vpr = DisplayGroupInfo::GetInstance().GetDisplayVirtualPixelRatio(node->GetDisplayId());
157     if (MathHelper::GreatNotEqual(shadow.elevation_, 0.f)) {
158         surfaceNode->SetShadowElevation(shadow.elevation_ * vpr);
159     } else {
160         surfaceNode->SetShadowRadius(ConvertRadiusToSigma(shadow.radius_ * vpr));
161     }
162     surfaceNode->SetShadowColor(colorValue);
163     surfaceNode->SetShadowOffsetX(shadow.offsetX_ * vpr);
164     surfaceNode->SetShadowOffsetY(shadow.offsetY_ * vpr);
165     surfaceNode->SetShadowAlpha(shadow.alpha_);
166     return WMError::WM_OK;
167 }
168 
SetWindowEffect(const sptr<WindowNode> & node,bool needCheckAnimation)169 WMError WindowSystemEffect::SetWindowEffect(const sptr<WindowNode>& node, bool needCheckAnimation)
170 {
171     auto winRoot = windowRoot_.promote();
172     if (node == nullptr) {
173         WLOGFE("window node is null");
174         return WMError::WM_ERROR_NULLPTR;
175     }
176     SetCornerRadius(node, needCheckAnimation);
177     SetWindowShadow(node);
178     return WMError::WM_OK;
179 }
180 } // Rosen
181 } // OHOS
182