├── windows ├── flutter │ ├── .template_version │ ├── generated_plugin_registrant.cc │ ├── generated_plugin_registrant.h │ └── GeneratedPlugins.props ├── .vs │ └── Runner │ │ └── v15 │ │ ├── Browse.VC.db │ │ └── Solution.VC.db ├── runner │ ├── resources │ │ └── app_icon.ico │ ├── utils.h │ ├── window_configuration.cpp │ ├── resource.h │ ├── utils.cpp │ ├── window_configuration.h │ ├── runner.exe.manifest │ ├── flutter_window.cpp │ ├── flutter_window.h │ ├── run_loop.h │ ├── main.cpp │ ├── Runner.rc │ ├── run_loop.cpp │ └── win32_window.h ├── scripts │ ├── prepare_dependencies.bat │ └── bundle_assets_and_deps.bat ├── AppConfiguration.props ├── .gitignore ├── FlutterBuild.vcxproj ├── Runner.sln └── Runner.vcxproj.filters ├── ios ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner │ ├── Runner-Bridging-Header.h │ ├── Assets.xcassets │ │ ├── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ └── Info.plist ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist ├── Runner.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme └── .gitignore ├── plugins ├── menubar │ ├── .gitignore │ ├── analysis_options.yaml │ ├── ios │ │ ├── Classes │ │ │ ├── MenubarPlugin.h │ │ │ └── MenubarPlugin.m │ │ ├── .gitignore │ │ └── menubar.podspec │ ├── pubspec.yaml │ ├── linux │ │ ├── CMakeLists.txt │ │ └── include │ │ │ └── menubar │ │ │ └── menubar_plugin.h │ ├── lib │ │ ├── menubar.dart │ │ └── src │ │ │ ├── set_application_menu.dart │ │ │ └── menu_item.dart │ ├── macos │ │ ├── Classes │ │ │ ├── MenubarPlugin.swift │ │ │ └── FLEMenubarPlugin.h │ │ └── menubar.podspec │ └── README.md ├── color_panel │ ├── .gitignore │ ├── analysis_options.yaml │ ├── ios │ │ ├── Classes │ │ │ ├── ColorPanelPlugin.h │ │ │ └── ColorPanelPlugin.m │ │ ├── .gitignore │ │ └── color_panel.podspec │ ├── pubspec.yaml │ ├── linux │ │ ├── CMakeLists.txt │ │ └── include │ │ │ └── color_panel │ │ │ └── color_panel_plugin.h │ ├── README.md │ ├── macos │ │ ├── color_panel.podspec │ │ └── Classes │ │ │ ├── ColorPanelPlugin.swift │ │ │ ├── FLEColorPanelPlugin.h │ │ │ └── FLEColorPanelPlugin.m │ └── lib │ │ └── color_panel.dart ├── file_chooser │ ├── analysis_options.yaml │ ├── windows │ │ ├── .gitignore │ │ ├── PluginInfo.props │ │ ├── file_chooser_plugin.h │ │ └── plugin.vcxproj.filters │ ├── .gitignore │ ├── ios │ │ ├── Classes │ │ │ ├── FileChooserPlugin.h │ │ │ └── FileChooserPlugin.m │ │ ├── .gitignore │ │ └── file_chooser.podspec │ ├── pubspec.yaml │ ├── linux │ │ ├── CMakeLists.txt │ │ └── include │ │ │ └── file_chooser │ │ │ └── file_chooser_plugin.h │ ├── lib │ │ ├── file_chooser.dart │ │ └── src │ │ │ ├── result.dart │ │ │ ├── filter_group.dart │ │ │ ├── utilities.dart │ │ │ └── channel_controller.dart │ ├── macos │ │ ├── file_chooser.podspec │ │ └── Classes │ │ │ ├── FileChooserPlugin.swift │ │ │ ├── FLEFileChooserPlugin.h │ │ │ └── FLEFileChooserPlugin.m │ └── README.md ├── window_size │ ├── .gitignore │ ├── analysis_options.yaml │ ├── windows │ │ ├── .gitignore │ │ ├── PluginInfo.props │ │ ├── window_size_plugin.h │ │ └── plugin.vcxproj.filters │ ├── ios │ │ ├── Classes │ │ │ ├── WindowSizePlugin.h │ │ │ └── WindowSizePlugin.m │ │ ├── .gitignore │ │ └── window_size.podspec │ ├── pubspec.yaml │ ├── linux │ │ ├── CMakeLists.txt │ │ └── include │ │ │ └── window_size │ │ │ └── window_size_plugin.h │ ├── lib │ │ ├── window_size.dart │ │ └── src │ │ │ ├── screen.dart │ │ │ ├── platform_window.dart │ │ │ └── window_size_utils.dart │ ├── README.md │ └── macos │ │ ├── Classes │ │ ├── WindowSizePlugin.swift │ │ └── FLEWindowSizePlugin.h │ │ └── window_size.podspec ├── flutter_plugins │ ├── url_launcher_fde │ │ ├── .gitignore │ │ ├── windows │ │ │ ├── .gitignore │ │ │ ├── PluginInfo.props │ │ │ ├── url_launcher_plugin.h │ │ │ ├── plugin.vcxproj.filters │ │ │ └── url_launcher_plugin.cpp │ │ ├── README.md │ │ ├── pubspec.yaml │ │ ├── linux │ │ │ ├── CMakeLists.txt │ │ │ ├── include │ │ │ │ └── url_launcher_fde │ │ │ │ │ └── url_launcher_plugin.h │ │ │ └── url_launcher_plugin.cc │ │ └── ios │ │ │ └── url_launcher_fde.podspec │ ├── path_provider_fde │ │ ├── windows │ │ │ ├── .gitignore │ │ │ ├── PluginInfo.props │ │ │ ├── path_provider_plugin.h │ │ │ ├── plugin.vcxproj.filters │ │ │ └── path_provider_plugin.cpp │ │ ├── .gitignore │ │ ├── pubspec.yaml │ │ ├── README.md │ │ └── ios │ │ │ └── path_provider_fde.podspec │ └── README.md └── README.md ├── android ├── gradle.properties ├── .gitignore ├── app │ ├── src │ │ ├── main │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ └── ic_launcher.png │ │ │ │ ├── drawable │ │ │ │ │ └── launch_background.xml │ │ │ │ └── values │ │ │ │ │ └── styles.xml │ │ │ ├── java │ │ │ │ └── oboard │ │ │ │ │ └── oboard │ │ │ │ │ └── MainActivity.java │ │ │ └── AndroidManifest.xml │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ └── profile │ │ │ └── AndroidManifest.xml │ └── build.gradle ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── build.gradle ├── lib ├── app_provider.dart ├── board.dart ├── about.dart ├── color_choose.dart └── setting.dart ├── .metadata ├── README.md ├── .gitignore └── pubspec.yaml /windows/flutter/.template_version: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /plugins/menubar/.gitignore: -------------------------------------------------------------------------------- 1 | .packages 2 | .flutter-plugins 3 | pubspec.lock 4 | -------------------------------------------------------------------------------- /plugins/menubar/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: ../../analysis_options.yaml 2 | -------------------------------------------------------------------------------- /plugins/color_panel/.gitignore: -------------------------------------------------------------------------------- 1 | .packages 2 | .flutter-plugins 3 | pubspec.lock 4 | -------------------------------------------------------------------------------- /plugins/color_panel/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: ../../analysis_options.yaml 2 | -------------------------------------------------------------------------------- /plugins/file_chooser/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: ../../analysis_options.yaml 2 | -------------------------------------------------------------------------------- /plugins/window_size/.gitignore: -------------------------------------------------------------------------------- 1 | .packages 2 | .flutter-plugins 3 | pubspec.lock 4 | -------------------------------------------------------------------------------- /plugins/window_size/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: ../../analysis_options.yaml 2 | -------------------------------------------------------------------------------- /plugins/window_size/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ 2 | 3 | # Visual Studio files 4 | *.user 5 | -------------------------------------------------------------------------------- /plugins/file_chooser/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ 2 | 3 | # Visual Studio files 4 | *.user 5 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/.gitignore: -------------------------------------------------------------------------------- 1 | .packages 2 | .flutter-plugins 3 | pubspec.lock 4 | -------------------------------------------------------------------------------- /windows/.vs/Runner/v15/Browse.VC.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/windows/.vs/Runner/v15/Browse.VC.db -------------------------------------------------------------------------------- /plugins/flutter_plugins/path_provider_fde/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ 2 | 3 | # Visual Studio files 4 | *.user 5 | *.suo 6 | .vs -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ 2 | 3 | # Visual Studio files 4 | *.user 5 | *.suo 6 | .vs -------------------------------------------------------------------------------- /windows/.vs/Runner/v15/Solution.VC.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/windows/.vs/Runner/v15/Solution.VC.db -------------------------------------------------------------------------------- /windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /plugins/file_chooser/.gitignore: -------------------------------------------------------------------------------- 1 | .dart_tool 2 | .packages 3 | .flutter-plugins 4 | .flutter-plugins-dependencies 5 | pubspec.lock 6 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /plugins/menubar/ios/Classes/MenubarPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface MenubarPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/path_provider_fde/.gitignore: -------------------------------------------------------------------------------- 1 | .dart_tool 2 | .packages 3 | .flutter-plugins 4 | .flutter-plugins-dependencies 5 | pubspec.lock 6 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /plugins/color_panel/ios/Classes/ColorPanelPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface ColorPanelPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /plugins/file_chooser/ios/Classes/FileChooserPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface FileChooserPlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /plugins/window_size/ios/Classes/WindowSizePlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface WindowSizePlugin : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oboard/board/master/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /windows/scripts/prepare_dependencies.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :: Run flutter tool backend. 4 | set BUILD_MODE=%~1 5 | "%FLUTTER_ROOT%\packages\flutter_tools\bin\tool_backend" windows-x64 %BUILD_MODE% 6 | -------------------------------------------------------------------------------- /plugins/menubar/ios/Classes/MenubarPlugin.m: -------------------------------------------------------------------------------- 1 | #import "MenubarPlugin.h" 2 | 3 | @implementation MenubarPlugin 4 | + (void)registerWithRegistrar:(NSObject*)registrar {} 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /android/app/src/main/java/oboard/oboard/MainActivity.java: -------------------------------------------------------------------------------- 1 | package oboard.oboard; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /plugins/color_panel/ios/Classes/ColorPanelPlugin.m: -------------------------------------------------------------------------------- 1 | #import "ColorPanelPlugin.h" 2 | 3 | @implementation ColorPanelPlugin 4 | + (void)registerWithRegistrar:(NSObject*)registrar {} 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /plugins/window_size/ios/Classes/WindowSizePlugin.m: -------------------------------------------------------------------------------- 1 | #import "WindowSizePlugin.h" 2 | 3 | @implementation WindowSizePlugin 4 | + (void)registerWithRegistrar:(NSObject*)registrar {} 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /plugins/file_chooser/ios/Classes/FileChooserPlugin.m: -------------------------------------------------------------------------------- 1 | #import "FileChooserPlugin.h" 2 | 3 | @implementation FileChooserPlugin 4 | + (void)registerWithRegistrar:(NSObject*)registrar {} 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /windows/AppConfiguration.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | testbed 5 | 6 | 7 | -------------------------------------------------------------------------------- /windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef CONSOLE_UTILS_H_ 2 | #define CONSOLE_UTILS_H_ 3 | 4 | // Creates a console for the process, and redirects stdout and stderr to 5 | // it for both the runner and the Flutter library. 6 | void CreateAndAttachConsole(); 7 | 8 | #endif // CONSOLE_UTILS_H_ 9 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/app_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class AppInfoProvider with ChangeNotifier { 4 | String _themeColor = ''; 5 | 6 | String get themeColor => _themeColor; 7 | 8 | setTheme(String themeColor) { 9 | _themeColor = themeColor; 10 | notifyListeners(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /windows/runner/window_configuration.cpp: -------------------------------------------------------------------------------- 1 | #include "window_configuration.h" 2 | 3 | const wchar_t* kFlutterWindowTitle = L"testbed"; 4 | const unsigned int kFlutterWindowOriginX = 10; 5 | const unsigned int kFlutterWindowOriginY = 10; 6 | const unsigned int kFlutterWindowWidth = 1280; 7 | const unsigned int kFlutterWindowHeight = 720; 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 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: 5f21edf8b66e31a39133177319414395cc5b5f48 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | #include "generated_plugin_registrant.h" 6 | 7 | #include 8 | 9 | void RegisterPlugins(flutter::PluginRegistry* registry) { 10 | WindowSizePluginRegisterWithRegistrar( 11 | registry->GetRegistrarForPlugin("WindowSizePlugin")); 12 | } 13 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 6 | #define GENERATED_PLUGIN_REGISTRANT_ 7 | 8 | #include 9 | 10 | // Registers Flutter plugins. 11 | void RegisterPlugins(flutter::PluginRegistry* registry); 12 | 13 | #endif // GENERATED_PLUGIN_REGISTRANT_ 14 | -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/README.md: -------------------------------------------------------------------------------- 1 | # url_launcher_fde 2 | 3 | Prototype desktop implementations of 4 | [url_launcher](https://pub.dev/packages/url_launcher) 5 | 6 | See [the main flutter_plugins README](../README.md) for general information about what 7 | this plugin is and how to use it. 8 | 9 | ## Supported Platforms 10 | 11 | - [x] Windows 12 | - [x] Linux 13 | 14 | ## Caveats 15 | 16 | Only `launch` is implemented, so the common pattern of calling `launch` only if 17 | `canLaunch` returns true will not work. 18 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plugins/menubar/ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | -------------------------------------------------------------------------------- /plugins/color_panel/ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | -------------------------------------------------------------------------------- /plugins/file_chooser/ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | -------------------------------------------------------------------------------- /plugins/window_size/ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | -------------------------------------------------------------------------------- /plugins/file_chooser/windows/PluginInfo.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | file_chooser 6 | 7 | 8 | 9 | 10 | 11 | $(FlutterPluginName) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /plugins/window_size/windows/PluginInfo.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | window_size 6 | 7 | 8 | 9 | 10 | 11 | $(FlutterPluginName) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/path_provider_fde/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: path_provider_fde 2 | description: Temporary desktop implmentations of path_provider from flutter/plugins 3 | version: 0.0.1 4 | 5 | # Do not publish this plugin. See: 6 | # https://github.com/google/flutter-desktop-embedding/blob/master/plugins/README.md#using-plugins 7 | publish_to: none 8 | 9 | flutter: 10 | plugin: 11 | platforms: 12 | windows: 13 | pluginClass: PathProviderPlugin 14 | 15 | environment: 16 | sdk: ">=2.1.0 <3.0.0" 17 | 18 | dependencies: 19 | flutter: 20 | sdk: flutter 21 | -------------------------------------------------------------------------------- /windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugins/color_panel/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: color_panel 2 | description: Provides access to the platform's native color picker. 3 | version: 0.1.0 4 | 5 | # Do not publish this plugin. See: 6 | # https://github.com/google/flutter-desktop-embedding/blob/master/plugins/README.md#using-plugins 7 | publish_to: none 8 | 9 | flutter: 10 | plugin: 11 | platforms: 12 | linux: 13 | pluginClass: ColorPanelPlugin 14 | macos: 15 | pluginClass: ColorPanelPlugin 16 | 17 | environment: 18 | sdk: ">=2.1.0 <3.0.0" 19 | 20 | dependencies: 21 | flutter: 22 | sdk: flutter 23 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/path_provider_fde/windows/PluginInfo.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | path_provider 6 | 7 | 8 | 9 | 10 | 11 | $(FlutterPluginName) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/windows/PluginInfo.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | url_launcher_plugin 6 | 7 | 8 | 9 | 10 | 11 | $(FlutterPluginName) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /plugins/menubar/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: menubar 2 | description: Provides the ability to add native menubar items with Dart callbacks. 3 | version: 0.1.0 4 | 5 | # Do not publish this plugin. See: 6 | # https://github.com/google/flutter-desktop-embedding/blob/master/plugins/README.md#using-plugins 7 | publish_to: none 8 | 9 | flutter: 10 | plugin: 11 | platforms: 12 | linux: 13 | pluginClass: MenubarPlugin 14 | macos: 15 | pluginClass: MenubarPlugin 16 | 17 | environment: 18 | sdk: ">=2.1.0 <3.0.0" 19 | 20 | dependencies: 21 | flutter: 22 | sdk: flutter 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # oboard 2 | 3 | A Canvas application. 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 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: url_launcher_fde 2 | description: Temporary desktop implmentations of url_launcher from flutter/plugins 3 | version: 0.1.0 4 | 5 | # Do not publish this plugin. See: 6 | # https://github.com/google/flutter-desktop-embedding/blob/master/plugins/README.md#using-plugins 7 | publish_to: none 8 | 9 | flutter: 10 | plugin: 11 | platforms: 12 | linux: 13 | pluginClass: UrlLauncherPlugin 14 | windows: 15 | pluginClass: UrlLauncherPlugin 16 | 17 | environment: 18 | sdk: ">=2.1.0 <3.0.0" 19 | 20 | dependencies: 21 | flutter: 22 | sdk: flutter 23 | -------------------------------------------------------------------------------- /plugins/file_chooser/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: file_chooser 2 | description: Displays native platform open and save panels. 3 | version: 0.2.0 4 | 5 | # Do not publish this plugin. See: 6 | # https://github.com/google/flutter-desktop-embedding/blob/master/plugins/README.md#using-plugins 7 | publish_to: none 8 | 9 | flutter: 10 | plugin: 11 | platforms: 12 | linux: 13 | pluginClass: FileChooserPlugin 14 | macos: 15 | pluginClass: FileChooserPlugin 16 | windows: 17 | pluginClass: FileChooserPlugin 18 | 19 | environment: 20 | sdk: ">=2.1.0 <3.0.0" 21 | 22 | dependencies: 23 | flutter: 24 | sdk: flutter 25 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/path_provider_fde/README.md: -------------------------------------------------------------------------------- 1 | # path_provider_fde 2 | 3 | Prototype desktop implementations of 4 | [path_provider](https://pub.dev/packages/path_provider) 5 | 6 | See [the main flutter_plugins README](../README.md) for general information about what 7 | this plugin is and how to use it. 8 | 9 | ## Supported Platforms 10 | 11 | - [x] Windows 12 | 13 | macOS and Linux are already supported by `path_provider`. 14 | 15 | ## Caveats 16 | 17 | ### Windows 18 | 19 | The paths returned by this plugin may change in the future. Most notably, 20 | `getApplicationSupportDirectory` will likely return a different path in the 21 | future. 22 | -------------------------------------------------------------------------------- /plugins/window_size/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: window_size 2 | description: Allows resizing and repositioning the window containing Flutter. 3 | version: 0.1.0 4 | 5 | # Do not publish this plugin. See: 6 | # https://github.com/google/flutter-desktop-embedding/blob/master/plugins/README.md#using-plugins 7 | publish_to: none 8 | 9 | flutter: 10 | plugin: 11 | platforms: 12 | linux: 13 | pluginClass: WindowSizePlugin 14 | macos: 15 | pluginClass: WindowSizePlugin 16 | windows: 17 | pluginClass: WindowSizePlugin 18 | 19 | environment: 20 | sdk: ">=2.1.0 <3.0.0" 21 | 22 | dependencies: 23 | flutter: 24 | sdk: flutter 25 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /windows/flutter/GeneratedPlugins.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | flutter\ephemeral\.plugin_symlinks\window_size\windows;%(AdditionalIncludeDirectories) 9 | 10 | 11 | window_size_plugin.lib;%(AdditionalDependencies) 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Flutter Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | include ':app' 6 | 7 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 8 | def properties = new Properties() 9 | 10 | assert localPropertiesFile.exists() 11 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 12 | 13 | def flutterSdkPath = properties.getProperty("flutter.sdk") 14 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 15 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 16 | -------------------------------------------------------------------------------- /plugins/menubar/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(PROJECT_NAME "menubar") 3 | project(${PROJECT_NAME} LANGUAGES CXX) 4 | 5 | set(PLUGIN_NAME "${PROJECT_NAME}_plugin") 6 | 7 | add_library(${PLUGIN_NAME} SHARED 8 | "${PLUGIN_NAME}.cc" 9 | ) 10 | apply_standard_settings(${PLUGIN_NAME}) 11 | set_target_properties(${PLUGIN_NAME} PROPERTIES 12 | CXX_VISIBILITY_PRESET hidden) 13 | target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) 14 | target_include_directories(${PLUGIN_NAME} INTERFACE 15 | "${CMAKE_CURRENT_SOURCE_DIR}/include") 16 | target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) 17 | target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) 18 | -------------------------------------------------------------------------------- /plugins/color_panel/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(PROJECT_NAME "color_panel") 3 | project(${PROJECT_NAME} LANGUAGES CXX) 4 | 5 | set(PLUGIN_NAME "${PROJECT_NAME}_plugin") 6 | 7 | add_library(${PLUGIN_NAME} SHARED 8 | "${PLUGIN_NAME}.cc" 9 | ) 10 | apply_standard_settings(${PLUGIN_NAME}) 11 | set_target_properties(${PLUGIN_NAME} PROPERTIES 12 | CXX_VISIBILITY_PRESET hidden) 13 | target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) 14 | target_include_directories(${PLUGIN_NAME} INTERFACE 15 | "${CMAKE_CURRENT_SOURCE_DIR}/include") 16 | target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) 17 | target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) 18 | -------------------------------------------------------------------------------- /plugins/file_chooser/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(PROJECT_NAME "file_chooser") 3 | project(${PROJECT_NAME} LANGUAGES CXX) 4 | 5 | set(PLUGIN_NAME "${PROJECT_NAME}_plugin") 6 | 7 | add_library(${PLUGIN_NAME} SHARED 8 | "${PLUGIN_NAME}.cc" 9 | ) 10 | apply_standard_settings(${PLUGIN_NAME}) 11 | set_target_properties(${PLUGIN_NAME} PROPERTIES 12 | CXX_VISIBILITY_PRESET hidden) 13 | target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) 14 | target_include_directories(${PLUGIN_NAME} INTERFACE 15 | "${CMAKE_CURRENT_SOURCE_DIR}/include") 16 | target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) 17 | target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) 18 | -------------------------------------------------------------------------------- /plugins/window_size/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(PROJECT_NAME "window_size") 3 | project(${PROJECT_NAME} LANGUAGES CXX) 4 | 5 | set(PLUGIN_NAME "${PROJECT_NAME}_plugin") 6 | 7 | add_library(${PLUGIN_NAME} SHARED 8 | "${PLUGIN_NAME}.cc" 9 | ) 10 | apply_standard_settings(${PLUGIN_NAME}) 11 | set_target_properties(${PLUGIN_NAME} PROPERTIES 12 | CXX_VISIBILITY_PRESET hidden) 13 | target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) 14 | target_include_directories(${PLUGIN_NAME} INTERFACE 15 | "${CMAKE_CURRENT_SOURCE_DIR}/include") 16 | target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) 17 | target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) 18 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(PROJECT_NAME "url_launcher_fde") 3 | project(${PROJECT_NAME} LANGUAGES CXX) 4 | 5 | set(PLUGIN_NAME "${PROJECT_NAME}_plugin") 6 | 7 | add_library(${PLUGIN_NAME} SHARED 8 | "url_launcher_plugin.cc" 9 | ) 10 | apply_standard_settings(${PLUGIN_NAME}) 11 | set_target_properties(${PLUGIN_NAME} PROPERTIES 12 | CXX_VISIBILITY_PRESET hidden) 13 | target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) 14 | target_include_directories(${PLUGIN_NAME} INTERFACE 15 | "${CMAKE_CURRENT_SOURCE_DIR}/include") 16 | target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) 17 | target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) 18 | -------------------------------------------------------------------------------- /plugins/menubar/lib/menubar.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export 'src/menu_item.dart'; 15 | export 'src/set_application_menu.dart'; 16 | -------------------------------------------------------------------------------- /plugins/color_panel/README.md: -------------------------------------------------------------------------------- 1 | # color_panel 2 | 3 | This plugin provides access to a native color picker. 4 | 5 | It exists primarily to serve as an example of using native UI in a desktop plugin, 6 | and may be removed at some point in the future. 7 | 8 | ## Supported Platforms 9 | 10 | - [x] macOS 11 | - [ ] [Windows](https://github.com/google/flutter-desktop-embedding/issues/105) 12 | - [x] Linux 13 | 14 | ## Use 15 | 16 | See [the plugin README](../README.md) for general instructions on using FDE plugins. 17 | 18 | ### Linux 19 | 20 | You will need to update `main.cc` to include [the GTK initialization and runloop changes 21 | shown in the `testbed` 22 | example](https://github.com/google/flutter-desktop-embedding/blob/master/testbed/linux/main.cc#L81-L91). 23 | -------------------------------------------------------------------------------- /plugins/file_chooser/lib/file_chooser.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export 'src/filter_group.dart'; 15 | export 'src/result.dart'; 16 | export 'src/utilities.dart'; 17 | -------------------------------------------------------------------------------- /plugins/window_size/lib/window_size.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | export 'src/platform_window.dart'; 15 | export 'src/screen.dart'; 16 | export 'src/window_size_utils.dart'; 17 | -------------------------------------------------------------------------------- /windows/runner/window_configuration.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOW_CONFIGURATION_ 2 | #define WINDOW_CONFIGURATION_ 3 | 4 | // This is a temporary approach to isolate changes that people are likely to 5 | // make to main.cpp, where the APIs are still in flux. This will reduce the 6 | // need to resolve conflicts or re-create changes slightly differently every 7 | // time the Windows Flutter API surface changes. 8 | // 9 | // Longer term there should be simpler configuration options for common 10 | // customizations like this, without requiring native code changes. 11 | 12 | extern const wchar_t* kFlutterWindowTitle; 13 | extern const unsigned int kFlutterWindowOriginX; 14 | extern const unsigned int kFlutterWindowOriginY; 15 | extern const unsigned int kFlutterWindowWidth; 16 | extern const unsigned int kFlutterWindowHeight; 17 | 18 | #endif // WINDOW_CONFIGURATION_ 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Exceptions to above rules. 43 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 44 | -------------------------------------------------------------------------------- /plugins/file_chooser/macos/file_chooser.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'file_chooser' 6 | s.version = '0.0.2' 7 | s.summary = 'Displays macOS open and save panels.' 8 | s.description = <<-DESC 9 | Displays macOS open and save panels. 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/file_chooser' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.dependency 'FlutterMacOS' 17 | 18 | s.platform = :osx 19 | s.osx.deployment_target = '10.11' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /plugins/color_panel/macos/color_panel.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'color_panel' 6 | s.version = '0.0.2' 7 | s.summary = 'Provides access to the macOS color picker.' 8 | s.description = <<-DESC 9 | Provides access to the macOS color picker. 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/color_panel' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.dependency 'FlutterMacOS' 17 | 18 | s.platform = :osx 19 | s.osx.deployment_target = '10.11' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /plugins/menubar/ios/menubar.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'menubar' 6 | s.version = '0.0.1' 7 | s.summary = 'No-op implementation of menubar desktop plugin to avoid build issues on iOS' 8 | s.description = <<-DESC 9 | temp fake menubar plugin 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/color_panel' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.public_header_files = 'Classes/**/*.h' 17 | s.dependency 'Flutter' 18 | 19 | s.ios.deployment_target = '8.0' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /plugins/menubar/macos/Classes/MenubarPlugin.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import FlutterMacOS 16 | import Foundation 17 | 18 | public class MenubarPlugin: NSObject, FlutterPlugin { 19 | public static func register(with registrar: FlutterPluginRegistrar) { 20 | FLEMenubarPlugin.register(with: registrar) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugins/menubar/macos/menubar.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'menubar' 6 | s.version = '0.0.2' 7 | s.summary = 'Provides the ability to add menubar items with Dart callbacks.' 8 | s.description = <<-DESC 9 | Provides the ability to add menubar items with Dart callbacks. 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/menubar' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.dependency 'FlutterMacOS' 17 | 18 | s.platform = :osx 19 | s.osx.deployment_target = '10.11' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /plugins/window_size/README.md: -------------------------------------------------------------------------------- 1 | # window_size 2 | 3 | This plugin allows resizing and repositioning the window containing the Flutter 4 | content, as well as querying screen information. 5 | 6 | This is a prototype, and in the long term will likely be replaced by functionality 7 | within the Flutter framework itself. The API will likely change significantly. 8 | 9 | **Note**: Further related functionality, such as window minimization and maximization, 10 | will likely be added to this plugin in the future. PRs are welcome to add functionality 11 | of that kind to any or all platforms. 12 | 13 | ## Supported Platforms 14 | 15 | - [x] macOS 16 | - [x] Windows 17 | - [x] Linux 18 | 19 | Not all operations have been implemented on all platforms, but the core functionality 20 | of resizing and repositioning is available for all three. 21 | 22 | ## Use 23 | 24 | See [the plugin README](../README.md) for general instructions on using FDE plugins. 25 | -------------------------------------------------------------------------------- /plugins/color_panel/ios/color_panel.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'color_panel' 6 | s.version = '0.0.1' 7 | s.summary = 'No-op implementation of color_panel desktop plugin to avoid build issues on iOS' 8 | s.description = <<-DESC 9 | temp fake color_panel plugin 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/color_panel' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.public_header_files = 'Classes/**/*.h' 17 | s.dependency 'Flutter' 18 | 19 | s.ios.deployment_target = '8.0' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /plugins/window_size/ios/window_size.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'window_size' 6 | s.version = '0.0.1' 7 | s.summary = 'No-op implementation of window_size desktop plugin to avoid build issues on iOS' 8 | s.description = <<-DESC 9 | temp fake window_size plugin 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/color_panel' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.public_header_files = 'Classes/**/*.h' 17 | s.dependency 'Flutter' 18 | 19 | s.ios.deployment_target = '8.0' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /plugins/color_panel/macos/Classes/ColorPanelPlugin.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import FlutterMacOS 16 | import Foundation 17 | 18 | public class ColorPanelPlugin: NSObject, FlutterPlugin { 19 | public static func register(with registrar: FlutterPluginRegistrar) { 20 | FLEColorPanelPlugin.register(with: registrar) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugins/file_chooser/ios/file_chooser.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'file_chooser' 6 | s.version = '0.0.1' 7 | s.summary = 'No-op implementation of file_chooser desktop plugin to avoid build issues on iOS' 8 | s.description = <<-DESC 9 | temp fake file_chooser plugin 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/file_chooser' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.public_header_files = 'Classes/**/*.h' 17 | s.dependency 'Flutter' 18 | 19 | s.ios.deployment_target = '8.0' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /plugins/window_size/macos/Classes/WindowSizePlugin.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import FlutterMacOS 16 | import Foundation 17 | 18 | public class WindowSizePlugin: NSObject, FlutterPlugin { 19 | public static func register(with registrar: FlutterPluginRegistrar) { 20 | FLEWindowSizePlugin.register(with: registrar) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugins/file_chooser/macos/Classes/FileChooserPlugin.swift: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | import FlutterMacOS 16 | import Foundation 17 | 18 | public class FileChooserPlugin: NSObject, FlutterPlugin { 19 | public static func register(with registrar: FlutterPluginRegistrar) { 20 | FLEFileChooserPlugin.register(with: registrar) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugins/window_size/macos/window_size.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'window_size' 6 | s.version = '0.0.2' 7 | s.summary = 'Allows resizing and repositioning the window containing Flutter.' 8 | s.description = <<-DESC 9 | Allows resizing and repositioning the window containing Flutter. 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/window_size' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.dependency 'FlutterMacOS' 17 | 18 | s.platform = :osx 19 | s.osx.deployment_target = '10.11' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/ios/url_launcher_fde.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'url_launcher_fde' 6 | s.version = '0.0.1' 7 | s.summary = 'No-op implementation of url_launcher_fde desktop plugin to avoid build issues on iOS' 8 | s.description = <<-DESC 9 | temp fake url_launcher_fde plugin 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/url_launcher_fde' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.public_header_files = 'Classes/**/*.h' 17 | s.dependency 'Flutter' 18 | 19 | s.ios.deployment_target = '8.0' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/path_provider_fde/ios/path_provider_fde.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 3 | # 4 | Pod::Spec.new do |s| 5 | s.name = 'path_provider_fde' 6 | s.version = '0.0.1' 7 | s.summary = 'No-op implementation of path_provider_fde desktop plugin to avoid build issues on iOS' 8 | s.description = <<-DESC 9 | temp fake path_provider_fde plugin 10 | DESC 11 | s.homepage = 'https://github.com/google/flutter-desktop-embedding/tree/master/plugins/path_provider_fde' 12 | s.license = { :file => '../LICENSE' } 13 | s.author = { 'Flutter Desktop Embedding Developers' => 'flutter-desktop-embedding-dev@googlegroups.com' } 14 | s.source = { :path => '.' } 15 | s.source_files = 'Classes/**/*' 16 | s.public_header_files = 'Classes/**/*.h' 17 | s.dependency 'Flutter' 18 | 19 | s.ios.deployment_target = '8.0' 20 | end 21 | 22 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include "flutter/generated_plugin_registrant.h" 4 | 5 | FlutterWindow::FlutterWindow(RunLoop* run_loop, 6 | const flutter::DartProject& project) 7 | : run_loop_(run_loop), project_(project) {} 8 | 9 | FlutterWindow::~FlutterWindow() {} 10 | 11 | void FlutterWindow::OnCreate() { 12 | Win32Window::OnCreate(); 13 | 14 | // The size here is arbitrary since SetChildContent will resize it. 15 | flutter_controller_ = 16 | std::make_unique(100, 100, project_); 17 | RegisterPlugins(flutter_controller_.get()); 18 | run_loop_->RegisterFlutterInstance(flutter_controller_.get()); 19 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 20 | } 21 | 22 | void FlutterWindow::OnDestroy() { 23 | if (flutter_controller_) { 24 | run_loop_->UnregisterFlutterInstance(flutter_controller_.get()); 25 | flutter_controller_ = nullptr; 26 | } 27 | 28 | Win32Window::OnDestroy(); 29 | } 30 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /plugins/color_panel/macos/Classes/FLEColorPanelPlugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | 17 | #import 18 | 19 | /** 20 | * A FlutterPlugin to manage macOS's shared NSColorPanel singleton. 21 | * Responsible for managing the panel's display state and sending selected color data to Flutter. 22 | */ 23 | @interface FLEColorPanelPlugin : NSObject 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /plugins/window_size/macos/Classes/FLEWindowSizePlugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | 17 | #import 18 | 19 | /** 20 | * A FlutterPlugin to manage macOS's shared NSColorPanel singleton. 21 | * Responsible for managing the panel's display state and sending selected color data to Flutter. 22 | */ 23 | @interface FLEWindowSizePlugin : NSObject 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { url 'https://maven.aliyun.com/repository/google' } 4 | maven { url 'https://maven.aliyun.com/repository/jcenter' } 5 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } 6 | maven { url "http://download.flutter.io" } 7 | } 8 | 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.5.0' 11 | } 12 | } 13 | 14 | allprojects{ 15 | repositories { 16 | maven { url 'https://maven.aliyun.com/repository/google' } 17 | maven { url 'https://maven.aliyun.com/repository/jcenter' } 18 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } 19 | maven { url "http://download.flutter.io" } 20 | } 21 | } 22 | 23 | rootProject.buildDir = '../build' 24 | subprojects { 25 | project.buildDir = "${rootProject.buildDir}/${project.name}" 26 | } 27 | subprojects { 28 | project.evaluationDependsOn(':app') 29 | } 30 | 31 | task clean(type: Delete) { 32 | delete rootProject.buildDir 33 | } 34 | -------------------------------------------------------------------------------- /plugins/menubar/lib/src/set_application_menu.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import 'dart:async'; 15 | 16 | import 'menu_channel.dart'; 17 | import 'menu_item.dart'; 18 | 19 | /// Sets the application menu for the app based on the [menuSpec]. 20 | /// 21 | /// Adjacent [MenuDivider]s will be coalesced, leading and/or trailing 22 | /// [MenuDivider]s will be removed. 23 | Future setApplicationMenu(List menuSpec) async { 24 | await MenuChannel.instance.setMenu(menuSpec); 25 | } 26 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_WINDOW_H_ 2 | #define FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "run_loop.h" 8 | #include "win32_window.h" 9 | 10 | #include 11 | 12 | // A window that does nothing but host a Flutter view. 13 | class FlutterWindow : public Win32Window { 14 | public: 15 | // Creates a new FlutterWindow driven by the |run_loop|, hosting a 16 | // Flutter view running |project|. 17 | explicit FlutterWindow(RunLoop* run_loop, 18 | const flutter::DartProject& project); 19 | virtual ~FlutterWindow(); 20 | 21 | protected: 22 | // Win32Window: 23 | void OnCreate() override; 24 | void OnDestroy() override; 25 | 26 | private: 27 | // The run loop driving events for this window. 28 | RunLoop* run_loop_; 29 | 30 | // The project to run. 31 | flutter::DartProject project_; 32 | 33 | // The Flutter instance hosted by this window. 34 | std::unique_ptr flutter_controller_; 35 | }; 36 | 37 | #endif // FLUTTER_WINDOW_H_ 38 | -------------------------------------------------------------------------------- /plugins/file_chooser/macos/Classes/FLEFileChooserPlugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | 17 | #import 18 | 19 | /** 20 | * A FlutterPlugin to handle file choosing affordances. Owned by the FlutterViewController. 21 | * Responsible for creating and showing instances of NSSavePanel or NSOpenPanel and sending 22 | * selected file paths to flutter clients, via system channels. 23 | */ 24 | @interface FLEFileChooserPlugin : NSObject 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /plugins/file_chooser/lib/src/result.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// The result of a file chooser operation. 16 | class FileChooserResult { 17 | /// Creates a new result object with the given state and paths. 18 | const FileChooserResult({this.paths, this.canceled}); 19 | 20 | /// Whether or not the file chooser operation was canceled by the user. 21 | final bool canceled; 22 | 23 | /// A list of file paths chosen by the user. If [canceled] is true, the list 24 | /// should always be empty. 25 | final List paths; 26 | } 27 | -------------------------------------------------------------------------------- /plugins/menubar/macos/Classes/FLEMenubarPlugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import 16 | 17 | #import 18 | 19 | /** 20 | * A Flutter plugin to control the native menu bar. 21 | */ 22 | @interface FLEMenubarPlugin : NSObject 23 | 24 | /** 25 | * The menu item that Flutter-provided menus should be inserted after. If unset, Flutter-provided 26 | * menus will be inserted after the application menu (i.e., starting at index 1). 27 | */ 28 | @property(nonatomic) NSMenuItem *insertAfterMenuItem; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /windows/runner/run_loop.h: -------------------------------------------------------------------------------- 1 | #ifndef RUN_LOOP_H_ 2 | #define RUN_LOOP_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | // A runloop that will service events for Flutter instances as well 10 | // as native messages. 11 | class RunLoop { 12 | public: 13 | RunLoop(); 14 | ~RunLoop(); 15 | 16 | // Prevent copying 17 | RunLoop(RunLoop const&) = delete; 18 | RunLoop& operator=(RunLoop const&) = delete; 19 | 20 | // Runs the run loop until the application quits. 21 | void Run(); 22 | 23 | // Registers the given Flutter instance for event servicing. 24 | void RegisterFlutterInstance( 25 | flutter::FlutterViewController* flutter_instance); 26 | 27 | // Unregisters the given Flutter instance from event servicing. 28 | void UnregisterFlutterInstance( 29 | flutter::FlutterViewController* flutter_instance); 30 | 31 | private: 32 | using TimePoint = std::chrono::steady_clock::time_point; 33 | 34 | // Processes all currently pending messages for registered Flutter instances. 35 | TimePoint ProcessFlutterMessages(); 36 | 37 | std::set flutter_instances_; 38 | }; 39 | 40 | #endif // RUN_LOOP_H_ 41 | -------------------------------------------------------------------------------- /plugins/file_chooser/README.md: -------------------------------------------------------------------------------- 1 | # file_chooser 2 | 3 | This plugin provides access to a native file chooser for Open and Save operations. 4 | 5 | This is a prototype, and in the long term will either be replaced by functionality 6 | within the Flutter framework itself, or a published plugin (likely part of 7 | flutter/plugins). Either way, the API may change significantly. 8 | 9 | ## Supported Platforms 10 | 11 | - [x] macOS 12 | - [x] Windows 13 | - [x] Linux 14 | 15 | ## Use 16 | 17 | See [the plugin README](../README.md) for general instructions on using FDE plugins. 18 | 19 | ### macOS 20 | 21 | You will need to [add an 22 | entitlement](https://github.com/google/flutter-desktop-embedding/blob/master/macOS-Security.md) 23 | for either read-only access: 24 | ``` 25 | com.apple.security.files.user-selected.read-only 26 | 27 | ``` 28 | or read/write access: 29 | ``` 30 | com.apple.security.files.user-selected.read-write 31 | 32 | ``` 33 | depending on your use case. 34 | 35 | ### Linux 36 | 37 | You will need to update `main.cc` to include [the GTK initialization and runloop changes 38 | shown in the `testbed` 39 | example](https://github.com/google/flutter-desktop-embedding/blob/master/testbed/linux/main.cc#L81-L91). 40 | -------------------------------------------------------------------------------- /plugins/file_chooser/lib/src/filter_group.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /// A set of allowed file types. 16 | class FileTypeFilterGroup { 17 | /// Creates a new group with the given label and file extensions. 18 | const FileTypeFilterGroup({this.label, this.fileExtensions}); 19 | 20 | /// The label for the grouping. On platforms that support selectable groups, 21 | /// this will be visible to the user for selecting the group. 22 | final String label; 23 | 24 | /// A list of allowed file extensions. E.g., ['png', 'jpg', 'jpeg', 'gif']. 25 | /// 26 | /// A null or empty list indicates any type is allowed. 27 | final List fileExtensions; 28 | } 29 | -------------------------------------------------------------------------------- /plugins/window_size/lib/src/screen.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import 'dart:ui'; 15 | 16 | /// Represents a screen, containing information about its size, position, and 17 | /// properties. 18 | class Screen { 19 | /// Create a new screen. 20 | Screen(this.frame, this.visibleFrame, this.scaleFactor); 21 | 22 | /// The frame of the screen, in screen coordinates. 23 | final Rect frame; 24 | 25 | /// The portion of the screen's frame that is available for use by application 26 | /// windows. E.g., on macOS, this excludes the menu bar. 27 | final Rect visibleFrame; 28 | 29 | /// The number of pixels per screen coordinate for this screen. 30 | final double scaleFactor; 31 | } 32 | -------------------------------------------------------------------------------- /windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "run_loop.h" 7 | #include "utils.h" 8 | #include "window_configuration.h" 9 | 10 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 11 | _In_ wchar_t *command_line, _In_ int show_command) { 12 | // Attach to console when present (e.g., 'flutter run') or create a 13 | // new console when running with a debugger. 14 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 15 | CreateAndAttachConsole(); 16 | } 17 | 18 | // Initialize COM, so that it is available for use in the library and/or 19 | // plugins. 20 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 21 | 22 | RunLoop run_loop; 23 | 24 | flutter::DartProject project(L"data"); 25 | FlutterWindow window(&run_loop, project); 26 | Win32Window::Point origin(kFlutterWindowOriginX, kFlutterWindowOriginY); 27 | Win32Window::Size size(kFlutterWindowWidth, kFlutterWindowHeight); 28 | if (!window.CreateAndShow(kFlutterWindowTitle, origin, size)) { 29 | return EXIT_FAILURE; 30 | } 31 | window.SetQuitOnClose(true); 32 | 33 | run_loop.Run(); 34 | 35 | ::CoUninitialize(); 36 | return EXIT_SUCCESS; 37 | } 38 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/path_provider_fde/windows/path_provider_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef PLUGINS_PATH_PROVIDER_PLUGIN_WINDOWS_H_ 15 | #define PLUGINS_PATH_PROVIDER_PLUGIN_WINDOWS_H_ 16 | 17 | #include 18 | 19 | #ifdef FLUTTER_PLUGIN_IMPL 20 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) 21 | #else 22 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) 23 | #endif 24 | 25 | #if defined(__cplusplus) 26 | extern "C" { 27 | #endif 28 | 29 | FLUTTER_PLUGIN_EXPORT void PathProviderPluginRegisterWithRegistrar( 30 | FlutterDesktopPluginRegistrarRef registrar); 31 | 32 | #if defined(__cplusplus) 33 | } // extern "C" 34 | #endif 35 | 36 | #endif // PLUGINS_PATH_PROVIDER_PLUGIN_WINDOWS_H_ 37 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/windows/url_launcher_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef PLUGINS_URL_LAUNCHER_PLUGIN_WINDOWS_H_ 15 | #define PLUGINS_URL_LAUNCHER_PLUGIN_WINDOWS_H_ 16 | 17 | #include 18 | 19 | #ifdef FLUTTER_PLUGIN_IMPL 20 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) 21 | #else 22 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) 23 | #endif 24 | 25 | #if defined(__cplusplus) 26 | extern "C" { 27 | #endif 28 | 29 | FLUTTER_PLUGIN_EXPORT void UrlLauncherPluginRegisterWithRegistrar( 30 | FlutterDesktopPluginRegistrarRef registrar); 31 | 32 | #if defined(__cplusplus) 33 | } // extern "C" 34 | #endif 35 | 36 | #endif // PLUGINS_EXAMPLE_EXAMPLE_PLUGIN_WINDOWS_H_ 37 | -------------------------------------------------------------------------------- /plugins/window_size/lib/src/platform_window.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import 'dart:ui'; 15 | 16 | import 'screen.dart'; 17 | 18 | /// Represents a window, containing information about its size, position, and 19 | /// properties. 20 | /// 21 | /// TODO: Evaluate how to reconcile this with the highly mobile-centric Window 22 | /// class in dart::ui 23 | class PlatformWindow { 24 | /// Create a new window. 25 | PlatformWindow(this.frame, this.scaleFactor, this.screen); 26 | 27 | /// The frame of the screen, in screen coordinates. 28 | final Rect frame; 29 | 30 | /// The number of pixels per screen coordinate for this screen. 31 | final double scaleFactor; 32 | 33 | /// The (or a) screen containing this window, if any. 34 | final Screen screen; 35 | } 36 | -------------------------------------------------------------------------------- /plugins/menubar/README.md: -------------------------------------------------------------------------------- 1 | # menubar 2 | 3 | This plugin provides access to a native menubar. 4 | 5 | This is a prototype, and in the long term will either be replaced by functionality 6 | within the Flutter framework itself, or a published plugin (likely part of 7 | flutter/plugins). Either way, the API will change significantly. 8 | 9 | ## Supported Platforms 10 | 11 | - [x] macOS 12 | - [ ] [Windows](https://github.com/google/flutter-desktop-embedding/issues/105) 13 | - [x] Linux 14 | 15 | ## Caveats 16 | 17 | ### macOS 18 | 19 | Currently there is no way to interact with existing top-level menus, only add new ones. 20 | E.g., the Window menu cannot be extended from Flutter code. 21 | 22 | ### Linux 23 | 24 | The menubar [is a standalone window](https://github.com/google/flutter-desktop-embedding/issues/290) 25 | rather than at the top of the window. This implementation exists purely to allow for early 26 | experimentation with native menus on Linux until the full (non-GLFW) Linux embedding is 27 | written. 28 | 29 | ## Use 30 | 31 | See [the plugin README](../README.md) for general instructions on using FDE plugins. 32 | 33 | ### Linux 34 | 35 | You will need to update `main.cc` to include [the GTK initialization and runloop changes 36 | shown in the `testbed` 37 | example](https://github.com/google/flutter-desktop-embedding/blob/master/testbed/linux/main.cc#L81-L91). 38 | -------------------------------------------------------------------------------- /plugins/window_size/windows/window_size_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef PLUGINS_WINDOW_SIZE_WINDOWS_WINDOW_SIZE_PLUGIN_H_ 15 | #define PLUGINS_WINDOW_SIZE_WINDOWS_WINDOW_SIZE_PLUGIN_H_ 16 | 17 | // A plugin to allow resizing the window. 18 | 19 | #include 20 | 21 | #ifdef FLUTTER_PLUGIN_IMPL 22 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) 23 | #else 24 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) 25 | #endif 26 | 27 | #if defined(__cplusplus) 28 | extern "C" { 29 | #endif 30 | 31 | FLUTTER_PLUGIN_EXPORT void WindowSizePluginRegisterWithRegistrar( 32 | FlutterDesktopPluginRegistrarRef registrar); 33 | 34 | #if defined(__cplusplus) 35 | } // extern "C" 36 | #endif 37 | 38 | #endif // PLUGINS_WINDOW_SIZE_WINDOWS_WINDOW_SIZE_PLUGIN_H_ 39 | -------------------------------------------------------------------------------- /plugins/file_chooser/windows/file_chooser_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef PLUGINS_FILE_CHOOSER_WINDOWS_FILE_CHOOSER_PLUGIN_H_ 15 | #define PLUGINS_FILE_CHOOSER_WINDOWS_FILE_CHOOSER_PLUGIN_H_ 16 | 17 | // A plugin to allow resizing the window. 18 | 19 | #include 20 | 21 | #ifdef FLUTTER_PLUGIN_IMPL 22 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) 23 | #else 24 | #define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) 25 | #endif 26 | 27 | #if defined(__cplusplus) 28 | extern "C" { 29 | #endif 30 | 31 | FLUTTER_PLUGIN_EXPORT void FileChooserPluginRegisterWithRegistrar( 32 | FlutterDesktopPluginRegistrarRef registrar); 33 | 34 | #if defined(__cplusplus) 35 | } // extern "C" 36 | #endif 37 | 38 | #endif // PLUGINS_FILE_CHOOSER_WINDOWS_FILE_CHOOSER_PLUGIN_H_ 39 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/README.md: -------------------------------------------------------------------------------- 1 | # Windows and Linux Implementation of flutter/plugins Plugins 2 | 3 | Each plugin in this directory corresponds to a 4 | [`flutter/plugins`](https://github.com/flutter/plugins) plugin with the 5 | same name, minus the `_fde` suffix. 6 | 7 | These implementations exist here only as a temporary solution to use these 8 | plugins while the plugin APIs on Windows and Linux stabilize enough that 9 | they can move to the official location and be distributed as normal Flutter 10 | plugins. macOS plugin APIs and tooling are stable, so are already hosted 11 | normally rather than here. 12 | 13 | ## Using These Plugins 14 | 15 | For these plugins, the Dart code comes from the official plugin, so you 16 | must include that in your `pubspec.yaml` as well. For instance, to use 17 | url\_launcher on desktop, you would include both `url_launcher` and 18 | `url_launcher_fde` in your pubspec.yaml (see [the main plugin 19 | README](../README.md) for instructions on adding these plugins to your 20 | `pubspec.yaml`). 21 | 22 | Since the Dart code for those plugins comes from the official plugin, you 23 | do not need to add any `import` in the Dart code other than the main 24 | plugin's `import`. For instance, you would just 25 | `import 'package:url_launcher/url_launcher.dart';` to use url\_launcher\_fde. 26 | 27 | ## Contributing 28 | 29 | If you are interested in implementing a flutter/plugins plugin for Windows 30 | and/or Linux, please open a PR! 31 | -------------------------------------------------------------------------------- /plugins/menubar/linux/include/menubar/menubar_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef PLUGINS_MENUBAR_LINUX_MENUBAR_PLUGIN_H_ 15 | #define PLUGINS_MENUBAR_LINUX_MENUBAR_PLUGIN_H_ 16 | 17 | // A plugin to control a native menubar. 18 | 19 | #include 20 | 21 | G_BEGIN_DECLS 22 | 23 | #ifdef FLUTTER_PLUGIN_IMPL 24 | #define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) 25 | #else 26 | #define FLUTTER_PLUGIN_EXPORT 27 | #endif 28 | 29 | G_DECLARE_FINAL_TYPE(FlMenubarPlugin, fl_menubar_plugin, FL, MENUBAR_PLUGIN, 30 | GObject) 31 | 32 | FLUTTER_PLUGIN_EXPORT FlMenubarPlugin* fl_menubar_plugin_new( 33 | FlPluginRegistrar* registrar); 34 | 35 | FLUTTER_PLUGIN_EXPORT void menubar_plugin_register_with_registrar( 36 | FlPluginRegistrar* registrar); 37 | 38 | G_END_DECLS 39 | 40 | #endif // PLUGINS_MENUBAR_LINUX_MENUBAR_PLUGIN_H_ 41 | -------------------------------------------------------------------------------- /plugins/window_size/linux/include/window_size/window_size_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef PLUGINS_WINDOW_SIZE_LINUX_WINDOW_SIZE_PLUGIN_H_ 15 | #define PLUGINS_WINDOW_SIZE_LINUX_WINDOW_SIZE_PLUGIN_H_ 16 | 17 | // A plugin to allow resizing the window. 18 | 19 | #include 20 | 21 | G_BEGIN_DECLS 22 | 23 | #ifdef FLUTTER_PLUGIN_IMPL 24 | #define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) 25 | #else 26 | #define FLUTTER_PLUGIN_EXPORT 27 | #endif 28 | 29 | G_DECLARE_FINAL_TYPE(FlWindowSizePlugin, fl_window_size_plugin, FL, 30 | WINDOW_SIZE_PLUGIN, GObject) 31 | 32 | FLUTTER_PLUGIN_EXPORT FlWindowSizePlugin* fl_window_size_plugin_new( 33 | FlPluginRegistrar* registrar); 34 | 35 | FLUTTER_PLUGIN_EXPORT void window_size_plugin_register_with_registrar( 36 | FlPluginRegistrar* registrar); 37 | 38 | G_END_DECLS 39 | 40 | #endif // PLUGINS_WINDOW_SIZE_LINUX_WINDOW_SIZE_PLUGIN_H_ 41 | -------------------------------------------------------------------------------- /plugins/color_panel/linux/include/color_panel/color_panel_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef PLUGINS_COLOR_PANEL_LINUX_COLOR_PANEL_PLUGIN_H_ 15 | #define PLUGINS_COLOR_PANEL_LINUX_COLOR_PANEL_PLUGIN_H_ 16 | 17 | // A plugin for communicating with a native color picker panel. 18 | 19 | #include 20 | 21 | G_BEGIN_DECLS 22 | 23 | #ifdef FLUTTER_PLUGIN_IMPL 24 | #define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) 25 | #else 26 | #define FLUTTER_PLUGIN_EXPORT 27 | #endif 28 | 29 | G_DECLARE_FINAL_TYPE(FlColorPanelPlugin, fl_color_panel_plugin, FL, 30 | COLOR_PANEL_PLUGIN, GObject) 31 | 32 | FLUTTER_PLUGIN_EXPORT FlColorPanelPlugin* fl_color_panel_plugin_new( 33 | FlPluginRegistrar* registrar); 34 | 35 | FLUTTER_PLUGIN_EXPORT void color_panel_plugin_register_with_registrar( 36 | FlPluginRegistrar* registrar); 37 | 38 | G_END_DECLS 39 | 40 | #endif // PLUGINS_COLOR_PANEL_LINUX_COLOR_PANEL_PLUGIN_H_ 41 | -------------------------------------------------------------------------------- /plugins/file_chooser/linux/include/file_chooser/file_chooser_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef PLUGINS_FILE_CHOOSER_LINUX_FILE_CHOOSER_PLUGIN_H_ 15 | #define PLUGINS_FILE_CHOOSER_LINUX_FILE_CHOOSER_PLUGIN_H_ 16 | 17 | // A plugin to show native save/open file choosers. 18 | 19 | #include 20 | 21 | G_BEGIN_DECLS 22 | 23 | #ifdef FLUTTER_PLUGIN_IMPL 24 | #define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) 25 | #else 26 | #define FLUTTER_PLUGIN_EXPORT 27 | #endif 28 | 29 | G_DECLARE_FINAL_TYPE(FlFileChooserPlugin, fl_file_chooser_plugin, FL, 30 | FILE_CHOOSER_PLUGIN, GObject) 31 | 32 | FLUTTER_PLUGIN_EXPORT FlFileChooserPlugin* fl_file_chooser_plugin_new( 33 | FlPluginRegistrar* registrar); 34 | 35 | FLUTTER_PLUGIN_EXPORT void file_chooser_plugin_register_with_registrar( 36 | FlPluginRegistrar* registrar); 37 | 38 | G_END_DECLS 39 | 40 | #endif // PLUGINS_FILE_CHOOSER_LINUX_FILE_CHOOSER_PLUGIN_H_ 41 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/linux/include/url_launcher_fde/url_launcher_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #ifndef PLUGINS_URL_LAUNCHER_LINUX_URL_LAUNCHER_PLUGIN_H_ 15 | #define PLUGINS_URL_LAUNCHER_LINUX_URL_LAUNCHER_PLUGIN_H_ 16 | 17 | // A plugin to launch URLs. 18 | 19 | #include 20 | 21 | G_BEGIN_DECLS 22 | 23 | #ifdef FLUTTER_PLUGIN_IMPL 24 | #define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) 25 | #else 26 | #define FLUTTER_PLUGIN_EXPORT 27 | #endif 28 | 29 | G_DECLARE_FINAL_TYPE(FlUrlLauncherPlugin, fl_url_launcher_plugin, FL, URL_LAUNCHER_PLUGIN, 30 | GObject) 31 | 32 | FLUTTER_PLUGIN_EXPORT FlUrlLauncherPlugin* fl_url_launcher_plugin_new( 33 | FlPluginRegistrar* registrar); 34 | 35 | FLUTTER_PLUGIN_EXPORT void url_launcher_plugin_register_with_registrar( 36 | FlPluginRegistrar* registrar); 37 | 38 | G_END_DECLS 39 | 40 | #endif // PLUGINS_URL_LAUNCHER_LINUX_URL_LAUNCHER_PLUGIN_H_ 41 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | oboard 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /windows/scripts/bundle_assets_and_deps.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set FLUTTER_CACHE_DIR=%~1 4 | set BUNDLE_DIR=%~2 5 | set PLUGIN_DIR=%~3 6 | set EXE_NAME=%~4 7 | set BUILD_MODE=%~5 8 | 9 | set DATA_DIR=%BUNDLE_DIR%data 10 | 11 | if not exist "%DATA_DIR%" call mkdir "%DATA_DIR%" 12 | if %errorlevel% neq 0 exit /b %errorlevel% 13 | 14 | :: Write the executable name to the location expected by the Flutter tool. 15 | echo %EXE_NAME%>"%FLUTTER_CACHE_DIR%exe_filename" 16 | 17 | :: Copy the Flutter assets to the data directory. 18 | set FLUTTER_BUILD_DIR=%~dp0..\..\build\ 19 | set ASSET_DIR_NAME=flutter_assets 20 | set TARGET_ASSET_DIR=%DATA_DIR%\%ASSET_DIR_NAME% 21 | if exist "%TARGET_ASSET_DIR%" call rmdir /s /q "%TARGET_ASSET_DIR%" 22 | if %errorlevel% neq 0 exit /b %errorlevel% 23 | call xcopy /s /e /i /q "%FLUTTER_BUILD_DIR%%ASSET_DIR_NAME%" "%TARGET_ASSET_DIR%" 24 | if %errorlevel% neq 0 exit /b %errorlevel% 25 | 26 | :: Copy the icudtl.dat file from the Flutter tree to the data directory. 27 | call xcopy /y /d /q "%FLUTTER_CACHE_DIR%icudtl.dat" "%DATA_DIR%" 28 | if %errorlevel% neq 0 exit /b %errorlevel% 29 | 30 | :: For non-debug modes, copy app.so into the data directory. 31 | if not %BUILD_MODE% == "Debug" ( 32 | call xcopy /y /d /q "%FLUTTER_BUILD_DIR%windows\app.so" "%DATA_DIR%" 33 | if %errorlevel% neq 0 exit /b %errorlevel% 34 | ) 35 | 36 | :: Copy the Flutter DLL to the target location. 37 | call xcopy /y /d /q "%FLUTTER_CACHE_DIR%flutter_windows.dll" "%BUNDLE_DIR%" 38 | if %errorlevel% neq 0 exit /b %errorlevel% 39 | 40 | :: Copy any Plugin DLLs to the target location. 41 | if exist "%PLUGIN_DIR%" ( 42 | call xcopy /y /d /q "%PLUGIN_DIR%"*.dll "%BUNDLE_DIR%" 43 | if %errorlevel% neq 0 exit /b %errorlevel% 44 | ) 45 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "oboard.oboard" 37 | minSdkVersion 16 38 | targetSdkVersion 28 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | } 42 | 43 | buildTypes { 44 | release { 45 | // TODO: Add your own signing config for the release build. 46 | // Signing with the debug keys for now, so `flutter run --release` works. 47 | signingConfig signingConfigs.debug 48 | } 49 | } 50 | } 51 | 52 | flutter { 53 | source '../..' 54 | } 55 | -------------------------------------------------------------------------------- /plugins/README.md: -------------------------------------------------------------------------------- 1 | # Desktop Plugins 2 | 3 | See [the Flutter desktop 4 | page](https://github.com/flutter/flutter/wiki/Desktop-shells#plugins) 5 | for an overview of the current state of plugin development on desktop. 6 | 7 | This directory contains two types of plugins: 8 | * `flutter_plugins`, which contain Windows and Linux implementations of plugins 9 | from [the flutter/plugins repository](https://github.com/flutter/plugins). 10 | They are expected to move to that repository once the plugin APIs for those 11 | platforms are sufficiently stable. 12 | * Plugins that prototype functionality that will likely become part of 13 | Flutter itself. 14 | 15 | ## Using Plugins 16 | 17 | Since the plugins in this repository are not intended to live here long term, 18 | and the `flutter` tool's plugin support isn't finalized on all platforms yet, 19 | these plugins are not published on pub.dev like normal Flutter plugins. Instead, 20 | you should include them directly from this repository: 21 | 22 | ``` 23 | dependencies: 24 | ... 25 | file_chooser: 26 | git: 27 | url: git://github.com/google/flutter-desktop-embedding.git 28 | path: plugins/file_chooser 29 | ref: INSERT_HASH_HERE 30 | ``` 31 | 32 | Replace `INSERT_HASH_HERE` with the hash of commit you want to pin to, 33 | usually the latest commit to the repository at the time you add the plugin. 34 | While omitting the `ref` is possible, it is **strongly** discouraged, as 35 | without it any breaking change to the plugin would break your project 36 | without warning. 37 | 38 | ### Linux 39 | 40 | Many of the Linux plugins in this project require the following libraries: 41 | 42 | * GTK 3 43 | * pkg-config 44 | 45 | Installation example for debian-based systems: 46 | 47 | ``` 48 | $ sudo apt-get install libgtk-3-dev pkg-config 49 | ``` 50 | -------------------------------------------------------------------------------- /windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | #endif // English (United States) resources 58 | ///////////////////////////////////////////////////////////////////////////// 59 | 60 | 61 | 62 | #ifndef APSTUDIO_INVOKED 63 | ///////////////////////////////////////////////////////////////////////////// 64 | // 65 | // Generated from the TEXTINCLUDE 3 resource. 66 | // 67 | 68 | 69 | ///////////////////////////////////////////////////////////////////////////// 70 | #endif // not APSTUDIO_INVOKED 71 | -------------------------------------------------------------------------------- /plugins/file_chooser/windows/plugin.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {dbe2dac9-4a21-4849-bef5-2069d695609d} 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files\cpp_client_wrapper 34 | 35 | 36 | Source Files\cpp_client_wrapper 37 | 38 | 39 | Source Files\cpp_client_wrapper 40 | 41 | 42 | Source Files 43 | 44 | 45 | -------------------------------------------------------------------------------- /plugins/window_size/windows/plugin.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {dbe2dac9-4a21-4849-bef5-2069d695609d} 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files\cpp_client_wrapper 34 | 35 | 36 | Source Files\cpp_client_wrapper 37 | 38 | 39 | Source Files\cpp_client_wrapper 40 | 41 | 42 | Source Files 43 | 44 | 45 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/windows/plugin.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {dbe2dac9-4a21-4849-bef5-2069d695609d} 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Source Files\cpp_client_wrapper 34 | 35 | 36 | Source Files\cpp_client_wrapper 37 | 38 | 39 | Source Files\cpp_client_wrapper 40 | 41 | 42 | Source Files 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/path_provider_fde/windows/plugin.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {dbe2dac9-4a21-4849-bef5-2069d695609d} 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Source Files\cpp_client_wrapper 34 | 35 | 36 | Source Files\cpp_client_wrapper 37 | 38 | 39 | Source Files\cpp_client_wrapper 40 | 41 | 42 | Source Files 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /windows/FlutterBuild.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Profile 10 | x64 11 | 12 | 13 | Release 14 | x64 15 | 16 | 17 | 18 | 15.0 19 | {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} 20 | Flutter Build 21 | 10.0 22 | 23 | 24 | 25 | v141 26 | v142 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | "$(ProjectDir)scripts\prepare_dependencies" $(Configuration) 41 | Running Flutter backend build 42 | force_to_run_every_time 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /windows/runner/run_loop.cpp: -------------------------------------------------------------------------------- 1 | #include "run_loop.h" 2 | 3 | #include 4 | // Don't stomp std::min/std::max 5 | #undef max 6 | #undef min 7 | 8 | #include 9 | 10 | RunLoop::RunLoop() {} 11 | 12 | RunLoop::~RunLoop() {} 13 | 14 | void RunLoop::Run() { 15 | bool keep_running = true; 16 | TimePoint next_flutter_event_time = TimePoint::clock::now(); 17 | while (keep_running) { 18 | std::chrono::nanoseconds wait_duration = 19 | std::max(std::chrono::nanoseconds(0), 20 | next_flutter_event_time - TimePoint::clock::now()); 21 | ::MsgWaitForMultipleObjects( 22 | 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), 23 | QS_ALLINPUT); 24 | bool processed_events = false; 25 | MSG message; 26 | // All pending Windows messages must be processed; MsgWaitForMultipleObjects 27 | // won't return again for items left in the queue after PeekMessage. 28 | while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { 29 | processed_events = true; 30 | if (message.message == WM_QUIT) { 31 | keep_running = false; 32 | break; 33 | } 34 | ::TranslateMessage(&message); 35 | ::DispatchMessage(&message); 36 | // Allow Flutter to process messages each time a Windows message is 37 | // processed, to prevent starvation. 38 | next_flutter_event_time = 39 | std::min(next_flutter_event_time, ProcessFlutterMessages()); 40 | } 41 | // If the PeekMessage loop didn't run, process Flutter messages. 42 | if (!processed_events) { 43 | next_flutter_event_time = 44 | std::min(next_flutter_event_time, ProcessFlutterMessages()); 45 | } 46 | } 47 | } 48 | 49 | void RunLoop::RegisterFlutterInstance( 50 | flutter::FlutterViewController* flutter_instance) { 51 | flutter_instances_.insert(flutter_instance); 52 | } 53 | 54 | void RunLoop::UnregisterFlutterInstance( 55 | flutter::FlutterViewController* flutter_instance) { 56 | flutter_instances_.erase(flutter_instance); 57 | } 58 | 59 | RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { 60 | TimePoint next_event_time = TimePoint::max(); 61 | for (auto flutter_controller : flutter_instances_) { 62 | std::chrono::nanoseconds wait_duration = 63 | flutter_controller->ProcessMessages(); 64 | if (wait_duration != std::chrono::nanoseconds::max()) { 65 | next_event_time = 66 | std::min(next_event_time, TimePoint::clock::now() + wait_duration); 67 | } 68 | } 69 | return next_event_time; 70 | } 71 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 19 | 23 | 27 | 32 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /plugins/menubar/lib/src/menu_item.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import 'package:flutter/widgets.dart'; 15 | import 'package:meta/meta.dart'; 16 | 17 | /// A callback provided to [MenuItem] to handle menu selection. 18 | typedef MenuSelectedCallback = void Function(); 19 | 20 | /// The base type for an individual menu item that can be shown in a menu. 21 | abstract class AbstractMenuItem { 22 | /// Creates a new menu item with the give label. 23 | const AbstractMenuItem(this.label); 24 | 25 | /// The displayed label for the menu item. 26 | final String label; 27 | } 28 | 29 | /// A standard menu item, with no submenus. 30 | class MenuItem extends AbstractMenuItem { 31 | /// Creates a new menu item with the given [label] and options. 32 | /// 33 | /// Note that onClicked should generally be set unless [enabled] is false, 34 | /// or the menu item will be selectable but not do anything. 35 | const MenuItem({ 36 | @required String label, 37 | this.shortcut, 38 | this.enabled = true, 39 | this.onClicked, 40 | }) : super(label); 41 | 42 | /// The callback to call whenever the menu item is selected. 43 | final MenuSelectedCallback onClicked; 44 | 45 | /// Whether or not the menu item is enabled. 46 | final bool enabled; 47 | 48 | /// The shortcut/accelerator for the menu item, if any. 49 | /// 50 | /// Note: Currently modifiers have only Left or Right variants, so must be 51 | /// specified with one of those. The actual left/right distinction will be 52 | /// ignored. This part of the API is likely to change in the future. 53 | /// 54 | /// Example: a Save menu item would likely use: 55 | /// LogicalKeySet(LogicalKeyboardKey.meta, LogicalKeyboardKey.keyS) 56 | final LogicalKeySet shortcut; 57 | } 58 | 59 | /// A menu item continaing a submenu. 60 | /// 61 | /// The item itself can't be selected, it just displays the submenu. 62 | class Submenu extends AbstractMenuItem { 63 | /// Creates a new submenu with the given [label] and [children]. 64 | const Submenu({@required String label, @required this.children}) 65 | : super(label); 66 | 67 | /// The menu items contained in the submenu. 68 | final List children; 69 | } 70 | 71 | /// A menu item that serves as a divider, generally drawn as a line. 72 | class MenuDivider extends AbstractMenuItem { 73 | /// Creates a new divider item. 74 | const MenuDivider() : super(null); 75 | } 76 | -------------------------------------------------------------------------------- /plugins/file_chooser/lib/src/utilities.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import 'channel_controller.dart'; 15 | import 'filter_group.dart'; 16 | import 'result.dart'; 17 | 18 | /// Shows a file chooser for selecting paths to one or more existing files. 19 | /// 20 | /// A number of configuration options are available: 21 | /// - [initialDirectory] defaults the panel to the given directory path. 22 | /// - [allowedFileTypes] restricts selection to the given file types. 23 | /// - [allowsMultipleSelection] controls whether or not more than one file 24 | /// can be selected. Defaults to single file selection if unset. 25 | /// - [canSelectDirectories] allows choosing directories instead of files. 26 | /// Defaults to file selection if unset. 27 | /// - [confirmButtonText] overrides the button that confirms selection. 28 | Future showOpenPanel({ 29 | String initialDirectory, 30 | List allowedFileTypes, 31 | bool allowsMultipleSelection, 32 | bool canSelectDirectories, 33 | String confirmButtonText, 34 | }) async { 35 | final options = FileChooserConfigurationOptions( 36 | initialDirectory: initialDirectory, 37 | allowedFileTypes: allowedFileTypes, 38 | allowsMultipleSelection: allowsMultipleSelection, 39 | canSelectDirectories: canSelectDirectories, 40 | confirmButtonText: confirmButtonText); 41 | return FileChooserChannelController.instance 42 | .show(FileChooserType.open, options); 43 | } 44 | 45 | /// Shows a file chooser for selecting a save path. 46 | /// 47 | /// A number of configuration options are available: 48 | /// - [initialDirectory] defaults the panel to the given directory path. 49 | /// - [suggestedFileName] provides an initial value for the save filename. 50 | /// - [allowedFileTypes] restricts selection to the given file types. 51 | /// - [confirmButtonText] overrides the button that confirms selection. 52 | Future showSavePanel( 53 | {String initialDirectory, 54 | String suggestedFileName, 55 | List allowedFileTypes, 56 | String confirmButtonText}) async { 57 | final options = FileChooserConfigurationOptions( 58 | initialDirectory: initialDirectory, 59 | initialFileName: suggestedFileName, 60 | allowedFileTypes: allowedFileTypes, 61 | confirmButtonText: confirmButtonText); 62 | return FileChooserChannelController.instance 63 | .show(FileChooserType.save, options); 64 | } 65 | -------------------------------------------------------------------------------- /lib/board.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:event_bus/event_bus.dart'; 4 | import 'package:flutter/material.dart'; 5 | 6 | import 'main.dart'; 7 | 8 | EventBus boardEvent = EventBus(); 9 | Color paintColor = Colors.black; 10 | 11 | class BoardPainter extends CustomPainter { 12 | /// 帧集合 13 | final List frames; 14 | 15 | BoardPainter({this.frames}); 16 | 17 | /// 初始化画笔 18 | var lineP = Paint() 19 | ..strokeWidth = 5.0 20 | ..isAntiAlias = false 21 | ..strokeCap = StrokeCap.round; 22 | 23 | @override 24 | void paint(Canvas canvas, Size size) { 25 | if (frames.length == 0) return; 26 | canvas.translate(sy * 20, sx * 20); 27 | for (int i = 0; i < frames.length; i++) { 28 | lineP..color = frames[i].color; 29 | 30 | /// 当前frame 点集合 31 | List currentPoints = frames[i].points; 32 | 33 | if (currentPoints == null || currentPoints.length == 0) return; 34 | canvas.drawPoints(PointMode.polygon, currentPoints, lineP); 35 | } 36 | } 37 | 38 | @override 39 | bool shouldRepaint(CustomPainter oldDelegate) { 40 | return true; 41 | } 42 | } 43 | 44 | class Frame { 45 | /// 绘制的点集合 46 | List points; 47 | Color color; 48 | 49 | Frame(this.points, this.color); 50 | } 51 | 52 | class Board extends StatefulWidget { 53 | BoardState createState() => new BoardState(); 54 | } 55 | 56 | class BoardState extends State { 57 | // List _points = [], _pointsLast = []; 58 | // List painters; 59 | 60 | List frames = [Frame([], Colors.red)]; 61 | 62 | Widget build(BuildContext context) { 63 | return CustomPaint( 64 | painter: BoardPainter(frames: frames), 65 | child: GestureDetector( 66 | onPanStart: (details) { 67 | /// 开始绘制 可以初始化一些配置 68 | frames.last.color = paintColor; 69 | }, 70 | onPanUpdate: (details) { 71 | /// 拖动更新 72 | RenderBox renderBox = context.findRenderObject(); 73 | Offset _currentPoint = 74 | renderBox.globalToLocal(details.globalPosition); 75 | Offset currentPoint = 76 | Offset(_currentPoint.dx - sy * 20, _currentPoint.dy - sx * 20); 77 | setState(() { 78 | frames.last.points.add(currentPoint); 79 | }); 80 | }, 81 | onPanEnd: (details) { 82 | Color _randomColor = Colors.black; 83 | frames.add(Frame([], _randomColor)); 84 | }, 85 | ), 86 | ); 87 | } 88 | 89 | @override 90 | void initState() { 91 | super.initState(); 92 | boardEvent.on().listen((event) { 93 | switch (event) { 94 | case 'clear': 95 | frames.clear(); 96 | frames = [Frame([], Colors.red)]; 97 | break; 98 | } 99 | }); 100 | } 101 | 102 | @override 103 | void dispose() { 104 | super.dispose(); 105 | boardEvent.destroy(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /windows/Runner.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29709.97 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Runner", "Runner.vcxproj", "{5A827760-CF8B-408A-99A3-B6C0AD2271E7}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} = {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} 9 | {9FDE4FCF-34A0-48B0-818B-877485F2AFEB} = {9FDE4FCF-34A0-48B0-818B-877485F2AFEB} 10 | EndProjectSection 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Flutter Build", "FlutterBuild.vcxproj", "{6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "window_size", "Flutter\ephemeral\.plugin_symlinks\window_size\windows\plugin.vcxproj", "{9FDE4FCF-34A0-48B0-818B-877485F2AFEB}" 15 | ProjectSection(ProjectDependencies) = postProject 16 | {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} = {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F} 17 | EndProjectSection 18 | EndProject 19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Flutter Plugins", "Flutter Plugins", "{5C2E738A-1DD3-445A-AAC8-EEB9648DD07C}" 20 | EndProject 21 | Global 22 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 23 | Debug|x64 = Debug|x64 24 | Profile|x64 = Profile|x64 25 | Release|x64 = Release|x64 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Debug|x64.ActiveCfg = Debug|x64 29 | {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Debug|x64.Build.0 = Debug|x64 30 | {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Profile|x64.ActiveCfg = Profile|x64 31 | {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Profile|x64.Build.0 = Profile|x64 32 | {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Release|x64.ActiveCfg = Release|x64 33 | {5A827760-CF8B-408A-99A3-B6C0AD2271E7}.Release|x64.Build.0 = Release|x64 34 | {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Debug|x64.ActiveCfg = Debug|x64 35 | {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Debug|x64.Build.0 = Debug|x64 36 | {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Profile|x64.ActiveCfg = Profile|x64 37 | {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Profile|x64.Build.0 = Profile|x64 38 | {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Release|x64.ActiveCfg = Release|x64 39 | {6419BF13-6ECD-4CD2-9E85-E566A1F03F8F}.Release|x64.Build.0 = Release|x64 40 | {9FDE4FCF-34A0-48B0-818B-877485F2AFEB}.Debug|x64.ActiveCfg = Debug|x64 41 | {9FDE4FCF-34A0-48B0-818B-877485F2AFEB}.Debug|x64.Build.0 = Debug|x64 42 | {9FDE4FCF-34A0-48B0-818B-877485F2AFEB}.Profile|x64.ActiveCfg = Profile|x64 43 | {9FDE4FCF-34A0-48B0-818B-877485F2AFEB}.Profile|x64.Build.0 = Profile|x64 44 | {9FDE4FCF-34A0-48B0-818B-877485F2AFEB}.Release|x64.ActiveCfg = Release|x64 45 | {9FDE4FCF-34A0-48B0-818B-877485F2AFEB}.Release|x64.Build.0 = Release|x64 46 | EndGlobalSection 47 | GlobalSection(SolutionProperties) = preSolution 48 | HideSolutionNode = FALSE 49 | EndGlobalSection 50 | GlobalSection(ExtensibilityGlobals) = postSolution 51 | SolutionGuid = {B8A69CB0-A974-4774-9EBD-1E5EECACD186} 52 | EndGlobalSection 53 | GlobalSection(NestedProjects) = preSolution 54 | {9FDE4FCF-34A0-48B0-818B-877485F2AFEB} = {5C2E738A-1DD3-445A-AAC8-EEB9648DD07C} 55 | EndGlobalSection 56 | EndGlobal -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: oboard 2 | description: A Canvas application. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.7.0 <3.0.0" 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | 27 | 28 | # The following adds the Cupertino Icons font to your application. 29 | # Use with the CupertinoIcons class for iOS style icons. 30 | 31 | window_size: 32 | path: plugins/window_size 33 | cupertino_icons: ^0.1.3 34 | event_bus: ^1.1.0 35 | provider: ^4.0.5 36 | flustars: ^0.2.6+1 37 | sensors: ^0.4.0+1 38 | 39 | dev_dependencies: 40 | flutter_test: 41 | sdk: flutter 42 | 43 | # For information on the generic Dart part of this file, see the 44 | # following page: https://dart.dev/tools/pub/pubspec 45 | 46 | # The following section is specific to Flutter. 47 | flutter: 48 | 49 | # The following line ensures that the Material Icons font is 50 | # included with your application, so that you can use the icons in 51 | # the material Icons class. 52 | uses-material-design: true 53 | 54 | # To add assets to your application, add an assets section, like this: 55 | # assets: 56 | # - images/a_dot_burr.jpeg 57 | # - images/a_dot_ham.jpeg 58 | 59 | # An image asset can refer to one or more resolution-specific "variants", see 60 | # https://flutter.dev/assets-and-images/#resolution-aware. 61 | 62 | # For details regarding adding assets from package dependencies, see 63 | # https://flutter.dev/assets-and-images/#from-packages 64 | 65 | # To add custom fonts to your application, add a fonts section here, 66 | # in this "flutter" section. Each entry in this list should have a 67 | # "family" key with the font family name, and a "fonts" key with a 68 | # list giving the asset and other descriptors for the font. For 69 | # example: 70 | # fonts: 71 | # - family: Schyler 72 | # fonts: 73 | # - asset: fonts/Schyler-Regular.ttf 74 | # - asset: fonts/Schyler-Italic.ttf 75 | # style: italic 76 | # - family: Trajan Pro 77 | # fonts: 78 | # - asset: fonts/TrajanPro.ttf 79 | # - asset: fonts/TrajanPro_Bold.ttf 80 | # weight: 700 81 | # 82 | # For details regarding fonts from package dependencies, 83 | # see https://flutter.dev/custom-fonts/#from-packages 84 | -------------------------------------------------------------------------------- /plugins/window_size/lib/src/window_size_utils.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import 'dart:async'; 15 | import 'dart:ui'; 16 | 17 | import 'platform_window.dart'; 18 | import 'screen.dart'; 19 | import 'window_size_channel.dart'; 20 | 21 | /// Returns a list of [Screen]s for the current screen configuration. 22 | /// 23 | /// It is possible for this list to be empty, if the machine is running in 24 | /// a headless mode. 25 | Future> getScreenList() async { 26 | return await WindowSizeChannel.instance.getScreenList(); 27 | } 28 | 29 | /// Returns the [Screen] showing the window that contains this Flutter instance. 30 | /// 31 | /// If the window is not being displayed, returns null. If the window is being 32 | /// displayed on multiple screens, the platform can return any of those screens. 33 | Future getCurrentScreen() async { 34 | final windowInfo = await WindowSizeChannel.instance.getWindowInfo(); 35 | return windowInfo.screen; 36 | } 37 | 38 | /// Returns information about the window containing this Flutter instance. 39 | Future getWindowInfo() async { 40 | return await WindowSizeChannel.instance.getWindowInfo(); 41 | } 42 | 43 | /// Sets the frame of the window containing this Flutter instance, in 44 | /// screen coordinates. 45 | /// 46 | /// The platform may adjust the frame as necessary if the provided frame would 47 | /// cause significant usability issues (e.g., a window with no visible portion 48 | /// that can be used to move the window). 49 | void setWindowFrame(Rect frame) async { 50 | WindowSizeChannel.instance.setWindowFrame(frame); 51 | } 52 | 53 | /// Sets the minimum [Size] of the window containing this Flutter instance. 54 | void setWindowMinSize(Size size) async { 55 | WindowSizeChannel.instance.setWindowMinSize(size); 56 | } 57 | 58 | /// Sets the maximum [Size] of the window containing this Flutter instance. 59 | void setWindowMaxSize(Size size) async { 60 | WindowSizeChannel.instance.setWindowMaxSize(size); 61 | } 62 | 63 | /// Sets the window title, as a [String], of the window containing this Flutter instance. 64 | void setWindowTitle(String title) async { 65 | WindowSizeChannel.instance.setWindowTitle(title); 66 | } 67 | 68 | /// Sets the window title's represented [Uri], of the window containing this Flutter instance. 69 | /// 70 | /// Only implemented for macOS. If the URL is a file URL, the 71 | /// window shows an icon in its title bar. 72 | void setWindowTitleRepresentedUrl(Uri url) async { 73 | WindowSizeChannel.instance.setWindowTitleRepresentedUrl(url); 74 | } 75 | 76 | /// Gets the minimum [Size] of the window containing this Flutter instance. 77 | Future getWindowMinSize() async { 78 | return WindowSizeChannel.instance.getWindowMinSize(); 79 | } 80 | 81 | /// Gets the maximum [Size] of the window containing this Flutter instance. 82 | Future getWindowMaxSize() async { 83 | return WindowSizeChannel.instance.getWindowMaxSize(); 84 | } 85 | -------------------------------------------------------------------------------- /windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef WIN32_WINDOW_H_ 2 | #define WIN32_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 12 | // inherited from by classes that wish to specialize with custom 13 | // rendering and input handling 14 | class Win32Window { 15 | public: 16 | struct Point { 17 | unsigned int x; 18 | unsigned int y; 19 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 20 | }; 21 | 22 | struct Size { 23 | unsigned int width; 24 | unsigned int height; 25 | Size(unsigned int width, unsigned int height) 26 | : width(width), height(height) {} 27 | }; 28 | 29 | Win32Window(); 30 | virtual ~Win32Window(); 31 | 32 | // Creates and shows a win32 window with |title| and position and size using 33 | // |origin| and |size|. New windows are created on the default monitor. Window 34 | // sizes are specified to the OS in physical pixels, hence to ensure a 35 | // consistent size to will treat the width height passed in to this function 36 | // as logical pixels and scale to appropriate for the default monitor. Returns 37 | // true if the window was created successfully. 38 | bool CreateAndShow(const std::wstring& title, 39 | const Point& origin, 40 | const Size& size); 41 | 42 | // Release OS resources associated with window. 43 | void Destroy(); 44 | 45 | // Inserts |content| into the window tree. 46 | void SetChildContent(HWND content); 47 | 48 | // Returns the backing Window handle to enable clients to set icon and other 49 | // window properties. Returns nullptr if the window has been destroyed. 50 | HWND GetHandle(); 51 | 52 | // If true, closing this window will quit the application. 53 | void SetQuitOnClose(bool quit_on_close); 54 | 55 | protected: 56 | // Processes and route salient window messages for mouse handling, 57 | // size change and DPI. Delegates handling of these to member overloads that 58 | // inheriting classes can handle. 59 | virtual LRESULT MessageHandler(HWND window, 60 | UINT const message, 61 | WPARAM const wparam, 62 | LPARAM const lparam) noexcept; 63 | 64 | // Called when CreateAndShow is called, allowing subclass window-related 65 | // setup. 66 | virtual void OnCreate(); 67 | 68 | // Called when Destroy is called. 69 | virtual void OnDestroy(); 70 | 71 | private: 72 | friend class WindowClassRegistrar; 73 | 74 | // OS callback called by message pump. Handles the WM_NCCREATE message which 75 | // is passed when the non-client area is being created and enables automatic 76 | // non-client DPI scaling so that the non-client area automatically 77 | // responsponds to changes in DPI. All other messages are handled by 78 | // MessageHandler. 79 | static LRESULT CALLBACK WndProc(HWND const window, 80 | UINT const message, 81 | WPARAM const wparam, 82 | LPARAM const lparam) noexcept; 83 | 84 | // Retrieves a class instance pointer for |window| 85 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 86 | 87 | bool quit_on_close_ = false; 88 | 89 | // window handle for top level window. 90 | HWND window_handle_ = nullptr; 91 | 92 | // window handle for hosted content. 93 | HWND child_content_ = nullptr; 94 | }; 95 | 96 | #endif // WIN32_WINDOW_H_ 97 | -------------------------------------------------------------------------------- /windows/Runner.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {2761a4b5-57b2-4d50-a677-d20ddc17a7f1} 18 | 19 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files\Client Wrapper 44 | 45 | 46 | Source Files\Client Wrapper 47 | 48 | 49 | Source Files\Client Wrapper 50 | 51 | 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Resource Files 81 | 82 | 83 | 84 | 85 | Resource Files 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/windows/url_launcher_plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "url_launcher_plugin.h" 15 | 16 | // Must be before VersionHelpers.h 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | namespace { 28 | 29 | using flutter::EncodableMap; 30 | using flutter::EncodableValue; 31 | 32 | class UrlLauncherPlugin : public flutter::Plugin { 33 | public: 34 | static void RegisterWithRegistrar(flutter::PluginRegistrar *registrar); 35 | 36 | virtual ~UrlLauncherPlugin(); 37 | 38 | private: 39 | UrlLauncherPlugin(); 40 | 41 | // Called when a method is called on plugin channel; 42 | void HandleMethodCall( 43 | const flutter::MethodCall &method_call, 44 | std::unique_ptr> result); 45 | }; 46 | 47 | // static 48 | void UrlLauncherPlugin::RegisterWithRegistrar( 49 | flutter::PluginRegistrar *registrar) { 50 | auto channel = std::make_unique>( 51 | registrar->messenger(), "plugins.flutter.io/url_launcher", 52 | &flutter::StandardMethodCodec::GetInstance()); 53 | 54 | // Uses new instead of make_unique due to private constructor. 55 | std::unique_ptr plugin(new UrlLauncherPlugin()); 56 | 57 | channel->SetMethodCallHandler( 58 | [plugin_pointer = plugin.get()](const auto &call, auto result) { 59 | plugin_pointer->HandleMethodCall(call, std::move(result)); 60 | }); 61 | 62 | registrar->AddPlugin(std::move(plugin)); 63 | } 64 | 65 | UrlLauncherPlugin::UrlLauncherPlugin() = default; 66 | 67 | UrlLauncherPlugin::~UrlLauncherPlugin() = default; 68 | 69 | void UrlLauncherPlugin::HandleMethodCall( 70 | const flutter::MethodCall &method_call, 71 | std::unique_ptr> result) { 72 | if (method_call.method_name().compare("launch") == 0) { 73 | std::string url; 74 | if (method_call.arguments() && method_call.arguments()->IsMap()) { 75 | const EncodableMap &arguments = method_call.arguments()->MapValue(); 76 | auto url_it = arguments.find(EncodableValue("url")); 77 | if (url_it != arguments.end()) { 78 | url = url_it->second.StringValue(); 79 | } 80 | } 81 | if (url.empty()) { 82 | result->Error("argument_error", "No URL provided"); 83 | return; 84 | } 85 | 86 | // launch a URL on Windows 87 | size_t size = url.length() + 1; 88 | std::wstring wurl; 89 | wurl.reserve(size); 90 | size_t outSize; 91 | mbstowcs_s(&outSize, &wurl[0], size, url.c_str(), size - 1); 92 | 93 | int status = static_cast(reinterpret_cast(ShellExecute( 94 | nullptr, TEXT("open"), wurl.c_str(), nullptr, nullptr, SW_SHOWNORMAL))); 95 | 96 | if (status <= 32) { 97 | std::ostringstream error_message; 98 | error_message << "Failed to open " << url << ": ShellExecute error code " 99 | << status; 100 | result->Error("open_error", error_message.str()); 101 | return; 102 | } 103 | result->Success(); 104 | } else { 105 | result->NotImplemented(); 106 | } 107 | } 108 | 109 | } // namespace 110 | 111 | void UrlLauncherPluginRegisterWithRegistrar( 112 | FlutterDesktopPluginRegistrarRef registrar) { 113 | UrlLauncherPlugin::RegisterWithRegistrar( 114 | flutter::PluginRegistrarManager::GetInstance() 115 | ->GetRegistrar(registrar)); 116 | } 117 | -------------------------------------------------------------------------------- /lib/about.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flutter/cupertino.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/services.dart'; 7 | 8 | String ver = '1.0beta'; 9 | String bun = '1'; 10 | String nam = '小板子'; 11 | 12 | class AboutPage extends StatefulWidget { 13 | const AboutPage({Key key}) : super(key: key); 14 | 15 | @override 16 | AboutPageState createState() => new AboutPageState(); 17 | } 18 | 19 | class AboutPageState extends State { 20 | @override 21 | Future didChangeDependencies() async { 22 | super.didChangeDependencies(); 23 | } 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return new Theme( 28 | data: Theme.of(context), 29 | child: new Scaffold( 30 | appBar: new AppBar( 31 | title: new Text("关于"), 32 | ), 33 | body: ListView( 34 | children: [ 35 | new Padding( 36 | padding: new EdgeInsets.all(8.0), 37 | child: Center( 38 | child: new Column( 39 | children: [ 40 | Container( 41 | decoration: new BoxDecoration( 42 | borderRadius: BorderRadius.all( 43 | Radius.circular(10.0), 44 | ), 45 | ), 46 | child: InkResponse( 47 | radius: 1000, 48 | onLongPress: () { 49 | Navigator.of(context).pop(); 50 | }, 51 | child: Text( 52 | ''' 53 | 小板子 54 | ''', 55 | style: Theme.of(context).textTheme.title.copyWith( 56 | color: Colors.white, 57 | ), 58 | textAlign: TextAlign.center, 59 | ), 60 | ), 61 | padding: EdgeInsets.all(50), 62 | ), 63 | new Divider(), 64 | new Text( 65 | '$nam', 66 | style: new TextStyle(fontSize: 20), 67 | ), 68 | new Text('$ver($bun)'), 69 | new Divider(), 70 | new Text( 71 | ''' 72 | \ 73 | 本软件永久免费 74 | 酷安:一块小板子 75 | QQ:2232442466\"''', 76 | textAlign: TextAlign.center, 77 | style: new TextStyle( 78 | fontStyle: FontStyle.italic, 79 | color: Colors.grey, 80 | ), 81 | ) 82 | ], 83 | ), 84 | ), 85 | ), 86 | ], 87 | ), 88 | ), 89 | ); 90 | } 91 | } 92 | 93 | final key = new GlobalKey(); 94 | 95 | class DonatePage extends StatefulWidget { 96 | const DonatePage({Key key}) : super(key: key); 97 | 98 | @override 99 | DonatePageState createState() => new DonatePageState(); 100 | } 101 | 102 | class DonatePageState extends State 103 | with AutomaticKeepAliveClientMixin { 104 | @override 105 | bool get wantKeepAlive => true; 106 | 107 | @override 108 | void initState() { 109 | super.initState(); 110 | } 111 | 112 | @override 113 | Widget build(BuildContext context) { 114 | super.build(context); 115 | return new Theme( 116 | data: Theme.of(context), 117 | child: new Scaffold( 118 | key: key, 119 | appBar: new AppBar( 120 | title: new Text("捐赠"), 121 | ), 122 | body: new Padding( 123 | padding: EdgeInsets.all(8.0), 124 | child: new SingleChildScrollView( 125 | child: new Column( 126 | children: [ 127 | //new Image.asset("images/qrpay.png"), 128 | new FlatButton.icon( 129 | icon: new Icon(Icons.attach_money), 130 | label: new Text('复制捐款链接'), 131 | onPressed: () async { 132 | const url = 'http://esa7y5.coding-pages.com/'; 133 | Clipboard.setData(new ClipboardData(text: url)); 134 | key.currentState.showSnackBar( 135 | new SnackBar(content: new Text('已复制到剪辑版'))); 136 | }, 137 | ) 138 | ], 139 | ), 140 | ), 141 | ), 142 | ), 143 | ); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /lib/color_choose.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:oboard/main.dart'; 6 | 7 | import 'board.dart'; 8 | 9 | List colorList = [ 10 | Colors.red, 11 | Colors.orange, 12 | Colors.yellow, 13 | Colors.green, 14 | Colors.teal, 15 | Colors.blue, 16 | Colors.purple, 17 | Colors.black 18 | ]; 19 | 20 | class CircleTrianglePage extends StatefulWidget { 21 | @override 22 | _CircleTriangleState createState() => _CircleTriangleState(); 23 | } 24 | 25 | double radius = 0; 26 | double screenW = 0, screenH = 0; 27 | List chooser = []; 28 | 29 | class _CircleTriangleState extends State { 30 | double _len = 0.0; 31 | double _x = 0.0; 32 | double _y = 0.0; 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | radius = MediaQuery.of(context).size.width / 3; 37 | screenW = MediaQuery.of(context).size.width; 38 | screenH = MediaQuery.of(context).size.height - 39 | MediaQueryData.fromWindow(window).viewInsets.bottom; 40 | return Container( 41 | child: Container( 42 | width: radius * 2, 43 | height: radius * 2, 44 | child: CustomPaint( 45 | painter: CircleTrianglePainter(scrollLen: _len), 46 | child: Stack( 47 | children: chooser, 48 | )), 49 | ), 50 | ); 51 | } 52 | } 53 | 54 | class ArcClipper extends CustomClipper { 55 | final double radius; 56 | final double startAngle; 57 | final double sweepAngle; 58 | 59 | ArcClipper(this.radius, this.startAngle, this.sweepAngle); 60 | 61 | @override 62 | Path getClip(Size size) { 63 | //x坐标为0.0 y坐标为手机高度一半 64 | //到x坐标为手机宽度 到 手机宽度的一半减去100 达到斜线的结果 65 | //到x坐标为手机宽度 到 y坐标为手机宽度 66 | //完成 67 | var path = Path() 68 | // ..lineTo(cos(startAngle) * radius, sin(startAngle) * radius) 69 | ..addArc(Rect.fromCircle(center: Offset(radius, radius), radius: radius), 70 | startAngle, sweepAngle) 71 | ..lineTo(size.width / 2, size.height / 2) 72 | ..close(); 73 | return path; 74 | } 75 | 76 | @override 77 | bool shouldReclip(CustomClipper oldClipper) => false; 78 | } 79 | 80 | const List POINT = [Point(100, 100)]; 81 | 82 | class CircleTrianglePainter extends CustomPainter { 83 | CircleTrianglePainter({this.scrollLen}); 84 | 85 | final double scrollLen; 86 | 87 | @override 88 | void paint(Canvas canvas, Size size) { 89 | if (size.width > 1.0 && size.height > 1.0) { 90 | // _sizeUtil.logicSize = size; 91 | } 92 | 93 | var paint = Paint() 94 | ..style = PaintingStyle.fill 95 | ..color = Colors.black 96 | ..strokeWidth = 2.0; 97 | 98 | paint.color = Colors.grey[900]; 99 | 100 | // canvas.drawCircle( 101 | 102 | // Offset(_sizeUtil.getAxisX(250), _sizeUtil.getAxisY(250.0)), 103 | 104 | // _sizeUtil.getAxisBoth(200.0), 105 | 106 | // paint); 107 | 108 | paint.strokeWidth = 20; 109 | 110 | paint.style = PaintingStyle.stroke; 111 | paint.style = PaintingStyle.fill; 112 | 113 | // canvas.drawArc(Rect.fromCircle(center: center, radius: radius), 114 | 115 | // 1.4 * scrollLen / radius, pi / 2, true, paint); 116 | 117 | _drawTriCircle( 118 | canvas, 119 | paint, 120 | sources: [1, 1, 1, 1, 1, 1, 1, 1], 121 | colors: colorList, 122 | radius: radius, 123 | startRadian: scrollLen / radius, 124 | ); 125 | 126 | canvas.save(); 127 | 128 | canvas.restore(); 129 | } 130 | 131 | void _drawTriCircle(Canvas canvas, Paint paint, 132 | {double radius, 133 | List sources, 134 | List colors, 135 | double startRadian}) { 136 | assert(sources != null && sources.length > 0); 137 | 138 | assert(colors != null && colors.length > 0); 139 | 140 | var total = 0.0; 141 | 142 | for (var d in sources) { 143 | total += d; 144 | } 145 | 146 | List radians = []; 147 | 148 | for (var data in sources) { 149 | radians.add(data * 2 * pi / total); 150 | } 151 | 152 | //!!! 153 | chooser.clear(); 154 | for (int i = 0; i < radians.length; i++) { 155 | paint.color = colors[i % colors.length]; 156 | 157 | // canvas.drawArc( 158 | // Rect.fromCircle(center: Offset(radius, radius), radius: radius), 159 | // startRadian, 160 | // radians[i], 161 | // true, 162 | // paint); 163 | //!!! 164 | chooser.add( 165 | ClipPath( 166 | clipper: ArcClipper( 167 | radius, 168 | startRadian, 169 | radians[i], 170 | ), 171 | child: Container( 172 | color: colors[i % colors.length], 173 | child: GestureDetector( 174 | onTapDown: (detail) { 175 | paintColor = colors[i % colors.length]; 176 | eventBus.fire(''); 177 | print(paintColor); 178 | }, 179 | ), 180 | ), 181 | ), 182 | ); 183 | 184 | startRadian += radians[i]; 185 | } 186 | } 187 | 188 | @override 189 | bool shouldRepaint(CircleTrianglePainter oldDelegate) => 190 | oldDelegate.scrollLen != scrollLen; 191 | } 192 | -------------------------------------------------------------------------------- /plugins/color_panel/lib/color_panel.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import 'dart:async'; 15 | import 'dart:ui'; 16 | 17 | import 'package:flutter/services.dart'; 18 | 19 | /// The name of the plugin's platform channel. 20 | const String _kColorPanelChannel = 'flutter/colorpanel'; 21 | 22 | /// The method name to instruct the native plugin to show the panel. 23 | const String _kShowColorPanelMethod = 'ColorPanel.Show'; 24 | /// The method name to instruct the native plugin to hide the panel. 25 | const String _kHideColorPanelMethod = 'ColorPanel.Hide'; 26 | /// The method name for the Dart-side callback that receives color values. 27 | const String _kColorPanelColorSelectedCallback = 28 | 'ColorPanel.ColorSelectedCallback'; 29 | /// The method name for the Dart-side callback that is called if the panel is 30 | /// closed from the UI, rather than via a call to kHideColorPanelMethod. 31 | const String _kColorPanelClosedCallback = 'ColorPanel.ClosedCallback'; 32 | 33 | /// The argument to show an opacity modifier on the panel. Default is true. 34 | const String _kColorPanelShowAlpha = 'ColorPanel.ShowAlpha'; 35 | 36 | // Keys for the ARGB color map sent to kColorPanelCallback. 37 | // The values should be numbers between 0 and 1. 38 | const String _kRedKey = 'red'; 39 | const String _kGreenKey = 'green'; 40 | const String _kBlueKey = 'blue'; 41 | // Platform implementations should return 1 if the opacity slider is not shown. 42 | const String _kAlphaKey = 'alpha'; 43 | 44 | const MethodChannel _platformChannel = const MethodChannel(_kColorPanelChannel); 45 | 46 | /// A callback to pass to [ColorPanel] to receive user-selected colors. 47 | typedef ColorPanelCallback = void Function(Color color); 48 | 49 | /// Provides access to an OS-provided color chooser. 50 | /// 51 | /// This class is a singleton, since the OS may not allow multiple color panels 52 | /// simultaneously. 53 | class ColorPanel { 54 | /// Private constructor. 55 | ColorPanel._() { 56 | _platformChannel.setMethodCallHandler(_wrappedColorPanelCallback); 57 | } 58 | 59 | ColorPanelCallback _callback; 60 | 61 | /// The static instance of the panel. 62 | static ColorPanel instance = new ColorPanel._(); 63 | 64 | /// Whether or not the panel is showing. 65 | bool get showing => _callback != null; 66 | 67 | /// Shows the color panel. 68 | /// 69 | /// [callback] will be called when the user selects a color; it can be called 70 | /// an number of times depending on the interaction model of the native 71 | /// panel. Set [showAlpha] to false to hide the color opacity modifier UI. 72 | /// 73 | /// It is an error to call [show] if the panel is already showing. 74 | void show(ColorPanelCallback callback, {bool showAlpha = true}) { 75 | try { 76 | if (!showing) { 77 | _callback = callback; 78 | _platformChannel.invokeMethod( 79 | _kShowColorPanelMethod, {_kColorPanelShowAlpha: showAlpha}); 80 | } else { 81 | throw new StateError('Color panel is already shown'); 82 | } 83 | } on PlatformException catch (e) { 84 | print('PLATFORM ERROR: ${e.message}'); 85 | } 86 | } 87 | 88 | /// Hides the color panel. 89 | /// 90 | /// It is an error to call [hide] if the panel is not showing. Since 91 | /// the panel can be closed by the user, you should always check 92 | /// [showing] before calling [hide]. 93 | void hide() { 94 | try { 95 | if (showing) { 96 | _platformChannel.invokeMethod(_kHideColorPanelMethod); 97 | _callback = null; 98 | } else { 99 | throw new StateError('Color panel is already hidden'); 100 | } 101 | } on PlatformException catch (e) { 102 | print('PLATFORM ERROR: ${e.message}'); 103 | } 104 | } 105 | 106 | /// Given a color component value from 0-1, converts it to an int 107 | /// from 0-255. 108 | int _colorComponentFloatToInt(num value) { 109 | const colorMax = 255; 110 | return (value * colorMax).round(); 111 | } 112 | 113 | /// Mediates between the platform channel callback and the client callback. 114 | Future _wrappedColorPanelCallback(MethodCall methodCall) async { 115 | if (methodCall.method == _kColorPanelClosedCallback) { 116 | _callback = null; 117 | } else if (_callback != null && 118 | methodCall.method == _kColorPanelColorSelectedCallback) { 119 | try { 120 | final Map arg = 121 | methodCall.arguments.cast(); 122 | if (arg != null) { 123 | _callback(Color.fromARGB( 124 | _colorComponentFloatToInt(arg[_kAlphaKey]), 125 | _colorComponentFloatToInt(arg[_kRedKey]), 126 | _colorComponentFloatToInt(arg[_kGreenKey]), 127 | _colorComponentFloatToInt(arg[_kBlueKey]))); 128 | } 129 | } on Exception catch (e, s) { 130 | print('Exception in callback handler: $e\n$s'); 131 | } 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /plugins/file_chooser/macos/Classes/FLEFileChooserPlugin.m: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import "FLEFileChooserPlugin.h" 16 | 17 | #import 18 | 19 | // See channel_controller.dart for documentation. 20 | static NSString *const kChannelName = @"flutter/filechooser"; 21 | static NSString *const kShowOpenPanelMethod = @"FileChooser.Show.Open"; 22 | static NSString *const kShowSavePanelMethod = @"FileChooser.Show.Save"; 23 | static NSString *const kInitialDirectoryKey = @"initialDirectory"; 24 | static NSString *const kInitialFileNameKey = @"initialFileName"; 25 | static NSString *const kAllowedFileTypesKey = @"allowedFileTypes"; 26 | static NSString *const kConfirmButtonTextKey = @"confirmButtonText"; 27 | static NSString *const kAllowsMultipleSelectionKey = @"allowsMultipleSelection"; 28 | static NSString *const kCanChooseDirectoriesKey = @"canChooseDirectories"; 29 | 30 | @implementation FLEFileChooserPlugin { 31 | // The plugin registrar, for obtaining the view. 32 | NSObject *_registrar; 33 | } 34 | 35 | - (instancetype)initWithRegistrar:(NSObject *)registrar { 36 | self = [super init]; 37 | if (self != nil) { 38 | _registrar = registrar; 39 | } 40 | return self; 41 | } 42 | 43 | /** 44 | * Configures an NSSavePanel instance on behalf of a flutter client. 45 | * 46 | * @param panel - The panel to configure. 47 | * @param arguments - A dictionary of method arguments used to configure a panel instance. 48 | */ 49 | - (void)configureSavePanel:(nonnull NSSavePanel *)panel 50 | withArguments:(nonnull NSDictionary *)arguments { 51 | NSSet *argKeys = [NSSet setWithArray:arguments.allKeys]; 52 | if ([argKeys containsObject:kInitialDirectoryKey]) { 53 | panel.directoryURL = [NSURL URLWithString:arguments[kInitialDirectoryKey]]; 54 | } 55 | if ([argKeys containsObject:kAllowedFileTypesKey]) { 56 | // macOS doesn't support filter groups, so combine all allowed types into a flat list. 57 | NSMutableArray *allowedTypes = [NSMutableArray array]; 58 | for (NSArray *filter in arguments[kAllowedFileTypesKey]) { 59 | NSArray *extensions = filter[1]; 60 | // If any group allows all extensions, don't do any filtering. 61 | if (extensions.count == 0) { 62 | allowedTypes = nil; 63 | break; 64 | } 65 | [allowedTypes addObjectsFromArray:extensions]; 66 | } 67 | panel.allowedFileTypes = allowedTypes; 68 | } 69 | if ([argKeys containsObject:kInitialFileNameKey]) { 70 | panel.nameFieldStringValue = arguments[kInitialFileNameKey]; 71 | } 72 | if ([argKeys containsObject:kConfirmButtonTextKey]) { 73 | panel.prompt = arguments[kConfirmButtonTextKey]; 74 | } 75 | } 76 | 77 | /** 78 | * Configures an NSOpenPanel instance on behalf of a flutter client. 79 | * 80 | * @param panel - The open panel to configure. 81 | * @param arguments - A dictionary of method arguments used to configure a panel instance. 82 | */ 83 | - (void)configureOpenPanel:(nonnull NSOpenPanel *)panel 84 | withArguments:(nonnull NSDictionary *)arguments { 85 | NSSet *argKeys = [NSSet setWithArray:arguments.allKeys]; 86 | if ([argKeys containsObject:kAllowsMultipleSelectionKey]) { 87 | panel.allowsMultipleSelection = [arguments[kAllowsMultipleSelectionKey] boolValue]; 88 | } 89 | if ([argKeys containsObject:kCanChooseDirectoriesKey]) { 90 | BOOL canChooseDirectories = [arguments[kCanChooseDirectoriesKey] boolValue]; 91 | panel.canChooseDirectories = canChooseDirectories; 92 | panel.canChooseFiles = !canChooseDirectories; 93 | } 94 | } 95 | 96 | #pragma FlutterPlugin implementation 97 | 98 | + (void)registerWithRegistrar:(id)registrar { 99 | FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:kChannelName 100 | binaryMessenger:registrar.messenger]; 101 | FLEFileChooserPlugin *instance = [[FLEFileChooserPlugin alloc] initWithRegistrar:registrar]; 102 | [registrar addMethodCallDelegate:instance channel:channel]; 103 | } 104 | 105 | - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { 106 | NSDictionary *arguments = call.arguments; 107 | 108 | if ([call.method isEqualToString:kShowSavePanelMethod]) { 109 | NSSavePanel *savePanel = [NSSavePanel savePanel]; 110 | savePanel.canCreateDirectories = YES; 111 | [self configureSavePanel:savePanel withArguments:arguments]; 112 | [savePanel beginSheetModalForWindow:_registrar.view.window 113 | completionHandler:^(NSModalResponse panelResult) { 114 | NSArray *URLs = 115 | (panelResult == NSModalResponseOK) ? @[ savePanel.URL ] : nil; 116 | result([URLs valueForKey:@"path"]); 117 | }]; 118 | 119 | } else if ([call.method isEqualToString:kShowOpenPanelMethod]) { 120 | NSOpenPanel *openPanel = [NSOpenPanel openPanel]; 121 | [self configureSavePanel:openPanel withArguments:arguments]; 122 | [self configureOpenPanel:openPanel withArguments:arguments]; 123 | [openPanel beginSheetModalForWindow:_registrar.view.window 124 | completionHandler:^(NSModalResponse panelResult) { 125 | NSArray *URLs = 126 | (panelResult == NSModalResponseOK) ? openPanel.URLs : nil; 127 | result([URLs valueForKey:@"path"]); 128 | }]; 129 | } else { 130 | result(FlutterMethodNotImplemented); 131 | } 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /plugins/color_panel/macos/Classes/FLEColorPanelPlugin.m: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #import "FLEColorPanelPlugin.h" 16 | 17 | #import 18 | 19 | // See color_panel.dart for descriptions. 20 | static NSString *const kChannelName = @"flutter/colorpanel"; 21 | static NSString *const kShowColorPanelMethod = @"ColorPanel.Show"; 22 | static NSString *const kColorPanelShowAlpha = @"ColorPanel.ShowAlpha"; 23 | static NSString *const kHideColorPanelMethod = @"ColorPanel.Hide"; 24 | static NSString *const kColorSelectedCallbackMethod = @"ColorPanel.ColorSelectedCallback"; 25 | static NSString *const kClosedCallbackMethod = @"ColorPanel.ClosedCallback"; 26 | static NSString *const kColorComponentAlphaKey = @"alpha"; 27 | static NSString *const kColorComponentRedKey = @"red"; 28 | static NSString *const kColorComponentGreenKey = @"green"; 29 | static NSString *const kColorComponentBlueKey = @"blue"; 30 | 31 | @implementation FLEColorPanelPlugin { 32 | // The channel used to communicate with Flutter. 33 | FlutterMethodChannel *_channel; 34 | } 35 | 36 | + (void)registerWithRegistrar:(id)registrar { 37 | FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:kChannelName 38 | binaryMessenger:registrar.messenger]; 39 | FLEColorPanelPlugin *instance = [[FLEColorPanelPlugin alloc] initWithChannel:channel]; 40 | [registrar addMethodCallDelegate:instance channel:channel]; 41 | } 42 | 43 | - (instancetype)initWithChannel:(FlutterMethodChannel *)channel { 44 | self = [super init]; 45 | if (self) { 46 | _channel = channel; 47 | } 48 | return self; 49 | } 50 | 51 | /** 52 | * Handles platform messages generated by the Flutter framework on the color 53 | * panel channel. 54 | */ 55 | - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { 56 | id methodResult = nil; 57 | if ([call.method isEqualToString:kShowColorPanelMethod]) { 58 | if ([call.arguments isKindOfClass:[NSDictionary class]]) { 59 | BOOL showAlpha = [[call.arguments valueForKey:kColorPanelShowAlpha] boolValue]; 60 | [self showColorPanelWithAlpha:showAlpha]; 61 | } else { 62 | NSString *errorString = [NSString 63 | stringWithFormat:@"Malformed call for %@. Expected an NSDictionary but got %@", 64 | kShowColorPanelMethod, NSStringFromClass([call.arguments class])]; 65 | methodResult = [FlutterError errorWithCode:@"Bad arguments" message:errorString details:nil]; 66 | } 67 | } else if ([call.method isEqualToString:kHideColorPanelMethod]) { 68 | [self hideColorPanel]; 69 | } else { 70 | methodResult = FlutterMethodNotImplemented; 71 | } 72 | // If no errors are generated, send an immediate empty success message for handled messages, since 73 | // the actual color data will be provided in follow-up messages. 74 | result(methodResult); 75 | } 76 | 77 | /** 78 | * Configures the shared instance of NSColorPanel and makes it the frontmost & key window. 79 | */ 80 | - (void)showColorPanelWithAlpha:(BOOL)showAlpha { 81 | NSColorPanel *sharedColor = [NSColorPanel sharedColorPanel]; 82 | sharedColor.delegate = self; 83 | [sharedColor setShowsAlpha:showAlpha]; 84 | [sharedColor setTarget:self]; 85 | [sharedColor setAction:@selector(selectedColorDidChange)]; 86 | if (!sharedColor.isKeyWindow) { 87 | [sharedColor makeKeyAndOrderFront:nil]; 88 | } 89 | } 90 | 91 | /** 92 | * Closes the shared color panel. 93 | */ 94 | - (void)hideColorPanel { 95 | if (![NSColorPanel sharedColorPanelExists]) { 96 | return; 97 | } 98 | 99 | // Disconnect before closing to prevent invoking the close callback. 100 | [self removeColorPanelConnections]; 101 | 102 | NSColorPanel *sharedColor = [NSColorPanel sharedColorPanel]; 103 | [sharedColor close]; 104 | } 105 | 106 | /** 107 | * Removes the connections from the shared color panel back to this instance. 108 | */ 109 | - (void)removeColorPanelConnections { 110 | NSColorPanel *sharedColor = [NSColorPanel sharedColorPanel]; 111 | [sharedColor setTarget:nil]; 112 | [sharedColor setAction:nil]; 113 | sharedColor.delegate = nil; 114 | } 115 | 116 | /** 117 | * Called when the user selects a color in the color panel. Grabs the selected color from the 118 | * panel and sends it to Flutter via the '_channel'. 119 | */ 120 | - (void)selectedColorDidChange { 121 | NSColor *color = [NSColorPanel sharedColorPanel].color; 122 | NSDictionary *colorDictionary = [self dictionaryWithColor:color]; 123 | [_channel invokeMethod:kColorSelectedCallbackMethod arguments:colorDictionary]; 124 | } 125 | 126 | /** 127 | * Converts an instance of NSColor to a dictionary representation suitable for Flutter channel 128 | * messages. 129 | * 130 | * @param color An instance of NSColor. 131 | * @return An instance of NSDictionary representing the color. 132 | */ 133 | - (NSDictionary *)dictionaryWithColor:(NSColor *)color { 134 | NSMutableDictionary *result = [NSMutableDictionary dictionary]; 135 | // TODO: Consider being able to pass other type of color space (Gray scale, CMYK, etc). 136 | NSColor *rgbColor = [color colorUsingColorSpace:[NSColorSpace genericRGBColorSpace]]; 137 | result[kColorComponentAlphaKey] = @(rgbColor.alphaComponent); 138 | result[kColorComponentRedKey] = @(rgbColor.redComponent); 139 | result[kColorComponentGreenKey] = @(rgbColor.greenComponent); 140 | result[kColorComponentBlueKey] = @(rgbColor.blueComponent); 141 | return result; 142 | } 143 | 144 | #pragma mark - NSWindowDelegate 145 | 146 | - (void)windowWillClose:(NSNotification *)notification { 147 | [self removeColorPanelConnections]; 148 | [_channel invokeMethod:kClosedCallbackMethod arguments:nil]; 149 | } 150 | 151 | @end 152 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/path_provider_fde/windows/path_provider_plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "path_provider_plugin.h" 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace { 28 | 29 | using flutter::EncodableValue; 30 | 31 | // Converts an null-terminated array of wchar_t's to a std::string. 32 | std::string StdStringFromWideChars(wchar_t *wide_chars) { 33 | std::wstring_convert> wide_to_utf8; 34 | return wide_to_utf8.to_bytes(wide_chars); 35 | } 36 | 37 | // Gets the path to the given folder ID, without verifying that it exists, 38 | // or an empty string on failure. 39 | std::string GetFolderPath(REFKNOWNFOLDERID folder_id) { 40 | wchar_t *wide_path = nullptr; 41 | if (!SUCCEEDED(SHGetKnownFolderPath(folder_id, KF_FLAG_DONT_VERIFY, nullptr, 42 | &wide_path))) { 43 | return ""; 44 | } 45 | std::string path = StdStringFromWideChars(wide_path); 46 | CoTaskMemFree(wide_path); 47 | return path; 48 | } 49 | 50 | // Returns the name of the executable, without the .exe extension, or an empty 51 | // string on failure. 52 | std::string GetExecutableName() { 53 | wchar_t buffer[MAX_PATH]; 54 | if (GetModuleFileName(nullptr, buffer, MAX_PATH) == 0) { 55 | return ""; 56 | } 57 | std::string executable_path = StdStringFromWideChars(buffer); 58 | size_t last_separator_position = executable_path.find_last_of('\\'); 59 | std::string executable_name; 60 | if (last_separator_position == std::string::npos) { 61 | executable_name = executable_path; 62 | } else { 63 | executable_name = executable_path.substr(last_separator_position + 1); 64 | } 65 | // Strip the .exe extension, if present. 66 | std::string extension = ".exe"; 67 | if (executable_name.compare(executable_name.size() - extension.size(), 68 | extension.size(), extension) == 0) { 69 | executable_name = 70 | executable_name.substr(0, executable_name.size() - extension.size()); 71 | } 72 | return executable_name; 73 | } 74 | 75 | class PathProviderPlugin : public flutter::Plugin { 76 | public: 77 | static void RegisterWithRegistrar(flutter::PluginRegistrar *registrar); 78 | 79 | virtual ~PathProviderPlugin(); 80 | 81 | private: 82 | PathProviderPlugin(); 83 | 84 | // Called when a method is called on plugin channel; 85 | void HandleMethodCall( 86 | const flutter::MethodCall &method_call, 87 | std::unique_ptr> result); 88 | }; 89 | 90 | // static 91 | void PathProviderPlugin::RegisterWithRegistrar( 92 | flutter::PluginRegistrar *registrar) { 93 | auto channel = std::make_unique>( 94 | registrar->messenger(), "plugins.flutter.io/path_provider", 95 | &flutter::StandardMethodCodec::GetInstance()); 96 | 97 | // Uses new instead of make_unique due to private constructor. 98 | std::unique_ptr plugin(new PathProviderPlugin()); 99 | 100 | channel->SetMethodCallHandler( 101 | [plugin_pointer = plugin.get()](const auto &call, auto result) { 102 | plugin_pointer->HandleMethodCall(call, std::move(result)); 103 | }); 104 | 105 | registrar->AddPlugin(std::move(plugin)); 106 | } 107 | 108 | PathProviderPlugin::PathProviderPlugin() = default; 109 | 110 | PathProviderPlugin::~PathProviderPlugin() = default; 111 | 112 | void PathProviderPlugin::HandleMethodCall( 113 | const flutter::MethodCall &method_call, 114 | std::unique_ptr> result) { 115 | if (method_call.method_name().compare("getTemporaryDirectory") == 0) { 116 | wchar_t path_buffer[MAX_PATH]; 117 | DWORD length = GetTempPath(MAX_PATH, path_buffer); 118 | if (length == 0 || length > MAX_PATH) { 119 | result->Error("Unable to get temporary path"); 120 | return; 121 | } 122 | std::string result_path = StdStringFromWideChars(path_buffer); 123 | flutter::EncodableValue response(result_path); 124 | result->Success(&response); 125 | } else if (method_call.method_name().compare( 126 | "getApplicationSupportDirectory") == 0) { 127 | std::string path = GetFolderPath(FOLDERID_RoamingAppData); 128 | if (path.empty()) { 129 | result->Error("Unable to get application data path"); 130 | return; 131 | } 132 | // Use the executable name as the subdirectory for now. 133 | std::string exe_name = GetExecutableName(); 134 | if (exe_name.empty()) { 135 | result->Error("Unable to get exe name"); 136 | return; 137 | } 138 | std::ostringstream response_stream; 139 | response_stream << path << "\\" << exe_name; 140 | flutter::EncodableValue response(response_stream.str()); 141 | result->Success(&response); 142 | } else if (method_call.method_name().compare( 143 | "getApplicationDocumentsDirectory") == 0) { 144 | std::string path = GetFolderPath(FOLDERID_Documents); 145 | if (path.empty()) { 146 | result->Error("Unable to get documents path"); 147 | return; 148 | } 149 | flutter::EncodableValue response(path); 150 | result->Success(&response); 151 | } else { 152 | result->NotImplemented(); 153 | } 154 | } 155 | 156 | } // namespace 157 | 158 | void PathProviderPluginRegisterWithRegistrar( 159 | FlutterDesktopPluginRegistrarRef registrar) { 160 | PathProviderPlugin::RegisterWithRegistrar( 161 | flutter::PluginRegistrarManager::GetInstance() 162 | ->GetRegistrar(registrar)); 163 | } 164 | -------------------------------------------------------------------------------- /plugins/flutter_plugins/url_launcher_fde/linux/url_launcher_plugin.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | #include "include/url_launcher_fde/url_launcher_plugin.h" 15 | 16 | #include 17 | #include 18 | 19 | // See url_launcher_channel.dart for documentation. 20 | const char kChannelName[] = "plugins.flutter.io/url_launcher"; 21 | const char kBadArgumentsError[] = "Bad Arguments"; 22 | const char kLaunchError[] = "Launch Error"; 23 | const char kCanLaunchMethod[] = "canLaunch"; 24 | const char kLaunchMethod[] = "launch"; 25 | const char kUrlKey[] = "url"; 26 | 27 | struct _FlUrlLauncherPlugin { 28 | GObject parent_instance; 29 | 30 | FlPluginRegistrar* registrar; 31 | 32 | // Connection to Flutter engine. 33 | FlMethodChannel* channel; 34 | }; 35 | 36 | G_DEFINE_TYPE(FlUrlLauncherPlugin, fl_url_launcher_plugin, g_object_get_type()) 37 | 38 | // Gets the URL from the arguments or generates an error. 39 | static gchar* get_url(FlValue* args, GError** error) { 40 | if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) { 41 | g_set_error(error, 0, 0, "Argument map missing or malformed"); 42 | return nullptr; 43 | } 44 | FlValue* url_value = fl_value_lookup_string(args, kUrlKey); 45 | if (url_value == nullptr) { 46 | g_set_error(error, 0, 0, "Missing URL"); 47 | return nullptr; 48 | } 49 | 50 | return g_strdup(fl_value_get_string(url_value)); 51 | } 52 | 53 | // Called to check if a URL can be launched. 54 | static FlMethodResponse* can_launch(FlUrlLauncherPlugin* self, FlValue* args) { 55 | g_autoptr(GError) error = nullptr; 56 | g_autofree gchar* url = get_url(args, &error); 57 | if (url == nullptr) { 58 | return FL_METHOD_RESPONSE(fl_method_error_response_new( 59 | kBadArgumentsError, error->message, nullptr)); 60 | } 61 | 62 | gboolean is_launchable = FALSE; 63 | g_autofree gchar* scheme = g_uri_parse_scheme(url); 64 | if (scheme == nullptr) { 65 | return FL_METHOD_RESPONSE(fl_method_error_response_new( 66 | kLaunchError, "Unable to determine URL scheme", nullptr)); 67 | } 68 | 69 | g_autoptr(GAppInfo) app_info = g_app_info_get_default_for_uri_scheme(scheme); 70 | is_launchable = app_info != nullptr; 71 | 72 | g_autoptr(FlValue) result = fl_value_new_bool(is_launchable); 73 | return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); 74 | } 75 | 76 | // Called when a URL should launch. 77 | static FlMethodResponse* launch(FlUrlLauncherPlugin* self, FlValue* args) { 78 | g_autoptr(GError) error = nullptr; 79 | g_autofree gchar* url = get_url(args, &error); 80 | if (url == nullptr) { 81 | return FL_METHOD_RESPONSE(fl_method_error_response_new( 82 | kBadArgumentsError, error->message, nullptr)); 83 | } 84 | 85 | FlView* view = fl_plugin_registrar_get_view(self->registrar); 86 | gboolean launched; 87 | if (view != nullptr) { 88 | GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))); 89 | launched = gtk_show_uri_on_window(window, url, GDK_CURRENT_TIME, &error); 90 | } else { 91 | launched = g_app_info_launch_default_for_uri(url, nullptr, &error); 92 | } 93 | if (!launched) { 94 | g_autofree gchar* message = 95 | g_strdup_printf("Failed to launch URL: %s", error->message); 96 | return FL_METHOD_RESPONSE( 97 | fl_method_error_response_new(kLaunchError, message, nullptr)); 98 | } 99 | 100 | g_autoptr(FlValue) result = fl_value_new_bool(TRUE); 101 | return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); 102 | } 103 | 104 | // Called when a method call is received from Flutter. 105 | static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call, 106 | gpointer user_data) { 107 | FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN(user_data); 108 | 109 | const gchar* method = fl_method_call_get_name(method_call); 110 | FlValue* args = fl_method_call_get_args(method_call); 111 | 112 | g_autoptr(FlMethodResponse) response = nullptr; 113 | if (strcmp(method, kCanLaunchMethod) == 0) 114 | response = can_launch(self, args); 115 | else if (strcmp(method, kLaunchMethod) == 0) 116 | response = launch(self, args); 117 | else 118 | response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); 119 | 120 | g_autoptr(GError) error = nullptr; 121 | if (!fl_method_call_respond(method_call, response, &error)) 122 | g_warning("Failed to send method call response: %s", error->message); 123 | } 124 | 125 | static void fl_url_launcher_plugin_dispose(GObject* object) { 126 | FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN(object); 127 | 128 | g_clear_object(&self->registrar); 129 | g_clear_object(&self->channel); 130 | 131 | G_OBJECT_CLASS(fl_url_launcher_plugin_parent_class)->dispose(object); 132 | } 133 | 134 | static void fl_url_launcher_plugin_class_init(FlUrlLauncherPluginClass* klass) { 135 | G_OBJECT_CLASS(klass)->dispose = fl_url_launcher_plugin_dispose; 136 | } 137 | 138 | FlUrlLauncherPlugin* fl_url_launcher_plugin_new(FlPluginRegistrar* registrar) { 139 | FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN( 140 | g_object_new(fl_url_launcher_plugin_get_type(), nullptr)); 141 | 142 | self->registrar = FL_PLUGIN_REGISTRAR(g_object_ref(registrar)); 143 | 144 | g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); 145 | self->channel = 146 | fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar), 147 | kChannelName, FL_METHOD_CODEC(codec)); 148 | fl_method_channel_set_method_call_handler(self->channel, method_call_cb, 149 | g_object_ref(self), g_object_unref); 150 | 151 | return self; 152 | } 153 | 154 | static void fl_url_launcher_plugin_init(FlUrlLauncherPlugin* self) {} 155 | 156 | void url_launcher_plugin_register_with_registrar(FlPluginRegistrar* registrar) { 157 | FlUrlLauncherPlugin* plugin = fl_url_launcher_plugin_new(registrar); 158 | g_object_unref(plugin); 159 | } 160 | -------------------------------------------------------------------------------- /plugins/file_chooser/lib/src/channel_controller.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | import 'package:flutter/services.dart'; 15 | 16 | import 'filter_group.dart'; 17 | import 'result.dart'; 18 | 19 | /// The name of the plugin's platform channel. 20 | const String _kChannelName = 'flutter/filechooser'; 21 | 22 | /// The method name to instruct the native plugin to show an open panel. 23 | const String _kShowOpenPanelMethod = 'FileChooser.Show.Open'; 24 | 25 | /// The method name to instruct the native plugin to show a save panel. 26 | const String _kShowSavePanelMethod = 'FileChooser.Show.Save'; 27 | 28 | // Configuration parameters for file chooser panels: 29 | 30 | /// The path, as a string, for initial directory to display. Default behavior is 31 | /// left to the OS if not provided.] 32 | const String _kInitialDirectoryKey = 'initialDirectory'; 33 | 34 | /// The initial file name that should appears in the file chooser. Defaults to 35 | /// an empty string if not provided. 36 | const String _kInitialFileNameKey = 'initialFileName'; 37 | 38 | /// An array of UTI or file extension groups a user should be able to select. 39 | /// 40 | /// The format is: 41 | /// [ 42 | /// [ label, [extension, extension, ...] ], 43 | /// [ label, [extension, extension, ...] ], 44 | /// ... 45 | /// ] 46 | /// 47 | /// On platforms that don't support selectable groups (e.g., macOS), the 48 | /// extension lists can be merged. An empty extension array indicates that any 49 | /// type is allowed; when merging, this should cause all other arrays to be 50 | /// ignored. 51 | const String _kAllowedFileTypesKey = 'allowedFileTypes'; 52 | 53 | /// The text that appears on the panel's confirmation button. If not provided, 54 | /// the OS default is used. 55 | const String _kConfirmButtonTextKey = 'confirmButtonText'; 56 | 57 | // Configuration parameters that only apply to open panels: 58 | 59 | /// A boolean indicating whether a panel should allow choosing multiple file 60 | /// paths. Defaults to false if not set. 61 | const String _kAllowsMultipleSelectionKey = 'allowsMultipleSelection'; 62 | 63 | /// A boolean indicating whether a panel should allow choosing directories 64 | /// instead of files. Defaults to false if not set. 65 | const String _kCanChooseDirectoriesKey = 'canChooseDirectories'; 66 | 67 | /// A File chooser type. 68 | enum FileChooserType { 69 | /// An open panel, for choosing one or more files to open. 70 | open, 71 | 72 | /// A save panel, for choosing where to save a file. 73 | save, 74 | } 75 | 76 | /// A set of configuration options for a file chooser. 77 | class FileChooserConfigurationOptions { 78 | /// Creates a new configuration options object with the given settings. 79 | const FileChooserConfigurationOptions( 80 | {this.initialDirectory, 81 | this.initialFileName, 82 | this.allowedFileTypes, 83 | this.allowsMultipleSelection, 84 | this.canSelectDirectories, 85 | this.confirmButtonText}); 86 | 87 | // See the constants above for documentation; these correspond exactly to 88 | // the configuration parameters defined in the channel protocol. 89 | final String initialDirectory; // ignore: public_member_api_docs 90 | final String initialFileName; // ignore: public_member_api_docs 91 | final List 92 | allowedFileTypes; // ignore: public_member_api_docs 93 | final bool allowsMultipleSelection; // ignore: public_member_api_docs 94 | final bool canSelectDirectories; // ignore: public_member_api_docs 95 | final String confirmButtonText; // ignore: public_member_api_docs 96 | 97 | /// Returns the configuration as a map that can be passed as the 98 | /// arguments to invokeMethod for [_kShowOpenPanelMethod] or 99 | /// [_kShowSavePanelMethod]. 100 | Map asInvokeMethodArguments() { 101 | final args = {}; 102 | if (initialDirectory != null && initialDirectory.isNotEmpty) { 103 | args[_kInitialDirectoryKey] = initialDirectory; 104 | } 105 | if (allowsMultipleSelection != null) { 106 | args[_kAllowsMultipleSelectionKey] = allowsMultipleSelection; 107 | } 108 | if (canSelectDirectories != null) { 109 | args[_kCanChooseDirectoriesKey] = canSelectDirectories; 110 | } 111 | if (allowedFileTypes != null && allowedFileTypes.isNotEmpty) { 112 | args[_kAllowedFileTypesKey] = allowedFileTypes 113 | .map((filter) => [filter.label ?? '', filter.fileExtensions ?? []]) 114 | .toList(); 115 | } 116 | if (confirmButtonText != null && confirmButtonText.isNotEmpty) { 117 | args[_kConfirmButtonTextKey] = confirmButtonText; 118 | } 119 | if (confirmButtonText != null && confirmButtonText.isNotEmpty) { 120 | args[_kConfirmButtonTextKey] = confirmButtonText; 121 | } 122 | if (initialFileName != null && initialFileName.isNotEmpty) { 123 | args[_kInitialFileNameKey] = initialFileName; 124 | } 125 | return args; 126 | } 127 | } 128 | 129 | /// A singleton object that controls file-choosing interactions with macOS. 130 | class FileChooserChannelController { 131 | FileChooserChannelController._(); 132 | 133 | /// The platform channel used to manage native file chooser affordances. 134 | final _channel = new MethodChannel(_kChannelName); 135 | 136 | /// A reference to the singleton instance of the class. 137 | static final FileChooserChannelController instance = 138 | new FileChooserChannelController._(); 139 | 140 | /// Shows a file chooser of [type] configured with [options], returning a 141 | /// [FileChooserResult] when complete. 142 | Future show( 143 | FileChooserType type, 144 | FileChooserConfigurationOptions options, 145 | ) async { 146 | final methodName = type == FileChooserType.open 147 | ? _kShowOpenPanelMethod 148 | : _kShowSavePanelMethod; 149 | final paths = await _channel.invokeListMethod( 150 | methodName, options.asInvokeMethodArguments()); 151 | return FileChooserResult(paths: paths ?? [], canceled: paths == null); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /lib/setting.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flustars/flustars.dart'; 5 | import 'package:flutter/cupertino.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:provider/provider.dart'; 8 | 9 | import 'about.dart'; 10 | import 'app_provider.dart'; 11 | import 'main.dart'; 12 | 13 | String colorKey = 'teal', appTitle = '小板子'; 14 | int sensorKey = 1; 15 | 16 | Map themeColorMap = { 17 | 'gray': Colors.grey, 18 | 'blue': Colors.blue, 19 | 'blueAccent': Colors.blueAccent, 20 | 'cyan': Colors.cyan, 21 | 'deepPurple': Colors.purple, 22 | 'deepPurpleAccent': Colors.deepPurpleAccent, 23 | 'deepOrange': Colors.orange, 24 | 'green': Colors.green, 25 | 'indigo': Colors.indigo, 26 | 'indigoAccent': Colors.indigoAccent, 27 | 'orange': Colors.orange, 28 | 'purple': Colors.purple, 29 | 'pink': Colors.pink, 30 | 'red': Colors.red, 31 | 'teal': Colors.teal, 32 | 'black': Colors.black, 33 | }; 34 | 35 | Map sensorMap = { 36 | 0: '无', 37 | 1: '仅陀螺仪', 38 | 2: '仅加速度传感器', 39 | 3: '两者共用', 40 | }; 41 | 42 | class SettingPage extends StatefulWidget { 43 | const SettingPage({Key key}) : super(key: key); 44 | 45 | @override 46 | SettingPageState createState() => SettingPageState(); 47 | } 48 | 49 | class SettingPageState extends State { 50 | @override 51 | Future didChangeDependencies() async { 52 | super.didChangeDependencies(); 53 | } 54 | 55 | @override 56 | Widget build(BuildContext context) { 57 | return Theme( 58 | data: Theme.of(context), 59 | child: Scaffold( 60 | appBar: AppBar( 61 | title: Text('设置'), 62 | ), 63 | body: ListView( 64 | children: [ 65 | Padding( 66 | padding: EdgeInsets.all(8.0), 67 | child: Center( 68 | child: Column( 69 | children: [ 70 | ExpansionTile( 71 | leading: Icon(Icons.color_lens), 72 | title: Text('颜色主题'), 73 | initiallyExpanded: false, 74 | children: [ 75 | Padding( 76 | padding: 77 | EdgeInsets.only(left: 10, right: 10, bottom: 10), 78 | child: Wrap( 79 | spacing: 8, 80 | runSpacing: 8, 81 | children: themeColorMap.keys.map((key) { 82 | Color value = themeColorMap[key]; 83 | return InkWell( 84 | onTap: () { 85 | SpUtil.putString('key_theme_color', key); 86 | setState(() { 87 | colorKey = key; 88 | }); 89 | 90 | Provider.of(context, 91 | listen: false) 92 | .setTheme(key); 93 | }, 94 | child: Container( 95 | width: 40, 96 | height: 40, 97 | color: value, 98 | child: colorKey == key 99 | ? Icon( 100 | Icons.done, 101 | color: Colors.white, 102 | ) 103 | : null, 104 | ), 105 | ); 106 | }).toList(), 107 | ), 108 | ) 109 | ], 110 | ), 111 | ExpansionTile( 112 | leading: Icon(Icons.settings_overscan), 113 | title: Text('传感器模式'), 114 | initiallyExpanded: false, 115 | children: [ 116 | Padding( 117 | padding: 118 | EdgeInsets.only(left: 10, right: 10, bottom: 10), 119 | child: Wrap( 120 | spacing: 3, 121 | runSpacing: 3, 122 | children: sensorMap.keys.map((key) { 123 | int value = SpUtil.getInt('sensor'); 124 | return InkWell( 125 | onTap: () { 126 | SpUtil.putInt('sensor', key); 127 | setState(() { 128 | sensorKey = key; 129 | }); 130 | }, 131 | child: Container( 132 | height: 40, 133 | child: Row( 134 | children: [ 135 | Text(sensorMap[key]), 136 | value == key 137 | ? Icon( 138 | Icons.done, 139 | ) 140 | : Icon( 141 | Icons.done, 142 | color: Colors.transparent, 143 | ), 144 | ], 145 | ), 146 | ), 147 | ); 148 | }).toList(), 149 | ), 150 | ) 151 | ], 152 | ), 153 | ListTile( 154 | leading: Icon(Icons.help), 155 | title: Text( 156 | '关于', 157 | style: TextStyle(fontSize: 18), 158 | ), 159 | onTap: () { 160 | turnToPage(context, AboutPage()); 161 | }, 162 | ), 163 | ], 164 | ), 165 | ), 166 | ), 167 | ], 168 | ), 169 | ), 170 | ); 171 | } 172 | } 173 | --------------------------------------------------------------------------------