| 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
5 #include "flutter/shell/platform/linux/fl_keyboard_handler.h"
6
7 #include <cstring>
8 #include <vector>
9
10 #include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
11 #include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
12 #include "flutter/shell/platform/linux/fl_method_codec_private.h"
13 #include "flutter/shell/platform/linux/key_mapping.h"
14 #include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
15 #include "flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h"
16 #include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
17 #include "flutter/shell/platform/linux/testing/fl_test.h"
18 #include "flutter/shell/platform/linux/testing/mock_binary_messenger.h"
19 #include "flutter/shell/platform/linux/testing/mock_text_input_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
175 G_DEFINE_TYPE_WITH_CODE(
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
183 #define FL_MOCK_KEY_BINARY_MESSENGER_GET_PRIVATE(obj) \
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 =
190 FL_MOCK_KEY_BINARY_MESSENGER_GET_PRIVATE(self);
191 new (priv) FlMockKeyBinaryMessengerPrivate();
192 }
193
194 static void fl_mock_key_binary_messenger_finalize(GObject* object) {
195 FL_MOCK_KEY_BINARY_MESSENGER_GET_PRIVATE(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
315 G_DEFINE_TYPE_WITH_CODE(
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
323 #define FL_MOCK_VIEW_DELEGATE_GET_PRIVATE(obj) \
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,
1042 fl_binary_messenger_send_response(
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