Skip to content

Commit 83a776c

Browse files
authored
Add RAII wrapper for Win32 IMM context (flutter#24699)
Wraps Win32 IME context management in an RAII container that automates management via ImmGetContext() and ImmReleaseContext().
1 parent cd0e543 commit 83a776c

File tree

1 file changed

+48
-21
lines changed

1 file changed

+48
-21
lines changed

shell/platform/windows/text_input_manager_win32.cc

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,44 @@
1010

1111
#include <imm.h>
1212

13+
#include <cassert>
1314
#include <memory>
1415

1516
namespace flutter {
1617

18+
// RAII wrapper for the Win32 Input Method Manager context.
19+
class ImmContext {
20+
public:
21+
ImmContext(HWND window_handle)
22+
: context_(::ImmGetContext(window_handle)),
23+
window_handle_(window_handle) {
24+
assert(window_handle);
25+
}
26+
27+
~ImmContext() {
28+
if (context_ != nullptr) {
29+
::ImmReleaseContext(window_handle_, context_);
30+
}
31+
}
32+
33+
// Prevent copying.
34+
ImmContext(const ImmContext& other) = delete;
35+
ImmContext& operator=(const ImmContext& other) = delete;
36+
37+
// Returns true if a valid IMM context has been obtained.
38+
bool IsValid() const { return context_ != nullptr; }
39+
40+
// Returns the IMM context.
41+
HIMC get() {
42+
assert(context_);
43+
return context_;
44+
}
45+
46+
private:
47+
HWND window_handle_;
48+
HIMC context_;
49+
};
50+
1751
void TextInputManagerWin32::SetWindowHandle(HWND window_handle) {
1852
window_handle_ = window_handle;
1953
}
@@ -52,10 +86,9 @@ void TextInputManagerWin32::UpdateImeWindow() {
5286
return;
5387
}
5488

55-
HIMC imm_context = ::ImmGetContext(window_handle_);
56-
if (imm_context) {
57-
MoveImeWindow(imm_context);
58-
::ImmReleaseContext(window_handle_, imm_context);
89+
ImmContext imm_context(window_handle_);
90+
if (imm_context.IsValid()) {
91+
MoveImeWindow(imm_context.get());
5992
}
6093
}
6194

@@ -66,11 +99,9 @@ void TextInputManagerWin32::UpdateCaretRect(const Rect& rect) {
6699
return;
67100
}
68101

69-
// TODO(cbracken): wrap these in an RAII container.
70-
HIMC imm_context = ::ImmGetContext(window_handle_);
71-
if (imm_context) {
72-
MoveImeWindow(imm_context);
73-
::ImmReleaseContext(window_handle_, imm_context);
102+
ImmContext imm_context(window_handle_);
103+
if (imm_context.IsValid()) {
104+
MoveImeWindow(imm_context.get());
74105
}
75106
}
76107

@@ -79,13 +110,11 @@ long TextInputManagerWin32::GetComposingCursorPosition() const {
79110
return false;
80111
}
81112

82-
HIMC imm_context = ::ImmGetContext(window_handle_);
83-
if (imm_context) {
113+
ImmContext imm_context(window_handle_);
114+
if (imm_context.IsValid()) {
84115
// Read the cursor position within the composing string.
85-
const int pos =
86-
ImmGetCompositionStringW(imm_context, GCS_CURSORPOS, nullptr, 0);
87-
::ImmReleaseContext(window_handle_, imm_context);
88-
return pos;
116+
return ImmGetCompositionString(imm_context.get(), GCS_CURSORPOS, nullptr,
117+
0);
89118
}
90119
return -1;
91120
}
@@ -103,20 +132,18 @@ std::optional<std::u16string> TextInputManagerWin32::GetString(int type) const {
103132
if (window_handle_ == nullptr || !ime_active_) {
104133
return std::nullopt;
105134
}
106-
HIMC imm_context = ::ImmGetContext(window_handle_);
107-
if (imm_context) {
135+
ImmContext imm_context(window_handle_);
136+
if (imm_context.IsValid()) {
108137
// Read the composing string length.
109138
const long compose_bytes =
110-
::ImmGetCompositionString(imm_context, type, nullptr, 0);
139+
::ImmGetCompositionString(imm_context.get(), type, nullptr, 0);
111140
const long compose_length = compose_bytes / sizeof(wchar_t);
112141
if (compose_length <= 0) {
113-
::ImmReleaseContext(window_handle_, imm_context);
114142
return std::nullopt;
115143
}
116144

117145
std::u16string text(compose_length, '\0');
118-
::ImmGetCompositionString(imm_context, type, &text[0], compose_bytes);
119-
::ImmReleaseContext(window_handle_, imm_context);
146+
::ImmGetCompositionString(imm_context.get(), type, &text[0], compose_bytes);
120147
return text;
121148
}
122149
return std::nullopt;

0 commit comments

Comments
 (0)