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