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 "screen_session_manager/include/screen_session_manager_client.h"
18 
19 #include "common/include/session_permission.h"
20 #include "key_event.h"
21 #include "window_helper.h"
22 #include "parameters.h"
23 #include "pointer_event.h"
24 #include "window_manager_hilog.h"
25 
26 
27 namespace OHOS::Rosen {
28 namespace {
29 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "SubSession" };
30 } // namespace
31 
SubSession(const SessionInfo & info,const sptr<SpecificSessionCallback> & specificCallback)32 SubSession::SubSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)
33     : SceneSession(info, specificCallback)
34 {
35     moveDragController_ = new (std::nothrow) MoveDragController(GetPersistentId());
36     if (moveDragController_ != nullptr && specificCallback != nullptr &&
37         specificCallback->onWindowInputPidChangeCallback_ != nullptr) {
38         moveDragController_->SetNotifyWindowPidChangeCallback(specificCallback->onWindowInputPidChangeCallback_);
39     }
40     SetMoveDragCallback();
41     TLOGD(WmsLogTag::WMS_LIFE, "Create SubSession");
42 }
43 
~SubSession()44 SubSession::~SubSession()
45 {
46     TLOGD(WmsLogTag::WMS_LIFE, "~SubSession, id: %{public}d", GetPersistentId());
47 }
48 
Show(sptr<WindowSessionProperty> property)49 WSError SubSession::Show(sptr<WindowSessionProperty> property)
50 {
51     if (!CheckPermissionWithPropertyAnimation(property)) {
52         return WSError::WS_ERROR_NOT_SYSTEM_APP;
53     }
54     auto task = [weakThis = wptr(this), property]() {
55         auto session = weakThis.promote();
56         if (!session) {
57             TLOGE(WmsLogTag::WMS_SUB, "session is null");
58             return WSError::WS_ERROR_DESTROYED_OBJECT;
59         }
60         TLOGI(WmsLogTag::WMS_LIFE, "Show session, id: %{public}d", session->GetPersistentId());
61 
62         // use property from client
63         auto sessionProperty = session->GetSessionProperty();
64         if (property && property->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM) &&
65             sessionProperty) {
66             sessionProperty->SetAnimationFlag(static_cast<uint32_t>(WindowAnimation::CUSTOM));
67             session->NotifyIsCustomAnimationPlaying(true);
68         }
69         auto ret = session->SceneSession::Foreground(property);
70         return ret;
71     };
72     PostTask(task, "Show");
73     return WSError::WS_OK;
74 }
75 
Hide()76 WSError SubSession::Hide()
77 {
78     return Hide(false);  // async mode
79 }
80 
HideSync()81 WSError SubSession::HideSync()
82 {
83     return Hide(true);  // sync mode
84 }
85 
Hide(bool needSyncHide)86 WSError SubSession::Hide(bool needSyncHide)
87 {
88     if (!CheckPermissionWithPropertyAnimation(GetSessionProperty())) {
89         return WSError::WS_ERROR_NOT_SYSTEM_APP;
90     }
91     auto task = [weakThis = wptr(this)]() {
92         auto session = weakThis.promote();
93         if (!session) {
94             TLOGE(WmsLogTag::WMS_SUB, "session is null");
95             return WSError::WS_ERROR_DESTROYED_OBJECT;
96         }
97         TLOGI(WmsLogTag::WMS_LIFE, "Hide session, id: %{public}d", session->GetPersistentId());
98         auto ret = session->SetActive(false);
99         if (ret != WSError::WS_OK) {
100             return ret;
101         }
102         // background will remove surfaceNode, custom not execute
103         // not animation playing when already background; inactive may be animation playing
104         auto sessionProperty = session->GetSessionProperty();
105         if (sessionProperty &&
106             sessionProperty->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM)) {
107             session->NotifyIsCustomAnimationPlaying(true);
108             return WSError::WS_OK;
109         }
110         ret = session->SceneSession::Background();
111         return ret;
112     };
113 
114     if (needSyncHide) {
115         return PostSyncTask(task, "HideSync");
116     }
117 
118     PostTask(task, "HideAsync");
119     return WSError::WS_OK;
120 }
121 
ProcessPointDownSession(int32_t posX,int32_t posY)122 WSError SubSession::ProcessPointDownSession(int32_t posX, int32_t posY)
123 {
124     const auto& id = GetPersistentId();
125     WLOGFI("id: %{public}d, type: %{public}d", id, GetWindowType());
126     auto parentSession = GetParentSession();
127     if (parentSession && parentSession->CheckDialogOnForeground()) {
128         WLOGFI("Has dialog foreground, id: %{public}d, type: %{public}d", id, GetWindowType());
129         return WSError::WS_OK;
130     }
131     auto sessionProperty = GetSessionProperty();
132     if (sessionProperty && sessionProperty->GetRaiseEnabled()) {
133         RaiseToAppTopForPointDown();
134     }
135     PresentFocusIfPointDown();
136     return SceneSession::ProcessPointDownSession(posX, posY);
137 }
138 
GetMissionId() const139 int32_t SubSession::GetMissionId() const
140 {
141     auto parentSession = GetParentSession();
142     return parentSession != nullptr ? parentSession->GetPersistentId() : SceneSession::GetMissionId();
143 }
144 
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)145 WSError SubSession::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
146 {
147     if (!IsSessionValid()) {
148         return WSError::WS_ERROR_INVALID_SESSION;
149     }
150     if (keyEvent == nullptr) {
151         WLOGFE("KeyEvent is nullptr");
152         return WSError::WS_ERROR_NULLPTR;
153     }
154     auto parentSession = GetParentSession();
155     if (parentSession && parentSession->CheckDialogOnForeground()) {
156         TLOGD(WmsLogTag::WMS_DIALOG, "Its main window has dialog on foreground, not transfer pointer event");
157         return WSError::WS_ERROR_INVALID_PERMISSION;
158     }
159 
160     WSError ret = Session::TransferKeyEvent(keyEvent);
161     return ret;
162 }
163 
UpdatePointerArea(const WSRect & rect)164 void SubSession::UpdatePointerArea(const WSRect& rect)
165 {
166     auto property = GetSessionProperty();
167     if (!(property->IsDecorEnable() && GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING)) {
168         return;
169     }
170     Session::UpdatePointerArea(rect);
171 }
172 
CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent> & pointerEvent) const173 bool SubSession::CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) const
174 {
175     auto sessionState = GetSessionState();
176     int32_t action = pointerEvent->GetPointerAction();
177     auto isPC = systemConfig_.uiType_ == UI_TYPE_PC;
178     if (isPC && sessionState != SessionState::STATE_FOREGROUND &&
179         sessionState != SessionState::STATE_ACTIVE &&
180         action != MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW) {
181         WLOGFW("Current Session Info: [persistentId: %{public}d, "
182             "state: %{public}d, action:%{public}d]", GetPersistentId(), GetSessionState(), action);
183         return false;
184     }
185     return true;
186 }
187 
RectCheck(uint32_t curWidth,uint32_t curHeight)188 void SubSession::RectCheck(uint32_t curWidth, uint32_t curHeight)
189 {
190     uint32_t minWidth = GetSystemConfig().miniWidthOfSubWindow_;
191     uint32_t minHeight = GetSystemConfig().miniHeightOfSubWindow_;
192     uint32_t maxFloatingWindowSize = GetSystemConfig().maxFloatingWindowSize_;
193     RectSizeCheckProcess(curWidth, curHeight, minWidth, minHeight, maxFloatingWindowSize);
194 }
195 
IsTopmost() const196 bool SubSession::IsTopmost() const
197 {
198     bool isTopmost = false;
199     auto sessionProperty = GetSessionProperty();
200     if (sessionProperty) {
201         isTopmost = sessionProperty->IsTopmost();
202     }
203     TLOGI(WmsLogTag::WMS_SUB, "isTopmost: %{public}d", isTopmost);
204     return isTopmost;
205 }
206 
IsModal() const207 bool SubSession::IsModal() const
208 {
209     return WindowHelper::IsModalSubWindow(GetSessionProperty()->GetWindowType(),
210                                           GetSessionProperty()->GetWindowFlags());
211 }
212 
IsApplicationModal() const213 bool SubSession::IsApplicationModal() const
214 {
215     return WindowHelper::IsApplicationModalSubWindow(GetSessionProperty()->GetWindowType(),
216                                                      GetSessionProperty()->GetWindowFlags());
217 }
218 
IsVisibleForeground() const219 bool SubSession::IsVisibleForeground() const
220 {
221     if (parentSession_ && WindowHelper::IsMainWindow(parentSession_->GetWindowType())) {
222         return parentSession_->IsVisibleForeground() && Session::IsVisibleForeground();
223     }
224     return Session::IsVisibleForeground();
225 }
226 } // namespace OHOS::Rosen
227