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;
108class MockKeyHandlerDelegate
109 :
public KeyboardKeyHandler::KeyboardKeyHandlerDelegate {
111 class KeyboardHookCall {
139 virtual ~MockKeyHandlerDelegate() =
default;
141 virtual void KeyboardHook(
int key,
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);
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);
361 EXPECT_EQ(
map.at(physical_value), logical_value);
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 *)
static constexpr char kGetKeyboardStateMethod[]
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Dart_NativeFunction function
FlutterKeyEventCallback callback
std::list< KeyboardHookCall > * hook_history
CallbackHandler callback_handler
const GrXPFactory * Get(SkBlendMode mode)
constexpr uint64_t kPhysicalKeyA
constexpr uint64_t kLogicalKeyA
constexpr uint64_t kScanCodeKeyA
constexpr uint64_t kVirtualKeyA
TEST(DisplayListComplexity, EmptyDisplayList)
constexpr int kScanCodeShiftRight
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
std::function< void(MTLRenderPipelineDescriptor *)> Callback
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
#define EXPECT_TRUE(handle)