• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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