Flutter Engine
 
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, static_cast<size_t>(3840));
92 EXPECT_EQ(event->height, static_cast<size_t>(2160));
93 EXPECT_EQ(event->pixel_ratio, 2.0);
94
95 return kSuccess;
96 }));
97
98 fl_engine_send_window_metrics_event(engine, 99, 1, 3840, 2160, 2.0);
99
100 EXPECT_TRUE(called);
101}
102
103// Checks sending mouse pointer events works.
104TEST(FlEngineTest, MousePointer) {
105 g_autoptr(FlDartProject) project = fl_dart_project_new();
106 g_autoptr(FlEngine) engine = fl_engine_new(project);
107
108 bool called = false;
110 SendPointerEvent,
111 ([&called](auto engine, const FlutterPointerEvent* events,
112 size_t events_count) {
113 called = true;
114 EXPECT_EQ(events_count, static_cast<size_t>(1));
115 EXPECT_EQ(events[0].view_id, 1);
116 EXPECT_EQ(events[0].phase, kDown);
117 EXPECT_EQ(events[0].timestamp, static_cast<size_t>(1234567890));
118 EXPECT_EQ(events[0].x, 800);
119 EXPECT_EQ(events[0].y, 600);
120 EXPECT_EQ(events[0].device, static_cast<int32_t>(0));
121 EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindScroll);
122 EXPECT_EQ(events[0].scroll_delta_x, 1.2);
123 EXPECT_EQ(events[0].scroll_delta_y, -3.4);
124 EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindMouse);
125 EXPECT_EQ(events[0].buttons, kFlutterPointerButtonMouseSecondary);
126
127 return kSuccess;
128 }));
129
130 g_autoptr(GError) error = nullptr;
131 EXPECT_TRUE(fl_engine_start(engine, &error));
132 EXPECT_EQ(error, nullptr);
133 fl_engine_send_mouse_pointer_event(engine, 1, kDown, 1234567890, 800, 600,
136
137 EXPECT_TRUE(called);
138}
139
140// Checks sending pan/zoom events works.
141TEST(FlEngineTest, PointerPanZoom) {
142 g_autoptr(FlDartProject) project = fl_dart_project_new();
143 g_autoptr(FlEngine) engine = fl_engine_new(project);
144
145 bool called = false;
147 SendPointerEvent,
148 ([&called](auto engine, const FlutterPointerEvent* events,
149 size_t events_count) {
150 called = true;
151 EXPECT_EQ(events_count, static_cast<size_t>(1));
152 EXPECT_EQ(events[0].view_id, 1);
153 EXPECT_EQ(events[0].phase, kPanZoomUpdate);
154 EXPECT_EQ(events[0].timestamp, static_cast<size_t>(1234567890));
155 EXPECT_EQ(events[0].x, 800);
156 EXPECT_EQ(events[0].y, 600);
157 EXPECT_EQ(events[0].device, static_cast<int32_t>(1));
158 EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindNone);
159 EXPECT_EQ(events[0].pan_x, 1.5);
160 EXPECT_EQ(events[0].pan_y, 2.5);
161 EXPECT_EQ(events[0].scale, 3.5);
162 EXPECT_EQ(events[0].rotation, 4.5);
163 EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindTrackpad);
164 EXPECT_EQ(events[0].buttons, 0);
165
166 return kSuccess;
167 }));
168
169 g_autoptr(GError) error = nullptr;
170 EXPECT_TRUE(fl_engine_start(engine, &error));
171 EXPECT_EQ(error, nullptr);
172 fl_engine_send_pointer_pan_zoom_event(engine, 1, 1234567890, 800, 600,
173 kPanZoomUpdate, 1.5, 2.5, 3.5, 4.5);
174
175 EXPECT_TRUE(called);
176}
177
178// Checks dispatching a semantics action works.
179TEST(FlEngineTest, DispatchSemanticsAction) {
180 g_autoptr(FlDartProject) project = fl_dart_project_new();
181 g_autoptr(FlEngine) engine = fl_engine_new(project);
182
183 bool called = false;
185 SendSemanticsAction,
186 ([&called](auto engine, const FlutterSendSemanticsActionInfo* info) {
187 EXPECT_EQ(info->view_id, static_cast<int64_t>(456));
188 EXPECT_EQ(info->node_id, static_cast<uint64_t>(42));
189 EXPECT_EQ(info->action, kFlutterSemanticsActionTap);
190 EXPECT_EQ(info->data_length, static_cast<size_t>(4));
191 EXPECT_EQ(info->data[0], 't');
192 EXPECT_EQ(info->data[1], 'e');
193 EXPECT_EQ(info->data[2], 's');
194 EXPECT_EQ(info->data[3], 't');
195 called = true;
196
197 return kSuccess;
198 }));
199
200 g_autoptr(GError) error = nullptr;
201 EXPECT_TRUE(fl_engine_start(engine, &error));
202 EXPECT_EQ(error, nullptr);
203 g_autoptr(GBytes) data = g_bytes_new_static("test", 4);
206
207 EXPECT_TRUE(called);
208}
209
210// Checks sending platform messages works.
211TEST(FlEngineTest, PlatformMessage) {
212 g_autoptr(FlDartProject) project = fl_dart_project_new();
213 g_autoptr(FlEngine) engine = fl_engine_new(project);
214
215 bool called = false;
219 SendPlatformMessage,
220 ([&called, old_handler](auto engine,
222 if (strcmp(message->channel, "test") != 0) {
223 return old_handler(engine, message);
224 }
225
226 called = true;
227
228 EXPECT_EQ(message->message_size, static_cast<size_t>(4));
229 EXPECT_EQ(message->message[0], 't');
230 EXPECT_EQ(message->message[1], 'e');
231 EXPECT_EQ(message->message[2], 's');
232 EXPECT_EQ(message->message[3], 't');
233
234 return kSuccess;
235 }));
236
237 g_autoptr(GError) error = nullptr;
238 EXPECT_TRUE(fl_engine_start(engine, &error));
239 EXPECT_EQ(error, nullptr);
240 g_autoptr(GBytes) message = g_bytes_new_static("test", 4);
241 fl_engine_send_platform_message(engine, "test", message, nullptr, nullptr,
242 nullptr);
243
244 EXPECT_TRUE(called);
245}
246
247// Checks sending platform message responses works.
249 g_autoptr(FlDartProject) project = fl_dart_project_new();
250 g_autoptr(FlEngine) engine = fl_engine_new(project);
251
252 bool called = false;
255 SendPlatformMessageResponse,
256 ([&called](auto engine,
258 const uint8_t* data, size_t data_length) {
259 called = true;
260
261 EXPECT_EQ(
262 handle,
263 reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(
264 42));
265 EXPECT_EQ(data_length, static_cast<size_t>(4));
266 EXPECT_EQ(data[0], 't');
267 EXPECT_EQ(data[1], 'e');
268 EXPECT_EQ(data[2], 's');
269 EXPECT_EQ(data[3], 't');
270
271 return kSuccess;
272 }));
273
274 g_autoptr(GError) error = nullptr;
275 EXPECT_TRUE(fl_engine_start(engine, &error));
276 EXPECT_EQ(error, nullptr);
277 g_autoptr(GBytes) response = g_bytes_new_static("test", 4);
279 engine, reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(42),
280 response, &error));
281 EXPECT_EQ(error, nullptr);
282
283 EXPECT_TRUE(called);
284}
285
286// Checks settings handler sends settings on startup.
287TEST(FlEngineTest, SettingsHandler) {
288 g_autoptr(FlDartProject) project = fl_dart_project_new();
289 g_autoptr(FlEngine) engine = fl_engine_new(project);
290
291 bool called = false;
293 SendPlatformMessage,
294 ([&called](auto engine, const FlutterPlatformMessage* message) {
295 called = true;
296
297 EXPECT_STREQ(message->channel, "flutter/settings");
298
299 g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
300 g_autoptr(GBytes) data =
301 g_bytes_new(message->message, message->message_size);
302 g_autoptr(GError) error = nullptr;
304 FL_MESSAGE_CODEC(codec), data, &error);
305 EXPECT_NE(settings, nullptr);
306 EXPECT_EQ(error, nullptr);
307
308 FlValue* text_scale_factor =
309 fl_value_lookup_string(settings, "textScaleFactor");
310 EXPECT_NE(text_scale_factor, nullptr);
311 EXPECT_EQ(fl_value_get_type(text_scale_factor), FL_VALUE_TYPE_FLOAT);
312
313 FlValue* always_use_24hr_format =
314 fl_value_lookup_string(settings, "alwaysUse24HourFormat");
315 EXPECT_NE(always_use_24hr_format, nullptr);
316 EXPECT_EQ(fl_value_get_type(always_use_24hr_format),
318
319 FlValue* platform_brightness =
320 fl_value_lookup_string(settings, "platformBrightness");
321 EXPECT_NE(platform_brightness, nullptr);
322 EXPECT_EQ(fl_value_get_type(platform_brightness), FL_VALUE_TYPE_STRING);
323
324 return kSuccess;
325 }));
326
327 g_autoptr(GError) error = nullptr;
328 EXPECT_TRUE(fl_engine_start(engine, &error));
329 EXPECT_EQ(error, nullptr);
330
331 EXPECT_TRUE(called);
332}
333
334void on_pre_engine_restart_cb(FlEngine* engine, gpointer user_data) {
335 int* count = reinterpret_cast<int*>(user_data);
336 *count += 1;
337}
338
339// Checks restarting the engine invokes the correct callback.
340TEST(FlEngineTest, OnPreEngineRestart) {
341 g_autoptr(FlDartProject) project = fl_dart_project_new();
342 g_autoptr(FlEngine) engine = fl_engine_new(project);
343
345 void* callback_user_data;
346
347 bool called = false;
349 Initialize, ([&callback, &callback_user_data, &called](
350 size_t version, const FlutterRendererConfig* config,
351 const FlutterProjectArgs* args, void* user_data,
352 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
353 called = true;
354 callback = args->on_pre_engine_restart_callback;
355 callback_user_data = user_data;
356
357 return kSuccess;
358 }));
360 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
361
362 g_autoptr(GError) error = nullptr;
363 EXPECT_TRUE(fl_engine_start(engine, &error));
364 EXPECT_EQ(error, nullptr);
365
366 EXPECT_TRUE(called);
367 EXPECT_NE(callback, nullptr);
368
369 // The following call has no effect but should not crash.
370 callback(callback_user_data);
371
372 int count = 0;
373
374 // Set handler so that:
375 //
376 // * When the engine restarts, count += 1;
377 // * When the engine is freed, count += 10.
378 g_signal_connect(engine, "on-pre-engine-restart",
379 G_CALLBACK(on_pre_engine_restart_cb), &count);
380
381 callback(callback_user_data);
382 EXPECT_EQ(count, 1);
383}
384
385TEST(FlEngineTest, DartEntrypointArgs) {
386 GPtrArray* args_array = g_ptr_array_new();
387 g_ptr_array_add(args_array, const_cast<char*>("arg_one"));
388 g_ptr_array_add(args_array, const_cast<char*>("arg_two"));
389 g_ptr_array_add(args_array, const_cast<char*>("arg_three"));
390 g_ptr_array_add(args_array, nullptr);
391 gchar** args = reinterpret_cast<gchar**>(g_ptr_array_free(args_array, false));
392
393 g_autoptr(FlDartProject) project = fl_dart_project_new();
395 g_autoptr(FlEngine) engine = fl_engine_new(project);
396
397 bool called = false;
399 Initialize, ([&called, &set_args = args](
400 size_t version, const FlutterRendererConfig* config,
401 const FlutterProjectArgs* args, void* user_data,
402 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
403 called = true;
404 EXPECT_NE(set_args, args->dart_entrypoint_argv);
405 EXPECT_EQ(args->dart_entrypoint_argc, 3);
406
407 return kSuccess;
408 }));
410 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
411
412 g_autoptr(GError) error = nullptr;
413 EXPECT_TRUE(fl_engine_start(engine, &error));
414 EXPECT_EQ(error, nullptr);
415
416 EXPECT_TRUE(called);
417}
418
419TEST(FlEngineTest, EngineId) {
420 g_autoptr(FlDartProject) project = fl_dart_project_new();
421 g_autoptr(FlEngine) engine = fl_engine_new(project);
422 int64_t engine_id;
424 Initialize,
425 ([&engine_id](size_t version, const FlutterRendererConfig* config,
426 const FlutterProjectArgs* args, void* user_data,
427 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
428 engine_id = args->engine_id;
429 return kSuccess;
430 }));
432 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
433
434 g_autoptr(GError) error = nullptr;
435 EXPECT_TRUE(fl_engine_start(engine, &error));
436 EXPECT_EQ(error, nullptr);
437 EXPECT_TRUE(engine_id != 0);
438
439 EXPECT_EQ(fl_engine_for_id(engine_id), engine);
440}
441
442TEST(FlEngineTest, UIIsolateDefaultThreadPolicy) {
443 g_autoptr(FlDartProject) project = fl_dart_project_new();
444 g_autoptr(FlEngine) engine = fl_engine_new(project);
446
447 bool same_task_runner = false;
448
450 Initialize,
451 ([&same_task_runner](size_t version, const FlutterRendererConfig* config,
452 const FlutterProjectArgs* args, void* user_data,
453 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
454 same_task_runner = args->custom_task_runners->platform_task_runner ==
455 args->custom_task_runners->ui_task_runner;
456 return kSuccess;
457 }));
459 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
460
461 g_autoptr(GError) error = nullptr;
462 EXPECT_TRUE(fl_engine_start(engine, &error));
463 EXPECT_EQ(error, nullptr);
464 EXPECT_TRUE(same_task_runner);
465}
466
467TEST(FlEngineTest, UIIsolateOnPlatformTaskRunner) {
468 g_autoptr(FlDartProject) project = fl_dart_project_new();
469 g_autoptr(FlEngine) engine = fl_engine_new(project);
472
473 bool same_task_runner = false;
474
476 Initialize,
477 ([&same_task_runner](size_t version, const FlutterRendererConfig* config,
478 const FlutterProjectArgs* args, void* user_data,
479 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
480 same_task_runner = args->custom_task_runners->platform_task_runner ==
481 args->custom_task_runners->ui_task_runner;
482 return kSuccess;
483 }));
485 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
486
487 g_autoptr(GError) error = nullptr;
488 EXPECT_TRUE(fl_engine_start(engine, &error));
489 EXPECT_EQ(error, nullptr);
490 EXPECT_TRUE(same_task_runner);
491}
492
493TEST(FlEngineTest, UIIsolateOnSeparateThread) {
494 g_autoptr(FlDartProject) project = fl_dart_project_new();
495 g_autoptr(FlEngine) engine = fl_engine_new(project);
498
499 bool separate_thread = false;
500
502 Initialize,
503 ([&separate_thread](size_t version, const FlutterRendererConfig* config,
504 const FlutterProjectArgs* args, void* user_data,
505 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
506 separate_thread = args->custom_task_runners->ui_task_runner == nullptr;
507 return kSuccess;
508 }));
510 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
511
512 g_autoptr(GError) error = nullptr;
513 EXPECT_TRUE(fl_engine_start(engine, &error));
514 EXPECT_EQ(error, nullptr);
515 EXPECT_TRUE(separate_thread);
516}
517
518TEST(FlEngineTest, Locales) {
519 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
520 g_setenv("LANGUAGE", "de:en_US", TRUE);
521 g_autoptr(FlDartProject) project = fl_dart_project_new();
522
523 g_autoptr(FlEngine) engine = fl_engine_new(project);
524
525 bool called = false;
527 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
528 size_t locales_count) {
529 called = true;
530
531 EXPECT_EQ(locales_count, static_cast<size_t>(4));
532
533 EXPECT_STREQ(locales[0]->language_code, "de");
534 EXPECT_STREQ(locales[0]->country_code, nullptr);
535 EXPECT_STREQ(locales[0]->script_code, nullptr);
536 EXPECT_STREQ(locales[0]->variant_code, nullptr);
537
538 EXPECT_STREQ(locales[1]->language_code, "en");
539 EXPECT_STREQ(locales[1]->country_code, "US");
540 EXPECT_STREQ(locales[1]->script_code, nullptr);
541 EXPECT_STREQ(locales[1]->variant_code, nullptr);
542
543 EXPECT_STREQ(locales[2]->language_code, "en");
544 EXPECT_STREQ(locales[2]->country_code, nullptr);
545 EXPECT_STREQ(locales[2]->script_code, nullptr);
546 EXPECT_STREQ(locales[2]->variant_code, nullptr);
547
548 EXPECT_STREQ(locales[3]->language_code, "C");
549 EXPECT_STREQ(locales[3]->country_code, nullptr);
550 EXPECT_STREQ(locales[3]->script_code, nullptr);
551 EXPECT_STREQ(locales[3]->variant_code, nullptr);
552
553 return kSuccess;
554 }));
555
556 g_autoptr(GError) error = nullptr;
557 EXPECT_TRUE(fl_engine_start(engine, &error));
558 EXPECT_EQ(error, nullptr);
559
560 EXPECT_TRUE(called);
561
562 if (initial_language) {
563 g_setenv("LANGUAGE", initial_language, TRUE);
564 } else {
565 g_unsetenv("LANGUAGE");
566 }
567}
568
569TEST(FlEngineTest, CLocale) {
570 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
571 g_setenv("LANGUAGE", "C", TRUE);
572 g_autoptr(FlDartProject) project = fl_dart_project_new();
573
574 g_autoptr(FlEngine) engine = fl_engine_new(project);
575
576 bool called = false;
578 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
579 size_t locales_count) {
580 called = true;
581
582 EXPECT_EQ(locales_count, static_cast<size_t>(1));
583
584 EXPECT_STREQ(locales[0]->language_code, "C");
585 EXPECT_STREQ(locales[0]->country_code, nullptr);
586 EXPECT_STREQ(locales[0]->script_code, nullptr);
587 EXPECT_STREQ(locales[0]->variant_code, nullptr);
588
589 return kSuccess;
590 }));
591
592 g_autoptr(GError) error = nullptr;
593 EXPECT_TRUE(fl_engine_start(engine, &error));
594 EXPECT_EQ(error, nullptr);
595
596 EXPECT_TRUE(called);
597
598 if (initial_language) {
599 g_setenv("LANGUAGE", initial_language, TRUE);
600 } else {
601 g_unsetenv("LANGUAGE");
602 }
603}
604
605TEST(FlEngineTest, DuplicateLocale) {
606 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
607 g_setenv("LANGUAGE", "en:en", TRUE);
608 g_autoptr(FlDartProject) project = fl_dart_project_new();
609
610 g_autoptr(FlEngine) engine = fl_engine_new(project);
611
612 bool called = false;
614 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
615 size_t locales_count) {
616 called = true;
617
618 EXPECT_EQ(locales_count, static_cast<size_t>(2));
619
620 EXPECT_STREQ(locales[0]->language_code, "en");
621 EXPECT_STREQ(locales[0]->country_code, nullptr);
622 EXPECT_STREQ(locales[0]->script_code, nullptr);
623 EXPECT_STREQ(locales[0]->variant_code, nullptr);
624
625 EXPECT_STREQ(locales[1]->language_code, "C");
626 EXPECT_STREQ(locales[1]->country_code, nullptr);
627 EXPECT_STREQ(locales[1]->script_code, nullptr);
628 EXPECT_STREQ(locales[1]->variant_code, nullptr);
629
630 return kSuccess;
631 }));
632
633 g_autoptr(GError) error = nullptr;
634 EXPECT_TRUE(fl_engine_start(engine, &error));
635 EXPECT_EQ(error, nullptr);
636
637 EXPECT_TRUE(called);
638
639 if (initial_language) {
640 g_setenv("LANGUAGE", initial_language, TRUE);
641 } else {
642 g_unsetenv("LANGUAGE");
643 }
644}
645
646TEST(FlEngineTest, EmptyLocales) {
647 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
648 g_setenv("LANGUAGE", "de:: :en_US", TRUE);
649 g_autoptr(FlDartProject) project = fl_dart_project_new();
650
651 g_autoptr(FlEngine) engine = fl_engine_new(project);
652
653 bool called = false;
655 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
656 size_t locales_count) {
657 called = true;
658
659 EXPECT_EQ(locales_count, static_cast<size_t>(4));
660
661 EXPECT_STREQ(locales[0]->language_code, "de");
662 EXPECT_STREQ(locales[0]->country_code, nullptr);
663 EXPECT_STREQ(locales[0]->script_code, nullptr);
664 EXPECT_STREQ(locales[0]->variant_code, nullptr);
665
666 EXPECT_STREQ(locales[1]->language_code, "en");
667 EXPECT_STREQ(locales[1]->country_code, "US");
668 EXPECT_STREQ(locales[1]->script_code, nullptr);
669 EXPECT_STREQ(locales[1]->variant_code, nullptr);
670
671 EXPECT_STREQ(locales[2]->language_code, "en");
672 EXPECT_STREQ(locales[2]->country_code, nullptr);
673 EXPECT_STREQ(locales[2]->script_code, nullptr);
674 EXPECT_STREQ(locales[2]->variant_code, nullptr);
675
676 EXPECT_STREQ(locales[3]->language_code, "C");
677 EXPECT_STREQ(locales[3]->country_code, nullptr);
678 EXPECT_STREQ(locales[3]->script_code, nullptr);
679 EXPECT_STREQ(locales[3]->variant_code, nullptr);
680
681 return kSuccess;
682 }));
683
684 g_autoptr(GError) error = nullptr;
685 EXPECT_TRUE(fl_engine_start(engine, &error));
686 EXPECT_EQ(error, nullptr);
687
688 EXPECT_TRUE(called);
689
690 if (initial_language) {
691 g_setenv("LANGUAGE", initial_language, TRUE);
692 } else {
693 g_unsetenv("LANGUAGE");
694 }
695}
696
697static void add_view_cb(GObject* object,
698 GAsyncResult* result,
699 gpointer user_data) {
700 g_autoptr(GError) error = nullptr;
701 gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
702 EXPECT_TRUE(r);
703 EXPECT_EQ(error, nullptr);
704
705 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
706}
707
708TEST(FlEngineTest, AddView) {
709 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
710
711 g_autoptr(FlDartProject) project = fl_dart_project_new();
712 g_autoptr(FlEngine) engine = fl_engine_new(project);
713
714 bool called = false;
716 AddView, ([&called](auto engine, const FlutterAddViewInfo* info) {
717 called = true;
718 EXPECT_EQ(info->view_metrics->width, 123u);
719 EXPECT_EQ(info->view_metrics->height, 456u);
720 EXPECT_EQ(info->view_metrics->pixel_ratio, 2.0);
721
723 result.struct_size = sizeof(FlutterAddViewResult);
724 result.added = true;
725 result.user_data = info->user_data;
726 info->add_view_callback(&result);
727
728 return kSuccess;
729 }));
730
731 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
733 fl_engine_add_view(engine, FL_RENDERABLE(renderable), 123, 456, 2.0,
734 nullptr, add_view_cb, loop);
735 EXPECT_GT(view_id, 0);
736 EXPECT_TRUE(called);
737
738 // Blocks here until add_view_cb is called.
739 g_main_loop_run(loop);
740}
741
742static void add_view_error_cb(GObject* object,
743 GAsyncResult* result,
744 gpointer user_data) {
745 g_autoptr(GError) error = nullptr;
746 gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
747 EXPECT_FALSE(r);
748 EXPECT_NE(error, nullptr);
749
750 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
751}
752
753TEST(FlEngineTest, AddViewError) {
754 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
755
756 g_autoptr(FlDartProject) project = fl_dart_project_new();
757 g_autoptr(FlEngine) engine = fl_engine_new(project);
758
760 AddView, ([](auto engine, const FlutterAddViewInfo* info) {
762 result.struct_size = sizeof(FlutterAddViewResult);
763 result.added = false;
764 result.user_data = info->user_data;
765 info->add_view_callback(&result);
766
767 return kSuccess;
768 }));
769
770 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
772 fl_engine_add_view(engine, FL_RENDERABLE(renderable), 123, 456, 2.0,
773 nullptr, add_view_error_cb, loop);
774 EXPECT_GT(view_id, 0);
775
776 // Blocks here until add_view_error_cb is called.
777 g_main_loop_run(loop);
778}
779
780static void add_view_engine_error_cb(GObject* object,
781 GAsyncResult* result,
782 gpointer user_data) {
783 g_autoptr(GError) error = nullptr;
784 gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
785 EXPECT_FALSE(r);
786 EXPECT_NE(error, nullptr);
787
788 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
789}
790
791TEST(FlEngineTest, AddViewEngineError) {
792 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
793
794 g_autoptr(FlDartProject) project = fl_dart_project_new();
795 g_autoptr(FlEngine) engine = fl_engine_new(project);
796
798 AddView, ([](auto engine, const FlutterAddViewInfo* info) {
799 return kInvalidArguments;
800 }));
801
802 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
804 fl_engine_add_view(engine, FL_RENDERABLE(renderable), 123, 456, 2.0,
805 nullptr, add_view_engine_error_cb, loop);
806 EXPECT_GT(view_id, 0);
807
808 // Blocks here until remove_view_engine_error_cb is called.
809 g_main_loop_run(loop);
810}
811
812static void remove_view_cb(GObject* object,
813 GAsyncResult* result,
814 gpointer user_data) {
815 g_autoptr(GError) error = nullptr;
816 gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
817 EXPECT_TRUE(r);
818 EXPECT_EQ(error, nullptr);
819
820 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
821}
822
823TEST(FlEngineTest, RemoveView) {
824 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
825
826 g_autoptr(FlDartProject) project = fl_dart_project_new();
827 g_autoptr(FlEngine) engine = fl_engine_new(project);
828
829 bool called = false;
831 RemoveView, ([&called](auto engine, const FlutterRemoveViewInfo* info) {
832 called = true;
833 EXPECT_EQ(info->view_id, 123);
834
836 result.struct_size = sizeof(FlutterRemoveViewResult);
837 result.removed = true;
838 result.user_data = info->user_data;
839 info->remove_view_callback(&result);
840
841 return kSuccess;
842 }));
843
844 fl_engine_remove_view(engine, 123, nullptr, remove_view_cb, loop);
845 EXPECT_TRUE(called);
846
847 // Blocks here until remove_view_cb is called.
848 g_main_loop_run(loop);
849}
850
851static void remove_view_error_cb(GObject* object,
852 GAsyncResult* result,
853 gpointer user_data) {
854 g_autoptr(GError) error = nullptr;
855 gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
856 EXPECT_FALSE(r);
857 EXPECT_NE(error, nullptr);
858
859 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
860}
861
862TEST(FlEngineTest, RemoveViewError) {
863 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
864
865 g_autoptr(FlDartProject) project = fl_dart_project_new();
866 g_autoptr(FlEngine) engine = fl_engine_new(project);
867
869 RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
871 result.struct_size = sizeof(FlutterRemoveViewResult);
872 result.removed = false;
873 result.user_data = info->user_data;
874 info->remove_view_callback(&result);
875
876 return kSuccess;
877 }));
878
880
881 // Blocks here until remove_view_error_cb is called.
882 g_main_loop_run(loop);
883}
884
885static void remove_view_engine_error_cb(GObject* object,
886 GAsyncResult* result,
887 gpointer user_data) {
888 g_autoptr(GError) error = nullptr;
889 gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
890 EXPECT_FALSE(r);
891 EXPECT_NE(error, nullptr);
892
893 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
894}
895
896TEST(FlEngineTest, RemoveViewEngineError) {
897 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
898
899 g_autoptr(FlDartProject) project = fl_dart_project_new();
900 g_autoptr(FlEngine) engine = fl_engine_new(project);
901
903 RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
904 return kInvalidArguments;
905 }));
906
908 loop);
909
910 // Blocks here until remove_view_engine_error_cb is called.
911 g_main_loop_run(loop);
912}
913
914TEST(FlEngineTest, SendKeyEvent) {
915 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
916
917 g_autoptr(FlDartProject) project = fl_dart_project_new();
918 g_autoptr(FlEngine) engine = fl_engine_new(project);
919
920 g_autoptr(GError) error = nullptr;
921 EXPECT_TRUE(fl_engine_start(engine, &error));
922 EXPECT_EQ(error, nullptr);
923
924 bool called;
926 SendKeyEvent,
927 ([&called](auto engine, const FlutterKeyEvent* event,
929 called = true;
930 EXPECT_EQ(event->timestamp, 1234);
931 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
932 EXPECT_EQ(event->physical, static_cast<uint64_t>(42));
933 EXPECT_EQ(event->logical, static_cast<uint64_t>(123));
934 EXPECT_TRUE(event->synthesized);
937 return kSuccess;
938 }));
939
940 FlutterKeyEvent event = {.struct_size = sizeof(FlutterKeyEvent),
941 .timestamp = 1234,
943 .physical = 42,
944 .logical = 123,
945 .character = nullptr,
946 .synthesized = true,
949 engine, &event, nullptr,
950 [](GObject* object, GAsyncResult* result, gpointer user_data) {
951 gboolean handled;
952 g_autoptr(GError) error = nullptr;
953 EXPECT_TRUE(fl_engine_send_key_event_finish(FL_ENGINE(object), result,
954 &handled, &error));
955 EXPECT_EQ(error, nullptr);
956 EXPECT_TRUE(handled);
957 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
958 },
959 loop);
960
961 g_main_loop_run(loop);
962 EXPECT_TRUE(called);
963}
964
965TEST(FlEngineTest, SendKeyEventNotHandled) {
966 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
967
968 g_autoptr(FlDartProject) project = fl_dart_project_new();
969 g_autoptr(FlEngine) engine = fl_engine_new(project);
970
971 g_autoptr(GError) error = nullptr;
972 EXPECT_TRUE(fl_engine_start(engine, &error));
973 EXPECT_EQ(error, nullptr);
974
975 bool called;
977 SendKeyEvent,
978 ([&called](auto engine, const FlutterKeyEvent* event,
980 called = true;
981 callback(FALSE, user_data);
982 return kSuccess;
983 }));
984
985 FlutterKeyEvent event = {.struct_size = sizeof(FlutterKeyEvent),
986 .timestamp = 1234,
988 .physical = 42,
989 .logical = 123,
990 .character = nullptr,
991 .synthesized = true,
994 engine, &event, nullptr,
995 [](GObject* object, GAsyncResult* result, gpointer user_data) {
996 gboolean handled;
997 g_autoptr(GError) error = nullptr;
998 EXPECT_TRUE(fl_engine_send_key_event_finish(FL_ENGINE(object), result,
999 &handled, &error));
1000 EXPECT_EQ(error, nullptr);
1001 EXPECT_FALSE(handled);
1002 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1003 },
1004 loop);
1005
1006 g_main_loop_run(loop);
1007 EXPECT_TRUE(called);
1008}
1009
1010TEST(FlEngineTest, SendKeyEventError) {
1011 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
1012
1013 g_autoptr(FlDartProject) project = fl_dart_project_new();
1014 g_autoptr(FlEngine) engine = fl_engine_new(project);
1015
1016 g_autoptr(GError) error = nullptr;
1017 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.Assign)
1018 EXPECT_TRUE(fl_engine_start(engine, &error));
1019 EXPECT_EQ(error, nullptr);
1020
1021 bool called;
1023 SendKeyEvent,
1024 ([&called](auto engine, const FlutterKeyEvent* event,
1026 called = true;
1027 return kInvalidArguments;
1028 }));
1029
1030 FlutterKeyEvent event = {.struct_size = sizeof(FlutterKeyEvent),
1031 .timestamp = 1234,
1033 .physical = 42,
1034 .logical = 123,
1035 .character = nullptr,
1036 .synthesized = true,
1037 .device_type = kFlutterKeyEventDeviceTypeKeyboard};
1039 engine, &event, nullptr,
1040 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1041 gboolean handled;
1042 g_autoptr(GError) error = nullptr;
1043 EXPECT_FALSE(fl_engine_send_key_event_finish(FL_ENGINE(object), result,
1044 &handled, &error));
1045 EXPECT_NE(error, nullptr);
1046 EXPECT_STREQ(error->message, "Failed to send key event");
1047 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1048 },
1049 loop);
1050
1051 g_main_loop_run(loop);
1052 EXPECT_TRUE(called);
1053}
1054
1055TEST(FlEngineTest, ChildObjects) {
1056 g_autoptr(FlDartProject) project = fl_dart_project_new();
1057 g_autoptr(FlEngine) engine = fl_engine_new(project);
1058
1059 // Check objects exist before engine started.
1060 EXPECT_NE(fl_engine_get_binary_messenger(engine), nullptr);
1061 EXPECT_NE(fl_engine_get_display_monitor(engine), nullptr);
1062 EXPECT_NE(fl_engine_get_task_runner(engine), nullptr);
1063 EXPECT_NE(fl_engine_get_keyboard_manager(engine), nullptr);
1064 EXPECT_NE(fl_engine_get_mouse_cursor_handler(engine), nullptr);
1065 EXPECT_NE(fl_engine_get_windowing_handler(engine), nullptr);
1066}
1067
1068// NOLINTEND(clang-analyzer-core.StackAddressEscape)
GLenum type
int32_t x
#define FLUTTER_API_SYMBOL(symbol)
Definition embedder.h:67
@ kFlutterKeyEventDeviceTypeKeyboard
Definition embedder.h:1353
@ kPanZoomUpdate
The pan/zoom updated.
Definition embedder.h:1273
@ kDown
Definition embedder.h:1252
FlutterEngineResult(* FlutterEngineSendPlatformMessageFnPtr)(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *message)
Definition embedder.h:3606
@ kFlutterPointerButtonMouseSecondary
Definition embedder.h:1290
@ kInvalidArguments
Definition embedder.h:75
@ kSuccess
Definition embedder.h:73
@ kFlutterPointerSignalKindScroll
Definition embedder.h:1301
@ kFlutterPointerSignalKindNone
Definition embedder.h:1300
FlutterEngineDisplaysUpdateType
Definition embedder.h:2318
@ kFlutterEngineDisplaysUpdateTypeStartup
Definition embedder.h:2324
@ kFlutterSemanticsActionTap
Definition embedder.h:118
void(* FlutterKeyEventCallback)(bool, void *)
Definition embedder.h:1427
int64_t FlutterViewId
Definition embedder.h:386
@ kFlutterKeyEventTypeUp
Definition embedder.h:1347
@ kFlutterPointerDeviceKindTrackpad
Definition embedder.h:1283
@ kFlutterPointerDeviceKindMouse
Definition embedder.h:1280
void(* OnPreEngineRestartCallback)(void *)
Definition embedder.h:624
VkDevice device
Definition main.cc:69
FlutterEngine engine
Definition main.cc:84
g_autoptr(GMutexLocker) locker
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)
FlWindowingHandler * fl_engine_get_windowing_handler(FlEngine *self)
void fl_engine_notify_display_update(FlEngine *self, const FlutterEngineDisplay *displays, size_t displays_length)
Definition fl_engine.cc:872
void fl_engine_send_window_metrics_event(FlEngine *self, FlutterEngineDisplayId display_id, FlutterViewId view_id, size_t width, size_t height, double pixel_ratio)
FlMouseCursorHandler * fl_engine_get_mouse_cursor_handler(FlEngine *self)
gboolean fl_engine_remove_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
Definition fl_engine.cc:983
FlDisplayMonitor * fl_engine_get_display_monitor(FlEngine *self)
Definition fl_engine.cc:721
gboolean fl_engine_send_platform_message_response(FlEngine *self, const FlutterPlatformMessageResponseHandle *handle, GBytes *response, GError **error)
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:697
FlEngine * fl_engine_for_id(int64_t id)
Definition fl_engine.cc:691
void fl_engine_remove_view(FlEngine *self, FlutterViewId view_id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition fl_engine.cc:956
gboolean fl_engine_add_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
Definition fl_engine.cc:941
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)
FlutterViewId fl_engine_add_view(FlEngine *self, FlRenderable *renderable, size_t width, size_t height, double pixel_ratio, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition fl_engine.cc:892
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition fl_engine.cc:868
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:726
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)
G_BEGIN_DECLS GBytes * message
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)
int32_t height
int32_t width
FlutterAddViewCallback add_view_callback
Definition embedder.h:1117
const FlutterWindowMetricsEvent * view_metrics
Definition embedder.h:1102
void * user_data
The |FlutterAddViewInfo.user_data|.
Definition embedder.h:1081
bool added
True if the add view operation succeeded.
Definition embedder.h:1078
size_t struct_size
The size of this struct. Must be sizeof(FlutterEngineDisplay).
Definition embedder.h:2291
FlutterEngineUpdateLocalesFnPtr UpdateLocales
Definition embedder.h:3739
FlutterEngineAddViewFnPtr AddView
Definition embedder.h:3748
FlutterEngineRemoveViewFnPtr RemoveView
Definition embedder.h:3749
FlutterEngineSendKeyEventFnPtr SendKeyEvent
Definition embedder.h:3717
FlutterEngineSendWindowMetricsEventFnPtr SendWindowMetricsEvent
Definition embedder.h:3715
FlutterEngineSendPointerEventFnPtr SendPointerEvent
Definition embedder.h:3716
FlutterEngineInitializeFnPtr Initialize
Definition embedder.h:3712
FlutterEngineNotifyDisplayUpdateFnPtr NotifyDisplayUpdate
Definition embedder.h:3745
FlutterEngineSendPlatformMessageFnPtr SendPlatformMessage
Definition embedder.h:3718
FlutterEngineRunInitializedFnPtr RunInitialized
Definition embedder.h:3714
FlutterEngineSendPlatformMessageResponseFnPtr SendPlatformMessageResponse
Definition embedder.h:3723
FlutterEngineSendSemanticsActionFnPtr SendSemanticsAction
Definition embedder.h:3751
uint64_t logical
Definition embedder.h:1406
size_t struct_size
The size of this struct. Must be sizeof(FlutterKeyEvent).
Definition embedder.h:1384
uint64_t physical
Definition embedder.h:1398
FlutterKeyEventDeviceType device_type
The source device for the key event.
Definition embedder.h:1424
FlutterKeyEventType type
The event kind.
Definition embedder.h:1390
FlutterRemoveViewCallback remove_view_callback
Definition embedder.h:1165
FlutterViewId view_id
Definition embedder.h:1148
void * user_data
The |FlutterRemoveViewInfo.user_data|.
Definition embedder.h:1129
bool removed
True if the remove view operation succeeded.
Definition embedder.h:1126
FlutterViewId view_id
The ID of the view that includes the node.
Definition embedder.h:2774
FlutterSemanticsAction action
The semantics action.
Definition embedder.h:2780
size_t data_length
The data length.
Definition embedder.h:2786
uint64_t node_id
The semantics node identifier.
Definition embedder.h:2777
const uint8_t * data
Data associated with the action.
Definition embedder.h:2783
FlutterEngineDisplayId display_id
The identifier of the display the view is rendering on.
Definition embedder.h:1067
size_t height
Physical height of the window.
Definition embedder.h:1051
int64_t view_id
The view that this event is describing.
Definition embedder.h:1069
double pixel_ratio
Scale factor for the physical screen.
Definition embedder.h:1053
size_t width
Physical width of the window.
Definition embedder.h:1049
std::shared_ptr< const fml::Mapping > data