5 #include "flutter/fml/macros.h"
7 #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
8 #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
9 #include "flutter/shell/platform/windows/testing/mock_window_binding_handler_delegate.h"
10 #include "flutter/shell/platform/windows/testing/windows_test.h"
11 #include "flutter/shell/platform/windows/testing/wm_builders.h"
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
20 using ::testing::AnyNumber;
22 using ::testing::Invoke;
23 using ::testing::Return;
26 static constexpr int32_t kDefaultPointerDeviceId = 0;
28 class MockFlutterWindow :
public FlutterWindow {
30 MockFlutterWindow(
bool reset_view_on_exit =
true)
31 : reset_view_on_exit_(reset_view_on_exit) {
32 ON_CALL(*
this, GetDpiScale())
35 virtual ~MockFlutterWindow() {
36 if (reset_view_on_exit_) {
42 UINT GetDpi() {
return GetCurrentDPI(); }
45 LRESULT InjectWindowMessage(UINT
const message,
47 LPARAM
const lparam) {
48 return HandleMessage(
message, wparam, lparam);
51 MOCK_METHOD(
void, OnDpiScale, (
unsigned int), (
override));
52 MOCK_METHOD(
void, OnResize, (
unsigned int,
unsigned int), (
override));
55 (
double,
double, FlutterPointerDeviceKind, int32_t,
int),
59 (
double,
double, FlutterPointerDeviceKind, int32_t, UINT),
63 (
double,
double, FlutterPointerDeviceKind, int32_t, UINT),
67 (
double,
double, FlutterPointerDeviceKind, int32_t),
69 MOCK_METHOD(
float, GetScrollOffsetMultiplier, (), (
override));
70 MOCK_METHOD(
float, GetDpiScale, (), (
override));
71 MOCK_METHOD(
void, UpdateCursorRect, (
const Rect&), (
override));
72 MOCK_METHOD(
void, OnResetImeComposing, (), (
override));
73 MOCK_METHOD(UINT, Win32DispatchMessage, (UINT, WPARAM, LPARAM), (
override));
74 MOCK_METHOD(BOOL, Win32PeekMessage, (LPMSG, UINT, UINT, UINT), (
override));
75 MOCK_METHOD(uint32_t, Win32MapVkToChar, (uint32_t), (
override));
76 MOCK_METHOD(HWND, GetWindowHandle, (), (
override));
77 MOCK_METHOD(ui::AXFragmentRootDelegateWin*,
78 GetAxFragmentRootDelegate,
85 LRESULT Win32DefWindowProc(HWND hWnd,
88 LPARAM lParam)
override {
89 return kWmResultDefault;
93 bool reset_view_on_exit_;
94 FML_DISALLOW_COPY_AND_ASSIGN(MockFlutterWindow);
97 class MockFlutterWindowsView :
public FlutterWindowsView {
100 std::unique_ptr<WindowBindingHandler> window_binding)
103 std::move(window_binding),
109 NotifyWinEventWrapper,
110 (ui::AXPlatformNodeWin*, ax::mojom::Event),
114 FML_DISALLOW_COPY_AND_ASSIGN(MockFlutterWindowsView);
117 class FlutterWindowTest :
public WindowsTest {};
121 TEST_F(FlutterWindowTest, CreateDestroy) {
122 std::unique_ptr<FlutterWindowsEngine> engine =
123 FlutterWindowsEngineBuilder{GetContext()}.Build();
128 TEST_F(FlutterWindowTest, OnBitmapSurfaceUpdated) {
129 std::unique_ptr<FlutterWindowsEngine> engine =
130 FlutterWindowsEngineBuilder{GetContext()}.Build();
131 FlutterWindow win32window(100, 100, engine->display_manager());
132 int old_handle_count = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
134 constexpr
size_t row_bytes = 100 * 4;
135 constexpr
size_t height = 100;
136 std::array<char, row_bytes * height> allocation;
139 int new_handle_count = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
141 EXPECT_EQ(old_handle_count, new_handle_count);
147 TEST_F(FlutterWindowTest, OnCursorRectUpdatedRegularDPI) {
148 MockFlutterWindow win32window;
149 EXPECT_CALL(win32window, GetDpiScale()).WillOnce(Return(1.0));
151 Rect cursor_rect(Point(10, 20), Size(30, 40));
152 EXPECT_CALL(win32window, UpdateCursorRect(cursor_rect)).Times(1);
154 win32window.OnCursorRectUpdated(cursor_rect);
160 TEST_F(FlutterWindowTest, OnCursorRectUpdatedHighDPI) {
161 MockFlutterWindow win32window;
162 EXPECT_CALL(win32window, GetDpiScale()).WillOnce(Return(1.5));
164 Rect expected_cursor_rect(Point(15, 30), Size(45, 60));
165 EXPECT_CALL(win32window, UpdateCursorRect(expected_cursor_rect)).Times(1);
167 Rect cursor_rect(Point(10, 20), Size(30, 40));
168 win32window.OnCursorRectUpdated(cursor_rect);
171 TEST_F(FlutterWindowTest, OnPointerStarSendsDeviceType) {
172 std::unique_ptr<FlutterWindowsEngine> engine =
173 FlutterWindowsEngineBuilder{GetContext()}.Build();
174 FlutterWindow win32window(100, 100, engine->display_manager());
175 MockWindowBindingHandlerDelegate delegate;
176 EXPECT_CALL(delegate, OnWindowStateEvent).Times(AnyNumber());
177 win32window.
SetView(&delegate);
180 EXPECT_CALL(delegate,
181 OnPointerMove(10.0, 10.0, kFlutterPointerDeviceKindMouse,
182 kDefaultPointerDeviceId, 0))
184 EXPECT_CALL(delegate,
185 OnPointerMove(10.0, 10.0, kFlutterPointerDeviceKindTouch,
186 kDefaultPointerDeviceId, 0))
188 EXPECT_CALL(delegate,
189 OnPointerMove(10.0, 10.0, kFlutterPointerDeviceKindStylus,
190 kDefaultPointerDeviceId, 0))
196 OnPointerDown(10.0, 10.0, kFlutterPointerDeviceKindMouse,
197 kDefaultPointerDeviceId, kFlutterPointerButtonMousePrimary))
201 OnPointerDown(10.0, 10.0, kFlutterPointerDeviceKindTouch,
202 kDefaultPointerDeviceId, kFlutterPointerButtonMousePrimary))
206 OnPointerDown(10.0, 10.0, kFlutterPointerDeviceKindStylus,
207 kDefaultPointerDeviceId, kFlutterPointerButtonMousePrimary))
211 EXPECT_CALL(delegate, OnPointerUp(10.0, 10.0, kFlutterPointerDeviceKindMouse,
212 kDefaultPointerDeviceId,
213 kFlutterPointerButtonMousePrimary))
215 EXPECT_CALL(delegate, OnPointerUp(10.0, 10.0, kFlutterPointerDeviceKindTouch,
216 kDefaultPointerDeviceId,
217 kFlutterPointerButtonMousePrimary))
219 EXPECT_CALL(delegate, OnPointerUp(10.0, 10.0, kFlutterPointerDeviceKindStylus,
220 kDefaultPointerDeviceId,
221 kFlutterPointerButtonMousePrimary))
225 EXPECT_CALL(delegate,
226 OnPointerLeave(10.0, 10.0, kFlutterPointerDeviceKindMouse,
227 kDefaultPointerDeviceId))
229 EXPECT_CALL(delegate,
230 OnPointerLeave(10.0, 10.0, kFlutterPointerDeviceKindTouch,
231 kDefaultPointerDeviceId))
233 EXPECT_CALL(delegate,
234 OnPointerLeave(10.0, 10.0, kFlutterPointerDeviceKindStylus,
235 kDefaultPointerDeviceId))
238 win32window.
OnPointerMove(10.0, 10.0, kFlutterPointerDeviceKindMouse,
239 kDefaultPointerDeviceId, 0);
240 win32window.
OnPointerDown(10.0, 10.0, kFlutterPointerDeviceKindMouse,
241 kDefaultPointerDeviceId, WM_LBUTTONDOWN);
242 win32window.
OnPointerUp(10.0, 10.0, kFlutterPointerDeviceKindMouse,
243 kDefaultPointerDeviceId, WM_LBUTTONDOWN);
244 win32window.
OnPointerLeave(10.0, 10.0, kFlutterPointerDeviceKindMouse,
245 kDefaultPointerDeviceId);
248 win32window.
OnPointerMove(10.0, 10.0, kFlutterPointerDeviceKindTouch,
249 kDefaultPointerDeviceId, 0);
250 win32window.
OnPointerDown(10.0, 10.0, kFlutterPointerDeviceKindTouch,
251 kDefaultPointerDeviceId, WM_LBUTTONDOWN);
252 win32window.
OnPointerUp(10.0, 10.0, kFlutterPointerDeviceKindTouch,
253 kDefaultPointerDeviceId, WM_LBUTTONDOWN);
254 win32window.
OnPointerLeave(10.0, 10.0, kFlutterPointerDeviceKindTouch,
255 kDefaultPointerDeviceId);
258 win32window.
OnPointerMove(10.0, 10.0, kFlutterPointerDeviceKindStylus,
259 kDefaultPointerDeviceId, 0);
260 win32window.
OnPointerDown(10.0, 10.0, kFlutterPointerDeviceKindStylus,
261 kDefaultPointerDeviceId, WM_LBUTTONDOWN);
262 win32window.
OnPointerUp(10.0, 10.0, kFlutterPointerDeviceKindStylus,
263 kDefaultPointerDeviceId, WM_LBUTTONDOWN);
264 win32window.
OnPointerLeave(10.0, 10.0, kFlutterPointerDeviceKindStylus,
265 kDefaultPointerDeviceId);
274 TEST_F(FlutterWindowTest, OnScrollCallsGetScrollOffsetMultiplier) {
275 MockFlutterWindow win32window;
276 MockWindowBindingHandlerDelegate delegate;
277 EXPECT_CALL(win32window, OnWindowStateEvent).Times(AnyNumber());
278 win32window.SetView(&delegate);
280 EXPECT_CALL(win32window, GetWindowHandle).WillOnce([&win32window]() {
281 return win32window.FlutterWindow::GetWindowHandle();
283 EXPECT_CALL(win32window, GetScrollOffsetMultiplier).WillOnce(Return(120.0f));
285 EXPECT_CALL(delegate,
286 OnScroll(_, _, 0, 0, 120.0f, kFlutterPointerDeviceKindMouse,
287 kDefaultPointerDeviceId))
290 win32window.OnScroll(0.0f, 0.0f, kFlutterPointerDeviceKindMouse,
291 kDefaultPointerDeviceId);
294 TEST_F(FlutterWindowTest, OnWindowRepaint) {
295 MockFlutterWindow win32window;
296 MockWindowBindingHandlerDelegate delegate;
297 EXPECT_CALL(win32window, OnWindowStateEvent).Times(AnyNumber());
298 win32window.SetView(&delegate);
300 EXPECT_CALL(delegate, OnWindowRepaint()).Times(1);
302 win32window.InjectWindowMessage(WM_PAINT, 0, 0);
305 TEST_F(FlutterWindowTest, OnThemeChange) {
306 MockFlutterWindow win32window;
307 MockWindowBindingHandlerDelegate delegate;
308 EXPECT_CALL(win32window, OnWindowStateEvent).Times(AnyNumber());
309 win32window.SetView(&delegate);
311 EXPECT_CALL(delegate, OnHighContrastChanged).Times(1);
313 win32window.InjectWindowMessage(WM_THEMECHANGED, 0, 0);
319 TEST_F(FlutterWindowTest, AccessibilityNodeWithoutView) {
320 MockFlutterWindow win32window;
322 EXPECT_EQ(win32window.GetNativeViewAccessible(),
nullptr);
328 std::unique_ptr<FlutterWindowsEngine> engine =
329 FlutterWindowsEngineBuilder{GetContext()}.Build();
330 auto win32window = std::make_unique<MockFlutterWindow>();
331 EXPECT_CALL(*win32window.get(), GetAxFragmentRootDelegate())
332 .WillRepeatedly(Return(
nullptr));
333 EXPECT_CALL(*win32window.get(), OnWindowStateEvent).Times(AnyNumber());
334 EXPECT_CALL(*win32window.get(), GetWindowHandle).Times(AnyNumber());
335 MockFlutterWindowsView view{engine.get(), std::move(win32window)};
336 std::wstring
message = L
"Test alert";
337 EXPECT_CALL(view, NotifyWinEventWrapper(_, ax::mojom::Event::kAlert))
341 IAccessible* alert = view.AlertNode();
342 VARIANT
self{.vt = VT_I4, .lVal = CHILDID_SELF};
344 alert->get_accName(
self, &strptr);
347 alert->get_accDescription(
self, &strptr);
350 alert->get_accValue(
self, &strptr);
354 alert->get_accRole(
self, &role);
355 EXPECT_EQ(role.vt, VT_I4);
356 EXPECT_EQ(role.lVal, ROLE_SYSTEM_ALERT);
359 TEST_F(FlutterWindowTest, LifecycleFocusMessages) {
360 MockFlutterWindow win32window;
361 EXPECT_CALL(win32window, GetWindowHandle)
362 .WillRepeatedly(Return(
reinterpret_cast<HWND
>(1)));
363 MockWindowBindingHandlerDelegate delegate;
366 EXPECT_CALL(delegate, OnWindowStateEvent)
370 EXPECT_CALL(win32window, OnWindowStateEvent)
372 win32window.FlutterWindow::OnWindowStateEvent(event);
374 EXPECT_CALL(win32window, OnResize).Times(AnyNumber());
376 win32window.SetView(&delegate);
378 win32window.InjectWindowMessage(WM_SIZE, 0, 0);
381 win32window.InjectWindowMessage(WM_SIZE, 0, MAKEWORD(1, 1));
384 EXPECT_CALL(delegate, OnFocus(Eq(FlutterViewFocusState::kFocused),
385 Eq(FlutterViewFocusDirection::kUndefined)))
387 win32window.InjectWindowMessage(WM_SETFOCUS, 0, 0);
390 EXPECT_CALL(delegate, OnFocus(Eq(FlutterViewFocusState::kUnfocused),
391 Eq(FlutterViewFocusDirection::kUndefined)))
393 win32window.InjectWindowMessage(WM_KILLFOCUS, 0, 0);
397 TEST_F(FlutterWindowTest, CachedLifecycleMessage) {
398 MockFlutterWindow win32window;
399 EXPECT_CALL(win32window, GetWindowHandle)
400 .WillRepeatedly(Return(
reinterpret_cast<HWND
>(1)));
401 EXPECT_CALL(win32window, OnWindowStateEvent)
403 win32window.FlutterWindow::OnWindowStateEvent(event);
405 EXPECT_CALL(win32window, OnResize).Times(1);
408 win32window.InjectWindowMessage(WM_SIZE, 0, MAKEWORD(1, 1));
411 win32window.InjectWindowMessage(WM_SETFOCUS, 0, 0);
413 MockWindowBindingHandlerDelegate delegate;
414 bool focused =
false;
415 bool restored =
false;
416 EXPECT_CALL(delegate, OnWindowStateEvent)
425 EXPECT_CALL(delegate, OnFocus(Eq(FlutterViewFocusState::kFocused),
426 Eq(FlutterViewFocusDirection::kUndefined)))
428 win32window.SetView(&delegate);
429 EXPECT_TRUE(focused);
430 EXPECT_TRUE(restored);
virtual void OnPointerLeave(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id)
virtual bool OnBitmapSurfaceUpdated(const void *allocation, size_t row_bytes, size_t height) override
virtual void OnPointerUp(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, UINT button)
virtual void OnPointerDown(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, UINT button)
virtual void OnPointerMove(double x, double y, FlutterPointerDeviceKind device_kind, int32_t device_id, int modifiers_state)
virtual void SetView(WindowBindingHandlerDelegate *view) override
virtual float GetDpiScale() override
FlutterWindowsView(FlutterViewId view_id, FlutterWindowsEngine *engine, std::unique_ptr< WindowBindingHandler > window_binding, bool is_sized_to_content, const BoxConstraints &box_constraints, FlutterWindowsViewSizingDelegate *sizing_delegate=nullptr, std::shared_ptr< WindowsProcTable > windows_proc_table=nullptr)
MOCK_METHOD(void, NotifyWinEventWrapper,(ui::AXPlatformNodeWin *, ax::mojom::Event),(override))
MockFlutterWindowsView(FlutterWindowsEngine *engine, std::unique_ptr< WindowBindingHandler > wbh)
TEST_F(AccessibilityPluginTest, DirectAnnounceCall)
WindowStateEvent
An event representing a change in window state that may update the.
constexpr FlutterViewId kImplicitViewId