6#include <rapidjson/document.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;
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;
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));
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);
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);
345 handler.AddDelegate(std::move(embedder_handler));
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);
367 EXPECT_TRUE(success);
std::function< SHORT(int)> GetKeyStateHandler
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 *)
static constexpr char kGetKeyboardStateMethod[]
const gchar FlBinaryMessengerMessageHandler handler
G_BEGIN_DECLS GBytes * message
FlutterDesktopBinaryReply callback
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
std::list< KeyboardHookCall > * hook_history
CallbackHandler callback_handler
constexpr uint64_t kScanCodeKeyA
constexpr uint64_t kVirtualKeyA
TEST(NativeAssetsManagerTest, NoAvailableAssets)
constexpr int kScanCodeShiftRight
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
std::function< void(MTLRenderPipelineDescriptor *)> Callback
size_t struct_size
The size of this struct. Must be sizeof(FlutterKeyEvent).
FlutterKeyEventType type
The event kind.