| Flutter Windows Embedder |

window_proc_delegate_manager_unittests.cc
Go to the documentation of this file.
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/window_proc_delegate_manager.h"
6 #include "gtest/gtest.h"
7
8 namespace flutter {
9 namespace testing {
10
11 namespace {
12
13 #ifdef _WIN32
14 #define FLUTTER_NOINLINE __declspec(noinline)
15 #else
16 #define FLUTTER_NOINLINE __attribute__((noinline))
17 #endif
18
19 using TestWindowProcDelegate = std::function<std::optional<
20 LRESULT>(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)>;
21
22 // A FlutterDesktopWindowProcCallback that forwards to a std::function provided
23 // as user_data.
24 FLUTTER_NOINLINE
25 bool TestWindowProcCallback(HWND hwnd,
26 UINT message,
27 WPARAM wparam,
28 LPARAM lparam,
29 void* user_data,
30 LRESULT* result) {
31 TestWindowProcDelegate& delegate =
32 *static_cast<TestWindowProcDelegate*>(user_data);
33 auto delegate_result = delegate(hwnd, message, wparam, lparam);
34 if (delegate_result) {
35 *result = *delegate_result;
36 }
37 return delegate_result.has_value();
38 }
39
40 // Same as the above, but with a different address, to test multiple
41 // registration.
42 bool TestWindowProcCallback2(HWND hwnd,
43 UINT message,
44 WPARAM wparam,
45 LPARAM lparam,
46 void* user_data,
47 LRESULT* result) {
48 return TestWindowProcCallback(hwnd, message, wparam, lparam, user_data,
49 result);
50 }
51
52 } // namespace
53
54 TEST(WindowProcDelegateManagerTest, CallsCorrectly) {
55 WindowProcDelegateManager manager;
56 HWND dummy_hwnd;
57
58 bool called = false;
59 TestWindowProcDelegate delegate = [&called, &dummy_hwnd](
60 HWND hwnd, UINT message, WPARAM wparam,
61 LPARAM lparam) {
62 called = true;
63 EXPECT_EQ(hwnd, dummy_hwnd);
64 EXPECT_EQ(message, 2);
65 EXPECT_EQ(wparam, 3);
66 EXPECT_EQ(lparam, 4);
67 return std::optional<LRESULT>();
68 };
69 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback, &delegate);
70 auto result = manager.OnTopLevelWindowProc(dummy_hwnd, 2, 3, 4);
71
72 EXPECT_TRUE(called);
73 EXPECT_FALSE(result);
74 }
75
76 TEST(WindowProcDelegateManagerTest, ReplacementRegister) {
77 WindowProcDelegateManager manager;
78
79 bool called_a = false;
80 TestWindowProcDelegate delegate_a =
81 [&called_a](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
82 called_a = true;
83 return std::optional<LRESULT>();
84 };
85 bool called_b = false;
86 TestWindowProcDelegate delegate_b =
87 [&called_b](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
88 called_b = true;
89 return std::optional<LRESULT>();
90 };
91 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback,
92 &delegate_a);
93 // The function pointer is the same, so this should replace, not add.
94 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback,
95 &delegate_b);
96 manager.OnTopLevelWindowProc(nullptr, 0, 0, 0);
97
98 EXPECT_FALSE(called_a);
99 EXPECT_TRUE(called_b);
100 }
101
102 TEST(WindowProcDelegateManagerTest, RegisterMultiple) {
103 WindowProcDelegateManager manager;
104
105 bool called_a = false;
106 TestWindowProcDelegate delegate_a =
107 [&called_a](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
108 called_a = true;
109 return std::optional<LRESULT>();
110 };
111 bool called_b = false;
112 TestWindowProcDelegate delegate_b =
113 [&called_b](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
114 called_b = true;
115 return std::optional<LRESULT>();
116 };
117 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback,
118 &delegate_a);
119 // Function pointer is different, so both should be called.
120 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback2,
121 &delegate_b);
122 manager.OnTopLevelWindowProc(nullptr, 0, 0, 0);
123
124 EXPECT_TRUE(called_a);
125 EXPECT_TRUE(called_b);
126 }
127
128 TEST(WindowProcDelegateManagerTest, Ordered) {
129 TestWindowProcDelegate delegate_1 = [](HWND hwnd, UINT message, WPARAM wparam,
130 LPARAM lparam) { return 1; };
131 TestWindowProcDelegate delegate_2 = [](HWND hwnd, UINT message, WPARAM wparam,
132 LPARAM lparam) { return 2; };
133
134 // Result should be 1 if delegate '1' is registered before delegate '2'.
135 {
136 WindowProcDelegateManager manager;
137 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback,
138 &delegate_1);
139 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback2,
140 &delegate_2);
141
142 std::optional<LRESULT> result =
143 manager.OnTopLevelWindowProc(nullptr, 0, 0, 0);
144
145 EXPECT_EQ(result, 1);
146 }
147
148 // Result should be 2 if delegate '2' is registered before delegate '1'.
149 {
150 WindowProcDelegateManager manager;
151 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback2,
152 &delegate_2);
153 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback,
154 &delegate_1);
155
156 std::optional<LRESULT> result =
157 manager.OnTopLevelWindowProc(nullptr, 0, 0, 0);
158
159 EXPECT_EQ(result, 2);
160 }
161 }
162
163 TEST(WindowProcDelegateManagerTest, ConflictingDelegates) {
164 WindowProcDelegateManager manager;
165
166 bool called_a = false;
167 TestWindowProcDelegate delegate_a =
168 [&called_a](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
169 called_a = true;
170 return std::optional<LRESULT>(1);
171 };
172 bool called_b = false;
173 TestWindowProcDelegate delegate_b =
174 [&called_b](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
175 called_b = true;
176 return std::optional<LRESULT>(1);
177 };
178 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback,
179 &delegate_a);
180 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback2,
181 &delegate_b);
182 auto result = manager.OnTopLevelWindowProc(nullptr, 0, 0, 0);
183
184 EXPECT_TRUE(result);
185 // Exactly one of the handlers should be called since each will claim to have
186 // handled the message. Which one is unspecified, since the calling order is
187 // unspecified.
188 EXPECT_TRUE(called_a || called_b);
189 EXPECT_NE(called_a, called_b);
190 }
191
192 TEST(WindowProcDelegateManagerTest, Unregister) {
193 WindowProcDelegateManager manager;
194
195 bool called = false;
196 TestWindowProcDelegate delegate = [&called](HWND hwnd, UINT message,
197 WPARAM wparam, LPARAM lparam) {
198 called = true;
199 return std::optional<LRESULT>();
200 };
201 manager.RegisterTopLevelWindowProcDelegate(TestWindowProcCallback, &delegate);
202 manager.UnregisterTopLevelWindowProcDelegate(TestWindowProcCallback);
203 auto result = manager.OnTopLevelWindowProc(nullptr, 0, 0, 0);
204
205 EXPECT_FALSE(result);
206 EXPECT_FALSE(called);
207 }
208
209 } // namespace testing
210 } // namespace flutter
flutter::WindowProcDelegateManager
Definition: window_proc_delegate_manager.h:20
flutter::WindowProcDelegateManager::OnTopLevelWindowProc
std::optional< LRESULT > OnTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) const
Definition: window_proc_delegate_manager.cc:37
flutter::WindowProcDelegateManager::UnregisterTopLevelWindowProcDelegate
void UnregisterTopLevelWindowProcDelegate(FlutterDesktopWindowProcCallback callback)
Definition: window_proc_delegate_manager.cc:27
flutter::WindowProcDelegateManager::RegisterTopLevelWindowProcDelegate
void RegisterTopLevelWindowProcDelegate(FlutterDesktopWindowProcCallback callback, void *user_data)
Definition: window_proc_delegate_manager.cc:16
user_data
void * user_data
Definition: flutter_windows_view_unittests.cc:53
message
Win32Message message
Definition: keyboard_unittests.cc:137
flutter::testing::TEST
TEST(AccessibilityBridgeWindows, GetParent)
Definition: accessibility_bridge_windows_unittests.cc:247
flutter
Definition: accessibility_bridge_windows.cc:11
window_proc_delegate_manager.h
FLUTTER_NOINLINE
#define FLUTTER_NOINLINE
Definition: window_proc_delegate_manager_unittests.cc:16