From ee12a4366b6cdb5380674d082a9e77ff45ef1594 Mon Sep 17 00:00:00 2001 From: Michele Maione Date: Wed, 10 Apr 2024 16:09:29 +0200 Subject: [PATCH] build: add Windows github build workflow --- .github/workflows/windows.yaml | 50 ++++++++++++++++++++++++++ assets/favicon.ico | Bin 0 -> 28685 bytes pubspec.lock | 28 +++++++++++++-- pubspec.yaml | 11 ++++++ windows/CMakeLists.txt | 8 ++++- windows/flutter/CMakeLists.txt | 7 +++- windows/runner/CMakeLists.txt | 8 +++++ windows/runner/Runner.rc | 10 +++--- windows/runner/flutter_window.cpp | 10 ++++++ windows/runner/main.cpp | 2 +- windows/runner/runner.exe.manifest | 2 +- windows/runner/utils.cpp | 9 ++--- windows/runner/win32_window.cpp | 55 +++++++++++++++++++++++++---- windows/runner/win32_window.h | 20 ++++++----- 14 files changed, 191 insertions(+), 29 deletions(-) create mode 100644 .github/workflows/windows.yaml create mode 100644 assets/favicon.ico diff --git a/.github/workflows/windows.yaml b/.github/workflows/windows.yaml new file mode 100644 index 00000000..5acf0da1 --- /dev/null +++ b/.github/workflows/windows.yaml @@ -0,0 +1,50 @@ +name: Release Workflow Windows + +on: + release: + types: + - created + +concurrency: + group: release_workflow + cancel-in-progress: true + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-windows: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + - run: cat .github/workflows/versions.env >> $GITHUB_ENV + + - uses: subosito/flutter-action@v2 + with: + flutter-version: ${{ env.FLUTTER_VERSION }} + cache: true + + - name: Build Windows App + run: | + flutter config --enable-windows-desktop + flutter build windows --release + + - name: Build iss script + run: dart run inno_bundle:build --no-app --release --no-installer + + - name: Output config into github output + id: envs + # thanks to https://github.com/actions/runner/issues/2224#issuecomment-1289925992 + run: echo $(dart run inno_bundle:build --envs --no-hf --release) | Out-File -FilePath $Env:GITHUB_OUTPUT -Encoding utf8 -Append + + - name: Build installer + uses: Minionguyjpro/Inno-Setup-Action@v1.2.2 + with: + path: ./build/windows/x64/installer/Release/inno-script.iss + + - name: Upload release + uses: softprops/action-gh-release@v2 + with: + files: ./build/windows/x64/installer/Release/${{ steps.envs.outputs.APP_NAME_CAMEL_CASE }}-x86_64-${{ steps.envs.outputs.APP_VERSION }}-Installer.exe diff --git a/assets/favicon.ico b/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3826006233b90cb2044310f498f4b135382d82f5 GIT binary patch literal 28685 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 literal 0 HcmV?d00001 diff --git a/pubspec.lock b/pubspec.lock index 24d0e5a8..ea47a973 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -433,6 +433,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -1000,6 +1008,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.6.0" + inno_bundle: + dependency: "direct dev" + description: + name: inno_bundle + sha256: "05b18d03142bfbaf708f340e007a04d50cc24295195c5ddf9f1c102978878335" + url: "https://pub.dev" + source: hosted + version: "0.4.1" integration_test: dependency: "direct dev" description: flutter @@ -1867,6 +1883,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" sqflite: dependency: transitive description: @@ -2199,10 +2223,10 @@ packages: dependency: transitive description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + sha256: "814e9e88f21a176ae1359149021870e87f7cddaf633ab678a5d2b0bff7fd1ba8" url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "4.4.0" vector_graphics: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2c7d5894..f822edd3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -101,6 +101,7 @@ dev_dependencies: flutter_test: sdk: flutter import_sorter: ^4.6.0 + inno_bundle: ^0.4.1 integration_test: sdk: flutter license_checker: ^1.6.0 @@ -149,6 +150,16 @@ msix_config: sign_msix: false install_certificate: false +inno_bundle: + id: 7c872d9b-2c56-56de-b8dc-3763cd082da9 # <-- dart run inno_bundle:id --ns "chat.fluffy.fluffychat" + name: FluffyChat + publisher: Famedly GmbH + admin: false + installer_icon: assets/favicon.ico + url: https://fluffychat.im + support_url: https://github.com/krille-chan/fluffychat/wiki + updates_url: https://github.com/krille-chan/fluffychat/releases + dependency_overrides: # Until https://github.com/mogol/flutter_secure_storage/issues/616 is fixed flutter_secure_storage_linux: 1.1.3 diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 1c2b9945..39645030 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -8,7 +8,7 @@ set(BINARY_NAME "fluffychat") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. -cmake_policy(SET CMP0063 NEW) +cmake_policy(VERSION 3.14...3.25) # Define build configuration option. get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) @@ -86,6 +86,12 @@ if(PLUGIN_BUNDLED_LIBRARIES) 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") diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt index 930d2071..903f4899 100644 --- a/windows/flutter/CMakeLists.txt +++ b/windows/flutter/CMakeLists.txt @@ -10,6 +10,11 @@ include(${EPHEMERAL_DIR}/generated_config.cmake) # 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") @@ -92,7 +97,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E env ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" - windows-x64 $ + ${FLUTTER_TARGET_PLATFORM} $ VERBATIM ) add_custom_target(flutter_assemble DEPENDS diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt index b9e550fb..394917c0 100644 --- a/windows/runner/CMakeLists.txt +++ b/windows/runner/CMakeLists.txt @@ -20,12 +20,20 @@ add_executable(${BINARY_NAME} WIN32 # 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. diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index 52aa4877..c11941c4 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -60,14 +60,14 @@ IDI_APP_ICON ICON "resources\\app_icon.ico" // Version // -#ifdef FLUTTER_BUILD_NUMBER -#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#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 +#define VERSION_AS_NUMBER 1,0,0,0 #endif -#ifdef FLUTTER_BUILD_NAME -#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION #else #define VERSION_AS_STRING "1.0.0" #endif diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp index b43b9095..955ee303 100644 --- a/windows/runner/flutter_window.cpp +++ b/windows/runner/flutter_window.cpp @@ -26,6 +26,16 @@ bool FlutterWindow::OnCreate() { } 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; } diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp index 3c2f3ab5..af7fea68 100644 --- a/windows/runner/main.cpp +++ b/windows/runner/main.cpp @@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); - if (!window.CreateAndShow(L"FluffyChat", origin, size)) { + if (!window.Create(L"FluffyChat", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest index c977c4a4..a42ea768 100644 --- a/windows/runner/runner.exe.manifest +++ b/windows/runner/runner.exe.manifest @@ -7,7 +7,7 @@ - + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp index f5bf9fa0..b2b08734 100644 --- a/windows/runner/utils.cpp +++ b/windows/runner/utils.cpp @@ -47,16 +47,17 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { } int target_length = ::WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr); + -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()) { + 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, - -1, utf8_string.data(), - target_length, nullptr, nullptr); + input_length, utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp index c10f08dc..60608d0f 100644 --- a/windows/runner/win32_window.cpp +++ b/windows/runner/win32_window.cpp @@ -1,13 +1,31 @@ #include "win32_window.h" +#include #include #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; @@ -31,8 +49,8 @@ void EnableFullDpiSupportIfAvailable(HWND hwnd) { GetProcAddress(user32_module, "EnableNonClientDpiScaling")); if (enable_non_client_dpi_scaling != nullptr) { enable_non_client_dpi_scaling(hwnd); - FreeLibrary(user32_module); } + FreeLibrary(user32_module); } } // namespace @@ -42,7 +60,7 @@ class WindowClassRegistrar { public: ~WindowClassRegistrar() = default; - // Returns the singleton registar instance. + // Returns the singleton registrar instance. static WindowClassRegistrar* GetInstance() { if (!instance_) { instance_ = new WindowClassRegistrar(); @@ -102,9 +120,9 @@ Win32Window::~Win32Window() { Destroy(); } -bool Win32Window::CreateAndShow(const std::wstring& title, - const Point& origin, - const Size& size) { +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { Destroy(); const wchar_t* window_class = @@ -117,7 +135,7 @@ bool Win32Window::CreateAndShow(const std::wstring& title, double scale_factor = dpi / 96.0; HWND window = CreateWindow( - window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 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); @@ -126,9 +144,15 @@ bool Win32Window::CreateAndShow(const std::wstring& title, 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, @@ -188,6 +212,10 @@ Win32Window::MessageHandler(HWND hwnd, SetFocus(child_content_); } return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; } return DefWindowProc(window_handle_, message, wparam, lparam); @@ -243,3 +271,18 @@ bool Win32Window::OnCreate() { 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)); + } +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h index 17ba4311..e901dde6 100644 --- a/windows/runner/win32_window.h +++ b/windows/runner/win32_window.h @@ -28,15 +28,16 @@ class Win32Window { Win32Window(); virtual ~Win32Window(); - // Creates and shows a win32 window with |title| and position and size using + // 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 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); + // 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(); @@ -76,7 +77,7 @@ class Win32Window { // 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 + // responds to changes in DPI. All other messages are handled by // MessageHandler. static LRESULT CALLBACK WndProc(HWND const window, UINT const message, @@ -86,6 +87,9 @@ class Win32Window { // 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.