10 #include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
17 #include "flutter/shell/platform/linux/testing/fl_test.h"
18 #include "flutter/shell/platform/linux/testing/mock_binary_messenger.h"
19 #include "flutter/shell/platform/linux/testing/mock_text_input_plugin.h"
20 #include "flutter/testing/testing.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
28 #define EXPECT_KEY_EVENT(RECORD, TYPE, PHYSICAL, LOGICAL, CHAR, SYNTHESIZED) \
29 EXPECT_EQ((RECORD).type, CallRecord::kKeyCallEmbedder); \
30 EXPECT_EQ((RECORD).event->type, (TYPE)); \
31 EXPECT_EQ((RECORD).event->physical, (PHYSICAL)); \
32 EXPECT_EQ((RECORD).event->logical, (LOGICAL)); \
33 EXPECT_STREQ((RECORD).event->character, (CHAR)); \
34 EXPECT_EQ((RECORD).event->synthesized, (SYNTHESIZED));
36 #define VERIFY_DOWN(OUT_LOGICAL, OUT_CHAR) \
37 EXPECT_EQ(call_records[0].type, CallRecord::kKeyCallEmbedder); \
38 EXPECT_EQ(call_records[0].event->type, kFlutterKeyEventTypeDown); \
39 EXPECT_EQ(call_records[0].event->logical, (OUT_LOGICAL)); \
40 EXPECT_STREQ(call_records[0].event->character, (OUT_CHAR)); \
41 EXPECT_EQ(call_records[0].event->synthesized, false); \
45 using ::flutter::testing::keycodes::kLogicalAltLeft;
46 using ::flutter::testing::keycodes::kLogicalBracketLeft;
47 using ::flutter::testing::keycodes::kLogicalComma;
48 using ::flutter::testing::keycodes::kLogicalControlLeft;
49 using ::flutter::testing::keycodes::kLogicalDigit1;
50 using ::flutter::testing::keycodes::kLogicalKeyA;
51 using ::flutter::testing::keycodes::kLogicalKeyB;
52 using ::flutter::testing::keycodes::kLogicalKeyM;
53 using ::flutter::testing::keycodes::kLogicalKeyQ;
54 using ::flutter::testing::keycodes::kLogicalMetaLeft;
55 using ::flutter::testing::keycodes::kLogicalMinus;
56 using ::flutter::testing::keycodes::kLogicalParenthesisRight;
57 using ::flutter::testing::keycodes::kLogicalSemicolon;
58 using ::flutter::testing::keycodes::kLogicalShiftLeft;
59 using ::flutter::testing::keycodes::kLogicalUnderscore;
61 using ::flutter::testing::keycodes::kPhysicalAltLeft;
62 using ::flutter::testing::keycodes::kPhysicalControlLeft;
63 using ::flutter::testing::keycodes::kPhysicalKeyA;
64 using ::flutter::testing::keycodes::kPhysicalKeyB;
65 using ::flutter::testing::keycodes::kPhysicalMetaLeft;
66 using ::flutter::testing::keycodes::kPhysicalShiftLeft;
69 typedef std::function<void(
bool handled)> AsyncKeyCallback;
70 typedef std::function<void(AsyncKeyCallback
callback)> ChannelCallHandler;
71 typedef std::function<void(
const FlutterKeyEvent*
event,
74 typedef std::function<void(std::unique_ptr<FlKeyEvent>)> RedispatchHandler;
87 std::unique_ptr<FlutterKeyEvent>
event;
88 std::unique_ptr<char[]> event_character;
94 char* cloneString(
const char* source) {
95 if (source ==
nullptr) {
98 size_t charLen = strlen(source);
99 char*
target =
new char[charLen + 1];
100 strncpy(
target, source, charLen + 1);
104 constexpr guint16 kKeyCodeKeyA = 0x26u;
105 constexpr guint16 kKeyCodeKeyB = 0x38u;
106 constexpr guint16 kKeyCodeKeyM = 0x3au;
107 constexpr guint16 kKeyCodeDigit1 = 0x0au;
108 constexpr guint16 kKeyCodeMinus = 0x14u;
109 constexpr guint16 kKeyCodeSemicolon = 0x2fu;
110 constexpr guint16 kKeyCodeKeyLeftBracket = 0x22u;
112 static constexpr
char kKeyEventChannelName[] =
"flutter/keyevent";
113 static constexpr
char kKeyboardChannelName[] =
"flutter/keyboard";
115 static constexpr uint64_t kMockPhysicalKey = 42;
116 static constexpr uint64_t kMockLogicalKey = 42;
123 typedef std::array<uint32_t, 256> MockGroupLayoutData;
124 typedef std::vector<const MockGroupLayoutData*> MockLayoutData;
126 extern const MockLayoutData kLayoutUs;
127 extern const MockLayoutData kLayoutRussian;
128 extern const MockLayoutData kLayoutFrench;
133 fl_mock_view_delegate,
139 fl_mock_key_binary_messenger,
141 MOCK_KEY_BINARY_MESSENGER,
148 g_autoptr(FlMethodResponse) response =
155 *result_listener << ::testing::PrintToString(response);
164 struct _FlMockKeyBinaryMessenger {
165 GObject parent_instance;
168 struct FlMockKeyBinaryMessengerPrivate {
169 ChannelCallHandler callback_handler;
172 static void fl_mock_key_binary_messenger_iface_init(
173 FlBinaryMessengerInterface* iface);
176 FlMockKeyBinaryMessenger,
177 fl_mock_key_binary_messenger,
179 G_IMPLEMENT_INTERFACE(fl_binary_messenger_get_type(),
180 fl_mock_key_binary_messenger_iface_init);
181 G_ADD_PRIVATE(FlMockKeyBinaryMessenger))
184 static_cast<FlMockKeyBinaryMessengerPrivate*>( \
185 fl_mock_key_binary_messenger_get_instance_private( \
186 FL_MOCK_KEY_BINARY_MESSENGER(obj)))
188 static void fl_mock_key_binary_messenger_init(FlMockKeyBinaryMessenger*
self) {
189 FlMockKeyBinaryMessengerPrivate*
priv =
191 new (
priv) FlMockKeyBinaryMessengerPrivate();
194 static void fl_mock_key_binary_messenger_finalize(GObject*
object) {
196 ->~FlMockKeyBinaryMessengerPrivate();
199 static void fl_mock_key_binary_messenger_class_init(
200 FlMockKeyBinaryMessengerClass* klass) {
201 G_OBJECT_CLASS(klass)->finalize = fl_mock_key_binary_messenger_finalize;
204 static void fl_mock_key_binary_messenger_send_on_channel(
205 FlBinaryMessenger* messenger,
206 const gchar* channel,
208 GCancellable* cancellable,
211 FlMockKeyBinaryMessenger*
self = FL_MOCK_KEY_BINARY_MESSENGER(messenger);
214 EXPECT_STREQ(channel, kKeyEventChannelName);
217 g_autoptr(GTask) task =
223 g_autoptr(GError)
error =
nullptr;
227 g_task_return_pointer(
228 task, data,
reinterpret_cast<GDestroyNotify
>(g_bytes_unref));
233 static GBytes* fl_mock_key_binary_messenger_send_on_channel_finish(
234 FlBinaryMessenger* messenger,
237 return static_cast<GBytes*
>(g_task_propagate_pointer(G_TASK(
result),
error));
240 static void fl_mock_binary_messenger_resize_channel(
241 FlBinaryMessenger* messenger,
242 const gchar* channel,
247 static void fl_mock_binary_messenger_set_warns_on_channel_overflow(
248 FlBinaryMessenger* messenger,
249 const gchar* channel,
254 static void fl_mock_key_binary_messenger_iface_init(
255 FlBinaryMessengerInterface* iface) {
256 iface->set_message_handler_on_channel =
257 [](FlBinaryMessenger* messenger,
const gchar* channel,
259 GDestroyNotify destroy_notify) {
260 EXPECT_STREQ(channel, kKeyEventChannelName);
264 iface->send_response = [](FlBinaryMessenger* messenger,
265 FlBinaryMessengerResponseHandle* response_handle,
266 GBytes* response, GError**
error) -> gboolean {
269 g_return_val_if_reached(
TRUE);
272 iface->send_on_channel = fl_mock_key_binary_messenger_send_on_channel;
273 iface->send_on_channel_finish =
274 fl_mock_key_binary_messenger_send_on_channel_finish;
275 iface->resize_channel = fl_mock_binary_messenger_resize_channel;
276 iface->set_warns_on_channel_overflow =
277 fl_mock_binary_messenger_set_warns_on_channel_overflow;
280 static FlMockKeyBinaryMessenger* fl_mock_key_binary_messenger_new() {
281 FlMockKeyBinaryMessenger*
self = FL_MOCK_KEY_BINARY_MESSENGER(
282 g_object_new(fl_mock_key_binary_messenger_get_type(), NULL));
285 FL_IS_MOCK_KEY_BINARY_MESSENGER(
self);
290 static void fl_mock_key_binary_messenger_set_callback_handler(
291 FlMockKeyBinaryMessenger*
self,
292 ChannelCallHandler handler) {
299 struct _FlMockViewDelegate {
300 GObject parent_instance;
303 struct FlMockViewDelegatePrivate {
304 FlMockKeyBinaryMessenger* messenger;
305 EmbedderCallHandler embedder_handler;
306 bool text_filter_result;
307 RedispatchHandler redispatch_handler;
309 const MockLayoutData* layout_data;
312 static void fl_mock_view_keyboard_delegate_iface_init(
313 FlKeyboardViewDelegateInterface* iface);
317 fl_mock_view_delegate,
319 G_IMPLEMENT_INTERFACE(fl_keyboard_view_delegate_get_type(),
320 fl_mock_view_keyboard_delegate_iface_init);
321 G_ADD_PRIVATE(FlMockViewDelegate))
324 static_cast<FlMockViewDelegatePrivate*>( \
325 fl_mock_view_delegate_get_instance_private(FL_MOCK_VIEW_DELEGATE(obj)))
327 static void fl_mock_view_delegate_init(FlMockViewDelegate*
self) {
329 new (
priv) FlMockViewDelegatePrivate();
332 static void fl_mock_view_delegate_finalize(GObject*
object) {
336 static void fl_mock_view_delegate_dispose(GObject*
object) {
339 g_clear_object(&
priv->messenger);
341 G_OBJECT_CLASS(fl_mock_view_delegate_parent_class)->dispose(
object);
344 static void fl_mock_view_delegate_class_init(FlMockViewDelegateClass* klass) {
345 G_OBJECT_CLASS(klass)->dispose = fl_mock_view_delegate_dispose;
346 G_OBJECT_CLASS(klass)->finalize = fl_mock_view_delegate_finalize;
349 static void fl_mock_view_keyboard_send_key_event(
350 FlKeyboardViewDelegate* view_delegate,
351 const FlutterKeyEvent*
event,
354 FlMockViewDelegatePrivate*
priv =
363 static gboolean fl_mock_view_keyboard_text_filter_key_press(
364 FlKeyboardViewDelegate* view_delegate,
366 FlMockViewDelegatePrivate*
priv =
368 return priv->text_filter_result;
371 static FlBinaryMessenger* fl_mock_view_keyboard_get_messenger(
372 FlKeyboardViewDelegate* view_delegate) {
373 FlMockViewDelegatePrivate*
priv =
375 return FL_BINARY_MESSENGER(
priv->messenger);
378 static void fl_mock_view_keyboard_redispatch_event(
379 FlKeyboardViewDelegate* view_delegate,
380 std::unique_ptr<FlKeyEvent>
event) {
381 FlMockViewDelegatePrivate*
priv =
383 if (
priv->redispatch_handler) {
384 priv->redispatch_handler(std::move(
event));
388 static void fl_mock_view_keyboard_subscribe_to_layout_change(
389 FlKeyboardViewDelegate* delegate,
392 priv->layout_notifier = std::move(notifier);
395 static guint fl_mock_view_keyboard_lookup_key(FlKeyboardViewDelegate* delegate,
396 const GdkKeymapKey* key) {
398 guint8 group =
static_cast<guint8
>(key->group);
399 EXPECT_LT(group,
priv->layout_data->size());
400 const MockGroupLayoutData* group_layout = (*
priv->layout_data)[group];
401 EXPECT_TRUE(group_layout !=
nullptr);
402 EXPECT_TRUE(key->level == 0 || key->level == 1);
403 bool shift = key->level == 1;
404 return (*group_layout)[key->keycode * 2 + shift];
407 static GHashTable* fl_mock_view_keyboard_get_keyboard_state(
408 FlKeyboardViewDelegate* view_delegate) {
409 GHashTable*
result = g_hash_table_new(g_direct_hash, g_direct_equal);
410 g_hash_table_insert(
result,
reinterpret_cast<gpointer
>(kMockPhysicalKey),
411 reinterpret_cast<gpointer
>(kMockLogicalKey));
416 static void fl_mock_view_keyboard_delegate_iface_init(
417 FlKeyboardViewDelegateInterface* iface) {
418 iface->send_key_event = fl_mock_view_keyboard_send_key_event;
419 iface->text_filter_key_press = fl_mock_view_keyboard_text_filter_key_press;
420 iface->get_messenger = fl_mock_view_keyboard_get_messenger;
421 iface->redispatch_event = fl_mock_view_keyboard_redispatch_event;
422 iface->subscribe_to_layout_change =
423 fl_mock_view_keyboard_subscribe_to_layout_change;
424 iface->lookup_key = fl_mock_view_keyboard_lookup_key;
425 iface->get_keyboard_state = fl_mock_view_keyboard_get_keyboard_state;
428 static FlMockViewDelegate* fl_mock_view_delegate_new() {
429 FlMockViewDelegate*
self = FL_MOCK_VIEW_DELEGATE(
430 g_object_new(fl_mock_view_delegate_get_type(),
nullptr));
433 FL_IS_MOCK_VIEW_DELEGATE(
self);
436 priv->messenger = fl_mock_key_binary_messenger_new();
441 static void fl_mock_view_set_embedder_handler(FlMockViewDelegate*
self,
442 EmbedderCallHandler handler) {
444 priv->embedder_handler = std::move(handler);
447 static void fl_mock_view_set_text_filter_result(FlMockViewDelegate*
self,
453 static void fl_mock_view_set_redispatch_handler(FlMockViewDelegate*
self,
454 RedispatchHandler handler) {
456 priv->redispatch_handler = std::move(handler);
459 static void fl_mock_view_set_layout(FlMockViewDelegate*
self,
460 const MockLayoutData* layout) {
462 priv->layout_data = layout;
463 if (
priv->layout_notifier !=
nullptr) {
464 priv->layout_notifier();
474 GdkModifierType
state,
475 gboolean is_modifier,
478 event->is_press = is_press;
480 event->state =
state;
481 event->keyval = keyval;
482 event->group = group;
483 event->keycode = keycode;
487 class KeyboardTester {
490 ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
492 view_ = fl_mock_view_delegate_new();
493 respondToEmbedderCallsWith(
false);
494 respondToChannelCallsWith(
false);
495 respondToTextInputWith(
false);
496 setLayout(kLayoutUs);
503 g_clear_object(&view_);
504 g_clear_object(&manager_);
511 void flushChannelMessages() {
512 GMainLoop* loop = g_main_loop_new(
nullptr, 0);
513 g_idle_add(_flushChannelMessagesCb, loop);
514 g_main_loop_run(loop);
523 int redispatchEventsAndClear(
524 std::vector<std::unique_ptr<FlKeyEvent>>& events) {
525 size_t event_count = events.size();
526 int first_error = -1;
527 during_redispatch_ =
true;
528 for (
size_t event_id = 0; event_id < event_count; event_id += 1) {
530 manager_, events[event_id].release());
531 EXPECT_FALSE(handled);
533 first_error = first_error == -1 ? event_id : first_error;
536 during_redispatch_ =
false;
538 return first_error < 0 ? event_count : -first_error;
541 void respondToEmbedderCallsWith(
bool response) {
542 fl_mock_view_set_embedder_handler(
543 view_, [response,
this](
const FlutterKeyEvent*
event,
545 EXPECT_FALSE(during_redispatch_);
550 void recordEmbedderCallsTo(std::vector<CallRecord>& storage) {
551 fl_mock_view_set_embedder_handler(
552 view_, [&storage,
this](
const FlutterKeyEvent*
event,
554 EXPECT_FALSE(during_redispatch_);
555 auto new_event = std::make_unique<FlutterKeyEvent>(*
event);
556 char* new_event_character = cloneString(
event->character);
557 new_event->character = new_event_character;
558 storage.push_back(CallRecord{
559 .type = CallRecord::kKeyCallEmbedder,
561 .event = std::move(new_event),
562 .event_character = std::unique_ptr<char[]>(new_event_character),
567 void respondToEmbedderCallsWithAndRecordsTo(
569 std::vector<CallRecord>& storage) {
570 fl_mock_view_set_embedder_handler(
571 view_, [&storage, response,
this](
const FlutterKeyEvent*
event,
573 EXPECT_FALSE(during_redispatch_);
574 auto new_event = std::make_unique<FlutterKeyEvent>(*
event);
575 char* new_event_character = cloneString(
event->character);
576 new_event->character = new_event_character;
577 storage.push_back(CallRecord{
578 .type = CallRecord::kKeyCallEmbedder,
579 .event = std::move(new_event),
580 .event_character = std::unique_ptr<char[]>(new_event_character),
586 void respondToChannelCallsWith(
bool response) {
589 fl_mock_key_binary_messenger_set_callback_handler(
590 priv->messenger, [response,
this](
const AsyncKeyCallback&
callback) {
591 EXPECT_FALSE(during_redispatch_);
596 void recordChannelCallsTo(std::vector<CallRecord>& storage) {
599 fl_mock_key_binary_messenger_set_callback_handler(
600 priv->messenger, [&storage,
this](AsyncKeyCallback
callback) {
601 EXPECT_FALSE(during_redispatch_);
602 storage.push_back(CallRecord{
603 .type = CallRecord::kKeyCallChannel,
604 .callback = std::move(callback),
609 void respondToTextInputWith(
bool response) {
610 fl_mock_view_set_text_filter_result(view_, response);
613 void recordRedispatchedEventsTo(
614 std::vector<std::unique_ptr<FlKeyEvent>>& storage) {
615 fl_mock_view_set_redispatch_handler(
616 view_, [&storage](std::unique_ptr<FlKeyEvent> key) {
617 storage.push_back(std::move(key));
621 void setLayout(
const MockLayoutData& layout) {
622 fl_mock_view_set_layout(view_, &layout);
626 FlMockViewDelegate* view_;
628 bool during_redispatch_ =
false;
630 static gboolean _flushChannelMessagesCb(gpointer data) {
631 g_autoptr(GMainLoop) loop =
reinterpret_cast<GMainLoop*
>(data);
632 g_main_loop_quit(loop);
639 TEST(FlKeyboardManagerTest, DisposeWithUnresolvedPends) {
640 KeyboardTester tester;
641 std::vector<CallRecord> call_records;
644 tester.recordEmbedderCallsTo(call_records);
648 static_cast<GdkModifierType
>(0),
false));
650 tester.respondToEmbedderCallsWith(
true);
654 static_cast<GdkModifierType
>(0),
false));
656 tester.flushChannelMessages();
661 TEST(FlKeyboardManagerTest, SingleDelegateWithAsyncResponds) {
662 KeyboardTester tester;
663 std::vector<CallRecord> call_records;
664 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
666 gboolean manager_handled =
false;
669 tester.recordEmbedderCallsTo(call_records);
670 tester.recordRedispatchedEventsTo(redispatched);
676 static_cast<GdkModifierType
>(0),
false));
677 tester.flushChannelMessages();
678 EXPECT_EQ(manager_handled,
true);
679 EXPECT_EQ(redispatched.size(), 0u);
680 EXPECT_EQ(call_records.size(), 1u);
682 kLogicalKeyA,
"a",
false);
684 call_records[0].callback(
true);
685 tester.flushChannelMessages();
686 EXPECT_EQ(redispatched.size(), 0u);
688 call_records.clear();
694 static_cast<GdkModifierType
>(0),
false));
695 tester.flushChannelMessages();
696 EXPECT_EQ(manager_handled,
true);
697 EXPECT_EQ(redispatched.size(), 0u);
698 EXPECT_EQ(call_records.size(), 1u);
700 kLogicalKeyA,
nullptr,
false);
706 static_cast<GdkModifierType
>(0),
false));
707 tester.flushChannelMessages();
708 EXPECT_EQ(manager_handled,
true);
709 EXPECT_EQ(redispatched.size(), 0u);
710 EXPECT_EQ(call_records.size(), 2u);
712 kLogicalKeyB,
"b",
false);
715 call_records[1].callback(
false);
716 EXPECT_EQ(redispatched.size(), 1u);
717 EXPECT_EQ(redispatched[0]->keyval, 0x62u);
718 call_records[0].callback(
false);
719 tester.flushChannelMessages();
720 EXPECT_EQ(redispatched.size(), 2u);
721 EXPECT_EQ(redispatched[1]->keyval, 0x61u);
724 call_records.clear();
727 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 2);
728 tester.flushChannelMessages();
729 EXPECT_EQ(call_records.size(), 0u);
737 static_cast<GdkModifierType
>(0),
false));
738 tester.flushChannelMessages();
739 EXPECT_EQ(manager_handled,
true);
740 EXPECT_EQ(redispatched.size(), 0u);
741 EXPECT_EQ(call_records.size(), 1u);
743 call_records[0].callback(
true);
747 TEST(FlKeyboardManagerTest, SingleDelegateWithSyncResponds) {
748 KeyboardTester tester;
749 gboolean manager_handled =
false;
750 std::vector<CallRecord> call_records;
751 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
754 tester.respondToEmbedderCallsWithAndRecordsTo(
true, call_records);
755 tester.recordRedispatchedEventsTo(redispatched);
761 static_cast<GdkModifierType
>(0),
false));
762 tester.flushChannelMessages();
763 EXPECT_EQ(manager_handled,
true);
764 EXPECT_EQ(call_records.size(), 1u);
766 kLogicalKeyA,
"a",
false);
767 EXPECT_EQ(redispatched.size(), 0u);
768 call_records.clear();
771 redispatched.clear();
774 tester.respondToEmbedderCallsWithAndRecordsTo(
false, call_records);
778 static_cast<GdkModifierType
>(0),
false));
779 tester.flushChannelMessages();
780 EXPECT_EQ(manager_handled,
true);
781 EXPECT_EQ(call_records.size(), 1u);
783 kLogicalKeyA,
nullptr,
false);
784 EXPECT_EQ(redispatched.size(), 1u);
785 call_records.clear();
789 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
790 EXPECT_EQ(call_records.size(), 0u);
795 TEST(FlKeyboardManagerTest, WithTwoAsyncDelegates) {
796 KeyboardTester tester;
797 std::vector<CallRecord> call_records;
798 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
800 gboolean manager_handled =
false;
802 tester.recordEmbedderCallsTo(call_records);
803 tester.recordChannelCallsTo(call_records);
804 tester.recordRedispatchedEventsTo(redispatched);
811 static_cast<GdkModifierType
>(0),
false));
813 EXPECT_EQ(manager_handled,
true);
814 EXPECT_EQ(redispatched.size(), 0u);
815 EXPECT_EQ(call_records.size(), 2u);
817 EXPECT_EQ(call_records[0].
type, CallRecord::kKeyCallEmbedder);
818 EXPECT_EQ(call_records[1].
type, CallRecord::kKeyCallChannel);
820 call_records[0].callback(
true);
821 call_records[1].callback(
false);
822 tester.flushChannelMessages();
823 EXPECT_EQ(redispatched.size(), 0u);
826 call_records.clear();
832 static_cast<GdkModifierType
>(0),
false));
834 EXPECT_EQ(manager_handled,
true);
835 EXPECT_EQ(redispatched.size(), 0u);
836 EXPECT_EQ(call_records.size(), 2u);
838 EXPECT_EQ(call_records[0].
type, CallRecord::kKeyCallEmbedder);
839 EXPECT_EQ(call_records[1].
type, CallRecord::kKeyCallChannel);
841 call_records[0].callback(
false);
842 call_records[1].callback(
false);
844 call_records.clear();
847 tester.flushChannelMessages();
848 EXPECT_EQ(redispatched.size(), 1u);
849 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
850 EXPECT_EQ(call_records.size(), 0u);
855 TEST(FlKeyboardManagerTest, TextInputPluginReturnsFalse) {
856 KeyboardTester tester;
857 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
858 gboolean manager_handled =
false;
859 tester.recordRedispatchedEventsTo(redispatched);
860 tester.respondToTextInputWith(
false);
866 static_cast<GdkModifierType
>(0),
false));
867 tester.flushChannelMessages();
868 EXPECT_EQ(manager_handled,
true);
870 EXPECT_EQ(redispatched.size(), 1u);
873 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
878 TEST(FlKeyboardManagerTest, TextInputPluginReturnsTrue) {
879 KeyboardTester tester;
880 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
881 gboolean manager_handled =
false;
882 tester.recordRedispatchedEventsTo(redispatched);
883 tester.respondToTextInputWith(
true);
889 static_cast<GdkModifierType
>(0),
false));
890 tester.flushChannelMessages();
891 EXPECT_EQ(manager_handled,
true);
893 EXPECT_EQ(redispatched.size(), 0u);
898 TEST(FlKeyboardManagerTest, CorrectLogicalKeyForLayouts) {
899 KeyboardTester tester;
901 std::vector<CallRecord> call_records;
902 tester.recordEmbedderCallsTo(call_records);
904 auto sendTap = [&](guint8 keycode, guint keyval, guint8 group) {
907 true, keyval, keycode,
908 static_cast<GdkModifierType
>(0),
false, group));
911 false, keyval, keycode,
912 static_cast<GdkModifierType
>(0),
false, group));
917 sendTap(kKeyCodeKeyA, GDK_KEY_a, 0);
920 sendTap(kKeyCodeKeyA, GDK_KEY_A, 0);
923 sendTap(kKeyCodeDigit1, GDK_KEY_1, 0);
926 sendTap(kKeyCodeDigit1, GDK_KEY_exclam, 0);
929 sendTap(kKeyCodeMinus, GDK_KEY_minus, 0);
932 sendTap(kKeyCodeMinus, GDK_KEY_underscore, 0);
938 tester.setLayout(kLayoutFrench);
940 sendTap(kKeyCodeKeyA, GDK_KEY_q, 3);
943 sendTap(kKeyCodeKeyA, GDK_KEY_Q, 3);
946 sendTap(kKeyCodeSemicolon, GDK_KEY_m, 3);
949 sendTap(kKeyCodeKeyM, GDK_KEY_comma, 3);
952 sendTap(kKeyCodeDigit1, GDK_KEY_ampersand, 3);
955 sendTap(kKeyCodeDigit1, GDK_KEY_1, 3);
958 sendTap(kKeyCodeMinus, GDK_KEY_parenright, 3);
961 sendTap(kKeyCodeMinus, GDK_KEY_degree, 3);
967 sendTap(kKeyCodeKeyA, GDK_KEY_a, 0);
970 sendTap(kKeyCodeDigit1, GDK_KEY_1, 0);
974 tester.setLayout(kLayoutRussian);
976 sendTap(kKeyCodeKeyA, GDK_KEY_Cyrillic_ef, 2);
979 sendTap(kKeyCodeDigit1, GDK_KEY_1, 2);
982 sendTap(kKeyCodeKeyLeftBracket, GDK_KEY_Cyrillic_ha, 2);
986 sendTap(kKeyCodeKeyA, GDK_KEY_a, 0);
989 sendTap(kKeyCodeKeyLeftBracket, GDK_KEY_bracketleft, 0);
993 TEST(FlKeyboardManagerTest, SynthesizeModifiersIfNeeded) {
994 KeyboardTester tester;
995 std::vector<CallRecord> call_records;
996 tester.recordEmbedderCallsTo(call_records);
998 auto verifyModifierIsSynthesized = [&](GdkModifierType mask,
999 uint64_t physical, uint64_t logical) {
1003 EXPECT_EQ(call_records.size(), 1u);
1005 logical, NULL,
true);
1009 EXPECT_EQ(call_records.size(), 2u);
1010 EXPECT_KEY_EVENT(call_records[1], kFlutterKeyEventTypeUp, physical, logical,
1012 call_records.clear();
1018 EXPECT_EQ(call_records.size(), 0u);
1019 call_records.clear();
1022 verifyModifierIsSynthesized(GDK_CONTROL_MASK, kPhysicalControlLeft,
1023 kLogicalControlLeft);
1024 verifyModifierIsSynthesized(GDK_META_MASK, kPhysicalMetaLeft,
1026 verifyModifierIsSynthesized(GDK_MOD1_MASK, kPhysicalAltLeft, kLogicalAltLeft);
1027 verifyModifierIsSynthesized(GDK_SHIFT_MASK, kPhysicalShiftLeft,
1031 TEST(FlKeyboardManagerTest, GetPressedState) {
1032 KeyboardTester tester;
1033 tester.respondToTextInputWith(
true);
1039 static_cast<GdkModifierType
>(0),
false));
1041 GHashTable* pressedState =
1043 EXPECT_EQ(g_hash_table_size(pressedState), 1u);
1045 gpointer physical_key =
1050 TEST(FlKeyboardPluginTest, KeyboardChannelGetPressedState) {
1051 ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
1054 messenger, FL_KEYBOARD_VIEW_DELEGATE(fl_mock_view_delegate_new()));
1055 EXPECT_NE(manager,
nullptr);
1064 EXPECT_CALL(messenger,
1066 ::testing::Eq<FlBinaryMessenger*>(messenger), ::testing::_,
1067 MethodSuccessResponse(response), ::testing::_))
1068 .WillOnce(::testing::Return(
true));
1070 messenger.ReceiveMessage(kKeyboardChannelName, message);
1075 const MockGroupLayoutData kLayoutUs0{{
1077 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1078 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1079 0xffff, 0x0031, 0xffff, 0x0031, 0x0031, 0x0021, 0x0032, 0x0040,
1080 0x0033, 0x0023, 0x0034, 0x0024, 0x0035, 0x0025, 0x0036, 0x005e,
1081 0x0037, 0x0026, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029,
1082 0x002d, 0x005f, 0x003d, 0x002b, 0xffff, 0xffff, 0xffff, 0xffff,
1083 0x0071, 0x0051, 0x0077, 0x0057, 0x0065, 0x0045, 0x0072, 0x0052,
1084 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049,
1085 0x006f, 0x004f, 0x0070, 0x0050, 0x005b, 0x007b, 0x005d, 0x007d,
1086 0xffff, 0xffff, 0xffff, 0x0061, 0x0061, 0x0041, 0x0073, 0x0053,
1087 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048,
1088 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x003b, 0x003a,
1089 0x0027, 0x0022, 0x0060, 0x007e, 0xffff, 0x005c, 0x005c, 0x007c,
1090 0x007a, 0x005a, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056,
1091 0x0062, 0x0042, 0x006e, 0x004e, 0x006d, 0x004d, 0x002c, 0x003c,
1092 0x002e, 0x003e, 0x002f, 0x003f, 0xffff, 0xffff, 0xffff, 0xffff,
1093 0xffff, 0xffff, 0x0020, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1094 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1095 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1096 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1097 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1098 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1099 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1100 0xffff, 0xffff, 0x003c, 0x003e, 0x003c, 0x003e, 0xffff, 0xffff,
1101 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1102 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1103 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1104 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1105 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1106 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1107 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1108 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, 0xffff, 0xffff,
1111 const MockGroupLayoutData kLayoutRussian0{
1113 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1114 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1115 0x0000, 0xffff, 0xffff, 0x0031, 0x0031, 0x0021, 0x0032, 0x0040,
1116 0x0033, 0x0023, 0x0034, 0x0024, 0x0035, 0x0025, 0x0036, 0x005e,
1117 0x0037, 0x0026, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029,
1118 0x002d, 0x005f, 0x003d, 0x002b, 0xffff, 0xffff, 0xffff, 0xffff,
1119 0x0071, 0x0051, 0x0077, 0x0057, 0x0065, 0x0045, 0x0072, 0x0052,
1120 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049,
1121 0x006f, 0x004f, 0x0070, 0x0050, 0x005b, 0x007b, 0x005d, 0x007d,
1122 0xffff, 0xffff, 0xffff, 0x0061, 0x0061, 0x0041, 0x0073, 0x0053,
1123 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048,
1124 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x003b, 0x003a,
1125 0x0027, 0x0022, 0x0060, 0x007e, 0xffff, 0x005c, 0x005c, 0x007c,
1126 0x007a, 0x005a, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056,
1127 0x0062, 0x0042, 0x006e, 0x004e, 0x006d, 0x004d, 0x002c, 0x003c,
1128 0x002e, 0x003e, 0x002f, 0x003f, 0xffff, 0xffff, 0xffff, 0xffff,
1129 0xffff, 0xffff, 0x0020, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1130 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1131 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1132 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1133 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1134 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1135 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1136 0xffff, 0xffff, 0x0000, 0xffff, 0x003c, 0x003e, 0xffff, 0xffff,
1137 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1138 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff,
1139 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1140 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1141 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1142 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1143 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1144 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, 0xffff, 0xffff,
1147 const MockGroupLayoutData kLayoutRussian2{{
1149 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1150 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1151 0xffff, 0x0031, 0x0021, 0x0000, 0x0031, 0x0021, 0x0032, 0x0022,
1152 0x0033, 0x06b0, 0x0034, 0x003b, 0x0035, 0x0025, 0x0036, 0x003a,
1153 0x0037, 0x003f, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029,
1154 0x002d, 0x005f, 0x003d, 0x002b, 0x0071, 0x0051, 0x0000, 0x0000,
1155 0x06ca, 0x06ea, 0x06c3, 0x06e3, 0x06d5, 0x06f5, 0x06cb, 0x06eb,
1156 0x06c5, 0x06e5, 0x06ce, 0x06ee, 0x06c7, 0x06e7, 0x06db, 0x06fb,
1157 0x06dd, 0x06fd, 0x06da, 0x06fa, 0x06c8, 0x06e8, 0x06df, 0x06ff,
1158 0x0061, 0x0041, 0x0041, 0x0000, 0x06c6, 0x06e6, 0x06d9, 0x06f9,
1159 0x06d7, 0x06f7, 0x06c1, 0x06e1, 0x06d0, 0x06f0, 0x06d2, 0x06f2,
1160 0x06cf, 0x06ef, 0x06cc, 0x06ec, 0x06c4, 0x06e4, 0x06d6, 0x06f6,
1161 0x06dc, 0x06fc, 0x06a3, 0x06b3, 0x007c, 0x0000, 0x005c, 0x002f,
1162 0x06d1, 0x06f1, 0x06de, 0x06fe, 0x06d3, 0x06f3, 0x06cd, 0x06ed,
1163 0x06c9, 0x06e9, 0x06d4, 0x06f4, 0x06d8, 0x06f8, 0x06c2, 0x06e2,
1164 0x06c0, 0x06e0, 0x002e, 0x002c, 0xffff, 0xffff, 0xffff, 0xffff,
1165 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1166 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1167 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1168 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1169 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1170 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1171 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1172 0xffff, 0xffff, 0x003c, 0x003e, 0x002f, 0x007c, 0xffff, 0xffff,
1173 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1174 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1175 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0x0000,
1176 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1177 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1178 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1179 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x00b1,
1180 0x00b1, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1183 const MockGroupLayoutData kLayoutFrench0 = {
1185 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1186 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1187 0x0000, 0xffff, 0xffff, 0x0031, 0x0031, 0x0021, 0x0032, 0x0040,
1188 0x0033, 0x0023, 0x0034, 0x0024, 0x0035, 0x0025, 0x0036, 0x005e,
1189 0x0037, 0x0026, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029,
1190 0x002d, 0x005f, 0x003d, 0x002b, 0xffff, 0xffff, 0xffff, 0xffff,
1191 0x0071, 0x0051, 0x0077, 0x0057, 0x0065, 0x0045, 0x0072, 0x0052,
1192 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049,
1193 0x006f, 0x004f, 0x0070, 0x0050, 0x005b, 0x007b, 0x005d, 0x007d,
1194 0xffff, 0xffff, 0xffff, 0x0061, 0x0061, 0x0041, 0x0073, 0x0053,
1195 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048,
1196 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x003b, 0x003a,
1197 0x0027, 0x0022, 0x0060, 0x007e, 0xffff, 0x005c, 0x005c, 0x007c,
1198 0x007a, 0x005a, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056,
1199 0x0062, 0x0042, 0x006e, 0x004e, 0x006d, 0x004d, 0x002c, 0x003c,
1200 0x002e, 0x003e, 0x002f, 0x003f, 0xffff, 0xffff, 0xffff, 0xffff,
1201 0xffff, 0xffff, 0x0020, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1202 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1203 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1204 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1205 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1206 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1207 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1208 0xffff, 0xffff, 0x0000, 0xffff, 0x003c, 0x003e, 0xffff, 0xffff,
1209 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1210 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff,
1211 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1212 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1213 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1214 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1215 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1216 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, 0xffff, 0xffff,
1219 const MockGroupLayoutData kLayoutFrench3 = {
1221 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1222 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1223 0x0000, 0xffff, 0x0000, 0x0000, 0x0026, 0x0031, 0x00e9, 0x0032,
1224 0x0022, 0x0033, 0x0027, 0x0034, 0x0028, 0x0035, 0x002d, 0x0036,
1225 0x00e8, 0x0037, 0x005f, 0x0038, 0x00e7, 0x0039, 0x00e0, 0x0030,
1226 0x0029, 0x00b0, 0x003d, 0x002b, 0x0000, 0x0000, 0x0061, 0x0041,
1227 0x0061, 0x0041, 0x007a, 0x005a, 0x0065, 0x0045, 0x0072, 0x0052,
1228 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049,
1229 0x006f, 0x004f, 0x0070, 0x0050, 0xffff, 0xffff, 0x0024, 0x00a3,
1230 0x0041, 0x0000, 0x0000, 0x0000, 0x0071, 0x0051, 0x0073, 0x0053,
1231 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048,
1232 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x006d, 0x004d,
1233 0x00f9, 0x0025, 0x00b2, 0x007e, 0x0000, 0x0000, 0x002a, 0x00b5,
1234 0x0077, 0x0057, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056,
1235 0x0062, 0x0042, 0x006e, 0x004e, 0x002c, 0x003f, 0x003b, 0x002e,
1236 0x003a, 0x002f, 0x0021, 0x00a7, 0xffff, 0xffff, 0xffff, 0xffff,
1237 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1238 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1239 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1240 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1241 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1242 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1243 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1244 0xffff, 0x003c, 0x0000, 0xffff, 0x003c, 0x003e, 0xffff, 0xffff,
1245 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1246 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff,
1247 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1248 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1249 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1250 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1251 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff,
1252 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1255 const MockLayoutData kLayoutUs{&kLayoutUs0};
1256 const MockLayoutData kLayoutRussian{&kLayoutRussian0,
nullptr,
1258 const MockLayoutData kLayoutFrench{&kLayoutFrench0,
nullptr,
nullptr,