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