1 /*
2 * Copyright (c) 2024 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/keyboard_session.h"
17 #include "session/host/include/session.h"
18 #include "common/include/session_permission.h"
19 #include "display_manager.h"
20 #include "screen_session_manager/include/screen_session_manager_client.h"
21 #include "session_helper.h"
22 #include <parameters.h>
23 #include "window_helper.h"
24 #include "window_manager_hilog.h"
25
26 namespace OHOS::Rosen {
27
KeyboardSession(const SessionInfo & info,const sptr<SpecificSessionCallback> & specificCallback,const sptr<KeyboardSessionCallback> & keyboardCallback)28 KeyboardSession::KeyboardSession(const SessionInfo& info, const sptr<SpecificSessionCallback>& specificCallback,
29 const sptr<KeyboardSessionCallback>& keyboardCallback)
30 : SystemSession(info, specificCallback)
31 {
32 keyboardCallback_ = keyboardCallback;
33 TLOGI(WmsLogTag::WMS_KEYBOARD, "Create KeyboardSession");
34 }
35
~KeyboardSession()36 KeyboardSession::~KeyboardSession()
37 {
38 TLOGI(WmsLogTag::WMS_KEYBOARD, "~KeyboardSession");
39 }
40
BindKeyboardPanelSession(sptr<SceneSession> panelSession)41 void KeyboardSession::BindKeyboardPanelSession(sptr<SceneSession> panelSession)
42 {
43 if (panelSession == nullptr) {
44 TLOGE(WmsLogTag::WMS_KEYBOARD, "panelSession is nullptr");
45 return;
46 }
47 keyboardPanelSession_ = panelSession;
48 TLOGI(WmsLogTag::WMS_KEYBOARD, "Success, panelId: %{public}d", panelSession->GetPersistentId());
49 }
50
GetKeyboardPanelSession() const51 sptr<SceneSession> KeyboardSession::GetKeyboardPanelSession() const
52 {
53 return keyboardPanelSession_;
54 }
55
GetKeyboardGravity() const56 SessionGravity KeyboardSession::GetKeyboardGravity() const
57 {
58 SessionGravity gravity = SessionGravity::SESSION_GRAVITY_DEFAULT;
59 auto sessionProperty = GetSessionProperty();
60 if (sessionProperty) {
61 gravity = static_cast<SessionGravity>(sessionProperty->GetKeyboardLayoutParams().gravity_);
62 }
63 TLOGI(WmsLogTag::WMS_KEYBOARD, "gravity: %{public}d", gravity);
64 return gravity;
65 }
66
Show(sptr<WindowSessionProperty> property)67 WSError KeyboardSession::Show(sptr<WindowSessionProperty> property)
68 {
69 if (property == nullptr) {
70 TLOGE(WmsLogTag::WMS_KEYBOARD, "Session property is null");
71 return WSError::WS_ERROR_NULLPTR;
72 }
73 if (!CheckPermissionWithPropertyAnimation(property)) {
74 return WSError::WS_ERROR_NOT_SYSTEM_APP;
75 }
76 auto task = [weakThis = wptr(this), property]() {
77 auto session = weakThis.promote();
78 if (!session) {
79 TLOGE(WmsLogTag::WMS_KEYBOARD, "Session is null, show keyboard failed");
80 return WSError::WS_ERROR_DESTROYED_OBJECT;
81 }
82 session->UseFocusIdIfCallingSessionIdInvalid();
83 TLOGI(WmsLogTag::WMS_KEYBOARD, "Show keyboard session, id: %{public}d, calling session id: %{public}d",
84 session->GetPersistentId(), session->GetCallingSessionId());
85 session->MoveAndResizeKeyboard(property->GetKeyboardLayoutParams(), property, true);
86 session->NotifySessionRectChange(session->GetSessionRequestRect(), SizeChangeReason::UNDEFINED);
87 return session->SceneSession::Foreground(property);
88 };
89 PostTask(task, "Show");
90 return WSError::WS_OK;
91 }
92
Hide()93 WSError KeyboardSession::Hide()
94 {
95 if (!CheckPermissionWithPropertyAnimation(GetSessionProperty())) {
96 return WSError::WS_ERROR_NOT_SYSTEM_APP;
97 }
98 auto task = [weakThis = wptr(this)]() {
99 auto session = weakThis.promote();
100 if (!session) {
101 TLOGE(WmsLogTag::WMS_KEYBOARD, "Session is null, hide keyboard failed!");
102 return WSError::WS_ERROR_DESTROYED_OBJECT;
103 }
104
105 TLOGI(WmsLogTag::WMS_KEYBOARD, "Hide keyboard session, set callingSessionId to 0, id: %{public}d",
106 session->GetPersistentId());
107 auto ret = session->SetActive(false);
108 if (ret != WSError::WS_OK) {
109 TLOGE(WmsLogTag::WMS_KEYBOARD, "Set session active state failed, ret: %{public}d", ret);
110 return ret;
111 }
112 ret = session->SceneSession::Background();
113 WSRect rect = {0, 0, 0, 0};
114 session->NotifyKeyboardPanelInfoChange(rect, false);
115 if (session->systemConfig_.uiType_ == UI_TYPE_PC || session->GetSessionScreenName() == "HiCar"
116 || session->GetSessionScreenName() == "SuperLauncher") {
117 TLOGD(WmsLogTag::WMS_KEYBOARD, "pc or virtual screen, restore calling session");
118 session->RestoreCallingSession();
119 auto sessionProperty = session->GetSessionProperty();
120 if (sessionProperty) {
121 sessionProperty->SetCallingSessionId(INVALID_WINDOW_ID);
122 }
123 }
124 return ret;
125 };
126 PostTask(task, "Hide");
127 return WSError::WS_OK;
128 }
129
Disconnect(bool isFromClient,const std::string & identityToken)130 WSError KeyboardSession::Disconnect(bool isFromClient, const std::string& identityToken)
131 {
132 auto task = [weakThis = wptr(this), isFromClient]() {
133 auto session = weakThis.promote();
134 if (!session) {
135 TLOGE(WmsLogTag::WMS_KEYBOARD, "Session is null, disconnect keyboard session failed!");
136 return WSError::WS_ERROR_DESTROYED_OBJECT;
137 }
138 TLOGI(WmsLogTag::WMS_KEYBOARD, "Disconnect keyboard session, id: %{public}d, isFromClient: %{public}d",
139 session->GetPersistentId(), isFromClient);
140 session->SceneSession::Disconnect(isFromClient);
141 WSRect rect = {0, 0, 0, 0};
142 session->NotifyKeyboardPanelInfoChange(rect, false);
143 session->RestoreCallingSession();
144 auto sessionProperty = session->GetSessionProperty();
145 if (sessionProperty) {
146 sessionProperty->SetCallingSessionId(INVALID_WINDOW_ID);
147 }
148 return WSError::WS_OK;
149 };
150 PostTask(task, "Disconnect");
151 return WSError::WS_OK;
152 }
153
NotifyClientToUpdateRect(const std::string & updateReason,std::shared_ptr<RSTransaction> rsTransaction)154 WSError KeyboardSession::NotifyClientToUpdateRect(const std::string& updateReason,
155 std::shared_ptr<RSTransaction> rsTransaction)
156 {
157 auto task = [weakThis = wptr(this), rsTransaction, updateReason]() {
158 auto session = weakThis.promote();
159 if (!session) {
160 TLOGE(WmsLogTag::WMS_KEYBOARD, "session is null");
161 return WSError::WS_ERROR_DESTROYED_OBJECT;
162 }
163
164 WSError ret = session->NotifyClientToUpdateRectTask(updateReason, rsTransaction);
165 return ret;
166 };
167 PostTask(task, "NotifyClientToUpdateRect");
168 return WSError::WS_OK;
169 }
170
UpdateKeyboardAvoidArea()171 void KeyboardSession::UpdateKeyboardAvoidArea()
172 {
173 if (!IsSessionForeground() || (Session::IsScbCoreEnabled() && !IsVisibleForeground())) {
174 TLOGI(WmsLogTag::WMS_KEYBOARD, "Keyboard is not foreground, no need update avoid Area");
175 return;
176 }
177 if (specificCallback_ != nullptr && specificCallback_->onUpdateAvoidArea_ != nullptr) {
178 if (Session::IsScbCoreEnabled()) {
179 dirtyFlags_ |= static_cast<uint32_t>(SessionUIDirtyFlag::AVOID_AREA);
180 } else {
181 specificCallback_->onUpdateAvoidArea_(GetPersistentId());
182 }
183 }
184 }
185
OnKeyboardPanelUpdated()186 void KeyboardSession::OnKeyboardPanelUpdated()
187 {
188 TLOGI(WmsLogTag::WMS_KEYBOARD, "id: %{public}d", GetPersistentId());
189 WSRect panelRect = { 0, 0, 0, 0 };
190 panelRect = (keyboardPanelSession_ == nullptr) ? panelRect : keyboardPanelSession_->GetSessionRect();
191 RaiseCallingSession(panelRect, true);
192 UpdateKeyboardAvoidArea();
193 }
194
OnCallingSessionUpdated()195 void KeyboardSession::OnCallingSessionUpdated()
196 {
197 TLOGI(WmsLogTag::WMS_KEYBOARD, "id: %{public}d", GetPersistentId());
198 if (!IsSessionForeground() || (Session::IsScbCoreEnabled() && !IsVisibleForeground())) {
199 TLOGI(WmsLogTag::WMS_KEYBOARD, "Keyboard is not foreground.");
200 return;
201 }
202 WSRect panelRect = { 0, 0, 0, 0 };
203 panelRect = (keyboardPanelSession_ == nullptr) ? panelRect : keyboardPanelSession_->GetSessionRect();
204 sptr<SceneSession> callingSession = GetSceneSession(GetCallingSessionId());
205 if (callingSession == nullptr) {
206 TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session is nullptr");
207 return;
208 }
209 bool isCallingSessionFloating = (callingSession->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING);
210 if (!CheckIfNeedRaiseCallingSession(callingSession, isCallingSessionFloating)) {
211 return;
212 }
213 WSRect callingSessionRect = callingSession->GetSessionRect();
214 NotifyOccupiedAreaChangeInfo(callingSession, callingSessionRect, panelRect);
215
216 TLOGI(WmsLogTag::WMS_KEYBOARD, "callSession Rect: %{public}s", callingSessionRect.ToString().c_str());
217 }
218
SetKeyboardSessionGravity(SessionGravity gravity)219 WSError KeyboardSession::SetKeyboardSessionGravity(SessionGravity gravity)
220 {
221 TLOGI(WmsLogTag::WMS_KEYBOARD, "keyboardId: %{public}d, gravity: %{public}d", GetPersistentId(), gravity);
222 if (keyboardGravityChangeFunc_) {
223 keyboardGravityChangeFunc_(gravity);
224 }
225 RelayoutKeyBoard();
226 if (gravity == SessionGravity::SESSION_GRAVITY_FLOAT) {
227 SetWindowAnimationFlag(false);
228 if (IsSessionForeground()) {
229 RestoreCallingSession();
230 }
231 } else {
232 SetWindowAnimationFlag(true);
233 }
234 return WSError::WS_OK;
235 }
236
SetCallingSessionId(uint32_t callingSessionId)237 void KeyboardSession::SetCallingSessionId(uint32_t callingSessionId)
238 {
239 auto task = [weakThis = wptr(this), callingSessionId]() mutable {
240 auto session = weakThis.promote();
241 if (!session) {
242 TLOGE(WmsLogTag::WMS_KEYBOARD, "session is null");
243 return;
244 }
245 if (session->GetSceneSession(callingSessionId) == nullptr) {
246 uint32_t focusedSessionId = static_cast<uint32_t>(session->GetFocusedSessionId());
247 if (session->GetSceneSession(focusedSessionId) == nullptr) {
248 TLOGE(WmsLogTag::WMS_KEYBOARD, "Focused session is null, set id: %{public}d failed", focusedSessionId);
249 return;
250 } else {
251 TLOGI(WmsLogTag::WMS_KEYBOARD, "Using focusedSession id: %{public}d", focusedSessionId);
252 callingSessionId = focusedSessionId;
253 }
254 }
255 uint32_t curCallingSessionId = session->GetCallingSessionId();
256 TLOGI(WmsLogTag::WMS_KEYBOARD, "curId: %{public}d, newId: %{public}d", curCallingSessionId, callingSessionId);
257 auto sessionProperty = session->GetSessionProperty();
258 if (sessionProperty != nullptr) {
259 if (curCallingSessionId != INVALID_WINDOW_ID && callingSessionId != curCallingSessionId &&
260 session->IsSessionForeground()) {
261 session->MoveAndResizeKeyboard(sessionProperty->GetKeyboardLayoutParams(), sessionProperty, true);
262 session->NotifySessionRectChange(session->GetSessionRequestRect(), SizeChangeReason::UNDEFINED);
263
264 session->UpdateCallingSessionIdAndPosition(callingSessionId);
265 } else {
266 sessionProperty->SetCallingSessionId(callingSessionId);
267 }
268 }
269 if (session->keyboardCallback_ == nullptr ||
270 session->keyboardCallback_->onCallingSessionIdChange_ == nullptr) {
271 TLOGE(WmsLogTag::WMS_KEYBOARD, "KeyboardCallback_, callingSessionId: %{public}d", callingSessionId);
272 return;
273 }
274 session->keyboardCallback_->onCallingSessionIdChange_(callingSessionId);
275 };
276 PostTask(task, "SetCallingSessionId");
277 return;
278 }
279
GetCallingSessionId()280 uint32_t KeyboardSession::GetCallingSessionId()
281 {
282 auto sessionProperty = GetSessionProperty();
283 if (sessionProperty == nullptr) {
284 TLOGE(WmsLogTag::WMS_KEYBOARD, "Session property is null");
285 return INVALID_SESSION_ID;
286 }
287 return sessionProperty->GetCallingSessionId();
288 }
289
AdjustKeyboardLayout(const KeyboardLayoutParams & params)290 WSError KeyboardSession::AdjustKeyboardLayout(const KeyboardLayoutParams& params)
291 {
292 auto task = [weakThis = wptr(this), params]() -> WSError {
293 auto session = weakThis.promote();
294 if (!session) {
295 TLOGE(WmsLogTag::WMS_KEYBOARD, "keyboard session is null");
296 return WSError::WS_ERROR_DESTROYED_OBJECT;
297 }
298 auto sessionProperty = session->GetSessionProperty();
299 if (sessionProperty == nullptr) {
300 TLOGE(WmsLogTag::WMS_KEYBOARD, "Session property is null");
301 return WSError::WS_ERROR_NULLPTR;
302 }
303 sessionProperty->SetKeyboardLayoutParams(params);
304 session->MoveAndResizeKeyboard(params, sessionProperty, false);
305 session->SetKeyboardSessionGravity(static_cast<SessionGravity>(params.gravity_));
306 if (session->adjustKeyboardLayoutFunc_) {
307 session->adjustKeyboardLayoutFunc_(params);
308 }
309 session->NotifySessionRectChange(session->GetSessionRequestRect(), SizeChangeReason::UNDEFINED);
310 TLOGI(WmsLogTag::WMS_KEYBOARD, "adjust keyboard layout, keyboardId: %{public}d, gravity: %{public}u, "
311 "LandscapeKeyboardRect: %{public}s, PortraitKeyboardRect: %{public}s, LandscapePanelRect: %{public}s, "
312 "PortraitPanelRect: %{public}s, requestRect: %{public}s", session->GetPersistentId(),
313 static_cast<uint32_t>(params.gravity_), params.LandscapeKeyboardRect_.ToString().c_str(),
314 params.PortraitKeyboardRect_.ToString().c_str(), params.LandscapePanelRect_.ToString().c_str(),
315 params.PortraitPanelRect_.ToString().c_str(), session->GetSessionRequestRect().ToString().c_str());
316 return WSError::WS_OK;
317 };
318 PostTask(task, "AdjustKeyboardLayout");
319 return WSError::WS_OK;
320 }
321
GetSceneSession(uint32_t persistentId)322 sptr<SceneSession> KeyboardSession::GetSceneSession(uint32_t persistentId)
323 {
324 if (keyboardCallback_ == nullptr || keyboardCallback_->onGetSceneSession_ == nullptr) {
325 TLOGE(WmsLogTag::WMS_KEYBOARD, "Get scene session failed, persistentId: %{public}d", persistentId);
326 return nullptr;
327 }
328 return keyboardCallback_->onGetSceneSession_(persistentId);
329 }
330
GetFocusedSessionId()331 int32_t KeyboardSession::GetFocusedSessionId()
332 {
333 if (keyboardCallback_ == nullptr || keyboardCallback_->onGetFocusedSessionId_ == nullptr) {
334 TLOGE(WmsLogTag::WMS_KEYBOARD, "keyboardCallback_ is nullptr, get focusedSessionId failed!");
335 return INVALID_WINDOW_ID;
336 }
337 return keyboardCallback_->onGetFocusedSessionId_();
338 }
339
GetStatusBarHeight()340 int32_t KeyboardSession::GetStatusBarHeight()
341 {
342 int32_t statusBarHeight = 0;
343 auto sessionProperty = GetSessionProperty();
344 if (specificCallback_ == nullptr || specificCallback_->onGetSceneSessionVectorByType_ == nullptr ||
345 sessionProperty == nullptr) {
346 TLOGE(WmsLogTag::WMS_KEYBOARD, "keyboardCallback_ or session property is null, get statusBarHeight failed!");
347 return statusBarHeight;
348 }
349
350 std::vector<sptr<SceneSession>> statusBarVector = specificCallback_->onGetSceneSessionVectorByType_(
351 WindowType::WINDOW_TYPE_STATUS_BAR, GetSessionProperty()->GetDisplayId());
352 for (const auto& statusBar : statusBarVector) {
353 if (statusBar != nullptr && statusBar->GetSessionRect().height_ > statusBarHeight) {
354 statusBarHeight = statusBar->GetSessionRect().height_;
355 }
356 }
357 TLOGI(WmsLogTag::WMS_KEYBOARD, "Status Bar height: %{public}d", statusBarHeight);
358 return statusBarHeight;
359 }
360
NotifyOccupiedAreaChangeInfo(const sptr<SceneSession> & callingSession,const WSRect & rect,const WSRect & occupiedArea,const std::shared_ptr<RSTransaction> & rsTransaction)361 void KeyboardSession::NotifyOccupiedAreaChangeInfo(const sptr<SceneSession>& callingSession, const WSRect& rect,
362 const WSRect& occupiedArea, const std::shared_ptr<RSTransaction>& rsTransaction)
363 {
364 // if keyboard will occupy calling, notify calling window the occupied area and safe height
365 const WSRect& safeRect = SessionHelper::GetOverlap(occupiedArea, rect, 0, 0);
366 const WSRect& lastSafeRect = callingSession->GetLastSafeRect();
367 if (lastSafeRect == safeRect) {
368 TLOGI(WmsLogTag::WMS_KEYBOARD, "SafeRect is same to lastSafeRect: %{public}s", safeRect.ToString().c_str());
369 return;
370 }
371 callingSession->SetLastSafeRect(safeRect);
372 double textFieldPositionY = 0.0;
373 double textFieldHeight = 0.0;
374 auto sessionProperty = GetSessionProperty();
375 if (sessionProperty != nullptr) {
376 textFieldPositionY = sessionProperty->GetTextFieldPositionY();
377 textFieldHeight = sessionProperty->GetTextFieldHeight();
378 }
379 sptr<OccupiedAreaChangeInfo> info = sptr<OccupiedAreaChangeInfo>::MakeSptr(OccupiedAreaType::TYPE_INPUT,
380 SessionHelper::TransferToRect(safeRect), safeRect.height_, textFieldPositionY, textFieldHeight);
381 TLOGI(WmsLogTag::WMS_KEYBOARD, "lastSafeRect: %{public}s, safeRect: %{public}s, keyboardRect: %{public}s, "
382 "textFieldPositionY_: %{public}f, textFieldHeight_: %{public}f", lastSafeRect.ToString().c_str(),
383 safeRect.ToString().c_str(), occupiedArea.ToString().c_str(), textFieldPositionY, textFieldHeight);
384 callingSession->NotifyOccupiedAreaChangeInfo(info, rsTransaction);
385 }
386
NotifyKeyboardPanelInfoChange(WSRect rect,bool isKeyboardPanelShow)387 void KeyboardSession::NotifyKeyboardPanelInfoChange(WSRect rect, bool isKeyboardPanelShow)
388 {
389 if (!sessionStage_) {
390 TLOGE(WmsLogTag::WMS_KEYBOARD, "sessionStage_ is nullptr, notify keyboard panel rect change failed");
391 return;
392 }
393 KeyboardPanelInfo keyboardPanelInfo;
394 keyboardPanelInfo.rect_ = SessionHelper::TransferToRect(rect);
395 keyboardPanelInfo.gravity_ = static_cast<WindowGravity>(GetKeyboardGravity());
396 keyboardPanelInfo.isShowing_ = isKeyboardPanelShow;
397
398 sessionStage_->NotifyKeyboardPanelInfoChange(keyboardPanelInfo);
399 }
400
CheckIfNeedRaiseCallingSession(sptr<SceneSession> callingSession,bool isCallingSessionFloating)401 bool KeyboardSession::CheckIfNeedRaiseCallingSession(sptr<SceneSession> callingSession, bool isCallingSessionFloating)
402 {
403 if (callingSession == nullptr) {
404 TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session is nullptr");
405 return false;
406 }
407
408 SessionGravity gravity = GetKeyboardGravity();
409 if (gravity == SessionGravity::SESSION_GRAVITY_FLOAT) {
410 TLOGI(WmsLogTag::WMS_KEYBOARD, "No need to raise calling session, gravity: %{public}d", gravity);
411 return false;
412 }
413 bool isMainOrParentFloating = WindowHelper::IsMainWindow(callingSession->GetWindowType()) ||
414 (WindowHelper::IsSubWindow(callingSession->GetWindowType()) && callingSession->GetParentSession() != nullptr &&
415 callingSession->GetParentSession()->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING);
416 bool isFreeMultiWindowMode = callingSession->IsFreeMultiWindowMode();
417 bool isMidScene = callingSession->GetIsMidScene();
418 if (isCallingSessionFloating && isMainOrParentFloating && !isMidScene &&
419 (systemConfig_.uiType_ == UI_TYPE_PHONE || (systemConfig_.uiType_ == UI_TYPE_PAD && !isFreeMultiWindowMode))) {
420 TLOGI(WmsLogTag::WMS_KEYBOARD, "No need to raise calling session in float window.");
421 return false;
422 }
423
424 return true;
425 }
426
RaiseCallingSession(const WSRect & keyboardPanelRect,bool needCheckVisible,const std::shared_ptr<RSTransaction> & rsTransaction)427 void KeyboardSession::RaiseCallingSession(const WSRect& keyboardPanelRect, bool needCheckVisible,
428 const std::shared_ptr<RSTransaction>& rsTransaction)
429 {
430 if (!IsSessionForeground() || (Session::IsScbCoreEnabled() && needCheckVisible && !IsVisibleForeground())) {
431 TLOGI(WmsLogTag::WMS_KEYBOARD, "Keyboard is not foreground.");
432 return;
433 }
434 sptr<SceneSession> callingSession = GetSceneSession(GetCallingSessionId());
435 if (callingSession == nullptr) {
436 TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session is nullptr");
437 return;
438 }
439 NotifyKeyboardPanelInfoChange(keyboardPanelRect, true);
440
441 bool isCallingSessionFloating = (callingSession->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING);
442 if (!CheckIfNeedRaiseCallingSession(callingSession, isCallingSessionFloating)) {
443 return;
444 }
445
446 WSRect callingSessionRect = callingSession->GetSessionRect();
447 int32_t oriPosYBeforeRaisedByKeyboard = callingSession->GetOriPosYBeforeRaisedByKeyboard();
448 if (oriPosYBeforeRaisedByKeyboard != 0 && isCallingSessionFloating) {
449 callingSessionRect.posY_ = oriPosYBeforeRaisedByKeyboard;
450 }
451 if (SessionHelper::IsEmptyRect(SessionHelper::GetOverlap(keyboardPanelRect, callingSessionRect, 0, 0)) &&
452 oriPosYBeforeRaisedByKeyboard == 0) {
453 TLOGI(WmsLogTag::WMS_KEYBOARD, "No overlap area, keyboardRect: %{public}s, callingRect: %{public}s",
454 keyboardPanelRect.ToString().c_str(), callingSessionRect.ToString().c_str());
455 NotifyOccupiedAreaChangeInfo(callingSession, callingSessionRect, keyboardPanelRect, rsTransaction);
456 return;
457 }
458
459 WSRect newRect = callingSessionRect;
460 int32_t statusHeight = GetStatusBarHeight();
461 if (isCallingSessionFloating && callingSessionRect.posY_ > statusHeight) {
462 if (oriPosYBeforeRaisedByKeyboard == 0) {
463 oriPosYBeforeRaisedByKeyboard = callingSessionRect.posY_;
464 callingSession->SetOriPosYBeforeRaisedByKeyboard(callingSessionRect.posY_);
465 }
466 // calculate new rect of calling session
467 newRect.posY_ = std::max(keyboardPanelRect.posY_ - newRect.height_, statusHeight);
468 newRect.posY_ = std::min(oriPosYBeforeRaisedByKeyboard, newRect.posY_);
469 NotifyOccupiedAreaChangeInfo(callingSession, newRect, keyboardPanelRect, rsTransaction);
470 callingSession->UpdateSessionRect(newRect, SizeChangeReason::UNDEFINED);
471 } else {
472 NotifyOccupiedAreaChangeInfo(callingSession, newRect, keyboardPanelRect, rsTransaction);
473 }
474
475 TLOGI(WmsLogTag::WMS_KEYBOARD, "keyboardRect: %{public}s, CallSession OriRect: %{public}s, NewRect: %{public}s"
476 ", oriPosYBeforeRaisedByKeyboard: %{public}d, isCallingSessionFloating: %{public}d",
477 keyboardPanelRect.ToString().c_str(), callingSessionRect.ToString().c_str(), newRect.ToString().c_str(),
478 oriPosYBeforeRaisedByKeyboard, isCallingSessionFloating);
479 }
480
RestoreCallingSession(const std::shared_ptr<RSTransaction> & rsTransaction)481 void KeyboardSession::RestoreCallingSession(const std::shared_ptr<RSTransaction>& rsTransaction)
482 {
483 sptr<SceneSession> callingSession = GetSceneSession(GetCallingSessionId());
484 if (callingSession == nullptr) {
485 TLOGI(WmsLogTag::WMS_KEYBOARD, "Calling session is nullptr");
486 return;
487 }
488 const WSRect& emptyRect = { 0, 0, 0, 0 };
489 int32_t oriPosYBeforeRaisedByKeyboard = callingSession->GetOriPosYBeforeRaisedByKeyboard();
490 NotifyOccupiedAreaChangeInfo(callingSession, emptyRect, emptyRect, rsTransaction);
491 if (oriPosYBeforeRaisedByKeyboard != 0 &&
492 callingSession->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
493 WSRect callingSessionRestoringRect = callingSession->GetSessionRect();
494 if (oriPosYBeforeRaisedByKeyboard != 0) {
495 callingSessionRestoringRect.posY_ = oriPosYBeforeRaisedByKeyboard;
496 }
497 TLOGI(WmsLogTag::WMS_KEYBOARD, "oriPosYBeforeRaisedByKeyboard: %{public}d, sessionMode: %{public}d",
498 oriPosYBeforeRaisedByKeyboard, callingSession->GetWindowMode());
499 callingSession->UpdateSessionRect(callingSessionRestoringRect, SizeChangeReason::UNDEFINED);
500 }
501 callingSession->SetOriPosYBeforeRaisedByKeyboard(0); // 0: default value
502 }
503
504 // Use focused session id when calling session id is invalid.
UseFocusIdIfCallingSessionIdInvalid()505 void KeyboardSession::UseFocusIdIfCallingSessionIdInvalid()
506 {
507 if (GetSceneSession(GetCallingSessionId()) != nullptr) {
508 return;
509 }
510 uint32_t focusedSessionId = static_cast<uint32_t>(GetFocusedSessionId());
511 if (GetSceneSession(focusedSessionId) == nullptr) {
512 TLOGE(WmsLogTag::WMS_KEYBOARD, "Focused session is null, id: %{public}d", focusedSessionId);
513 } else {
514 TLOGI(WmsLogTag::WMS_KEYBOARD, "Using focusedSession id: %{public}d", focusedSessionId);
515 GetSessionProperty()->SetCallingSessionId(focusedSessionId);
516 }
517 }
518
UpdateCallingSessionIdAndPosition(uint32_t newCallingSessionId)519 void KeyboardSession::UpdateCallingSessionIdAndPosition(uint32_t newCallingSessionId)
520 {
521 auto sessionProperty = GetSessionProperty();
522 if (sessionProperty == nullptr) {
523 TLOGE(WmsLogTag::WMS_KEYBOARD, "Session property is nullptr");
524 return;
525 }
526 RestoreCallingSession();
527
528 sessionProperty->SetCallingSessionId(newCallingSessionId);
529 WSRect panelRect = { 0, 0, 0, 0 };
530 panelRect = (keyboardPanelSession_ == nullptr) ? panelRect : keyboardPanelSession_->GetSessionRect();
531 RaiseCallingSession(panelRect, true);
532 }
533
RelayoutKeyBoard()534 void KeyboardSession::RelayoutKeyBoard()
535 {
536 auto sessionProperty = GetSessionProperty();
537 if (sessionProperty == nullptr) {
538 TLOGE(WmsLogTag::WMS_KEYBOARD, "Session property is nullptr, relayout keyboard failed");
539 return;
540 }
541 uint32_t screenWidth = 0;
542 uint32_t screenHeight = 0;
543 SessionGravity gravity = GetKeyboardGravity();
544 if (gravity == SessionGravity::SESSION_GRAVITY_FLOAT) {
545 return;
546 }
547 if (!GetScreenWidthAndHeightFromClient(sessionProperty, screenWidth, screenHeight)) {
548 return;
549 }
550
551 auto requestRect = sessionProperty->GetRequestRect();
552 if (gravity == SessionGravity::SESSION_GRAVITY_BOTTOM) {
553 requestRect.width_ = screenWidth;
554 requestRect.posX_ = 0;
555 }
556 requestRect.posY_ = static_cast<int32_t>(screenHeight - requestRect.height_);
557 sessionProperty->SetRequestRect(requestRect);
558 TLOGI(WmsLogTag::WMS_KEYBOARD, "Id: %{public}d, rect: %{public}s", GetPersistentId(),
559 SessionHelper::TransferToWSRect(requestRect).ToString().c_str());
560 }
561
OpenKeyboardSyncTransaction()562 void KeyboardSession::OpenKeyboardSyncTransaction()
563 {
564 auto task = [weakThis = wptr(this)]() {
565 auto session = weakThis.promote();
566 if (!session) {
567 TLOGNE(WmsLogTag::WMS_KEYBOARD, "keyboard session is null");
568 return WSError::WS_ERROR_DESTROYED_OBJECT;
569 }
570 if (session->isKeyboardSyncTransactionOpen_) {
571 TLOGNI(WmsLogTag::WMS_KEYBOARD, "Keyboard sync transaction is already open");
572 return WSError::WS_OK;
573 }
574 TLOGNI(WmsLogTag::WMS_KEYBOARD, "Open keyboard sync");
575 session->isKeyboardSyncTransactionOpen_ = true;
576 auto transactionController = RSSyncTransactionController::GetInstance();
577 if (transactionController) {
578 transactionController->OpenSyncTransaction(session->GetEventHandler());
579 }
580 return WSError::WS_OK;
581 };
582 PostSyncTask(task);
583 }
584
CloseKeyboardSyncTransaction(const WSRect & keyboardPanelRect,bool isKeyboardShow,bool isRotating)585 void KeyboardSession::CloseKeyboardSyncTransaction(const WSRect& keyboardPanelRect,
586 bool isKeyboardShow, bool isRotating)
587 {
588 auto task = [weakThis = wptr(this), keyboardPanelRect, isKeyboardShow, isRotating]() {
589 auto session = weakThis.promote();
590 if (!session) {
591 TLOGE(WmsLogTag::WMS_KEYBOARD, "keyboard session is null");
592 return WSError::WS_ERROR_DESTROYED_OBJECT;
593 }
594 TLOGNI(WmsLogTag::WMS_KEYBOARD, "Close keyboard sync, isKeyboardShow: %{public}d, isRotating: %{public}d",
595 isKeyboardShow, isRotating);
596 std::shared_ptr<RSTransaction> rsTransaction = nullptr;
597 if (!isRotating && session->isKeyboardSyncTransactionOpen_) {
598 rsTransaction = session->GetRSTransaction();
599 }
600 if (isKeyboardShow) {
601 // notify calling session when keyboard is not visible
602 session->RaiseCallingSession(keyboardPanelRect, false, rsTransaction);
603 session->UpdateKeyboardAvoidArea();
604 } else {
605 session->RestoreCallingSession(rsTransaction);
606 auto sessionProperty = session->GetSessionProperty();
607 if (sessionProperty) {
608 sessionProperty->SetCallingSessionId(INVALID_WINDOW_ID);
609 }
610 }
611
612 if (!session->isKeyboardSyncTransactionOpen_) {
613 TLOGI(WmsLogTag::WMS_KEYBOARD, "Keyboard sync transaction is closed");
614 return WSError::WS_OK;
615 }
616 session->isKeyboardSyncTransactionOpen_ = false;
617 auto transactionController = RSSyncTransactionController::GetInstance();
618 if (transactionController) {
619 transactionController->CloseSyncTransaction(session->GetEventHandler());
620 }
621 return WSError::WS_OK;
622 };
623 PostTask(task, "CloseKeyboardSyncTransaction");
624 }
625
GetRSTransaction()626 std::shared_ptr<RSTransaction> KeyboardSession::GetRSTransaction()
627 {
628 auto transactionController = RSSyncTransactionController::GetInstance();
629 std::shared_ptr<RSTransaction> rsTransaction = nullptr;
630 if (transactionController) {
631 rsTransaction = transactionController->GetRSTransaction();
632 }
633 return rsTransaction;
634 }
635
GetSessionScreenName()636 std::string KeyboardSession::GetSessionScreenName()
637 {
638 auto sessionProperty = GetSessionProperty();
639 if (sessionProperty != nullptr) {
640 auto displayId = sessionProperty->GetDisplayId();
641 auto screenSession = ScreenSessionManagerClient::GetInstance().GetScreenSession(displayId);
642 if (screenSession != nullptr) {
643 return screenSession->GetName();
644 }
645 }
646 return "";
647 }
648
MoveAndResizeKeyboard(const KeyboardLayoutParams & params,const sptr<WindowSessionProperty> & sessionProperty,bool isShow)649 void KeyboardSession::MoveAndResizeKeyboard(const KeyboardLayoutParams& params,
650 const sptr<WindowSessionProperty>& sessionProperty, bool isShow)
651 {
652 uint32_t screenWidth = 0;
653 uint32_t screenHeight = 0;
654 WSRect newWinRect = winRect_;
655 WSRect newRequestRect = GetSessionRequestRect();
656 bool ret = (isShow) ? GetScreenWidthAndHeightFromServer(sessionProperty, screenWidth, screenHeight) :
657 GetScreenWidthAndHeightFromClient(sessionProperty, screenWidth, screenHeight);
658 if (!ret) {
659 TLOGE(WmsLogTag::WMS_KEYBOARD, "getScreenWidthAndHeight failed, isShow: %{public}d", isShow);
660 return;
661 }
662 bool isLandscape = screenWidth > screenHeight ? true : false;
663 WSRect rect = isLandscape ? SessionHelper::TransferToWSRect(params.LandscapeKeyboardRect_) :
664 SessionHelper::TransferToWSRect(params.PortraitKeyboardRect_);
665 SessionGravity gravity = static_cast<SessionGravity>(params.gravity_);
666 if (gravity == SessionGravity::SESSION_GRAVITY_BOTTOM || gravity == SessionGravity::SESSION_GRAVITY_DEFAULT) {
667 newWinRect.width_ = (gravity == SessionGravity::SESSION_GRAVITY_BOTTOM) ?
668 static_cast<int32_t>(screenWidth) : rect.width_;
669 newWinRect.height_ = rect.height_;
670 newWinRect.posX_ = (gravity == SessionGravity::SESSION_GRAVITY_BOTTOM) ? 0 : rect.posX_;
671 newWinRect.posY_ = static_cast<int32_t>(screenHeight) - rect.height_;
672 newRequestRect= newWinRect;
673 } else if (rect.width_ > 0 && rect.height_ > 0) {
674 newWinRect = rect;
675 newRequestRect = newWinRect;
676 }
677 SetSessionRequestRect(newRequestRect);
678 TLOGI(WmsLogTag::WMS_KEYBOARD, "Id: %{public}d, gravity: %{public}d, rect: %{public}s, newRequestRect: %{public}s"
679 ", isLandscape: %{public}d, screenWidth: %{public}d, screenHeight: %{public}d", GetPersistentId(), gravity,
680 rect.ToString().c_str(), newRequestRect.ToString().c_str(), isLandscape, screenWidth, screenHeight);
681 }
682
IsVisibleForeground() const683 bool KeyboardSession::IsVisibleForeground() const
684 {
685 return isVisible_;
686 }
687 } // namespace OHOS::Rosen
688