From 720ecc1d1da32a03093891060b146469aa3d1e0c Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Sat, 2 Dec 2023 16:25:56 +0800 Subject: [PATCH 1/8] modify focus Signed-off-by: zhaolinglan --- .../include/i_input_method_core.h | 4 + .../include/input_method_ability.h | 3 +- .../include/input_method_core_proxy.h | 5 +- .../include/input_method_core_stub.h | 6 + .../src/input_method_ability.cpp | 12 ++ .../src/input_method_core_proxy.cpp | 16 +- .../src/input_method_core_stub.cpp | 31 +++ .../src/input_method_panel.cpp | 10 +- .../include/i_input_client.h | 9 +- .../include/input_client_info.h | 5 +- .../include/input_client_proxy.h | 4 +- .../include/input_client_stub.h | 2 + .../include/itypes_util.h | 3 + .../src/input_client_proxy.cpp | 8 +- .../src/input_client_stub.cpp | 14 ++ .../src/input_method_controller.cpp | 119 ++++++----- .../src/itypes_util.cpp | 21 +- .../include/input_method_controller.h | 11 ++ services/include/peruser_session.h | 12 +- services/src/peruser_session.cpp | 186 ++++++++++++------ 20 files changed, 352 insertions(+), 129 deletions(-) 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 eb50548c0..fde8af4f9 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 1ff7f5a82..a0c722dc8 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 f225116d5..de80ba41d 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 00ed132dd..4bc96d50d 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 67a45702a..d5bf6112f 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 85ee3eb8b..4e34936a2 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 00583b965..498ce89d7 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 6d2c1b9f6..6607cc6af 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 52bf2a508..4a01d378f 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 8175f297c..386601aff 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::ACTIVE }; // 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 38e545766..9f6816e4e 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 3a9cf7f29..c59878eee 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 bb7537745..c35099cca 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 a7c03b517..f32101fbe 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 90a8b456e..1c5cd5f97 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 29b04b79f..3097d549b 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -196,6 +196,22 @@ int32_t InputMethodController::OnPanelStatusChange( return ErrorCode::NO_ERROR; } +void InputMethodController::DeactivateClient() +{ + { + 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); + } + std::lock_guard lock(clientInfoLock_); + clientInfo_.state = ClientState::INACTIVE; +} + void InputMethodController::SaveTextConfig(const TextConfig &textConfig) { std::lock_guard lock(textConfigLock_); @@ -233,6 +249,7 @@ int32_t InputMethodController::Attach( InputMethodSyncTrace tracer("InputMethodController Attach with textConfig trace."); SetTextListener(listener); clientInfo_.isShowKeyboard = isShowKeyboard; + clientInfo_.state = ClientState::ACTIVE; SaveTextConfig(textConfig); GetTextConfig(clientInfo_.config); @@ -252,8 +269,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 +288,7 @@ int32_t InputMethodController::ShowTextInput() int32_t InputMethodController::HideTextInput() { - if (!isBound_.load()) { - IMSA_HILOGE("not bound yet"); + if (!IsBound()) { return ErrorCode::ERROR_CLIENT_NOT_BOUND; } IMSA_HILOGI("run in"); @@ -284,8 +300,7 @@ int32_t InputMethodController::HideTextInput() int32_t InputMethodController::HideCurrentInput() { IMSA_HILOGD("InputMethodController::HideCurrentInput"); - if (!isEditable_.load()) { - IMSA_HILOGE("not in editable state"); + if (!IsEditable()) { return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -300,7 +315,7 @@ int32_t InputMethodController::HideCurrentInput() int32_t InputMethodController::ShowCurrentInput() { - if (!isEditable_.load()) { + if (!IsEditable()) { IMSA_HILOGE("not in editable state"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } @@ -529,8 +544,7 @@ void InputMethodController::RestoreListenInfoInSaDied() void InputMethodController::RestoreAttachInfoInSaDied() { - if (!isEditable_.load()) { - IMSA_HILOGD("not in editable state"); + if (!IsEditable()) { return; } auto attach = [=]() -> bool { @@ -564,12 +578,7 @@ 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()) { return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } { @@ -597,12 +606,7 @@ 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()) { return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } { @@ -630,15 +634,14 @@ 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()) { + 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 +657,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 +669,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 +681,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 +692,7 @@ 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()) { return false; } if (keyEvent == nullptr) { @@ -749,12 +751,7 @@ 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()) { return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } { @@ -773,8 +770,7 @@ int32_t InputMethodController::SetCallingWindow(uint32_t windowId) int32_t InputMethodController::ShowSoftKeyboard() { - if (!isEditable_.load()) { - IMSA_HILOGE("not in editable state"); + if (!IsEditable()) { return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -790,8 +786,7 @@ int32_t InputMethodController::ShowSoftKeyboard() int32_t InputMethodController::HideSoftKeyboard() { - if (!isEditable_.load()) { - IMSA_HILOGE("not in editable state"); + if (!IsEditable()) { return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -922,7 +917,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 +934,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 +951,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 +971,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 +1015,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 +1028,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 +1041,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 +1084,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 da1a82946..89f329e55 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.client->AsObject(), input.channel->AsObject(), input.state)) { 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,20 @@ bool ITypesUtil::Unmarshalling(PanelInfo &output, MessageParcel &data) output.panelType = static_cast(panelType); return true; } + +bool ITypesUtil::Marshalling(ClientState input, MessageParcel &data) +{ + return data.WriteInt32(static_cast(input)); +} + +bool ITypesUtil::Unmarshalling(ClientState &output, MessageParcel &data) +{ + int32_t ret = 0; + if (!data.ReadInt32(ret)) { + return false; + } + output = static_cast(ret); + 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 18d88ca7f..f952042b4 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/include/peruser_session.h b/services/include/peruser_session.h index 31d5fc19b..f8192b7db 100644 --- a/services/include/peruser_session.h +++ b/services/include/peruser_session.h @@ -128,13 +128,16 @@ private: int AddClientInfo(sptr inputClient, const InputClientInfo &clientInfo, ClientAddEvent event); std::shared_ptr GetClientInfo(sptr inputClient); + std::shared_ptr GetClientInfo(pid_t pid); void UpdateClientInfo(const sptr &client, - const std::unordered_map> &updateInfos); + const std::unordered_map> &updateInfos); void RemoveClientInfo(const sptr &client, bool isClientDied = false); int32_t AddImeData(ImeType type, sptr core, sptr agent); std::shared_ptr GetImeData(ImeType type); + std::shared_ptr GetValidIme(ImeType type); void RemoveImeData(ImeType type); + void DeactivateClient(const sptr &client); int32_t RemoveClient(const sptr &client, bool isUnbindFromClient = false); int32_t RemoveIme(const sptr &core, ImeType type); @@ -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 db75b3884..e43198193 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -41,7 +41,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 +56,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 +74,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 +107,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 +132,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 +369,17 @@ 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()) { + return nullptr; + } + return iter->second; +} + int32_t PerUserSession::OnPrepareInput(const InputClientInfo &clientInfo) { IMSA_HILOGD("PerUserSession::OnPrepareInput Start"); @@ -399,14 +407,33 @@ 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; + } + 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 +444,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 +482,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 +497,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; } @@ -670,9 +681,43 @@ void PerUserSession::SetCurrentClient(sptr client) sptr PerUserSession::GetCurrentClient() { std::lock_guard lock(clientLock_); + IMSA_HILOGD("get current client"); 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 +769,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 +801,34 @@ void PerUserSession::RemoveImeData(ImeType type) void PerUserSession::OnFocused(int32_t pid, int32_t uid) { - if (IsCurrentClient(pid, uid)) { - IMSA_HILOGD("pid[%{public}d] same as current client", pid); - return; - } + std::lock_guard lock(focusedClientLock_); auto client = GetCurrentClient(); if (client == nullptr) { - IMSA_HILOGD("no client in bound state"); return; } - IMSA_HILOGI("focus shifts to pid: %{public}d, clear unfocused client", pid); - RemoveClient(client); - InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED); + if (IsCurrentClient(pid, uid)) { + IMSA_HILOGD("pid[%{public}d] same as current client", pid); + return; + } + 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 +846,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 +985,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); -- Gitee From 6284ab5717cba1739ee61fee7459d6195c78bba8 Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Sat, 2 Dec 2023 16:58:33 +0800 Subject: [PATCH 2/8] modify focus Signed-off-by: zhaolinglan --- .../include/input_client_info.h | 2 +- .../src/input_method_controller.cpp | 2 +- services/include/peruser_session.h | 12 ++++++------ services/src/peruser_session.cpp | 1 + 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/frameworks/native/inputmethod_controller/include/input_client_info.h b/frameworks/native/inputmethod_controller/include/input_client_info.h index 386601aff..129dee356 100644 --- a/frameworks/native/inputmethod_controller/include/input_client_info.h +++ b/frameworks/native/inputmethod_controller/include/input_client_info.h @@ -39,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 - ClientState state{ ClientState::ACTIVE }; // the state of input client + ClientState state{ ClientState::INACTIVE }; // the state of input client }; } // 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 3097d549b..a983e6947 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -249,7 +249,6 @@ int32_t InputMethodController::Attach( InputMethodSyncTrace tracer("InputMethodController Attach with textConfig trace."); SetTextListener(listener); clientInfo_.isShowKeyboard = isShowKeyboard; - clientInfo_.state = ClientState::ACTIVE; SaveTextConfig(textConfig); GetTextConfig(clientInfo_.config); @@ -259,6 +258,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); diff --git a/services/include/peruser_session.h b/services/include/peruser_session.h index f8192b7db..282bd1515 100644 --- a/services/include/peruser_session.h +++ b/services/include/peruser_session.h @@ -127,19 +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); + int32_t AddImeData(ImeType type, sptr core, sptr agent); - std::shared_ptr GetImeData(ImeType type); - std::shared_ptr GetValidIme(ImeType type); void RemoveImeData(ImeType type); - - void DeactivateClient(const sptr &client); - 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); diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index e43198193..5ceab455b 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -375,6 +375,7 @@ std::shared_ptr PerUserSession::GetClientInfo(pid_t pid) 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; -- Gitee From 1e88f5123e54d48d9c2748be36fb88cd9c1ca046 Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Sat, 2 Dec 2023 17:04:39 +0800 Subject: [PATCH 3/8] modify focus Signed-off-by: zhaolinglan --- .../inputmethod_controller/src/input_method_controller.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp index a983e6947..244d7d3be 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -198,6 +198,10 @@ int32_t InputMethodController::OnPanelStatusChange( void InputMethodController::DeactivateClient() { + { + std::lock_guard lock(clientInfoLock_); + clientInfo_.state = ClientState::INACTIVE; + } { std::lock_guard autoLock(agentLock_); agent_ = nullptr; @@ -208,8 +212,6 @@ void InputMethodController::DeactivateClient() IMSA_HILOGD("textListener_ is not nullptr"); listener->SendKeyboardStatus(KeyboardStatus::NONE); } - std::lock_guard lock(clientInfoLock_); - clientInfo_.state = ClientState::INACTIVE; } void InputMethodController::SaveTextConfig(const TextConfig &textConfig) -- Gitee From e4b8a93cccef03a74e185fbdbb554f5158067e14 Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Sat, 2 Dec 2023 17:15:14 +0800 Subject: [PATCH 4/8] modify focus Signed-off-by: zhaolinglan --- .../native/inputmethod_controller/src/itypes_util.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frameworks/native/inputmethod_controller/src/itypes_util.cpp b/frameworks/native/inputmethod_controller/src/itypes_util.cpp index 89f329e55..4257994c5 100644 --- a/frameworks/native/inputmethod_controller/src/itypes_util.cpp +++ b/frameworks/native/inputmethod_controller/src/itypes_util.cpp @@ -373,13 +373,13 @@ bool ITypesUtil::Unmarshalling(PanelInfo &output, MessageParcel &data) bool ITypesUtil::Marshalling(ClientState input, MessageParcel &data) { - return data.WriteInt32(static_cast(input)); + return data.WriteUint32(static_cast(input)); } bool ITypesUtil::Unmarshalling(ClientState &output, MessageParcel &data) { - int32_t ret = 0; - if (!data.ReadInt32(ret)) { + uint32_t ret = 0; + if (!data.ReadUint32(ret)) { return false; } output = static_cast(ret); -- Gitee From aa68fde801e33eef9022c127f0042cc51617ac4a Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Sat, 2 Dec 2023 18:25:47 +0800 Subject: [PATCH 5/8] modify focus Signed-off-by: zhaolinglan --- .../inputmethod_ability/src/input_method_ability.cpp | 4 +--- .../native/inputmethod_controller/src/itypes_util.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index d5bf6112f..fa53762be 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -948,9 +948,7 @@ 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(); - } + panel->HidePanel(); return false; }); } diff --git a/frameworks/native/inputmethod_controller/src/itypes_util.cpp b/frameworks/native/inputmethod_controller/src/itypes_util.cpp index 4257994c5..df43bc0b0 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.state, input.client->AsObject(), input.channel->AsObject())) { IMSA_HILOGE("write InputClientInfo to message parcel failed"); return false; } @@ -378,11 +378,12 @@ bool ITypesUtil::Marshalling(ClientState input, MessageParcel &data) bool ITypesUtil::Unmarshalling(ClientState &output, MessageParcel &data) { - uint32_t ret = 0; - if (!data.ReadUint32(ret)) { + uint32_t state = 0; + if (!data.ReadUint32(state)) { + IMSA_HILOGE("ClientState read failed"); return false; } - output = static_cast(ret); + output = static_cast(state); return true; } } // namespace MiscServices -- Gitee From 91b6ad569a6c1da0be737e87dc06c87e4e9f542b Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Sat, 2 Dec 2023 18:47:24 +0800 Subject: [PATCH 6/8] modify code Signed-off-by: zhaolinglan --- frameworks/native/inputmethod_controller/src/itypes_util.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/native/inputmethod_controller/src/itypes_util.cpp b/frameworks/native/inputmethod_controller/src/itypes_util.cpp index df43bc0b0..572685f1d 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.state, input.client->AsObject(), input.channel->AsObject())) { + input.state, input.client->AsObject(), input.channel->AsObject())) { IMSA_HILOGE("write InputClientInfo to message parcel failed"); return false; } @@ -253,7 +253,7 @@ 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, - output.state)) { + output.state)) { IMSA_HILOGE("read InputClientInfo from message parcel failed"); return false; } -- Gitee From bf4ba58306617da00f1ab9ca838f784f9888f26a Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Sat, 2 Dec 2023 20:06:17 +0800 Subject: [PATCH 7/8] modify code Signed-off-by: zhaolinglan --- .../inputmethod_ability/src/input_method_ability.cpp | 4 +++- .../src/input_method_controller.cpp | 12 +++++++++++- services/src/peruser_session.cpp | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp index fa53762be..d5bf6112f 100644 --- a/frameworks/native/inputmethod_ability/src/input_method_ability.cpp +++ b/frameworks/native/inputmethod_ability/src/input_method_ability.cpp @@ -948,7 +948,9 @@ void InputMethodAbility::OnClientInactive(const sptr &channel) IMSA_HILOGI("client inactive"); ClearDataChannel(channel); panels_.ForEach([](const PanelType &panelType, const std::shared_ptr &panel) { - panel->HidePanel(); + if (panelType != PanelType::SOFT_KEYBOARD || panel->GetPanelFlag() != PanelFlag::FLG_FIXED) { + panel->HidePanel(); + } return false; }); } diff --git a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp index 244d7d3be..3c232a38a 100644 --- a/frameworks/native/inputmethod_controller/src/input_method_controller.cpp +++ b/frameworks/native/inputmethod_controller/src/input_method_controller.cpp @@ -291,6 +291,7 @@ int32_t InputMethodController::ShowTextInput() int32_t InputMethodController::HideTextInput() { if (!IsBound()) { + IMSA_HILOGE("not bound"); return ErrorCode::ERROR_CLIENT_NOT_BOUND; } IMSA_HILOGI("run in"); @@ -303,6 +304,7 @@ int32_t InputMethodController::HideCurrentInput() { IMSA_HILOGD("InputMethodController::HideCurrentInput"); if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -318,7 +320,7 @@ int32_t InputMethodController::HideCurrentInput() int32_t InputMethodController::ShowCurrentInput() { if (!IsEditable()) { - IMSA_HILOGE("not in editable state"); + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -547,6 +549,7 @@ void InputMethodController::RestoreListenInfoInSaDied() void InputMethodController::RestoreAttachInfoInSaDied() { if (!IsEditable()) { + IMSA_HILOGD("not editable"); return; } auto attach = [=]() -> bool { @@ -581,6 +584,7 @@ void InputMethodController::RestoreAttachInfoInSaDied() int32_t InputMethodController::OnCursorUpdate(CursorInfo cursorInfo) { if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } { @@ -609,6 +613,7 @@ int32_t InputMethodController::OnCursorUpdate(CursorInfo cursorInfo) int32_t InputMethodController::OnSelectionChange(std::u16string text, int start, int end) { if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } { @@ -642,6 +647,7 @@ int32_t InputMethodController::OnConfigurationChange(Configuration info) 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", @@ -695,6 +701,7 @@ bool InputMethodController::DispatchKeyEvent(std::shared_ptr keyE { InputMethodSyncTrace tracer("DispatchKeyEvent trace"); if (!IsEditable()) { + IMSA_HILOGD("not editable"); return false; } if (keyEvent == nullptr) { @@ -754,6 +761,7 @@ int32_t InputMethodController::GetTextConfig(TextTotalConfig &config) int32_t InputMethodController::SetCallingWindow(uint32_t windowId) { if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } { @@ -773,6 +781,7 @@ int32_t InputMethodController::SetCallingWindow(uint32_t windowId) int32_t InputMethodController::ShowSoftKeyboard() { if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); @@ -789,6 +798,7 @@ int32_t InputMethodController::ShowSoftKeyboard() int32_t InputMethodController::HideSoftKeyboard() { if (!IsEditable()) { + IMSA_HILOGD("not editable"); return ErrorCode::ERROR_CLIENT_NOT_EDITABLE; } auto proxy = GetSystemAbilityProxy(); diff --git a/services/src/peruser_session.cpp b/services/src/peruser_session.cpp index 5ceab455b..7742e7a97 100644 --- a/services/src/peruser_session.cpp +++ b/services/src/peruser_session.cpp @@ -423,6 +423,7 @@ void PerUserSession::DeactivateClient(const sptr &client) if (clientInfo == nullptr) { return; } + IMSA_HILOGI("deactive client[%{public}d]", clientInfo->pid); UpdateClientInfo(client->AsObject(), { { UpdateFlag::STATE, ClientState::INACTIVE } }); if (IsCurrentClient(client)) { SetCurrentClient(nullptr); @@ -682,7 +683,6 @@ void PerUserSession::SetCurrentClient(sptr client) sptr PerUserSession::GetCurrentClient() { std::lock_guard lock(clientLock_); - IMSA_HILOGD("get current client"); return currentClient_; } -- Gitee From 42a784b7684873278af7080a274d3a26fcb898e4 Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Sat, 2 Dec 2023 22:27:48 +0800 Subject: [PATCH 8/8] modify code Signed-off-by: zhaolinglan --- services/BUILD.gn | 1 + services/src/peruser_session.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/services/BUILD.gn b/services/BUILD.gn index ee34f0328..9c29b520a 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/src/peruser_session.cpp b/services/src/peruser_session.cpp index 7742e7a97..b62e57f40 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" @@ -811,6 +812,11 @@ void PerUserSession::OnFocused(int32_t pid, int32_t uid) IMSA_HILOGD("pid[%{public}d] same as current client", pid); return; } + 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, deactivate current client", pid); DeactivateClient(client); } -- Gitee