Flutter Windows Embedder
cursor_handler_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.
5 
6 #include <memory>
7 #include <vector>
8 
9 #include "flutter/fml/macros.h"
14 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
15 #include "flutter/shell/platform/windows/testing/flutter_windows_engine_builder.h"
16 #include "flutter/shell/platform/windows/testing/mock_window_binding_handler.h"
17 #include "flutter/shell/platform/windows/testing/mock_windows_proc_table.h"
18 #include "flutter/shell/platform/windows/testing/test_binary_messenger.h"
19 #include "flutter/shell/platform/windows/testing/windows_test.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 
23 namespace flutter {
24 namespace testing {
25 
26 namespace {
27 using ::testing::_;
28 using ::testing::IsNull;
29 using ::testing::NotNull;
30 using ::testing::Return;
31 
32 static constexpr char kChannelName[] = "flutter/mousecursor";
33 
34 static constexpr char kActivateSystemCursorMethod[] = "activateSystemCursor";
35 static constexpr char kCreateCustomCursorMethod[] =
36  "createCustomCursor/windows";
37 static constexpr char kSetCustomCursorMethod[] = "setCustomCursor/windows";
38 static constexpr char kDeleteCustomCursorMethod[] =
39  "deleteCustomCursor/windows";
40 
41 void SimulateCursorMessage(TestBinaryMessenger* messenger,
42  const std::string& method_name,
43  std::unique_ptr<EncodableValue> arguments,
44  MethodResult<EncodableValue>* result_handler) {
45  MethodCall<> call(method_name, std::move(arguments));
46 
48 
49  EXPECT_TRUE(messenger->SimulateEngineMessage(
50  kChannelName, message->data(), message->size(),
51  [&result_handler](const uint8_t* reply, size_t reply_size) {
52  StandardMethodCodec::GetInstance().DecodeAndProcessResponseEnvelope(
53  reply, reply_size, result_handler);
54  }));
55 }
56 
57 } // namespace
58 
59 class CursorHandlerTest : public WindowsTest {
60  public:
61  CursorHandlerTest() = default;
62  virtual ~CursorHandlerTest() = default;
63 
64  protected:
65  FlutterWindowsEngine* engine() { return engine_.get(); }
66  FlutterWindowsView* view() { return view_.get(); }
67  MockWindowBindingHandler* window() { return window_; }
68  MockWindowsProcTable* proc_table() { return windows_proc_table_.get(); }
69 
71  FlutterWindowsEngineBuilder builder{GetContext()};
72 
73  engine_ = builder.Build();
74  }
75 
77  windows_proc_table_ = std::make_shared<MockWindowsProcTable>();
78 
79  FlutterWindowsEngineBuilder builder{GetContext()};
80  builder.SetWindowsProcTable(windows_proc_table_);
81 
82  auto window = std::make_unique<MockWindowBindingHandler>();
83  EXPECT_CALL(*window.get(), SetView).Times(1);
84  EXPECT_CALL(*window.get(), GetWindowHandle).WillRepeatedly(Return(nullptr));
85 
86  window_ = window.get();
87  engine_ = builder.Build();
88  view_ =
89  engine_->CreateView(std::move(window),
90  /*is_sized_to_content=*/false, BoxConstraints());
91  }
92 
93  private:
94  std::unique_ptr<FlutterWindowsEngine> engine_;
95  std::unique_ptr<FlutterWindowsView> view_;
96  MockWindowBindingHandler* window_;
97  std::shared_ptr<MockWindowsProcTable> windows_proc_table_;
98 
99  FML_DISALLOW_COPY_AND_ASSIGN(CursorHandlerTest);
100 };
101 
102 TEST_F(CursorHandlerTest, ActivateSystemCursor) {
103  UseEngineWithView();
104 
105  TestBinaryMessenger messenger;
106  CursorHandler cursor_handler(&messenger, engine());
107 
108  EXPECT_CALL(*proc_table(), LoadCursor(IsNull(), IDC_HAND)).Times(1);
109  EXPECT_CALL(*proc_table(), SetCursor).Times(1);
110 
111  bool success = false;
112  MethodResultFunctions<> result_handler(
113  [&success](const EncodableValue* result) {
114  success = true;
115  EXPECT_EQ(result, nullptr);
116  },
117  nullptr, nullptr);
118 
119  SimulateCursorMessage(&messenger, kActivateSystemCursorMethod,
120  std::make_unique<EncodableValue>(EncodableMap{
121  {EncodableValue("device"), EncodableValue(0)},
122  {EncodableValue("kind"), EncodableValue("click")},
123  }),
124  &result_handler);
125 
126  EXPECT_TRUE(success);
127 }
128 
129 TEST_F(CursorHandlerTest, CreateCustomCursor) {
130  UseEngineWithView();
131 
132  TestBinaryMessenger messenger;
133  CursorHandler cursor_handler(&messenger, engine());
134 
135  // Create a 4x4 raw BGRA test cursor buffer.
136  std::vector<uint8_t> buffer(4 * 4 * 4, 0);
137 
138  bool success = false;
139  MethodResultFunctions<> result_handler(
140  [&success](const EncodableValue* result) {
141  success = true;
142  EXPECT_EQ(std::get<std::string>(*result), "hello");
143  },
144  nullptr, nullptr);
145 
146  SimulateCursorMessage(&messenger, kCreateCustomCursorMethod,
147  std::make_unique<EncodableValue>(EncodableMap{
148  {EncodableValue("name"), EncodableValue("hello")},
149  {EncodableValue("buffer"), EncodableValue(buffer)},
150  {EncodableValue("width"), EncodableValue(4)},
151  {EncodableValue("height"), EncodableValue(4)},
152  {EncodableValue("hotX"), EncodableValue(0.0)},
153  {EncodableValue("hotY"), EncodableValue(0.0)},
154  }),
155  &result_handler);
156 
157  EXPECT_TRUE(success);
158 }
159 
160 TEST_F(CursorHandlerTest, SetCustomCursor) {
161  UseEngineWithView();
162 
163  TestBinaryMessenger messenger;
164  CursorHandler cursor_handler(&messenger, engine());
165 
166  // Create a 4x4 raw BGRA test cursor buffer.
167  std::vector<uint8_t> buffer(4 * 4 * 4, 0);
168 
169  bool success = false;
170  MethodResultFunctions<> create_result_handler(nullptr, nullptr, nullptr);
171  MethodResultFunctions<> set_result_handler(
172  [&success](const EncodableValue* result) {
173  success = true;
174  EXPECT_EQ(result, nullptr);
175  },
176  nullptr, nullptr);
177 
178  EXPECT_CALL(*proc_table(), LoadCursor).Times(0);
179  EXPECT_CALL(*proc_table(), SetCursor(NotNull())).Times(1);
180 
181  SimulateCursorMessage(&messenger, kCreateCustomCursorMethod,
182  std::make_unique<EncodableValue>(EncodableMap{
183  {EncodableValue("name"), EncodableValue("hello")},
184  {EncodableValue("buffer"), EncodableValue(buffer)},
185  {EncodableValue("width"), EncodableValue(4)},
186  {EncodableValue("height"), EncodableValue(4)},
187  {EncodableValue("hotX"), EncodableValue(0.0)},
188  {EncodableValue("hotY"), EncodableValue(0.0)},
189  }),
190  &create_result_handler);
191 
192  SimulateCursorMessage(&messenger, kSetCustomCursorMethod,
193  std::make_unique<EncodableValue>(EncodableMap{
194  {EncodableValue("name"), EncodableValue("hello")},
195  }),
196  &set_result_handler);
197 
198  EXPECT_TRUE(success);
199 }
200 
201 TEST_F(CursorHandlerTest, SetNonexistentCustomCursor) {
202  UseEngineWithView();
203 
204  TestBinaryMessenger messenger;
205  CursorHandler cursor_handler(&messenger, engine());
206 
207  bool error = false;
208  MethodResultFunctions<> result_handler(
209  nullptr,
210  [&error](const std::string& error_code, const std::string& error_message,
211  const EncodableValue* value) {
212  error = true;
213  EXPECT_EQ(
214  error_message,
215  "The custom cursor identified by the argument key cannot be found");
216  },
217  nullptr);
218 
219  EXPECT_CALL(*proc_table(), LoadCursor).Times(0);
220  EXPECT_CALL(*proc_table(), SetCursor).Times(0);
221 
222  SimulateCursorMessage(&messenger, kSetCustomCursorMethod,
223  std::make_unique<EncodableValue>(EncodableMap{
224  {EncodableValue("name"), EncodableValue("hello")},
225  }),
226  &result_handler);
227 
228  EXPECT_TRUE(error);
229 }
230 
231 TEST_F(CursorHandlerTest, DeleteCustomCursor) {
232  UseEngineWithView();
233 
234  TestBinaryMessenger messenger;
235  CursorHandler cursor_handler(&messenger, engine());
236 
237  // Create a 4x4 raw BGRA test cursor buffer.
238  std::vector<uint8_t> buffer(4 * 4 * 4, 0);
239 
240  bool success = false;
241  MethodResultFunctions<> create_result_handler(nullptr, nullptr, nullptr);
242  MethodResultFunctions<> delete_result_handler(
243  [&success](const EncodableValue* result) {
244  success = true;
245  EXPECT_EQ(result, nullptr);
246  },
247  nullptr, nullptr);
248 
249  SimulateCursorMessage(&messenger, kCreateCustomCursorMethod,
250  std::make_unique<EncodableValue>(EncodableMap{
251  {EncodableValue("name"), EncodableValue("hello")},
252  {EncodableValue("buffer"), EncodableValue(buffer)},
253  {EncodableValue("width"), EncodableValue(4)},
254  {EncodableValue("height"), EncodableValue(4)},
255  {EncodableValue("hotX"), EncodableValue(0.0)},
256  {EncodableValue("hotY"), EncodableValue(0.0)},
257  }),
258  &create_result_handler);
259 
260  SimulateCursorMessage(&messenger, kDeleteCustomCursorMethod,
261  std::make_unique<EncodableValue>(EncodableMap{
262  {EncodableValue("name"), EncodableValue("hello")},
263  }),
264  &delete_result_handler);
265 
266  EXPECT_TRUE(success);
267 }
268 
269 TEST_F(CursorHandlerTest, DeleteNonexistentCustomCursor) {
270  UseEngineWithView();
271 
272  TestBinaryMessenger messenger;
273  CursorHandler cursor_handler(&messenger, engine());
274 
275  bool success = false;
276  MethodResultFunctions<> result_handler(
277  [&success](const EncodableValue* result) {
278  success = true;
279  EXPECT_EQ(result, nullptr);
280  },
281  nullptr, nullptr);
282 
283  SimulateCursorMessage(&messenger, kDeleteCustomCursorMethod,
284  std::make_unique<EncodableValue>(EncodableMap{
285  {EncodableValue("name"), EncodableValue("fake")},
286  }),
287  &result_handler);
288 
289  EXPECT_TRUE(success);
290 }
291 
292 } // namespace testing
293 } // namespace flutter
std::unique_ptr< std::vector< uint8_t > > EncodeMethodCall(const MethodCall< T > &method_call) const
Definition: method_codec.h:48
static const StandardMethodCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
static constexpr char kDeleteCustomCursorMethod[]
static constexpr char kActivateSystemCursorMethod[]
static constexpr char kChannelName[]
static constexpr char kCreateCustomCursorMethod[]
static constexpr char kSetCustomCursorMethod[]
Win32Message message
TEST_F(AccessibilityPluginTest, DirectAnnounceCall)
std::map< EncodableValue, EncodableValue > EncodableMap