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