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 ¶ms)
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 ¶ms,
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 ¶ms)
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 ¶ms, 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