aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/win/native/window.hpp5
-rw-r--r--include/cru/win/string.hpp8
-rw-r--r--src/win/native/window.cpp12
3 files changed, 23 insertions, 2 deletions
diff --git a/include/cru/win/native/window.hpp b/include/cru/win/native/window.hpp
index a137463b..a27a3384 100644
--- a/include/cru/win/native/window.hpp
+++ b/include/cru/win/native/window.hpp
@@ -156,6 +156,11 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
Event<std::string> char_event_;
Event<WindowNativeMessageEventArgs&> native_message_event_;
+
+ // WM_CHAR may be sent twice successively with two utf-16 code units of
+ // surrogate pair when character is from supplementary planes. This field is
+ // used to save the previous one.
+ wchar_t last_wm_char_event_wparam_;
};
class WinNativeWindowResolver : public WinNativeResource,
diff --git a/include/cru/win/string.hpp b/include/cru/win/string.hpp
index 3fdadbf8..b2bfd245 100644
--- a/include/cru/win/string.hpp
+++ b/include/cru/win/string.hpp
@@ -27,6 +27,14 @@ namespace cru::platform::win {
std::string ToUtf8String(const std::wstring_view& string);
std::wstring ToUtf16String(const std::string_view& string);
+inline bool IsSurrogatePairLeading(wchar_t c) {
+ return c >= 0xD800 && c <= 0xDBFF;
+}
+
+inline bool IsSurrogatePairTrailing(wchar_t c) {
+ return c >= 0xDC00 && c <= 0xDFFF;
+}
+
using CodePoint = std::int32_t;
constexpr CodePoint k_code_point_end = -1;
diff --git a/src/win/native/window.cpp b/src/win/native/window.cpp
index 6f66cb57..a0ac2f6f 100644
--- a/src/win/native/window.cpp
+++ b/src/win/native/window.cpp
@@ -404,8 +404,16 @@ void WinNativeWindow::OnKeyUpInternal(int virtual_code) {
}
void WinNativeWindow::OnCharInternal(wchar_t c) {
- wchar_t s[2] = {c, 0};
- char_event_.Raise(platform::win::ToUtf8String(s));
+ if (platform::win::IsSurrogatePairLeading(c)) {
+ last_wm_char_event_wparam_ = c;
+ return;
+ } else if (platform::win::IsSurrogatePairTrailing(c)) {
+ wchar_t s[3] = {last_wm_char_event_wparam_, c, 0};
+ char_event_.Raise(platform::win::ToUtf8String(s));
+ } else {
+ wchar_t s[2] = {c, 0};
+ char_event_.Raise(platform::win::ToUtf8String(s));
+ }
}
void WinNativeWindow::OnActivatedInternal() {}