mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Remove rapidjson from TextInputModel (#18397)
This allows this class to be shared with the Linux plugin. Also move client_id outside this class as was noted in a TODO.
This commit is contained in:
parent
88eff68a82
commit
474e6f121e
@ -8,26 +8,6 @@
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
|
||||
// TODO(awdavies): Need to fix this regarding issue #47.
|
||||
static constexpr char kComposingBaseKey[] = "composingBase";
|
||||
|
||||
static constexpr char kComposingExtentKey[] = "composingExtent";
|
||||
|
||||
static constexpr char kSelectionAffinityKey[] = "selectionAffinity";
|
||||
static constexpr char kAffinityDownstream[] = "TextAffinity.downstream";
|
||||
|
||||
static constexpr char kSelectionBaseKey[] = "selectionBase";
|
||||
static constexpr char kSelectionExtentKey[] = "selectionExtent";
|
||||
|
||||
static constexpr char kSelectionIsDirectionalKey[] = "selectionIsDirectional";
|
||||
|
||||
static constexpr char kTextKey[] = "text";
|
||||
|
||||
// Input client configuration keys.
|
||||
static constexpr char kTextInputAction[] = "inputAction";
|
||||
static constexpr char kTextInputType[] = "inputType";
|
||||
static constexpr char kTextInputTypeName[] = "name";
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// TODO(naifu): This temporary code is to solve link error.(VS2015/2017)
|
||||
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error
|
||||
@ -49,28 +29,12 @@ bool IsTrailingSurrogate(char32_t code_point) {
|
||||
|
||||
} // namespace
|
||||
|
||||
TextInputModel::TextInputModel(int client_id, const rapidjson::Value& config)
|
||||
: client_id_(client_id),
|
||||
TextInputModel::TextInputModel(const std::string& input_type,
|
||||
const std::string& input_action)
|
||||
: input_type_(input_type),
|
||||
input_action_(input_action),
|
||||
selection_base_(text_.begin()),
|
||||
selection_extent_(text_.begin()) {
|
||||
// TODO: Improve error handling during refactoring; this is just minimal
|
||||
// checking to avoid asserts since RapidJSON is stricter than jsoncpp.
|
||||
if (config.IsObject()) {
|
||||
auto input_action = config.FindMember(kTextInputAction);
|
||||
if (input_action != config.MemberEnd() && input_action->value.IsString()) {
|
||||
input_action_ = input_action->value.GetString();
|
||||
}
|
||||
auto input_type_info = config.FindMember(kTextInputType);
|
||||
if (input_type_info != config.MemberEnd() &&
|
||||
input_type_info->value.IsObject()) {
|
||||
auto input_type = input_type_info->value.FindMember(kTextInputTypeName);
|
||||
if (input_type != input_type_info->value.MemberEnd() &&
|
||||
input_type->value.IsString()) {
|
||||
input_type_ = input_type->value.GetString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
selection_extent_(text_.begin()) {}
|
||||
|
||||
TextInputModel::~TextInputModel() = default;
|
||||
|
||||
@ -192,34 +156,10 @@ bool TextInputModel::MoveCursorBack() {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<rapidjson::Document> TextInputModel::GetState() const {
|
||||
// TODO(stuartmorgan): Move client_id out up to the plugin so that this
|
||||
// function just returns the editing state.
|
||||
auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
|
||||
auto& allocator = args->GetAllocator();
|
||||
args->PushBack(client_id_, allocator);
|
||||
|
||||
rapidjson::Value editing_state(rapidjson::kObjectType);
|
||||
// TODO(awdavies): Most of these are hard-coded for now.
|
||||
editing_state.AddMember(kComposingBaseKey, -1, allocator);
|
||||
editing_state.AddMember(kComposingExtentKey, -1, allocator);
|
||||
editing_state.AddMember(kSelectionAffinityKey, kAffinityDownstream,
|
||||
allocator);
|
||||
editing_state.AddMember(kSelectionBaseKey,
|
||||
static_cast<int>(selection_base_ - text_.begin()),
|
||||
allocator);
|
||||
editing_state.AddMember(kSelectionExtentKey,
|
||||
static_cast<int>(selection_extent_ - text_.begin()),
|
||||
allocator);
|
||||
editing_state.AddMember(kSelectionIsDirectionalKey, false, allocator);
|
||||
std::string TextInputModel::GetText() const {
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>
|
||||
utf8_converter;
|
||||
editing_state.AddMember(
|
||||
kTextKey,
|
||||
rapidjson::Value(utf8_converter.to_bytes(text_), allocator).Move(),
|
||||
allocator);
|
||||
args->PushBack(editing_state, allocator);
|
||||
return args;
|
||||
return utf8_converter.to_bytes(text_);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -8,15 +8,14 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
namespace flutter {
|
||||
// Handles underlying text input state, using a simple ASCII model.
|
||||
//
|
||||
// Ignores special states like "insert mode" for now.
|
||||
class TextInputModel {
|
||||
public:
|
||||
TextInputModel(int client_id, const rapidjson::Value& config);
|
||||
TextInputModel(const std::string& input_type,
|
||||
const std::string& input_action);
|
||||
virtual ~TextInputModel();
|
||||
|
||||
// Attempts to set the text state.
|
||||
@ -78,11 +77,18 @@ class TextInputModel {
|
||||
// Returns true if the cursor could be moved.
|
||||
void MoveCursorToEnd();
|
||||
|
||||
// Returns the state in the form of a platform message.
|
||||
std::unique_ptr<rapidjson::Document> GetState() const;
|
||||
// Get the current text
|
||||
std::string GetText() const;
|
||||
|
||||
// Id of the text input client.
|
||||
int client_id() const { return client_id_; }
|
||||
// The position of the cursor
|
||||
int selection_base() const {
|
||||
return static_cast<int>(selection_base_ - text_.begin());
|
||||
}
|
||||
|
||||
// The end of the selection
|
||||
int selection_extent() const {
|
||||
return static_cast<int>(selection_extent_ - text_.begin());
|
||||
}
|
||||
|
||||
// Keyboard type of the client. See available options:
|
||||
// https://docs.flutter.io/flutter/services/TextInputType-class.html
|
||||
@ -96,7 +102,6 @@ class TextInputModel {
|
||||
void DeleteSelected();
|
||||
|
||||
std::u16string text_;
|
||||
int client_id_;
|
||||
std::string input_type_;
|
||||
std::string input_action_;
|
||||
std::u16string::iterator selection_base_;
|
||||
|
||||
@ -21,9 +21,16 @@ static constexpr char kUpdateEditingStateMethod[] =
|
||||
"TextInputClient.updateEditingState";
|
||||
static constexpr char kPerformActionMethod[] = "TextInputClient.performAction";
|
||||
|
||||
static constexpr char kTextInputAction[] = "inputAction";
|
||||
static constexpr char kTextInputType[] = "inputType";
|
||||
static constexpr char kTextInputTypeName[] = "name";
|
||||
static constexpr char kComposingBaseKey[] = "composingBase";
|
||||
static constexpr char kComposingExtentKey[] = "composingExtent";
|
||||
static constexpr char kSelectionAffinityKey[] = "selectionAffinity";
|
||||
static constexpr char kAffinityDownstream[] = "TextAffinity.downstream";
|
||||
static constexpr char kSelectionBaseKey[] = "selectionBase";
|
||||
static constexpr char kSelectionExtentKey[] = "selectionExtent";
|
||||
|
||||
static constexpr char kSelectionIsDirectionalKey[] = "selectionIsDirectional";
|
||||
static constexpr char kTextKey[] = "text";
|
||||
|
||||
static constexpr char kChannelName[] = "flutter/textinput";
|
||||
@ -133,8 +140,25 @@ void TextInputPlugin::HandleMethodCall(
|
||||
result->Error(kBadArgumentError,
|
||||
"Could not set client, missing arguments.");
|
||||
}
|
||||
int client_id = client_id_json.GetInt();
|
||||
active_model_ = std::make_unique<TextInputModel>(client_id, client_config);
|
||||
client_id_ = client_id_json.GetInt();
|
||||
std::string input_action;
|
||||
auto input_action_json = client_config.FindMember(kTextInputAction);
|
||||
if (input_action_json != client_config.MemberEnd() &&
|
||||
input_action_json->value.IsString()) {
|
||||
input_action = input_action_json->value.GetString();
|
||||
}
|
||||
std::string input_type;
|
||||
auto input_type_info_json = client_config.FindMember(kTextInputType);
|
||||
if (input_type_info_json != client_config.MemberEnd() &&
|
||||
input_type_info_json->value.IsObject()) {
|
||||
auto input_type_json =
|
||||
input_type_info_json->value.FindMember(kTextInputTypeName);
|
||||
if (input_type_json != input_type_info_json->value.MemberEnd() &&
|
||||
input_type_json->value.IsString()) {
|
||||
input_type = input_type_json->value.GetString();
|
||||
}
|
||||
}
|
||||
active_model_ = std::make_unique<TextInputModel>(input_type, input_action);
|
||||
} else if (method.compare(kSetEditingStateMethod) == 0) {
|
||||
if (!method_call.arguments() || method_call.arguments()->IsNull()) {
|
||||
result->Error(kBadArgumentError, "Method invoked without args");
|
||||
@ -176,7 +200,24 @@ void TextInputPlugin::HandleMethodCall(
|
||||
}
|
||||
|
||||
void TextInputPlugin::SendStateUpdate(const TextInputModel& model) {
|
||||
channel_->InvokeMethod(kUpdateEditingStateMethod, model.GetState());
|
||||
auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
|
||||
auto& allocator = args->GetAllocator();
|
||||
args->PushBack(client_id_, allocator);
|
||||
|
||||
rapidjson::Value editing_state(rapidjson::kObjectType);
|
||||
editing_state.AddMember(kComposingBaseKey, -1, allocator);
|
||||
editing_state.AddMember(kComposingExtentKey, -1, allocator);
|
||||
editing_state.AddMember(kSelectionAffinityKey, kAffinityDownstream,
|
||||
allocator);
|
||||
editing_state.AddMember(kSelectionBaseKey, model.selection_base(), allocator);
|
||||
editing_state.AddMember(kSelectionExtentKey, model.selection_extent(),
|
||||
allocator);
|
||||
editing_state.AddMember(kSelectionIsDirectionalKey, false, allocator);
|
||||
editing_state.AddMember(
|
||||
kTextKey, rapidjson::Value(model.GetText(), allocator).Move(), allocator);
|
||||
args->PushBack(editing_state, allocator);
|
||||
|
||||
channel_->InvokeMethod(kUpdateEditingStateMethod, std::move(args));
|
||||
}
|
||||
|
||||
void TextInputPlugin::EnterPressed(TextInputModel* model) {
|
||||
@ -186,7 +227,7 @@ void TextInputPlugin::EnterPressed(TextInputModel* model) {
|
||||
}
|
||||
auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
|
||||
auto& allocator = args->GetAllocator();
|
||||
args->PushBack(model->client_id(), allocator);
|
||||
args->PushBack(client_id_, allocator);
|
||||
args->PushBack(rapidjson::Value(model->input_action(), allocator).Move(),
|
||||
allocator);
|
||||
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
#include "flutter/shell/platform/glfw/keyboard_hook_handler.h"
|
||||
#include "flutter/shell/platform/glfw/public/flutter_glfw.h"
|
||||
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// Implements a text input plugin.
|
||||
@ -50,6 +52,9 @@ class TextInputPlugin : public KeyboardHookHandler {
|
||||
// The MethodChannel used for communication with the Flutter engine.
|
||||
std::unique_ptr<flutter::MethodChannel<rapidjson::Document>> channel_;
|
||||
|
||||
// The active client id.
|
||||
int client_id_;
|
||||
|
||||
// The active model. nullptr if not set.
|
||||
std::unique_ptr<TextInputModel> active_model_;
|
||||
};
|
||||
|
||||
@ -23,9 +23,16 @@ static constexpr char kUpdateEditingStateMethod[] =
|
||||
"TextInputClient.updateEditingState";
|
||||
static constexpr char kPerformActionMethod[] = "TextInputClient.performAction";
|
||||
|
||||
static constexpr char kTextInputAction[] = "inputAction";
|
||||
static constexpr char kTextInputType[] = "inputType";
|
||||
static constexpr char kTextInputTypeName[] = "name";
|
||||
static constexpr char kComposingBaseKey[] = "composingBase";
|
||||
static constexpr char kComposingExtentKey[] = "composingExtent";
|
||||
static constexpr char kSelectionAffinityKey[] = "selectionAffinity";
|
||||
static constexpr char kAffinityDownstream[] = "TextAffinity.downstream";
|
||||
static constexpr char kSelectionBaseKey[] = "selectionBase";
|
||||
static constexpr char kSelectionExtentKey[] = "selectionExtent";
|
||||
|
||||
static constexpr char kSelectionIsDirectionalKey[] = "selectionIsDirectional";
|
||||
static constexpr char kTextKey[] = "text";
|
||||
|
||||
static constexpr char kChannelName[] = "flutter/textinput";
|
||||
@ -135,8 +142,25 @@ void TextInputPlugin::HandleMethodCall(
|
||||
"Could not set client, missing arguments.");
|
||||
return;
|
||||
}
|
||||
int client_id = client_id_json.GetInt();
|
||||
active_model_ = std::make_unique<TextInputModel>(client_id, client_config);
|
||||
client_id_ = client_id_json.GetInt();
|
||||
std::string input_action;
|
||||
auto input_action_json = client_config.FindMember(kTextInputAction);
|
||||
if (input_action_json != client_config.MemberEnd() &&
|
||||
input_action_json->value.IsString()) {
|
||||
input_action = input_action_json->value.GetString();
|
||||
}
|
||||
std::string input_type;
|
||||
auto input_type_info_json = client_config.FindMember(kTextInputType);
|
||||
if (input_type_info_json != client_config.MemberEnd() &&
|
||||
input_type_info_json->value.IsObject()) {
|
||||
auto input_type_json =
|
||||
input_type_info_json->value.FindMember(kTextInputTypeName);
|
||||
if (input_type_json != input_type_info_json->value.MemberEnd() &&
|
||||
input_type_json->value.IsString()) {
|
||||
input_type = input_type_json->value.GetString();
|
||||
}
|
||||
}
|
||||
active_model_ = std::make_unique<TextInputModel>(input_type, input_action);
|
||||
} else if (method.compare(kSetEditingStateMethod) == 0) {
|
||||
if (!method_call.arguments() || method_call.arguments()->IsNull()) {
|
||||
result->Error(kBadArgumentError, "Method invoked without args");
|
||||
@ -178,7 +202,24 @@ void TextInputPlugin::HandleMethodCall(
|
||||
}
|
||||
|
||||
void TextInputPlugin::SendStateUpdate(const TextInputModel& model) {
|
||||
channel_->InvokeMethod(kUpdateEditingStateMethod, model.GetState());
|
||||
auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
|
||||
auto& allocator = args->GetAllocator();
|
||||
args->PushBack(client_id_, allocator);
|
||||
|
||||
rapidjson::Value editing_state(rapidjson::kObjectType);
|
||||
editing_state.AddMember(kComposingBaseKey, -1, allocator);
|
||||
editing_state.AddMember(kComposingExtentKey, -1, allocator);
|
||||
editing_state.AddMember(kSelectionAffinityKey, kAffinityDownstream,
|
||||
allocator);
|
||||
editing_state.AddMember(kSelectionBaseKey, model.selection_base(), allocator);
|
||||
editing_state.AddMember(kSelectionExtentKey, model.selection_extent(),
|
||||
allocator);
|
||||
editing_state.AddMember(kSelectionIsDirectionalKey, false, allocator);
|
||||
editing_state.AddMember(
|
||||
kTextKey, rapidjson::Value(model.GetText(), allocator).Move(), allocator);
|
||||
args->PushBack(editing_state, allocator);
|
||||
|
||||
channel_->InvokeMethod(kUpdateEditingStateMethod, std::move(args));
|
||||
}
|
||||
|
||||
void TextInputPlugin::EnterPressed(TextInputModel* model) {
|
||||
@ -188,7 +229,7 @@ void TextInputPlugin::EnterPressed(TextInputModel* model) {
|
||||
}
|
||||
auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
|
||||
auto& allocator = args->GetAllocator();
|
||||
args->PushBack(model->client_id(), allocator);
|
||||
args->PushBack(client_id_, allocator);
|
||||
args->PushBack(rapidjson::Value(model->input_action(), allocator).Move(),
|
||||
allocator);
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h"
|
||||
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/method_channel.h"
|
||||
#include "flutter/shell/platform/common/cpp/json_method_codec.h"
|
||||
#include "flutter/shell/platform/common/cpp/text_input_model.h"
|
||||
#include "flutter/shell/platform/windows/keyboard_hook_handler.h"
|
||||
#include "flutter/shell/platform/windows/public/flutter_windows.h"
|
||||
@ -53,6 +54,9 @@ class TextInputPlugin : public KeyboardHookHandler {
|
||||
// The MethodChannel used for communication with the Flutter engine.
|
||||
std::unique_ptr<flutter::MethodChannel<rapidjson::Document>> channel_;
|
||||
|
||||
// The active client id.
|
||||
int client_id_;
|
||||
|
||||
// The active model. nullptr if not set.
|
||||
std::unique_ptr<TextInputModel> active_model_;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user