88#include < vector>
99
1010#include " flutter/shell/platform/embedder/test_utils/key_codes.g.h"
11+ #include " flutter/shell/platform/linux/fl_binary_messenger_private.h"
12+ #include " flutter/shell/platform/linux/fl_method_codec_private.h"
13+ #include " flutter/shell/platform/linux/key_mapping.h"
1114#include " flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
15+ #include " flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h"
16+ #include " flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
17+ #include " flutter/shell/platform/linux/testing/fl_test.h"
18+ #include " flutter/shell/platform/linux/testing/mock_binary_messenger.h"
1219#include " flutter/shell/platform/linux/testing/mock_text_input_plugin.h"
20+ #include " flutter/testing/testing.h"
21+
22+ #include " gmock/gmock.h"
1323#include " gtest/gtest.h"
1424
1525// Define compound `expect` in macros. If they were defined in functions, the
@@ -100,6 +110,10 @@ constexpr guint16 kKeyCodeSemicolon = 0x2fu;
100110constexpr guint16 kKeyCodeKeyLeftBracket = 0x22u ;
101111
102112static constexpr char kKeyEventChannelName [] = " flutter/keyevent" ;
113+ static constexpr char kKeyboardChannelName [] = " flutter/keyboard" ;
114+ static constexpr char kGetKeyboardStateMethod [] = " getKeyboardState" ;
115+ static constexpr uint64_t kMockPhysicalKey = 42 ;
116+ static constexpr uint64_t kMockLogicalKey = 42 ;
103117
104118// All key clues for a keyboard layout.
105119//
@@ -129,6 +143,19 @@ G_DECLARE_FINAL_TYPE(FlMockKeyBinaryMessenger,
129143
130144G_END_DECLS
131145
146+ MATCHER_P (MethodSuccessResponse, result, " " ) {
147+ g_autoptr (FlStandardMethodCodec) codec = fl_standard_method_codec_new ();
148+ g_autoptr (FlMethodResponse) response =
149+ fl_method_codec_decode_response (FL_METHOD_CODEC (codec), arg, nullptr );
150+ fl_method_response_get_result (response, nullptr );
151+ if (fl_value_equal (fl_method_response_get_result (response, nullptr ),
152+ result)) {
153+ return true ;
154+ }
155+ *result_listener << ::testing::PrintToString (response);
156+ return false ;
157+ }
158+
132159/* **** FlMockKeyBinaryMessenger *****/
133160/* Mock a binary messenger that only processes messages from the embedding on
134161 * the key event channel, and does so according to the callback set by
@@ -322,6 +349,15 @@ static guint fl_mock_view_keyboard_lookup_key(FlKeyboardViewDelegate* delegate,
322349 return (*group_layout)[key->keycode * 2 + shift];
323350}
324351
352+ static GHashTable* fl_mock_view_keyboard_get_keyboard_state (
353+ FlKeyboardViewDelegate* view_delegate) {
354+ GHashTable* result = g_hash_table_new (g_direct_hash, g_direct_equal);
355+ g_hash_table_insert (result, reinterpret_cast <gpointer>(kMockPhysicalKey ),
356+ reinterpret_cast <gpointer>(kMockLogicalKey ));
357+
358+ return result;
359+ }
360+
325361static void fl_mock_view_keyboard_delegate_iface_init (
326362 FlKeyboardViewDelegateInterface* iface) {
327363 iface->send_key_event = fl_mock_view_keyboard_send_key_event;
@@ -331,6 +367,7 @@ static void fl_mock_view_keyboard_delegate_iface_init(
331367 iface->subscribe_to_layout_change =
332368 fl_mock_view_keyboard_subscribe_to_layout_change;
333369 iface->lookup_key = fl_mock_view_keyboard_lookup_key;
370+ iface->get_keyboard_state = fl_mock_view_keyboard_get_keyboard_state;
334371}
335372
336373static FlMockViewDelegate* fl_mock_view_delegate_new () {
@@ -406,13 +443,16 @@ static FlKeyEvent* fl_key_event_new_by_mock(bool is_press,
406443class KeyboardTester {
407444 public:
408445 KeyboardTester () {
446+ ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
447+
409448 view_ = fl_mock_view_delegate_new ();
410449 respondToEmbedderCallsWith (false );
411450 respondToChannelCallsWith (false );
412451 respondToTextInputWith (false );
413452 setLayout (kLayoutUs );
414453
415- manager_ = fl_keyboard_manager_new (FL_KEYBOARD_VIEW_DELEGATE (view_));
454+ manager_ =
455+ fl_keyboard_manager_new (messenger, FL_KEYBOARD_VIEW_DELEGATE (view_));
416456 }
417457
418458 ~KeyboardTester () {
@@ -926,6 +966,47 @@ TEST(FlKeyboardManagerTest, SynthesizeModifiersIfNeeded) {
926966 kLogicalShiftLeft );
927967}
928968
969+ TEST (FlKeyboardManagerTest, GetPressedState) {
970+ KeyboardTester tester;
971+ tester.respondToTextInputWith (true );
972+
973+ // Dispatch a key event.
974+ fl_keyboard_manager_handle_event (
975+ tester.manager (),
976+ fl_key_event_new_by_mock (true , GDK_KEY_a, kKeyCodeKeyA , 0 , false ));
977+
978+ GHashTable* pressedState =
979+ fl_keyboard_manager_get_pressed_state (tester.manager ());
980+ EXPECT_EQ (g_hash_table_size (pressedState), 1u );
981+
982+ gpointer physical_key =
983+ g_hash_table_lookup (pressedState, uint64_to_gpointer (kPhysicalKeyA ));
984+ EXPECT_EQ (gpointer_to_uint64 (physical_key), kLogicalKeyA );
985+ }
986+
987+ TEST (FlKeyboardPluginTest, KeyboardChannelGetPressedState) {
988+ ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
989+
990+ g_autoptr (FlKeyboardManager) manager = fl_keyboard_manager_new (
991+ messenger, FL_KEYBOARD_VIEW_DELEGATE (fl_mock_view_delegate_new ()));
992+ EXPECT_NE (manager, nullptr );
993+
994+ g_autoptr (FlStandardMethodCodec) codec = fl_standard_method_codec_new ();
995+ g_autoptr (GBytes) message = fl_method_codec_encode_method_call (
996+ FL_METHOD_CODEC (codec), kGetKeyboardStateMethod , nullptr , nullptr );
997+
998+ g_autoptr (FlValue) response = fl_value_new_map ();
999+ fl_value_set_take (response, fl_value_new_int (kMockPhysicalKey ),
1000+ fl_value_new_int (kMockLogicalKey ));
1001+ EXPECT_CALL (messenger,
1002+ fl_binary_messenger_send_response (
1003+ ::testing::Eq<FlBinaryMessenger*>(messenger), ::testing::_,
1004+ MethodSuccessResponse (response), ::testing::_))
1005+ .WillOnce (::testing::Return (true ));
1006+
1007+ messenger.ReceiveMessage (kKeyboardChannelName , message);
1008+ }
1009+
9291010// The following layout data is generated using DEBUG_PRINT_LAYOUT.
9301011
9311012const MockGroupLayoutData kLayoutUs0 {{
0 commit comments