Skip to content

Commit 140bd93

Browse files
authored
Check for both compose string and result string. (flutter#29620)
It turns out that unlike the Microsoft IME, Sogou sends a single IME_COMPOSITION message that has both the GCS_COMPSTR and GCS_RESULTSTR flags set, and we check for a composition string before result string, with an "else" clause to check for the result string, so if GCS_COMPSTR is set, we never check for a result string.
1 parent ea8386f commit 140bd93

File tree

9 files changed

+197
-36
lines changed

9 files changed

+197
-36
lines changed

shell/platform/windows/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ executable("flutter_windows_unittests") {
253253
"platform_handler_unittests.cc",
254254
"testing/flutter_window_win32_test.cc",
255255
"testing/flutter_window_win32_test.h",
256+
"testing/mock_text_input_manager_win32.cc",
257+
"testing/mock_text_input_manager_win32.h",
256258
"testing/mock_window_binding_handler.cc",
257259
"testing/mock_window_binding_handler.h",
258260
"testing/mock_window_win32.cc",
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/shell/platform/windows/testing/mock_text_input_manager_win32.h"
6+
7+
namespace flutter {
8+
namespace testing {
9+
10+
MockTextInputManagerWin32::MockTextInputManagerWin32()
11+
: TextInputManagerWin32(){};
12+
13+
MockTextInputManagerWin32::~MockTextInputManagerWin32() = default;
14+
15+
} // namespace testing
16+
} // namespace flutter
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_TEXT_INPUT_MANAGER_WIN32_H_
6+
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_TEXT_INPUT_MANAGER_WIN32_H_
7+
8+
#include <windowsx.h>
9+
#include <cstring>
10+
#include <optional>
11+
12+
#include "flutter/shell/platform/windows/text_input_manager_win32.h"
13+
#include "gmock/gmock.h"
14+
15+
namespace flutter {
16+
namespace testing {
17+
18+
/// Mock for the |WindowWin32| base class.
19+
class MockTextInputManagerWin32 : public TextInputManagerWin32 {
20+
public:
21+
MockTextInputManagerWin32();
22+
virtual ~MockTextInputManagerWin32();
23+
24+
// Prevent copying.
25+
MockTextInputManagerWin32(MockTextInputManagerWin32 const&) = delete;
26+
MockTextInputManagerWin32& operator=(MockTextInputManagerWin32 const&) =
27+
delete;
28+
29+
MOCK_CONST_METHOD0(GetComposingString, std::optional<std::u16string>());
30+
MOCK_CONST_METHOD0(GetResultString, std::optional<std::u16string>());
31+
MOCK_CONST_METHOD0(GetComposingCursorPosition, long());
32+
};
33+
34+
} // namespace testing
35+
} // namespace flutter
36+
37+
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_TEXT_INPUT_MANAGER_WIN32_H_

shell/platform/windows/testing/mock_window_win32.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
namespace flutter {
88
namespace testing {
9-
109
MockWin32Window::MockWin32Window() : WindowWin32(){};
10+
MockWin32Window::MockWin32Window(
11+
std::unique_ptr<TextInputManagerWin32> text_input_manager)
12+
: WindowWin32(std::move(text_input_manager)){};
1113

1214
MockWin32Window::~MockWin32Window() = default;
1315

@@ -35,5 +37,11 @@ LRESULT MockWin32Window::Win32SendMessage(HWND hWnd,
3537
return HandleMessage(message, wparam, lparam);
3638
}
3739

40+
void MockWin32Window::CallOnImeComposition(UINT const message,
41+
WPARAM const wparam,
42+
LPARAM const lparam) {
43+
WindowWin32::OnImeComposition(message, wparam, lparam);
44+
}
45+
3846
} // namespace testing
3947
} // namespace flutter

shell/platform/windows/testing/mock_window_win32.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace testing {
1818
class MockWin32Window : public WindowWin32, public MockMessageQueue {
1919
public:
2020
MockWin32Window();
21+
MockWin32Window(std::unique_ptr<TextInputManagerWin32> text_input_manager);
2122
virtual ~MockWin32Window();
2223

2324
// Prevent copying.
@@ -51,6 +52,11 @@ class MockWin32Window : public WindowWin32, public MockMessageQueue {
5152
MOCK_METHOD0(OnComposeCommit, void());
5253
MOCK_METHOD0(OnComposeEnd, void());
5354
MOCK_METHOD2(OnComposeChange, void(const std::u16string&, int));
55+
MOCK_METHOD3(OnImeComposition, void(UINT const, WPARAM const, LPARAM const));
56+
57+
void CallOnImeComposition(UINT const message,
58+
WPARAM const wparam,
59+
LPARAM const lparam);
5460

5561
protected:
5662
LRESULT Win32DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

shell/platform/windows/text_input_manager_win32.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace flutter {
2828
class TextInputManagerWin32 {
2929
public:
3030
TextInputManagerWin32() noexcept = default;
31-
~TextInputManagerWin32() = default;
31+
virtual ~TextInputManagerWin32() = default;
3232

3333
TextInputManagerWin32(const TextInputManagerWin32&) = delete;
3434
TextInputManagerWin32& operator=(const TextInputManagerWin32&) = delete;
@@ -60,22 +60,22 @@ class TextInputManagerWin32 {
6060
void UpdateCaretRect(const Rect& rect);
6161

6262
// Returns the cursor position relative to the start of the composing range.
63-
long GetComposingCursorPosition() const;
63+
virtual long GetComposingCursorPosition() const;
6464

6565
// Returns the contents of the composing string.
6666
//
6767
// This may be called in response to WM_IME_COMPOSITION events where the
6868
// GCS_COMPSTR flag is set in the lparam. In some IMEs, this string may also
6969
// be set in events where the GCS_RESULTSTR flag is set. This contains the
7070
// in-progress composing string.
71-
std::optional<std::u16string> GetComposingString() const;
71+
virtual std::optional<std::u16string> GetComposingString() const;
7272

7373
// Returns the contents of the result string.
7474
//
7575
// This may be called in response to WM_IME_COMPOSITION events where the
7676
// GCS_RESULTSTR flag is set in the lparam. This contains the final string to
7777
// be committed in the composing region when composition is ended.
78-
std::optional<std::u16string> GetResultString() const;
78+
virtual std::optional<std::u16string> GetResultString() const;
7979

8080
/// Aborts IME composing.
8181
///

shell/platform/windows/window_win32.cc

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,19 @@ static const int kMaxTouchDeviceId = 128;
4444

4545
} // namespace
4646

47-
WindowWin32::WindowWin32()
48-
: touch_id_generator_(kMinTouchDeviceId, kMaxTouchDeviceId) {
47+
WindowWin32::WindowWin32() : WindowWin32(nullptr) {}
48+
49+
WindowWin32::WindowWin32(
50+
std::unique_ptr<TextInputManagerWin32> text_input_manager)
51+
: touch_id_generator_(kMinTouchDeviceId, kMaxTouchDeviceId),
52+
text_input_manager_(std::move(text_input_manager)) {
4953
// Get the DPI of the primary monitor as the initial DPI. If Per-Monitor V2 is
5054
// supported, |current_dpi_| should be updated in the
5155
// kWmDpiChangedBeforeParent message.
5256
current_dpi_ = GetDpiForHWND(nullptr);
57+
if (text_input_manager_ == nullptr) {
58+
text_input_manager_ = std::make_unique<TextInputManagerWin32>();
59+
}
5360
}
5461

5562
WindowWin32::~WindowWin32() {
@@ -119,7 +126,7 @@ LRESULT CALLBACK WindowWin32::WndProc(HWND const window,
119126

120127
auto that = static_cast<WindowWin32*>(cs->lpCreateParams);
121128
that->window_handle_ = window;
122-
that->text_input_manager_.SetWindowHandle(window);
129+
that->text_input_manager_->SetWindowHandle(window);
123130
RegisterTouchWindow(window, 0);
124131
} else if (WindowWin32* that = GetThisFromHandle(window)) {
125132
return that->HandleMessage(message, wparam, lparam);
@@ -170,36 +177,37 @@ void WindowWin32::OnImeSetContext(UINT const message,
170177
WPARAM const wparam,
171178
LPARAM const lparam) {
172179
if (wparam != 0) {
173-
text_input_manager_.CreateImeWindow();
180+
text_input_manager_->CreateImeWindow();
174181
}
175182
}
176183

177184
void WindowWin32::OnImeStartComposition(UINT const message,
178185
WPARAM const wparam,
179186
LPARAM const lparam) {
180-
text_input_manager_.CreateImeWindow();
187+
text_input_manager_->CreateImeWindow();
181188
OnComposeBegin();
182189
}
183190

184191
void WindowWin32::OnImeComposition(UINT const message,
185192
WPARAM const wparam,
186193
LPARAM const lparam) {
187194
// Update the IME window position.
188-
text_input_manager_.UpdateImeWindow();
195+
text_input_manager_->UpdateImeWindow();
189196

190197
if (lparam & GCS_COMPSTR) {
191198
// Read the in-progress composing string.
192-
long pos = text_input_manager_.GetComposingCursorPosition();
199+
long pos = text_input_manager_->GetComposingCursorPosition();
193200
std::optional<std::u16string> text =
194-
text_input_manager_.GetComposingString();
201+
text_input_manager_->GetComposingString();
195202
if (text) {
196203
OnComposeChange(text.value(), pos);
197204
}
198-
} else if (lparam & GCS_RESULTSTR) {
205+
}
206+
if (lparam & GCS_RESULTSTR) {
199207
// Commit but don't end composing.
200208
// Read the committed composing string.
201-
long pos = text_input_manager_.GetComposingCursorPosition();
202-
std::optional<std::u16string> text = text_input_manager_.GetResultString();
209+
long pos = text_input_manager_->GetComposingCursorPosition();
210+
std::optional<std::u16string> text = text_input_manager_->GetResultString();
203211
if (text) {
204212
OnComposeChange(text.value(), pos);
205213
OnComposeCommit();
@@ -210,7 +218,7 @@ void WindowWin32::OnImeComposition(UINT const message,
210218
void WindowWin32::OnImeEndComposition(UINT const message,
211219
WPARAM const wparam,
212220
LPARAM const lparam) {
213-
text_input_manager_.DestroyImeWindow();
221+
text_input_manager_->DestroyImeWindow();
214222
OnComposeEnd();
215223
}
216224

@@ -223,11 +231,11 @@ void WindowWin32::OnImeRequest(UINT const message,
223231
}
224232

225233
void WindowWin32::AbortImeComposing() {
226-
text_input_manager_.AbortComposing();
234+
text_input_manager_->AbortComposing();
227235
}
228236

229237
void WindowWin32::UpdateCursorRect(const Rect& rect) {
230-
text_input_manager_.UpdateCaretRect(rect);
238+
text_input_manager_->UpdateCaretRect(rect);
231239
}
232240

233241
static uint16_t ResolveKeyCode(uint16_t original,
@@ -588,7 +596,7 @@ HWND WindowWin32::GetWindowHandle() {
588596

589597
void WindowWin32::Destroy() {
590598
if (window_handle_) {
591-
text_input_manager_.SetWindowHandle(nullptr);
599+
text_input_manager_->SetWindowHandle(nullptr);
592600
DestroyWindow(window_handle_);
593601
window_handle_ = nullptr;
594602
}

shell/platform/windows/window_win32.h

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace flutter {
2525
class WindowWin32 {
2626
public:
2727
WindowWin32();
28+
WindowWin32(std::unique_ptr<TextInputManagerWin32> text_input_manager);
2829
virtual ~WindowWin32();
2930

3031
// Initializes as a child window with size using |width| and |height| and
@@ -143,31 +144,31 @@ class WindowWin32 {
143144

144145
// Called when a window is activated in order to configure IME support for
145146
// multi-step text input.
146-
void OnImeSetContext(UINT const message,
147-
WPARAM const wparam,
148-
LPARAM const lparam);
147+
virtual void OnImeSetContext(UINT const message,
148+
WPARAM const wparam,
149+
LPARAM const lparam);
149150

150151
// Called when multi-step text input begins when using an IME.
151-
void OnImeStartComposition(UINT const message,
152-
WPARAM const wparam,
153-
LPARAM const lparam);
152+
virtual void OnImeStartComposition(UINT const message,
153+
WPARAM const wparam,
154+
LPARAM const lparam);
154155

155156
// Called when edits/commit of multi-step text input occurs when using an IME.
156-
void OnImeComposition(UINT const message,
157-
WPARAM const wparam,
158-
LPARAM const lparam);
157+
virtual void OnImeComposition(UINT const message,
158+
WPARAM const wparam,
159+
LPARAM const lparam);
159160

160161
// Called when multi-step text input ends when using an IME.
161-
void OnImeEndComposition(UINT const message,
162-
WPARAM const wparam,
163-
LPARAM const lparam);
162+
virtual void OnImeEndComposition(UINT const message,
163+
WPARAM const wparam,
164+
LPARAM const lparam);
164165

165166
// Called when the user triggers an IME-specific request such as input
166167
// reconversion, where an existing input sequence is returned to composing
167168
// mode to select an alternative candidate conversion.
168-
void OnImeRequest(UINT const message,
169-
WPARAM const wparam,
170-
LPARAM const lparam);
169+
virtual void OnImeRequest(UINT const message,
170+
WPARAM const wparam,
171+
LPARAM const lparam);
171172

172173
// Called when the app ends IME composing, such as when the text input client
173174
// is cleared or changed.
@@ -264,7 +265,7 @@ class WindowWin32 {
264265
std::map<uint16_t, std::u16string> text_for_scancode_on_redispatch_;
265266

266267
// Manages IME state.
267-
TextInputManagerWin32 text_input_manager_;
268+
std::unique_ptr<TextInputManagerWin32> text_input_manager_;
268269

269270
// Used for temporarily storing the WM_TOUCH-provided touch points.
270271
std::vector<TOUCHINPUT> touch_points_;

0 commit comments

Comments
 (0)