aboutsummaryrefslogtreecommitdiff
path: root/src/win/native/input_method.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/win/native/input_method.cpp')
-rw-r--r--src/win/native/input_method.cpp75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/win/native/input_method.cpp b/src/win/native/input_method.cpp
new file mode 100644
index 00000000..4edfdc5f
--- /dev/null
+++ b/src/win/native/input_method.cpp
@@ -0,0 +1,75 @@
+#include "cru/win/native/input_method.hpp"
+
+#include "cru/common/logger.hpp"
+#include "cru/win/exception.hpp"
+#include "cru/win/native/window.hpp"
+#include "cru/win/string.hpp"
+#include "dpi_util.hpp"
+
+#include <vector>
+
+namespace cru::platform::native::win {
+WinInputMethodContextRef::WinInputMethodContextRef(WinNativeWindow* window)
+ : window_(window) {
+ Expects(window);
+
+ window_handle_ = window->GetWindowHandle();
+ handle_ = ::ImmGetContext(window_handle_);
+
+ // TODO: Events
+}
+
+WinInputMethodContextRef::~WinInputMethodContextRef() {
+ ::ImmReleaseContext(window_handle_, handle_);
+}
+
+void WinInputMethodContextRef::Reset() {
+ wchar_t s[1] = {L'\0'};
+
+ if (!::ImmSetCompositionStringW(handle_, SCS_SETSTR, static_cast<LPVOID>(s),
+ sizeof(s), static_cast<LPVOID>(s),
+ sizeof(s))) {
+ log::Warn(
+ "WinInputMethodContextRef: Failed to reset input method context.");
+ }
+}
+
+std::string WinInputMethodContextRef::GetCompositionString() {
+ const auto length =
+ ::ImmGetCompositionStringW(handle_, GCS_RESULTREADSTR, NULL, 0) +
+ sizeof(wchar_t);
+ std::vector<std::byte> data(length);
+ const auto result = ::ImmGetCompositionStringW(
+ handle_, GCS_RESULTREADSTR, static_cast<LPVOID>(data.data()), length);
+
+ if (result == IMM_ERROR_NODATA) {
+ return std::string{};
+ } else if (result == IMM_ERROR_GENERAL) {
+ throw new platform::win::Win32Error(::GetLastError(),
+ "Failed to get composition string.");
+ }
+
+ return platform::win::ToUtf8String(
+ std::wstring_view(reinterpret_cast<wchar_t*>(data.data())));
+}
+
+void WinInputMethodContextRef::SetCandidateWindowPosition(const Point& point) {
+ ::CANDIDATEFORM form;
+ form.dwIndex = 1;
+ form.dwStyle = CFS_CANDIDATEPOS;
+ form.ptCurrentPos = DipToPi(point);
+
+ if (!::ImmSetCandidateWindow(handle_, &form))
+ log::Debug(
+ "WinInputMethodContextRef: Failed to set input method candidate window "
+ "position.");
+}
+
+IEvent<std::string>* WinInputMethodContextRef::CompositionTextChangeEvent() {
+ return &composition_text_change_event_;
+}
+
+IEvent<std::string>* WinInputMethodContextRef::CharEvent() {
+ return &char_event_;
+}
+} // namespace cru::platform::native::win