1 /*
2  * Copyright (C) 2023 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 std::atomic<uint32_t> InputMethodPanel::sequenceId_{ 0 };
42 constexpr int32_t MAXWAITTIME = 30;
43 constexpr int32_t WAITTIME = 10;
44 InputMethodPanel::~InputMethodPanel() = default;
45 
CreatePanel(const std::shared_ptr<AbilityRuntime::Context> & context,const PanelInfo & panelInfo)46 int32_t InputMethodPanel::CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context,
47     const PanelInfo &panelInfo)
48 {
49     IMSA_HILOGD("start, type/flag: %{public}d/%{public}d.", static_cast<int32_t>(panelType_),
50         static_cast<int32_t>(panelFlag_));
51     panelType_ = panelInfo.panelType;
52     panelFlag_ = panelInfo.panelFlag;
53     adjustPanelRectLayoutParams_ = {
54         {0, 0, 0, 0},
55         {0, 0, 0, 0}
56     };
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()164 LayoutParams InputMethodPanel::GetResizeParams()
165 {
166     if (Rosen::DisplayManager::GetInstance().IsFoldable() &&
167         Rosen::DisplayManager::GetInstance().GetFoldStatus() != Rosen::FoldStatus::FOLDED) {
168         IMSA_HILOGI("is fold device and unfold state");
169         return resizePanelUnfoldParams_;
170     }
171     IMSA_HILOGI("is fold device and fold state or other");
172     return resizePanelFoldParams_;
173 }
174 
SetResizeParams(uint32_t width,uint32_t height)175 void InputMethodPanel::SetResizeParams(uint32_t width, uint32_t height)
176 {
177     if (Rosen::DisplayManager::GetInstance().IsFoldable() &&
178         Rosen::DisplayManager::GetInstance().GetFoldStatus() != Rosen::FoldStatus::FOLDED) {
179         IMSA_HILOGI("set fold device and unfold state resize params, width/height: %{public}u/%{public}u.",
180             width, height);
181         if (IsDisplayPortrait()) {
182             resizePanelUnfoldParams_.portraitRect.height_ = height;
183             resizePanelUnfoldParams_.portraitRect.width_ = width;
184         } else {
185             resizePanelUnfoldParams_.landscapeRect.height_ = height;
186             resizePanelUnfoldParams_.landscapeRect.width_ = width;
187         }
188     } else {
189         IMSA_HILOGI("set fold device and fold state or other resize params, width/height: %{public}u/%{public}u.",
190             width, height);
191         if (IsDisplayPortrait()) {
192             resizePanelFoldParams_.portraitRect.height_ = height;
193             resizePanelFoldParams_.portraitRect.width_ = width;
194         } else {
195             resizePanelFoldParams_.landscapeRect.height_ = height;
196             resizePanelFoldParams_.landscapeRect.width_ = width;
197         }
198     }
199 }
200 
Resize(uint32_t width,uint32_t height)201 int32_t InputMethodPanel::Resize(uint32_t width, uint32_t height)
202 {
203     if (window_ == nullptr) {
204         IMSA_HILOGE("window is nullptr!");
205         return ErrorCode::ERROR_NULL_POINTER;
206     }
207     if (!IsSizeValid(width, height)) {
208         IMSA_HILOGE("size is invalid!");
209         return ErrorCode::ERROR_BAD_PARAMETERS;
210     }
211     if (!isScbEnable_ || window_->GetType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
212         auto ret = window_->Resize(width, height);
213         if (ret != WMError::WM_OK) {
214             IMSA_HILOGE("failed to resize, ret: %{public}d", ret);
215             return ErrorCode::ERROR_OPERATE_PANEL;
216         }
217     } else {
218         LayoutParams params = adjustPanelRectLayoutParams_;
219         LayoutParams deviceParams = GetResizeParams();
220         if (IsDisplayPortrait()) {
221             params.landscapeRect.height_ = deviceParams.landscapeRect.height_;
222             params.landscapeRect.width_ = deviceParams.landscapeRect.width_;
223             params.portraitRect.height_ = height;
224             params.portraitRect.width_ = width;
225             IMSA_HILOGI("isPortrait now, updata portrait size");
226         } else {
227             params.portraitRect.height_ = deviceParams.portraitRect.height_;
228             params.portraitRect.width_ = deviceParams.portraitRect.width_;
229             params.landscapeRect.height_ = height;
230             params.landscapeRect.width_ = width;
231             IMSA_HILOGI("isLandscapeRect now, updata landscape size");
232         }
233         auto ret = AdjustPanelRect(panelFlag_, params);
234         if (ret != ErrorCode::NO_ERROR) {
235             IMSA_HILOGE("failed to resize, ret: %{public}d", ret);
236             return ErrorCode::ERROR_OPERATE_PANEL;
237         }
238         SetResizeParams(width, height);
239     }
240     std::lock_guard<std::mutex> lock(keyboardSizeLock_);
241     keyboardSize_ = { width, height };
242     IMSA_HILOGI("success, width/height: %{public}u/%{public}u.", width, height);
243     return ErrorCode::NO_ERROR;
244 }
245 
MoveTo(int32_t x,int32_t y)246 int32_t InputMethodPanel::MoveTo(int32_t x, int32_t y)
247 {
248     if (window_ == nullptr) {
249         IMSA_HILOGE("window_ is nullptr!");
250         return ErrorCode::ERROR_NULL_POINTER;
251     }
252     if (panelType_ == SOFT_KEYBOARD && panelFlag_ == FLG_FIXED) {
253         IMSA_HILOGE("FLG_FIXED panel can not moveTo!");
254         return ErrorCode::NO_ERROR;
255     }
256     if (!isScbEnable_ || window_->GetType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
257         auto ret = window_->MoveTo(x, y);
258         IMSA_HILOGI("x/y: %{public}d/%{public}d, ret = %{public}d", x, y, ret);
259         return ret == WMError::WM_ERROR_INVALID_PARAM ? ErrorCode::ERROR_PARAMETER_CHECK_FAILED : ErrorCode::NO_ERROR;
260     } else {
261         LayoutParams params = adjustPanelRectLayoutParams_;
262         if (IsDisplayPortrait()) {
263             params.portraitRect.posX_ = x;
264             params.portraitRect.posY_ = y;
265             IMSA_HILOGI("isPortrait now, updata portrait size");
266         } else {
267             params.landscapeRect.posX_ = x;
268             params.landscapeRect.posY_ = y;
269             IMSA_HILOGI("isLandscapeRect now, updata landscape size");
270         }
271         auto ret = AdjustPanelRect(panelFlag_, params);
272         IMSA_HILOGI("x/y: %{public}d/%{public}d, ret = %{public}d", x, y, ret);
273         return ret == ErrorCode::NO_ERROR ? ErrorCode::NO_ERROR : ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
274     }
275 }
276 
AdjustPanelRect(const PanelFlag panelFlag,const LayoutParams & layoutParams)277 int32_t InputMethodPanel::AdjustPanelRect(const PanelFlag panelFlag, const LayoutParams &layoutParams)
278 {
279     if (window_ == nullptr) {
280         IMSA_HILOGE("window_ is nullptr!");
281         return ErrorCode::ERROR_WINDOW_MANAGER;
282     }
283     if (layoutParams.portraitRect.posX_ < 0 || layoutParams.portraitRect.posY_ < 0 ||
284         layoutParams.landscapeRect.posX_ < 0 || layoutParams.landscapeRect.posY_ < 0) {
285         IMSA_HILOGE("posX_ and posY_ cannot be less than 0!");
286         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
287     }
288     if (!CheckSize(panelFlag, layoutParams.portraitRect.width_, layoutParams.portraitRect.height_, true)) {
289         IMSA_HILOGE("portrait invalid size!");
290         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
291     }
292     if (!CheckSize(panelFlag, layoutParams.landscapeRect.width_, layoutParams.landscapeRect.height_, false)) {
293         IMSA_HILOGE("landscape invalid size!");
294         return ErrorCode::ERROR_PARAMETER_CHECK_FAILED;
295     }
296     auto result = ParsePanelRect(panelFlag, layoutParams);
297     if (result != ErrorCode::NO_ERROR) {
298         IMSA_HILOGE("failed to parse panel rect, result: %{public}d!", result);
299         return ErrorCode::ERROR_WINDOW_MANAGER;
300     }
301     panelFlag_ = panelFlag;
302     adjustPanelRectLayoutParams_ = layoutParams;
303     auto ret = window_->AdjustKeyboardLayout(keyboardLayoutParams_);
304     if (ret != WMError::WM_OK) {
305         IMSA_HILOGE("AdjustPanelRect error, err: %{public}d!", ret);
306         return ErrorCode::ERROR_WINDOW_MANAGER;
307     }
308     IMSA_HILOGI("success, type/flag: %{public}d/%{public}d.", static_cast<int32_t>(panelType_),
309         static_cast<int32_t>(panelFlag_));
310     return ErrorCode::NO_ERROR;
311 }
312 
ParsePanelRect(const PanelFlag panelFlag,const LayoutParams & layoutParams)313 int32_t InputMethodPanel::ParsePanelRect(const PanelFlag panelFlag, const LayoutParams &layoutParams)
314 {
315     std::vector<SysPanelAdjust> configs;
316     auto isSuccess = SysCfgParser::ParsePanelAdjust(configs);
317     if (isSuccess) {
318         std::lock_guard<std::mutex> lk(panelAdjustLock_);
319         panelAdjust_.clear();
320         for (const auto &config : configs) {
321             panelAdjust_.insert({ config.style, { config.top, config.left, config.right, config.bottom } });
322         }
323     } else {
324         IMSA_HILOGE("there is no configuration file.");
325         auto ret = CalculateNoConfigRect(panelFlag, layoutParams);
326         if (ret != ErrorCode::NO_ERROR) {
327             IMSA_HILOGE("failed to calculate NoConfigRect, err: %{public}d!", ret);
328             return ret;
329         }
330         return ErrorCode::NO_ERROR;
331     }
332     std::tuple<std::vector<std::string>, std::vector<std::string>> keys = GetScreenStatus(panelFlag);
333     auto ret = GetSysPanelAdjust(panelFlag, keys, layoutParams);
334     if (ret != ErrorCode::NO_ERROR) {
335         IMSA_HILOGE("GetSysPanelAdjust failed!");
336         return ErrorCode::ERROR_BAD_PARAMETERS;
337     }
338     return ErrorCode::NO_ERROR;
339 }
340 
CalculateNoConfigRect(const PanelFlag panelFlag,const LayoutParams & layoutParams)341 int32_t InputMethodPanel::CalculateNoConfigRect(const PanelFlag panelFlag, const LayoutParams &layoutParams)
342 {
343     if (panelFlag == PanelFlag::FLG_FIXED) {
344         keyboardLayoutParams_.gravity_ = WindowGravity::WINDOW_GRAVITY_BOTTOM;
345         WindowSize portraitDisplaySize;
346         if (!GetDisplaySize(true, portraitDisplaySize)) {
347             IMSA_HILOGE("GetPortraitDisplaySize failed!");
348             return ErrorCode::ERROR_WINDOW_MANAGER;
349         }
350         keyboardLayoutParams_.PortraitPanelRect_.width_ = portraitDisplaySize.width;
351         keyboardLayoutParams_.PortraitPanelRect_.height_ = layoutParams.portraitRect.height_;
352         keyboardLayoutParams_.PortraitPanelRect_.posY_ =
353             static_cast<int32_t>(portraitDisplaySize.height - keyboardLayoutParams_.PortraitPanelRect_.height_);
354         keyboardLayoutParams_.PortraitPanelRect_.posX_ = NUMBER_ZERO;
355         //fixed Portraitkeyboard
356         keyboardLayoutParams_.PortraitKeyboardRect_.width_ = keyboardLayoutParams_.PortraitPanelRect_.width_;
357         keyboardLayoutParams_.PortraitKeyboardRect_.height_ = keyboardLayoutParams_.PortraitPanelRect_.height_;
358         keyboardLayoutParams_.PortraitKeyboardRect_.posY_ = keyboardLayoutParams_.PortraitPanelRect_.posY_;
359         keyboardLayoutParams_.PortraitKeyboardRect_.posX_ = keyboardLayoutParams_.PortraitPanelRect_.posX_;
360 
361         WindowSize landscapeDisplaySize;
362         if (!GetDisplaySize(false, landscapeDisplaySize)) {
363             IMSA_HILOGE("GetLandscapeDisplaySize failed!");
364             return ErrorCode::ERROR_WINDOW_MANAGER;
365         }
366         keyboardLayoutParams_.LandscapePanelRect_.width_ = landscapeDisplaySize.width;
367         keyboardLayoutParams_.LandscapePanelRect_.height_ = layoutParams.landscapeRect.height_;
368         keyboardLayoutParams_.LandscapePanelRect_.posY_ =
369             static_cast<int32_t>(landscapeDisplaySize.height - keyboardLayoutParams_.LandscapePanelRect_.height_);
370         keyboardLayoutParams_.LandscapePanelRect_.posX_ = NUMBER_ZERO;
371         //Landscapekeyboard
372         keyboardLayoutParams_.LandscapeKeyboardRect_.width_ = keyboardLayoutParams_.LandscapePanelRect_.width_;
373         keyboardLayoutParams_.LandscapeKeyboardRect_.height_ = keyboardLayoutParams_.LandscapePanelRect_.height_;
374         keyboardLayoutParams_.LandscapeKeyboardRect_.posY_ = keyboardLayoutParams_.LandscapePanelRect_.posY_;
375         keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ = keyboardLayoutParams_.LandscapePanelRect_.posX_;
376     } else {
377         keyboardLayoutParams_.gravity_ = WindowGravity::WINDOW_GRAVITY_FLOAT;
378         keyboardLayoutParams_.LandscapeKeyboardRect_ = layoutParams.landscapeRect;
379         keyboardLayoutParams_.PortraitKeyboardRect_ = layoutParams.portraitRect;
380         keyboardLayoutParams_.LandscapePanelRect_ = layoutParams.landscapeRect;
381         keyboardLayoutParams_.PortraitPanelRect_ = layoutParams.portraitRect;
382     }
383     return ErrorCode::NO_ERROR;
384 }
385 
GetScreenStatus(const PanelFlag panelFlag)386 std::tuple<std::vector<std::string>, std::vector<std::string>> InputMethodPanel::GetScreenStatus(
387     const PanelFlag panelFlag)
388 {
389     std::lock_guard<std::mutex> lock(panelAdjustLock_);
390     std::string flag;
391     std::string foldStatus = "default";
392     if (panelFlag == PanelFlag::FLG_FIXED) {
393         flag = "fix";
394         keyboardLayoutParams_.gravity_ = WindowGravity::WINDOW_GRAVITY_BOTTOM;
395     } else {
396         flag = "floating";
397         keyboardLayoutParams_.gravity_ = WindowGravity::WINDOW_GRAVITY_FLOAT;
398     }
399     if (Rosen::DisplayManager::GetInstance().IsFoldable() &&
400         Rosen::DisplayManager::GetInstance().GetFoldStatus() != Rosen::FoldStatus::FOLDED) {
401         foldStatus = "foldable";
402     }
403     std::vector<std::string> lanPanel = { flag, foldStatus, "landscape" };
404     std::vector<std::string> porPanel = { flag, foldStatus, "portrait" };
405     return std::make_tuple(lanPanel, porPanel);
406 }
407 
GetSysPanelAdjust(const PanelFlag panelFlag,std::tuple<std::vector<std::string>,std::vector<std::string>> & keys,const LayoutParams & layoutParams)408 int32_t InputMethodPanel::GetSysPanelAdjust(const PanelFlag panelFlag,
409     std::tuple<std::vector<std::string>, std::vector<std::string>> &keys, const LayoutParams &layoutParams)
410 {
411     std::lock_guard<std::mutex> lock(panelAdjustLock_);
412     auto lanPanel = std::get<0>(keys);
413     auto porPanel = std::get<1>(keys);
414     auto lanIter = panelAdjust_.find(lanPanel);
415     auto porIter = panelAdjust_.find(porPanel);
416     if (lanIter == panelAdjust_.end() || porIter == panelAdjust_.end()) {
417         IMSA_HILOGE("lanIter or porIter not supported!");
418         return ErrorCode::ERROR_BAD_PARAMETERS;
419     }
420     auto lanIterValue = lanIter->second;
421     auto porIterValue = porIter->second;
422     keyboardLayoutParams_.LandscapeKeyboardRect_ = layoutParams.landscapeRect;
423     keyboardLayoutParams_.PortraitKeyboardRect_ = layoutParams.portraitRect;
424     keyboardLayoutParams_.LandscapePanelRect_ = layoutParams.landscapeRect;
425     keyboardLayoutParams_.PortraitPanelRect_ = layoutParams.portraitRect;
426     return CalculatePanelRect(panelFlag, lanIterValue, porIterValue, layoutParams);
427 }
428 
CalculatePanelRect(const PanelFlag panelFlag,PanelAdjustInfo & lanIterValue,PanelAdjustInfo & porIterValue,const LayoutParams & layoutParams)429 int32_t InputMethodPanel::CalculatePanelRect(const PanelFlag panelFlag, PanelAdjustInfo &lanIterValue,
430     PanelAdjustInfo &porIterValue, const LayoutParams &layoutParams)
431 {
432     auto instance = InputMethodAbility::GetInstance();
433     if (instance != nullptr && instance->GetInputAttribute().GetSecurityFlag()) {
434         IMSA_HILOGI("The security keyboard is handled according to no configuration file");
435         return CalculateNoConfigRect(panelFlag, layoutParams);
436     }
437     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
438     if (defaultDisplay == nullptr) {
439         IMSA_HILOGE("GetDefaultDisplay failed!");
440         return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
441     }
442     auto displayInfo = defaultDisplay->GetDisplayInfo();
443     if (displayInfo == nullptr) {
444         IMSA_HILOGE("GetDisplayInfo failed.");
445         return ErrorCode::ERROR_EX_SERVICE_SPECIFIC;
446     }
447     auto densityDpi = displayInfo->GetDensityInCurResolution();
448     IMSA_HILOGI("densityDpi: %{public}f", densityDpi);
449     if (densityDpi <= 0) {
450         return ErrorCode::ERROR_WINDOW_MANAGER;
451     }
452     if (panelFlag == PanelFlag::FLG_FIXED) {
453         //fixed PortraitPanel
454         WindowSize portraitDisplaySize;
455         if (!GetDisplaySize(true, portraitDisplaySize)) {
456             IMSA_HILOGE("GetDisplaySize failed!");
457             return ErrorCode::ERROR_WINDOW_MANAGER;
458         }
459         keyboardLayoutParams_.PortraitPanelRect_.width_ = portraitDisplaySize.width;
460         keyboardLayoutParams_.PortraitPanelRect_.height_ = layoutParams.portraitRect.height_ +
461             static_cast<uint32_t>((porIterValue.top + porIterValue.bottom) * densityDpi);
462         if (keyboardLayoutParams_.PortraitPanelRect_.height_ >
463             portraitDisplaySize.height * FIXED_SOFT_KEYBOARD_PANEL_RATIO) {
464             keyboardLayoutParams_.PortraitPanelRect_.height_ =
465                 portraitDisplaySize.height * FIXED_SOFT_KEYBOARD_PANEL_RATIO;
466         }
467         keyboardLayoutParams_.PortraitPanelRect_.posY_ =
468             static_cast<int32_t>(portraitDisplaySize.height - keyboardLayoutParams_.PortraitPanelRect_.height_);
469         keyboardLayoutParams_.PortraitPanelRect_.posX_ = NUMBER_ZERO;
470         //fixed Portraitkeyboard
471         keyboardLayoutParams_.PortraitKeyboardRect_.width_ = keyboardLayoutParams_.PortraitPanelRect_.width_ -
472             static_cast<uint32_t>((porIterValue.left + porIterValue.right) * densityDpi);
473         keyboardLayoutParams_.PortraitKeyboardRect_.height_ = keyboardLayoutParams_.PortraitPanelRect_.height_ -
474             static_cast<uint32_t>((porIterValue.top + porIterValue.bottom) * densityDpi);
475         keyboardLayoutParams_.PortraitKeyboardRect_.posY_ = keyboardLayoutParams_.PortraitPanelRect_.posY_ +
476             static_cast<int32_t>(porIterValue.top * densityDpi);
477         keyboardLayoutParams_.PortraitKeyboardRect_.posX_ = keyboardLayoutParams_.PortraitPanelRect_.posX_ +
478             static_cast<int32_t>(porIterValue.left * densityDpi);
479         return CalculateLandscapeRect(defaultDisplay, layoutParams, lanIterValue, densityDpi);
480     }
481     return CalculateFloatRect(layoutParams, lanIterValue, porIterValue, densityDpi);
482 }
483 
CalculateFloatRect(const LayoutParams & layoutParams,PanelAdjustInfo & lanIterValue,PanelAdjustInfo & porIterValue,float densityDpi)484 int32_t InputMethodPanel::CalculateFloatRect(const LayoutParams &layoutParams, PanelAdjustInfo &lanIterValue,
485     PanelAdjustInfo &porIterValue, float densityDpi)
486 {
487     //portrait floating keyboard
488     keyboardLayoutParams_.PortraitKeyboardRect_.width_ = layoutParams.portraitRect.width_;
489     keyboardLayoutParams_.PortraitKeyboardRect_.height_ = layoutParams.portraitRect.height_;
490     keyboardLayoutParams_.PortraitKeyboardRect_.posY_ = layoutParams.portraitRect.posY_;
491     keyboardLayoutParams_.PortraitKeyboardRect_.posX_ = layoutParams.portraitRect.posX_;
492     //portrait floating panel
493     keyboardLayoutParams_.PortraitPanelRect_.width_ = keyboardLayoutParams_.PortraitKeyboardRect_.width_ +
494         static_cast<uint32_t>((porIterValue.left + porIterValue.right) * densityDpi);
495     keyboardLayoutParams_.PortraitPanelRect_.height_ = keyboardLayoutParams_.PortraitKeyboardRect_.height_ +
496         static_cast<uint32_t>((porIterValue.top + porIterValue.bottom) * densityDpi);
497     keyboardLayoutParams_.PortraitPanelRect_.posY_ =
498         keyboardLayoutParams_.PortraitKeyboardRect_.posY_ - static_cast<int32_t>(porIterValue.top * densityDpi);
499     keyboardLayoutParams_.PortraitPanelRect_.posX_ =
500         keyboardLayoutParams_.PortraitKeyboardRect_.posX_ - static_cast<int32_t>(porIterValue.left * densityDpi);
501 
502     //landscape floating keyboard
503     keyboardLayoutParams_.LandscapeKeyboardRect_.width_ = layoutParams.landscapeRect.width_;
504     keyboardLayoutParams_.LandscapeKeyboardRect_.height_ = layoutParams.landscapeRect.height_;
505     keyboardLayoutParams_.LandscapeKeyboardRect_.posY_ = layoutParams.landscapeRect.posY_;
506     keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ = layoutParams.landscapeRect.posX_;
507     //landscape floating panel
508     keyboardLayoutParams_.LandscapePanelRect_.width_ = keyboardLayoutParams_.LandscapeKeyboardRect_.width_ +
509         static_cast<uint32_t>((lanIterValue.left + lanIterValue.right) * densityDpi);
510     keyboardLayoutParams_.LandscapePanelRect_.height_ = keyboardLayoutParams_.LandscapeKeyboardRect_.height_ +
511         static_cast<uint32_t>((lanIterValue.top + lanIterValue.bottom) * densityDpi);
512     keyboardLayoutParams_.LandscapePanelRect_.posY_ =
513         keyboardLayoutParams_.LandscapeKeyboardRect_.posY_ - static_cast<int32_t>(lanIterValue.top * densityDpi);
514     keyboardLayoutParams_.LandscapePanelRect_.posX_ =
515         keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ - static_cast<int32_t>(lanIterValue.left * densityDpi);
516     return ErrorCode::NO_ERROR;
517 }
518 
CalculateLandscapeRect(sptr<OHOS::Rosen::Display> & defaultDisplay,const LayoutParams & layoutParams,PanelAdjustInfo & lanIterValue,float densityDpi)519 int32_t InputMethodPanel::CalculateLandscapeRect(sptr<OHOS::Rosen::Display> &defaultDisplay,
520     const LayoutParams &layoutParams, PanelAdjustInfo &lanIterValue, float densityDpi)
521 {
522     //LandscapePanel
523     WindowSize landscapeDisplaySize;
524     if (!GetDisplaySize(false, landscapeDisplaySize)) {
525         IMSA_HILOGE("GetDisplaySize failed!");
526         return ErrorCode::ERROR_WINDOW_MANAGER;
527     }
528     keyboardLayoutParams_.LandscapePanelRect_.width_ = landscapeDisplaySize.width;
529     keyboardLayoutParams_.LandscapePanelRect_.height_ = layoutParams.landscapeRect.height_ +
530         static_cast<uint32_t>((lanIterValue.top + lanIterValue.bottom) * densityDpi);
531     if (keyboardLayoutParams_.LandscapePanelRect_.height_ >
532         landscapeDisplaySize.height * FIXED_SOFT_KEYBOARD_PANEL_RATIO) {
533         keyboardLayoutParams_.LandscapePanelRect_.height_ =
534             landscapeDisplaySize.height * FIXED_SOFT_KEYBOARD_PANEL_RATIO;
535     }
536     keyboardLayoutParams_.LandscapePanelRect_.posY_ =
537         static_cast<int32_t>(landscapeDisplaySize.height - keyboardLayoutParams_.LandscapePanelRect_.height_);
538     keyboardLayoutParams_.LandscapePanelRect_.posX_ = NUMBER_ZERO;
539     //Landscapekeyboard
540     keyboardLayoutParams_.LandscapeKeyboardRect_.width_ = keyboardLayoutParams_.LandscapePanelRect_.width_ -
541         static_cast<uint32_t>((lanIterValue.left + lanIterValue.right) * densityDpi);
542     keyboardLayoutParams_.LandscapeKeyboardRect_.height_ = keyboardLayoutParams_.LandscapePanelRect_.height_ -
543         static_cast<uint32_t>((lanIterValue.top + lanIterValue.bottom) * densityDpi);
544     keyboardLayoutParams_.LandscapeKeyboardRect_.posY_ =
545         keyboardLayoutParams_.LandscapePanelRect_.posY_ + static_cast<int32_t>(lanIterValue.top * densityDpi);
546     keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ =
547         keyboardLayoutParams_.LandscapePanelRect_.posX_ + static_cast<int32_t>(lanIterValue.left * densityDpi);
548     sptr<Rosen::CutoutInfo> cutoutInfo = defaultDisplay->GetCutoutInfo();
549     if (cutoutInfo != nullptr) {
550         if (Rosen::DisplayManager::GetInstance().IsFoldable() &&
551             Rosen::DisplayManager::GetInstance().GetFoldStatus() != Rosen::FoldStatus::FOLDED) {
552             return ErrorCode::NO_ERROR;
553         }
554         keyboardLayoutParams_.LandscapeKeyboardRect_.width_ = keyboardLayoutParams_.LandscapeKeyboardRect_.width_ -
555             static_cast<uint32_t>((CUTOUTINFO - lanIterValue.left) * NUMBER_TWO  * densityDpi);
556         keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ = keyboardLayoutParams_.LandscapeKeyboardRect_.posX_ +
557             static_cast<int32_t>((CUTOUTINFO - lanIterValue.left) * densityDpi);
558     }
559     return ErrorCode::NO_ERROR;
560 }
561 
ChangePanelFlag(PanelFlag panelFlag)562 int32_t InputMethodPanel::ChangePanelFlag(PanelFlag panelFlag)
563 {
564     if (window_ == nullptr) {
565         IMSA_HILOGE("window_ is nullptr!");
566         return ErrorCode::ERROR_NULL_POINTER;
567     }
568     if (panelFlag_ == panelFlag) {
569         return ErrorCode::NO_ERROR;
570     }
571     if (panelType_ == STATUS_BAR) {
572         IMSA_HILOGE("STATUS_BAR cannot ChangePanelFlag!");
573         return ErrorCode::ERROR_BAD_PARAMETERS;
574     }
575     if (panelType_ == SOFT_KEYBOARD && panelFlag == FLG_CANDIDATE_COLUMN) {
576         PanelStatusChangeToImc(InputWindowStatus::HIDE, { 0, 0, 0, 0 });
577     }
578     WindowGravity gravity = WindowGravity::WINDOW_GRAVITY_FLOAT;
579     if (panelFlag == FLG_FIXED) {
580         gravity = WindowGravity::WINDOW_GRAVITY_BOTTOM;
581     } else {
582         auto surfaceNode = window_->GetSurfaceNode();
583         if (surfaceNode == nullptr) {
584             IMSA_HILOGE("surfaceNode is nullptr");
585             return ErrorCode::ERROR_NULL_POINTER;
586         }
587         surfaceNode->SetFrameGravity(Rosen::Gravity::TOP_LEFT);
588         Rosen::RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
589     }
590     if (!isScbEnable_) {
591         auto ret = window_->SetWindowGravity(gravity, invalidGravityPercent);
592         if (ret == WMError::WM_OK) {
593             panelFlag_ = panelFlag;
594         }
595         IMSA_HILOGI("flag: %{public}d, ret: %{public}d.", panelFlag, ret);
596         return ret == WMError::WM_OK ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL;
597     }
598     keyboardLayoutParams_.gravity_ = gravity;
599     auto ret = window_->AdjustKeyboardLayout(keyboardLayoutParams_);
600     if (ret == WMError::WM_OK) {
601         panelFlag_ = panelFlag;
602     }
603     IMSA_HILOGI("flag: %{public}d, ret: %{public}d.", panelFlag, ret);
604     return ret == WMError::WM_OK ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL;
605 }
606 
GetPanelType()607 PanelType InputMethodPanel::GetPanelType()
608 {
609     return panelType_;
610 }
611 
GetPanelFlag()612 PanelFlag InputMethodPanel::GetPanelFlag()
613 {
614     return panelFlag_;
615 }
616 
ShowPanel()617 int32_t InputMethodPanel::ShowPanel()
618 {
619     IMSA_HILOGD("InputMethodPanel start.");
620     int32_t waitTime = 0;
621     while (isWaitSetUiContent_ && waitTime < MAXWAITTIME) {
622         std::this_thread::sleep_for(std::chrono::milliseconds(WAITTIME));
623         waitTime += WAITTIME;
624         IMSA_HILOGI("InputMethodPanel show pannel waitTime %{public}d.", waitTime);
625     }
626     if (window_ == nullptr) {
627         IMSA_HILOGE("window_ is nullptr!");
628         return ErrorCode::ERROR_NULL_POINTER;
629     }
630     if (IsShowing()) {
631         IMSA_HILOGI("panel already shown.");
632         return ErrorCode::NO_ERROR;
633     }
634     auto ret = WMError::WM_OK;
635     {
636         InputMethodSyncTrace tracer("InputMethodPanel_ShowPanel");
637         ret = window_->Show();
638     }
639     if (ret != WMError::WM_OK) {
640         IMSA_HILOGE("ShowPanel error, err = %{public}d", ret);
641         return ErrorCode::ERROR_OPERATE_PANEL;
642     }
643     IMSA_HILOGI("success, type/flag: %{public}d/%{public}d.", static_cast<int32_t>(panelType_),
644         static_cast<int32_t>(panelFlag_));
645     PanelStatusChange(InputWindowStatus::SHOW);
646     if (!isScbEnable_) {
647         PanelStatusChangeToImc(InputWindowStatus::SHOW, window_->GetRect());
648     }
649     return ErrorCode::NO_ERROR;
650 }
651 
SetTextFieldAvoidInfo(double positionY,double height)652 int32_t InputMethodPanel::SetTextFieldAvoidInfo(double positionY, double height)
653 {
654     if (window_ == nullptr) {
655         IMSA_HILOGE("window_ is nullptr!");
656         return ErrorCode::ERROR_NULL_POINTER;
657     }
658     auto ret = window_->SetTextFieldAvoidInfo(positionY, height);
659     if (ret != WMError::WM_OK) {
660         IMSA_HILOGE("SetTextFieldAvoidInfo error, err: %{public}d!", ret);
661         return ErrorCode::ERROR_OPERATE_PANEL;
662     }
663     return ErrorCode::NO_ERROR;
664 }
665 
HidePanel()666 int32_t InputMethodPanel::HidePanel()
667 {
668     IMSA_HILOGD("InputMethodPanel start");
669     if (window_ == nullptr) {
670         IMSA_HILOGE("window_ is nullptr!");
671         return ErrorCode::ERROR_NULL_POINTER;
672     }
673     if (IsHidden()) {
674         IMSA_HILOGI("panel already hidden.");
675         return ErrorCode::NO_ERROR;
676     }
677     auto ret = WMError::WM_OK;
678     {
679         InputMethodSyncTrace tracer("InputMethodPanel_HidePanel");
680         ret = window_->Hide();
681     }
682     if (ret != WMError::WM_OK) {
683         IMSA_HILOGE("HidePanel error, err: %{public}d!", ret);
684         return ErrorCode::ERROR_OPERATE_PANEL;
685     }
686     IMSA_HILOGI("success, type/flag: %{public}d/%{public}d.", static_cast<int32_t>(panelType_),
687         static_cast<int32_t>(panelFlag_));
688     PanelStatusChange(InputWindowStatus::HIDE);
689     if (!isScbEnable_) {
690         PanelStatusChangeToImc(InputWindowStatus::HIDE, { 0, 0, 0, 0 });
691     }
692     return ErrorCode::NO_ERROR;
693 }
694 
SetCallingWindow(uint32_t windowId)695 int32_t InputMethodPanel::SetCallingWindow(uint32_t windowId)
696 {
697     IMSA_HILOGD("InputMethodPanel start, windowId: %{public}d.", windowId);
698     if (window_ == nullptr) {
699         IMSA_HILOGE("window_ is nullptr!");
700         return ErrorCode::ERROR_PANEL_NOT_FOUND;
701     }
702     auto ret = window_->SetCallingWindow(windowId);
703     IMSA_HILOGI("ret: %{public}d, windowId: %{public}u", ret, windowId);
704     return ret == WMError::WM_OK ? ErrorCode::NO_ERROR : ErrorCode::ERROR_WINDOW_MANAGER;
705 }
706 
GetCallingWindowInfo(CallingWindowInfo & windowInfo)707 int32_t InputMethodPanel::GetCallingWindowInfo(CallingWindowInfo &windowInfo)
708 {
709     IMSA_HILOGD("InputMethodPanel start.");
710     if (window_ == nullptr) {
711         IMSA_HILOGE("window_ is nullptr!");
712         return ErrorCode::ERROR_PANEL_NOT_FOUND;
713     }
714     auto ret = window_->GetCallingWindowWindowStatus(windowInfo.status);
715     if (ret != WMError::WM_OK) {
716         IMSA_HILOGE("get status failed, ret: %{public}d!", ret);
717         return ErrorCode::ERROR_WINDOW_MANAGER;
718     }
719     ret = window_->GetCallingWindowRect(windowInfo.rect);
720     if (ret != WMError::WM_OK) {
721         IMSA_HILOGE("get rect failed, ret: %{public}d!", ret);
722         return ErrorCode::ERROR_WINDOW_MANAGER;
723     }
724     IMSA_HILOGI("status: %{public}d, rect[x/y/w/h]: [%{public}d/%{public}d/%{public}d/%{public}d].",
725         static_cast<uint32_t>(windowInfo.status), windowInfo.rect.posX_, windowInfo.rect.posY_, windowInfo.rect.width_,
726         windowInfo.rect.height_);
727     return ErrorCode::NO_ERROR;
728 }
729 
SetPrivacyMode(bool isPrivacyMode)730 int32_t InputMethodPanel::SetPrivacyMode(bool isPrivacyMode)
731 {
732     IMSA_HILOGD("isPrivacyMode: %{public}d.", isPrivacyMode);
733     if (window_ == nullptr) {
734         IMSA_HILOGE("window_ is nullptr.");
735         return ErrorCode::ERROR_NULL_POINTER;
736     }
737     auto ret = window_->SetPrivacyMode(isPrivacyMode);
738     if (ret != WMError::WM_OK) {
739         IMSA_HILOGE("SetWindowPrivacyMode error, ret: %{public}d", ret);
740         return static_cast<int32_t>(ret);
741     }
742     IMSA_HILOGI("end, isPrivacyMode: %{public}d.", isPrivacyMode);
743     return ErrorCode::NO_ERROR;
744 }
745 
PanelStatusChange(const InputWindowStatus & status)746 void InputMethodPanel::PanelStatusChange(const InputWindowStatus &status)
747 {
748     if (status == InputWindowStatus::SHOW && showRegistered_ && panelStatusListener_ != nullptr) {
749         IMSA_HILOGD("ShowPanel panelStatusListener_ is not nullptr.");
750         panelStatusListener_->OnPanelStatus(windowId_, true);
751     }
752     if (status == InputWindowStatus::HIDE && hideRegistered_ && panelStatusListener_ != nullptr) {
753         IMSA_HILOGD("HidePanel panelStatusListener_ is not nullptr.");
754         panelStatusListener_->OnPanelStatus(windowId_, false);
755     }
756 }
757 
PanelStatusChangeToImc(const InputWindowStatus & status,const Rosen::Rect & rect)758 void InputMethodPanel::PanelStatusChangeToImc(const InputWindowStatus &status, const Rosen::Rect &rect)
759 {
760     ImeWindowInfo info;
761     info.panelInfo = { panelType_, panelFlag_ };
762     if (info.panelInfo.panelType != SOFT_KEYBOARD || info.panelInfo.panelFlag == FLG_CANDIDATE_COLUMN) {
763         IMSA_HILOGD("no need to deal.");
764         return;
765     }
766     auto proxy = ImaUtils::GetImsaProxy();
767     if (proxy == nullptr) {
768         IMSA_HILOGE("proxy is nullptr!");
769         return;
770     }
771     std::string name = window_->GetWindowName() + "/" + std::to_string(window_->GetWindowId());
772     info.windowInfo = { std::move(name), rect.posX_, rect.posY_, rect.width_, rect.height_ };
773     IMSA_HILOGD("rect[%{public}d, %{public}d, %{public}u, %{public}u], status: %{public}d, "
774                 "panelFlag: %{public}d.",
775         rect.posX_, rect.posY_, rect.width_, rect.height_, status, info.panelInfo.panelFlag);
776     proxy->PanelStatusChange(status, info);
777 }
778 
IsShowing()779 bool InputMethodPanel::IsShowing()
780 {
781     auto windowState = window_->GetWindowState();
782     if (windowState == WindowState::STATE_SHOWN) {
783         return true;
784     }
785     IMSA_HILOGD("windowState: %{public}d.", static_cast<int>(windowState));
786     return false;
787 }
788 
IsHidden()789 bool InputMethodPanel::IsHidden()
790 {
791     auto windowState = window_->GetWindowState();
792     if (windowState == WindowState::STATE_HIDDEN) {
793         return true;
794     }
795     IMSA_HILOGD("windowState: %{public}d.", static_cast<int>(windowState));
796     return false;
797 }
798 
SetUiContent(const std::string & contentInfo,napi_env env,std::shared_ptr<NativeReference> storage)799 int32_t InputMethodPanel::SetUiContent(const std::string &contentInfo, napi_env env,
800     std::shared_ptr<NativeReference> storage)
801 {
802     if (window_ == nullptr) {
803         IMSA_HILOGE("window_ is nullptr, can not SetUiContent.");
804         return ErrorCode::ERROR_NULL_POINTER;
805     }
806     WMError ret = WMError::WM_OK;
807     if (storage == nullptr) {
808         ret = window_->NapiSetUIContent(contentInfo, env, nullptr);
809     } else {
810         ret = window_->NapiSetUIContent(contentInfo, env, storage->GetNapiValue());
811     }
812     WMError wmError = window_->SetTransparent(true);
813     if (isWaitSetUiContent_) {
814         isWaitSetUiContent_ = false;
815     }
816     IMSA_HILOGI("SetTransparent ret: %{public}u.", wmError);
817     IMSA_HILOGI("NapiSetUIContent ret: %{public}d.", ret);
818     return ret == WMError::WM_ERROR_INVALID_PARAM ? ErrorCode::ERROR_PARAMETER_CHECK_FAILED : ErrorCode::NO_ERROR;
819 }
820 
SetPanelStatusListener(std::shared_ptr<PanelStatusListener> statusListener,const std::string & type)821 bool InputMethodPanel::SetPanelStatusListener(std::shared_ptr<PanelStatusListener> statusListener,
822     const std::string &type)
823 {
824     if (!MarkListener(type, true)) {
825         return false;
826     }
827     IMSA_HILOGD("type: %{public}s.", type.c_str());
828     if (type == "show" || type == "hide") {
829         if (panelStatusListener_ == nullptr) {
830             IMSA_HILOGD("panelStatusListener_ is nullptr, need to be set");
831             panelStatusListener_ = std::move(statusListener);
832         }
833         if (window_ != nullptr) {
834             if (type == "show" && IsShowing()) {
835                 panelStatusListener_->OnPanelStatus(windowId_, true);
836             }
837             if (type == "hide" && IsHidden()) {
838                 panelStatusListener_->OnPanelStatus(windowId_, false);
839             }
840         }
841     }
842     if (panelType_ == PanelType::SOFT_KEYBOARD &&
843         (panelFlag_ == PanelFlag::FLG_FIXED || panelFlag_ == PanelFlag::FLG_FLOATING) && type == "sizeChange") {
844         if (panelStatusListener_ == nullptr && statusListener != nullptr) {
845             panelStatusListener_ = std::move(statusListener);
846         }
847         std::lock_guard<std::mutex> lock(windowListenerLock_);
848         if (windowChangedListener_ != nullptr) {
849             IMSA_HILOGD("windowChangedListener already registered.");
850             return true;
851         }
852         windowChangedListener_ = new (std::nothrow)
853             WindowChangeListenerImpl([this](WindowSize windowSize) { SizeChange(windowSize); });
854         if (windowChangedListener_ == nullptr || window_ == nullptr) {
855             IMSA_HILOGE("observer or window_ is nullptr!");
856             return false;
857         }
858         auto ret = window_->RegisterWindowChangeListener(windowChangedListener_);
859         if (ret != WMError::WM_OK) {
860             IMSA_HILOGE("RegisterWindowChangeListener error: %{public}d!", ret);
861             return false;
862         }
863     }
864     return true;
865 }
866 
ClearPanelListener(const std::string & type)867 void InputMethodPanel::ClearPanelListener(const std::string &type)
868 {
869     if (!MarkListener(type, false)) {
870         return;
871     }
872     IMSA_HILOGD("type: %{public}s.", type.c_str());
873     if (type == "sizeChange" && windowChangedListener_ != nullptr && window_ != nullptr) {
874         auto ret = window_->UnregisterWindowChangeListener(windowChangedListener_);
875         IMSA_HILOGI("UnregisterWindowChangeListener ret: %{public}d.", ret);
876         windowChangedListener_ = nullptr;
877     }
878     if (panelStatusListener_ == nullptr) {
879         IMSA_HILOGD("panelStatusListener_ not set, don't need to remove.");
880         return;
881     }
882     if (showRegistered_ || hideRegistered_ || sizeChangeRegistered_) {
883         return;
884     }
885     panelStatusListener_ = nullptr;
886 }
887 
MarkListener(const std::string & type,bool isRegister)888 bool InputMethodPanel::MarkListener(const std::string &type, bool isRegister)
889 {
890     if (type == "show") {
891         showRegistered_ = isRegister;
892     } else if (type == "hide") {
893         hideRegistered_ = isRegister;
894     } else if (type == "sizeChange") {
895         sizeChangeRegistered_ = isRegister;
896     } else {
897         IMSA_HILOGE("type error.");
898         return false;
899     }
900     return true;
901 }
902 
GenerateSequenceId()903 uint32_t InputMethodPanel::GenerateSequenceId()
904 {
905     uint32_t seqId = ++sequenceId_;
906     if (seqId == std::numeric_limits<uint32_t>::max()) {
907         return ++sequenceId_;
908     }
909     return seqId;
910 }
911 
IsSizeValid(uint32_t width,uint32_t height)912 bool InputMethodPanel::IsSizeValid(uint32_t width, uint32_t height)
913 {
914     if (width > INT32_MAX || height > INT32_MAX) {
915         IMSA_HILOGE("width or height over maximum!");
916         return false;
917     }
918     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
919     if (defaultDisplay == nullptr) {
920         IMSA_HILOGE("GetDefaultDisplay failed.");
921         return false;
922     }
923     float ratio = panelType_ == PanelType::SOFT_KEYBOARD && panelFlag_ == PanelFlag::FLG_FIXED
924                       ? FIXED_SOFT_KEYBOARD_PANEL_RATIO
925                       : NON_FIXED_SOFT_KEYBOARD_PANEL_RATIO;
926     if (static_cast<float>(height) > defaultDisplay->GetHeight() * ratio) {
927         IMSA_HILOGE("height is invalid, defaultDisplay height: %{public}d, target height: %{public}u!",
928             defaultDisplay->GetHeight(), height);
929         return false;
930     }
931     if (static_cast<int32_t>(width) > defaultDisplay->GetWidth()) {
932         IMSA_HILOGE("width is invalid, defaultDisplay width: %{public}d, target width: %{public}u!",
933             defaultDisplay->GetWidth(), width);
934         return false;
935     }
936     return true;
937 }
938 
GetKeyboardSize()939 WindowSize InputMethodPanel::GetKeyboardSize()
940 {
941     std::lock_guard<std::mutex> lock(keyboardSizeLock_);
942     return keyboardSize_;
943 }
944 
SizeChange(const WindowSize & size)945 int32_t InputMethodPanel::SizeChange(const WindowSize &size)
946 {
947     IMSA_HILOGD("InputMethodPanel start.");
948     IMSA_HILOGI("type/flag: %{public}d/%{public}d, width/height: %{public}d/%{public}d.",
949         static_cast<int32_t>(panelType_), static_cast<int32_t>(panelFlag_), static_cast<int32_t>(size.width),
950         static_cast<int32_t>(size.height));
951     std::lock_guard<std::mutex> lock(keyboardSizeLock_);
952     keyboardSize_ = size;
953     panelStatusListener_->OnSizeChange(windowId_, size);
954     return ErrorCode::NO_ERROR;
955 }
956 
RegisterKeyboardPanelInfoChangeListener()957 void InputMethodPanel::RegisterKeyboardPanelInfoChangeListener()
958 {
959     kbPanelInfoListener_ = new (std::nothrow)
960         KeyboardPanelInfoChangeListener([this](const KeyboardPanelInfo &keyboardPanelInfo) {
961             if (panelHeightCallback_ != nullptr) {
962                 panelHeightCallback_(keyboardPanelInfo.rect_.height_, panelFlag_);
963             }
964             HandleKbPanelInfoChange(keyboardPanelInfo);
965         });
966     if (kbPanelInfoListener_ == nullptr) {
967         return;
968     }
969     if (window_ == nullptr) {
970         return;
971     }
972     auto ret = window_->RegisterKeyboardPanelInfoChangeListener(kbPanelInfoListener_);
973     IMSA_HILOGD("ret: %{public}d.", ret);
974 }
975 
UnregisterKeyboardPanelInfoChangeListener()976 void InputMethodPanel::UnregisterKeyboardPanelInfoChangeListener()
977 {
978     if (window_ == nullptr) {
979         return;
980     }
981     auto ret = window_->UnregisterKeyboardPanelInfoChangeListener(kbPanelInfoListener_);
982     kbPanelInfoListener_ = nullptr;
983     IMSA_HILOGD("ret: %{public}d.", ret);
984 }
985 
HandleKbPanelInfoChange(const KeyboardPanelInfo & keyboardPanelInfo)986 void InputMethodPanel::HandleKbPanelInfoChange(const KeyboardPanelInfo &keyboardPanelInfo)
987 {
988     IMSA_HILOGD("start.");
989     InputWindowStatus status = InputWindowStatus::HIDE;
990     if (keyboardPanelInfo.isShowing_) {
991         status = InputWindowStatus::SHOW;
992     }
993     PanelStatusChangeToImc(status, keyboardPanelInfo.rect_);
994 }
995 
GetDisplaySize(bool isPortrait,WindowSize & size)996 bool InputMethodPanel::GetDisplaySize(bool isPortrait, WindowSize &size)
997 {
998     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
999     if (defaultDisplay == nullptr) {
1000         IMSA_HILOGE("GetDefaultDisplay failed.");
1001         return false;
1002     }
1003     auto width = defaultDisplay->GetWidth();
1004     auto height = defaultDisplay->GetHeight();
1005     bool isDisplayPortrait = width < height;
1006     if (isPortrait != isDisplayPortrait) {
1007         size = { .width = height, .height = width };
1008     } else {
1009         size = { .width = width, .height = height };
1010     }
1011     return true;
1012 }
1013 
IsDisplayPortrait()1014 bool InputMethodPanel::IsDisplayPortrait()
1015 {
1016     auto defaultDisplay = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
1017     if (defaultDisplay == nullptr) {
1018     IMSA_HILOGE("GetDefaultDisplay failed.");
1019         return false;
1020     }
1021     auto width = defaultDisplay->GetWidth();
1022     auto height = defaultDisplay->GetHeight();
1023     return width < height;
1024 }
1025 
CheckSize(PanelFlag panelFlag,uint32_t width,uint32_t height,bool isDataPortrait)1026 bool InputMethodPanel::CheckSize(PanelFlag panelFlag, uint32_t width, uint32_t height, bool isDataPortrait)
1027 {
1028     WindowSize displaySize;
1029     if (!GetDisplaySize(isDataPortrait, displaySize)) {
1030         IMSA_HILOGE("GetDisplaySize failed.");
1031         return false;
1032     }
1033     return IsSizeValid(panelFlag, width, height, displaySize.width, displaySize.height);
1034 }
1035 
IsSizeValid(PanelFlag panelFlag,uint32_t width,uint32_t height,int32_t displayWidth,int32_t displayHeight)1036 bool InputMethodPanel::IsSizeValid(PanelFlag panelFlag, uint32_t width, uint32_t height, int32_t displayWidth,
1037     int32_t displayHeight)
1038 {
1039     if (width > INT32_MAX || height > INT32_MAX) {
1040         IMSA_HILOGE("width or height over maximum!");
1041         return false;
1042     }
1043     float ratio = panelType_ == PanelType::SOFT_KEYBOARD && panelFlag == PanelFlag::FLG_FIXED
1044                       ? FIXED_SOFT_KEYBOARD_PANEL_RATIO
1045                       : NON_FIXED_SOFT_KEYBOARD_PANEL_RATIO;
1046     if (static_cast<float>(height) > displayHeight * ratio) {
1047         IMSA_HILOGE("height is invalid, defaultDisplay height: %{public}d, target height: %{public}u!", displayHeight,
1048             height);
1049         return false;
1050     }
1051     if (static_cast<int32_t>(width) > displayWidth) {
1052         IMSA_HILOGE("width is invalid, defaultDisplay width: %{public}d, target width: %{public}u!", displayWidth,
1053             width);
1054         return false;
1055     }
1056     return true;
1057 }
1058 
SetPanelHeightCallback(CallbackFunc heightCallback)1059 void InputMethodPanel::SetPanelHeightCallback(CallbackFunc heightCallback)
1060 {
1061     panelHeightCallback_ = std::move(heightCallback);
1062 }
1063 } // namespace MiscServices
1064 } // namespace OHOS