1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "session/host/include/sub_session.h"
17 #include "window_helper.h"
18 #include "pointer_event.h"
19 #include "window_manager_hilog.h"
20
21
22 namespace OHOS::Rosen {
23 namespace {
24 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "SubSession" };
25 } // namespace
26
SubSession(const SessionInfo & info,const sptr<SpecificSessionCallback> & specificCallback)27 SubSession::SubSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)
28 : SceneSession(info, specificCallback)
29 {
30 pcFoldScreenController_ = sptr<PcFoldScreenController>::MakeSptr(wptr(this), GetPersistentId());
31 moveDragController_ = sptr<MoveDragController>::MakeSptr(GetPersistentId(), GetWindowType());
32 if (specificCallback != nullptr &&
33 specificCallback->onWindowInputPidChangeCallback_ != nullptr) {
34 moveDragController_->SetNotifyWindowPidChangeCallback(specificCallback->onWindowInputPidChangeCallback_);
35 }
36 SetMoveDragCallback();
37 TLOGD(WmsLogTag::WMS_LIFE, "Create");
38 }
39
~SubSession()40 SubSession::~SubSession()
41 {
42 TLOGD(WmsLogTag::WMS_LIFE, "id: %{public}d", GetPersistentId());
43 }
44
Show(sptr<WindowSessionProperty> property)45 WSError SubSession::Show(sptr<WindowSessionProperty> property)
46 {
47 if (!CheckPermissionWithPropertyAnimation(property)) {
48 return WSError::WS_ERROR_NOT_SYSTEM_APP;
49 }
50 if (property->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_IS_TEXT_MENU) &&
51 GetForceHideState() != ForceHideState::NOT_HIDDEN) {
52 TLOGI(WmsLogTag::WMS_SUB, "UEC force hide, id: %{public}d forceHideState: %{public}d",
53 GetPersistentId(), GetForceHideState());
54 return WSError::WS_ERROR_INVALID_OPERATION;
55 }
56 PostTask([weakThis = wptr(this), property]() {
57 auto session = weakThis.promote();
58 if (!session) {
59 TLOGE(WmsLogTag::WMS_SUB, "session is null");
60 return WSError::WS_ERROR_DESTROYED_OBJECT;
61 }
62 TLOGI(WmsLogTag::WMS_LIFE, "Show session, id: %{public}d", session->GetPersistentId());
63
64 auto parentSession = session->GetParentSession();
65 if (parentSession && session->GetShouldFollowParentWhenShow()) {
66 session->CheckAndMoveDisplayIdRecursively(parentSession->GetSessionProperty()->GetDisplayId());
67 } else {
68 TLOGNE(WmsLogTag::WMS_SUB, "session has no parent, id: %{public}d", session->GetPersistentId());
69 }
70 // use property from client
71 auto sessionProperty = session->GetSessionProperty();
72 if (property && property->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM) &&
73 sessionProperty) {
74 sessionProperty->SetAnimationFlag(static_cast<uint32_t>(WindowAnimation::CUSTOM));
75 session->NotifyIsCustomAnimationPlaying(true);
76 }
77 auto ret = session->SceneSession::Foreground(property);
78 return ret;
79 }, "Show");
80 return WSError::WS_OK;
81 }
82
NotifySessionRectChange(const WSRect & rect,SizeChangeReason reason,DisplayId displayId,const RectAnimationConfig & rectAnimationConfig)83 void SubSession::NotifySessionRectChange(const WSRect& rect, SizeChangeReason reason, DisplayId displayId,
84 const RectAnimationConfig& rectAnimationConfig)
85 {
86 if (reason == SizeChangeReason::DRAG_END) {
87 SetShouldFollowParentWhenShow(false);
88 }
89 SceneSession::NotifySessionRectChange(rect, reason, displayId, rectAnimationConfig);
90 }
91
UpdateSessionRectInner(const WSRect & rect,SizeChangeReason reason,const MoveConfiguration & moveConfiguration,const RectAnimationConfig & rectAnimationConfig)92 void SubSession::UpdateSessionRectInner(const WSRect& rect, SizeChangeReason reason,
93 const MoveConfiguration& moveConfiguration, const RectAnimationConfig& rectAnimationConfig)
94 {
95 if (moveConfiguration.displayId != DISPLAY_ID_INVALID) {
96 SetShouldFollowParentWhenShow(false);
97 }
98 SceneSession::UpdateSessionRectInner(rect, reason, moveConfiguration, rectAnimationConfig);
99 }
100
Hide()101 WSError SubSession::Hide()
102 {
103 return Hide(false); // async mode
104 }
105
HideSync()106 WSError SubSession::HideSync()
107 {
108 return Hide(true); // sync mode
109 }
110
Hide(bool needSyncHide)111 WSError SubSession::Hide(bool needSyncHide)
112 {
113 if (!CheckPermissionWithPropertyAnimation(GetSessionProperty())) {
114 return WSError::WS_ERROR_NOT_SYSTEM_APP;
115 }
116 auto task = [weakThis = wptr(this)]() {
117 auto session = weakThis.promote();
118 if (!session) {
119 TLOGNE(WmsLogTag::WMS_SUB, "session is null");
120 return WSError::WS_ERROR_DESTROYED_OBJECT;
121 }
122 TLOGNI(WmsLogTag::WMS_LIFE, "Hide session, id: %{public}d", session->GetPersistentId());
123 auto ret = session->SetActive(false);
124 if (ret != WSError::WS_OK) {
125 return ret;
126 }
127 // background will remove surfaceNode, custom not execute
128 // not animation playing when already background; inactive may be animation playing
129 auto sessionProperty = session->GetSessionProperty();
130 if (sessionProperty &&
131 sessionProperty->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM)) {
132 session->NotifyIsCustomAnimationPlaying(true);
133 return WSError::WS_OK;
134 }
135 ret = session->SceneSession::Background();
136 return ret;
137 };
138
139 if (needSyncHide) {
140 return PostSyncTask(task, "HideSync");
141 }
142
143 PostTask(task, "HideAsync");
144 return WSError::WS_OK;
145 }
146
ProcessPointDownSession(int32_t posX,int32_t posY)147 WSError SubSession::ProcessPointDownSession(int32_t posX, int32_t posY)
148 {
149 const auto& id = GetPersistentId();
150 TLOGD(WmsLogTag::WMS_INPUT_KEY_FLOW, "id:%{public}d, type:%{public}d", id, GetWindowType());
151 auto isModal = IsModal();
152 auto parentSession = GetParentSession();
153 if (!isModal && parentSession && parentSession->CheckDialogOnForeground()) {
154 WLOGFI("Has dialog foreground, id: %{public}d, type: %{public}d", id, GetWindowType());
155 return WSError::WS_OK;
156 }
157 if (isModal) {
158 Session::ProcessClickModalWindowOutside(posX, posY);
159 }
160 auto sessionProperty = GetSessionProperty();
161 if (sessionProperty && sessionProperty->GetRaiseEnabled()) {
162 RaiseToAppTopForPointDown();
163 }
164 PresentFocusIfPointDown();
165 return SceneSession::ProcessPointDownSession(posX, posY);
166 }
167
GetMissionId() const168 int32_t SubSession::GetMissionId() const
169 {
170 auto parentSession = GetParentSession();
171 return parentSession != nullptr ? parentSession->GetPersistentId() : SceneSession::GetMissionId();
172 }
173
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)174 WSError SubSession::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
175 {
176 if (!IsSessionValid()) {
177 return WSError::WS_ERROR_INVALID_SESSION;
178 }
179 if (keyEvent == nullptr) {
180 WLOGFE("KeyEvent is nullptr");
181 return WSError::WS_ERROR_NULLPTR;
182 }
183 auto parentSession = GetParentSession();
184 if (parentSession && parentSession->CheckDialogOnForeground()) {
185 TLOGD(WmsLogTag::WMS_DIALOG, "Its main window has dialog on foreground, not transfer pointer event");
186 return WSError::WS_ERROR_INVALID_PERMISSION;
187 }
188
189 WSError ret = Session::TransferKeyEvent(keyEvent);
190 return ret;
191 }
192
UpdatePointerArea(const WSRect & rect)193 void SubSession::UpdatePointerArea(const WSRect& rect)
194 {
195 auto property = GetSessionProperty();
196 if (!(property->IsDecorEnable() && GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING)) {
197 return;
198 }
199 Session::UpdatePointerArea(rect);
200 }
201
CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent> & pointerEvent) const202 bool SubSession::CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) const
203 {
204 auto sessionState = GetSessionState();
205 int32_t action = pointerEvent->GetPointerAction();
206 auto isPC = systemConfig_.IsPcWindow();
207 if (isPC && sessionState != SessionState::STATE_FOREGROUND &&
208 sessionState != SessionState::STATE_ACTIVE &&
209 action != MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW) {
210 WLOGFW("Current Session Info: [persistentId: %{public}d, "
211 "state: %{public}d, action:%{public}d]", GetPersistentId(), GetSessionState(), action);
212 return false;
213 }
214 return true;
215 }
216
RectCheck(uint32_t curWidth,uint32_t curHeight)217 void SubSession::RectCheck(uint32_t curWidth, uint32_t curHeight)
218 {
219 uint32_t minWidth = GetSystemConfig().miniWidthOfSubWindow_;
220 uint32_t minHeight = GetSystemConfig().miniHeightOfSubWindow_;
221 uint32_t maxFloatingWindowSize = GetSystemConfig().maxFloatingWindowSize_;
222 RectSizeCheckProcess(curWidth, curHeight, minWidth, minHeight, maxFloatingWindowSize);
223 }
224
IsTopmost() const225 bool SubSession::IsTopmost() const
226 {
227 bool isTopmost = false;
228 auto sessionProperty = GetSessionProperty();
229 if (sessionProperty) {
230 isTopmost = sessionProperty->IsTopmost();
231 }
232 TLOGI(WmsLogTag::WMS_SUB, "isTopmost: %{public}d", isTopmost);
233 return isTopmost;
234 }
235
IsModal() const236 bool SubSession::IsModal() const
237 {
238 return WindowHelper::IsModalSubWindow(GetSessionProperty()->GetWindowType(),
239 GetSessionProperty()->GetWindowFlags());
240 }
241
IsApplicationModal() const242 bool SubSession::IsApplicationModal() const
243 {
244 return WindowHelper::IsApplicationModalSubWindow(GetSessionProperty()->GetWindowType(),
245 GetSessionProperty()->GetWindowFlags());
246 }
247
IsVisibleForeground() const248 bool SubSession::IsVisibleForeground() const
249 {
250 const auto& mainOrFloatSession = GetMainOrFloatSession();
251 if (mainOrFloatSession) {
252 return mainOrFloatSession->IsVisibleForeground() && Session::IsVisibleForeground();
253 }
254 return Session::IsVisibleForeground();
255 }
256
SetParentSessionCallback(NotifySetParentSessionFunc && func)257 void SubSession::SetParentSessionCallback(NotifySetParentSessionFunc&& func)
258 {
259 const char* const where = __func__;
260 PostTask([weakThis = wptr(this), where, func = std::move(func)] {
261 auto session = weakThis.promote();
262 if (!session || !func) {
263 TLOGNE(WmsLogTag::WMS_SUB, "%{public}s session or func is nullptr", where);
264 return;
265 }
266 session->setParentSessionFunc_ = std::move(func);
267 TLOGND(WmsLogTag::WMS_SUB, "%{public}s id: %{public}d", where,
268 session->GetPersistentId());
269 }, __func__);
270 }
271
NotifySetParentSession(int32_t oldParentWindowId,int32_t newParentWindowId)272 WMError SubSession::NotifySetParentSession(int32_t oldParentWindowId, int32_t newParentWindowId)
273 {
274 return PostSyncTask([weakThis = wptr(this), oldParentWindowId, newParentWindowId, where = __func__] {
275 auto session = weakThis.promote();
276 if (!session) {
277 TLOGNE(WmsLogTag::WMS_SUB, "%{public}s session is nullptr", where);
278 return WMError::WM_ERROR_INVALID_WINDOW;
279 }
280 if (session->setParentSessionFunc_) {
281 session->setParentSessionFunc_(oldParentWindowId, newParentWindowId);
282 TLOGND(WmsLogTag::WMS_SUB, "%{public}s id: %{public}d oldParentWindowId: %{public}d "
283 "newParentWindowId: %{public}d", where, session->GetPersistentId(), oldParentWindowId,
284 newParentWindowId);
285 }
286 return WMError::WM_OK;
287 }, __func__);
288 }
289
NotifyFollowParentMultiScreenPolicy(bool enabled)290 WSError SubSession::NotifyFollowParentMultiScreenPolicy(bool enabled)
291 {
292 PostTask([weakThis = wptr(this), enabled, funcName = __func__] {
293 auto session = weakThis.promote();
294 if (!session) {
295 TLOGNE(WmsLogTag::WMS_SUB, "%{public}s: session is null", funcName);
296 return;
297 }
298 TLOGNI(WmsLogTag::WMS_SUB, "%{public}s: enabled:%{public}d", funcName, enabled);
299 session->isFollowParentMultiScreenPolicy_ = enabled;
300 }, __func__);
301 return WSError::WS_OK;
302 }
303
IsFollowParentMultiScreenPolicy() const304 bool SubSession::IsFollowParentMultiScreenPolicy() const
305 {
306 return isFollowParentMultiScreenPolicy_;
307 }
308
SetSubWindowZLevel(int32_t zLevel)309 WSError SubSession::SetSubWindowZLevel(int32_t zLevel)
310 {
311 PostTask([weakThis = wptr(this), zLevel]() {
312 auto session = weakThis.promote();
313 if (!session) {
314 TLOGE(WmsLogTag::WMS_HIERARCHY, "session is null");
315 return;
316 }
317 auto property = session->GetSessionProperty();
318 TLOGI(WmsLogTag::WMS_HIERARCHY, "Notify session zLevel change, id: %{public}d, zLevel: %{public}d",
319 session->GetPersistentId(), zLevel);
320 property->SetSubWindowZLevel(zLevel);
321 if (session->onSubSessionZLevelChange_) {
322 session->onSubSessionZLevelChange_(zLevel);
323 }
324 }, "SetSubWindowZLevel");
325 return WSError::WS_OK;
326 }
327
GetSubWindowZLevel() const328 int32_t SubSession::GetSubWindowZLevel() const
329 {
330 int32_t zLevel = 0;
331 auto sessionProperty = GetSessionProperty();
332 zLevel = sessionProperty->GetSubWindowZLevel();
333 TLOGI(WmsLogTag::WMS_HIERARCHY, "zLevel: %{public}d", zLevel);
334 return zLevel;
335 }
336 } // namespace OHOS::Rosen
337