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