mirror of
https://gitee.com/openharmony/inputmethod_imf
synced 2024-11-23 22:59:45 +00:00
编辑文本相关处理排队处理
Signed-off-by: cy7717 <chenyu301@huawei.com>
This commit is contained in:
parent
ba8c941ddb
commit
06dbe5c373
71
common/queue.h
Normal file
71
common/queue.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
#ifndef OHOS_INPUTMETHOD_QUEUE_H
|
||||
#define OHOS_INPUTMETHOD_QUEUE_H
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
namespace OHOS {
|
||||
namespace MiscServices {
|
||||
template<typename T> class Queue {
|
||||
public:
|
||||
explicit Queue(uint32_t interval) : INTERVAL(interval)
|
||||
{
|
||||
}
|
||||
|
||||
~Queue()
|
||||
{
|
||||
}
|
||||
|
||||
void Pop()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queuesMutex_);
|
||||
queues_.pop();
|
||||
execCv_.notify_all();
|
||||
}
|
||||
|
||||
void Push(const T &data)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queuesMutex_);
|
||||
queues_.push(data);
|
||||
}
|
||||
|
||||
void WaitExec(const T &data)
|
||||
{
|
||||
if (!IsReadyToExec(data)) {
|
||||
std::unique_lock<std::mutex> lock(execMutex_);
|
||||
execCv_.wait_for(
|
||||
lock, std::chrono::milliseconds(INTERVAL), [&data, this]() { return IsReadyToExec(data); });
|
||||
}
|
||||
}
|
||||
|
||||
bool IsReadyToExec(const T &data)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queuesMutex_);
|
||||
return data == queues_.front();
|
||||
}
|
||||
|
||||
private:
|
||||
const uint32_t INTERVAL;
|
||||
std::mutex queuesMutex_;
|
||||
std::queue<T> queues_;
|
||||
std::mutex execMutex_;
|
||||
std::condition_variable execCv_;
|
||||
};
|
||||
} // namespace MiscServices
|
||||
} // namespace OHOS
|
||||
#endif // OHOS_INPUTMETHOD_QUEUE_H
|
@ -19,6 +19,7 @@
|
||||
#include <mutex>
|
||||
|
||||
namespace OHOS {
|
||||
namespace MiscServices {
|
||||
template<typename T> class BlockData {
|
||||
public:
|
||||
explicit BlockData(uint32_t interval, const T &invalid = T()) : INTERVAL(interval), data_(invalid)
|
||||
@ -67,5 +68,6 @@ private:
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cv_;
|
||||
};
|
||||
} // namespace MiscServices
|
||||
} // namespace OHOS
|
||||
#endif // OHOS_INPUTMETHOD_IMF_FRAMEWORKS_BLOCK_DATA_H
|
||||
|
@ -18,6 +18,7 @@ config("inputmethodengine_native_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"${inputmethod_path}/common",
|
||||
"${inputmethod_path}/frameworks/common",
|
||||
"${inputmethod_path}/frameworks/native/inputmethod_ability/include",
|
||||
"${inputmethod_path}/frameworks/native/inputmethod_controller/include",
|
||||
@ -35,6 +36,7 @@ config("inputmethodengine_native_public_config") {
|
||||
visibility = [ "./*" ]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"${inputmethod_path}/common",
|
||||
"${inputmethod_path}/frameworks/common",
|
||||
"${inputmethod_path}/frameworks/js/napi/inputmethodclient",
|
||||
"${inputmethod_path}/frameworks/js/napi/inputmethodability",
|
||||
|
@ -18,13 +18,17 @@ config("imf_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"../inputmethodability",
|
||||
"${inputmethod_path}/common",
|
||||
"${inputmethod_path}/frameworks/js/napi/inputmethodability",
|
||||
]
|
||||
}
|
||||
|
||||
config("imf_public_config") {
|
||||
visibility = [ "./*" ]
|
||||
include_dirs = [ "include" ]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"${inputmethod_path}/common",
|
||||
]
|
||||
ldflags = [ "-Wl,--exclude-libs=ALL" ]
|
||||
cflags = [
|
||||
"-fdata-sections",
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "async_call.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#include "global.h"
|
||||
#include "js_utils.h"
|
||||
@ -23,6 +24,10 @@
|
||||
namespace OHOS {
|
||||
namespace MiscServices {
|
||||
constexpr size_t ARGC_MAX = 6;
|
||||
constexpr int32_t MAX_WAIT_TIME = 1000;
|
||||
std::shared_ptr<Queue<EventInfo>> AsyncCall::queues_ = std::make_shared<Queue<EventInfo>>(MAX_WAIT_TIME);
|
||||
const std::set<std::string> QUEUE_EVENT_TYPE{ "moveCursor", "deleteForward", "deleteBackward", "insertText",
|
||||
"getForward", "getBackward", "selectByRange", "selectByMovement", "sendExtendAction", "getTextIndexAtCursor" };
|
||||
AsyncCall::AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr<Context> context, size_t maxParamCount)
|
||||
: env_(env)
|
||||
{
|
||||
@ -75,6 +80,10 @@ napi_value AsyncCall::Call(napi_env env, Context::ExecAction exec, const std::st
|
||||
napi_value resource = nullptr;
|
||||
std::string name = "IMF_" + resourceName;
|
||||
napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &resource);
|
||||
if (QUEUE_EVENT_TYPE.find(resourceName) != QUEUE_EVENT_TYPE.end()) {
|
||||
context_->ctx->eventInfo = { std::chrono::system_clock::now(), resourceName };
|
||||
queues_->Push(context_->ctx->eventInfo);
|
||||
}
|
||||
napi_create_async_work(env, nullptr, resource, AsyncCall::OnExecute, AsyncCall::OnComplete, context_, &work);
|
||||
context_->work = work;
|
||||
context_ = nullptr;
|
||||
@ -103,7 +112,13 @@ napi_value AsyncCall::SyncCall(napi_env env, AsyncCall::Context::ExecAction exec
|
||||
void AsyncCall::OnExecute(napi_env env, void *data)
|
||||
{
|
||||
AsyncContext *context = reinterpret_cast<AsyncContext *>(data);
|
||||
if (QUEUE_EVENT_TYPE.find(context->ctx->eventInfo.type) != QUEUE_EVENT_TYPE.end()) {
|
||||
queues_->WaitExec(context->ctx->eventInfo);
|
||||
}
|
||||
context->ctx->Exec();
|
||||
if (QUEUE_EVENT_TYPE.find(context->ctx->eventInfo.type) != QUEUE_EVENT_TYPE.end()) {
|
||||
queues_->Pop();
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncCall::OnComplete(napi_env env, napi_status status, void *data)
|
||||
|
@ -15,15 +15,24 @@
|
||||
#ifndef ASYN_CALL_H
|
||||
#define ASYN_CALL_H
|
||||
|
||||
#include "input_method_info.h"
|
||||
#include "global.h"
|
||||
#include "input_method_info.h"
|
||||
#include "js_utils.h"
|
||||
#include "napi/native_api.h"
|
||||
#include "napi/native_common.h"
|
||||
#include "napi/native_node_api.h"
|
||||
#include "queue.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace MiscServices {
|
||||
struct EventInfo {
|
||||
std::chrono::system_clock::time_point timestamp{};
|
||||
std::string type;
|
||||
bool operator==(const EventInfo &info) const
|
||||
{
|
||||
return (timestamp == info.timestamp && type == info.type);
|
||||
}
|
||||
};
|
||||
class AsyncCall final {
|
||||
public:
|
||||
class Context {
|
||||
@ -91,6 +100,7 @@ public:
|
||||
ExecAction exec_ = nullptr;
|
||||
napi_status status_ = napi_generic_failure;
|
||||
int32_t errorCode_ = 0;
|
||||
EventInfo eventInfo;
|
||||
};
|
||||
AsyncCall(napi_env env, napi_callback_info info, std::shared_ptr<Context> context, size_t maxParamCount);
|
||||
~AsyncCall();
|
||||
@ -111,6 +121,7 @@ private:
|
||||
static void DeleteContext(napi_env env, AsyncContext *context);
|
||||
AsyncContext *context_ = nullptr;
|
||||
napi_env env_ = nullptr;
|
||||
static std::shared_ptr<Queue<EventInfo>> queues_;
|
||||
};
|
||||
} // namespace MiscServices
|
||||
} // namespace OHOS
|
||||
|
@ -18,6 +18,7 @@ config("inputmethod_services_native_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"${inputmethod_path}/common",
|
||||
"${inputmethod_path}/frameworks/common",
|
||||
"${inputmethod_path}/frameworks/native/inputmethod_ability/include",
|
||||
"${inputmethod_path}/frameworks/native/inputmethod_controller/include",
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "inputmethod_dump.h"
|
||||
#include "inputmethod_trace.h"
|
||||
#include "peruser_session.h"
|
||||
#include "queue.h"
|
||||
#include "system_ability.h"
|
||||
|
||||
namespace OHOS {
|
||||
@ -113,15 +114,8 @@ private:
|
||||
static constexpr const char *SELECT_DIALOG_ACTION = "action.system.inputmethodchoose";
|
||||
static constexpr const char *SELECT_DIALOG_HAP = "cn.openharmony.inputmethodchoosedialog";
|
||||
static constexpr const char *SELECT_DIALOG_ABILITY = "InputMethod";
|
||||
|
||||
std::mutex switchMutex_;
|
||||
std::condition_variable switchCV_;
|
||||
std::mutex switchQueueMutex_;
|
||||
std::queue<SwitchInfo> switchQueue_;
|
||||
void PopSwitchQueue();
|
||||
void PushToSwitchQueue(const SwitchInfo &info);
|
||||
bool CheckReadyToSwitch(const SwitchInfo &info);
|
||||
|
||||
static constexpr int32_t MAX_WAIT_TIME = 1000;
|
||||
std::shared_ptr<Queue<SwitchInfo>> switchQueues_{ nullptr };
|
||||
int32_t InitKeyEventMonitor();
|
||||
bool InitFocusChangeMonitor();
|
||||
int32_t SwitchByCombinationKey(uint32_t state);
|
||||
|
@ -180,6 +180,7 @@ void InputMethodSystemAbility::Initialize()
|
||||
workThreadHandler = std::thread([this] { WorkThread(); });
|
||||
userSession_ = std::make_shared<PerUserSession>(MAIN_USER_ID);
|
||||
userId_ = MAIN_USER_ID;
|
||||
switchQueues_ = std::make_shared<Queue<SwitchInfo>>(MAX_WAIT_TIME);
|
||||
}
|
||||
|
||||
void InputMethodSystemAbility::StartUserIdListener()
|
||||
@ -357,39 +358,19 @@ int32_t InputMethodSystemAbility::DisplayOptionalInputMethod()
|
||||
return OnDisplayOptionalInputMethod();
|
||||
};
|
||||
|
||||
void InputMethodSystemAbility::PushToSwitchQueue(const SwitchInfo &info)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switchQueueMutex_);
|
||||
switchQueue_.push(info);
|
||||
}
|
||||
|
||||
void InputMethodSystemAbility::PopSwitchQueue()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switchQueueMutex_);
|
||||
switchQueue_.pop();
|
||||
switchCV_.notify_all();
|
||||
}
|
||||
|
||||
bool InputMethodSystemAbility::CheckReadyToSwitch(const SwitchInfo &info)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switchQueueMutex_);
|
||||
return info == switchQueue_.front();
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbility::SwitchInputMethod(const std::string &bundleName, const std::string &subName)
|
||||
{
|
||||
SwitchInfo switchInfo = { std::chrono::system_clock::now(), bundleName, subName };
|
||||
PushToSwitchQueue(switchInfo);
|
||||
switchQueues_->Push(switchInfo);
|
||||
return OnSwitchInputMethod(switchInfo, true);
|
||||
}
|
||||
|
||||
int32_t InputMethodSystemAbility::OnSwitchInputMethod(const SwitchInfo &switchInfo, bool isCheckPermission)
|
||||
{
|
||||
IMSA_HILOGD("run in, switchInfo: %{public}s|%{public}s", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
|
||||
if (!CheckReadyToSwitch(switchInfo)) {
|
||||
if (!switchQueues_->IsReadyToExec(switchInfo)) {
|
||||
IMSA_HILOGD("start wait");
|
||||
std::unique_lock<std::mutex> lock(switchMutex_);
|
||||
switchCV_.wait(lock, [this, &switchInfo]() { return CheckReadyToSwitch(switchInfo); });
|
||||
switchQueues_->WaitExec(switchInfo);
|
||||
usleep(SWITCH_BLOCK_TIME);
|
||||
}
|
||||
IMSA_HILOGD("start switch %{public}s", (switchInfo.bundleName + '/' + switchInfo.subName).c_str());
|
||||
@ -399,21 +380,21 @@ int32_t InputMethodSystemAbility::OnSwitchInputMethod(const SwitchInfo &switchIn
|
||||
&& !BundleChecker::CheckPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)
|
||||
&& !(switchInfo.bundleName == currentIme
|
||||
&& BundleChecker::IsCurrentIme(IPCSkeleton::GetCallingTokenID(), currentIme))) {
|
||||
PopSwitchQueue();
|
||||
switchQueues_->Pop();
|
||||
return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
|
||||
}
|
||||
if (!IsNeedSwitch(switchInfo.bundleName, switchInfo.subName)) {
|
||||
PopSwitchQueue();
|
||||
switchQueues_->Pop();
|
||||
return ErrorCode::NO_ERROR;
|
||||
}
|
||||
ImeInfo info;
|
||||
int32_t ret = ImeInfoInquirer::GetInstance().GetImeInfo(userId_, switchInfo.bundleName, switchInfo.subName, info);
|
||||
if (ret != ErrorCode::NO_ERROR) {
|
||||
PopSwitchQueue();
|
||||
switchQueues_->Pop();
|
||||
return ret;
|
||||
}
|
||||
ret = info.isNewIme ? Switch(switchInfo.bundleName, info) : SwitchExtension(info);
|
||||
PopSwitchQueue();
|
||||
switchQueues_->Pop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -710,7 +691,7 @@ int32_t InputMethodSystemAbility::SwitchMode()
|
||||
return ErrorCode::ERROR_BAD_PARAMETERS;
|
||||
}
|
||||
SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
|
||||
PushToSwitchQueue(switchInfo);
|
||||
switchQueues_->Push(switchInfo);
|
||||
return OnSwitchInputMethod(switchInfo, false);
|
||||
}
|
||||
|
||||
@ -734,7 +715,7 @@ int32_t InputMethodSystemAbility::SwitchLanguage()
|
||||
return ErrorCode::ERROR_BAD_PARAMETERS;
|
||||
}
|
||||
SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
|
||||
PushToSwitchQueue(switchInfo);
|
||||
switchQueues_->Push(switchInfo);
|
||||
return OnSwitchInputMethod(switchInfo, false);
|
||||
}
|
||||
|
||||
@ -751,7 +732,7 @@ int32_t InputMethodSystemAbility::SwitchType()
|
||||
[¤tImeBundle](const Property &property) { return property.name != currentImeBundle; });
|
||||
if (iter != props.end()) {
|
||||
SwitchInfo switchInfo = { std::chrono::system_clock::now(), iter->name, "" };
|
||||
PushToSwitchQueue(switchInfo);
|
||||
switchQueues_->Push(switchInfo);
|
||||
return OnSwitchInputMethod(switchInfo, false);
|
||||
}
|
||||
return ErrorCode::NO_ERROR;
|
||||
|
Loading…
Reference in New Issue
Block a user