diff --git a/common/include/global.h b/common/include/global.h index 3748e1939ebbd035879152555e0820043c36fc31..83d68a713dce6c9ed70234ced5c7d0658f1d44a1 100644 --- a/common/include/global.h +++ b/common/include/global.h @@ -142,6 +142,7 @@ enum { ERROR_SA_POST_TASK_FAILED, ERROR_IME_HAS_STARTED, ERROR_OPERATION_NOT_ALLOWED, + ERROR_INVALID_DISPLAYID, ERROR_IMSA_END, }; }; // namespace ErrorCode diff --git a/frameworks/js/napi/inputmethodability/js_panel.cpp b/frameworks/js/napi/inputmethodability/js_panel.cpp index d448f4020f5b0ef2f95c613124d813afe7ed7ffc..cb71ca175bf93fca57c871b5b72032ed8dd035df 100644 --- a/frameworks/js/napi/inputmethodability/js_panel.cpp +++ b/frameworks/js/napi/inputmethodability/js_panel.cpp @@ -65,6 +65,7 @@ napi_value JsPanel::Init(napi_env env) DECLARE_NAPI_FUNCTION("getImmersiveMode", GetImmersiveMode), DECLARE_NAPI_FUNCTION("setImmersiveEffect", SetImmersiveEffect), DECLARE_NAPI_FUNCTION("setKeepScreenOn", SetKeepScreenOn), + DECLARE_NAPI_FUNCTION("getSystemPanelInsets", GetSystemPanelInsets), }; NAPI_CALL(env, napi_define_class(env, CLASS_NAME.c_str(), CLASS_NAME.size(), JsNew, nullptr, sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor)); @@ -918,5 +919,63 @@ napi_value JsPanel::SetKeepScreenOn(napi_env env, napi_callback_info info) AsyncCall asyncCall(env, info, ctxt, 1); return asyncCall.Call(env, exec, "setKeepScreenOn"); } + +void JsPanel::GetSystemPanelInsetsOutput(std::shared_ptr ctxt, napi_env env, napi_value *result) +{ + napi_value prop = nullptr; + napi_create_object(env, &prop); + napi_value left = nullptr; + napi_create_uint32(env, ctxt->systemPanelInsets.left, &left); + napi_set_named_property(env, prop, "left", left); + napi_value right = nullptr; + napi_create_uint32(env, ctxt->systemPanelInsets.right, &right); + napi_set_named_property(env, prop, "right", right); + napi_value bottom = nullptr; + napi_create_uint32(env, ctxt->systemPanelInsets.bottom, &bottom); + napi_set_named_property(env, prop, "bottom", bottom); + *result = prop; +} + +napi_value JsPanel::GetSystemPanelInsets(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(env, info); + auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { + PARAM_CHECK_RETURN(env, ctxt->inputMethodPanel != nullptr, "panel is null", TYPE_NONE, napi_generic_failure); + PARAM_CHECK_RETURN(env, argc > 0, "at least one parameters is required", TYPE_NONE, napi_generic_failure); + uint32_t displayId = 0; + PARAM_CHECK_RETURN(env, JsUtils::GetValue(env, argv[0], displayId) == napi_ok, "failed to convert inputRegion", + TYPE_NONE, napi_generic_failure); + if (displayId < 0) { + return napi_generic_failure; + } + ctxt->displayId = static_cast(displayId); + ctxt->info = { std::chrono::system_clock::now(), JsEvent::GET_SYSTEM_PANEL_INSETS }; + jsQueue_.Push(ctxt->info); + return napi_ok; + }; + auto exec = [ctxt](AsyncCall::Context *ctx) { + jsQueue_.Wait(ctxt->info); + if (ctxt->inputMethodPanel == nullptr) { + IMSA_HILOGE("inputMethodPanel_ is nullptr!"); + jsQueue_.Pop(); + return; + } + auto ret = ctxt->inputMethodPanel->GetSystemPanelInsets(ctxt->displayId, ctxt->systemPanelInsets); + jsQueue_.Pop(); + if (ret == ErrorCode::NO_ERROR) { + ctxt->SetState(napi_ok); + return; + } + ctxt->SetErrorCode(ret); + }; + auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { + GetSystemPanelInsetsOutput(ctxt, env, result); + return napi_ok; + }; + ctxt->SetAction(std::move(input), std::move(output)); + // 1 means JsAPI:getSystemPanelInsets has 1 params at most. + AsyncCall asyncCall(env, info, ctxt, 1); + return asyncCall.Call(env, exec, "getSystemPanelInsets"); +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/frameworks/js/napi/inputmethodability/js_panel.h b/frameworks/js/napi/inputmethodability/js_panel.h index e2345c0591d151e1a89aa7731175b5a2a8b4e776..222a89076313db4d5ec486f54ff1f10b3d34003d 100644 --- a/frameworks/js/napi/inputmethodability/js_panel.h +++ b/frameworks/js/napi/inputmethodability/js_panel.h @@ -44,6 +44,7 @@ enum class JsEvent : uint32_t { SET_IMMERSIVE_MODE, GET_IMMERSIVE_MODE, SET_IMMERSIVE_EFFECT, + GET_SYSTEM_PANEL_INSETS, EVENT_END, }; @@ -97,6 +98,7 @@ public: static napi_value GetImmersiveMode(napi_env env, napi_callback_info info); static napi_value SetImmersiveEffect(napi_env env, napi_callback_info info); static napi_value SetKeepScreenOn(napi_env env, napi_callback_info info); + static napi_value GetSystemPanelInsets(napi_env env, napi_callback_info info); private: struct PanelContentContext : public AsyncCall::Context { @@ -113,6 +115,7 @@ private: int32_t y = 0; uint64_t displayId = 0; bool isKeepScreenOn = false; + SystemPanelInsets systemPanelInsets = {0, 0, 0}; std::shared_ptr inputMethodPanel = nullptr; std::shared_ptr contentStorage = nullptr; JsEventInfo info; @@ -154,6 +157,8 @@ private: napi_env env, size_t argc, napi_value *argv, std::shared_ptr ctxt); static void AdjustLayoutParam(std::shared_ptr ctxt); static void AdjustEnhancedLayoutParam(std::shared_ptr ctxt); + static void GetSystemPanelInsetsOutput(std::shared_ptr ctxt, napi_env env, + napi_value *result); static const std::string CLASS_NAME; static constexpr size_t ARGC_MAX = 6; diff --git a/frameworks/js/napi/inputmethodclient/js_utils.cpp b/frameworks/js/napi/inputmethodclient/js_utils.cpp index 737d2e7a2a2b1e18dc109494b8aae445c40213ba..96e0cf5dabcf4a201d4a5cde3548a55c0d0ec87f 100644 --- a/frameworks/js/napi/inputmethodclient/js_utils.cpp +++ b/frameworks/js/napi/inputmethodclient/js_utils.cpp @@ -94,6 +94,7 @@ const std::map JsUtils::ERROR_CODE_MAP = { { ErrorCode::ERROR_IMA_DATA_CHANNEL_ABNORMAL, EXCEPTION_IMCLIENT }, { ErrorCode::ERROR_IMA_INVALID_IMMERSIVE_EFFECT, EXCEPTION_INVALID_IMMERSIVE_EFFECT }, { ErrorCode::ERROR_IMA_PRECONDITION_REQUIRED, EXCEPTION_PRECONDITION_REQUIRED }, + { ErrorCode::ERROR_INVALID_DISPLAYID, EXCEPTION_INVALID_DISPLAYID }, }; const std::map JsUtils::ERROR_CODE_CONVERT_MESSAGE_MAP = { @@ -129,6 +130,7 @@ const std::map JsUtils::ERROR_CODE_CONVERT_MESSAGE_MAP = { 2.The fluid light mode can only be used when the gradient mode is enabled.\n\ 3.When the gradient mode is not enabled, the gradient height can only be 0." }, { EXCEPTION_PRECONDITION_REQUIRED, "this operation must be called after adjustPanelRect or resize." }, + { EXCEPTION_INVALID_DISPLAYID, "invalid displayid." }, }; const std::map JsUtils::PARAMETER_TYPE = { diff --git a/frameworks/js/napi/inputmethodclient/js_utils.h b/frameworks/js/napi/inputmethodclient/js_utils.h index 71797468f739718b8eeefa501cfaece793387c98..166330947fcb6d941f3694f4dbe85acb3b01c366 100644 --- a/frameworks/js/napi/inputmethodclient/js_utils.h +++ b/frameworks/js/napi/inputmethodclient/js_utils.h @@ -58,6 +58,7 @@ enum IMFErrorCode : int32_t { EXCEPTION_OPERATE_DEFAULTIME = 12800019, EXCEPTION_INVALID_IMMERSIVE_EFFECT = 12800020, EXCEPTION_PRECONDITION_REQUIRED = 12800021, + EXCEPTION_INVALID_DISPLAYID = 12800022, }; enum TypeCode : int32_t { diff --git a/frameworks/native/inputmethod_ability/include/input_method_panel.h b/frameworks/native/inputmethod_ability/include/input_method_panel.h index bc995a06d9735a976339bc595b3cda88dce6ae9c..c791797acb2401d0e584b00b17d3dbe47a1cc406 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_panel.h +++ b/frameworks/native/inputmethod_ability/include/input_method_panel.h @@ -83,6 +83,8 @@ public: bool IsInMainDisplay(); int32_t SetImmersiveEffect(const ImmersiveEffect &effect); int32_t SetKeepScreenOn(bool isKeepScreenOn); + int32_t GetSystemPanelInsets(uint64_t displayId, SystemPanelInsets &systemPanelInsets); + int32_t AreaInsets(SystemPanelInsets &systemPanelInsets); uint32_t windowId_ = INVALID_WINDOW_ID; private: diff --git a/frameworks/native/inputmethod_ability/include/panel_info.h b/frameworks/native/inputmethod_ability/include/panel_info.h index e10d0bf9d006f287516d418bdedb18efe1f98712..ec09e20375ba5e873c689e7b3c39bcfd576ff5d3 100644 --- a/frameworks/native/inputmethod_ability/include/panel_info.h +++ b/frameworks/native/inputmethod_ability/include/panel_info.h @@ -99,6 +99,12 @@ struct ImmersiveEffect { return ss.str(); } }; + +struct SystemPanelInsets { + int32_t left{ 0 }; + int32_t right{ 0 }; + int32_t bottom{ 0 }; +}; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/src/input_method_panel.cpp b/frameworks/native/inputmethod_ability/src/input_method_panel.cpp index 5c2307489598b32a2d7e477b6bb2394a5defb6f5..88b4c31b4bc6f2499dcc3f69bbee4ee4110fefb7 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_panel.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_panel.cpp @@ -2237,5 +2237,62 @@ void InputMethodPanel::SetChangeY(ChangeY changeY) std::lock_guard lock(changeYMutex_); changeY_ = changeY; } + +int32_t InputMethodPanel::AreaInsets(SystemPanelInsets &systemPanelInsets) +{ + FullPanelAdjustInfo adjustInfo; + auto code = GetAdjustInfo(panelFlag_, adjustInfo); + if (code != ErrorCode::NO_ERROR) { + IMSA_HILOGE("GetAdjustInfo failed ret: %{public}d", code); + return code; + } + if (IsDisplayPortrait()) { + systemPanelInsets.bottom = adjustInfo.portrait.bottom; + systemPanelInsets.left = adjustInfo.portrait.left; + systemPanelInsets.right = adjustInfo.portrait.right; + } else { + systemPanelInsets.bottom = adjustInfo.landscape.bottom; + systemPanelInsets.left = adjustInfo.landscape.left; + systemPanelInsets.right = adjustInfo.landscape.right; + } + return ErrorCode::NO_ERROR; +} + +int32_t InputMethodPanel::GetSystemPanelInsets(uint64_t displayId, SystemPanelInsets &systemPanelInsets) +{ + IMSA_HILOGD("enter!!"); + if (window_ == nullptr) { + IMSA_HILOGE("window_ is nullptr!"); + return ErrorCode::ERROR_WINDOW_MANAGER; + } + if (panelType_ == PanelType::STATUS_BAR) { + IMSA_HILOGE("invalid panel type!"); + return ErrorCode::ERROR_INVALID_PANEL_TYPE; + } + if (panelFlag_ == PanelFlag::FLG_CANDIDATE_COLUMN) { + IMSA_HILOGE("panelFlag_ is candidate column"); + return ErrorCode::ERROR_INVALID_PANEL_FLAG; + } + uint64_t curDisplayId = 0; + auto ret = GetDisplayId(curDisplayId); + if (ret != ErrorCode::NO_ERROR) { + IMSA_HILOGE("GetDisplayId err:%{public}d!", ret); + return ErrorCode::ERROR_WINDOW_MANAGER; + } + if (displayId != curDisplayId) { + IMSA_HILOGE("invalid displayId"); + return ErrorCode::ERROR_INVALID_DISPLAYID; + } + if (!IsNeedConfig()) { + IMSA_HILOGI("is special InputType or is not in main display"); + return ErrorCode::NO_ERROR; + } + auto code = AreaInsets(systemPanelInsets); + if (code != ErrorCode::NO_ERROR) { + return code; + } + IMSA_HILOGD("GetSystemPanelInsets success!!"); + return ErrorCode::NO_ERROR; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/test/unittest/cpp_test/src/input_method_panel_test.cpp b/test/unittest/cpp_test/src/input_method_panel_test.cpp index 5ec49b7a5183c633db7bb546fc2b78bc14ce7f60..1de49d43c7b42273ae77d3535872388ca4a1e68c 100644 --- a/test/unittest/cpp_test/src/input_method_panel_test.cpp +++ b/test/unittest/cpp_test/src/input_method_panel_test.cpp @@ -2619,5 +2619,122 @@ HWTEST_F(InputMethodPanelTest, TestInitAdjustInfo, TestSize.Level1) ret = panel->InitAdjustInfo(); EXPECT_EQ(ret, ErrorCode::NO_ERROR); } + +/** + * @tc.name: testGetSystemPanelInsets1 + * @tc.desc: Test GetSystemPanelInsets. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodPanelTest, testGetSystemPanelInsets1, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPanelTest::testGetSystemPanelInsets1 start."); + auto inputMethodPanel = InputMethodPanelTest::CreatePanel(); + uint64_t displayId = 0; + auto ret = inputMethodPanel->GetDisplayId(displayId); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + + SystemPanelInsets panelInsets = {0, 0, 0}; + ret = inputMethodPanel->GetSystemPanelInsets(displayId, panelInsets); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + InputMethodPanelTest::DestroyPanel(inputMethodPanel); +} + +/** + * @tc.name: testGetSystemPanelInsets2 + * @tc.desc: Test GetSystemPanelInsets. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodPanelTest, testGetSystemPanelInsets2, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPanelTest::testGetSystemPanelInsets2 start."); + + AccessScope scope(currentImeTokenId_, currentImeUid_); + auto inputMethodPanel = std::make_shared(); + PanelInfo panelInfo; + panelInfo.panelType = PanelType::STATUS_BAR; + panelInfo.panelFlag = PanelFlag::FLG_CANDIDATE_COLUMN; + auto ret = inputMethodPanel->CreatePanel(nullptr, panelInfo); + + SystemPanelInsets panelInsets = {0, 0, 0}; + uint64_t displayId = 0; + inputMethodPanel->GetDisplayId(displayId); + ret = inputMethodPanel->GetSystemPanelInsets(displayId, panelInsets); + EXPECT_EQ(ret, ErrorCode::ERROR_INVALID_PANEL_TYPE); + + InputMethodPanelTest::DestroyPanel(inputMethodPanel); +} + +/** + * @tc.name: testGetSystemPanelInsets3 + * @tc.desc: Test GetSystemPanelInsets. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodPanelTest, testGetSystemPanelInsets3, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPanelTest::testGetSystemPanelInsets3 start."); + + AccessScope scope(currentImeTokenId_, currentImeUid_); + auto inputMethodPanel = std::make_shared(); + PanelInfo panelInfo; + panelInfo.panelType = PanelType::SOFT_KEYBOARD; + panelInfo.panelFlag = PanelFlag::FLG_CANDIDATE_COLUMN; + auto ret = inputMethodPanel->CreatePanel(nullptr, panelInfo); + + SystemPanelInsets panelInsets = {0, 0, 0}; + uint64_t displayId = 0; + inputMethodPanel->GetDisplayId(displayId); + ret = inputMethodPanel->GetSystemPanelInsets(displayId, panelInsets); + EXPECT_EQ(ret, ErrorCode::ERROR_INVALID_PANEL_FLAG); + + InputMethodPanelTest::DestroyPanel(inputMethodPanel); +} + +/** + * @tc.name: testGetSystemPanelInsets4 + * @tc.desc: Test GetSystemPanelInsets. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodPanelTest, testGetSystemPanelInsets4, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPanelTest::testGetSystemPanelInsets4 start."); + + AccessScope scope(currentImeTokenId_, currentImeUid_); + auto inputMethodPanel = std::make_shared(); + PanelInfo panelInfo; + panelInfo.panelType = PanelType::SOFT_KEYBOARD;; + panelInfo.panelFlag = PanelFlag::FLG_FIXED; + auto ret = inputMethodPanel->CreatePanel(nullptr, panelInfo); + + SystemPanelInsets panelInsets = {0, 0, 0}; + uint64_t displayId = 10; + ret = inputMethodPanel->GetSystemPanelInsets(displayId, panelInsets); + EXPECT_EQ(ret, ErrorCode::ERROR_INVALID_DISPLAYID); + InputMethodPanelTest::DestroyPanel(inputMethodPanel); +} + +/** + * @tc.name: testGetSystemPanelInsets5 + * @tc.desc: Test GetSystemPanelInsets. + * @tc.type: FUNC + */ +HWTEST_F(InputMethodPanelTest, testGetSystemPanelInsets5, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodPanelTest::testGetSystemPanelInsets4 start."); + + AccessScope scope(currentImeTokenId_, currentImeUid_); + auto inputMethodPanel = std::make_shared(); + PanelInfo panelInfo; + panelInfo.panelType = PanelType::SOFT_KEYBOARD;; + panelInfo.panelFlag = PanelFlag::FLG_FIXED; + auto ret = inputMethodPanel->CreatePanel(nullptr, panelInfo); + + SystemPanelInsets panelInsets = {0, 0, 0}; + uint64_t displayId = 0; + + InputMethodPanelTest::DestroyPanel(inputMethodPanel); + inputMethodPanel->window_ = nullptr; + ret = inputMethodPanel->GetSystemPanelInsets(displayId, panelInsets); + EXPECT_EQ(ret, ErrorCode::ERROR_WINDOW_MANAGER); +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/test/unittest/napi_test/src/InputMethodWithAttachTest.js b/test/unittest/napi_test/src/InputMethodWithAttachTest.js index 109ecd8864715dd69349e0d38e2d310572adae15..7e9b5c4a6f72160a215adcd9e743b0d8c77b5462 100644 --- a/test/unittest/napi_test/src/InputMethodWithAttachTest.js +++ b/test/unittest/napi_test/src/InputMethodWithAttachTest.js @@ -44,7 +44,8 @@ describe('InputMethodWithAttachTest', function () { ADJUST_SUCCESS: 19, SET_PREVIEW_TEXT: 20, FINISH_TEXT_PREVIEW: 21, - SET_KEEP_SCREEN_ON: 22 + SET_KEEP_SCREEN_ON: 22, + GET_SYSTEM_PANEL_INSETS: 23 } beforeAll(async function (done) { @@ -683,6 +684,28 @@ describe('InputMethodWithAttachTest', function () { } }); + /* + * @tc.number inputmethod_test_getSystemPanelInsets_001 + * @tc.name Test Indicates the input method which will replace the current one. + * @tc.desc Function test + * @tc.level 2 + */ + it('inputmethod_test_getSystemPanelInsets_001', 0, async function (done) { + console.info('************* inputmethod_test_getSystemPanelInsets_001 Test start*************'); + let inputMethodCtrl = inputMethod.getController(); + await inputMethodCtrl.showSoftKeyboard(); + try { + let subscribeInfo = { + events: ['getSystemPanelInsets'] + }; + subscribe(subscribeInfo, TEST_FUNCTION.GET_SYSTEM_PANEL_INSETS, done); + } catch(error) { + console.info(`inputmethod_test_getSystemPanelInsets_001 result: ${JSON.stringify(error)}`); + expect().assertFail(); + done(); + } + }); + /* * @tc.number inputmethod_test_getSystemPanelInsets_001 * @tc.name Test Indicates the input method which will replace the current one. diff --git a/test/unittest/resource/bundle_dependencies/extImfBundle/entry/src/main/ets/InputMethodExtAbility/model/KeyboardController.ts b/test/unittest/resource/bundle_dependencies/extImfBundle/entry/src/main/ets/InputMethodExtAbility/model/KeyboardController.ts index 6b16505fafb01bbf5b00d868e999ffa06a8cdd47..aa8d939031a2c4dcbf57bc6532f9120e07ee0cb6 100644 --- a/test/unittest/resource/bundle_dependencies/extImfBundle/entry/src/main/ets/InputMethodExtAbility/model/KeyboardController.ts +++ b/test/unittest/resource/bundle_dependencies/extImfBundle/entry/src/main/ets/InputMethodExtAbility/model/KeyboardController.ts @@ -53,6 +53,7 @@ enum TEST_FUNCTION { SET_PREVIEW_TEXT, FINISH_TEXT_PREVIEW, SET_KEEP_SCREEN_ON, + GET_SYSTEM_PANEL_INSETS, } export class KeyboardController { @@ -196,6 +197,9 @@ export class KeyboardController { case TEST_FUNCTION.SET_KEEP_SCREEN_ON: this.setKeepScreenOn(); break; + case TEST_FUNCTION.GET_SYSTEM_PANEL_INSETS: + this.getSystemPanelInsets(); + break; default: break; } @@ -203,6 +207,21 @@ export class KeyboardController { }) } + private async getSystemPanelInsets() { + try { + let displayId: number = await this.panel.getDisplayId(); + let insets = await this.panel.getSystemPanelInsets(displayId); + if (insets === undefined || insets === null) { + console.log('[getSystemPanelInsets] failed, insets is null.' ) + this.publishCommonEvent('getSystemPanelInsets', TEST_RESULT_CODE.FAILED); + } + this.publishCommonEvent('getSystemPanelInsets', TEST_RESULT_CODE.SUCCESS); + } catch (err) { + console.log('[getSystemPanelInsets] failed.' ) + this.publishCommonEvent('getSystemPanelInsets', TEST_RESULT_CODE.FAILED); + } + } + private async setKeepScreenOn() { try { await this.panel.setKeepScreenOn(true);