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
RegisterBufferAvailableCallback(const SystemSessionBufferAvailableCallback & func)49 void SCBSystemSession::RegisterBufferAvailableCallback(const SystemSessionBufferAvailableCallback& func)
50 {
51 if (surfaceNode_) {
52 TLOGI(WmsLogTag::WMS_MULTI_USER, "Set buffer available callback");
53 surfaceNode_->SetBufferAvailableCallback(func);
54 } else {
55 TLOGE(WmsLogTag::WMS_MULTI_USER, "surfaceNode_ is null");
56 }
57 }
58
ProcessPointDownSession(int32_t posX,int32_t posY)59 WSError SCBSystemSession::ProcessPointDownSession(int32_t posX, int32_t posY)
60 {
61 const auto& id = GetPersistentId();
62 const auto& type = GetWindowType();
63 WLOGFI("id: %{public}d, type: %{public}d", id, type);
64 PresentFocusIfPointDown();
65 return SceneSession::ProcessPointDownSession(posX, posY);
66 }
67
NotifyClientToUpdateRect(const std::string & updateReason,std::shared_ptr<RSTransaction> rsTransaction)68 WSError SCBSystemSession::NotifyClientToUpdateRect(const std::string& updateReason,
69 std::shared_ptr<RSTransaction> rsTransaction)
70 {
71 auto task = [weakThis = wptr(this), rsTransaction, updateReason]() {
72 auto session = weakThis.promote();
73 if (!session) {
74 WLOGFE("session is null");
75 return WSError::WS_ERROR_DESTROYED_OBJECT;
76 }
77 WSError ret = session->NotifyClientToUpdateRectTask(updateReason, rsTransaction);
78 if (session->specificCallback_ != nullptr && session->specificCallback_->onUpdateAvoidArea_ != nullptr &&
79 session->specificCallback_->onClearDisplayStatusBarTemporarilyFlags_ != nullptr) {
80 if (Session::IsScbCoreEnabled()) {
81 session->dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::AVOID_AREA);
82 } else {
83 session->specificCallback_->onUpdateAvoidArea_(session->GetPersistentId());
84 }
85 session->specificCallback_->onClearDisplayStatusBarTemporarilyFlags_();
86 }
87 if (session->GetWindowType() == WindowType::WINDOW_TYPE_KEYBOARD_PANEL &&
88 session->keyboardPanelRectUpdateCallback_ && session->isKeyboardPanelEnabled_) {
89 session->keyboardPanelRectUpdateCallback_();
90 }
91 return ret;
92 };
93 PostTask(task, "NotifyClientToUpdateRect");
94 return WSError::WS_OK;
95 }
96
SetKeyboardPanelRectUpdateCallback(const KeyboardPanelRectUpdateCallback & func)97 void SCBSystemSession::SetKeyboardPanelRectUpdateCallback(const KeyboardPanelRectUpdateCallback& func)
98 {
99 keyboardPanelRectUpdateCallback_ = func;
100 }
101
BindKeyboardSession(sptr<SceneSession> session)102 void SCBSystemSession::BindKeyboardSession(sptr<SceneSession> session)
103 {
104 if (session == nullptr) {
105 TLOGE(WmsLogTag::WMS_KEYBOARD, "session is nullptr");
106 return;
107 }
108 keyboardSession_ = session;
109 KeyboardPanelRectUpdateCallback onKeyboardPanelRectUpdate = [this]() {
110 if (this->keyboardSession_ != nullptr) {
111 this->keyboardSession_->OnKeyboardPanelUpdated();
112 }
113 };
114 SetKeyboardPanelRectUpdateCallback(onKeyboardPanelRectUpdate);
115 TLOGI(WmsLogTag::WMS_KEYBOARD, "Success, id: %{public}d", keyboardSession_->GetPersistentId());
116 }
117
GetKeyboardSession() const118 sptr<SceneSession> SCBSystemSession::GetKeyboardSession() const
119 {
120 return keyboardSession_;
121 }
122
PresentFocusIfPointDown()123 void SCBSystemSession::PresentFocusIfPointDown()
124 {
125 WLOGFI("PresentFocusIfPointDown, id: %{public}d, type: %{public}d", GetPersistentId(), GetWindowType());
126 if (!isFocused_ && GetFocusable()) {
127 FocusChangeReason reason = FocusChangeReason::CLICK;
128 NotifyRequestFocusStatusNotifyManager(true, false, reason);
129 NotifyClick();
130 }
131 }
132
TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent> & keyEvent)133 WSError SCBSystemSession::TransferKeyEvent(const std::shared_ptr<MMI::KeyEvent>& keyEvent)
134 {
135 if (keyEvent == nullptr) {
136 WLOGFE("KeyEvent is nullptr");
137 return WSError::WS_ERROR_NULLPTR;
138 }
139
140 WSError ret = Session::TransferKeyEvent(keyEvent);
141 return ret;
142 }
143
PresentFoucusIfNeed(int32_t pointerAction)144 void SCBSystemSession::PresentFoucusIfNeed(int32_t pointerAction)
145 {
146 WLOGFD("OnClick down, id: %{public}d", GetPersistentId());
147 if (pointerAction == MMI::PointerEvent::POINTER_ACTION_DOWN ||
148 pointerAction == MMI::PointerEvent::POINTER_ACTION_BUTTON_DOWN) {
149 if (!isFocused_ && GetFocusable()) {
150 FocusChangeReason reason = FocusChangeReason::CLICK;
151 NotifyRequestFocusStatusNotifyManager(true, false, reason);
152 NotifyClick();
153 }
154 }
155 }
156
UpdateFocus(bool isFocused)157 WSError SCBSystemSession::UpdateFocus(bool isFocused)
158 {
159 if (isFocused_ == isFocused) {
160 TLOGD(WmsLogTag::WMS_FOCUS, "Session focus do not change");
161 return WSError::WS_DO_NOTHING;
162 }
163 isFocused_ = isFocused;
164 // notify scb arkui focus
165 if (isFocused) {
166 HiSysEventWrite(
167 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
168 "FOCUS_WINDOW",
169 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
170 "PID", getpid(),
171 "UID", getuid(),
172 "BUNDLE_NAME", sessionInfo_.bundleName_);
173 NotifyUIRequestFocus();
174 } else {
175 NotifyUILostFocus();
176 }
177 return WSError::WS_OK;
178 }
179
UpdateWindowMode(WindowMode mode)180 WSError SCBSystemSession::UpdateWindowMode(WindowMode mode)
181 {
182 WLOGFD("session is system, id: %{public}d, mode: %{public}d, name: %{public}s, state: %{public}u",
183 GetPersistentId(), static_cast<int32_t>(mode), sessionInfo_.bundleName_.c_str(), GetSessionState());
184 return WSError::WS_ERROR_INVALID_SESSION;
185 }
186
SetSystemSceneBlockingFocus(bool blocking)187 WSError SCBSystemSession::SetSystemSceneBlockingFocus(bool blocking)
188 {
189 TLOGD(WmsLogTag::WMS_FOCUS, "Session set blocking focus, id: %{public}d, mode: %{public}d",
190 GetPersistentId(), blocking);
191 blockingFocus_ = blocking;
192 return WSError::WS_OK;
193 }
194
UpdatePointerArea(const WSRect & rect)195 void SCBSystemSession::UpdatePointerArea(const WSRect& rect)
196 {
197 // scb system session do nothing
198 return;
199 }
200
SetSkipSelfWhenShowOnVirtualScreen(bool isSkip)201 void SCBSystemSession::SetSkipSelfWhenShowOnVirtualScreen(bool isSkip)
202 {
203 TLOGD(WmsLogTag::WMS_SCB, "Set Skip Self, isSkip: %{public}d", isSkip);
204 auto task = [weakThis = wptr(this), isSkip]() {
205 auto session = weakThis.promote();
206 if (!session) {
207 TLOGE(WmsLogTag::WMS_SCB, "session is null");
208 return WSError::WS_ERROR_DESTROYED_OBJECT;
209 }
210 std::shared_ptr<RSSurfaceNode> surfaceNode = session->GetSurfaceNode();
211 if (!surfaceNode) {
212 TLOGE(WmsLogTag::WMS_SCB, "surfaceNode_ is null");
213 return WSError::WS_OK;
214 }
215 if (session->specificCallback_ != nullptr
216 && session->specificCallback_->onSetSkipSelfWhenShowOnVirtualScreen_ != nullptr) {
217 session->specificCallback_->onSetSkipSelfWhenShowOnVirtualScreen_(surfaceNode->GetId(), isSkip);
218 }
219 return WSError::WS_OK;
220 };
221 PostTask(task, "SetSkipSelf");
222 }
223
GetSurfaceNode()224 std::shared_ptr<RSSurfaceNode> SCBSystemSession::GetSurfaceNode()
225 {
226 if (!surfaceNode_) {
227 TLOGE(WmsLogTag::WMS_SCB, "surfaceNode_ is null");
228 return nullptr;
229 }
230 return surfaceNode_;
231 }
232
IsVisibleForeground() const233 bool SCBSystemSession::IsVisibleForeground() const
234 {
235 return isVisible_;
236 }
237
NotifyClientToUpdateAvoidArea()238 void SCBSystemSession::NotifyClientToUpdateAvoidArea()
239 {
240 SceneSession::NotifyClientToUpdateAvoidArea();
241 if (GetWindowType() == WindowType::WINDOW_TYPE_KEYBOARD_PANEL &&
242 keyboardPanelRectUpdateCallback_ && isKeyboardPanelEnabled_) {
243 keyboardPanelRectUpdateCallback_();
244 }
245 }
246
SyncScenePanelGlobalPosition(bool needSync)247 void SCBSystemSession::SyncScenePanelGlobalPosition(bool needSync)
248 {
249 TLOGI(WmsLogTag::WMS_PIPELINE, "change isNeedSyncGlobalPos from %{public}d to %{public}d",
250 isNeedSyncGlobalPos_, needSync);
251 if (isNeedSyncGlobalPos_ != needSync) {
252 isNeedSyncGlobalPos_ = needSync;
253 }
254 }
255 } // namespace OHOS::Rosen
256