mirror of
https://gitee.com/openharmony/inputmethod_imf
synced 2024-11-23 22:59:45 +00:00
commit
c1375ba0f5
68
common/block_queue.h
Normal file
68
common/block_queue.h
Normal 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
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -18,7 +18,7 @@ config("imf_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"../inputmethodability",
|
||||
"${inputmethod_path}/frameworks/js/napi/inputmethodability",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
[¤tImeBundle](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;
|
||||
|
Loading…
Reference in New Issue
Block a user