4#include "flutter/shell/platform/windows/keyboard_key_handler.h"
6#include <rapidjson/document.h>
9#include "flutter/shell/platform/common/client_wrapper/include/flutter/method_result_functions.h"
10#include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_message_codec.h"
11#include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_method_codec.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"
14#include "flutter/shell/platform/windows/keyboard_utils.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"
27static constexpr char kChannelName[] =
"flutter/keyboard";
30constexpr SHORT kStateMaskToggled = 0x01;
31constexpr SHORT kStateMaskPressed = 0x80;
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)
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_;
80 return MapVirtualKey(virtual_key,
81 extended ? MAPVK_VK_TO_VSC_EX : MAPVK_VK_TO_VSC);
84static constexpr int kHandledScanCode = 20;
85static constexpr int kHandledScanCode2 = 22;
86static constexpr int kUnhandledScanCode = 21;
89constexpr uint64_t kScanCodeControl = 0x1D;
90constexpr uint64_t kScanCodeAltLeft = 0x38;
95typedef std::function<void(
bool)>
Callback;
96typedef std::function<void(Callback&)> CallbackHandler;
97void dont_respond(Callback&
callback) {}
98void respond_true(Callback&
callback) {
101void respond_false(Callback&
callback) {
108class MockKeyHandlerDelegate
109 :
public KeyboardKeyHandler::KeyboardKeyHandlerDelegate {
111 class KeyboardHookCall {
134 MockKeyHandlerDelegate(
int delegate_id,
135 std::list<KeyboardHookCall>* hook_history)
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;
177enum KeyEventResponse {
183static KeyEventResponse key_event_response = kNoResponse;
185void OnKeyEventResult(
bool handled) {
186 key_event_response = handled ? kHandled : kUnhandled;
189void 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));
198 [&result_handler](
const uint8_t* reply,
size_t reply_size) {
199 StandardMethodCodec::GetInstance().DecodeAndProcessResponseEnvelope(
200 reply, reply_size, result_handler);
208TEST(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;
270TEST(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;
311TEST(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>(
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);
335TEST(KeyboardKeyHandlerTest, KeyboardChannelGetPressedState) {
336 TestKeystate key_state;
337 TestBinaryMessenger messenger;
340 std::unique_ptr<KeyboardKeyEmbedderHandler> embedder_handler =
341 std::make_unique<KeyboardKeyEmbedderHandler>(
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);
#define TEST(S, s, D, expected)
std::function< SHORT(int)> GetKeyStateHandler
void KeyboardHook(int key, int scancode, int action, char32_t character, bool extended, bool was_down, KeyEventCallback callback) override
void AddDelegate(std::unique_ptr< KeyboardKeyHandlerDelegate > delegate)
void InitKeyboardChannel()
std::unique_ptr< std::vector< uint8_t > > EncodeMethodCall(const MethodCall< T > &method_call) const
static const StandardMethodCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
void(* FlutterKeyEventCallback)(bool, void *)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static constexpr char kGetKeyboardStateMethod[]
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
std::list< KeyboardHookCall > * hook_history
CallbackHandler callback_handler
const GrXPFactory * Get(SkBlendMode mode)
constexpr uint64_t kScanCodeKeyA
constexpr uint64_t kVirtualKeyA
constexpr int kScanCodeShiftRight
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
std::function< void(MTLRenderPipelineDescriptor *)> Callback
#define EXPECT_TRUE(handle)