first setup and basic building blocks
This commit is contained in:
		
							
								
								
									
										17
									
								
								windows/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								windows/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| flutter/ephemeral/ | ||||
|  | ||||
| # Visual Studio user-specific files. | ||||
| *.suo | ||||
| *.user | ||||
| *.userosscache | ||||
| *.sln.docstates | ||||
|  | ||||
| # Visual Studio build-related files. | ||||
| x64/ | ||||
| x86/ | ||||
|  | ||||
| # Visual Studio cache files | ||||
| # files ending in .cache can be ignored | ||||
| *.[Cc]ache | ||||
| # but keep track of directories ending in .cache | ||||
| !*.[Cc]ache/ | ||||
							
								
								
									
										108
									
								
								windows/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								windows/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| # Project-level configuration. | ||||
| cmake_minimum_required(VERSION 3.14) | ||||
| project(fast_network_navigation LANGUAGES CXX) | ||||
|  | ||||
| # The name of the executable created for the application. Change this to change | ||||
| # the on-disk name of your application. | ||||
| set(BINARY_NAME "fast_network_navigation") | ||||
|  | ||||
| # Explicitly opt in to modern CMake behaviors to avoid warnings with recent | ||||
| # versions of CMake. | ||||
| cmake_policy(VERSION 3.14...3.25) | ||||
|  | ||||
| # Define build configuration option. | ||||
| get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||||
| if(IS_MULTICONFIG) | ||||
|   set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" | ||||
|     CACHE STRING "" FORCE) | ||||
| else() | ||||
|   if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) | ||||
|     set(CMAKE_BUILD_TYPE "Debug" CACHE | ||||
|       STRING "Flutter build mode" FORCE) | ||||
|     set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS | ||||
|       "Debug" "Profile" "Release") | ||||
|   endif() | ||||
| endif() | ||||
| # Define settings for the Profile build mode. | ||||
| set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") | ||||
| set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") | ||||
| set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") | ||||
| set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") | ||||
|  | ||||
| # Use Unicode for all projects. | ||||
| add_definitions(-DUNICODE -D_UNICODE) | ||||
|  | ||||
| # Compilation settings that should be applied to most targets. | ||||
| # | ||||
| # Be cautious about adding new options here, as plugins use this function by | ||||
| # default. In most cases, you should add new options to specific targets instead | ||||
| # of modifying this function. | ||||
| function(APPLY_STANDARD_SETTINGS TARGET) | ||||
|   target_compile_features(${TARGET} PUBLIC cxx_std_17) | ||||
|   target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") | ||||
|   target_compile_options(${TARGET} PRIVATE /EHsc) | ||||
|   target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") | ||||
|   target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>") | ||||
| endfunction() | ||||
|  | ||||
| # Flutter library and tool build rules. | ||||
| set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") | ||||
| add_subdirectory(${FLUTTER_MANAGED_DIR}) | ||||
|  | ||||
| # Application build; see runner/CMakeLists.txt. | ||||
| add_subdirectory("runner") | ||||
|  | ||||
|  | ||||
| # Generated plugin build rules, which manage building the plugins and adding | ||||
| # them to the application. | ||||
| include(flutter/generated_plugins.cmake) | ||||
|  | ||||
|  | ||||
| # === Installation === | ||||
| # Support files are copied into place next to the executable, so that it can | ||||
| # run in place. This is done instead of making a separate bundle (as on Linux) | ||||
| # so that building and running from within Visual Studio will work. | ||||
| set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>") | ||||
| # Make the "install" step default, as it's required to run. | ||||
| set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) | ||||
| if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) | ||||
|   set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) | ||||
| endif() | ||||
|  | ||||
| set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") | ||||
| set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") | ||||
|  | ||||
| install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" | ||||
|   COMPONENT Runtime) | ||||
|  | ||||
| install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | ||||
|   COMPONENT Runtime) | ||||
|  | ||||
| install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||||
|   COMPONENT Runtime) | ||||
|  | ||||
| if(PLUGIN_BUNDLED_LIBRARIES) | ||||
|   install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" | ||||
|     DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||||
|     COMPONENT Runtime) | ||||
| endif() | ||||
|  | ||||
| # Copy the native assets provided by the build.dart from all packages. | ||||
| set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") | ||||
| install(DIRECTORY "${NATIVE_ASSETS_DIR}" | ||||
|    DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||||
|    COMPONENT Runtime) | ||||
|  | ||||
| # Fully re-copy the assets directory on each build to avoid having stale files | ||||
| # from a previous install. | ||||
| set(FLUTTER_ASSET_DIR_NAME "flutter_assets") | ||||
| install(CODE " | ||||
|   file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") | ||||
|   " COMPONENT Runtime) | ||||
| install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" | ||||
|   DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) | ||||
|  | ||||
| # Install the AOT library on non-Debug builds only. | ||||
| install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | ||||
|   CONFIGURATIONS Profile;Release | ||||
|   COMPONENT Runtime) | ||||
							
								
								
									
										109
									
								
								windows/flutter/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								windows/flutter/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| # This file controls Flutter-level build steps. It should not be edited. | ||||
| cmake_minimum_required(VERSION 3.14) | ||||
|  | ||||
| set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") | ||||
|  | ||||
| # Configuration provided via flutter tool. | ||||
| include(${EPHEMERAL_DIR}/generated_config.cmake) | ||||
|  | ||||
| # TODO: Move the rest of this into files in ephemeral. See | ||||
| # https://github.com/flutter/flutter/issues/57146. | ||||
| set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") | ||||
|  | ||||
| # Set fallback configurations for older versions of the flutter tool. | ||||
| if (NOT DEFINED FLUTTER_TARGET_PLATFORM) | ||||
|   set(FLUTTER_TARGET_PLATFORM "windows-x64") | ||||
| endif() | ||||
|  | ||||
| # === Flutter Library === | ||||
| set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") | ||||
|  | ||||
| # Published to parent scope for install step. | ||||
| set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) | ||||
| set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) | ||||
| set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) | ||||
| set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) | ||||
|  | ||||
| list(APPEND FLUTTER_LIBRARY_HEADERS | ||||
|   "flutter_export.h" | ||||
|   "flutter_windows.h" | ||||
|   "flutter_messenger.h" | ||||
|   "flutter_plugin_registrar.h" | ||||
|   "flutter_texture_registrar.h" | ||||
| ) | ||||
| list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") | ||||
| add_library(flutter INTERFACE) | ||||
| target_include_directories(flutter INTERFACE | ||||
|   "${EPHEMERAL_DIR}" | ||||
| ) | ||||
| target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") | ||||
| add_dependencies(flutter flutter_assemble) | ||||
|  | ||||
| # === Wrapper === | ||||
| list(APPEND CPP_WRAPPER_SOURCES_CORE | ||||
|   "core_implementations.cc" | ||||
|   "standard_codec.cc" | ||||
| ) | ||||
| list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") | ||||
| list(APPEND CPP_WRAPPER_SOURCES_PLUGIN | ||||
|   "plugin_registrar.cc" | ||||
| ) | ||||
| list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") | ||||
| list(APPEND CPP_WRAPPER_SOURCES_APP | ||||
|   "flutter_engine.cc" | ||||
|   "flutter_view_controller.cc" | ||||
| ) | ||||
| list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") | ||||
|  | ||||
| # Wrapper sources needed for a plugin. | ||||
| add_library(flutter_wrapper_plugin STATIC | ||||
|   ${CPP_WRAPPER_SOURCES_CORE} | ||||
|   ${CPP_WRAPPER_SOURCES_PLUGIN} | ||||
| ) | ||||
| apply_standard_settings(flutter_wrapper_plugin) | ||||
| set_target_properties(flutter_wrapper_plugin PROPERTIES | ||||
|   POSITION_INDEPENDENT_CODE ON) | ||||
| set_target_properties(flutter_wrapper_plugin PROPERTIES | ||||
|   CXX_VISIBILITY_PRESET hidden) | ||||
| target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) | ||||
| target_include_directories(flutter_wrapper_plugin PUBLIC | ||||
|   "${WRAPPER_ROOT}/include" | ||||
| ) | ||||
| add_dependencies(flutter_wrapper_plugin flutter_assemble) | ||||
|  | ||||
| # Wrapper sources needed for the runner. | ||||
| add_library(flutter_wrapper_app STATIC | ||||
|   ${CPP_WRAPPER_SOURCES_CORE} | ||||
|   ${CPP_WRAPPER_SOURCES_APP} | ||||
| ) | ||||
| apply_standard_settings(flutter_wrapper_app) | ||||
| target_link_libraries(flutter_wrapper_app PUBLIC flutter) | ||||
| target_include_directories(flutter_wrapper_app PUBLIC | ||||
|   "${WRAPPER_ROOT}/include" | ||||
| ) | ||||
| add_dependencies(flutter_wrapper_app flutter_assemble) | ||||
|  | ||||
| # === Flutter tool backend === | ||||
| # _phony_ is a non-existent file to force this command to run every time, | ||||
| # since currently there's no way to get a full input/output list from the | ||||
| # flutter tool. | ||||
| set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") | ||||
| set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) | ||||
| add_custom_command( | ||||
|   OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} | ||||
|     ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} | ||||
|     ${CPP_WRAPPER_SOURCES_APP} | ||||
|     ${PHONY_OUTPUT} | ||||
|   COMMAND ${CMAKE_COMMAND} -E env | ||||
|     ${FLUTTER_TOOL_ENVIRONMENT} | ||||
|     "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" | ||||
|       ${FLUTTER_TARGET_PLATFORM} $<CONFIG> | ||||
|   VERBATIM | ||||
| ) | ||||
| add_custom_target(flutter_assemble DEPENDS | ||||
|   "${FLUTTER_LIBRARY}" | ||||
|   ${FLUTTER_LIBRARY_HEADERS} | ||||
|   ${CPP_WRAPPER_SOURCES_CORE} | ||||
|   ${CPP_WRAPPER_SOURCES_PLUGIN} | ||||
|   ${CPP_WRAPPER_SOURCES_APP} | ||||
| ) | ||||
							
								
								
									
										11
									
								
								windows/flutter/generated_plugin_registrant.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								windows/flutter/generated_plugin_registrant.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| // | ||||
| //  Generated file. Do not edit. | ||||
| // | ||||
|  | ||||
| // clang-format off | ||||
|  | ||||
| #include "generated_plugin_registrant.h" | ||||
|  | ||||
|  | ||||
| void RegisterPlugins(flutter::PluginRegistry* registry) { | ||||
| } | ||||
							
								
								
									
										15
									
								
								windows/flutter/generated_plugin_registrant.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								windows/flutter/generated_plugin_registrant.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| // | ||||
| //  Generated file. Do not edit. | ||||
| // | ||||
|  | ||||
| // clang-format off | ||||
|  | ||||
| #ifndef GENERATED_PLUGIN_REGISTRANT_ | ||||
| #define GENERATED_PLUGIN_REGISTRANT_ | ||||
|  | ||||
| #include <flutter/plugin_registry.h> | ||||
|  | ||||
| // Registers Flutter plugins. | ||||
| void RegisterPlugins(flutter::PluginRegistry* registry); | ||||
|  | ||||
| #endif  // GENERATED_PLUGIN_REGISTRANT_ | ||||
							
								
								
									
										23
									
								
								windows/flutter/generated_plugins.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								windows/flutter/generated_plugins.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # | ||||
| # Generated file, do not edit. | ||||
| # | ||||
|  | ||||
| list(APPEND FLUTTER_PLUGIN_LIST | ||||
| ) | ||||
|  | ||||
| list(APPEND FLUTTER_FFI_PLUGIN_LIST | ||||
| ) | ||||
|  | ||||
| set(PLUGIN_BUNDLED_LIBRARIES) | ||||
|  | ||||
| foreach(plugin ${FLUTTER_PLUGIN_LIST}) | ||||
|   add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) | ||||
|   target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) | ||||
|   list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>) | ||||
|   list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) | ||||
| endforeach(plugin) | ||||
|  | ||||
| foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) | ||||
|   add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) | ||||
|   list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) | ||||
| endforeach(ffi_plugin) | ||||
							
								
								
									
										40
									
								
								windows/runner/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								windows/runner/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| cmake_minimum_required(VERSION 3.14) | ||||
| project(runner LANGUAGES CXX) | ||||
|  | ||||
| # Define the application target. To change its name, change BINARY_NAME in the | ||||
| # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer | ||||
| # work. | ||||
| # | ||||
| # Any new source files that you add to the application should be added here. | ||||
| add_executable(${BINARY_NAME} WIN32 | ||||
|   "flutter_window.cpp" | ||||
|   "main.cpp" | ||||
|   "utils.cpp" | ||||
|   "win32_window.cpp" | ||||
|   "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" | ||||
|   "Runner.rc" | ||||
|   "runner.exe.manifest" | ||||
| ) | ||||
|  | ||||
| # Apply the standard set of build settings. This can be removed for applications | ||||
| # that need different build settings. | ||||
| apply_standard_settings(${BINARY_NAME}) | ||||
|  | ||||
| # Add preprocessor definitions for the build version. | ||||
| target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") | ||||
| target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") | ||||
| target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") | ||||
| target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") | ||||
| target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") | ||||
|  | ||||
| # Disable Windows macros that collide with C++ standard library functions. | ||||
| target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") | ||||
|  | ||||
| # Add dependency libraries and include directories. Add any application-specific | ||||
| # dependencies here. | ||||
| target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) | ||||
| target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") | ||||
| target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") | ||||
|  | ||||
| # Run the Flutter tool portions of the build. This must not be removed. | ||||
| add_dependencies(${BINARY_NAME} flutter_assemble) | ||||
							
								
								
									
										121
									
								
								windows/runner/Runner.rc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								windows/runner/Runner.rc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | ||||
| // Microsoft Visual C++ generated resource script. | ||||
| // | ||||
| #pragma code_page(65001) | ||||
| #include "resource.h" | ||||
|  | ||||
| #define APSTUDIO_READONLY_SYMBOLS | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| // | ||||
| // Generated from the TEXTINCLUDE 2 resource. | ||||
| // | ||||
| #include "winres.h" | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| #undef APSTUDIO_READONLY_SYMBOLS | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| // English (United States) resources | ||||
|  | ||||
| #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) | ||||
| LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US | ||||
|  | ||||
| #ifdef APSTUDIO_INVOKED | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| // | ||||
| // TEXTINCLUDE | ||||
| // | ||||
|  | ||||
| 1 TEXTINCLUDE | ||||
| BEGIN | ||||
|     "resource.h\0" | ||||
| END | ||||
|  | ||||
| 2 TEXTINCLUDE | ||||
| BEGIN | ||||
|     "#include ""winres.h""\r\n" | ||||
|     "\0" | ||||
| END | ||||
|  | ||||
| 3 TEXTINCLUDE | ||||
| BEGIN | ||||
|     "\r\n" | ||||
|     "\0" | ||||
| END | ||||
|  | ||||
| #endif    // APSTUDIO_INVOKED | ||||
|  | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| // | ||||
| // Icon | ||||
| // | ||||
|  | ||||
| // Icon with lowest ID value placed first to ensure application icon | ||||
| // remains consistent on all systems. | ||||
| IDI_APP_ICON            ICON                    "resources\\app_icon.ico" | ||||
|  | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| // | ||||
| // Version | ||||
| // | ||||
|  | ||||
| #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) | ||||
| #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD | ||||
| #else | ||||
| #define VERSION_AS_NUMBER 1,0,0,0 | ||||
| #endif | ||||
|  | ||||
| #if defined(FLUTTER_VERSION) | ||||
| #define VERSION_AS_STRING FLUTTER_VERSION | ||||
| #else | ||||
| #define VERSION_AS_STRING "1.0.0" | ||||
| #endif | ||||
|  | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION VERSION_AS_NUMBER | ||||
|  PRODUCTVERSION VERSION_AS_NUMBER | ||||
|  FILEFLAGSMASK VS_FFI_FILEFLAGSMASK | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS VS_FF_DEBUG | ||||
| #else | ||||
|  FILEFLAGS 0x0L | ||||
| #endif | ||||
|  FILEOS VOS__WINDOWS32 | ||||
|  FILETYPE VFT_APP | ||||
|  FILESUBTYPE 0x0L | ||||
| BEGIN | ||||
|     BLOCK "StringFileInfo" | ||||
|     BEGIN | ||||
|         BLOCK "040904e4" | ||||
|         BEGIN | ||||
|             VALUE "CompanyName", "com.example" "\0" | ||||
|             VALUE "FileDescription", "fast_network_navigation" "\0" | ||||
|             VALUE "FileVersion", VERSION_AS_STRING "\0" | ||||
|             VALUE "InternalName", "fast_network_navigation" "\0" | ||||
|             VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0" | ||||
|             VALUE "OriginalFilename", "fast_network_navigation.exe" "\0" | ||||
|             VALUE "ProductName", "fast_network_navigation" "\0" | ||||
|             VALUE "ProductVersion", VERSION_AS_STRING "\0" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|     BEGIN | ||||
|         VALUE "Translation", 0x409, 1252 | ||||
|     END | ||||
| END | ||||
|  | ||||
| #endif    // English (United States) resources | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
|  | ||||
|  | ||||
| #ifndef APSTUDIO_INVOKED | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| // | ||||
| // Generated from the TEXTINCLUDE 3 resource. | ||||
| // | ||||
|  | ||||
|  | ||||
| ///////////////////////////////////////////////////////////////////////////// | ||||
| #endif    // not APSTUDIO_INVOKED | ||||
							
								
								
									
										71
									
								
								windows/runner/flutter_window.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								windows/runner/flutter_window.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| #include "flutter_window.h" | ||||
|  | ||||
| #include <optional> | ||||
|  | ||||
| #include "flutter/generated_plugin_registrant.h" | ||||
|  | ||||
| FlutterWindow::FlutterWindow(const flutter::DartProject& project) | ||||
|     : project_(project) {} | ||||
|  | ||||
| FlutterWindow::~FlutterWindow() {} | ||||
|  | ||||
| bool FlutterWindow::OnCreate() { | ||||
|   if (!Win32Window::OnCreate()) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   RECT frame = GetClientArea(); | ||||
|  | ||||
|   // The size here must match the window dimensions to avoid unnecessary surface | ||||
|   // creation / destruction in the startup path. | ||||
|   flutter_controller_ = std::make_unique<flutter::FlutterViewController>( | ||||
|       frame.right - frame.left, frame.bottom - frame.top, project_); | ||||
|   // Ensure that basic setup of the controller was successful. | ||||
|   if (!flutter_controller_->engine() || !flutter_controller_->view()) { | ||||
|     return false; | ||||
|   } | ||||
|   RegisterPlugins(flutter_controller_->engine()); | ||||
|   SetChildContent(flutter_controller_->view()->GetNativeWindow()); | ||||
|  | ||||
|   flutter_controller_->engine()->SetNextFrameCallback([&]() { | ||||
|     this->Show(); | ||||
|   }); | ||||
|  | ||||
|   // Flutter can complete the first frame before the "show window" callback is | ||||
|   // registered. The following call ensures a frame is pending to ensure the | ||||
|   // window is shown. It is a no-op if the first frame hasn't completed yet. | ||||
|   flutter_controller_->ForceRedraw(); | ||||
|  | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| void FlutterWindow::OnDestroy() { | ||||
|   if (flutter_controller_) { | ||||
|     flutter_controller_ = nullptr; | ||||
|   } | ||||
|  | ||||
|   Win32Window::OnDestroy(); | ||||
| } | ||||
|  | ||||
| LRESULT | ||||
| FlutterWindow::MessageHandler(HWND hwnd, UINT const message, | ||||
|                               WPARAM const wparam, | ||||
|                               LPARAM const lparam) noexcept { | ||||
|   // Give Flutter, including plugins, an opportunity to handle window messages. | ||||
|   if (flutter_controller_) { | ||||
|     std::optional<LRESULT> result = | ||||
|         flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, | ||||
|                                                       lparam); | ||||
|     if (result) { | ||||
|       return *result; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   switch (message) { | ||||
|     case WM_FONTCHANGE: | ||||
|       flutter_controller_->engine()->ReloadSystemFonts(); | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   return Win32Window::MessageHandler(hwnd, message, wparam, lparam); | ||||
| } | ||||
							
								
								
									
										33
									
								
								windows/runner/flutter_window.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								windows/runner/flutter_window.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| #ifndef RUNNER_FLUTTER_WINDOW_H_ | ||||
| #define RUNNER_FLUTTER_WINDOW_H_ | ||||
|  | ||||
| #include <flutter/dart_project.h> | ||||
| #include <flutter/flutter_view_controller.h> | ||||
|  | ||||
| #include <memory> | ||||
|  | ||||
| #include "win32_window.h" | ||||
|  | ||||
| // A window that does nothing but host a Flutter view. | ||||
| class FlutterWindow : public Win32Window { | ||||
|  public: | ||||
|   // Creates a new FlutterWindow hosting a Flutter view running |project|. | ||||
|   explicit FlutterWindow(const flutter::DartProject& project); | ||||
|   virtual ~FlutterWindow(); | ||||
|  | ||||
|  protected: | ||||
|   // Win32Window: | ||||
|   bool OnCreate() override; | ||||
|   void OnDestroy() override; | ||||
|   LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, | ||||
|                          LPARAM const lparam) noexcept override; | ||||
|  | ||||
|  private: | ||||
|   // The project to run. | ||||
|   flutter::DartProject project_; | ||||
|  | ||||
|   // The Flutter instance hosted by this window. | ||||
|   std::unique_ptr<flutter::FlutterViewController> flutter_controller_; | ||||
| }; | ||||
|  | ||||
| #endif  // RUNNER_FLUTTER_WINDOW_H_ | ||||
							
								
								
									
										43
									
								
								windows/runner/main.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								windows/runner/main.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| #include <flutter/dart_project.h> | ||||
| #include <flutter/flutter_view_controller.h> | ||||
| #include <windows.h> | ||||
|  | ||||
| #include "flutter_window.h" | ||||
| #include "utils.h" | ||||
|  | ||||
| int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, | ||||
|                       _In_ wchar_t *command_line, _In_ int show_command) { | ||||
|   // Attach to console when present (e.g., 'flutter run') or create a | ||||
|   // new console when running with a debugger. | ||||
|   if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { | ||||
|     CreateAndAttachConsole(); | ||||
|   } | ||||
|  | ||||
|   // Initialize COM, so that it is available for use in the library and/or | ||||
|   // plugins. | ||||
|   ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); | ||||
|  | ||||
|   flutter::DartProject project(L"data"); | ||||
|  | ||||
|   std::vector<std::string> command_line_arguments = | ||||
|       GetCommandLineArguments(); | ||||
|  | ||||
|   project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); | ||||
|  | ||||
|   FlutterWindow window(project); | ||||
|   Win32Window::Point origin(10, 10); | ||||
|   Win32Window::Size size(1280, 720); | ||||
|   if (!window.Create(L"fast_network_navigation", origin, size)) { | ||||
|     return EXIT_FAILURE; | ||||
|   } | ||||
|   window.SetQuitOnClose(true); | ||||
|  | ||||
|   ::MSG msg; | ||||
|   while (::GetMessage(&msg, nullptr, 0, 0)) { | ||||
|     ::TranslateMessage(&msg); | ||||
|     ::DispatchMessage(&msg); | ||||
|   } | ||||
|  | ||||
|   ::CoUninitialize(); | ||||
|   return EXIT_SUCCESS; | ||||
| } | ||||
							
								
								
									
										16
									
								
								windows/runner/resource.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								windows/runner/resource.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| //{{NO_DEPENDENCIES}} | ||||
| // Microsoft Visual C++ generated include file. | ||||
| // Used by Runner.rc | ||||
| // | ||||
| #define IDI_APP_ICON                    101 | ||||
|  | ||||
| // Next default values for new objects | ||||
| // | ||||
| #ifdef APSTUDIO_INVOKED | ||||
| #ifndef APSTUDIO_READONLY_SYMBOLS | ||||
| #define _APS_NEXT_RESOURCE_VALUE        102 | ||||
| #define _APS_NEXT_COMMAND_VALUE         40001 | ||||
| #define _APS_NEXT_CONTROL_VALUE         1001 | ||||
| #define _APS_NEXT_SYMED_VALUE           101 | ||||
| #endif | ||||
| #endif | ||||
							
								
								
									
										
											BIN
										
									
								
								windows/runner/resources/app_icon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								windows/runner/resources/app_icon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 33 KiB | 
							
								
								
									
										20
									
								
								windows/runner/runner.exe.manifest
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								windows/runner/runner.exe.manifest
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||||
| <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> | ||||
|   <application xmlns="urn:schemas-microsoft-com:asm.v3"> | ||||
|     <windowsSettings> | ||||
|       <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness> | ||||
|     </windowsSettings> | ||||
|   </application> | ||||
|   <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> | ||||
|     <application> | ||||
|       <!-- Windows 10 and Windows 11 --> | ||||
|       <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> | ||||
|       <!-- Windows 8.1 --> | ||||
|       <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> | ||||
|       <!-- Windows 8 --> | ||||
|       <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> | ||||
|       <!-- Windows 7 --> | ||||
|       <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> | ||||
|     </application> | ||||
|   </compatibility> | ||||
| </assembly> | ||||
							
								
								
									
										65
									
								
								windows/runner/utils.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								windows/runner/utils.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| #include "utils.h" | ||||
|  | ||||
| #include <flutter_windows.h> | ||||
| #include <io.h> | ||||
| #include <stdio.h> | ||||
| #include <windows.h> | ||||
|  | ||||
| #include <iostream> | ||||
|  | ||||
| void CreateAndAttachConsole() { | ||||
|   if (::AllocConsole()) { | ||||
|     FILE *unused; | ||||
|     if (freopen_s(&unused, "CONOUT$", "w", stdout)) { | ||||
|       _dup2(_fileno(stdout), 1); | ||||
|     } | ||||
|     if (freopen_s(&unused, "CONOUT$", "w", stderr)) { | ||||
|       _dup2(_fileno(stdout), 2); | ||||
|     } | ||||
|     std::ios::sync_with_stdio(); | ||||
|     FlutterDesktopResyncOutputStreams(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| std::vector<std::string> GetCommandLineArguments() { | ||||
|   // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. | ||||
|   int argc; | ||||
|   wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); | ||||
|   if (argv == nullptr) { | ||||
|     return std::vector<std::string>(); | ||||
|   } | ||||
|  | ||||
|   std::vector<std::string> command_line_arguments; | ||||
|  | ||||
|   // Skip the first argument as it's the binary name. | ||||
|   for (int i = 1; i < argc; i++) { | ||||
|     command_line_arguments.push_back(Utf8FromUtf16(argv[i])); | ||||
|   } | ||||
|  | ||||
|   ::LocalFree(argv); | ||||
|  | ||||
|   return command_line_arguments; | ||||
| } | ||||
|  | ||||
| std::string Utf8FromUtf16(const wchar_t* utf16_string) { | ||||
|   if (utf16_string == nullptr) { | ||||
|     return std::string(); | ||||
|   } | ||||
|   int target_length = ::WideCharToMultiByte( | ||||
|       CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, | ||||
|       -1, nullptr, 0, nullptr, nullptr) | ||||
|     -1; // remove the trailing null character | ||||
|   int input_length = (int)wcslen(utf16_string); | ||||
|   std::string utf8_string; | ||||
|   if (target_length <= 0 || target_length > utf8_string.max_size()) { | ||||
|     return utf8_string; | ||||
|   } | ||||
|   utf8_string.resize(target_length); | ||||
|   int converted_length = ::WideCharToMultiByte( | ||||
|       CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, | ||||
|       input_length, utf8_string.data(), target_length, nullptr, nullptr); | ||||
|   if (converted_length == 0) { | ||||
|     return std::string(); | ||||
|   } | ||||
|   return utf8_string; | ||||
| } | ||||
							
								
								
									
										19
									
								
								windows/runner/utils.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								windows/runner/utils.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| #ifndef RUNNER_UTILS_H_ | ||||
| #define RUNNER_UTILS_H_ | ||||
|  | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| // Creates a console for the process, and redirects stdout and stderr to | ||||
| // it for both the runner and the Flutter library. | ||||
| void CreateAndAttachConsole(); | ||||
|  | ||||
| // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string | ||||
| // encoded in UTF-8. Returns an empty std::string on failure. | ||||
| std::string Utf8FromUtf16(const wchar_t* utf16_string); | ||||
|  | ||||
| // Gets the command line arguments passed in as a std::vector<std::string>, | ||||
| // encoded in UTF-8. Returns an empty std::vector<std::string> on failure. | ||||
| std::vector<std::string> GetCommandLineArguments(); | ||||
|  | ||||
| #endif  // RUNNER_UTILS_H_ | ||||
							
								
								
									
										288
									
								
								windows/runner/win32_window.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								windows/runner/win32_window.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,288 @@ | ||||
| #include "win32_window.h" | ||||
|  | ||||
| #include <dwmapi.h> | ||||
| #include <flutter_windows.h> | ||||
|  | ||||
| #include "resource.h" | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| /// Window attribute that enables dark mode window decorations. | ||||
| /// | ||||
| /// Redefined in case the developer's machine has a Windows SDK older than | ||||
| /// version 10.0.22000.0. | ||||
| /// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute | ||||
| #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE | ||||
| #define DWMWA_USE_IMMERSIVE_DARK_MODE 20 | ||||
| #endif | ||||
|  | ||||
| constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; | ||||
|  | ||||
| /// Registry key for app theme preference. | ||||
| /// | ||||
| /// A value of 0 indicates apps should use dark mode. A non-zero or missing | ||||
| /// value indicates apps should use light mode. | ||||
| constexpr const wchar_t kGetPreferredBrightnessRegKey[] = | ||||
|   L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; | ||||
| constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; | ||||
|  | ||||
| // The number of Win32Window objects that currently exist. | ||||
| static int g_active_window_count = 0; | ||||
|  | ||||
| using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); | ||||
|  | ||||
| // Scale helper to convert logical scaler values to physical using passed in | ||||
| // scale factor | ||||
| int Scale(int source, double scale_factor) { | ||||
|   return static_cast<int>(source * scale_factor); | ||||
| } | ||||
|  | ||||
| // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. | ||||
| // This API is only needed for PerMonitor V1 awareness mode. | ||||
| void EnableFullDpiSupportIfAvailable(HWND hwnd) { | ||||
|   HMODULE user32_module = LoadLibraryA("User32.dll"); | ||||
|   if (!user32_module) { | ||||
|     return; | ||||
|   } | ||||
|   auto enable_non_client_dpi_scaling = | ||||
|       reinterpret_cast<EnableNonClientDpiScaling*>( | ||||
|           GetProcAddress(user32_module, "EnableNonClientDpiScaling")); | ||||
|   if (enable_non_client_dpi_scaling != nullptr) { | ||||
|     enable_non_client_dpi_scaling(hwnd); | ||||
|   } | ||||
|   FreeLibrary(user32_module); | ||||
| } | ||||
|  | ||||
| }  // namespace | ||||
|  | ||||
| // Manages the Win32Window's window class registration. | ||||
| class WindowClassRegistrar { | ||||
|  public: | ||||
|   ~WindowClassRegistrar() = default; | ||||
|  | ||||
|   // Returns the singleton registrar instance. | ||||
|   static WindowClassRegistrar* GetInstance() { | ||||
|     if (!instance_) { | ||||
|       instance_ = new WindowClassRegistrar(); | ||||
|     } | ||||
|     return instance_; | ||||
|   } | ||||
|  | ||||
|   // Returns the name of the window class, registering the class if it hasn't | ||||
|   // previously been registered. | ||||
|   const wchar_t* GetWindowClass(); | ||||
|  | ||||
|   // Unregisters the window class. Should only be called if there are no | ||||
|   // instances of the window. | ||||
|   void UnregisterWindowClass(); | ||||
|  | ||||
|  private: | ||||
|   WindowClassRegistrar() = default; | ||||
|  | ||||
|   static WindowClassRegistrar* instance_; | ||||
|  | ||||
|   bool class_registered_ = false; | ||||
| }; | ||||
|  | ||||
| WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; | ||||
|  | ||||
| const wchar_t* WindowClassRegistrar::GetWindowClass() { | ||||
|   if (!class_registered_) { | ||||
|     WNDCLASS window_class{}; | ||||
|     window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); | ||||
|     window_class.lpszClassName = kWindowClassName; | ||||
|     window_class.style = CS_HREDRAW | CS_VREDRAW; | ||||
|     window_class.cbClsExtra = 0; | ||||
|     window_class.cbWndExtra = 0; | ||||
|     window_class.hInstance = GetModuleHandle(nullptr); | ||||
|     window_class.hIcon = | ||||
|         LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); | ||||
|     window_class.hbrBackground = 0; | ||||
|     window_class.lpszMenuName = nullptr; | ||||
|     window_class.lpfnWndProc = Win32Window::WndProc; | ||||
|     RegisterClass(&window_class); | ||||
|     class_registered_ = true; | ||||
|   } | ||||
|   return kWindowClassName; | ||||
| } | ||||
|  | ||||
| void WindowClassRegistrar::UnregisterWindowClass() { | ||||
|   UnregisterClass(kWindowClassName, nullptr); | ||||
|   class_registered_ = false; | ||||
| } | ||||
|  | ||||
| Win32Window::Win32Window() { | ||||
|   ++g_active_window_count; | ||||
| } | ||||
|  | ||||
| Win32Window::~Win32Window() { | ||||
|   --g_active_window_count; | ||||
|   Destroy(); | ||||
| } | ||||
|  | ||||
| bool Win32Window::Create(const std::wstring& title, | ||||
|                          const Point& origin, | ||||
|                          const Size& size) { | ||||
|   Destroy(); | ||||
|  | ||||
|   const wchar_t* window_class = | ||||
|       WindowClassRegistrar::GetInstance()->GetWindowClass(); | ||||
|  | ||||
|   const POINT target_point = {static_cast<LONG>(origin.x), | ||||
|                               static_cast<LONG>(origin.y)}; | ||||
|   HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); | ||||
|   UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); | ||||
|   double scale_factor = dpi / 96.0; | ||||
|  | ||||
|   HWND window = CreateWindow( | ||||
|       window_class, title.c_str(), WS_OVERLAPPEDWINDOW, | ||||
|       Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), | ||||
|       Scale(size.width, scale_factor), Scale(size.height, scale_factor), | ||||
|       nullptr, nullptr, GetModuleHandle(nullptr), this); | ||||
|  | ||||
|   if (!window) { | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   UpdateTheme(window); | ||||
|  | ||||
|   return OnCreate(); | ||||
| } | ||||
|  | ||||
| bool Win32Window::Show() { | ||||
|   return ShowWindow(window_handle_, SW_SHOWNORMAL); | ||||
| } | ||||
|  | ||||
| // static | ||||
| LRESULT CALLBACK Win32Window::WndProc(HWND const window, | ||||
|                                       UINT const message, | ||||
|                                       WPARAM const wparam, | ||||
|                                       LPARAM const lparam) noexcept { | ||||
|   if (message == WM_NCCREATE) { | ||||
|     auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam); | ||||
|     SetWindowLongPtr(window, GWLP_USERDATA, | ||||
|                      reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams)); | ||||
|  | ||||
|     auto that = static_cast<Win32Window*>(window_struct->lpCreateParams); | ||||
|     EnableFullDpiSupportIfAvailable(window); | ||||
|     that->window_handle_ = window; | ||||
|   } else if (Win32Window* that = GetThisFromHandle(window)) { | ||||
|     return that->MessageHandler(window, message, wparam, lparam); | ||||
|   } | ||||
|  | ||||
|   return DefWindowProc(window, message, wparam, lparam); | ||||
| } | ||||
|  | ||||
| LRESULT | ||||
| Win32Window::MessageHandler(HWND hwnd, | ||||
|                             UINT const message, | ||||
|                             WPARAM const wparam, | ||||
|                             LPARAM const lparam) noexcept { | ||||
|   switch (message) { | ||||
|     case WM_DESTROY: | ||||
|       window_handle_ = nullptr; | ||||
|       Destroy(); | ||||
|       if (quit_on_close_) { | ||||
|         PostQuitMessage(0); | ||||
|       } | ||||
|       return 0; | ||||
|  | ||||
|     case WM_DPICHANGED: { | ||||
|       auto newRectSize = reinterpret_cast<RECT*>(lparam); | ||||
|       LONG newWidth = newRectSize->right - newRectSize->left; | ||||
|       LONG newHeight = newRectSize->bottom - newRectSize->top; | ||||
|  | ||||
|       SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, | ||||
|                    newHeight, SWP_NOZORDER | SWP_NOACTIVATE); | ||||
|  | ||||
|       return 0; | ||||
|     } | ||||
|     case WM_SIZE: { | ||||
|       RECT rect = GetClientArea(); | ||||
|       if (child_content_ != nullptr) { | ||||
|         // Size and position the child window. | ||||
|         MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, | ||||
|                    rect.bottom - rect.top, TRUE); | ||||
|       } | ||||
|       return 0; | ||||
|     } | ||||
|  | ||||
|     case WM_ACTIVATE: | ||||
|       if (child_content_ != nullptr) { | ||||
|         SetFocus(child_content_); | ||||
|       } | ||||
|       return 0; | ||||
|  | ||||
|     case WM_DWMCOLORIZATIONCOLORCHANGED: | ||||
|       UpdateTheme(hwnd); | ||||
|       return 0; | ||||
|   } | ||||
|  | ||||
|   return DefWindowProc(window_handle_, message, wparam, lparam); | ||||
| } | ||||
|  | ||||
| void Win32Window::Destroy() { | ||||
|   OnDestroy(); | ||||
|  | ||||
|   if (window_handle_) { | ||||
|     DestroyWindow(window_handle_); | ||||
|     window_handle_ = nullptr; | ||||
|   } | ||||
|   if (g_active_window_count == 0) { | ||||
|     WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { | ||||
|   return reinterpret_cast<Win32Window*>( | ||||
|       GetWindowLongPtr(window, GWLP_USERDATA)); | ||||
| } | ||||
|  | ||||
| void Win32Window::SetChildContent(HWND content) { | ||||
|   child_content_ = content; | ||||
|   SetParent(content, window_handle_); | ||||
|   RECT frame = GetClientArea(); | ||||
|  | ||||
|   MoveWindow(content, frame.left, frame.top, frame.right - frame.left, | ||||
|              frame.bottom - frame.top, true); | ||||
|  | ||||
|   SetFocus(child_content_); | ||||
| } | ||||
|  | ||||
| RECT Win32Window::GetClientArea() { | ||||
|   RECT frame; | ||||
|   GetClientRect(window_handle_, &frame); | ||||
|   return frame; | ||||
| } | ||||
|  | ||||
| HWND Win32Window::GetHandle() { | ||||
|   return window_handle_; | ||||
| } | ||||
|  | ||||
| void Win32Window::SetQuitOnClose(bool quit_on_close) { | ||||
|   quit_on_close_ = quit_on_close; | ||||
| } | ||||
|  | ||||
| bool Win32Window::OnCreate() { | ||||
|   // No-op; provided for subclasses. | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| void Win32Window::OnDestroy() { | ||||
|   // No-op; provided for subclasses. | ||||
| } | ||||
|  | ||||
| void Win32Window::UpdateTheme(HWND const window) { | ||||
|   DWORD light_mode; | ||||
|   DWORD light_mode_size = sizeof(light_mode); | ||||
|   LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, | ||||
|                                kGetPreferredBrightnessRegValue, | ||||
|                                RRF_RT_REG_DWORD, nullptr, &light_mode, | ||||
|                                &light_mode_size); | ||||
|  | ||||
|   if (result == ERROR_SUCCESS) { | ||||
|     BOOL enable_dark_mode = light_mode == 0; | ||||
|     DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, | ||||
|                           &enable_dark_mode, sizeof(enable_dark_mode)); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										102
									
								
								windows/runner/win32_window.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								windows/runner/win32_window.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| #ifndef RUNNER_WIN32_WINDOW_H_ | ||||
| #define RUNNER_WIN32_WINDOW_H_ | ||||
|  | ||||
| #include <windows.h> | ||||
|  | ||||
| #include <functional> | ||||
| #include <memory> | ||||
| #include <string> | ||||
|  | ||||
| // A class abstraction for a high DPI-aware Win32 Window. Intended to be | ||||
| // inherited from by classes that wish to specialize with custom | ||||
| // rendering and input handling | ||||
| class Win32Window { | ||||
|  public: | ||||
|   struct Point { | ||||
|     unsigned int x; | ||||
|     unsigned int y; | ||||
|     Point(unsigned int x, unsigned int y) : x(x), y(y) {} | ||||
|   }; | ||||
|  | ||||
|   struct Size { | ||||
|     unsigned int width; | ||||
|     unsigned int height; | ||||
|     Size(unsigned int width, unsigned int height) | ||||
|         : width(width), height(height) {} | ||||
|   }; | ||||
|  | ||||
|   Win32Window(); | ||||
|   virtual ~Win32Window(); | ||||
|  | ||||
|   // Creates a win32 window with |title| that is positioned and sized using | ||||
|   // |origin| and |size|. New windows are created on the default monitor. Window | ||||
|   // sizes are specified to the OS in physical pixels, hence to ensure a | ||||
|   // consistent size this function will scale the inputted width and height as | ||||
|   // as appropriate for the default monitor. The window is invisible until | ||||
|   // |Show| is called. Returns true if the window was created successfully. | ||||
|   bool Create(const std::wstring& title, const Point& origin, const Size& size); | ||||
|  | ||||
|   // Show the current window. Returns true if the window was successfully shown. | ||||
|   bool Show(); | ||||
|  | ||||
|   // Release OS resources associated with window. | ||||
|   void Destroy(); | ||||
|  | ||||
|   // Inserts |content| into the window tree. | ||||
|   void SetChildContent(HWND content); | ||||
|  | ||||
|   // Returns the backing Window handle to enable clients to set icon and other | ||||
|   // window properties. Returns nullptr if the window has been destroyed. | ||||
|   HWND GetHandle(); | ||||
|  | ||||
|   // If true, closing this window will quit the application. | ||||
|   void SetQuitOnClose(bool quit_on_close); | ||||
|  | ||||
|   // Return a RECT representing the bounds of the current client area. | ||||
|   RECT GetClientArea(); | ||||
|  | ||||
|  protected: | ||||
|   // Processes and route salient window messages for mouse handling, | ||||
|   // size change and DPI. Delegates handling of these to member overloads that | ||||
|   // inheriting classes can handle. | ||||
|   virtual LRESULT MessageHandler(HWND window, | ||||
|                                  UINT const message, | ||||
|                                  WPARAM const wparam, | ||||
|                                  LPARAM const lparam) noexcept; | ||||
|  | ||||
|   // Called when CreateAndShow is called, allowing subclass window-related | ||||
|   // setup. Subclasses should return false if setup fails. | ||||
|   virtual bool OnCreate(); | ||||
|  | ||||
|   // Called when Destroy is called. | ||||
|   virtual void OnDestroy(); | ||||
|  | ||||
|  private: | ||||
|   friend class WindowClassRegistrar; | ||||
|  | ||||
|   // OS callback called by message pump. Handles the WM_NCCREATE message which | ||||
|   // is passed when the non-client area is being created and enables automatic | ||||
|   // non-client DPI scaling so that the non-client area automatically | ||||
|   // responds to changes in DPI. All other messages are handled by | ||||
|   // MessageHandler. | ||||
|   static LRESULT CALLBACK WndProc(HWND const window, | ||||
|                                   UINT const message, | ||||
|                                   WPARAM const wparam, | ||||
|                                   LPARAM const lparam) noexcept; | ||||
|  | ||||
|   // Retrieves a class instance pointer for |window| | ||||
|   static Win32Window* GetThisFromHandle(HWND const window) noexcept; | ||||
|  | ||||
|   // Update the window frame's theme to match the system theme. | ||||
|   static void UpdateTheme(HWND const window); | ||||
|  | ||||
|   bool quit_on_close_ = false; | ||||
|  | ||||
|   // window handle for top level window. | ||||
|   HWND window_handle_ = nullptr; | ||||
|  | ||||
|   // window handle for hosted content. | ||||
|   HWND child_content_ = nullptr; | ||||
| }; | ||||
|  | ||||
| #endif  // RUNNER_WIN32_WINDOW_H_ | ||||
		Reference in New Issue
	
	Block a user