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