6 #include <rapidjson/document.h>
12 #include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
13 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
15 #include "flutter/shell/platform/windows/testing/engine_modifier.h"
16 #include "flutter/shell/platform/windows/testing/test_binary_messenger.h"
18 #include "flutter/fml/macros.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
27 static constexpr
char kChannelName[] =
"flutter/keyboard";
28 static constexpr
char kGetKeyboardStateMethod[] =
"getKeyboardState";
30 constexpr SHORT kStateMaskToggled = 0x01;
31 constexpr SHORT kStateMaskPressed = 0x80;
33 class TestFlutterKeyEvent :
public FlutterKeyEvent {
35 TestFlutterKeyEvent(
const FlutterKeyEvent& src,
39 struct_size = src.struct_size;
40 timestamp = src.timestamp;
42 physical = src.physical;
43 logical = src.logical;
45 synthesized = src.synthesized;
48 TestFlutterKeyEvent(TestFlutterKeyEvent&& source)
49 : FlutterKeyEvent(source),
59 const std::string character_str;
65 state_[virtual_key] = (
pressed ? kStateMaskPressed : 0) |
69 SHORT Get(
int virtual_key) {
return state_[virtual_key]; }
72 return [
this](
int virtual_key) {
return Get(virtual_key); };
76 std::map<int, SHORT> state_;
79 UINT DefaultMapVkToScan(UINT virtual_key,
bool extended) {
80 return MapVirtualKey(virtual_key,
81 extended ? MAPVK_VK_TO_VSC_EX : MAPVK_VK_TO_VSC);
84 static constexpr
int kHandledScanCode = 20;
85 static constexpr
int kHandledScanCode2 = 22;
86 static constexpr
int kUnhandledScanCode = 21;
89 constexpr uint64_t kScanCodeControl = 0x1D;
90 constexpr uint64_t kScanCodeAltLeft = 0x38;
95 typedef std::function<void(
bool)> Callback;
96 typedef std::function<void(Callback&)> CallbackHandler;
97 void dont_respond(Callback&
callback) {}
98 void respond_true(Callback&
callback) {
101 void respond_false(Callback&
callback) {
108 class MockKeyHandlerDelegate
109 :
public KeyboardKeyHandler::KeyboardKeyHandlerDelegate {
111 class KeyboardHookCall {
139 virtual ~MockKeyHandlerDelegate() =
default;
141 virtual void KeyboardHook(
int key,
147 std::function<
void(
bool)>
callback) {
160 virtual void SyncModifiersIfNeeded(
int modifiers_state) {
164 virtual std::map<uint64_t, uint64_t> GetPressedState() {
165 std::map<uint64_t, uint64_t> Empty_State;
174 FML_DISALLOW_COPY_AND_ASSIGN(MockKeyHandlerDelegate);
177 enum KeyEventResponse {
183 static KeyEventResponse key_event_response = kNoResponse;
185 void OnKeyEventResult(
bool handled) {
186 key_event_response = handled ? kHandled : kUnhandled;
189 void SimulateKeyboardMessage(TestBinaryMessenger* messenger,
190 const std::string& method_name,
191 std::unique_ptr<EncodableValue> arguments,
192 MethodResult<EncodableValue>* result_handler) {
193 MethodCall<> call(method_name, std::move(arguments));
196 EXPECT_TRUE(messenger->SimulateEngineMessage(
198 [&result_handler](
const uint8_t* reply,
size_t reply_size) {
199 StandardMethodCodec::GetInstance().DecodeAndProcessResponseEnvelope(
200 reply, reply_size, result_handler);
206 using namespace ::flutter::testing::keycodes;
208 TEST(KeyboardKeyHandlerTest, SingleDelegateWithAsyncResponds) {
209 std::list<MockKeyHandlerDelegate::KeyboardHookCall>
hook_history;
211 TestBinaryMessenger messenger([](
const std::string& channel,
212 const uint8_t*
message,
size_t message_size,
217 auto delegate = std::make_unique<MockKeyHandlerDelegate>(1, &
hook_history);
218 handler.AddDelegate(std::move(delegate));
223 handler.KeyboardHook(64, kHandledScanCode, WM_KEYDOWN, L
'a',
false,
true,
225 EXPECT_EQ(key_event_response, kNoResponse);
228 EXPECT_EQ(
hook_history.back().scancode, kHandledScanCode);
231 EXPECT_EQ(key_event_response, kNoResponse);
233 EXPECT_EQ(key_event_response, kHandled);
235 key_event_response = kNoResponse;
240 handler.KeyboardHook(64, kHandledScanCode, WM_KEYDOWN, L
'a',
false,
false,
242 EXPECT_EQ(key_event_response, kNoResponse);
245 EXPECT_EQ(
hook_history.back().scancode, kHandledScanCode);
249 handler.KeyboardHook(65, kHandledScanCode2, WM_KEYUP, L
'b',
false,
true,
251 EXPECT_EQ(key_event_response, kNoResponse);
254 EXPECT_EQ(
hook_history.back().scancode, kHandledScanCode2);
259 EXPECT_EQ(key_event_response, kUnhandled);
260 key_event_response = kNoResponse;
264 EXPECT_EQ(key_event_response, kUnhandled);
267 key_event_response = kNoResponse;
270 TEST(KeyboardKeyHandlerTest, SingleDelegateWithSyncResponds) {
271 std::list<MockKeyHandlerDelegate::KeyboardHookCall>
hook_history;
273 TestBinaryMessenger messenger([](
const std::string& channel,
274 const uint8_t*
message,
size_t message_size,
278 auto delegate = std::make_unique<MockKeyHandlerDelegate>(1, &
hook_history);
279 CallbackHandler& delegate_handler = delegate->callback_handler;
280 handler.AddDelegate(std::move(delegate));
285 delegate_handler = respond_true;
286 handler.KeyboardHook(64, kHandledScanCode, WM_KEYDOWN, L
'a',
false,
false,
288 EXPECT_EQ(key_event_response, kHandled);
291 EXPECT_EQ(
hook_history.back().scancode, kHandledScanCode);
298 delegate_handler = respond_false;
299 handler.KeyboardHook(64, kHandledScanCode, WM_KEYDOWN, L
'a',
false,
false,
301 EXPECT_EQ(key_event_response, kUnhandled);
304 EXPECT_EQ(
hook_history.back().scancode, kHandledScanCode);
308 key_event_response = kNoResponse;
311 TEST(KeyboardKeyHandlerTest, HandlerGetPressedState) {
312 TestKeystate key_state;
314 TestBinaryMessenger messenger([](
const std::string& channel,
315 const uint8_t*
message,
size_t message_size,
319 std::unique_ptr<KeyboardKeyEmbedderHandler> embedder_handler =
320 std::make_unique<KeyboardKeyEmbedderHandler>(
321 [](
const FlutterKeyEvent& event, FlutterKeyEventCallback
callback,
323 key_state.Getter(), DefaultMapVkToScan);
324 handler.AddDelegate(std::move(embedder_handler));
328 false, OnKeyEventResult);
330 std::map<uint64_t, uint64_t> pressed_state = handler.GetPressedState();
331 EXPECT_EQ(pressed_state.size(), 1);
332 EXPECT_EQ(pressed_state.at(kPhysicalKeyA), kLogicalKeyA);
335 TEST(KeyboardKeyHandlerTest, KeyboardChannelGetPressedState) {
336 TestKeystate key_state;
337 TestBinaryMessenger messenger;
340 std::unique_ptr<KeyboardKeyEmbedderHandler> embedder_handler =
341 std::make_unique<KeyboardKeyEmbedderHandler>(
342 [](
const FlutterKeyEvent& event, FlutterKeyEventCallback
callback,
344 key_state.Getter(), DefaultMapVkToScan);
350 false, OnKeyEventResult);
352 bool success =
false;
357 auto& map = std::get<EncodableMap>(*result);
358 EXPECT_EQ(map.size(), 1);
359 EncodableValue physical_value(
static_cast<long long>(kPhysicalKeyA));
360 EncodableValue logical_value(
static_cast<long long>(kLogicalKeyA));
361 EXPECT_EQ(map.at(physical_value), logical_value);
365 SimulateKeyboardMessage(&messenger, kGetKeyboardStateMethod,
nullptr,
367 EXPECT_TRUE(success);