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 
6 
7 #include <cstring>
8 #include <vector>
9 
10 #include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
17 #include "flutter/shell/platform/linux/testing/fl_test.h"
18 #include "flutter/shell/platform/linux/testing/mock_binary_messenger.h"
19 #include "flutter/shell/platform/linux/testing/mock_text_input_plugin.h"
20 #include "flutter/testing/testing.h"
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 
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_allow_channel_overflow(
226  FlBinaryMessenger* messenger,
227  const gchar* channel,
228  bool allowed) {
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_allow_channel_overflow =
255  fl_mock_binary_messenger_set_allow_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 
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);
615  tester.manager(),
616  fl_key_event_new_by_mock(true, GDK_KEY_a, kKeyCodeKeyA, 0x0, false));
617 
618  tester.respondToEmbedderCallsWith(true);
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) {
863  tester.manager(),
864  fl_key_event_new_by_mock(true, keyval, keycode, 0, false, group));
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.
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,
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:17
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:43
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:64
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