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/main_session.h"
17 
18 #include "session_helper.h"
19 #include "window_helper.h"
20 #include "session/host/include/scene_persistent_storage.h"
21 
22 namespace OHOS::Rosen {
23 namespace {
24 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "MainSession" };
25 } // namespace
26 
MainSession(const SessionInfo & info,const sptr<SpecificSessionCallback> & specificCallback)27 MainSession::MainSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)
28     : SceneSession(info, specificCallback)
29 {
30     scenePersistence_ = new ScenePersistence(info.bundleName_, GetPersistentId());
31     if (info.persistentId_ != 0 && info.persistentId_ != GetPersistentId()) {
32         // persistentId changed due to id conflicts. Need to rename the old snapshot if exists
33         scenePersistence_->RenameSnapshotFromOldPersistentId(info.persistentId_);
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     std::string key = GetRatioPreferenceKey();
42     if (!key.empty()) {
43         if (ScenePersistentStorage::HasKey(key, ScenePersistentStorageType::ASPECT_RATIO)) {
44             ScenePersistentStorage::Get(key, aspectRatio_, ScenePersistentStorageType::ASPECT_RATIO);
45             WLOGD("SceneSession init aspectRatio , key %{public}s, value: %{public}f", key.c_str(), aspectRatio_);
46             if (moveDragController_) {
47                 moveDragController_->SetAspectRatio(aspectRatio_);
48             }
49         }
50     }
51 
52     WLOGFD("Create MainSession");
53 }
54 
~MainSession()55 MainSession::~MainSession()
56 {
57     WLOGD("~MainSession, id: %{public}d", GetPersistentId());
58 }
59 
Reconnect(const sptr<ISessionStage> & sessionStage,const sptr<IWindowEventChannel> & eventChannel,const std::shared_ptr<RSSurfaceNode> & surfaceNode,sptr<WindowSessionProperty> property,sptr<IRemoteObject> token,int32_t pid,int32_t uid)60 WSError MainSession::Reconnect(const sptr<ISessionStage>& sessionStage, const sptr<IWindowEventChannel>& eventChannel,
61     const std::shared_ptr<RSSurfaceNode>& surfaceNode, sptr<WindowSessionProperty> property, sptr<IRemoteObject> token,
62     int32_t pid, int32_t uid)
63 {
64     return PostSyncTask([weakThis = wptr(this), sessionStage, eventChannel, surfaceNode, property, token, pid, uid]() {
65         auto session = weakThis.promote();
66         if (!session) {
67             WLOGFE("session is null");
68             return WSError::WS_ERROR_DESTROYED_OBJECT;
69         }
70         WSError ret = session->Session::Reconnect(sessionStage, eventChannel, surfaceNode, property, token, pid, uid);
71         if (ret != WSError::WS_OK) {
72             return ret;
73         }
74         WindowState windowState = property->GetWindowState();
75         if (windowState == WindowState::STATE_SHOWN) {
76             session->isActive_ = true;
77             session->UpdateSessionState(SessionState::STATE_ACTIVE);
78         } else {
79             session->isActive_ = false;
80             session->UpdateSessionState(SessionState::STATE_BACKGROUND);
81             if (session->scenePersistence_) {
82                 session->scenePersistence_->SetHasSnapshot(true);
83             }
84         }
85         return ret;
86     });
87 }
88 
ProcessPointDownSession(int32_t posX,int32_t posY)89 WSError MainSession::ProcessPointDownSession(int32_t posX, int32_t posY)
90 {
91     const auto& id = GetPersistentId();
92     WLOGFI("id: %{public}d, type: %{public}d", id, GetWindowType());
93     auto isModal = IsModal();
94     if (!isModal && CheckDialogOnForeground()) {
95         HandlePointDownDialog();
96         return WSError::WS_OK;
97     }
98     PresentFocusIfPointDown();
99     return SceneSession::ProcessPointDownSession(posX, posY);
100 }
101 
NotifyForegroundInteractiveStatus(bool interactive)102 void MainSession::NotifyForegroundInteractiveStatus(bool interactive)
103 {
104     SetForegroundInteractiveStatus(interactive);
105     if (!IsSessionValid() || !sessionStage_) {
106         TLOGW(WmsLogTag::WMS_MAIN, "Session or sessionStage is invalid, id: %{public}d state: %{public}u",
107             GetPersistentId(), GetSessionState());
108         return;
109     }
110     const auto& state = GetSessionState();
111     if (isVisible_ || state == SessionState::STATE_ACTIVE || state == SessionState::STATE_FOREGROUND) {
112         WLOGFI("NotifyForegroundInteractiveStatus %{public}d", interactive);
113         sessionStage_->NotifyForegroundInteractiveStatus(interactive);
114     }
115 }
116 
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)117 WSError MainSession::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
118 {
119     if (!IsSessionValid()) {
120         return WSError::WS_ERROR_INVALID_SESSION;
121     }
122     if (keyEvent == nullptr) {
123         WLOGFE("KeyEvent is nullptr");
124         return WSError::WS_ERROR_NULLPTR;
125     }
126     if (CheckDialogOnForeground()) {
127         TLOGD(WmsLogTag::WMS_DIALOG, "Has dialog on foreground, not transfer pointer event");
128         return WSError::WS_ERROR_INVALID_PERMISSION;
129     }
130 
131     WSError ret = Session::TransferKeyEvent(keyEvent);
132     return ret;
133 }
134 
UpdatePointerArea(const WSRect & rect)135 void MainSession::UpdatePointerArea(const WSRect& rect)
136 {
137     if (GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING) {
138         return;
139     }
140     Session::UpdatePointerArea(rect);
141 }
142 
CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent> & pointerEvent) const143 bool MainSession::CheckPointerEventDispatch(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) const
144 {
145     auto sessionState = GetSessionState();
146     int32_t action = pointerEvent->GetPointerAction();
147     if (sessionState != SessionState::STATE_FOREGROUND &&
148         sessionState != SessionState::STATE_ACTIVE &&
149         action != MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW) {
150         WLOGFW("Current Session Info: [persistentId: %{public}d, "
151             "state: %{public}d, action:%{public}d]", GetPersistentId(), GetSessionState(), action);
152         return false;
153     }
154     return true;
155 }
156 
SetTopmost(bool topmost)157 WSError MainSession::SetTopmost(bool topmost)
158 {
159     TLOGI(WmsLogTag::WMS_LAYOUT, "SetTopmost id: %{public}d, topmost: %{public}d", GetPersistentId(), topmost);
160     auto task = [weakThis = wptr(this), topmost]() {
161         auto session = weakThis.promote();
162         if (!session) {
163             TLOGE(WmsLogTag::WMS_LAYOUT, "session is null");
164             return;
165         }
166         auto property = session->GetSessionProperty();
167         if (property) {
168             TLOGI(WmsLogTag::WMS_LAYOUT, "Notify session topmost change, id: %{public}d, topmost: %{public}u",
169                 session->GetPersistentId(), topmost);
170             property->SetTopmost(topmost);
171             if (session->sessionChangeCallback_ && session->sessionChangeCallback_->onSessionTopmostChange_) {
172                 session->sessionChangeCallback_->onSessionTopmostChange_(topmost);
173             }
174         }
175     };
176     PostTask(task, "SetTopmost");
177     return WSError::WS_OK;
178 }
179 
IsTopmost() const180 bool MainSession::IsTopmost() const
181 {
182     return GetSessionProperty()->IsTopmost();
183 }
184 
SetMainWindowTopmost(bool isTopmost)185 WSError MainSession::SetMainWindowTopmost(bool isTopmost)
186 {
187     GetSessionProperty()->SetMainWindowTopmost(isTopmost);
188     TLOGD(WmsLogTag::WMS_HIERARCHY, "id: %{public}d, isTopmost: %{public}u",
189         GetPersistentId(), isTopmost);
190     if (mainWindowTopmostChangeFunc_) {
191         mainWindowTopmostChangeFunc_(isTopmost);
192     }
193     return WSError::WS_OK;
194 }
195 
IsMainWindowTopmost() const196 bool MainSession::IsMainWindowTopmost() const
197 {
198     return GetSessionProperty()->IsMainWindowTopmost();
199 }
200 
RectCheck(uint32_t curWidth,uint32_t curHeight)201 void MainSession::RectCheck(uint32_t curWidth, uint32_t curHeight)
202 {
203     uint32_t minWidth = GetSystemConfig().miniWidthOfMainWindow_;
204     uint32_t minHeight = GetSystemConfig().miniHeightOfMainWindow_;
205     uint32_t maxFloatingWindowSize = GetSystemConfig().maxFloatingWindowSize_;
206     RectSizeCheckProcess(curWidth, curHeight, minWidth, minHeight, maxFloatingWindowSize);
207 }
208 
SetExitSplitOnBackground(bool isExitSplitOnBackground)209 void MainSession::SetExitSplitOnBackground(bool isExitSplitOnBackground)
210 {
211     TLOGI(WmsLogTag::WMS_MULTI_WINDOW, "id: %{public}d, isExitSplitOnBackground: %{public}d", persistentId_,
212         isExitSplitOnBackground);
213     isExitSplitOnBackground_ = isExitSplitOnBackground;
214 }
215 
IsExitSplitOnBackground() const216 bool MainSession::IsExitSplitOnBackground() const
217 {
218     return isExitSplitOnBackground_;
219 }
220 
NotifyClientToUpdateInteractive(bool interactive)221 void MainSession::NotifyClientToUpdateInteractive(bool interactive)
222 {
223     if (!sessionStage_) {
224         return;
225     }
226     const auto state = GetSessionState();
227     if (state == SessionState::STATE_ACTIVE || state == SessionState::STATE_FOREGROUND) {
228         WLOGFI("%{public}d", interactive);
229         sessionStage_->NotifyForegroundInteractiveStatus(interactive);
230         isClientInteractive_ = interactive;
231     }
232 }
233 
OnTitleAndDockHoverShowChange(bool isTitleHoverShown,bool isDockHoverShown)234 WSError MainSession::OnTitleAndDockHoverShowChange(bool isTitleHoverShown, bool isDockHoverShown)
235 {
236     const char* const funcName = __func__;
237     auto task = [weakThis = wptr(this), isTitleHoverShown, isDockHoverShown, funcName] {
238         auto session = weakThis.promote();
239         if (!session) {
240             TLOGNE(WmsLogTag::WMS_IMMS, "%{public}s session is null", funcName);
241             return;
242         }
243         TLOGNI(WmsLogTag::WMS_IMMS, "%{public}s isTitleHoverShown: %{public}d, isDockHoverShown: %{public}d", funcName,
244             isTitleHoverShown, isDockHoverShown);
245         if (session->onTitleAndDockHoverShowChangeFunc_) {
246             session->onTitleAndDockHoverShowChangeFunc_(isTitleHoverShown, isDockHoverShown);
247         }
248     };
249     PostTask(task, funcName);
250     return WSError::WS_OK;
251 }
252 
OnRestoreMainWindow()253 WSError MainSession::OnRestoreMainWindow()
254 {
255     auto task = [weakThis = wptr(this)] {
256         auto session = weakThis.promote();
257         if (!session) {
258             TLOGNE(WmsLogTag::WMS_LIFE, "session is null");
259             return;
260         }
261         if (session->onRestoreMainWindowFunc_) {
262             session->onRestoreMainWindowFunc_();
263         }
264     };
265     PostTask(task, __func__);
266     return WSError::WS_OK;
267 }
268 
OnSetWindowRectAutoSave(bool enabled)269 WSError MainSession::OnSetWindowRectAutoSave(bool enabled)
270 {
271     auto task = [weakThis = wptr(this), enabled] {
272         auto session = weakThis.promote();
273         if (!session) {
274             TLOGNE(WmsLogTag::WMS_MAIN, "session is null");
275             return;
276         }
277         if (session->onSetWindowRectAutoSaveFunc_) {
278             session->onSetWindowRectAutoSaveFunc_(enabled);
279         }
280     };
281     PostTask(task, __func__);
282     return WSError::WS_OK;
283 }
284 
NotifyMainModalTypeChange(bool isModal)285 WSError MainSession::NotifyMainModalTypeChange(bool isModal)
286 {
287     const char* const where = __func__;
288     PostTask([weakThis = wptr(this), isModal, where] {
289         auto session = weakThis.promote();
290         if (!session) {
291             TLOGNE(WmsLogTag::WMS_LIFE, "%{public}s session is null", where);
292             return;
293         }
294         TLOGNI(WmsLogTag::WMS_HIERARCHY, "%{public}s main window isModal:%{public}d", where, isModal);
295         if (session->onMainModalTypeChange_) {
296             session->onMainModalTypeChange_(isModal);
297         }
298     }, __func__);
299     return WSError::WS_OK;
300 }
301 
IsModal() const302 bool MainSession::IsModal() const
303 {
304     return WindowHelper::IsModalMainWindow(GetSessionProperty()->GetWindowType(),
305                                            GetSessionProperty()->GetWindowFlags());
306 }
307 
IsApplicationModal() const308 bool MainSession::IsApplicationModal() const
309 {
310     return IsModal();
311 }
312 } // namespace OHOS::Rosen
313