未验证 提交 83a776c1 编写于 作者: C Chris Bracken 提交者: GitHub

Add RAII wrapper for Win32 IMM context (#24699)

Wraps Win32 IME context management in an RAII container that automates
management via ImmGetContext() and ImmReleaseContext().
上级 cd0e5434
...@@ -10,10 +10,44 @@ ...@@ -10,10 +10,44 @@
#include <imm.h> #include <imm.h>
#include <cassert>
#include <memory> #include <memory>
namespace flutter { namespace flutter {
// RAII wrapper for the Win32 Input Method Manager context.
class ImmContext {
public:
ImmContext(HWND window_handle)
: context_(::ImmGetContext(window_handle)),
window_handle_(window_handle) {
assert(window_handle);
}
~ImmContext() {
if (context_ != nullptr) {
::ImmReleaseContext(window_handle_, context_);
}
}
// Prevent copying.
ImmContext(const ImmContext& other) = delete;
ImmContext& operator=(const ImmContext& other) = delete;
// Returns true if a valid IMM context has been obtained.
bool IsValid() const { return context_ != nullptr; }
// Returns the IMM context.
HIMC get() {
assert(context_);
return context_;
}
private:
HWND window_handle_;
HIMC context_;
};
void TextInputManagerWin32::SetWindowHandle(HWND window_handle) { void TextInputManagerWin32::SetWindowHandle(HWND window_handle) {
window_handle_ = window_handle; window_handle_ = window_handle;
} }
...@@ -52,10 +86,9 @@ void TextInputManagerWin32::UpdateImeWindow() { ...@@ -52,10 +86,9 @@ void TextInputManagerWin32::UpdateImeWindow() {
return; return;
} }
HIMC imm_context = ::ImmGetContext(window_handle_); ImmContext imm_context(window_handle_);
if (imm_context) { if (imm_context.IsValid()) {
MoveImeWindow(imm_context); MoveImeWindow(imm_context.get());
::ImmReleaseContext(window_handle_, imm_context);
} }
} }
...@@ -66,11 +99,9 @@ void TextInputManagerWin32::UpdateCaretRect(const Rect& rect) { ...@@ -66,11 +99,9 @@ void TextInputManagerWin32::UpdateCaretRect(const Rect& rect) {
return; return;
} }
// TODO(cbracken): wrap these in an RAII container. ImmContext imm_context(window_handle_);
HIMC imm_context = ::ImmGetContext(window_handle_); if (imm_context.IsValid()) {
if (imm_context) { MoveImeWindow(imm_context.get());
MoveImeWindow(imm_context);
::ImmReleaseContext(window_handle_, imm_context);
} }
} }
...@@ -79,13 +110,11 @@ long TextInputManagerWin32::GetComposingCursorPosition() const { ...@@ -79,13 +110,11 @@ long TextInputManagerWin32::GetComposingCursorPosition() const {
return false; return false;
} }
HIMC imm_context = ::ImmGetContext(window_handle_); ImmContext imm_context(window_handle_);
if (imm_context) { if (imm_context.IsValid()) {
// Read the cursor position within the composing string. // Read the cursor position within the composing string.
const int pos = return ImmGetCompositionString(imm_context.get(), GCS_CURSORPOS, nullptr,
ImmGetCompositionStringW(imm_context, GCS_CURSORPOS, nullptr, 0); 0);
::ImmReleaseContext(window_handle_, imm_context);
return pos;
} }
return -1; return -1;
} }
...@@ -103,20 +132,18 @@ std::optional<std::u16string> TextInputManagerWin32::GetString(int type) const { ...@@ -103,20 +132,18 @@ std::optional<std::u16string> TextInputManagerWin32::GetString(int type) const {
if (window_handle_ == nullptr || !ime_active_) { if (window_handle_ == nullptr || !ime_active_) {
return std::nullopt; return std::nullopt;
} }
HIMC imm_context = ::ImmGetContext(window_handle_); ImmContext imm_context(window_handle_);
if (imm_context) { if (imm_context.IsValid()) {
// Read the composing string length. // Read the composing string length.
const long compose_bytes = const long compose_bytes =
::ImmGetCompositionString(imm_context, type, nullptr, 0); ::ImmGetCompositionString(imm_context.get(), type, nullptr, 0);
const long compose_length = compose_bytes / sizeof(wchar_t); const long compose_length = compose_bytes / sizeof(wchar_t);
if (compose_length <= 0) { if (compose_length <= 0) {
::ImmReleaseContext(window_handle_, imm_context);
return std::nullopt; return std::nullopt;
} }
std::u16string text(compose_length, '\0'); std::u16string text(compose_length, '\0');
::ImmGetCompositionString(imm_context, type, &text[0], compose_bytes); ::ImmGetCompositionString(imm_context.get(), type, &text[0], compose_bytes);
::ImmReleaseContext(window_handle_, imm_context);
return text; return text;
} }
return std::nullopt; return std::nullopt;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册