aboutsummaryrefslogtreecommitdiff
path: root/src/win/gui/InputMethod.cpp
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-05-15 13:56:40 +0800
committercrupest <crupest@outlook.com>2022-05-15 13:56:40 +0800
commit9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752 (patch)
tree7342f6991771fa31b16fd6a5ed892ff6025f3d05 /src/win/gui/InputMethod.cpp
parent41de54bad2c0f857821fcc83f41af3334d068b6d (diff)
downloadcru-9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752.tar.gz
cru-9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752.tar.bz2
cru-9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752.zip
...
Diffstat (limited to 'src/win/gui/InputMethod.cpp')
-rw-r--r--src/win/gui/InputMethod.cpp286
1 files changed, 0 insertions, 286 deletions
diff --git a/src/win/gui/InputMethod.cpp b/src/win/gui/InputMethod.cpp
deleted file mode 100644
index 8a54577b..00000000
--- a/src/win/gui/InputMethod.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-#include "cru/win/gui/InputMethod.h"
-
-#include "cru/common/log/Logger.h"
-#include "cru/common/StringUtil.h"
-#include "cru/platform/Check.h"
-#include "cru/platform/gui/DebugFlags.h"
-#include "cru/win/Exception.h"
-#include "cru/win/gui/Window.h"
-
-#include <vector>
-
-namespace cru::platform::gui::win {
-AutoHIMC::AutoHIMC(HWND hwnd) : hwnd_(hwnd) {
- Expects(hwnd);
- handle_ = ::ImmGetContext(hwnd);
-}
-
-AutoHIMC::AutoHIMC(AutoHIMC&& other)
- : hwnd_(other.hwnd_), handle_(other.handle_) {
- other.hwnd_ = nullptr;
- other.handle_ = nullptr;
-}
-
-AutoHIMC& AutoHIMC::operator=(AutoHIMC&& other) {
- if (this != &other) {
- Object::operator=(std::move(other));
- this->hwnd_ = other.hwnd_;
- this->handle_ = other.handle_;
- other.hwnd_ = nullptr;
- other.handle_ = nullptr;
- }
- return *this;
-}
-
-AutoHIMC::~AutoHIMC() {
- if (handle_) {
- if (!::ImmReleaseContext(hwnd_, handle_))
- CRU_LOG_WARN(u"Failed to release HIMC.");
- }
-}
-
-// copied from chromium
-namespace {
-// Determines whether or not the given attribute represents a target
-// (a.k.a. a selection).
-bool IsTargetAttribute(char attribute) {
- return (attribute == ATTR_TARGET_CONVERTED ||
- attribute == ATTR_TARGET_NOTCONVERTED);
-}
-// Helper function for ImeInput::GetCompositionInfo() method, to get the target
-// range that's selected by the user in the current composition string.
-void GetCompositionTargetRange(HIMC imm_context, int* target_start,
- int* target_end) {
- int attribute_size =
- ::ImmGetCompositionString(imm_context, GCS_COMPATTR, NULL, 0);
- if (attribute_size > 0) {
- int start = 0;
- int end = 0;
- std::vector<char> attribute_data(attribute_size);
- ::ImmGetCompositionString(imm_context, GCS_COMPATTR, attribute_data.data(),
- attribute_size);
- for (start = 0; start < attribute_size; ++start) {
- if (IsTargetAttribute(attribute_data[start])) break;
- }
- for (end = start; end < attribute_size; ++end) {
- if (!IsTargetAttribute(attribute_data[end])) break;
- }
- if (start == attribute_size) {
- // This composition clause does not contain any target clauses,
- // i.e. this clauses is an input clause.
- // We treat the whole composition as a target clause.
- start = 0;
- end = attribute_size;
- }
- *target_start = start;
- *target_end = end;
- }
-}
-// Helper function for ImeInput::GetCompositionInfo() method, to get underlines
-// information of the current composition string.
-CompositionClauses GetCompositionClauses(HIMC imm_context, int target_start,
- int target_end) {
- CompositionClauses result;
- int clause_size =
- ::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE, NULL, 0);
- int clause_length = clause_size / sizeof(std::uint32_t);
- if (clause_length) {
- result.reserve(clause_length - 1);
- std::vector<std::uint32_t> clause_data(clause_length);
- ::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE, clause_data.data(),
- clause_size);
- for (int i = 0; i < clause_length - 1; ++i) {
- CompositionClause clause;
- clause.start = clause_data[i];
- clause.end = clause_data[i + 1];
- clause.target = false;
- // Use thick underline for the target clause.
- if (clause.start >= target_start && clause.end <= target_end) {
- clause.target = true;
- }
- result.push_back(clause);
- }
- }
- return result;
-}
-
-String GetString(HIMC imm_context) {
- LONG string_size =
- ::ImmGetCompositionString(imm_context, GCS_COMPSTR, NULL, 0);
- String result((string_size / sizeof(char16_t)), 0);
- ::ImmGetCompositionString(imm_context, GCS_COMPSTR, result.data(),
- string_size);
- return result;
-}
-
-String GetResultString(HIMC imm_context) {
- LONG string_size =
- ::ImmGetCompositionString(imm_context, GCS_RESULTSTR, NULL, 0);
- String result((string_size / sizeof(char16_t)), 0);
- ::ImmGetCompositionString(imm_context, GCS_RESULTSTR, result.data(),
- string_size);
- return result;
-}
-
-CompositionText GetCompositionInfo(HIMC imm_context) {
- // We only care about GCS_COMPATTR, GCS_COMPCLAUSE and GCS_CURSORPOS, and
- // convert them into underlines and selection range respectively.
-
- auto text = GetString(imm_context);
-
- int length = static_cast<int>(text.length());
- // Find out the range selected by the user.
- int target_start = length;
- int target_end = length;
- GetCompositionTargetRange(imm_context, &target_start, &target_end);
-
- auto clauses = GetCompositionClauses(imm_context, target_start, target_end);
-
- int cursor = ::ImmGetCompositionString(imm_context, GCS_CURSORPOS, NULL, 0);
-
- return CompositionText{std::move(text), std::move(clauses),
- TextRange{cursor}};
-}
-
-} // namespace
-
-WinInputMethodContext::WinInputMethodContext(
- gsl::not_null<WinNativeWindow*> window)
- : native_window_(window) {
- event_guard_ += window->NativeMessageEvent()->AddHandler(
- std::bind(&WinInputMethodContext::OnWindowNativeMessage, this,
- std::placeholders::_1));
-}
-
-WinInputMethodContext::~WinInputMethodContext() {}
-
-void WinInputMethodContext::EnableIME() {
- const auto hwnd = native_window_->GetWindowHandle();
- if (::ImmAssociateContextEx(hwnd, nullptr, IACE_DEFAULT) == FALSE) {
- CRU_LOG_WARN(u"Failed to enable ime.");
- }
-}
-
-void WinInputMethodContext::DisableIME() {
- const auto hwnd = native_window_->GetWindowHandle();
- AutoHIMC himc{hwnd};
-
- ::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
-
- if (::ImmAssociateContextEx(hwnd, nullptr, 0) == FALSE) {
- CRU_LOG_WARN(u"Failed to disable ime.");
- }
-}
-
-void WinInputMethodContext::CompleteComposition() {
- auto himc = GetHIMC();
- if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) {
- CRU_LOG_WARN(u"Failed to complete composition.");
- }
-}
-
-void WinInputMethodContext::CancelComposition() {
- auto himc = GetHIMC();
- if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_CANCEL, 0)) {
- CRU_LOG_WARN(u"Failed to complete composition.");
- }
-}
-
-CompositionText WinInputMethodContext::GetCompositionText() {
- auto himc = GetHIMC();
- return GetCompositionInfo(himc.Get());
-}
-
-void WinInputMethodContext::SetCandidateWindowPosition(const Point& point) {
- auto himc = GetHIMC();
-
- ::CANDIDATEFORM form;
- form.dwIndex = 0;
- form.dwStyle = CFS_CANDIDATEPOS;
-
- form.ptCurrentPos = native_window_->DipToPixel(point);
-
- if (!::ImmSetCandidateWindow(himc.Get(), &form))
- CRU_LOG_DEBUG(
- u"Failed to set input method candidate window position.");
-}
-
-IEvent<std::nullptr_t>* WinInputMethodContext::CompositionStartEvent() {
- return &composition_start_event_;
-}
-
-IEvent<std::nullptr_t>* WinInputMethodContext::CompositionEndEvent() {
- return &composition_end_event_;
-};
-
-IEvent<std::nullptr_t>* WinInputMethodContext::CompositionEvent() {
- return &composition_event_;
-}
-
-IEvent<StringView>* WinInputMethodContext::TextEvent() { return &text_event_; }
-
-void WinInputMethodContext::OnWindowNativeMessage(
- WindowNativeMessageEventArgs& args) {
- const auto& message = args.GetWindowMessage();
- switch (message.msg) {
- case WM_CHAR: {
- auto c = static_cast<char16_t>(message.w_param);
- if (IsUtf16SurrogatePairCodeUnit(c)) {
- // I don't think this will happen because normal key strike without ime
- // should only trigger ascci character. If it is a charater from
- // supplementary planes, it should be handled with ime messages.
- CRU_LOG_WARN(
- u"A WM_CHAR message for character from supplementary "
- u"planes is ignored.");
- } else {
- if (c != '\b') { // ignore backspace
- if (c == '\r') c = '\n'; // Change \r to \n
-
- char16_t s[1] = {c};
- text_event_.Raise({s, 1});
- }
- }
- args.HandleWithResult(0);
- break;
- }
- case WM_IME_COMPOSITION: {
- composition_event_.Raise(nullptr);
- auto composition_text = GetCompositionText();
- if constexpr (DebugFlags::input_method) {
- CRU_LOG_DEBUG(u"WM_IME_COMPOSITION composition text:\n{}",
- composition_text);
- }
- if (message.l_param & GCS_RESULTSTR) {
- auto result_string = GetResultString();
- text_event_.Raise(result_string);
- }
- break;
- }
- case WM_IME_STARTCOMPOSITION: {
- if constexpr (DebugFlags::input_method) {
- CRU_LOG_DEBUG(u"WM_IME_STARTCOMPOSITION received.");
- }
- composition_start_event_.Raise(nullptr);
- break;
- }
- case WM_IME_ENDCOMPOSITION: {
- if constexpr (DebugFlags::input_method) {
- CRU_LOG_DEBUG(u"WM_IME_ENDCOMPOSITION received.");
- }
- composition_end_event_.Raise(nullptr);
- break;
- }
- }
-}
-
-String WinInputMethodContext::GetResultString() {
- auto himc = GetHIMC();
- auto result = win::GetResultString(himc.Get());
- return result;
-}
-
-AutoHIMC WinInputMethodContext::GetHIMC() {
- const auto hwnd = native_window_->GetWindowHandle();
- return AutoHIMC{hwnd};
-}
-} // namespace cru::platform::gui::win