main.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #include <flutter/flutter_view_controller.h>
  2. #include <windows.h>
  3. #include <chrono>
  4. #include <codecvt>
  5. #include <iostream>
  6. #include <string>
  7. #include <vector>
  8. #include "flutter/generated_plugin_registrant.h"
  9. #include "win32_window.h"
  10. #include "window_configuration.h"
  11. namespace {
  12. // Returns the path of the directory containing this executable, or an empty
  13. // string if the directory cannot be found.
  14. std::string GetExecutableDirectory() {
  15. wchar_t buffer[MAX_PATH];
  16. if (GetModuleFileName(nullptr, buffer, MAX_PATH) == 0) {
  17. std::cerr << "Couldn't locate executable" << std::endl;
  18. return "";
  19. }
  20. std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> wide_to_utf8;
  21. std::string executable_path = wide_to_utf8.to_bytes(buffer);
  22. size_t last_separator_position = executable_path.find_last_of('\\');
  23. if (last_separator_position == std::string::npos) {
  24. std::cerr << "Unabled to find parent directory of " << executable_path
  25. << std::endl;
  26. return "";
  27. }
  28. return executable_path.substr(0, last_separator_position);
  29. }
  30. } // namespace
  31. int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
  32. _In_ wchar_t *command_line, _In_ int show_command) {
  33. // Attach to console when present (e.g., 'flutter run') or create a
  34. // new console when running with a debugger.
  35. if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
  36. ::AllocConsole();
  37. }
  38. // Resources are located relative to the executable.
  39. std::string base_directory = GetExecutableDirectory();
  40. if (base_directory.empty()) {
  41. base_directory = ".";
  42. }
  43. std::string data_directory = base_directory + "\\data";
  44. std::string assets_path = data_directory + "\\flutter_assets";
  45. std::string icu_data_path = data_directory + "\\icudtl.dat";
  46. // Arguments for the Flutter Engine.
  47. std::vector<std::string> arguments;
  48. // Top-level window frame.
  49. Win32Window::Point origin(kFlutterWindowOriginX, kFlutterWindowOriginY);
  50. Win32Window::Size size(kFlutterWindowWidth, kFlutterWindowHeight);
  51. flutter::FlutterViewController flutter_controller(
  52. icu_data_path, size.width, size.height, assets_path, arguments);
  53. RegisterPlugins(&flutter_controller);
  54. // Create a top-level win32 window to host the Flutter view.
  55. Win32Window window;
  56. if (!window.CreateAndShow(kFlutterWindowTitle, origin, size)) {
  57. return EXIT_FAILURE;
  58. }
  59. // Parent and resize Flutter view into top-level window.
  60. window.SetChildContent(flutter_controller.view()->GetNativeWindow());
  61. // Run messageloop with a hook for flutter_controller to do work until
  62. // the window is closed.
  63. std::chrono::nanoseconds wait_duration(0);
  64. // Run until the window is closed.
  65. while (window.GetHandle() != nullptr) {
  66. MsgWaitForMultipleObjects(0, nullptr, FALSE,
  67. static_cast<DWORD>(wait_duration.count() / 1000),
  68. QS_ALLINPUT);
  69. MSG message;
  70. // All pending Windows messages must be processed; MsgWaitForMultipleObjects
  71. // won't return again for items left in the queue after PeekMessage.
  72. while (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) {
  73. if (message.message == WM_QUIT) {
  74. window.Destroy();
  75. break;
  76. }
  77. TranslateMessage(&message);
  78. DispatchMessage(&message);
  79. }
  80. // Allow Flutter to process its messages.
  81. // TODO: Consider interleaving processing on a per-message basis to avoid
  82. // the possibility of one queue starving the other.
  83. wait_duration = flutter_controller.ProcessMessages();
  84. }
  85. return EXIT_SUCCESS;
  86. }