Committed by
GitHub
Functional Windows implementation (#96)
* Basic windows implementation * Added details to of platform assign blocking issue * Handled response code on state set * Add additional docs
Showing
30 changed files
with
1292 additions
and
2 deletions
| @@ -40,6 +40,8 @@ dependency_overrides: | @@ -40,6 +40,8 @@ dependency_overrides: | ||
| 40 | # current platform implementations. | 40 | # current platform implementations. |
| 41 | wakelock_macos: | 41 | wakelock_macos: |
| 42 | path: ../../wakelock_macos | 42 | path: ../../wakelock_macos |
| 43 | + wakelock_windows: | ||
| 44 | + path: ../../wakelock_windows | ||
| 43 | wakelock_platform_interface: | 45 | wakelock_platform_interface: |
| 44 | path: ../../wakelock_platform_interface | 46 | path: ../../wakelock_platform_interface |
| 45 | wakelock_web: | 47 | wakelock_web: |
wakelock/example/windows/.gitignore
0 → 100644
| 1 | +flutter/ephemeral/ | ||
| 2 | + | ||
| 3 | +# Visual Studio user-specific files. | ||
| 4 | +*.suo | ||
| 5 | +*.user | ||
| 6 | +*.userosscache | ||
| 7 | +*.sln.docstates | ||
| 8 | + | ||
| 9 | +# Visual Studio build-related files. | ||
| 10 | +x64/ | ||
| 11 | +x86/ | ||
| 12 | + | ||
| 13 | +# Visual Studio cache files | ||
| 14 | +# files ending in .cache can be ignored | ||
| 15 | +*.[Cc]ache | ||
| 16 | +# but keep track of directories ending in .cache | ||
| 17 | +!*.[Cc]ache/ |
wakelock/example/windows/CMakeLists.txt
0 → 100644
| 1 | +cmake_minimum_required(VERSION 3.15) | ||
| 2 | +project(example LANGUAGES CXX) | ||
| 3 | + | ||
| 4 | +set(BINARY_NAME "example") | ||
| 5 | + | ||
| 6 | +cmake_policy(SET CMP0063 NEW) | ||
| 7 | + | ||
| 8 | +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") | ||
| 9 | + | ||
| 10 | +# Configure build options. | ||
| 11 | +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) | ||
| 12 | +if(IS_MULTICONFIG) | ||
| 13 | + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" | ||
| 14 | + CACHE STRING "" FORCE) | ||
| 15 | +else() | ||
| 16 | + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) | ||
| 17 | + set(CMAKE_BUILD_TYPE "Debug" CACHE | ||
| 18 | + STRING "Flutter build mode" FORCE) | ||
| 19 | + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS | ||
| 20 | + "Debug" "Profile" "Release") | ||
| 21 | + endif() | ||
| 22 | +endif() | ||
| 23 | + | ||
| 24 | +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") | ||
| 25 | +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") | ||
| 26 | +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") | ||
| 27 | +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") | ||
| 28 | + | ||
| 29 | +# Use Unicode for all projects. | ||
| 30 | +add_definitions(-DUNICODE -D_UNICODE) | ||
| 31 | + | ||
| 32 | +# Compilation settings that should be applied to most targets. | ||
| 33 | +function(APPLY_STANDARD_SETTINGS TARGET) | ||
| 34 | + target_compile_features(${TARGET} PUBLIC cxx_std_17) | ||
| 35 | + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") | ||
| 36 | + target_compile_options(${TARGET} PRIVATE /EHsc) | ||
| 37 | + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") | ||
| 38 | + target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>") | ||
| 39 | +endfunction() | ||
| 40 | + | ||
| 41 | +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") | ||
| 42 | + | ||
| 43 | +# Flutter library and tool build rules. | ||
| 44 | +add_subdirectory(${FLUTTER_MANAGED_DIR}) | ||
| 45 | + | ||
| 46 | +# Application build | ||
| 47 | +add_subdirectory("runner") | ||
| 48 | + | ||
| 49 | +# Generated plugin build rules, which manage building the plugins and adding | ||
| 50 | +# them to the application. | ||
| 51 | +include(flutter/generated_plugins.cmake) | ||
| 52 | + | ||
| 53 | + | ||
| 54 | +# === Installation === | ||
| 55 | +# Support files are copied into place next to the executable, so that it can | ||
| 56 | +# run in place. This is done instead of making a separate bundle (as on Linux) | ||
| 57 | +# so that building and running from within Visual Studio will work. | ||
| 58 | +set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>") | ||
| 59 | +# Make the "install" step default, as it's required to run. | ||
| 60 | +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) | ||
| 61 | +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) | ||
| 62 | + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) | ||
| 63 | +endif() | ||
| 64 | + | ||
| 65 | +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") | ||
| 66 | +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") | ||
| 67 | + | ||
| 68 | +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" | ||
| 69 | + COMPONENT Runtime) | ||
| 70 | + | ||
| 71 | +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | ||
| 72 | + COMPONENT Runtime) | ||
| 73 | + | ||
| 74 | +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 75 | + COMPONENT Runtime) | ||
| 76 | + | ||
| 77 | +if(PLUGIN_BUNDLED_LIBRARIES) | ||
| 78 | + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" | ||
| 79 | + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" | ||
| 80 | + COMPONENT Runtime) | ||
| 81 | +endif() | ||
| 82 | + | ||
| 83 | +# Fully re-copy the assets directory on each build to avoid having stale files | ||
| 84 | +# from a previous install. | ||
| 85 | +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") | ||
| 86 | +install(CODE " | ||
| 87 | + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") | ||
| 88 | + " COMPONENT Runtime) | ||
| 89 | +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" | ||
| 90 | + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) | ||
| 91 | + | ||
| 92 | +# Install the AOT library on non-Debug builds only. | ||
| 93 | +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" | ||
| 94 | + CONFIGURATIONS Profile;Release | ||
| 95 | + COMPONENT Runtime) |
| 1 | +cmake_minimum_required(VERSION 3.15) | ||
| 2 | + | ||
| 3 | +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") | ||
| 4 | + | ||
| 5 | +# Configuration provided via flutter tool. | ||
| 6 | +include(${EPHEMERAL_DIR}/generated_config.cmake) | ||
| 7 | + | ||
| 8 | +# TODO: Move the rest of this into files in ephemeral. See | ||
| 9 | +# https://github.com/flutter/flutter/issues/57146. | ||
| 10 | +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") | ||
| 11 | + | ||
| 12 | +# === Flutter Library === | ||
| 13 | +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") | ||
| 14 | + | ||
| 15 | +# Published to parent scope for install step. | ||
| 16 | +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) | ||
| 17 | +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) | ||
| 18 | +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) | ||
| 19 | +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) | ||
| 20 | + | ||
| 21 | +list(APPEND FLUTTER_LIBRARY_HEADERS | ||
| 22 | + "flutter_export.h" | ||
| 23 | + "flutter_windows.h" | ||
| 24 | + "flutter_messenger.h" | ||
| 25 | + "flutter_plugin_registrar.h" | ||
| 26 | + "flutter_texture_registrar.h" | ||
| 27 | +) | ||
| 28 | +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") | ||
| 29 | +add_library(flutter INTERFACE) | ||
| 30 | +target_include_directories(flutter INTERFACE | ||
| 31 | + "${EPHEMERAL_DIR}" | ||
| 32 | +) | ||
| 33 | +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") | ||
| 34 | +add_dependencies(flutter flutter_assemble) | ||
| 35 | + | ||
| 36 | +# === Wrapper === | ||
| 37 | +list(APPEND CPP_WRAPPER_SOURCES_CORE | ||
| 38 | + "core_implementations.cc" | ||
| 39 | + "standard_codec.cc" | ||
| 40 | +) | ||
| 41 | +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") | ||
| 42 | +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN | ||
| 43 | + "plugin_registrar.cc" | ||
| 44 | +) | ||
| 45 | +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") | ||
| 46 | +list(APPEND CPP_WRAPPER_SOURCES_APP | ||
| 47 | + "flutter_engine.cc" | ||
| 48 | + "flutter_view_controller.cc" | ||
| 49 | +) | ||
| 50 | +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") | ||
| 51 | + | ||
| 52 | +# Wrapper sources needed for a plugin. | ||
| 53 | +add_library(flutter_wrapper_plugin STATIC | ||
| 54 | + ${CPP_WRAPPER_SOURCES_CORE} | ||
| 55 | + ${CPP_WRAPPER_SOURCES_PLUGIN} | ||
| 56 | +) | ||
| 57 | +apply_standard_settings(flutter_wrapper_plugin) | ||
| 58 | +set_target_properties(flutter_wrapper_plugin PROPERTIES | ||
| 59 | + POSITION_INDEPENDENT_CODE ON) | ||
| 60 | +set_target_properties(flutter_wrapper_plugin PROPERTIES | ||
| 61 | + CXX_VISIBILITY_PRESET hidden) | ||
| 62 | +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) | ||
| 63 | +target_include_directories(flutter_wrapper_plugin PUBLIC | ||
| 64 | + "${WRAPPER_ROOT}/include" | ||
| 65 | +) | ||
| 66 | +add_dependencies(flutter_wrapper_plugin flutter_assemble) | ||
| 67 | + | ||
| 68 | +# Wrapper sources needed for the runner. | ||
| 69 | +add_library(flutter_wrapper_app STATIC | ||
| 70 | + ${CPP_WRAPPER_SOURCES_CORE} | ||
| 71 | + ${CPP_WRAPPER_SOURCES_APP} | ||
| 72 | +) | ||
| 73 | +apply_standard_settings(flutter_wrapper_app) | ||
| 74 | +target_link_libraries(flutter_wrapper_app PUBLIC flutter) | ||
| 75 | +target_include_directories(flutter_wrapper_app PUBLIC | ||
| 76 | + "${WRAPPER_ROOT}/include" | ||
| 77 | +) | ||
| 78 | +add_dependencies(flutter_wrapper_app flutter_assemble) | ||
| 79 | + | ||
| 80 | +# === Flutter tool backend === | ||
| 81 | +# _phony_ is a non-existent file to force this command to run every time, | ||
| 82 | +# since currently there's no way to get a full input/output list from the | ||
| 83 | +# flutter tool. | ||
| 84 | +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") | ||
| 85 | +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) | ||
| 86 | +add_custom_command( | ||
| 87 | + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} | ||
| 88 | + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} | ||
| 89 | + ${CPP_WRAPPER_SOURCES_APP} | ||
| 90 | + ${PHONY_OUTPUT} | ||
| 91 | + COMMAND ${CMAKE_COMMAND} -E env | ||
| 92 | + ${FLUTTER_TOOL_ENVIRONMENT} | ||
| 93 | + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" | ||
| 94 | + windows-x64 $<CONFIG> | ||
| 95 | + VERBATIM | ||
| 96 | +) | ||
| 97 | +add_custom_target(flutter_assemble DEPENDS | ||
| 98 | + "${FLUTTER_LIBRARY}" | ||
| 99 | + ${FLUTTER_LIBRARY_HEADERS} | ||
| 100 | + ${CPP_WRAPPER_SOURCES_CORE} | ||
| 101 | + ${CPP_WRAPPER_SOURCES_PLUGIN} | ||
| 102 | + ${CPP_WRAPPER_SOURCES_APP} | ||
| 103 | +) |
| 1 | +// | ||
| 2 | +// Generated file. Do not edit. | ||
| 3 | +// | ||
| 4 | + | ||
| 5 | +#ifndef GENERATED_PLUGIN_REGISTRANT_ | ||
| 6 | +#define GENERATED_PLUGIN_REGISTRANT_ | ||
| 7 | + | ||
| 8 | +#include <flutter/plugin_registry.h> | ||
| 9 | + | ||
| 10 | +// Registers Flutter plugins. | ||
| 11 | +void RegisterPlugins(flutter::PluginRegistry* registry); | ||
| 12 | + | ||
| 13 | +#endif // GENERATED_PLUGIN_REGISTRANT_ |
| 1 | +# | ||
| 2 | +# Generated file, do not edit. | ||
| 3 | +# | ||
| 4 | + | ||
| 5 | +list(APPEND FLUTTER_PLUGIN_LIST | ||
| 6 | +) | ||
| 7 | + | ||
| 8 | +set(PLUGIN_BUNDLED_LIBRARIES) | ||
| 9 | + | ||
| 10 | +foreach(plugin ${FLUTTER_PLUGIN_LIST}) | ||
| 11 | + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) | ||
| 12 | + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) | ||
| 13 | + list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>) | ||
| 14 | + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) | ||
| 15 | +endforeach(plugin) |
| 1 | +cmake_minimum_required(VERSION 3.15) | ||
| 2 | +project(runner LANGUAGES CXX) | ||
| 3 | + | ||
| 4 | +add_executable(${BINARY_NAME} WIN32 | ||
| 5 | + "flutter_window.cpp" | ||
| 6 | + "main.cpp" | ||
| 7 | + "run_loop.cpp" | ||
| 8 | + "utils.cpp" | ||
| 9 | + "win32_window.cpp" | ||
| 10 | + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" | ||
| 11 | + "Runner.rc" | ||
| 12 | + "runner.exe.manifest" | ||
| 13 | +) | ||
| 14 | +apply_standard_settings(${BINARY_NAME}) | ||
| 15 | +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") | ||
| 16 | +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) | ||
| 17 | +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") | ||
| 18 | +add_dependencies(${BINARY_NAME} flutter_assemble) |
wakelock/example/windows/runner/Runner.rc
0 → 100644
| 1 | +// Microsoft Visual C++ generated resource script. | ||
| 2 | +// | ||
| 3 | +#pragma code_page(65001) | ||
| 4 | +#include "resource.h" | ||
| 5 | + | ||
| 6 | +#define APSTUDIO_READONLY_SYMBOLS | ||
| 7 | +///////////////////////////////////////////////////////////////////////////// | ||
| 8 | +// | ||
| 9 | +// Generated from the TEXTINCLUDE 2 resource. | ||
| 10 | +// | ||
| 11 | +#include "winres.h" | ||
| 12 | + | ||
| 13 | +///////////////////////////////////////////////////////////////////////////// | ||
| 14 | +#undef APSTUDIO_READONLY_SYMBOLS | ||
| 15 | + | ||
| 16 | +///////////////////////////////////////////////////////////////////////////// | ||
| 17 | +// English (United States) resources | ||
| 18 | + | ||
| 19 | +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) | ||
| 20 | +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US | ||
| 21 | + | ||
| 22 | +#ifdef APSTUDIO_INVOKED | ||
| 23 | +///////////////////////////////////////////////////////////////////////////// | ||
| 24 | +// | ||
| 25 | +// TEXTINCLUDE | ||
| 26 | +// | ||
| 27 | + | ||
| 28 | +1 TEXTINCLUDE | ||
| 29 | +BEGIN | ||
| 30 | + "resource.h\0" | ||
| 31 | +END | ||
| 32 | + | ||
| 33 | +2 TEXTINCLUDE | ||
| 34 | +BEGIN | ||
| 35 | + "#include ""winres.h""\r\n" | ||
| 36 | + "\0" | ||
| 37 | +END | ||
| 38 | + | ||
| 39 | +3 TEXTINCLUDE | ||
| 40 | +BEGIN | ||
| 41 | + "\r\n" | ||
| 42 | + "\0" | ||
| 43 | +END | ||
| 44 | + | ||
| 45 | +#endif // APSTUDIO_INVOKED | ||
| 46 | + | ||
| 47 | + | ||
| 48 | +///////////////////////////////////////////////////////////////////////////// | ||
| 49 | +// | ||
| 50 | +// Icon | ||
| 51 | +// | ||
| 52 | + | ||
| 53 | +// Icon with lowest ID value placed first to ensure application icon | ||
| 54 | +// remains consistent on all systems. | ||
| 55 | +IDI_APP_ICON ICON "resources\\app_icon.ico" | ||
| 56 | + | ||
| 57 | + | ||
| 58 | +///////////////////////////////////////////////////////////////////////////// | ||
| 59 | +// | ||
| 60 | +// Version | ||
| 61 | +// | ||
| 62 | + | ||
| 63 | +#ifdef FLUTTER_BUILD_NUMBER | ||
| 64 | +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER | ||
| 65 | +#else | ||
| 66 | +#define VERSION_AS_NUMBER 1,0,0 | ||
| 67 | +#endif | ||
| 68 | + | ||
| 69 | +#ifdef FLUTTER_BUILD_NAME | ||
| 70 | +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME | ||
| 71 | +#else | ||
| 72 | +#define VERSION_AS_STRING "1.0.0" | ||
| 73 | +#endif | ||
| 74 | + | ||
| 75 | +VS_VERSION_INFO VERSIONINFO | ||
| 76 | + FILEVERSION VERSION_AS_NUMBER | ||
| 77 | + PRODUCTVERSION VERSION_AS_NUMBER | ||
| 78 | + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK | ||
| 79 | +#ifdef _DEBUG | ||
| 80 | + FILEFLAGS VS_FF_DEBUG | ||
| 81 | +#else | ||
| 82 | + FILEFLAGS 0x0L | ||
| 83 | +#endif | ||
| 84 | + FILEOS VOS__WINDOWS32 | ||
| 85 | + FILETYPE VFT_APP | ||
| 86 | + FILESUBTYPE 0x0L | ||
| 87 | +BEGIN | ||
| 88 | + BLOCK "StringFileInfo" | ||
| 89 | + BEGIN | ||
| 90 | + BLOCK "040904e4" | ||
| 91 | + BEGIN | ||
| 92 | + VALUE "CompanyName", "creativemaybeno" "\0" | ||
| 93 | + VALUE "FileDescription", "A new Flutter project." "\0" | ||
| 94 | + VALUE "FileVersion", VERSION_AS_STRING "\0" | ||
| 95 | + VALUE "InternalName", "example" "\0" | ||
| 96 | + VALUE "LegalCopyright", "Copyright (C) 2021 creativemaybeno. All rights reserved." "\0" | ||
| 97 | + VALUE "OriginalFilename", "example.exe" "\0" | ||
| 98 | + VALUE "ProductName", "example" "\0" | ||
| 99 | + VALUE "ProductVersion", VERSION_AS_STRING "\0" | ||
| 100 | + END | ||
| 101 | + END | ||
| 102 | + BLOCK "VarFileInfo" | ||
| 103 | + BEGIN | ||
| 104 | + VALUE "Translation", 0x409, 1252 | ||
| 105 | + END | ||
| 106 | +END | ||
| 107 | + | ||
| 108 | +#endif // English (United States) resources | ||
| 109 | +///////////////////////////////////////////////////////////////////////////// | ||
| 110 | + | ||
| 111 | + | ||
| 112 | + | ||
| 113 | +#ifndef APSTUDIO_INVOKED | ||
| 114 | +///////////////////////////////////////////////////////////////////////////// | ||
| 115 | +// | ||
| 116 | +// Generated from the TEXTINCLUDE 3 resource. | ||
| 117 | +// | ||
| 118 | + | ||
| 119 | + | ||
| 120 | +///////////////////////////////////////////////////////////////////////////// | ||
| 121 | +#endif // not APSTUDIO_INVOKED |
| 1 | +#include "flutter_window.h" | ||
| 2 | + | ||
| 3 | +#include <optional> | ||
| 4 | + | ||
| 5 | +#include "flutter/generated_plugin_registrant.h" | ||
| 6 | + | ||
| 7 | +FlutterWindow::FlutterWindow(RunLoop* run_loop, | ||
| 8 | + const flutter::DartProject& project) | ||
| 9 | + : run_loop_(run_loop), project_(project) {} | ||
| 10 | + | ||
| 11 | +FlutterWindow::~FlutterWindow() {} | ||
| 12 | + | ||
| 13 | +bool FlutterWindow::OnCreate() { | ||
| 14 | + if (!Win32Window::OnCreate()) { | ||
| 15 | + return false; | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | + RECT frame = GetClientArea(); | ||
| 19 | + | ||
| 20 | + // The size here must match the window dimensions to avoid unnecessary surface | ||
| 21 | + // creation / destruction in the startup path. | ||
| 22 | + flutter_controller_ = std::make_unique<flutter::FlutterViewController>( | ||
| 23 | + frame.right - frame.left, frame.bottom - frame.top, project_); | ||
| 24 | + // Ensure that basic setup of the controller was successful. | ||
| 25 | + if (!flutter_controller_->engine() || !flutter_controller_->view()) { | ||
| 26 | + return false; | ||
| 27 | + } | ||
| 28 | + RegisterPlugins(flutter_controller_->engine()); | ||
| 29 | + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); | ||
| 30 | + SetChildContent(flutter_controller_->view()->GetNativeWindow()); | ||
| 31 | + return true; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +void FlutterWindow::OnDestroy() { | ||
| 35 | + if (flutter_controller_) { | ||
| 36 | + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); | ||
| 37 | + flutter_controller_ = nullptr; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + Win32Window::OnDestroy(); | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +LRESULT | ||
| 44 | +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, | ||
| 45 | + WPARAM const wparam, | ||
| 46 | + LPARAM const lparam) noexcept { | ||
| 47 | + // Give Flutter, including plugins, an opporutunity to handle window messages. | ||
| 48 | + if (flutter_controller_) { | ||
| 49 | + std::optional<LRESULT> result = | ||
| 50 | + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, | ||
| 51 | + lparam); | ||
| 52 | + if (result) { | ||
| 53 | + return *result; | ||
| 54 | + } | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + switch (message) { | ||
| 58 | + case WM_FONTCHANGE: | ||
| 59 | + flutter_controller_->engine()->ReloadSystemFonts(); | ||
| 60 | + break; | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); | ||
| 64 | +} |
| 1 | +#ifndef RUNNER_FLUTTER_WINDOW_H_ | ||
| 2 | +#define RUNNER_FLUTTER_WINDOW_H_ | ||
| 3 | + | ||
| 4 | +#include <flutter/dart_project.h> | ||
| 5 | +#include <flutter/flutter_view_controller.h> | ||
| 6 | + | ||
| 7 | +#include <memory> | ||
| 8 | + | ||
| 9 | +#include "run_loop.h" | ||
| 10 | +#include "win32_window.h" | ||
| 11 | + | ||
| 12 | +// A window that does nothing but host a Flutter view. | ||
| 13 | +class FlutterWindow : public Win32Window { | ||
| 14 | + public: | ||
| 15 | + // Creates a new FlutterWindow driven by the |run_loop|, hosting a | ||
| 16 | + // Flutter view running |project|. | ||
| 17 | + explicit FlutterWindow(RunLoop* run_loop, | ||
| 18 | + const flutter::DartProject& project); | ||
| 19 | + virtual ~FlutterWindow(); | ||
| 20 | + | ||
| 21 | + protected: | ||
| 22 | + // Win32Window: | ||
| 23 | + bool OnCreate() override; | ||
| 24 | + void OnDestroy() override; | ||
| 25 | + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, | ||
| 26 | + LPARAM const lparam) noexcept override; | ||
| 27 | + | ||
| 28 | + private: | ||
| 29 | + // The run loop driving events for this window. | ||
| 30 | + RunLoop* run_loop_; | ||
| 31 | + | ||
| 32 | + // The project to run. | ||
| 33 | + flutter::DartProject project_; | ||
| 34 | + | ||
| 35 | + // The Flutter instance hosted by this window. | ||
| 36 | + std::unique_ptr<flutter::FlutterViewController> flutter_controller_; | ||
| 37 | +}; | ||
| 38 | + | ||
| 39 | +#endif // RUNNER_FLUTTER_WINDOW_H_ |
wakelock/example/windows/runner/main.cpp
0 → 100644
| 1 | +#include <flutter/dart_project.h> | ||
| 2 | +#include <flutter/flutter_view_controller.h> | ||
| 3 | +#include <windows.h> | ||
| 4 | + | ||
| 5 | +#include "flutter_window.h" | ||
| 6 | +#include "run_loop.h" | ||
| 7 | +#include "utils.h" | ||
| 8 | + | ||
| 9 | +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, | ||
| 10 | + _In_ wchar_t *command_line, _In_ int show_command) { | ||
| 11 | + // Attach to console when present (e.g., 'flutter run') or create a | ||
| 12 | + // new console when running with a debugger. | ||
| 13 | + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { | ||
| 14 | + CreateAndAttachConsole(); | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + // Initialize COM, so that it is available for use in the library and/or | ||
| 18 | + // plugins. | ||
| 19 | + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); | ||
| 20 | + | ||
| 21 | + RunLoop run_loop; | ||
| 22 | + | ||
| 23 | + flutter::DartProject project(L"data"); | ||
| 24 | + | ||
| 25 | + std::vector<std::string> command_line_arguments = | ||
| 26 | + GetCommandLineArguments(); | ||
| 27 | + | ||
| 28 | + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); | ||
| 29 | + | ||
| 30 | + FlutterWindow window(&run_loop, project); | ||
| 31 | + Win32Window::Point origin(10, 10); | ||
| 32 | + Win32Window::Size size(1280, 720); | ||
| 33 | + if (!window.CreateAndShow(L"example", origin, size)) { | ||
| 34 | + return EXIT_FAILURE; | ||
| 35 | + } | ||
| 36 | + window.SetQuitOnClose(true); | ||
| 37 | + | ||
| 38 | + run_loop.Run(); | ||
| 39 | + | ||
| 40 | + ::CoUninitialize(); | ||
| 41 | + return EXIT_SUCCESS; | ||
| 42 | +} |
wakelock/example/windows/runner/resource.h
0 → 100644
| 1 | +//{{NO_DEPENDENCIES}} | ||
| 2 | +// Microsoft Visual C++ generated include file. | ||
| 3 | +// Used by Runner.rc | ||
| 4 | +// | ||
| 5 | +#define IDI_APP_ICON 101 | ||
| 6 | + | ||
| 7 | +// Next default values for new objects | ||
| 8 | +// | ||
| 9 | +#ifdef APSTUDIO_INVOKED | ||
| 10 | +#ifndef APSTUDIO_READONLY_SYMBOLS | ||
| 11 | +#define _APS_NEXT_RESOURCE_VALUE 102 | ||
| 12 | +#define _APS_NEXT_COMMAND_VALUE 40001 | ||
| 13 | +#define _APS_NEXT_CONTROL_VALUE 1001 | ||
| 14 | +#define _APS_NEXT_SYMED_VALUE 101 | ||
| 15 | +#endif | ||
| 16 | +#endif |
No preview for this file type
wakelock/example/windows/runner/run_loop.cpp
0 → 100644
| 1 | +#include "run_loop.h" | ||
| 2 | + | ||
| 3 | +#include <windows.h> | ||
| 4 | + | ||
| 5 | +#include <algorithm> | ||
| 6 | + | ||
| 7 | +RunLoop::RunLoop() {} | ||
| 8 | + | ||
| 9 | +RunLoop::~RunLoop() {} | ||
| 10 | + | ||
| 11 | +void RunLoop::Run() { | ||
| 12 | + bool keep_running = true; | ||
| 13 | + TimePoint next_flutter_event_time = TimePoint::clock::now(); | ||
| 14 | + while (keep_running) { | ||
| 15 | + std::chrono::nanoseconds wait_duration = | ||
| 16 | + std::max(std::chrono::nanoseconds(0), | ||
| 17 | + next_flutter_event_time - TimePoint::clock::now()); | ||
| 18 | + ::MsgWaitForMultipleObjects( | ||
| 19 | + 0, nullptr, FALSE, static_cast<DWORD>(wait_duration.count() / 1000), | ||
| 20 | + QS_ALLINPUT); | ||
| 21 | + bool processed_events = false; | ||
| 22 | + MSG message; | ||
| 23 | + // All pending Windows messages must be processed; MsgWaitForMultipleObjects | ||
| 24 | + // won't return again for items left in the queue after PeekMessage. | ||
| 25 | + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { | ||
| 26 | + processed_events = true; | ||
| 27 | + if (message.message == WM_QUIT) { | ||
| 28 | + keep_running = false; | ||
| 29 | + break; | ||
| 30 | + } | ||
| 31 | + ::TranslateMessage(&message); | ||
| 32 | + ::DispatchMessage(&message); | ||
| 33 | + // Allow Flutter to process messages each time a Windows message is | ||
| 34 | + // processed, to prevent starvation. | ||
| 35 | + next_flutter_event_time = | ||
| 36 | + std::min(next_flutter_event_time, ProcessFlutterMessages()); | ||
| 37 | + } | ||
| 38 | + // If the PeekMessage loop didn't run, process Flutter messages. | ||
| 39 | + if (!processed_events) { | ||
| 40 | + next_flutter_event_time = | ||
| 41 | + std::min(next_flutter_event_time, ProcessFlutterMessages()); | ||
| 42 | + } | ||
| 43 | + } | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +void RunLoop::RegisterFlutterInstance( | ||
| 47 | + flutter::FlutterEngine* flutter_instance) { | ||
| 48 | + flutter_instances_.insert(flutter_instance); | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +void RunLoop::UnregisterFlutterInstance( | ||
| 52 | + flutter::FlutterEngine* flutter_instance) { | ||
| 53 | + flutter_instances_.erase(flutter_instance); | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { | ||
| 57 | + TimePoint next_event_time = TimePoint::max(); | ||
| 58 | + for (auto instance : flutter_instances_) { | ||
| 59 | + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); | ||
| 60 | + if (wait_duration != std::chrono::nanoseconds::max()) { | ||
| 61 | + next_event_time = | ||
| 62 | + std::min(next_event_time, TimePoint::clock::now() + wait_duration); | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + return next_event_time; | ||
| 66 | +} |
wakelock/example/windows/runner/run_loop.h
0 → 100644
| 1 | +#ifndef RUNNER_RUN_LOOP_H_ | ||
| 2 | +#define RUNNER_RUN_LOOP_H_ | ||
| 3 | + | ||
| 4 | +#include <flutter/flutter_engine.h> | ||
| 5 | + | ||
| 6 | +#include <chrono> | ||
| 7 | +#include <set> | ||
| 8 | + | ||
| 9 | +// A runloop that will service events for Flutter instances as well | ||
| 10 | +// as native messages. | ||
| 11 | +class RunLoop { | ||
| 12 | + public: | ||
| 13 | + RunLoop(); | ||
| 14 | + ~RunLoop(); | ||
| 15 | + | ||
| 16 | + // Prevent copying | ||
| 17 | + RunLoop(RunLoop const&) = delete; | ||
| 18 | + RunLoop& operator=(RunLoop const&) = delete; | ||
| 19 | + | ||
| 20 | + // Runs the run loop until the application quits. | ||
| 21 | + void Run(); | ||
| 22 | + | ||
| 23 | + // Registers the given Flutter instance for event servicing. | ||
| 24 | + void RegisterFlutterInstance( | ||
| 25 | + flutter::FlutterEngine* flutter_instance); | ||
| 26 | + | ||
| 27 | + // Unregisters the given Flutter instance from event servicing. | ||
| 28 | + void UnregisterFlutterInstance( | ||
| 29 | + flutter::FlutterEngine* flutter_instance); | ||
| 30 | + | ||
| 31 | + private: | ||
| 32 | + using TimePoint = std::chrono::steady_clock::time_point; | ||
| 33 | + | ||
| 34 | + // Processes all currently pending messages for registered Flutter instances. | ||
| 35 | + TimePoint ProcessFlutterMessages(); | ||
| 36 | + | ||
| 37 | + std::set<flutter::FlutterEngine*> flutter_instances_; | ||
| 38 | +}; | ||
| 39 | + | ||
| 40 | +#endif // RUNNER_RUN_LOOP_H_ |
| 1 | +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
| 2 | +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> | ||
| 3 | + <application xmlns="urn:schemas-microsoft-com:asm.v3"> | ||
| 4 | + <windowsSettings> | ||
| 5 | + <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness> | ||
| 6 | + </windowsSettings> | ||
| 7 | + </application> | ||
| 8 | + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> | ||
| 9 | + <application> | ||
| 10 | + <!-- Windows 10 --> | ||
| 11 | + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> | ||
| 12 | + <!-- Windows 8.1 --> | ||
| 13 | + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> | ||
| 14 | + <!-- Windows 8 --> | ||
| 15 | + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> | ||
| 16 | + <!-- Windows 7 --> | ||
| 17 | + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> | ||
| 18 | + </application> | ||
| 19 | + </compatibility> | ||
| 20 | +</assembly> |
wakelock/example/windows/runner/utils.cpp
0 → 100644
| 1 | +#include "utils.h" | ||
| 2 | + | ||
| 3 | +#include <flutter_windows.h> | ||
| 4 | +#include <io.h> | ||
| 5 | +#include <stdio.h> | ||
| 6 | +#include <windows.h> | ||
| 7 | + | ||
| 8 | +#include <iostream> | ||
| 9 | + | ||
| 10 | +void CreateAndAttachConsole() { | ||
| 11 | + if (::AllocConsole()) { | ||
| 12 | + FILE *unused; | ||
| 13 | + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { | ||
| 14 | + _dup2(_fileno(stdout), 1); | ||
| 15 | + } | ||
| 16 | + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { | ||
| 17 | + _dup2(_fileno(stdout), 2); | ||
| 18 | + } | ||
| 19 | + std::ios::sync_with_stdio(); | ||
| 20 | + FlutterDesktopResyncOutputStreams(); | ||
| 21 | + } | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +std::vector<std::string> GetCommandLineArguments() { | ||
| 25 | + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. | ||
| 26 | + int argc; | ||
| 27 | + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); | ||
| 28 | + if (argv == nullptr) { | ||
| 29 | + return std::vector<std::string>(); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + std::vector<std::string> command_line_arguments; | ||
| 33 | + | ||
| 34 | + // Skip the first argument as it's the binary name. | ||
| 35 | + for (int i = 1; i < argc; i++) { | ||
| 36 | + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + ::LocalFree(argv); | ||
| 40 | + | ||
| 41 | + return command_line_arguments; | ||
| 42 | +} | ||
| 43 | + | ||
| 44 | +std::string Utf8FromUtf16(const wchar_t* utf16_string) { | ||
| 45 | + if (utf16_string == nullptr) { | ||
| 46 | + return std::string(); | ||
| 47 | + } | ||
| 48 | + int target_length = ::WideCharToMultiByte( | ||
| 49 | + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, | ||
| 50 | + -1, nullptr, 0, nullptr, nullptr); | ||
| 51 | + if (target_length == 0) { | ||
| 52 | + return std::string(); | ||
| 53 | + } | ||
| 54 | + std::string utf8_string; | ||
| 55 | + utf8_string.resize(target_length); | ||
| 56 | + int converted_length = ::WideCharToMultiByte( | ||
| 57 | + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, | ||
| 58 | + -1, utf8_string.data(), | ||
| 59 | + target_length, nullptr, nullptr); | ||
| 60 | + if (converted_length == 0) { | ||
| 61 | + return std::string(); | ||
| 62 | + } | ||
| 63 | + return utf8_string; | ||
| 64 | +} |
wakelock/example/windows/runner/utils.h
0 → 100644
| 1 | +#ifndef RUNNER_UTILS_H_ | ||
| 2 | +#define RUNNER_UTILS_H_ | ||
| 3 | + | ||
| 4 | +#include <string> | ||
| 5 | +#include <vector> | ||
| 6 | + | ||
| 7 | +// Creates a console for the process, and redirects stdout and stderr to | ||
| 8 | +// it for both the runner and the Flutter library. | ||
| 9 | +void CreateAndAttachConsole(); | ||
| 10 | + | ||
| 11 | +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string | ||
| 12 | +// encoded in UTF-8. Returns an empty std::string on failure. | ||
| 13 | +std::string Utf8FromUtf16(const wchar_t* utf16_string); | ||
| 14 | + | ||
| 15 | +// Gets the command line arguments passed in as a std::vector<std::string>, | ||
| 16 | +// encoded in UTF-8. Returns an empty std::vector<std::string> on failure. | ||
| 17 | +std::vector<std::string> GetCommandLineArguments(); | ||
| 18 | + | ||
| 19 | +#endif // RUNNER_UTILS_H_ |
| 1 | +#include "win32_window.h" | ||
| 2 | + | ||
| 3 | +#include <flutter_windows.h> | ||
| 4 | + | ||
| 5 | +#include "resource.h" | ||
| 6 | + | ||
| 7 | +namespace { | ||
| 8 | + | ||
| 9 | +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; | ||
| 10 | + | ||
| 11 | +// The number of Win32Window objects that currently exist. | ||
| 12 | +static int g_active_window_count = 0; | ||
| 13 | + | ||
| 14 | +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); | ||
| 15 | + | ||
| 16 | +// Scale helper to convert logical scaler values to physical using passed in | ||
| 17 | +// scale factor | ||
| 18 | +int Scale(int source, double scale_factor) { | ||
| 19 | + return static_cast<int>(source * scale_factor); | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. | ||
| 23 | +// This API is only needed for PerMonitor V1 awareness mode. | ||
| 24 | +void EnableFullDpiSupportIfAvailable(HWND hwnd) { | ||
| 25 | + HMODULE user32_module = LoadLibraryA("User32.dll"); | ||
| 26 | + if (!user32_module) { | ||
| 27 | + return; | ||
| 28 | + } | ||
| 29 | + auto enable_non_client_dpi_scaling = | ||
| 30 | + reinterpret_cast<EnableNonClientDpiScaling*>( | ||
| 31 | + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); | ||
| 32 | + if (enable_non_client_dpi_scaling != nullptr) { | ||
| 33 | + enable_non_client_dpi_scaling(hwnd); | ||
| 34 | + FreeLibrary(user32_module); | ||
| 35 | + } | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +} // namespace | ||
| 39 | + | ||
| 40 | +// Manages the Win32Window's window class registration. | ||
| 41 | +class WindowClassRegistrar { | ||
| 42 | + public: | ||
| 43 | + ~WindowClassRegistrar() = default; | ||
| 44 | + | ||
| 45 | + // Returns the singleton registar instance. | ||
| 46 | + static WindowClassRegistrar* GetInstance() { | ||
| 47 | + if (!instance_) { | ||
| 48 | + instance_ = new WindowClassRegistrar(); | ||
| 49 | + } | ||
| 50 | + return instance_; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + // Returns the name of the window class, registering the class if it hasn't | ||
| 54 | + // previously been registered. | ||
| 55 | + const wchar_t* GetWindowClass(); | ||
| 56 | + | ||
| 57 | + // Unregisters the window class. Should only be called if there are no | ||
| 58 | + // instances of the window. | ||
| 59 | + void UnregisterWindowClass(); | ||
| 60 | + | ||
| 61 | + private: | ||
| 62 | + WindowClassRegistrar() = default; | ||
| 63 | + | ||
| 64 | + static WindowClassRegistrar* instance_; | ||
| 65 | + | ||
| 66 | + bool class_registered_ = false; | ||
| 67 | +}; | ||
| 68 | + | ||
| 69 | +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; | ||
| 70 | + | ||
| 71 | +const wchar_t* WindowClassRegistrar::GetWindowClass() { | ||
| 72 | + if (!class_registered_) { | ||
| 73 | + WNDCLASS window_class{}; | ||
| 74 | + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); | ||
| 75 | + window_class.lpszClassName = kWindowClassName; | ||
| 76 | + window_class.style = CS_HREDRAW | CS_VREDRAW; | ||
| 77 | + window_class.cbClsExtra = 0; | ||
| 78 | + window_class.cbWndExtra = 0; | ||
| 79 | + window_class.hInstance = GetModuleHandle(nullptr); | ||
| 80 | + window_class.hIcon = | ||
| 81 | + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); | ||
| 82 | + window_class.hbrBackground = 0; | ||
| 83 | + window_class.lpszMenuName = nullptr; | ||
| 84 | + window_class.lpfnWndProc = Win32Window::WndProc; | ||
| 85 | + RegisterClass(&window_class); | ||
| 86 | + class_registered_ = true; | ||
| 87 | + } | ||
| 88 | + return kWindowClassName; | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | +void WindowClassRegistrar::UnregisterWindowClass() { | ||
| 92 | + UnregisterClass(kWindowClassName, nullptr); | ||
| 93 | + class_registered_ = false; | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +Win32Window::Win32Window() { | ||
| 97 | + ++g_active_window_count; | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +Win32Window::~Win32Window() { | ||
| 101 | + --g_active_window_count; | ||
| 102 | + Destroy(); | ||
| 103 | +} | ||
| 104 | + | ||
| 105 | +bool Win32Window::CreateAndShow(const std::wstring& title, | ||
| 106 | + const Point& origin, | ||
| 107 | + const Size& size) { | ||
| 108 | + Destroy(); | ||
| 109 | + | ||
| 110 | + const wchar_t* window_class = | ||
| 111 | + WindowClassRegistrar::GetInstance()->GetWindowClass(); | ||
| 112 | + | ||
| 113 | + const POINT target_point = {static_cast<LONG>(origin.x), | ||
| 114 | + static_cast<LONG>(origin.y)}; | ||
| 115 | + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); | ||
| 116 | + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); | ||
| 117 | + double scale_factor = dpi / 96.0; | ||
| 118 | + | ||
| 119 | + HWND window = CreateWindow( | ||
| 120 | + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, | ||
| 121 | + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), | ||
| 122 | + Scale(size.width, scale_factor), Scale(size.height, scale_factor), | ||
| 123 | + nullptr, nullptr, GetModuleHandle(nullptr), this); | ||
| 124 | + | ||
| 125 | + if (!window) { | ||
| 126 | + return false; | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + return OnCreate(); | ||
| 130 | +} | ||
| 131 | + | ||
| 132 | +// static | ||
| 133 | +LRESULT CALLBACK Win32Window::WndProc(HWND const window, | ||
| 134 | + UINT const message, | ||
| 135 | + WPARAM const wparam, | ||
| 136 | + LPARAM const lparam) noexcept { | ||
| 137 | + if (message == WM_NCCREATE) { | ||
| 138 | + auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam); | ||
| 139 | + SetWindowLongPtr(window, GWLP_USERDATA, | ||
| 140 | + reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams)); | ||
| 141 | + | ||
| 142 | + auto that = static_cast<Win32Window*>(window_struct->lpCreateParams); | ||
| 143 | + EnableFullDpiSupportIfAvailable(window); | ||
| 144 | + that->window_handle_ = window; | ||
| 145 | + } else if (Win32Window* that = GetThisFromHandle(window)) { | ||
| 146 | + return that->MessageHandler(window, message, wparam, lparam); | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + return DefWindowProc(window, message, wparam, lparam); | ||
| 150 | +} | ||
| 151 | + | ||
| 152 | +LRESULT | ||
| 153 | +Win32Window::MessageHandler(HWND hwnd, | ||
| 154 | + UINT const message, | ||
| 155 | + WPARAM const wparam, | ||
| 156 | + LPARAM const lparam) noexcept { | ||
| 157 | + switch (message) { | ||
| 158 | + case WM_DESTROY: | ||
| 159 | + window_handle_ = nullptr; | ||
| 160 | + Destroy(); | ||
| 161 | + if (quit_on_close_) { | ||
| 162 | + PostQuitMessage(0); | ||
| 163 | + } | ||
| 164 | + return 0; | ||
| 165 | + | ||
| 166 | + case WM_DPICHANGED: { | ||
| 167 | + auto newRectSize = reinterpret_cast<RECT*>(lparam); | ||
| 168 | + LONG newWidth = newRectSize->right - newRectSize->left; | ||
| 169 | + LONG newHeight = newRectSize->bottom - newRectSize->top; | ||
| 170 | + | ||
| 171 | + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, | ||
| 172 | + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); | ||
| 173 | + | ||
| 174 | + return 0; | ||
| 175 | + } | ||
| 176 | + case WM_SIZE: { | ||
| 177 | + RECT rect = GetClientArea(); | ||
| 178 | + if (child_content_ != nullptr) { | ||
| 179 | + // Size and position the child window. | ||
| 180 | + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, | ||
| 181 | + rect.bottom - rect.top, TRUE); | ||
| 182 | + } | ||
| 183 | + return 0; | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + case WM_ACTIVATE: | ||
| 187 | + if (child_content_ != nullptr) { | ||
| 188 | + SetFocus(child_content_); | ||
| 189 | + } | ||
| 190 | + return 0; | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + return DefWindowProc(window_handle_, message, wparam, lparam); | ||
| 194 | +} | ||
| 195 | + | ||
| 196 | +void Win32Window::Destroy() { | ||
| 197 | + OnDestroy(); | ||
| 198 | + | ||
| 199 | + if (window_handle_) { | ||
| 200 | + DestroyWindow(window_handle_); | ||
| 201 | + window_handle_ = nullptr; | ||
| 202 | + } | ||
| 203 | + if (g_active_window_count == 0) { | ||
| 204 | + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); | ||
| 205 | + } | ||
| 206 | +} | ||
| 207 | + | ||
| 208 | +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { | ||
| 209 | + return reinterpret_cast<Win32Window*>( | ||
| 210 | + GetWindowLongPtr(window, GWLP_USERDATA)); | ||
| 211 | +} | ||
| 212 | + | ||
| 213 | +void Win32Window::SetChildContent(HWND content) { | ||
| 214 | + child_content_ = content; | ||
| 215 | + SetParent(content, window_handle_); | ||
| 216 | + RECT frame = GetClientArea(); | ||
| 217 | + | ||
| 218 | + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, | ||
| 219 | + frame.bottom - frame.top, true); | ||
| 220 | + | ||
| 221 | + SetFocus(child_content_); | ||
| 222 | +} | ||
| 223 | + | ||
| 224 | +RECT Win32Window::GetClientArea() { | ||
| 225 | + RECT frame; | ||
| 226 | + GetClientRect(window_handle_, &frame); | ||
| 227 | + return frame; | ||
| 228 | +} | ||
| 229 | + | ||
| 230 | +HWND Win32Window::GetHandle() { | ||
| 231 | + return window_handle_; | ||
| 232 | +} | ||
| 233 | + | ||
| 234 | +void Win32Window::SetQuitOnClose(bool quit_on_close) { | ||
| 235 | + quit_on_close_ = quit_on_close; | ||
| 236 | +} | ||
| 237 | + | ||
| 238 | +bool Win32Window::OnCreate() { | ||
| 239 | + // No-op; provided for subclasses. | ||
| 240 | + return true; | ||
| 241 | +} | ||
| 242 | + | ||
| 243 | +void Win32Window::OnDestroy() { | ||
| 244 | + // No-op; provided for subclasses. | ||
| 245 | +} |
| 1 | +#ifndef RUNNER_WIN32_WINDOW_H_ | ||
| 2 | +#define RUNNER_WIN32_WINDOW_H_ | ||
| 3 | + | ||
| 4 | +#include <windows.h> | ||
| 5 | + | ||
| 6 | +#include <functional> | ||
| 7 | +#include <memory> | ||
| 8 | +#include <string> | ||
| 9 | + | ||
| 10 | +// A class abstraction for a high DPI-aware Win32 Window. Intended to be | ||
| 11 | +// inherited from by classes that wish to specialize with custom | ||
| 12 | +// rendering and input handling | ||
| 13 | +class Win32Window { | ||
| 14 | + public: | ||
| 15 | + struct Point { | ||
| 16 | + unsigned int x; | ||
| 17 | + unsigned int y; | ||
| 18 | + Point(unsigned int x, unsigned int y) : x(x), y(y) {} | ||
| 19 | + }; | ||
| 20 | + | ||
| 21 | + struct Size { | ||
| 22 | + unsigned int width; | ||
| 23 | + unsigned int height; | ||
| 24 | + Size(unsigned int width, unsigned int height) | ||
| 25 | + : width(width), height(height) {} | ||
| 26 | + }; | ||
| 27 | + | ||
| 28 | + Win32Window(); | ||
| 29 | + virtual ~Win32Window(); | ||
| 30 | + | ||
| 31 | + // Creates and shows a win32 window with |title| and position and size using | ||
| 32 | + // |origin| and |size|. New windows are created on the default monitor. Window | ||
| 33 | + // sizes are specified to the OS in physical pixels, hence to ensure a | ||
| 34 | + // consistent size to will treat the width height passed in to this function | ||
| 35 | + // as logical pixels and scale to appropriate for the default monitor. Returns | ||
| 36 | + // true if the window was created successfully. | ||
| 37 | + bool CreateAndShow(const std::wstring& title, | ||
| 38 | + const Point& origin, | ||
| 39 | + const Size& size); | ||
| 40 | + | ||
| 41 | + // Release OS resources associated with window. | ||
| 42 | + void Destroy(); | ||
| 43 | + | ||
| 44 | + // Inserts |content| into the window tree. | ||
| 45 | + void SetChildContent(HWND content); | ||
| 46 | + | ||
| 47 | + // Returns the backing Window handle to enable clients to set icon and other | ||
| 48 | + // window properties. Returns nullptr if the window has been destroyed. | ||
| 49 | + HWND GetHandle(); | ||
| 50 | + | ||
| 51 | + // If true, closing this window will quit the application. | ||
| 52 | + void SetQuitOnClose(bool quit_on_close); | ||
| 53 | + | ||
| 54 | + // Return a RECT representing the bounds of the current client area. | ||
| 55 | + RECT GetClientArea(); | ||
| 56 | + | ||
| 57 | + protected: | ||
| 58 | + // Processes and route salient window messages for mouse handling, | ||
| 59 | + // size change and DPI. Delegates handling of these to member overloads that | ||
| 60 | + // inheriting classes can handle. | ||
| 61 | + virtual LRESULT MessageHandler(HWND window, | ||
| 62 | + UINT const message, | ||
| 63 | + WPARAM const wparam, | ||
| 64 | + LPARAM const lparam) noexcept; | ||
| 65 | + | ||
| 66 | + // Called when CreateAndShow is called, allowing subclass window-related | ||
| 67 | + // setup. Subclasses should return false if setup fails. | ||
| 68 | + virtual bool OnCreate(); | ||
| 69 | + | ||
| 70 | + // Called when Destroy is called. | ||
| 71 | + virtual void OnDestroy(); | ||
| 72 | + | ||
| 73 | + private: | ||
| 74 | + friend class WindowClassRegistrar; | ||
| 75 | + | ||
| 76 | + // OS callback called by message pump. Handles the WM_NCCREATE message which | ||
| 77 | + // is passed when the non-client area is being created and enables automatic | ||
| 78 | + // non-client DPI scaling so that the non-client area automatically | ||
| 79 | + // responsponds to changes in DPI. All other messages are handled by | ||
| 80 | + // MessageHandler. | ||
| 81 | + static LRESULT CALLBACK WndProc(HWND const window, | ||
| 82 | + UINT const message, | ||
| 83 | + WPARAM const wparam, | ||
| 84 | + LPARAM const lparam) noexcept; | ||
| 85 | + | ||
| 86 | + // Retrieves a class instance pointer for |window| | ||
| 87 | + static Win32Window* GetThisFromHandle(HWND const window) noexcept; | ||
| 88 | + | ||
| 89 | + bool quit_on_close_ = false; | ||
| 90 | + | ||
| 91 | + // window handle for top level window. | ||
| 92 | + HWND window_handle_ = nullptr; | ||
| 93 | + | ||
| 94 | + // window handle for hosted content. | ||
| 95 | + HWND child_content_ = nullptr; | ||
| 96 | +}; | ||
| 97 | + | ||
| 98 | +#endif // RUNNER_WIN32_WINDOW_H_ |
| @@ -2,6 +2,7 @@ import 'dart:io'; | @@ -2,6 +2,7 @@ import 'dart:io'; | ||
| 2 | 2 | ||
| 3 | import 'package:flutter/foundation.dart'; | 3 | import 'package:flutter/foundation.dart'; |
| 4 | import 'package:wakelock_macos/wakelock_macos.dart'; | 4 | import 'package:wakelock_macos/wakelock_macos.dart'; |
| 5 | +import 'package:wakelock_windows/wakelock_windows.dart'; | ||
| 5 | import 'package:wakelock_platform_interface/wakelock_platform_interface.dart'; | 6 | import 'package:wakelock_platform_interface/wakelock_platform_interface.dart'; |
| 6 | 7 | ||
| 7 | /// The [WakelockPlatformInterface] that is used by [Wakelock]. | 8 | /// The [WakelockPlatformInterface] that is used by [Wakelock]. |
| @@ -20,7 +21,10 @@ var wakelockPlatformInstance = !kIsWeb && | @@ -20,7 +21,10 @@ var wakelockPlatformInstance = !kIsWeb && | ||
| 20 | // on web. | 21 | // on web. |
| 21 | Platform.isMacOS | 22 | Platform.isMacOS |
| 22 | ? WakelockMacOS() | 23 | ? WakelockMacOS() |
| 23 | - : WakelockPlatformInterface.instance; | 24 | + // This doesn't feel like the correct way to assign the windows implementation, |
| 25 | + // but platform channels aren't used due to the win32 package. | ||
| 26 | + // See this issue for details: https://github.com/flutter/flutter/issues/52267. | ||
| 27 | + : (!kIsWeb && Platform.isWindows ? WakelockWindows() : WakelockPlatformInterface.instance); | ||
| 24 | 28 | ||
| 25 | /// Class providing all wakelock functionality using static members. | 29 | /// Class providing all wakelock functionality using static members. |
| 26 | /// | 30 | /// |
| 1 | name: wakelock | 1 | name: wakelock |
| 2 | description: >-2 | 2 | description: >-2 |
| 3 | Plugin that allows you to keep the device screen awake, i.e. prevent the screen from sleeping on | 3 | Plugin that allows you to keep the device screen awake, i.e. prevent the screen from sleeping on |
| 4 | - Android, iOS, macOS, and web. | 4 | + Android, iOS, macOS, Windows and web. |
| 5 | version: 0.4.0 | 5 | version: 0.4.0 |
| 6 | homepage: https://github.com/creativecreatorormaybenot/wakelock/tree/master/wakelock | 6 | homepage: https://github.com/creativecreatorormaybenot/wakelock/tree/master/wakelock |
| 7 | 7 | ||
| @@ -16,6 +16,7 @@ dependencies: | @@ -16,6 +16,7 @@ dependencies: | ||
| 16 | meta: ^1.2.0 | 16 | meta: ^1.2.0 |
| 17 | 17 | ||
| 18 | wakelock_macos: ^0.1.0 | 18 | wakelock_macos: ^0.1.0 |
| 19 | + wakelock_windows: ^0.1.0 | ||
| 19 | wakelock_platform_interface: ^0.2.0 | 20 | wakelock_platform_interface: ^0.2.0 |
| 20 | wakelock_web: ^0.2.0 | 21 | wakelock_web: ^0.2.0 |
| 21 | 22 | ||
| @@ -36,5 +37,7 @@ flutter: | @@ -36,5 +37,7 @@ flutter: | ||
| 36 | pluginClass: WakelockPlugin | 37 | pluginClass: WakelockPlugin |
| 37 | macos: | 38 | macos: |
| 38 | default_package: wakelock_macos | 39 | default_package: wakelock_macos |
| 40 | + windows: | ||
| 41 | + default_package: wakelock_windows | ||
| 39 | web: | 42 | web: |
| 40 | default_package: wakelock_web | 43 | default_package: wakelock_web |
wakelock_windows/.gitignore
0 → 100644
| 1 | +# Miscellaneous | ||
| 2 | +*.class | ||
| 3 | +*.log | ||
| 4 | +*.pyc | ||
| 5 | +*.swp | ||
| 6 | +.DS_Store | ||
| 7 | +.atom/ | ||
| 8 | +.buildlog/ | ||
| 9 | +.history | ||
| 10 | +.svn/ | ||
| 11 | + | ||
| 12 | +# IntelliJ related | ||
| 13 | +*.iml | ||
| 14 | +*.ipr | ||
| 15 | +*.iws | ||
| 16 | +.idea/ | ||
| 17 | + | ||
| 18 | +# The .vscode folder contains launch configuration and tasks you configure in | ||
| 19 | +# VS Code which you may wish to be included in version control, so this line | ||
| 20 | +# is commented out by default. | ||
| 21 | +#.vscode/ | ||
| 22 | + | ||
| 23 | +# Flutter/Dart/Pub related | ||
| 24 | +**/doc/api/ | ||
| 25 | +.dart_tool/ | ||
| 26 | +.flutter-plugins | ||
| 27 | +.flutter-plugins-dependencies | ||
| 28 | +.packages | ||
| 29 | +.pub-cache/ | ||
| 30 | +.pub/ | ||
| 31 | +build/ | ||
| 32 | + | ||
| 33 | +# Android related | ||
| 34 | +**/android/**/gradle-wrapper.jar | ||
| 35 | +**/android/.gradle | ||
| 36 | +**/android/captures/ | ||
| 37 | +**/android/gradlew | ||
| 38 | +**/android/gradlew.bat | ||
| 39 | +**/android/local.properties | ||
| 40 | +**/android/**/GeneratedPluginRegistrant.java | ||
| 41 | + | ||
| 42 | +# iOS/XCode related | ||
| 43 | +**/ios/**/*.mode1v3 | ||
| 44 | +**/ios/**/*.mode2v3 | ||
| 45 | +**/ios/**/*.moved-aside | ||
| 46 | +**/ios/**/*.pbxuser | ||
| 47 | +**/ios/**/*.perspectivev3 | ||
| 48 | +**/ios/**/*sync/ | ||
| 49 | +**/ios/**/.sconsign.dblite | ||
| 50 | +**/ios/**/.tags* | ||
| 51 | +**/ios/**/.vagrant/ | ||
| 52 | +**/ios/**/DerivedData/ | ||
| 53 | +**/ios/**/Icon? | ||
| 54 | +**/ios/**/Pods/ | ||
| 55 | +**/ios/**/.symlinks/ | ||
| 56 | +**/ios/**/profile | ||
| 57 | +**/ios/**/xcuserdata | ||
| 58 | +**/ios/.generated/ | ||
| 59 | +**/ios/Flutter/App.framework | ||
| 60 | +**/ios/Flutter/Flutter.framework | ||
| 61 | +**/ios/Flutter/Flutter.podspec | ||
| 62 | +**/ios/Flutter/Generated.xcconfig | ||
| 63 | +**/ios/Flutter/app.flx | ||
| 64 | +**/ios/Flutter/app.zip | ||
| 65 | +**/ios/Flutter/flutter_assets/ | ||
| 66 | +**/ios/Flutter/flutter_export_environment.sh | ||
| 67 | +**/ios/ServiceDefinitions.json | ||
| 68 | +**/ios/Runner/GeneratedPluginRegistrant.* | ||
| 69 | + | ||
| 70 | +# Exceptions to above rules. | ||
| 71 | +!**/ios/**/default.mode1v3 | ||
| 72 | +!**/ios/**/default.mode2v3 | ||
| 73 | +!**/ios/**/default.pbxuser | ||
| 74 | +!**/ios/**/default.perspectivev3 |
wakelock_windows/CHANGELOG.md
0 → 100644
wakelock_windows/LICENSE
0 → 100644
| 1 | +BSD 3-Clause License | ||
| 2 | + | ||
| 3 | +Copyright (c) 2020-2021, creativecreatorormaybenot | ||
| 4 | +All rights reserved. | ||
| 5 | + | ||
| 6 | +Redistribution and use in source and binary forms, with or without | ||
| 7 | +modification, are permitted provided that the following conditions are met: | ||
| 8 | + | ||
| 9 | +1. Redistributions of source code must retain the above copyright notice, this | ||
| 10 | +list of conditions and the following disclaimer. | ||
| 11 | + | ||
| 12 | +2. Redistributions in binary form must reproduce the above copyright notice, | ||
| 13 | +this list of conditions and the following disclaimer in the documentation | ||
| 14 | +and/or other materials provided with the distribution. | ||
| 15 | + | ||
| 16 | +3. Neither the name of the copyright holder nor the names of its | ||
| 17 | +contributors may be used to endorse or promote products derived from | ||
| 18 | +this software without specific prior written permission. | ||
| 19 | + | ||
| 20 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 21 | +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 22 | +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 23 | +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||
| 24 | +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 25 | +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
| 26 | +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
| 27 | +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
| 28 | +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 29 | +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
wakelock_windows/README.md
0 → 100644
| 1 | +# wakelock_windows | ||
| 2 | + | ||
| 3 | +Windows platform implementation of the `wakelock_platform_interface` for the | ||
| 4 | +[wakelock plugin][wakelock GitHub]. | ||
| 5 | + | ||
| 6 | +## Getting started | ||
| 7 | + | ||
| 8 | +If you want to use the wakelock plugin on Windows, see the [main `wakelock` plugin package](https://pub.dev/packages/wakelock). | ||
| 9 | + | ||
| 10 | +## Implementation | ||
| 11 | + | ||
| 12 | +Note that the implementation does not use a `MethodChannel` implementation as relies on the win32 package. |
wakelock_windows/analysis_options.yaml
0 → 100644
wakelock_windows/lib/wakelock_windows.dart
0 → 100644
| 1 | +import 'dart:async'; | ||
| 2 | + | ||
| 3 | +import 'package:wakelock_platform_interface/wakelock_platform_interface.dart'; | ||
| 4 | +import 'package:win32/win32.dart'; | ||
| 5 | + | ||
| 6 | +const _ES_CONTINUOUS = 0x80000000; | ||
| 7 | +const _ES_DISPLAY_REQUIRED = 0x00000002; | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +/// The windows implementation of the [WakelockPlatformInterface]. | ||
| 11 | +/// | ||
| 12 | +/// This class implements the `wakelock` plugin functionality for windows using | ||
| 13 | +/// SetThreadExecutionState from win32 api. | ||
| 14 | +/// | ||
| 15 | +/// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate#parameters | ||
| 16 | +/// | ||
| 17 | +class WakelockWindows extends WakelockPlatformInterface { | ||
| 18 | + bool _isEnabled = false; | ||
| 19 | + | ||
| 20 | + @override | ||
| 21 | + Future<void> toggle({required bool enable}) async { | ||
| 22 | + int response; | ||
| 23 | + if (enable) { | ||
| 24 | + response = SetThreadExecutionState(_ES_CONTINUOUS | _ES_DISPLAY_REQUIRED); | ||
| 25 | + } else { | ||
| 26 | + response = SetThreadExecutionState(_ES_CONTINUOUS); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + // SetThreadExecutionState returns 0 if the operation failed | ||
| 30 | + if (response != 0) { | ||
| 31 | + _isEnabled = enable; | ||
| 32 | + } | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + @override | ||
| 36 | + Future<bool> get enabled async => _isEnabled; | ||
| 37 | + | ||
| 38 | + @override | ||
| 39 | + bool get isMock => false; | ||
| 40 | +} |
wakelock_windows/pubspec.yaml
0 → 100644
| 1 | +name: wakelock_windows | ||
| 2 | +description: Windows platform implementation of the wakelock_platform_interface for the wakelock plugin. | ||
| 3 | +version: 0.1.0 | ||
| 4 | + | ||
| 5 | +environment: | ||
| 6 | + sdk: ">=2.12.0 <3.0.0" | ||
| 7 | + flutter: ">=2.0.0" | ||
| 8 | + | ||
| 9 | +dependencies: | ||
| 10 | + flutter: | ||
| 11 | + sdk: flutter | ||
| 12 | + wakelock_platform_interface: ^0.2.0 | ||
| 13 | + win32: ^2.0.0 | ||
| 14 | + | ||
| 15 | +dev_dependencies: | ||
| 16 | + flutter_test: | ||
| 17 | + sdk: flutter | ||
| 18 | + | ||
| 19 | + pedantic: ^1.10.0 |
-
Please register or login to post a comment