From 3750beacb41d6fa1dc55833a9c021ca2fb47331f Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Fri, 7 Jan 2022 12:16:24 -0800 Subject: [PATCH] Update platform shims in dev/manual_tests (#94616) Updates the platform shims in dev/manual_tests so that Windows and Linux can be built. I had to update the Windows shims, because I was unable to build a Windows app there. Also updates the analyze.dart script to report all license issues simultaneously instead of just dying after the first failure. The only substantive code changes are in dev/bots/analyze.dart and dev/bots/test/analyze_test.dart --- dev/bots/analyze.dart | 60 ++++++--- dev/bots/test/analyze_test.dart | 9 +- dev/manual_tests/android/.gitignore | 13 ++ dev/manual_tests/android/app/build.gradle | 6 +- .../android/app/src/debug/AndroidManifest.xml | 2 +- .../android/app/src/main/AndroidManifest.xml | 20 +-- .../com/example/manual_tests/MainActivity.kt | 12 -- .../dev/flutter/manual_tests/MainActivity.kt | 6 + .../res/drawable-v21/launch_background.xml | 16 +++ .../main/res/drawable/launch_background.xml | 1 + .../app/src/main/res/values-night/styles.xml | 22 ++++ .../app/src/main/res/values/styles.xml | 13 +- .../app/src/profile/AndroidManifest.xml | 2 +- dev/manual_tests/android/project-app.lockfile | 4 +- dev/manual_tests/ios/.gitignore | 34 +++++ .../ios/Flutter/AppFrameworkInfo.plist | 2 +- .../ios/Runner.xcodeproj/project.pbxproj | 36 +++--- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++ .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++ .../xcshareddata/xcschemes/Runner.xcscheme | 8 +- .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++ .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++ dev/manual_tests/ios/Runner/Info.plist | 4 +- dev/manual_tests/linux/.gitignore | 1 + dev/manual_tests/linux/CMakeLists.txt | 116 ++++++++++++++++++ dev/manual_tests/linux/flutter/CMakeLists.txt | 87 +++++++++++++ .../flutter/generated_plugin_registrant.cc | 11 ++ .../flutter/generated_plugin_registrant.h | 15 +++ .../linux/flutter/generated_plugins.cmake | 15 +++ dev/manual_tests/linux/main.cc | 10 ++ dev/manual_tests/linux/my_application.cc | 108 ++++++++++++++++ dev/manual_tests/linux/my_application.h | 22 ++++ dev/manual_tests/macos/.gitignore | 1 + .../macos/Runner.xcodeproj/project.pbxproj | 6 +- .../xcshareddata/xcschemes/Runner.xcscheme | 8 +- .../macos/Runner/Base.lproj/MainMenu.xib | 4 + .../macos/Runner/Configs/AppInfo.xcconfig | 4 +- dev/manual_tests/web/favicon.png | Bin 0 -> 917 bytes dev/manual_tests/web/icons/Icon-192.png | Bin 0 -> 5292 bytes dev/manual_tests/web/icons/Icon-512.png | Bin 0 -> 8252 bytes .../web/icons/Icon-maskable-192.png | Bin 0 -> 5292 bytes .../web/icons/Icon-maskable-512.png | Bin 0 -> 8252 bytes dev/manual_tests/web/index.html | 97 ++++++++++++++- dev/manual_tests/web/manifest.json | 35 ++++++ .../windows/flutter/CMakeLists.txt | 1 + .../windows/runner/CMakeLists.txt | 1 - dev/manual_tests/windows/runner/Runner.rc | 16 ++- .../windows/runner/flutter_window.cpp | 11 +- .../windows/runner/flutter_window.h | 10 +- dev/manual_tests/windows/runner/main.cpp | 15 ++- dev/manual_tests/windows/runner/resource.h | 3 +- .../windows/runner/resources/app_icon.ico | Bin 0 -> 787 bytes dev/manual_tests/windows/runner/run_loop.cpp | 66 ---------- dev/manual_tests/windows/runner/run_loop.h | 44 ------- 54 files changed, 787 insertions(+), 222 deletions(-) create mode 100644 dev/manual_tests/android/.gitignore delete mode 100644 dev/manual_tests/android/app/src/main/kotlin/com/example/manual_tests/MainActivity.kt create mode 100644 dev/manual_tests/android/app/src/main/kotlin/dev/flutter/manual_tests/MainActivity.kt create mode 100644 dev/manual_tests/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 dev/manual_tests/android/app/src/main/res/values-night/styles.xml create mode 100644 dev/manual_tests/ios/.gitignore create mode 100644 dev/manual_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 dev/manual_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 dev/manual_tests/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 dev/manual_tests/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 dev/manual_tests/linux/.gitignore create mode 100644 dev/manual_tests/linux/CMakeLists.txt create mode 100644 dev/manual_tests/linux/flutter/CMakeLists.txt create mode 100644 dev/manual_tests/linux/flutter/generated_plugin_registrant.cc create mode 100644 dev/manual_tests/linux/flutter/generated_plugin_registrant.h create mode 100644 dev/manual_tests/linux/flutter/generated_plugins.cmake create mode 100644 dev/manual_tests/linux/main.cc create mode 100644 dev/manual_tests/linux/my_application.cc create mode 100644 dev/manual_tests/linux/my_application.h create mode 100644 dev/manual_tests/web/favicon.png create mode 100644 dev/manual_tests/web/icons/Icon-192.png create mode 100644 dev/manual_tests/web/icons/Icon-512.png create mode 100644 dev/manual_tests/web/icons/Icon-maskable-192.png create mode 100644 dev/manual_tests/web/icons/Icon-maskable-512.png create mode 100644 dev/manual_tests/web/manifest.json create mode 100644 dev/manual_tests/windows/runner/resources/app_icon.ico delete mode 100644 dev/manual_tests/windows/runner/run_loop.cpp delete mode 100644 dev/manual_tests/windows/runner/run_loop.h diff --git a/dev/bots/analyze.dart b/dev/bots/analyze.dart index 131fb14232..119784dd26 100644 --- a/dev/bots/analyze.dart +++ b/dev/bots/analyze.dart @@ -406,42 +406,62 @@ String _generateLicense(String prefix) { Future verifyNoMissingLicense(String workingDirectory, { bool checkMinimums = true }) async { final int? overrideMinimumMatches = checkMinimums ? null : 0; - await _verifyNoMissingLicenseForExtension(workingDirectory, 'dart', overrideMinimumMatches ?? 2000, _generateLicense('// ')); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'java', overrideMinimumMatches ?? 39, _generateLicense('// ')); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'h', overrideMinimumMatches ?? 30, _generateLicense('// ')); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'm', overrideMinimumMatches ?? 30, _generateLicense('// ')); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'swift', overrideMinimumMatches ?? 10, _generateLicense('// ')); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'gradle', overrideMinimumMatches ?? 80, _generateLicense('// ')); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'gn', overrideMinimumMatches ?? 0, _generateLicense('# ')); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'sh', overrideMinimumMatches ?? 1, '#!/usr/bin/env bash\n${_generateLicense('# ')}'); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'bat', overrideMinimumMatches ?? 1, '@ECHO off\n${_generateLicense('REM ')}'); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'ps1', overrideMinimumMatches ?? 1, _generateLicense('# ')); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'html', overrideMinimumMatches ?? 1, '\n', trailingBlank: false); - await _verifyNoMissingLicenseForExtension(workingDirectory, 'xml', overrideMinimumMatches ?? 1, ''); + int failed = 0; + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'dart', overrideMinimumMatches ?? 2000, _generateLicense('// ')); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'java', overrideMinimumMatches ?? 39, _generateLicense('// ')); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'h', overrideMinimumMatches ?? 30, _generateLicense('// ')); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'm', overrideMinimumMatches ?? 30, _generateLicense('// ')); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'swift', overrideMinimumMatches ?? 10, _generateLicense('// ')); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'gradle', overrideMinimumMatches ?? 80, _generateLicense('// ')); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'gn', overrideMinimumMatches ?? 0, _generateLicense('# ')); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'sh', overrideMinimumMatches ?? 1, _generateLicense('# '), header: r'#!/usr/bin/env bash\n',); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'bat', overrideMinimumMatches ?? 1, _generateLicense('REM '), header: r'@ECHO off\n'); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'ps1', overrideMinimumMatches ?? 1, _generateLicense('# ')); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'html', overrideMinimumMatches ?? 1, '', trailingBlank: false, header: r'\n'); + failed += await _verifyNoMissingLicenseForExtension(workingDirectory, 'xml', overrideMinimumMatches ?? 1, '', header: r'(<\?xml version="1.0" encoding="utf-8"\?>\n)?'); + if (failed > 0) { + exitWithError(['License check failed.']); + } } -Future _verifyNoMissingLicenseForExtension(String workingDirectory, String extension, int minimumMatches, String license, { bool trailingBlank = true }) async { +Future _verifyNoMissingLicenseForExtension( + String workingDirectory, + String extension, + int minimumMatches, + String license, { + bool trailingBlank = true, + // The "header" is a regular expression matching the header that comes before + // the license in some files. + String header = '', +}) async { assert(!license.endsWith('\n')); - final String licensePattern = '$license\n${trailingBlank ? '\n' : ''}'; + final String licensePattern = RegExp.escape('$license\n${trailingBlank ? '\n' : ''}'); final List errors = []; await for (final File file in _allFiles(workingDirectory, extension, minimumMatches: minimumMatches)) { final String contents = file.readAsStringSync().replaceAll('\r\n', '\n'); if (contents.isEmpty) continue; // let's not go down the /bin/true rabbit hole - if (!contents.startsWith(licensePattern)) + if (!contents.startsWith(RegExp(header + licensePattern))) errors.add(file.path); } // Fail if any errors if (errors.isNotEmpty) { - final String s = errors.length == 1 ? ' does' : 's do'; - exitWithError([ - '${bold}The following ${errors.length} file$s not have the right license header:$reset', - ...errors, + final String redLine = '$red━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━$reset'; + final String fileDoes = errors.length == 1 ? 'file does' : '${errors.length} files do'; + print([ + redLine, + '${bold}The following $fileDoes not have the right license header for $extension files:$reset', + ...errors.map((String error) => ' $error'), 'The expected license header is:', + if (header.isNotEmpty) 'A header matching the regular expression "$header",', + if (header.isNotEmpty) 'followed by the following license text:', license, if (trailingBlank) '...followed by a blank line.', - ]); + redLine, + ].join('\n')); + return 1; } + return 0; } class _TestSkip { diff --git a/dev/bots/test/analyze_test.dart b/dev/bots/test/analyze_test.dart index d5548952db..1d6668e0f0 100644 --- a/dev/bots/test/analyze_test.dart +++ b/dev/bots/test/analyze_test.dart @@ -120,18 +120,21 @@ void main() { test('analyze.dart - verifyNoMissingLicense', () async { final String result = await capture(() => verifyNoMissingLicense(testRootPath, checkMinimums: false), exitCode: 1); - final String lines = 'test/analyze-test-input/root/packages/foo/foo.dart' + final String file = 'test/analyze-test-input/root/packages/foo/foo.dart' .replaceAll('/', Platform.isWindows ? r'\' : '/'); expect(result, '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n' - 'The following 1 file does not have the right license header:\n' - '$lines\n' + 'The following file does not have the right license header for dart files:\n' + ' $file\n' 'The expected license header is:\n' '// Copyright 2014 The Flutter Authors. All rights reserved.\n' '// Use of this source code is governed by a BSD-style license that can be\n' '// found in the LICENSE file.\n' '...followed by a blank line.\n' '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n' + '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n' + 'License check failed.\n' + '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n' ); }); diff --git a/dev/manual_tests/android/.gitignore b/dev/manual_tests/android/.gitignore new file mode 100644 index 0000000000..6f568019d3 --- /dev/null +++ b/dev/manual_tests/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/dev/manual_tests/android/app/build.gradle b/dev/manual_tests/android/app/build.gradle index b8402f7c36..f3664fe1ed 100644 --- a/dev/manual_tests/android/app/build.gradle +++ b/dev/manual_tests/android/app/build.gradle @@ -45,13 +45,9 @@ android { main.java.srcDirs += 'src/main/kotlin' } - lintOptions { - disable 'InvalidPackage' - } - defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.manual_tests" + applicationId "dev.flutter.manual_tests" minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() diff --git a/dev/manual_tests/android/app/src/debug/AndroidManifest.xml b/dev/manual_tests/android/app/src/debug/AndroidManifest.xml index 5009c58c3c..2d503e4fcb 100644 --- a/dev/manual_tests/android/app/src/debug/AndroidManifest.xml +++ b/dev/manual_tests/android/app/src/debug/AndroidManifest.xml @@ -3,7 +3,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> + package="dev.flutter.manual_tests"> diff --git a/dev/manual_tests/android/app/src/main/AndroidManifest.xml b/dev/manual_tests/android/app/src/main/AndroidManifest.xml index dd93b27811..b2dd6fbee2 100644 --- a/dev/manual_tests/android/app/src/main/AndroidManifest.xml +++ b/dev/manual_tests/android/app/src/main/AndroidManifest.xml @@ -3,23 +3,27 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> - - + + + diff --git a/dev/manual_tests/android/app/src/main/kotlin/com/example/manual_tests/MainActivity.kt b/dev/manual_tests/android/app/src/main/kotlin/com/example/manual_tests/MainActivity.kt deleted file mode 100644 index f5dae92f65..0000000000 --- a/dev/manual_tests/android/app/src/main/kotlin/com/example/manual_tests/MainActivity.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.manual_tests - -import androidx.annotation.NonNull; -import io.flutter.embedding.android.FlutterActivity -import io.flutter.embedding.engine.FlutterEngine -import io.flutter.plugins.GeneratedPluginRegistrant - -class MainActivity: FlutterActivity() { - override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { - GeneratedPluginRegistrant.registerWith(flutterEngine); - } -} diff --git a/dev/manual_tests/android/app/src/main/kotlin/dev/flutter/manual_tests/MainActivity.kt b/dev/manual_tests/android/app/src/main/kotlin/dev/flutter/manual_tests/MainActivity.kt new file mode 100644 index 0000000000..f2ca557a8c --- /dev/null +++ b/dev/manual_tests/android/app/src/main/kotlin/dev/flutter/manual_tests/MainActivity.kt @@ -0,0 +1,6 @@ +package dev.flutter.manual_tests + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/dev/manual_tests/android/app/src/main/res/drawable-v21/launch_background.xml b/dev/manual_tests/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000000..9f19e2f904 --- /dev/null +++ b/dev/manual_tests/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/dev/manual_tests/android/app/src/main/res/drawable/launch_background.xml b/dev/manual_tests/android/app/src/main/res/drawable/launch_background.xml index bb6811b2ee..3727f9e00a 100644 --- a/dev/manual_tests/android/app/src/main/res/drawable/launch_background.xml +++ b/dev/manual_tests/android/app/src/main/res/drawable/launch_background.xml @@ -1,3 +1,4 @@ + diff --git a/dev/manual_tests/android/app/src/main/res/values-night/styles.xml b/dev/manual_tests/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000000..ad59180989 --- /dev/null +++ b/dev/manual_tests/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/dev/manual_tests/android/app/src/main/res/values/styles.xml b/dev/manual_tests/android/app/src/main/res/values/styles.xml index 223593b171..55fd7b57ee 100644 --- a/dev/manual_tests/android/app/src/main/res/values/styles.xml +++ b/dev/manual_tests/android/app/src/main/res/values/styles.xml @@ -1,11 +1,22 @@ + - + + diff --git a/dev/manual_tests/android/app/src/profile/AndroidManifest.xml b/dev/manual_tests/android/app/src/profile/AndroidManifest.xml index 5009c58c3c..2d503e4fcb 100644 --- a/dev/manual_tests/android/app/src/profile/AndroidManifest.xml +++ b/dev/manual_tests/android/app/src/profile/AndroidManifest.xml @@ -3,7 +3,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> + package="dev.flutter.manual_tests"> diff --git a/dev/manual_tests/android/project-app.lockfile b/dev/manual_tests/android/project-app.lockfile index c573760e20..340de7c6ee 100644 --- a/dev/manual_tests/android/project-app.lockfile +++ b/dev/manual_tests/android/project-app.lockfile @@ -21,8 +21,8 @@ androidx.savedstate:savedstate:1.0.0=debugAndroidTestCompileClasspath,debugApiDe androidx.tracing:tracing:1.0.0=debugAndroidTestCompileClasspath,debugApiDependenciesMetadata,debugCompileClasspath,debugImplementationDependenciesMetadata,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileApiDependenciesMetadata,profileCompileClasspath,profileImplementationDependenciesMetadata,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseApiDependenciesMetadata,releaseCompileClasspath,releaseImplementationDependenciesMetadata,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.versionedparcelable:versionedparcelable:1.1.1=debugAndroidTestCompileClasspath,debugApiDependenciesMetadata,debugCompileClasspath,debugImplementationDependenciesMetadata,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileApiDependenciesMetadata,profileCompileClasspath,profileImplementationDependenciesMetadata,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseApiDependenciesMetadata,releaseCompileClasspath,releaseImplementationDependenciesMetadata,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath androidx.viewpager:viewpager:1.0.0=debugAndroidTestCompileClasspath,debugApiDependenciesMetadata,debugCompileClasspath,debugImplementationDependenciesMetadata,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileApiDependenciesMetadata,profileCompileClasspath,profileImplementationDependenciesMetadata,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseApiDependenciesMetadata,releaseCompileClasspath,releaseImplementationDependenciesMetadata,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.window:window-java:1.0.0-beta03=debugAndroidTestCompileClasspath,debugApiDependenciesMetadata,debugCompileClasspath,debugImplementationDependenciesMetadata,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileApiDependenciesMetadata,profileCompileClasspath,profileImplementationDependenciesMetadata,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseApiDependenciesMetadata,releaseCompileClasspath,releaseImplementationDependenciesMetadata,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath -androidx.window:window:1.0.0-beta03=debugAndroidTestCompileClasspath,debugApiDependenciesMetadata,debugCompileClasspath,debugImplementationDependenciesMetadata,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileApiDependenciesMetadata,profileCompileClasspath,profileImplementationDependenciesMetadata,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseApiDependenciesMetadata,releaseCompileClasspath,releaseImplementationDependenciesMetadata,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.window:window-java:1.0.0-beta04=debugAndroidTestCompileClasspath,debugApiDependenciesMetadata,debugCompileClasspath,debugImplementationDependenciesMetadata,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileApiDependenciesMetadata,profileCompileClasspath,profileImplementationDependenciesMetadata,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseApiDependenciesMetadata,releaseCompileClasspath,releaseImplementationDependenciesMetadata,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath +androidx.window:window:1.0.0-beta04=debugAndroidTestCompileClasspath,debugApiDependenciesMetadata,debugCompileClasspath,debugImplementationDependenciesMetadata,debugRuntimeClasspath,debugUnitTestCompileClasspath,debugUnitTestRuntimeClasspath,profileApiDependenciesMetadata,profileCompileClasspath,profileImplementationDependenciesMetadata,profileRuntimeClasspath,profileUnitTestCompileClasspath,profileUnitTestRuntimeClasspath,releaseApiDependenciesMetadata,releaseCompileClasspath,releaseImplementationDependenciesMetadata,releaseRuntimeClasspath,releaseUnitTestCompileClasspath,releaseUnitTestRuntimeClasspath com.android.tools.analytics-library:protos:27.1.3=lintClassPath com.android.tools.analytics-library:shared:27.1.3=lintClassPath com.android.tools.analytics-library:tracker:27.1.3=lintClassPath diff --git a/dev/manual_tests/ios/.gitignore b/dev/manual_tests/ios/.gitignore new file mode 100644 index 0000000000..7a7f9873ad --- /dev/null +++ b/dev/manual_tests/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/dev/manual_tests/ios/Flutter/AppFrameworkInfo.plist b/dev/manual_tests/ios/Flutter/AppFrameworkInfo.plist index f2872cf474..8d4492f977 100644 --- a/dev/manual_tests/ios/Flutter/AppFrameworkInfo.plist +++ b/dev/manual_tests/ios/Flutter/AppFrameworkInfo.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) + en CFBundleExecutable App CFBundleIdentifier diff --git a/dev/manual_tests/ios/Runner.xcodeproj/project.pbxproj b/dev/manual_tests/ios/Runner.xcodeproj/project.pbxproj index e53745fdcd..438ad2e3e7 100644 --- a/dev/manual_tests/ios/Runner.xcodeproj/project.pbxproj +++ b/dev/manual_tests/ios/Runner.xcodeproj/project.pbxproj @@ -90,7 +90,6 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, @@ -99,13 +98,6 @@ path = Runner; sourceTree = ""; }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - ); - name = "Supporting Files"; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -136,7 +128,7 @@ isa = PBXProject; attributes = { LastUpgradeCheck = 1300; - ORGANIZATIONNAME = "The Flutter Authors"; + ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; @@ -145,7 +137,7 @@ }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; + compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -298,8 +290,11 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.manualTests; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.manualTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -407,7 +402,8 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -422,8 +418,11 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.manualTests; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.manualTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -441,8 +440,11 @@ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.example.manualTests; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.manualTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/dev/manual_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/dev/manual_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/dev/manual_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/dev/manual_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/dev/manual_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000..f9b0d7c5ea --- /dev/null +++ b/dev/manual_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/dev/manual_tests/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/dev/manual_tests/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 3db53b6e1f..c87d15a335 100644 --- a/dev/manual_tests/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/dev/manual_tests/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -27,8 +27,6 @@ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - + + - - + + + + IDEDidComputeMac32BitWarning + + + diff --git a/dev/manual_tests/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/dev/manual_tests/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000..f9b0d7c5ea --- /dev/null +++ b/dev/manual_tests/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/dev/manual_tests/ios/Runner/Info.plist b/dev/manual_tests/ios/Runner/Info.plist index 80358121b6..f2184f0713 100644 --- a/dev/manual_tests/ios/Runner/Info.plist +++ b/dev/manual_tests/ios/Runner/Info.plist @@ -4,6 +4,8 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Manual Tests CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -40,6 +42,6 @@ UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance - + diff --git a/dev/manual_tests/linux/.gitignore b/dev/manual_tests/linux/.gitignore new file mode 100644 index 0000000000..d3896c9844 --- /dev/null +++ b/dev/manual_tests/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/dev/manual_tests/linux/CMakeLists.txt b/dev/manual_tests/linux/CMakeLists.txt new file mode 100644 index 0000000000..399b80bb8b --- /dev/null +++ b/dev/manual_tests/linux/CMakeLists.txt @@ -0,0 +1,116 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "manual_tests") +set(APPLICATION_ID "dev.flutter.manual_tests") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/dev/manual_tests/linux/flutter/CMakeLists.txt b/dev/manual_tests/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000000..33fd5801e7 --- /dev/null +++ b/dev/manual_tests/linux/flutter/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/dev/manual_tests/linux/flutter/generated_plugin_registrant.cc b/dev/manual_tests/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000000..e71a16d23d --- /dev/null +++ b/dev/manual_tests/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/dev/manual_tests/linux/flutter/generated_plugin_registrant.h b/dev/manual_tests/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000000..e0f0a47bc0 --- /dev/null +++ b/dev/manual_tests/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/dev/manual_tests/linux/flutter/generated_plugins.cmake b/dev/manual_tests/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000000..51436ae8c9 --- /dev/null +++ b/dev/manual_tests/linux/flutter/generated_plugins.cmake @@ -0,0 +1,15 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) diff --git a/dev/manual_tests/linux/main.cc b/dev/manual_tests/linux/main.cc new file mode 100644 index 0000000000..281a29e16b --- /dev/null +++ b/dev/manual_tests/linux/main.cc @@ -0,0 +1,10 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/dev/manual_tests/linux/my_application.cc b/dev/manual_tests/linux/my_application.cc new file mode 100644 index 0000000000..9fed00806a --- /dev/null +++ b/dev/manual_tests/linux/my_application.cc @@ -0,0 +1,108 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "manual_tests"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "manual_tests"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/dev/manual_tests/linux/my_application.h b/dev/manual_tests/linux/my_application.h new file mode 100644 index 0000000000..8c66ec4854 --- /dev/null +++ b/dev/manual_tests/linux/my_application.h @@ -0,0 +1,22 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/dev/manual_tests/macos/.gitignore b/dev/manual_tests/macos/.gitignore index d2fd377230..746adbb6b9 100644 --- a/dev/manual_tests/macos/.gitignore +++ b/dev/manual_tests/macos/.gitignore @@ -3,4 +3,5 @@ **/Pods/ # Xcode-related +**/dgph **/xcuserdata/ diff --git a/dev/manual_tests/macos/Runner.xcodeproj/project.pbxproj b/dev/manual_tests/macos/Runner.xcodeproj/project.pbxproj index 1bfdc68555..1a4b4e8bac 100644 --- a/dev/manual_tests/macos/Runner.xcodeproj/project.pbxproj +++ b/dev/manual_tests/macos/Runner.xcodeproj/project.pbxproj @@ -182,8 +182,8 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0930; - ORGANIZATIONNAME = "The Flutter Authors"; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { CreatedOnToolsVersion = 9.2; @@ -268,7 +268,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh\ntouch Flutter/ephemeral/tripwire\n"; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/dev/manual_tests/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/dev/manual_tests/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index ebd5303915..ec0c182ee8 100644 --- a/dev/manual_tests/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/dev/manual_tests/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ - - + + - - + + + + diff --git a/dev/manual_tests/macos/Runner/Configs/AppInfo.xcconfig b/dev/manual_tests/macos/Runner/Configs/AppInfo.xcconfig index da7e6ed689..736cdb41d1 100644 --- a/dev/manual_tests/macos/Runner/Configs/AppInfo.xcconfig +++ b/dev/manual_tests/macos/Runner/Configs/AppInfo.xcconfig @@ -8,7 +8,7 @@ PRODUCT_NAME = manual_tests // The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.manualTests +PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.manualTests // The copyright displayed in application information -PRODUCT_COPYRIGHT = Copyright © 2019 com.example. All rights reserved. +PRODUCT_COPYRIGHT = Copyright © 2021 dev.flutter. All rights reserved. diff --git a/dev/manual_tests/web/favicon.png b/dev/manual_tests/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s77>k44ofy`glX=O&z`$AH z5n0T@pr;JNj1^1m%NQ6KBQrxHN+NuHtdjF{^%7I^lT!66atjzhz^1~gBDWwnwIorY zA~z?m*s8)-39P~@uhG~7qCqZhc3d|4;4lG&j~$oK zA@xWG2F9zNE{-7;ld7wO#(qnZWJZzI2E3_xA*Lsx!2?73+ET^w%+}I@67GR zPL~gKB+lnDthp%7_f?t4uW8c8|3WP+WgZ_FE&TA=jOG3EO9#GP7O}Aw)>E_$k#Ij{ zy7GD-^V?e9l7~+mufGc|5hy!fsr=)zztlt_?dh+%eqZG?+EVFvYJGT3%B4l+c?Nxv zA961J%WD)5K5(#z=Uq!-q}j6RjfU+9tC!e#p8CvEH~sU+6WhDDJxnp0o^W94eWCU1 zQd#DyR^MO$Yr>MKOsyrcjGjlI&9nHBnS0EEGw0Y$CX2WHmGZe!`~O@#c5SN5zDu26 zDI4BKt!FtLvCi9OcFDt_gv}BORd*bZl^1SM*A_yFxrSX8ds2x$lS21HT;^ zTCIz7I(nCKmV|Unv7TVUR`#dH$H;AN(TuMbbG%<%3CMZUe|J|QuJuIw1-!H;WNWB?$;ib zdFQ+9g^uhz>as0SX1QKp$Jx0PS=bUhTs~c2!d=hEU?gX@B64~UD6e?B`njxgN@xNA DfL3B_ literal 0 HcmV?d00001 diff --git a/dev/manual_tests/web/icons/Icon-192.png b/dev/manual_tests/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 L>gTe~DWM4f2kRIC literal 0 HcmV?d00001 diff --git a/dev/manual_tests/web/icons/Icon-512.png b/dev/manual_tests/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/dev/manual_tests/web/icons/Icon-maskable-192.png b/dev/manual_tests/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 L>gTe~DWM4f2kRIC literal 0 HcmV?d00001 diff --git a/dev/manual_tests/web/icons/Icon-maskable-512.png b/dev/manual_tests/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/dev/manual_tests/web/index.html b/dev/manual_tests/web/index.html index 6602df01ef..095c2ba12c 100644 --- a/dev/manual_tests/web/index.html +++ b/dev/manual_tests/web/index.html @@ -2,12 +2,107 @@ + + + + + + + + + + + + + + + + manual_tests + - + + diff --git a/dev/manual_tests/web/manifest.json b/dev/manual_tests/web/manifest.json new file mode 100644 index 0000000000..cf80086c6a --- /dev/null +++ b/dev/manual_tests/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "manual_tests", + "short_name": "manual_tests", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/dev/manual_tests/windows/flutter/CMakeLists.txt b/dev/manual_tests/windows/flutter/CMakeLists.txt index 66188df94b..b2e4bd8d65 100644 --- a/dev/manual_tests/windows/flutter/CMakeLists.txt +++ b/dev/manual_tests/windows/flutter/CMakeLists.txt @@ -23,6 +23,7 @@ list(APPEND FLUTTER_LIBRARY_HEADERS "flutter_windows.h" "flutter_messenger.h" "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) diff --git a/dev/manual_tests/windows/runner/CMakeLists.txt b/dev/manual_tests/windows/runner/CMakeLists.txt index 72cf6b86e4..de2d8916b7 100644 --- a/dev/manual_tests/windows/runner/CMakeLists.txt +++ b/dev/manual_tests/windows/runner/CMakeLists.txt @@ -4,7 +4,6 @@ project(runner LANGUAGES CXX) add_executable(${BINARY_NAME} WIN32 "flutter_window.cpp" "main.cpp" - "run_loop.cpp" "utils.cpp" "win32_window.cpp" "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" diff --git a/dev/manual_tests/windows/runner/Runner.rc b/dev/manual_tests/windows/runner/Runner.rc index 96fec5afe0..1f4ecbcebc 100644 --- a/dev/manual_tests/windows/runner/Runner.rc +++ b/dev/manual_tests/windows/runner/Runner.rc @@ -45,6 +45,16 @@ END #endif // APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + ///////////////////////////////////////////////////////////////////////////// // // Version @@ -79,11 +89,11 @@ BEGIN BEGIN BLOCK "040904e4" BEGIN - VALUE "CompanyName", "com.example" "\0" - VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "CompanyName", "dev.flutter" "\0" + VALUE "FileDescription", "manual_tests" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "manual_tests" "\0" - VALUE "LegalCopyright", "Copyright (C) 2021 com.example. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 dev.flutter. All rights reserved." "\0" VALUE "OriginalFilename", "manual_tests.exe" "\0" VALUE "ProductName", "manual_tests" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/dev/manual_tests/windows/runner/flutter_window.cpp b/dev/manual_tests/windows/runner/flutter_window.cpp index 41bbc5e034..9cbd3109c3 100644 --- a/dev/manual_tests/windows/runner/flutter_window.cpp +++ b/dev/manual_tests/windows/runner/flutter_window.cpp @@ -1,12 +1,15 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "flutter_window.h" #include #include "flutter/generated_plugin_registrant.h" -FlutterWindow::FlutterWindow(RunLoop* run_loop, - const flutter::DartProject& project) - : run_loop_(run_loop), project_(project) {} +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} FlutterWindow::~FlutterWindow() {} @@ -26,14 +29,12 @@ bool FlutterWindow::OnCreate() { return false; } RegisterPlugins(flutter_controller_->engine()); - run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); return true; } void FlutterWindow::OnDestroy() { if (flutter_controller_) { - run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); flutter_controller_ = nullptr; } diff --git a/dev/manual_tests/windows/runner/flutter_window.h b/dev/manual_tests/windows/runner/flutter_window.h index 62c11f15c3..bbc5836c01 100644 --- a/dev/manual_tests/windows/runner/flutter_window.h +++ b/dev/manual_tests/windows/runner/flutter_window.h @@ -10,16 +10,13 @@ #include -#include "run_loop.h" #include "win32_window.h" // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { public: - // Creates a new FlutterWindow driven by the |run_loop|, hosting a - // Flutter view running |project|. - explicit FlutterWindow(RunLoop* run_loop, - const flutter::DartProject& project); + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); virtual ~FlutterWindow(); protected: @@ -30,9 +27,6 @@ class FlutterWindow : public Win32Window { LPARAM const lparam) noexcept override; private: - // The run loop driving events for this window. - RunLoop* run_loop_; - // The project to run. flutter::DartProject project_; diff --git a/dev/manual_tests/windows/runner/main.cpp b/dev/manual_tests/windows/runner/main.cpp index 876f83882d..5bd83f75ab 100644 --- a/dev/manual_tests/windows/runner/main.cpp +++ b/dev/manual_tests/windows/runner/main.cpp @@ -1,9 +1,12 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include #include #include #include "flutter_window.h" -#include "run_loop.h" #include "utils.h" int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, @@ -18,8 +21,6 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, // plugins. ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - RunLoop run_loop; - flutter::DartProject project(L"data"); std::vector command_line_arguments = @@ -27,7 +28,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); - FlutterWindow window(&run_loop, project); + FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); if (!window.CreateAndShow(L"manual_tests", origin, size)) { @@ -35,7 +36,11 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, } window.SetQuitOnClose(true); - run_loop.Run(); + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } ::CoUninitialize(); return EXIT_SUCCESS; diff --git a/dev/manual_tests/windows/runner/resource.h b/dev/manual_tests/windows/runner/resource.h index 365297a05d..c245ff19cb 100644 --- a/dev/manual_tests/windows/runner/resource.h +++ b/dev/manual_tests/windows/runner/resource.h @@ -6,12 +6,13 @@ // Microsoft Visual C++ generated include file. // Used by Runner.rc // +#define IDI_APP_ICON 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/dev/manual_tests/windows/runner/resources/app_icon.ico b/dev/manual_tests/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2e4cc829b07d6ce44fb5c1a9ade8070767724e8c GIT binary patch literal 787 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hE{(JaZG%Q-e|yQz{EjrrIztFm3g8aSW-r^=9_oY!OG11NUd_R-XN%aOniKX=N|h z=B#z~zV7s4ec%SsoxB>0Sb|s<&3(kaO^`Q=#VJ8}gRsiUld6&TD|Q|#IC<{eKJ)iy zck)lOot9cww}0;Y+l(2DI{#bsY~#86=SF?Ua@M9LV$;|8rl*>3opSK|hbclTQ+FO% zt;KlcL;2!WOhF&CSUe7Ob5Cd!7hS*@=hGloA;>uEK{NLSHu;bSw;u^iTMn@cE|8oT z+fY^!#%Oq8GiL|uJXZ&w4^Nnqn$<-Glx=1bk?eONqRu&(oJ=+^R8@~$~ zcz&45>LXR7%DC{sN6XI@v(zij`PZC_y6LN%`r(`YM)Qi2*M}Y#&RxQCgzNpMZ@F{0 zL#~D#vfj>U>fIRiL!fs-R>ix#0Na|UW)CDZR&&>vmgXm>?-yu)F2yzdQ2)J}?a2vx zhDje}CM%}@xM=Fnsq*2<<%g#}%o95CKvUf1fcU;eEI}1QjHwTq-fJ|<+&eZ!tU~&) zbAuye!N%OC1Dm;4aMic5m{piD?)#9evf+@mf4l7?zq^j-`q%pY`1SAZ?f9F2P0wXz zNvv-8&hqN}IkhM2;}0H~bA02gkgz>Fj&G|vVkY~qEcsaJjX(M|`xt+|;^IjVEBjQ@9pZBtnx+dH7BF_49zh?F63ZGW4d8;I7cQ@|U!NBia2U<@vygj16 z@>cAU8^mdKI;Vst0Q8z+_5c6? literal 0 HcmV?d00001 diff --git a/dev/manual_tests/windows/runner/run_loop.cpp b/dev/manual_tests/windows/runner/run_loop.cpp deleted file mode 100644 index 2d6636ab6b..0000000000 --- a/dev/manual_tests/windows/runner/run_loop.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "run_loop.h" - -#include - -#include - -RunLoop::RunLoop() {} - -RunLoop::~RunLoop() {} - -void RunLoop::Run() { - bool keep_running = true; - TimePoint next_flutter_event_time = TimePoint::clock::now(); - while (keep_running) { - std::chrono::nanoseconds wait_duration = - std::max(std::chrono::nanoseconds(0), - next_flutter_event_time - TimePoint::clock::now()); - ::MsgWaitForMultipleObjects( - 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), - QS_ALLINPUT); - bool processed_events = false; - MSG message; - // All pending Windows messages must be processed; MsgWaitForMultipleObjects - // won't return again for items left in the queue after PeekMessage. - while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { - processed_events = true; - if (message.message == WM_QUIT) { - keep_running = false; - break; - } - ::TranslateMessage(&message); - ::DispatchMessage(&message); - // Allow Flutter to process messages each time a Windows message is - // processed, to prevent starvation. - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - // If the PeekMessage loop didn't run, process Flutter messages. - if (!processed_events) { - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - } -} - -void RunLoop::RegisterFlutterInstance( - flutter::FlutterEngine* flutter_instance) { - flutter_instances_.insert(flutter_instance); -} - -void RunLoop::UnregisterFlutterInstance( - flutter::FlutterEngine* flutter_instance) { - flutter_instances_.erase(flutter_instance); -} - -RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { - TimePoint next_event_time = TimePoint::max(); - for (auto instance : flutter_instances_) { - std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); - if (wait_duration != std::chrono::nanoseconds::max()) { - next_event_time = - std::min(next_event_time, TimePoint::clock::now() + wait_duration); - } - } - return next_event_time; -} diff --git a/dev/manual_tests/windows/runner/run_loop.h b/dev/manual_tests/windows/runner/run_loop.h deleted file mode 100644 index 441e7b1cd1..0000000000 --- a/dev/manual_tests/windows/runner/run_loop.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef RUNNER_RUN_LOOP_H_ -#define RUNNER_RUN_LOOP_H_ - -#include - -#include -#include - -// A runloop that will service events for Flutter instances as well -// as native messages. -class RunLoop { - public: - RunLoop(); - ~RunLoop(); - - // Prevent copying - RunLoop(RunLoop const&) = delete; - RunLoop& operator=(RunLoop const&) = delete; - - // Runs the run loop until the application quits. - void Run(); - - // Registers the given Flutter instance for event servicing. - void RegisterFlutterInstance( - flutter::FlutterEngine* flutter_instance); - - // Unregisters the given Flutter instance from event servicing. - void UnregisterFlutterInstance( - flutter::FlutterEngine* flutter_instance); - - private: - using TimePoint = std::chrono::steady_clock::time_point; - - // Processes all currently pending messages for registered Flutter instances. - TimePoint ProcessFlutterMessages(); - - std::set flutter_instances_; -}; - -#endif // RUNNER_RUN_LOOP_H_