!789 编辑文本相关处理排队处理

Merge pull request !789 from cy7717/master
This commit is contained in:
openharmony_ci 2023-07-09 08:46:54 +00:00 committed by Gitee
commit c1375ba0f5
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
11 changed files with 210 additions and 59 deletions

68
common/block_queue.h Normal file
View File

@ -0,0 +1,68 @@
/*
* 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_BLOCK_QUEUE_H
#define OHOS_INPUTMETHOD_BLOCK_QUEUE_H
#include <condition_variable>
#include <mutex>
#include <queue>
namespace OHOS {
namespace MiscServices {
template<typename T> class BlockQueue {
public:
explicit BlockQueue(uint32_t timeout) : timeout_(timeout)
{
}
~BlockQueue() = default;
void Pop()
{
std::lock_guard<std::mutex> lock(queuesMutex_);
queues_.pop();
cv_.notify_all();
}
void Push(const T &data)
{
std::lock_guard<std::mutex> lock(queuesMutex_);
queues_.push(data);
}
void Wait(const T &data)
{
if (!IsReady(data)) {
std::unique_lock<std::mutex> lock(cvMutex_);
cv_.wait_for(lock, std::chrono::milliseconds(timeout_), [&data, this]() { return IsReady(data); });
}
}
bool IsReady(const T &data)
{
std::lock_guard<std::mutex> lock(queuesMutex_);
return data == queues_.front();
}
private:
const uint32_t timeout_;
std::mutex queuesMutex_;
std::queue<T> queues_;
std::mutex cvMutex_;
std::condition_variable cv_;
};
} // namespace MiscServices
} // namespace OHOS
#endif // OHOS_INPUTMETHOD_BLOCK_QUEUE_H

View File

@ -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

View File

@ -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",

View File

@ -25,7 +25,8 @@ namespace OHOS {
namespace MiscServices {
thread_local napi_ref JsTextInputClientEngine::TICRef_ = nullptr;
const std::string JsTextInputClientEngine::TIC_CLASS_NAME = "TextInputClient";
constexpr int32_t MAX_WAIT_TIME = 5000;
BlockQueue<EditorEventInfo> JsTextInputClientEngine::editorQueue_{ MAX_WAIT_TIME };
napi_value JsTextInputClientEngine::Init(napi_env env, napi_value info)
{
IMSA_HILOGI("JsTextInputClientEngine init");
@ -57,10 +58,17 @@ napi_value JsTextInputClientEngine::MoveCursor(napi_env env, napi_callback_info
auto ctxt = std::make_shared<MoveCursorContext>();
auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
PARAM_CHECK_RETURN(env, argc > 0, " should 1 or 2 parameters! ", TYPE_NONE, napi_generic_failure);
return JsUtils::GetValue(env, argv[0], ctxt->num);
auto status = JsUtils::GetValue(env, argv[0], ctxt->num);
if (status == napi_ok) {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::MOVE_CURSOR };
editorQueue_.Push(ctxt->info);
}
return status;
};
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
int32_t code = InputMethodAbility::GetInstance()->MoveCursor(ctxt->num);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->status = napi_ok;
ctxt->SetState(ctxt->status);
@ -205,14 +213,21 @@ napi_value JsTextInputClientEngine::DeleteForward(napi_env env, napi_callback_in
auto ctxt = std::make_shared<DeleteForwardContext>();
auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
PARAM_CHECK_RETURN(env, argc > 0, "should 1 or 2 parameters!", TYPE_NONE, napi_generic_failure);
return JsUtils::GetValue(env, argv[0], ctxt->length);
auto status = JsUtils::GetValue(env, argv[0], ctxt->length);
if (status == napi_ok) {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::DELETE_FORWARD };
editorQueue_.Push(ctxt->info);
}
return status;
};
auto output = [ctxt](napi_env env, napi_value *result) -> napi_status {
napi_status status = napi_get_boolean(env, ctxt->isDeleteForward, result);
return status;
};
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
int32_t code = InputMethodAbility::GetInstance()->DeleteForward(ctxt->length);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->status = napi_ok;
ctxt->SetState(ctxt->status);
@ -232,14 +247,21 @@ napi_value JsTextInputClientEngine::DeleteBackward(napi_env env, napi_callback_i
auto ctxt = std::make_shared<DeleteBackwardContext>();
auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
PARAM_CHECK_RETURN(env, argc > 0, "should 1 or 2 parameters!", TYPE_NONE, napi_generic_failure);
return JsUtils::GetValue(env, argv[0], ctxt->length);
auto status = JsUtils::GetValue(env, argv[0], ctxt->length);
if (status == napi_ok) {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::DELETE_BACKWARD };
editorQueue_.Push(ctxt->info);
}
return status;
};
auto output = [ctxt](napi_env env, napi_value *result) -> napi_status {
napi_status status = napi_get_boolean(env, ctxt->isDeleteBackward, result);
return status;
};
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
int32_t code = InputMethodAbility::GetInstance()->DeleteBackward(ctxt->length);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->status = napi_ok;
ctxt->SetState(ctxt->status);
@ -259,14 +281,21 @@ napi_value JsTextInputClientEngine::InsertText(napi_env env, napi_callback_info
auto ctxt = std::make_shared<InsertTextContext>();
auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
PARAM_CHECK_RETURN(env, argc > 0, "should 1 or 2 parameters!", TYPE_NONE, napi_generic_failure);
return JsUtils::GetValue(env, argv[0], ctxt->text);
auto status = JsUtils::GetValue(env, argv[0], ctxt->text);
if (status == napi_ok) {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::INSERT_TEXT };
editorQueue_.Push(ctxt->info);
}
return status;
};
auto output = [ctxt](napi_env env, napi_value *result) -> napi_status {
napi_status status = napi_get_boolean(env, ctxt->isInsertText, result);
return status;
};
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
int32_t code = InputMethodAbility::GetInstance()->InsertText(ctxt->text);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->status = napi_ok;
ctxt->SetState(ctxt->status);
@ -286,7 +315,12 @@ napi_value JsTextInputClientEngine::GetForward(napi_env env, napi_callback_info
auto ctxt = std::make_shared<GetForwardContext>();
auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
PARAM_CHECK_RETURN(env, argc > 0, "should 1 or 2 parameters!", TYPE_NONE, napi_generic_failure);
return JsUtils::GetValue(env, argv[0], ctxt->length);
auto status = JsUtils::GetValue(env, argv[0], ctxt->length);
if (status == napi_ok) {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::GET_FORWARD };
editorQueue_.Push(ctxt->info);
}
return status;
};
auto output = [ctxt](napi_env env, napi_value *result) -> napi_status {
napi_value data = GetResult(env, ctxt->text);
@ -294,8 +328,10 @@ napi_value JsTextInputClientEngine::GetForward(napi_env env, napi_callback_info
return napi_ok;
};
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
std::u16string temp;
int32_t code = InputMethodAbility::GetInstance()->GetTextBeforeCursor(ctxt->length, temp);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->status = napi_ok;
ctxt->SetState(ctxt->status);
@ -315,7 +351,12 @@ napi_value JsTextInputClientEngine::GetBackward(napi_env env, napi_callback_info
auto ctxt = std::make_shared<GetBackwardContext>();
auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
PARAM_CHECK_RETURN(env, argc > 0, "should 1 or 2 parameters!", TYPE_NONE, napi_generic_failure);
return JsUtils::GetValue(env, argv[0], ctxt->length);
auto status = JsUtils::GetValue(env, argv[0], ctxt->length);
if (status == napi_ok) {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::GET_BACKWARD };
editorQueue_.Push(ctxt->info);
}
return status;
};
auto output = [ctxt](napi_env env, napi_value *result) -> napi_status {
napi_value data = GetResult(env, ctxt->text);
@ -323,8 +364,10 @@ napi_value JsTextInputClientEngine::GetBackward(napi_env env, napi_callback_info
return napi_ok;
};
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
std::u16string temp;
int32_t code = InputMethodAbility::GetInstance()->GetTextAfterCursor(ctxt->length, temp);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->status = napi_ok;
ctxt->SetState(ctxt->status);
@ -374,11 +417,18 @@ napi_value JsTextInputClientEngine::SelectByRange(napi_env env, napi_callback_in
napi_valuetype valueType = napi_undefined;
napi_typeof(env, argv[0], &valueType);
PARAM_CHECK_RETURN(env, valueType == napi_object, "range", TYPE_OBJECT, napi_generic_failure);
return GetSelectRange(env, argv[0], ctxt);
auto status = GetSelectRange(env, argv[0], ctxt);
if (status == napi_ok) {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::SELECT_BY_RANGE };
editorQueue_.Push(ctxt->info);
}
return status;
};
auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { return napi_ok; };
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
int32_t code = InputMethodAbility::GetInstance()->SelectByRange(ctxt->start, ctxt->end);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->status = napi_ok;
ctxt->SetState(ctxt->status);
@ -401,11 +451,18 @@ napi_value JsTextInputClientEngine::SelectByMovement(napi_env env, napi_callback
napi_valuetype valueType = napi_undefined;
napi_typeof(env, argv[0], &valueType);
PARAM_CHECK_RETURN(env, valueType == napi_object, "movement", TYPE_NUMBER, napi_generic_failure);
return GetSelectMovement(env, argv[0], ctxt);
auto status = GetSelectMovement(env, argv[0], ctxt);
if (status == napi_ok) {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::SELECT_BY_MOVEMENT };
editorQueue_.Push(ctxt->info);
}
return status;
};
auto output = [ctxt](napi_env env, napi_value *result) -> napi_status { return napi_ok; };
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
int32_t code = InputMethodAbility::GetInstance()->SelectByMovement(ctxt->direction);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->status = napi_ok;
ctxt->SetState(ctxt->status);
@ -424,10 +481,17 @@ napi_value JsTextInputClientEngine::SendExtendAction(napi_env env, napi_callback
auto ctxt = std::make_shared<SendExtendActionContext>();
auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
PARAM_CHECK_RETURN(env, argc > 0, "should 1 or 2 parameters!", TYPE_NONE, napi_generic_failure);
return JsUtils::GetValue(env, argv[0], ctxt->action);
auto status = JsUtils::GetValue(env, argv[0], ctxt->action);
if (status == napi_ok) {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::SEND_EXTEND_ACTION };
editorQueue_.Push(ctxt->info);
}
return status;
};
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
int32_t code = InputMethodAbility::GetInstance()->SendExtendAction(ctxt->action);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->SetState(napi_ok);
return;
@ -444,12 +508,18 @@ napi_value JsTextInputClientEngine::GetTextIndexAtCursor(napi_env env, napi_call
{
IMSA_HILOGE("GetTextIndexAtCursor");
auto ctxt = std::make_shared<GetTextIndexAtCursorContext>();
auto input = [](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status { return napi_ok; };
auto input = [ctxt](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
ctxt->info = { std::chrono::system_clock::now(), EditorEvent::GET_TEXT_INDEX_AT_CURSOR };
editorQueue_.Push(ctxt->info);
return napi_ok;
};
auto output = [ctxt](napi_env env, napi_value *result) -> napi_status {
return napi_create_int32(env, ctxt->index, result);
};
auto exec = [ctxt](AsyncCall::Context *ctx) {
editorQueue_.Wait(ctxt->info);
int32_t code = InputMethodAbility::GetInstance()->GetTextIndexAtCursor(ctxt->index);
editorQueue_.Pop();
if (code == ErrorCode::NO_ERROR) {
ctxt->status = napi_ok;
ctxt->SetState(ctxt->status);

View File

@ -19,9 +19,31 @@
#include "global.h"
#include "native_engine/native_engine.h"
#include "native_engine/native_value.h"
#include "block_queue.h"
namespace OHOS {
namespace MiscServices {
enum class EditorEvent : uint32_t {
INSERT_TEXT = 0,
DELETE_FORWARD,
DELETE_BACKWARD,
MOVE_CURSOR,
SELECT_BY_RANGE,
SELECT_BY_MOVEMENT,
SEND_EXTEND_ACTION,
GET_FORWARD,
GET_BACKWARD,
GET_TEXT_INDEX_AT_CURSOR,
EVENT_END,
};
struct EditorEventInfo {
std::chrono::system_clock::time_point timestamp{};
EditorEvent event{ EditorEvent::EVENT_END };
bool operator==(const EditorEventInfo &info) const
{
return (timestamp == info.timestamp && event == info.event);
}
};
struct SendKeyFunctionContext : public AsyncCall::Context {
bool isSendKeyFunction = false;
int32_t action = 0;
@ -47,6 +69,7 @@ struct SendKeyFunctionContext : public AsyncCall::Context {
struct MoveCursorContext : public AsyncCall::Context {
int32_t num = 0;
EditorEventInfo info;
napi_status status = napi_generic_failure;
MoveCursorContext() : Context(nullptr, nullptr){};
MoveCursorContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
@ -69,6 +92,7 @@ struct MoveCursorContext : public AsyncCall::Context {
struct DeleteForwardContext : public AsyncCall::Context {
bool isDeleteForward = false;
int32_t length = 0;
EditorEventInfo info;
napi_status status = napi_generic_failure;
DeleteForwardContext() : Context(nullptr, nullptr){};
DeleteForwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
@ -91,6 +115,7 @@ struct DeleteForwardContext : public AsyncCall::Context {
struct DeleteBackwardContext : public AsyncCall::Context {
bool isDeleteBackward = false;
int32_t length = 0;
EditorEventInfo info;
napi_status status = napi_generic_failure;
DeleteBackwardContext() : Context(nullptr, nullptr){};
DeleteBackwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
@ -113,6 +138,7 @@ struct DeleteBackwardContext : public AsyncCall::Context {
struct InsertTextContext : public AsyncCall::Context {
bool isInsertText = false;
std::string text;
EditorEventInfo info;
napi_status status = napi_generic_failure;
InsertTextContext() : Context(nullptr, nullptr){};
InsertTextContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
@ -135,6 +161,7 @@ struct InsertTextContext : public AsyncCall::Context {
struct GetForwardContext : public AsyncCall::Context {
int32_t length = 0;
std::string text;
EditorEventInfo info;
napi_status status = napi_generic_failure;
GetForwardContext() : Context(nullptr, nullptr){};
GetForwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
@ -157,6 +184,7 @@ struct GetForwardContext : public AsyncCall::Context {
struct GetBackwardContext : public AsyncCall::Context {
int32_t length = 0;
std::string text;
EditorEventInfo info;
napi_status status = napi_generic_failure;
GetBackwardContext() : Context(nullptr, nullptr){};
GetBackwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
@ -202,6 +230,7 @@ struct SelectContext : public AsyncCall::Context {
int32_t start = 0;
int32_t end = 0;
int32_t direction = 0;
EditorEventInfo info;
napi_status status = napi_generic_failure;
SelectContext() : Context(nullptr, nullptr){};
SelectContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
@ -214,6 +243,7 @@ struct SelectContext : public AsyncCall::Context {
struct GetTextIndexAtCursorContext : public AsyncCall::Context {
int32_t index = 0;
EditorEventInfo info;
napi_status status = napi_generic_failure;
GetTextIndexAtCursorContext() : Context(nullptr, nullptr){};
GetTextIndexAtCursorContext(InputAction input, OutputAction output)
@ -236,6 +266,7 @@ struct GetTextIndexAtCursorContext : public AsyncCall::Context {
struct SendExtendActionContext : public AsyncCall::Context {
int32_t action = 0;
EditorEventInfo info;
SendExtendActionContext() : Context(nullptr, nullptr) {};
SendExtendActionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {};
@ -285,6 +316,7 @@ private:
static const std::string TIC_CLASS_NAME;
static thread_local napi_ref TICRef_;
static constexpr std::int32_t MAX_VALUE_LEN = 4096;
static BlockQueue<EditorEventInfo> editorQueue_;
};
} // namespace MiscServices
} // namespace OHOS

View File

@ -18,7 +18,7 @@ config("imf_config") {
visibility = [ ":*" ]
include_dirs = [
"include",
"../inputmethodability",
"${inputmethod_path}/frameworks/js/napi/inputmethodability",
]
}

View File

@ -15,8 +15,8 @@
#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"

View File

@ -189,7 +189,7 @@ void InputMethodController::WorkThread()
std::lock_guard<std::mutex> lock(textListenerLock_);
switch (msg->msgId_) {
case MSG_ID_INSERT_CHAR: {
IMSA_HILOGI("insert text");
IMSA_HILOGD("insert text");
if (!isEditable_.load() || textListener_ == nullptr) {
IMSA_HILOGE("not editable or textListener is nullptr");
break;
@ -199,7 +199,7 @@ void InputMethodController::WorkThread()
break;
}
case MSG_ID_DELETE_FORWARD: {
IMSA_HILOGI("delete forward");
IMSA_HILOGD("delete forward");
if (!isEditable_.load() || textListener_ == nullptr) {
IMSA_HILOGE("not editable or textListener is nullptr");
break;
@ -210,7 +210,7 @@ void InputMethodController::WorkThread()
break;
}
case MSG_ID_DELETE_BACKWARD: {
IMSA_HILOGI("delete backward");
IMSA_HILOGD("delete backward");
if (!isEditable_.load() || textListener_ == nullptr) {
IMSA_HILOGE("not editable or textListener is nullptr");
break;
@ -221,7 +221,6 @@ void InputMethodController::WorkThread()
break;
}
case MSG_ID_ON_INPUT_STOP: {
IMSA_HILOGI("input stop");
isBound_.store(false);
isEditable_.store(false);
textListener_ = nullptr;
@ -234,7 +233,6 @@ void InputMethodController::WorkThread()
break;
}
case MSG_ID_SEND_KEYBOARD_STATUS: {
IMSA_HILOGI("send keyboard status");
if (!isEditable_.load() || textListener_ == nullptr) {
IMSA_HILOGE("not editable or textListener_ is nullptr");
break;
@ -248,7 +246,6 @@ void InputMethodController::WorkThread()
break;
}
case MSG_ID_SEND_FUNCTION_KEY: {
IMSA_HILOGI("send fuction key");
if (!isEditable_.load() || textListener_ == nullptr) {
IMSA_HILOGE("not editable or textListener_ is nullptr");
break;
@ -261,7 +258,7 @@ void InputMethodController::WorkThread()
break;
}
case MSG_ID_MOVE_CURSOR: {
IMSA_HILOGI("move cursor");
IMSA_HILOGD("move cursor");
if (!isEditable_.load() || textListener_ == nullptr) {
IMSA_HILOGE("not editable or textListener_ is nullptr");
break;
@ -294,6 +291,7 @@ void InputMethodController::WorkThread()
break;
}
case MSG_ID_SELECT_BY_RANGE: {
IMSA_HILOGD("select by range");
MessageParcel *data = msg->msgContent_;
int32_t start = 0;
int32_t end = 0;
@ -305,6 +303,7 @@ void InputMethodController::WorkThread()
break;
}
case MSG_ID_HANDLE_EXTEND_ACTION: {
IMSA_HILOGD("handle extend action");
MessageParcel *data = msg->msgContent_;
int32_t action;
if (!ITypesUtil::Unmarshal(*data, action)) {
@ -315,6 +314,7 @@ void InputMethodController::WorkThread()
break;
}
case MSG_ID_SELECT_BY_MOVEMENT: {
IMSA_HILOGD("select by movement");
MessageParcel *data = msg->msgContent_;
int32_t direction = 0;
int32_t cursorMoveSkip = 0;
@ -327,10 +327,12 @@ void InputMethodController::WorkThread()
}
case MSG_ID_GET_TEXT_BEFORE_CURSOR:
case MSG_ID_GET_TEXT_AFTER_CURSOR: {
IMSA_HILOGD("get text, msgId:%{public}d", msg->msgId_);
GetText(msg);
break;
}
case MSG_ID_GET_TEXT_INDEX_AT_CURSOR: {
IMSA_HILOGD("get text index at cursor");
GetTextIndexAtCursor(msg);
break;
}

View File

@ -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",

View File

@ -31,6 +31,7 @@
#include "inputmethod_trace.h"
#include "peruser_session.h"
#include "system_ability.h"
#include "block_queue.h"
namespace OHOS {
namespace MiscServices {
@ -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 = 5000;
BlockQueue<SwitchInfo> switchQueue_{ MAX_WAIT_TIME };
int32_t InitKeyEventMonitor();
bool InitFocusChangeMonitor();
int32_t SwitchByCombinationKey(uint32_t state);

View File

@ -356,39 +356,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);
switchQueue_.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 (!switchQueue_.IsReady(switchInfo)) {
IMSA_HILOGD("start wait");
std::unique_lock<std::mutex> lock(switchMutex_);
switchCV_.wait(lock, [this, &switchInfo]() { return CheckReadyToSwitch(switchInfo); });
switchQueue_.Wait(switchInfo);
usleep(SWITCH_BLOCK_TIME);
}
IMSA_HILOGD("start switch %{public}s", (switchInfo.bundleName + '/' + switchInfo.subName).c_str());
@ -398,21 +378,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();
switchQueue_.Pop();
return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
}
if (!IsNeedSwitch(switchInfo.bundleName, switchInfo.subName)) {
PopSwitchQueue();
switchQueue_.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();
switchQueue_.Pop();
return ret;
}
ret = info.isNewIme ? Switch(switchInfo.bundleName, info) : SwitchExtension(info);
PopSwitchQueue();
switchQueue_.Pop();
return ret;
}
@ -709,7 +689,7 @@ int32_t InputMethodSystemAbility::SwitchMode()
return ErrorCode::ERROR_BAD_PARAMETERS;
}
SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
PushToSwitchQueue(switchInfo);
switchQueue_.Push(switchInfo);
return OnSwitchInputMethod(switchInfo, false);
}
@ -733,7 +713,7 @@ int32_t InputMethodSystemAbility::SwitchLanguage()
return ErrorCode::ERROR_BAD_PARAMETERS;
}
SwitchInfo switchInfo = { std::chrono::system_clock::now(), target->name, target->id };
PushToSwitchQueue(switchInfo);
switchQueue_.Push(switchInfo);
return OnSwitchInputMethod(switchInfo, false);
}
@ -750,7 +730,7 @@ int32_t InputMethodSystemAbility::SwitchType()
[&currentImeBundle](const Property &property) { return property.name != currentImeBundle; });
if (iter != props.end()) {
SwitchInfo switchInfo = { std::chrono::system_clock::now(), iter->name, "" };
PushToSwitchQueue(switchInfo);
switchQueue_.Push(switchInfo);
return OnSwitchInputMethod(switchInfo, false);
}
return ErrorCode::NO_ERROR;