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_handler.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(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,
381 FlMockViewDelegatePrivate*
priv =
383 if (
priv->redispatch_handler) {
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();
470 class KeyboardTester {
473 ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
475 view_ = fl_mock_view_delegate_new();
476 respondToEmbedderCallsWith(
false);
477 respondToChannelCallsWith(
false);
478 respondToTextInputWith(
false);
479 setLayout(kLayoutUs);
486 g_clear_object(&view_);
487 g_clear_object(&handler_);
488 g_clear_pointer(&redispatched_events_, g_ptr_array_unref);
491 FlKeyboardHandler* handler() {
return handler_; }
495 void flushChannelMessages() {
496 GMainLoop* loop = g_main_loop_new(
nullptr, 0);
497 g_idle_add(_flushChannelMessagesCb, loop);
498 g_main_loop_run(loop);
507 int redispatchEventsAndClear(GPtrArray* events) {
508 guint event_count = events->len;
509 int first_error = -1;
510 during_redispatch_ =
true;
511 for (guint event_id = 0; event_id < event_count; event_id += 1) {
512 FlKeyEvent*
event = FL_KEY_EVENT(g_ptr_array_index(events, event_id));
514 EXPECT_FALSE(handled);
516 first_error = first_error == -1 ? event_id : first_error;
519 during_redispatch_ =
false;
520 g_ptr_array_set_size(events, 0);
521 return first_error < 0 ? event_count : -first_error;
524 void respondToEmbedderCallsWith(
bool response) {
525 fl_mock_view_set_embedder_handler(
526 view_, [response,
this](
const FlutterKeyEvent*
event,
528 EXPECT_FALSE(during_redispatch_);
533 void recordEmbedderCallsTo(std::vector<CallRecord>& storage) {
534 fl_mock_view_set_embedder_handler(
535 view_, [&storage,
this](
const FlutterKeyEvent*
event,
537 EXPECT_FALSE(during_redispatch_);
538 auto new_event = std::make_unique<FlutterKeyEvent>(*
event);
539 char* new_event_character = cloneString(
event->character);
540 new_event->character = new_event_character;
541 storage.push_back(CallRecord{
542 .type = CallRecord::kKeyCallEmbedder,
544 .event = std::move(new_event),
545 .event_character = std::unique_ptr<char[]>(new_event_character),
550 void respondToEmbedderCallsWithAndRecordsTo(
552 std::vector<CallRecord>& storage) {
553 fl_mock_view_set_embedder_handler(
554 view_, [&storage, response,
this](
const FlutterKeyEvent*
event,
556 EXPECT_FALSE(during_redispatch_);
557 auto new_event = std::make_unique<FlutterKeyEvent>(*
event);
558 char* new_event_character = cloneString(
event->character);
559 new_event->character = new_event_character;
560 storage.push_back(CallRecord{
561 .type = CallRecord::kKeyCallEmbedder,
562 .event = std::move(new_event),
563 .event_character = std::unique_ptr<char[]>(new_event_character),
569 void respondToChannelCallsWith(
bool response) {
572 fl_mock_key_binary_messenger_set_callback_handler(
573 priv->messenger, [response,
this](
const AsyncKeyCallback&
callback) {
574 EXPECT_FALSE(during_redispatch_);
579 void recordChannelCallsTo(std::vector<CallRecord>& storage) {
582 fl_mock_key_binary_messenger_set_callback_handler(
583 priv->messenger, [&storage,
this](AsyncKeyCallback
callback) {
584 EXPECT_FALSE(during_redispatch_);
585 storage.push_back(CallRecord{
586 .type = CallRecord::kKeyCallChannel,
587 .callback = std::move(callback),
592 void respondToTextInputWith(
bool response) {
593 fl_mock_view_set_text_filter_result(view_, response);
596 void recordRedispatchedEventsTo(GPtrArray* storage) {
597 redispatched_events_ = g_ptr_array_ref(storage);
598 fl_mock_view_set_redispatch_handler(view_, [
this](FlKeyEvent* key) {
599 g_ptr_array_add(redispatched_events_, g_object_ref(key));
603 void setLayout(
const MockLayoutData& layout) {
604 fl_mock_view_set_layout(view_, &layout);
608 FlMockViewDelegate* view_;
609 FlKeyboardHandler* handler_;
610 GPtrArray* redispatched_events_ =
nullptr;
611 bool during_redispatch_ =
false;
613 static gboolean _flushChannelMessagesCb(gpointer data) {
614 g_autoptr(GMainLoop) loop =
reinterpret_cast<GMainLoop*
>(data);
615 g_main_loop_quit(loop);
622 TEST(FlKeyboardHandlerTest, DisposeWithUnresolvedPends) {
623 KeyboardTester tester;
624 std::vector<CallRecord> call_records;
627 tester.recordEmbedderCallsTo(call_records);
629 0,
TRUE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
632 tester.respondToEmbedderCallsWith(
true);
634 0, FALSE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
637 tester.flushChannelMessages();
642 TEST(FlKeyboardHandlerTest, SingleDelegateWithAsyncResponds) {
643 KeyboardTester tester;
644 std::vector<CallRecord> call_records;
645 g_autoptr(GPtrArray) redispatched =
646 g_ptr_array_new_with_free_func(g_object_unref);
648 gboolean handler_handled =
false;
651 tester.recordEmbedderCallsTo(call_records);
652 tester.recordRedispatchedEventsTo(redispatched);
656 0,
TRUE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
658 tester.flushChannelMessages();
659 EXPECT_EQ(handler_handled,
true);
660 EXPECT_EQ(redispatched->len, 0u);
661 EXPECT_EQ(call_records.size(), 1u);
663 kLogicalKeyA,
"a",
false);
665 call_records[0].callback(
true);
666 tester.flushChannelMessages();
667 EXPECT_EQ(redispatched->len, 0u);
669 call_records.clear();
673 0, FALSE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
675 tester.flushChannelMessages();
676 EXPECT_EQ(handler_handled,
true);
677 EXPECT_EQ(redispatched->len, 0u);
678 EXPECT_EQ(call_records.size(), 1u);
680 kLogicalKeyA,
nullptr,
false);
684 0,
TRUE, kKeyCodeKeyB, GDK_KEY_b,
static_cast<GdkModifierType
>(0), 0);
686 tester.flushChannelMessages();
687 EXPECT_EQ(handler_handled,
true);
688 EXPECT_EQ(redispatched->len, 0u);
689 EXPECT_EQ(call_records.size(), 2u);
691 kLogicalKeyB,
"b",
false);
694 call_records[1].callback(
false);
695 EXPECT_EQ(redispatched->len, 1u);
699 call_records[0].callback(
false);
700 tester.flushChannelMessages();
701 EXPECT_EQ(redispatched->len, 2u);
707 call_records.clear();
710 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 2);
711 tester.flushChannelMessages();
712 EXPECT_EQ(call_records.size(), 0u);
718 0, FALSE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
720 tester.flushChannelMessages();
721 EXPECT_EQ(handler_handled,
true);
722 EXPECT_EQ(redispatched->len, 0u);
723 EXPECT_EQ(call_records.size(), 1u);
725 call_records[0].callback(
true);
729 TEST(FlKeyboardHandlerTest, SingleDelegateWithSyncResponds) {
730 KeyboardTester tester;
731 gboolean handler_handled =
false;
732 std::vector<CallRecord> call_records;
733 g_autoptr(GPtrArray) redispatched =
734 g_ptr_array_new_with_free_func(g_object_unref);
737 tester.respondToEmbedderCallsWithAndRecordsTo(
true, call_records);
738 tester.recordRedispatchedEventsTo(redispatched);
742 0,
TRUE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
744 tester.flushChannelMessages();
745 EXPECT_EQ(handler_handled,
true);
746 EXPECT_EQ(call_records.size(), 1u);
748 kLogicalKeyA,
"a",
false);
749 EXPECT_EQ(redispatched->len, 0u);
750 call_records.clear();
753 g_ptr_array_set_size(redispatched, 0);
756 tester.respondToEmbedderCallsWithAndRecordsTo(
false, call_records);
758 0, FALSE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
760 tester.flushChannelMessages();
761 EXPECT_EQ(handler_handled,
true);
762 EXPECT_EQ(call_records.size(), 1u);
764 kLogicalKeyA,
nullptr,
false);
765 EXPECT_EQ(redispatched->len, 1u);
766 call_records.clear();
770 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
771 EXPECT_EQ(call_records.size(), 0u);
776 TEST(FlKeyboardHandlerTest, WithTwoAsyncDelegates) {
777 KeyboardTester tester;
778 std::vector<CallRecord> call_records;
779 g_autoptr(GPtrArray) redispatched =
780 g_ptr_array_new_with_free_func(g_object_unref);
782 gboolean handler_handled =
false;
784 tester.recordEmbedderCallsTo(call_records);
785 tester.recordChannelCallsTo(call_records);
786 tester.recordRedispatchedEventsTo(redispatched);
791 0,
TRUE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
794 EXPECT_EQ(handler_handled,
true);
795 EXPECT_EQ(redispatched->len, 0u);
796 EXPECT_EQ(call_records.size(), 2u);
798 EXPECT_EQ(call_records[0].
type, CallRecord::kKeyCallEmbedder);
799 EXPECT_EQ(call_records[1].
type, CallRecord::kKeyCallChannel);
801 call_records[0].callback(
true);
802 call_records[1].callback(
false);
803 tester.flushChannelMessages();
804 EXPECT_EQ(redispatched->len, 0u);
807 call_records.clear();
811 0, FALSE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
814 EXPECT_EQ(handler_handled,
true);
815 EXPECT_EQ(redispatched->len, 0u);
816 EXPECT_EQ(call_records.size(), 2u);
818 EXPECT_EQ(call_records[0].
type, CallRecord::kKeyCallEmbedder);
819 EXPECT_EQ(call_records[1].
type, CallRecord::kKeyCallChannel);
821 call_records[0].callback(
false);
822 call_records[1].callback(
false);
824 call_records.clear();
827 tester.flushChannelMessages();
828 EXPECT_EQ(redispatched->len, 1u);
829 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
830 EXPECT_EQ(call_records.size(), 0u);
835 TEST(FlKeyboardHandlerTest, TextInputHandlerReturnsFalse) {
836 KeyboardTester tester;
837 g_autoptr(GPtrArray) redispatched =
838 g_ptr_array_new_with_free_func(g_object_unref);
839 gboolean handler_handled =
false;
840 tester.recordRedispatchedEventsTo(redispatched);
841 tester.respondToTextInputWith(
false);
845 0,
TRUE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
847 tester.flushChannelMessages();
848 EXPECT_EQ(handler_handled,
true);
850 EXPECT_EQ(redispatched->len, 1u);
853 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
858 TEST(FlKeyboardHandlerTest, TextInputHandlerReturnsTrue) {
859 KeyboardTester tester;
860 g_autoptr(GPtrArray) redispatched =
861 g_ptr_array_new_with_free_func(g_object_unref);
862 gboolean handler_handled =
false;
863 tester.recordRedispatchedEventsTo(redispatched);
864 tester.respondToTextInputWith(
true);
868 0,
TRUE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
870 tester.flushChannelMessages();
871 EXPECT_EQ(handler_handled,
true);
873 EXPECT_EQ(redispatched->len, 0u);
878 TEST(FlKeyboardHandlerTest, CorrectLogicalKeyForLayouts) {
879 KeyboardTester tester;
881 std::vector<CallRecord> call_records;
882 tester.recordEmbedderCallsTo(call_records);
884 auto sendTap = [&](guint8 keycode, guint keyval, guint8 group) {
886 0,
TRUE, keycode, keyval,
static_cast<GdkModifierType
>(0), group);
889 0, FALSE, keycode, keyval,
static_cast<GdkModifierType
>(0), group);
895 sendTap(kKeyCodeKeyA, GDK_KEY_a, 0);
898 sendTap(kKeyCodeKeyA, GDK_KEY_A, 0);
901 sendTap(kKeyCodeDigit1, GDK_KEY_1, 0);
904 sendTap(kKeyCodeDigit1, GDK_KEY_exclam, 0);
907 sendTap(kKeyCodeMinus, GDK_KEY_minus, 0);
910 sendTap(kKeyCodeMinus, GDK_KEY_underscore, 0);
916 tester.setLayout(kLayoutFrench);
918 sendTap(kKeyCodeKeyA, GDK_KEY_q, 3);
921 sendTap(kKeyCodeKeyA, GDK_KEY_Q, 3);
924 sendTap(kKeyCodeSemicolon, GDK_KEY_m, 3);
927 sendTap(kKeyCodeKeyM, GDK_KEY_comma, 3);
930 sendTap(kKeyCodeDigit1, GDK_KEY_ampersand, 3);
933 sendTap(kKeyCodeDigit1, GDK_KEY_1, 3);
936 sendTap(kKeyCodeMinus, GDK_KEY_parenright, 3);
939 sendTap(kKeyCodeMinus, GDK_KEY_degree, 3);
945 sendTap(kKeyCodeKeyA, GDK_KEY_a, 0);
948 sendTap(kKeyCodeDigit1, GDK_KEY_1, 0);
952 tester.setLayout(kLayoutRussian);
954 sendTap(kKeyCodeKeyA, GDK_KEY_Cyrillic_ef, 2);
957 sendTap(kKeyCodeDigit1, GDK_KEY_1, 2);
960 sendTap(kKeyCodeKeyLeftBracket, GDK_KEY_Cyrillic_ha, 2);
964 sendTap(kKeyCodeKeyA, GDK_KEY_a, 0);
967 sendTap(kKeyCodeKeyLeftBracket, GDK_KEY_bracketleft, 0);
971 TEST(FlKeyboardHandlerTest, SynthesizeModifiersIfNeeded) {
972 KeyboardTester tester;
973 std::vector<CallRecord> call_records;
974 tester.recordEmbedderCallsTo(call_records);
976 auto verifyModifierIsSynthesized = [&](GdkModifierType mask,
977 uint64_t physical, uint64_t logical) {
981 EXPECT_EQ(call_records.size(), 1u);
983 logical, NULL,
true);
987 EXPECT_EQ(call_records.size(), 2u);
988 EXPECT_KEY_EVENT(call_records[1], kFlutterKeyEventTypeUp, physical, logical,
990 call_records.clear();
996 EXPECT_EQ(call_records.size(), 0u);
997 call_records.clear();
1000 verifyModifierIsSynthesized(GDK_CONTROL_MASK, kPhysicalControlLeft,
1001 kLogicalControlLeft);
1002 verifyModifierIsSynthesized(GDK_META_MASK, kPhysicalMetaLeft,
1004 verifyModifierIsSynthesized(GDK_MOD1_MASK, kPhysicalAltLeft, kLogicalAltLeft);
1005 verifyModifierIsSynthesized(GDK_SHIFT_MASK, kPhysicalShiftLeft,
1009 TEST(FlKeyboardHandlerTest, GetPressedState) {
1010 KeyboardTester tester;
1011 tester.respondToTextInputWith(
true);
1015 0,
TRUE, kKeyCodeKeyA, GDK_KEY_a,
static_cast<GdkModifierType
>(0), 0);
1018 GHashTable* pressedState =
1020 EXPECT_EQ(g_hash_table_size(pressedState), 1u);
1022 gpointer physical_key =
1027 TEST(FlKeyboardHandlerTest, KeyboardChannelGetPressedState) {
1028 ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
1031 messenger, FL_KEYBOARD_VIEW_DELEGATE(fl_mock_view_delegate_new()));
1032 EXPECT_NE(handler,
nullptr);
1041 EXPECT_CALL(messenger,
1043 ::testing::Eq<FlBinaryMessenger*>(messenger), ::testing::_,
1044 MethodSuccessResponse(response), ::testing::_))
1045 .WillOnce(::testing::Return(
true));
1047 messenger.ReceiveMessage(kKeyboardChannelName, message);
1052 const MockGroupLayoutData kLayoutUs0{{
1054 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1055 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1056 0xffff, 0x0031, 0xffff, 0x0031, 0x0031, 0x0021, 0x0032, 0x0040,
1057 0x0033, 0x0023, 0x0034, 0x0024, 0x0035, 0x0025, 0x0036, 0x005e,
1058 0x0037, 0x0026, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029,
1059 0x002d, 0x005f, 0x003d, 0x002b, 0xffff, 0xffff, 0xffff, 0xffff,
1060 0x0071, 0x0051, 0x0077, 0x0057, 0x0065, 0x0045, 0x0072, 0x0052,
1061 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049,
1062 0x006f, 0x004f, 0x0070, 0x0050, 0x005b, 0x007b, 0x005d, 0x007d,
1063 0xffff, 0xffff, 0xffff, 0x0061, 0x0061, 0x0041, 0x0073, 0x0053,
1064 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048,
1065 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x003b, 0x003a,
1066 0x0027, 0x0022, 0x0060, 0x007e, 0xffff, 0x005c, 0x005c, 0x007c,
1067 0x007a, 0x005a, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056,
1068 0x0062, 0x0042, 0x006e, 0x004e, 0x006d, 0x004d, 0x002c, 0x003c,
1069 0x002e, 0x003e, 0x002f, 0x003f, 0xffff, 0xffff, 0xffff, 0xffff,
1070 0xffff, 0xffff, 0x0020, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1071 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1072 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1073 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1074 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1075 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1076 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1077 0xffff, 0xffff, 0x003c, 0x003e, 0x003c, 0x003e, 0xffff, 0xffff,
1078 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1079 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1080 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1081 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1082 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1083 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1084 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1085 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, 0xffff, 0xffff,
1088 const MockGroupLayoutData kLayoutRussian0{
1090 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1091 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1092 0x0000, 0xffff, 0xffff, 0x0031, 0x0031, 0x0021, 0x0032, 0x0040,
1093 0x0033, 0x0023, 0x0034, 0x0024, 0x0035, 0x0025, 0x0036, 0x005e,
1094 0x0037, 0x0026, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029,
1095 0x002d, 0x005f, 0x003d, 0x002b, 0xffff, 0xffff, 0xffff, 0xffff,
1096 0x0071, 0x0051, 0x0077, 0x0057, 0x0065, 0x0045, 0x0072, 0x0052,
1097 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049,
1098 0x006f, 0x004f, 0x0070, 0x0050, 0x005b, 0x007b, 0x005d, 0x007d,
1099 0xffff, 0xffff, 0xffff, 0x0061, 0x0061, 0x0041, 0x0073, 0x0053,
1100 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048,
1101 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x003b, 0x003a,
1102 0x0027, 0x0022, 0x0060, 0x007e, 0xffff, 0x005c, 0x005c, 0x007c,
1103 0x007a, 0x005a, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056,
1104 0x0062, 0x0042, 0x006e, 0x004e, 0x006d, 0x004d, 0x002c, 0x003c,
1105 0x002e, 0x003e, 0x002f, 0x003f, 0xffff, 0xffff, 0xffff, 0xffff,
1106 0xffff, 0xffff, 0x0020, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1107 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1108 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1109 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1110 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1111 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1112 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1113 0xffff, 0xffff, 0x0000, 0xffff, 0x003c, 0x003e, 0xffff, 0xffff,
1114 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1115 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff,
1116 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1117 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1118 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1119 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1120 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1121 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, 0xffff, 0xffff,
1124 const MockGroupLayoutData kLayoutRussian2{{
1126 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1127 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1128 0xffff, 0x0031, 0x0021, 0x0000, 0x0031, 0x0021, 0x0032, 0x0022,
1129 0x0033, 0x06b0, 0x0034, 0x003b, 0x0035, 0x0025, 0x0036, 0x003a,
1130 0x0037, 0x003f, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029,
1131 0x002d, 0x005f, 0x003d, 0x002b, 0x0071, 0x0051, 0x0000, 0x0000,
1132 0x06ca, 0x06ea, 0x06c3, 0x06e3, 0x06d5, 0x06f5, 0x06cb, 0x06eb,
1133 0x06c5, 0x06e5, 0x06ce, 0x06ee, 0x06c7, 0x06e7, 0x06db, 0x06fb,
1134 0x06dd, 0x06fd, 0x06da, 0x06fa, 0x06c8, 0x06e8, 0x06df, 0x06ff,
1135 0x0061, 0x0041, 0x0041, 0x0000, 0x06c6, 0x06e6, 0x06d9, 0x06f9,
1136 0x06d7, 0x06f7, 0x06c1, 0x06e1, 0x06d0, 0x06f0, 0x06d2, 0x06f2,
1137 0x06cf, 0x06ef, 0x06cc, 0x06ec, 0x06c4, 0x06e4, 0x06d6, 0x06f6,
1138 0x06dc, 0x06fc, 0x06a3, 0x06b3, 0x007c, 0x0000, 0x005c, 0x002f,
1139 0x06d1, 0x06f1, 0x06de, 0x06fe, 0x06d3, 0x06f3, 0x06cd, 0x06ed,
1140 0x06c9, 0x06e9, 0x06d4, 0x06f4, 0x06d8, 0x06f8, 0x06c2, 0x06e2,
1141 0x06c0, 0x06e0, 0x002e, 0x002c, 0xffff, 0xffff, 0xffff, 0xffff,
1142 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1143 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1144 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1145 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1146 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1147 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1148 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1149 0xffff, 0xffff, 0x003c, 0x003e, 0x002f, 0x007c, 0xffff, 0xffff,
1150 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1151 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1152 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0x0000,
1153 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1154 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1155 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1156 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x00b1,
1157 0x00b1, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1160 const MockGroupLayoutData kLayoutFrench0 = {
1162 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1163 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1164 0x0000, 0xffff, 0xffff, 0x0031, 0x0031, 0x0021, 0x0032, 0x0040,
1165 0x0033, 0x0023, 0x0034, 0x0024, 0x0035, 0x0025, 0x0036, 0x005e,
1166 0x0037, 0x0026, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029,
1167 0x002d, 0x005f, 0x003d, 0x002b, 0xffff, 0xffff, 0xffff, 0xffff,
1168 0x0071, 0x0051, 0x0077, 0x0057, 0x0065, 0x0045, 0x0072, 0x0052,
1169 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049,
1170 0x006f, 0x004f, 0x0070, 0x0050, 0x005b, 0x007b, 0x005d, 0x007d,
1171 0xffff, 0xffff, 0xffff, 0x0061, 0x0061, 0x0041, 0x0073, 0x0053,
1172 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048,
1173 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x003b, 0x003a,
1174 0x0027, 0x0022, 0x0060, 0x007e, 0xffff, 0x005c, 0x005c, 0x007c,
1175 0x007a, 0x005a, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056,
1176 0x0062, 0x0042, 0x006e, 0x004e, 0x006d, 0x004d, 0x002c, 0x003c,
1177 0x002e, 0x003e, 0x002f, 0x003f, 0xffff, 0xffff, 0xffff, 0xffff,
1178 0xffff, 0xffff, 0x0020, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1179 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1180 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1181 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1182 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1183 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1184 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1185 0xffff, 0xffff, 0x0000, 0xffff, 0x003c, 0x003e, 0xffff, 0xffff,
1186 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1187 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff,
1188 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1189 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1190 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1191 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1192 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1193 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, 0xffff, 0xffff,
1196 const MockGroupLayoutData kLayoutFrench3 = {
1198 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1199 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff,
1200 0x0000, 0xffff, 0x0000, 0x0000, 0x0026, 0x0031, 0x00e9, 0x0032,
1201 0x0022, 0x0033, 0x0027, 0x0034, 0x0028, 0x0035, 0x002d, 0x0036,
1202 0x00e8, 0x0037, 0x005f, 0x0038, 0x00e7, 0x0039, 0x00e0, 0x0030,
1203 0x0029, 0x00b0, 0x003d, 0x002b, 0x0000, 0x0000, 0x0061, 0x0041,
1204 0x0061, 0x0041, 0x007a, 0x005a, 0x0065, 0x0045, 0x0072, 0x0052,
1205 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049,
1206 0x006f, 0x004f, 0x0070, 0x0050, 0xffff, 0xffff, 0x0024, 0x00a3,
1207 0x0041, 0x0000, 0x0000, 0x0000, 0x0071, 0x0051, 0x0073, 0x0053,
1208 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048,
1209 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x006d, 0x004d,
1210 0x00f9, 0x0025, 0x00b2, 0x007e, 0x0000, 0x0000, 0x002a, 0x00b5,
1211 0x0077, 0x0057, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056,
1212 0x0062, 0x0042, 0x006e, 0x004e, 0x002c, 0x003f, 0x003b, 0x002e,
1213 0x003a, 0x002f, 0x0021, 0x00a7, 0xffff, 0xffff, 0xffff, 0xffff,
1214 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1215 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1216 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1217 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1218 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1219 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1220 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1221 0xffff, 0x003c, 0x0000, 0xffff, 0x003c, 0x003e, 0xffff, 0xffff,
1222 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1223 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff,
1224 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1225 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1226 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1227 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1228 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff,
1229 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
1232 const MockLayoutData kLayoutUs{&kLayoutUs0};
1233 const MockLayoutData kLayoutRussian{&kLayoutRussian0,
nullptr,
1235 const MockLayoutData kLayoutFrench{&kLayoutFrench0,
nullptr,
nullptr,