diff --git a/DEPS b/DEPS index 8987e849fde2b..1a37214ef7cb5 100644 --- a/DEPS +++ b/DEPS @@ -422,6 +422,7 @@ deps = { 'src/third_party/angle': Var('github_git') + '/google/angle.git' + '@' + '3ea90d609720b7b9b9d05ca094860382f2425294', + #Var('github_git') + '/clarkezone/angle.git' + '@' + 'cf00b8ccd9ff59645e7fab8837ca4547e1954695', 'src/third_party/pkg/when': Var('dart_git') + '/when.git' + '@' + '0.2.0', diff --git a/shell/platform/glfw/client_wrapper/flutter_window_controller_unittests.cc b/shell/platform/glfw/client_wrapper/flutter_window_controller_unittests.cc index d0e90fcb5056c..52074347c9779 100644 --- a/shell/platform/glfw/client_wrapper/flutter_window_controller_unittests.cc +++ b/shell/platform/glfw/client_wrapper/flutter_window_controller_unittests.cc @@ -37,7 +37,7 @@ class TestGlfwApi : public testing::StubFlutterGlfwApi { } // namespace -TEST(FlutterViewControllerTest, CreateDestroy) { +TEST(Win32FlutterViewControllerTest, CreateDestroy) { const std::string icu_data_path = "fake/path/to/icu"; testing::ScopedStubFlutterGlfwApi scoped_api_stub( std::make_unique()); diff --git a/shell/platform/windows/BUILD.gn b/shell/platform/windows/BUILD.gn index ce8c6c0ec7fe1..b8114978f9ad8 100644 --- a/shell/platform/windows/BUILD.gn +++ b/shell/platform/windows/BUILD.gn @@ -41,8 +41,6 @@ source_set("flutter_windows_source") { sources = [ "angle_surface_manager.cc", "angle_surface_manager.h", - "dpi_utils.cc", - "dpi_utils.h", "flutter_windows.cc", "key_event_handler.cc", "key_event_handler.h", @@ -53,13 +51,11 @@ source_set("flutter_windows_source") { "string_conversion.h", "text_input_plugin.cc", "text_input_plugin.h", - "win32_flutter_window.cc", - "win32_flutter_window.h", - "win32_task_runner.cc", - "win32_task_runner.h", - "win32_window.cc", - "win32_window.h", - "window_state.h", + "flutter_windows_view.cc", + "flutter_windows_view.h", + "window_state_comp.h", + "task_runner.cc", + "task_runner.h", ] configs += [ @@ -98,6 +94,8 @@ shared_library("flutter_windows") { ":flutter_windows_source", ] + libs = [ "windowsapp.lib" ] + public_configs = [ "//flutter:config" ] } @@ -109,14 +107,10 @@ executable("flutter_windows_unittests") { testonly = true sources = [ - "dpi_utils_unittests.cc", "string_conversion_unittests.cc", - "testing/win32_flutter_window_test.cc", - "testing/win32_flutter_window_test.h", - "testing/win32_window_test.cc", - "testing/win32_window_test.h", - "win32_flutter_window_unittests.cc", - "win32_window_unittests.cc", + "testing/flutter_compview_test.cc", + "testing/flutter_compview_test.h", + "flutter_compview_unittests.cc", ] public_configs = [ "//flutter:config" ] @@ -128,6 +122,8 @@ executable("flutter_windows_unittests") { "//flutter/testing", "//third_party/rapidjson", ] + + libs = [ "windowsapp.lib" ] } shared_library("flutter_windows_glfw") { diff --git a/shell/platform/windows/angle_surface_manager.cc b/shell/platform/windows/angle_surface_manager.cc index c7a07cb5d36bc..9b467d667ae85 100644 --- a/shell/platform/windows/angle_surface_manager.cc +++ b/shell/platform/windows/angle_surface_manager.cc @@ -184,6 +184,35 @@ EGLSurface AngleSurfaceManager::CreateSurface(HWND window) { return surface; } +EGLSurface AngleSurfaceManager::CreateSurface( + ABI::Windows::UI::Composition::ISpriteVisual* visual) { + auto displayExtensions = eglQueryString(egl_display_, EGL_EXTENSIONS); + + // Check that the EGL_ANGLE_windows_ui_composition display extension is + // available + if (strstr(displayExtensions, "EGL_ANGLE_windows_ui_composition") == + nullptr) { + OutputDebugString(L"EGL: Composition display check failed"); + } + + if (visual == nullptr || !initialize_succeeded_) { + return EGL_NO_SURFACE; + } + + EGLSurface surface = EGL_NO_SURFACE; + + const EGLint surfaceAttributes[] = {EGL_NONE}; + + surface = eglCreateWindowSurface( + egl_display_, egl_config_, + static_cast((void*)visual), surfaceAttributes); + if (surface == EGL_NO_SURFACE) { + OutputDebugString(L"Surface creation failed."); + } + + return surface; +} + void AngleSurfaceManager::GetSurfaceDimensions(const EGLSurface surface, EGLint* width, EGLint* height) { diff --git a/shell/platform/windows/angle_surface_manager.h b/shell/platform/windows/angle_surface_manager.h index 21c0648203a73..1c65d53032e22 100644 --- a/shell/platform/windows/angle_surface_manager.h +++ b/shell/platform/windows/angle_surface_manager.h @@ -14,6 +14,7 @@ // Windows platform specific includes #include +#include namespace flutter { @@ -33,6 +34,11 @@ class AngleSurfaceManager { // HWND-backed window. EGLSurface CreateSurface(HWND window); + // Creates and returns an EGLSurface wrapper and backing DirectX 11 SwapChain + // asociated with a compositor visual. + EGLSurface CreateSurface( + ABI::Windows::UI::Composition::ISpriteVisual* visual); + // queries EGL for the dimensions of surface in physical // pixels returning width and height as out params. void GetSurfaceDimensions(const EGLSurface surface, diff --git a/shell/platform/windows/client_wrapper/BUILD.gn b/shell/platform/windows/client_wrapper/BUILD.gn index f92640e80f7f7..1a6258870d3a6 100644 --- a/shell/platform/windows/client_wrapper/BUILD.gn +++ b/shell/platform/windows/client_wrapper/BUILD.gn @@ -7,12 +7,19 @@ import("//flutter/testing/testing.gni") _wrapper_includes = [ "include/flutter/dart_project.h", - "include/flutter/flutter_view_controller.h", - "include/flutter/flutter_view.h", + "include/flutter/win32_flutter_view_controller.h", + "include/flutter/win32_flutter_view.h", "include/flutter/plugin_registrar_windows.h", + "include/flutter/win32_window_pub.h", + "include/flutter/win32_flutter_window_pub.h", + "include/flutter/dpi_utils_pub.h", ] -_wrapper_sources = [ "flutter_view_controller.cc" ] +_wrapper_sources = [ "win32_flutter_view_controller.cc", +"win32_flutter_window_pub.cc", +"win32_window_pub.cc", +"dpi_utils_pub.cc", + ] # This code will be merged into .../common/cpp/client_wrapper for client use, # so uses header paths that assume the merged state. Include the header @@ -43,6 +50,8 @@ source_set("client_wrapper_windows") { ] } + + # Copies the Windows client wrapper code to the output directory. publish_client_wrapper_extension("publish_wrapper_windows") { public = _wrapper_includes @@ -69,10 +78,14 @@ test_fixtures("client_wrapper_windows_fixtures") { executable("client_wrapper_windows_unittests") { testonly = true + cflags = ["/EHsc"] + + libs = [ "windowsapp.lib", "CoreMessaging.lib" ] + sources = [ "dart_project_unittests.cc", - "flutter_view_controller_unittests.cc", - "flutter_view_unittests.cc", + "win32_flutter_view_controller_unittests.cc", + "win32_flutter_view_unittests.cc", "plugin_registrar_windows_unittests.cc", ] diff --git a/shell/platform/windows/dpi_utils.cc b/shell/platform/windows/client_wrapper/dpi_utils_pub.cc similarity index 88% rename from shell/platform/windows/dpi_utils.cc rename to shell/platform/windows/client_wrapper/dpi_utils_pub.cc index 20b706ef2fa95..52948f4ae2e02 100644 --- a/shell/platform/windows/dpi_utils.cc +++ b/shell/platform/windows/client_wrapper/dpi_utils_pub.cc @@ -1,8 +1,8 @@ -#include "dpi_utils.h" +#include "include/flutter/dpi_utils_pub.h" namespace flutter { -namespace { +namespace pubdpi { constexpr UINT kDefaultDpi = 96; @@ -22,11 +22,11 @@ bool AssignProcAddress(HMODULE comBaseModule, const char* name, T*& outProc) { /// A helper class for abstracting various Windows DPI related functions across /// Windows OS versions. -class Win32DpiHelper { +class Win32DpiHelperPub { public: - Win32DpiHelper(); + Win32DpiHelperPub(); - ~Win32DpiHelper(); + ~Win32DpiHelperPub(); /// Returns the DPI for |hwnd|. Supports all DPI awareness modes, and is /// backward compatible down to Windows Vista. If |hwnd| is nullptr, returns @@ -56,7 +56,7 @@ class Win32DpiHelper { bool dpi_for_monitor_supported_ = false; }; -Win32DpiHelper::Win32DpiHelper() { +Win32DpiHelperPub::Win32DpiHelperPub() { if ((user32_module_ = LoadLibraryA("User32.dll")) != nullptr) { dpi_for_window_supported_ = (AssignProcAddress( user32_module_, "GetDpiForWindow", get_dpi_for_window_)); @@ -67,7 +67,7 @@ Win32DpiHelper::Win32DpiHelper() { } } -Win32DpiHelper::~Win32DpiHelper() { +Win32DpiHelperPub::~Win32DpiHelperPub() { if (user32_module_ != nullptr) { FreeLibrary(user32_module_); } @@ -76,7 +76,7 @@ Win32DpiHelper::~Win32DpiHelper() { } } -UINT Win32DpiHelper::GetDpiForWindow(HWND hwnd) { +UINT Win32DpiHelperPub::GetDpiForWindow(HWND hwnd) { // GetDpiForWindow returns the DPI for any awareness mode. If not available, // or no |hwnd| is provided, fallback to a per monitor, system, or default // DPI. @@ -97,7 +97,7 @@ UINT Win32DpiHelper::GetDpiForWindow(HWND hwnd) { return dpi; } -UINT Win32DpiHelper::GetDpiForMonitor(HMONITOR monitor) { +UINT Win32DpiHelperPub::GetDpiForMonitor(HMONITOR monitor) { if (dpi_for_monitor_supported_) { if (monitor == nullptr) { const POINT target_point = {0, 0}; @@ -113,10 +113,10 @@ UINT Win32DpiHelper::GetDpiForMonitor(HMONITOR monitor) { return kDefaultDpi; } // namespace -Win32DpiHelper* GetHelper() { - static Win32DpiHelper* dpi_helper = new Win32DpiHelper(); +Win32DpiHelperPub* GetHelper() { + static Win32DpiHelperPub* dpi_helper = new Win32DpiHelperPub(); return dpi_helper; -} + } // namespace UINT GetDpiForHWND(HWND hwnd) { @@ -126,4 +126,5 @@ UINT GetDpiForHWND(HWND hwnd) { UINT GetDpiForMonitor(HMONITOR monitor) { return GetHelper()->GetDpiForMonitor(monitor); } +} // namespace pubdpi } // namespace flutter diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller.cc b/shell/platform/windows/client_wrapper/flutter_view_controller.cc deleted file mode 100644 index a16a0699dd188..0000000000000 --- a/shell/platform/windows/client_wrapper/flutter_view_controller.cc +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "include/flutter/flutter_view_controller.h" - -#include -#include - -namespace flutter { - -FlutterViewController::FlutterViewController(int width, - int height, - const DartProject& project) { - std::vector switches; - std::transform( - project.engine_switches().begin(), project.engine_switches().end(), - std::back_inserter(switches), - [](const std::string& arg) -> const char* { return arg.c_str(); }); - size_t switch_count = switches.size(); - - FlutterDesktopEngineProperties properties = {}; - properties.assets_path = project.assets_path().c_str(); - properties.icu_data_path = project.icu_data_path().c_str(); - properties.switches = switch_count > 0 ? switches.data() : nullptr; - properties.switches_count = switch_count; - controller_ = FlutterDesktopCreateViewController(width, height, properties); - if (!controller_) { - std::cerr << "Failed to create view controller." << std::endl; - return; - } - view_ = std::make_unique(FlutterDesktopGetView(controller_)); -} - -FlutterViewController::FlutterViewController( - const std::string& icu_data_path, - int width, - int height, - const std::string& assets_path, - const std::vector& arguments) { - if (controller_) { - std::cerr << "Only one Flutter view can exist at a time." << std::endl; - } - - std::vector engine_arguments; - std::transform( - arguments.begin(), arguments.end(), std::back_inserter(engine_arguments), - [](const std::string& arg) -> const char* { return arg.c_str(); }); - size_t arg_count = engine_arguments.size(); - - controller_ = FlutterDesktopCreateViewControllerLegacy( - width, height, assets_path.c_str(), icu_data_path.c_str(), - arg_count > 0 ? &engine_arguments[0] : nullptr, arg_count); - if (!controller_) { - std::cerr << "Failed to create view controller." << std::endl; - return; - } - view_ = std::make_unique(FlutterDesktopGetView(controller_)); -} - -FlutterViewController::~FlutterViewController() { - if (controller_) { - FlutterDesktopDestroyViewController(controller_); - } -} - -std::chrono::nanoseconds FlutterViewController::ProcessMessages() { - return std::chrono::nanoseconds(FlutterDesktopProcessMessages(controller_)); -} - -FlutterDesktopPluginRegistrarRef FlutterViewController::GetRegistrarForPlugin( - const std::string& plugin_name) { - if (!controller_) { - std::cerr << "Cannot get plugin registrar without a window; call " - "CreateWindow first." - << std::endl; - return nullptr; - } - return FlutterDesktopGetPluginRegistrar(controller_, plugin_name.c_str()); -} - -} // namespace flutter diff --git a/shell/platform/windows/client_wrapper/include/flutter/dart_project.h b/shell/platform/windows/client_wrapper/include/flutter/dart_project.h index 3595239ebd51d..b5516d0d8c7e9 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/dart_project.h +++ b/shell/platform/windows/client_wrapper/include/flutter/dart_project.h @@ -43,7 +43,7 @@ class DartProject { // flexible options for project structures are needed later without it // being a breaking change. Provide access to internal classes that need // them. - friend class FlutterViewController; + friend class Win32FlutterViewController; friend class DartProjectTest; const std::wstring& assets_path() const { return assets_path_; } diff --git a/shell/platform/windows/dpi_utils.h b/shell/platform/windows/client_wrapper/include/flutter/dpi_utils_pub.h similarity index 95% rename from shell/platform/windows/dpi_utils.h rename to shell/platform/windows/client_wrapper/include/flutter/dpi_utils_pub.h index 1c14994b61235..0e79e32a8bb07 100644 --- a/shell/platform/windows/dpi_utils.h +++ b/shell/platform/windows/client_wrapper/include/flutter/dpi_utils_pub.h @@ -8,6 +8,7 @@ #define FLUTTER_SHELL_PLATFORM_WINDOWS_DPI_UTILS_H_ namespace flutter { +namespace pubdpi { /// Returns the DPI for |hwnd|. Supports all DPI awareness modes, and is /// backward compatible down to Windows Vista. If |hwnd| is nullptr, returns the @@ -18,7 +19,7 @@ UINT GetDpiForHWND(HWND hwnd); /// Returns the DPI of a given monitor. Defaults to 96 if the API is not /// available. UINT GetDpiForMonitor(HMONITOR monitor); - +} // namespace pubdpi } // namespace flutter #endif // FLUTTER_SHELL_PLATFORM_WINDOWS_DPI_UTILS_H_ diff --git a/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h b/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h deleted file mode 100644 index 18c908e977deb..0000000000000 --- a/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_H_ -#define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_H_ - -#include - -namespace flutter { - -// A view displaying Flutter content. -class FlutterView { - public: - explicit FlutterView(FlutterDesktopViewRef view) : view_(view) {} - - virtual ~FlutterView() = default; - - // Prevent copying. - FlutterView(FlutterView const&) = delete; - FlutterView& operator=(FlutterView const&) = delete; - - // Returns the backing HWND for the view. - HWND GetNativeWindow() { return FlutterDesktopViewGetHWND(view_); } - - private: - // Handle for interacting with the C API's view. - FlutterDesktopViewRef view_ = nullptr; -}; - -} // namespace flutter - -#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_H_ diff --git a/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h b/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h index 052f22bbc8a80..da0e4e4288533 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h +++ b/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h @@ -9,7 +9,7 @@ #include -#include "flutter_view.h" +#include "win32_flutter_view.h" #include "plugin_registrar.h" namespace flutter { @@ -23,7 +23,7 @@ class PluginRegistrarWindows : public PluginRegistrar { explicit PluginRegistrarWindows( FlutterDesktopPluginRegistrarRef core_registrar) : PluginRegistrar(core_registrar) { - view_ = std::make_unique( + view_ = std::make_unique( FlutterDesktopRegistrarGetView(core_registrar)); } @@ -33,11 +33,11 @@ class PluginRegistrarWindows : public PluginRegistrar { PluginRegistrarWindows(PluginRegistrarWindows const&) = delete; PluginRegistrarWindows& operator=(PluginRegistrarWindows const&) = delete; - FlutterView* GetView() { return view_.get(); } + Win32FlutterView* GetView() { return view_.get(); } private: // The associated FlutterView, if any. - std::unique_ptr view_; + std::unique_ptr view_; }; } // namespace flutter diff --git a/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view.h b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view.h new file mode 100644 index 0000000000000..01169e591df6e --- /dev/null +++ b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view.h @@ -0,0 +1,81 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_H_ +#define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_H_ + +//#include + +#include +#include "win32_flutter_window_pub.h" + +namespace flutter { + +// A view displaying Flutter content. +class Win32FlutterView { + public: + explicit Win32FlutterView( + FlutterDesktopViewRef view + ) + : view_(view) { + } + + virtual ~Win32FlutterView() = default; + + // Prevent copying. + Win32FlutterView(Win32FlutterView const&) = delete; + Win32FlutterView& operator=(Win32FlutterView const&) = delete; + + // Returns the backing HWND for the view. + HWND GetNativeWindow() { + // Retreive our hosting state from the backing view + HostEnvironmentState windowptr = V2FlutterDesktopGetHostState(view_); + Win32FlutterWindowPub* ptr = static_cast(windowptr); + return ptr->GetWindowHandle(); + } + + void SendWindowMetrics(size_t width, size_t height, double dpiScale) { + V2FlutterDesktopSendWindowMetrics(view_, width, height, dpiScale); + } + + void SendPointerMove(double x, double y) { + V2FlutterDesktopSendPointerMove(view_, x, y); + } + + void SendPointerDown(double x, double y, uint64_t btn) { + V2FlutterDesktopSendPointerDown(view_, x, y, btn); + } + + void SendPointerUp(double x, double y, uint64_t btn) { + V2FlutterDesktopSendPointerUp(view_, x, y, btn); + } + + void SendPointerLeave() { V2FlutterDesktopSendPointerLeave(view_); + } + + void SendScroll(double x, double y, double delta_x, double delta_y) { + V2FlutterDesktopSendScroll(view_, x, y, delta_x, delta_y); + } + + void SendFontChange() { + V2FlutterDesktopSendFontChange(view_); + } + + void SendText(const char16_t* code_point, size_t size) { + V2FlutterDesktopSendText(view_, code_point, size); + } + + void SendKey(int key, int scancode, int action, char32_t character) { + V2FlutterDesktopSendKey(view_, key, scancode, action, character); + } + + + private: + // Handle for interacting with the C API's view. + FlutterDesktopViewRef view_ = nullptr; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_H_ diff --git a/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view_controller.h similarity index 62% rename from shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h rename to shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view_controller.h index 607e01a72f247..3603203882b11 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h +++ b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view_controller.h @@ -6,15 +6,18 @@ #define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_CONTROLLER_H_ #include +#include +#include #include #include #include #include "dart_project.h" -#include "flutter_view.h" +#include "win32_flutter_view.h" #include "plugin_registrar.h" #include "plugin_registry.h" +#include "win32_flutter_window_pub.h" namespace flutter { @@ -23,30 +26,30 @@ namespace flutter { // This is the primary wrapper class for the desktop C API. // If you use this class, you should not call any of the setup or teardown // methods in the C API directly, as this class will do that internally. -class FlutterViewController : public PluginRegistry { +class Win32FlutterViewController : public PluginRegistry { public: // Creates a FlutterView that can be parented into a Windows View hierarchy // either using HWNDs or in the future into a CoreWindow, or using compositor. // // |dart_project| will be used to configure the engine backing this view. - explicit FlutterViewController(int width, + explicit Win32FlutterViewController(int width, int height, - const DartProject& project); + const DartProject& project, + void* compositor); - // DEPRECATED. Will be removed soon; use the version above. - explicit FlutterViewController(const std::string& icu_data_path, - int width, + //TODO + explicit Win32FlutterViewController(int width, int height, - const std::string& assets_path, - const std::vector& arguments); + const DartProject& project, + HWND parentwindow); - virtual ~FlutterViewController(); + virtual ~Win32FlutterViewController(); // Prevent copying. - FlutterViewController(FlutterViewController const&) = delete; - FlutterViewController& operator=(FlutterViewController const&) = delete; + Win32FlutterViewController(Win32FlutterViewController const&) = delete; + Win32FlutterViewController& operator=(Win32FlutterViewController const&) = delete; - FlutterView* view() { return view_.get(); } + Win32FlutterView* view() { return view_.get(); } // Processes any pending events in the Flutter engine, and returns the // nanosecond delay until the next scheduled event (or max, if none). @@ -64,8 +67,18 @@ class FlutterViewController : public PluginRegistry { // Handle for interacting with the C API's view controller, if any. FlutterDesktopViewControllerRef controller_ = nullptr; - // The owned FlutterView. - std::unique_ptr view_; + //// The owned FlutterView. + std::unique_ptr view_; + + // The owned Flutter child window + std::unique_ptr child_window_; + + // Compositor smart pointer + winrt::Windows::UI::Composition::Compositor compositor_{nullptr}; + + // DispatcherQueueController smart pointer + winrt::Windows::System::DispatcherQueueController dispatcherController_{ + nullptr}; }; } // namespace flutter diff --git a/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_window_pub.h b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_window_pub.h new file mode 100644 index 0000000000000..531336bd1395f --- /dev/null +++ b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_window_pub.h @@ -0,0 +1,129 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_H_ +#define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_H_ + +#include + +#include +#include +#include + +#include +//#include +#include +#include +#include +#include + +#include +#include "win32_window_pub.h" + +namespace flutter { + + //TODO these should not be copied and pasted.. confirm with stuart per constants in flutter_windows.h + typedef enum { + kFlutterPointerButtonMousePrimary = 1 << 0, + kFlutterPointerButtonMouseSecondary = 1 << 1, + kFlutterPointerButtonMouseMiddle = 1 << 2, + kFlutterPointerButtonMouseBack = 1 << 3, + kFlutterPointerButtonMouseForward = 1 << 4, + /// If a mouse has more than five buttons, send higher bit shifted values + /// corresponding to the button number: 1 << 5 for the 6th, etc. +} FlutterPointerMouseButtons; + +//Forward declare to avoid circular references +class Win32FlutterView; + +// A win32 flutter child window used as implementatin for flutter view. In the +// future, there will likely be a CoreWindow-based FlutterWindow as well. At +// the point may make sense to dependency inject the native window rather than +// inherit. +class Win32FlutterWindowPub : public Win32WindowPub { + public: + // Create flutter Window for use as child window + Win32FlutterWindowPub( + int width, + int height, + winrt::Windows::UI::Composition::Compositor const& compositor); + + // Create flutter Window for use as child window + Win32FlutterWindowPub( + int width, + int height); + + virtual ~Win32FlutterWindowPub(); + + //TODO + void SetView(Win32FlutterView* view); + + // |Win32WindowPub| + void OnDpiScale(unsigned int dpi) override; + + // |Win32WindowPub| + void OnResize(unsigned int width, unsigned int height) override; + + // |Win32WindowPub| + void OnPointerMove(double x, double y) override; + + // |Win32WindowPub| + void OnPointerDown(double x, double y, UINT button) override; + + // |Win32WindowPub| + void OnPointerUp(double x, double y, UINT button) override; + + // |Win32WindowPub| + void OnPointerLeave() override; + + // |Win32WindowPub| + void OnText(const std::u16string& text) override; + + // |Win32WindowPub| + void OnKey(int key, int scancode, int action, char32_t character) override; + + // |Win32WindowPub| + void OnScroll(double delta_x, double delta_y) override; + + // |Win32WindowPub| + void OnFontChange() override; + + winrt::Windows::UI::Composition::Compositor compositor_; + + winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget target_{nullptr}; + + winrt::Windows::UI::Composition::SpriteVisual host_visual_{nullptr}; + + // Sends a window metrics update to the Flutter engine using current window + // dimensions in physical + void SendWindowMetrics(); + + private: + Win32FlutterView* flutter_view_; + // // Destroy current rendering surface if one has been allocated. + // void DestroyRenderSurface(); + + // // Reports a mouse movement to Flutter engine. + void SendPointerMove(double x, double y); + + // // Reports mouse press to Flutter engine. + void SendPointerDown(double x, double y, uint64_t btn); + + // // Reports mouse release to Flutter engine. + void SendPointerUp(double x, double y, uint64_t btn); + + // // Reports mouse left the window client area. + // // + // // Win32 api doesn't have "mouse enter" event. Therefore, there is no + // // SendPointerEnter method. A mouse enter event is tracked then the "move" + // // event is called. + void SendPointerLeave(); + + // // Updates |event_data| with the current location of the mouse cursor. + void GetEventLocationFromCursorPosition(POINT& location); +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_H_ diff --git a/shell/platform/windows/win32_window.h b/shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h similarity index 93% rename from shell/platform/windows/win32_window.h rename to shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h index d4481d89e2a68..4fec59bd34301 100644 --- a/shell/platform/windows/win32_window.h +++ b/shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h @@ -15,7 +15,7 @@ namespace flutter { // Struct holding the mouse state. The engine doesn't keep track of which mouse // buttons have been pressed, so it's the embedding's responsibility. -struct MouseState { +struct MouseStatePub { // True if the last event sent to Flutter had at least one mouse button // pressed. bool flutter_state_is_down = false; @@ -32,10 +32,10 @@ struct MouseState { // 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 { +class Win32WindowPub { public: - Win32Window(); - virtual ~Win32Window(); + Win32WindowPub(); + virtual ~Win32WindowPub(); // Initializes as a child window with size using |width| and |height| and // |title| to identify the windowclass. Does not show window, window must be @@ -121,10 +121,10 @@ class Win32Window { UINT GetCurrentHeight(); // Gets the current mouse state. - MouseState GetMouseState() { return mouse_state_; } + MouseStatePub GetMouseStatePub() { return mouse_state_; } // Resets the mouse state to its default values. - void ResetMouseState() { mouse_state_ = MouseState(); } + void ResetMouseState() { mouse_state_ = MouseStatePub(); } // Updates the mouse state to whether the last event to Flutter had at least // one mouse button pressed. @@ -141,6 +141,8 @@ class Win32Window { // Updates the currently pressed buttons. void SetMouseButtons(uint64_t buttons) { mouse_state_.buttons = buttons; } + + private: // Release OS resources asociated with window. void Destroy(); @@ -152,7 +154,7 @@ class Win32Window { void HandleResize(UINT width, UINT height); // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; + static Win32WindowPub* GetThisFromHandle(HWND const window) noexcept; int current_dpi_ = 0; int current_width_ = 0; int current_height_ = 0; @@ -164,6 +166,9 @@ class Win32Window { // Member variable to hold window handle. HWND window_handle_ = nullptr; + // Member variable to hold window handle. + HWND parent_content_ = nullptr; + // Member variable to hold the window title. std::wstring window_class_name_; @@ -171,7 +176,7 @@ class Win32Window { bool tracking_mouse_leave_ = false; // Keeps track of mouse state in relation to the window. - MouseState mouse_state_; + MouseStatePub mouse_state_; // Keeps track of the last key code produced by a WM_KEYDOWN or WM_SYSKEYDOWN // message. diff --git a/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc b/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc index b84d9195daf26..15bdabb6717d0 100644 --- a/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc +++ b/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc @@ -35,34 +35,125 @@ ScopedStubFlutterWindowsApi::~ScopedStubFlutterWindowsApi() { // Forwarding dummy implementations of the C API. -FlutterDesktopViewControllerRef FlutterDesktopCreateViewController( +FlutterDesktopViewControllerRef V2CreateViewControllerWindow( int width, int height, - const FlutterDesktopEngineProperties& engine_properties) { + const FlutterDesktopEngineProperties& engine_properties, + HWND windowrendertarget, + HostEnvironmentState state) { if (s_stub_implementation) { - return s_stub_implementation->CreateViewController(width, height, - engine_properties); + return s_stub_implementation->V2CreateViewControllerWindow(width, height, + engine_properties, windowrendertarget, state); } return nullptr; } -FlutterDesktopViewControllerRef FlutterDesktopCreateViewControllerLegacy( - int initial_width, - int initial_height, - const char* assets_path, - const char* icu_data_path, - const char** arguments, - size_t argument_count) { +FlutterDesktopViewControllerRef V2CreateViewControllerVisual( + int width, + int height, + const FlutterDesktopEngineProperties& engine_properties, + ABI::Windows::UI::Composition::IVisual* visual, + HostEnvironmentState state) { if (s_stub_implementation) { - // This stub will be removed shortly, and the current tests don't need the - // arguments, so there's no need to translate them to engine_properties. - FlutterDesktopEngineProperties engine_properties; - return s_stub_implementation->CreateViewController( - initial_width, initial_height, engine_properties); + return s_stub_implementation->V2CreateViewControllerVisual( + width, height, + engine_properties, visual, state); } return nullptr; } +void* V2FlutterDesktopViewGetVisual(FlutterDesktopViewRef view) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopViewGetVisual(view); + } + return nullptr; +} + +void V2FlutterDesktopSendWindowMetrics( + FlutterDesktopViewRef view, + size_t width, + size_t height, + double dpiScale) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopSendWindowMetrics(view, width, height, dpiScale); + } +} + +void V2FlutterDesktopSendPointerMove(FlutterDesktopViewRef view, + double x, + double y) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopSendPointerMove( + view, x, y); + } +} + +void V2FlutterDesktopSendPointerDown( + FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopSendPointerDown(view, x, y, btn); + } +} + +void V2FlutterDesktopSendPointerUp( + FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopSendPointerUp(view, x, y, + btn); + } +} + +void V2FlutterDesktopSendPointerLeave(FlutterDesktopViewRef view) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopSendPointerLeave(view); + } +} + +void V2FlutterDesktopSendScroll(FlutterDesktopViewRef view, + double x, + double y, + double delta_x, + double delta_y) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopSendScroll(view, x, y, + delta_x, delta_y); + } +} + +void V2FlutterDesktopSendFontChange(FlutterDesktopViewRef view) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopSendFontChange(view); + } +} + +void V2FlutterDesktopSendText(FlutterDesktopViewRef view, + const char16_t* code_point, + size_t size) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopSendText(view, code_point, + size); + } +} + +void V2FlutterDesktopSendKey(FlutterDesktopViewRef view, + int key, + int scancode, + int action, + char32_t character) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopSendKey(view, key, scancode, action, character + ); + } +} + + + void FlutterDesktopDestroyViewController( FlutterDesktopViewControllerRef controller) { if (s_stub_implementation) { @@ -91,6 +182,13 @@ HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef controller) { return reinterpret_cast(-1); } +void* V2FlutterDesktopGetHostState(FlutterDesktopViewRef view) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopGetHostState(view); + } + return static_cast(nullptr); +} + FlutterDesktopEngineRef FlutterDesktopRunEngine( const FlutterDesktopEngineProperties& engine_properties) { if (s_stub_implementation) { @@ -118,3 +216,4 @@ FlutterDesktopViewRef FlutterDesktopRegistrarGetView( // The stub ignores this, so just return an arbitrary non-zero value. return reinterpret_cast(1); } + diff --git a/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h b/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h index 631d445802f28..04fd3984d6c24 100644 --- a/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h +++ b/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h @@ -7,6 +7,8 @@ #include +#include + #include "flutter/shell/platform/windows/public/flutter_windows.h" namespace flutter { @@ -30,13 +32,74 @@ class StubFlutterWindowsApi { virtual ~StubFlutterWindowsApi() {} // Called for FlutterDesktopCreateViewController. - virtual FlutterDesktopViewControllerRef CreateViewController( + virtual FlutterDesktopViewControllerRef V2CreateViewControllerWindow( int width, int height, - const FlutterDesktopEngineProperties& engine_properties) { + const FlutterDesktopEngineProperties& engine_properties, + HWND windowrendertarget, + HostEnvironmentState state + ) { + return nullptr; + } + + virtual FlutterDesktopViewControllerRef V2CreateViewControllerVisual( + int width, + int height, + const FlutterDesktopEngineProperties& engine_properties, + ABI::Windows::UI::Composition::IVisual* visual, + HostEnvironmentState state +) { return nullptr; } + virtual void* V2FlutterDesktopViewGetVisual(FlutterDesktopViewRef view) { + return nullptr; + } + + // TODO + virtual void V2FlutterDesktopSendWindowMetrics( + FlutterDesktopViewRef view, + size_t width, + size_t height, + double dpiScale) {} + + virtual void V2FlutterDesktopSendPointerMove(FlutterDesktopViewRef view, + double x, + double y) {} + + virtual void V2FlutterDesktopSendPointerDown(FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn) {} + + virtual void V2FlutterDesktopSendPointerUp(FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn) {} + + virtual void V2FlutterDesktopSendPointerLeave(FlutterDesktopViewRef view) {} + + // TODO + virtual void V2FlutterDesktopSendScroll(FlutterDesktopViewRef view, + double x, + double y, + double delta_x, + double delta_y) {} + // TODO + virtual void V2FlutterDesktopSendFontChange(FlutterDesktopViewRef view) {} + + // TODO + virtual void V2FlutterDesktopSendText(FlutterDesktopViewRef view, + const char16_t* code_point, + size_t size) {} + + // TODO + virtual void V2FlutterDesktopSendKey(FlutterDesktopViewRef view, + int key, + int scancode, + int action, + char32_t character) {} + // Called for FlutterDesktopDestroyView. virtual void DestroyViewController() {} @@ -52,6 +115,10 @@ class StubFlutterWindowsApi { return nullptr; } + virtual HostEnvironmentState V2FlutterDesktopGetHostState(FlutterDesktopViewRef view) { + return nullptr; + } + // Called for FlutterDesktopShutDownEngine. virtual bool ShutDownEngine() { return true; } }; diff --git a/shell/platform/windows/client_wrapper/win32_flutter_view_controller.cc b/shell/platform/windows/client_wrapper/win32_flutter_view_controller.cc new file mode 100644 index 0000000000000..905e9180b9035 --- /dev/null +++ b/shell/platform/windows/client_wrapper/win32_flutter_view_controller.cc @@ -0,0 +1,131 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "include/flutter/win32_flutter_view_controller.h" +#include +#include +#include +#include + + +#include +#include + +namespace flutter { + +auto CreateDispatcherQueueController() { + namespace abi = ABI::Windows::System; + + DispatcherQueueOptions options{sizeof(DispatcherQueueOptions), + DQTYPE_THREAD_CURRENT, DQTAT_COM_STA}; + + winrt::Windows::System::DispatcherQueueController controller{nullptr}; + winrt::check_hresult(CreateDispatcherQueueController( + options, reinterpret_cast( + winrt::put_abi(controller)))); + return controller; +} + +// Compositor overload +Win32FlutterViewController::Win32FlutterViewController(int width, + int height, + const DartProject& project, + void* compositor) { + if (compositor == nullptr) { + std::cerr << "Failed to create view controller: compositor can't be null." << std::endl; + return; + } + + std::vector switches; + std::transform( + project.engine_switches().begin(), project.engine_switches().end(), + std::back_inserter(switches), + [](const std::string& arg) -> const char* { return arg.c_str(); }); + size_t switch_count = switches.size(); + + FlutterDesktopEngineProperties properties = {}; + properties.assets_path = project.assets_path().c_str(); + properties.icu_data_path = project.icu_data_path().c_str(); + properties.switches = switch_count > 0 ? switches.data() : nullptr; + properties.switches_count = switch_count; + + child_window_ = + std::make_unique(width, height, compositor_); + + HostEnvironmentState host_state = + static_cast(child_window_.get()); + + controller_ = V2CreateViewControllerVisual( + width, height, properties, + static_cast( + winrt::get_abi(compositor_)), + host_state); + if (!controller_) { + std::cerr << "Failed to create view controller." << std::endl; + return; + } + view_ = std::make_unique(FlutterDesktopGetView(controller_)); + child_window_->SetView(view_.get()); +} + +// Window overload +Win32FlutterViewController::Win32FlutterViewController(int width, + int height, + const DartProject& project, + HWND parentwindow) { + std::vector switches; + std::transform( + project.engine_switches().begin(), project.engine_switches().end(), + std::back_inserter(switches), + [](const std::string& arg) -> const char* { return arg.c_str(); }); + size_t switch_count = switches.size(); + + FlutterDesktopEngineProperties properties = {}; + properties.assets_path = project.assets_path().c_str(); + properties.icu_data_path = project.icu_data_path().c_str(); + properties.switches = switch_count > 0 ? switches.data() : nullptr; + properties.switches_count = switch_count; + + child_window_ = + std::make_unique(width, height); + + HostEnvironmentState host_state = + static_cast(child_window_.get()); + + controller_ = V2CreateViewControllerWindow( + width, height, properties, + child_window_->GetWindowHandle(), + host_state); + if (!controller_) { + std::cerr << "Failed to create view controller." << std::endl; + return; + } + view_ = std::make_unique(FlutterDesktopGetView(controller_)); + child_window_->SetView(view_.get()); +} + +Win32FlutterViewController::~Win32FlutterViewController() { + if (controller_) { + FlutterDesktopDestroyViewController(controller_); + } +} + +std::chrono::nanoseconds Win32FlutterViewController::ProcessMessages() { + return std::chrono::nanoseconds(FlutterDesktopProcessMessages(controller_)); +} + +FlutterDesktopPluginRegistrarRef Win32FlutterViewController::GetRegistrarForPlugin( + const std::string& plugin_name) { + if (!controller_) { + std::cerr << "Cannot get plugin registrar without a window; call " + "CreateWindow first." + << std::endl; + return nullptr; + } + return FlutterDesktopGetPluginRegistrar(controller_, plugin_name.c_str()); +} + +} // namespace flutter diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc b/shell/platform/windows/client_wrapper/win32_flutter_view_controller_unittests.cc similarity index 60% rename from shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc rename to shell/platform/windows/client_wrapper/win32_flutter_view_controller_unittests.cc index ec1b7fb561eae..3ca9a439b927f 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc +++ b/shell/platform/windows/client_wrapper/win32_flutter_view_controller_unittests.cc @@ -5,7 +5,7 @@ #include #include -#include "flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h" +#include "flutter/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view_controller.h" #include "flutter/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h" #include "gtest/gtest.h" @@ -15,40 +15,33 @@ namespace { // Stub implementation to validate calls to the API. class TestWindowsApi : public testing::StubFlutterWindowsApi { - FlutterDesktopViewControllerRef CreateViewController( + FlutterDesktopViewControllerRef V2CreateViewControllerWindow( int width, int height, - const FlutterDesktopEngineProperties& engine_properties) override { + const FlutterDesktopEngineProperties& engine_properties, + HWND windowrendertarget, + HostEnvironmentState hostwindow + ) override { return reinterpret_cast(1); } }; } // namespace -TEST(FlutterViewControllerTest, CreateDestroyLegacy) { - testing::ScopedStubFlutterWindowsApi scoped_api_stub( - std::make_unique()); - auto test_api = static_cast(scoped_api_stub.stub()); - { - FlutterViewController controller("", 100, 100, "", - std::vector{}); - } -} - -TEST(FlutterViewControllerTest, CreateDestroy) { +TEST(Win32FlutterViewControllerTest, CreateDestroy) { DartProject project(L"data"); testing::ScopedStubFlutterWindowsApi scoped_api_stub( std::make_unique()); auto test_api = static_cast(scoped_api_stub.stub()); - { FlutterViewController controller(100, 100, project); } + { Win32FlutterViewController controller(100, 100, project, static_cast(nullptr)); } } -TEST(FlutterViewControllerTest, GetView) { +TEST(Win32FlutterViewControllerTest, GetView) { DartProject project(L"data"); testing::ScopedStubFlutterWindowsApi scoped_api_stub( std::make_unique()); auto test_api = static_cast(scoped_api_stub.stub()); - FlutterViewController controller(100, 100, project); + Win32FlutterViewController controller(100, 100, project, static_cast(nullptr)); EXPECT_NE(controller.view(), nullptr); } diff --git a/shell/platform/windows/client_wrapper/flutter_view_unittests.cc b/shell/platform/windows/client_wrapper/win32_flutter_view_unittests.cc similarity index 85% rename from shell/platform/windows/client_wrapper/flutter_view_unittests.cc rename to shell/platform/windows/client_wrapper/win32_flutter_view_unittests.cc index 6fbe2981aa09b..3cd8eba565002 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_unittests.cc +++ b/shell/platform/windows/client_wrapper/win32_flutter_view_unittests.cc @@ -5,7 +5,7 @@ #include #include -#include "flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h" +#include "flutter/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view.h" #include "flutter/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.h" #include "gtest/gtest.h" @@ -20,11 +20,11 @@ class TestWindowsApi : public testing::StubFlutterWindowsApi { } // namespace -TEST(FlutterViewTest, HwndAccessPassesThrough) { +TEST(Win32FlutterViewTest, HwndAccessPassesThrough) { testing::ScopedStubFlutterWindowsApi scoped_api_stub( std::make_unique()); auto test_api = static_cast(scoped_api_stub.stub()); - FlutterView view(reinterpret_cast(2)); + Win32FlutterView view(reinterpret_cast(2)); EXPECT_EQ(view.GetNativeWindow(), reinterpret_cast(7)); } diff --git a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc new file mode 100644 index 0000000000000..e79f24df58a23 --- /dev/null +++ b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc @@ -0,0 +1,173 @@ +#include "include/flutter/win32_flutter_window_pub.h" + +#include + +#include "include/flutter/win32_flutter_view.h" + +namespace flutter { + +winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget +CreateDesktopWindowTarget( + winrt::Windows::UI::Composition::Compositor const& compositor, + HWND window) { + namespace abi = ABI::Windows::UI::Composition::Desktop; + + // attempt workaround for https://bugs.llvm.org/show_bug.cgi?id=38490 + + //auto interop = compositor.as(); + winrt::com_ptr interop; + //winrt::check_hresult(compositor.as(__uuidof(interop), interop.put_void())); + winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget target{nullptr}; + /* + winrt::check_hresult(interop->CreateDesktopWindowTarget( + window, true, + reinterpret_cast(winrt::put_abi(target)))); + return target;*/ + return nullptr; +} + +// The Windows DPI system is based on this +// constant for machines running at 100% scaling. +constexpr int base_dpi = 96; + +Win32FlutterWindowPub::Win32FlutterWindowPub( + int width, + int height, + winrt::Windows::UI::Composition::Compositor const& compositor) + : compositor_(compositor), flutter_view_(nullptr) { + Win32WindowPub::InitializeChild("Win32FlutterView", width, height); + + // Create Window target, set visual returned from the engine as the root + target_ = + CreateDesktopWindowTarget(compositor_, Win32WindowPub::GetWindowHandle()); + + host_visual_ = compositor_.CreateSpriteVisual(); + target_.Root(host_visual_); +} + +Win32FlutterWindowPub::Win32FlutterWindowPub(int width, int height) + : compositor_(nullptr), flutter_view_(nullptr) { + Win32WindowPub::InitializeChild("Win32FlutterView", width, height); +} + +void Win32FlutterWindowPub::SetView(Win32FlutterView* view) { + flutter_view_ = view; +} + +Win32FlutterWindowPub::~Win32FlutterWindowPub() {} + +// Translates button codes from Win32 API to FlutterPointerMouseButtons. + static uint64_t ConvertWinButtonToFlutterButton(UINT button) { + switch (button) { + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + return kFlutterPointerButtonMousePrimary; + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + return kFlutterPointerButtonMouseSecondary; + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + return kFlutterPointerButtonMouseMiddle; + case XBUTTON1: + return kFlutterPointerButtonMouseBack; + case XBUTTON2: + return kFlutterPointerButtonMouseForward; + } + std::cerr << "Mouse button not recognized: " << button << std::endl; + return 0; +} + +void Win32FlutterWindowPub::OnDpiScale(unsigned int dpi){ + if (flutter_view_ != nullptr) { + flutter_view_->SendWindowMetrics( + GetCurrentWidth(), GetCurrentHeight(), + static_cast(GetCurrentDPI()) / base_dpi); + } +}; + +// When DesktopWindow notifies that a WM_Size message has come in +// lets FlutterEngine know about the new size. +void Win32FlutterWindowPub::OnResize(unsigned int width, unsigned int height) { + if (flutter_view_ != nullptr) { + flutter_view_->SendWindowMetrics( + GetCurrentWidth(), GetCurrentHeight(), + static_cast(GetCurrentDPI()) / base_dpi); + } +} + +void Win32FlutterWindowPub::OnPointerMove(double x, double y) { + SendPointerMove(x, y); +} + +void Win32FlutterWindowPub::OnPointerDown(double x, double y, UINT button) { + uint64_t flutter_button = ConvertWinButtonToFlutterButton(button); + if (flutter_button != 0) { + SendPointerDown(x, y, flutter_button); + } +} + +void Win32FlutterWindowPub::OnPointerUp(double x, double y, UINT button) { + uint64_t flutter_button = ConvertWinButtonToFlutterButton(button); + if (flutter_button != 0) { + SendPointerUp(x, y, flutter_button); + } +} + +void Win32FlutterWindowPub::OnPointerLeave() { + SendPointerLeave(); +} + +void Win32FlutterWindowPub::OnText(const std::u16string& text) { + flutter_view_->SendText(text.c_str(), text.length()); +} + +void Win32FlutterWindowPub::OnKey(int key, + int scancode, + int action, + char32_t character) { + flutter_view_->SendKey(key, scancode, action, character); +} + +void Win32FlutterWindowPub::OnScroll(double delta_x, double delta_y) { + POINT position; + GetEventLocationFromCursorPosition(position); + flutter_view_->SendScroll(position.x, position.y, delta_x, delta_y); +} + +void Win32FlutterWindowPub::OnFontChange() { + flutter_view_->SendFontChange(); +} + +// Sends new size information to FlutterEngine. +void Win32FlutterWindowPub::SendWindowMetrics() { + flutter_view_->SendWindowMetrics( + GetCurrentWidth(), GetCurrentHeight(), + static_cast(GetCurrentDPI()) / base_dpi); +} + +// Updates |event_data| with the current location of the mouse cursor. +void Win32FlutterWindowPub::GetEventLocationFromCursorPosition( + POINT &location + ) { + GetCursorPos(&location); + + ScreenToClient(GetWindowHandle(), &location); +} + + void Win32FlutterWindowPub::SendPointerMove(double x, double y) { + flutter_view_->SendPointerMove(x, y); + } + + void Win32FlutterWindowPub::SendPointerDown(double x, double y, uint64_t btn) { + flutter_view_->SendPointerDown(x, y, btn); + } + + void Win32FlutterWindowPub::SendPointerUp(double x, double y, uint64_t btn) { + flutter_view_->SendPointerUp(x, y, btn); + } + + void Win32FlutterWindowPub::SendPointerLeave() { + flutter_view_->SendPointerLeave(); + } + +} // namespace flutter diff --git a/shell/platform/windows/win32_window.cc b/shell/platform/windows/client_wrapper/win32_window_pub.cc similarity index 86% rename from shell/platform/windows/win32_window.cc rename to shell/platform/windows/client_wrapper/win32_window_pub.cc index e4cf979167b73..d82e2c1bd65ae 100644 --- a/shell/platform/windows/win32_window.cc +++ b/shell/platform/windows/client_wrapper/win32_window_pub.cc @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "flutter/shell/platform/windows/win32_window.h" +#include "include/flutter/win32_window_pub.h" -#include "dpi_utils.h" +#include "include/flutter/dpi_utils_pub.h" namespace flutter { @@ -15,18 +15,18 @@ char32_t CodePointFromSurrogatePair(wchar_t high, wchar_t low) { } } // namespace -Win32Window::Win32Window() { +Win32WindowPub::Win32WindowPub() { // Get the DPI of the primary monitor as the initial DPI. If Per-Monitor V2 is // supported, |current_dpi_| should be updated in the // kWmDpiChangedBeforeParent message. - current_dpi_ = GetDpiForHWND(nullptr); + current_dpi_ = pubdpi::GetDpiForHWND(nullptr); } -Win32Window::~Win32Window() { +Win32WindowPub::~Win32WindowPub() { Destroy(); } -void Win32Window::InitializeChild(const char* title, +void Win32WindowPub::InitializeChild(const char* title, unsigned int width, unsigned int height) { Destroy(); @@ -42,7 +42,7 @@ void Win32Window::InitializeChild(const char* title, if (result == nullptr) { auto error = GetLastError(); LPWSTR message = nullptr; - size_t size = FormatMessageW( + FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), @@ -52,7 +52,7 @@ void Win32Window::InitializeChild(const char* title, } } -std::wstring Win32Window::NarrowToWide(const char* source) { +std::wstring Win32WindowPub::NarrowToWide(const char* source) { size_t length = strlen(source); size_t outlen = 0; std::wstring wideTitle(length, L'#'); @@ -60,7 +60,7 @@ std::wstring Win32Window::NarrowToWide(const char* source) { return wideTitle; } -WNDCLASS Win32Window::RegisterWindowClass(std::wstring& title) { +WNDCLASS Win32WindowPub::RegisterWindowClass(std::wstring& title) { window_class_name_ = title; WNDCLASS window_class{}; @@ -78,7 +78,7 @@ WNDCLASS Win32Window::RegisterWindowClass(std::wstring& title) { return window_class; } -LRESULT CALLBACK Win32Window::WndProc(HWND const window, +LRESULT CALLBACK Win32WindowPub::WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { @@ -87,16 +87,16 @@ LRESULT CALLBACK Win32Window::WndProc(HWND const window, SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast(cs->lpCreateParams)); - auto that = static_cast(cs->lpCreateParams); + auto that = static_cast(cs->lpCreateParams); that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { + } else if (Win32WindowPub* that = GetThisFromHandle(window)) { return that->MessageHandler(window, message, wparam, lparam); } return DefWindowProc(window, message, wparam, lparam); } -void Win32Window::TrackMouseLeaveEvent(HWND hwnd) { +void Win32WindowPub::TrackMouseLeaveEvent(HWND hwnd) { if (!tracking_mouse_leave_) { TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); @@ -108,20 +108,21 @@ void Win32Window::TrackMouseLeaveEvent(HWND hwnd) { } LRESULT -Win32Window::MessageHandler(HWND hwnd, +Win32WindowPub::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { int xPos = 0, yPos = 0; UINT width = 0, height = 0; auto window = - reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); + reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); UINT button_pressed = 0; if (window != nullptr) { switch (message) { case kWmDpiChangedBeforeParent: - current_dpi_ = GetDpiForHWND(window_handle_); + // TODO may need add after parent + current_dpi_ = pubdpi::GetDpiForHWND(window_handle_); window->OnDpiScale(current_dpi_); return 0; case WM_SIZE: @@ -251,12 +252,12 @@ Win32Window::MessageHandler(HWND hwnd, // Check if this key produces a character. If so, the key press should // be sent with the character produced at WM_CHAR. Store the produced // keycode (it's not accessible from WM_CHAR) to be used in WM_CHAR. - const unsigned int character = MapVirtualKey(wparam, MAPVK_VK_TO_CHAR); + const unsigned int character = MapVirtualKey(static_cast(wparam), MAPVK_VK_TO_CHAR); if (character > 0 && is_keydown_message) { - keycode_for_char_message_ = wparam; + keycode_for_char_message_ = static_cast(wparam); break; } - unsigned int keyCode(wparam); + unsigned int keyCode(static_cast(wparam)); const unsigned int scancode = (lparam >> 16) & 0xff; // If the key is a modifier, get its side. if (keyCode == VK_SHIFT || keyCode == VK_MENU || @@ -273,23 +274,24 @@ Win32Window::MessageHandler(HWND hwnd, return DefWindowProc(window_handle_, message, wparam, lparam); } -UINT Win32Window::GetCurrentDPI() { +UINT Win32WindowPub::GetCurrentDPI() { return current_dpi_; } -UINT Win32Window::GetCurrentWidth() { +UINT Win32WindowPub::GetCurrentWidth() { return current_width_; } -UINT Win32Window::GetCurrentHeight() { +UINT Win32WindowPub::GetCurrentHeight() { return current_height_; } -HWND Win32Window::GetWindowHandle() { +HWND Win32WindowPub::GetWindowHandle() { return window_handle_; } -void Win32Window::Destroy() { +void Win32WindowPub::Destroy() { + //TODO.. unparent? if (window_handle_) { DestroyWindow(window_handle_); window_handle_ = nullptr; @@ -298,14 +300,14 @@ void Win32Window::Destroy() { UnregisterClass(window_class_name_.c_str(), nullptr); } -void Win32Window::HandleResize(UINT width, UINT height) { +void Win32WindowPub::HandleResize(UINT width, UINT height) { current_width_ = width; current_height_ = height; OnResize(width, height); } -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( +Win32WindowPub* Win32WindowPub::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( GetWindowLongPtr(window, GWLP_USERDATA)); } diff --git a/shell/platform/windows/dpi_utils_unittests.cc b/shell/platform/windows/dpi_utils_unittests.cc deleted file mode 100644 index d69da0588827b..0000000000000 --- a/shell/platform/windows/dpi_utils_unittests.cc +++ /dev/null @@ -1,21 +0,0 @@ -#include - -#include "flutter/shell/platform/windows/dpi_utils.h" -#include "gtest/gtest.h" - -namespace flutter { -namespace testing { - -TEST(DpiUtilsTest, NonZero) { - ASSERT_GT(GetDpiForHWND(nullptr), 0); - ASSERT_GT(GetDpiForMonitor(nullptr), 0); -}; - -TEST(DpiUtilsTest, NullHwndUsesPrimaryMonitor) { - const POINT target_point = {0, 0}; - HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTOPRIMARY); - ASSERT_EQ(GetDpiForHWND(nullptr), GetDpiForMonitor(monitor)); -}; - -} // namespace testing -} // namespace flutter diff --git a/shell/platform/windows/flutter_compview_unittests.cc b/shell/platform/windows/flutter_compview_unittests.cc new file mode 100644 index 0000000000000..dd33d993bf5b5 --- /dev/null +++ b/shell/platform/windows/flutter_compview_unittests.cc @@ -0,0 +1,22 @@ +#include "flutter/shell/platform/windows/testing/flutter_compview_test.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { + +TEST(FlutterWindowsViewTest, CreateDestroy) { + FlutterWindowsViewTest window(800, 600); + ASSERT_TRUE(TRUE); +} + +// TODO MOVE to wrapper +// TEST(FlutterWindowsViewTest, CanFontChange) { +// FlutterWindowsViewTest window(800, 600); +// HWND hwnd = window.GetWindowHandle(); +// LRESULT result = SendMessage(hwnd, WM_FONTCHANGE, NULL, NULL); +// ASSERT_EQ(result, 0); +// ASSERT_TRUE(window.OnFontChangeWasCalled()); +//} + +} // namespace testing +} // namespace flutter diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index 805ca6cd31a3a..3f42bae0e7f95 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -14,18 +14,18 @@ #include #include +#include + #include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h" #include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h" #include "flutter/shell/platform/common/cpp/path_utils.h" #include "flutter/shell/platform/embedder/embedder.h" -#include "flutter/shell/platform/windows/dpi_utils.h" +#include "flutter/shell/platform/windows/flutter_windows_view.h" #include "flutter/shell/platform/windows/key_event_handler.h" #include "flutter/shell/platform/windows/keyboard_hook_handler.h" #include "flutter/shell/platform/windows/platform_handler.h" +#include "flutter/shell/platform/windows/task_runner.h" #include "flutter/shell/platform/windows/text_input_plugin.h" -#include "flutter/shell/platform/windows/win32_flutter_window.h" -#include "flutter/shell/platform/windows/win32_task_runner.h" -#include "flutter/shell/platform/windows/window_state.h" static_assert(FLUTTER_ENGINE_VERSION == 1, ""); @@ -38,7 +38,7 @@ static_assert(FLUTTER_ENGINE_VERSION == 1, ""); // Returns the state object for the engine, or null on failure to start the // engine. static std::unique_ptr RunFlutterEngine( - flutter::Win32FlutterWindow* window, + flutter::FlutterWindowsView* window, const FlutterDesktopEngineProperties& engine_properties) { auto state = std::make_unique(); @@ -58,15 +58,15 @@ static std::unique_ptr RunFlutterEngine( config.type = kOpenGL; config.open_gl.struct_size = sizeof(config.open_gl); config.open_gl.make_current = [](void* user_data) -> bool { - auto host = static_cast(user_data); + auto host = static_cast(user_data); return host->MakeCurrent(); }; config.open_gl.clear_current = [](void* user_data) -> bool { - auto host = static_cast(user_data); + auto host = static_cast(user_data); return host->ClearContext(); }; config.open_gl.present = [](void* user_data) -> bool { - auto host = static_cast(user_data); + auto host = static_cast(user_data); return host->SwapBuffers(); }; config.open_gl.fbo_callback = [](void* user_data) -> uint32_t { return 0; }; @@ -75,13 +75,13 @@ static std::unique_ptr RunFlutterEngine( return reinterpret_cast(eglGetProcAddress(what)); }; config.open_gl.make_resource_current = [](void* user_data) -> bool { - auto host = static_cast(user_data); + auto host = static_cast(user_data); return host->MakeResourceCurrent(); }; // Configure task runner interop. auto state_ptr = state.get(); - state->task_runner = std::make_unique( + state->task_runner = std::make_unique( GetCurrentThreadId(), [state_ptr](const auto* task) { if (FlutterEngineRunTask(state_ptr->engine, task) != kSuccess) { std::cerr << "Could not post an engine task." << std::endl; @@ -92,13 +92,13 @@ static std::unique_ptr RunFlutterEngine( platform_task_runner.user_data = state->task_runner.get(); platform_task_runner.runs_task_on_current_thread_callback = [](void* user_data) -> bool { - return reinterpret_cast(user_data) + return reinterpret_cast(user_data) ->RunsTasksOnCurrentThread(); }; platform_task_runner.post_task_callback = [](FlutterTask task, uint64_t target_time_nanos, void* user_data) -> void { - reinterpret_cast(user_data)->PostTask( + reinterpret_cast(user_data)->PostTask( task, target_time_nanos); }; @@ -133,7 +133,7 @@ static std::unique_ptr RunFlutterEngine( args.platform_message_callback = [](const FlutterPlatformMessage* engine_message, void* user_data) -> void { - auto window = reinterpret_cast(user_data); + auto window = reinterpret_cast(user_data); return window->HandlePlatformMessage(engine_message); }; args.custom_task_runners = &custom_task_runners; @@ -150,41 +150,79 @@ static std::unique_ptr RunFlutterEngine( return state; } -FlutterDesktopViewControllerRef FlutterDesktopCreateViewController( +V2FlutterDesktopViewControllerRef V2CreateViewControllerVisual( int width, int height, - const FlutterDesktopEngineProperties& engine_properties) { - FlutterDesktopViewControllerRef state = - flutter::Win32FlutterWindow::CreateWin32FlutterWindow(width, height); + const FlutterDesktopEngineProperties& engine_properties, + ABI::Windows::UI::Composition::IVisual* visual, + HostEnvironmentState externalWindow) { + V2FlutterDesktopViewControllerRef state = + flutter::FlutterWindowsView::CreateFlutterWindowsView(width, height, + visual); auto engine_state = RunFlutterEngine(state->view.get(), engine_properties); if (!engine_state) { return nullptr; } - state->view->SetState(engine_state->engine); + state->view_wrapper->externalwindow = externalWindow; + state->view->SetState(engine_state->engine, externalWindow); state->engine_state = std::move(engine_state); return state; } -FlutterDesktopViewControllerRef FlutterDesktopCreateViewControllerLegacy( - int initial_width, - int initial_height, - const char* assets_path, - const char* icu_data_path, - const char** arguments, - size_t argument_count) { - std::filesystem::path assets_path_fs = std::filesystem::u8path(assets_path); - std::filesystem::path icu_data_path_fs = - std::filesystem::u8path(icu_data_path); - FlutterDesktopEngineProperties engine_properties = {}; - engine_properties.assets_path = assets_path_fs.c_str(); - engine_properties.icu_data_path = icu_data_path_fs.c_str(); - engine_properties.switches = arguments; - engine_properties.switches_count = argument_count; - - return FlutterDesktopCreateViewController(initial_width, initial_height, - engine_properties); +V2FlutterDesktopViewControllerRef V2CreateViewControllerWindow( + int width, + int height, + const FlutterDesktopEngineProperties& engine_properties, + HWND windowrendertarget, + HostEnvironmentState externalWindow) { + V2FlutterDesktopViewControllerRef state = + flutter::FlutterWindowsView::CreateFlutterWindowsViewHwnd( + width, height, externalWindow, static_cast(windowrendertarget)); + + auto engine_state = RunFlutterEngine(state->view.get(), engine_properties); + + if (!engine_state) { + return nullptr; + } + state->view_wrapper->externalwindow = externalWindow; + state->view->SetState(engine_state->engine, externalWindow); + state->engine_state = std::move(engine_state); + return state; +} + +void V2FlutterDesktopSendWindowMetrics(FlutterDesktopViewRef view, + size_t width, + size_t height, + double dpiScale) { + view->window->SendWindowMetrics(width, height, dpiScale); +} + +void V2FlutterDesktopSendPointerMove(FlutterDesktopViewRef view, + double x, + double y) { + view->window->OnPointerMove(x, y); +} + +void V2FlutterDesktopSendPointerDown(FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn) { + view->window->OnPointerDown(x, y, + static_cast(btn)); +} + +void V2FlutterDesktopSendPointerUp(FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn) { + view->window->OnPointerUp(x, y, static_cast(btn)); +} + +// TODO +void V2FlutterDesktopSendPointerLeave(FlutterDesktopViewRef view) { + view->window->OnPointerLeave(); } uint64_t FlutterDesktopProcessMessages( @@ -213,16 +251,41 @@ FlutterDesktopViewRef FlutterDesktopGetView( return controller->view_wrapper.get(); } -HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view) { - return view->window->GetWindowHandle(); +// TODO return something more strongly typed +HostEnvironmentState V2FlutterDesktopGetHostState(FlutterDesktopViewRef view) { + return (HostEnvironmentState)view->externalwindow; } -UINT FlutterDesktopGetDpiForHWND(HWND hwnd) { - return flutter::GetDpiForHWND(hwnd); +// TODO +void V2FlutterDesktopSendScroll(FlutterDesktopViewRef view, + double x, + double y, + double delta_x, + double delta_y) { + view->window->OnScroll(x, y, delta_x, delta_y); } -UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor) { - return flutter::GetDpiForMonitor(monitor); +// TODO +void V2FlutterDesktopSendFontChange(FlutterDesktopViewRef view) { + view->window->OnFontChange(); +} + +// TODO +void V2FlutterDesktopSendText(FlutterDesktopViewRef view, + const char16_t* code_point, + size_t size) { + std::u16string str; + str.append(code_point, size); + view->window->OnText(str); +} + +// TODO +void V2FlutterDesktopSendKey(FlutterDesktopViewRef view, + int key, + int scancode, + int action, + char32_t character) { + view->window->OnKey(key, scancode, action, character); } void FlutterDesktopResyncOutputStreams() { @@ -236,18 +299,20 @@ void FlutterDesktopResyncOutputStreams() { std::ios::sync_with_stdio(); } -FlutterDesktopEngineRef FlutterDesktopRunEngine( - const FlutterDesktopEngineProperties& engine_properties) { - auto engine = RunFlutterEngine(nullptr, engine_properties); - return engine.release(); -} - -bool FlutterDesktopShutDownEngine(FlutterDesktopEngineRef engine_ref) { - std::cout << "Shutting down flutter engine process." << std::endl; - auto result = FlutterEngineShutdown(engine_ref->engine); - delete engine_ref; - return (result == kSuccess); -} +////TODO: do we still need this? Appears to be dead code +// FlutterDesktopEngineRef FlutterDesktopRunEngine( +// const FlutterDesktopEngineProperties& engine_properties) { +// auto engine = RunFlutterEngine(nullptr, engine_properties); +// return engine.release(); +//} + +////TODO: do we still need this? Appears to be dead code +// bool FlutterDesktopShutDownEngine(FlutterDesktopEngineRef engine_ref) { +// std::cout << "Shutting down flutter engine process." << std::endl; +// auto result = FlutterEngineShutdown(engine_ref->engine); +// delete engine_ref; +// return (result == kSuccess); +//} void FlutterDesktopRegistrarEnableInputBlocking( FlutterDesktopPluginRegistrarRef registrar, diff --git a/shell/platform/windows/flutter_windows_view.cc b/shell/platform/windows/flutter_windows_view.cc new file mode 100644 index 0000000000000..3b69e8214c5dd --- /dev/null +++ b/shell/platform/windows/flutter_windows_view.cc @@ -0,0 +1,604 @@ +#include "flutter/shell/platform/windows/flutter_windows_view.h" + +#include + +namespace flutter { + +// the Windows DPI system is based on this +// constant for machines running at 100% scaling. +constexpr int base_dpi = 96; + +FlutterWindowsView::FlutterWindowsView(int width, int height) { + surface_manager = std::make_unique(); + + width_ = width; + height_ = height; +} + +FlutterWindowsView::~FlutterWindowsView() { + DestroyRenderSurface(); + if (plugin_registrar_ && plugin_registrar_->destruction_handler) { + plugin_registrar_->destruction_handler(plugin_registrar_.get()); + } +} + +FlutterDesktopViewControllerRef +FlutterWindowsView::CreateFlutterWindowsViewHwnd(const int width, + const int height, + void* externalWindow, + HWND windowrendertarget) { + auto state = std::make_unique(); + state->view = std::make_unique(width, height); + + state->view->window_rendertarget_ = windowrendertarget; + + // a window wrapper for the state block, distinct from the + // window_wrapper handed to plugin_registrar. + state->view_wrapper = std::make_unique(); + state->view_wrapper->window = state->view.get(); + state->view_wrapper->externalwindow = externalWindow; + return state.release(); +} + +FlutterDesktopViewControllerRef FlutterWindowsView::CreateFlutterWindowsView( + const int width, + const int height, + ABI::Windows::UI::Composition::IVisual* visual) { + auto state = std::make_unique(); + state->view = std::make_unique(width, height); + + // a window wrapper for the state block, distinct from the + // window_wrapper handed to plugin_registrar. + state->view_wrapper = std::make_unique(); + state->view_wrapper->window = state->view.get(); + + // retreieve compositor from parent visual, store it and use it to create a + // child that we store for rendering + namespace wuc = winrt::Windows::UI::Composition; + wuc::Visual parentVisual{nullptr}; + + winrt::copy_from_abi(parentVisual, *reinterpret_cast(&visual)); + state->view->compositor_ = state->view->flutter_host_.Compositor(); + state->view->flutter_host_ = state->view->compositor_.CreateSpriteVisual(); + + // add the host visual we created as a child of the visual passed in to us + wuc::SpriteVisual sv{nullptr}; + parentVisual.as(sv); + sv.Children().InsertAtTop(state->view->flutter_host_); + + return state.release(); +} + +void FlutterWindowsView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng, + void* externalwindow) { + engine_ = eng; + + auto messenger = std::make_unique(); + message_dispatcher_ = + std::make_unique(messenger.get()); + messenger->engine = engine_; + messenger->dispatcher = message_dispatcher_.get(); + + window_wrapper_ = std::make_unique(); + window_wrapper_->window = this; + window_wrapper_->externalwindow = externalwindow; + + plugin_registrar_ = std::make_unique(); + plugin_registrar_->messenger = std::move(messenger); + plugin_registrar_->window = window_wrapper_.get(); + + internal_plugin_registrar_ = + std::make_unique(plugin_registrar_.get()); + + // Set up the keyboard handlers. + auto internal_plugin_messenger = internal_plugin_registrar_->messenger(); + keyboard_hook_handlers_.push_back( + std::make_unique(internal_plugin_messenger)); + keyboard_hook_handlers_.push_back( + std::make_unique(internal_plugin_messenger)); + platform_handler_ = std::make_unique( + internal_plugin_messenger, this); + + process_events_ = true; +} + +FlutterDesktopPluginRegistrarRef FlutterWindowsView::GetRegistrar() { + return plugin_registrar_.get(); +} + +// Converts a FlutterPlatformMessage to an equivalent FlutterDesktopMessage. +static FlutterDesktopMessage ConvertToDesktopMessage( + const FlutterPlatformMessage& engine_message) { + FlutterDesktopMessage message = {}; + message.struct_size = sizeof(message); + message.channel = engine_message.channel; + message.message = engine_message.message; + message.message_size = engine_message.message_size; + message.response_handle = engine_message.response_handle; + return message; +} + +// The Flutter Engine calls out to this function when new platform messages +// are available. +void FlutterWindowsView::HandlePlatformMessage( + const FlutterPlatformMessage* engine_message) { + if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) { + std::cerr << "Invalid message size received. Expected: " + << sizeof(FlutterPlatformMessage) << " but received " + << engine_message->struct_size << std::endl; + return; + } + + auto message = ConvertToDesktopMessage(*engine_message); + + message_dispatcher_->HandleMessage( + message, [this] { this->process_events_ = false; }, + [this] { this->process_events_ = true; }); +} + +void FlutterWindowsView::OnPointerMove(double x, double y) { + if (process_events_) { + SendPointerMove(x, y); + } +} + +void FlutterWindowsView::OnPointerDown( + double x, + double y, + FlutterPointerMouseButtons flutter_button) { + if (process_events_) { + if (flutter_button != 0) { + uint64_t mouse_buttons = GetMouseState().buttons | flutter_button; + SetMouseButtons(mouse_buttons); + SendPointerDown(x, y); + } + } +} + +void FlutterWindowsView::OnPointerUp( + double x, + double y, + FlutterPointerMouseButtons flutter_button) { + if (process_events_) { + if (flutter_button != 0) { + uint64_t mouse_buttons = GetMouseState().buttons & ~flutter_button; + SetMouseButtons(mouse_buttons); + SendPointerUp(x, y); + } + } +} + +void FlutterWindowsView::OnPointerLeave() { + if (process_events_) { + SendPointerLeave(); + } +} + +void FlutterWindowsView::OnText(const std::u16string& text) { + if (process_events_) { + SendText(text); + } +} + +void FlutterWindowsView::OnKey(int key, + int scancode, + int action, + char32_t character) { + if (process_events_) { + SendKey(key, scancode, action, character); + } +} + +void FlutterWindowsView::OnScroll(double x, + double y, + double delta_x, + double delta_y) { + if (process_events_) { + SendScroll(x, y, delta_x, delta_y); + } +} + +void FlutterWindowsView::OnFontChange() { + if (engine_ == nullptr) { + return; + } + FlutterEngineReloadSystemFonts(engine_); +} + +// Sends new size information to FlutterEngine. +void FlutterWindowsView::SendWindowMetrics(size_t width, + size_t height, + double dpiScale) { + if (engine_ == nullptr) { + return; + } + + FlutterWindowMetricsEvent event = {}; + event.struct_size = sizeof(event); + event.width = width; + event.height = height; + event.pixel_ratio = dpiScale; + auto result = FlutterEngineSendWindowMetricsEvent(engine_, &event); + + if (flutter_host_ != nullptr) { + SizeHostVisual(width, height); + } +} + +// Set's |event_data|'s phase to either kMove or kHover depending on the current +// primary mouse button state. +void FlutterWindowsView::SetEventPhaseFromCursorButtonState( + FlutterPointerEvent* event_data) { + MouseState state = GetMouseState(); + // For details about this logic, see FlutterPointerPhase in the embedder.h + // file. + event_data->phase = state.buttons == 0 ? state.flutter_state_is_down + ? FlutterPointerPhase::kUp + : FlutterPointerPhase::kHover + : state.flutter_state_is_down + ? FlutterPointerPhase::kMove + : FlutterPointerPhase::kDown; +} + +void FlutterWindowsView::SendPointerMove(double x, double y) { + FlutterPointerEvent event = {}; + event.x = x; + event.y = y; + SetEventPhaseFromCursorButtonState(&event); + SendPointerEventWithData(event); +} + +void FlutterWindowsView::SendPointerDown(double x, double y) { + FlutterPointerEvent event = {}; + SetEventPhaseFromCursorButtonState(&event); + event.x = x; + event.y = y; + SendPointerEventWithData(event); + SetMouseFlutterStateDown(true); +} + +void FlutterWindowsView::SendPointerUp(double x, double y) { + FlutterPointerEvent event = {}; + SetEventPhaseFromCursorButtonState(&event); + event.x = x; + event.y = y; + SendPointerEventWithData(event); + if (event.phase == FlutterPointerPhase::kUp) { + SetMouseFlutterStateDown(false); + } +} + +void FlutterWindowsView::SendPointerLeave() { + FlutterPointerEvent event = {}; + event.phase = FlutterPointerPhase::kRemove; + SendPointerEventWithData(event); +} + +void FlutterWindowsView::SendText(const std::u16string& code_point) { + for (const auto& handler : keyboard_hook_handlers_) { + handler->TextHook(this, code_point); + } +} + +void FlutterWindowsView::SendKey(int key, int scancode, int action, int mods) { + for (const auto& handler : keyboard_hook_handlers_) { + handler->KeyboardHook(this, key, scancode, action, mods); + } +} + +void FlutterWindowsView::SendScroll(double x, + double y, + double delta_x, + double delta_y) { + FlutterPointerEvent event = {}; + SetEventPhaseFromCursorButtonState(&event); + event.signal_kind = FlutterPointerSignalKind::kFlutterPointerSignalKindScroll; + // TODO: See if this can be queried from the OS; this value is chosen + // arbitrarily to get something that feels reasonable. + const int kScrollOffsetMultiplier = 20; + event.x = x; + event.y = y; + event.scroll_delta_x = delta_x * kScrollOffsetMultiplier; + event.scroll_delta_y = delta_y * kScrollOffsetMultiplier; + SendPointerEventWithData(event); +} + +void FlutterWindowsView::SendPointerEventWithData( + const FlutterPointerEvent& event_data) { + // TODO + MouseState mouse_state = GetMouseState(); + // If sending anything other than an add, and the pointer isn't already added, + // synthesize an add to satisfy Flutter's expectations about events. + if (!mouse_state.flutter_state_is_added && + event_data.phase != FlutterPointerPhase::kAdd) { + FlutterPointerEvent event = {}; + event.phase = FlutterPointerPhase::kAdd; + event.x = event_data.x; + event.y = event_data.y; + event.buttons = 0; + SendPointerEventWithData(event); + } + // Don't double-add (e.g., if events are delivered out of order, so an add has + // already been synthesized). + if (mouse_state.flutter_state_is_added && + event_data.phase == FlutterPointerPhase::kAdd) { + return; + } + + FlutterPointerEvent event = event_data; + event.device_kind = kFlutterPointerDeviceKindMouse; + event.buttons = mouse_state.buttons; + + // Set metadata that's always the same regardless of the event. + event.struct_size = sizeof(event); + event.timestamp = + std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()) + .count(); + + FlutterEngineSendPointerEvent(engine_, &event, 1); + + if (event_data.phase == FlutterPointerPhase::kAdd) { + SetMouseFlutterStateAdded(true); + } else if (event_data.phase == FlutterPointerPhase::kRemove) { + SetMouseFlutterStateAdded(false); + ResetMouseState(); + } +} + +bool FlutterWindowsView::MakeCurrent() { + return surface_manager->MakeCurrent(render_surface); +} + +bool FlutterWindowsView::MakeResourceCurrent() { + return surface_manager->MakeResourceCurrent(); +} + +bool FlutterWindowsView::ClearContext() { + return surface_manager->MakeCurrent(nullptr); +} + +bool FlutterWindowsView::SwapBuffers() { + return surface_manager->SwapBuffers(render_surface); +} + +void FlutterWindowsView::SizeHostVisual(size_t width, size_t height) { + flutter_host_.Size({static_cast(width), static_cast(height)}); +} + +void FlutterWindowsView::CreateRenderSurface() { + if (compositor_ != nullptr) { + CreateRenderSurfaceUWP(); + } else { + CreateRenderSurfaceHWND(); + } +} + +void FlutterWindowsView::CreateRenderSurfaceHWND() { + render_surface = + surface_manager->CreateSurface(static_cast(window_rendertarget_)); +} + +void FlutterWindowsView::CreateRenderSurfaceUWP() { + if (surface_manager && render_surface == EGL_NO_SURFACE) { + // TODO: replace ROHelper with regen'd c++/WinRT with downlevel + RoHelper helper; + HSTRING act; + HSTRING_HEADER header; + + flutter_host_.Size( + {static_cast(width_), static_cast(height_)}); + + render_surface = surface_manager->CreateSurface( + static_cast( + winrt::get_abi(flutter_host_))); + } +} + +void FlutterWindowsView::DestroyRenderSurface() { + if (surface_manager) { + surface_manager->DestroySurface(render_surface); + } + render_surface = EGL_NO_SURFACE; +} + +// RoHelperImpl. This is temporary and will go away. + +template +bool AssignProcAddress(HMODULE comBaseModule, const char* name, T*& outProc) { + outProc = reinterpret_cast(GetProcAddress(comBaseModule, name)); + return *outProc != nullptr; +} + +RoHelper::RoHelper() + : mFpWindowsCreateStringReference(nullptr), + mFpGetActivationFactory(nullptr), + mFpWindowsCompareStringOrdinal(nullptr), + mFpCreateDispatcherQueueController(nullptr), + mFpWindowsDeleteString(nullptr), + mFpRoInitialize(nullptr), + mFpRoUninitialize(nullptr), + mWinRtAvailable(false), + mComBaseModule(nullptr), + mCoreMessagingModule(nullptr) { + mComBaseModule = LoadLibraryA("ComBase.dll"); + + if (mComBaseModule == nullptr) { + return; + } + + if (!AssignProcAddress(mComBaseModule, "WindowsCreateStringReference", + mFpWindowsCreateStringReference)) { + return; + } + + if (!AssignProcAddress(mComBaseModule, "RoGetActivationFactory", + mFpGetActivationFactory)) { + return; + } + + if (!AssignProcAddress(mComBaseModule, "WindowsCompareStringOrdinal", + mFpWindowsCompareStringOrdinal)) { + return; + } + + if (!AssignProcAddress(mComBaseModule, "WindowsDeleteString", + mFpWindowsDeleteString)) { + return; + } + + if (!AssignProcAddress(mComBaseModule, "RoInitialize", mFpRoInitialize)) { + return; + } + + if (!AssignProcAddress(mComBaseModule, "RoUninitialize", mFpRoUninitialize)) { + return; + } + + mCoreMessagingModule = LoadLibraryA("coremessaging.dll"); + + if (mCoreMessagingModule == nullptr) { + return; + } + + if (!AssignProcAddress(mCoreMessagingModule, + "CreateDispatcherQueueController", + mFpCreateDispatcherQueueController)) { + return; + } + + auto result = RoInitialize(RO_INIT_SINGLETHREADED); + + if (SUCCEEDED(result)) { + // TODO + } + + mWinRtAvailable = true; +} + +RoHelper::~RoHelper() { + if (mWinRtAvailable) { + // TODO + // RoUninitialize(); + } + + if (mCoreMessagingModule != nullptr) { + FreeLibrary(mCoreMessagingModule); + mCoreMessagingModule = nullptr; + } + + if (mComBaseModule != nullptr) { + FreeLibrary(mComBaseModule); + mComBaseModule = nullptr; + } +} + +bool RoHelper::WinRtAvailable() const { + return mWinRtAvailable; +} + +bool RoHelper::SupportedWindowsRelease() { + // if (!IsWindows10OrGreater() || !mWinRtAvailable) + if (!mWinRtAvailable) { + return false; + } + + HSTRING className, contractName; + HSTRING_HEADER classNameHeader, contractNameHeader; + boolean isSupported = false; + + HRESULT hr = GetStringReference( + RuntimeClass_Windows_Foundation_Metadata_ApiInformation, &className, + &classNameHeader); + + if (FAILED(hr)) { + return !!isSupported; + } + + Microsoft::WRL::ComPtr< + ABI::Windows::Foundation::Metadata::IApiInformationStatics> + api; + + hr = GetActivationFactory( + className, + __uuidof(ABI::Windows::Foundation::Metadata::IApiInformationStatics), + &api); + + if (FAILED(hr)) { + return !!isSupported; + } + + hr = GetStringReference(L"Windows.Foundation.UniversalApiContract", + &contractName, &contractNameHeader); + if (FAILED(hr)) { + return !!isSupported; + } + + api->IsApiContractPresentByMajor(contractName, 6, &isSupported); + + return !!isSupported; +} + +HRESULT RoHelper::GetStringReference(PCWSTR source, + HSTRING* act, + HSTRING_HEADER* header) { + if (!mWinRtAvailable) { + return E_FAIL; + } + + const wchar_t* str = static_cast(source); + + unsigned int length; + HRESULT hr = SizeTToUInt32(::wcslen(str), &length); + if (FAILED(hr)) { + return hr; + } + + return mFpWindowsCreateStringReference(source, length, header, act); +} + +HRESULT RoHelper::GetActivationFactory(const HSTRING act, + const IID& interfaceId, + void** fac) { + if (!mWinRtAvailable) { + return E_FAIL; + } + auto hr = mFpGetActivationFactory(act, interfaceId, fac); + return hr; +} + +HRESULT RoHelper::WindowsCompareStringOrdinal(HSTRING one, + HSTRING two, + int* result) { + if (!mWinRtAvailable) { + return E_FAIL; + } + return mFpWindowsCompareStringOrdinal(one, two, result); +} + +HRESULT RoHelper::CreateDispatcherQueueController( + DispatcherQueueOptions options, + ABI::Windows::System::IDispatcherQueueController** + dispatcherQueueController) { + if (!mWinRtAvailable) { + return E_FAIL; + } + return mFpCreateDispatcherQueueController(options, dispatcherQueueController); +} + +HRESULT RoHelper::WindowsDeleteString(HSTRING one) { + if (!mWinRtAvailable) { + return E_FAIL; + } + return mFpWindowsDeleteString(one); +} + +HRESULT RoHelper::RoInitialize(RO_INIT_TYPE type) { + return mFpRoInitialize(type); +} + +void RoHelper::RoUninitialize() { + mFpRoUninitialize(); +} + +} // namespace flutter diff --git a/shell/platform/windows/flutter_windows_view.h b/shell/platform/windows/flutter_windows_view.h new file mode 100644 index 0000000000000..12f195c044b3c --- /dev/null +++ b/shell/platform/windows/flutter_windows_view.h @@ -0,0 +1,300 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_H_ +#define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_H_ + +#include + +#include +#include + +#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h" +#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h" +#include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/windows/angle_surface_manager.h" +#include "flutter/shell/platform/windows/key_event_handler.h" +#include "flutter/shell/platform/windows/keyboard_hook_handler.h" +#include "flutter/shell/platform/windows/platform_handler.h" +#include "flutter/shell/platform/windows/public/flutter_windows.h" +#include "flutter/shell/platform/windows/text_input_plugin.h" +//#include "flutter/shell/platform/windows/window_state.h" +#include +#include +#include +#include +#include +#include +#include + +#include "flutter/shell/platform/windows/window_state_comp.h" + +namespace flutter { + +class RoHelper { + public: + RoHelper(); + ~RoHelper(); + bool WinRtAvailable() const; + bool SupportedWindowsRelease(); + HRESULT GetStringReference(PCWSTR source, + HSTRING* act, + HSTRING_HEADER* header); + HRESULT GetActivationFactory(const HSTRING act, + const IID& interfaceId, + void** fac); + HRESULT WindowsCompareStringOrdinal(HSTRING one, HSTRING two, int* result); + HRESULT CreateDispatcherQueueController( + DispatcherQueueOptions options, + ABI::Windows::System::IDispatcherQueueController** + dispatcherQueueController); + HRESULT WindowsDeleteString(HSTRING one); + HRESULT RoInitialize(RO_INIT_TYPE type); + void RoUninitialize(); + + private: + using WindowsCreateStringReference_ = HRESULT __stdcall(PCWSTR, + UINT32, + HSTRING_HEADER*, + HSTRING*); + + using GetActivationFactory_ = HRESULT __stdcall(HSTRING, REFIID, void**); + + using WindowsCompareStringOrginal_ = HRESULT __stdcall(HSTRING, + HSTRING, + int*); + + using WindowsDeleteString_ = HRESULT __stdcall(HSTRING); + + using CreateDispatcherQueueController_ = + HRESULT __stdcall(DispatcherQueueOptions, + ABI::Windows::System::IDispatcherQueueController**); + + using RoInitialize_ = HRESULT __stdcall(RO_INIT_TYPE); + using RoUninitialize_ = void __stdcall(); + + WindowsCreateStringReference_* mFpWindowsCreateStringReference; + GetActivationFactory_* mFpGetActivationFactory; + WindowsCompareStringOrginal_* mFpWindowsCompareStringOrdinal; + CreateDispatcherQueueController_* mFpCreateDispatcherQueueController; + WindowsDeleteString_* mFpWindowsDeleteString; + RoInitialize_* mFpRoInitialize; + RoUninitialize_* mFpRoUninitialize; + + bool mWinRtAvailable; + + HMODULE mComBaseModule; + HMODULE mCoreMessagingModule; +}; + +// Struct holding the mouse state. The engine doesn't keep track of which mouse +// buttons have been pressed, so it's the embedding's responsibility. +struct MouseState { + // True if the last event sent to Flutter had at least one mouse button + // pressed. + bool flutter_state_is_down = false; + + // True if kAdd has been sent to Flutter. Used to determine whether + // to send a kAdd event before sending an incoming mouse event, since Flutter + // expects pointers to be added before events are sent for them. + bool flutter_state_is_added = false; + + // The currently pressed buttons, as represented in FlutterPointerEvent. + uint64_t buttons = 0; +}; + +// A windowing neutral flutter child video used as implementation for flutter +// view that works with win32 hwnds and Windows::UI::Composition visuals +class FlutterWindowsView { + public: + // Create flutter Window for use as child window + FlutterWindowsView(int width, int height); + + ~FlutterWindowsView(); + + static FlutterDesktopViewControllerRef CreateFlutterWindowsView( + int width, + int height, + ABI::Windows::UI::Composition::IVisual* visual); + + static FlutterDesktopViewControllerRef CreateFlutterWindowsViewHwnd( + int width, + int height, + void* externalwindow, + HWND windowrendertarget); + + // Configures the window instance with an instance of a running Flutter engine + // returning a configured FlutterDesktopWindowControllerRef. + void SetState(FLUTTER_API_SYMBOL(FlutterEngine) state, void* externalwindow); + + // Returns the currently configured Plugin Registrar. + FlutterDesktopPluginRegistrarRef GetRegistrar(); + + // Callback passed to Flutter engine for notifying window of platform + // messages. + void HandlePlatformMessage(const FlutterPlatformMessage*); + + void CreateRenderSurface(); + + // Destroy current rendering surface if one has been allocated. + void DestroyRenderSurface(); + + // Callbacks for clearing context, settings context and swapping buffers. + bool ClearContext(); + bool MakeCurrent(); + bool MakeResourceCurrent(); + bool SwapBuffers(); + + // Sends a window metrics update to the Flutter engine using current window + // dimensions in physical + void SendWindowMetrics(size_t width, size_t height, double dpiscale); + + // TODO + void OnPointerMove(double x, double y); + + // TODO + void OnPointerDown(double x, double y, FlutterPointerMouseButtons button); + + // TODO + void OnPointerUp(double x, double y, FlutterPointerMouseButtons button); + + // TODO + void OnPointerLeave(); + + // TODO + void OnText(const std::u16string&); + + // TODO + void OnKey(int key, int scancode, int action, char32_t character); + + // TODO + void OnScroll(double x, double y, double delta_x, double delta_y); + + // TODO + void OnFontChange(); + + private: + // Create a surface for Flutter engine to render into. + void CreateRenderSurfaceUWP(); + + void CreateRenderSurfaceHWND(); + + // Reports a mouse movement to Flutter engine. + void SendPointerMove(double x, double y); + + // Reports mouse press to Flutter engine. + void SendPointerDown(double x, double y); + + // Reports mouse release to Flutter engine. + void SendPointerUp(double x, double y); + + // Reports mouse left the window client area. + // + // Win32 api doesn't have "mouse enter" event. Therefore, there is no + // SendPointerEnter method. A mouse enter event is tracked then the "move" + // event is called. + void SendPointerLeave(); + + // Reports a keyboard character to Flutter engine. + void SendText(const std::u16string&); + + // Reports a raw keyboard message to Flutter engine. + void SendKey(int key, int scancode, int action, int mods); + + // Reports scroll wheel events to Flutter engine. + void SendScroll(double x, double y, double delta_x, double delta_y); + + // Set's |event_data|'s phase to either kMove or kHover depending on the + // current + // primary mouse button state. + void SetEventPhaseFromCursorButtonState(FlutterPointerEvent* event_data); + + // Sends a pointer event to the Flutter engine based on givern data. Since + // all input messages are passed in physical pixel values, no translation is + // needed before passing on to engine. + void SendPointerEventWithData(const FlutterPointerEvent& event_data); + + // Gets the current mouse state. + MouseState GetMouseState() { return mouse_state_; } + + // Resets the mouse state to its default values. + void ResetMouseState() { mouse_state_ = MouseState(); } + + // Updates the mouse state to whether the last event to Flutter had at least + // one mouse button pressed. + void SetMouseFlutterStateDown(bool is_down) { + mouse_state_.flutter_state_is_down = is_down; + } + + // Updates the mouse state to whether the last event to Flutter was a kAdd + // event. + void SetMouseFlutterStateAdded(bool is_added) { + mouse_state_.flutter_state_is_added = is_added; + } + + // Updates the currently pressed buttons. + void SetMouseButtons(uint64_t buttons) { mouse_state_.buttons = buttons; } + + // Updates the size of the compositor host visual + void SizeHostVisual(size_t width, size_t height); + + std::unique_ptr surface_manager = nullptr; + EGLSurface render_surface = EGL_NO_SURFACE; + + // state of the mouse button + bool pointer_is_down_ = false; + + // The handle to the Flutter engine instance. + FLUTTER_API_SYMBOL(FlutterEngine) engine_ = nullptr; + + // Whether or not to track mouse movements to send kHover events. + bool hover_tracking_is_enabled_ = false; + + // Whether or not the pointer has been added (or if tracking is enabled, has + // been added since it was last removed). + bool pointer_currently_added_ = false; + + // Set to true to be notified when the mouse leaves the window. + bool tracking_mouse_leave_ = false; + + // Keeps track of mouse state in relation to the window. + MouseState mouse_state_; + + // The window handle given to API clients. + std::unique_ptr window_wrapper_; + + // The plugin registrar handle given to API clients. + std::unique_ptr plugin_registrar_; + + // Message dispatch manager for messages from the Flutter engine. + std::unique_ptr message_dispatcher_; + + // The plugin registrar managing internal plugins. + std::unique_ptr internal_plugin_registrar_; + + // Handlers for keyboard events from Windows. + std::vector> + keyboard_hook_handlers_; + + // Handler for the flutter/platform channel. + std::unique_ptr platform_handler_; + + // should we forword input messages or not + bool process_events_ = false; + + // flag indicating if the message loop should be running + bool messageloop_running_ = false; + + winrt::Windows::UI::Composition::Compositor compositor_{nullptr}; + + winrt::Windows::UI::Composition::Visual flutter_host_{nullptr}; + + HWND window_rendertarget_; + + int width_ = 0, height_ = 0; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_H_ diff --git a/shell/platform/windows/key_event_handler.cc b/shell/platform/windows/key_event_handler.cc index 3747a9f5a05a0..82197dfcc4e2f 100644 --- a/shell/platform/windows/key_event_handler.cc +++ b/shell/platform/windows/key_event_handler.cc @@ -92,10 +92,10 @@ KeyEventHandler::KeyEventHandler(flutter::BinaryMessenger* messenger) KeyEventHandler::~KeyEventHandler() = default; -void KeyEventHandler::TextHook(Win32FlutterWindow* window, +void KeyEventHandler::TextHook(FlutterWindowsView* window, const std::u16string& code_point) {} -void KeyEventHandler::KeyboardHook(Win32FlutterWindow* window, +void KeyEventHandler::KeyboardHook(FlutterWindowsView* window, int key, int scancode, int action, diff --git a/shell/platform/windows/key_event_handler.h b/shell/platform/windows/key_event_handler.h index 6e9a77f1d3514..9a1b2752288e9 100644 --- a/shell/platform/windows/key_event_handler.h +++ b/shell/platform/windows/key_event_handler.h @@ -16,7 +16,7 @@ namespace flutter { -class Win32FlutterWindow; +class FlutterWindowsView; // Implements a KeyboardHookHandler // @@ -28,14 +28,14 @@ class KeyEventHandler : public KeyboardHookHandler { virtual ~KeyEventHandler(); // |KeyboardHookHandler| - void KeyboardHook(Win32FlutterWindow* window, + void KeyboardHook(FlutterWindowsView* window, int key, int scancode, int action, char32_t character) override; // |KeyboardHookHandler| - void TextHook(Win32FlutterWindow* window, + void TextHook(FlutterWindowsView* window, const std::u16string& text) override; private: diff --git a/shell/platform/windows/keyboard_hook_handler.h b/shell/platform/windows/keyboard_hook_handler.h index aa574a545d64e..ddc8cdabed1b7 100644 --- a/shell/platform/windows/keyboard_hook_handler.h +++ b/shell/platform/windows/keyboard_hook_handler.h @@ -11,7 +11,7 @@ namespace flutter { -class Win32FlutterWindow; +class FlutterWindowsView; // Abstract class for handling keyboard input events. class KeyboardHookHandler { @@ -19,14 +19,14 @@ class KeyboardHookHandler { virtual ~KeyboardHookHandler() = default; // A function for hooking into keyboard input. - virtual void KeyboardHook(Win32FlutterWindow* window, + virtual void KeyboardHook(FlutterWindowsView* window, int key, int scancode, int action, char32_t character) = 0; // A function for hooking into Unicode text input. - virtual void TextHook(Win32FlutterWindow* window, + virtual void TextHook(FlutterWindowsView* window, const std::u16string& text) = 0; }; diff --git a/shell/platform/windows/platform_handler.cc b/shell/platform/windows/platform_handler.cc index c4b83130a785b..c45e0aebd9696 100644 --- a/shell/platform/windows/platform_handler.cc +++ b/shell/platform/windows/platform_handler.cc @@ -10,8 +10,8 @@ #include #include "flutter/shell/platform/common/cpp/json_method_codec.h" +#include "flutter/shell/platform/windows/flutter_windows_view.h" #include "flutter/shell/platform/windows/string_conversion.h" -#include "flutter/shell/platform/windows/win32_flutter_window.h" static constexpr char kChannelName[] = "flutter/platform"; @@ -198,7 +198,7 @@ bool ScopedClipboard::SetString(const std::wstring string) { } // namespace PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger, - Win32FlutterWindow* window) + FlutterWindowsView* window) : channel_(std::make_unique>( messenger, kChannelName, @@ -215,71 +215,74 @@ PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger, void PlatformHandler::HandleMethodCall( const flutter::MethodCall& method_call, std::unique_ptr> result) { - const std::string& method = method_call.method_name(); - if (method.compare(kGetClipboardDataMethod) == 0) { - // Only one string argument is expected. - const rapidjson::Value& format = method_call.arguments()[0]; - - if (strcmp(format.GetString(), kTextPlainFormat) != 0) { - result->Error(kClipboardError, kUnknownClipboardFormatMessage); - return; - } - - ScopedClipboard clipboard; - if (!clipboard.Open(window_->GetWindowHandle())) { - rapidjson::Document error_code; - error_code.SetInt(::GetLastError()); - result->Error(kClipboardError, "Unable to open clipboard", &error_code); - return; - } - if (!clipboard.HasString()) { - rapidjson::Document null; - result->Success(&null); - return; - } - std::optional clipboard_string = clipboard.GetString(); - if (!clipboard_string) { - rapidjson::Document error_code; - error_code.SetInt(::GetLastError()); - result->Error(kClipboardError, "Unable to get clipboard data", - &error_code); - return; - } - - rapidjson::Document document; - document.SetObject(); - rapidjson::Document::AllocatorType& allocator = document.GetAllocator(); - document.AddMember( - rapidjson::Value(kTextKey, allocator), - rapidjson::Value(Utf8FromUtf16(*clipboard_string), allocator), - allocator); - result->Success(&document); - } else if (method.compare(kSetClipboardDataMethod) == 0) { - const rapidjson::Value& document = *method_call.arguments(); - rapidjson::Value::ConstMemberIterator itr = document.FindMember(kTextKey); - if (itr == document.MemberEnd()) { - result->Error(kClipboardError, kUnknownClipboardFormatMessage); - return; - } - - ScopedClipboard clipboard; - if (!clipboard.Open(window_->GetWindowHandle())) { - rapidjson::Document error_code; - error_code.SetInt(::GetLastError()); - result->Error(kClipboardError, "Unable to open clipboard", &error_code); - return; - } - if (!clipboard.SetString(Utf16FromUtf8(itr->value.GetString()))) { - rapidjson::Document error_code; - error_code.SetInt(::GetLastError()); - result->Error(kClipboardError, "Unable to set clipboard data", - &error_code); - return; - } - result->Success(); - } else { - result->NotImplemented(); - } + result->NotImplemented(); + return; + + // const std::string& method = method_call.method_name(); + // if (method.compare(kGetClipboardDataMethod) == 0) { + // // Only one string argument is expected. + // const rapidjson::Value& format = method_call.arguments()[0]; + + // if (strcmp(format.GetString(), kTextPlainFormat) != 0) { + // result->Error(kClipboardError, kUnknownClipboardFormatMessage); + // return; + // } + + // ScopedClipboard clipboard; + // if (!clipboard.Open(window_->GetWindowHandle())) { + // rapidjson::Document error_code; + // error_code.SetInt(::GetLastError()); + // result->Error(kClipboardError, "Unable to open clipboard", &error_code); + // return; + // } + // if (!clipboard.HasString()) { + // rapidjson::Document null; + // result->Success(&null); + // return; + // } + // std::optional clipboard_string = clipboard.GetString(); + // if (!clipboard_string) { + // rapidjson::Document error_code; + // error_code.SetInt(::GetLastError()); + // result->Error(kClipboardError, "Unable to get clipboard data", + // &error_code); + // return; + // } + + // rapidjson::Document document; + // document.SetObject(); + // rapidjson::Document::AllocatorType& allocator = document.GetAllocator(); + // document.AddMember( + // rapidjson::Value(kTextKey, allocator), + // rapidjson::Value(Utf8FromUtf16(*clipboard_string), allocator), + // allocator); + // result->Success(&document); + //} else if (method.compare(kSetClipboardDataMethod) == 0) { + // const rapidjson::Value& document = *method_call.arguments(); + // rapidjson::Value::ConstMemberIterator itr = document.FindMember(kTextKey); + // if (itr == document.MemberEnd()) { + // result->Error(kClipboardError, kUnknownClipboardFormatMessage); + // return; + // } + + // ScopedClipboard clipboard; + // if (!clipboard.Open(window_->GetWindowHandle())) { + // rapidjson::Document error_code; + // error_code.SetInt(::GetLastError()); + // result->Error(kClipboardError, "Unable to open clipboard", &error_code); + // return; + // } + // if (!clipboard.SetString(Utf16FromUtf8(itr->value.GetString()))) { + // rapidjson::Document error_code; + // error_code.SetInt(::GetLastError()); + // result->Error(kClipboardError, "Unable to set clipboard data", + // &error_code); + // return; + // } + // result->Success(); + //} else { + // result->NotImplemented(); + //} } } // namespace flutter diff --git a/shell/platform/windows/platform_handler.h b/shell/platform/windows/platform_handler.h index 8cb09a80666a7..eed2b2f169ef8 100644 --- a/shell/platform/windows/platform_handler.h +++ b/shell/platform/windows/platform_handler.h @@ -12,13 +12,13 @@ namespace flutter { -class Win32FlutterWindow; +class FlutterWindowsView; // Handler for internal system channels. class PlatformHandler { public: explicit PlatformHandler(flutter::BinaryMessenger* messenger, - Win32FlutterWindow* window); + FlutterWindowsView* window); private: // Called when a method is called on |channel_|; @@ -30,7 +30,7 @@ class PlatformHandler { std::unique_ptr> channel_; // A reference to the win32 window. - Win32FlutterWindow* window_; + FlutterWindowsView* window_; }; } // namespace flutter diff --git a/shell/platform/windows/public/flutter_windows.h b/shell/platform/windows/public/flutter_windows.h index 633169a4cf4b1..1757fe62a4fba 100644 --- a/shell/platform/windows/public/flutter_windows.h +++ b/shell/platform/windows/public/flutter_windows.h @@ -13,6 +13,7 @@ #include "flutter_plugin_registrar.h" #include "Windows.h" +#include "windows.ui.composition.h" #if defined(__cplusplus) extern "C" { @@ -22,12 +23,19 @@ extern "C" { typedef struct FlutterDesktopViewControllerState* FlutterDesktopViewControllerRef; +// Opaque reference to a Flutter window controller. +typedef struct FlutterDesktopViewControllerState* + V2FlutterDesktopViewControllerRef; + // Opaque reference to a Flutter window. typedef struct FlutterDesktopView* FlutterDesktopViewRef; // Opaque reference to a Flutter engine instance. typedef struct FlutterDesktopEngineState* FlutterDesktopEngineRef; +// Opaque reference to runner / host specific state +typedef void* HostEnvironmentState; + // Properties for configuring a Flutter engine instance. typedef struct { // The path to the flutter_assets folder for the application to be run. @@ -51,25 +59,98 @@ typedef struct { } FlutterDesktopEngineProperties; // Creates a View with the given dimensions running a Flutter Application. +// callable from Win32 runner on Windows 1703 or later or UWP host runner. // // This will set up and run an associated Flutter engine using the settings in // |engine_properties|. // +// |visual| supplied must be integrated into host visual tree prior to making this call +// +// |hostwindow| specifies environment state supplied will be available to plugins that request it via Win32FlutterView. +// // Returns a null pointer in the event of an error. FLUTTER_EXPORT FlutterDesktopViewControllerRef -FlutterDesktopCreateViewController( +V2CreateViewControllerVisual( int width, int height, - const FlutterDesktopEngineProperties& engine_properties); + const FlutterDesktopEngineProperties& engine_properties, + ABI::Windows::UI::Composition::IVisual* visual, + HostEnvironmentState hoststate); -// DEPRECATED. Will be removed soon; switch to the version above. +// Creates a View with the given dimensions running a Flutter Application. +// Callable from Win32 host runner down to Windows 7. +// +// This will set up and run an associated Flutter engine using the settings in +// |engine_properties|. +// +// |windowrendertarget| is used to specify the render target for the view. +// +// |hostwindow| specifies environment state supplied will be available to plugins that request it +// via Win32FlutterView. +// +// Returns a null pointer in the event of an error. FLUTTER_EXPORT FlutterDesktopViewControllerRef -FlutterDesktopCreateViewControllerLegacy(int initial_width, - int initial_height, - const char* assets_path, - const char* icu_data_path, - const char** arguments, - size_t argument_count); +V2CreateViewControllerWindow( + int width, + int height, + const FlutterDesktopEngineProperties& engine_properties, + HWND windowrendertarget, + HostEnvironmentState hostwindow + ); + +// Returns runner / host-specific state supplied when creating a viewcontroller. +// Typically used by plugins +FLUTTER_EXPORT +HostEnvironmentState V2FlutterDesktopGetHostState(FlutterDesktopViewRef view); + +//TODO +FLUTTER_EXPORT void V2FlutterDesktopSendWindowMetrics(FlutterDesktopViewRef view, + size_t width, + size_t height, + double dpiScale); + +//TODO +FLUTTER_EXPORT void V2FlutterDesktopSendPointerMove(FlutterDesktopViewRef view, + double x, + double y); + +//TODO +FLUTTER_EXPORT void V2FlutterDesktopSendPointerDown( + FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn); // TODO: can / should this be a FlutterPointerMouseButtons + +//TODO +FLUTTER_EXPORT void V2FlutterDesktopSendPointerUp(FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn); //TODO typedef per above + +// TODO +FLUTTER_EXPORT void V2FlutterDesktopSendPointerLeave(FlutterDesktopViewRef view); + +// TODO +FLUTTER_EXPORT void V2FlutterDesktopSendScroll(FlutterDesktopViewRef view, + double x, + double y, + double delta_x, + double delta_y); + +// TODO +FLUTTER_EXPORT void V2FlutterDesktopSendFontChange(FlutterDesktopViewRef view); + +// TODO +FLUTTER_EXPORT void V2FlutterDesktopSendText(FlutterDesktopViewRef view, + const char16_t* code_point, + size_t size); + +// TODO +FLUTTER_EXPORT void V2FlutterDesktopSendKey(FlutterDesktopViewRef view, + int key, + int scancode, + int action, + char32_t character); // Shuts down the engine instance associated with |controller|, and cleans up // associated state. @@ -98,33 +179,23 @@ FlutterDesktopGetView(FlutterDesktopViewControllerRef controller); FLUTTER_EXPORT uint64_t FlutterDesktopProcessMessages(FlutterDesktopViewControllerRef controller); -// Return backing HWND for manipulation in host application. -FLUTTER_EXPORT HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view); - -// Gets the DPI for a given |hwnd|, depending on the supported APIs per -// windows version and DPI awareness mode. If nullptr is passed, returns the DPI -// of the primary monitor. -FLUTTER_EXPORT UINT FlutterDesktopGetDpiForHWND(HWND hwnd); - -// Gets the DPI for a given |monitor|. If the API is not available, a default -// DPI of 96 is returned. -FLUTTER_EXPORT UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor); - // Reopens stdout and stderr and resysncs the standard library output streams. // Should be called if output is being directed somewhere in the runner process // (e.g., after an AllocConsole call). FLUTTER_EXPORT void FlutterDesktopResyncOutputStreams(); -// Runs an instance of a headless Flutter engine. -// -// Returns a null pointer in the event of an error. -FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopRunEngine( - const FlutterDesktopEngineProperties& engine_properties); - -// Shuts down the given engine instance. Returns true if the shutdown was -// successful. |engine_ref| is no longer valid after this call. -FLUTTER_EXPORT bool FlutterDesktopShutDownEngine( - FlutterDesktopEngineRef engine_ref); +// This is dead code that never gets called. +//// Runs an instance of a headless Flutter engine. +//// +//// Returns a null pointer in the event of an error. +//FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopRunEngine( +// const FlutterDesktopEngineProperties& engine_properties); + +//This is dead code that never gets called. The ViewController shuts down the engine now +//// Shuts down the given engine instance. Returns true if the shutdown was +//// successful. |engine_ref| is no longer valid after this call. +//FLUTTER_EXPORT bool FlutterDesktopShutDownEngine( +// FlutterDesktopEngineRef engine_ref); // Returns the view associated with this registrar's engine instance // This is a Windows-specific extension to flutter_plugin_registrar.h. diff --git a/shell/platform/windows/win32_task_runner.cc b/shell/platform/windows/task_runner.cc similarity index 83% rename from shell/platform/windows/win32_task_runner.cc rename to shell/platform/windows/task_runner.cc index e8d66b9fab6f1..377f890869cce 100644 --- a/shell/platform/windows/win32_task_runner.cc +++ b/shell/platform/windows/task_runner.cc @@ -2,25 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "flutter/shell/platform/windows/win32_task_runner.h" +#include "flutter/shell/platform/windows/task_runner.h" #include #include namespace flutter { -Win32TaskRunner::Win32TaskRunner(DWORD main_thread_id, - const TaskExpiredCallback& on_task_expired) +TaskRunner::TaskRunner(DWORD main_thread_id, + const TaskExpiredCallback& on_task_expired) : main_thread_id_(main_thread_id), on_task_expired_(std::move(on_task_expired)) {} -Win32TaskRunner::~Win32TaskRunner() = default; +TaskRunner::~TaskRunner() = default; -bool Win32TaskRunner::RunsTasksOnCurrentThread() const { +bool TaskRunner::RunsTasksOnCurrentThread() const { return GetCurrentThreadId() == main_thread_id_; } -std::chrono::nanoseconds Win32TaskRunner::ProcessTasks() { +std::chrono::nanoseconds TaskRunner::ProcessTasks() { const TaskTimePoint now = TaskTimePoint::clock::now(); std::vector expired_tasks; @@ -65,7 +65,7 @@ std::chrono::nanoseconds Win32TaskRunner::ProcessTasks() { } } -Win32TaskRunner::TaskTimePoint Win32TaskRunner::TimePointFromFlutterTime( +TaskRunner::TaskTimePoint TaskRunner::TimePointFromFlutterTime( uint64_t flutter_target_time_nanos) { const auto now = TaskTimePoint::clock::now(); const auto flutter_duration = @@ -73,8 +73,8 @@ Win32TaskRunner::TaskTimePoint Win32TaskRunner::TimePointFromFlutterTime( return now + std::chrono::nanoseconds(flutter_duration); } -void Win32TaskRunner::PostTask(FlutterTask flutter_task, - uint64_t flutter_target_time_nanos) { +void TaskRunner::PostTask(FlutterTask flutter_task, + uint64_t flutter_target_time_nanos) { static std::atomic_uint64_t sGlobalTaskOrder(0); Task task; diff --git a/shell/platform/windows/win32_task_runner.h b/shell/platform/windows/task_runner.h similarity index 87% rename from shell/platform/windows/win32_task_runner.h rename to shell/platform/windows/task_runner.h index 9bc45c33e9ab4..e24afaff87369 100644 --- a/shell/platform/windows/win32_task_runner.h +++ b/shell/platform/windows/task_runner.h @@ -21,13 +21,12 @@ namespace flutter { // A custom task runner that integrates with user32 GetMessage semantics so that // host app can own its own message loop and flutter still gets to process // tasks on a timely basis. -class Win32TaskRunner { +class TaskRunner { public: using TaskExpiredCallback = std::function; - Win32TaskRunner(DWORD main_thread_id, - const TaskExpiredCallback& on_task_expired); + TaskRunner(DWORD main_thread_id, const TaskExpiredCallback& on_task_expired); - ~Win32TaskRunner(); + ~TaskRunner(); // Returns if the current thread is the thread used by the win32 event loop. bool RunsTasksOnCurrentThread() const; @@ -59,9 +58,9 @@ class Win32TaskRunner { std::priority_queue, Task::Comparer> task_queue_; std::condition_variable task_queue_cv_; - Win32TaskRunner(const Win32TaskRunner&) = delete; + TaskRunner(const TaskRunner&) = delete; - Win32TaskRunner& operator=(const Win32TaskRunner&) = delete; + TaskRunner& operator=(const TaskRunner&) = delete; static TaskTimePoint TimePointFromFlutterTime( uint64_t flutter_target_time_nanos); diff --git a/shell/platform/windows/testing/flutter_compview_test.cc b/shell/platform/windows/testing/flutter_compview_test.cc new file mode 100644 index 0000000000000..20795f21fbb44 --- /dev/null +++ b/shell/platform/windows/testing/flutter_compview_test.cc @@ -0,0 +1,20 @@ +#include "flutter/shell/platform/windows/testing/flutter_compview_test.h" + +namespace flutter { +namespace testing { + +FlutterWindowsViewTest::FlutterWindowsViewTest(int width, int height) + : FlutterWindowsView(width, height){}; + +FlutterWindowsViewTest::~FlutterWindowsViewTest() = default; + +//void FlutterWindowsViewTest::OnFontChange() { +// on_font_change_called_ = true; +//} + +bool FlutterWindowsViewTest::OnFontChangeWasCalled() { + return true; //TODO create an actual test + //return on_font_change_called_; +} +} // namespace testing +} // namespace flutter diff --git a/shell/platform/windows/testing/win32_flutter_window_test.h b/shell/platform/windows/testing/flutter_compview_test.h similarity index 53% rename from shell/platform/windows/testing/win32_flutter_window_test.h rename to shell/platform/windows/testing/flutter_compview_test.h index 6da56d9383a5b..a446b6f43ce61 100644 --- a/shell/platform/windows/testing/win32_flutter_window_test.h +++ b/shell/platform/windows/testing/flutter_compview_test.h @@ -4,23 +4,23 @@ #include -#include "flutter/shell/platform/windows/win32_flutter_window.h" +#include "flutter/shell/platform/windows/flutter_windows_view.h" namespace flutter { namespace testing { /// Test class for Win32FlutterWindow. -class Win32FlutterWindowTest : public Win32FlutterWindow { +class FlutterWindowsViewTest : public FlutterWindowsView { public: - Win32FlutterWindowTest(int width, int height); - virtual ~Win32FlutterWindowTest(); + FlutterWindowsViewTest(int width, int height); + virtual ~FlutterWindowsViewTest(); // Prevent copying. - Win32FlutterWindowTest(Win32FlutterWindowTest const&) = delete; - Win32FlutterWindowTest& operator=(Win32FlutterWindowTest const&) = delete; + FlutterWindowsViewTest(FlutterWindowsViewTest const&) = delete; + FlutterWindowsViewTest& operator=(FlutterWindowsViewTest const&) = delete; - // |Win32Window| - void OnFontChange() override; + //// |Win32Window| + //void OnFontChange() override; bool OnFontChangeWasCalled(); diff --git a/shell/platform/windows/testing/win32_flutter_window_test.cc b/shell/platform/windows/testing/win32_flutter_window_test.cc deleted file mode 100644 index bae1d9cd8d5b3..0000000000000 --- a/shell/platform/windows/testing/win32_flutter_window_test.cc +++ /dev/null @@ -1,19 +0,0 @@ -#include "flutter/shell/platform/windows/testing/win32_flutter_window_test.h" - -namespace flutter { -namespace testing { - -Win32FlutterWindowTest::Win32FlutterWindowTest(int width, int height) - : Win32FlutterWindow(width, height){}; - -Win32FlutterWindowTest::~Win32FlutterWindowTest() = default; - -void Win32FlutterWindowTest::OnFontChange() { - on_font_change_called_ = true; -} - -bool Win32FlutterWindowTest::OnFontChangeWasCalled() { - return on_font_change_called_; -} -} // namespace testing -} // namespace flutter diff --git a/shell/platform/windows/testing/win32_window_test.cc b/shell/platform/windows/testing/win32_window_test.cc deleted file mode 100644 index da4bc43b9dabe..0000000000000 --- a/shell/platform/windows/testing/win32_window_test.cc +++ /dev/null @@ -1,38 +0,0 @@ -#include "flutter/shell/platform/windows/testing/win32_window_test.h" - -namespace flutter { -namespace testing { - -Win32WindowTest::Win32WindowTest() : Win32Window(){}; - -Win32WindowTest::~Win32WindowTest() = default; - -void Win32WindowTest::OnDpiScale(unsigned int dpi){}; - -void Win32WindowTest::OnResize(unsigned int width, unsigned int height) {} - -void Win32WindowTest::OnPointerMove(double x, double y) {} - -void Win32WindowTest::OnPointerDown(double x, double y, UINT button) {} - -void Win32WindowTest::OnPointerUp(double x, double y, UINT button) {} - -void Win32WindowTest::OnPointerLeave() {} - -void Win32WindowTest::OnText(const std::u16string& text) {} - -void Win32WindowTest::OnKey(int key, - int scancode, - int action, - char32_t character) {} - -void Win32WindowTest::OnScroll(double delta_x, double delta_y) {} - -void Win32WindowTest::OnFontChange() {} - -UINT Win32WindowTest::GetDpi() { - return GetCurrentDPI(); -} - -} // namespace testing -} // namespace flutter diff --git a/shell/platform/windows/testing/win32_window_test.h b/shell/platform/windows/testing/win32_window_test.h deleted file mode 100644 index 5d8630c0181c6..0000000000000 --- a/shell/platform/windows/testing/win32_window_test.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include - -#include "flutter/shell/platform/windows/win32_window.h" - -namespace flutter { -namespace testing { - -/// Test class for the Win32Window base class. Used to access protected methods -/// for testing. -class Win32WindowTest : public Win32Window { - public: - Win32WindowTest(); - virtual ~Win32WindowTest(); - - // Prevent copying. - Win32WindowTest(Win32WindowTest const&) = delete; - Win32WindowTest& operator=(Win32WindowTest const&) = delete; - - // Wrapper for GetCurrentDPI() which is a protected method. - UINT GetDpi(); - - // |Win32Window| - void OnDpiScale(unsigned int dpi) override; - - // |Win32Window| - void OnResize(unsigned int width, unsigned int height) override; - - // |Win32Window| - void OnPointerMove(double x, double y) override; - - // |Win32Window| - void OnPointerDown(double x, double y, UINT button) override; - - // |Win32Window| - void OnPointerUp(double x, double y, UINT button) override; - - // |Win32Window| - void OnPointerLeave() override; - - // |Win32Window| - void OnText(const std::u16string& text) override; - - // |Win32Window| - void OnKey(int key, int scancode, int action, char32_t character) override; - - // |Win32Window| - void OnScroll(double delta_x, double delta_y) override; - - // |Win32Window| - void OnFontChange() override; -}; - -} // namespace testing -} // namespace flutter diff --git a/shell/platform/windows/text_input_plugin.cc b/shell/platform/windows/text_input_plugin.cc index be34dee567d35..18bdcabd44a5c 100644 --- a/shell/platform/windows/text_input_plugin.cc +++ b/shell/platform/windows/text_input_plugin.cc @@ -36,7 +36,7 @@ static constexpr char kInternalConsistencyError[] = namespace flutter { -void TextInputPlugin::TextHook(Win32FlutterWindow* window, +void TextInputPlugin::TextHook(FlutterWindowsView* window, const std::u16string& text) { if (active_model_ == nullptr) { return; @@ -45,7 +45,7 @@ void TextInputPlugin::TextHook(Win32FlutterWindow* window, SendStateUpdate(*active_model_); } -void TextInputPlugin::KeyboardHook(Win32FlutterWindow* window, +void TextInputPlugin::KeyboardHook(FlutterWindowsView* window, int key, int scancode, int action, diff --git a/shell/platform/windows/text_input_plugin.h b/shell/platform/windows/text_input_plugin.h index 44179f8b8b818..5a74c27d0b883 100644 --- a/shell/platform/windows/text_input_plugin.h +++ b/shell/platform/windows/text_input_plugin.h @@ -16,7 +16,7 @@ namespace flutter { -class Win32FlutterWindow; +class FlutterWindowsView; // Implements a text input plugin. // @@ -28,14 +28,14 @@ class TextInputPlugin : public KeyboardHookHandler { virtual ~TextInputPlugin(); // |KeyboardHookHandler| - void KeyboardHook(Win32FlutterWindow* window, + void KeyboardHook(FlutterWindowsView* window, int key, int scancode, int action, char32_t character) override; // |KeyboardHookHandler| - void TextHook(Win32FlutterWindow* window, + void TextHook(FlutterWindowsView* window, const std::u16string& text) override; private: diff --git a/shell/platform/windows/win32_flutter_window.cc b/shell/platform/windows/win32_flutter_window.cc deleted file mode 100644 index 4976a70b064d0..0000000000000 --- a/shell/platform/windows/win32_flutter_window.cc +++ /dev/null @@ -1,365 +0,0 @@ -#include "flutter/shell/platform/windows/win32_flutter_window.h" - -#include - -namespace flutter { - -// The Windows DPI system is based on this -// constant for machines running at 100% scaling. -constexpr int base_dpi = 96; - -Win32FlutterWindow::Win32FlutterWindow(int width, int height) { - surface_manager = std::make_unique(); - Win32Window::InitializeChild("FLUTTERVIEW", width, height); -} - -Win32FlutterWindow::~Win32FlutterWindow() { - DestroyRenderSurface(); - if (plugin_registrar_ && plugin_registrar_->destruction_handler) { - plugin_registrar_->destruction_handler(plugin_registrar_.get()); - } -} - -FlutterDesktopViewControllerRef Win32FlutterWindow::CreateWin32FlutterWindow( - const int width, - const int height) { - auto state = std::make_unique(); - state->view = std::make_unique(width, height); - - // a window wrapper for the state block, distinct from the - // window_wrapper handed to plugin_registrar. - state->view_wrapper = std::make_unique(); - state->view_wrapper->window = state->view.get(); - return state.release(); -} - -void Win32FlutterWindow::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng) { - engine_ = eng; - - auto messenger = std::make_unique(); - message_dispatcher_ = - std::make_unique(messenger.get()); - messenger->engine = engine_; - messenger->dispatcher = message_dispatcher_.get(); - - window_wrapper_ = std::make_unique(); - window_wrapper_->window = this; - - plugin_registrar_ = std::make_unique(); - plugin_registrar_->messenger = std::move(messenger); - plugin_registrar_->window = window_wrapper_.get(); - - internal_plugin_registrar_ = - std::make_unique(plugin_registrar_.get()); - - // Set up the keyboard handlers. - auto internal_plugin_messenger = internal_plugin_registrar_->messenger(); - keyboard_hook_handlers_.push_back( - std::make_unique(internal_plugin_messenger)); - keyboard_hook_handlers_.push_back( - std::make_unique(internal_plugin_messenger)); - platform_handler_ = std::make_unique( - internal_plugin_messenger, this); - - process_events_ = true; -} - -FlutterDesktopPluginRegistrarRef Win32FlutterWindow::GetRegistrar() { - return plugin_registrar_.get(); -} - -// Converts a FlutterPlatformMessage to an equivalent FlutterDesktopMessage. -static FlutterDesktopMessage ConvertToDesktopMessage( - const FlutterPlatformMessage& engine_message) { - FlutterDesktopMessage message = {}; - message.struct_size = sizeof(message); - message.channel = engine_message.channel; - message.message = engine_message.message; - message.message_size = engine_message.message_size; - message.response_handle = engine_message.response_handle; - return message; -} - -// Translates button codes from Win32 API to FlutterPointerMouseButtons. -static uint64_t ConvertWinButtonToFlutterButton(UINT button) { - switch (button) { - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - return kFlutterPointerButtonMousePrimary; - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - return kFlutterPointerButtonMouseSecondary; - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - return kFlutterPointerButtonMouseMiddle; - case XBUTTON1: - return kFlutterPointerButtonMouseBack; - case XBUTTON2: - return kFlutterPointerButtonMouseForward; - } - std::cerr << "Mouse button not recognized: " << button << std::endl; - return 0; -} - -// The Flutter Engine calls out to this function when new platform messages -// are available. -void Win32FlutterWindow::HandlePlatformMessage( - const FlutterPlatformMessage* engine_message) { - if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) { - std::cerr << "Invalid message size received. Expected: " - << sizeof(FlutterPlatformMessage) << " but received " - << engine_message->struct_size << std::endl; - return; - } - - auto message = ConvertToDesktopMessage(*engine_message); - - message_dispatcher_->HandleMessage( - message, [this] { this->process_events_ = false; }, - [this] { this->process_events_ = true; }); -} - -void Win32FlutterWindow::OnDpiScale(unsigned int dpi){}; - -// When DesktopWindow notifies that a WM_Size message has come in -// lets FlutterEngine know about the new size. -void Win32FlutterWindow::OnResize(unsigned int width, unsigned int height) { - SendWindowMetrics(); -} - -void Win32FlutterWindow::OnPointerMove(double x, double y) { - if (process_events_) { - SendPointerMove(x, y); - } -} - -void Win32FlutterWindow::OnPointerDown(double x, double y, UINT button) { - if (process_events_) { - uint64_t flutter_button = ConvertWinButtonToFlutterButton(button); - if (flutter_button != 0) { - uint64_t mouse_buttons = GetMouseState().buttons | flutter_button; - SetMouseButtons(mouse_buttons); - SendPointerDown(x, y); - } - } -} - -void Win32FlutterWindow::OnPointerUp(double x, double y, UINT button) { - if (process_events_) { - uint64_t flutter_button = ConvertWinButtonToFlutterButton(button); - if (flutter_button != 0) { - uint64_t mouse_buttons = GetMouseState().buttons & ~flutter_button; - SetMouseButtons(mouse_buttons); - SendPointerUp(x, y); - } - } -} - -void Win32FlutterWindow::OnPointerLeave() { - if (process_events_) { - SendPointerLeave(); - } -} - -void Win32FlutterWindow::OnText(const std::u16string& text) { - if (process_events_) { - SendText(text); - } -} - -void Win32FlutterWindow::OnKey(int key, - int scancode, - int action, - char32_t character) { - if (process_events_) { - SendKey(key, scancode, action, character); - } -} - -void Win32FlutterWindow::OnScroll(double delta_x, double delta_y) { - if (process_events_) { - SendScroll(delta_x, delta_y); - } -} - -void Win32FlutterWindow::OnFontChange() { - if (engine_ == nullptr) { - return; - } - FlutterEngineReloadSystemFonts(engine_); -} - -// Sends new size information to FlutterEngine. -void Win32FlutterWindow::SendWindowMetrics() { - if (engine_ == nullptr) { - return; - } - - FlutterWindowMetricsEvent event = {}; - event.struct_size = sizeof(event); - event.width = GetCurrentWidth(); - event.height = GetCurrentHeight(); - event.pixel_ratio = static_cast(GetCurrentDPI()) / base_dpi; - auto result = FlutterEngineSendWindowMetricsEvent(engine_, &event); -} - -// Updates |event_data| with the current location of the mouse cursor. -void Win32FlutterWindow::SetEventLocationFromCursorPosition( - FlutterPointerEvent* event_data) { - POINT point; - GetCursorPos(&point); - - ScreenToClient(GetWindowHandle(), &point); - - event_data->x = point.x; - event_data->y = point.y; -} - -// Set's |event_data|'s phase to either kMove or kHover depending on the current -// primary mouse button state. -void Win32FlutterWindow::SetEventPhaseFromCursorButtonState( - FlutterPointerEvent* event_data) { - MouseState state = GetMouseState(); - // For details about this logic, see FlutterPointerPhase in the embedder.h - // file. - event_data->phase = state.buttons == 0 ? state.flutter_state_is_down - ? FlutterPointerPhase::kUp - : FlutterPointerPhase::kHover - : state.flutter_state_is_down - ? FlutterPointerPhase::kMove - : FlutterPointerPhase::kDown; -} - -void Win32FlutterWindow::SendPointerMove(double x, double y) { - FlutterPointerEvent event = {}; - event.x = x; - event.y = y; - SetEventPhaseFromCursorButtonState(&event); - SendPointerEventWithData(event); -} - -void Win32FlutterWindow::SendPointerDown(double x, double y) { - FlutterPointerEvent event = {}; - SetEventPhaseFromCursorButtonState(&event); - event.x = x; - event.y = y; - SendPointerEventWithData(event); - SetMouseFlutterStateDown(true); -} - -void Win32FlutterWindow::SendPointerUp(double x, double y) { - FlutterPointerEvent event = {}; - SetEventPhaseFromCursorButtonState(&event); - event.x = x; - event.y = y; - SendPointerEventWithData(event); - if (event.phase == FlutterPointerPhase::kUp) { - SetMouseFlutterStateDown(false); - } -} - -void Win32FlutterWindow::SendPointerLeave() { - FlutterPointerEvent event = {}; - event.phase = FlutterPointerPhase::kRemove; - SendPointerEventWithData(event); -} - -void Win32FlutterWindow::SendText(const std::u16string& text) { - for (const auto& handler : keyboard_hook_handlers_) { - handler->TextHook(this, text); - } -} - -void Win32FlutterWindow::SendKey(int key, - int scancode, - int action, - char32_t character) { - for (const auto& handler : keyboard_hook_handlers_) { - handler->KeyboardHook(this, key, scancode, action, character); - } -} - -void Win32FlutterWindow::SendScroll(double delta_x, double delta_y) { - FlutterPointerEvent event = {}; - SetEventLocationFromCursorPosition(&event); - SetEventPhaseFromCursorButtonState(&event); - event.signal_kind = FlutterPointerSignalKind::kFlutterPointerSignalKindScroll; - // TODO: See if this can be queried from the OS; this value is chosen - // arbitrarily to get something that feels reasonable. - const int kScrollOffsetMultiplier = 20; - event.scroll_delta_x = delta_x * kScrollOffsetMultiplier; - event.scroll_delta_y = delta_y * kScrollOffsetMultiplier; - SendPointerEventWithData(event); -} - -void Win32FlutterWindow::SendPointerEventWithData( - const FlutterPointerEvent& event_data) { - MouseState mouse_state = GetMouseState(); - // If sending anything other than an add, and the pointer isn't already added, - // synthesize an add to satisfy Flutter's expectations about events. - if (!mouse_state.flutter_state_is_added && - event_data.phase != FlutterPointerPhase::kAdd) { - FlutterPointerEvent event = {}; - event.phase = FlutterPointerPhase::kAdd; - event.x = event_data.x; - event.y = event_data.y; - event.buttons = 0; - SendPointerEventWithData(event); - } - // Don't double-add (e.g., if events are delivered out of order, so an add has - // already been synthesized). - if (mouse_state.flutter_state_is_added && - event_data.phase == FlutterPointerPhase::kAdd) { - return; - } - - FlutterPointerEvent event = event_data; - event.device_kind = kFlutterPointerDeviceKindMouse; - event.buttons = mouse_state.buttons; - - // Set metadata that's always the same regardless of the event. - event.struct_size = sizeof(event); - event.timestamp = - std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()) - .count(); - - FlutterEngineSendPointerEvent(engine_, &event, 1); - - if (event_data.phase == FlutterPointerPhase::kAdd) { - SetMouseFlutterStateAdded(true); - } else if (event_data.phase == FlutterPointerPhase::kRemove) { - SetMouseFlutterStateAdded(false); - ResetMouseState(); - } -} - -bool Win32FlutterWindow::MakeCurrent() { - return surface_manager->MakeCurrent(render_surface); -} - -bool Win32FlutterWindow::MakeResourceCurrent() { - return surface_manager->MakeResourceCurrent(); -} - -bool Win32FlutterWindow::ClearContext() { - return surface_manager->MakeCurrent(nullptr); -} - -bool Win32FlutterWindow::SwapBuffers() { - return surface_manager->SwapBuffers(render_surface); -} - -void Win32FlutterWindow::CreateRenderSurface() { - if (surface_manager && render_surface == EGL_NO_SURFACE) { - render_surface = surface_manager->CreateSurface(GetWindowHandle()); - } -} - -void Win32FlutterWindow::DestroyRenderSurface() { - if (surface_manager) { - surface_manager->DestroySurface(render_surface); - } - render_surface = EGL_NO_SURFACE; -} -} // namespace flutter diff --git a/shell/platform/windows/win32_flutter_window.h b/shell/platform/windows/win32_flutter_window.h deleted file mode 100644 index aff194a0e5ea4..0000000000000 --- a/shell/platform/windows/win32_flutter_window.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_H_ -#define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_H_ - -#include - -#include -#include - -#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h" -#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h" -#include "flutter/shell/platform/embedder/embedder.h" -#include "flutter/shell/platform/windows/angle_surface_manager.h" -#include "flutter/shell/platform/windows/key_event_handler.h" -#include "flutter/shell/platform/windows/keyboard_hook_handler.h" -#include "flutter/shell/platform/windows/platform_handler.h" -#include "flutter/shell/platform/windows/public/flutter_windows.h" -#include "flutter/shell/platform/windows/text_input_plugin.h" -#include "flutter/shell/platform/windows/win32_window.h" -#include "flutter/shell/platform/windows/window_state.h" - -namespace flutter { - -// A win32 flutter child window used as implementatin for flutter view. In the -// future, there will likely be a CoreWindow-based FlutterWindow as well. At -// the point may make sense to dependency inject the native window rather than -// inherit. -class Win32FlutterWindow : public Win32Window { - public: - // Create flutter Window for use as child window - Win32FlutterWindow(int width, int height); - - virtual ~Win32FlutterWindow(); - - static FlutterDesktopViewControllerRef CreateWin32FlutterWindow(int width, - int height); - - // |Win32Window| - void OnDpiScale(unsigned int dpi) override; - - // |Win32Window| - void OnResize(unsigned int width, unsigned int height) override; - - // |Win32Window| - void OnPointerMove(double x, double y) override; - - // |Win32Window| - void OnPointerDown(double x, double y, UINT button) override; - - // |Win32Window| - void OnPointerUp(double x, double y, UINT button) override; - - // |Win32Window| - void OnPointerLeave() override; - - // |Win32Window| - void OnText(const std::u16string& text) override; - - // |Win32Window| - void OnKey(int key, int scancode, int action, char32_t character) override; - - // |Win32Window| - void OnScroll(double delta_x, double delta_y) override; - - // |Win32Window| - void OnFontChange() override; - - // Configures the window instance with an instance of a running Flutter engine - // returning a configured FlutterDesktopWindowControllerRef. - void SetState(FLUTTER_API_SYMBOL(FlutterEngine) state); - - // Returns the currently configured Plugin Registrar. - FlutterDesktopPluginRegistrarRef GetRegistrar(); - - // Callback passed to Flutter engine for notifying window of platform - // messages. - void HandlePlatformMessage(const FlutterPlatformMessage*); - - // Create a surface for Flutter engine to render into. - void CreateRenderSurface(); - - // Callbacks for clearing context, settings context and swapping buffers. - bool ClearContext(); - bool MakeCurrent(); - bool MakeResourceCurrent(); - bool SwapBuffers(); - - // Sends a window metrics update to the Flutter engine using current window - // dimensions in physical - void SendWindowMetrics(); - - private: - // Destroy current rendering surface if one has been allocated. - void DestroyRenderSurface(); - - // Reports a mouse movement to Flutter engine. - void SendPointerMove(double x, double y); - - // Reports mouse press to Flutter engine. - void SendPointerDown(double x, double y); - - // Reports mouse release to Flutter engine. - void SendPointerUp(double x, double y); - - // Reports mouse left the window client area. - // - // Win32 api doesn't have "mouse enter" event. Therefore, there is no - // SendPointerEnter method. A mouse enter event is tracked then the "move" - // event is called. - void SendPointerLeave(); - - // Reports text input to Flutter engine. - void SendText(const std::u16string& text); - - // Reports a raw keyboard message to Flutter engine. - void SendKey(int key, int scancode, int action, char32_t character); - - // Reports scroll wheel events to Flutter engine. - void SendScroll(double delta_x, double delta_y); - - // Updates |event_data| with the current location of the mouse cursor. - void SetEventLocationFromCursorPosition(FlutterPointerEvent* event_data); - - // Set's |event_data|'s phase to either kMove or kHover depending on the - // current - // primary mouse button state. - void SetEventPhaseFromCursorButtonState(FlutterPointerEvent* event_data); - - // Sends a pointer event to the Flutter engine based on givern data. Since - // all input messages are passed in physical pixel values, no translation is - // needed before passing on to engine. - void SendPointerEventWithData(const FlutterPointerEvent& event_data); - - std::unique_ptr surface_manager = nullptr; - EGLSurface render_surface = EGL_NO_SURFACE; - - // state of the mouse button - bool pointer_is_down_ = false; - - // The handle to the Flutter engine instance. - FLUTTER_API_SYMBOL(FlutterEngine) engine_ = nullptr; - - // Whether or not to track mouse movements to send kHover events. - bool hover_tracking_is_enabled_ = false; - - // Whether or not the pointer has been added (or if tracking is enabled, has - // been added since it was last removed). - bool pointer_currently_added_ = false; - - // The window handle given to API clients. - std::unique_ptr window_wrapper_; - - // The plugin registrar handle given to API clients. - std::unique_ptr plugin_registrar_; - - // Message dispatch manager for messages from the Flutter engine. - std::unique_ptr message_dispatcher_; - - // The plugin registrar managing internal plugins. - std::unique_ptr internal_plugin_registrar_; - - // Handlers for keyboard events from Windows. - std::vector> - keyboard_hook_handlers_; - - // Handler for the flutter/platform channel. - std::unique_ptr platform_handler_; - - // should we forword input messages or not - bool process_events_ = false; -}; - -} // namespace flutter - -#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_H_ diff --git a/shell/platform/windows/win32_flutter_window_unittests.cc b/shell/platform/windows/win32_flutter_window_unittests.cc deleted file mode 100644 index dece5a280f807..0000000000000 --- a/shell/platform/windows/win32_flutter_window_unittests.cc +++ /dev/null @@ -1,21 +0,0 @@ -#include "flutter/shell/platform/windows/testing/win32_flutter_window_test.h" -#include "gtest/gtest.h" - -namespace flutter { -namespace testing { - -TEST(Win32FlutterWindowTest, CreateDestroy) { - Win32FlutterWindowTest window(800, 600); - ASSERT_TRUE(TRUE); -} - -TEST(Win32FlutterWindowTest, CanFontChange) { - Win32FlutterWindowTest window(800, 600); - HWND hwnd = window.GetWindowHandle(); - LRESULT result = SendMessage(hwnd, WM_FONTCHANGE, NULL, NULL); - ASSERT_EQ(result, 0); - ASSERT_TRUE(window.OnFontChangeWasCalled()); -} - -} // namespace testing -} // namespace flutter diff --git a/shell/platform/windows/win32_window_unittests.cc b/shell/platform/windows/win32_window_unittests.cc deleted file mode 100644 index 0adc0b0388389..0000000000000 --- a/shell/platform/windows/win32_window_unittests.cc +++ /dev/null @@ -1,18 +0,0 @@ -#include "flutter/shell/platform/windows/testing/win32_window_test.h" -#include "gtest/gtest.h" - -namespace flutter { -namespace testing { - -TEST(Win32WindowTest, CreateDestroy) { - Win32WindowTest window; - ASSERT_TRUE(TRUE); -} - -TEST(Win32WindowTest, GetDpiAfterCreate) { - Win32WindowTest window; - ASSERT_TRUE(window.GetDpi() > 0); -} - -} // namespace testing -} // namespace flutter diff --git a/shell/platform/windows/window_state_comp.h b/shell/platform/windows/window_state_comp.h new file mode 100644 index 0000000000000..908dad30895d8 --- /dev/null +++ b/shell/platform/windows/window_state_comp.h @@ -0,0 +1,74 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_STATE_H_ +#define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_STATE_H_ + +#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h" +#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h" +#include "flutter/shell/platform/embedder/embedder.h" +#include "flutter/shell/platform/windows/key_event_handler.h" +#include "flutter/shell/platform/windows/keyboard_hook_handler.h" +#include "flutter/shell/platform/windows/platform_handler.h" +#include "flutter/shell/platform/windows/task_runner.h" +#include "flutter/shell/platform/windows/text_input_plugin.h" + +namespace flutter { +struct FlutterWindowsView; +} + +// Struct for storing state within an instance of the windows native (HWND or +// CoreWindow) Window. +struct FlutterDesktopViewControllerState { + // The win32 window that owns this state object. + std::unique_ptr view; + + // The state associate with the engine backing the view. + std::unique_ptr engine_state; + + // The window handle given to API clients. + std::unique_ptr view_wrapper; +}; + +// Opaque reference for the native windows itself. This is separate from the +// controller so that it can be provided to plugins without giving them access +// to all of the controller-based functionality. +struct FlutterDesktopView { + // The window that (indirectly) owns this state object. + flutter::FlutterWindowsView* window; + + void* externalwindow; +}; + +// Struct for storing state of a Flutter engine instance. +struct FlutterDesktopEngineState { + // The handle to the Flutter engine instance. + FLUTTER_API_SYMBOL(FlutterEngine) engine; + + // Task runner for tasks posted from the engine. + std::unique_ptr task_runner; +}; + +// State associated with the plugin registrar. +struct FlutterDesktopPluginRegistrar { + // The plugin messenger handle given to API clients. + std::unique_ptr messenger; + + // The handle for the window associated with this registrar. + FlutterDesktopView* window; + + // Callback to be called on registrar destruction. + FlutterDesktopOnRegistrarDestroyed destruction_handler; +}; + +// State associated with the messenger used to communicate with the engine. +struct FlutterDesktopMessenger { + // The Flutter engine this messenger sends outgoing messages to. + FLUTTER_API_SYMBOL(FlutterEngine) engine; + + // The message dispatcher for handling incoming messages. + flutter::IncomingMessageDispatcher* dispatcher; +}; + +#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOW_STATE_H_