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.
diff --git a/shell/platform/common/cpp/text_input_model.cc b/shell/platform/common/cpp/text_input_model.cc
index b8377ed..0a92dc7 100644
--- a/shell/platform/common/cpp/text_input_model.cc
+++ b/shell/platform/common/cpp/text_input_model.cc
@@ -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 @@
} // 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 @@
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
diff --git a/shell/platform/common/cpp/text_input_model.h b/shell/platform/common/cpp/text_input_model.h
index 5aeda0a..ac6cf8d 100644
--- a/shell/platform/common/cpp/text_input_model.h
+++ b/shell/platform/common/cpp/text_input_model.h
@@ -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 @@
// 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 @@
void DeleteSelected();
std::u16string text_;
- int client_id_;
std::string input_type_;
std::string input_action_;
std::u16string::iterator selection_base_;
diff --git a/shell/platform/glfw/text_input_plugin.cc b/shell/platform/glfw/text_input_plugin.cc
index f95d0d0..484c6c8 100644
--- a/shell/platform/glfw/text_input_plugin.cc
+++ b/shell/platform/glfw/text_input_plugin.cc
@@ -21,9 +21,16 @@
"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 @@
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::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 @@
}
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);
diff --git a/shell/platform/glfw/text_input_plugin.h b/shell/platform/glfw/text_input_plugin.h
index c3e6673..00c9a73 100644
--- a/shell/platform/glfw/text_input_plugin.h
+++ b/shell/platform/glfw/text_input_plugin.h
@@ -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 @@
// 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_;
};
diff --git a/shell/platform/windows/text_input_plugin.cc b/shell/platform/windows/text_input_plugin.cc
index be34dee..36f6389 100644
--- a/shell/platform/windows/text_input_plugin.cc
+++ b/shell/platform/windows/text_input_plugin.cc
@@ -23,9 +23,16 @@
"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 @@
"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::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 @@
}
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);
diff --git a/shell/platform/windows/text_input_plugin.h b/shell/platform/windows/text_input_plugin.h
index 44179f8..9000da7 100644
--- a/shell/platform/windows/text_input_plugin.h
+++ b/shell/platform/windows/text_input_plugin.h
@@ -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 @@
// 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_;
};