| Flutter Linux Embedder |

fl_keyboard_manager_test.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/shell/platform/linux/fl_keyboard_manager.h"
6
7 #include <cstring>
8 #include <vector>
9
10 #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"
14 #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"
19 #include "flutter/shell/platform/linux/testing/mock_text_input_plugin.h"
20 #include "flutter/testing/testing.h"
21
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24
25 // Define compound `expect` in macros. If they were defined in functions, the
26 // stacktrace wouldn't print where the function is called in the unit tests.
27
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));
35
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); \
42 call_records.clear()
43
44 namespace {
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;
60
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;
67
68 // Hardware key codes.
69 typedef std::function<void(bool handled)> AsyncKeyCallback;
70 typedef std::function<void(AsyncKeyCallback callback)> ChannelCallHandler;
71 typedef std::function<void(const FlutterKeyEvent* event,
72 AsyncKeyCallback callback)>
73 EmbedderCallHandler;
74 typedef std::function<void(std::unique_ptr<FlKeyEvent>)> RedispatchHandler;
75
76 // A type that can record all kinds of effects that the keyboard manager
77 // triggers.
78 //
79 // An instance of `CallRecord` might not have all the fields filled.
80 typedef struct {
81 enum {
82 kKeyCallEmbedder,
83 kKeyCallChannel,
84 } type;
85
86 AsyncKeyCallback callback;
87 std::unique_ptr<FlutterKeyEvent> event;
88 std::unique_ptr<char[]> event_character;
89 } CallRecord;
90
91 // Clone a C-string.
92 //
93 // Must be deleted by delete[].
94 char* cloneString(const char* source) {
95 if (source == nullptr) {
96 return nullptr;
97 }
98 size_t charLen = strlen(source);
99 char* target = new char[charLen + 1];
100 strncpy(target, source, charLen + 1);
101 return target;
102 }
103
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;
111
112 static 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;
117
118 // All key clues for a keyboard layout.
119 //
120 // The index is (keyCode * 2 + hasShift), where each value is the character for
121 // this key (GTK only supports UTF-16.) Since the maximum keycode of interest
122 // is 128, it has a total of 256 entries..
123 typedef std::array<uint32_t, 256> MockGroupLayoutData;
124 typedef std::vector<const MockGroupLayoutData*> MockLayoutData;
125
126 extern const MockLayoutData kLayoutUs;
127 extern const MockLayoutData kLayoutRussian;
128 extern const MockLayoutData kLayoutFrench;
129
130 G_BEGIN_DECLS
131
132 G_DECLARE_FINAL_TYPE(FlMockViewDelegate,
133 fl_mock_view_delegate,
134 FL,
135 MOCK_VIEW_DELEGATE,
136 GObject);
137
138 G_DECLARE_FINAL_TYPE(FlMockKeyBinaryMessenger,
139 fl_mock_key_binary_messenger,
140 FL,
141 MOCK_KEY_BINARY_MESSENGER,
142 GObject)
143
144 G_END_DECLS
145
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
159 /***** FlMockKeyBinaryMessenger *****/
160 /* Mock a binary messenger that only processes messages from the embedding on
161 * the key event channel, and does so according to the callback set by
162 * fl_mock_key_binary_messenger_set_callback_handler */
163
164 struct _FlMockKeyBinaryMessenger {
165 GObject parent_instance;
166
167 ChannelCallHandler callback_handler;
168 };
169
170 static void fl_mock_key_binary_messenger_iface_init(
171 FlBinaryMessengerInterface* iface);
172
173 G_DEFINE_TYPE_WITH_CODE(
174 FlMockKeyBinaryMessenger,
175 fl_mock_key_binary_messenger,
176 G_TYPE_OBJECT,
177 G_IMPLEMENT_INTERFACE(fl_binary_messenger_get_type(),
178 fl_mock_key_binary_messenger_iface_init))
179
180 static void fl_mock_key_binary_messenger_class_init(
181 FlMockKeyBinaryMessengerClass* klass) {}
182
183 static void fl_mock_key_binary_messenger_send_on_channel(
184 FlBinaryMessenger* messenger,
185 const gchar* channel,
186 GBytes* message,
187 GCancellable* cancellable,
188 GAsyncReadyCallback callback,
189 gpointer user_data) {
190 FlMockKeyBinaryMessenger* self = FL_MOCK_KEY_BINARY_MESSENGER(messenger);
191
192 if (callback != nullptr) {
193 EXPECT_STREQ(channel, kKeyEventChannelName);
194 self->callback_handler([self, cancellable, callback,
195 user_data](bool handled) {
196 g_autoptr(GTask) task =
197 g_task_new(self, cancellable, callback, user_data);
198 g_autoptr(FlValue) result = fl_value_new_map();
199 fl_value_set_string_take(result, "handled", fl_value_new_bool(handled));
200 g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
201 g_autoptr(GError) error = nullptr;
202 GBytes* data = fl_message_codec_encode_message(FL_MESSAGE_CODEC(codec),
203 result, &error);
204
205 g_task_return_pointer(task, data,
206 reinterpret_cast<GDestroyNotify>(g_bytes_unref));
207 });
208 }
209 }
210
211 static GBytes* fl_mock_key_binary_messenger_send_on_channel_finish(
212 FlBinaryMessenger* messenger,
213 GAsyncResult* result,
214 GError** error) {
215 return static_cast<GBytes*>(g_task_propagate_pointer(G_TASK(result), error));
216 }
217
218 static void fl_mock_binary_messenger_resize_channel(
219 FlBinaryMessenger* messenger,
220 const gchar* channel,
221 int64_t new_size) {
222 // Mock implementation. Do nothing.
223 }
224
225 static void fl_mock_binary_messenger_set_warns_on_channel_overflow(
226 FlBinaryMessenger* messenger,
227 const gchar* channel,
228 bool warns) {
229 // Mock implementation. Do nothing.
230 }
231
232 static void fl_mock_key_binary_messenger_iface_init(
233 FlBinaryMessengerInterface* iface) {
234 iface->set_message_handler_on_channel =
235 [](FlBinaryMessenger* messenger, const gchar* channel,
236 FlBinaryMessengerMessageHandler handler, gpointer user_data,
237 GDestroyNotify destroy_notify) {
238 EXPECT_STREQ(channel, kKeyEventChannelName);
239 // No need to mock. The key event channel expects no incoming messages
240 // from the framework.
241 };
242 iface->send_response = [](FlBinaryMessenger* messenger,
243 FlBinaryMessengerResponseHandle* response_handle,
244 GBytes* response, GError** error) -> gboolean {
245 // The key event channel expects no incoming messages from the framework,
246 // hence no responses either.
247 g_return_val_if_reached(TRUE);
248 return TRUE;
249 };
250 iface->send_on_channel = fl_mock_key_binary_messenger_send_on_channel;
251 iface->send_on_channel_finish =
252 fl_mock_key_binary_messenger_send_on_channel_finish;
253 iface->resize_channel = fl_mock_binary_messenger_resize_channel;
254 iface->set_warns_on_channel_overflow =
255 fl_mock_binary_messenger_set_warns_on_channel_overflow;
256 }
257
258 static void fl_mock_key_binary_messenger_init(FlMockKeyBinaryMessenger* self) {}
259
260 static FlMockKeyBinaryMessenger* fl_mock_key_binary_messenger_new() {
261 FlMockKeyBinaryMessenger* self = FL_MOCK_KEY_BINARY_MESSENGER(
262 g_object_new(fl_mock_key_binary_messenger_get_type(), NULL));
263
264 // Added to stop compiler complaining about an unused function.
265 FL_IS_MOCK_KEY_BINARY_MESSENGER(self);
266
267 return self;
268 }
269
270 static void fl_mock_key_binary_messenger_set_callback_handler(
271 FlMockKeyBinaryMessenger* self,
272 ChannelCallHandler handler) {
273 self->callback_handler = std::move(handler);
274 }
275
276 /***** FlMockViewDelegate *****/
277
278 struct _FlMockViewDelegate {
279 GObject parent_instance;
280
281 FlMockKeyBinaryMessenger* messenger;
282 EmbedderCallHandler embedder_handler;
283 bool text_filter_result;
284 RedispatchHandler redispatch_handler;
285 KeyboardLayoutNotifier layout_notifier;
286 const MockLayoutData* layout_data;
287 };
288
289 static void fl_mock_view_keyboard_delegate_iface_init(
290 FlKeyboardViewDelegateInterface* iface);
291
292 G_DEFINE_TYPE_WITH_CODE(
293 FlMockViewDelegate,
294 fl_mock_view_delegate,
295 G_TYPE_OBJECT,
296 G_IMPLEMENT_INTERFACE(fl_keyboard_view_delegate_get_type(),
297 fl_mock_view_keyboard_delegate_iface_init))
298
299 static void fl_mock_view_delegate_init(FlMockViewDelegate* self) {}
300
301 static void fl_mock_view_delegate_dispose(GObject* object) {
302 FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(object);
303
304 g_clear_object(&self->messenger);
305
306 G_OBJECT_CLASS(fl_mock_view_delegate_parent_class)->dispose(object);
307 }
308
309 static void fl_mock_view_delegate_class_init(FlMockViewDelegateClass* klass) {
310 G_OBJECT_CLASS(klass)->dispose = fl_mock_view_delegate_dispose;
311 }
312
313 static FlKeyEvent* fl_key_event_clone_information_only(FlKeyEvent* event);
314
315 static void fl_mock_view_keyboard_send_key_event(
316 FlKeyboardViewDelegate* view_delegate,
317 const FlutterKeyEvent* event,
318 FlutterKeyEventCallback callback,
319 void* user_data) {
320 FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(view_delegate);
321 self->embedder_handler(event, [callback, user_data](bool handled) {
322 if (callback != nullptr) {
323 callback(handled, user_data);
324 }
325 });
326 }
327
328 static gboolean fl_mock_view_keyboard_text_filter_key_press(
329 FlKeyboardViewDelegate* view_delegate,
330 FlKeyEvent* event) {
331 FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(view_delegate);
332 return self->text_filter_result;
333 }
334
335 static FlBinaryMessenger* fl_mock_view_keyboard_get_messenger(
336 FlKeyboardViewDelegate* view_delegate) {
337 FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(view_delegate);
338 return FL_BINARY_MESSENGER(self->messenger);
339 }
340
341 static void fl_mock_view_keyboard_redispatch_event(
342 FlKeyboardViewDelegate* view_delegate,
343 std::unique_ptr<FlKeyEvent> event) {
344 FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(view_delegate);
345 if (self->redispatch_handler) {
346 self->redispatch_handler(std::move(event));
347 }
348 }
349
350 static void fl_mock_view_keyboard_subscribe_to_layout_change(
351 FlKeyboardViewDelegate* delegate,
352 KeyboardLayoutNotifier notifier) {
353 FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(delegate);
354 self->layout_notifier = std::move(notifier);
355 }
356
357 static guint fl_mock_view_keyboard_lookup_key(FlKeyboardViewDelegate* delegate,
358 const GdkKeymapKey* key) {
359 FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(delegate);
360 guint8 group = static_cast<guint8>(key->group);
361 EXPECT_LT(group, self->layout_data->size());
362 const MockGroupLayoutData* group_layout = (*self->layout_data)[group];
363 EXPECT_TRUE(group_layout != nullptr);
364 EXPECT_TRUE(key->level == 0 || key->level == 1);
365 bool shift = key->level == 1;
366 return (*group_layout)[key->keycode * 2 + shift];
367 }
368
369 static GHashTable* fl_mock_view_keyboard_get_keyboard_state(
370 FlKeyboardViewDelegate* view_delegate) {
371 GHashTable* result = g_hash_table_new(g_direct_hash, g_direct_equal);
372 g_hash_table_insert(result, reinterpret_cast<gpointer>(kMockPhysicalKey),
373 reinterpret_cast<gpointer>(kMockLogicalKey));
374
375 return result;
376 }
377
378 static void fl_mock_view_keyboard_delegate_iface_init(
379 FlKeyboardViewDelegateInterface* iface) {
380 iface->send_key_event = fl_mock_view_keyboard_send_key_event;
381 iface->text_filter_key_press = fl_mock_view_keyboard_text_filter_key_press;
382 iface->get_messenger = fl_mock_view_keyboard_get_messenger;
383 iface->redispatch_event = fl_mock_view_keyboard_redispatch_event;
384 iface->subscribe_to_layout_change =
385 fl_mock_view_keyboard_subscribe_to_layout_change;
386 iface->lookup_key = fl_mock_view_keyboard_lookup_key;
387 iface->get_keyboard_state = fl_mock_view_keyboard_get_keyboard_state;
388 }
389
390 static FlMockViewDelegate* fl_mock_view_delegate_new() {
391 FlMockViewDelegate* self = FL_MOCK_VIEW_DELEGATE(
392 g_object_new(fl_mock_view_delegate_get_type(), nullptr));
393
394 // Added to stop compiler complaining about an unused function.
395 FL_IS_MOCK_VIEW_DELEGATE(self);
396
397 self->messenger = fl_mock_key_binary_messenger_new();
398
399 return self;
400 }
401
402 static void fl_mock_view_set_embedder_handler(FlMockViewDelegate* self,
403 EmbedderCallHandler handler) {
404 self->embedder_handler = std::move(handler);
405 }
406
407 static void fl_mock_view_set_text_filter_result(FlMockViewDelegate* self,
408 bool result) {
409 self->text_filter_result = result;
410 }
411
412 static void fl_mock_view_set_redispatch_handler(FlMockViewDelegate* self,
413 RedispatchHandler handler) {
414 self->redispatch_handler = std::move(handler);
415 }
416
417 static void fl_mock_view_set_layout(FlMockViewDelegate* self,
418 const MockLayoutData* layout) {
419 self->layout_data = layout;
420 if (self->layout_notifier != nullptr) {
421 self->layout_notifier();
422 }
423 }
424
425 /***** End FlMockViewDelegate *****/
426
427 // Return a newly allocated #FlKeyEvent that is a clone to the given #event
428 // but with #origin and #dispose set to 0.
429 static FlKeyEvent* fl_key_event_clone_information_only(FlKeyEvent* event) {
430 FlKeyEvent* new_event = fl_key_event_clone(event);
431 new_event->origin = nullptr;
432 new_event->dispose_origin = nullptr;
433 return new_event;
434 }
435
436 // Create a new #FlKeyEvent with the given information.
437 //
438 // The #origin will be another #FlKeyEvent with the exact information,
439 // so that it can be used to redispatch, and is freed upon disposal.
440 static FlKeyEvent* fl_key_event_new_by_mock(bool is_press,
441 guint keyval,
442 guint16 keycode,
443 int state,
444 gboolean is_modifier,
445 guint8 group = 0) {
446 FlKeyEvent* event = g_new(FlKeyEvent, 1);
447 event->is_press = is_press;
448 event->time = 0;
449 event->state = state;
450 event->keyval = keyval;
451 event->string = nullptr;
452 event->group = group;
453 event->keycode = keycode;
454 FlKeyEvent* origin_event = fl_key_event_clone_information_only(event);
455 event->origin = origin_event;
456 event->dispose_origin = [](gpointer origin) { g_free(origin); };
457 return event;
458 }
459
460 class KeyboardTester {
461 public:
462 KeyboardTester() {
463 ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
464
465 view_ = fl_mock_view_delegate_new();
466 respondToEmbedderCallsWith(false);
467 respondToChannelCallsWith(false);
468 respondToTextInputWith(false);
469 setLayout(kLayoutUs);
470
471 manager_ =
472 fl_keyboard_manager_new(messenger, FL_KEYBOARD_VIEW_DELEGATE(view_));
473 }
474
475 ~KeyboardTester() {
476 g_clear_object(&view_);
477 g_clear_object(&manager_);
478 }
479
480 FlKeyboardManager* manager() { return manager_; }
481
482 // Block until all GdkMainLoop messages are processed, which is basically
483 // used only for channel messages.
484 void flushChannelMessages() {
485 GMainLoop* loop = g_main_loop_new(nullptr, 0);
486 g_idle_add(_flushChannelMessagesCb, loop);
487 g_main_loop_run(loop);
488 }
489
490 // Dispatch each of the given events, expect their results to be false
491 // (unhandled), and clear the event array.
492 //
493 // Returns the number of events redispatched. If any result is unexpected
494 // (handled), return a minus number `-x` instead, where `x` is the index of
495 // the first unexpected redispatch.
496 int redispatchEventsAndClear(
497 std::vector<std::unique_ptr<FlKeyEvent>>& events) {
498 size_t event_count = events.size();
499 int first_error = -1;
500 during_redispatch_ = true;
501 for (size_t event_id = 0; event_id < event_count; event_id += 1) {
502 bool handled = fl_keyboard_manager_handle_event(
503 manager_, events[event_id].release());
504 EXPECT_FALSE(handled);
505 if (handled) {
506 first_error = first_error == -1 ? event_id : first_error;
507 }
508 }
509 during_redispatch_ = false;
510 events.clear();
511 return first_error < 0 ? event_count : -first_error;
512 }
513
514 void respondToEmbedderCallsWith(bool response) {
515 fl_mock_view_set_embedder_handler(
516 view_, [response, this](const FlutterKeyEvent* event,
517 const AsyncKeyCallback& callback) {
518 EXPECT_FALSE(during_redispatch_);
519 callback(response);
520 });
521 }
522
523 void recordEmbedderCallsTo(std::vector<CallRecord>& storage) {
524 fl_mock_view_set_embedder_handler(
525 view_, [&storage, this](const FlutterKeyEvent* event,
526 AsyncKeyCallback callback) {
527 EXPECT_FALSE(during_redispatch_);
528 auto new_event = std::make_unique<FlutterKeyEvent>(*event);
529 char* new_event_character = cloneString(event->character);
530 new_event->character = new_event_character;
531 storage.push_back(CallRecord{
532 .type = CallRecord::kKeyCallEmbedder,
533 .callback = std::move(callback),
534 .event = std::move(new_event),
535 .event_character = std::unique_ptr<char[]>(new_event_character),
536 });
537 });
538 }
539
540 void respondToEmbedderCallsWithAndRecordsTo(
541 bool response,
542 std::vector<CallRecord>& storage) {
543 fl_mock_view_set_embedder_handler(
544 view_, [&storage, response, this](const FlutterKeyEvent* event,
545 const AsyncKeyCallback& callback) {
546 EXPECT_FALSE(during_redispatch_);
547 auto new_event = std::make_unique<FlutterKeyEvent>(*event);
548 char* new_event_character = cloneString(event->character);
549 new_event->character = new_event_character;
550 storage.push_back(CallRecord{
551 .type = CallRecord::kKeyCallEmbedder,
552 .event = std::move(new_event),
553 .event_character = std::unique_ptr<char[]>(new_event_character),
554 });
555 callback(response);
556 });
557 }
558
559 void respondToChannelCallsWith(bool response) {
560 fl_mock_key_binary_messenger_set_callback_handler(
561 view_->messenger, [response, this](const AsyncKeyCallback& callback) {
562 EXPECT_FALSE(during_redispatch_);
563 callback(response);
564 });
565 }
566
567 void recordChannelCallsTo(std::vector<CallRecord>& storage) {
568 fl_mock_key_binary_messenger_set_callback_handler(
569 view_->messenger, [&storage, this](AsyncKeyCallback callback) {
570 EXPECT_FALSE(during_redispatch_);
571 storage.push_back(CallRecord{
572 .type = CallRecord::kKeyCallChannel,
573 .callback = std::move(callback),
574 });
575 });
576 }
577
578 void respondToTextInputWith(bool response) {
579 fl_mock_view_set_text_filter_result(view_, response);
580 }
581
582 void recordRedispatchedEventsTo(
583 std::vector<std::unique_ptr<FlKeyEvent>>& storage) {
584 fl_mock_view_set_redispatch_handler(
585 view_, [&storage](std::unique_ptr<FlKeyEvent> key) {
586 storage.push_back(std::move(key));
587 });
588 }
589
590 void setLayout(const MockLayoutData& layout) {
591 fl_mock_view_set_layout(view_, &layout);
592 }
593
594 private:
595 FlMockViewDelegate* view_;
596 FlKeyboardManager* manager_;
597 bool during_redispatch_ = false;
598
599 static gboolean _flushChannelMessagesCb(gpointer data) {
600 g_autoptr(GMainLoop) loop = reinterpret_cast<GMainLoop*>(data);
601 g_main_loop_quit(loop);
602 return FALSE;
603 }
604 };
605
606 // Make sure that the keyboard can be disposed without crashes when there are
607 // unresolved pending events.
608 TEST(FlKeyboardManagerTest, DisposeWithUnresolvedPends) {
609 KeyboardTester tester;
610 std::vector<CallRecord> call_records;
611
612 // Record calls so that they aren't responded.
613 tester.recordEmbedderCallsTo(call_records);
614 fl_keyboard_manager_handle_event(
615 tester.manager(),
616 fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
617
618 tester.respondToEmbedderCallsWith(true);
619 fl_keyboard_manager_handle_event(
620 tester.manager(),
621 fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
622
623 tester.flushChannelMessages();
624
625 // Passes if the cleanup does not crash.
626 }
627
628 TEST(FlKeyboardManagerTest, SingleDelegateWithAsyncResponds) {
629 KeyboardTester tester;
630 std::vector<CallRecord> call_records;
631 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
632
633 gboolean manager_handled = false;
634
635 /// Test 1: One event that is handled by the framework
636 tester.recordEmbedderCallsTo(call_records);
637 tester.recordRedispatchedEventsTo(redispatched);
638
639 // Dispatch a key event
640 manager_handled = fl_keyboard_manager_handle_event(
641 tester.manager(),
642 fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
643 tester.flushChannelMessages();
644 EXPECT_EQ(manager_handled, true);
645 EXPECT_EQ(redispatched.size(), 0u);
646 EXPECT_EQ(call_records.size(), 1u);
647 EXPECT_KEY_EVENT(call_records[0], kFlutterKeyEventTypeDown, kPhysicalKeyA,
648 kLogicalKeyA, "a", false);
649
650 call_records[0].callback(true);
651 tester.flushChannelMessages();
652 EXPECT_EQ(redispatched.size(), 0u);
653 EXPECT_TRUE(fl_keyboard_manager_is_state_clear(tester.manager()));
654 call_records.clear();
655
656 /// Test 2: Two events that are unhandled by the framework
657 manager_handled = fl_keyboard_manager_handle_event(
658 tester.manager(),
659 fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
660 tester.flushChannelMessages();
661 EXPECT_EQ(manager_handled, true);
662 EXPECT_EQ(redispatched.size(), 0u);
663 EXPECT_EQ(call_records.size(), 1u);
664 EXPECT_KEY_EVENT(call_records[0], kFlutterKeyEventTypeUp, kPhysicalKeyA,
665 kLogicalKeyA, nullptr, false);
666
667 // Dispatch another key event
668 manager_handled = fl_keyboard_manager_handle_event(
669 tester.manager(),
670 fl_key_event_new_by_mock(true, GDK_KEY_b, kKeyCodeKeyB, 0x0, false));
671 tester.flushChannelMessages();
672 EXPECT_EQ(manager_handled, true);
673 EXPECT_EQ(redispatched.size(), 0u);
674 EXPECT_EQ(call_records.size(), 2u);
675 EXPECT_KEY_EVENT(call_records[1], kFlutterKeyEventTypeDown, kPhysicalKeyB,
676 kLogicalKeyB, "b", false);
677
678 // Resolve the second event first to test out-of-order response
679 call_records[1].callback(false);
680 EXPECT_EQ(redispatched.size(), 1u);
681 EXPECT_EQ(redispatched[0]->keyval, 0x62u);
682 call_records[0].callback(false);
683 tester.flushChannelMessages();
684 EXPECT_EQ(redispatched.size(), 2u);
685 EXPECT_EQ(redispatched[1]->keyval, 0x61u);
686
687 EXPECT_FALSE(fl_keyboard_manager_is_state_clear(tester.manager()));
688 call_records.clear();
689
690 // Resolve redispatches
691 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 2);
692 tester.flushChannelMessages();
693 EXPECT_EQ(call_records.size(), 0u);
694 EXPECT_TRUE(fl_keyboard_manager_is_state_clear(tester.manager()));
695
696 /// Test 3: Dispatch the same event again to ensure that prevention from
697 /// redispatching only works once.
698 manager_handled = fl_keyboard_manager_handle_event(
699 tester.manager(),
700 fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
701 tester.flushChannelMessages();
702 EXPECT_EQ(manager_handled, true);
703 EXPECT_EQ(redispatched.size(), 0u);
704 EXPECT_EQ(call_records.size(), 1u);
705
706 call_records[0].callback(true);
707 EXPECT_TRUE(fl_keyboard_manager_is_state_clear(tester.manager()));
708 }
709
710 TEST(FlKeyboardManagerTest, SingleDelegateWithSyncResponds) {
711 KeyboardTester tester;
712 gboolean manager_handled = false;
713 std::vector<CallRecord> call_records;
714 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
715
716 /// Test 1: One event that is handled by the framework
717 tester.respondToEmbedderCallsWithAndRecordsTo(true, call_records);
718 tester.recordRedispatchedEventsTo(redispatched);
719
720 // Dispatch a key event
721 manager_handled = fl_keyboard_manager_handle_event(
722 tester.manager(),
723 fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
724 tester.flushChannelMessages();
725 EXPECT_EQ(manager_handled, true);
726 EXPECT_EQ(call_records.size(), 1u);
727 EXPECT_KEY_EVENT(call_records[0], kFlutterKeyEventTypeDown, kPhysicalKeyA,
728 kLogicalKeyA, "a", false);
729 EXPECT_EQ(redispatched.size(), 0u);
730 call_records.clear();
731
732 EXPECT_TRUE(fl_keyboard_manager_is_state_clear(tester.manager()));
733 redispatched.clear();
734
735 /// Test 2: An event unhandled by the framework
736 tester.respondToEmbedderCallsWithAndRecordsTo(false, call_records);
737 manager_handled = fl_keyboard_manager_handle_event(
738 tester.manager(),
739 fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
740 tester.flushChannelMessages();
741 EXPECT_EQ(manager_handled, true);
742 EXPECT_EQ(call_records.size(), 1u);
743 EXPECT_KEY_EVENT(call_records[0], kFlutterKeyEventTypeUp, kPhysicalKeyA,
744 kLogicalKeyA, nullptr, false);
745 EXPECT_EQ(redispatched.size(), 1u);
746 call_records.clear();
747
748 EXPECT_FALSE(fl_keyboard_manager_is_state_clear(tester.manager()));
749
750 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
751 EXPECT_EQ(call_records.size(), 0u);
752
753 EXPECT_TRUE(fl_keyboard_manager_is_state_clear(tester.manager()));
754 }
755
756 TEST(FlKeyboardManagerTest, WithTwoAsyncDelegates) {
757 KeyboardTester tester;
758 std::vector<CallRecord> call_records;
759 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
760
761 gboolean manager_handled = false;
762
763 tester.recordEmbedderCallsTo(call_records);
764 tester.recordChannelCallsTo(call_records);
765 tester.recordRedispatchedEventsTo(redispatched);
766
767 /// Test 1: One delegate responds true, the other false
768
769 manager_handled = fl_keyboard_manager_handle_event(
770 tester.manager(),
771 fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
772
773 EXPECT_EQ(manager_handled, true);
774 EXPECT_EQ(redispatched.size(), 0u);
775 EXPECT_EQ(call_records.size(), 2u);
776
777 EXPECT_EQ(call_records[0].type, CallRecord::kKeyCallEmbedder);
778 EXPECT_EQ(call_records[1].type, CallRecord::kKeyCallChannel);
779
780 call_records[0].callback(true);
781 call_records[1].callback(false);
782 tester.flushChannelMessages();
783 EXPECT_EQ(redispatched.size(), 0u);
784
785 EXPECT_TRUE(fl_keyboard_manager_is_state_clear(tester.manager()));
786 call_records.clear();
787
788 /// Test 2: All delegates respond false
789 manager_handled = fl_keyboard_manager_handle_event(
790 tester.manager(),
791 fl_key_event_new_by_mock(false, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
792
793 EXPECT_EQ(manager_handled, true);
794 EXPECT_EQ(redispatched.size(), 0u);
795 EXPECT_EQ(call_records.size(), 2u);
796
797 EXPECT_EQ(call_records[0].type, CallRecord::kKeyCallEmbedder);
798 EXPECT_EQ(call_records[1].type, CallRecord::kKeyCallChannel);
799
800 call_records[0].callback(false);
801 call_records[1].callback(false);
802
803 call_records.clear();
804
805 // Resolve redispatch
806 tester.flushChannelMessages();
807 EXPECT_EQ(redispatched.size(), 1u);
808 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
809 EXPECT_EQ(call_records.size(), 0u);
810
811 EXPECT_TRUE(fl_keyboard_manager_is_state_clear(tester.manager()));
812 }
813
814 TEST(FlKeyboardManagerTest, TextInputPluginReturnsFalse) {
815 KeyboardTester tester;
816 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
817 gboolean manager_handled = false;
818 tester.recordRedispatchedEventsTo(redispatched);
819 tester.respondToTextInputWith(false);
820
821 // Dispatch a key event.
822 manager_handled = fl_keyboard_manager_handle_event(
823 tester.manager(),
824 fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA, 0, false));
825 tester.flushChannelMessages();
826 EXPECT_EQ(manager_handled, true);
827 // The event was redispatched because no one handles it.
828 EXPECT_EQ(redispatched.size(), 1u);
829
830 // Resolve redispatched event.
831 EXPECT_EQ(tester.redispatchEventsAndClear(redispatched), 1);
832
833 EXPECT_TRUE(fl_keyboard_manager_is_state_clear(tester.manager()));
834 }
835
836 TEST(FlKeyboardManagerTest, TextInputPluginReturnsTrue) {
837 KeyboardTester tester;
838 std::vector<std::unique_ptr<FlKeyEvent>> redispatched;
839 gboolean manager_handled = false;
840 tester.recordRedispatchedEventsTo(redispatched);
841 tester.respondToTextInputWith(true);
842
843 // Dispatch a key event.
844 manager_handled = fl_keyboard_manager_handle_event(
845 tester.manager(),
846 fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA, 0, false));
847 tester.flushChannelMessages();
848 EXPECT_EQ(manager_handled, true);
849 // The event was not redispatched because text input plugin handles it.
850 EXPECT_EQ(redispatched.size(), 0u);
851
852 EXPECT_TRUE(fl_keyboard_manager_is_state_clear(tester.manager()));
853 }
854
855 TEST(FlKeyboardManagerTest, CorrectLogicalKeyForLayouts) {
856 KeyboardTester tester;
857
858 std::vector<CallRecord> call_records;
859 tester.recordEmbedderCallsTo(call_records);
860
861 auto sendTap = [&](guint8 keycode, guint keyval, guint8 group) {
862 fl_keyboard_manager_handle_event(
863 tester.manager(),
864 fl_key_event_new_by_mock(true, keyval, keycode, 0, false, group));
865 fl_keyboard_manager_handle_event(
866 tester.manager(),
867 fl_key_event_new_by_mock(false, keyval, keycode, 0, false, group));
868 };
869
870 /* US keyboard layout */
871
872 sendTap(kKeyCodeKeyA, GDK_KEY_a, 0); // KeyA
873 VERIFY_DOWN(kLogicalKeyA, "a");
874
875 sendTap(kKeyCodeKeyA, GDK_KEY_A, 0); // Shift-KeyA
876 VERIFY_DOWN(kLogicalKeyA, "A");
877
878 sendTap(kKeyCodeDigit1, GDK_KEY_1, 0); // Digit1
879 VERIFY_DOWN(kLogicalDigit1, "1");
880
881 sendTap(kKeyCodeDigit1, GDK_KEY_exclam, 0); // Shift-Digit1
882 VERIFY_DOWN(kLogicalDigit1, "!");
883
884 sendTap(kKeyCodeMinus, GDK_KEY_minus, 0); // Minus
885 VERIFY_DOWN(kLogicalMinus, "-");
886
887 sendTap(kKeyCodeMinus, GDK_KEY_underscore, 0); // Shift-Minus
888 VERIFY_DOWN(kLogicalUnderscore, "_");
889
890 /* French keyboard layout, group 3, which is when the input method is showing
891 * "Fr" */
892
893 tester.setLayout(kLayoutFrench);
894
895 sendTap(kKeyCodeKeyA, GDK_KEY_q, 3); // KeyA
896 VERIFY_DOWN(kLogicalKeyQ, "q");
897
898 sendTap(kKeyCodeKeyA, GDK_KEY_Q, 3); // Shift-KeyA
899 VERIFY_DOWN(kLogicalKeyQ, "Q");
900
901 sendTap(kKeyCodeSemicolon, GDK_KEY_m, 3); // ; but prints M
902 VERIFY_DOWN(kLogicalKeyM, "m");
903
904 sendTap(kKeyCodeKeyM, GDK_KEY_comma, 3); // M but prints ,
905 VERIFY_DOWN(kLogicalComma, ",");
906
907 sendTap(kKeyCodeDigit1, GDK_KEY_ampersand, 3); // Digit1
908 VERIFY_DOWN(kLogicalDigit1, "&");
909
910 sendTap(kKeyCodeDigit1, GDK_KEY_1, 3); // Shift-Digit1
911 VERIFY_DOWN(kLogicalDigit1, "1");
912
913 sendTap(kKeyCodeMinus, GDK_KEY_parenright, 3); // Minus
914 VERIFY_DOWN(kLogicalParenthesisRight, ")");
915
916 sendTap(kKeyCodeMinus, GDK_KEY_degree, 3); // Shift-Minus
917 VERIFY_DOWN(static_cast<uint32_t>(L'°'), "°");
918
919 /* French keyboard layout, group 0, which is pressing the "extra key for
920 * triggering input method" key once after switching to French IME. */
921
922 sendTap(kKeyCodeKeyA, GDK_KEY_a, 0); // KeyA
923 VERIFY_DOWN(kLogicalKeyA, "a");
924
925 sendTap(kKeyCodeDigit1, GDK_KEY_1, 0); // Digit1
926 VERIFY_DOWN(kLogicalDigit1, "1");
927
928 /* Russian keyboard layout, group 2 */
929 tester.setLayout(kLayoutRussian);
930
931 sendTap(kKeyCodeKeyA, GDK_KEY_Cyrillic_ef, 2); // KeyA
932 VERIFY_DOWN(kLogicalKeyA, "ф");
933
934 sendTap(kKeyCodeDigit1, GDK_KEY_1, 2); // Shift-Digit1
935 VERIFY_DOWN(kLogicalDigit1, "1");
936
937 sendTap(kKeyCodeKeyLeftBracket, GDK_KEY_Cyrillic_ha, 2);
938 VERIFY_DOWN(kLogicalBracketLeft, "х");
939
940 /* Russian keyboard layout, group 0 */
941 sendTap(kKeyCodeKeyA, GDK_KEY_a, 0); // KeyA
942 VERIFY_DOWN(kLogicalKeyA, "a");
943
944 sendTap(kKeyCodeKeyLeftBracket, GDK_KEY_bracketleft, 0);
945 VERIFY_DOWN(kLogicalBracketLeft, "[");
946 }
947
948 TEST(FlKeyboardManagerTest, SynthesizeModifiersIfNeeded) {
949 KeyboardTester tester;
950 std::vector<CallRecord> call_records;
951 tester.recordEmbedderCallsTo(call_records);
952
953 auto verifyModifierIsSynthesized = [&](GdkModifierType mask,
954 uint64_t physical, uint64_t logical) {
955 // Modifier is pressed.
956 guint state = mask;
957 fl_keyboard_manager_sync_modifier_if_needed(tester.manager(), state, 1000);
958 EXPECT_EQ(call_records.size(), 1u);
959 EXPECT_KEY_EVENT(call_records[0], kFlutterKeyEventTypeDown, physical,
960 logical, NULL, true);
961 // Modifier is released.
962 state = state ^ mask;
963 fl_keyboard_manager_sync_modifier_if_needed(tester.manager(), state, 1001);
964 EXPECT_EQ(call_records.size(), 2u);
965 EXPECT_KEY_EVENT(call_records[1], kFlutterKeyEventTypeUp, physical, logical,
966 NULL, true);
967 call_records.clear();
968 };
969
970 // No modifiers pressed.
971 guint state = 0;
972 fl_keyboard_manager_sync_modifier_if_needed(tester.manager(), state, 1000);
973 EXPECT_EQ(call_records.size(), 0u);
974 call_records.clear();
975
976 // Press and release each modifier once.
977 verifyModifierIsSynthesized(GDK_CONTROL_MASK, kPhysicalControlLeft,
978 kLogicalControlLeft);
979 verifyModifierIsSynthesized(GDK_META_MASK, kPhysicalMetaLeft,
980 kLogicalMetaLeft);
981 verifyModifierIsSynthesized(GDK_MOD1_MASK, kPhysicalAltLeft, kLogicalAltLeft);
982 verifyModifierIsSynthesized(GDK_SHIFT_MASK, kPhysicalShiftLeft,
983 kLogicalShiftLeft);
984 }
985
986 TEST(FlKeyboardManagerTest, GetPressedState) {
987 KeyboardTester tester;
988 tester.respondToTextInputWith(true);
989
990 // Dispatch a key event.
991 fl_keyboard_manager_handle_event(
992 tester.manager(),
993 fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA, 0, false));
994
995 GHashTable* pressedState =
996 fl_keyboard_manager_get_pressed_state(tester.manager());
997 EXPECT_EQ(g_hash_table_size(pressedState), 1u);
998
999 gpointer physical_key =
1000 g_hash_table_lookup(pressedState, uint64_to_gpointer(kPhysicalKeyA));
1001 EXPECT_EQ(gpointer_to_uint64(physical_key), kLogicalKeyA);
1002 }
1003
1004 TEST(FlKeyboardPluginTest, KeyboardChannelGetPressedState) {
1005 ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
1006
1007 g_autoptr(FlKeyboardManager) manager = fl_keyboard_manager_new(
1008 messenger, FL_KEYBOARD_VIEW_DELEGATE(fl_mock_view_delegate_new()));
1009 EXPECT_NE(manager, nullptr);
1010
1011 g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
1012 g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
1013 FL_METHOD_CODEC(codec), kGetKeyboardStateMethod, nullptr, nullptr);
1014
1015 g_autoptr(FlValue) response = fl_value_new_map();
1016 fl_value_set_take(response, fl_value_new_int(kMockPhysicalKey),
1017 fl_value_new_int(kMockLogicalKey));
1018 EXPECT_CALL(messenger,
1019 fl_binary_messenger_send_response(
1020 ::testing::Eq<FlBinaryMessenger*>(messenger), ::testing::_,
1021 MethodSuccessResponse(response), ::testing::_))
1022 .WillOnce(::testing::Return(true));
1023
1024 messenger.ReceiveMessage(kKeyboardChannelName, message);
1025 }
1026
1027 // The following layout data is generated using DEBUG_PRINT_LAYOUT.
1028
1029 const MockGroupLayoutData kLayoutUs0{{
1030 // +0x0 Shift +0x1 Shift +0x2 Shift +0x3 Shift
1031 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x00
1032 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x04
1033 0xffff, 0x0031, 0xffff, 0x0031, 0x0031, 0x0021, 0x0032, 0x0040, // 0x08
1034 0x0033, 0x0023, 0x0034, 0x0024, 0x0035, 0x0025, 0x0036, 0x005e, // 0x0c
1035 0x0037, 0x0026, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029, // 0x10
1036 0x002d, 0x005f, 0x003d, 0x002b, 0xffff, 0xffff, 0xffff, 0xffff, // 0x14
1037 0x0071, 0x0051, 0x0077, 0x0057, 0x0065, 0x0045, 0x0072, 0x0052, // 0x18
1038 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049, // 0x1c
1039 0x006f, 0x004f, 0x0070, 0x0050, 0x005b, 0x007b, 0x005d, 0x007d, // 0x20
1040 0xffff, 0xffff, 0xffff, 0x0061, 0x0061, 0x0041, 0x0073, 0x0053, // 0x24
1041 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048, // 0x28
1042 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x003b, 0x003a, // 0x2c
1043 0x0027, 0x0022, 0x0060, 0x007e, 0xffff, 0x005c, 0x005c, 0x007c, // 0x30
1044 0x007a, 0x005a, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056, // 0x34
1045 0x0062, 0x0042, 0x006e, 0x004e, 0x006d, 0x004d, 0x002c, 0x003c, // 0x38
1046 0x002e, 0x003e, 0x002f, 0x003f, 0xffff, 0xffff, 0xffff, 0xffff, // 0x3c
1047 0xffff, 0xffff, 0x0020, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x40
1048 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x44
1049 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x48
1050 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x4c
1051 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x50
1052 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x54
1053 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x58
1054 0xffff, 0xffff, 0x003c, 0x003e, 0x003c, 0x003e, 0xffff, 0xffff, // 0x5c
1055 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x60
1056 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x64
1057 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x68
1058 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x6c
1059 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x70
1060 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x74
1061 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x78
1062 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, 0xffff, 0xffff, // 0x7c
1063 }};
1064
1065 const MockGroupLayoutData kLayoutRussian0{
1066 // +0x0 Shift +0x1 Shift +0x2 Shift +0x3 Shift
1067 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x00
1068 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x04
1069 0x0000, 0xffff, 0xffff, 0x0031, 0x0031, 0x0021, 0x0032, 0x0040, // 0x08
1070 0x0033, 0x0023, 0x0034, 0x0024, 0x0035, 0x0025, 0x0036, 0x005e, // 0x0c
1071 0x0037, 0x0026, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029, // 0x10
1072 0x002d, 0x005f, 0x003d, 0x002b, 0xffff, 0xffff, 0xffff, 0xffff, // 0x14
1073 0x0071, 0x0051, 0x0077, 0x0057, 0x0065, 0x0045, 0x0072, 0x0052, // 0x18
1074 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049, // 0x1c
1075 0x006f, 0x004f, 0x0070, 0x0050, 0x005b, 0x007b, 0x005d, 0x007d, // 0x20
1076 0xffff, 0xffff, 0xffff, 0x0061, 0x0061, 0x0041, 0x0073, 0x0053, // 0x24
1077 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048, // 0x28
1078 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x003b, 0x003a, // 0x2c
1079 0x0027, 0x0022, 0x0060, 0x007e, 0xffff, 0x005c, 0x005c, 0x007c, // 0x30
1080 0x007a, 0x005a, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056, // 0x34
1081 0x0062, 0x0042, 0x006e, 0x004e, 0x006d, 0x004d, 0x002c, 0x003c, // 0x38
1082 0x002e, 0x003e, 0x002f, 0x003f, 0xffff, 0xffff, 0xffff, 0xffff, // 0x3c
1083 0xffff, 0xffff, 0x0020, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x40
1084 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x44
1085 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x48
1086 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x4c
1087 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x50
1088 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x54
1089 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x58
1090 0xffff, 0xffff, 0x0000, 0xffff, 0x003c, 0x003e, 0xffff, 0xffff, // 0x5c
1091 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x60
1092 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, // 0x64
1093 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x68
1094 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x6c
1095 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x70
1096 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x74
1097 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x78
1098 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, 0xffff, 0xffff, // 0x7c
1099 };
1100
1101 const MockGroupLayoutData kLayoutRussian2{{
1102 // +0x0 Shift +0x1 Shift +0x2 Shift +0x3 Shift
1103 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x00
1104 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x04
1105 0xffff, 0x0031, 0x0021, 0x0000, 0x0031, 0x0021, 0x0032, 0x0022, // 0x08
1106 0x0033, 0x06b0, 0x0034, 0x003b, 0x0035, 0x0025, 0x0036, 0x003a, // 0x0c
1107 0x0037, 0x003f, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029, // 0x10
1108 0x002d, 0x005f, 0x003d, 0x002b, 0x0071, 0x0051, 0x0000, 0x0000, // 0x14
1109 0x06ca, 0x06ea, 0x06c3, 0x06e3, 0x06d5, 0x06f5, 0x06cb, 0x06eb, // 0x18
1110 0x06c5, 0x06e5, 0x06ce, 0x06ee, 0x06c7, 0x06e7, 0x06db, 0x06fb, // 0x1c
1111 0x06dd, 0x06fd, 0x06da, 0x06fa, 0x06c8, 0x06e8, 0x06df, 0x06ff, // 0x20
1112 0x0061, 0x0041, 0x0041, 0x0000, 0x06c6, 0x06e6, 0x06d9, 0x06f9, // 0x24
1113 0x06d7, 0x06f7, 0x06c1, 0x06e1, 0x06d0, 0x06f0, 0x06d2, 0x06f2, // 0x28
1114 0x06cf, 0x06ef, 0x06cc, 0x06ec, 0x06c4, 0x06e4, 0x06d6, 0x06f6, // 0x2c
1115 0x06dc, 0x06fc, 0x06a3, 0x06b3, 0x007c, 0x0000, 0x005c, 0x002f, // 0x30
1116 0x06d1, 0x06f1, 0x06de, 0x06fe, 0x06d3, 0x06f3, 0x06cd, 0x06ed, // 0x34
1117 0x06c9, 0x06e9, 0x06d4, 0x06f4, 0x06d8, 0x06f8, 0x06c2, 0x06e2, // 0x38
1118 0x06c0, 0x06e0, 0x002e, 0x002c, 0xffff, 0xffff, 0xffff, 0xffff, // 0x3c
1119 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x40
1120 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x44
1121 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x48
1122 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x4c
1123 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x50
1124 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x54
1125 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x58
1126 0xffff, 0xffff, 0x003c, 0x003e, 0x002f, 0x007c, 0xffff, 0xffff, // 0x5c
1127 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x60
1128 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x64
1129 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0x0000, // 0x68
1130 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x6c
1131 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x70
1132 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x74
1133 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x00b1, // 0x78
1134 0x00b1, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x7c
1135 }};
1136
1137 const MockGroupLayoutData kLayoutFrench0 = {
1138 // +0x0 Shift +0x1 Shift +0x2 Shift +0x3 Shift
1139 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x00
1140 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x04
1141 0x0000, 0xffff, 0xffff, 0x0031, 0x0031, 0x0021, 0x0032, 0x0040, // 0x08
1142 0x0033, 0x0023, 0x0034, 0x0024, 0x0035, 0x0025, 0x0036, 0x005e, // 0x0c
1143 0x0037, 0x0026, 0x0038, 0x002a, 0x0039, 0x0028, 0x0030, 0x0029, // 0x10
1144 0x002d, 0x005f, 0x003d, 0x002b, 0xffff, 0xffff, 0xffff, 0xffff, // 0x14
1145 0x0071, 0x0051, 0x0077, 0x0057, 0x0065, 0x0045, 0x0072, 0x0052, // 0x18
1146 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049, // 0x1c
1147 0x006f, 0x004f, 0x0070, 0x0050, 0x005b, 0x007b, 0x005d, 0x007d, // 0x20
1148 0xffff, 0xffff, 0xffff, 0x0061, 0x0061, 0x0041, 0x0073, 0x0053, // 0x24
1149 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048, // 0x28
1150 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x003b, 0x003a, // 0x2c
1151 0x0027, 0x0022, 0x0060, 0x007e, 0xffff, 0x005c, 0x005c, 0x007c, // 0x30
1152 0x007a, 0x005a, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056, // 0x34
1153 0x0062, 0x0042, 0x006e, 0x004e, 0x006d, 0x004d, 0x002c, 0x003c, // 0x38
1154 0x002e, 0x003e, 0x002f, 0x003f, 0xffff, 0xffff, 0xffff, 0xffff, // 0x3c
1155 0xffff, 0xffff, 0x0020, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x40
1156 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x44
1157 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x48
1158 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x4c
1159 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x50
1160 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x54
1161 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x58
1162 0xffff, 0xffff, 0x0000, 0xffff, 0x003c, 0x003e, 0xffff, 0xffff, // 0x5c
1163 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x60
1164 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, // 0x64
1165 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x68
1166 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x6c
1167 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x70
1168 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x74
1169 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x78
1170 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, 0xffff, 0xffff, // 0x7c
1171 };
1172
1173 const MockGroupLayoutData kLayoutFrench3 = {
1174 // +0x0 Shift +0x1 Shift +0x2 Shift +0x3 Shift
1175 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x00
1176 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, // 0x04
1177 0x0000, 0xffff, 0x0000, 0x0000, 0x0026, 0x0031, 0x00e9, 0x0032, // 0x08
1178 0x0022, 0x0033, 0x0027, 0x0034, 0x0028, 0x0035, 0x002d, 0x0036, // 0x0c
1179 0x00e8, 0x0037, 0x005f, 0x0038, 0x00e7, 0x0039, 0x00e0, 0x0030, // 0x10
1180 0x0029, 0x00b0, 0x003d, 0x002b, 0x0000, 0x0000, 0x0061, 0x0041, // 0x14
1181 0x0061, 0x0041, 0x007a, 0x005a, 0x0065, 0x0045, 0x0072, 0x0052, // 0x18
1182 0x0074, 0x0054, 0x0079, 0x0059, 0x0075, 0x0055, 0x0069, 0x0049, // 0x1c
1183 0x006f, 0x004f, 0x0070, 0x0050, 0xffff, 0xffff, 0x0024, 0x00a3, // 0x20
1184 0x0041, 0x0000, 0x0000, 0x0000, 0x0071, 0x0051, 0x0073, 0x0053, // 0x24
1185 0x0064, 0x0044, 0x0066, 0x0046, 0x0067, 0x0047, 0x0068, 0x0048, // 0x28
1186 0x006a, 0x004a, 0x006b, 0x004b, 0x006c, 0x004c, 0x006d, 0x004d, // 0x2c
1187 0x00f9, 0x0025, 0x00b2, 0x007e, 0x0000, 0x0000, 0x002a, 0x00b5, // 0x30
1188 0x0077, 0x0057, 0x0078, 0x0058, 0x0063, 0x0043, 0x0076, 0x0056, // 0x34
1189 0x0062, 0x0042, 0x006e, 0x004e, 0x002c, 0x003f, 0x003b, 0x002e, // 0x38
1190 0x003a, 0x002f, 0x0021, 0x00a7, 0xffff, 0xffff, 0xffff, 0xffff, // 0x3c
1191 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x40
1192 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x44
1193 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x48
1194 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x4c
1195 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x50
1196 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x54
1197 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x58
1198 0xffff, 0x003c, 0x0000, 0xffff, 0x003c, 0x003e, 0xffff, 0xffff, // 0x5c
1199 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x60
1200 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0xffff, // 0x64
1201 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x68
1202 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x6c
1203 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x70
1204 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x74
1205 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x00b1, 0x00b1, 0xffff, // 0x78
1206 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, // 0x7c
1207 };
1208
1209 const MockLayoutData kLayoutUs{&kLayoutUs0};
1210 const MockLayoutData kLayoutRussian{&kLayoutRussian0, nullptr,
1211 &kLayoutRussian2};
1212 const MockLayoutData kLayoutFrench{&kLayoutFrench0, nullptr, nullptr,
1213 &kLayoutFrench3};
1214
1215 } // namespace
event
FlKeyEvent * event
Definition: fl_key_channel_responder.cc:118
fl_method_codec_encode_method_call
GBytes * fl_method_codec_encode_method_call(FlMethodCodec *self, const gchar *name, FlValue *args, GError **error)
Definition: fl_method_codec.cc:16
fl_value_set_string_take
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:610
fl_key_event_new_by_mock
static FlKeyEvent * fl_key_event_new_by_mock(guint32 time_in_milliseconds, bool is_press, guint keyval, guint16 keycode, int state, const char *string, gboolean is_modifier)
Definition: fl_key_channel_responder_test.cc:44
fl_standard_method_codec_new
G_MODULE_EXPORT FlStandardMethodCodec * fl_standard_method_codec_new()
Definition: fl_standard_method_codec.cc:248
G_DECLARE_FINAL_TYPE
G_BEGIN_DECLS G_DECLARE_FINAL_TYPE(FlAccessibilityPlugin, fl_accessibility_plugin, FL, ACCESSIBILITY_PLUGIN, GObject)
fl_keyboard_manager.h
kGetKeyboardStateMethod
static constexpr char kGetKeyboardStateMethod[]
Definition: fl_keyboard_manager.cc:23
fl_value_new_bool
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition: fl_value.cc:244
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:40
fl_json_message_codec_new
G_MODULE_EXPORT FlJsonMessageCodec * fl_json_message_codec_new()
Definition: fl_json_message_codec.cc:306
fl_json_message_codec.h
uint64_to_gpointer
gpointer uint64_to_gpointer(uint64_t number)
Definition: key_mapping.h:17
user_data
FlKeyEvent uint64_t FlKeyResponderAsyncCallback gpointer user_data
Definition: fl_key_channel_responder.cc:121
fl_value_set_take
G_MODULE_EXPORT void fl_value_set_take(FlValue *self, FlValue *key, FlValue *value)
Definition: fl_value.cc:578
MATCHER_P
MATCHER_P(SuccessResponse, result, "")
Definition: fl_platform_plugin_test.cc:19
fl_method_response_get_result
G_MODULE_EXPORT FlValue * fl_method_response_get_result(FlMethodResponse *self, GError **error)
Definition: fl_method_response.cc:82
fl_value_new_int
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:251
_FlKeyEvent::origin
gpointer origin
Definition: fl_key_event.h:52
fl_keyboard_manager_is_state_clear
gboolean fl_keyboard_manager_is_state_clear(FlKeyboardManager *self)
Definition: fl_keyboard_manager.cc:666
_FlKeyEvent
Definition: fl_key_event.h:31
state
AtkStateType state
Definition: fl_accessible_node.cc:10
fl_keyboard_manager_handle_event
gboolean fl_keyboard_manager_handle_event(FlKeyboardManager *self, FlKeyEvent *event)
Definition: fl_keyboard_manager.cc:635
KeyboardLayoutNotifier
std::function< void()> KeyboardLayoutNotifier
Definition: fl_keyboard_view_delegate.h:17
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:355
_FlKeyEvent::dispose_origin
FlKeyEventDisposeOrigin dispose_origin
Definition: fl_key_event.h:56
fl_key_event_clone
FlKeyEvent * fl_key_event_clone(const FlKeyEvent *event)
Definition: fl_key_event.cc:49
key_mapping.h
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
FlBinaryMessengerMessageHandler
G_MODULE_EXPORT GObject typedef void(* FlBinaryMessengerMessageHandler)(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
Definition: fl_binary_messenger.h:66
fl_method_codec_decode_response
FlMethodResponse * fl_method_codec_decode_response(FlMethodCodec *self, GBytes *message, GError **error)
Definition: fl_method_codec.cc:62
fl_method_codec.h
FL
FL
Definition: fl_binary_messenger.cc:27
fl_value_equal
G_MODULE_EXPORT bool fl_value_equal(FlValue *a, FlValue *b)
Definition: fl_value.cc:433
fl_standard_method_codec.h
fl_keyboard_manager_new
FlKeyboardManager * fl_keyboard_manager_new(FlBinaryMessenger *messenger, FlKeyboardViewDelegate *view_delegate)
Definition: fl_keyboard_manager.cc:585
EXPECT_KEY_EVENT
#define EXPECT_KEY_EVENT(RECORD, TYPE, PHYSICAL, LOGICAL, CHAR, SYNTHESIZED)
Definition: fl_keyboard_manager_test.cc:28
fl_keyboard_manager_sync_modifier_if_needed
void fl_keyboard_manager_sync_modifier_if_needed(FlKeyboardManager *self, guint state, double event_time)
Definition: fl_keyboard_manager.cc:672
self
GdkEvent FlView * self
Definition: fl_view.cc:100
fl_binary_messenger_private.h
fl_keyboard_manager_get_pressed_state
GHashTable * fl_keyboard_manager_get_pressed_state(FlKeyboardManager *self)
Definition: fl_keyboard_manager.cc:685
result
GAsyncResult * result
Definition: fl_text_input_plugin.cc:106
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
TEST
TEST(FlAccessibleNodeTest, BuildTree)
Definition: fl_accessible_node_test.cc:12
target
uint32_t * target
Definition: fl_texture_registrar_test.cc:40
fl_message_codec_encode_message
G_MODULE_EXPORT GBytes * fl_message_codec_encode_message(FlMessageCodec *self, FlValue *message, GError **error)
Definition: fl_message_codec.cc:17
callback
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Definition: fl_key_channel_responder.cc:120
fl_binary_messenger_send_response
G_MODULE_EXPORT gboolean fl_binary_messenger_send_response(FlBinaryMessenger *self, FlBinaryMessengerResponseHandle *response_handle, GBytes *response, GError **error)
Definition: fl_binary_messenger.cc:438
fl_method_codec_private.h
VERIFY_DOWN
#define VERIFY_DOWN(OUT_LOGICAL, OUT_CHAR)
Definition: fl_keyboard_manager_test.cc:36
gpointer_to_uint64
uint64_t gpointer_to_uint64(gpointer pointer)
Definition: key_mapping.h:13
G_DEFINE_TYPE_WITH_CODE
G_DEFINE_TYPE_WITH_CODE(FlAccessibleNode, fl_accessible_node, ATK_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(ATK_TYPE_COMPONENT, fl_accessible_node_component_interface_init) G_IMPLEMENT_INTERFACE(ATK_TYPE_ACTION, fl_accessible_node_action_interface_init)) static gboolean flag_is_changed(FlutterSemanticsFlag old_flags
FlKeyboardManager
typedefG_BEGIN_DECLS struct _FlKeyboardManager FlKeyboardManager
Definition: fl_key_responder.h:17