* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "input_method_impl.h"
#include "input_method_controller.h"
namespace OHOS {
namespace MiscServices {
std::mutex InputMethodImpl::jsCbsLock_;
std::mutex InputMethodImpl::listenerMutex_;
std::shared_ptr<InputMethodImpl> InputMethodImpl::listener_{ nullptr };
std::unordered_map<std::string,
std::vector<taihe::callback<void(AttachFailureReason_t data)>>> InputMethodImpl::jsCbMap_;
constexpr const char *ATTACH_FAIL_CB_EVENT_TYPE = "attachmentDidFail";
std::shared_ptr<InputMethodImpl> InputMethodImpl::GetInstance()
{
if (listener_ == nullptr) {
std::lock_guard<std::mutex> lock(listenerMutex_);
if (listener_ == nullptr) {
listener_ = std::make_shared<InputMethodImpl>();
}
}
return listener_;
}
void InputMethodImpl::SetImcInnerListener()
{
auto instance = InputMethodController::GetInstance();
if (instance == nullptr) {
return;
}
instance->SetImcInnerListener(listener_);
}
void InputMethodImpl::RegisterListener(std::string const &type,
taihe::callback_view<void(AttachFailureReason_t data)> callback)
{
IMSA_HILOGD("event type: %{public}s.", type.c_str());
SetImcInnerListener();
{
std::lock_guard<std::mutex> lock(jsCbsLock_);
auto &cbVec = jsCbMap_[type];
auto it = std::find_if(cbVec.begin(), cbVec.end(),
[&callback](const auto &existingCb) {
return callback == existingCb;
});
if (it == cbVec.end()) {
cbVec.emplace_back(callback);
IMSA_HILOGD("callback registered success");
} else {
IMSA_HILOGD("%{public}s is already registered", type.c_str());
}
}
}
void InputMethodImpl::UnRegisterListener(std::string const &type,
taihe::optional_view<taihe::callback<void(AttachFailureReason_t data)>> callback)
{
IMSA_HILOGD("event type: %{public}s.", type.c_str());
std::lock_guard<std::mutex> lock(jsCbsLock_);
const auto iter = jsCbMap_.find(type);
if (iter == jsCbMap_.end()) {
IMSA_HILOGE("%{public}s is not registered", type.c_str());
return;
}
if (!callback.has_value()) {
jsCbMap_.erase(iter);
IMSA_HILOGD("unregistered all %{public}s callback", type.c_str());
return;
}
auto &callbacks = iter->second;
auto onceCallback = callback.value();
auto it = std::find_if(callbacks.begin(), callbacks.end(),
[&onceCallback](const auto &existingCb) {
return onceCallback == existingCb;
});
if (it != callbacks.end()) {
IMSA_HILOGD("unregistered callback success");
callbacks.erase(it);
}
if (callbacks.empty()) {
jsCbMap_.erase(iter);
IMSA_HILOGD("callback is empty");
}
}
void InputMethodImpl::OnAttachmentDidFail(AttachFailureReason reason)
{
IMSA_HILOGD("reason: %{public}d.", reason);
std::lock_guard<std::mutex> lock(jsCbsLock_);
auto &cbVec = jsCbMap_[ATTACH_FAIL_CB_EVENT_TYPE];
for (auto &cb : cbVec) {
AttachFailureReason_t tmpReason = EnumConvert::ConvertAttachFailureReason(reason);
cb(tmpReason);
}
}
}
}