1010
1111#include < imm.h>
1212
13+ #include < cassert>
1314#include < memory>
1415
1516namespace 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+
1751void 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