• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-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 "input_method_panel.h"
17 
18 #include <tuple>
19 
20 #include "dm_common.h"
21 #include "display_info.h"
22 #include "global.h"
23 #include "inputmethod_trace.h"
24 #include "input_method_ability.h"
25 #include "input_method_ability_utils.h"
26 #include "scene_board_judgement.h"
27 #include "sys_cfg_parser.h"
28 #include "ui/rs_surface_node.h"
29 
30 namespace OHOS {
31 namespace MiscServices {
32 using WMError = OHOS::Rosen::WMError;
33 using WindowGravity = OHOS::Rosen::WindowGravity;
34 using WindowState = OHOS::Rosen::WindowState;
35 using namespace Rosen;
36 constexpr float FIXED_SOFT_KEYBOARD_PANEL_RATIO = 0.7;
37 constexpr float NON_FIXED_SOFT_KEYBOARD_PANEL_RATIO = 1;
38 constexpr int32_t NUMBER_ZERO = 0;
39 constexpr int32_t NUMBER_TWO = 2;
40 constexpr int32_t CUTOUTINFO = 100;
41 constexpr int32_t FIXED_PANEL_POS_X = 0;
42 constexpr int32_t ORIGIN_POS_X = 0;
43 constexpr int32_t ORIGIN_POS_Y = 0;
44 constexpr int32_t DEFAULT_AVOID_HEIGHT = -1;
45 std::atomic<uint32_t> InputMethodPanel::sequenceId_{ 0 };
46 constexpr int32_t MAXWAITTIME = 30;
47 constexpr int32_t WAITTIME = 10;
48 InputMethodPanel::~InputMethodPanel() = default;
49 
CreatePanel(const std::shared_ptr<AbilityRuntime::Context> & context,const PanelInfo & panelInfo)50 int32_t InputMethodPanel::CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context,
51     const PanelInfo &panelInfo)
52 {
53     IMSA_HILOGD("start, type/flag: %{public}d/%{public}d.", static_cast<int32_t>(panelType_),
54         static_cast<int32_t>(panelFlag_));
55     panelType_ = panelInfo.panelType;
56     panelFlag_ = panelInfo.panelFlag;
57     winOption_ = new (std::nothrow) OHOS::Rosen::WindowOption();
58     if (winOption_ == nullptr) {
59         return ErrorCode::ERROR_NULL_POINTER;
60     }
61     if (panelInfo.panelType == PanelType::STATUS_BAR) {
62         winOption_->SetWindowType(OHOS::Rosen::WindowType::WINDOW_TYPE_INPUT_METHOD_STATUS_BAR);
63     } else {
64         winOption_->SetWindowType(OHOS::Rosen::WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT);
65     }
66     WMError wmError = WMError::WM_OK;
67     window_ = OHOS::Rosen::Window::Create(GeneratePanelName(), winOption_, context, wmError);
68     if (wmError == WMError::WM_ERROR_INVALID_PERMISSION || wmError == WMError::WM_ERROR_NOT_SYSTEM_APP) {
69         IMSA_HILOGE("create window failed, permission denied, %{public}d!", wmError);
70         return ErrorCode::ERROR_NOT_IME;
71     }
72     if (window_ == nullptr || wmError != WMError::WM_OK) {
73         IMSA_HILOGE("create window failed: %{public}d!", wmError);
74         return ErrorCode::ERROR_OPERATE_PANEL;
75     }
76     if (SetPanelProperties() != ErrorCode::NO_ERROR) {
77         wmError = window_->Destroy();
78         IMSA_HILOGI("destroy window end, wmError is %{public}d.", wmError);
79         return ErrorCode::ERROR_OPERATE_PANEL;
80     }
81     windowId_ = window_->GetWindowId();
82     IMSA_HILOGI("success, type/flag/windowId: %{public}d/%{public}d/%{public}u.", static_cast<int32_t>(panelType_),
83         static_cast<int32_t>(panelFlag_), windowId_);
84     if (panelInfo.panelType == SOFT_KEYBOARD) {
85         isScbEnable_ = Rosen::SceneBoardJudgement::IsSceneBoardEnabled();
86         if (isScbEnable_) {
87             RegisterKeyboardPanelInfoChangeListener();
88         }
89     }
90     return ErrorCode::NO_ERROR;
91 }
92 
GeneratePanelName()93 std::string InputMethodPanel::GeneratePanelName()
94 {
95     uint32_t sequenceId = GenerateSequenceId();
96     std::string windowName = panelType_ == SOFT_KEYBOARD ? "softKeyboard" + std::to_string(sequenceId)
97                                                          : "statusBar" + std::to_string(sequenceId);
98     IMSA_HILOGD("InputMethodPanel, windowName: %{public}s.", windowName.c_str());
99     return windowName;
100 }
101 
SetPanelProperties()102 int32_t InputMethodPanel::SetPanelProperties()
103 {
104     if (window_ == nullptr) {
105         IMSA_HILOGE("window is nullptr!");
106         return ErrorCode::ERROR_OPERATE_PANEL;
107     }
108     WindowGravity gravity = WindowGravity::WINDOW_GRAVITY_FLOAT;
109     if (panelType_ == SOFT_KEYBOARD && panelFlag_ == FLG_FIXED) {
110         gravity = WindowGravity::WINDOW_GRAVITY_BOTTOM;
111     } else if (panelType_ == SOFT_KEYBOARD && panelFlag_ == FLG_FLOATING) {
112         auto surfaceNode = window_->GetSurfaceNode();
113         if (surfaceNode == nullptr) {
114             IMSA_HILOGE("surfaceNode is nullptr");
115             return ErrorCode::ERROR_OPERATE_PANEL;
116         }
117         surfaceNode->SetFrameGravity(Rosen::Gravity::TOP_LEFT);
118         Rosen::RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
119     } else if (panelType_ == STATUS_BAR) {
120         auto surfaceNo = window_->GetSurfaceNode();
121         if (surfaceNo == nullptr) {
122             IMSA_HILOGE("surfaceNo is nullptr");
123             return ErrorCode::ERROR_OPERATE_PANEL;
124         }
125         surfaceNo->SetFrameGravity(Rosen::Gravity::TOP_LEFT);
126         Rosen::RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
127         return ErrorCode::NO_ERROR;
128     }
129     if (!isScbEnable_) {
130         WMError wmError = window_->SetWindowGravity(gravity, invalidGravityPercent);
131         if (wmError != WMError::WM_OK) {
132             IMSA_HILOGE("failed to set window gravity, wmError is %{public}d, start destroy window!", wmError);
133             return ErrorCode::ERROR_OPERATE_PANEL;
134         }
135         return ErrorCode::NO_ERROR;
136     }
137     keyboardLayoutParams_.gravity_ = gravity;
138     auto ret = window_->AdjustKeyboardLayout(keyboardLayoutParams_);
139     if (ret != WMError::WM_OK) {
140         IMSA_HILOGE("SetWindowGravity failed, wmError is %{public}d, start destroy window.", ret);
141         return ErrorCode::ERROR_OPERATE_PANEL;
142     }
143     return ErrorCode::NO_ERROR;
144 }
145 
DestroyPanel()146 int32_t InputMethodPanel::DestroyPanel()
147 {
148     auto ret = HidePanel();
149     if (ret != ErrorCode::NO_ERROR) {
150         IMSA_HILOGE("InputMethodPanel, hide panel failed, ret: %{public}d!", ret);
151     }
152     if (window_ == nullptr) {
153         IMSA_HILOGE("window_ is nullptr!");
154         return ErrorCode::ERROR_NULL_POINTER;
155     }
156     if (panelType_ == SOFT_KEYBOARD) {
157         UnregisterKeyboardPanelInfoChangeListener();
158     }
159     auto result = window_->Destroy();
160     IMSA_HILOGI("destroy ret: %{public}d", result);
161     return ErrorCode::NO_ERROR;
162 }
163 
GetResizeParams(Rosen::Rect & portrait,Rosen::Rect & landscape,uint32_t width,uint32_t height)164 int32_t InputMethodPanel::GetResizeParams(
165     Rosen::Rect &portrait, Rosen::Rect &landscape, uint32_t width, uint32_t height)
166 {
167     LayoutParams currParams;
168     DisplaySize displaySize;
169     auto ret = GetDisplaySize(displaySize);
170     if (ret != ErrorCode::NO_ERROR) {
171         IMSA_HILOGE("failed to GetDisplaySize ret: %{public}d", ret);
172         return ret;
173     }
174 
175     if (displaySize.portrait.height == displaySize.portrait.width) {
176         portrait.height_ = height;
177         portrait.width_ = width;
178         landscape.height_ = height;
179         landscape.width_ = width;
180         IMSA_HILOGI("isScreenEqual now, update screen equal size");
181         return ErrorCode::NO_ERROR;
182     }
183 
184     if (IsDisplayUnfolded()) {
185         IMSA_HILOGI("foldable device without fold state");
186         if (!isInEnhancedAdjust_) {
187             resizePanelUnfoldParams_.portraitRect.height_ =
188                 std::min(static_cast<float>(displaySize.portrait.height) * FIXED_SOFT_KEYBOARD_PANEL_RATIO,
189                     static_cast<float>(resizePanelUnfoldParams_.portraitRect.height_));
190             resizePanelUnfoldParams_.landscapeRect.height_ =
191                 std::min(static_cast<float>(displaySize.landscape.height) * FIXED_SOFT_KEYBOARD_PANEL_RATIO,
192                     static_cast<float>(resizePanelUnfoldParams_.landscapeRect.height_));
193         }
194         currParams = resizePanelUnfoldParams_;
195     } else {
196         IMSA_HILOGI("foldable device with fold state or non-foldable device");
197         if (!isInEnhancedAdjust_) {
198             resizePanelFoldParams_.portraitRect.height_ =
199                 std::min(static_cast<float>(displaySize.portrait.height) * FIXED_SOFT_KEYBOARD_PANEL_RATIO,
200                     static_cast<float>(resizePanelFoldParams_.portraitRect.height_));
201             resizePanelFoldParams_.landscapeRect.height_ =
202                 std::min(static_cast<float>(displaySize.landscape.height) * FIXED_SOFT_KEYBOARD_PANEL_RATIO,
203                     static_cast<float>(resizePanelFoldParams_.landscapeRect.height_));
204         }
205         currParams = resizePanelFoldParams_;
206     }
207 
208     UpdateRectParams(portrait, landscape, width, height, currParams);
209     return ErrorCode::NO_ERROR;
210 }
211 
UpdateRectParams(Rosen::Rect & portrait,Rosen::Rect & landscape,uint32_t width,uint32_t height,const LayoutParams & currParams)212 void InputMethodPanel::UpdateRectParams(
213     Rosen::Rect &portrait, Rosen::Rect &landscape, uint32_t width, uint32_t height, const LayoutParams &currParams)
214 {
215     if (IsDisplayPortrait()) {
216         landscape.height_ = currParams.landscapeRect.height_;
217         landscape.width_ = currParams.landscapeRect.width_;
218         portrait.height_ = height;
219         portrait.width_ = width;
220         IMSA_HILOGI("isPortrait now, update portrait size");
221     } else {
222         portrait.height_ = currParams.portraitRect.height_;
223         portrait.width_ = currParams.portraitRect.width_;
224         landscape.height_ = height;
225         landscape.width_ = width;
226         IMSA_HILOGI("isLandscapeRect now, update landscape size");
227     }
228 }
229 
UpdateResizeParams()230 void InputMethodPanel::UpdateResizeParams()
231 {
232     if (IsDisplayUnfolded()) {
233         IMSA_HILOGI("foldable device without fold state");
234         resizePanelUnfoldParams_ = { keyboardLayoutParams_.LandscapeKeyboardRect_,
235             keyboardLayoutParams_.PortraitKeyboardRect_ };
236     } else {
237         IMSA_HILOGI("foldable device in fold state or non-foldable device");
238         resizePanelFoldParams_ = { keyboardLayoutParams_.LandscapeKeyboardRect_,
239             keyboardLayoutParams_.PortraitKeyboardRect_ };
240     }
241 }
242 
ResizeEnhancedPanel(uint32_t width,uint32_t height)243 int32_t InputMethodPanel::ResizeEnhancedPanel(uint32_t width, uint32_t height)
244 {
245     EnhancedLayoutParams layoutParam = enhancedLayoutParams_;
246     auto ret = GetResizeParams(layoutParam.portrait.rect, layoutParam.landscape.rect, width, height);
247     if (ret != ErrorCode::NO_ERROR) {
248         IMSA_HILOGE("failed to GetResizeParams, ret: %{public}d", ret);
249         return ret;
250     }
251     auto hotAreas = GetHotAreas();
252     ret = AdjustPanelRect(panelFlag_, layoutParam, hotAreas);
253     if (ret != ErrorCode::NO_ERROR) {
254         IMSA_HILOGE("failed to AdjustPanelRect, ret: %{public}d", ret);
255         return ErrorCode::ERROR_OPERATE_PANEL;
256     }
257     UpdateResizeParams();
258     std::lock_guard<std::mutex> lock(keyboardSizeLock_);
259     keyboardSize_ = { width, height };
260     IMSA_HILOGI("success, width/height: %{public}u/%{public}u.", width, height);
261     return ErrorCode::NO_ERROR;
262 }
263 
ResizeWithoutAdjust(uint32_t width,uint32_t height)264 int32_t InputMethodPanel::ResizeWithoutAdjust(uint32_t width, uint32_t height)
265 {
266     if (!IsSizeValid(width, height)) {
267         IMSA_HILOGE("size is invalid!");
268         return ErrorCode::ERROR_BAD_PARAMETERS;
269     }
270     auto ret = window_->Resize(width, height);
271     if (ret != WMError::WM_OK) {
272         IMSA_HILOGE("failed to resize, ret: %{public}d", ret);
273         return ErrorCode::ERROR_OPERATE_PANEL;
274     }
275     std::lock_guard<std::mutex> lock(keyboardSizeLock_);
276     keyboardSize_ = { width, height };
277     IMSA_HILOGI("success, width/height: %{public}u/%{public}u.", width, height);
278     return ErrorCode::NO_ERROR;
279 }
280 
ResizePanel(uint32_t width,uint32_t height)281 int32_t InputMethodPanel::ResizePanel(uint32_t width, uint32_t height)
282 {
283     if (!IsSizeValid(width, height)) {
284         IMSA_HILOGE("size is invalid!");
285         return ErrorCode::ERROR_BAD_PARAMETERS;
286     }
287     LayoutParams params = { enhancedLayoutParams_.landscape.rect, enhancedLayoutParams_.portrait.rect };
288     auto ret = GetResizeParams(params.portraitRect, params.landscapeRect, width, height);
289     if (ret != ErrorCode::NO_ERROR) {
290         IMSA_HILOGE("failed to GetResizeParams, ret: %{public}d", ret);
291         return ret;
292     }
293     ret = AdjustPanelRect(panelFlag_, params);
294     if (ret != ErrorCode::NO_ERROR) {
295         IMSA_HILOGE("failed to resize, ret: %{public}d", ret);
296         return ErrorCode::ERROR_OPERATE_PANEL;
297     }
298     UpdateResizeParams();
299     std::lock_guard<std::mutex> lock(keyboardSizeLock_);
300     keyboardSize_ = { width, height };
301     IMSA_HILOGI("success, width/height: %{public}u/%{public}u.", width, height);
302     return ErrorCode::NO_ERROR;
303 }
304 
Resize(uint32_t width,uint32_t height)305 int32_t InputMethodPanel::Resize(uint32_t width, uint32_t height)
306 {
307     if (window_ == nullptr) {
308         IMSA_HILOGE("window is nullptr!");
309         return ErrorCode::ERROR_NULL_POINTER;
310     }
311     if (!isScbEnable_ || window_->GetType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
312         return ResizeWithoutAdjust(width, height);
313     }
314     if (isInEnhancedAdjust_.load()) {
315         return ResizeEnhancedPanel(width, height);
316     }
317     return ResizePanel(width, height);
318 }
319 
MovePanelRect(int32_t x,int32_t y)320 int32_t InputMethodPanel::MovePanelRect(int32_t x, int32_t y)
321 {
322     LayoutParams params = { enhancedLayoutParams_.landscape.rect, enhancedLayoutParams_.portrait.rect };
323     if (IsDisplayPortrait()) {
324         params.portraitRect.posX_ = x;
325         params.portraitRect.posY_ = y;
326         IMSA_HILOGI("isPortrait now, updata portrait size");
327     } else {
328         params.landscapeRect.posX_ = x;
329         params.landscapeRect.posY_ = y;
330         IMSA_HILOGI("isLandscapeRect now, updata landscape size");
331     }
332     auto ret = AdjustPanelRect(panelFlag_, params, false);
333     IMSA_HILOGI("x/y: %{public}d/%{public}d, ret = %{public}d", x, y, ret);
334     return ret == ErrorCode::NO_ERROR ? ErrorCode::NO_ERROR : ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
335 }
336 
MoveEnhancedPanelRect(int32_t x,int32_t y)337 int32_t InputMethodPanel::MoveEnhancedPanelRect(int32_t x, int32_t y)
338 {
339     auto params = enhancedLayoutParams_;
340     if (IsDisplayPortrait()) {
341         params.portrait.rect.posX_ = x;
342         params.portrait.rect.posY_ = y;
343     } else {
344         params.landscape.rect.posX_ = x;
345         params.landscape.rect.posY_ = y;
346     }
347     auto hotAreas = GetHotAreas();
348     auto ret = AdjustPanelRect(panelFlag_, params, hotAreas);
349     IMSA_HILOGI("x/y: %{public}d/%{public}d, ret = %{public}d", x, y, ret);
350     return ret == ErrorCode::NO_ERROR ? ErrorCode::NO_ERROR : ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
351 }
352 
MoveTo(int32_t x,int32_t y)353 int32_t InputMethodPanel::MoveTo(int32_t x, int32_t y)
354 {
355     if (window_ == nullptr) {
356         IMSA_HILOGE("window_ is nullptr!");
357         return ErrorCode::ERROR_NULL_POINTER;
358     }
359     if (panelType_ == SOFT_KEYBOARD && panelFlag_ == FLG_FIXED) {
360         IMSA_HILOGE("FLG_FIXED panel can not moveTo!");
361         return ErrorCode::NO_ERROR;
362     }
363     if (!isScbEnable_ || window_->GetType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
364         auto ret = window_->MoveTo(x, y);
365         IMSA_HILOGI("x/y: %{public}d/%{public}d, ret = %{public}d", x, y, ret);
366         return ret == WMError::WM_ERROR_INVALID_PARAM ? ErrorCode::ERROR_PARAMETER_CHECK_FAILED : ErrorCode::NO_ERROR;
367     } else if (isInEnhancedAdjust_.load()) {
368         return MoveEnhancedPanelRect(x, y);
369     } else {
370         return MovePanelRect(x, y);
371     }
372 }
373 
StartMoving()374 int32_t InputMethodPanel::StartMoving()
375 {
376     if (window_ == nullptr) {
377         IMSA_HILOGE("window_ is nullptr!");
378         return ErrorCode::ERROR_IME;
379     }
380     if (panelType_ != STATUS_BAR) {
381         IMSA_HILOGE("SOFT_KEYBOARD panel can not move!");
382         return ErrorCode::ERROR_INVALID_PANEL_TYPE;
383     }
384     if (panelFlag_ != FLG_FLOATING) {
385         IMSA_HILOGE("invalid panel flag: %{public}d", panelFlag_);
386         return ErrorCode::ERROR_INVALID_PANEL_FLAG;
387     }
388     auto ret = window_->StartMoveWindow();
389     if (ret != WmErrorCode::WM_OK) {
390         IMSA_HILOGE("window manager service error ret = %{public}d.", ret);
391         return ErrorCode::ERROR_WINDOW_MANAGER;
392     }
393     IMSA_HILOGI("StartMoving  success!");
394     return ErrorCode::NO_ERROR;
395 }
396 
GetDisplayId(uint64_t & displayId)397 int32_t InputMethodPanel::GetDisplayId(uint64_t &displayId)
398 {
399     if (window_ == nullptr) {
400         IMSA_HILOGE("window_ is nullptr!");
401         return ErrorCode::ERROR_IME;
402     }
403     displayId = window_->GetDisplayId();
404     if (displayId == Rosen::DISPLAY_ID_INVALID) {
405         IMSA_HILOGE("display id invalid!");
406         return ErrorCode::ERROR_WINDOW_MANAGER;
407     }
408     IMSA_HILOGI("GetDisplayId success dispalyId = %{public}" PRIu64 "", displayId);
409     return ErrorCode::NO_ERROR;
410 }
411 
AdjustPanelRect(const PanelFlag panelFlag,const LayoutParams & layoutParams,bool needUpdateRegion)412 int32_t InputMethodPanel::AdjustPanelRect(
413     const PanelFlag panelFlag, const LayoutParams &layoutParams, bool needUpdateRegion)
414 {
415     if (window_ == nullptr) {
416         IMSA_HILOGE("window_ is nullptr!");
417         return ErrorCode::ERROR_WINDOW_MANAGER;
418     }
419     if (layoutParams.portraitRect.posX_ < 0 || layoutParams.portraitRect.posY_ < 0 ||
420         layoutParams.landscapeRect.posX_ < 0 || layoutParams.landscapeRect.posY_ < 0) {
421         IMSA_HILOGE("posX_ and posY_ cannot be less than 0!");
422         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
423     }
424     if (!CheckSize(panelFlag, layoutParams.portraitRect.width_, layoutParams.portraitRect.height_, true)) {
425         IMSA_HILOGE("portrait invalid size!");
426         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
427     }
428     if (!CheckSize(panelFlag, layoutParams.landscapeRect.width_, layoutParams.landscapeRect.height_, false)) {
429         IMSA_HILOGE("landscape invalid size!");
430         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
431     }
432     auto result = ParsePanelRect(panelFlag, layoutParams);
433     if (result != ErrorCode::NO_ERROR) {
434         IMSA_HILOGE("failed to parse panel rect, result: %{public}d!", result);
435         return ErrorCode::ERROR_WINDOW_MANAGER;
436     }
437     panelFlag_ = panelFlag;
438     auto ret = window_->AdjustKeyboardLayout(keyboardLayoutParams_);
439     if (ret != WMError::WM_OK) {
440         IMSA_HILOGE("AdjustPanelRect error, err: %{public}d!", ret);
441         return ErrorCode::ERROR_WINDOW_MANAGER;
442     }
443     UpdateResizeParams();
444     UpdateLayoutInfo(panelFlag, layoutParams, {}, keyboardLayoutParams_, false);
445     if (needUpdateRegion) {
446         UpdateHotAreas();
447     }
448     IMSA_HILOGI("success, type/flag: %{public}d/%{public}d.", static_cast<int32_t>(panelType_),
449         static_cast<int32_t>(panelFlag_));
450     return ErrorCode::NO_ERROR;
451 }
452 
ConvertToWMSParam(PanelFlag panelFlag,const EnhancedLayoutParams & layoutParams)453 Rosen::KeyboardLayoutParams InputMethodPanel::ConvertToWMSParam(
454     PanelFlag panelFlag, const EnhancedLayoutParams &layoutParams)
455 {
456     Rosen::KeyboardLayoutParams wmsParams;
457     if (panelFlag == PanelFlag::FLG_FIXED) {
458         wmsParams.gravity_ = WindowGravity::WINDOW_GRAVITY_BOTTOM;
459     } else {
460         wmsParams.gravity_ = WindowGravity::WINDOW_GRAVITY_FLOAT;
461     }
462     wmsParams.LandscapeKeyboardRect_ = layoutParams.landscape.rect;
463     wmsParams.LandscapePanelRect_ = layoutParams.landscape.rect;
464     wmsParams.PortraitKeyboardRect_ = layoutParams.portrait.rect;
465     wmsParams.PortraitPanelRect_ = layoutParams.portrait.rect;
466     wmsParams.portraitAvoidHeight_ = layoutParams.portrait.avoidHeight;
467     wmsParams.landscapeAvoidHeight_ = layoutParams.landscape.avoidHeight;
468     return wmsParams;
469 }
470 
ConvertToWMSHotArea(const HotAreas & hotAreas)471 Rosen::KeyboardTouchHotAreas InputMethodPanel::ConvertToWMSHotArea(const HotAreas &hotAreas)
472 {
473     return { .landscapeKeyboardHotAreas_ = hotAreas.landscape.keyboardHotArea,
474         .portraitKeyboardHotAreas_ = hotAreas.portrait.keyboardHotArea,
475         .landscapePanelHotAreas_ = hotAreas.landscape.panelHotArea,
476         .portraitPanelHotAreas_ = hotAreas.portrait.panelHotArea };
477 }
478 
IsEnhancedParamValid(PanelFlag panelFlag,EnhancedLayoutParams & params)479 int32_t InputMethodPanel::IsEnhancedParamValid(PanelFlag panelFlag, EnhancedLayoutParams &params)
480 {
481     if (window_ == nullptr) {
482         IMSA_HILOGE("window_ is nullptr!");
483         return ErrorCode::ERROR_WINDOW_MANAGER;
484     }
485     if (panelType_ != PanelType::SOFT_KEYBOARD) {
486         IMSA_HILOGE("not soft keyboard panel");
487         return ErrorCode::ERROR_INVALID_PANEL_TYPE;
488     }
489     FullPanelAdjustInfo adjustInfo;
490     auto ret = GetAdjustInfo(panelFlag, adjustInfo);
491     if (ret != ErrorCode::NO_ERROR) {
492         return ret;
493     }
494     ret = ParseEnhancedParams(panelFlag, adjustInfo, params);
495     if (ret != ErrorCode::NO_ERROR) {
496         return ret;
497     }
498     return ErrorCode::NO_ERROR;
499 }
500 
AdjustPanelRect(PanelFlag panelFlag,EnhancedLayoutParams params,HotAreas hotAreas)501 int32_t InputMethodPanel::AdjustPanelRect(PanelFlag panelFlag, EnhancedLayoutParams params, HotAreas hotAreas)
502 {
503     if (window_ == nullptr) {
504         IMSA_HILOGE("window_ is nullptr!");
505         return ErrorCode::ERROR_WINDOW_MANAGER;
506     }
507     if (panelType_ != PanelType::SOFT_KEYBOARD) {
508         IMSA_HILOGE("not soft keyboard panel");
509         return ErrorCode::ERROR_INVALID_PANEL_TYPE;
510     }
511     FullPanelAdjustInfo adjustInfo;
512     auto ret = GetAdjustInfo(panelFlag, adjustInfo);
513     if (ret != ErrorCode::NO_ERROR) {
514         return ret;
515     }
516     ret = ParseEnhancedParams(panelFlag, adjustInfo, params);
517     if (ret != ErrorCode::NO_ERROR) {
518         return ret;
519     }
520     // adjust rect
521     auto wmsParams = ConvertToWMSParam(panelFlag, params);
522     WMError result = window_->AdjustKeyboardLayout(wmsParams);
523     if (result != WMError::WM_OK) {
524         IMSA_HILOGE("AdjustKeyboardLayout error, err: %{public}d!", result);
525         return ErrorCode::ERROR_WINDOW_MANAGER;
526     }
527     // set hot area
528     isInEnhancedAdjust_.store(true);
529     CalculateHotAreas(params, wmsParams, adjustInfo, hotAreas);
530     auto wmsHotAreas = ConvertToWMSHotArea(hotAreas);
531     result = window_->SetKeyboardTouchHotAreas(wmsHotAreas);
532     if (result != WMError::WM_OK) {
533         IMSA_HILOGE("SetKeyboardTouchHotAreas error, err: %{public}d!", result);
534         result = window_->AdjustKeyboardLayout(keyboardLayoutParams_);
535         IMSA_HILOGE("restore layout param, result: %{public}d", result);
536         return ErrorCode::ERROR_WINDOW_MANAGER;
537     }
538     SetHotAreas(hotAreas);
539     UpdateLayoutInfo(panelFlag, {}, params, wmsParams, true);
540     UpdateResizeParams();
541     IMSA_HILOGI("success, type/flag: %{public}d/%{public}d.", static_cast<int32_t>(panelType_),
542         static_cast<int32_t>(panelFlag_));
543     return ErrorCode::NO_ERROR;
544 }
545 
UpdateLayoutInfo(PanelFlag panelFlag,const LayoutParams & params,const EnhancedLayoutParams & enhancedParams,const KeyboardLayoutParams & wmsParams,bool isEnhanced)546 void InputMethodPanel::UpdateLayoutInfo(PanelFlag panelFlag, const LayoutParams &params,
547     const EnhancedLayoutParams &enhancedParams, const KeyboardLayoutParams &wmsParams, bool isEnhanced)
548 {
549     if (isEnhanced) {
550         enhancedLayoutParams_ = enhancedParams;
551         keyboardLayoutParams_ = wmsParams;
552     } else {
553         EnhancedLayoutParams enhancedLayoutParams = { .isFullScreen = false,
554             .portrait = { .rect = params.portraitRect },
555             .landscape = { .rect = params.landscapeRect } };
556         enhancedLayoutParams_ = std::move(enhancedLayoutParams);
557     }
558     panelFlag_ = panelFlag;
559     isInEnhancedAdjust_.store(isEnhanced);
560 }
561 
ParseEnhancedParams(PanelFlag panelFlag,const FullPanelAdjustInfo & adjustInfo,EnhancedLayoutParams & params)562 int32_t InputMethodPanel::ParseEnhancedParams(
563     PanelFlag panelFlag, const FullPanelAdjustInfo &adjustInfo, EnhancedLayoutParams &params)
564 {
565     DisplaySize display;
566     auto ret = GetDisplaySize(display);
567     if (ret != ErrorCode::NO_ERROR) {
568         IMSA_HILOGE("failed to GetDisplaySize ret: %{public}d", ret);
569         return ret;
570     }
571     ret = RectifyRect(params.isFullScreen, params.portrait, display.portrait, panelFlag, adjustInfo.portrait);
572     if (ret != ErrorCode::NO_ERROR) {
573         IMSA_HILOGE("RectifyRect portrait failed, ret: %{public}d", ret);
574         return ret;
575     }
576     ret = RectifyRect(params.isFullScreen, params.landscape, display.landscape, panelFlag, adjustInfo.landscape);
577     if (ret != ErrorCode::NO_ERROR) {
578         IMSA_HILOGE("RectifyRect landscape failed, ret: %{public}d", ret);
579         return ret;
580     }
581     ret = CalculateAvoidHeight(params.portrait, display.portrait, panelFlag, adjustInfo.portrait);
582     if (ret != ErrorCode::NO_ERROR) {
583         IMSA_HILOGE("CalculateAvoidHeight portrait failed, ret: %{public}d", ret);
584         return ret;
585     }
586     ret = CalculateAvoidHeight(params.landscape, display.landscape, panelFlag, adjustInfo.landscape);
587     if (ret != ErrorCode::NO_ERROR) {
588         IMSA_HILOGE("CalculateAvoidHeight landscape failed, ret: %{public}d", ret);
589         return ret;
590     }
591     IMSA_HILOGD("success, portrait: %{public}s, landscape: %{public}s", params.portrait.ToString().c_str(),
592         params.landscape.ToString().c_str());
593     return ErrorCode::NO_ERROR;
594 }
595 
IsRectValid(const Rosen::Rect & rect,const WindowSize & displaySize)596 bool InputMethodPanel::IsRectValid(const Rosen::Rect &rect, const WindowSize &displaySize)
597 {
598     if (rect.posX_ < 0 || rect.posY_ < 0) {
599         IMSA_HILOGE("posX_ and posY_ cannot be less than 0!");
600         return false;
601     }
602     if (rect.width_ > INT32_MAX || rect.height_ > INT32_MAX) {
603         IMSA_HILOGE("width or height over maximum!");
604         return false;
605     }
606     if (rect.width_ > displaySize.width || rect.height_ > displaySize.height) {
607         IMSA_HILOGE("invalid width or height, target: %{public}u/%{public}u, display: %{public}u/%{public}u",
608             rect.width_, rect.height_, displaySize.width, displaySize.height);
609         return false;
610     }
611     return true;
612 }
613 
RectifyRect(bool isFullScreen,EnhancedLayoutParam & layoutParam,const WindowSize & displaySize,PanelFlag panelFlag,const PanelAdjustInfo & adjustInfo)614 int32_t InputMethodPanel::RectifyRect(bool isFullScreen, EnhancedLayoutParam &layoutParam,
615     const WindowSize &displaySize, PanelFlag panelFlag, const PanelAdjustInfo &adjustInfo)
616 {
617     if (isFullScreen) {
618         layoutParam.rect = { ORIGIN_POS_X, ORIGIN_POS_Y, displaySize.width, displaySize.height };
619         return ErrorCode::NO_ERROR;
620     }
621     if (!IsRectValid(layoutParam.rect, displaySize)) {
622         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
623     }
624     layoutParam.rect.height_ = std::max(layoutParam.rect.height_, static_cast<uint32_t>(adjustInfo.bottom));
625     if (panelFlag == PanelFlag::FLG_FIXED) {
626         layoutParam.rect = { FIXED_PANEL_POS_X, static_cast<int32_t>(displaySize.height - layoutParam.rect.height_),
627             displaySize.width, layoutParam.rect.height_ };
628     }
629     return ErrorCode::NO_ERROR;
630 }
631 
CalculateAvoidHeight(EnhancedLayoutParam & layoutParam,const WindowSize & displaySize,PanelFlag panelFlag,const PanelAdjustInfo & adjustInfo)632 int32_t InputMethodPanel::CalculateAvoidHeight(EnhancedLayoutParam &layoutParam, const WindowSize &displaySize,
633     PanelFlag panelFlag, const PanelAdjustInfo &adjustInfo)
634 {
635     if (layoutParam.avoidY < 0 || layoutParam.avoidY > INT32_MAX) {
636         IMSA_HILOGE("invalid avoidY");
637         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
638     }
639     if (static_cast<uint32_t>(layoutParam.avoidY) > layoutParam.rect.height_) {
640         IMSA_HILOGE(
641             "invalid avoidY %{public}d, keyboard height %{public}u", layoutParam.avoidY, layoutParam.rect.height_);
642         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
643     }
644     auto ratio = panelFlag == PanelFlag::FLG_FIXED ? FIXED_SOFT_KEYBOARD_PANEL_RATIO
645                                                    : NON_FIXED_SOFT_KEYBOARD_PANEL_RATIO;
646     uint32_t avoidHeight = layoutParam.rect.height_ -  static_cast<uint32_t>(layoutParam.avoidY);
647     if (static_cast<float>(avoidHeight) > displaySize.height * ratio) {
648         IMSA_HILOGE("invalid avoidY: %{public}d, avoidHeight: %{public}u, displayHeight: %{public}u",
649             layoutParam.avoidY, avoidHeight, displaySize.height);
650         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
651     }
652     if (avoidHeight < static_cast<uint32_t>(adjustInfo.bottom)) {
653         avoidHeight = adjustInfo.bottom;
654         layoutParam.avoidY = static_cast<int32_t>(layoutParam.rect.height_) - static_cast<int32_t>(avoidHeight);
655         IMSA_HILOGI("rectify avoidY to %{public}d", layoutParam.avoidY);
656     }
657     layoutParam.avoidHeight = avoidHeight;
658     return ErrorCode::NO_ERROR;
659 }
660 
UpdateHotAreas()661 void InputMethodPanel::UpdateHotAreas()
662 {
663     auto hotAreas = GetHotAreas();
664     if (!hotAreas.isSet) {
665         IMSA_HILOGD("hot area is not customized, no need to update");
666         return;
667     }
668     FullPanelAdjustInfo adjustInfo;
669     auto ret = GetAdjustInfo(panelFlag_, adjustInfo);
670     if (ret != ErrorCode::NO_ERROR) {
671         IMSA_HILOGE("GetAdjustInfo failed ret: %{public}d", ret);
672         return;
673     }
674     CalculateDefaultHotArea(keyboardLayoutParams_.LandscapeKeyboardRect_, keyboardLayoutParams_.LandscapePanelRect_,
675         adjustInfo.landscape, hotAreas.landscape);
676     CalculateDefaultHotArea(keyboardLayoutParams_.PortraitKeyboardRect_, keyboardLayoutParams_.PortraitPanelRect_,
677         adjustInfo.portrait, hotAreas.portrait);
678     auto wmsHotAreas = ConvertToWMSHotArea(hotAreas);
679     WMError result = window_->SetKeyboardTouchHotAreas(wmsHotAreas);
680     if (result != WMError::WM_OK) {
681         IMSA_HILOGE("SetKeyboardTouchHotAreas error, err: %{public}d!", result);
682         return;
683     }
684     SetHotAreas(hotAreas);
685     IMSA_HILOGI("success, portrait: %{public}s, landscape: %{public}s",
686         HotArea::ToString(hotAreas.portrait.keyboardHotArea).c_str(),
687         HotArea::ToString(hotAreas.landscape.keyboardHotArea).c_str());
688 }
689 
CalculateHotAreas(const EnhancedLayoutParams & enhancedParams,const Rosen::KeyboardLayoutParams & params,const FullPanelAdjustInfo & adjustInfo,HotAreas & hotAreas)690 void InputMethodPanel::CalculateHotAreas(const EnhancedLayoutParams &enhancedParams,
691     const Rosen::KeyboardLayoutParams &params, const FullPanelAdjustInfo &adjustInfo, HotAreas &hotAreas)
692 {
693     if (isInEnhancedAdjust_.load()) {
694         CalculateEnhancedHotArea(enhancedParams.portrait, adjustInfo.portrait, hotAreas.portrait);
695         CalculateEnhancedHotArea(enhancedParams.landscape, adjustInfo.landscape, hotAreas.landscape);
696     } else {
697         CalculateHotArea(
698             params.PortraitKeyboardRect_, params.PortraitPanelRect_, adjustInfo.portrait, hotAreas.portrait);
699         CalculateHotArea(
700             params.LandscapeKeyboardRect_, params.LandscapePanelRect_, adjustInfo.landscape, hotAreas.landscape);
701     }
702     hotAreas.isSet = true;
703     IMSA_HILOGD("portrait keyboard: %{public}s, panel: %{public}s",
704         HotArea::ToString(hotAreas.portrait.keyboardHotArea).c_str(),
705         HotArea::ToString(hotAreas.portrait.panelHotArea).c_str());
706     IMSA_HILOGD("landscape keyboard: %{public}s, panel: %{public}s",
707         HotArea::ToString(hotAreas.landscape.keyboardHotArea).c_str(),
708         HotArea::ToString(hotAreas.landscape.panelHotArea).c_str());
709 }
710 
CalculateHotArea(const Rosen::Rect & keyboard,const Rosen::Rect & panel,const PanelAdjustInfo & adjustInfo,HotArea & hotArea)711 void InputMethodPanel::CalculateHotArea(
712     const Rosen::Rect &keyboard, const Rosen::Rect &panel, const PanelAdjustInfo &adjustInfo, HotArea &hotArea)
713 {
714     // calculate keyboard hot area
715     if (hotArea.keyboardHotArea.empty()) {
716         hotArea.keyboardHotArea.push_back({ ORIGIN_POS_X, ORIGIN_POS_Y, keyboard.width_, keyboard.height_ });
717     }
718     std::vector<Rosen::Rect> availableAreas = { { { ORIGIN_POS_X, ORIGIN_POS_Y, keyboard.width_, keyboard.height_ } } };
719     RectifyAreas(availableAreas, hotArea.keyboardHotArea);
720     // calculate panel hot area
721     Rosen::Rect left = { ORIGIN_POS_X, ORIGIN_POS_Y, static_cast<uint32_t>(adjustInfo.left), panel.height_ };
722     Rosen::Rect right = { .posX_ = static_cast<int32_t>(panel.width_) - adjustInfo.right,
723         .posY_ = ORIGIN_POS_Y,
724         .width_ = static_cast<uint32_t>(adjustInfo.right),
725         .height_ = panel.height_ };
726     Rosen::Rect bottom = { .posX_ = ORIGIN_POS_X,
727         .posY_ = static_cast<int32_t>(panel.height_) - adjustInfo.bottom,
728         .width_ = panel.width_,
729         .height_ = static_cast<uint32_t>(adjustInfo.bottom) };
730     hotArea.panelHotArea = { left, right, bottom };
731 }
732 
CalculateEnhancedHotArea(const EnhancedLayoutParam & layout,const PanelAdjustInfo & adjustInfo,HotArea & hotArea)733 void InputMethodPanel::CalculateEnhancedHotArea(
734     const EnhancedLayoutParam &layout, const PanelAdjustInfo &adjustInfo, HotArea &hotArea)
735 {
736     // calculate keyboard hot area
737     if (hotArea.keyboardHotArea.empty()) {
738         hotArea.keyboardHotArea.push_back({ ORIGIN_POS_X, ORIGIN_POS_Y, layout.rect.width_, layout.rect.height_ });
739     }
740     std::vector<Rosen::Rect> availableAreas;
741     availableAreas.push_back({ ORIGIN_POS_X, ORIGIN_POS_Y, layout.rect.width_, static_cast<uint32_t>(layout.avoidY) });
742     availableAreas.push_back({ .posX_ = adjustInfo.left,
743         .posY_ = layout.avoidY,
744         .width_ = SafeSubtract(layout.rect.width_, static_cast<uint32_t>(adjustInfo.left + adjustInfo.right)),
745         .height_ = SafeSubtract(layout.avoidHeight, static_cast<uint32_t>(adjustInfo.bottom)) });
746     RectifyAreas(availableAreas, hotArea.keyboardHotArea);
747     // calculate panel hot area
748     Rosen::Rect left = { ORIGIN_POS_X, layout.avoidY, static_cast<uint32_t>(adjustInfo.left), layout.avoidHeight };
749     Rosen::Rect right = { .posX_ = static_cast<int32_t>(layout.rect.width_) - adjustInfo.right,
750         .posY_ = layout.avoidY,
751         .width_ = static_cast<uint32_t>(adjustInfo.right),
752         .height_ = layout.avoidHeight };
753     Rosen::Rect bottom = { .posX_ = ORIGIN_POS_X,
754         .posY_ = static_cast<int32_t>(layout.rect.height_) - adjustInfo.bottom,
755         .width_ = layout.rect.width_,
756         .height_ = static_cast<uint32_t>(adjustInfo.bottom) };
757     hotArea.panelHotArea = { left, right, bottom };
758 }
759 
CalculateDefaultHotArea(const Rosen::Rect & keyboard,const Rosen::Rect & panel,const PanelAdjustInfo & adjustInfo,HotArea & hotArea)760 void InputMethodPanel::CalculateDefaultHotArea(
761     const Rosen::Rect &keyboard, const Rosen::Rect &panel, const PanelAdjustInfo &adjustInfo, HotArea &hotArea)
762 {
763     // calculate keyboard hot area
764     hotArea.keyboardHotArea.clear();
765     hotArea.keyboardHotArea.push_back({ ORIGIN_POS_X, ORIGIN_POS_Y, keyboard.width_, keyboard.height_ });
766     // calculate panel hot area
767     Rosen::Rect left = { ORIGIN_POS_X, ORIGIN_POS_Y, static_cast<uint32_t>(adjustInfo.left), panel.height_ };
768     Rosen::Rect right = { .posX_ = static_cast<int32_t>(panel.width_) - adjustInfo.right,
769         .posY_ = ORIGIN_POS_Y,
770         .width_ = static_cast<uint32_t>(adjustInfo.right),
771         .height_ = panel.height_ };
772     Rosen::Rect bottom = { .posX_ = ORIGIN_POS_X,
773         .posY_ = static_cast<int32_t>(panel.height_) - adjustInfo.bottom,
774         .width_ = panel.width_,
775         .height_ = static_cast<uint32_t>(adjustInfo.bottom) };
776     hotArea.panelHotArea = { left, right, bottom };
777 }
778 
RectifyAreas(const std::vector<Rosen::Rect> availableAreas,std::vector<Rosen::Rect> & areas)779 void InputMethodPanel::RectifyAreas(const std::vector<Rosen::Rect> availableAreas, std::vector<Rosen::Rect> &areas)
780 {
781     std::vector<Rosen::Rect> validAreas;
782     for (const auto &availableArea : availableAreas) {
783         std::vector<Rosen::Rect> modifiedAreas;
784         for (const auto &area : areas) {
785             auto inter = GetRectIntersection(area, availableArea);
786             if (inter.width_ != 0 && inter.height_ != 0) {
787                 modifiedAreas.push_back(inter);
788             }
789         }
790         validAreas.insert(validAreas.end(), modifiedAreas.begin(), modifiedAreas.end());
791     }
792     areas = std::move(validAreas);
793     // If no valid area, set the region size to 0.
794     if (areas.empty()) {
795         areas.push_back({ 0, 0, 0, 0 });
796     }
797 }
798 
GetRectIntersection(Rosen::Rect a,Rosen::Rect b)799 Rosen::Rect InputMethodPanel::GetRectIntersection(Rosen::Rect a, Rosen::Rect b)
800 {
801     int32_t left = std::max(a.posX_, b.posX_);
802     int32_t right = std::min(a.posX_ + static_cast<int32_t>(a.width_), b.posX_ + static_cast<int32_t>(b.width_));
803     int32_t top = std::max(a.posY_, b.posY_);
804     int32_t bottom = std::min(a.posY_ + static_cast<int32_t>(a.height_), b.posY_ + static_cast<int32_t>(b.height_));
805     if (left < right && top < bottom) {
806         return { left, top, static_cast<uint32_t>(right - left), static_cast<uint32_t>(bottom - top) };
807     } else {
808         return { 0, 0, 0, 0 };
809     }
810 }
811 
SafeSubtract(uint32_t minuend,uint32_t subtrahend)812 uint32_t InputMethodPanel::SafeSubtract(uint32_t minuend, uint32_t subtrahend)
813 {
814     if (minuend < subtrahend) {
815         return 0;
816     }
817     return minuend - subtrahend;
818 }
819 
UpdateRegion(std::vector<Rosen::Rect> region)820 int32_t InputMethodPanel::UpdateRegion(std::vector<Rosen::Rect> region)
821 {
822     if (window_ == nullptr) {
823         IMSA_HILOGE("window_ is nullptr!");
824         return ErrorCode::ERROR_WINDOW_MANAGER;
825     }
826     if (panelType_ != PanelType::SOFT_KEYBOARD) {
827         IMSA_HILOGE("not soft keyboard panel: %{public}d", panelType_);
828         return ErrorCode::ERROR_INVALID_PANEL_TYPE;
829     }
830     if (panelFlag_ != PanelFlag::FLG_FIXED && panelFlag_ != PanelFlag::FLG_FLOATING) {
831         IMSA_HILOGE("flag not fixed or floating: %{public}d", panelFlag_);
832         return ErrorCode::ERROR_INVALID_PANEL_FLAG;
833     }
834     FullPanelAdjustInfo adjustInfo;
835     auto ret = GetAdjustInfo(panelFlag_, adjustInfo);
836     if (ret != ErrorCode::NO_ERROR) {
837         IMSA_HILOGE("GetAdjustInfo failed ret: %{public}d", ret);
838         return ret;
839     }
840     IMSA_HILOGD("region: %{public}s", HotArea::ToString(region).c_str());
841     auto hotAreas = GetHotAreas();
842     bool isPortrait = IsDisplayPortrait();
843     if (isPortrait) {
844         hotAreas.portrait.keyboardHotArea = region;
845     } else {
846         hotAreas.landscape.keyboardHotArea = region;
847     }
848     CalculateHotAreas(enhancedLayoutParams_, keyboardLayoutParams_, adjustInfo, hotAreas);
849     auto wmsHotAreas = ConvertToWMSHotArea(hotAreas);
850     WMError result = window_->SetKeyboardTouchHotAreas(wmsHotAreas);
851     if (result != WMError::WM_OK) {
852         IMSA_HILOGE("SetKeyboardTouchHotAreas error, err: %{public}d!", result);
853         return ErrorCode::ERROR_WINDOW_MANAGER;
854     }
855     SetHotAreas(hotAreas);
856     if (isPortrait) {
857         IMSA_HILOGI("success, portrait: %{public}s", HotArea::ToString(hotAreas.portrait.keyboardHotArea).c_str());
858     } else {
859         IMSA_HILOGI("success, landscape: %{public}s", HotArea::ToString(hotAreas.landscape.keyboardHotArea).c_str());
860     }
861     return ErrorCode::NO_ERROR;
862 }
863 
InitAdjustInfo()864 int32_t InputMethodPanel::InitAdjustInfo()
865 {
866     if (isAdjustInfoInitialized_.load()) {
867         return ErrorCode::NO_ERROR;
868     }
869     std::lock_guard<std::mutex> initLk(adjustInfoInitLock_);
870     if (isAdjustInfoInitialized_.load()) {
871         return ErrorCode::NO_ERROR;
872     }
873     std::vector<SysPanelAdjust> configs;
874     auto isSuccess = SysCfgParser::ParsePanelAdjust(configs);
875     if (!isSuccess) {
876         isAdjustInfoInitialized_.store(true);
877         return ErrorCode::NO_ERROR;
878     }
879     float densityDpi = 0;
880     if (GetDensityDpi(densityDpi) != ErrorCode::NO_ERROR) {
881         IMSA_HILOGE("failed to get density dpi");
882         return ErrorCode::ERROR_WINDOW_MANAGER;
883     }
884     std::lock_guard<std::mutex> lk(panelAdjustLock_);
885     panelAdjust_.clear();
886     for (const auto &config : configs) {
887         PanelAdjustInfo info = {
888             .top = static_cast<int32_t>(config.top * densityDpi),
889             .left = static_cast<int32_t>(config.left * densityDpi),
890             .right = static_cast<int32_t>(config.right * densityDpi),
891             .bottom = static_cast<int32_t>(config.bottom * densityDpi) };
892         panelAdjust_.insert({ config.style, info });
893     }
894     isAdjustInfoInitialized_.store(true);
895     return ErrorCode::NO_ERROR;
896 }
897 
ParsePanelRect(const PanelFlag panelFlag,const LayoutParams & layoutParams)898 int32_t InputMethodPanel::ParsePanelRect(const PanelFlag panelFlag, const LayoutParams &layoutParams)
899 {
900     keyboardLayoutParams_.landscapeAvoidHeight_ = DEFAULT_AVOID_HEIGHT;
901     keyboardLayoutParams_.portraitAvoidHeight_ = DEFAULT_AVOID_HEIGHT;
902     std::vector<SysPanelAdjust> configs;
903     auto isSuccess = SysCfgParser::ParsePanelAdjust(configs);
904     if (isSuccess) {
905         InitAdjustInfo();
906     } else {
907         IMSA_HILOGE("there is no configuration file.");
908         auto ret = CalculateNoConfigRect(panelFlag, layoutParams);
909         if (ret != ErrorCode::NO_ERROR) {
910             IMSA_HILOGE("failed to calculate NoConfigRect, err: %{public}d!", ret);
911             return ret;
912         }
913         return ErrorCode::NO_ERROR;
914     }
915     std::tuple<std::vector<std::string>, std::vector<std::string>> keys = GetScreenStatus(panelFlag);
916     auto ret = GetSysPanelAdjust(panelFlag, keys, layoutParams);
917     if (ret != ErrorCode::NO_ERROR) {
918         IMSA_HILOGE("GetSysPanelAdjust failed!");
919         return ErrorCode::ERROR_BAD_PARAMETERS;
920     }
921     return ErrorCode::NO_ERROR;
922 }
923 
CalculateNoConfigRect(const PanelFlag panelFlag,const LayoutParams & layoutParams)924 int32_t InputMethodPanel::CalculateNoConfigRect(const PanelFlag panelFlag, const LayoutParams &layoutParams)
925 {
926     if (panelFlag == PanelFlag::FLG_FIXED) {
927         keyboardLayoutParams_.gravity_ = WindowGravity::WINDOW_GRAVITY_BOTTOM;
928         WindowSize portraitDisplaySize;
929         if (!GetDisplaySize(true, portraitDisplaySize)) {
930             IMSA_HILOGE("GetPortraitDisplaySize failed!");
931             return ErrorCode::ERROR_WINDOW_MANAGER;
932         }
933         keyboardLayoutParams_.PortraitPanelRect_.width_ = portraitDisplaySize.width;
934         keyboardLayoutParams_.PortraitPanelRect_.height_ = layoutParams.portraitRect.height_;
935         keyboardLayoutParams_.PortraitPanelRect_.posY_ =
936             static_cast<int32_t>(portraitDisplaySize.height - keyboardLayoutParams_.PortraitPanelRect_.height_);
937         keyboardLayoutParams_.PortraitPanelRect_.posX_ = NUMBER_ZERO;
938         //fixed Portraitkeyboard
939         keyboardLayoutParams_.PortraitKeyboardRect_.width_ = keyboardLayoutParams_.PortraitPanelRect_.width_;
940         keyboardLayoutParams_.PortraitKeyboardRect_.height_ = keyboardLayoutParams_.PortraitPanelRect_.height_;
941         keyboardLayoutParams_.PortraitKeyboardRect_.posY_ = keyboardLayoutParams_.PortraitPanelRect_.posY_;
942         keyboardLayoutParams_.PortraitKeyboardRect_.posX_ = keyboardLayoutParams_.PortraitPanelRect_.posX_;
943 
944         WindowSize landscapeDisplaySize;
945         if (!GetDisplaySize(false, landscapeDisplaySize)) {
946             IMSA_HILOGE("GetLandscapeDisplaySize failed!");
947             return ErrorCode::ERROR_WINDOW_MANAGER;
948         }
949         keyboardLayoutParams_.LandscapePanelRect_.width_ = landscapeDisplaySize.width;
950         keyboardLayoutParams_.LandscapePanelRect_.height_ = layoutParams.landscapeRect.height_;
951         keyboardLayoutParams_.LandscapePanelRect_.posY_ =
952             static_cast<int32_t>(landscapeDisplaySize.height - keyboardLayoutParams_.LandscapePanelRect_.height_);
953         keyboardLayoutParams_.LandscapePanelRect_.posX_ = NUMBER_ZERO;
954         //Landscapekeyboard
955         keyboardLayoutParams_.LandscapeKeyboardRect_.width_ = keyboardLayoutParams_.LandscapePanelRect_.width_;
956         keyboardLayoutParams_.LandscapeKeyboardRect_.height_ = keyboardLayoutParams_.LandscapePanelRect_.height_;
957         keyboardLayoutParams_.LandscapeKeyboardRect_.posY_ = keyboardLayoutParams_.LandscapePanelRect_.posY_;
958         keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ = keyboardLayoutParams_.LandscapePanelRect_.posX_;
959     } else {
960         keyboardLayoutParams_.gravity_ = WindowGravity::WINDOW_GRAVITY_FLOAT;
961         keyboardLayoutParams_.LandscapeKeyboardRect_ = layoutParams.landscapeRect;
962         keyboardLayoutParams_.PortraitKeyboardRect_ = layoutParams.portraitRect;
963         keyboardLayoutParams_.LandscapePanelRect_ = layoutParams.landscapeRect;
964         keyboardLayoutParams_.PortraitPanelRect_ = layoutParams.portraitRect;
965     }
966     return ErrorCode::NO_ERROR;
967 }
968 
GetScreenStatus(const PanelFlag panelFlag)969 std::tuple<std::vector<std::string>, std::vector<std::string>> InputMethodPanel::GetScreenStatus(
970     const PanelFlag panelFlag)
971 {
972     std::string flag;
973     std::string foldStatus = "default";
974     if (panelFlag == PanelFlag::FLG_FIXED) {
975         flag = "fix";
976         keyboardLayoutParams_.gravity_ = WindowGravity::WINDOW_GRAVITY_BOTTOM;
977     } else {
978         flag = "floating";
979         keyboardLayoutParams_.gravity_ = WindowGravity::WINDOW_GRAVITY_FLOAT;
980     }
981     if (Rosen::DisplayManager::GetInstance().IsFoldable() &&
982         Rosen::DisplayManager::GetInstance().GetFoldStatus() != Rosen::FoldStatus::FOLDED) {
983         foldStatus = "foldable";
984     }
985     std::vector<std::string> lanPanel = { flag, foldStatus, "landscape" };
986     std::vector<std::string> porPanel = { flag, foldStatus, "portrait" };
987     return std::make_tuple(lanPanel, porPanel);
988 }
989 
GetAdjustInfo(PanelFlag panelFlag,FullPanelAdjustInfo & fullPanelAdjustInfo)990 int32_t InputMethodPanel::GetAdjustInfo(PanelFlag panelFlag, FullPanelAdjustInfo &fullPanelAdjustInfo)
991 {
992     int32_t ret = InitAdjustInfo();
993     if (ret != ErrorCode::NO_ERROR) {
994         IMSA_HILOGE("failed to init adjust info, ret: %{public}d", ret);
995         return ret;
996     }
997     auto keys = GetScreenStatus(panelFlag);
998     auto landscapeKey = std::get<0>(keys);
999     auto portraitKey = std::get<1>(keys);
1000     std::lock_guard<std::mutex> lock(panelAdjustLock_);
1001     auto lanIter = panelAdjust_.find(landscapeKey);
1002     auto porIter = panelAdjust_.find(portraitKey);
1003     if (lanIter != panelAdjust_.end()) {
1004         fullPanelAdjustInfo.landscape = lanIter->second;
1005     }
1006     if (porIter != panelAdjust_.end()) {
1007         fullPanelAdjustInfo.portrait = porIter->second;
1008     }
1009     return ErrorCode::NO_ERROR;
1010 }
1011 
GetSysPanelAdjust(const PanelFlag panelFlag,std::tuple<std::vector<std::string>,std::vector<std::string>> & keys,const LayoutParams & layoutParams)1012 int32_t InputMethodPanel::GetSysPanelAdjust(const PanelFlag panelFlag,
1013     std::tuple<std::vector<std::string>, std::vector<std::string>> &keys, const LayoutParams &layoutParams)
1014 {
1015     std::lock_guard<std::mutex> lock(panelAdjustLock_);
1016     auto lanPanel = std::get<0>(keys);
1017     auto porPanel = std::get<1>(keys);
1018     auto lanIter = panelAdjust_.find(lanPanel);
1019     auto porIter = panelAdjust_.find(porPanel);
1020     if (lanIter == panelAdjust_.end() || porIter == panelAdjust_.end()) {
1021         IMSA_HILOGE("lanIter or porIter not supported!");
1022         return ErrorCode::ERROR_BAD_PARAMETERS;
1023     }
1024     auto lanIterValue = lanIter->second;
1025     auto porIterValue = porIter->second;
1026     keyboardLayoutParams_.LandscapeKeyboardRect_ = layoutParams.landscapeRect;
1027     keyboardLayoutParams_.PortraitKeyboardRect_ = layoutParams.portraitRect;
1028     keyboardLayoutParams_.LandscapePanelRect_ = layoutParams.landscapeRect;
1029     keyboardLayoutParams_.PortraitPanelRect_ = layoutParams.portraitRect;
1030     return CalculatePanelRect(panelFlag, lanIterValue, porIterValue, layoutParams);
1031 }
1032 
CalculatePanelRect(const PanelFlag panelFlag,PanelAdjustInfo & lanIterValue,PanelAdjustInfo & porIterValue,const LayoutParams & layoutParams)1033 int32_t InputMethodPanel::CalculatePanelRect(const PanelFlag panelFlag, PanelAdjustInfo &lanIterValue,
1034     PanelAdjustInfo &porIterValue, const LayoutParams &layoutParams)
1035 {
1036     auto instance = InputMethodAbility::GetInstance();
1037     if (instance != nullptr && instance->GetInputAttribute().GetSecurityFlag()) {
1038         IMSA_HILOGI("The security keyboard is handled according to no configuration file");
1039         return CalculateNoConfigRect(panelFlag, layoutParams);
1040     }
1041     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
1042     if (defaultDisplay == nullptr) {
1043         IMSA_HILOGE("GetDefaultDisplay failed!");
1044         return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
1045     }
1046     if (panelFlag == PanelFlag::FLG_FIXED) {
1047         //fixed PortraitPanel
1048         WindowSize portraitDisplaySize;
1049         if (!GetDisplaySize(true, portraitDisplaySize)) {
1050             IMSA_HILOGE("GetDisplaySize failed!");
1051             return ErrorCode::ERROR_WINDOW_MANAGER;
1052         }
1053         keyboardLayoutParams_.PortraitPanelRect_.width_ = portraitDisplaySize.width;
1054         keyboardLayoutParams_.PortraitPanelRect_.height_ = layoutParams.portraitRect.height_ +
1055             static_cast<uint32_t>(porIterValue.top + porIterValue.bottom);
1056         if (keyboardLayoutParams_.PortraitPanelRect_.height_ >
1057             portraitDisplaySize.height * FIXED_SOFT_KEYBOARD_PANEL_RATIO) {
1058             keyboardLayoutParams_.PortraitPanelRect_.height_ =
1059                 portraitDisplaySize.height * FIXED_SOFT_KEYBOARD_PANEL_RATIO;
1060         }
1061         keyboardLayoutParams_.PortraitPanelRect_.posY_ =
1062             static_cast<int32_t>(portraitDisplaySize.height - keyboardLayoutParams_.PortraitPanelRect_.height_);
1063         keyboardLayoutParams_.PortraitPanelRect_.posX_ = NUMBER_ZERO;
1064         //fixed Portraitkeyboard
1065         keyboardLayoutParams_.PortraitKeyboardRect_.width_ = keyboardLayoutParams_.PortraitPanelRect_.width_ -
1066             static_cast<uint32_t>(porIterValue.left + porIterValue.right);
1067         keyboardLayoutParams_.PortraitKeyboardRect_.height_ = keyboardLayoutParams_.PortraitPanelRect_.height_ -
1068             static_cast<uint32_t>(porIterValue.top + porIterValue.bottom);
1069         keyboardLayoutParams_.PortraitKeyboardRect_.posY_ =
1070             keyboardLayoutParams_.PortraitPanelRect_.posY_ + static_cast<int32_t>(porIterValue.top);
1071         keyboardLayoutParams_.PortraitKeyboardRect_.posX_ =
1072             keyboardLayoutParams_.PortraitPanelRect_.posX_ + static_cast<int32_t>(porIterValue.left);
1073         return CalculateLandscapeRect(defaultDisplay, layoutParams, lanIterValue);
1074     }
1075     return CalculateFloatRect(layoutParams, lanIterValue, porIterValue);
1076 }
1077 
CalculateFloatRect(const LayoutParams & layoutParams,PanelAdjustInfo & lanIterValue,PanelAdjustInfo & porIterValue)1078 int32_t InputMethodPanel::CalculateFloatRect(
1079     const LayoutParams &layoutParams, PanelAdjustInfo &lanIterValue, PanelAdjustInfo &porIterValue)
1080 {
1081     //portrait floating keyboard
1082     keyboardLayoutParams_.PortraitKeyboardRect_.width_ = layoutParams.portraitRect.width_;
1083     keyboardLayoutParams_.PortraitKeyboardRect_.height_ = layoutParams.portraitRect.height_;
1084     keyboardLayoutParams_.PortraitKeyboardRect_.posY_ = layoutParams.portraitRect.posY_;
1085     keyboardLayoutParams_.PortraitKeyboardRect_.posX_ = layoutParams.portraitRect.posX_;
1086     //portrait floating panel
1087     keyboardLayoutParams_.PortraitPanelRect_.width_ = keyboardLayoutParams_.PortraitKeyboardRect_.width_ +
1088         static_cast<uint32_t>(porIterValue.left + porIterValue.right);
1089     keyboardLayoutParams_.PortraitPanelRect_.height_ = keyboardLayoutParams_.PortraitKeyboardRect_.height_ +
1090         static_cast<uint32_t>(porIterValue.top + porIterValue.bottom);
1091     keyboardLayoutParams_.PortraitPanelRect_.posY_ =
1092         keyboardLayoutParams_.PortraitKeyboardRect_.posY_ - static_cast<int32_t>(porIterValue.top);
1093     keyboardLayoutParams_.PortraitPanelRect_.posX_ =
1094         keyboardLayoutParams_.PortraitKeyboardRect_.posX_ - static_cast<int32_t>(porIterValue.left);
1095 
1096     //landscape floating keyboard
1097     keyboardLayoutParams_.LandscapeKeyboardRect_.width_ = layoutParams.landscapeRect.width_;
1098     keyboardLayoutParams_.LandscapeKeyboardRect_.height_ = layoutParams.landscapeRect.height_;
1099     keyboardLayoutParams_.LandscapeKeyboardRect_.posY_ = layoutParams.landscapeRect.posY_;
1100     keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ = layoutParams.landscapeRect.posX_;
1101     //landscape floating panel
1102     keyboardLayoutParams_.LandscapePanelRect_.width_ = keyboardLayoutParams_.LandscapeKeyboardRect_.width_ +
1103         static_cast<uint32_t>(lanIterValue.left + lanIterValue.right);
1104     keyboardLayoutParams_.LandscapePanelRect_.height_ = keyboardLayoutParams_.LandscapeKeyboardRect_.height_ +
1105         static_cast<uint32_t>(lanIterValue.top + lanIterValue.bottom);
1106     keyboardLayoutParams_.LandscapePanelRect_.posY_ =
1107         keyboardLayoutParams_.LandscapeKeyboardRect_.posY_ - static_cast<int32_t>(lanIterValue.top);
1108     keyboardLayoutParams_.LandscapePanelRect_.posX_ =
1109         keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ - static_cast<int32_t>(lanIterValue.left);
1110     return ErrorCode::NO_ERROR;
1111 }
1112 
CalculateLandscapeRect(sptr<OHOS::Rosen::Display> & defaultDisplay,const LayoutParams & layoutParams,PanelAdjustInfo & lanIterValue)1113 int32_t InputMethodPanel::CalculateLandscapeRect(sptr<OHOS::Rosen::Display> &defaultDisplay,
1114     const LayoutParams &layoutParams, PanelAdjustInfo &lanIterValue)
1115 {
1116     //LandscapePanel
1117     WindowSize landscapeDisplaySize;
1118     if (!GetDisplaySize(false, landscapeDisplaySize)) {
1119         IMSA_HILOGE("GetDisplaySize failed!");
1120         return ErrorCode::ERROR_WINDOW_MANAGER;
1121     }
1122     keyboardLayoutParams_.LandscapePanelRect_.width_ = landscapeDisplaySize.width;
1123     keyboardLayoutParams_.LandscapePanelRect_.height_ = layoutParams.landscapeRect.height_ +
1124         static_cast<uint32_t>(lanIterValue.top + lanIterValue.bottom);
1125     if (keyboardLayoutParams_.LandscapePanelRect_.height_ >
1126         landscapeDisplaySize.height * FIXED_SOFT_KEYBOARD_PANEL_RATIO) {
1127         keyboardLayoutParams_.LandscapePanelRect_.height_ =
1128             landscapeDisplaySize.height * FIXED_SOFT_KEYBOARD_PANEL_RATIO;
1129     }
1130     keyboardLayoutParams_.LandscapePanelRect_.posY_ =
1131         static_cast<int32_t>(landscapeDisplaySize.height - keyboardLayoutParams_.LandscapePanelRect_.height_);
1132     keyboardLayoutParams_.LandscapePanelRect_.posX_ = NUMBER_ZERO;
1133     //Landscapekeyboard
1134     keyboardLayoutParams_.LandscapeKeyboardRect_.width_ = keyboardLayoutParams_.LandscapePanelRect_.width_ -
1135         static_cast<uint32_t>(lanIterValue.left + lanIterValue.right);
1136     keyboardLayoutParams_.LandscapeKeyboardRect_.height_ = keyboardLayoutParams_.LandscapePanelRect_.height_ -
1137         static_cast<uint32_t>(lanIterValue.top + lanIterValue.bottom);
1138     keyboardLayoutParams_.LandscapeKeyboardRect_.posY_ =
1139         keyboardLayoutParams_.LandscapePanelRect_.posY_ + static_cast<int32_t>(lanIterValue.top);
1140     keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ =
1141         keyboardLayoutParams_.LandscapePanelRect_.posX_ + static_cast<int32_t>(lanIterValue.left);
1142     sptr<Rosen::CutoutInfo> cutoutInfo = defaultDisplay->GetCutoutInfo();
1143     if (cutoutInfo != nullptr) {
1144         if (Rosen::DisplayManager::GetInstance().IsFoldable() &&
1145             Rosen::DisplayManager::GetInstance().GetFoldStatus() != Rosen::FoldStatus::FOLDED) {
1146             return ErrorCode::NO_ERROR;
1147         }
1148         keyboardLayoutParams_.LandscapeKeyboardRect_.width_ = keyboardLayoutParams_.LandscapeKeyboardRect_.width_ -
1149             static_cast<uint32_t>((CUTOUTINFO - lanIterValue.left) * NUMBER_TWO);
1150         keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ = keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ +
1151             static_cast<int32_t>((CUTOUTINFO - lanIterValue.left));
1152     }
1153     return ErrorCode::NO_ERROR;
1154 }
1155 
ChangePanelFlag(PanelFlag panelFlag)1156 int32_t InputMethodPanel::ChangePanelFlag(PanelFlag panelFlag)
1157 {
1158     if (window_ == nullptr) {
1159         IMSA_HILOGE("window_ is nullptr!");
1160         return ErrorCode::ERROR_NULL_POINTER;
1161     }
1162     if (panelFlag_ == panelFlag) {
1163         return ErrorCode::NO_ERROR;
1164     }
1165     if (panelType_ == STATUS_BAR) {
1166         IMSA_HILOGE("STATUS_BAR cannot ChangePanelFlag!");
1167         return ErrorCode::ERROR_BAD_PARAMETERS;
1168     }
1169     if (panelType_ == SOFT_KEYBOARD && panelFlag == FLG_CANDIDATE_COLUMN) {
1170         PanelStatusChangeToImc(InputWindowStatus::HIDE, { 0, 0, 0, 0 });
1171     }
1172     WindowGravity gravity = WindowGravity::WINDOW_GRAVITY_FLOAT;
1173     if (panelFlag == FLG_FIXED) {
1174         gravity = WindowGravity::WINDOW_GRAVITY_BOTTOM;
1175     } else {
1176         auto surfaceNode = window_->GetSurfaceNode();
1177         if (surfaceNode == nullptr) {
1178             IMSA_HILOGE("surfaceNode is nullptr");
1179             return ErrorCode::ERROR_NULL_POINTER;
1180         }
1181         surfaceNode->SetFrameGravity(Rosen::Gravity::TOP_LEFT);
1182         Rosen::RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
1183     }
1184     if (!isScbEnable_) {
1185         auto ret = window_->SetWindowGravity(gravity, invalidGravityPercent);
1186         if (ret == WMError::WM_OK) {
1187             panelFlag_ = panelFlag;
1188         }
1189         IMSA_HILOGI("flag: %{public}d, ret: %{public}d.", panelFlag, ret);
1190         return ret == WMError::WM_OK ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL;
1191     }
1192     keyboardLayoutParams_.gravity_ = gravity;
1193     auto ret = window_->AdjustKeyboardLayout(keyboardLayoutParams_);
1194     if (ret == WMError::WM_OK) {
1195         panelFlag_ = panelFlag;
1196     }
1197     IMSA_HILOGI("flag: %{public}d, ret: %{public}d.", panelFlag, ret);
1198     return ret == WMError::WM_OK ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL;
1199 }
1200 
GetPanelType()1201 PanelType InputMethodPanel::GetPanelType()
1202 {
1203     return panelType_;
1204 }
1205 
GetPanelFlag()1206 PanelFlag InputMethodPanel::GetPanelFlag()
1207 {
1208     return panelFlag_;
1209 }
1210 
ShowPanel()1211 int32_t InputMethodPanel::ShowPanel()
1212 {
1213     IMSA_HILOGD("InputMethodPanel start.");
1214     int32_t waitTime = 0;
1215     while (isWaitSetUiContent_ && waitTime < MAXWAITTIME) {
1216         std::this_thread::sleep_for(std::chrono::milliseconds(WAITTIME));
1217         waitTime += WAITTIME;
1218         IMSA_HILOGI("InputMethodPanel show pannel waitTime %{public}d.", waitTime);
1219     }
1220     if (window_ == nullptr) {
1221         IMSA_HILOGE("window_ is nullptr!");
1222         return ErrorCode::ERROR_NULL_POINTER;
1223     }
1224     if (IsShowing()) {
1225         IMSA_HILOGI("panel already shown.");
1226         return ErrorCode::NO_ERROR;
1227     }
1228     auto ret = WMError::WM_OK;
1229     {
1230         InputMethodSyncTrace tracer("InputMethodPanel_ShowPanel");
1231         ret = window_->ShowKeyboard(static_cast<KeyboardViewMode>(immersiveMode_));
1232     }
1233     if (ret != WMError::WM_OK) {
1234         IMSA_HILOGE("ShowPanel error, err = %{public}d", ret);
1235         return ErrorCode::ERROR_OPERATE_PANEL;
1236     }
1237     IMSA_HILOGI("success, type/flag: %{public}d/%{public}d.", static_cast<int32_t>(panelType_),
1238         static_cast<int32_t>(panelFlag_));
1239     PanelStatusChange(InputWindowStatus::SHOW);
1240     if (!isScbEnable_) {
1241         PanelStatusChangeToImc(InputWindowStatus::SHOW, window_->GetRect());
1242     }
1243     return ErrorCode::NO_ERROR;
1244 }
1245 
SetTextFieldAvoidInfo(double positionY,double height)1246 int32_t InputMethodPanel::SetTextFieldAvoidInfo(double positionY, double height)
1247 {
1248     if (window_ == nullptr) {
1249         IMSA_HILOGE("window_ is nullptr!");
1250         return ErrorCode::ERROR_NULL_POINTER;
1251     }
1252     auto ret = window_->SetTextFieldAvoidInfo(positionY, height);
1253     if (ret != WMError::WM_OK) {
1254         IMSA_HILOGE("SetTextFieldAvoidInfo error, err: %{public}d!", ret);
1255         return ErrorCode::ERROR_OPERATE_PANEL;
1256     }
1257     return ErrorCode::NO_ERROR;
1258 }
1259 
HidePanel()1260 int32_t InputMethodPanel::HidePanel()
1261 {
1262     IMSA_HILOGD("InputMethodPanel start");
1263     if (window_ == nullptr) {
1264         IMSA_HILOGE("window_ is nullptr!");
1265         return ErrorCode::ERROR_NULL_POINTER;
1266     }
1267     if (IsHidden()) {
1268         IMSA_HILOGI("panel already hidden.");
1269         return ErrorCode::NO_ERROR;
1270     }
1271     auto ret = WMError::WM_OK;
1272     {
1273         InputMethodSyncTrace tracer("InputMethodPanel_HidePanel");
1274         ret = window_->Hide();
1275     }
1276     if (ret != WMError::WM_OK) {
1277         IMSA_HILOGE("HidePanel error, err: %{public}d!", ret);
1278         return ErrorCode::ERROR_OPERATE_PANEL;
1279     }
1280     IMSA_HILOGI("success, type/flag: %{public}d/%{public}d.", static_cast<int32_t>(panelType_),
1281         static_cast<int32_t>(panelFlag_));
1282     PanelStatusChange(InputWindowStatus::HIDE);
1283     if (!isScbEnable_) {
1284         PanelStatusChangeToImc(InputWindowStatus::HIDE, { 0, 0, 0, 0 });
1285     }
1286     return ErrorCode::NO_ERROR;
1287 }
1288 
SetCallingWindow(uint32_t windowId)1289 int32_t InputMethodPanel::SetCallingWindow(uint32_t windowId)
1290 {
1291     IMSA_HILOGD("InputMethodPanel start, windowId: %{public}d.", windowId);
1292     if (window_ == nullptr) {
1293         IMSA_HILOGE("window_ is nullptr!");
1294         return ErrorCode::ERROR_PANEL_NOT_FOUND;
1295     }
1296     auto ret = window_->SetCallingWindow(windowId);
1297     IMSA_HILOGI("ret: %{public}d, windowId: %{public}u", ret, windowId);
1298     return ret == WMError::WM_OK ? ErrorCode::NO_ERROR : ErrorCode::ERROR_WINDOW_MANAGER;
1299 }
1300 
GetCallingWindowInfo(CallingWindowInfo & windowInfo)1301 int32_t InputMethodPanel::GetCallingWindowInfo(CallingWindowInfo &windowInfo)
1302 {
1303     IMSA_HILOGD("InputMethodPanel start.");
1304     if (window_ == nullptr) {
1305         IMSA_HILOGE("window_ is nullptr!");
1306         return ErrorCode::ERROR_PANEL_NOT_FOUND;
1307     }
1308     auto ret = window_->GetCallingWindowWindowStatus(windowInfo.status);
1309     if (ret != WMError::WM_OK) {
1310         IMSA_HILOGE("get status failed, ret: %{public}d!", ret);
1311         return ErrorCode::ERROR_WINDOW_MANAGER;
1312     }
1313     ret = window_->GetCallingWindowRect(windowInfo.rect);
1314     if (ret != WMError::WM_OK) {
1315         IMSA_HILOGE("get rect failed, ret: %{public}d!", ret);
1316         return ErrorCode::ERROR_WINDOW_MANAGER;
1317     }
1318     IMSA_HILOGI("status: %{public}u, rect[x/y/w/h]: [%{public}d/%{public}d/%{public}u/%{public}u].",
1319         static_cast<uint32_t>(windowInfo.status), windowInfo.rect.posX_, windowInfo.rect.posY_, windowInfo.rect.width_,
1320         windowInfo.rect.height_);
1321     return ErrorCode::NO_ERROR;
1322 }
1323 
SetPrivacyMode(bool isPrivacyMode)1324 int32_t InputMethodPanel::SetPrivacyMode(bool isPrivacyMode)
1325 {
1326     IMSA_HILOGD("isPrivacyMode: %{public}d.", isPrivacyMode);
1327     if (window_ == nullptr) {
1328         IMSA_HILOGE("window_ is nullptr.");
1329         return ErrorCode::ERROR_NULL_POINTER;
1330     }
1331     auto ret = window_->SetPrivacyMode(isPrivacyMode);
1332     if (ret != WMError::WM_OK) {
1333         IMSA_HILOGE("SetWindowPrivacyMode error, ret: %{public}d", ret);
1334         return static_cast<int32_t>(ret);
1335     }
1336     IMSA_HILOGI("end, isPrivacyMode: %{public}d.", isPrivacyMode);
1337     return ErrorCode::NO_ERROR;
1338 }
1339 
PanelStatusChange(const InputWindowStatus & status)1340 void InputMethodPanel::PanelStatusChange(const InputWindowStatus &status)
1341 {
1342     if (status == InputWindowStatus::SHOW && showRegistered_ && panelStatusListener_ != nullptr) {
1343         IMSA_HILOGD("ShowPanel panelStatusListener_ is not nullptr.");
1344         panelStatusListener_->OnPanelStatus(windowId_, true);
1345     }
1346     if (status == InputWindowStatus::HIDE && hideRegistered_ && panelStatusListener_ != nullptr) {
1347         IMSA_HILOGD("HidePanel panelStatusListener_ is not nullptr.");
1348         panelStatusListener_->OnPanelStatus(windowId_, false);
1349     }
1350 }
1351 
PanelStatusChangeToImc(const InputWindowStatus & status,const Rosen::Rect & rect)1352 void InputMethodPanel::PanelStatusChangeToImc(const InputWindowStatus &status, const Rosen::Rect &rect)
1353 {
1354     ImeWindowInfo info;
1355     info.panelInfo = { panelType_, panelFlag_ };
1356     if (info.panelInfo.panelType != SOFT_KEYBOARD || info.panelInfo.panelFlag == FLG_CANDIDATE_COLUMN) {
1357         IMSA_HILOGD("no need to deal.");
1358         return;
1359     }
1360     auto proxy = ImaUtils::GetImsaProxy();
1361     if (proxy == nullptr) {
1362         IMSA_HILOGE("proxy is nullptr!");
1363         return;
1364     }
1365     std::string name = window_->GetWindowName() + "/" + std::to_string(window_->GetWindowId());
1366     info.windowInfo = { std::move(name), rect.posX_, rect.posY_, rect.width_, rect.height_ };
1367     IMSA_HILOGD("rect[%{public}d, %{public}d, %{public}u, %{public}u], status: %{public}d, "
1368                 "panelFlag: %{public}d.",
1369         rect.posX_, rect.posY_, rect.width_, rect.height_, status, info.panelInfo.panelFlag);
1370     proxy->PanelStatusChange(status, info);
1371 }
1372 
IsShowing()1373 bool InputMethodPanel::IsShowing()
1374 {
1375     auto windowState = window_->GetWindowState();
1376     if (windowState == WindowState::STATE_SHOWN) {
1377         return true;
1378     }
1379     IMSA_HILOGD("windowState: %{public}d.", static_cast<int>(windowState));
1380     return false;
1381 }
1382 
IsHidden()1383 bool InputMethodPanel::IsHidden()
1384 {
1385     auto windowState = window_->GetWindowState();
1386     if (windowState == WindowState::STATE_HIDDEN) {
1387         return true;
1388     }
1389     IMSA_HILOGD("windowState: %{public}d.", static_cast<int>(windowState));
1390     return false;
1391 }
1392 
SetUiContent(const std::string & contentInfo,napi_env env,std::shared_ptr<NativeReference> storage)1393 int32_t InputMethodPanel::SetUiContent(const std::string &contentInfo, napi_env env,
1394     std::shared_ptr<NativeReference> storage)
1395 {
1396     if (window_ == nullptr) {
1397         IMSA_HILOGE("window_ is nullptr, can not SetUiContent.");
1398         return ErrorCode::ERROR_NULL_POINTER;
1399     }
1400     WMError ret = WMError::WM_OK;
1401     if (storage == nullptr) {
1402         ret = window_->NapiSetUIContent(contentInfo, env, nullptr);
1403     } else {
1404         ret = window_->NapiSetUIContent(contentInfo, env, storage->GetNapiValue());
1405     }
1406     WMError wmError = window_->SetTransparent(true);
1407     if (isWaitSetUiContent_) {
1408         isWaitSetUiContent_ = false;
1409     }
1410     IMSA_HILOGI("SetTransparent ret: %{public}u.", wmError);
1411     IMSA_HILOGI("NapiSetUIContent ret: %{public}d.", ret);
1412     return ret == WMError::WM_ERROR_INVALID_PARAM ? ErrorCode::ERROR_PARAMETER_CHECK_FAILED : ErrorCode::NO_ERROR;
1413 }
1414 
SetPanelStatusListener(std::shared_ptr<PanelStatusListener> statusListener,const std::string & type)1415 bool InputMethodPanel::SetPanelStatusListener(std::shared_ptr<PanelStatusListener> statusListener,
1416     const std::string &type)
1417 {
1418     if (!MarkListener(type, true)) {
1419         return false;
1420     }
1421     IMSA_HILOGD("type: %{public}s.", type.c_str());
1422     if (type == "show" || type == "hide") {
1423         if (panelStatusListener_ == nullptr) {
1424             IMSA_HILOGD("panelStatusListener_ is nullptr, need to be set");
1425             panelStatusListener_ = std::move(statusListener);
1426         }
1427         if (window_ != nullptr) {
1428             if (type == "show" && IsShowing()) {
1429                 panelStatusListener_->OnPanelStatus(windowId_, true);
1430             }
1431             if (type == "hide" && IsHidden()) {
1432                 panelStatusListener_->OnPanelStatus(windowId_, false);
1433             }
1434         }
1435     }
1436     if (type == "sizeChange" || type == "sizeUpdate") {
1437         return SetPanelSizeChangeListener(statusListener);
1438     }
1439     return true;
1440 }
1441 
SetPanelSizeChangeListener(std::shared_ptr<PanelStatusListener> statusListener)1442 bool InputMethodPanel::SetPanelSizeChangeListener(std::shared_ptr<PanelStatusListener> statusListener)
1443 {
1444     if (panelType_ != PanelType::SOFT_KEYBOARD
1445         || (panelFlag_ != PanelFlag::FLG_FIXED && panelFlag_ != PanelFlag::FLG_FLOATING)) {
1446         return true;
1447     }
1448     if (panelStatusListener_ == nullptr && statusListener != nullptr) {
1449         panelStatusListener_ = std::move(statusListener);
1450     }
1451     std::lock_guard<std::mutex> lock(windowListenerLock_);
1452     if (windowChangedListener_ != nullptr) {
1453         IMSA_HILOGD("windowChangedListener already registered.");
1454         return true;
1455     }
1456     windowChangedListener_ = new (std::nothrow)
1457         WindowChangeListenerImpl([this](WindowSize windowSize) { SizeChange(windowSize); });
1458     if (windowChangedListener_ == nullptr || window_ == nullptr) {
1459         IMSA_HILOGE("observer or window_ is nullptr!");
1460         return false;
1461     }
1462     auto ret = window_->RegisterWindowChangeListener(windowChangedListener_);
1463     if (ret != WMError::WM_OK) {
1464         IMSA_HILOGE("RegisterWindowChangeListener error: %{public}d!", ret);
1465         return false;
1466     }
1467     return true;
1468 }
1469 
ClearPanelListener(const std::string & type)1470 void InputMethodPanel::ClearPanelListener(const std::string &type)
1471 {
1472     if (!MarkListener(type, false)) {
1473         return;
1474     }
1475     IMSA_HILOGD("type: %{public}s.", type.c_str());
1476     if (!sizeChangeRegistered_ && !sizeUpdateRegistered_ && windowChangedListener_ != nullptr && window_ != nullptr) {
1477         auto ret = window_->UnregisterWindowChangeListener(windowChangedListener_);
1478         IMSA_HILOGI("UnregisterWindowChangeListener ret: %{public}d.", ret);
1479         windowChangedListener_ = nullptr;
1480     }
1481     if (panelStatusListener_ == nullptr) {
1482         IMSA_HILOGD("panelStatusListener_ not set, don't need to remove.");
1483         return;
1484     }
1485     if (showRegistered_ || hideRegistered_ || sizeChangeRegistered_ || sizeUpdateRegistered_) {
1486         return;
1487     }
1488     panelStatusListener_ = nullptr;
1489 }
1490 
GetPanelListener()1491 std::shared_ptr<PanelStatusListener> InputMethodPanel::GetPanelListener()
1492 {
1493     return panelStatusListener_;
1494 }
1495 
MarkListener(const std::string & type,bool isRegister)1496 bool InputMethodPanel::MarkListener(const std::string &type, bool isRegister)
1497 {
1498     if (type == "show") {
1499         showRegistered_ = isRegister;
1500     } else if (type == "hide") {
1501         hideRegistered_ = isRegister;
1502     } else if (type == "sizeChange") {
1503         sizeChangeRegistered_ = isRegister;
1504     } else if (type == "sizeUpdate") {
1505         sizeUpdateRegistered_ = isRegister;
1506     } else {
1507         IMSA_HILOGE("type error.");
1508         return false;
1509     }
1510     return true;
1511 }
1512 
GenerateSequenceId()1513 uint32_t InputMethodPanel::GenerateSequenceId()
1514 {
1515     uint32_t seqId = ++sequenceId_;
1516     if (seqId == std::numeric_limits<uint32_t>::max()) {
1517         return ++sequenceId_;
1518     }
1519     return seqId;
1520 }
1521 
IsSizeValid(uint32_t width,uint32_t height)1522 bool InputMethodPanel::IsSizeValid(uint32_t width, uint32_t height)
1523 {
1524     if (width > INT32_MAX || height > INT32_MAX) {
1525         IMSA_HILOGE("width or height over maximum!");
1526         return false;
1527     }
1528     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
1529     if (defaultDisplay == nullptr) {
1530         IMSA_HILOGE("GetDefaultDisplay failed.");
1531         return false;
1532     }
1533     float ratio = panelType_ == PanelType::SOFT_KEYBOARD && panelFlag_ == PanelFlag::FLG_FIXED
1534                       ? FIXED_SOFT_KEYBOARD_PANEL_RATIO
1535                       : NON_FIXED_SOFT_KEYBOARD_PANEL_RATIO;
1536     if (static_cast<float>(height) > defaultDisplay->GetHeight() * ratio) {
1537         IMSA_HILOGE("height is invalid, defaultDisplay height: %{public}d, target height: %{public}u!",
1538             defaultDisplay->GetHeight(), height);
1539         return false;
1540     }
1541     if (static_cast<int32_t>(width) > defaultDisplay->GetWidth()) {
1542         IMSA_HILOGE("width is invalid, defaultDisplay width: %{public}d, target width: %{public}u!",
1543             defaultDisplay->GetWidth(), width);
1544         return false;
1545     }
1546     return true;
1547 }
1548 
GetKeyboardSize()1549 WindowSize InputMethodPanel::GetKeyboardSize()
1550 {
1551     std::lock_guard<std::mutex> lock(keyboardSizeLock_);
1552     return keyboardSize_;
1553 }
1554 
SizeChange(const WindowSize & size)1555 int32_t InputMethodPanel::SizeChange(const WindowSize &size)
1556 {
1557     IMSA_HILOGD("InputMethodPanel start.");
1558     IMSA_HILOGI("type/flag: %{public}d/%{public}d, width/height: %{public}d/%{public}d.",
1559         static_cast<int32_t>(panelType_), static_cast<int32_t>(panelFlag_), static_cast<int32_t>(size.width),
1560         static_cast<int32_t>(size.height));
1561     {
1562         std::lock_guard<std::mutex> lock(keyboardSizeLock_);
1563         keyboardSize_ = size;
1564     }
1565     auto listener = GetPanelListener();
1566     if (listener == nullptr) {
1567         IMSA_HILOGD("panelStatusListener_ is nullptr");
1568         return ErrorCode::ERROR_NULL_POINTER;
1569     }
1570     PanelAdjustInfo keyboardArea;
1571     if (isInEnhancedAdjust_.load() && GetKeyboardArea(panelFlag_, size, keyboardArea) != ErrorCode::NO_ERROR) {
1572         IMSA_HILOGE("failed to GetKeyboardArea");
1573         return ErrorCode::ERROR_BAD_PARAMETERS;
1574     }
1575     if (sizeChangeRegistered_) {
1576         listener->OnSizeChange(windowId_, keyboardSize_, keyboardArea, "sizeChange");
1577     }
1578     if (sizeUpdateRegistered_) {
1579         listener->OnSizeChange(windowId_, keyboardSize_, keyboardArea, "sizeUpdate");
1580     }
1581     return ErrorCode::NO_ERROR;
1582 }
1583 
GetKeyboardArea(PanelFlag panelFlag,const WindowSize & size,PanelAdjustInfo & keyboardArea)1584 int32_t InputMethodPanel::GetKeyboardArea(PanelFlag panelFlag, const WindowSize &size, PanelAdjustInfo &keyboardArea)
1585 {
1586     bool isPortrait = false;
1587     if (GetWindowOrientation(panelFlag, size.width, isPortrait) != ErrorCode::NO_ERROR) {
1588         IMSA_HILOGE("failed to GetWindowOrientation");
1589         return ErrorCode::ERROR_WINDOW_MANAGER;
1590     }
1591     FullPanelAdjustInfo adjustInfo;
1592     if (GetAdjustInfo(panelFlag, adjustInfo) != ErrorCode::NO_ERROR) {
1593         IMSA_HILOGE("GetAdjustInfo failed");
1594         return ErrorCode::ERROR_BAD_PARAMETERS;
1595     }
1596     if (isPortrait) {
1597         keyboardArea = adjustInfo.portrait;
1598         keyboardArea.top = enhancedLayoutParams_.portrait.avoidY;
1599     } else {
1600         keyboardArea = adjustInfo.landscape;
1601         keyboardArea.top = enhancedLayoutParams_.landscape.avoidY;
1602     }
1603     return ErrorCode::NO_ERROR;
1604 }
1605 
GetWindowOrientation(PanelFlag panelFlag,uint32_t windowWidth,bool & isPortrait)1606 int32_t InputMethodPanel::GetWindowOrientation(PanelFlag panelFlag, uint32_t windowWidth, bool &isPortrait)
1607 {
1608     if (panelFlag != PanelFlag::FLG_FIXED) {
1609         isPortrait = IsDisplayPortrait();
1610         return ErrorCode::NO_ERROR;
1611     }
1612     DisplaySize displaySize;
1613     if (GetDisplaySize(displaySize) != ErrorCode::NO_ERROR) {
1614         IMSA_HILOGE("failed to GetDisplaySize");
1615         return ErrorCode::ERROR_WINDOW_MANAGER;
1616     }
1617     if (windowWidth == displaySize.portrait.width) {
1618         isPortrait = true;
1619     }
1620     if (windowWidth == displaySize.landscape.width) {
1621         isPortrait = false;
1622     }
1623     return ErrorCode::NO_ERROR;
1624 }
1625 
RegisterKeyboardPanelInfoChangeListener()1626 void InputMethodPanel::RegisterKeyboardPanelInfoChangeListener()
1627 {
1628     kbPanelInfoListener_ =
1629         new (std::nothrow) KeyboardPanelInfoChangeListener([this](const KeyboardPanelInfo &keyboardPanelInfo) {
1630             OnPanelHeightChange(keyboardPanelInfo);
1631             HandleKbPanelInfoChange(keyboardPanelInfo);
1632         });
1633     if (kbPanelInfoListener_ == nullptr) {
1634         return;
1635     }
1636     if (window_ == nullptr) {
1637         return;
1638     }
1639     auto ret = window_->RegisterKeyboardPanelInfoChangeListener(kbPanelInfoListener_);
1640     IMSA_HILOGD("ret: %{public}d.", ret);
1641 }
1642 
OnPanelHeightChange(const Rosen::KeyboardPanelInfo & keyboardPanelInfo)1643 void InputMethodPanel::OnPanelHeightChange(const Rosen::KeyboardPanelInfo &keyboardPanelInfo)
1644 {
1645     if (panelHeightCallback_ == nullptr) {
1646         return;
1647     }
1648     if (!isInEnhancedAdjust_.load()) {
1649         panelHeightCallback_(keyboardPanelInfo.rect_.height_, panelFlag_);
1650         return;
1651     }
1652     bool isPortrait = false;
1653     if (GetWindowOrientation(panelFlag_, keyboardPanelInfo.rect_.width_, isPortrait) != ErrorCode::NO_ERROR) {
1654         IMSA_HILOGE("failed to GetWindowOrientation");
1655         return;
1656     }
1657     if (isPortrait) {
1658         panelHeightCallback_(enhancedLayoutParams_.portrait.avoidHeight, panelFlag_);
1659     } else {
1660         panelHeightCallback_(enhancedLayoutParams_.landscape.avoidHeight, panelFlag_);
1661     }
1662 }
1663 
UnregisterKeyboardPanelInfoChangeListener()1664 void InputMethodPanel::UnregisterKeyboardPanelInfoChangeListener()
1665 {
1666     if (window_ == nullptr) {
1667         return;
1668     }
1669     auto ret = window_->UnregisterKeyboardPanelInfoChangeListener(kbPanelInfoListener_);
1670     kbPanelInfoListener_ = nullptr;
1671     IMSA_HILOGD("ret: %{public}d.", ret);
1672 }
1673 
HandleKbPanelInfoChange(const KeyboardPanelInfo & keyboardPanelInfo)1674 void InputMethodPanel::HandleKbPanelInfoChange(const KeyboardPanelInfo &keyboardPanelInfo)
1675 {
1676     IMSA_HILOGD("start.");
1677     InputWindowStatus status = InputWindowStatus::HIDE;
1678     if (keyboardPanelInfo.isShowing_) {
1679         status = InputWindowStatus::SHOW;
1680     }
1681     PanelStatusChangeToImc(status, keyboardPanelInfo.rect_);
1682 }
1683 
GetDisplaySize(bool isPortrait,WindowSize & size)1684 bool InputMethodPanel::GetDisplaySize(bool isPortrait, WindowSize &size)
1685 {
1686     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
1687     if (defaultDisplay == nullptr) {
1688         IMSA_HILOGE("GetDefaultDisplay failed.");
1689         return false;
1690     }
1691     auto width = defaultDisplay->GetWidth();
1692     auto height = defaultDisplay->GetHeight();
1693     bool isDisplayPortrait = width < height;
1694     if (isPortrait != isDisplayPortrait) {
1695         size = { .width = height, .height = width };
1696     } else {
1697         size = { .width = width, .height = height };
1698     }
1699     return true;
1700 }
1701 
IsDisplayPortrait()1702 bool InputMethodPanel::IsDisplayPortrait()
1703 {
1704     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
1705     if (defaultDisplay == nullptr) {
1706     IMSA_HILOGE("GetDefaultDisplay failed.");
1707         return false;
1708     }
1709     auto width = defaultDisplay->GetWidth();
1710     auto height = defaultDisplay->GetHeight();
1711     return width < height;
1712 }
1713 
IsDisplayUnfolded()1714 bool InputMethodPanel::IsDisplayUnfolded()
1715 {
1716     return Rosen::DisplayManager::GetInstance().IsFoldable()
1717            && Rosen::DisplayManager::GetInstance().GetFoldStatus() != Rosen::FoldStatus::FOLDED;
1718 }
1719 
CheckSize(PanelFlag panelFlag,uint32_t width,uint32_t height,bool isDataPortrait)1720 bool InputMethodPanel::CheckSize(PanelFlag panelFlag, uint32_t width, uint32_t height, bool isDataPortrait)
1721 {
1722     WindowSize displaySize;
1723     if (!GetDisplaySize(isDataPortrait, displaySize)) {
1724         IMSA_HILOGE("GetDisplaySize failed.");
1725         return false;
1726     }
1727     return IsSizeValid(panelFlag, width, height, displaySize.width, displaySize.height);
1728 }
1729 
IsSizeValid(PanelFlag panelFlag,uint32_t width,uint32_t height,int32_t displayWidth,int32_t displayHeight)1730 bool InputMethodPanel::IsSizeValid(PanelFlag panelFlag, uint32_t width, uint32_t height, int32_t displayWidth,
1731     int32_t displayHeight)
1732 {
1733     if (width > INT32_MAX || height > INT32_MAX) {
1734         IMSA_HILOGE("width or height over maximum!");
1735         return false;
1736     }
1737     float ratio = panelType_ == PanelType::SOFT_KEYBOARD && panelFlag == PanelFlag::FLG_FIXED
1738                       ? FIXED_SOFT_KEYBOARD_PANEL_RATIO
1739                       : NON_FIXED_SOFT_KEYBOARD_PANEL_RATIO;
1740     if (static_cast<float>(height) > displayHeight * ratio) {
1741         IMSA_HILOGE("height is invalid, defaultDisplay height: %{public}d, target height: %{public}u!", displayHeight,
1742             height);
1743         return false;
1744     }
1745     if (static_cast<int32_t>(width) > displayWidth) {
1746         IMSA_HILOGE("width is invalid, defaultDisplay width: %{public}d, target width: %{public}u!", displayWidth,
1747             width);
1748         return false;
1749     }
1750     return true;
1751 }
1752 
SetPanelHeightCallback(CallbackFunc heightCallback)1753 void InputMethodPanel::SetPanelHeightCallback(CallbackFunc heightCallback)
1754 {
1755     panelHeightCallback_ = std::move(heightCallback);
1756 }
1757 
GetDensityDpi(float & densityDpi)1758 int32_t InputMethodPanel::GetDensityDpi(float &densityDpi)
1759 {
1760     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
1761     if (defaultDisplay == nullptr) {
1762         IMSA_HILOGE("GetDefaultDisplay failed!");
1763         return ErrorCode::ERROR_WINDOW_MANAGER;
1764     }
1765     auto displayInfo = defaultDisplay->GetDisplayInfo();
1766     if (displayInfo == nullptr) {
1767         IMSA_HILOGE("GetDisplayInfo failed!");
1768         return ErrorCode::ERROR_WINDOW_MANAGER;
1769     }
1770     densityDpi = displayInfo->GetDensityInCurResolution();
1771     IMSA_HILOGI("densityDpi: %{public}f", densityDpi);
1772     if (densityDpi <= 0) {
1773         return ErrorCode::ERROR_WINDOW_MANAGER;
1774     }
1775     return ErrorCode::NO_ERROR;
1776 }
1777 
GetDisplaySize(DisplaySize & size)1778 int32_t InputMethodPanel::GetDisplaySize(DisplaySize &size)
1779 {
1780     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
1781     if (defaultDisplay == nullptr) {
1782         IMSA_HILOGE("GetDefaultDisplay failed!");
1783         return ErrorCode::ERROR_WINDOW_MANAGER;
1784     }
1785     auto width = defaultDisplay->GetWidth();
1786     auto height = defaultDisplay->GetHeight();
1787     if (width < height) {
1788         size.portrait = { .width = width, .height = height };
1789         size.landscape = { .width = height, .height = width };
1790     } else {
1791         size.portrait = { .width = height, .height = width };
1792         size.landscape = { .width = width, .height = height };
1793     }
1794     return ErrorCode::NO_ERROR;
1795 }
1796 
SetImmersiveMode(ImmersiveMode mode)1797 int32_t InputMethodPanel::SetImmersiveMode(ImmersiveMode mode)
1798 {
1799     if ((mode != ImmersiveMode::NONE_IMMERSIVE && mode != ImmersiveMode::LIGHT_IMMERSIVE &&
1800             mode != ImmersiveMode::DARK_IMMERSIVE)) {
1801         IMSA_HILOGE("invalid mode: %{public}d", mode);
1802         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
1803     }
1804     if (!IsShowing()) {
1805         immersiveMode_ = mode;
1806         IMSA_HILOGW("window is not show, mode: %{public}d", mode);
1807         return ErrorCode::NO_ERROR;
1808     }
1809 
1810     if (window_ == nullptr) {
1811         IMSA_HILOGE("window is null");
1812         return ErrorCode::ERROR_IME;
1813     }
1814 
1815     // call window manager to set immersive mode
1816     auto ret = window_->ChangeKeyboardViewMode(static_cast<KeyboardViewMode>(mode));
1817     if (ret == WMError::WM_DO_NOTHING) {
1818         IMSA_HILOGW("repeat set mode new:%{public}d, old:%{public}d", mode, immersiveMode_);
1819         return ErrorCode::NO_ERROR;
1820     }
1821     if (ret != WMError::WM_OK) {
1822         IMSA_HILOGE("ChangeKeyboardViewMode failed, ret: %{public}d", ret);
1823         return ErrorCode::ERROR_WINDOW_MANAGER;
1824     }
1825     immersiveMode_ = mode;
1826     IMSA_HILOGD("SetImmersiveMode success, mode: %{public}d", mode);
1827     return ErrorCode::NO_ERROR;
1828 }
1829 
GetImmersiveMode()1830 ImmersiveMode InputMethodPanel::GetImmersiveMode()
1831 {
1832     IMSA_HILOGD("GetImmersiveMode mode: %{public}d", immersiveMode_);
1833     return immersiveMode_;
1834 }
1835 
SetHotAreas(const HotAreas & hotAreas)1836 void InputMethodPanel::SetHotAreas(const HotAreas &hotAreas)
1837 {
1838     std::lock_guard<std::mutex> lock(hotAreasLock_);
1839     hotAreas_ = hotAreas;
1840 }
1841 
GetHotAreas()1842 HotAreas InputMethodPanel::GetHotAreas()
1843 {
1844     std::lock_guard<std::mutex> lock(hotAreasLock_);
1845     return hotAreas_;
1846 }
1847 } // namespace MiscServices
1848 } // namespace OHOS