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