diff --git a/frameworks/js/napi/inputmethodability/js_panel.cpp b/frameworks/js/napi/inputmethodability/js_panel.cpp index b77751a0..6bd4091e 100644 --- a/frameworks/js/napi/inputmethodability/js_panel.cpp +++ b/frameworks/js/napi/inputmethodability/js_panel.cpp @@ -156,6 +156,7 @@ napi_value JsPanel::Resize(napi_env env, napi_callback_info info) CHECK_RETURN_VOID(ctxt->inputMethodPanel != nullptr, "inputMethodPanel_ is nullptr."); auto code = ctxt->inputMethodPanel->Resize(ctxt->width, ctxt->height); if (code == ErrorCode::NO_ERROR) { + InputMethodAbility::GetInstance()->NotifyKeyboardHeight(ctxt->inputMethodPanel); ctxt->SetState(napi_ok); return; } @@ -245,6 +246,7 @@ napi_value JsPanel::ChangeFlag(napi_env env, napi_callback_info info) auto inputMethodPanel = UnwrapPanel(env, thisVar); auto ret = inputMethodPanel->ChangePanelFlag(PanelFlag(panelFlag)); CHECK_RETURN(ret == ErrorCode::NO_ERROR, "ChangePanelFlag failed!", nullptr); + InputMethodAbility::GetInstance()->NotifyKeyboardHeight(inputMethodPanel); return nullptr; } diff --git a/frameworks/native/inputmethod_ability/include/input_method_ability.h b/frameworks/native/inputmethod_ability/include/input_method_ability.h index 661f6522..30765443 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_ability.h +++ b/frameworks/native/inputmethod_ability/include/input_method_ability.h @@ -84,6 +84,7 @@ public: int32_t OnSecurityChange(int32_t security); void OnClientInactive(const sptr &channel); int32_t OnTextConfigChange(const InputClientInfo &clientInfo); + void NotifyKeyboardHeight(const std::shared_ptr inputMethodPanel); private: std::thread workThreadHandler; diff --git a/frameworks/native/inputmethod_ability/include/input_method_panel.h b/frameworks/native/inputmethod_ability/include/input_method_panel.h index a77f37a3..b245cf6a 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_panel.h +++ b/frameworks/native/inputmethod_ability/include/input_method_panel.h @@ -49,6 +49,7 @@ public: int32_t SetPrivacyMode(bool isPrivacyMode); bool IsShowing(); int32_t SetTextFieldAvoidInfo(double positionY, double height); + uint32_t GetHeight(); uint32_t windowId_ = 0; private: @@ -70,6 +71,8 @@ private: std::shared_ptr panelStatusListener_ = nullptr; static std::atomic sequenceId_; + std::mutex heightLock_; + uint32_t panelHeight_ = 0; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index c0c51cc5..0a56ff76 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -944,5 +944,27 @@ int32_t InputMethodAbility::OnTextConfigChange(const InputClientInfo &clientInfo InvokeTextChangeCallback(clientInfo.config); return clientInfo.isShowKeyboard ? ShowKeyboard() : ErrorCode::NO_ERROR; } + +void InputMethodAbility::NotifyKeyboardHeight(const std::shared_ptr inputMethodPanel) +{ + if (inputMethodPanel == nullptr) { + IMSA_HILOGE("inputMethodPanel is nullptr"); + return; + } + if (inputMethodPanel->GetPanelType() != PanelType::SOFT_KEYBOARD) { + IMSA_HILOGW("current panel is not soft keyboard"); + return; + } + auto channel = GetInputDataChannelProxy(); + if (channel == nullptr) { + IMSA_HILOGE("channel is nullptr"); + return; + } + if (inputMethodPanel->GetPanelFlag() != PanelFlag::FLG_FIXED) { + channel->NotifyKeyboardHeight(0); + return; + } + channel->NotifyKeyboardHeight(inputMethodPanel->GetHeight()); +} } // 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 0ce607fc..1ac75b82 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_panel.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_panel.cpp @@ -121,7 +121,14 @@ int32_t InputMethodPanel::Resize(uint32_t width, uint32_t height) } auto ret = window_->Resize(width, height); IMSA_HILOGI("ret = %{public}d", ret); - return ret == WMError::WM_OK ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL; + if (ret != WMError::WM_OK) { + return ErrorCode::ERROR_OPERATE_PANEL; + } + { + std::lock_guard lock(heightLock_); + panelHeight_ = height; + } + return ErrorCode::NO_ERROR; } int32_t InputMethodPanel::MoveTo(int32_t x, int32_t y) @@ -404,5 +411,11 @@ bool InputMethodPanel::IsSizeValid(uint32_t width, uint32_t height) } return true; } + +uint32_t InputMethodPanel::GetHeight() +{ + std::lock_guard lock(heightLock_); + return panelHeight_; +} } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/i_input_data_channel.h b/frameworks/native/inputmethod_controller/include/i_input_data_channel.h index 048ba529..058d6bb2 100644 --- a/frameworks/native/inputmethod_controller/include/i_input_data_channel.h +++ b/frameworks/native/inputmethod_controller/include/i_input_data_channel.h @@ -46,6 +46,7 @@ public: GET_TEXT_INDEX_AT_CURSOR, GET_TEXT_CONFIG, NOTIFY_PANEL_STATUS_INFO, + NOTIFY_KEYBOARD_HEIGHT, DATA_CHANNEL_CMD_LAST }; @@ -67,6 +68,7 @@ public: virtual int32_t HandleExtendAction(int32_t action) = 0; virtual int32_t GetTextIndexAtCursor(int32_t &index) = 0; virtual void NotifyPanelStatusInfo(const PanelStatusInfo &info) = 0; + virtual void NotifyKeyboardHeight(uint32_t height) = 0; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/input_data_channel_proxy.h b/frameworks/native/inputmethod_controller/include/input_data_channel_proxy.h index 4f405acf..6fc929a9 100644 --- a/frameworks/native/inputmethod_controller/include/input_data_channel_proxy.h +++ b/frameworks/native/inputmethod_controller/include/input_data_channel_proxy.h @@ -51,6 +51,7 @@ public: int32_t GetTextIndexAtCursor(int32_t &index) override; int32_t GetTextConfig(TextTotalConfig &textConfig) override; void NotifyPanelStatusInfo(const PanelStatusInfo &info) override; + void NotifyKeyboardHeight(uint32_t height) override; private: static inline BrokerDelegator delegator_; diff --git a/frameworks/native/inputmethod_controller/include/input_data_channel_stub.h b/frameworks/native/inputmethod_controller/include/input_data_channel_stub.h index ffd99e04..89b6828d 100644 --- a/frameworks/native/inputmethod_controller/include/input_data_channel_stub.h +++ b/frameworks/native/inputmethod_controller/include/input_data_channel_stub.h @@ -53,6 +53,7 @@ public: int32_t HandleExtendAction(int32_t action) override; int32_t GetTextConfig(TextTotalConfig &textConfig) override; void NotifyPanelStatusInfo(const PanelStatusInfo &info) override; + void NotifyKeyboardHeight(uint32_t height) override; private: int32_t InsertTextOnRemote(MessageParcel &data, MessageParcel &reply); @@ -71,6 +72,7 @@ private: int32_t HandleExtendActionOnRemote(MessageParcel &data, MessageParcel &reply); int32_t GetTextIndexAtCursorOnRemote(MessageParcel &data, MessageParcel &reply); int32_t NotifyPanelStatusInfoOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t NotifyKeyboardHeightOnRemote(MessageParcel &data, MessageParcel &reply); using RequestHandler = int32_t (InputDataChannelStub::*)(MessageParcel &, MessageParcel &); static inline const std::unordered_map HANDLERS = { { static_cast(INSERT_TEXT), &InputDataChannelStub::InsertTextOnRemote }, @@ -89,6 +91,7 @@ private: { static_cast(GET_TEXT_INDEX_AT_CURSOR), &InputDataChannelStub::GetTextIndexAtCursorOnRemote }, { static_cast(GET_TEXT_CONFIG), &InputDataChannelStub::GetTextConfigOnRemote }, { static_cast(NOTIFY_PANEL_STATUS_INFO), &InputDataChannelStub::NotifyPanelStatusInfoOnRemote }, + { static_cast(NOTIFY_KEYBOARD_HEIGHT), &InputDataChannelStub::NotifyKeyboardHeightOnRemote }, }; }; } // namespace MiscServices diff --git a/frameworks/native/inputmethod_controller/src/input_data_channel_proxy.cpp b/frameworks/native/inputmethod_controller/src/input_data_channel_proxy.cpp index 526f1ec1..bdc2fcb9 100644 --- a/frameworks/native/inputmethod_controller/src/input_data_channel_proxy.cpp +++ b/frameworks/native/inputmethod_controller/src/input_data_channel_proxy.cpp @@ -124,10 +124,17 @@ int32_t InputDataChannelProxy::HandleExtendAction(int32_t action) HANDLE_EXTEND_ACTION, [action](MessageParcel &parcel) { return ITypesUtil::Marshal(parcel, action); }); } +void InputDataChannelProxy::NotifyKeyboardHeight(uint32_t height) +{ + SendRequest( + NOTIFY_KEYBOARD_HEIGHT, [height](MessageParcel &parcel) { return ITypesUtil::Marshal(parcel, height); }); +} + void InputDataChannelProxy::GetMessageOption(int32_t code, MessageOption &option) { switch (code) { case SEND_KEYBOARD_STATUS: + case NOTIFY_KEYBOARD_HEIGHT: IMSA_HILOGD("Async IPC."); option.SetFlags(MessageOption::TF_ASYNC); break; diff --git a/frameworks/native/inputmethod_controller/src/input_data_channel_stub.cpp b/frameworks/native/inputmethod_controller/src/input_data_channel_stub.cpp index 241474f8..5403a4c9 100644 --- a/frameworks/native/inputmethod_controller/src/input_data_channel_stub.cpp +++ b/frameworks/native/inputmethod_controller/src/input_data_channel_stub.cpp @@ -207,6 +207,17 @@ int32_t InputDataChannelStub::NotifyPanelStatusInfoOnRemote(MessageParcel &data, return reply.WriteInt32(ErrorCode::NO_ERROR) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; } +int32_t InputDataChannelStub::NotifyKeyboardHeightOnRemote(MessageParcel &data, MessageParcel &reply) +{ + uint32_t height = 0; + if (!ITypesUtil::Unmarshal(data, height)) { + IMSA_HILOGE("failed to read message parcel"); + return ErrorCode::ERROR_EX_PARCELABLE; + } + NotifyKeyboardHeight(height); + return reply.WriteInt32(ErrorCode::NO_ERROR) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; +} + int32_t InputDataChannelStub::InsertText(const std::u16string &text) { return InputMethodController::GetInstance()->InsertText(text); @@ -288,5 +299,10 @@ void InputDataChannelStub::NotifyPanelStatusInfo(const PanelStatusInfo &info) { InputMethodController::GetInstance()->NotifyPanelStatusInfo(info); } + +void InputDataChannelStub::NotifyKeyboardHeight(uint32_t height) +{ + InputMethodController::GetInstance()->NotifyKeyboardHeight(height); +} } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp index 9281b282..1fc1fc6e 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -1098,6 +1098,17 @@ void InputMethodController::NotifyPanelStatusInfo(const PanelStatusInfo &info) } } +void InputMethodController::NotifyKeyboardHeight(uint32_t height) +{ + IMSA_HILOGD("InputMethodController, height: %{public}u.", height); + auto listener = GetTextListener(); + if (listener == nullptr) { + IMSA_HILOGE("textListener_ is nullptr"); + return; + } + listener->NotifyKeyboardHeight(height); +} + int32_t InputMethodController::SendFunctionKey(int32_t functionKey) { IMSA_HILOGD("run in, functionKey: %{public}d", static_cast(functionKey)); diff --git a/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h b/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h index 2c879906..a6da60a5 100644 --- a/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h +++ b/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h @@ -53,6 +53,9 @@ public: virtual void NotifyPanelStatusInfo(const PanelStatusInfo &info) { } + virtual void NotifyKeyboardHeight(uint32_t height) + { + } virtual void SendFunctionKey(const FunctionKey &functionKey) = 0; virtual void SetKeyboardStatus(bool status) = 0; virtual void MoveCursor(const Direction direction) = 0; @@ -619,6 +622,16 @@ public: */ IMF_API void NotifyPanelStatusInfo(const PanelStatusInfo &info); + /** + * @brief Send panel height. + * + * This function is used to send panel height to editor. + * + * @param info Indicates the panel height. + * @since 11 + */ + IMF_API void NotifyKeyboardHeight(uint32_t height); + /** * @brief Send function key. * diff --git a/test/common/include/text_listener.h b/test/common/include/text_listener.h index 8a33ffc6..356c6bbb 100644 --- a/test/common/include/text_listener.h +++ b/test/common/include/text_listener.h @@ -16,9 +16,10 @@ #ifndef INPUTMETHOD_TEST_TEXT_LISTENER_H #define INPUTMETHOD_TEST_TEXT_LISTENER_H -#include #include +#include + #include "input_method_controller.h" #include "input_method_utils.h" #include "key_event.h" @@ -42,12 +43,14 @@ public: void HandleExtendAction(int32_t action) override; void HandleSelect(int32_t keyCode, int32_t cursorMoveSkip) override; void NotifyPanelStatusInfo(const PanelStatusInfo &info) override; + void NotifyKeyboardHeight(uint32_t height) override; std::u16string GetLeftTextOfCursor(int32_t number) override; std::u16string GetRightTextOfCursor(int32_t number) override; int32_t GetTextIndexAtCursor() override; static void ResetParam(); static bool WaitSendKeyboardStatusCallback(const KeyboardStatus &keyboardStatus); static bool WaitNotifyPanelStatusInfoCallback(const PanelStatusInfo &info); + static bool WaitNotifyKeyboardHeightCallback(uint32_t height); static std::mutex textListenerCallbackLock_; static std::condition_variable textListenerCv_; static int32_t direction_; @@ -61,6 +64,7 @@ public: static int32_t selectionDirection_; static int32_t selectionSkip_; static int32_t action_; + static uint32_t height_; static KeyboardStatus keyboardStatus_; static PanelStatusInfo info_; std::shared_ptr serviceHandler_; diff --git a/test/common/src/text_listener.cpp b/test/common/src/text_listener.cpp index 2e2d793e..cad56203 100644 --- a/test/common/src/text_listener.cpp +++ b/test/common/src/text_listener.cpp @@ -30,16 +30,18 @@ int32_t TextListener::selectionEnd_ = -1; int32_t TextListener::selectionDirection_ = -1; int32_t TextListener::selectionSkip_ = -1; int32_t TextListener::action_ = -1; +uint32_t TextListener::height_ = 0; KeyboardStatus TextListener::keyboardStatus_ = { KeyboardStatus::NONE }; PanelStatusInfo TextListener::info_{}; - TextListener::TextListener() { std::shared_ptr runner = AppExecFwk::EventRunner::Create("TextListenerNotifier"); serviceHandler_ = std::make_shared(runner); } -TextListener::~TextListener() {} +TextListener::~TextListener() +{ +} void TextListener::InsertText(const std::u16string &text) { @@ -61,7 +63,9 @@ void TextListener::DeleteBackward(int32_t length) IMSA_HILOGI("TextChangeListener: DeleteBackward, direction is: %{public}d", length); } -void TextListener::SendKeyEventFromInputMethod(const KeyEvent &event) {} +void TextListener::SendKeyEventFromInputMethod(const KeyEvent &event) +{ +} void TextListener::SendKeyboardStatus(const KeyboardStatus &keyboardStatus) { @@ -112,18 +116,22 @@ void TextListener::HandleSelect(int32_t keyCode, int32_t cursorMoveSkip) textListenerCv_.notify_one(); IMSA_HILOGI("TextChangeListener, selectionDirection_: %{public}d", selectionDirection_); } + std::u16string TextListener::GetLeftTextOfCursor(int32_t number) { return Str8ToStr16(TEXT_BEFORE_CURSOR); } + std::u16string TextListener::GetRightTextOfCursor(int32_t number) { return Str8ToStr16(TEXT_AFTER_CURSOR); } + int32_t TextListener::GetTextIndexAtCursor() { return TEXT_INDEX; } + void TextListener::NotifyPanelStatusInfo(const PanelStatusInfo &info) { IMSA_HILOGD("TextListener::type: %{public}d, flag: %{public}d, visible: %{public}d, trigger: %{public}d.", @@ -132,6 +140,14 @@ void TextListener::NotifyPanelStatusInfo(const PanelStatusInfo &info) info_ = info; textListenerCv_.notify_one(); } + +void TextListener::NotifyKeyboardHeight(uint32_t height) +{ + IMSA_HILOGD("keyboard height: %{public}u", height); + height_ = height; + textListenerCv_.notify_one(); +} + void TextListener::ResetParam() { direction_ = -1; @@ -147,7 +163,9 @@ void TextListener::ResetParam() action_ = -1; keyboardStatus_ = KeyboardStatus::NONE; info_ = {}; + height_ = 0; } + bool TextListener::WaitSendKeyboardStatusCallback(const KeyboardStatus &keyboardStatus) { std::unique_lock lock(textListenerCallbackLock_); @@ -155,11 +173,19 @@ bool TextListener::WaitSendKeyboardStatusCallback(const KeyboardStatus &keyboard lock, std::chrono::seconds(1), [&keyboardStatus]() { return keyboardStatus == keyboardStatus_; }); return keyboardStatus == keyboardStatus_; } + bool TextListener::WaitNotifyPanelStatusInfoCallback(const PanelStatusInfo &info) { std::unique_lock lock(textListenerCallbackLock_); textListenerCv_.wait_for(lock, std::chrono::seconds(1), [info]() { return info == info_; }); return info == info_; } + +bool TextListener::WaitNotifyKeyboardHeightCallback(uint32_t height) +{ + std::unique_lock lock(textListenerCallbackLock_); + textListenerCv_.wait_for(lock, std::chrono::seconds(1), [height]() { return height_ == height; }); + return height_ == height; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file diff --git a/test/unittest/cpp_test/src/input_method_ability_test.cpp b/test/unittest/cpp_test/src/input_method_ability_test.cpp index 937c6912..25ed4289 100644 --- a/test/unittest/cpp_test/src/input_method_ability_test.cpp +++ b/test/unittest/cpp_test/src/input_method_ability_test.cpp @@ -801,6 +801,7 @@ HWTEST_F(InputMethodAbilityTest, testNotifyPanelStatusInfo_002, TestSize.Level0) auto panel = std::make_shared(); auto ret = inputMethodAbility_->CreatePanel(nullptr, info, panel); EXPECT_EQ(ret, ErrorCode::NO_ERROR); + // ShowPanel CheckPanelStatusInfo(panel, { info, true, Trigger::IME_APP }); // HidePanel @@ -895,5 +896,80 @@ HWTEST_F(InputMethodAbilityTest, testNotifyPanelStatusInfo_005, TestSize.Level0) ret = inputMethodAbility_->DestroyPanel(panel); EXPECT_EQ(ret, ErrorCode::NO_ERROR); } + +/** +* @tc.name: testNotifyKeyboardHeight_001 +* @tc.desc: NotifyKeyboardHeight SOFT_KEYBOARD FLG_FIXED +* @tc.type: FUNC +* @tc.require: + +* @tc.author: mashaoyin +*/ +HWTEST_F(InputMethodAbilityTest, testNotifyKeyboardHeight_001, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbility testNotifyKeyboardHeight_001 START"); + TextListener::ResetParam(); + imc_->Attach(textListener_); + PanelInfo info = { .panelType = SOFT_KEYBOARD, .panelFlag = FLG_FIXED }; + auto panel = std::make_shared(); + auto ret = inputMethodAbility_->CreatePanel(nullptr, info, panel); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + panel->Resize(1, 1); + inputMethodAbility_->NotifyKeyboardHeight(panel); + EXPECT_TRUE(TextListener::WaitNotifyKeyboardHeightCallback(1)); + + ret = inputMethodAbility_->DestroyPanel(panel); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} + +/** +* @tc.name: testNotifyKeyboardHeight_002 +* @tc.desc: NotifyKeyboardHeight STATUS_BAR FLG_FIXED +* @tc.type: FUNC +* @tc.require: + +* @tc.author: mashaoyin +*/ +HWTEST_F(InputMethodAbilityTest, testNotifyKeyboardHeight_002, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbility testNotifyKeyboardHeight_002 START"); + TextListener::ResetParam(); + imc_->Attach(textListener_); + PanelInfo info = { .panelType = STATUS_BAR, .panelFlag = FLG_FIXED }; + auto panel = std::make_shared(); + auto ret = inputMethodAbility_->CreatePanel(nullptr, info, panel); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + panel->Resize(1, 1); + inputMethodAbility_->NotifyKeyboardHeight(panel); + EXPECT_TRUE(TextListener::WaitNotifyKeyboardHeightCallback(0)); + + ret = inputMethodAbility_->DestroyPanel(panel); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} + +/** +* @tc.name: testNotifyKeyboardHeight_003 +* @tc.desc: NotifyKeyboardHeight SOFT_KEYBOARD FLG_CANDIDATE_COLUMN +* @tc.type: FUNC +* @tc.require: + +* @tc.author: mashaoyin +*/ +HWTEST_F(InputMethodAbilityTest, testNotifyKeyboardHeight_003, TestSize.Level0) +{ + IMSA_HILOGI("InputMethodAbility testNotifyKeyboardHeight_003 START"); + TextListener::ResetParam(); + imc_->Attach(textListener_); + PanelInfo info = { .panelType = SOFT_KEYBOARD, .panelFlag = FLG_CANDIDATE_COLUMN }; + auto panel = std::make_shared(); + auto ret = inputMethodAbility_->CreatePanel(nullptr, info, panel); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); + panel->Resize(1, 1); + inputMethodAbility_->NotifyKeyboardHeight(panel); + EXPECT_TRUE(TextListener::WaitNotifyKeyboardHeightCallback(0)); + + ret = inputMethodAbility_->DestroyPanel(panel); + EXPECT_EQ(ret, ErrorCode::NO_ERROR); +} } // namespace MiscServices } // namespace OHOS