feat: Implement basic windows linux support
							parent
							
								
									f98f87db8e
								
							
						
					
					
						commit
						cb27314739
					
				@ -0,0 +1 @@
 | 
			
		||||
flutter/ephemeral
 | 
			
		||||
@ -0,0 +1,98 @@
 | 
			
		||||
cmake_minimum_required(VERSION 3.10)
 | 
			
		||||
project(runner LANGUAGES CXX)
 | 
			
		||||
 | 
			
		||||
set(BINARY_NAME "fluffychat")
 | 
			
		||||
set(APPLICATION_ID "chat.fluffy.fluffychat")
 | 
			
		||||
 | 
			
		||||
cmake_policy(SET CMP0063 NEW)
 | 
			
		||||
 | 
			
		||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
 | 
			
		||||
 | 
			
		||||
# Configure build options.
 | 
			
		||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
 | 
			
		||||
  set(CMAKE_BUILD_TYPE "Debug" CACHE
 | 
			
		||||
    STRING "Flutter build mode" FORCE)
 | 
			
		||||
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
 | 
			
		||||
    "Debug" "Profile" "Release")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
# Compilation settings that should be applied to most targets.
 | 
			
		||||
function(APPLY_STANDARD_SETTINGS TARGET)
 | 
			
		||||
  target_compile_features(${TARGET} PUBLIC cxx_std_14)
 | 
			
		||||
  target_compile_options(${TARGET} PRIVATE -Wall -Werror)
 | 
			
		||||
  target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
 | 
			
		||||
  target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
 | 
			
		||||
 | 
			
		||||
# Flutter library and tool build rules.
 | 
			
		||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
 | 
			
		||||
 | 
			
		||||
# System-level dependencies.
 | 
			
		||||
find_package(PkgConfig REQUIRED)
 | 
			
		||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
 | 
			
		||||
 | 
			
		||||
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
 | 
			
		||||
 | 
			
		||||
# Application build
 | 
			
		||||
add_executable(${BINARY_NAME}
 | 
			
		||||
  "main.cc"
 | 
			
		||||
  "my_application.cc"
 | 
			
		||||
  "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
 | 
			
		||||
)
 | 
			
		||||
apply_standard_settings(${BINARY_NAME})
 | 
			
		||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
 | 
			
		||||
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
 | 
			
		||||
add_dependencies(${BINARY_NAME} flutter_assemble)
 | 
			
		||||
 | 
			
		||||
# Generated plugin build rules, which manage building the plugins and adding
 | 
			
		||||
# them to the application.
 | 
			
		||||
include(flutter/generated_plugins.cmake)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# === Installation ===
 | 
			
		||||
# By default, "installing" just makes a relocatable bundle in the build
 | 
			
		||||
# directory.
 | 
			
		||||
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
 | 
			
		||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
 | 
			
		||||
  set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
# Start with a clean build bundle directory every time.
 | 
			
		||||
install(CODE "
 | 
			
		||||
  file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
 | 
			
		||||
  " COMPONENT Runtime)
 | 
			
		||||
 | 
			
		||||
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
 | 
			
		||||
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
 | 
			
		||||
 | 
			
		||||
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
 | 
			
		||||
  COMPONENT Runtime)
 | 
			
		||||
 | 
			
		||||
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
 | 
			
		||||
  COMPONENT Runtime)
 | 
			
		||||
 | 
			
		||||
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
 | 
			
		||||
  COMPONENT Runtime)
 | 
			
		||||
 | 
			
		||||
if(PLUGIN_BUNDLED_LIBRARIES)
 | 
			
		||||
  install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
 | 
			
		||||
    DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
 | 
			
		||||
    COMPONENT Runtime)
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
# Fully re-copy the assets directory on each build to avoid having stale files
 | 
			
		||||
# from a previous install.
 | 
			
		||||
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
 | 
			
		||||
install(CODE "
 | 
			
		||||
  file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
 | 
			
		||||
  " COMPONENT Runtime)
 | 
			
		||||
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
 | 
			
		||||
  DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
 | 
			
		||||
 | 
			
		||||
# Install the AOT library on non-Debug builds only.
 | 
			
		||||
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
 | 
			
		||||
  install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
 | 
			
		||||
    COMPONENT Runtime)
 | 
			
		||||
endif()
 | 
			
		||||
@ -0,0 +1,88 @@
 | 
			
		||||
cmake_minimum_required(VERSION 3.10)
 | 
			
		||||
 | 
			
		||||
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
 | 
			
		||||
 | 
			
		||||
# Configuration provided via flutter tool.
 | 
			
		||||
include(${EPHEMERAL_DIR}/generated_config.cmake)
 | 
			
		||||
 | 
			
		||||
# TODO: Move the rest of this into files in ephemeral. See
 | 
			
		||||
# https://github.com/flutter/flutter/issues/57146.
 | 
			
		||||
 | 
			
		||||
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
 | 
			
		||||
# which isn't available in 3.10.
 | 
			
		||||
function(list_prepend LIST_NAME PREFIX)
 | 
			
		||||
    set(NEW_LIST "")
 | 
			
		||||
    foreach(element ${${LIST_NAME}})
 | 
			
		||||
        list(APPEND NEW_LIST "${PREFIX}${element}")
 | 
			
		||||
    endforeach(element)
 | 
			
		||||
    set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
 | 
			
		||||
endfunction()
 | 
			
		||||
 | 
			
		||||
# === Flutter Library ===
 | 
			
		||||
# System-level dependencies.
 | 
			
		||||
find_package(PkgConfig REQUIRED)
 | 
			
		||||
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
 | 
			
		||||
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
 | 
			
		||||
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
 | 
			
		||||
pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid)
 | 
			
		||||
 | 
			
		||||
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
 | 
			
		||||
 | 
			
		||||
# Published to parent scope for install step.
 | 
			
		||||
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
 | 
			
		||||
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
 | 
			
		||||
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
 | 
			
		||||
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
 | 
			
		||||
 | 
			
		||||
list(APPEND FLUTTER_LIBRARY_HEADERS
 | 
			
		||||
  "fl_basic_message_channel.h"
 | 
			
		||||
  "fl_binary_codec.h"
 | 
			
		||||
  "fl_binary_messenger.h"
 | 
			
		||||
  "fl_dart_project.h"
 | 
			
		||||
  "fl_engine.h"
 | 
			
		||||
  "fl_json_message_codec.h"
 | 
			
		||||
  "fl_json_method_codec.h"
 | 
			
		||||
  "fl_message_codec.h"
 | 
			
		||||
  "fl_method_call.h"
 | 
			
		||||
  "fl_method_channel.h"
 | 
			
		||||
  "fl_method_codec.h"
 | 
			
		||||
  "fl_method_response.h"
 | 
			
		||||
  "fl_plugin_registrar.h"
 | 
			
		||||
  "fl_plugin_registry.h"
 | 
			
		||||
  "fl_standard_message_codec.h"
 | 
			
		||||
  "fl_standard_method_codec.h"
 | 
			
		||||
  "fl_string_codec.h"
 | 
			
		||||
  "fl_value.h"
 | 
			
		||||
  "fl_view.h"
 | 
			
		||||
  "flutter_linux.h"
 | 
			
		||||
)
 | 
			
		||||
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
 | 
			
		||||
add_library(flutter INTERFACE)
 | 
			
		||||
target_include_directories(flutter INTERFACE
 | 
			
		||||
  "${EPHEMERAL_DIR}"
 | 
			
		||||
)
 | 
			
		||||
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
 | 
			
		||||
target_link_libraries(flutter INTERFACE
 | 
			
		||||
  PkgConfig::GTK
 | 
			
		||||
  PkgConfig::GLIB
 | 
			
		||||
  PkgConfig::GIO
 | 
			
		||||
  PkgConfig::BLKID
 | 
			
		||||
)
 | 
			
		||||
add_dependencies(flutter flutter_assemble)
 | 
			
		||||
 | 
			
		||||
# === Flutter tool backend ===
 | 
			
		||||
# _phony_ is a non-existent file to force this command to run every time,
 | 
			
		||||
# since currently there's no way to get a full input/output list from the
 | 
			
		||||
# flutter tool.
 | 
			
		||||
add_custom_command(
 | 
			
		||||
  OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
 | 
			
		||||
    ${CMAKE_CURRENT_BINARY_DIR}/_phony_
 | 
			
		||||
  COMMAND ${CMAKE_COMMAND} -E env
 | 
			
		||||
    ${FLUTTER_TOOL_ENVIRONMENT}
 | 
			
		||||
    "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
 | 
			
		||||
      linux-x64 ${CMAKE_BUILD_TYPE}
 | 
			
		||||
)
 | 
			
		||||
add_custom_target(flutter_assemble DEPENDS
 | 
			
		||||
  "${FLUTTER_LIBRARY}"
 | 
			
		||||
  ${FLUTTER_LIBRARY_HEADERS}
 | 
			
		||||
)
 | 
			
		||||
@ -0,0 +1,13 @@
 | 
			
		||||
//
 | 
			
		||||
//  Generated file. Do not edit.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include "generated_plugin_registrant.h"
 | 
			
		||||
 | 
			
		||||
#include <url_launcher_linux/url_launcher_plugin.h>
 | 
			
		||||
 | 
			
		||||
void fl_register_plugins(FlPluginRegistry* registry) {
 | 
			
		||||
  g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
 | 
			
		||||
      fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
 | 
			
		||||
  url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,13 @@
 | 
			
		||||
//
 | 
			
		||||
//  Generated file. Do not edit.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
 | 
			
		||||
#define GENERATED_PLUGIN_REGISTRANT_
 | 
			
		||||
 | 
			
		||||
#include <flutter_linux/flutter_linux.h>
 | 
			
		||||
 | 
			
		||||
// Registers Flutter plugins.
 | 
			
		||||
void fl_register_plugins(FlPluginRegistry* registry);
 | 
			
		||||
 | 
			
		||||
#endif  // GENERATED_PLUGIN_REGISTRANT_
 | 
			
		||||
@ -0,0 +1,16 @@
 | 
			
		||||
#
 | 
			
		||||
# Generated file, do not edit.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
list(APPEND FLUTTER_PLUGIN_LIST
 | 
			
		||||
  url_launcher_linux
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set(PLUGIN_BUNDLED_LIBRARIES)
 | 
			
		||||
 | 
			
		||||
foreach(plugin ${FLUTTER_PLUGIN_LIST})
 | 
			
		||||
  add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
 | 
			
		||||
  target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
 | 
			
		||||
  list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
 | 
			
		||||
  list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
 | 
			
		||||
endforeach(plugin)
 | 
			
		||||
@ -0,0 +1,10 @@
 | 
			
		||||
#include "my_application.h"
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv) {
 | 
			
		||||
  // Only X11 is currently supported.
 | 
			
		||||
  // Wayland support is being developed: https://github.com/flutter/flutter/issues/57932.
 | 
			
		||||
  gdk_set_allowed_backends("x11");
 | 
			
		||||
 | 
			
		||||
  g_autoptr(MyApplication) app = my_application_new();
 | 
			
		||||
  return g_application_run(G_APPLICATION(app), argc, argv);
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,46 @@
 | 
			
		||||
#include "my_application.h"
 | 
			
		||||
 | 
			
		||||
#include <flutter_linux/flutter_linux.h>
 | 
			
		||||
 | 
			
		||||
#include "flutter/generated_plugin_registrant.h"
 | 
			
		||||
 | 
			
		||||
struct _MyApplication {
 | 
			
		||||
  GtkApplication parent_instance;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
 | 
			
		||||
 | 
			
		||||
// Implements GApplication::activate.
 | 
			
		||||
static void my_application_activate(GApplication* application) {
 | 
			
		||||
  GtkWindow* window =
 | 
			
		||||
      GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
 | 
			
		||||
  GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
 | 
			
		||||
  gtk_widget_show(GTK_WIDGET(header_bar));
 | 
			
		||||
  gtk_header_bar_set_title(header_bar, "fluffychat");
 | 
			
		||||
  gtk_header_bar_set_show_close_button(header_bar, TRUE);
 | 
			
		||||
  gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
 | 
			
		||||
  gtk_window_set_default_size(window, 1280, 720);
 | 
			
		||||
  gtk_widget_show(GTK_WIDGET(window));
 | 
			
		||||
 | 
			
		||||
  g_autoptr(FlDartProject) project = fl_dart_project_new();
 | 
			
		||||
 | 
			
		||||
  FlView* view = fl_view_new(project);
 | 
			
		||||
  gtk_widget_show(GTK_WIDGET(view));
 | 
			
		||||
  gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
 | 
			
		||||
 | 
			
		||||
  fl_register_plugins(FL_PLUGIN_REGISTRY(view));
 | 
			
		||||
 | 
			
		||||
  gtk_widget_grab_focus(GTK_WIDGET(view));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void my_application_class_init(MyApplicationClass* klass) {
 | 
			
		||||
  G_APPLICATION_CLASS(klass)->activate = my_application_activate;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void my_application_init(MyApplication* self) {}
 | 
			
		||||
 | 
			
		||||
MyApplication* my_application_new() {
 | 
			
		||||
  return MY_APPLICATION(g_object_new(my_application_get_type(),
 | 
			
		||||
                                     "application-id", APPLICATION_ID,
 | 
			
		||||
                                     nullptr));
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
#ifndef FLUTTER_MY_APPLICATION_H_
 | 
			
		||||
#define FLUTTER_MY_APPLICATION_H_
 | 
			
		||||
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
 | 
			
		||||
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
 | 
			
		||||
                     GtkApplication)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * my_application_new:
 | 
			
		||||
 *
 | 
			
		||||
 * Creates a new Flutter-based application.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns: a new #MyApplication.
 | 
			
		||||
 */
 | 
			
		||||
MyApplication* my_application_new();
 | 
			
		||||
 | 
			
		||||
#endif  // FLUTTER_MY_APPLICATION_H_
 | 
			
		||||
@ -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/
 | 
			
		||||
@ -0,0 +1,95 @@
 | 
			
		||||
cmake_minimum_required(VERSION 3.15)
 | 
			
		||||
project(fluffychat LANGUAGES CXX)
 | 
			
		||||
 | 
			
		||||
set(BINARY_NAME "fluffychat")
 | 
			
		||||
 | 
			
		||||
cmake_policy(SET CMP0063 NEW)
 | 
			
		||||
 | 
			
		||||
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
 | 
			
		||||
 | 
			
		||||
# Configure build options.
 | 
			
		||||
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()
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
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()
 | 
			
		||||
 | 
			
		||||
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
 | 
			
		||||
 | 
			
		||||
# Flutter library and tool build rules.
 | 
			
		||||
add_subdirectory(${FLUTTER_MANAGED_DIR})
 | 
			
		||||
 | 
			
		||||
# Application build
 | 
			
		||||
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()
 | 
			
		||||
 | 
			
		||||
# 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)
 | 
			
		||||
@ -0,0 +1 @@
 | 
			
		||||
5
 | 
			
		||||
@ -0,0 +1,99 @@
 | 
			
		||||
cmake_minimum_required(VERSION 3.15)
 | 
			
		||||
 | 
			
		||||
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")
 | 
			
		||||
 | 
			
		||||
# === 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"
 | 
			
		||||
)
 | 
			
		||||
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
 | 
			
		||||
  "engine_method_result.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.
 | 
			
		||||
add_custom_command(
 | 
			
		||||
  OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
 | 
			
		||||
    ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
 | 
			
		||||
    ${CPP_WRAPPER_SOURCES_APP}
 | 
			
		||||
    ${CMAKE_CURRENT_BINARY_DIR}/_phony_
 | 
			
		||||
  COMMAND ${CMAKE_COMMAND} -E env
 | 
			
		||||
    ${FLUTTER_TOOL_ENVIRONMENT}
 | 
			
		||||
    "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
 | 
			
		||||
      windows-x64 $<CONFIG>
 | 
			
		||||
)
 | 
			
		||||
add_custom_target(flutter_assemble DEPENDS
 | 
			
		||||
  "${FLUTTER_LIBRARY}"
 | 
			
		||||
  ${FLUTTER_LIBRARY_HEADERS}
 | 
			
		||||
  ${CPP_WRAPPER_SOURCES_CORE}
 | 
			
		||||
  ${CPP_WRAPPER_SOURCES_PLUGIN}
 | 
			
		||||
  ${CPP_WRAPPER_SOURCES_APP}
 | 
			
		||||
)
 | 
			
		||||
@ -0,0 +1,12 @@
 | 
			
		||||
//
 | 
			
		||||
//  Generated file. Do not edit.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include "generated_plugin_registrant.h"
 | 
			
		||||
 | 
			
		||||
#include <url_launcher_windows/url_launcher_plugin.h>
 | 
			
		||||
 | 
			
		||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
 | 
			
		||||
  UrlLauncherPluginRegisterWithRegistrar(
 | 
			
		||||
      registry->GetRegistrarForPlugin("UrlLauncherPlugin"));
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,13 @@
 | 
			
		||||
//
 | 
			
		||||
//  Generated file. Do not edit.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#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_
 | 
			
		||||
@ -0,0 +1,16 @@
 | 
			
		||||
#
 | 
			
		||||
# Generated file, do not edit.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
list(APPEND FLUTTER_PLUGIN_LIST
 | 
			
		||||
  url_launcher_windows
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
cmake_minimum_required(VERSION 3.15)
 | 
			
		||||
project(runner LANGUAGES CXX)
 | 
			
		||||
 | 
			
		||||
add_executable(${BINARY_NAME} WIN32
 | 
			
		||||
  "flutter_window.cpp"
 | 
			
		||||
  "main.cpp"
 | 
			
		||||
  "run_loop.cpp"
 | 
			
		||||
  "utils.cpp"
 | 
			
		||||
  "win32_window.cpp"
 | 
			
		||||
  "window_configuration.cpp"
 | 
			
		||||
  "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
 | 
			
		||||
  "Runner.rc"
 | 
			
		||||
  "runner.exe.manifest"
 | 
			
		||||
)
 | 
			
		||||
apply_standard_settings(${BINARY_NAME})
 | 
			
		||||
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
 | 
			
		||||
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
 | 
			
		||||
add_dependencies(${BINARY_NAME} flutter_assemble)
 | 
			
		||||
@ -0,0 +1,70 @@
 | 
			
		||||
// 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"
 | 
			
		||||
 | 
			
		||||
#endif    // English (United States) resources
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef APSTUDIO_INVOKED
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// Generated from the TEXTINCLUDE 3 resource.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
#endif    // not APSTUDIO_INVOKED
 | 
			
		||||
@ -0,0 +1,29 @@
 | 
			
		||||
#include "flutter_window.h"
 | 
			
		||||
 | 
			
		||||
#include "flutter/generated_plugin_registrant.h"
 | 
			
		||||
 | 
			
		||||
FlutterWindow::FlutterWindow(RunLoop* run_loop,
 | 
			
		||||
                             const flutter::DartProject& project)
 | 
			
		||||
    : run_loop_(run_loop), project_(project) {}
 | 
			
		||||
 | 
			
		||||
FlutterWindow::~FlutterWindow() {}
 | 
			
		||||
 | 
			
		||||
void FlutterWindow::OnCreate() {
 | 
			
		||||
  Win32Window::OnCreate();
 | 
			
		||||
 | 
			
		||||
  // The size here is arbitrary since SetChildContent will resize it.
 | 
			
		||||
  flutter_controller_ =
 | 
			
		||||
      std::make_unique<flutter::FlutterViewController>(100, 100, project_);
 | 
			
		||||
  RegisterPlugins(flutter_controller_.get());
 | 
			
		||||
  run_loop_->RegisterFlutterInstance(flutter_controller_.get());
 | 
			
		||||
  SetChildContent(flutter_controller_->view()->GetNativeWindow());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FlutterWindow::OnDestroy() {
 | 
			
		||||
  if (flutter_controller_) {
 | 
			
		||||
    run_loop_->UnregisterFlutterInstance(flutter_controller_.get());
 | 
			
		||||
    flutter_controller_ = nullptr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Win32Window::OnDestroy();
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,37 @@
 | 
			
		||||
#ifndef FLUTTER_WINDOW_H_
 | 
			
		||||
#define FLUTTER_WINDOW_H_
 | 
			
		||||
 | 
			
		||||
#include <flutter/dart_project.h>
 | 
			
		||||
#include <flutter/flutter_view_controller.h>
 | 
			
		||||
 | 
			
		||||
#include "run_loop.h"
 | 
			
		||||
#include "win32_window.h"
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
// A window that does nothing but host a Flutter view.
 | 
			
		||||
class FlutterWindow : public Win32Window {
 | 
			
		||||
 public:
 | 
			
		||||
  // Creates a new FlutterWindow driven by the |run_loop|, hosting a
 | 
			
		||||
  // Flutter view running |project|.
 | 
			
		||||
  explicit FlutterWindow(RunLoop* run_loop,
 | 
			
		||||
                         const flutter::DartProject& project);
 | 
			
		||||
  virtual ~FlutterWindow();
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  // Win32Window:
 | 
			
		||||
  void OnCreate() override;
 | 
			
		||||
  void OnDestroy() override;
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // The run loop driving events for this window.
 | 
			
		||||
  RunLoop* run_loop_;
 | 
			
		||||
 | 
			
		||||
  // The project to run.
 | 
			
		||||
  flutter::DartProject project_;
 | 
			
		||||
 | 
			
		||||
  // The Flutter instance hosted by this window.
 | 
			
		||||
  std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  // FLUTTER_WINDOW_H_
 | 
			
		||||
@ -0,0 +1,37 @@
 | 
			
		||||
#include <flutter/dart_project.h>
 | 
			
		||||
#include <flutter/flutter_view_controller.h>
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
 | 
			
		||||
#include "flutter_window.h"
 | 
			
		||||
#include "run_loop.h"
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include "window_configuration.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);
 | 
			
		||||
 | 
			
		||||
  RunLoop run_loop;
 | 
			
		||||
 | 
			
		||||
  flutter::DartProject project(L"data");
 | 
			
		||||
  FlutterWindow window(&run_loop, project);
 | 
			
		||||
  Win32Window::Point origin(kFlutterWindowOriginX, kFlutterWindowOriginY);
 | 
			
		||||
  Win32Window::Size size(kFlutterWindowWidth, kFlutterWindowHeight);
 | 
			
		||||
  if (!window.CreateAndShow(kFlutterWindowTitle, origin, size)) {
 | 
			
		||||
    return EXIT_FAILURE;
 | 
			
		||||
  }
 | 
			
		||||
  window.SetQuitOnClose(true);
 | 
			
		||||
 | 
			
		||||
  run_loop.Run();
 | 
			
		||||
 | 
			
		||||
  ::CoUninitialize();
 | 
			
		||||
  return EXIT_SUCCESS;
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
											
												Binary file not shown.
											
										
									
								| 
		 After Width: | Height: | Size: 33 KiB  | 
@ -0,0 +1,70 @@
 | 
			
		||||
#include "run_loop.h"
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
// Don't stomp std::min/std::max
 | 
			
		||||
#undef max
 | 
			
		||||
#undef min
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
RunLoop::RunLoop() {}
 | 
			
		||||
 | 
			
		||||
RunLoop::~RunLoop() {}
 | 
			
		||||
 | 
			
		||||
void RunLoop::Run() {
 | 
			
		||||
  bool keep_running = true;
 | 
			
		||||
  TimePoint next_flutter_event_time = TimePoint::clock::now();
 | 
			
		||||
  while (keep_running) {
 | 
			
		||||
    std::chrono::nanoseconds wait_duration =
 | 
			
		||||
        std::max(std::chrono::nanoseconds(0),
 | 
			
		||||
                 next_flutter_event_time - TimePoint::clock::now());
 | 
			
		||||
    ::MsgWaitForMultipleObjects(
 | 
			
		||||
        0, nullptr, FALSE, static_cast<DWORD>(wait_duration.count() / 1000),
 | 
			
		||||
        QS_ALLINPUT);
 | 
			
		||||
    bool processed_events = false;
 | 
			
		||||
    MSG message;
 | 
			
		||||
    // All pending Windows messages must be processed; MsgWaitForMultipleObjects
 | 
			
		||||
    // won't return again for items left in the queue after PeekMessage.
 | 
			
		||||
    while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) {
 | 
			
		||||
      processed_events = true;
 | 
			
		||||
      if (message.message == WM_QUIT) {
 | 
			
		||||
        keep_running = false;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      ::TranslateMessage(&message);
 | 
			
		||||
      ::DispatchMessage(&message);
 | 
			
		||||
      // Allow Flutter to process messages each time a Windows message is
 | 
			
		||||
      // processed, to prevent starvation.
 | 
			
		||||
      next_flutter_event_time =
 | 
			
		||||
          std::min(next_flutter_event_time, ProcessFlutterMessages());
 | 
			
		||||
    }
 | 
			
		||||
    // If the PeekMessage loop didn't run, process Flutter messages.
 | 
			
		||||
    if (!processed_events) {
 | 
			
		||||
      next_flutter_event_time =
 | 
			
		||||
          std::min(next_flutter_event_time, ProcessFlutterMessages());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RunLoop::RegisterFlutterInstance(
 | 
			
		||||
    flutter::FlutterViewController* flutter_instance) {
 | 
			
		||||
  flutter_instances_.insert(flutter_instance);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RunLoop::UnregisterFlutterInstance(
 | 
			
		||||
    flutter::FlutterViewController* flutter_instance) {
 | 
			
		||||
  flutter_instances_.erase(flutter_instance);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RunLoop::TimePoint RunLoop::ProcessFlutterMessages() {
 | 
			
		||||
  TimePoint next_event_time = TimePoint::max();
 | 
			
		||||
  for (auto flutter_controller : flutter_instances_) {
 | 
			
		||||
    std::chrono::nanoseconds wait_duration =
 | 
			
		||||
        flutter_controller->ProcessMessages();
 | 
			
		||||
    if (wait_duration != std::chrono::nanoseconds::max()) {
 | 
			
		||||
      next_event_time =
 | 
			
		||||
          std::min(next_event_time, TimePoint::clock::now() + wait_duration);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return next_event_time;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,40 @@
 | 
			
		||||
#ifndef RUN_LOOP_H_
 | 
			
		||||
#define RUN_LOOP_H_
 | 
			
		||||
 | 
			
		||||
#include <flutter/flutter_view_controller.h>
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
// A runloop that will service events for Flutter instances as well
 | 
			
		||||
// as native messages.
 | 
			
		||||
class RunLoop {
 | 
			
		||||
 public:
 | 
			
		||||
  RunLoop();
 | 
			
		||||
  ~RunLoop();
 | 
			
		||||
 | 
			
		||||
  // Prevent copying
 | 
			
		||||
  RunLoop(RunLoop const&) = delete;
 | 
			
		||||
  RunLoop& operator=(RunLoop const&) = delete;
 | 
			
		||||
 | 
			
		||||
  // Runs the run loop until the application quits.
 | 
			
		||||
  void Run();
 | 
			
		||||
 | 
			
		||||
  // Registers the given Flutter instance for event servicing.
 | 
			
		||||
  void RegisterFlutterInstance(
 | 
			
		||||
      flutter::FlutterViewController* flutter_instance);
 | 
			
		||||
 | 
			
		||||
  // Unregisters the given Flutter instance from event servicing.
 | 
			
		||||
  void UnregisterFlutterInstance(
 | 
			
		||||
      flutter::FlutterViewController* flutter_instance);
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  using TimePoint = std::chrono::steady_clock::time_point;
 | 
			
		||||
 | 
			
		||||
  // Processes all currently pending messages for registered Flutter instances.
 | 
			
		||||
  TimePoint ProcessFlutterMessages();
 | 
			
		||||
 | 
			
		||||
  std::set<flutter::FlutterViewController*> flutter_instances_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  // RUN_LOOP_H_
 | 
			
		||||
@ -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 -->
 | 
			
		||||
      <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>
 | 
			
		||||
@ -0,0 +1,22 @@
 | 
			
		||||
#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();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
#ifndef CONSOLE_UTILS_H_
 | 
			
		||||
#define CONSOLE_UTILS_H_
 | 
			
		||||
 | 
			
		||||
// Creates a console for the process, and redirects stdout and stderr to
 | 
			
		||||
// it for both the runner and the Flutter library.
 | 
			
		||||
void CreateAndAttachConsole();
 | 
			
		||||
 | 
			
		||||
#endif  // CONSOLE_UTILS_H_
 | 
			
		||||
@ -0,0 +1,249 @@
 | 
			
		||||
#include "win32_window.h"
 | 
			
		||||
 | 
			
		||||
#include <flutter_windows.h>
 | 
			
		||||
 | 
			
		||||
#include "resource.h"
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
 | 
			
		||||
 | 
			
		||||
// 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 registar 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::CreateAndShow(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 | WS_VISIBLE,
 | 
			
		||||
      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);
 | 
			
		||||
 | 
			
		||||
  OnCreate();
 | 
			
		||||
 | 
			
		||||
  return window != nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
  auto window =
 | 
			
		||||
      reinterpret_cast<Win32Window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
 | 
			
		||||
 | 
			
		||||
  if (window == nullptr) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
      GetClientRect(hwnd, &rect);
 | 
			
		||||
      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;
 | 
			
		||||
 | 
			
		||||
    // Messages that are directly forwarded to embedding.
 | 
			
		||||
    case WM_FONTCHANGE:
 | 
			
		||||
      SendMessage(child_content_, WM_FONTCHANGE, NULL, NULL);
 | 
			
		||||
      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;
 | 
			
		||||
  GetClientRect(window_handle_, &frame);
 | 
			
		||||
 | 
			
		||||
  MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
 | 
			
		||||
             frame.bottom - frame.top, true);
 | 
			
		||||
 | 
			
		||||
  SetFocus(child_content_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HWND Win32Window::GetHandle() {
 | 
			
		||||
  return window_handle_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Win32Window::SetQuitOnClose(bool quit_on_close) {
 | 
			
		||||
  quit_on_close_ = quit_on_close;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Win32Window::OnCreate() {
 | 
			
		||||
  // No-op; provided for subclasses.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Win32Window::OnDestroy() {
 | 
			
		||||
  // No-op; provided for subclasses.
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,96 @@
 | 
			
		||||
#ifndef WIN32_WINDOW_H_
 | 
			
		||||
#define WIN32_WINDOW_H_
 | 
			
		||||
 | 
			
		||||
#include <Windows.h>
 | 
			
		||||
#include <Windowsx.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 and shows a win32 window with |title| and position and size 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 to will treat the width height passed in to this function
 | 
			
		||||
  // as logical pixels and scale to appropriate for the default monitor. Returns
 | 
			
		||||
  // true if the window was created successfully.
 | 
			
		||||
  bool CreateAndShow(const std::wstring& title,
 | 
			
		||||
                     const Point& origin,
 | 
			
		||||
                     const Size& size);
 | 
			
		||||
 | 
			
		||||
  // 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);
 | 
			
		||||
 | 
			
		||||
 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.
 | 
			
		||||
  virtual void 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
 | 
			
		||||
  // responsponds 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;
 | 
			
		||||
 | 
			
		||||
  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  // WIN32_WINDOW_H_
 | 
			
		||||
@ -0,0 +1,7 @@
 | 
			
		||||
#include "window_configuration.h"
 | 
			
		||||
 | 
			
		||||
const wchar_t* kFlutterWindowTitle = L"fluffychat";
 | 
			
		||||
const unsigned int kFlutterWindowOriginX = 10;
 | 
			
		||||
const unsigned int kFlutterWindowOriginY = 10;
 | 
			
		||||
const unsigned int kFlutterWindowWidth = 1280;
 | 
			
		||||
const unsigned int kFlutterWindowHeight = 720;
 | 
			
		||||
@ -0,0 +1,18 @@
 | 
			
		||||
#ifndef WINDOW_CONFIGURATION_
 | 
			
		||||
#define WINDOW_CONFIGURATION_
 | 
			
		||||
 | 
			
		||||
// This is a temporary approach to isolate changes that people are likely to
 | 
			
		||||
// make to main.cpp, where the APIs are still in flux. This will reduce the
 | 
			
		||||
// need to resolve conflicts or re-create changes slightly differently every
 | 
			
		||||
// time the Windows Flutter API surface changes.
 | 
			
		||||
//
 | 
			
		||||
// Longer term there should be simpler configuration options for common
 | 
			
		||||
// customizations like this, without requiring native code changes.
 | 
			
		||||
 | 
			
		||||
extern const wchar_t* kFlutterWindowTitle;
 | 
			
		||||
extern const unsigned int kFlutterWindowOriginX;
 | 
			
		||||
extern const unsigned int kFlutterWindowOriginY;
 | 
			
		||||
extern const unsigned int kFlutterWindowWidth;
 | 
			
		||||
extern const unsigned int kFlutterWindowHeight;
 | 
			
		||||
 | 
			
		||||
#endif  // WINDOW_CONFIGURATION_
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue