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