diff --git a/frameworks/native/inputmethod_ability/include/i_input_method_core.h b/frameworks/native/inputmethod_ability/include/i_input_method_core.h index eb50548c0de74cdd04a49631c6fd08afd7f8fa6e..fde8af4f93cdcf752bae46174cb8a13465ac0f56 100644 --- a/frameworks/native/inputmethod_ability/include/i_input_method_core.h +++ b/frameworks/native/inputmethod_ability/include/i_input_method_core.h @@ -46,6 +46,8 @@ public: IS_ENABLE, IS_PANEL_SHOWN, SECURITY_CHANGE, + ON_CLIENT_INACTIVE, + ON_TEXT_CONFIG_CHANGE, CORE_CMD_LAST, }; @@ -61,6 +63,8 @@ public: virtual bool IsEnable() = 0; virtual int32_t IsPanelShown(const PanelInfo &panelInfo, bool &isShown) = 0; virtual int32_t OnSecurityChange(int32_t security) = 0 ; + virtual void OnClientInactive(const sptr &channel) = 0; + virtual int32_t OnTextConfigChange(const TextTotalConfig &config) = 0; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/include/input_method_ability.h b/frameworks/native/inputmethod_ability/include/input_method_ability.h index 1ff7f5a8239477c48e8a2db9e0145fe59d1294b5..a0c722dc898a28f587025acb0497156f7482dec2 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_ability.h +++ b/frameworks/native/inputmethod_ability/include/input_method_ability.h @@ -82,6 +82,8 @@ public: int32_t IsPanelShown(const PanelInfo &panelInfo, bool &isShown); int32_t GetSecurityMode(int32_t &security); int32_t OnSecurityChange(int32_t security); + void OnClientInactive(const sptr &channel); + void OnTextConfigChange(const TextTotalConfig &textConfig); private: std::thread workThreadHandler; @@ -122,7 +124,6 @@ private: void OnCursorUpdate(Message *msg); void OnSelectionChange(Message *msg); void OnConfigurationChange(Message *msg); - void OnTextConfigChange(const TextTotalConfig &textConfig); int32_t HideKeyboard(Trigger trigger); std::shared_ptr GetSoftKeyboardPanel(); diff --git a/frameworks/native/inputmethod_ability/include/input_method_core_proxy.h b/frameworks/native/inputmethod_ability/include/input_method_core_proxy.h index f225116d5ad67da5b14c3ba47a0814d47810d0fb..de80ba41d3bb1e80459e361cb4099e371eacd22b 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_core_proxy.h +++ b/frameworks/native/inputmethod_ability/include/input_method_core_proxy.h @@ -45,11 +45,14 @@ public: bool IsEnable() override; int32_t IsPanelShown(const PanelInfo &panelInfo, bool &isShown) override; int32_t OnSecurityChange(int32_t security) override; + void OnClientInactive(const sptr &channel) override; + int32_t OnTextConfigChange(const TextTotalConfig &config) override; private: static inline BrokerDelegator delegator_; using ParcelHandler = std::function; - int32_t SendRequest(int code, ParcelHandler input = nullptr, ParcelHandler output = nullptr); + int32_t SendRequest(int code, ParcelHandler input = nullptr, ParcelHandler output = nullptr, + MessageOption option = MessageOption::TF_SYNC); }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/include/input_method_core_stub.h b/frameworks/native/inputmethod_ability/include/input_method_core_stub.h index 00ed132ddde9cd39591ca15cdeee1ae84dea3ded..4bc96d50de693845a0f84febb9486bc86d6c9ff2 100644 --- a/frameworks/native/inputmethod_ability/include/input_method_core_stub.h +++ b/frameworks/native/inputmethod_ability/include/input_method_core_stub.h @@ -49,6 +49,8 @@ public: bool IsEnable() override; int32_t IsPanelShown(const PanelInfo &panelInfo, bool &isShown) override; int32_t OnSecurityChange(int32_t security) override; + void OnClientInactive(const sptr &channel) override; + int32_t OnTextConfigChange(const TextTotalConfig &config) override; void SetMessageHandler(MessageHandler *msgHandler); private: @@ -63,6 +65,8 @@ private: int32_t IsEnableOnRemote(MessageParcel &data, MessageParcel &reply); int32_t IsPanelShownOnRemote(MessageParcel &data, MessageParcel &reply); int32_t SecurityChangeOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t OnClientInactiveOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t OnTextConfigChangeOnRemote(MessageParcel &data, MessageParcel &reply); using ParcelHandler = std::function; int32_t SendMessage(int code, ParcelHandler input = nullptr); using RequestHandler = int32_t (InputMethodCoreStub::*)(MessageParcel &, MessageParcel &); @@ -77,6 +81,8 @@ private: { static_cast(IS_ENABLE), &InputMethodCoreStub::IsEnableOnRemote }, { static_cast(IS_PANEL_SHOWN), &InputMethodCoreStub::IsPanelShownOnRemote }, { static_cast(SECURITY_CHANGE), &InputMethodCoreStub::SecurityChangeOnRemote }, + { static_cast(ON_CLIENT_INACTIVE), &InputMethodCoreStub::OnClientInactiveOnRemote }, + { static_cast(ON_TEXT_CONFIG_CHANGE), &InputMethodCoreStub::OnTextConfigChangeOnRemote }, }; }; } // namespace MiscServices diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index 67a45702a873147d9e2d57a141bdd38de12b5899..d5bf6112f7ed9262504f1440513c3505bb54520b 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -942,5 +942,17 @@ int32_t InputMethodAbility::IsPanelShown(const PanelInfo &panelInfo, bool &isSho static_cast(panelInfo.panelFlag), isShown); return ErrorCode::NO_ERROR; } + +void InputMethodAbility::OnClientInactive(const sptr &channel) +{ + IMSA_HILOGI("client inactive"); + ClearDataChannel(channel); + panels_.ForEach([](const PanelType &panelType, const std::shared_ptr &panel) { + if (panelType != PanelType::SOFT_KEYBOARD || panel->GetPanelFlag() != PanelFlag::FLG_FIXED) { + panel->HidePanel(); + } + return false; + }); +} } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_ability/src/input_method_core_proxy.cpp b/frameworks/native/inputmethod_ability/src/input_method_core_proxy.cpp index 85ee3eb8b8aa78be5e035ca0bd6b3093bf93a05b..4e34936a2b1121b4b180f2fd4c9504bdd66d404e 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_core_proxy.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_core_proxy.cpp @@ -94,12 +94,24 @@ int32_t InputMethodCoreProxy::IsPanelShown(const PanelInfo &panelInfo, bool &isS [&isShown](MessageParcel &reply) { return ITypesUtil::Unmarshal(reply, isShown); }); } -int32_t InputMethodCoreProxy::SendRequest(int code, ParcelHandler input, ParcelHandler output) +void InputMethodCoreProxy::OnClientInactive(const sptr &channel) +{ + SendRequest( + ON_CLIENT_INACTIVE, [&channel](MessageParcel &data) { return ITypesUtil::Marshal(data, channel->AsObject()); }, + nullptr, MessageOption::TF_ASYNC); +} + +int32_t InputMethodCoreProxy::OnTextConfigChange(const TextTotalConfig &config) +{ + return SendRequest( + ON_TEXT_CONFIG_CHANGE, [&config](MessageParcel &data) { return ITypesUtil::Marshal(data, config); }); +} + +int32_t InputMethodCoreProxy::SendRequest(int code, ParcelHandler input, ParcelHandler output, MessageOption option) { IMSA_HILOGD("InputMethodCoreProxy, run in, code = %{public}d", code); MessageParcel data; MessageParcel reply; - MessageOption option{ MessageOption::TF_SYNC }; if (!data.WriteInterfaceToken(GetDescriptor())) { IMSA_HILOGE("InputMethodCoreProxy::write interface token failed"); return ErrorCode::ERROR_EX_ILLEGAL_ARGUMENT; diff --git a/frameworks/native/inputmethod_ability/src/input_method_core_stub.cpp b/frameworks/native/inputmethod_ability/src/input_method_core_stub.cpp index 00583b9654f999861b0dabdce6ceeb948c3be4a0..498ce89d710e2bdac17a508a41eb2103bffaed99 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_core_stub.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_core_stub.cpp @@ -178,6 +178,28 @@ int32_t InputMethodCoreStub::IsPanelShownOnRemote(MessageParcel &data, MessagePa return ITypesUtil::Marshal(reply, ret, isShown) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; } +int32_t InputMethodCoreStub::OnClientInactiveOnRemote(MessageParcel &data, MessageParcel &reply) +{ + sptr channel = nullptr; + if (!ITypesUtil::Unmarshal(data, channel)) { + IMSA_HILOGE("failed to read message parcel"); + return ErrorCode::ERROR_EX_PARCELABLE; + } + InputMethodAbility::GetInstance()->OnClientInactive(channel); + return ITypesUtil::Marshal(reply, ErrorCode::NO_ERROR) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; +} + +int32_t InputMethodCoreStub::OnTextConfigChangeOnRemote(MessageParcel &data, MessageParcel &reply) +{ + TextTotalConfig config; + if (!ITypesUtil::Unmarshal(data, config)) { + IMSA_HILOGE("failed to read message parcel"); + return ErrorCode::ERROR_EX_PARCELABLE; + } + InputMethodAbility::GetInstance()->OnTextConfigChange(config); + return ITypesUtil::Marshal(reply, ErrorCode::NO_ERROR) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; +} + int32_t InputMethodCoreStub::StartInput(const InputClientInfo &clientInfo, bool isBindFromClient) { return InputMethodAbility::GetInstance()->StartInput(clientInfo, isBindFromClient); @@ -208,6 +230,15 @@ int32_t InputMethodCoreStub::IsPanelShown(const PanelInfo &panelInfo, bool &isSh return InputMethodAbility::GetInstance()->IsPanelShown(panelInfo, isShown); } +void InputMethodCoreStub::OnClientInactive(const sptr &channel) +{ +} + +int32_t InputMethodCoreStub::OnTextConfigChange(const TextTotalConfig &config) +{ + return ErrorCode::NO_ERROR; +} + int32_t InputMethodCoreStub::SendMessage(int code, ParcelHandler input) { IMSA_HILOGD("InputMethodCoreStub::SendMessage"); diff --git a/frameworks/native/inputmethod_ability/src/input_method_panel.cpp b/frameworks/native/inputmethod_ability/src/input_method_panel.cpp index 6d2c1b9f69fe5050ad2958d97c12a8ba355484d2..6607cc6af56edeec54ee672ae521f4a9835e46a3 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_panel.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_panel.cpp @@ -190,7 +190,8 @@ int32_t InputMethodPanel::ShowPanel() IMSA_HILOGE("ShowPanel error, err = %{public}d", ret); return ErrorCode::ERROR_OPERATE_PANEL; } - IMSA_HILOGI("success"); + IMSA_HILOGI("success, type/flag: %{public}d/%{public}d", static_cast(panelType_), + static_cast(panelFlag_)); PanelStatusChange(InputWindowStatus::SHOW); return ErrorCode::NO_ERROR; } @@ -225,7 +226,8 @@ int32_t InputMethodPanel::HidePanel() IMSA_HILOGE("HidePanel error, err = %{public}d", ret); return ErrorCode::ERROR_OPERATE_PANEL; } - IMSA_HILOGI("success"); + IMSA_HILOGI("success, type/flag: %{public}d/%{public}d", static_cast(panelType_), + static_cast(panelFlag_)); PanelStatusChange(InputWindowStatus::HIDE); return ErrorCode::NO_ERROR; } @@ -261,11 +263,11 @@ int32_t InputMethodPanel::SetPrivacyMode(bool isPrivacyMode) void InputMethodPanel::PanelStatusChange(const InputWindowStatus &status) { if (status == InputWindowStatus::SHOW && showRegistered_ && panelStatusListener_ != nullptr) { - IMSA_HILOGD("InputMethodPanel::ShowPanel panelStatusListener_ is not nullptr"); + IMSA_HILOGD("ShowPanel panelStatusListener_ is not nullptr"); panelStatusListener_->OnPanelStatus(windowId_, true); } if (status == InputWindowStatus::HIDE && hideRegistered_ && panelStatusListener_ != nullptr) { - IMSA_HILOGD("InputMethodPanel::HidePanel panelStatusListener_ is not nullptr"); + IMSA_HILOGD("HidePanel panelStatusListener_ is not nullptr"); panelStatusListener_->OnPanelStatus(windowId_, false); } auto imsa = ImaUtils::GetImsaProxy(); diff --git a/frameworks/native/inputmethod_controller/include/i_input_client.h b/frameworks/native/inputmethod_controller/include/i_input_client.h index 52bf2a5084b3eddec9a9d77dafee92f553039b0f..4a01d378f9b77d734fcdeae5d3d6b06dc1255d4f 100644 --- a/frameworks/native/inputmethod_controller/include/i_input_client.h +++ b/frameworks/native/inputmethod_controller/include/i_input_client.h @@ -30,7 +30,13 @@ namespace OHOS { namespace MiscServices { class IInputClient : public IRemoteBroker { public: - enum { ON_INPUT_READY = FIRST_CALL_TRANSACTION, ON_INPUT_STOP, ON_SWITCH_INPUT, ON_PANEL_STATUS_CHANGE }; + enum { + ON_INPUT_READY = FIRST_CALL_TRANSACTION, + ON_INPUT_STOP, + ON_SWITCH_INPUT, + ON_PANEL_STATUS_CHANGE, + DEACTIVATE_CLIENT + }; DECLARE_INTERFACE_DESCRIPTOR(u"ohos.miscservices.inputmethod.InputClient"); @@ -39,6 +45,7 @@ public: virtual int32_t OnSwitchInput(const Property &property, const SubProperty &subProperty) = 0; virtual int32_t OnPanelStatusChange( const InputWindowStatus &status, const std::vector &windowInfo) = 0; + virtual void DeactivateClient() = 0; }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/input_client_info.h b/frameworks/native/inputmethod_controller/include/input_client_info.h index 8175f297c887638ab8b0ba3e5912cbf0eaba0eeb..129dee356b91a9f10de5e2cc9a2a31046edcc2c5 100644 --- a/frameworks/native/inputmethod_controller/include/input_client_info.h +++ b/frameworks/native/inputmethod_controller/include/input_client_info.h @@ -24,8 +24,9 @@ namespace OHOS { namespace MiscServices { -enum class UpdateFlag : uint32_t { EVENTFLAG = 0, ISSHOWKEYBOARD, BINDIMETYPE, ISATTACHING }; +enum class UpdateFlag : uint32_t { EVENTFLAG = 0, ISSHOWKEYBOARD, BINDIMETYPE, STATE }; enum class ImeType : int32_t { IME = 0, PROXY_IME, NONE }; +enum class ClientState : uint32_t { INACTIVE = 0, ACTIVE }; struct InputClientInfo { pid_t pid{ -1 }; // process id pid_t uid{ -1 }; // uid @@ -38,7 +39,7 @@ struct InputClientInfo { sptr client{ nullptr }; // the remote object handler for service to callback input client sptr channel{ nullptr }; // the remote object handler for ime to callback input client sptr deathRecipient{ nullptr }; // death recipient of client - bool isAttaching{ false }; // is attaching + ClientState state{ ClientState::INACTIVE }; // the state of input client }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/input_client_proxy.h b/frameworks/native/inputmethod_controller/include/input_client_proxy.h index 38e54576631b168928099320634371338c6372fe..9f6816e4e4451f37f2049a478ee3d38123d4f2fc 100644 --- a/frameworks/native/inputmethod_controller/include/input_client_proxy.h +++ b/frameworks/native/inputmethod_controller/include/input_client_proxy.h @@ -40,11 +40,13 @@ public: int32_t OnSwitchInput(const Property &property, const SubProperty &subProperty) override; int32_t OnPanelStatusChange( const InputWindowStatus &status, const std::vector &windowInfo) override; + void DeactivateClient() override; private: static inline BrokerDelegator delegator_; using ParcelHandler = std::function; - int32_t SendRequest(int code, ParcelHandler input = nullptr, ParcelHandler output = nullptr); + int32_t SendRequest(int code, ParcelHandler input = nullptr, ParcelHandler output = nullptr, + MessageOption option = MessageOption::TF_SYNC); }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/input_client_stub.h b/frameworks/native/inputmethod_controller/include/input_client_stub.h index 3a9cf7f29d0286e4b26505f2eff05d9cb2750bff..c59878eee0c1c05cdfa4c93e8cc9357cd493595e 100644 --- a/frameworks/native/inputmethod_controller/include/input_client_stub.h +++ b/frameworks/native/inputmethod_controller/include/input_client_stub.h @@ -41,12 +41,14 @@ public: int32_t OnSwitchInput(const Property &property, const SubProperty &subProperty) override; int32_t OnPanelStatusChange( const InputWindowStatus &status, const std::vector &windowInfo) override; + void DeactivateClient() override; private: void OnInputReadyOnRemote(MessageParcel &data, MessageParcel &reply); int32_t OnInputStopOnRemote(MessageParcel &data, MessageParcel &reply); int32_t OnSwitchInputOnRemote(MessageParcel &data, MessageParcel &reply); int32_t OnPanelStatusChangeOnRemote(MessageParcel &data, MessageParcel &reply); + int32_t DeactivateClientOnRemote(MessageParcel &data, MessageParcel &reply); }; } // namespace MiscServices } // namespace OHOS diff --git a/frameworks/native/inputmethod_controller/include/itypes_util.h b/frameworks/native/inputmethod_controller/include/itypes_util.h index bb7537745c780060798be60328a8e061ad929a3c..c35099cca78c4f7d5851a3d80522bb5c52047faf 100644 --- a/frameworks/native/inputmethod_controller/include/itypes_util.h +++ b/frameworks/native/inputmethod_controller/include/itypes_util.h @@ -95,6 +95,9 @@ public: static bool Marshalling(const PanelInfo &input, MessageParcel &data); static bool Unmarshalling(PanelInfo &output, MessageParcel &data); + static bool Marshalling(ClientState input, MessageParcel &data); + static bool Unmarshalling(ClientState &output, MessageParcel &data); + template static bool Marshalling(const std::vector &val, MessageParcel &parcel); template diff --git a/frameworks/native/inputmethod_controller/src/input_client_proxy.cpp b/frameworks/native/inputmethod_controller/src/input_client_proxy.cpp index a7c03b517ebab69d4392ac0a3044363d5710e4dd..f32101fbe1806a6060544a7cb8d602df12501afc 100644 --- a/frameworks/native/inputmethod_controller/src/input_client_proxy.cpp +++ b/frameworks/native/inputmethod_controller/src/input_client_proxy.cpp @@ -52,12 +52,16 @@ int32_t InputClientProxy::OnPanelStatusChange( }); } -int32_t InputClientProxy::SendRequest(int code, ParcelHandler input, ParcelHandler output) +void InputClientProxy::DeactivateClient() +{ + SendRequest(DEACTIVATE_CLIENT, nullptr, nullptr, MessageOption::TF_ASYNC); +} + +int32_t InputClientProxy::SendRequest(int code, ParcelHandler input, ParcelHandler output, MessageOption option) { IMSA_HILOGD("InputClientProxy run in, code = %{public}d", code); MessageParcel data; MessageParcel reply; - MessageOption option{ MessageOption::TF_SYNC }; if (!data.WriteInterfaceToken(GetDescriptor())) { IMSA_HILOGE("InputClientProxy::write interface token failed"); return ErrorCode::ERROR_EX_ILLEGAL_ARGUMENT; diff --git a/frameworks/native/inputmethod_controller/src/input_client_stub.cpp b/frameworks/native/inputmethod_controller/src/input_client_stub.cpp index 90a8b456e0a8a8e6122b797b41d4e80c080745b7..1c5cd5f9772ac8663d37c74c371008ec15675c25 100644 --- a/frameworks/native/inputmethod_controller/src/input_client_stub.cpp +++ b/frameworks/native/inputmethod_controller/src/input_client_stub.cpp @@ -57,6 +57,9 @@ int32_t InputClientStub::OnRemoteRequest( case ON_PANEL_STATUS_CHANGE: { return OnPanelStatusChangeOnRemote(data, reply); } + case DEACTIVATE_CLIENT: { + return DeactivateClientOnRemote(data, reply); + } default: return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } @@ -100,6 +103,12 @@ int32_t InputClientStub::OnPanelStatusChangeOnRemote(MessageParcel &data, Messag : ErrorCode::ERROR_EX_PARCELABLE; } +int32_t InputClientStub::DeactivateClientOnRemote(MessageParcel &data, MessageParcel &reply) +{ + DeactivateClient(); + return reply.WriteInt32(ErrorCode::NO_ERROR) ? ErrorCode::NO_ERROR : ErrorCode::ERROR_EX_PARCELABLE; +} + int32_t InputClientStub::OnInputReady(const sptr &agent) { return ErrorCode::NO_ERROR; @@ -121,5 +130,10 @@ int32_t InputClientStub::OnPanelStatusChange( { return InputMethodController::GetInstance()->OnPanelStatusChange(status, windowInfo); } + +void InputClientStub::DeactivateClient() +{ + InputMethodController::GetInstance()->DeactivateClient(); +} } // 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 29b04b79fe8e29f610ecbd1cfa506afcbbf4368a..3c232a38ab05789f86b9956a999e44be6bf2fa90 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -196,6 +196,24 @@ int32_t InputMethodController::OnPanelStatusChange( return ErrorCode::NO_ERROR; } +void InputMethodController::DeactivateClient() +{ + { + std::lock_guard lock(clientInfoLock_); + clientInfo_.state = ClientState::INACTIVE; + } + { + std::lock_guard autoLock(agentLock_); + agent_ = nullptr; + agentObject_ = nullptr; + } + auto listener = GetTextListener(); + if (listener != nullptr) { + IMSA_HILOGD("textListener_ is not nullptr"); + listener->SendKeyboardStatus(KeyboardStatus::NONE); + } +} + void InputMethodController::SaveTextConfig(const TextConfig &textConfig) { std::lock_guard lock(textConfigLock_); @@ -242,6 +260,7 @@ int32_t InputMethodController::Attach( IMSA_HILOGE("failed to start input, ret:%{public}d", ret); return ret; } + clientInfo_.state = ClientState::ACTIVE; OnInputReady(agent); if (isShowKeyboard) { InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_SHOW_ATTACH); @@ -252,8 +271,8 @@ int32_t InputMethodController::Attach( int32_t InputMethodController::ShowTextInput() { - if (!isBound_.load()) { - IMSA_HILOGE("not bound yet"); + if (!IsBound()) { + IMSA_HILOGE("not bound"); return ErrorCode::ERROR_CLIENT_NOT_BOUND; } IMSA_HILOGI("run in"); @@ -271,8 +290,8 @@ int32_t InputMethodController::ShowTextInput() int32_t InputMethodController::HideTextInput() { - if (!isBound_.load()) { - IMSA_HILOGE("not bound yet"); + if (!IsBound()) { + IMSA_HILOGE("not bound"); return ErrorCode::ERROR_CLIENT_NOT_BOUND; } IMSA_HILOGI("run in"); @@ -284,8 +303,8 @@ int32_t InputMethodController::HideTextInput() int32_t InputMethodController::HideCurrentInput() { IMSA_HILOGD("InputMethodController::HideCurrentInput"); - if (!isEditable_.load()) { - IMSA_HILOGE("not in editable state"); + if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -300,8 +319,8 @@ int32_t InputMethodController::HideCurrentInput() int32_t InputMethodController::ShowCurrentInput() { - if (!isEditable_.load()) { - IMSA_HILOGE("not in editable state"); + if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -529,8 +548,8 @@ void InputMethodController::RestoreListenInfoInSaDied() void InputMethodController::RestoreAttachInfoInSaDied() { - if (!isEditable_.load()) { - IMSA_HILOGD("not in editable state"); + if (!IsEditable()) { + IMSA_HILOGD("not editable"); return; } auto attach = [=]() -> bool { @@ -564,12 +583,8 @@ void InputMethodController::RestoreAttachInfoInSaDied() int32_t InputMethodController::OnCursorUpdate(CursorInfo cursorInfo) { - if (!isBound_.load()) { - IMSA_HILOGD("not bound yet"); - return ErrorCode::ERROR_CLIENT_NOT_BOUND; - } - if (!isEditable_.load()) { - IMSA_HILOGD("not in editable state"); + if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } { @@ -597,12 +612,8 @@ int32_t InputMethodController::OnCursorUpdate(CursorInfo cursorInfo) int32_t InputMethodController::OnSelectionChange(std::u16string text, int start, int end) { - if (!isBound_.load()) { - IMSA_HILOGD("not bound yet"); - return ErrorCode::ERROR_CLIENT_NOT_BOUND; - } - if (!isEditable_.load()) { - IMSA_HILOGD("not in editable state"); + if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } { @@ -630,15 +641,15 @@ int32_t InputMethodController::OnSelectionChange(std::u16string text, int start, int32_t InputMethodController::OnConfigurationChange(Configuration info) { - if (!isBound_.load()) { - IMSA_HILOGD("not bound yet"); - return ErrorCode::ERROR_CLIENT_NOT_BOUND; - } { std::lock_guard lock(textConfigLock_); textConfig_.inputAttribute.enterKeyType = static_cast(info.GetEnterKeyType()); textConfig_.inputAttribute.inputPattern = static_cast(info.GetTextInputType()); } + if (!IsEditable()) { + IMSA_HILOGD("not editable"); + return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; + } IMSA_HILOGI("IMC enterKeyType: %{public}d, textInputType: %{public}d", static_cast(info.GetEnterKeyType()), static_cast(info.GetTextInputType())); std::lock_guard agentLock(agentLock_); @@ -654,7 +665,7 @@ int32_t InputMethodController::GetLeft(int32_t length, std::u16string &text) { IMSA_HILOGD("run in, length: %{public}d", length); auto listener = GetTextListener(); - if (!isEditable_.load() || listener == nullptr) { + if (!IsEditable() || listener == nullptr) { IMSA_HILOGE("not editable or listener is nullptr"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } @@ -666,7 +677,7 @@ int32_t InputMethodController::GetRight(int32_t length, std::u16string &text) { IMSA_HILOGD("run in, length: %{public}d", length); auto listener = GetTextListener(); - if (!isEditable_.load() || listener == nullptr) { + if (!IsEditable() || listener == nullptr) { IMSA_HILOGE("not editable or textListener_ is nullptr"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } @@ -678,7 +689,7 @@ int32_t InputMethodController::GetTextIndexAtCursor(int32_t &index) { IMSA_HILOGD("run in"); auto listener = GetTextListener(); - if (!isEditable_.load() || listener == nullptr) { + if (!IsEditable() || listener == nullptr) { IMSA_HILOGE("not editable or textListener_ is nullptr"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } @@ -689,8 +700,8 @@ int32_t InputMethodController::GetTextIndexAtCursor(int32_t &index) bool InputMethodController::DispatchKeyEvent(std::shared_ptr keyEvent) { InputMethodSyncTrace tracer("DispatchKeyEvent trace"); - if (!isEditable_.load()) { - IMSA_HILOGD("not in editable state"); + if (!IsEditable()) { + IMSA_HILOGD("not editable"); return false; } if (keyEvent == nullptr) { @@ -749,12 +760,8 @@ int32_t InputMethodController::GetTextConfig(TextTotalConfig &config) int32_t InputMethodController::SetCallingWindow(uint32_t windowId) { - if (!isBound_.load()) { - IMSA_HILOGD("not bound yet"); - return ErrorCode::ERROR_CLIENT_NOT_BOUND; - } - if (!isEditable_.load()) { - IMSA_HILOGD("not in editable state"); + if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } { @@ -773,8 +780,8 @@ int32_t InputMethodController::SetCallingWindow(uint32_t windowId) int32_t InputMethodController::ShowSoftKeyboard() { - if (!isEditable_.load()) { - IMSA_HILOGE("not in editable state"); + if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -790,8 +797,8 @@ int32_t InputMethodController::ShowSoftKeyboard() int32_t InputMethodController::HideSoftKeyboard() { - if (!isEditable_.load()) { - IMSA_HILOGE("not in editable state"); + if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -922,7 +929,7 @@ void InputMethodController::SelectByRange(int32_t start, int32_t end) { IMSA_HILOGD("InputMethodController start: %{public}d, end: %{public}d", start, end); auto listener = GetTextListener(); - if (isEditable_.load() && listener != nullptr) { + if (IsEditable() && listener != nullptr) { listener->HandleSetSelection(start, end); } else { IMSA_HILOGE("not editable or textListener_ is nullptr"); @@ -939,7 +946,7 @@ void InputMethodController::SelectByMovement(int32_t direction, int32_t cursorMo { IMSA_HILOGD("InputMethodController, direction: %{public}d, cursorMoveSkip: %{public}d", direction, cursorMoveSkip); auto listener = GetTextListener(); - if (isEditable_.load() && listener != nullptr) { + if (IsEditable() && listener != nullptr) { listener->HandleSelect(CURSOR_DIRECTION_BASE_VALUE + direction, cursorMoveSkip); } else { IMSA_HILOGE("not editable or textListener_ is nullptr"); @@ -956,7 +963,7 @@ int32_t InputMethodController::HandleExtendAction(int32_t action) { IMSA_HILOGD("InputMethodController, action: %{public}d", action); auto listener = GetTextListener(); - if (!isEditable_.load() || listener == nullptr) { + if (!IsEditable() || listener == nullptr) { IMSA_HILOGE("not editable or textListener is nullptr"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } @@ -976,11 +983,39 @@ void InputMethodController::SetTextListener(sptr listener textListener_ = listener; } +bool InputMethodController::IsEditable() +{ + std::lock_guard lock(clientInfoLock_); + if (clientInfo_.state != ClientState::ACTIVE) { + IMSA_HILOGD("client not active"); + return false; + } + if (!isEditable_.load()) { + IMSA_HILOGD("not in editable state"); + return false; + } + return true; +} + +bool InputMethodController::IsBound() +{ + std::lock_guard lock(clientInfoLock_); + if (clientInfo_.state != ClientState::ACTIVE) { + IMSA_HILOGD("client not active"); + return false; + } + if (!isBound_.load()) { + IMSA_HILOGD("not bound"); + return false; + } + return true; +} + int32_t InputMethodController::InsertText(const std::u16string &text) { IMSA_HILOGD("in"); auto listener = GetTextListener(); - if (!isEditable_.load() || listener == nullptr) { + if (!IsEditable() || listener == nullptr) { IMSA_HILOGE("not editable or textListener is nullptr"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } @@ -992,7 +1027,7 @@ int32_t InputMethodController::DeleteForward(int32_t length) { IMSA_HILOGD("run in, length: %{public}d", length); auto listener = GetTextListener(); - if (!isEditable_.load() || listener == nullptr) { + if (!IsEditable() || listener == nullptr) { IMSA_HILOGE("not editable or textListener is nullptr"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } @@ -1005,7 +1040,7 @@ int32_t InputMethodController::DeleteBackward(int32_t length) { IMSA_HILOGD("run in, length: %{public}d", length); auto listener = GetTextListener(); - if (!isEditable_.load() || listener == nullptr) { + if (!IsEditable() || listener == nullptr) { IMSA_HILOGE("not editable or textListener is nullptr"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } @@ -1018,7 +1053,7 @@ int32_t InputMethodController::MoveCursor(Direction direction) { IMSA_HILOGD("run in, direction: %{public}d", static_cast(direction)); auto listener = GetTextListener(); - if (!isEditable_.load() || listener == nullptr) { + if (!IsEditable() || listener == nullptr) { IMSA_HILOGE("not editable or textListener_ is nullptr"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } @@ -1061,7 +1096,7 @@ int32_t InputMethodController::SendFunctionKey(int32_t functionKey) { IMSA_HILOGD("run in, functionKey: %{public}d", static_cast(functionKey)); auto listener = GetTextListener(); - if (!isEditable_.load() || listener == nullptr) { + if (!IsEditable() || listener == nullptr) { IMSA_HILOGE("not editable or textListener_ is nullptr"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } diff --git a/frameworks/native/inputmethod_controller/src/itypes_util.cpp b/frameworks/native/inputmethod_controller/src/itypes_util.cpp index da1a829469d45aade1293931e69a898440731c83..572685f1db27969a8e9247cf7fd6e3083c297f71 100644 --- a/frameworks/native/inputmethod_controller/src/itypes_util.cpp +++ b/frameworks/native/inputmethod_controller/src/itypes_util.cpp @@ -243,7 +243,7 @@ bool ITypesUtil::Unmarshalling(TextTotalConfig &output, MessageParcel &data) bool ITypesUtil::Marshalling(const InputClientInfo &input, MessageParcel &data) { if (!Marshal(data, input.pid, input.uid, input.userID, input.isShowKeyboard, input.eventFlag, input.config, - input.client->AsObject(), input.channel->AsObject())) { + input.state, input.client->AsObject(), input.channel->AsObject())) { IMSA_HILOGE("write InputClientInfo to message parcel failed"); return false; } @@ -252,8 +252,8 @@ bool ITypesUtil::Marshalling(const InputClientInfo &input, MessageParcel &data) bool ITypesUtil::Unmarshalling(InputClientInfo &output, MessageParcel &data) { - if (!Unmarshal( - data, output.pid, output.uid, output.userID, output.isShowKeyboard, output.eventFlag, output.config)) { + if (!Unmarshal(data, output.pid, output.uid, output.userID, output.isShowKeyboard, output.eventFlag, output.config, + output.state)) { IMSA_HILOGE("read InputClientInfo from message parcel failed"); return false; } @@ -370,5 +370,21 @@ bool ITypesUtil::Unmarshalling(PanelInfo &output, MessageParcel &data) output.panelType = static_cast(panelType); return true; } + +bool ITypesUtil::Marshalling(ClientState input, MessageParcel &data) +{ + return data.WriteUint32(static_cast(input)); +} + +bool ITypesUtil::Unmarshalling(ClientState &output, MessageParcel &data) +{ + uint32_t state = 0; + if (!data.ReadUint32(state)) { + IMSA_HILOGE("ClientState read failed"); + return false; + } + output = static_cast(state); + return true; +} } // namespace MiscServices } // namespace OHOS \ No newline at end of file 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 18d88ca7f6923bf25c765dd22bde320ac24ab4d2..f952042b4e15b5fec915240b9322e3780597e995 100644 --- a/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h +++ b/interfaces/inner_api/inputmethod_controller/include/input_method_controller.h @@ -654,6 +654,15 @@ public: IMF_API int32_t OnPanelStatusChange( const InputWindowStatus &status, const std::vector &windowInfo); + /** + * @brief Deactivate the input client. + * + * This function is used to deactivate the input client. + * + * @since 11 + */ + IMF_API void DeactivateClient(); + /** * @brief Query whether an input type is supported. * @@ -708,6 +717,8 @@ private: void SaveTextConfig(const TextConfig &textConfig); sptr GetTextListener(); void SetTextListener(sptr listener); + bool IsEditable(); + bool IsBound(); std::shared_ptr settingListener_; std::shared_ptr controllerListener_; diff --git a/services/BUILD.gn b/services/BUILD.gn index ee34f0328d31ba00a80e3934aefe2a230eb4973b..9c29b520af79fa1bc165896ac750bc72e0e2e8f7 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -97,6 +97,7 @@ ohos_shared_library("inputmethod_service") { "safwk:system_ability_fwk", "samgr:samgr_proxy", "window_manager:libwm", + "window_manager:libwsutils", ] subsystem_name = "inputmethod" diff --git a/services/include/peruser_session.h b/services/include/peruser_session.h index 31d5fc19b975683de7ac48129f8c003d87c828ac..282bd1515d0f05c2fe75d859c6ffc5b108506605 100644 --- a/services/include/peruser_session.h +++ b/services/include/peruser_session.h @@ -127,16 +127,19 @@ private: void OnImeDied(const sptr &remote, ImeType type); int AddClientInfo(sptr inputClient, const InputClientInfo &clientInfo, ClientAddEvent event); + void RemoveClientInfo(const sptr &client, bool isClientDied = false); + int32_t RemoveClient(const sptr &client, bool isUnbindFromClient = false); + void DeactivateClient(const sptr &client); std::shared_ptr GetClientInfo(sptr inputClient); + std::shared_ptr GetClientInfo(pid_t pid); void UpdateClientInfo(const sptr &client, - const std::unordered_map> &updateInfos); - void RemoveClientInfo(const sptr &client, bool isClientDied = false); + const std::unordered_map> &updateInfos); + int32_t AddImeData(ImeType type, sptr core, sptr agent); - std::shared_ptr GetImeData(ImeType type); void RemoveImeData(ImeType type); - - int32_t RemoveClient(const sptr &client, bool isUnbindFromClient = false); int32_t RemoveIme(const sptr &core, ImeType type); + std::shared_ptr GetImeData(ImeType type); + std::shared_ptr GetValidIme(ImeType type); int32_t BindClientWithIme( const std::shared_ptr &clientInfo, ImeType type, bool isBindFromClient = false); @@ -155,6 +158,9 @@ private: void SetCurrentClient(sptr client); sptr GetCurrentClient(); + void ReplaceCurrentClient(const sptr &client); + void SetInactiveClient(sptr client); + sptr GetInactiveClient(); bool IsCurrentClient(int32_t pid, int32_t uid); bool IsCurrentClient(sptr client); @@ -163,12 +169,16 @@ private: bool IsProxyImeStartInImeBind(ImeType bindImeType, ImeType startImeType); bool IsBindProxyImeInImeBind(ImeType bindImeType); bool IsBindImeInProxyImeBind(ImeType bindImeType); + bool IsImeBindChanged(ImeType bindImeType); BlockData isImeStarted_{ MAX_IME_START_TIME, false }; std::mutex imeDataLock_; std::unordered_map> imeData_; std::mutex attachLock_; std::condition_variable imeAttachCv_; + std::mutex inactiveClientLock_; + sptr inactiveClient_; // the inactive input client + std::mutex focusedClientLock_; }; } // namespace MiscServices } // namespace OHOS diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index db75b3884ad24980f9a3b5136735a0baf16a26b0..b62e57f40f6304ee2ae00caead25ccb76e0459a2 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -31,6 +31,7 @@ #include "iservice_registry.h" #include "message_parcel.h" #include "parcel.h" +#include "scene_board_judgement.h" #include "sys/prctl.h" #include "system_ability_definition.h" #include "unistd.h" @@ -41,7 +42,6 @@ namespace MiscServices { using namespace MessageID; constexpr uint32_t IME_RESTART_TIMES = 5; constexpr uint32_t IME_RESTART_INTERVAL = 300; -constexpr uint32_t IME_ATTACH_INTERVAL = 100; constexpr int64_t INVALID_PID = -1; PerUserSession::PerUserSession(int32_t userId) : userId_(userId) { @@ -57,13 +57,12 @@ int PerUserSession::AddClientInfo( IMSA_HILOGD("PerUserSession, run in"); auto cacheInfo = GetClientInfo(inputClient); if (cacheInfo != nullptr) { - IMSA_HILOGD("client info is exist, not need add."); + IMSA_HILOGD("info is existed"); if (event == START_LISTENING) { UpdateClientInfo(inputClient, { { UpdateFlag::EVENTFLAG, clientInfo.eventFlag } }); } return ErrorCode::NO_ERROR; } - auto info = std::make_shared(clientInfo); info->deathRecipient->SetDeathRecipient( [this, info](const wptr &) { this->OnClientDied(info->client); }); @@ -76,7 +75,6 @@ int PerUserSession::AddClientInfo( IMSA_HILOGE("failed to add client death recipient"); return ErrorCode::ERROR_CLIENT_ADD_FAILED; } - std::lock_guard lock(mtx); mapClients_.insert({ inputClient, info }); IMSA_HILOGI("add client end"); @@ -110,7 +108,7 @@ void PerUserSession::RemoveClientInfo(const sptr &client, bool is } void PerUserSession::UpdateClientInfo(const sptr &client, - const std::unordered_map> &updateInfos) + const std::unordered_map> &updateInfos) { if (client == nullptr) { IMSA_HILOGE("client is nullptr."); @@ -135,8 +133,8 @@ void PerUserSession::UpdateClientInfo(const sptr &client, info->bindImeType = std::get(updateInfo.second); break; } - case UpdateFlag::ISATTACHING: { - info->isAttaching = std::get(updateInfo.second); + case UpdateFlag::STATE: { + info->state = std::get(updateInfo.second); break; } default: @@ -372,6 +370,18 @@ std::shared_ptr PerUserSession::GetClientInfo(sptrsecond; } +std::shared_ptr PerUserSession::GetClientInfo(pid_t pid) +{ + std::lock_guard lock(mtx); + auto iter = std::find_if( + mapClients_.begin(), mapClients_.end(), [pid](const auto &mapClient) { return mapClient.second->pid == pid; }); + if (iter == mapClients_.end()) { + IMSA_HILOGD("not found"); + return nullptr; + } + return iter->second; +} + int32_t PerUserSession::OnPrepareInput(const InputClientInfo &clientInfo) { IMSA_HILOGD("PerUserSession::OnPrepareInput Start"); @@ -399,14 +409,34 @@ int32_t PerUserSession::RemoveClient(const sptr &client, bool isUn SetCurrentClient(nullptr); ExitCurrentInputType(); } + StopClientInput(client); RemoveClientInfo(client->AsObject()); return ErrorCode::NO_ERROR; } -bool PerUserSession::IsCurrentClient(sptr client) +void PerUserSession::DeactivateClient(const sptr &client) { - auto currentClient = GetCurrentClient(); - return currentClient != nullptr && client != nullptr && client->AsObject() == currentClient->AsObject(); + if (client == nullptr) { + IMSA_HILOGD("client is nullptr"); + return; + } + auto clientInfo = GetClientInfo(client->AsObject()); + if (clientInfo == nullptr) { + return; + } + IMSA_HILOGI("deactive client[%{public}d]", clientInfo->pid); + UpdateClientInfo(client->AsObject(), { { UpdateFlag::STATE, ClientState::INACTIVE } }); + if (IsCurrentClient(client)) { + SetCurrentClient(nullptr); + } + SetInactiveClient(client); + client->DeactivateClient(); + auto data = GetImeData(clientInfo->bindImeType); + if (data == nullptr) { + IMSA_HILOGE("ime %{public}d doesn't exist", clientInfo->bindImeType); + return; + } + data->core->OnClientInactive(clientInfo->channel); } bool PerUserSession::IsProxyImeEnable() @@ -417,33 +447,24 @@ bool PerUserSession::IsProxyImeEnable() int32_t PerUserSession::OnStartInput(const sptr &client, bool isShowKeyboard, sptr &agent) { - IMSA_HILOGD("start input with keyboard[%{public}d]", isShowKeyboard); if (client == nullptr) { IMSA_HILOGE("client is nullptr"); return ErrorCode::ERROR_CLIENT_NULL_POINTER; } auto clientInfo = GetClientInfo(client->AsObject()); if (clientInfo == nullptr) { - IMSA_HILOGE("client not find"); return ErrorCode::ERROR_CLIENT_NOT_FOUND; } - UpdateClientInfo(clientInfo->client->AsObject(), { { UpdateFlag::ISATTACHING, true } }); - if (IsCurrentClient(client)) { - if (IsBindImeInProxyImeBind(clientInfo->bindImeType) || IsBindProxyImeInImeBind(clientInfo->bindImeType)) { - UnBindClientWithIme(clientInfo); - } + IMSA_HILOGD("start input with keyboard[%{public}d]", isShowKeyboard); + if (IsCurrentClient(client) && IsImeBindChanged(clientInfo->bindImeType)) { + UnBindClientWithIme(clientInfo); } InputClientInfo infoTemp = *clientInfo; infoTemp.isShowKeyboard = isShowKeyboard; auto imeType = IsProxyImeEnable() ? ImeType::PROXY_IME : ImeType::IME; int32_t ret = BindClientWithIme(std::make_shared(infoTemp), imeType, true); - { - std::unique_lock lock(attachLock_); - UpdateClientInfo(clientInfo->client->AsObject(), { { UpdateFlag::ISATTACHING, false } }); - imeAttachCv_.notify_all(); - } if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("start client input failed, ret: %{public}d", ret); + IMSA_HILOGE("bind failed, ret: %{public}d", ret); return ret; } auto data = GetImeData(imeType); @@ -464,22 +485,14 @@ int32_t PerUserSession::BindClientWithIme( } IMSA_HILOGD("imeType: %{public}d, isShowKeyboard: %{public}d, isBindFromClient: %{public}d", type, clientInfo->isShowKeyboard, isBindFromClient); - auto data = GetImeData(type); - if (data == nullptr && type == ImeType::IME) { - IMSA_HILOGI("current ime is empty, try to restart it"); - if (!StartInputService(ImeInfoInquirer::GetInstance().GetImeToBeStarted(userId_), true)) { - IMSA_HILOGE("failed to restart ime"); - return ErrorCode::ERROR_IME_START_FAILED; - } - data = GetImeData(type); - } + auto data = GetValidIme(type); if (data == nullptr) { - IMSA_HILOGE("ime: %{public}d is abnormal", type); return ErrorCode::ERROR_IME_NOT_STARTED; } - auto ret = data->core->StartInput(*clientInfo, isBindFromClient); + auto ret = InputTypeManager::GetInstance().IsStarted() ? data->core->OnTextConfigChange(clientInfo->config) + : data->core->StartInput(*clientInfo, isBindFromClient); if (ret != ErrorCode::NO_ERROR) { - IMSA_HILOGE("start client input failed, ret: %{public}d", ret); + IMSA_HILOGE("start input failed, ret: %{public}d", ret); return ErrorCode::ERROR_IME_START_INPUT_FAILED; } if (!isBindFromClient && clientInfo->client->OnInputReady(data->agent) != ErrorCode::NO_ERROR) { @@ -487,8 +500,9 @@ int32_t PerUserSession::BindClientWithIme( return ErrorCode::ERROR_EX_PARCELABLE; } UpdateClientInfo(clientInfo->client->AsObject(), - { { UpdateFlag::BINDIMETYPE, type }, { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard } }); - SetCurrentClient(clientInfo->client); + { { UpdateFlag::BINDIMETYPE, type }, { UpdateFlag::ISSHOWKEYBOARD, clientInfo->isShowKeyboard }, + { UpdateFlag::STATE, ClientState::ACTIVE } }); + ReplaceCurrentClient(clientInfo->client); return ErrorCode::NO_ERROR; } @@ -673,6 +687,39 @@ sptr PerUserSession::GetCurrentClient() return currentClient_; } +void PerUserSession::ReplaceCurrentClient(const sptr &client) +{ + std::lock_guard lock(focusedClientLock_); + if (client == nullptr) { + return; + } + auto replacedClient = GetCurrentClient(); + SetCurrentClient(client); + if (replacedClient != nullptr && replacedClient != client) { + IMSA_HILOGD("remove replaced client"); + RemoveClient(replacedClient); + } + auto inactiveClient = GetInactiveClient(); + if (inactiveClient != nullptr && inactiveClient != client) { + IMSA_HILOGD("remove inactive client"); + RemoveClientInfo(inactiveClient->AsObject()); + SetInactiveClient(nullptr); + } +} + +void PerUserSession::SetInactiveClient(sptr client) +{ + IMSA_HILOGD("set inactive client"); + std::lock_guard lock(inactiveClientLock_); + inactiveClient_ = client; +} + +sptr PerUserSession::GetInactiveClient() +{ + std::lock_guard lock(inactiveClientLock_); + return inactiveClient_; +} + void PerUserSession::NotifyImeChangeToClients(const Property &property, const SubProperty &subProperty) { IMSA_HILOGD("PerUserSession::NotifyImeChangeToClients"); @@ -724,6 +771,20 @@ std::shared_ptr PerUserSession::GetImeData(ImeType type) return it->second; } +std::shared_ptr PerUserSession::GetValidIme(ImeType type) +{ + auto data = GetImeData(type); + if (data != nullptr || type != ImeType::IME) { + return data; + } + IMSA_HILOGI("current ime is empty, try to restart it"); + if (!StartInputService(ImeInfoInquirer::GetInstance().GetImeToBeStarted(userId_), true)) { + return nullptr; + } + data = GetImeData(type); + return data; +} + void PerUserSession::RemoveImeData(ImeType type) { std::lock_guard lock(imeDataLock_); @@ -742,45 +803,39 @@ void PerUserSession::RemoveImeData(ImeType type) void PerUserSession::OnFocused(int32_t pid, int32_t uid) { + std::lock_guard lock(focusedClientLock_); + auto client = GetCurrentClient(); + if (client == nullptr) { + return; + } if (IsCurrentClient(pid, uid)) { IMSA_HILOGD("pid[%{public}d] same as current client", pid); return; } - auto client = GetCurrentClient(); - if (client == nullptr) { - IMSA_HILOGD("no client in bound state"); + if (!OHOS::Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) { + IMSA_HILOGI("focus shifts to pid: %{public}d, remove current client", pid); + RemoveClient(client); return; } - IMSA_HILOGI("focus shifts to pid: %{public}d, clear unfocused client", pid); - RemoveClient(client); - InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED); + IMSA_HILOGI("focus shifts to pid: %{public}d, deactivate current client", pid); + DeactivateClient(client); } void PerUserSession::OnUnfocused(int32_t pid, int32_t uid) { + if (GetCurrentClient() == nullptr) { + return; + } if (IsCurrentClient(pid, uid)) { IMSA_HILOGD("pid[%{public}d] same as current client", pid); return; } - std::shared_ptr clientInfo; - { - std::lock_guard lock(mtx); - auto iter = std::find_if(mapClients_.begin(), mapClients_.end(), [pid](const auto &mapClient) { - return mapClient.second->pid == pid; - }); - if (iter != mapClients_.end()) { - clientInfo = iter->second; - } - } - if (clientInfo != nullptr) { - if (clientInfo->isAttaching) { - std::unique_lock lock(attachLock_); - imeAttachCv_.wait_for(lock, std::chrono::milliseconds(IME_ATTACH_INTERVAL), - [&clientInfo]() { return !clientInfo->isAttaching; }); - } - RemoveClient(clientInfo->client); - InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED); + auto clientInfo = GetClientInfo(pid); + if (clientInfo == nullptr) { + return; } + RemoveClient(clientInfo->client); + InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED); } bool PerUserSession::IsCurrentClient(int32_t pid, int32_t uid) @@ -798,6 +853,12 @@ bool PerUserSession::IsCurrentClient(int32_t pid, int32_t uid) return clientInfo->pid == pid && clientInfo->uid == uid; } +bool PerUserSession::IsCurrentClient(sptr client) +{ + auto currentClient = GetCurrentClient(); + return currentClient != nullptr && client != nullptr && client->AsObject() == currentClient->AsObject(); +} + bool PerUserSession::StartInputService(const std::string &imeName, bool isRetry) { std::string::size_type pos = imeName.find('/'); @@ -931,6 +992,12 @@ bool PerUserSession::IsBindImeInProxyImeBind(ImeType bindImeType) return bindImeType == ImeType::PROXY_IME && !IsProxyImeEnable(); } +bool PerUserSession::IsImeBindChanged(ImeType bindImeType) +{ + return (bindImeType == ImeType::IME && IsProxyImeEnable()) + || (bindImeType == ImeType::PROXY_IME && !IsProxyImeEnable()); +} + int32_t PerUserSession::SwitchSubtype(const SubProperty &subProperty) { auto data = GetImeData(ImeType::IME);