Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
fl_engine_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// Included first as it collides with the X11 headers.
6#include "gtest/gtest.h"
7
14
15// MOCK_ENGINE_PROC is leaky by design
16// NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
17
18// Checks notifying display updates works.
19TEST(FlEngineTest, NotifyDisplayUpdate) {
20 g_autoptr(FlDartProject) project = fl_dart_project_new();
21 g_autoptr(FlEngine) engine = fl_engine_new(project);
22
23 g_autoptr(GError) error = nullptr;
24 EXPECT_TRUE(fl_engine_start(engine, &error));
25 EXPECT_EQ(error, nullptr);
26
27 bool called = false;
29 NotifyDisplayUpdate,
30 ([&called](auto engine, FlutterEngineDisplaysUpdateType update_type,
31 const FlutterEngineDisplay* displays, size_t displays_length) {
32 called = true;
33 EXPECT_EQ(update_type, kFlutterEngineDisplaysUpdateTypeStartup);
34 EXPECT_EQ(displays_length, 2u);
35
36 EXPECT_EQ(displays[0].display_id, 1u);
37 EXPECT_EQ(displays[0].refresh_rate, 60);
38 EXPECT_EQ(displays[0].width, 1024u);
39 EXPECT_EQ(displays[0].height, 768u);
40 EXPECT_EQ(displays[0].device_pixel_ratio, 1.0);
41
42 EXPECT_EQ(displays[1].display_id, 2u);
43 EXPECT_EQ(displays[1].refresh_rate, 120);
44 EXPECT_EQ(displays[1].width, 3840u);
45 EXPECT_EQ(displays[1].height, 2160u);
46 EXPECT_EQ(displays[1].device_pixel_ratio, 2.0);
47
48 return kSuccess;
49 }));
50
52 {
54 .display_id = 1,
55 .single_display = false,
56 .refresh_rate = 60.0,
57 .width = 1024,
58 .height = 768,
59 .device_pixel_ratio = 1.0,
60 },
61 {
62 .struct_size = sizeof(FlutterEngineDisplay),
63 .display_id = 2,
64 .single_display = false,
65 .refresh_rate = 120.0,
66 .width = 3840,
67 .height = 2160,
68 .device_pixel_ratio = 2.0,
69 }};
71
72 EXPECT_TRUE(called);
73}
74
75// Checks sending window metrics events works.
76TEST(FlEngineTest, WindowMetrics) {
77 g_autoptr(FlDartProject) project = fl_dart_project_new();
78 g_autoptr(FlEngine) engine = fl_engine_new(project);
79
80 g_autoptr(GError) error = nullptr;
81 EXPECT_TRUE(fl_engine_start(engine, &error));
82 EXPECT_EQ(error, nullptr);
83
84 bool called = false;
86 SendWindowMetricsEvent,
87 ([&called](auto engine, const FlutterWindowMetricsEvent* event) {
88 called = true;
89 EXPECT_EQ(event->display_id, 99u);
90 EXPECT_EQ(event->view_id, 1);
91 EXPECT_EQ(event->width, 800u);
92 EXPECT_EQ(event->height, 600u);
93 EXPECT_TRUE(event->has_constraints);
94 EXPECT_EQ(event->min_width_constraint, 800u);
95 EXPECT_EQ(event->min_height_constraint, 600u);
96 EXPECT_EQ(event->max_width_constraint, 3840u);
97 EXPECT_EQ(event->max_height_constraint, 2160u);
98 EXPECT_EQ(event->pixel_ratio, 2.0);
99
100 return kSuccess;
101 }));
102
103 fl_engine_send_window_metrics_event(engine, 99, 1, 800, 600, 3840, 2160, 2.0);
104
105 EXPECT_TRUE(called);
106}
107
108// Checks sending mouse pointer events works.
109TEST(FlEngineTest, MousePointer) {
110 g_autoptr(FlDartProject) project = fl_dart_project_new();
111 g_autoptr(FlEngine) engine = fl_engine_new(project);
112
113 bool called = false;
115 SendPointerEvent,
116 ([&called](auto engine, const FlutterPointerEvent* events,
117 size_t events_count) {
118 called = true;
119 EXPECT_EQ(events_count, static_cast<size_t>(1));
120 EXPECT_EQ(events[0].view_id, 1);
121 EXPECT_EQ(events[0].phase, kDown);
122 EXPECT_EQ(events[0].timestamp, static_cast<size_t>(1234567890));
123 EXPECT_EQ(events[0].x, 800);
124 EXPECT_EQ(events[0].y, 600);
125 EXPECT_EQ(events[0].device, static_cast<int32_t>(0));
126 EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindScroll);
127 EXPECT_EQ(events[0].scroll_delta_x, 1.2);
128 EXPECT_EQ(events[0].scroll_delta_y, -3.4);
129 EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindMouse);
130 EXPECT_EQ(events[0].buttons, kFlutterPointerButtonMouseSecondary);
131
132 return kSuccess;
133 }));
134
135 g_autoptr(GError) error = nullptr;
136 EXPECT_TRUE(fl_engine_start(engine, &error));
137 EXPECT_EQ(error, nullptr);
138 fl_engine_send_mouse_pointer_event(engine, 1, kDown, 1234567890, 800, 600,
141
142 EXPECT_TRUE(called);
143}
144
145// Checks sending pan/zoom events works.
146TEST(FlEngineTest, PointerPanZoom) {
147 g_autoptr(FlDartProject) project = fl_dart_project_new();
148 g_autoptr(FlEngine) engine = fl_engine_new(project);
149
150 bool called = false;
152 SendPointerEvent,
153 ([&called](auto engine, const FlutterPointerEvent* events,
154 size_t events_count) {
155 called = true;
156 EXPECT_EQ(events_count, static_cast<size_t>(1));
157 EXPECT_EQ(events[0].view_id, 1);
158 EXPECT_EQ(events[0].phase, kPanZoomUpdate);
159 EXPECT_EQ(events[0].timestamp, static_cast<size_t>(1234567890));
160 EXPECT_EQ(events[0].x, 800);
161 EXPECT_EQ(events[0].y, 600);
162 EXPECT_EQ(events[0].device, static_cast<int32_t>(1));
163 EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindNone);
164 EXPECT_EQ(events[0].pan_x, 1.5);
165 EXPECT_EQ(events[0].pan_y, 2.5);
166 EXPECT_EQ(events[0].scale, 3.5);
167 EXPECT_EQ(events[0].rotation, 4.5);
168 EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindTrackpad);
169 EXPECT_EQ(events[0].buttons, 0);
170
171 return kSuccess;
172 }));
173
174 g_autoptr(GError) error = nullptr;
175 EXPECT_TRUE(fl_engine_start(engine, &error));
176 EXPECT_EQ(error, nullptr);
177 fl_engine_send_pointer_pan_zoom_event(engine, 1, 1234567890, 800, 600,
178 kPanZoomUpdate, 1.5, 2.5, 3.5, 4.5);
179
180 EXPECT_TRUE(called);
181}
182
183// Checks dispatching a semantics action works.
184TEST(FlEngineTest, DispatchSemanticsAction) {
185 g_autoptr(FlDartProject) project = fl_dart_project_new();
186 g_autoptr(FlEngine) engine = fl_engine_new(project);
187
188 bool called = false;
190 SendSemanticsAction,
191 ([&called](auto engine, const FlutterSendSemanticsActionInfo* info) {
192 EXPECT_EQ(info->view_id, static_cast<int64_t>(456));
193 EXPECT_EQ(info->node_id, static_cast<uint64_t>(42));
194 EXPECT_EQ(info->action, kFlutterSemanticsActionTap);
195 EXPECT_EQ(info->data_length, static_cast<size_t>(4));
196 EXPECT_EQ(info->data[0], 't');
197 EXPECT_EQ(info->data[1], 'e');
198 EXPECT_EQ(info->data[2], 's');
199 EXPECT_EQ(info->data[3], 't');
200 called = true;
201
202 return kSuccess;
203 }));
204
205 g_autoptr(GError) error = nullptr;
206 EXPECT_TRUE(fl_engine_start(engine, &error));
207 EXPECT_EQ(error, nullptr);
208 g_autoptr(GBytes) data = g_bytes_new_static("test", 4);
211
212 EXPECT_TRUE(called);
213}
214
215// Checks sending platform messages works.
216TEST(FlEngineTest, PlatformMessage) {
217 g_autoptr(FlDartProject) project = fl_dart_project_new();
218 g_autoptr(FlEngine) engine = fl_engine_new(project);
219
220 bool called = false;
224 SendPlatformMessage,
225 ([&called, old_handler](auto engine,
227 if (strcmp(message->channel, "test") != 0) {
228 return old_handler(engine, message);
229 }
230
231 called = true;
232
233 EXPECT_EQ(message->message_size, static_cast<size_t>(4));
234 EXPECT_EQ(message->message[0], 't');
235 EXPECT_EQ(message->message[1], 'e');
236 EXPECT_EQ(message->message[2], 's');
237 EXPECT_EQ(message->message[3], 't');
238
239 return kSuccess;
240 }));
241
242 g_autoptr(GError) error = nullptr;
243 EXPECT_TRUE(fl_engine_start(engine, &error));
244 EXPECT_EQ(error, nullptr);
245 g_autoptr(GBytes) message = g_bytes_new_static("test", 4);
246 fl_engine_send_platform_message(engine, "test", message, nullptr, nullptr,
247 nullptr);
248
249 EXPECT_TRUE(called);
250}
251
252// Checks sending platform message responses works.
254 g_autoptr(FlDartProject) project = fl_dart_project_new();
255 g_autoptr(FlEngine) engine = fl_engine_new(project);
256
257 bool called = false;
260 SendPlatformMessageResponse,
261 ([&called](auto engine,
263 const uint8_t* data, size_t data_length) {
264 called = true;
265
266 EXPECT_EQ(
267 handle,
268 reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(
269 42));
270 EXPECT_EQ(data_length, static_cast<size_t>(4));
271 EXPECT_EQ(data[0], 't');
272 EXPECT_EQ(data[1], 'e');
273 EXPECT_EQ(data[2], 's');
274 EXPECT_EQ(data[3], 't');
275
276 return kSuccess;
277 }));
278
279 g_autoptr(GError) error = nullptr;
280 EXPECT_TRUE(fl_engine_start(engine, &error));
281 EXPECT_EQ(error, nullptr);
282 g_autoptr(GBytes) response = g_bytes_new_static("test", 4);
284 engine, reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(42),
285 response, &error));
286 EXPECT_EQ(error, nullptr);
287
288 EXPECT_TRUE(called);
289}
290
291// Checks settings handler sends settings on startup.
292TEST(FlEngineTest, SettingsHandler) {
293 g_autoptr(FlDartProject) project = fl_dart_project_new();
294 g_autoptr(FlEngine) engine = fl_engine_new(project);
295
296 bool called = false;
298 SendPlatformMessage,
299 ([&called](auto engine, const FlutterPlatformMessage* message) {
300 called = true;
301
302 EXPECT_STREQ(message->channel, "flutter/settings");
303
304 g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
305 g_autoptr(GBytes) data =
306 g_bytes_new(message->message, message->message_size);
307 g_autoptr(GError) error = nullptr;
309 FL_MESSAGE_CODEC(codec), data, &error);
310 EXPECT_NE(settings, nullptr);
311 EXPECT_EQ(error, nullptr);
312
313 FlValue* text_scale_factor =
314 fl_value_lookup_string(settings, "textScaleFactor");
315 EXPECT_NE(text_scale_factor, nullptr);
316 EXPECT_EQ(fl_value_get_type(text_scale_factor), FL_VALUE_TYPE_FLOAT);
317
318 FlValue* always_use_24hr_format =
319 fl_value_lookup_string(settings, "alwaysUse24HourFormat");
320 EXPECT_NE(always_use_24hr_format, nullptr);
321 EXPECT_EQ(fl_value_get_type(always_use_24hr_format),
323
324 FlValue* platform_brightness =
325 fl_value_lookup_string(settings, "platformBrightness");
326 EXPECT_NE(platform_brightness, nullptr);
327 EXPECT_EQ(fl_value_get_type(platform_brightness), FL_VALUE_TYPE_STRING);
328
329 return kSuccess;
330 }));
331
332 g_autoptr(GError) error = nullptr;
333 EXPECT_TRUE(fl_engine_start(engine, &error));
334 EXPECT_EQ(error, nullptr);
335
336 EXPECT_TRUE(called);
337}
338
339void on_pre_engine_restart_cb(FlEngine* engine, gpointer user_data) {
340 int* count = reinterpret_cast<int*>(user_data);
341 *count += 1;
342}
343
344// Checks restarting the engine invokes the correct callback.
345TEST(FlEngineTest, OnPreEngineRestart) {
346 g_autoptr(FlDartProject) project = fl_dart_project_new();
347 g_autoptr(FlEngine) engine = fl_engine_new(project);
348
350 void* callback_user_data;
351
352 bool called = false;
354 Initialize, ([&callback, &callback_user_data, &called](
355 size_t version, const FlutterRendererConfig* config,
356 const FlutterProjectArgs* args, void* user_data,
357 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
358 called = true;
359 callback = args->on_pre_engine_restart_callback;
360 callback_user_data = user_data;
361
362 return kSuccess;
363 }));
365 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
366
367 g_autoptr(GError) error = nullptr;
368 EXPECT_TRUE(fl_engine_start(engine, &error));
369 EXPECT_EQ(error, nullptr);
370
371 EXPECT_TRUE(called);
372 EXPECT_NE(callback, nullptr);
373
374 // The following call has no effect but should not crash.
375 callback(callback_user_data);
376
377 int count = 0;
378
379 // Set handler so that:
380 //
381 // * When the engine restarts, count += 1;
382 // * When the engine is freed, count += 10.
383 g_signal_connect(engine, "on-pre-engine-restart",
384 G_CALLBACK(on_pre_engine_restart_cb), &count);
385
386 callback(callback_user_data);
387 EXPECT_EQ(count, 1);
388}
389
390TEST(FlEngineTest, DartEntrypointArgs) {
391 GPtrArray* args_array = g_ptr_array_new();
392 g_ptr_array_add(args_array, const_cast<char*>("arg_one"));
393 g_ptr_array_add(args_array, const_cast<char*>("arg_two"));
394 g_ptr_array_add(args_array, const_cast<char*>("arg_three"));
395 g_ptr_array_add(args_array, nullptr);
396 gchar** args = reinterpret_cast<gchar**>(g_ptr_array_free(args_array, false));
397
398 g_autoptr(FlDartProject) project = fl_dart_project_new();
400 g_autoptr(FlEngine) engine = fl_engine_new(project);
401
402 bool called = false;
404 Initialize, ([&called, &set_args = args](
405 size_t version, const FlutterRendererConfig* config,
406 const FlutterProjectArgs* args, void* user_data,
407 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
408 called = true;
409 EXPECT_NE(set_args, args->dart_entrypoint_argv);
410 EXPECT_EQ(args->dart_entrypoint_argc, 3);
411
412 return kSuccess;
413 }));
415 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
416
417 g_autoptr(GError) error = nullptr;
418 EXPECT_TRUE(fl_engine_start(engine, &error));
419 EXPECT_EQ(error, nullptr);
420
421 EXPECT_TRUE(called);
422}
423
424TEST(FlEngineTest, EngineId) {
425 g_autoptr(FlDartProject) project = fl_dart_project_new();
426 g_autoptr(FlEngine) engine = fl_engine_new(project);
427 int64_t engine_id;
429 Initialize,
430 ([&engine_id](size_t version, const FlutterRendererConfig* config,
431 const FlutterProjectArgs* args, void* user_data,
432 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
433 engine_id = args->engine_id;
434 return kSuccess;
435 }));
437 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
438
439 g_autoptr(GError) error = nullptr;
440 EXPECT_TRUE(fl_engine_start(engine, &error));
441 EXPECT_EQ(error, nullptr);
442 EXPECT_TRUE(engine_id != 0);
443
444 EXPECT_EQ(fl_engine_for_id(engine_id), engine);
445}
446
447TEST(FlEngineTest, UIIsolateDefaultThreadPolicy) {
448 g_autoptr(FlDartProject) project = fl_dart_project_new();
449 g_autoptr(FlEngine) engine = fl_engine_new(project);
451
452 bool same_task_runner = false;
453
455 Initialize,
456 ([&same_task_runner](size_t version, const FlutterRendererConfig* config,
457 const FlutterProjectArgs* args, void* user_data,
458 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
459 same_task_runner = args->custom_task_runners->platform_task_runner ==
460 args->custom_task_runners->ui_task_runner;
461 return kSuccess;
462 }));
464 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
465
466 g_autoptr(GError) error = nullptr;
467 EXPECT_TRUE(fl_engine_start(engine, &error));
468 EXPECT_EQ(error, nullptr);
469 EXPECT_TRUE(same_task_runner);
470}
471
472TEST(FlEngineTest, UIIsolateOnPlatformTaskRunner) {
473 g_autoptr(FlDartProject) project = fl_dart_project_new();
474 g_autoptr(FlEngine) engine = fl_engine_new(project);
477
478 bool same_task_runner = false;
479
481 Initialize,
482 ([&same_task_runner](size_t version, const FlutterRendererConfig* config,
483 const FlutterProjectArgs* args, void* user_data,
484 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
485 same_task_runner = args->custom_task_runners->platform_task_runner ==
486 args->custom_task_runners->ui_task_runner;
487 return kSuccess;
488 }));
490 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
491
492 g_autoptr(GError) error = nullptr;
493 EXPECT_TRUE(fl_engine_start(engine, &error));
494 EXPECT_EQ(error, nullptr);
495 EXPECT_TRUE(same_task_runner);
496}
497
498TEST(FlEngineTest, UIIsolateOnSeparateThread) {
499 g_autoptr(FlDartProject) project = fl_dart_project_new();
500 g_autoptr(FlEngine) engine = fl_engine_new(project);
503
504 bool separate_thread = false;
505
507 Initialize,
508 ([&separate_thread](size_t version, const FlutterRendererConfig* config,
509 const FlutterProjectArgs* args, void* user_data,
510 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
511 separate_thread = args->custom_task_runners->ui_task_runner == nullptr;
512 return kSuccess;
513 }));
515 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
516
517 g_autoptr(GError) error = nullptr;
518 EXPECT_TRUE(fl_engine_start(engine, &error));
519 EXPECT_EQ(error, nullptr);
520 EXPECT_TRUE(separate_thread);
521}
522
523TEST(FlEngineTest, Locales) {
524 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
525 g_setenv("LANGUAGE", "de:en_US", TRUE);
526 g_autoptr(FlDartProject) project = fl_dart_project_new();
527
528 g_autoptr(FlEngine) engine = fl_engine_new(project);
529
530 bool called = false;
532 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
533 size_t locales_count) {
534 called = true;
535
536 EXPECT_EQ(locales_count, static_cast<size_t>(4));
537
538 EXPECT_STREQ(locales[0]->language_code, "de");
539 EXPECT_STREQ(locales[0]->country_code, nullptr);
540 EXPECT_STREQ(locales[0]->script_code, nullptr);
541 EXPECT_STREQ(locales[0]->variant_code, nullptr);
542
543 EXPECT_STREQ(locales[1]->language_code, "en");
544 EXPECT_STREQ(locales[1]->country_code, "US");
545 EXPECT_STREQ(locales[1]->script_code, nullptr);
546 EXPECT_STREQ(locales[1]->variant_code, nullptr);
547
548 EXPECT_STREQ(locales[2]->language_code, "en");
549 EXPECT_STREQ(locales[2]->country_code, nullptr);
550 EXPECT_STREQ(locales[2]->script_code, nullptr);
551 EXPECT_STREQ(locales[2]->variant_code, nullptr);
552
553 EXPECT_STREQ(locales[3]->language_code, "C");
554 EXPECT_STREQ(locales[3]->country_code, nullptr);
555 EXPECT_STREQ(locales[3]->script_code, nullptr);
556 EXPECT_STREQ(locales[3]->variant_code, nullptr);
557
558 return kSuccess;
559 }));
560
561 g_autoptr(GError) error = nullptr;
562 EXPECT_TRUE(fl_engine_start(engine, &error));
563 EXPECT_EQ(error, nullptr);
564
565 EXPECT_TRUE(called);
566
567 if (initial_language) {
568 g_setenv("LANGUAGE", initial_language, TRUE);
569 } else {
570 g_unsetenv("LANGUAGE");
571 }
572}
573
574TEST(FlEngineTest, CLocale) {
575 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
576 g_setenv("LANGUAGE", "C", TRUE);
577 g_autoptr(FlDartProject) project = fl_dart_project_new();
578
579 g_autoptr(FlEngine) engine = fl_engine_new(project);
580
581 bool called = false;
583 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
584 size_t locales_count) {
585 called = true;
586
587 EXPECT_EQ(locales_count, static_cast<size_t>(1));
588
589 EXPECT_STREQ(locales[0]->language_code, "C");
590 EXPECT_STREQ(locales[0]->country_code, nullptr);
591 EXPECT_STREQ(locales[0]->script_code, nullptr);
592 EXPECT_STREQ(locales[0]->variant_code, nullptr);
593
594 return kSuccess;
595 }));
596
597 g_autoptr(GError) error = nullptr;
598 EXPECT_TRUE(fl_engine_start(engine, &error));
599 EXPECT_EQ(error, nullptr);
600
601 EXPECT_TRUE(called);
602
603 if (initial_language) {
604 g_setenv("LANGUAGE", initial_language, TRUE);
605 } else {
606 g_unsetenv("LANGUAGE");
607 }
608}
609
610TEST(FlEngineTest, DuplicateLocale) {
611 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
612 g_setenv("LANGUAGE", "en:en", TRUE);
613 g_autoptr(FlDartProject) project = fl_dart_project_new();
614
615 g_autoptr(FlEngine) engine = fl_engine_new(project);
616
617 bool called = false;
619 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
620 size_t locales_count) {
621 called = true;
622
623 EXPECT_EQ(locales_count, static_cast<size_t>(2));
624
625 EXPECT_STREQ(locales[0]->language_code, "en");
626 EXPECT_STREQ(locales[0]->country_code, nullptr);
627 EXPECT_STREQ(locales[0]->script_code, nullptr);
628 EXPECT_STREQ(locales[0]->variant_code, nullptr);
629
630 EXPECT_STREQ(locales[1]->language_code, "C");
631 EXPECT_STREQ(locales[1]->country_code, nullptr);
632 EXPECT_STREQ(locales[1]->script_code, nullptr);
633 EXPECT_STREQ(locales[1]->variant_code, nullptr);
634
635 return kSuccess;
636 }));
637
638 g_autoptr(GError) error = nullptr;
639 EXPECT_TRUE(fl_engine_start(engine, &error));
640 EXPECT_EQ(error, nullptr);
641
642 EXPECT_TRUE(called);
643
644 if (initial_language) {
645 g_setenv("LANGUAGE", initial_language, TRUE);
646 } else {
647 g_unsetenv("LANGUAGE");
648 }
649}
650
651TEST(FlEngineTest, EmptyLocales) {
652 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
653 g_setenv("LANGUAGE", "de:: :en_US", TRUE);
654 g_autoptr(FlDartProject) project = fl_dart_project_new();
655
656 g_autoptr(FlEngine) engine = fl_engine_new(project);
657
658 bool called = false;
660 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
661 size_t locales_count) {
662 called = true;
663
664 EXPECT_EQ(locales_count, static_cast<size_t>(4));
665
666 EXPECT_STREQ(locales[0]->language_code, "de");
667 EXPECT_STREQ(locales[0]->country_code, nullptr);
668 EXPECT_STREQ(locales[0]->script_code, nullptr);
669 EXPECT_STREQ(locales[0]->variant_code, nullptr);
670
671 EXPECT_STREQ(locales[1]->language_code, "en");
672 EXPECT_STREQ(locales[1]->country_code, "US");
673 EXPECT_STREQ(locales[1]->script_code, nullptr);
674 EXPECT_STREQ(locales[1]->variant_code, nullptr);
675
676 EXPECT_STREQ(locales[2]->language_code, "en");
677 EXPECT_STREQ(locales[2]->country_code, nullptr);
678 EXPECT_STREQ(locales[2]->script_code, nullptr);
679 EXPECT_STREQ(locales[2]->variant_code, nullptr);
680
681 EXPECT_STREQ(locales[3]->language_code, "C");
682 EXPECT_STREQ(locales[3]->country_code, nullptr);
683 EXPECT_STREQ(locales[3]->script_code, nullptr);
684 EXPECT_STREQ(locales[3]->variant_code, nullptr);
685
686 return kSuccess;
687 }));
688
689 g_autoptr(GError) error = nullptr;
690 EXPECT_TRUE(fl_engine_start(engine, &error));
691 EXPECT_EQ(error, nullptr);
692
693 EXPECT_TRUE(called);
694
695 if (initial_language) {
696 g_setenv("LANGUAGE", initial_language, TRUE);
697 } else {
698 g_unsetenv("LANGUAGE");
699 }
700}
701
702static void add_view_cb(GObject* object,
703 GAsyncResult* result,
704 gpointer user_data) {
705 g_autoptr(GError) error = nullptr;
706 gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
707 EXPECT_TRUE(r);
708 EXPECT_EQ(error, nullptr);
709
710 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
711}
712
713TEST(FlEngineTest, AddView) {
714 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
715
716 g_autoptr(FlDartProject) project = fl_dart_project_new();
717 g_autoptr(FlEngine) engine = fl_engine_new(project);
718
719 bool called = false;
721 AddView, ([&called](auto engine, const FlutterAddViewInfo* info) {
722 called = true;
723 EXPECT_EQ(info->view_metrics->width, 123u);
724 EXPECT_EQ(info->view_metrics->height, 456u);
725 EXPECT_TRUE(info->view_metrics->has_constraints);
726 EXPECT_EQ(info->view_metrics->min_width_constraint, 123u);
727 EXPECT_EQ(info->view_metrics->min_height_constraint, 456u);
728 EXPECT_EQ(info->view_metrics->max_width_constraint, 888u);
729 EXPECT_EQ(info->view_metrics->max_height_constraint, 999u);
730 EXPECT_EQ(info->view_metrics->pixel_ratio, 2.0);
731
733 result.struct_size = sizeof(FlutterAddViewResult);
734 result.added = true;
735 result.user_data = info->user_data;
736 info->add_view_callback(&result);
737
738 return kSuccess;
739 }));
740
741 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
743 fl_engine_add_view(engine, FL_RENDERABLE(renderable), 123, 456, 888, 999,
744 2.0, nullptr, add_view_cb, loop);
745 EXPECT_GT(view_id, 0);
746 EXPECT_TRUE(called);
747
748 // Blocks here until add_view_cb is called.
749 g_main_loop_run(loop);
750}
751
752static void add_view_error_cb(GObject* object,
753 GAsyncResult* result,
754 gpointer user_data) {
755 g_autoptr(GError) error = nullptr;
756 gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
757 EXPECT_FALSE(r);
758 EXPECT_NE(error, nullptr);
759
760 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
761}
762
763TEST(FlEngineTest, AddViewError) {
764 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
765
766 g_autoptr(FlDartProject) project = fl_dart_project_new();
767 g_autoptr(FlEngine) engine = fl_engine_new(project);
768
770 AddView, ([](auto engine, const FlutterAddViewInfo* info) {
772 result.struct_size = sizeof(FlutterAddViewResult);
773 result.added = false;
774 result.user_data = info->user_data;
775 info->add_view_callback(&result);
776
777 return kSuccess;
778 }));
779
780 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
782 fl_engine_add_view(engine, FL_RENDERABLE(renderable), 123, 456, 123, 456,
783 2.0, nullptr, add_view_error_cb, loop);
784 EXPECT_GT(view_id, 0);
785
786 // Blocks here until add_view_error_cb is called.
787 g_main_loop_run(loop);
788}
789
790static void add_view_engine_error_cb(GObject* object,
791 GAsyncResult* result,
792 gpointer user_data) {
793 g_autoptr(GError) error = nullptr;
794 gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
795 EXPECT_FALSE(r);
796 EXPECT_NE(error, nullptr);
797
798 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
799}
800
801TEST(FlEngineTest, AddViewEngineError) {
802 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
803
804 g_autoptr(FlDartProject) project = fl_dart_project_new();
805 g_autoptr(FlEngine) engine = fl_engine_new(project);
806
808 AddView, ([](auto engine, const FlutterAddViewInfo* info) {
809 return kInvalidArguments;
810 }));
811
812 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
814 fl_engine_add_view(engine, FL_RENDERABLE(renderable), 123, 456, 123, 456,
815 2.0, nullptr, add_view_engine_error_cb, loop);
816 EXPECT_GT(view_id, 0);
817
818 // Blocks here until remove_view_engine_error_cb is called.
819 g_main_loop_run(loop);
820}
821
822static void remove_view_cb(GObject* object,
823 GAsyncResult* result,
824 gpointer user_data) {
825 g_autoptr(GError) error = nullptr;
826 gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
827 EXPECT_TRUE(r);
828 EXPECT_EQ(error, nullptr);
829
830 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
831}
832
833TEST(FlEngineTest, RemoveView) {
834 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
835
836 g_autoptr(FlDartProject) project = fl_dart_project_new();
837 g_autoptr(FlEngine) engine = fl_engine_new(project);
838
839 bool called = false;
841 RemoveView, ([&called](auto engine, const FlutterRemoveViewInfo* info) {
842 called = true;
843 EXPECT_EQ(info->view_id, 123);
844
846 result.struct_size = sizeof(FlutterRemoveViewResult);
847 result.removed = true;
848 result.user_data = info->user_data;
849 info->remove_view_callback(&result);
850
851 return kSuccess;
852 }));
853
854 fl_engine_remove_view(engine, 123, nullptr, remove_view_cb, loop);
855 EXPECT_TRUE(called);
856
857 // Blocks here until remove_view_cb is called.
858 g_main_loop_run(loop);
859}
860
861static void remove_view_error_cb(GObject* object,
862 GAsyncResult* result,
863 gpointer user_data) {
864 g_autoptr(GError) error = nullptr;
865 gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
866 EXPECT_FALSE(r);
867 EXPECT_NE(error, nullptr);
868
869 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
870}
871
872TEST(FlEngineTest, RemoveViewError) {
873 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
874
875 g_autoptr(FlDartProject) project = fl_dart_project_new();
876 g_autoptr(FlEngine) engine = fl_engine_new(project);
877
879 RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
881 result.struct_size = sizeof(FlutterRemoveViewResult);
882 result.removed = false;
883 result.user_data = info->user_data;
884 info->remove_view_callback(&result);
885
886 return kSuccess;
887 }));
888
890
891 // Blocks here until remove_view_error_cb is called.
892 g_main_loop_run(loop);
893}
894
895static void remove_view_engine_error_cb(GObject* object,
896 GAsyncResult* result,
897 gpointer user_data) {
898 g_autoptr(GError) error = nullptr;
899 gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
900 EXPECT_FALSE(r);
901 EXPECT_NE(error, nullptr);
902
903 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
904}
905
906TEST(FlEngineTest, RemoveViewEngineError) {
907 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
908
909 g_autoptr(FlDartProject) project = fl_dart_project_new();
910 g_autoptr(FlEngine) engine = fl_engine_new(project);
911
913 RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
914 return kInvalidArguments;
915 }));
916
918 loop);
919
920 // Blocks here until remove_view_engine_error_cb is called.
921 g_main_loop_run(loop);
922}
923
924TEST(FlEngineTest, SendKeyEvent) {
925 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
926
927 g_autoptr(FlDartProject) project = fl_dart_project_new();
928 g_autoptr(FlEngine) engine = fl_engine_new(project);
929
930 g_autoptr(GError) error = nullptr;
931 EXPECT_TRUE(fl_engine_start(engine, &error));
932 EXPECT_EQ(error, nullptr);
933
934 bool called;
936 SendKeyEvent,
937 ([&called](auto engine, const FlutterKeyEvent* event,
939 called = true;
940 EXPECT_EQ(event->timestamp, 1234);
941 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
942 EXPECT_EQ(event->physical, static_cast<uint64_t>(42));
943 EXPECT_EQ(event->logical, static_cast<uint64_t>(123));
944 EXPECT_TRUE(event->synthesized);
947 return kSuccess;
948 }));
949
950 FlutterKeyEvent event = {.struct_size = sizeof(FlutterKeyEvent),
951 .timestamp = 1234,
953 .physical = 42,
954 .logical = 123,
955 .character = nullptr,
956 .synthesized = true,
959 engine, &event, nullptr,
960 [](GObject* object, GAsyncResult* result, gpointer user_data) {
961 gboolean handled;
962 g_autoptr(GError) error = nullptr;
963 EXPECT_TRUE(fl_engine_send_key_event_finish(FL_ENGINE(object), result,
964 &handled, &error));
965 EXPECT_EQ(error, nullptr);
966 EXPECT_TRUE(handled);
967 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
968 },
969 loop);
970
971 g_main_loop_run(loop);
972 EXPECT_TRUE(called);
973}
974
975TEST(FlEngineTest, SendKeyEventNotHandled) {
976 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
977
978 g_autoptr(FlDartProject) project = fl_dart_project_new();
979 g_autoptr(FlEngine) engine = fl_engine_new(project);
980
981 g_autoptr(GError) error = nullptr;
982 EXPECT_TRUE(fl_engine_start(engine, &error));
983 EXPECT_EQ(error, nullptr);
984
985 bool called;
987 SendKeyEvent,
988 ([&called](auto engine, const FlutterKeyEvent* event,
990 called = true;
991 callback(FALSE, user_data);
992 return kSuccess;
993 }));
994
995 FlutterKeyEvent event = {.struct_size = sizeof(FlutterKeyEvent),
996 .timestamp = 1234,
998 .physical = 42,
999 .logical = 123,
1000 .character = nullptr,
1001 .synthesized = true,
1002 .device_type = kFlutterKeyEventDeviceTypeKeyboard};
1004 engine, &event, nullptr,
1005 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1006 gboolean handled;
1007 g_autoptr(GError) error = nullptr;
1008 EXPECT_TRUE(fl_engine_send_key_event_finish(FL_ENGINE(object), result,
1009 &handled, &error));
1010 EXPECT_EQ(error, nullptr);
1011 EXPECT_FALSE(handled);
1012 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1013 },
1014 loop);
1015
1016 g_main_loop_run(loop);
1017 EXPECT_TRUE(called);
1018}
1019
1020TEST(FlEngineTest, SendKeyEventError) {
1021 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
1022
1023 g_autoptr(FlDartProject) project = fl_dart_project_new();
1024 g_autoptr(FlEngine) engine = fl_engine_new(project);
1025
1026 g_autoptr(GError) error = nullptr;
1027 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
1028 EXPECT_TRUE(fl_engine_start(engine, &error));
1029 EXPECT_EQ(error, nullptr);
1030
1031 bool called;
1033 SendKeyEvent,
1034 ([&called](auto engine, const FlutterKeyEvent* event,
1036 called = true;
1037 return kInvalidArguments;
1038 }));
1039
1040 FlutterKeyEvent event = {.struct_size = sizeof(FlutterKeyEvent),
1041 .timestamp = 1234,
1043 .physical = 42,
1044 .logical = 123,
1045 .character = nullptr,
1046 .synthesized = true,
1047 .device_type = kFlutterKeyEventDeviceTypeKeyboard};
1049 engine, &event, nullptr,
1050 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1051 gboolean handled;
1052 g_autoptr(GError) error = nullptr;
1053 EXPECT_FALSE(fl_engine_send_key_event_finish(FL_ENGINE(object), result,
1054 &handled, &error));
1055 EXPECT_NE(error, nullptr);
1056 EXPECT_STREQ(error->message, "Failed to send key event");
1057 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1058 },
1059 loop);
1060
1061 g_main_loop_run(loop);
1062 EXPECT_TRUE(called);
1063}
1064
1065TEST(FlEngineTest, ChildObjects) {
1066 g_autoptr(FlDartProject) project = fl_dart_project_new();
1067 g_autoptr(FlEngine) engine = fl_engine_new(project);
1068
1069 // Check objects exist before engine started.
1070 EXPECT_NE(fl_engine_get_binary_messenger(engine), nullptr);
1071 EXPECT_NE(fl_engine_get_display_monitor(engine), nullptr);
1072 EXPECT_NE(fl_engine_get_task_runner(engine), nullptr);
1073 EXPECT_NE(fl_engine_get_keyboard_manager(engine), nullptr);
1074 EXPECT_NE(fl_engine_get_mouse_cursor_handler(engine), nullptr);
1075}
1076
1077// NOLINTEND(clang-analyzer-core.StackAddressEscape)
int32_t x
#define FLUTTER_API_SYMBOL(symbol)
Definition embedder.h:67
@ kFlutterKeyEventDeviceTypeKeyboard
Definition embedder.h:1391
@ kPanZoomUpdate
The pan/zoom updated.
Definition embedder.h:1303
@ kDown
Definition embedder.h:1282
FlutterEngineResult(* FlutterEngineSendPlatformMessageFnPtr)(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *message)
Definition embedder.h:3648
@ kFlutterPointerButtonMouseSecondary
Definition embedder.h:1320
@ kInvalidArguments
Definition embedder.h:75
@ kSuccess
Definition embedder.h:73
@ kFlutterPointerSignalKindScroll
Definition embedder.h:1331
@ kFlutterPointerSignalKindNone
Definition embedder.h:1330
FlutterEngineDisplaysUpdateType
Definition embedder.h:2356
@ kFlutterEngineDisplaysUpdateTypeStartup
Definition embedder.h:2362
@ kFlutterSemanticsActionTap
Definition embedder.h:125
void(* FlutterKeyEventCallback)(bool, void *)
Definition embedder.h:1465
int64_t FlutterViewId
Definition embedder.h:393
@ kFlutterKeyEventTypeUp
Definition embedder.h:1385
@ kFlutterPointerDeviceKindTrackpad
Definition embedder.h:1313
@ kFlutterPointerDeviceKindMouse
Definition embedder.h:1310
void(* OnPreEngineRestartCallback)(void *)
Definition embedder.h:631
VkDevice device
Definition main.cc:69
FlutterEngine engine
Definition main.cc:84
const char * message
g_autoptr(FlEngine) engine
FlRenderable * renderable
return TRUE
G_MODULE_EXPORT void fl_dart_project_set_ui_thread_policy(FlDartProject *project, FlUIThreadPolicy policy)
G_MODULE_EXPORT void fl_dart_project_set_dart_entrypoint_arguments(FlDartProject *self, char **argv)
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
@ FL_UI_THREAD_POLICY_RUN_ON_PLATFORM_THREAD
@ FL_UI_THREAD_POLICY_RUN_ON_SEPARATE_THREAD
@ FL_UI_THREAD_POLICY_DEFAULT
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
void fl_engine_send_mouse_pointer_event(FlEngine *self, FlutterViewId view_id, FlutterPointerPhase phase, size_t timestamp, double x, double y, FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons)
gboolean fl_engine_send_key_event_finish(FlEngine *self, GAsyncResult *result, gboolean *handled, GError **error)
void fl_engine_dispatch_semantics_action(FlEngine *self, FlutterViewId view_id, uint64_t node_id, FlutterSemanticsAction action, GBytes *data)
void fl_engine_send_window_metrics_event(FlEngine *self, FlutterEngineDisplayId display_id, FlutterViewId view_id, size_t min_width, size_t min_height, size_t max_width, size_t max_height, double pixel_ratio)
void fl_engine_notify_display_update(FlEngine *self, const FlutterEngineDisplay *displays, size_t displays_length)
Definition fl_engine.cc:907
FlMouseCursorHandler * fl_engine_get_mouse_cursor_handler(FlEngine *self)
gboolean fl_engine_remove_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
FlDisplayMonitor * fl_engine_get_display_monitor(FlEngine *self)
Definition fl_engine.cc:754
gboolean fl_engine_send_platform_message_response(FlEngine *self, const FlutterPlatformMessageResponseHandle *handle, GBytes *response, GError **error)
FlutterViewId fl_engine_add_view(FlEngine *self, FlRenderable *renderable, size_t min_width, size_t min_height, size_t max_width, size_t max_height, double pixel_ratio, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition fl_engine.cc:924
void fl_engine_send_platform_message(FlEngine *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
G_MODULE_EXPORT FlEngine * fl_engine_new(FlDartProject *project)
Definition fl_engine.cc:730
FlEngine * fl_engine_for_id(int64_t id)
Definition fl_engine.cc:724
void fl_engine_remove_view(FlEngine *self, FlutterViewId view_id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition fl_engine.cc:990
gboolean fl_engine_add_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
Definition fl_engine.cc:977
void fl_engine_send_key_event(FlEngine *self, const FlutterKeyEvent *event, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
void fl_engine_send_pointer_pan_zoom_event(FlEngine *self, FlutterViewId view_id, size_t timestamp, double x, double y, FlutterPointerPhase phase, double pan_x, double pan_y, double scale, double rotation)
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition fl_engine.cc:903
FlKeyboardManager * fl_engine_get_keyboard_manager(FlEngine *self)
G_MODULE_EXPORT FlBinaryMessenger * fl_engine_get_binary_messenger(FlEngine *self)
gboolean fl_engine_start(FlEngine *self, GError **error)
Definition fl_engine.cc:759
void on_pre_engine_restart_cb(FlEngine *engine, gpointer user_data)
static void remove_view_engine_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
TEST(FlEngineTest, NotifyDisplayUpdate)
static void remove_view_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void add_view_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void add_view_engine_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void remove_view_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void add_view_cb(GObject *object, GAsyncResult *result, gpointer user_data)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_MODULE_EXPORT FlJsonMessageCodec * fl_json_message_codec_new()
G_MODULE_EXPORT FlValue * fl_message_codec_decode_message(FlMessageCodec *self, GBytes *message, GError **error)
const uint8_t uint32_t uint32_t GError ** error
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition fl_value.cc:811
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition fl_value.cc:466
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition fl_value.h:42
@ FL_VALUE_TYPE_STRING
Definition fl_value.h:68
@ FL_VALUE_TYPE_BOOL
Definition fl_value.h:65
@ FL_VALUE_TYPE_FLOAT
Definition fl_value.h:67
G_BEGIN_DECLS FlutterViewId view_id
FlutterDesktopBinaryReply callback
double y
std::vector< FlutterEngineDisplay > * displays
#define MOCK_ENGINE_PROC(proc, mock_impl)
impeller::ShaderType type
int32_t height
int32_t width
FlutterAddViewCallback add_view_callback
Definition embedder.h:1147
const FlutterWindowMetricsEvent * view_metrics
Definition embedder.h:1132
void * user_data
The |FlutterAddViewInfo.user_data|.
Definition embedder.h:1111
bool added
True if the add view operation succeeded.
Definition embedder.h:1108
size_t struct_size
The size of this struct. Must be sizeof(FlutterEngineDisplay).
Definition embedder.h:2329
FlutterEngineUpdateLocalesFnPtr UpdateLocales
Definition embedder.h:3781
FlutterEngineAddViewFnPtr AddView
Definition embedder.h:3790
FlutterEngineRemoveViewFnPtr RemoveView
Definition embedder.h:3791
FlutterEngineSendKeyEventFnPtr SendKeyEvent
Definition embedder.h:3759
FlutterEngineSendWindowMetricsEventFnPtr SendWindowMetricsEvent
Definition embedder.h:3757
FlutterEngineSendPointerEventFnPtr SendPointerEvent
Definition embedder.h:3758
FlutterEngineInitializeFnPtr Initialize
Definition embedder.h:3754
FlutterEngineNotifyDisplayUpdateFnPtr NotifyDisplayUpdate
Definition embedder.h:3787
FlutterEngineSendPlatformMessageFnPtr SendPlatformMessage
Definition embedder.h:3760
FlutterEngineRunInitializedFnPtr RunInitialized
Definition embedder.h:3756
FlutterEngineSendPlatformMessageResponseFnPtr SendPlatformMessageResponse
Definition embedder.h:3765
FlutterEngineSendSemanticsActionFnPtr SendSemanticsAction
Definition embedder.h:3793
uint64_t logical
Definition embedder.h:1444
size_t struct_size
The size of this struct. Must be sizeof(FlutterKeyEvent).
Definition embedder.h:1422
uint64_t physical
Definition embedder.h:1436
FlutterKeyEventDeviceType device_type
The source device for the key event.
Definition embedder.h:1462
FlutterKeyEventType type
The event kind.
Definition embedder.h:1428
FlutterRemoveViewCallback remove_view_callback
Definition embedder.h:1195
FlutterViewId view_id
Definition embedder.h:1178
void * user_data
The |FlutterRemoveViewInfo.user_data|.
Definition embedder.h:1159
bool removed
True if the remove view operation succeeded.
Definition embedder.h:1156
FlutterViewId view_id
The ID of the view that includes the node.
Definition embedder.h:2816
FlutterSemanticsAction action
The semantics action.
Definition embedder.h:2822
size_t data_length
The data length.
Definition embedder.h:2828
uint64_t node_id
The semantics node identifier.
Definition embedder.h:2819
const uint8_t * data
Data associated with the action.
Definition embedder.h:2825
FlutterEngineDisplayId display_id
The identifier of the display the view is rendering on.
Definition embedder.h:1074
size_t height
Physical height of the window.
Definition embedder.h:1058
int64_t view_id
The view that this event is describing.
Definition embedder.h:1076
double pixel_ratio
Scale factor for the physical screen.
Definition embedder.h:1060
size_t width
Physical width of the window.
Definition embedder.h:1056