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/scb_system_session.h"
17 
18 #include <hisysevent.h>
19 #include "key_event.h"
20 #include "pointer_event.h"
21 #include <ui/rs_surface_node.h>
22 #include "window_manager_hilog.h"
23 
24 namespace OHOS::Rosen {
25 namespace {
26 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "SCBSystemSession" };
27 } // namespace
28 
SCBSystemSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)29 SCBSystemSession::SCBSystemSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback)
30     : SceneSession(info, specificCallback)
31 {
32     auto name = sessionInfo_.bundleName_;
33     auto pos = name.find_last_of('.');
34     name = (pos == std::string::npos) ? name : name.substr(pos + 1); // skip '.'
35     if (sessionInfo_.isSystem_) {
36         RSSurfaceNodeConfig config;
37         config.SurfaceNodeName = name;
38         config.surfaceWindowType = SurfaceWindowType::SYSTEM_SCB_WINDOW;
39         surfaceNode_ = Rosen::RSSurfaceNode::Create(config, Rosen::RSSurfaceNodeType::APP_WINDOW_NODE);
40     }
41     WLOGFD("Create SCBSystemSession");
42 }
43 
~SCBSystemSession()44 SCBSystemSession::~SCBSystemSession()
45 {
46     WLOGD("~SCBSystemSession, id: %{public}d", GetPersistentId());
47 }
48 
ProcessPointDownSession(int32_t posX, int32_t posY)49 WSError SCBSystemSession::ProcessPointDownSession(int32_t posX, int32_t posY)
50 {
51     const auto& id = GetPersistentId();
52     const auto& type = GetWindowType();
53     WLOGFI("id: %{public}d, type: %{public}d", id, type);
54     PresentFocusIfPointDown();
55     return SceneSession::ProcessPointDownSession(posX, posY);
56 }
57 
NotifyClientToUpdateRect(const std::string& updateReason, std::shared_ptr<RSTransaction> rsTransaction)58 WSError SCBSystemSession::NotifyClientToUpdateRect(const std::string& updateReason,
59     std::shared_ptr<RSTransaction> rsTransaction)
60 {
61     auto task = [weakThis = wptr(this), rsTransaction, updateReason]() {
62         auto session = weakThis.promote();
63         if (!session) {
64             WLOGFE("session is null");
65             return WSError::WS_ERROR_DESTROYED_OBJECT;
66         }
67         WSError ret = session->NotifyClientToUpdateRectTask(updateReason, rsTransaction);
68         if (session->specificCallback_ != nullptr && session->specificCallback_->onUpdateAvoidArea_ != nullptr &&
69             session->specificCallback_->onClearDisplayStatusBarTemporarilyFlags_ != nullptr) {
70             if (Session::IsScbCoreEnabled()) {
71                 session->dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::AVOID_AREA);
72             } else {
73                 session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId());
74             }
75             session->specificCallback_->onClearDisplayStatusBarTemporarilyFlags_();
76         }
77         if (session->GetWindowType() == WindowType::WINDOW_TYPE_KEYBOARD_PANEL &&
78             session->keyboardPanelRectUpdateCallback_ && session->isKeyboardPanelEnabled_) {
79             session->keyboardPanelRectUpdateCallback_();
80         }
81         // clear after use
82         if (session->reason_ != SizeChangeReason::DRAG) {
83             session->reason_ = SizeChangeReason::UNDEFINED;
84             session->dirtyFlags_ &= ~static_cast<uint32_t>(SessionUIDirtyFlag::RECT);
85         }
86         return ret;
87     };
88     PostTask(task, "NotifyClientToUpdateRect");
89     return WSError::WS_OK;
90 }
91 
SetKeyboardPanelRectUpdateCallback(const KeyboardPanelRectUpdateCallback& func)92 void SCBSystemSession::SetKeyboardPanelRectUpdateCallback(const KeyboardPanelRectUpdateCallback& func)
93 {
94     keyboardPanelRectUpdateCallback_ = func;
95 }
96 
BindKeyboardSession(sptr<SceneSession> session)97 void SCBSystemSession::BindKeyboardSession(sptr<SceneSession> session)
98 {
99     if (session == nullptr) {
100         TLOGE(WmsLogTag::WMS_KEYBOARD, "session is nullptr");
101         return;
102     }
103     keyboardSession_ = session;
104     KeyboardPanelRectUpdateCallback onKeyboardPanelRectUpdate = [this]() {
105         if (this->keyboardSession_ != nullptr) {
106             this->keyboardSession_->OnKeyboardPanelUpdated();
107         }
108     };
109     SetKeyboardPanelRectUpdateCallback(onKeyboardPanelRectUpdate);
110     TLOGI(WmsLogTag::WMS_KEYBOARD, "Success, id: %{public}d", keyboardSession_->GetPersistentId());
111 }
112 
GetKeyboardSession() const113 sptr<SceneSession> SCBSystemSession::GetKeyboardSession() const
114 {
115     return keyboardSession_;
116 }
117 
PresentFocusIfPointDown()118 void SCBSystemSession::PresentFocusIfPointDown()
119 {
120     WLOGFI("PresentFocusIfPointDown, id: %{public}d, type: %{public}d", GetPersistentId(), GetWindowType());
121     if (!isFocused_ && GetFocusable()) {
122         FocusChangeReason reason = FocusChangeReason::CLICK;
123         NotifyRequestFocusStatusNotifyManager(true, false, reason);
124         NotifyClick();
125     }
126 }
127 
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)128 WSError SCBSystemSession::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
129 {
130     if (keyEvent == nullptr) {
131         WLOGFE("KeyEvent is nullptr");
132         return WSError::WS_ERROR_NULLPTR;
133     }
134 
135     WSError ret = Session::TransferKeyEvent(keyEvent);
136     return ret;
137 }
138 
PresentFoucusIfNeed(int32_t pointerAction)139 void SCBSystemSession::PresentFoucusIfNeed(int32_t pointerAction)
140 {
141     WLOGFD("OnClick down, id: %{public}d", GetPersistentId());
142     if (pointerAction == MMI::PointerEvent::POINTER_ACTION_DOWN ||
143         pointerAction == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
144         if (!isFocused_ && GetFocusable()) {
145             FocusChangeReason reason = FocusChangeReason::CLICK;
146             NotifyRequestFocusStatusNotifyManager(true, false, reason);
147             NotifyClick();
148         }
149     }
150 }
151 
UpdateFocus(bool isFocused)152 WSError SCBSystemSession::UpdateFocus(bool isFocused)
153 {
154     if (isFocused_ == isFocused) {
155         TLOGD(WmsLogTag::WMS_FOCUS, "Session focus do not change");
156         return WSError::WS_DO_NOTHING;
157     }
158     isFocused_ = isFocused;
159     // notify scb arkui focus
160     if (isFocused) {
161         HiSysEventWrite(
162             OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
163             "FOCUS_WINDOW",
164             OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
165             "PID", getpid(),
166             "UID", getuid(),
167             "BUNDLE_NAME", sessionInfo_.bundleName_);
168         NotifyUIRequestFocus();
169     } else {
170         NotifyUILostFocus();
171     }
172     return WSError::WS_OK;
173 }
174 
UpdateWindowMode(WindowMode mode)175 WSError SCBSystemSession::UpdateWindowMode(WindowMode mode)
176 {
177     WLOGFD("session is system, id: %{public}d, mode: %{public}d, name: %{public}s, state: %{public}u",
178         GetPersistentId(), static_cast<int32_t>(mode), sessionInfo_.bundleName_.c_str(), GetSessionState());
179     return WSError::WS_ERROR_INVALID_SESSION;
180 }
181 
SetSystemSceneBlockingFocus(bool blocking)182 WSError SCBSystemSession::SetSystemSceneBlockingFocus(bool blocking)
183 {
184     TLOGD(WmsLogTag::WMS_FOCUS, "Session set blocking focus, id: %{public}d, mode: %{public}d",
185         GetPersistentId(), blocking);
186     blockingFocus_ = blocking;
187     return WSError::WS_OK;
188 }
189 
UpdatePointerArea(const WSRect& rect)190 void SCBSystemSession::UpdatePointerArea(const WSRect& rect)
191 {
192     // scb system session do nothing
193     return;
194 }
195 
SetSkipSelfWhenShowOnVirtualScreen(bool isSkip)196 void SCBSystemSession::SetSkipSelfWhenShowOnVirtualScreen(bool isSkip)
197 {
198     TLOGD(WmsLogTag::WMS_SCB, "Set Skip Self, isSkip: %{public}d", isSkip);
199     auto task = [weakThis = wptr(this), isSkip]() {
200         auto session = weakThis.promote();
201         if (!session) {
202             TLOGE(WmsLogTag::WMS_SCB, "session is null");
203             return WSError::WS_ERROR_DESTROYED_OBJECT;
204         }
205         std::shared_ptr<RSSurfaceNode> surfaceNode = session->GetSurfaceNode();
206         if (!surfaceNode) {
207             TLOGE(WmsLogTag::WMS_SCB, "surfaceNode_ is null");
208             return WSError::WS_OK;
209         }
210         if (session->specificCallback_ != nullptr
211             && session->specificCallback_->onSetSkipSelfWhenShowOnVirtualScreen_ != nullptr) {
212             session->specificCallback_->onSetSkipSelfWhenShowOnVirtualScreen_(surfaceNode->GetId(), isSkip);
213         }
214         return WSError::WS_OK;
215     };
216     PostTask(task, "SetSkipSelf");
217 }
218 
GetSurfaceNode()219 std::shared_ptr<RSSurfaceNode> SCBSystemSession::GetSurfaceNode()
220 {
221     if (!surfaceNode_) {
222         TLOGE(WmsLogTag::WMS_SCB, "surfaceNode_ is null");
223         return nullptr;
224     }
225     return surfaceNode_;
226 }
227 
IsVisibleForeground() const228 bool SCBSystemSession::IsVisibleForeground() const
229 {
230     return isVisible_;
231 }
232 
NotifyClientToUpdateAvoidArea()233 void SCBSystemSession::NotifyClientToUpdateAvoidArea()
234 {
235     SceneSession::NotifyClientToUpdateAvoidArea();
236     if (GetWindowType() == WindowType::WINDOW_TYPE_KEYBOARD_PANEL &&
237         keyboardPanelRectUpdateCallback_ && isKeyboardPanelEnabled_) {
238         keyboardPanelRectUpdateCallback_();
239     }
240 }
241 
SyncScenePanelGlobalPosition(bool needSync)242 void SCBSystemSession::SyncScenePanelGlobalPosition(bool needSync)
243 {
244     TLOGI(WmsLogTag::WMS_PIPELINE, "change isNeedSyncGlobalPos from %{public}d to %{public}d",
245         isNeedSyncGlobalPos_, needSync);
246     isNeedSyncGlobalPos_ = needSync;
247 }
248 } // namespace OHOS::Rosen
249