Add Flutter example app with Linux runner
Adds the example/ app that exercises the vflutter_ffi plugin, including the Linux desktop runner and a widget test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7fdf712 parent: ad0ccda added
example/.gitignore +48 -0 | new file mode 100644 | ||
| @@ -0,0 +1,48 @@ | ||
| 1 | +# Miscellaneous | |
| 2 | +*.class | |
| 3 | +*.log | |
| 4 | +*.pyc | |
| 5 | +*.swp | |
| 6 | +.DS_Store | |
| 7 | +.atom/ | |
| 8 | +.build/ | |
| 9 | +.buildlog/ | |
| 10 | +.history | |
| 11 | +.svn/ | |
| 12 | +.swiftpm/ | |
| 13 | +migrate_working_dir/ | |
| 14 | + | |
| 15 | +# IntelliJ related | |
| 16 | +*.iml | |
| 17 | +*.ipr | |
| 18 | +*.iws | |
| 19 | +.idea/ | |
| 20 | + | |
| 21 | +# The .vscode folder contains launch configuration and tasks you configure in | |
| 22 | +# VS Code which you may wish to be included in version control, so this line | |
| 23 | +# is commented out by default. | |
| 24 | +#.vscode/ | |
| 25 | + | |
| 26 | +# Flutter/Dart/Pub related | |
| 27 | +**/doc/api/ | |
| 28 | +**/ios/Flutter/.last_build_id | |
| 29 | +.dart_tool/ | |
| 30 | +.flutter-plugins-dependencies | |
| 31 | +.pub-cache/ | |
| 32 | +.pub/ | |
| 33 | +/build/ | |
| 34 | +/coverage/ | |
| 35 | + | |
| 36 | +# Symbolication related | |
| 37 | +app.*.symbols | |
| 38 | + | |
| 39 | +# Obfuscation related | |
| 40 | +app.*.map.json | |
| 41 | + | |
| 42 | +# Android Studio will place build artifacts here | |
| 43 | +/android/app/debug | |
| 44 | +/android/app/profile | |
| 45 | +/android/app/release | |
| 46 | + | |
| 47 | +# Widget Preview related | |
| 48 | +.widget_preview/ | |
| new file mode 100644 | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | +# Miscellaneous | ||
| 2 | +*.class | ||
| 3 | +*.log | ||
| 4 | +*.pyc | ||
| 5 | +*.swp | ||
| 6 | +.DS_Store | ||
| 7 | +.atom/ | ||
| 8 | +.build/ | ||
| 9 | +.buildlog/ | ||
| 10 | +.history | ||
| 11 | +.svn/ | ||
| 12 | +.swiftpm/ | ||
| 13 | +migrate_working_dir/ | ||
| 14 | + | ||
| 15 | +# IntelliJ related | ||
| 16 | +*.iml | ||
| 17 | +*.ipr | ||
| 18 | +*.iws | ||
| 19 | +.idea/ | ||
| 20 | + | ||
| 21 | +# The .vscode folder contains launch configuration and tasks you configure in | ||
| 22 | +# VS Code which you may wish to be included in version control, so this line | ||
| 23 | +# is commented out by default. | ||
| 24 | +#.vscode/ | ||
| 25 | + | ||
| 26 | +# Flutter/Dart/Pub related | ||
| 27 | +**/doc/api/ | ||
| 28 | +**/ios/Flutter/.last_build_id | ||
| 29 | +.dart_tool/ | ||
| 30 | +.flutter-plugins-dependencies | ||
| 31 | +.pub-cache/ | ||
| 32 | +.pub/ | ||
| 33 | +/build/ | ||
| 34 | +/coverage/ | ||
| 35 | + | ||
| 36 | +# Symbolication related | ||
| 37 | +app.*.symbols | ||
| 38 | + | ||
| 39 | +# Obfuscation related | ||
| 40 | +app.*.map.json | ||
| 41 | + | ||
| 42 | +# Android Studio will place build artifacts here | ||
| 43 | +/android/app/debug | ||
| 44 | +/android/app/profile | ||
| 45 | +/android/app/release | ||
| 46 | + | ||
| 47 | +# Widget Preview related | ||
| 48 | +.widget_preview/ | ||
added
example/.metadata +30 -0 | new file mode 100644 | ||
| @@ -0,0 +1,30 @@ | ||
| 1 | +# This file tracks properties of this Flutter project. | |
| 2 | +# Used by Flutter tool to assess capabilities and perform upgrades etc. | |
| 3 | +# | |
| 4 | +# This file should be version controlled and should not be manually edited. | |
| 5 | + | |
| 6 | +version: | |
| 7 | + revision: "9584c6713b324636289d067944a46fd6b49df14b" | |
| 8 | + channel: "stable" | |
| 9 | + | |
| 10 | +project_type: app | |
| 11 | + | |
| 12 | +# Tracks metadata for the flutter migrate command | |
| 13 | +migration: | |
| 14 | + platforms: | |
| 15 | + - platform: root | |
| 16 | + create_revision: 9584c6713b324636289d067944a46fd6b49df14b | |
| 17 | + base_revision: 9584c6713b324636289d067944a46fd6b49df14b | |
| 18 | + - platform: linux | |
| 19 | + create_revision: 9584c6713b324636289d067944a46fd6b49df14b | |
| 20 | + base_revision: 9584c6713b324636289d067944a46fd6b49df14b | |
| 21 | + | |
| 22 | + # User provided section | |
| 23 | + | |
| 24 | + # List of Local paths (relative to this file) that should be | |
| 25 | + # ignored by the migrate tool. | |
| 26 | + # | |
| 27 | + # Files that are not part of the templates will be ignored by default. | |
| 28 | + unmanaged_files: | |
| 29 | + - 'lib/main.dart' | |
| 30 | + - 'ios/Runner.xcodeproj/project.pbxproj' | |
| new file mode 100644 | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | +# This file tracks properties of this Flutter project. | ||
| 2 | +# Used by Flutter tool to assess capabilities and perform upgrades etc. | ||
| 3 | +# | ||
| 4 | +# This file should be version controlled and should not be manually edited. | ||
| 5 | + | ||
| 6 | +version: | ||
| 7 | + revision: "9584c6713b324636289d067944a46fd6b49df14b" | ||
| 8 | + channel: "stable" | ||
| 9 | + | ||
| 10 | +project_type: app | ||
| 11 | + | ||
| 12 | +# Tracks metadata for the flutter migrate command | ||
| 13 | +migration: | ||
| 14 | + platforms: | ||
| 15 | + - platform: root | ||
| 16 | + create_revision: 9584c6713b324636289d067944a46fd6b49df14b | ||
| 17 | + base_revision: 9584c6713b324636289d067944a46fd6b49df14b | ||
| 18 | + - platform: linux | ||
| 19 | + create_revision: 9584c6713b324636289d067944a46fd6b49df14b | ||
| 20 | + base_revision: 9584c6713b324636289d067944a46fd6b49df14b | ||
| 21 | + | ||
| 22 | + # User provided section | ||
| 23 | + | ||
| 24 | + # List of Local paths (relative to this file) that should be | ||
| 25 | + # ignored by the migrate tool. | ||
| 26 | + # | ||
| 27 | + # Files that are not part of the templates will be ignored by default. | ||
| 28 | + unmanaged_files: | ||
| 29 | + - 'lib/main.dart' | ||
| 30 | + - 'ios/Runner.xcodeproj/project.pbxproj' | ||
added
example/README.md +17 -0 | new file mode 100644 | ||
| @@ -0,0 +1,17 @@ | ||
| 1 | +# vflutter_ffi_example | |
| 2 | + | |
| 3 | +A new Flutter project. | |
| 4 | + | |
| 5 | +## Getting Started | |
| 6 | + | |
| 7 | +This project is a starting point for a Flutter application. | |
| 8 | + | |
| 9 | +A few resources to get you started if this is your first Flutter project: | |
| 10 | + | |
| 11 | +- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) | |
| 12 | +- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) | |
| 13 | +- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) | |
| 14 | + | |
| 15 | +For help getting started with Flutter development, view the | |
| 16 | +[online documentation](https://docs.flutter.dev/), which offers tutorials, | |
| 17 | +samples, guidance on mobile development, and a full API reference. | |
| new file mode 100644 | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | +# vflutter_ffi_example | ||
| 2 | + | ||
| 3 | +A new Flutter project. | ||
| 4 | + | ||
| 5 | +## Getting Started | ||
| 6 | + | ||
| 7 | +This project is a starting point for a Flutter application. | ||
| 8 | + | ||
| 9 | +A few resources to get you started if this is your first Flutter project: | ||
| 10 | + | ||
| 11 | +- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) | ||
| 12 | +- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) | ||
| 13 | +- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) | ||
| 14 | + | ||
| 15 | +For help getting started with Flutter development, view the | ||
| 16 | +[online documentation](https://docs.flutter.dev/), which offers tutorials, | ||
| 17 | +samples, guidance on mobile development, and a full API reference. | ||
added
example/analysis_options.yaml +33 -0 | new file mode 100644 | ||
| @@ -0,0 +1,33 @@ | ||
| 1 | +# This file configures the analyzer, which statically analyzes Dart code to | |
| 2 | +# check for errors, warnings, and lints. | |
| 3 | +# | |
| 4 | +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled | |
| 5 | +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be | |
| 6 | +# invoked from the command line by running `flutter analyze`. | |
| 7 | + | |
| 8 | +# The following line activates a set of recommended lints for Flutter apps, | |
| 9 | +# packages, and plugins designed to encourage good coding practices. | |
| 10 | +include: package:flutter_lints/flutter.yaml | |
| 11 | + | |
| 12 | +analyzer: | |
| 13 | + exclude: | |
| 14 | + - build/** | |
| 15 | + - linux/** | |
| 16 | + | |
| 17 | +linter: | |
| 18 | + # The lint rules applied to this project can be customized in the | |
| 19 | + # section below to disable rules from the `package:flutter_lints/flutter.yaml` | |
| 20 | + # included above or to enable additional rules. A list of all available lints | |
| 21 | + # and their documentation is published at https://dart.dev/lints. | |
| 22 | + # | |
| 23 | + # Instead of disabling a lint rule for the entire project in the | |
| 24 | + # section below, it can also be suppressed for a single line of code | |
| 25 | + # or a specific dart file by using the `// ignore: name_of_lint` and | |
| 26 | + # `// ignore_for_file: name_of_lint` syntax on the line or in the file | |
| 27 | + # producing the lint. | |
| 28 | + rules: | |
| 29 | + # avoid_print: false # Uncomment to disable the `avoid_print` rule | |
| 30 | + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule | |
| 31 | + | |
| 32 | +# Additional information about this file can be found at | |
| 33 | +# https://dart.dev/guides/language/analysis-options | |
| new file mode 100644 | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | +# This file configures the analyzer, which statically analyzes Dart code to | ||
| 2 | +# check for errors, warnings, and lints. | ||
| 3 | +# | ||
| 4 | +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled | ||
| 5 | +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be | ||
| 6 | +# invoked from the command line by running `flutter analyze`. | ||
| 7 | + | ||
| 8 | +# The following line activates a set of recommended lints for Flutter apps, | ||
| 9 | +# packages, and plugins designed to encourage good coding practices. | ||
| 10 | +include: package:flutter_lints/flutter.yaml | ||
| 11 | + | ||
| 12 | +analyzer: | ||
| 13 | + exclude: | ||
| 14 | + - build/** | ||
| 15 | + - linux/** | ||
| 16 | + | ||
| 17 | +linter: | ||
| 18 | + # The lint rules applied to this project can be customized in the | ||
| 19 | + # section below to disable rules from the `package:flutter_lints/flutter.yaml` | ||
| 20 | + # included above or to enable additional rules. A list of all available lints | ||
| 21 | + # and their documentation is published at https://dart.dev/lints. | ||
| 22 | + # | ||
| 23 | + # Instead of disabling a lint rule for the entire project in the | ||
| 24 | + # section below, it can also be suppressed for a single line of code | ||
| 25 | + # or a specific dart file by using the `// ignore: name_of_lint` and | ||
| 26 | + # `// ignore_for_file: name_of_lint` syntax on the line or in the file | ||
| 27 | + # producing the lint. | ||
| 28 | + rules: | ||
| 29 | + # avoid_print: false # Uncomment to disable the `avoid_print` rule | ||
| 30 | + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule | ||
| 31 | + | ||
| 32 | +# Additional information about this file can be found at | ||
| 33 | +# https://dart.dev/guides/language/analysis-options | ||
added
example/lib/main.dart +121 -0 | new file mode 100644 | ||
| @@ -0,0 +1,121 @@ | ||
| 1 | +import 'package:flutter/material.dart'; | |
| 2 | +import 'package:vflutter_ffi/vflutter_ffi.dart' as v; | |
| 3 | + | |
| 4 | +void main() => runApp(const ExampleApp()); | |
| 5 | + | |
| 6 | +class ExampleApp extends StatelessWidget { | |
| 7 | + const ExampleApp({super.key}); | |
| 8 | + | |
| 9 | + @override | |
| 10 | + Widget build(BuildContext context) => MaterialApp( | |
| 11 | + title: 'vflutter_ffi', | |
| 12 | + theme: ThemeData(colorSchemeSeed: Colors.indigo, useMaterial3: true), | |
| 13 | + home: const HomePage(), | |
| 14 | + ); | |
| 15 | +} | |
| 16 | + | |
| 17 | +class HomePage extends StatefulWidget { | |
| 18 | + const HomePage({super.key}); | |
| 19 | + | |
| 20 | + @override | |
| 21 | + State<HomePage> createState() => _HomePageState(); | |
| 22 | +} | |
| 23 | + | |
| 24 | +class _HomePageState extends State<HomePage> { | |
| 25 | + final _controller = TextEditingController(text: 'Flutter'); | |
| 26 | + | |
| 27 | + // Synchronous results are cheap enough to compute in build(); the async one | |
| 28 | + // is not, so it is held here and refreshed on demand. | |
| 29 | + String _async = '(not run)'; | |
| 30 | + String _stress = '(not run)'; | |
| 31 | + | |
| 32 | + @override | |
| 33 | + void dispose() { | |
| 34 | + _controller.dispose(); | |
| 35 | + super.dispose(); | |
| 36 | + } | |
| 37 | + | |
| 38 | + Future<void> _runAsync() async { | |
| 39 | + final r = await v.greetAsync(_controller.text); | |
| 40 | + setState(() => _async = r); | |
| 41 | + } | |
| 42 | + | |
| 43 | + /// 20k round trips on the UI isolate. Fast enough not to jank, and proves | |
| 44 | + /// the V side frees its temporaries under load. | |
| 45 | + void _runStress() { | |
| 46 | + final sw = Stopwatch()..start(); | |
| 47 | + for (var i = 0; i < 20000; i++) { | |
| 48 | + v.greet('stress$i'); | |
| 49 | + } | |
| 50 | + sw.stop(); | |
| 51 | + setState(() => _stress = '20k calls in ${sw.elapsedMilliseconds} ms'); | |
| 52 | + } | |
| 53 | + | |
| 54 | + @override | |
| 55 | + Widget build(BuildContext context) { | |
| 56 | + return Scaffold( | |
| 57 | + appBar: AppBar(title: const Text('V → Flutter over dart:ffi')), | |
| 58 | + body: Center( | |
| 59 | + child: ConstrainedBox( | |
| 60 | + constraints: const BoxConstraints(maxWidth: 520), | |
| 61 | + child: ListView( | |
| 62 | + padding: const EdgeInsets.all(24), | |
| 63 | + shrinkWrap: true, | |
| 64 | + children: [ | |
| 65 | + _Row(label: 'v.add(20, 22)', value: '${v.add(20, 42 - 20)}'), | |
| 66 | + const Divider(height: 32), | |
| 67 | + TextField( | |
| 68 | + controller: _controller, | |
| 69 | + decoration: const InputDecoration( | |
| 70 | + labelText: 'name', | |
| 71 | + border: OutlineInputBorder(), | |
| 72 | + ), | |
| 73 | + onChanged: (_) => setState(() {}), | |
| 74 | + ), | |
| 75 | + const SizedBox(height: 16), | |
| 76 | + _Row(label: 'v.greet(name)', value: v.greet(_controller.text)), | |
| 77 | + const Divider(height: 32), | |
| 78 | + _Row(label: 'v.greetAsync(name)', value: _async), | |
| 79 | + const SizedBox(height: 8), | |
| 80 | + FilledButton.tonal( | |
| 81 | + onPressed: _runAsync, | |
| 82 | + child: const Text('run on background isolate'), | |
| 83 | + ), | |
| 84 | + const Divider(height: 32), | |
| 85 | + _Row(label: 'ownership stress', value: _stress), | |
| 86 | + const SizedBox(height: 8), | |
| 87 | + FilledButton.tonal( | |
| 88 | + onPressed: _runStress, | |
| 89 | + child: const Text('run 20k round trips'), | |
| 90 | + ), | |
| 91 | + ], | |
| 92 | + ), | |
| 93 | + ), | |
| 94 | + ), | |
| 95 | + ); | |
| 96 | + } | |
| 97 | +} | |
| 98 | + | |
| 99 | +class _Row extends StatelessWidget { | |
| 100 | + const _Row({required this.label, required this.value}); | |
| 101 | + | |
| 102 | + final String label; | |
| 103 | + final String value; | |
| 104 | + | |
| 105 | + @override | |
| 106 | + Widget build(BuildContext context) { | |
| 107 | + final theme = Theme.of(context); | |
| 108 | + return Column( | |
| 109 | + crossAxisAlignment: CrossAxisAlignment.start, | |
| 110 | + children: [ | |
| 111 | + Text(label, style: theme.textTheme.labelMedium), | |
| 112 | + const SizedBox(height: 4), | |
| 113 | + SelectableText( | |
| 114 | + value, | |
| 115 | + style: theme.textTheme.titleMedium | |
| 116 | + ?.copyWith(fontFamily: 'monospace', color: theme.colorScheme.primary), | |
| 117 | + ), | |
| 118 | + ], | |
| 119 | + ); | |
| 120 | + } | |
| 121 | +} | |
| new file mode 100644 | |||
| @@ -0,0 +1,121 @@ | |||
| 1 | +import 'package:flutter/material.dart'; | ||
| 2 | +import 'package:vflutter_ffi/vflutter_ffi.dart' as v; | ||
| 3 | + | ||
| 4 | +void main() => runApp(const ExampleApp()); | ||
| 5 | + | ||
| 6 | +class ExampleApp extends StatelessWidget { | ||
| 7 | + const ExampleApp({super.key}); | ||
| 8 | + | ||
| 9 | + @override | ||
| 10 | + Widget build(BuildContext context) => MaterialApp( | ||
| 11 | + title: 'vflutter_ffi', | ||
| 12 | + theme: ThemeData(colorSchemeSeed: Colors.indigo, useMaterial3: true), | ||
| 13 | + home: const HomePage(), | ||
| 14 | + ); | ||
| 15 | +} | ||
| 16 | + | ||
| 17 | +class HomePage extends StatefulWidget { | ||
| 18 | + const HomePage({super.key}); | ||
| 19 | + | ||
| 20 | + @override | ||
| 21 | + State<HomePage> createState() => _HomePageState(); | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +class _HomePageState extends State<HomePage> { | ||
| 25 | + final _controller = TextEditingController(text: 'Flutter'); | ||
| 26 | + | ||
| 27 | + // Synchronous results are cheap enough to compute in build(); the async one | ||
| 28 | + // is not, so it is held here and refreshed on demand. | ||
| 29 | + String _async = '(not run)'; | ||
| 30 | + String _stress = '(not run)'; | ||
| 31 | + | ||
| 32 | + @override | ||
| 33 | + void dispose() { | ||
| 34 | + _controller.dispose(); | ||
| 35 | + super.dispose(); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + Future<void> _runAsync() async { | ||
| 39 | + final r = await v.greetAsync(_controller.text); | ||
| 40 | + setState(() => _async = r); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + /// 20k round trips on the UI isolate. Fast enough not to jank, and proves | ||
| 44 | + /// the V side frees its temporaries under load. | ||
| 45 | + void _runStress() { | ||
| 46 | + final sw = Stopwatch()..start(); | ||
| 47 | + for (var i = 0; i < 20000; i++) { | ||
| 48 | + v.greet('stress$i'); | ||
| 49 | + } | ||
| 50 | + sw.stop(); | ||
| 51 | + setState(() => _stress = '20k calls in ${sw.elapsedMilliseconds} ms'); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + @override | ||
| 55 | + Widget build(BuildContext context) { | ||
| 56 | + return Scaffold( | ||
| 57 | + appBar: AppBar(title: const Text('V → Flutter over dart:ffi')), | ||
| 58 | + body: Center( | ||
| 59 | + child: ConstrainedBox( | ||
| 60 | + constraints: const BoxConstraints(maxWidth: 520), | ||
| 61 | + child: ListView( | ||
| 62 | + padding: const EdgeInsets.all(24), | ||
| 63 | + shrinkWrap: true, | ||
| 64 | + children: [ | ||
| 65 | + _Row(label: 'v.add(20, 22)', value: '${v.add(20, 42 - 20)}'), | ||
| 66 | + const Divider(height: 32), | ||
| 67 | + TextField( | ||
| 68 | + controller: _controller, | ||
| 69 | + decoration: const InputDecoration( | ||
| 70 | + labelText: 'name', | ||
| 71 | + border: OutlineInputBorder(), | ||
| 72 | + ), | ||
| 73 | + onChanged: (_) => setState(() {}), | ||
| 74 | + ), | ||
| 75 | + const SizedBox(height: 16), | ||
| 76 | + _Row(label: 'v.greet(name)', value: v.greet(_controller.text)), | ||
| 77 | + const Divider(height: 32), | ||
| 78 | + _Row(label: 'v.greetAsync(name)', value: _async), | ||
| 79 | + const SizedBox(height: 8), | ||
| 80 | + FilledButton.tonal( | ||
| 81 | + onPressed: _runAsync, | ||
| 82 | + child: const Text('run on background isolate'), | ||
| 83 | + ), | ||
| 84 | + const Divider(height: 32), | ||
| 85 | + _Row(label: 'ownership stress', value: _stress), | ||
| 86 | + const SizedBox(height: 8), | ||
| 87 | + FilledButton.tonal( | ||
| 88 | + onPressed: _runStress, | ||
| 89 | + child: const Text('run 20k round trips'), | ||
| 90 | + ), | ||
| 91 | + ], | ||
| 92 | + ), | ||
| 93 | + ), | ||
| 94 | + ), | ||
| 95 | + ); | ||
| 96 | + } | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +class _Row extends StatelessWidget { | ||
| 100 | + const _Row({required this.label, required this.value}); | ||
| 101 | + | ||
| 102 | + final String label; | ||
| 103 | + final String value; | ||
| 104 | + | ||
| 105 | + @override | ||
| 106 | + Widget build(BuildContext context) { | ||
| 107 | + final theme = Theme.of(context); | ||
| 108 | + return Column( | ||
| 109 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
| 110 | + children: [ | ||
| 111 | + Text(label, style: theme.textTheme.labelMedium), | ||
| 112 | + const SizedBox(height: 4), | ||
| 113 | + SelectableText( | ||
| 114 | + value, | ||
| 115 | + style: theme.textTheme.titleMedium | ||
| 116 | + ?.copyWith(fontFamily: 'monospace', color: theme.colorScheme.primary), | ||
| 117 | + ), | ||
| 118 | + ], | ||
| 119 | + ); | ||
| 120 | + } | ||
| 121 | +} | ||
added
example/linux/.gitignore +1 -0 | new file mode 100644 | ||
| @@ -0,0 +1 @@ | ||
| 1 | +flutter/ephemeral | |
| new file mode 100644 | |||
| @@ -0,0 +1 @@ | |||
| 1 | +flutter/ephemeral | ||
added
example/linux/CMakeLists.txt +128 -0 | new file mode 100644 | ||
| @@ -0,0 +1,128 @@ | ||
| 1 | +# Project-level configuration. | |
| 2 | +cmake_minimum_required(VERSION 3.13) | |
| 3 | +project(runner LANGUAGES CXX) | |
| 4 | + | |
| 5 | +# The name of the executable created for the application. Change this to change | |
| 6 | +# the on-disk name of your application. | |
| 7 | +set(BINARY_NAME "vflutter_ffi_example") | |
| 8 | +# The unique GTK application identifier for this application. See: | |
| 9 | +# https://wiki.gnome.org/HowDoI/ChooseApplicationID | |
| 10 | +set(APPLICATION_ID "com.example.vflutter_ffi_example") | |
| 11 | + | |
| 12 | +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent | |
| 13 | +# versions of CMake. | |
| 14 | +cmake_policy(SET CMP0063 NEW) | |
| 15 | + | |
| 16 | +# Load bundled libraries from the lib/ directory relative to the binary. | |
| 17 | +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") | |
| 18 | + | |
| 19 | +# Root filesystem for cross-building. | |
| 20 | +if(FLUTTER_TARGET_PLATFORM_SYSROOT) | |
| 21 | + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) | |
| 22 | + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) | |
| 23 | + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | |
| 24 | + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) | |
| 25 | + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | |
| 26 | + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | |
| 27 | +endif() | |
| 28 | + | |
| 29 | +# Define build configuration options. | |
| 30 | +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) | |
| 31 | + set(CMAKE_BUILD_TYPE "Debug" CACHE | |
| 32 | + STRING "Flutter build mode" FORCE) | |
| 33 | + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS | |
| 34 | + "Debug" "Profile" "Release") | |
| 35 | +endif() | |
| 36 | + | |
| 37 | +# Compilation settings that should be applied to most targets. | |
| 38 | +# | |
| 39 | +# Be cautious about adding new options here, as plugins use this function by | |
| 40 | +# default. In most cases, you should add new options to specific targets instead | |
| 41 | +# of modifying this function. | |
| 42 | +function(APPLY_STANDARD_SETTINGS TARGET) | |
| 43 | + target_compile_features(${TARGET} PUBLIC cxx_std_14) | |
| 44 | + target_compile_options(${TARGET} PRIVATE -Wall -Werror) | |
| 45 | + target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>") | |
| 46 | + target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>") | |
| 47 | +endfunction() | |
| 48 | + | |
| 49 | +# Flutter library and tool build rules. | |
| 50 | +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") | |
| 51 | +add_subdirectory(${FLUTTER_MANAGED_DIR}) | |
| 52 | + | |
| 53 | +# System-level dependencies. | |
| 54 | +find_package(PkgConfig REQUIRED) | |
| 55 | +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) | |
| 56 | + | |
| 57 | +# Application build; see runner/CMakeLists.txt. | |
| 58 | +add_subdirectory("runner") | |
| 59 | + | |
| 60 | +# Run the Flutter tool portions of the build. This must not be removed. | |
| 61 | +add_dependencies(${BINARY_NAME} flutter_assemble) | |
| 62 | + | |
| 63 | +# Only the install-generated bundle's copy of the executable will launch | |
| 64 | +# correctly, since the resources must in the right relative locations. To avoid | |
| 65 | +# people trying to run the unbundled copy, put it in a subdirectory instead of | |
| 66 | +# the default top-level location. | |
| 67 | +set_target_properties(${BINARY_NAME} | |
| 68 | + PROPERTIES | |
| 69 | + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" | |
| 70 | +) | |
| 71 | + | |
| 72 | + | |
| 73 | +# Generated plugin build rules, which manage building the plugins and adding | |
| 74 | +# them to the application. | |
| 75 | +include(flutter/generated_plugins.cmake) | |
| 76 | + | |
| 77 | + | |
| 78 | +# === Installation === | |
| 79 | +# By default, "installing" just makes a relocatable bundle in the build | |
| 80 | +# directory. | |
| 81 | +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") | |
| 82 | +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) | |
| 83 | + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) | |
| 84 | +endif() | |
| 85 | + | |
| 86 | +# Start with a clean build bundle directory every time. | |
| 87 | +install(CODE " | |
| 88 | + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") | |
| 89 | + " COMPONENT Runtime) | |
| 90 | + | |
| 91 | +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") | |
| 92 | +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") | |
| 93 | + | |
| 94 | +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" | |
| 95 | + COMPONENT Runtime) | |
| 96 | + | |
| 97 | +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | |
| 98 | + COMPONENT Runtime) | |
| 99 | + | |
| 100 | +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | |
| 101 | + COMPONENT Runtime) | |
| 102 | + | |
| 103 | +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) | |
| 104 | + install(FILES "${bundled_library}" | |
| 105 | + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | |
| 106 | + COMPONENT Runtime) | |
| 107 | +endforeach(bundled_library) | |
| 108 | + | |
| 109 | +# Copy the native assets provided by the build.dart from all packages. | |
| 110 | +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") | |
| 111 | +install(DIRECTORY "${NATIVE_ASSETS_DIR}" | |
| 112 | + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | |
| 113 | + COMPONENT Runtime) | |
| 114 | + | |
| 115 | +# Fully re-copy the assets directory on each build to avoid having stale files | |
| 116 | +# from a previous install. | |
| 117 | +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") | |
| 118 | +install(CODE " | |
| 119 | + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") | |
| 120 | + " COMPONENT Runtime) | |
| 121 | +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" | |
| 122 | + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) | |
| 123 | + | |
| 124 | +# Install the AOT library on non-Debug builds only. | |
| 125 | +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") | |
| 126 | + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | |
| 127 | + COMPONENT Runtime) | |
| 128 | +endif() | |
| new file mode 100644 | |||
| @@ -0,0 +1,128 @@ | |||
| 1 | +# Project-level configuration. | ||
| 2 | +cmake_minimum_required(VERSION 3.13) | ||
| 3 | +project(runner LANGUAGES CXX) | ||
| 4 | + | ||
| 5 | +# The name of the executable created for the application. Change this to change | ||
| 6 | +# the on-disk name of your application. | ||
| 7 | +set(BINARY_NAME "vflutter_ffi_example") | ||
| 8 | +# The unique GTK application identifier for this application. See: | ||
| 9 | +# https://wiki.gnome.org/HowDoI/ChooseApplicationID | ||
| 10 | +set(APPLICATION_ID "com.example.vflutter_ffi_example") | ||
| 11 | + | ||
| 12 | +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent | ||
| 13 | +# versions of CMake. | ||
| 14 | +cmake_policy(SET CMP0063 NEW) | ||
| 15 | + | ||
| 16 | +# Load bundled libraries from the lib/ directory relative to the binary. | ||
| 17 | +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") | ||
| 18 | + | ||
| 19 | +# Root filesystem for cross-building. | ||
| 20 | +if(FLUTTER_TARGET_PLATFORM_SYSROOT) | ||
| 21 | + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) | ||
| 22 | + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) | ||
| 23 | + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) | ||
| 24 | + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) | ||
| 25 | + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) | ||
| 26 | + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) | ||
| 27 | +endif() | ||
| 28 | + | ||
| 29 | +# Define build configuration options. | ||
| 30 | +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) | ||
| 31 | + set(CMAKE_BUILD_TYPE "Debug" CACHE | ||
| 32 | + STRING "Flutter build mode" FORCE) | ||
| 33 | + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS | ||
| 34 | + "Debug" "Profile" "Release") | ||
| 35 | +endif() | ||
| 36 | + | ||
| 37 | +# Compilation settings that should be applied to most targets. | ||
| 38 | +# | ||
| 39 | +# Be cautious about adding new options here, as plugins use this function by | ||
| 40 | +# default. In most cases, you should add new options to specific targets instead | ||
| 41 | +# of modifying this function. | ||
| 42 | +function(APPLY_STANDARD_SETTINGS TARGET) | ||
| 43 | + target_compile_features(${TARGET} PUBLIC cxx_std_14) | ||
| 44 | + target_compile_options(${TARGET} PRIVATE -Wall -Werror) | ||
| 45 | + target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>") | ||
| 46 | + target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>") | ||
| 47 | +endfunction() | ||
| 48 | + | ||
| 49 | +# Flutter library and tool build rules. | ||
| 50 | +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") | ||
| 51 | +add_subdirectory(${FLUTTER_MANAGED_DIR}) | ||
| 52 | + | ||
| 53 | +# System-level dependencies. | ||
| 54 | +find_package(PkgConfig REQUIRED) | ||
| 55 | +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) | ||
| 56 | + | ||
| 57 | +# Application build; see runner/CMakeLists.txt. | ||
| 58 | +add_subdirectory("runner") | ||
| 59 | + | ||
| 60 | +# Run the Flutter tool portions of the build. This must not be removed. | ||
| 61 | +add_dependencies(${BINARY_NAME} flutter_assemble) | ||
| 62 | + | ||
| 63 | +# Only the install-generated bundle's copy of the executable will launch | ||
| 64 | +# correctly, since the resources must in the right relative locations. To avoid | ||
| 65 | +# people trying to run the unbundled copy, put it in a subdirectory instead of | ||
| 66 | +# the default top-level location. | ||
| 67 | +set_target_properties(${BINARY_NAME} | ||
| 68 | + PROPERTIES | ||
| 69 | + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" | ||
| 70 | +) | ||
| 71 | + | ||
| 72 | + | ||
| 73 | +# Generated plugin build rules, which manage building the plugins and adding | ||
| 74 | +# them to the application. | ||
| 75 | +include(flutter/generated_plugins.cmake) | ||
| 76 | + | ||
| 77 | + | ||
| 78 | +# === Installation === | ||
| 79 | +# By default, "installing" just makes a relocatable bundle in the build | ||
| 80 | +# directory. | ||
| 81 | +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") | ||
| 82 | +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) | ||
| 83 | + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) | ||
| 84 | +endif() | ||
| 85 | + | ||
| 86 | +# Start with a clean build bundle directory every time. | ||
| 87 | +install(CODE " | ||
| 88 | + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") | ||
| 89 | + " COMPONENT Runtime) | ||
| 90 | + | ||
| 91 | +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") | ||
| 92 | +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") | ||
| 93 | + | ||
| 94 | +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" | ||
| 95 | + COMPONENT Runtime) | ||
| 96 | + | ||
| 97 | +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | ||
| 98 | + COMPONENT Runtime) | ||
| 99 | + | ||
| 100 | +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 101 | + COMPONENT Runtime) | ||
| 102 | + | ||
| 103 | +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) | ||
| 104 | + install(FILES "${bundled_library}" | ||
| 105 | + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 106 | + COMPONENT Runtime) | ||
| 107 | +endforeach(bundled_library) | ||
| 108 | + | ||
| 109 | +# Copy the native assets provided by the build.dart from all packages. | ||
| 110 | +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") | ||
| 111 | +install(DIRECTORY "${NATIVE_ASSETS_DIR}" | ||
| 112 | + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 113 | + COMPONENT Runtime) | ||
| 114 | + | ||
| 115 | +# Fully re-copy the assets directory on each build to avoid having stale files | ||
| 116 | +# from a previous install. | ||
| 117 | +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") | ||
| 118 | +install(CODE " | ||
| 119 | + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") | ||
| 120 | + " COMPONENT Runtime) | ||
| 121 | +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" | ||
| 122 | + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) | ||
| 123 | + | ||
| 124 | +# Install the AOT library on non-Debug builds only. | ||
| 125 | +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") | ||
| 126 | + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 127 | + COMPONENT Runtime) | ||
| 128 | +endif() | ||
added
example/linux/flutter/CMakeLists.txt +88 -0 | new file mode 100644 | ||
| @@ -0,0 +1,88 @@ | ||
| 1 | +# This file controls Flutter-level build steps. It should not be edited. | |
| 2 | +cmake_minimum_required(VERSION 3.10) | |
| 3 | + | |
| 4 | +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") | |
| 5 | + | |
| 6 | +# Configuration provided via flutter tool. | |
| 7 | +include(${EPHEMERAL_DIR}/generated_config.cmake) | |
| 8 | + | |
| 9 | +# TODO: Move the rest of this into files in ephemeral. See | |
| 10 | +# https://github.com/flutter/flutter/issues/57146. | |
| 11 | + | |
| 12 | +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), | |
| 13 | +# which isn't available in 3.10. | |
| 14 | +function(list_prepend LIST_NAME PREFIX) | |
| 15 | + set(NEW_LIST "") | |
| 16 | + foreach(element ${${LIST_NAME}}) | |
| 17 | + list(APPEND NEW_LIST "${PREFIX}${element}") | |
| 18 | + endforeach(element) | |
| 19 | + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) | |
| 20 | +endfunction() | |
| 21 | + | |
| 22 | +# === Flutter Library === | |
| 23 | +# System-level dependencies. | |
| 24 | +find_package(PkgConfig REQUIRED) | |
| 25 | +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) | |
| 26 | +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) | |
| 27 | +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) | |
| 28 | + | |
| 29 | +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") | |
| 30 | + | |
| 31 | +# Published to parent scope for install step. | |
| 32 | +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) | |
| 33 | +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) | |
| 34 | +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) | |
| 35 | +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) | |
| 36 | + | |
| 37 | +list(APPEND FLUTTER_LIBRARY_HEADERS | |
| 38 | + "fl_basic_message_channel.h" | |
| 39 | + "fl_binary_codec.h" | |
| 40 | + "fl_binary_messenger.h" | |
| 41 | + "fl_dart_project.h" | |
| 42 | + "fl_engine.h" | |
| 43 | + "fl_json_message_codec.h" | |
| 44 | + "fl_json_method_codec.h" | |
| 45 | + "fl_message_codec.h" | |
| 46 | + "fl_method_call.h" | |
| 47 | + "fl_method_channel.h" | |
| 48 | + "fl_method_codec.h" | |
| 49 | + "fl_method_response.h" | |
| 50 | + "fl_plugin_registrar.h" | |
| 51 | + "fl_plugin_registry.h" | |
| 52 | + "fl_standard_message_codec.h" | |
| 53 | + "fl_standard_method_codec.h" | |
| 54 | + "fl_string_codec.h" | |
| 55 | + "fl_value.h" | |
| 56 | + "fl_view.h" | |
| 57 | + "flutter_linux.h" | |
| 58 | +) | |
| 59 | +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") | |
| 60 | +add_library(flutter INTERFACE) | |
| 61 | +target_include_directories(flutter INTERFACE | |
| 62 | + "${EPHEMERAL_DIR}" | |
| 63 | +) | |
| 64 | +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") | |
| 65 | +target_link_libraries(flutter INTERFACE | |
| 66 | + PkgConfig::GTK | |
| 67 | + PkgConfig::GLIB | |
| 68 | + PkgConfig::GIO | |
| 69 | +) | |
| 70 | +add_dependencies(flutter flutter_assemble) | |
| 71 | + | |
| 72 | +# === Flutter tool backend === | |
| 73 | +# _phony_ is a non-existent file to force this command to run every time, | |
| 74 | +# since currently there's no way to get a full input/output list from the | |
| 75 | +# flutter tool. | |
| 76 | +add_custom_command( | |
| 77 | + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} | |
| 78 | + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ | |
| 79 | + COMMAND ${CMAKE_COMMAND} -E env | |
| 80 | + ${FLUTTER_TOOL_ENVIRONMENT} | |
| 81 | + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" | |
| 82 | + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} | |
| 83 | + VERBATIM | |
| 84 | +) | |
| 85 | +add_custom_target(flutter_assemble DEPENDS | |
| 86 | + "${FLUTTER_LIBRARY}" | |
| 87 | + ${FLUTTER_LIBRARY_HEADERS} | |
| 88 | +) | |
| new file mode 100644 | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | +# This file controls Flutter-level build steps. It should not be edited. | ||
| 2 | +cmake_minimum_required(VERSION 3.10) | ||
| 3 | + | ||
| 4 | +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") | ||
| 5 | + | ||
| 6 | +# Configuration provided via flutter tool. | ||
| 7 | +include(${EPHEMERAL_DIR}/generated_config.cmake) | ||
| 8 | + | ||
| 9 | +# TODO: Move the rest of this into files in ephemeral. See | ||
| 10 | +# https://github.com/flutter/flutter/issues/57146. | ||
| 11 | + | ||
| 12 | +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), | ||
| 13 | +# which isn't available in 3.10. | ||
| 14 | +function(list_prepend LIST_NAME PREFIX) | ||
| 15 | + set(NEW_LIST "") | ||
| 16 | + foreach(element ${${LIST_NAME}}) | ||
| 17 | + list(APPEND NEW_LIST "${PREFIX}${element}") | ||
| 18 | + endforeach(element) | ||
| 19 | + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) | ||
| 20 | +endfunction() | ||
| 21 | + | ||
| 22 | +# === Flutter Library === | ||
| 23 | +# System-level dependencies. | ||
| 24 | +find_package(PkgConfig REQUIRED) | ||
| 25 | +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) | ||
| 26 | +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) | ||
| 27 | +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) | ||
| 28 | + | ||
| 29 | +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") | ||
| 30 | + | ||
| 31 | +# Published to parent scope for install step. | ||
| 32 | +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) | ||
| 33 | +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) | ||
| 34 | +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) | ||
| 35 | +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) | ||
| 36 | + | ||
| 37 | +list(APPEND FLUTTER_LIBRARY_HEADERS | ||
| 38 | + "fl_basic_message_channel.h" | ||
| 39 | + "fl_binary_codec.h" | ||
| 40 | + "fl_binary_messenger.h" | ||
| 41 | + "fl_dart_project.h" | ||
| 42 | + "fl_engine.h" | ||
| 43 | + "fl_json_message_codec.h" | ||
| 44 | + "fl_json_method_codec.h" | ||
| 45 | + "fl_message_codec.h" | ||
| 46 | + "fl_method_call.h" | ||
| 47 | + "fl_method_channel.h" | ||
| 48 | + "fl_method_codec.h" | ||
| 49 | + "fl_method_response.h" | ||
| 50 | + "fl_plugin_registrar.h" | ||
| 51 | + "fl_plugin_registry.h" | ||
| 52 | + "fl_standard_message_codec.h" | ||
| 53 | + "fl_standard_method_codec.h" | ||
| 54 | + "fl_string_codec.h" | ||
| 55 | + "fl_value.h" | ||
| 56 | + "fl_view.h" | ||
| 57 | + "flutter_linux.h" | ||
| 58 | +) | ||
| 59 | +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") | ||
| 60 | +add_library(flutter INTERFACE) | ||
| 61 | +target_include_directories(flutter INTERFACE | ||
| 62 | + "${EPHEMERAL_DIR}" | ||
| 63 | +) | ||
| 64 | +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") | ||
| 65 | +target_link_libraries(flutter INTERFACE | ||
| 66 | + PkgConfig::GTK | ||
| 67 | + PkgConfig::GLIB | ||
| 68 | + PkgConfig::GIO | ||
| 69 | +) | ||
| 70 | +add_dependencies(flutter flutter_assemble) | ||
| 71 | + | ||
| 72 | +# === Flutter tool backend === | ||
| 73 | +# _phony_ is a non-existent file to force this command to run every time, | ||
| 74 | +# since currently there's no way to get a full input/output list from the | ||
| 75 | +# flutter tool. | ||
| 76 | +add_custom_command( | ||
| 77 | + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} | ||
| 78 | + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ | ||
| 79 | + COMMAND ${CMAKE_COMMAND} -E env | ||
| 80 | + ${FLUTTER_TOOL_ENVIRONMENT} | ||
| 81 | + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" | ||
| 82 | + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} | ||
| 83 | + VERBATIM | ||
| 84 | +) | ||
| 85 | +add_custom_target(flutter_assemble DEPENDS | ||
| 86 | + "${FLUTTER_LIBRARY}" | ||
| 87 | + ${FLUTTER_LIBRARY_HEADERS} | ||
| 88 | +) | ||
added
example/linux/flutter/generated_plugin_registrant.cc +11 -0 | new file mode 100644 | ||
| @@ -0,0 +1,11 @@ | ||
| 1 | +// | |
| 2 | +// Generated file. Do not edit. | |
| 3 | +// | |
| 4 | + | |
| 5 | +// clang-format off | |
| 6 | + | |
| 7 | +#include "generated_plugin_registrant.h" | |
| 8 | + | |
| 9 | + | |
| 10 | +void fl_register_plugins(FlPluginRegistry* registry) { | |
| 11 | +} | |
| new file mode 100644 | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | +// | ||
| 2 | +// Generated file. Do not edit. | ||
| 3 | +// | ||
| 4 | + | ||
| 5 | +// clang-format off | ||
| 6 | + | ||
| 7 | +#include "generated_plugin_registrant.h" | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +void fl_register_plugins(FlPluginRegistry* registry) { | ||
| 11 | +} | ||
added
example/linux/flutter/generated_plugin_registrant.h +15 -0 | new file mode 100644 | ||
| @@ -0,0 +1,15 @@ | ||
| 1 | +// | |
| 2 | +// Generated file. Do not edit. | |
| 3 | +// | |
| 4 | + | |
| 5 | +// clang-format off | |
| 6 | + | |
| 7 | +#ifndef GENERATED_PLUGIN_REGISTRANT_ | |
| 8 | +#define GENERATED_PLUGIN_REGISTRANT_ | |
| 9 | + | |
| 10 | +#include <flutter_linux/flutter_linux.h> | |
| 11 | + | |
| 12 | +// Registers Flutter plugins. | |
| 13 | +void fl_register_plugins(FlPluginRegistry* registry); | |
| 14 | + | |
| 15 | +#endif // GENERATED_PLUGIN_REGISTRANT_ | |
| new file mode 100644 | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | +// | ||
| 2 | +// Generated file. Do not edit. | ||
| 3 | +// | ||
| 4 | + | ||
| 5 | +// clang-format off | ||
| 6 | + | ||
| 7 | +#ifndef GENERATED_PLUGIN_REGISTRANT_ | ||
| 8 | +#define GENERATED_PLUGIN_REGISTRANT_ | ||
| 9 | + | ||
| 10 | +#include <flutter_linux/flutter_linux.h> | ||
| 11 | + | ||
| 12 | +// Registers Flutter plugins. | ||
| 13 | +void fl_register_plugins(FlPluginRegistry* registry); | ||
| 14 | + | ||
| 15 | +#endif // GENERATED_PLUGIN_REGISTRANT_ | ||
added
example/linux/flutter/generated_plugins.cmake +24 -0 | new file mode 100644 | ||
| @@ -0,0 +1,24 @@ | ||
| 1 | +# | |
| 2 | +# Generated file, do not edit. | |
| 3 | +# | |
| 4 | + | |
| 5 | +list(APPEND FLUTTER_PLUGIN_LIST | |
| 6 | +) | |
| 7 | + | |
| 8 | +list(APPEND FLUTTER_FFI_PLUGIN_LIST | |
| 9 | + vflutter_ffi | |
| 10 | +) | |
| 11 | + | |
| 12 | +set(PLUGIN_BUNDLED_LIBRARIES) | |
| 13 | + | |
| 14 | +foreach(plugin ${FLUTTER_PLUGIN_LIST}) | |
| 15 | + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) | |
| 16 | + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) | |
| 17 | + list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>) | |
| 18 | + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) | |
| 19 | +endforeach(plugin) | |
| 20 | + | |
| 21 | +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) | |
| 22 | + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) | |
| 23 | + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) | |
| 24 | +endforeach(ffi_plugin) | |
| new file mode 100644 | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | +# | ||
| 2 | +# Generated file, do not edit. | ||
| 3 | +# | ||
| 4 | + | ||
| 5 | +list(APPEND FLUTTER_PLUGIN_LIST | ||
| 6 | +) | ||
| 7 | + | ||
| 8 | +list(APPEND FLUTTER_FFI_PLUGIN_LIST | ||
| 9 | + vflutter_ffi | ||
| 10 | +) | ||
| 11 | + | ||
| 12 | +set(PLUGIN_BUNDLED_LIBRARIES) | ||
| 13 | + | ||
| 14 | +foreach(plugin ${FLUTTER_PLUGIN_LIST}) | ||
| 15 | + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) | ||
| 16 | + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) | ||
| 17 | + list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>) | ||
| 18 | + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) | ||
| 19 | +endforeach(plugin) | ||
| 20 | + | ||
| 21 | +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) | ||
| 22 | + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) | ||
| 23 | + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) | ||
| 24 | +endforeach(ffi_plugin) | ||
added
example/linux/runner/CMakeLists.txt +26 -0 | new file mode 100644 | ||
| @@ -0,0 +1,26 @@ | ||
| 1 | +cmake_minimum_required(VERSION 3.13) | |
| 2 | +project(runner LANGUAGES CXX) | |
| 3 | + | |
| 4 | +# Define the application target. To change its name, change BINARY_NAME in the | |
| 5 | +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer | |
| 6 | +# work. | |
| 7 | +# | |
| 8 | +# Any new source files that you add to the application should be added here. | |
| 9 | +add_executable(${BINARY_NAME} | |
| 10 | + "main.cc" | |
| 11 | + "my_application.cc" | |
| 12 | + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" | |
| 13 | +) | |
| 14 | + | |
| 15 | +# Apply the standard set of build settings. This can be removed for applications | |
| 16 | +# that need different build settings. | |
| 17 | +apply_standard_settings(${BINARY_NAME}) | |
| 18 | + | |
| 19 | +# Add preprocessor definitions for the application ID. | |
| 20 | +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") | |
| 21 | + | |
| 22 | +# Add dependency libraries. Add any application-specific dependencies here. | |
| 23 | +target_link_libraries(${BINARY_NAME} PRIVATE flutter) | |
| 24 | +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) | |
| 25 | + | |
| 26 | +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") | |
| new file mode 100644 | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | +cmake_minimum_required(VERSION 3.13) | ||
| 2 | +project(runner LANGUAGES CXX) | ||
| 3 | + | ||
| 4 | +# Define the application target. To change its name, change BINARY_NAME in the | ||
| 5 | +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer | ||
| 6 | +# work. | ||
| 7 | +# | ||
| 8 | +# Any new source files that you add to the application should be added here. | ||
| 9 | +add_executable(${BINARY_NAME} | ||
| 10 | + "main.cc" | ||
| 11 | + "my_application.cc" | ||
| 12 | + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" | ||
| 13 | +) | ||
| 14 | + | ||
| 15 | +# Apply the standard set of build settings. This can be removed for applications | ||
| 16 | +# that need different build settings. | ||
| 17 | +apply_standard_settings(${BINARY_NAME}) | ||
| 18 | + | ||
| 19 | +# Add preprocessor definitions for the application ID. | ||
| 20 | +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") | ||
| 21 | + | ||
| 22 | +# Add dependency libraries. Add any application-specific dependencies here. | ||
| 23 | +target_link_libraries(${BINARY_NAME} PRIVATE flutter) | ||
| 24 | +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) | ||
| 25 | + | ||
| 26 | +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") | ||
added
example/linux/runner/main.cc +6 -0 | new file mode 100644 | ||
| @@ -0,0 +1,6 @@ | ||
| 1 | +#include "my_application.h" | |
| 2 | + | |
| 3 | +int main(int argc, char** argv) { | |
| 4 | + g_autoptr(MyApplication) app = my_application_new(); | |
| 5 | + return g_application_run(G_APPLICATION(app), argc, argv); | |
| 6 | +} | |
| new file mode 100644 | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | +#include "my_application.h" | ||
| 2 | + | ||
| 3 | +int main(int argc, char** argv) { | ||
| 4 | + g_autoptr(MyApplication) app = my_application_new(); | ||
| 5 | + return g_application_run(G_APPLICATION(app), argc, argv); | ||
| 6 | +} | ||
added
example/linux/runner/my_application.cc +148 -0 | new file mode 100644 | ||
| @@ -0,0 +1,148 @@ | ||
| 1 | +#include "my_application.h" | |
| 2 | + | |
| 3 | +#include <flutter_linux/flutter_linux.h> | |
| 4 | +#ifdef GDK_WINDOWING_X11 | |
| 5 | +#include <gdk/gdkx.h> | |
| 6 | +#endif | |
| 7 | + | |
| 8 | +#include "flutter/generated_plugin_registrant.h" | |
| 9 | + | |
| 10 | +struct _MyApplication { | |
| 11 | + GtkApplication parent_instance; | |
| 12 | + char** dart_entrypoint_arguments; | |
| 13 | +}; | |
| 14 | + | |
| 15 | +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) | |
| 16 | + | |
| 17 | +// Called when first Flutter frame received. | |
| 18 | +static void first_frame_cb(MyApplication* self, FlView* view) { | |
| 19 | + gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); | |
| 20 | +} | |
| 21 | + | |
| 22 | +// Implements GApplication::activate. | |
| 23 | +static void my_application_activate(GApplication* application) { | |
| 24 | + MyApplication* self = MY_APPLICATION(application); | |
| 25 | + GtkWindow* window = | |
| 26 | + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); | |
| 27 | + | |
| 28 | + // Use a header bar when running in GNOME as this is the common style used | |
| 29 | + // by applications and is the setup most users will be using (e.g. Ubuntu | |
| 30 | + // desktop). | |
| 31 | + // If running on X and not using GNOME then just use a traditional title bar | |
| 32 | + // in case the window manager does more exotic layout, e.g. tiling. | |
| 33 | + // If running on Wayland assume the header bar will work (may need changing | |
| 34 | + // if future cases occur). | |
| 35 | + gboolean use_header_bar = TRUE; | |
| 36 | +#ifdef GDK_WINDOWING_X11 | |
| 37 | + GdkScreen* screen = gtk_window_get_screen(window); | |
| 38 | + if (GDK_IS_X11_SCREEN(screen)) { | |
| 39 | + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); | |
| 40 | + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { | |
| 41 | + use_header_bar = FALSE; | |
| 42 | + } | |
| 43 | + } | |
| 44 | +#endif | |
| 45 | + if (use_header_bar) { | |
| 46 | + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); | |
| 47 | + gtk_widget_show(GTK_WIDGET(header_bar)); | |
| 48 | + gtk_header_bar_set_title(header_bar, "vflutter_ffi_example"); | |
| 49 | + gtk_header_bar_set_show_close_button(header_bar, TRUE); | |
| 50 | + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); | |
| 51 | + } else { | |
| 52 | + gtk_window_set_title(window, "vflutter_ffi_example"); | |
| 53 | + } | |
| 54 | + | |
| 55 | + gtk_window_set_default_size(window, 1280, 720); | |
| 56 | + | |
| 57 | + g_autoptr(FlDartProject) project = fl_dart_project_new(); | |
| 58 | + fl_dart_project_set_dart_entrypoint_arguments( | |
| 59 | + project, self->dart_entrypoint_arguments); | |
| 60 | + | |
| 61 | + FlView* view = fl_view_new(project); | |
| 62 | + GdkRGBA background_color; | |
| 63 | + // Background defaults to black, override it here if necessary, e.g. #00000000 | |
| 64 | + // for transparent. | |
| 65 | + gdk_rgba_parse(&background_color, "#000000"); | |
| 66 | + fl_view_set_background_color(view, &background_color); | |
| 67 | + gtk_widget_show(GTK_WIDGET(view)); | |
| 68 | + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); | |
| 69 | + | |
| 70 | + // Show the window when Flutter renders. | |
| 71 | + // Requires the view to be realized so we can start rendering. | |
| 72 | + g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), | |
| 73 | + self); | |
| 74 | + gtk_widget_realize(GTK_WIDGET(view)); | |
| 75 | + | |
| 76 | + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); | |
| 77 | + | |
| 78 | + gtk_widget_grab_focus(GTK_WIDGET(view)); | |
| 79 | +} | |
| 80 | + | |
| 81 | +// Implements GApplication::local_command_line. | |
| 82 | +static gboolean my_application_local_command_line(GApplication* application, | |
| 83 | + gchar*** arguments, | |
| 84 | + int* exit_status) { | |
| 85 | + MyApplication* self = MY_APPLICATION(application); | |
| 86 | + // Strip out the first argument as it is the binary name. | |
| 87 | + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); | |
| 88 | + | |
| 89 | + g_autoptr(GError) error = nullptr; | |
| 90 | + if (!g_application_register(application, nullptr, &error)) { | |
| 91 | + g_warning("Failed to register: %s", error->message); | |
| 92 | + *exit_status = 1; | |
| 93 | + return TRUE; | |
| 94 | + } | |
| 95 | + | |
| 96 | + g_application_activate(application); | |
| 97 | + *exit_status = 0; | |
| 98 | + | |
| 99 | + return TRUE; | |
| 100 | +} | |
| 101 | + | |
| 102 | +// Implements GApplication::startup. | |
| 103 | +static void my_application_startup(GApplication* application) { | |
| 104 | + // MyApplication* self = MY_APPLICATION(object); | |
| 105 | + | |
| 106 | + // Perform any actions required at application startup. | |
| 107 | + | |
| 108 | + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); | |
| 109 | +} | |
| 110 | + | |
| 111 | +// Implements GApplication::shutdown. | |
| 112 | +static void my_application_shutdown(GApplication* application) { | |
| 113 | + // MyApplication* self = MY_APPLICATION(object); | |
| 114 | + | |
| 115 | + // Perform any actions required at application shutdown. | |
| 116 | + | |
| 117 | + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); | |
| 118 | +} | |
| 119 | + | |
| 120 | +// Implements GObject::dispose. | |
| 121 | +static void my_application_dispose(GObject* object) { | |
| 122 | + MyApplication* self = MY_APPLICATION(object); | |
| 123 | + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); | |
| 124 | + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); | |
| 125 | +} | |
| 126 | + | |
| 127 | +static void my_application_class_init(MyApplicationClass* klass) { | |
| 128 | + G_APPLICATION_CLASS(klass)->activate = my_application_activate; | |
| 129 | + G_APPLICATION_CLASS(klass)->local_command_line = | |
| 130 | + my_application_local_command_line; | |
| 131 | + G_APPLICATION_CLASS(klass)->startup = my_application_startup; | |
| 132 | + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; | |
| 133 | + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; | |
| 134 | +} | |
| 135 | + | |
| 136 | +static void my_application_init(MyApplication* self) {} | |
| 137 | + | |
| 138 | +MyApplication* my_application_new() { | |
| 139 | + // Set the program name to the application ID, which helps various systems | |
| 140 | + // like GTK and desktop environments map this running application to its | |
| 141 | + // corresponding .desktop file. This ensures better integration by allowing | |
| 142 | + // the application to be recognized beyond its binary name. | |
| 143 | + g_set_prgname(APPLICATION_ID); | |
| 144 | + | |
| 145 | + return MY_APPLICATION(g_object_new(my_application_get_type(), | |
| 146 | + "application-id", APPLICATION_ID, "flags", | |
| 147 | + G_APPLICATION_NON_UNIQUE, nullptr)); | |
| 148 | +} | |
| new file mode 100644 | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | +#include "my_application.h" | ||
| 2 | + | ||
| 3 | +#include <flutter_linux/flutter_linux.h> | ||
| 4 | +#ifdef GDK_WINDOWING_X11 | ||
| 5 | +#include <gdk/gdkx.h> | ||
| 6 | +#endif | ||
| 7 | + | ||
| 8 | +#include "flutter/generated_plugin_registrant.h" | ||
| 9 | + | ||
| 10 | +struct _MyApplication { | ||
| 11 | + GtkApplication parent_instance; | ||
| 12 | + char** dart_entrypoint_arguments; | ||
| 13 | +}; | ||
| 14 | + | ||
| 15 | +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) | ||
| 16 | + | ||
| 17 | +// Called when first Flutter frame received. | ||
| 18 | +static void first_frame_cb(MyApplication* self, FlView* view) { | ||
| 19 | + gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +// Implements GApplication::activate. | ||
| 23 | +static void my_application_activate(GApplication* application) { | ||
| 24 | + MyApplication* self = MY_APPLICATION(application); | ||
| 25 | + GtkWindow* window = | ||
| 26 | + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); | ||
| 27 | + | ||
| 28 | + // Use a header bar when running in GNOME as this is the common style used | ||
| 29 | + // by applications and is the setup most users will be using (e.g. Ubuntu | ||
| 30 | + // desktop). | ||
| 31 | + // If running on X and not using GNOME then just use a traditional title bar | ||
| 32 | + // in case the window manager does more exotic layout, e.g. tiling. | ||
| 33 | + // If running on Wayland assume the header bar will work (may need changing | ||
| 34 | + // if future cases occur). | ||
| 35 | + gboolean use_header_bar = TRUE; | ||
| 36 | +#ifdef GDK_WINDOWING_X11 | ||
| 37 | + GdkScreen* screen = gtk_window_get_screen(window); | ||
| 38 | + if (GDK_IS_X11_SCREEN(screen)) { | ||
| 39 | + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); | ||
| 40 | + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { | ||
| 41 | + use_header_bar = FALSE; | ||
| 42 | + } | ||
| 43 | + } | ||
| 44 | +#endif | ||
| 45 | + if (use_header_bar) { | ||
| 46 | + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); | ||
| 47 | + gtk_widget_show(GTK_WIDGET(header_bar)); | ||
| 48 | + gtk_header_bar_set_title(header_bar, "vflutter_ffi_example"); | ||
| 49 | + gtk_header_bar_set_show_close_button(header_bar, TRUE); | ||
| 50 | + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); | ||
| 51 | + } else { | ||
| 52 | + gtk_window_set_title(window, "vflutter_ffi_example"); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + gtk_window_set_default_size(window, 1280, 720); | ||
| 56 | + | ||
| 57 | + g_autoptr(FlDartProject) project = fl_dart_project_new(); | ||
| 58 | + fl_dart_project_set_dart_entrypoint_arguments( | ||
| 59 | + project, self->dart_entrypoint_arguments); | ||
| 60 | + | ||
| 61 | + FlView* view = fl_view_new(project); | ||
| 62 | + GdkRGBA background_color; | ||
| 63 | + // Background defaults to black, override it here if necessary, e.g. #00000000 | ||
| 64 | + // for transparent. | ||
| 65 | + gdk_rgba_parse(&background_color, "#000000"); | ||
| 66 | + fl_view_set_background_color(view, &background_color); | ||
| 67 | + gtk_widget_show(GTK_WIDGET(view)); | ||
| 68 | + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); | ||
| 69 | + | ||
| 70 | + // Show the window when Flutter renders. | ||
| 71 | + // Requires the view to be realized so we can start rendering. | ||
| 72 | + g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), | ||
| 73 | + self); | ||
| 74 | + gtk_widget_realize(GTK_WIDGET(view)); | ||
| 75 | + | ||
| 76 | + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); | ||
| 77 | + | ||
| 78 | + gtk_widget_grab_focus(GTK_WIDGET(view)); | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +// Implements GApplication::local_command_line. | ||
| 82 | +static gboolean my_application_local_command_line(GApplication* application, | ||
| 83 | + gchar*** arguments, | ||
| 84 | + int* exit_status) { | ||
| 85 | + MyApplication* self = MY_APPLICATION(application); | ||
| 86 | + // Strip out the first argument as it is the binary name. | ||
| 87 | + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); | ||
| 88 | + | ||
| 89 | + g_autoptr(GError) error = nullptr; | ||
| 90 | + if (!g_application_register(application, nullptr, &error)) { | ||
| 91 | + g_warning("Failed to register: %s", error->message); | ||
| 92 | + *exit_status = 1; | ||
| 93 | + return TRUE; | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + g_application_activate(application); | ||
| 97 | + *exit_status = 0; | ||
| 98 | + | ||
| 99 | + return TRUE; | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +// Implements GApplication::startup. | ||
| 103 | +static void my_application_startup(GApplication* application) { | ||
| 104 | + // MyApplication* self = MY_APPLICATION(object); | ||
| 105 | + | ||
| 106 | + // Perform any actions required at application startup. | ||
| 107 | + | ||
| 108 | + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); | ||
| 109 | +} | ||
| 110 | + | ||
| 111 | +// Implements GApplication::shutdown. | ||
| 112 | +static void my_application_shutdown(GApplication* application) { | ||
| 113 | + // MyApplication* self = MY_APPLICATION(object); | ||
| 114 | + | ||
| 115 | + // Perform any actions required at application shutdown. | ||
| 116 | + | ||
| 117 | + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +// Implements GObject::dispose. | ||
| 121 | +static void my_application_dispose(GObject* object) { | ||
| 122 | + MyApplication* self = MY_APPLICATION(object); | ||
| 123 | + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); | ||
| 124 | + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +static void my_application_class_init(MyApplicationClass* klass) { | ||
| 128 | + G_APPLICATION_CLASS(klass)->activate = my_application_activate; | ||
| 129 | + G_APPLICATION_CLASS(klass)->local_command_line = | ||
| 130 | + my_application_local_command_line; | ||
| 131 | + G_APPLICATION_CLASS(klass)->startup = my_application_startup; | ||
| 132 | + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; | ||
| 133 | + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; | ||
| 134 | +} | ||
| 135 | + | ||
| 136 | +static void my_application_init(MyApplication* self) {} | ||
| 137 | + | ||
| 138 | +MyApplication* my_application_new() { | ||
| 139 | + // Set the program name to the application ID, which helps various systems | ||
| 140 | + // like GTK and desktop environments map this running application to its | ||
| 141 | + // corresponding .desktop file. This ensures better integration by allowing | ||
| 142 | + // the application to be recognized beyond its binary name. | ||
| 143 | + g_set_prgname(APPLICATION_ID); | ||
| 144 | + | ||
| 145 | + return MY_APPLICATION(g_object_new(my_application_get_type(), | ||
| 146 | + "application-id", APPLICATION_ID, "flags", | ||
| 147 | + G_APPLICATION_NON_UNIQUE, nullptr)); | ||
| 148 | +} | ||
added
example/linux/runner/my_application.h +21 -0 | new file mode 100644 | ||
| @@ -0,0 +1,21 @@ | ||
| 1 | +#ifndef FLUTTER_MY_APPLICATION_H_ | |
| 2 | +#define FLUTTER_MY_APPLICATION_H_ | |
| 3 | + | |
| 4 | +#include <gtk/gtk.h> | |
| 5 | + | |
| 6 | +G_DECLARE_FINAL_TYPE(MyApplication, | |
| 7 | + my_application, | |
| 8 | + MY, | |
| 9 | + APPLICATION, | |
| 10 | + GtkApplication) | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * my_application_new: | |
| 14 | + * | |
| 15 | + * Creates a new Flutter-based application. | |
| 16 | + * | |
| 17 | + * Returns: a new #MyApplication. | |
| 18 | + */ | |
| 19 | +MyApplication* my_application_new(); | |
| 20 | + | |
| 21 | +#endif // FLUTTER_MY_APPLICATION_H_ | |
| new file mode 100644 | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | +#ifndef FLUTTER_MY_APPLICATION_H_ | ||
| 2 | +#define FLUTTER_MY_APPLICATION_H_ | ||
| 3 | + | ||
| 4 | +#include <gtk/gtk.h> | ||
| 5 | + | ||
| 6 | +G_DECLARE_FINAL_TYPE(MyApplication, | ||
| 7 | + my_application, | ||
| 8 | + MY, | ||
| 9 | + APPLICATION, | ||
| 10 | + GtkApplication) | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * my_application_new: | ||
| 14 | + * | ||
| 15 | + * Creates a new Flutter-based application. | ||
| 16 | + * | ||
| 17 | + * Returns: a new #MyApplication. | ||
| 18 | + */ | ||
| 19 | +MyApplication* my_application_new(); | ||
| 20 | + | ||
| 21 | +#endif // FLUTTER_MY_APPLICATION_H_ | ||
added
example/pubspec.lock +228 -0 | new file mode 100644 | ||
| @@ -0,0 +1,228 @@ | ||
| 1 | +# Generated by pub | |
| 2 | +# See https://dart.dev/tools/pub/glossary#lockfile | |
| 3 | +packages: | |
| 4 | + async: | |
| 5 | + dependency: transitive | |
| 6 | + description: | |
| 7 | + name: async | |
| 8 | + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 | |
| 9 | + url: "https://pub.dev" | |
| 10 | + source: hosted | |
| 11 | + version: "2.13.1" | |
| 12 | + boolean_selector: | |
| 13 | + dependency: transitive | |
| 14 | + description: | |
| 15 | + name: boolean_selector | |
| 16 | + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" | |
| 17 | + url: "https://pub.dev" | |
| 18 | + source: hosted | |
| 19 | + version: "2.1.2" | |
| 20 | + characters: | |
| 21 | + dependency: transitive | |
| 22 | + description: | |
| 23 | + name: characters | |
| 24 | + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b | |
| 25 | + url: "https://pub.dev" | |
| 26 | + source: hosted | |
| 27 | + version: "1.4.1" | |
| 28 | + clock: | |
| 29 | + dependency: transitive | |
| 30 | + description: | |
| 31 | + name: clock | |
| 32 | + sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e | |
| 33 | + url: "https://pub.dev" | |
| 34 | + source: hosted | |
| 35 | + version: "1.1.3" | |
| 36 | + collection: | |
| 37 | + dependency: transitive | |
| 38 | + description: | |
| 39 | + name: collection | |
| 40 | + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" | |
| 41 | + url: "https://pub.dev" | |
| 42 | + source: hosted | |
| 43 | + version: "1.19.1" | |
| 44 | + cupertino_icons: | |
| 45 | + dependency: "direct main" | |
| 46 | + description: | |
| 47 | + name: cupertino_icons | |
| 48 | + sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" | |
| 49 | + url: "https://pub.dev" | |
| 50 | + source: hosted | |
| 51 | + version: "1.0.9" | |
| 52 | + fake_async: | |
| 53 | + dependency: transitive | |
| 54 | + description: | |
| 55 | + name: fake_async | |
| 56 | + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" | |
| 57 | + url: "https://pub.dev" | |
| 58 | + source: hosted | |
| 59 | + version: "1.3.3" | |
| 60 | + ffi: | |
| 61 | + dependency: "direct main" | |
| 62 | + description: | |
| 63 | + name: ffi | |
| 64 | + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" | |
| 65 | + url: "https://pub.dev" | |
| 66 | + source: hosted | |
| 67 | + version: "2.2.0" | |
| 68 | + flutter: | |
| 69 | + dependency: "direct main" | |
| 70 | + description: flutter | |
| 71 | + source: sdk | |
| 72 | + version: "0.0.0" | |
| 73 | + flutter_lints: | |
| 74 | + dependency: "direct dev" | |
| 75 | + description: | |
| 76 | + name: flutter_lints | |
| 77 | + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" | |
| 78 | + url: "https://pub.dev" | |
| 79 | + source: hosted | |
| 80 | + version: "6.0.0" | |
| 81 | + flutter_test: | |
| 82 | + dependency: "direct dev" | |
| 83 | + description: flutter | |
| 84 | + source: sdk | |
| 85 | + version: "0.0.0" | |
| 86 | + leak_tracker: | |
| 87 | + dependency: transitive | |
| 88 | + description: | |
| 89 | + name: leak_tracker | |
| 90 | + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" | |
| 91 | + url: "https://pub.dev" | |
| 92 | + source: hosted | |
| 93 | + version: "11.0.2" | |
| 94 | + leak_tracker_flutter_testing: | |
| 95 | + dependency: transitive | |
| 96 | + description: | |
| 97 | + name: leak_tracker_flutter_testing | |
| 98 | + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" | |
| 99 | + url: "https://pub.dev" | |
| 100 | + source: hosted | |
| 101 | + version: "3.0.10" | |
| 102 | + leak_tracker_testing: | |
| 103 | + dependency: transitive | |
| 104 | + description: | |
| 105 | + name: leak_tracker_testing | |
| 106 | + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" | |
| 107 | + url: "https://pub.dev" | |
| 108 | + source: hosted | |
| 109 | + version: "3.0.2" | |
| 110 | + lints: | |
| 111 | + dependency: transitive | |
| 112 | + description: | |
| 113 | + name: lints | |
| 114 | + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" | |
| 115 | + url: "https://pub.dev" | |
| 116 | + source: hosted | |
| 117 | + version: "6.1.0" | |
| 118 | + matcher: | |
| 119 | + dependency: transitive | |
| 120 | + description: | |
| 121 | + name: matcher | |
| 122 | + sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" | |
| 123 | + url: "https://pub.dev" | |
| 124 | + source: hosted | |
| 125 | + version: "0.12.20" | |
| 126 | + material_color_utilities: | |
| 127 | + dependency: transitive | |
| 128 | + description: | |
| 129 | + name: material_color_utilities | |
| 130 | + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" | |
| 131 | + url: "https://pub.dev" | |
| 132 | + source: hosted | |
| 133 | + version: "0.13.0" | |
| 134 | + meta: | |
| 135 | + dependency: transitive | |
| 136 | + description: | |
| 137 | + name: meta | |
| 138 | + sha256: c82594181e3312f3d0695fc95aaaf7758d75b8d4ae2bbecf223b9fd5109a059d | |
| 139 | + url: "https://pub.dev" | |
| 140 | + source: hosted | |
| 141 | + version: "1.18.3" | |
| 142 | + path: | |
| 143 | + dependency: transitive | |
| 144 | + description: | |
| 145 | + name: path | |
| 146 | + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" | |
| 147 | + url: "https://pub.dev" | |
| 148 | + source: hosted | |
| 149 | + version: "1.9.1" | |
| 150 | + sky_engine: | |
| 151 | + dependency: transitive | |
| 152 | + description: flutter | |
| 153 | + source: sdk | |
| 154 | + version: "0.0.0" | |
| 155 | + source_span: | |
| 156 | + dependency: transitive | |
| 157 | + description: | |
| 158 | + name: source_span | |
| 159 | + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" | |
| 160 | + url: "https://pub.dev" | |
| 161 | + source: hosted | |
| 162 | + version: "1.10.2" | |
| 163 | + stack_trace: | |
| 164 | + dependency: transitive | |
| 165 | + description: | |
| 166 | + name: stack_trace | |
| 167 | + sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490" | |
| 168 | + url: "https://pub.dev" | |
| 169 | + source: hosted | |
| 170 | + version: "1.12.2" | |
| 171 | + stream_channel: | |
| 172 | + dependency: transitive | |
| 173 | + description: | |
| 174 | + name: stream_channel | |
| 175 | + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" | |
| 176 | + url: "https://pub.dev" | |
| 177 | + source: hosted | |
| 178 | + version: "2.1.4" | |
| 179 | + string_scanner: | |
| 180 | + dependency: transitive | |
| 181 | + description: | |
| 182 | + name: string_scanner | |
| 183 | + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" | |
| 184 | + url: "https://pub.dev" | |
| 185 | + source: hosted | |
| 186 | + version: "1.4.1" | |
| 187 | + term_glyph: | |
| 188 | + dependency: transitive | |
| 189 | + description: | |
| 190 | + name: term_glyph | |
| 191 | + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" | |
| 192 | + url: "https://pub.dev" | |
| 193 | + source: hosted | |
| 194 | + version: "1.2.2" | |
| 195 | + test_api: | |
| 196 | + dependency: transitive | |
| 197 | + description: | |
| 198 | + name: test_api | |
| 199 | + sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" | |
| 200 | + url: "https://pub.dev" | |
| 201 | + source: hosted | |
| 202 | + version: "0.7.12" | |
| 203 | + vector_math: | |
| 204 | + dependency: transitive | |
| 205 | + description: | |
| 206 | + name: vector_math | |
| 207 | + sha256: "1d774bbdf6b72a0b12122fc1560c9c2d2a67db5a4a4cc2bd8a5c990ab20e3188" | |
| 208 | + url: "https://pub.dev" | |
| 209 | + source: hosted | |
| 210 | + version: "2.4.0" | |
| 211 | + vflutter_ffi: | |
| 212 | + dependency: "direct main" | |
| 213 | + description: | |
| 214 | + path: ".." | |
| 215 | + relative: true | |
| 216 | + source: path | |
| 217 | + version: "0.1.0" | |
| 218 | + vm_service: | |
| 219 | + dependency: transitive | |
| 220 | + description: | |
| 221 | + name: vm_service | |
| 222 | + sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0" | |
| 223 | + url: "https://pub.dev" | |
| 224 | + source: hosted | |
| 225 | + version: "15.3.0" | |
| 226 | +sdks: | |
| 227 | + dart: ">=3.13.3 <4.0.0" | |
| 228 | + flutter: ">=3.18.0-18.0.pre.54" | |
| new file mode 100644 | |||
| @@ -0,0 +1,228 @@ | |||
| 1 | +# Generated by pub | ||
| 2 | +# See https://dart.dev/tools/pub/glossary#lockfile | ||
| 3 | +packages: | ||
| 4 | + async: | ||
| 5 | + dependency: transitive | ||
| 6 | + description: | ||
| 7 | + name: async | ||
| 8 | + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 | ||
| 9 | + url: "https://pub.dev" | ||
| 10 | + source: hosted | ||
| 11 | + version: "2.13.1" | ||
| 12 | + boolean_selector: | ||
| 13 | + dependency: transitive | ||
| 14 | + description: | ||
| 15 | + name: boolean_selector | ||
| 16 | + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" | ||
| 17 | + url: "https://pub.dev" | ||
| 18 | + source: hosted | ||
| 19 | + version: "2.1.2" | ||
| 20 | + characters: | ||
| 21 | + dependency: transitive | ||
| 22 | + description: | ||
| 23 | + name: characters | ||
| 24 | + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b | ||
| 25 | + url: "https://pub.dev" | ||
| 26 | + source: hosted | ||
| 27 | + version: "1.4.1" | ||
| 28 | + clock: | ||
| 29 | + dependency: transitive | ||
| 30 | + description: | ||
| 31 | + name: clock | ||
| 32 | + sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e | ||
| 33 | + url: "https://pub.dev" | ||
| 34 | + source: hosted | ||
| 35 | + version: "1.1.3" | ||
| 36 | + collection: | ||
| 37 | + dependency: transitive | ||
| 38 | + description: | ||
| 39 | + name: collection | ||
| 40 | + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" | ||
| 41 | + url: "https://pub.dev" | ||
| 42 | + source: hosted | ||
| 43 | + version: "1.19.1" | ||
| 44 | + cupertino_icons: | ||
| 45 | + dependency: "direct main" | ||
| 46 | + description: | ||
| 47 | + name: cupertino_icons | ||
| 48 | + sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" | ||
| 49 | + url: "https://pub.dev" | ||
| 50 | + source: hosted | ||
| 51 | + version: "1.0.9" | ||
| 52 | + fake_async: | ||
| 53 | + dependency: transitive | ||
| 54 | + description: | ||
| 55 | + name: fake_async | ||
| 56 | + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" | ||
| 57 | + url: "https://pub.dev" | ||
| 58 | + source: hosted | ||
| 59 | + version: "1.3.3" | ||
| 60 | + ffi: | ||
| 61 | + dependency: "direct main" | ||
| 62 | + description: | ||
| 63 | + name: ffi | ||
| 64 | + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" | ||
| 65 | + url: "https://pub.dev" | ||
| 66 | + source: hosted | ||
| 67 | + version: "2.2.0" | ||
| 68 | + flutter: | ||
| 69 | + dependency: "direct main" | ||
| 70 | + description: flutter | ||
| 71 | + source: sdk | ||
| 72 | + version: "0.0.0" | ||
| 73 | + flutter_lints: | ||
| 74 | + dependency: "direct dev" | ||
| 75 | + description: | ||
| 76 | + name: flutter_lints | ||
| 77 | + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" | ||
| 78 | + url: "https://pub.dev" | ||
| 79 | + source: hosted | ||
| 80 | + version: "6.0.0" | ||
| 81 | + flutter_test: | ||
| 82 | + dependency: "direct dev" | ||
| 83 | + description: flutter | ||
| 84 | + source: sdk | ||
| 85 | + version: "0.0.0" | ||
| 86 | + leak_tracker: | ||
| 87 | + dependency: transitive | ||
| 88 | + description: | ||
| 89 | + name: leak_tracker | ||
| 90 | + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" | ||
| 91 | + url: "https://pub.dev" | ||
| 92 | + source: hosted | ||
| 93 | + version: "11.0.2" | ||
| 94 | + leak_tracker_flutter_testing: | ||
| 95 | + dependency: transitive | ||
| 96 | + description: | ||
| 97 | + name: leak_tracker_flutter_testing | ||
| 98 | + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" | ||
| 99 | + url: "https://pub.dev" | ||
| 100 | + source: hosted | ||
| 101 | + version: "3.0.10" | ||
| 102 | + leak_tracker_testing: | ||
| 103 | + dependency: transitive | ||
| 104 | + description: | ||
| 105 | + name: leak_tracker_testing | ||
| 106 | + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" | ||
| 107 | + url: "https://pub.dev" | ||
| 108 | + source: hosted | ||
| 109 | + version: "3.0.2" | ||
| 110 | + lints: | ||
| 111 | + dependency: transitive | ||
| 112 | + description: | ||
| 113 | + name: lints | ||
| 114 | + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" | ||
| 115 | + url: "https://pub.dev" | ||
| 116 | + source: hosted | ||
| 117 | + version: "6.1.0" | ||
| 118 | + matcher: | ||
| 119 | + dependency: transitive | ||
| 120 | + description: | ||
| 121 | + name: matcher | ||
| 122 | + sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" | ||
| 123 | + url: "https://pub.dev" | ||
| 124 | + source: hosted | ||
| 125 | + version: "0.12.20" | ||
| 126 | + material_color_utilities: | ||
| 127 | + dependency: transitive | ||
| 128 | + description: | ||
| 129 | + name: material_color_utilities | ||
| 130 | + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" | ||
| 131 | + url: "https://pub.dev" | ||
| 132 | + source: hosted | ||
| 133 | + version: "0.13.0" | ||
| 134 | + meta: | ||
| 135 | + dependency: transitive | ||
| 136 | + description: | ||
| 137 | + name: meta | ||
| 138 | + sha256: c82594181e3312f3d0695fc95aaaf7758d75b8d4ae2bbecf223b9fd5109a059d | ||
| 139 | + url: "https://pub.dev" | ||
| 140 | + source: hosted | ||
| 141 | + version: "1.18.3" | ||
| 142 | + path: | ||
| 143 | + dependency: transitive | ||
| 144 | + description: | ||
| 145 | + name: path | ||
| 146 | + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" | ||
| 147 | + url: "https://pub.dev" | ||
| 148 | + source: hosted | ||
| 149 | + version: "1.9.1" | ||
| 150 | + sky_engine: | ||
| 151 | + dependency: transitive | ||
| 152 | + description: flutter | ||
| 153 | + source: sdk | ||
| 154 | + version: "0.0.0" | ||
| 155 | + source_span: | ||
| 156 | + dependency: transitive | ||
| 157 | + description: | ||
| 158 | + name: source_span | ||
| 159 | + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" | ||
| 160 | + url: "https://pub.dev" | ||
| 161 | + source: hosted | ||
| 162 | + version: "1.10.2" | ||
| 163 | + stack_trace: | ||
| 164 | + dependency: transitive | ||
| 165 | + description: | ||
| 166 | + name: stack_trace | ||
| 167 | + sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490" | ||
| 168 | + url: "https://pub.dev" | ||
| 169 | + source: hosted | ||
| 170 | + version: "1.12.2" | ||
| 171 | + stream_channel: | ||
| 172 | + dependency: transitive | ||
| 173 | + description: | ||
| 174 | + name: stream_channel | ||
| 175 | + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" | ||
| 176 | + url: "https://pub.dev" | ||
| 177 | + source: hosted | ||
| 178 | + version: "2.1.4" | ||
| 179 | + string_scanner: | ||
| 180 | + dependency: transitive | ||
| 181 | + description: | ||
| 182 | + name: string_scanner | ||
| 183 | + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" | ||
| 184 | + url: "https://pub.dev" | ||
| 185 | + source: hosted | ||
| 186 | + version: "1.4.1" | ||
| 187 | + term_glyph: | ||
| 188 | + dependency: transitive | ||
| 189 | + description: | ||
| 190 | + name: term_glyph | ||
| 191 | + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" | ||
| 192 | + url: "https://pub.dev" | ||
| 193 | + source: hosted | ||
| 194 | + version: "1.2.2" | ||
| 195 | + test_api: | ||
| 196 | + dependency: transitive | ||
| 197 | + description: | ||
| 198 | + name: test_api | ||
| 199 | + sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" | ||
| 200 | + url: "https://pub.dev" | ||
| 201 | + source: hosted | ||
| 202 | + version: "0.7.12" | ||
| 203 | + vector_math: | ||
| 204 | + dependency: transitive | ||
| 205 | + description: | ||
| 206 | + name: vector_math | ||
| 207 | + sha256: "1d774bbdf6b72a0b12122fc1560c9c2d2a67db5a4a4cc2bd8a5c990ab20e3188" | ||
| 208 | + url: "https://pub.dev" | ||
| 209 | + source: hosted | ||
| 210 | + version: "2.4.0" | ||
| 211 | + vflutter_ffi: | ||
| 212 | + dependency: "direct main" | ||
| 213 | + description: | ||
| 214 | + path: ".." | ||
| 215 | + relative: true | ||
| 216 | + source: path | ||
| 217 | + version: "0.1.0" | ||
| 218 | + vm_service: | ||
| 219 | + dependency: transitive | ||
| 220 | + description: | ||
| 221 | + name: vm_service | ||
| 222 | + sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0" | ||
| 223 | + url: "https://pub.dev" | ||
| 224 | + source: hosted | ||
| 225 | + version: "15.3.0" | ||
| 226 | +sdks: | ||
| 227 | + dart: ">=3.13.3 <4.0.0" | ||
| 228 | + flutter: ">=3.18.0-18.0.pre.54" | ||
added
example/pubspec.yaml +96 -0 | new file mode 100644 | ||
| @@ -0,0 +1,96 @@ | ||
| 1 | +name: vflutter_ffi_example | |
| 2 | +description: "A new Flutter project." | |
| 3 | +# The following line prevents the package from being accidentally published to | |
| 4 | +# pub.dev using `flutter pub publish`. This is preferred for private packages. | |
| 5 | +publish_to: 'none' # Remove this line if you wish to publish to pub.dev | |
| 6 | + | |
| 7 | +# The following defines the version and build number for your application. | |
| 8 | +# A version number is three numbers separated by dots, like 1.2.43 | |
| 9 | +# followed by an optional build number separated by a +. | |
| 10 | +# Both the version and the builder number may be overridden in flutter | |
| 11 | +# build by specifying --build-name and --build-number, respectively. | |
| 12 | +# In Android, build-name is used as versionName while build-number used as versionCode. | |
| 13 | +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning | |
| 14 | +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. | |
| 15 | +# Read more about iOS versioning at | |
| 16 | +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | |
| 17 | +# In Windows, build-name is used as the major, minor, and patch parts | |
| 18 | +# of the product and file versions while build-number is used as the build suffix. | |
| 19 | +version: 1.0.0+1 | |
| 20 | + | |
| 21 | +environment: | |
| 22 | + sdk: ^3.13.3 | |
| 23 | + | |
| 24 | +# Dependencies specify other packages that your package needs in order to work. | |
| 25 | +# To automatically upgrade your package dependencies to the latest versions | |
| 26 | +# consider running `flutter pub upgrade --major-versions`. Alternatively, | |
| 27 | +# dependencies can be manually updated by changing the version numbers below to | |
| 28 | +# the latest version available on pub.dev. To see which dependencies have newer | |
| 29 | +# versions available, run `flutter pub outdated`. | |
| 30 | +dependencies: | |
| 31 | + flutter: | |
| 32 | + sdk: flutter | |
| 33 | + | |
| 34 | + # The following adds the Cupertino Icons font to your application. | |
| 35 | + # Use with the CupertinoIcons class for iOS style icons. | |
| 36 | + cupertino_icons: ^1.0.8 | |
| 37 | + | |
| 38 | + # The plugin under test, from the repo root. | |
| 39 | + vflutter_ffi: | |
| 40 | + path: ../ | |
| 41 | + | |
| 42 | + # Used directly by lib/memory_check.dart. | |
| 43 | + ffi: ^2.1.0 | |
| 44 | + | |
| 45 | +dev_dependencies: | |
| 46 | + flutter_test: | |
| 47 | + sdk: flutter | |
| 48 | + | |
| 49 | + # The "flutter_lints" package below contains a set of recommended lints to | |
| 50 | + # encourage good coding practices. The lint set provided by the package is | |
| 51 | + # activated in the `analysis_options.yaml` file located at the root of your | |
| 52 | + # package. See that file for information about deactivating specific lint | |
| 53 | + # rules and activating additional ones. | |
| 54 | + flutter_lints: ^6.0.0 | |
| 55 | + | |
| 56 | +# For information on the generic Dart part of this file, see the | |
| 57 | +# following page: https://dart.dev/tools/pub/pubspec | |
| 58 | + | |
| 59 | +# The following section is specific to Flutter packages. | |
| 60 | +flutter: | |
| 61 | + | |
| 62 | + # The following line ensures that the Material Icons font is | |
| 63 | + # included with your application, so that you can use the icons in | |
| 64 | + # the material Icons class. | |
| 65 | + uses-material-design: true | |
| 66 | + | |
| 67 | + # To add assets to your application, add an assets section, like this: | |
| 68 | + # assets: | |
| 69 | + # - images/a_dot_burr.jpeg | |
| 70 | + # - images/a_dot_ham.jpeg | |
| 71 | + | |
| 72 | + # An image asset can refer to one or more resolution-specific "variants", see | |
| 73 | + # https://flutter.dev/to/resolution-aware-images | |
| 74 | + | |
| 75 | + # For details regarding adding assets from package dependencies, see | |
| 76 | + # https://flutter.dev/to/asset-from-package | |
| 77 | + | |
| 78 | + # To add custom fonts to your application, add a fonts section here, | |
| 79 | + # in this "flutter" section. Each entry in this list should have a | |
| 80 | + # "family" key with the font family name, and a "fonts" key with a | |
| 81 | + # list giving the asset and other descriptors for the font. For | |
| 82 | + # example: | |
| 83 | + # fonts: | |
| 84 | + # - family: Schyler | |
| 85 | + # fonts: | |
| 86 | + # - asset: fonts/Schyler-Regular.ttf | |
| 87 | + # - asset: fonts/Schyler-Italic.ttf | |
| 88 | + # style: italic | |
| 89 | + # - family: Trajan Pro | |
| 90 | + # fonts: | |
| 91 | + # - asset: fonts/TrajanPro.ttf | |
| 92 | + # - asset: fonts/TrajanPro_Bold.ttf | |
| 93 | + # weight: 700 | |
| 94 | + # | |
| 95 | + # For details regarding fonts from package dependencies, | |
| 96 | + # see https://flutter.dev/to/font-from-package | |
| new file mode 100644 | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | +name: vflutter_ffi_example | ||
| 2 | +description: "A new Flutter project." | ||
| 3 | +# The following line prevents the package from being accidentally published to | ||
| 4 | +# pub.dev using `flutter pub publish`. This is preferred for private packages. | ||
| 5 | +publish_to: 'none' # Remove this line if you wish to publish to pub.dev | ||
| 6 | + | ||
| 7 | +# The following defines the version and build number for your application. | ||
| 8 | +# A version number is three numbers separated by dots, like 1.2.43 | ||
| 9 | +# followed by an optional build number separated by a +. | ||
| 10 | +# Both the version and the builder number may be overridden in flutter | ||
| 11 | +# build by specifying --build-name and --build-number, respectively. | ||
| 12 | +# In Android, build-name is used as versionName while build-number used as versionCode. | ||
| 13 | +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning | ||
| 14 | +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. | ||
| 15 | +# Read more about iOS versioning at | ||
| 16 | +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html | ||
| 17 | +# In Windows, build-name is used as the major, minor, and patch parts | ||
| 18 | +# of the product and file versions while build-number is used as the build suffix. | ||
| 19 | +version: 1.0.0+1 | ||
| 20 | + | ||
| 21 | +environment: | ||
| 22 | + sdk: ^3.13.3 | ||
| 23 | + | ||
| 24 | +# Dependencies specify other packages that your package needs in order to work. | ||
| 25 | +# To automatically upgrade your package dependencies to the latest versions | ||
| 26 | +# consider running `flutter pub upgrade --major-versions`. Alternatively, | ||
| 27 | +# dependencies can be manually updated by changing the version numbers below to | ||
| 28 | +# the latest version available on pub.dev. To see which dependencies have newer | ||
| 29 | +# versions available, run `flutter pub outdated`. | ||
| 30 | +dependencies: | ||
| 31 | + flutter: | ||
| 32 | + sdk: flutter | ||
| 33 | + | ||
| 34 | + # The following adds the Cupertino Icons font to your application. | ||
| 35 | + # Use with the CupertinoIcons class for iOS style icons. | ||
| 36 | + cupertino_icons: ^1.0.8 | ||
| 37 | + | ||
| 38 | + # The plugin under test, from the repo root. | ||
| 39 | + vflutter_ffi: | ||
| 40 | + path: ../ | ||
| 41 | + | ||
| 42 | + # Used directly by lib/memory_check.dart. | ||
| 43 | + ffi: ^2.1.0 | ||
| 44 | + | ||
| 45 | +dev_dependencies: | ||
| 46 | + flutter_test: | ||
| 47 | + sdk: flutter | ||
| 48 | + | ||
| 49 | + # The "flutter_lints" package below contains a set of recommended lints to | ||
| 50 | + # encourage good coding practices. The lint set provided by the package is | ||
| 51 | + # activated in the `analysis_options.yaml` file located at the root of your | ||
| 52 | + # package. See that file for information about deactivating specific lint | ||
| 53 | + # rules and activating additional ones. | ||
| 54 | + flutter_lints: ^6.0.0 | ||
| 55 | + | ||
| 56 | +# For information on the generic Dart part of this file, see the | ||
| 57 | +# following page: https://dart.dev/tools/pub/pubspec | ||
| 58 | + | ||
| 59 | +# The following section is specific to Flutter packages. | ||
| 60 | +flutter: | ||
| 61 | + | ||
| 62 | + # The following line ensures that the Material Icons font is | ||
| 63 | + # included with your application, so that you can use the icons in | ||
| 64 | + # the material Icons class. | ||
| 65 | + uses-material-design: true | ||
| 66 | + | ||
| 67 | + # To add assets to your application, add an assets section, like this: | ||
| 68 | + # assets: | ||
| 69 | + # - images/a_dot_burr.jpeg | ||
| 70 | + # - images/a_dot_ham.jpeg | ||
| 71 | + | ||
| 72 | + # An image asset can refer to one or more resolution-specific "variants", see | ||
| 73 | + # https://flutter.dev/to/resolution-aware-images | ||
| 74 | + | ||
| 75 | + # For details regarding adding assets from package dependencies, see | ||
| 76 | + # https://flutter.dev/to/asset-from-package | ||
| 77 | + | ||
| 78 | + # To add custom fonts to your application, add a fonts section here, | ||
| 79 | + # in this "flutter" section. Each entry in this list should have a | ||
| 80 | + # "family" key with the font family name, and a "fonts" key with a | ||
| 81 | + # list giving the asset and other descriptors for the font. For | ||
| 82 | + # example: | ||
| 83 | + # fonts: | ||
| 84 | + # - family: Schyler | ||
| 85 | + # fonts: | ||
| 86 | + # - asset: fonts/Schyler-Regular.ttf | ||
| 87 | + # - asset: fonts/Schyler-Italic.ttf | ||
| 88 | + # style: italic | ||
| 89 | + # - family: Trajan Pro | ||
| 90 | + # fonts: | ||
| 91 | + # - asset: fonts/TrajanPro.ttf | ||
| 92 | + # - asset: fonts/TrajanPro_Bold.ttf | ||
| 93 | + # weight: 700 | ||
| 94 | + # | ||
| 95 | + # For details regarding fonts from package dependencies, | ||
| 96 | + # see https://flutter.dev/to/font-from-package | ||
added
example/test/widget_test.dart +36 -0 | new file mode 100644 | ||
| @@ -0,0 +1,36 @@ | ||
| 1 | +// Smoke test for the V bridge behind the UI. Runs on the host, so it loads | |
| 2 | +// the same libvflutter.so the desktop app does. | |
| 3 | + | |
| 4 | +import 'package:flutter_test/flutter_test.dart'; | |
| 5 | + | |
| 6 | +import 'package:vflutter_ffi_example/main.dart'; | |
| 7 | + | |
| 8 | +void main() { | |
| 9 | + testWidgets('renders results computed in V', (WidgetTester tester) async { | |
| 10 | + await tester.pumpWidget(const ExampleApp()); | |
| 11 | + | |
| 12 | + // vf_add across the C ABI. | |
| 13 | + expect(find.text('42'), findsOneWidget); | |
| 14 | + | |
| 15 | + // vf_greet round-trips a string and frees the V allocation. | |
| 16 | + expect(find.text('Hello, Flutter, from V!'), findsOneWidget); | |
| 17 | + }); | |
| 18 | + | |
| 19 | + testWidgets('background isolate returns the same answer', | |
| 20 | + (WidgetTester tester) async { | |
| 21 | + await tester.pumpWidget(const ExampleApp()); | |
| 22 | + | |
| 23 | + expect(find.text('(not run)'), findsNWidgets(2)); | |
| 24 | + | |
| 25 | + // greetAsync spawns a real isolate, which the default fake-async clock | |
| 26 | + // never lets complete — runAsync is required for the await to resolve. | |
| 27 | + await tester.runAsync(() async { | |
| 28 | + await tester.tap(find.text('run on background isolate')); | |
| 29 | + await Future<void>.delayed(const Duration(seconds: 2)); | |
| 30 | + }); | |
| 31 | + await tester.pump(); | |
| 32 | + | |
| 33 | + // Once on the sync row, once on the async row. | |
| 34 | + expect(find.text('Hello, Flutter, from V!'), findsNWidgets(2)); | |
| 35 | + }); | |
| 36 | +} | |
| new file mode 100644 | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | +// Smoke test for the V bridge behind the UI. Runs on the host, so it loads | ||
| 2 | +// the same libvflutter.so the desktop app does. | ||
| 3 | + | ||
| 4 | +import 'package:flutter_test/flutter_test.dart'; | ||
| 5 | + | ||
| 6 | +import 'package:vflutter_ffi_example/main.dart'; | ||
| 7 | + | ||
| 8 | +void main() { | ||
| 9 | + testWidgets('renders results computed in V', (WidgetTester tester) async { | ||
| 10 | + await tester.pumpWidget(const ExampleApp()); | ||
| 11 | + | ||
| 12 | + // vf_add across the C ABI. | ||
| 13 | + expect(find.text('42'), findsOneWidget); | ||
| 14 | + | ||
| 15 | + // vf_greet round-trips a string and frees the V allocation. | ||
| 16 | + expect(find.text('Hello, Flutter, from V!'), findsOneWidget); | ||
| 17 | + }); | ||
| 18 | + | ||
| 19 | + testWidgets('background isolate returns the same answer', | ||
| 20 | + (WidgetTester tester) async { | ||
| 21 | + await tester.pumpWidget(const ExampleApp()); | ||
| 22 | + | ||
| 23 | + expect(find.text('(not run)'), findsNWidgets(2)); | ||
| 24 | + | ||
| 25 | + // greetAsync spawns a real isolate, which the default fake-async clock | ||
| 26 | + // never lets complete — runAsync is required for the await to resolve. | ||
| 27 | + await tester.runAsync(() async { | ||
| 28 | + await tester.tap(find.text('run on background isolate')); | ||
| 29 | + await Future<void>.delayed(const Duration(seconds: 2)); | ||
| 30 | + }); | ||
| 31 | + await tester.pump(); | ||
| 32 | + | ||
| 33 | + // Once on the sync row, once on the async row. | ||
| 34 | + expect(find.text('Hello, Flutter, from V!'), findsNWidgets(2)); | ||
| 35 | + }); | ||
| 36 | +} | ||