diff options
Diffstat (limited to 'src/win/native/input_method.cpp')
-rw-r--r-- | src/win/native/input_method.cpp | 75 |
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 |