diff --git a/shell/platform/common/cpp/text_input_model.cc b/shell/platform/common/cpp/text_input_model.cc index 41231a6d611d40b009b0177b5b52d58d5548b9d3..35bc07592f0a2cf4cdede96012777e6fe7ebb72f 100644 --- a/shell/platform/common/cpp/text_input_model.cc +++ b/shell/platform/common/cpp/text_input_model.cc @@ -4,7 +4,9 @@ #include "flutter/shell/platform/common/cpp/text_input_model.h" +#include #include +#include // TODO(awdavies): Need to fix this regarding issue #47. static constexpr char kComposingBaseKey[] = "composingBase"; @@ -26,11 +28,16 @@ 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 +std::locale::id std::codecvt::id; +#endif // defined(_MSC_VER) + namespace flutter { TextInputModel::TextInputModel(int client_id, const rapidjson::Value& config) - : text_(""), - client_id_(client_id), + : client_id_(client_id), selection_base_(text_.begin()), selection_extent_(text_.begin()) { // TODO: Improve error handling during refactoring; this is just minimal @@ -64,7 +71,8 @@ bool TextInputModel::SetEditingState(size_t selection_base, if (selection_extent > text.size()) { return false; } - text_ = std::string(text); + std::wstring_convert, char32_t> utf32conv; + text_ = utf32conv.from_bytes(text); selection_base_ = text_.begin() + selection_base; selection_extent_ = text_.begin() + selection_extent; return true; @@ -76,7 +84,7 @@ void TextInputModel::DeleteSelected() { selection_extent_ = selection_base_; } -void TextInputModel::AddCharacter(char c) { +void TextInputModel::AddCharacter(char32_t c) { if (selection_base_ != selection_extent_) { DeleteSelected(); } @@ -172,8 +180,10 @@ std::unique_ptr TextInputModel::GetState() const { static_cast(selection_extent_ - text_.begin()), allocator); editing_state.AddMember(kSelectionIsDirectionalKey, false, allocator); - editing_state.AddMember(kTextKey, rapidjson::Value(text_, allocator).Move(), - allocator); + std::wstring_convert, char32_t> utf8conv; + editing_state.AddMember( + kTextKey, rapidjson::Value(utf8conv.to_bytes(text_), allocator).Move(), + allocator); args->PushBack(editing_state, allocator); return args; } diff --git a/shell/platform/common/cpp/text_input_model.h b/shell/platform/common/cpp/text_input_model.h index e3ea19bae90107f3c6ddb522e969e11bc2558e9d..0688512aedbd827a707b4cfb320b059b6f22e863 100644 --- a/shell/platform/common/cpp/text_input_model.h +++ b/shell/platform/common/cpp/text_input_model.h @@ -32,7 +32,7 @@ class TextInputModel { // Either appends after the cursor (when selection base and extent are the // same), or deletes the selected characters, replacing the text with the // character specified. - void AddCharacter(char c); + void AddCharacter(char32_t c); // Deletes either the selection, or one character ahead of the cursor. // @@ -89,12 +89,12 @@ class TextInputModel { private: void DeleteSelected(); - std::string text_; + std::u32string text_; int client_id_; std::string input_type_; std::string input_action_; - std::string::iterator selection_base_; - std::string::iterator selection_extent_; + std::u32string::iterator selection_base_; + std::u32string::iterator selection_extent_; }; } // namespace flutter diff --git a/shell/platform/glfw/text_input_plugin.cc b/shell/platform/glfw/text_input_plugin.cc index 3779510e301acd58eb5818cc5e175f12b5516af1..ebf7cc62bb121688faf8c8d1d7bc48ef3cf43c27 100644 --- a/shell/platform/glfw/text_input_plugin.cc +++ b/shell/platform/glfw/text_input_plugin.cc @@ -40,9 +40,7 @@ void TextInputPlugin::CharHook(GLFWwindow* window, unsigned int code_point) { if (active_model_ == nullptr) { return; } - // TODO(awdavies): Actually handle potential unicode characters. Probably - // requires some ICU data or something. - active_model_->AddCharacter(static_cast(code_point)); + active_model_->AddCharacter(code_point); SendStateUpdate(*active_model_); } diff --git a/shell/platform/windows/key_event_handler.cc b/shell/platform/windows/key_event_handler.cc index e2e94d63987488ef6231642f3ffad62b57e70982..63af2446b889b7a7b494673d982b4673b66fba7d 100644 --- a/shell/platform/windows/key_event_handler.cc +++ b/shell/platform/windows/key_event_handler.cc @@ -32,7 +32,7 @@ KeyEventHandler::KeyEventHandler(flutter::BinaryMessenger* messenger) KeyEventHandler::~KeyEventHandler() = default; void KeyEventHandler::CharHook(Win32FlutterWindow* window, - unsigned int code_point) {} + char32_t code_point) {} void KeyEventHandler::KeyboardHook(Win32FlutterWindow* window, int key, diff --git a/shell/platform/windows/key_event_handler.h b/shell/platform/windows/key_event_handler.h index 4fc569ffce9f458240adad3844fdad7f465ccb32..47ec63f6d1755dd9251474148fd4e3c5936b0a47 100644 --- a/shell/platform/windows/key_event_handler.h +++ b/shell/platform/windows/key_event_handler.h @@ -34,7 +34,7 @@ class KeyEventHandler : public KeyboardHookHandler { int mods) override; // |KeyboardHookHandler| - void CharHook(Win32FlutterWindow* window, unsigned int code_point) override; + void CharHook(Win32FlutterWindow* window, char32_t code_point) override; private: // The Flutter system channel for key event messages. diff --git a/shell/platform/windows/keyboard_hook_handler.h b/shell/platform/windows/keyboard_hook_handler.h index 761dbd655d22250e9d9c67b56231f33216d47e8a..1b3304ddd50b0d3a491a5baf1319150cbe8070df 100644 --- a/shell/platform/windows/keyboard_hook_handler.h +++ b/shell/platform/windows/keyboard_hook_handler.h @@ -24,8 +24,7 @@ class KeyboardHookHandler { int mods) = 0; // A function for hooking into unicode code point input. - virtual void CharHook(Win32FlutterWindow* window, - unsigned int code_point) = 0; + virtual void CharHook(Win32FlutterWindow* window, char32_t code_point) = 0; }; } // namespace flutter diff --git a/shell/platform/windows/text_input_plugin.cc b/shell/platform/windows/text_input_plugin.cc index 3324e8ee0f685035bea212158fd5d72ea51996f7..128f1f8d5b9a343132d1abf7d556fd020e4227ae 100644 --- a/shell/platform/windows/text_input_plugin.cc +++ b/shell/platform/windows/text_input_plugin.cc @@ -39,12 +39,11 @@ static constexpr uint32_t kInputModelLimit = 256; namespace flutter { void TextInputPlugin::CharHook(Win32FlutterWindow* window, - unsigned int code_point) { + char32_t code_point) { if (active_model_ == nullptr) { return; } - // TODO bug 30661 - active_model_->AddCharacter(static_cast(code_point)); + active_model_->AddCharacter(code_point); SendStateUpdate(*active_model_); } diff --git a/shell/platform/windows/text_input_plugin.h b/shell/platform/windows/text_input_plugin.h index 1cc57642e8af04e5a12dcbd0b541d444ee5c68d4..c367dbcc427b6405da4b35e8ebb6b75b6e43c9a9 100644 --- a/shell/platform/windows/text_input_plugin.h +++ b/shell/platform/windows/text_input_plugin.h @@ -35,7 +35,7 @@ class TextInputPlugin : public KeyboardHookHandler { int mods) override; // |KeyboardHookHandler| - void CharHook(Win32FlutterWindow* window, unsigned int code_point) override; + void CharHook(Win32FlutterWindow* window, char32_t code_point) override; private: // Sends the current state of the given model to the Flutter engine. diff --git a/shell/platform/windows/win32_flutter_window.cc b/shell/platform/windows/win32_flutter_window.cc index edd40d989309c1910d7be3e58ec044e3a964cc48..5b2f20c153576f2951dfb91038bd5ca39cd94211 100644 --- a/shell/platform/windows/win32_flutter_window.cc +++ b/shell/platform/windows/win32_flutter_window.cc @@ -125,7 +125,7 @@ void Win32FlutterWindow::OnPointerUp(double x, double y) { } } -void Win32FlutterWindow::OnChar(unsigned int code_point) { +void Win32FlutterWindow::OnChar(char32_t code_point) { if (process_events_) { SendChar(code_point); } @@ -207,7 +207,7 @@ void Win32FlutterWindow::SendPointerUp(double x, double y) { SendPointerEventWithData(event); } -void Win32FlutterWindow::SendChar(unsigned int code_point) { +void Win32FlutterWindow::SendChar(char32_t code_point) { for (const auto& handler : keyboard_hook_handlers_) { handler->CharHook(this, code_point); } diff --git a/shell/platform/windows/win32_flutter_window.h b/shell/platform/windows/win32_flutter_window.h index bd5f40c9b94ad83a675f1299903a2a1226ca98d3..c2316a88e0add83757a8cc0e7326c05c5aaf9f0c 100644 --- a/shell/platform/windows/win32_flutter_window.h +++ b/shell/platform/windows/win32_flutter_window.h @@ -54,7 +54,7 @@ class Win32FlutterWindow : public Win32Window { void OnPointerUp(double x, double y) override; // |Win32Window| - void OnChar(unsigned int code_point) override; + void OnChar(char32_t code_point) override; // |Win32Window| void OnKey(int key, int scancode, int action, int mods) override; @@ -103,7 +103,7 @@ class Win32FlutterWindow : public Win32Window { void SendPointerUp(double x, double y); // Reports a keyboard character to Flutter engine. - void SendChar(unsigned int code_point); + void SendChar(char32_t code_point); // Reports a raw keyboard message to Flutter engine. void SendKey(int key, int scancode, int action, int mods); diff --git a/shell/platform/windows/win32_window.cc b/shell/platform/windows/win32_window.cc index fce8ae73e14508142980daee54b21c5ace357cb7..ad6265109d80582452d2f1af75b3ce3b5aac8b42 100644 --- a/shell/platform/windows/win32_window.cc +++ b/shell/platform/windows/win32_window.cc @@ -153,13 +153,33 @@ Win32Window::MessageHandler(HWND hwnd, window->OnScroll( 0.0, -(static_cast(HIWORD(wparam)) / (double)WHEEL_DELTA)); break; + case WM_UNICHAR: { + // Tell third-pary app, we can support Unicode. + if (wparam == UNICODE_NOCHAR) + return TRUE; + // DefWindowProc will send WM_CHAR for this WM_UNICHAR. + break; + } case WM_CHAR: - case WM_SYSCHAR: - case WM_UNICHAR: - if (wparam != VK_BACK) { - window->OnChar(static_cast(wparam)); + case WM_SYSCHAR: { + if (wparam == VK_BACK) + break; + char32_t code_point = static_cast(wparam); + static char32_t lead_surrogate = 0; + // If code_point is LeadSurrogate, save and return. + if ((code_point & 0xFFFFFC00) == 0xD800) { + lead_surrogate = code_point; + return TRUE; + } + // Merge TrailSurrogate and LeadSurrogate. + if (lead_surrogate != 0 && (code_point & 0xFFFFFC00) == 0xDC00) { + code_point = 0x10000 + ((lead_surrogate & 0x000003FF) << 10) + + (code_point & 0x3FF); } + lead_surrogate = 0; + window->OnChar(code_point); break; + } case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_KEYUP: diff --git a/shell/platform/windows/win32_window.h b/shell/platform/windows/win32_window.h index 99036802f01a4d4735494a9c2c0e93f8ce2ea84b..45819b589ea61ebbb156ad4fdc8158fee6e01e69 100644 --- a/shell/platform/windows/win32_window.h +++ b/shell/platform/windows/win32_window.h @@ -89,7 +89,7 @@ class Win32Window { virtual void OnPointerUp(double x, double y) = 0; // Called when character input occurs. - virtual void OnChar(unsigned int code_point) = 0; + virtual void OnChar(char32_t code_point) = 0; // Called when raw keyboard input occurs. virtual void OnKey(int key, int scancode, int action, int mods) = 0;