| Flutter Linux Embedder |

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
8 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
9 #include "flutter/shell/platform/linux/fl_engine_private.h"
10 #include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
11 #include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
12 #include "flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h"
13 #include "flutter/shell/platform/linux/testing/mock_renderable.h"
14
15 // MOCK_ENGINE_PROC is leaky by design
16 // NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
17
18 // Checks notifying display updates works.
19 TEST(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;
28 fl_engine_get_embedder_api(engine)->NotifyDisplayUpdate = MOCK_ENGINE_PROC(
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
51 FlutterEngineDisplay displays[2] = {
52 {
53 .struct_size = sizeof(FlutterEngineDisplay),
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 }};
70 fl_engine_notify_display_update(engine, displays, 2);
71
72 EXPECT_TRUE(called);
73 }
74
75 // Checks sending window metrics events works.
76 TEST(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;
85 fl_engine_get_embedder_api(engine)->SendWindowMetricsEvent = MOCK_ENGINE_PROC(
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.
104 TEST(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;
109 fl_engine_get_embedder_api(engine)->SendPointerEvent = MOCK_ENGINE_PROC(
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,
134 kFlutterPointerDeviceKindMouse, 1.2, -3.4,
135 kFlutterPointerButtonMouseSecondary);
136
137 EXPECT_TRUE(called);
138 }
139
140 // Checks sending pan/zoom events works.
141 TEST(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;
146 fl_engine_get_embedder_api(engine)->SendPointerEvent = MOCK_ENGINE_PROC(
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.
179 TEST(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;
184 fl_engine_get_embedder_api(engine)->SendSemanticsAction = MOCK_ENGINE_PROC(
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);
204 fl_engine_dispatch_semantics_action(engine, 456, 42,
205 kFlutterSemanticsActionTap, data);
206
207 EXPECT_TRUE(called);
208 }
209
210 // Checks sending platform messages works.
211 TEST(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;
216 FlutterEngineSendPlatformMessageFnPtr old_handler =
217 fl_engine_get_embedder_api(engine)->SendPlatformMessage;
218 fl_engine_get_embedder_api(engine)->SendPlatformMessage = MOCK_ENGINE_PROC(
219 SendPlatformMessage,
220 ([&called, old_handler](auto engine,
221 const FlutterPlatformMessage* message) {
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.
248 TEST(FlEngineTest, PlatformMessageResponse) {
249 g_autoptr(FlDartProject) project = fl_dart_project_new();
250 g_autoptr(FlEngine) engine = fl_engine_new(project);
251
252 bool called = false;
253 fl_engine_get_embedder_api(engine)->SendPlatformMessageResponse =
254 MOCK_ENGINE_PROC(
255 SendPlatformMessageResponse,
256 ([&called](auto engine,
257 const FlutterPlatformMessageResponseHandle* handle,
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);
278 EXPECT_TRUE(fl_engine_send_platform_message_response(
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.
287 TEST(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;
292 fl_engine_get_embedder_api(engine)->SendPlatformMessage = MOCK_ENGINE_PROC(
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;
303 g_autoptr(FlValue) settings = fl_message_codec_decode_message(
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),
317 FL_VALUE_TYPE_BOOL);
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
334 void 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.
340 TEST(FlEngineTest, OnPreEngineRestart) {
341 g_autoptr(FlDartProject) project = fl_dart_project_new();
342 g_autoptr(FlEngine) engine = fl_engine_new(project);
343
344 OnPreEngineRestartCallback callback;
345 void* callback_user_data;
346
347 bool called = false;
348 fl_engine_get_embedder_api(engine)->Initialize = MOCK_ENGINE_PROC(
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 }));
359 fl_engine_get_embedder_api(engine)->RunInitialized =
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
385 TEST(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();
394 fl_dart_project_set_dart_entrypoint_arguments(project, args);
395 g_autoptr(FlEngine) engine = fl_engine_new(project);
396
397 bool called = false;
398 fl_engine_get_embedder_api(engine)->Initialize = MOCK_ENGINE_PROC(
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 }));
409 fl_engine_get_embedder_api(engine)->RunInitialized =
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
419 TEST(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;
423 fl_engine_get_embedder_api(engine)->Initialize = MOCK_ENGINE_PROC(
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 }));
431 fl_engine_get_embedder_api(engine)->RunInitialized =
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
442 TEST(FlEngineTest, UIIsolateOnPlatformTaskRunner) {
443 g_autoptr(FlDartProject) project = fl_dart_project_new();
444 g_autoptr(FlEngine) engine = fl_engine_new(project);
445 fl_dart_project_set_ui_thread_policy(
446 project, FL_UI_THREAD_POLICY_RUN_ON_PLATFORM_THREAD);
447
448 bool same_task_runner = false;
449
450 fl_engine_get_embedder_api(engine)->Initialize = MOCK_ENGINE_PROC(
451 Initialize,
452 ([&same_task_runner](size_t version, const FlutterRendererConfig* config,
453 const FlutterProjectArgs* args, void* user_data,
454 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
455 same_task_runner = args->custom_task_runners->platform_task_runner ==
456 args->custom_task_runners->ui_task_runner;
457 return kSuccess;
458 }));
459 fl_engine_get_embedder_api(engine)->RunInitialized =
460 MOCK_ENGINE_PROC(RunInitialized, ([](auto engine) { return kSuccess; }));
461
462 g_autoptr(GError) error = nullptr;
463 EXPECT_TRUE(fl_engine_start(engine, &error));
464 EXPECT_EQ(error, nullptr);
465 EXPECT_TRUE(same_task_runner);
466 }
467
468 TEST(FlEngineTest, UIIsolateOnSeparateThread) {
469 g_autoptr(FlDartProject) project = fl_dart_project_new();
470 g_autoptr(FlEngine) engine = fl_engine_new(project);
471 fl_dart_project_set_ui_thread_policy(
472 project, FL_UI_THREAD_POLICY_RUN_ON_SEPARATE_THREAD);
473
474 bool separate_thread = false;
475
476 fl_engine_get_embedder_api(engine)->Initialize = MOCK_ENGINE_PROC(
477 Initialize,
478 ([&separate_thread](size_t version, const FlutterRendererConfig* config,
479 const FlutterProjectArgs* args, void* user_data,
480 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
481 separate_thread = args->custom_task_runners->ui_task_runner == nullptr;
482 return kSuccess;
483 }));
484 fl_engine_get_embedder_api(engine)->RunInitialized =
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(separate_thread);
491 }
492
493 TEST(FlEngineTest, Locales) {
494 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
495 g_setenv("LANGUAGE", "de:en_US", TRUE);
496 g_autoptr(FlDartProject) project = fl_dart_project_new();
497
498 g_autoptr(FlEngine) engine = fl_engine_new(project);
499
500 bool called = false;
501 fl_engine_get_embedder_api(engine)->UpdateLocales = MOCK_ENGINE_PROC(
502 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
503 size_t locales_count) {
504 called = true;
505
506 EXPECT_EQ(locales_count, static_cast<size_t>(4));
507
508 EXPECT_STREQ(locales[0]->language_code, "de");
509 EXPECT_STREQ(locales[0]->country_code, nullptr);
510 EXPECT_STREQ(locales[0]->script_code, nullptr);
511 EXPECT_STREQ(locales[0]->variant_code, nullptr);
512
513 EXPECT_STREQ(locales[1]->language_code, "en");
514 EXPECT_STREQ(locales[1]->country_code, "US");
515 EXPECT_STREQ(locales[1]->script_code, nullptr);
516 EXPECT_STREQ(locales[1]->variant_code, nullptr);
517
518 EXPECT_STREQ(locales[2]->language_code, "en");
519 EXPECT_STREQ(locales[2]->country_code, nullptr);
520 EXPECT_STREQ(locales[2]->script_code, nullptr);
521 EXPECT_STREQ(locales[2]->variant_code, nullptr);
522
523 EXPECT_STREQ(locales[3]->language_code, "C");
524 EXPECT_STREQ(locales[3]->country_code, nullptr);
525 EXPECT_STREQ(locales[3]->script_code, nullptr);
526 EXPECT_STREQ(locales[3]->variant_code, nullptr);
527
528 return kSuccess;
529 }));
530
531 g_autoptr(GError) error = nullptr;
532 EXPECT_TRUE(fl_engine_start(engine, &error));
533 EXPECT_EQ(error, nullptr);
534
535 EXPECT_TRUE(called);
536
537 if (initial_language) {
538 g_setenv("LANGUAGE", initial_language, TRUE);
539 } else {
540 g_unsetenv("LANGUAGE");
541 }
542 }
543
544 TEST(FlEngineTest, CLocale) {
545 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
546 g_setenv("LANGUAGE", "C", TRUE);
547 g_autoptr(FlDartProject) project = fl_dart_project_new();
548
549 g_autoptr(FlEngine) engine = fl_engine_new(project);
550
551 bool called = false;
552 fl_engine_get_embedder_api(engine)->UpdateLocales = MOCK_ENGINE_PROC(
553 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
554 size_t locales_count) {
555 called = true;
556
557 EXPECT_EQ(locales_count, static_cast<size_t>(1));
558
559 EXPECT_STREQ(locales[0]->language_code, "C");
560 EXPECT_STREQ(locales[0]->country_code, nullptr);
561 EXPECT_STREQ(locales[0]->script_code, nullptr);
562 EXPECT_STREQ(locales[0]->variant_code, nullptr);
563
564 return kSuccess;
565 }));
566
567 g_autoptr(GError) error = nullptr;
568 EXPECT_TRUE(fl_engine_start(engine, &error));
569 EXPECT_EQ(error, nullptr);
570
571 EXPECT_TRUE(called);
572
573 if (initial_language) {
574 g_setenv("LANGUAGE", initial_language, TRUE);
575 } else {
576 g_unsetenv("LANGUAGE");
577 }
578 }
579
580 TEST(FlEngineTest, DuplicateLocale) {
581 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
582 g_setenv("LANGUAGE", "en:en", TRUE);
583 g_autoptr(FlDartProject) project = fl_dart_project_new();
584
585 g_autoptr(FlEngine) engine = fl_engine_new(project);
586
587 bool called = false;
588 fl_engine_get_embedder_api(engine)->UpdateLocales = MOCK_ENGINE_PROC(
589 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
590 size_t locales_count) {
591 called = true;
592
593 EXPECT_EQ(locales_count, static_cast<size_t>(2));
594
595 EXPECT_STREQ(locales[0]->language_code, "en");
596 EXPECT_STREQ(locales[0]->country_code, nullptr);
597 EXPECT_STREQ(locales[0]->script_code, nullptr);
598 EXPECT_STREQ(locales[0]->variant_code, nullptr);
599
600 EXPECT_STREQ(locales[1]->language_code, "C");
601 EXPECT_STREQ(locales[1]->country_code, nullptr);
602 EXPECT_STREQ(locales[1]->script_code, nullptr);
603 EXPECT_STREQ(locales[1]->variant_code, nullptr);
604
605 return kSuccess;
606 }));
607
608 g_autoptr(GError) error = nullptr;
609 EXPECT_TRUE(fl_engine_start(engine, &error));
610 EXPECT_EQ(error, nullptr);
611
612 EXPECT_TRUE(called);
613
614 if (initial_language) {
615 g_setenv("LANGUAGE", initial_language, TRUE);
616 } else {
617 g_unsetenv("LANGUAGE");
618 }
619 }
620
621 TEST(FlEngineTest, EmptyLocales) {
622 g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
623 g_setenv("LANGUAGE", "de:: :en_US", TRUE);
624 g_autoptr(FlDartProject) project = fl_dart_project_new();
625
626 g_autoptr(FlEngine) engine = fl_engine_new(project);
627
628 bool called = false;
629 fl_engine_get_embedder_api(engine)->UpdateLocales = MOCK_ENGINE_PROC(
630 UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
631 size_t locales_count) {
632 called = true;
633
634 EXPECT_EQ(locales_count, static_cast<size_t>(4));
635
636 EXPECT_STREQ(locales[0]->language_code, "de");
637 EXPECT_STREQ(locales[0]->country_code, nullptr);
638 EXPECT_STREQ(locales[0]->script_code, nullptr);
639 EXPECT_STREQ(locales[0]->variant_code, nullptr);
640
641 EXPECT_STREQ(locales[1]->language_code, "en");
642 EXPECT_STREQ(locales[1]->country_code, "US");
643 EXPECT_STREQ(locales[1]->script_code, nullptr);
644 EXPECT_STREQ(locales[1]->variant_code, nullptr);
645
646 EXPECT_STREQ(locales[2]->language_code, "en");
647 EXPECT_STREQ(locales[2]->country_code, nullptr);
648 EXPECT_STREQ(locales[2]->script_code, nullptr);
649 EXPECT_STREQ(locales[2]->variant_code, nullptr);
650
651 EXPECT_STREQ(locales[3]->language_code, "C");
652 EXPECT_STREQ(locales[3]->country_code, nullptr);
653 EXPECT_STREQ(locales[3]->script_code, nullptr);
654 EXPECT_STREQ(locales[3]->variant_code, nullptr);
655
656 return kSuccess;
657 }));
658
659 g_autoptr(GError) error = nullptr;
660 EXPECT_TRUE(fl_engine_start(engine, &error));
661 EXPECT_EQ(error, nullptr);
662
663 EXPECT_TRUE(called);
664
665 if (initial_language) {
666 g_setenv("LANGUAGE", initial_language, TRUE);
667 } else {
668 g_unsetenv("LANGUAGE");
669 }
670 }
671
672 static void add_view_cb(GObject* object,
673 GAsyncResult* result,
674 gpointer user_data) {
675 g_autoptr(GError) error = nullptr;
676 gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
677 EXPECT_TRUE(r);
678 EXPECT_EQ(error, nullptr);
679
680 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
681 }
682
683 TEST(FlEngineTest, AddView) {
684 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
685
686 g_autoptr(FlDartProject) project = fl_dart_project_new();
687 g_autoptr(FlEngine) engine = fl_engine_new(project);
688
689 bool called = false;
690 fl_engine_get_embedder_api(engine)->AddView = MOCK_ENGINE_PROC(
691 AddView, ([&called](auto engine, const FlutterAddViewInfo* info) {
692 called = true;
693 EXPECT_EQ(info->view_metrics->width, 123u);
694 EXPECT_EQ(info->view_metrics->height, 456u);
695 EXPECT_EQ(info->view_metrics->pixel_ratio, 2.0);
696
697 FlutterAddViewResult result;
698 result.struct_size = sizeof(FlutterAddViewResult);
699 result.added = true;
700 result.user_data = info->user_data;
701 info->add_view_callback(&result);
702
703 return kSuccess;
704 }));
705
706 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
707 FlutterViewId view_id =
708 fl_engine_add_view(engine, FL_RENDERABLE(renderable), 123, 456, 2.0,
709 nullptr, add_view_cb, loop);
710 EXPECT_GT(view_id, 0);
711 EXPECT_TRUE(called);
712
713 // Blocks here until add_view_cb is called.
714 g_main_loop_run(loop);
715 }
716
717 static void add_view_error_cb(GObject* object,
718 GAsyncResult* result,
719 gpointer user_data) {
720 g_autoptr(GError) error = nullptr;
721 gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
722 EXPECT_FALSE(r);
723 EXPECT_NE(error, nullptr);
724
725 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
726 }
727
728 TEST(FlEngineTest, AddViewError) {
729 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
730
731 g_autoptr(FlDartProject) project = fl_dart_project_new();
732 g_autoptr(FlEngine) engine = fl_engine_new(project);
733
734 fl_engine_get_embedder_api(engine)->AddView = MOCK_ENGINE_PROC(
735 AddView, ([](auto engine, const FlutterAddViewInfo* info) {
736 FlutterAddViewResult result;
737 result.struct_size = sizeof(FlutterAddViewResult);
738 result.added = false;
739 result.user_data = info->user_data;
740 info->add_view_callback(&result);
741
742 return kSuccess;
743 }));
744
745 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
746 FlutterViewId view_id =
747 fl_engine_add_view(engine, FL_RENDERABLE(renderable), 123, 456, 2.0,
748 nullptr, add_view_error_cb, loop);
749 EXPECT_GT(view_id, 0);
750
751 // Blocks here until add_view_error_cb is called.
752 g_main_loop_run(loop);
753 }
754
755 static void add_view_engine_error_cb(GObject* object,
756 GAsyncResult* result,
757 gpointer user_data) {
758 g_autoptr(GError) error = nullptr;
759 gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
760 EXPECT_FALSE(r);
761 EXPECT_NE(error, nullptr);
762
763 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
764 }
765
766 TEST(FlEngineTest, AddViewEngineError) {
767 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
768
769 g_autoptr(FlDartProject) project = fl_dart_project_new();
770 g_autoptr(FlEngine) engine = fl_engine_new(project);
771
772 fl_engine_get_embedder_api(engine)->AddView = MOCK_ENGINE_PROC(
773 AddView, ([](auto engine, const FlutterAddViewInfo* info) {
774 return kInvalidArguments;
775 }));
776
777 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
778 FlutterViewId view_id =
779 fl_engine_add_view(engine, FL_RENDERABLE(renderable), 123, 456, 2.0,
780 nullptr, add_view_engine_error_cb, loop);
781 EXPECT_GT(view_id, 0);
782
783 // Blocks here until remove_view_engine_error_cb is called.
784 g_main_loop_run(loop);
785 }
786
787 static void remove_view_cb(GObject* object,
788 GAsyncResult* result,
789 gpointer user_data) {
790 g_autoptr(GError) error = nullptr;
791 gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
792 EXPECT_TRUE(r);
793 EXPECT_EQ(error, nullptr);
794
795 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
796 }
797
798 TEST(FlEngineTest, RemoveView) {
799 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
800
801 g_autoptr(FlDartProject) project = fl_dart_project_new();
802 g_autoptr(FlEngine) engine = fl_engine_new(project);
803
804 bool called = false;
805 fl_engine_get_embedder_api(engine)->RemoveView = MOCK_ENGINE_PROC(
806 RemoveView, ([&called](auto engine, const FlutterRemoveViewInfo* info) {
807 called = true;
808 EXPECT_EQ(info->view_id, 123);
809
810 FlutterRemoveViewResult result;
811 result.struct_size = sizeof(FlutterRemoveViewResult);
812 result.removed = true;
813 result.user_data = info->user_data;
814 info->remove_view_callback(&result);
815
816 return kSuccess;
817 }));
818
819 fl_engine_remove_view(engine, 123, nullptr, remove_view_cb, loop);
820 EXPECT_TRUE(called);
821
822 // Blocks here until remove_view_cb is called.
823 g_main_loop_run(loop);
824 }
825
826 static void remove_view_error_cb(GObject* object,
827 GAsyncResult* result,
828 gpointer user_data) {
829 g_autoptr(GError) error = nullptr;
830 gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
831 EXPECT_FALSE(r);
832 EXPECT_NE(error, nullptr);
833
834 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
835 }
836
837 TEST(FlEngineTest, RemoveViewError) {
838 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
839
840 g_autoptr(FlDartProject) project = fl_dart_project_new();
841 g_autoptr(FlEngine) engine = fl_engine_new(project);
842
843 fl_engine_get_embedder_api(engine)->RemoveView = MOCK_ENGINE_PROC(
844 RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
845 FlutterRemoveViewResult result;
846 result.struct_size = sizeof(FlutterRemoveViewResult);
847 result.removed = false;
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_error_cb, loop);
855
856 // Blocks here until remove_view_error_cb is called.
857 g_main_loop_run(loop);
858 }
859
860 static void remove_view_engine_error_cb(GObject* object,
861 GAsyncResult* result,
862 gpointer user_data) {
863 g_autoptr(GError) error = nullptr;
864 gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
865 EXPECT_FALSE(r);
866 EXPECT_NE(error, nullptr);
867
868 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
869 }
870
871 TEST(FlEngineTest, RemoveViewEngineError) {
872 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
873
874 g_autoptr(FlDartProject) project = fl_dart_project_new();
875 g_autoptr(FlEngine) engine = fl_engine_new(project);
876
877 fl_engine_get_embedder_api(engine)->RemoveView = MOCK_ENGINE_PROC(
878 RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
879 return kInvalidArguments;
880 }));
881
882 fl_engine_remove_view(engine, 123, nullptr, remove_view_engine_error_cb,
883 loop);
884
885 // Blocks here until remove_view_engine_error_cb is called.
886 g_main_loop_run(loop);
887 }
888
889 TEST(FlEngineTest, SendKeyEvent) {
890 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
891
892 g_autoptr(FlDartProject) project = fl_dart_project_new();
893 g_autoptr(FlEngine) engine = fl_engine_new(project);
894
895 g_autoptr(GError) error = nullptr;
896 EXPECT_TRUE(fl_engine_start(engine, &error));
897 EXPECT_EQ(error, nullptr);
898
899 bool called;
900 fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
901 SendKeyEvent,
902 ([&called](auto engine, const FlutterKeyEvent* event,
903 FlutterKeyEventCallback callback, void* user_data) {
904 called = true;
905 EXPECT_EQ(event->timestamp, 1234);
906 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
907 EXPECT_EQ(event->physical, static_cast<uint64_t>(42));
908 EXPECT_EQ(event->logical, static_cast<uint64_t>(123));
909 EXPECT_TRUE(event->synthesized);
910 EXPECT_EQ(event->device_type, kFlutterKeyEventDeviceTypeKeyboard);
911 callback(TRUE, user_data);
912 return kSuccess;
913 }));
914
915 FlutterKeyEvent event = {.struct_size = sizeof(FlutterKeyEvent),
916 .timestamp = 1234,
917 .type = kFlutterKeyEventTypeUp,
918 .physical = 42,
919 .logical = 123,
920 .character = nullptr,
921 .synthesized = true,
922 .device_type = kFlutterKeyEventDeviceTypeKeyboard};
923 fl_engine_send_key_event(
924 engine, &event, nullptr,
925 [](GObject* object, GAsyncResult* result, gpointer user_data) {
926 gboolean handled;
927 g_autoptr(GError) error = nullptr;
928 EXPECT_TRUE(fl_engine_send_key_event_finish(FL_ENGINE(object), result,
929 &handled, &error));
930 EXPECT_EQ(error, nullptr);
931 EXPECT_TRUE(handled);
932 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
933 },
934 loop);
935
936 g_main_loop_run(loop);
937 EXPECT_TRUE(called);
938 }
939
940 TEST(FlEngineTest, SendKeyEventNotHandled) {
941 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
942
943 g_autoptr(FlDartProject) project = fl_dart_project_new();
944 g_autoptr(FlEngine) engine = fl_engine_new(project);
945
946 g_autoptr(GError) error = nullptr;
947 EXPECT_TRUE(fl_engine_start(engine, &error));
948 EXPECT_EQ(error, nullptr);
949
950 bool called;
951 fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
952 SendKeyEvent,
953 ([&called](auto engine, const FlutterKeyEvent* event,
954 FlutterKeyEventCallback callback, void* user_data) {
955 called = true;
956 callback(FALSE, user_data);
957 return kSuccess;
958 }));
959
960 FlutterKeyEvent event = {.struct_size = sizeof(FlutterKeyEvent),
961 .timestamp = 1234,
962 .type = kFlutterKeyEventTypeUp,
963 .physical = 42,
964 .logical = 123,
965 .character = nullptr,
966 .synthesized = true,
967 .device_type = kFlutterKeyEventDeviceTypeKeyboard};
968 fl_engine_send_key_event(
969 engine, &event, nullptr,
970 [](GObject* object, GAsyncResult* result, gpointer user_data) {
971 gboolean handled;
972 g_autoptr(GError) error = nullptr;
973 EXPECT_TRUE(fl_engine_send_key_event_finish(FL_ENGINE(object), result,
974 &handled, &error));
975 EXPECT_EQ(error, nullptr);
976 EXPECT_FALSE(handled);
977 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
978 },
979 loop);
980
981 g_main_loop_run(loop);
982 EXPECT_TRUE(called);
983 }
984
985 TEST(FlEngineTest, SendKeyEventError) {
986 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
987
988 g_autoptr(FlDartProject) project = fl_dart_project_new();
989 g_autoptr(FlEngine) engine = fl_engine_new(project);
990
991 g_autoptr(GError) error = nullptr;
992 EXPECT_TRUE(fl_engine_start(engine, &error));
993 EXPECT_EQ(error, nullptr);
994
995 bool called;
996 fl_engine_get_embedder_api(engine)->SendKeyEvent = MOCK_ENGINE_PROC(
997 SendKeyEvent,
998 ([&called](auto engine, const FlutterKeyEvent* event,
999 FlutterKeyEventCallback callback, void* user_data) {
1000 called = true;
1001 return kInvalidArguments;
1002 }));
1003
1004 FlutterKeyEvent event = {.struct_size = sizeof(FlutterKeyEvent),
1005 .timestamp = 1234,
1006 .type = kFlutterKeyEventTypeUp,
1007 .physical = 42,
1008 .logical = 123,
1009 .character = nullptr,
1010 .synthesized = true,
1011 .device_type = kFlutterKeyEventDeviceTypeKeyboard};
1012 fl_engine_send_key_event(
1013 engine, &event, nullptr,
1014 [](GObject* object, GAsyncResult* result, gpointer user_data) {
1015 gboolean handled;
1016 g_autoptr(GError) error = nullptr;
1017 EXPECT_FALSE(fl_engine_send_key_event_finish(FL_ENGINE(object), result,
1018 &handled, &error));
1019 EXPECT_NE(error, nullptr);
1020 EXPECT_STREQ(error->message, "Failed to send key event");
1021 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
1022 },
1023 loop);
1024
1025 g_main_loop_run(loop);
1026 EXPECT_TRUE(called);
1027 }
1028
1029 TEST(FlEngineTest, ChildObjects) {
1030 g_autoptr(FlDartProject) project = fl_dart_project_new();
1031 g_autoptr(FlEngine) engine = fl_engine_new(project);
1032
1033 // Check objects exist before engine started.
1034 EXPECT_NE(fl_engine_get_binary_messenger(engine), nullptr);
1035 EXPECT_NE(fl_engine_get_display_monitor(engine), nullptr);
1036 EXPECT_NE(fl_engine_get_task_runner(engine), nullptr);
1037 EXPECT_NE(fl_engine_get_keyboard_manager(engine), nullptr);
1038 EXPECT_NE(fl_engine_get_mouse_cursor_handler(engine), nullptr);
1039 EXPECT_NE(fl_engine_get_windowing_handler(engine), nullptr);
1040 }
1041
1042 // NOLINTEND(clang-analyzer-core.StackAddressEscape)
fl_dart_project_new
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
Definition: fl_dart_project.cc:52
fl_dart_project_set_ui_thread_policy
G_MODULE_EXPORT void fl_dart_project_set_ui_thread_policy(FlDartProject *project, FlUIThreadPolicy policy)
Definition: fl_dart_project.cc:121
fl_dart_project_set_dart_entrypoint_arguments
G_MODULE_EXPORT void fl_dart_project_set_dart_entrypoint_arguments(FlDartProject *self, char **argv)
Definition: fl_dart_project.cc:112
FL_UI_THREAD_POLICY_RUN_ON_PLATFORM_THREAD
@ FL_UI_THREAD_POLICY_RUN_ON_PLATFORM_THREAD
Definition: fl_dart_project.h:143
FL_UI_THREAD_POLICY_RUN_ON_SEPARATE_THREAD
@ FL_UI_THREAD_POLICY_RUN_ON_SEPARATE_THREAD
Definition: fl_dart_project.h:144
fl_engine_get_mouse_cursor_handler
FlMouseCursorHandler * fl_engine_get_mouse_cursor_handler(FlEngine *self)
Definition: fl_engine.cc:1466
fl_engine_send_mouse_pointer_event
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)
Definition: fl_engine.cc:1121
fl_engine_send_key_event_finish
gboolean fl_engine_send_key_event_finish(FlEngine *self, GAsyncResult *result, gboolean *handled, GError **error)
Definition: fl_engine.cc:1347
fl_engine_get_embedder_api
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition: fl_engine.cc:858
fl_engine_dispatch_semantics_action
void fl_engine_dispatch_semantics_action(FlEngine *self, FlutterViewId view_id, uint64_t node_id, FlutterSemanticsAction action, GBytes *data)
Definition: fl_engine.cc:1364
fl_engine_notify_display_update
void fl_engine_notify_display_update(FlEngine *self, const FlutterEngineDisplay *displays, size_t displays_length)
Definition: fl_engine.cc:862
fl_engine_send_window_metrics_event
void fl_engine_send_window_metrics_event(FlEngine *self, FlutterEngineDisplayId display_id, FlutterViewId view_id, size_t width, size_t height, double pixel_ratio)
Definition: fl_engine.cc:1099
fl_engine_get_windowing_handler
FlWindowingHandler * fl_engine_get_windowing_handler(FlEngine *self)
Definition: fl_engine.cc:1451
fl_engine_remove_view_finish
gboolean fl_engine_remove_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
Definition: fl_engine.cc:973
fl_engine_get_task_runner
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1419
fl_engine_get_keyboard_manager
FlKeyboardManager * fl_engine_get_keyboard_manager(FlEngine *self)
Definition: fl_engine.cc:1456
fl_engine_get_display_monitor
FlDisplayMonitor * fl_engine_get_display_monitor(FlEngine *self)
Definition: fl_engine.cc:715
fl_engine_send_platform_message_response
gboolean fl_engine_send_platform_message_response(FlEngine *self, const FlutterPlatformMessageResponseHandle *handle, GBytes *response, GError **error)
Definition: fl_engine.cc:999
fl_engine_send_platform_message
void fl_engine_send_platform_message(FlEngine *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_engine.cc:1031
fl_engine_for_id
FlEngine * fl_engine_for_id(int64_t id)
Definition: fl_engine.cc:685
fl_engine_remove_view
void fl_engine_remove_view(FlEngine *self, FlutterViewId view_id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_engine.cc:946
fl_engine_get_binary_messenger
G_MODULE_EXPORT FlBinaryMessenger * fl_engine_get_binary_messenger(FlEngine *self)
Definition: fl_engine.cc:1413
fl_engine_add_view_finish
gboolean fl_engine_add_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
Definition: fl_engine.cc:931
fl_engine_send_key_event
void fl_engine_send_key_event(FlEngine *self, const FlutterKeyEvent *event, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_engine.cc:1324
fl_engine_send_pointer_pan_zoom_event
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)
Definition: fl_engine.cc:1285
fl_engine_add_view
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:882
fl_engine_start
gboolean fl_engine_start(FlEngine *self, GError **error)
Definition: fl_engine.cc:720
fl_engine_new
G_MODULE_EXPORT FlEngine * fl_engine_new(FlDartProject *project)
Definition: fl_engine.cc:691
fl_engine.h
fl_engine_private.h
on_pre_engine_restart_cb
void on_pre_engine_restart_cb(FlEngine *engine, gpointer user_data)
Definition: fl_engine_test.cc:334
remove_view_engine_error_cb
static void remove_view_engine_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:860
TEST
TEST(FlEngineTest, NotifyDisplayUpdate)
Definition: fl_engine_test.cc:19
remove_view_cb
static void remove_view_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:787
add_view_error_cb
static void add_view_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:717
add_view_engine_error_cb
static void add_view_engine_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:755
remove_view_error_cb
static void remove_view_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:826
add_view_cb
static void add_view_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:672
args
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Definition: fl_event_channel.h:89
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
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
fl_message_codec_decode_message
G_MODULE_EXPORT FlValue * fl_message_codec_decode_message(FlMessageCodec *self, GBytes *message, GError **error)
Definition: fl_message_codec.cc:33
height
const uint8_t uint32_t uint32_t * height
Definition: fl_pixel_buffer_texture_test.cc:39
width
const uint8_t uint32_t * width
Definition: fl_pixel_buffer_texture_test.cc:38
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
type
uint8_t type
Definition: fl_standard_message_codec_test.cc:1117
fl_string_codec.h
fl_value_lookup_string
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition: fl_value.cc:811
fl_value_get_type
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
FL_VALUE_TYPE_STRING
@ FL_VALUE_TYPE_STRING
Definition: fl_value.h:68
FL_VALUE_TYPE_BOOL
@ FL_VALUE_TYPE_BOOL
Definition: fl_value.h:65
FL_VALUE_TYPE_FLOAT
@ FL_VALUE_TYPE_FLOAT
Definition: fl_value.h:67
view_id
G_BEGIN_DECLS FlutterViewId view_id
Definition: fl_view_accessible.h:49