From 2abfb0d550e59d58a15e6d86254aade22dd29f31 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sat, 25 Apr 2020 05:52:03 -0700 Subject: [PATCH 01/13] Move win32 window stub into wrapper --- .../platform/windows/client_wrapper/BUILD.gn | 9 +- .../windows/client_wrapper/dpi_utils_pub.cc | 130 +++++++ .../include/flutter/dpi_utils_pub.h | 25 ++ .../flutter/win32_flutter_window_pub.h | 180 +++++++++ .../include/flutter/win32_window_pub.h | 183 +++++++++ .../win32_flutter_window_pub.cc | 365 ++++++++++++++++++ .../client_wrapper/win32_window_pub.cc | 312 +++++++++++++++ 7 files changed, 1203 insertions(+), 1 deletion(-) create mode 100644 shell/platform/windows/client_wrapper/dpi_utils_pub.cc create mode 100644 shell/platform/windows/client_wrapper/include/flutter/dpi_utils_pub.h create mode 100644 shell/platform/windows/client_wrapper/include/flutter/win32_flutter_window_pub.h create mode 100644 shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h create mode 100644 shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc create mode 100644 shell/platform/windows/client_wrapper/win32_window_pub.cc diff --git a/shell/platform/windows/client_wrapper/BUILD.gn b/shell/platform/windows/client_wrapper/BUILD.gn index f92640e80f7f7..f27a1a2eef8ae 100644 --- a/shell/platform/windows/client_wrapper/BUILD.gn +++ b/shell/platform/windows/client_wrapper/BUILD.gn @@ -10,9 +10,16 @@ _wrapper_includes = [ "include/flutter/flutter_view_controller.h", "include/flutter/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 = [ "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 diff --git a/shell/platform/windows/client_wrapper/dpi_utils_pub.cc b/shell/platform/windows/client_wrapper/dpi_utils_pub.cc new file mode 100644 index 0000000000000..52948f4ae2e02 --- /dev/null +++ b/shell/platform/windows/client_wrapper/dpi_utils_pub.cc @@ -0,0 +1,130 @@ +#include "include/flutter/dpi_utils_pub.h" + +namespace flutter { + +namespace pubdpi { + +constexpr UINT kDefaultDpi = 96; + +// This is the MDT_EFFECTIVE_DPI value from MONITOR_DPI_TYPE, an enum declared +// in ShellScalingApi.h. Replicating here to avoid importing the library +// directly. +constexpr UINT kEffectiveDpiMonitorType = 0; + +template + +/// Retrieves a function |name| from a given |comBaseModule| into |outProc|. +/// Returns a bool indicating whether the function was found. +bool AssignProcAddress(HMODULE comBaseModule, const char* name, T*& outProc) { + outProc = reinterpret_cast(GetProcAddress(comBaseModule, name)); + return *outProc != nullptr; +} + +/// A helper class for abstracting various Windows DPI related functions across +/// Windows OS versions. +class Win32DpiHelperPub { + public: + Win32DpiHelperPub(); + + ~Win32DpiHelperPub(); + + /// Returns the DPI for |hwnd|. Supports all DPI awareness modes, and is + /// backward compatible down to Windows Vista. If |hwnd| is nullptr, returns + /// the DPI for the primary monitor. If Per-Monitor DPI awareness is not + /// available, returns the system's DPI. + UINT GetDpiForWindow(HWND); + + /// Returns the DPI of a given monitor. Defaults to 96 if the API is not + /// available. + UINT GetDpiForMonitor(HMONITOR); + + private: + using GetDpiForWindow_ = UINT __stdcall(HWND); + using GetDpiForMonitor_ = HRESULT __stdcall(HMONITOR hmonitor, + UINT dpiType, + UINT* dpiX, + UINT* dpiY); + using EnableNonClientDpiScaling_ = BOOL __stdcall(HWND hwnd); + + GetDpiForWindow_* get_dpi_for_window_ = nullptr; + GetDpiForMonitor_* get_dpi_for_monitor_ = nullptr; + EnableNonClientDpiScaling_* enable_non_client_dpi_scaling_ = nullptr; + + HMODULE user32_module_ = nullptr; + HMODULE shlib_module_ = nullptr; + bool dpi_for_window_supported_ = false; + bool dpi_for_monitor_supported_ = false; +}; + +Win32DpiHelperPub::Win32DpiHelperPub() { + if ((user32_module_ = LoadLibraryA("User32.dll")) != nullptr) { + dpi_for_window_supported_ = (AssignProcAddress( + user32_module_, "GetDpiForWindow", get_dpi_for_window_)); + } + if ((shlib_module_ = LoadLibraryA("Shcore.dll")) != nullptr) { + dpi_for_monitor_supported_ = AssignProcAddress( + shlib_module_, "GetDpiForMonitor", get_dpi_for_monitor_); + } +} + +Win32DpiHelperPub::~Win32DpiHelperPub() { + if (user32_module_ != nullptr) { + FreeLibrary(user32_module_); + } + if (shlib_module_ != nullptr) { + FreeLibrary(shlib_module_); + } +} + +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. + if (dpi_for_window_supported_ && hwnd != nullptr) { + return get_dpi_for_window_(hwnd); + } + + if (dpi_for_monitor_supported_) { + HMONITOR monitor = nullptr; + if (hwnd != nullptr) { + monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); + } + return GetDpiForMonitor(monitor); + } + HDC hdc = GetDC(hwnd); + UINT dpi = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC(hwnd, hdc); + return dpi; +} + +UINT Win32DpiHelperPub::GetDpiForMonitor(HMONITOR monitor) { + if (dpi_for_monitor_supported_) { + if (monitor == nullptr) { + const POINT target_point = {0, 0}; + monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTOPRIMARY); + } + UINT dpi_x = 0, dpi_y = 0; + HRESULT result = + get_dpi_for_monitor_(monitor, kEffectiveDpiMonitorType, &dpi_x, &dpi_y); + if (SUCCEEDED(result)) { + return dpi_x; + } + } + return kDefaultDpi; +} // namespace + +Win32DpiHelperPub* GetHelper() { + static Win32DpiHelperPub* dpi_helper = new Win32DpiHelperPub(); + return dpi_helper; + +} // namespace + +UINT GetDpiForHWND(HWND hwnd) { + return GetHelper()->GetDpiForWindow(hwnd); +} + +UINT GetDpiForMonitor(HMONITOR monitor) { + return GetHelper()->GetDpiForMonitor(monitor); +} +} // namespace pubdpi +} // namespace flutter diff --git a/shell/platform/windows/client_wrapper/include/flutter/dpi_utils_pub.h b/shell/platform/windows/client_wrapper/include/flutter/dpi_utils_pub.h new file mode 100644 index 0000000000000..0e79e32a8bb07 --- /dev/null +++ b/shell/platform/windows/client_wrapper/include/flutter/dpi_utils_pub.h @@ -0,0 +1,25 @@ +// 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 "Windows.h" + +#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_DPI_UTILS_H_ +#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 +/// DPI for the primary monitor. If Per-Monitor DPI awareness is not available, +/// returns the system's DPI. +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/win32_flutter_window_pub.h b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_window_pub.h new file mode 100644 index 0000000000000..5e8d8a21bb5b2 --- /dev/null +++ b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_window_pub.h @@ -0,0 +1,180 @@ +// 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" + +#include "win32_window_pub.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 Win32FlutterWindowPub : public Win32WindowPub { + public: + // Create flutter Window for use as child window + Win32FlutterWindowPub(int width, int height); + + virtual ~Win32FlutterWindowPub(); + + /*static FlutterDesktopViewControllerRef CreateWin32FlutterWindow(int width, + int height);*/ + + // |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; + + //// 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/client_wrapper/include/flutter/win32_window_pub.h b/shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h new file mode 100644 index 0000000000000..48a6c1b13904c --- /dev/null +++ b/shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h @@ -0,0 +1,183 @@ +// 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_WIN32_WINDOW_H_ +#define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WIN32_WINDOW_H_ + +#include +#include + +#include +#include + +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 MouseStatePub { + // 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 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 Win32WindowPub { + public: + 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 + // parented into window hierarchy by caller. + void InitializeChild(const char* title, + unsigned int width, + unsigned int height); + + HWND GetWindowHandle(); + + protected: + // Converts a c string to a wide unicode string. + std::wstring NarrowToWide(const char* source); + + // Registers a window class with default style attributes, cursor and + // icon. + WNDCLASS RegisterWindowClass(std::wstring& title); + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + LRESULT + MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // When WM_DPICHANGE process it using |hWnd|, |wParam|. If + // |top_level| is set, extract the suggested new size from |lParam| and resize + // the window to the new suggested size. If |top_level| is not set, the + // |lParam| will not contain a suggested size hence ignore it. + LRESULT + HandleDpiChange(HWND hWnd, WPARAM wParam, LPARAM lParam, bool top_level); + + // Called when the DPI changes either when a + // user drags the window between monitors of differing DPI or when the user + // manually changes the scale factor. + virtual void OnDpiScale(UINT dpi) = 0; + + // Called when a resize occurs. + virtual void OnResize(UINT width, UINT height) = 0; + + // Called when the pointer moves within the + // window bounds. + virtual void OnPointerMove(double x, double y) = 0; + + // Called when the a mouse button, determined by |button|, goes down. + virtual void OnPointerDown(double x, double y, UINT button) = 0; + + // Called when the a mouse button, determined by |button|, goes from + // down to up + virtual void OnPointerUp(double x, double y, UINT button) = 0; + + // Called when the mouse leaves the window. + virtual void OnPointerLeave() = 0; + + // Called when text input occurs. + virtual void OnText(const std::u16string& text) = 0; + + // Called when raw keyboard input occurs. + virtual void OnKey(int key, int scancode, int action, char32_t character) = 0; + + // Called when mouse scrollwheel input occurs. + virtual void OnScroll(double delta_x, double delta_y) = 0; + + // Called when the system font change. + virtual void OnFontChange() = 0; + + UINT GetCurrentDPI(); + + UINT GetCurrentWidth(); + + UINT GetCurrentHeight(); + + // Gets the current mouse state. + MouseStatePub GetMouseStatePub() { return mouse_state_; } + + // Resets the mouse state to its default values. + void ResetMouseState() { mouse_state_ = MouseStatePub(); } + + // 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; } + + private: + // Release OS resources asociated with window. + void Destroy(); + + // Activates tracking for a "mouse leave" event. + void TrackMouseLeaveEvent(HWND hwnd); + + // Stores new width and height and calls |OnResize| to notify inheritors + void HandleResize(UINT width, UINT height); + + // Retrieves a class instance pointer for |window| + static Win32WindowPub* GetThisFromHandle(HWND const window) noexcept; + int current_dpi_ = 0; + int current_width_ = 0; + int current_height_ = 0; + + // WM_DPICHANGED_BEFOREPARENT defined in more recent Windows + // SDK + const static long kWmDpiChangedBeforeParent = 0x02E2; + + // Member variable to hold window handle. + HWND window_handle_ = nullptr; + + // Member variable to hold the window title. + std::wstring window_class_name_; + + // 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. + MouseStatePub mouse_state_; + + // Keeps track of the last key code produced by a WM_KEYDOWN or WM_SYSKEYDOWN + // message. + int keycode_for_char_message_ = 0; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WIN32_WINDOW_H_ 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..529e563785d95 --- /dev/null +++ b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc @@ -0,0 +1,365 @@ +#include "include/flutter/win32_flutter_window_pub.h" + +#include + +namespace flutter { + +// 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) { + /*surface_manager = std::make_unique(); + Win32Window::InitializeChild("FLUTTERVIEW", width, height);*/ +} + +Win32FlutterWindowPub::~Win32FlutterWindowPub() { + /*DestroyRenderSurface(); + if (plugin_registrar_ && plugin_registrar_->destruction_handler) { + plugin_registrar_->destruction_handler(plugin_registrar_.get()); + }*/ +} + +//FlutterDesktopViewControllerRef Win32FlutterWindowPub::CreateWin32FlutterWindowPub( +// 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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::OnDpiScale(unsigned int 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) { + /*SendWindowMetrics();*/ +} + +void Win32FlutterWindowPub::OnPointerMove(double x, double y) { + /*if (process_events_) { + SendPointerMove(x, y); + }*/ +} + +void Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::OnPointerLeave() { + /* if (process_events_) { + SendPointerLeave(); + }*/ +} + +void Win32FlutterWindowPub::OnText(const std::u16string& text) { + /* if (process_events_) { + SendText(text); + }*/ +} + +void Win32FlutterWindowPub::OnKey(int key, + int scancode, + int action, + char32_t character) { + /*if (process_events_) { + SendKey(key, scancode, action, character); + }*/ +} + +void Win32FlutterWindowPub::OnScroll(double delta_x, double delta_y) { + /*if (process_events_) { + SendScroll(delta_x, delta_y); + }*/ +} + +void Win32FlutterWindowPub::OnFontChange() { + /*if (engine_ == nullptr) { + return; + } + FlutterEngineReloadSystemFonts(engine_);*/ +} + +// Sends new size information to FlutterEngine. +//void Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::SendPointerMove(double x, double y) { +// FlutterPointerEvent event = {}; +// event.x = x; +// event.y = y; +// SetEventPhaseFromCursorButtonState(&event); +// SendPointerEventWithData(event); +//} + +//void Win32FlutterWindowPub::SendPointerDown(double x, double y) { +// FlutterPointerEvent event = {}; +// SetEventPhaseFromCursorButtonState(&event); +// event.x = x; +// event.y = y; +// SendPointerEventWithData(event); +// SetMouseFlutterStateDown(true); +//} + +//void Win32FlutterWindowPub::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 Win32FlutterWindowPub::SendPointerLeave() { +// FlutterPointerEvent event = {}; +// event.phase = FlutterPointerPhase::kRemove; +// SendPointerEventWithData(event); +//} + +//void Win32FlutterWindowPub::SendText(const std::u16string& text) { +// for (const auto& handler : keyboard_hook_handlers_) { +// handler->TextHook(this, text); +// } +//} + +//void Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::MakeCurrent() { +// return surface_manager->MakeCurrent(render_surface); +//} +// +//bool Win32FlutterWindowPub::MakeResourceCurrent() { +// return surface_manager->MakeResourceCurrent(); +//} +// +//bool Win32FlutterWindowPub::ClearContext() { +// return surface_manager->MakeCurrent(nullptr); +//} +// +//bool Win32FlutterWindowPub::SwapBuffers() { +// return surface_manager->SwapBuffers(render_surface); +//} +// +//void Win32FlutterWindowPub::CreateRenderSurface() { +// if (surface_manager && render_surface == EGL_NO_SURFACE) { +// render_surface = surface_manager->CreateSurface(GetWindowHandle()); +// } +//} +// +//void Win32FlutterWindowPub::DestroyRenderSurface() { +// if (surface_manager) { +// surface_manager->DestroySurface(render_surface); +// } +// render_surface = EGL_NO_SURFACE; +//} +} // namespace flutter diff --git a/shell/platform/windows/client_wrapper/win32_window_pub.cc b/shell/platform/windows/client_wrapper/win32_window_pub.cc new file mode 100644 index 0000000000000..b6c01fb9ff822 --- /dev/null +++ b/shell/platform/windows/client_wrapper/win32_window_pub.cc @@ -0,0 +1,312 @@ +// 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/win32_window_pub.h" + +#include "include/flutter/dpi_utils_pub.h" + +namespace flutter { + +namespace { +char32_t CodePointFromSurrogatePair(wchar_t high, wchar_t low) { + return 0x10000 + ((static_cast(high) & 0x000003FF) << 10) + + (low & 0x3FF); +} +} // namespace + +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_ = pubdpi::GetDpiForHWND(nullptr); +} + +Win32WindowPub::~Win32WindowPub() { + Destroy(); +} + +void Win32WindowPub::InitializeChild(const char* title, + unsigned int width, + unsigned int height) { + Destroy(); + std::wstring converted_title = NarrowToWide(title); + + WNDCLASS window_class = RegisterWindowClass(converted_title); + + auto* result = CreateWindowEx( + 0, window_class.lpszClassName, converted_title.c_str(), + WS_CHILD | WS_VISIBLE, CW_DEFAULT, CW_DEFAULT, width, height, + HWND_MESSAGE, nullptr, window_class.hInstance, this); + + if (result == nullptr) { + auto error = GetLastError(); + LPWSTR message = nullptr; + size_t size = FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&message), 0, NULL); + OutputDebugString(message); + LocalFree(message); + } +} + +std::wstring Win32WindowPub::NarrowToWide(const char* source) { + size_t length = strlen(source); + size_t outlen = 0; + std::wstring wideTitle(length, L'#'); + mbstowcs_s(&outlen, &wideTitle[0], length + 1, source, length); + return wideTitle; +} + +WNDCLASS Win32WindowPub::RegisterWindowClass(std::wstring& title) { + window_class_name_ = title; + + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = title.c_str(); + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = nullptr; + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = WndProc; + RegisterClass(&window_class); + return window_class; +} + +LRESULT CALLBACK Win32WindowPub::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto cs = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(cs->lpCreateParams)); + + auto that = static_cast(cs->lpCreateParams); + that->window_handle_ = window; + } else if (Win32WindowPub* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +void Win32WindowPub::TrackMouseLeaveEvent(HWND hwnd) { + if (!tracking_mouse_leave_) { + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(tme); + tme.hwndTrack = hwnd; + tme.dwFlags = TME_LEAVE; + TrackMouseEvent(&tme); + tracking_mouse_leave_ = true; + } +} + +LRESULT +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)); + UINT button_pressed = 0; + + if (window != nullptr) { + switch (message) { + case kWmDpiChangedBeforeParent: + current_dpi_ = pubdpi::GetDpiForHWND(window_handle_); + window->OnDpiScale(current_dpi_); + return 0; + case WM_SIZE: + width = LOWORD(lparam); + height = HIWORD(lparam); + + current_width_ = width; + current_height_ = height; + window->HandleResize(width, height); + break; + case WM_FONTCHANGE: + window->OnFontChange(); + break; + case WM_MOUSEMOVE: + window->TrackMouseLeaveEvent(hwnd); + + xPos = GET_X_LPARAM(lparam); + yPos = GET_Y_LPARAM(lparam); + window->OnPointerMove(static_cast(xPos), + static_cast(yPos)); + break; + case WM_MOUSELEAVE:; + window->OnPointerLeave(); + // Once the tracked event is received, the TrackMouseEvent function + // resets. Set to false to make sure it's called once mouse movement is + // detected again. + tracking_mouse_leave_ = false; + break; + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_XBUTTONDOWN: + if (message == WM_LBUTTONDOWN) { + // Capture the pointer in case the user drags outside the client area. + // In this case, the "mouse leave" event is delayed until the user + // releases the button. It's only activated on left click given that + // it's more common for apps to handle dragging with only the left + // button. + SetCapture(hwnd); + } + button_pressed = message; + if (message == WM_XBUTTONDOWN) { + button_pressed = GET_XBUTTON_WPARAM(wparam); + } + xPos = GET_X_LPARAM(lparam); + yPos = GET_Y_LPARAM(lparam); + window->OnPointerDown(static_cast(xPos), + static_cast(yPos), button_pressed); + break; + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + case WM_XBUTTONUP: + if (message == WM_LBUTTONUP) { + ReleaseCapture(); + } + button_pressed = message; + if (message == WM_XBUTTONUP) { + button_pressed = GET_XBUTTON_WPARAM(wparam); + } + xPos = GET_X_LPARAM(lparam); + yPos = GET_Y_LPARAM(lparam); + window->OnPointerUp(static_cast(xPos), + static_cast(yPos), button_pressed); + break; + case WM_MOUSEWHEEL: + window->OnScroll( + 0.0, -(static_cast(HIWORD(wparam)) / (double)WHEEL_DELTA)); + break; + case WM_UNICHAR: { + // Tell third-pary app, we can support Unicode. + if (wparam == UNICODE_NOCHAR) + return TRUE; + // DefWindowProc will send WM_CHAR for this WM_UNICHAR. + break; + } + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + case WM_CHAR: + case WM_SYSCHAR: { + static wchar_t s_pending_high_surrogate = 0; + + wchar_t character = static_cast(wparam); + std::u16string text({character}); + char32_t code_point = character; + if (IS_HIGH_SURROGATE(character)) { + // Save to send later with the trailing surrogate. + s_pending_high_surrogate = character; + } else if (IS_LOW_SURROGATE(character) && + s_pending_high_surrogate != 0) { + text.insert(text.begin(), s_pending_high_surrogate); + // Merge the surrogate pairs for the key event. + code_point = + CodePointFromSurrogatePair(s_pending_high_surrogate, character); + s_pending_high_surrogate = 0; + } + + // Of the messages handled here, only WM_CHAR should be treated as + // characters. WM_SYS*CHAR are not part of text input, and WM_DEADCHAR + // will be incorporated into a later WM_CHAR with the full character. + // Also filter out: + // - Lead surrogates, which like dead keys will be send once combined. + // - ASCII control characters, which are sent as WM_CHAR events for all + // control key shortcuts. + if (message == WM_CHAR && s_pending_high_surrogate == 0 && + character >= u' ') { + window->OnText(text); + } + + // All key presses that generate a character should be sent from + // WM_CHAR. In order to send the full key press information, the keycode + // is persisted in keycode_for_char_message_ obtained from WM_KEYDOWN. + if (keycode_for_char_message_ != 0) { + const unsigned int scancode = (lparam >> 16) & 0xff; + window->OnKey(keycode_for_char_message_, scancode, WM_KEYDOWN, + code_point); + keycode_for_char_message_ = 0; + } + break; + } + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + case WM_KEYUP: + case WM_SYSKEYUP: + const bool is_keydown_message = + (message == WM_KEYDOWN || message == WM_SYSKEYDOWN); + // 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); + if (character > 0 && is_keydown_message) { + keycode_for_char_message_ = wparam; + break; + } + unsigned int keyCode(wparam); + const unsigned int scancode = (lparam >> 16) & 0xff; + // If the key is a modifier, get its side. + if (keyCode == VK_SHIFT || keyCode == VK_MENU || + keyCode == VK_CONTROL) { + keyCode = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); + } + const int action = is_keydown_message ? WM_KEYDOWN : WM_KEYUP; + window->OnKey(keyCode, scancode, action, 0); + break; + } + return DefWindowProc(hwnd, message, wparam, lparam); + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +UINT Win32WindowPub::GetCurrentDPI() { + return current_dpi_; +} + +UINT Win32WindowPub::GetCurrentWidth() { + return current_width_; +} + +UINT Win32WindowPub::GetCurrentHeight() { + return current_height_; +} + +HWND Win32WindowPub::GetWindowHandle() { + return window_handle_; +} + +void Win32WindowPub::Destroy() { + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + + UnregisterClass(window_class_name_.c_str(), nullptr); +} + +void Win32WindowPub::HandleResize(UINT width, UINT height) { + current_width_ = width; + current_height_ = height; + OnResize(width, height); +} + +Win32WindowPub* Win32WindowPub::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +} // namespace flutter From c35c8c8d5b31d78e83053e0c40b445cd72457c7e Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sat, 25 Apr 2020 07:03:37 -0700 Subject: [PATCH 02/13] Wrapper creates a Win32WindowPub; testbed launches with empty window --- .../client_wrapper/flutter_view_controller.cc | 14 ++++--- .../include/flutter/flutter_view_controller.h | 10 +++-- .../win32_flutter_window_pub.cc | 40 +++++++++---------- .../client_wrapper/win32_window_pub.cc | 8 ++-- 4 files changed, 39 insertions(+), 33 deletions(-) diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller.cc b/shell/platform/windows/client_wrapper/flutter_view_controller.cc index a16a0699dd188..8ba13f2e5dfd9 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_controller.cc +++ b/shell/platform/windows/client_wrapper/flutter_view_controller.cc @@ -24,12 +24,13 @@ FlutterViewController::FlutterViewController(int width, 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); + /*controller_ = FlutterDesktopCreateViewController(width, height, properties); if (!controller_) { std::cerr << "Failed to create view controller." << std::endl; return; - } - view_ = std::make_unique(FlutterDesktopGetView(controller_)); + }*/ + //view_ = std::make_unique(FlutterDesktopGetView(controller_)); + child_window_ = std::make_unique(width, height); } FlutterViewController::FlutterViewController( @@ -55,13 +56,14 @@ FlutterViewController::FlutterViewController( std::cerr << "Failed to create view controller." << std::endl; return; } - view_ = std::make_unique(FlutterDesktopGetView(controller_)); + //view_ = std::make_unique(FlutterDesktopGetView(controller_)); + child_window_ = std::make_unique(width,height); } FlutterViewController::~FlutterViewController() { - if (controller_) { + /*if (controller_) { FlutterDesktopDestroyViewController(controller_); - } + }*/ } std::chrono::nanoseconds FlutterViewController::ProcessMessages() { diff --git a/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h b/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h index 607e01a72f247..5a90849b9af65 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h +++ b/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h @@ -15,6 +15,7 @@ #include "flutter_view.h" #include "plugin_registrar.h" #include "plugin_registry.h" +#include "win32_flutter_window_pub.h" namespace flutter { @@ -46,7 +47,7 @@ class FlutterViewController : public PluginRegistry { FlutterViewController(FlutterViewController const&) = delete; FlutterViewController& operator=(FlutterViewController const&) = delete; - FlutterView* view() { return view_.get(); } + FlutterView* view() { return nullptr; /*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 +65,11 @@ 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_; }; } // namespace flutter diff --git a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc index 529e563785d95..66872cbd3b08a 100644 --- a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc +++ b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc @@ -80,26 +80,26 @@ Win32FlutterWindowPub::~Win32FlutterWindowPub() { // 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; -} +//// 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. diff --git a/shell/platform/windows/client_wrapper/win32_window_pub.cc b/shell/platform/windows/client_wrapper/win32_window_pub.cc index b6c01fb9ff822..5c661be209652 100644 --- a/shell/platform/windows/client_wrapper/win32_window_pub.cc +++ b/shell/platform/windows/client_wrapper/win32_window_pub.cc @@ -42,7 +42,7 @@ void Win32WindowPub::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), @@ -251,12 +251,12 @@ Win32WindowPub::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 || From 0ce3abff395fb5f656d0d2b0f4f9253f3d3c5c0a Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sat, 25 Apr 2020 08:50:08 -0700 Subject: [PATCH 03/13] Bring over V2 API from UWP prototype WIP --- shell/platform/windows/BUILD.gn | 24 +- shell/platform/windows/dpi_utils_unittests.cc | 21 - shell/platform/windows/flutter_comp_view.cc | 619 ++++++++++++++++++ shell/platform/windows/flutter_comp_view.h | 299 +++++++++ ...tests.cc => flutter_compview_unittests.cc} | 2 +- shell/platform/windows/flutter_windows.cc | 41 +- shell/platform/windows/key_event_handler.cc | 4 +- shell/platform/windows/key_event_handler.h | 6 +- .../platform/windows/keyboard_hook_handler.h | 6 +- shell/platform/windows/platform_handler.cc | 2 +- shell/platform/windows/platform_handler.h | 6 +- .../platform/windows/public/flutter_windows.h | 17 + .../{win32_task_runner.cc => task_runner.cc} | 14 +- .../{win32_task_runner.h => task_runner.h} | 10 +- .../windows/testing/flutter_compview_test.cc | 20 + ..._window_test.h => flutter_compview_test.h} | 16 +- .../testing/win32_flutter_window_test.cc | 19 - .../windows/testing/win32_window_test.cc | 38 -- .../windows/testing/win32_window_test.h | 58 -- shell/platform/windows/text_input_plugin.cc | 4 +- shell/platform/windows/text_input_plugin.h | 6 +- .../windows/win32_window_unittests.cc | 18 - shell/platform/windows/window_state_comp.h | 72 ++ 23 files changed, 1102 insertions(+), 220 deletions(-) delete mode 100644 shell/platform/windows/dpi_utils_unittests.cc create mode 100644 shell/platform/windows/flutter_comp_view.cc create mode 100644 shell/platform/windows/flutter_comp_view.h rename shell/platform/windows/{win32_flutter_window_unittests.cc => flutter_compview_unittests.cc} (86%) rename shell/platform/windows/{win32_task_runner.cc => task_runner.cc} (87%) rename shell/platform/windows/{win32_task_runner.h => task_runner.h} (90%) create mode 100644 shell/platform/windows/testing/flutter_compview_test.cc rename shell/platform/windows/testing/{win32_flutter_window_test.h => flutter_compview_test.h} (51%) delete mode 100644 shell/platform/windows/testing/win32_flutter_window_test.cc delete mode 100644 shell/platform/windows/testing/win32_window_test.cc delete mode 100644 shell/platform/windows/testing/win32_window_test.h delete mode 100644 shell/platform/windows/win32_window_unittests.cc create mode 100644 shell/platform/windows/window_state_comp.h diff --git a/shell/platform/windows/BUILD.gn b/shell/platform/windows/BUILD.gn index ce8c6c0ec7fe1..4b72d26ba7bed 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_comp_view.cc", + "flutter_comp_view.h", + "window_state_comp.h", + "task_runner.cc", + "task_runner.h", ] configs += [ @@ -109,14 +105,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" ] 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_comp_view.cc b/shell/platform/windows/flutter_comp_view.cc new file mode 100644 index 0000000000000..13264be6aa266 --- /dev/null +++ b/shell/platform/windows/flutter_comp_view.cc @@ -0,0 +1,619 @@ +#include "flutter/shell/platform/windows/flutter_comp_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; + +FlutterCompView::FlutterCompView(int width, int height, void* compositor) { + surface_manager = std::make_unique(); + + compositor_.Attach(static_cast(compositor)); + + //TODO: use C++/Winrt copy_from_abi once C++.Winrt is supportrf + //winrt::copy_from_abi(compositor_, compositor); + + width_ = width; + height_ = height; +} + +FlutterCompView::~FlutterCompView() { + DestroyRenderSurface(); +} + +FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompView( + const int width, + const int height, + void* compositor) { + auto state = std::make_unique(); + state->view = std::make_unique(width, height, compositor); + + // 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 FlutterCompView::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; + + //HACK for UWP + if (compositor_ != nullptr) { + SendWindowMetrics(width_, height_); + } +} + +FlutterDesktopPluginRegistrarRef FlutterCompView::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 FlutterCompView::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 FlutterCompView::OnPointerMove(double x, double y) { + if (process_events_) { + SendPointerMove(x, y); + } +} + +void FlutterCompView::OnPointerDown(double x, + double y, + FlutterPointerMouseButtons flutter_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 FlutterCompView::OnPointerUp(double x, + double y, + FlutterPointerMouseButtons flutter_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 FlutterCompView::OnPointerLeave() { + if (process_events_) { + SendPointerLeave(); + } +} + +void FlutterCompView::OnChar(char32_t code_point) { + if (process_events_) { + SendChar(code_point); + } +} + +void FlutterCompView::OnKey(int key, + int scancode, + int action, + char32_t character) { + if (process_events_) { + SendKey(key, scancode, action, character); + } +} + +void FlutterCompView::OnScroll(double delta_x, double delta_y) { + if (process_events_) { + SendScroll(delta_x, delta_y); + } +} + +void FlutterCompView::OnFontChange() { + if (engine_ == nullptr) { + return; + } + FlutterEngineReloadSystemFonts(engine_); +} + +// Sends new size information to FlutterEngine. +void FlutterCompView::SendWindowMetrics(size_t width, size_t height) { + if (engine_ == nullptr) { + return; + } + + FlutterWindowMetricsEvent event = {}; + event.struct_size = sizeof(event); + //event.width = 320; // GetCurrentWidth(); TODO + //event.height = 240; //GetCurrentHeight(); TODO + event.width = width; // GetCurrentWidth(); TODO + event.height = height; // GetCurrentHeight(); TODO + event.pixel_ratio = 1.2; // static_cast(GetCurrentDPI()) / base_dpi; TODO + auto result = FlutterEngineSendWindowMetricsEvent(engine_, &event); + + + SizeHostVisual(width, height); +} + +// Updates |event_data| with the current location of the mouse cursor. +void FlutterCompView::SetEventLocationFromCursorPosition( + FlutterPointerEvent* event_data) { + //POINT point; + //GetCursorPos(&point); + + //ScreenToClient(GetWindowHandle(), &point); TODO + + //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 FlutterCompView::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 FlutterCompView::SendPointerMove(double x, double y) { + FlutterPointerEvent event = {}; + event.x = x; + event.y = y; + SetEventPhaseFromCursorButtonState(&event); + SendPointerEventWithData(event); +} + +void FlutterCompView::SendPointerDown(double x, double y) { + FlutterPointerEvent event = {}; + SetEventPhaseFromCursorButtonState(&event); + event.x = x; + event.y = y; + SendPointerEventWithData(event); + SetMouseFlutterStateDown(true); +} + +void FlutterCompView::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 FlutterCompView::SendPointerLeave() { + FlutterPointerEvent event = {}; + event.phase = FlutterPointerPhase::kRemove; + SendPointerEventWithData(event); +} + +void FlutterCompView::SendChar(char32_t code_point) { + for (const auto& handler : keyboard_hook_handlers_) { + handler->CharHook(this, code_point); + } +} + +void FlutterCompView::SendKey(int key, int scancode, int action, int mods) { + for (const auto& handler : keyboard_hook_handlers_) { + handler->KeyboardHook(this, key, scancode, action, mods); + } +} + +void FlutterCompView::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 FlutterCompView::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(); + + //// Windows passes all input in either physical pixels (Per-monitor, System + //// DPI) or pre-scaled to match bitmap scaling of output where process is + //// running in DPI unaware more. In either case, no need to manually scale + //// input here. For more information see DPIHelper. + //event.scroll_delta_x; + //event.scroll_delta_y; + + FlutterEngineSendPointerEvent(engine_, &event, 1); + + if (event_data.phase == FlutterPointerPhase::kAdd) { + SetMouseFlutterStateAdded(true); + } else if (event_data.phase == FlutterPointerPhase::kRemove) { + SetMouseFlutterStateAdded(false); + ResetMouseState(); + } +} + +bool FlutterCompView::MakeCurrent() { + return surface_manager->MakeCurrent(render_surface); +} + +bool FlutterCompView::MakeResourceCurrent() { + return surface_manager->MakeResourceCurrent(); +} + +bool FlutterCompView::ClearContext() { + return surface_manager->MakeCurrent(nullptr); +} + +bool FlutterCompView::SwapBuffers() { + return surface_manager->SwapBuffers(render_surface); +} + +Microsoft::WRL::ComPtr +FlutterCompView::GetFlutterHost() { + return flutter_host_; +} + +void FlutterCompView::SizeHostVisual(size_t width, size_t height) { + Microsoft::WRL::ComPtr visualPtr; + + auto hr = flutter_host_.As(&visualPtr); + (SUCCEEDED(hr)); + hr = visualPtr->put_Size({static_cast(width), static_cast(height)}); + (SUCCEEDED(hr)); +} + +// TODO: move this into visual_flutter_host class when that exists +// TODO: can we use c++/winrt in here (requires newer windows SDK and c++17 +// support in compiler toolchain) +// TODO: do we still need RoHelper with the above? +void FlutterCompView::CreateRenderSurfaceUWP() { + + if (surface_manager && render_surface == EGL_NO_SURFACE) { + // render_surface = surface_manager->CreateSurface(GetWindowHandle()); + + RoHelper helper; + HSTRING act; + HSTRING_HEADER header; + + auto hr = compositor_->CreateSpriteVisual(flutter_host_.GetAddressOf()); + (SUCCEEDED(hr)); + + Microsoft::WRL::ComPtr visualPtr; + + hr = flutter_host_.As(&visualPtr); + (SUCCEEDED(hr)); + hr = visualPtr->put_Size({static_cast(width_), static_cast(height_)}); + (SUCCEEDED(hr)); + + hr = visualPtr->put_Offset({40, 20}); + (SUCCEEDED(hr)); + + render_surface = surface_manager->CreateSurface(flutter_host_.Get()); + } +} + +void FlutterCompView::DestroyRenderSurface() { + if (surface_manager) { + surface_manager->DestroySurface(render_surface); + } + render_surface = EGL_NO_SURFACE; +} + +// RoHelperImpl + +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_comp_view.h b/shell/platform/windows/flutter_comp_view.h new file mode 100644 index 0000000000000..03352d21ad6d5 --- /dev/null +++ b/shell/platform/windows/flutter_comp_view.h @@ -0,0 +1,299 @@ +// 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 "flutter/shell/platform/windows/window_state_comp.h" + +#include +#include +#include +#include +#include +#include + +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 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 FlutterCompView { + public: + // Create flutter Window for use as child window + FlutterCompView(int width, int height, void* compositor); + + ~FlutterCompView(); + + static FlutterDesktopViewControllerRef CreateFlutterCompView( + int width, + int height, + void* compositor); + + // 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 CreateRenderSurfaceUWP(); + + // 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); + + Microsoft::WRL::ComPtr + GetFlutterHost(); + + // 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 OnChar(char32_t code_point); + + // TODO + void OnKey(int key, int scancode, int action, char32_t character); + + // TODO + void OnScroll(double delta_x, double delta_y); + + // TODO + void OnFontChange(); + + private: + +// 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 SendChar(char32_t code_point); + + // 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 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); + + // 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; + + Microsoft::WRL::ComPtr compositor_ {nullptr}; + + Microsoft::WRL::ComPtr + flutter_host_{nullptr}; + + + int width_ = 0, height_ = 0; +}; + +} // 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/flutter_compview_unittests.cc similarity index 86% rename from shell/platform/windows/win32_flutter_window_unittests.cc rename to shell/platform/windows/flutter_compview_unittests.cc index dece5a280f807..671a4adb9ea8a 100644 --- a/shell/platform/windows/win32_flutter_window_unittests.cc +++ b/shell/platform/windows/flutter_compview_unittests.cc @@ -1,4 +1,4 @@ -#include "flutter/shell/platform/windows/testing/win32_flutter_window_test.h" +#include "flutter/shell/platform/windows/testing/flutter_compview_test.h" #include "gtest/gtest.h" namespace flutter { diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index 805ca6cd31a3a..cb49ce2f84b8a 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -18,14 +18,12 @@ #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/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/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" +#include "flutter/shell/platform/windows/task_runner.h" +#include "flutter/shell/platform/windows/flutter_comp_view.h" static_assert(FLUTTER_ENGINE_VERSION == 1, ""); @@ -38,7 +36,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::FlutterCompView* window, const FlutterDesktopEngineProperties& engine_properties) { auto state = std::make_unique(); @@ -58,15 +56,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 +73,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 +90,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); }; @@ -167,6 +165,25 @@ FlutterDesktopViewControllerRef FlutterDesktopCreateViewController( return state; } +V2FlutterDesktopViewControllerRef V2FlutterDesktopCreateViewController( + int width, + int height, + const FlutterDesktopEngineProperties& engine_properties, + void* compositor) { + V2FlutterDesktopViewControllerRef state = + flutter::FlutterCompView::CreateFlutterCompView(width, height, + compositor); + + auto engine_state = RunFlutterEngine(state->view.get(), engine_properties); + + if (!engine_state) { + return nullptr; + } + state->view->SetState(engine_state->engine); + state->engine_state = std::move(engine_state); + return state; +} + FlutterDesktopViewControllerRef FlutterDesktopCreateViewControllerLegacy( int initial_width, int initial_height, diff --git a/shell/platform/windows/key_event_handler.cc b/shell/platform/windows/key_event_handler.cc index 3747a9f5a05a0..671c3e0c69859 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(FlutterCompView* window, const std::u16string& code_point) {} -void KeyEventHandler::KeyboardHook(Win32FlutterWindow* window, +void KeyEventHandler::KeyboardHook(FlutterCompView* 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..33d19f1ff85b1 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 FlutterCompView; // Implements a KeyboardHookHandler // @@ -28,14 +28,14 @@ class KeyEventHandler : public KeyboardHookHandler { virtual ~KeyEventHandler(); // |KeyboardHookHandler| - void KeyboardHook(Win32FlutterWindow* window, + void KeyboardHook(FlutterCompView* window, int key, int scancode, int action, char32_t character) override; // |KeyboardHookHandler| - void TextHook(Win32FlutterWindow* window, + void TextHook(FlutterCompView* 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..23cf92d638af6 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 FlutterCompView; // 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(FlutterCompView* 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(FlutterCompView* window, const std::u16string& text) = 0; }; diff --git a/shell/platform/windows/platform_handler.cc b/shell/platform/windows/platform_handler.cc index c4b83130a785b..fff03fdab14ac 100644 --- a/shell/platform/windows/platform_handler.cc +++ b/shell/platform/windows/platform_handler.cc @@ -11,7 +11,7 @@ #include "flutter/shell/platform/common/cpp/json_method_codec.h" #include "flutter/shell/platform/windows/string_conversion.h" -#include "flutter/shell/platform/windows/win32_flutter_window.h" +#include "flutter/shell/platform/windows/flutter_comp_view.h" static constexpr char kChannelName[] = "flutter/platform"; diff --git a/shell/platform/windows/platform_handler.h b/shell/platform/windows/platform_handler.h index 8cb09a80666a7..3238b91a9c830 100644 --- a/shell/platform/windows/platform_handler.h +++ b/shell/platform/windows/platform_handler.h @@ -12,13 +12,13 @@ namespace flutter { -class Win32FlutterWindow; +class FlutterCompView; // Handler for internal system channels. class PlatformHandler { public: explicit PlatformHandler(flutter::BinaryMessenger* messenger, - Win32FlutterWindow* window); + FlutterCompView* 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_; + FlutterCompView* window_; }; } // namespace flutter diff --git a/shell/platform/windows/public/flutter_windows.h b/shell/platform/windows/public/flutter_windows.h index 633169a4cf4b1..ec6910d5a1bbf 100644 --- a/shell/platform/windows/public/flutter_windows.h +++ b/shell/platform/windows/public/flutter_windows.h @@ -22,6 +22,10 @@ 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; @@ -50,6 +54,19 @@ typedef struct { size_t switches_count; } FlutterDesktopEngineProperties; +// Creates a View with the given dimensions running a Flutter Application. +// +// This will set up and run an associated Flutter engine using the settings in +// |engine_properties|. +// +// Returns a null pointer in the event of an error. +FLUTTER_EXPORT FlutterDesktopViewControllerRef +V2FlutterDesktopCreateViewController( + int width, + int height, + const FlutterDesktopEngineProperties& engine_properties, + void* compositor); + // Creates a View with the given dimensions running a Flutter Application. // // This will set up and run an associated Flutter engine using the settings in diff --git a/shell/platform/windows/win32_task_runner.cc b/shell/platform/windows/task_runner.cc similarity index 87% rename from shell/platform/windows/win32_task_runner.cc rename to shell/platform/windows/task_runner.cc index e8d66b9fab6f1..a89470474f490 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, +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,7 +73,7 @@ Win32TaskRunner::TaskTimePoint Win32TaskRunner::TimePointFromFlutterTime( return now + std::chrono::nanoseconds(flutter_duration); } -void Win32TaskRunner::PostTask(FlutterTask flutter_task, +void TaskRunner::PostTask(FlutterTask flutter_task, uint64_t flutter_target_time_nanos) { static std::atomic_uint64_t sGlobalTaskOrder(0); diff --git a/shell/platform/windows/win32_task_runner.h b/shell/platform/windows/task_runner.h similarity index 90% rename from shell/platform/windows/win32_task_runner.h rename to shell/platform/windows/task_runner.h index 9bc45c33e9ab4..b361204324088 100644 --- a/shell/platform/windows/win32_task_runner.h +++ b/shell/platform/windows/task_runner.h @@ -21,13 +21,13 @@ 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, + 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 +59,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..95fc58b64eb36 --- /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 { + +FlutterCompViewTest::FlutterCompViewTest(int width, int height) + : FlutterCompView(width, height, nullptr){}; + +FlutterCompViewTest::~FlutterCompViewTest() = default; + +//void FlutterCompViewTest::OnFontChange() { +// on_font_change_called_ = true; +//} + +bool FlutterCompViewTest::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 51% rename from shell/platform/windows/testing/win32_flutter_window_test.h rename to shell/platform/windows/testing/flutter_compview_test.h index 6da56d9383a5b..42c18dd9da1dd 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_comp_view.h" namespace flutter { namespace testing { /// Test class for Win32FlutterWindow. -class Win32FlutterWindowTest : public Win32FlutterWindow { +class FlutterCompViewTest : public FlutterCompView { public: - Win32FlutterWindowTest(int width, int height); - virtual ~Win32FlutterWindowTest(); + FlutterCompViewTest(int width, int height); + virtual ~FlutterCompViewTest(); // Prevent copying. - Win32FlutterWindowTest(Win32FlutterWindowTest const&) = delete; - Win32FlutterWindowTest& operator=(Win32FlutterWindowTest const&) = delete; + FlutterCompViewTest(FlutterCompViewTest const&) = delete; + FlutterCompViewTest& operator=(FlutterCompViewTest 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..20789067e9bc9 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(FlutterCompView* 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(FlutterCompView* 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..3ae3c1882ad15 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 FlutterCompView; // Implements a text input plugin. // @@ -28,14 +28,14 @@ class TextInputPlugin : public KeyboardHookHandler { virtual ~TextInputPlugin(); // |KeyboardHookHandler| - void KeyboardHook(Win32FlutterWindow* window, + void KeyboardHook(FlutterCompView* window, int key, int scancode, int action, char32_t character) override; // |KeyboardHookHandler| - void TextHook(Win32FlutterWindow* window, + void TextHook(FlutterCompView* window, const std::u16string& text) override; private: 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..d1ef8d14780df --- /dev/null +++ b/shell/platform/windows/window_state_comp.h @@ -0,0 +1,72 @@ +// 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/text_input_plugin.h" +#include "flutter/shell/platform/windows/task_runner.h" + +namespace flutter { + struct FlutterCompView; +} + +// 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::FlutterCompView* window; +}; + +// 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_ From a2449ad80d3828c514eaa2e104a15abf5be8dc84 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sat, 2 May 2020 13:16:24 -0700 Subject: [PATCH 04/13] Prototype V2 API hooked up to Win32 runner --- DEPS | 1 + shell/platform/windows/BUILD.gn | 4 + .../platform/windows/angle_surface_manager.cc | 29 ++ .../platform/windows/angle_surface_manager.h | 7 + .../platform/windows/client_wrapper/BUILD.gn | 6 + .../client_wrapper/flutter_view_controller.cc | 94 +++- .../flutter_view_controller_unittests.cc | 20 +- .../include/flutter/flutter_view.h | 55 ++- .../include/flutter/flutter_view_controller.h | 23 +- .../flutter/win32_flutter_window_pub.h | 68 ++- .../include/flutter/win32_window_pub.h | 5 + .../testing/stub_flutter_windows_api.cc | 131 ++++- .../testing/stub_flutter_windows_api.h | 68 ++- .../win32_flutter_window_pub.cc | 453 ++++++------------ .../client_wrapper/win32_window_pub.cc | 2 + shell/platform/windows/flutter_comp_view.cc | 132 +++-- shell/platform/windows/flutter_comp_view.h | 56 ++- .../windows/flutter_compview_unittests.cc | 19 +- shell/platform/windows/flutter_windows.cc | 139 ++++-- shell/platform/windows/platform_handler.cc | 132 ++--- .../platform/windows/public/flutter_windows.h | 105 +++- .../windows/testing/flutter_compview_test.cc | 2 +- shell/platform/windows/window_state_comp.h | 2 + 23 files changed, 923 insertions(+), 630 deletions(-) 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/windows/BUILD.gn b/shell/platform/windows/BUILD.gn index 4b72d26ba7bed..a33cc8b7e630d 100644 --- a/shell/platform/windows/BUILD.gn +++ b/shell/platform/windows/BUILD.gn @@ -94,6 +94,8 @@ shared_library("flutter_windows") { ":flutter_windows_source", ] + libs = [ "windowsapp.lib" ] + public_configs = [ "//flutter:config" ] } @@ -120,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..bc6ad742db4cd 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,12 @@ 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 f27a1a2eef8ae..00b83f85e8033 100644 --- a/shell/platform/windows/client_wrapper/BUILD.gn +++ b/shell/platform/windows/client_wrapper/BUILD.gn @@ -50,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 @@ -76,6 +78,10 @@ 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", diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller.cc b/shell/platform/windows/client_wrapper/flutter_view_controller.cc index 8ba13f2e5dfd9..ba1cf1f99066a 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_controller.cc +++ b/shell/platform/windows/client_wrapper/flutter_view_controller.cc @@ -2,16 +2,48 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include + #include "include/flutter/flutter_view_controller.h" +#include +#include +#include +#include + + +using namespace winrt; +using namespace Windows::UI; +using namespace Windows::UI::Composition; +using namespace Windows::UI::Composition::Desktop; #include #include namespace flutter { +auto CreateDispatcherQueueController() { + namespace abi = ABI::Windows::System; + + DispatcherQueueOptions options{sizeof(DispatcherQueueOptions), + DQTYPE_THREAD_CURRENT, DQTAT_COM_STA}; + + Windows::System::DispatcherQueueController controller{nullptr}; + check_hresult(CreateDispatcherQueueController( + options, reinterpret_cast( + put_abi(controller)))); + return controller; +} + +// Compositor overload FlutterViewController::FlutterViewController(int width, int height, - const DartProject& project) { + 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(), @@ -24,46 +56,58 @@ FlutterViewController::FlutterViewController(int width, 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); + + child_window_ = + std::make_unique(width, height, compositor_); + + controller_ = V2FlutterDesktopCreateViewControllerComposition( + width, height, properties, + static_cast(winrt::get_abi(compositor_)),child_window_.get()); if (!controller_) { std::cerr << "Failed to create view controller." << std::endl; return; - }*/ - //view_ = std::make_unique(FlutterDesktopGetView(controller_)); - child_window_ = std::make_unique(width, height); -} - -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; } + view_ = std::make_unique(FlutterDesktopGetView(controller_)); + + child_window_->SetViewComposition(view_.get()); +} - std::vector engine_arguments; +// Window overload +FlutterViewController::FlutterViewController(int width, + int height, + const DartProject& project, + HWND parentwindow) { + std::vector switches; std::transform( - arguments.begin(), arguments.end(), std::back_inserter(engine_arguments), + project.engine_switches().begin(), project.engine_switches().end(), + std::back_inserter(switches), [](const std::string& arg) -> const char* { return arg.c_str(); }); - size_t arg_count = engine_arguments.size(); + size_t switch_count = switches.size(); - controller_ = FlutterDesktopCreateViewControllerLegacy( - width, height, assets_path.c_str(), icu_data_path.c_str(), - arg_count > 0 ? &engine_arguments[0] : nullptr, arg_count); + 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); + + controller_ = V2CreateViewControllerWindow( + width, height, properties, + child_window_.get(),child_window_->GetWindowHandle()); if (!controller_) { std::cerr << "Failed to create view controller." << std::endl; return; } - //view_ = std::make_unique(FlutterDesktopGetView(controller_)); - child_window_ = std::make_unique(width,height); + view_ = std::make_unique(FlutterDesktopGetView(controller_)); + child_window_->SetView(view_.get()); } FlutterViewController::~FlutterViewController() { - /*if (controller_) { + if (controller_) { FlutterDesktopDestroyViewController(controller_); - }*/ + } } std::chrono::nanoseconds FlutterViewController::ProcessMessages() { diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc b/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc index ec1b7fb561eae..f19eca5b20e0a 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc +++ b/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc @@ -15,32 +15,24 @@ 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, + void* hostwindow, + HWND windowrendertarget) 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) { 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); } + { FlutterViewController controller(100, 100, project, static_cast(nullptr)); } } TEST(FlutterViewControllerTest, GetView) { @@ -48,7 +40,7 @@ TEST(FlutterViewControllerTest, GetView) { testing::ScopedStubFlutterWindowsApi scoped_api_stub( std::make_unique()); auto test_api = static_cast(scoped_api_stub.stub()); - FlutterViewController controller(100, 100, project); + FlutterViewController controller(100, 100, project, static_cast(nullptr)); EXPECT_NE(controller.view(), nullptr); } diff --git a/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h b/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h index 18c908e977deb..e332cbd8b6360 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h +++ b/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h @@ -5,14 +5,21 @@ #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 FlutterView { public: - explicit FlutterView(FlutterDesktopViewRef view) : view_(view) {} + explicit FlutterView( + FlutterDesktopViewRef view + ) + : view_(view) { + } virtual ~FlutterView() = default; @@ -21,7 +28,51 @@ class FlutterView { FlutterView& operator=(FlutterView const&) = delete; // Returns the backing HWND for the view. - HWND GetNativeWindow() { return FlutterDesktopViewGetHWND(view_); } + HWND GetNativeWindow() { + void* windowptr = V2FlutterDesktopGetExternalWindow(view_); + Win32FlutterWindowPub* ptr = static_cast(windowptr); + return ptr->GetWindowHandle(); + } + + void* GetVisual() { + return V2FlutterDesktopViewGetVisual(view_); + } + + 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. diff --git a/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h b/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h index 5a90849b9af65..952dddd08fbcb 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h +++ b/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h @@ -6,6 +6,8 @@ #define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_CONTROLLER_H_ #include +#include +#include #include #include @@ -32,14 +34,14 @@ class FlutterViewController : public PluginRegistry { // |dart_project| will be used to configure the engine backing this view. explicit FlutterViewController(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 FlutterViewController(int width, int height, - const std::string& assets_path, - const std::vector& arguments); + const DartProject& project, + HWND parentwindow); virtual ~FlutterViewController(); @@ -47,7 +49,7 @@ class FlutterViewController : public PluginRegistry { FlutterViewController(FlutterViewController const&) = delete; FlutterViewController& operator=(FlutterViewController const&) = delete; - FlutterView* view() { return nullptr; /*return view_.get();*/ } + FlutterView* 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). @@ -66,10 +68,15 @@ class FlutterViewController : public PluginRegistry { FlutterDesktopViewControllerRef controller_ = nullptr; //// The owned FlutterView. - //std::unique_ptr view_; + std::unique_ptr view_; // The owned Flutter child window std::unique_ptr child_window_; + + winrt::Windows::UI::Composition::Compositor compositor_{nullptr}; + + 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 index 5e8d8a21bb5b2..dbdc7d36811b0 100644 --- 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 @@ -7,25 +7,35 @@ #include +#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" +#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 FlutterView; + // 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 @@ -33,13 +43,25 @@ namespace flutter { class Win32FlutterWindowPub : public Win32WindowPub { public: // Create flutter Window for use as child window - Win32FlutterWindowPub(int width, int height); + 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(); /*static FlutterDesktopViewControllerRef CreateWin32FlutterWindow(int width, int height);*/ + void SetView(FlutterView* view); + + void SetViewComposition(FlutterView* view); + // |Win32WindowPub| void OnDpiScale(unsigned int dpi) override; @@ -70,6 +92,10 @@ class Win32FlutterWindowPub : public Win32WindowPub { // |Win32WindowPub| void OnFontChange() override; + winrt::Windows::UI::Composition::Compositor const& compositor_; + + winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget target_{nullptr}; + //// Configures the window instance with an instance of a running Flutter engine //// returning a configured FlutterDesktopWindowControllerRef. //void SetState(FLUTTER_API_SYMBOL(FlutterEngine) state); @@ -92,27 +118,28 @@ class Win32FlutterWindowPub : public Win32WindowPub { // Sends a window metrics update to the Flutter engine using current window // dimensions in physical - // void SendWindowMetrics(); + void SendWindowMetrics(); - //private: + private: + FlutterView* 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); + void SendPointerMove(double x, double y); // // Reports mouse press to Flutter engine. - // void SendPointerDown(double x, double y); + void SendPointerDown(double x, double y, uint64_t btn); // // Reports mouse release to Flutter engine. - // void SendPointerUp(double x, double y); + 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(); + void SendPointerLeave(); // // Reports text input to Flutter engine. // void SendText(const std::u16string& text); @@ -120,11 +147,8 @@ class Win32FlutterWindowPub : public Win32WindowPub { // // 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); + void GetEventLocationFromCursorPosition(POINT& location); // // Set's |event_data|'s phase to either kMove or kHover depending on the // // current diff --git a/shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h b/shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h index 48a6c1b13904c..4fec59bd34301 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h +++ b/shell/platform/windows/client_wrapper/include/flutter/win32_window_pub.h @@ -141,6 +141,8 @@ class Win32WindowPub { // Updates the currently pressed buttons. void SetMouseButtons(uint64_t buttons) { mouse_state_.buttons = buttons; } + + private: // Release OS resources asociated with window. void Destroy(); @@ -164,6 +166,9 @@ class Win32WindowPub { // 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_; 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..81d8fbe026c70 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, + void* hostwindow, + HWND windowrendertarget) { if (s_stub_implementation) { - return s_stub_implementation->CreateViewController(width, height, - engine_properties); + return s_stub_implementation->V2CreateViewControllerWindow(width, height, + engine_properties, hostwindow, windowrendertarget); } 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 V2FlutterDesktopCreateViewControllerComposition( + int width, + int height, + const FlutterDesktopEngineProperties& engine_properties, + void* compositor, + void* hostwindow) { 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 + ->V2FlutterDesktopCreateViewControllerComposition(width, height, + engine_properties, compositor, hostwindow); } 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* V2FlutterDesktopGetExternalWindow(FlutterDesktopViewRef view) { + if (s_stub_implementation) { + return s_stub_implementation->V2FlutterDesktopGetExternalWindow(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..5aeddb5585807 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 @@ -30,13 +30,73 @@ 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, + void* hostwindow, + HWND windowrendertarget) { return nullptr; } + virtual FlutterDesktopViewControllerRef + V2FlutterDesktopCreateViewControllerComposition( + int width, + int height, + const FlutterDesktopEngineProperties& engine_properties, + void* compositor, + void* hostwindow) { + 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 +112,10 @@ class StubFlutterWindowsApi { return nullptr; } + virtual void* V2FlutterDesktopGetExternalWindow(FlutterDesktopViewRef view) { + return nullptr; + } + // Called for FlutterDesktopShutDownEngine. virtual bool ShutDownEngine() { return true; } }; diff --git a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc index 66872cbd3b08a..f603c1656cfc0 100644 --- a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc +++ b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc @@ -1,365 +1,188 @@ #include "include/flutter/win32_flutter_window_pub.h" +// TODO move these to headers +#include +#include +#include +#include +#include + #include +#include "include/flutter/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; + + auto interop = compositor.as(); + winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget target{nullptr}; + winrt::check_hresult(interop->CreateDesktopWindowTarget( + window, true, + reinterpret_cast(winrt::put_abi(target)))); + return target; +} + // 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) { - /*surface_manager = std::make_unique(); - Win32Window::InitializeChild("FLUTTERVIEW", width, height);*/ +Win32FlutterWindowPub::Win32FlutterWindowPub( + int width, + int height, + winrt::Windows::UI::Composition::Compositor const& compositor) + : compositor_(compositor), flutter_view_(nullptr) { + Win32WindowPub::InitializeChild("FLUTTERVIEW", width, height); +} + +Win32FlutterWindowPub::Win32FlutterWindowPub(int width, int height) + : compositor_(nullptr), flutter_view_(nullptr) { + Win32WindowPub::InitializeChild("FLUTTERVIEW", width, height); +} + +void Win32FlutterWindowPub::SetView(FlutterView* view) { + flutter_view_ = view; +} + +// Called after view has been created. Binds the child HWND represented by this +// class to a composition visual that is passed to Flutter Engine +void Win32FlutterWindowPub::SetViewComposition(FlutterView* view) { + // Create Window target, set visual returned from the engine as the root + target_ = + CreateDesktopWindowTarget(compositor_, Win32WindowPub::GetWindowHandle()); + + void* pointer = view->GetVisual(); //TODO: change this to push + + winrt::com_ptr rawAbi = nullptr; + + winrt::Windows::UI::Composition::ISpriteVisual abiFlutterVisual = nullptr; + + winrt::copy_from_abi(abiFlutterVisual, pointer); + + winrt::Windows::UI::Composition::Visual flutterVisual = nullptr; + abiFlutterVisual.as(flutterVisual); + + target_.Root(flutterVisual); } -Win32FlutterWindowPub::~Win32FlutterWindowPub() { - /*DestroyRenderSurface(); - if (plugin_registrar_ && plugin_registrar_->destruction_handler) { - plugin_registrar_->destruction_handler(plugin_registrar_.get()); - }*/ +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; } -//FlutterDesktopViewControllerRef Win32FlutterWindowPub::CreateWin32FlutterWindowPub( -// 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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::OnDpiScale(unsigned int dpi){}; +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) { - /*SendWindowMetrics();*/ + if (flutter_view_ != nullptr) { + flutter_view_->SendWindowMetrics( + GetCurrentWidth(), GetCurrentHeight(), + static_cast(GetCurrentDPI()) / base_dpi); + } } void Win32FlutterWindowPub::OnPointerMove(double x, double y) { - /*if (process_events_) { SendPointerMove(x, y); - }*/ } void Win32FlutterWindowPub::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); + SendPointerDown(x, y, flutter_button); } - }*/ } void Win32FlutterWindowPub::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); - } - }*/ + uint64_t flutter_button = ConvertWinButtonToFlutterButton(button); + if (flutter_button != 0) { + SendPointerUp(x, y, flutter_button); + } } void Win32FlutterWindowPub::OnPointerLeave() { - /* if (process_events_) { - SendPointerLeave(); - }*/ + SendPointerLeave(); } void Win32FlutterWindowPub::OnText(const std::u16string& text) { - /* if (process_events_) { - SendText(text); - }*/ + flutter_view_->SendText(text.c_str(), text.length()); } void Win32FlutterWindowPub::OnKey(int key, - int scancode, - int action, - char32_t character) { - /*if (process_events_) { - SendKey(key, scancode, action, character); - }*/ + int scancode, + int action, + char32_t character) { + flutter_view_->SendKey(key, scancode, action, character); } void Win32FlutterWindowPub::OnScroll(double delta_x, double delta_y) { - /*if (process_events_) { - SendScroll(delta_x, delta_y); - }*/ + POINT position; + GetEventLocationFromCursorPosition(position); + flutter_view_->SendScroll(position.x, position.y, delta_x, delta_y); } void Win32FlutterWindowPub::OnFontChange() { - /*if (engine_ == nullptr) { - return; - } - FlutterEngineReloadSystemFonts(engine_);*/ + flutter_view_->SendFontChange(); } // Sends new size information to FlutterEngine. -//void Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::SendPointerMove(double x, double y) { -// FlutterPointerEvent event = {}; -// event.x = x; -// event.y = y; -// SetEventPhaseFromCursorButtonState(&event); -// SendPointerEventWithData(event); -//} - -//void Win32FlutterWindowPub::SendPointerDown(double x, double y) { -// FlutterPointerEvent event = {}; -// SetEventPhaseFromCursorButtonState(&event); -// event.x = x; -// event.y = y; -// SendPointerEventWithData(event); -// SetMouseFlutterStateDown(true); -//} - -//void Win32FlutterWindowPub::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 Win32FlutterWindowPub::SendPointerLeave() { -// FlutterPointerEvent event = {}; -// event.phase = FlutterPointerPhase::kRemove; -// SendPointerEventWithData(event); -//} - -//void Win32FlutterWindowPub::SendText(const std::u16string& text) { -// for (const auto& handler : keyboard_hook_handlers_) { -// handler->TextHook(this, text); -// } -//} - -//void Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::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 Win32FlutterWindowPub::MakeCurrent() { -// return surface_manager->MakeCurrent(render_surface); -//} -// -//bool Win32FlutterWindowPub::MakeResourceCurrent() { -// return surface_manager->MakeResourceCurrent(); -//} -// -//bool Win32FlutterWindowPub::ClearContext() { -// return surface_manager->MakeCurrent(nullptr); -//} -// -//bool Win32FlutterWindowPub::SwapBuffers() { -// return surface_manager->SwapBuffers(render_surface); -//} -// -//void Win32FlutterWindowPub::CreateRenderSurface() { -// if (surface_manager && render_surface == EGL_NO_SURFACE) { -// render_surface = surface_manager->CreateSurface(GetWindowHandle()); -// } -//} -// -//void Win32FlutterWindowPub::DestroyRenderSurface() { -// if (surface_manager) { -// surface_manager->DestroySurface(render_surface); -// } -// render_surface = EGL_NO_SURFACE; -//} +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/client_wrapper/win32_window_pub.cc b/shell/platform/windows/client_wrapper/win32_window_pub.cc index 5c661be209652..d82e2c1bd65ae 100644 --- a/shell/platform/windows/client_wrapper/win32_window_pub.cc +++ b/shell/platform/windows/client_wrapper/win32_window_pub.cc @@ -121,6 +121,7 @@ Win32WindowPub::MessageHandler(HWND hwnd, if (window != nullptr) { switch (message) { case kWmDpiChangedBeforeParent: + // TODO may need add after parent current_dpi_ = pubdpi::GetDpiForHWND(window_handle_); window->OnDpiScale(current_dpi_); return 0; @@ -290,6 +291,7 @@ HWND Win32WindowPub::GetWindowHandle() { } void Win32WindowPub::Destroy() { + //TODO.. unparent? if (window_handle_) { DestroyWindow(window_handle_); window_handle_ = nullptr; diff --git a/shell/platform/windows/flutter_comp_view.cc b/shell/platform/windows/flutter_comp_view.cc index 13264be6aa266..33c8493aacb6e 100644 --- a/shell/platform/windows/flutter_comp_view.cc +++ b/shell/platform/windows/flutter_comp_view.cc @@ -8,20 +8,38 @@ namespace flutter { // constant for machines running at 100% scaling. constexpr int base_dpi = 96; -FlutterCompView::FlutterCompView(int width, int height, void* compositor) { +FlutterCompView::FlutterCompView(int width, int height) { surface_manager = std::make_unique(); - compositor_.Attach(static_cast(compositor)); - - //TODO: use C++/Winrt copy_from_abi once C++.Winrt is supportrf - //winrt::copy_from_abi(compositor_, compositor); - width_ = width; height_ = height; } FlutterCompView::~FlutterCompView() { DestroyRenderSurface(); + if (plugin_registrar_ && plugin_registrar_->destruction_handler) { + plugin_registrar_->destruction_handler(plugin_registrar_.get()); + } +} + +FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompViewHwnd( + 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 FlutterCompView::CreateFlutterCompView( @@ -29,7 +47,15 @@ FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompView( const int height, void* compositor) { auto state = std::make_unique(); - state->view = std::make_unique(width, height, compositor); + state->view = std::make_unique(width, height); + + if (compositor != nullptr) { + state->view->compositor_.Attach( + static_cast(compositor)); + } + + // TODO: use C++/Winrt copy_from_abi once C++.Winrt is supportrf + // winrt::copy_from_abi(compositor_, compositor); // a window wrapper for the state block, distinct from the // window_wrapper handed to plugin_registrar. @@ -38,7 +64,7 @@ FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompView( return state.release(); } -void FlutterCompView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng) { +void FlutterCompView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng, void* externalwindow) { engine_ = eng; auto messenger = std::make_unique(); @@ -49,6 +75,7 @@ void FlutterCompView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng) { window_wrapper_ = std::make_unique(); window_wrapper_->window = this; + window_wrapper_->externalwindow = externalwindow; plugin_registrar_ = std::make_unique(); plugin_registrar_->messenger = std::move(messenger); @@ -67,11 +94,6 @@ void FlutterCompView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng) { internal_plugin_messenger, this); process_events_ = true; - - //HACK for UWP - if (compositor_ != nullptr) { - SendWindowMetrics(width_, height_); - } } FlutterDesktopPluginRegistrarRef FlutterCompView::GetRegistrar() { @@ -90,27 +112,6 @@ static FlutterDesktopMessage ConvertToDesktopMessage( 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 FlutterCompView::HandlePlatformMessage( @@ -139,7 +140,6 @@ void FlutterCompView::OnPointerDown(double x, double y, FlutterPointerMouseButtons flutter_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); @@ -152,7 +152,6 @@ void FlutterCompView::OnPointerUp(double x, double y, FlutterPointerMouseButtons flutter_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); @@ -167,9 +166,9 @@ void FlutterCompView::OnPointerLeave() { } } -void FlutterCompView::OnChar(char32_t code_point) { +void FlutterCompView::OnText(const std::u16string& text) { if (process_events_) { - SendChar(code_point); + SendText(text); } } @@ -182,9 +181,9 @@ void FlutterCompView::OnKey(int key, } } -void FlutterCompView::OnScroll(double delta_x, double delta_y) { +void FlutterCompView::OnScroll(double x, double y, double delta_x, double delta_y) { if (process_events_) { - SendScroll(delta_x, delta_y); + SendScroll(x, y, delta_x, delta_y); } } @@ -196,34 +195,21 @@ void FlutterCompView::OnFontChange() { } // Sends new size information to FlutterEngine. -void FlutterCompView::SendWindowMetrics(size_t width, size_t height) { +void FlutterCompView::SendWindowMetrics(size_t width, size_t height, double dpiScale) { if (engine_ == nullptr) { return; } FlutterWindowMetricsEvent event = {}; event.struct_size = sizeof(event); - //event.width = 320; // GetCurrentWidth(); TODO - //event.height = 240; //GetCurrentHeight(); TODO - event.width = width; // GetCurrentWidth(); TODO - event.height = height; // GetCurrentHeight(); TODO - event.pixel_ratio = 1.2; // static_cast(GetCurrentDPI()) / base_dpi; TODO + event.width = width; + event.height = height; + event.pixel_ratio = dpiScale; auto result = FlutterEngineSendWindowMetricsEvent(engine_, &event); - - SizeHostVisual(width, height); -} - -// Updates |event_data| with the current location of the mouse cursor. -void FlutterCompView::SetEventLocationFromCursorPosition( - FlutterPointerEvent* event_data) { - //POINT point; - //GetCursorPos(&point); - - //ScreenToClient(GetWindowHandle(), &point); TODO - - //event_data->x = point.x; - //event_data->y = point.y; + if (flutter_host_ != nullptr) { + SizeHostVisual(width, height); + } } // Set's |event_data|'s phase to either kMove or kHover depending on the current @@ -275,9 +261,9 @@ void FlutterCompView::SendPointerLeave() { SendPointerEventWithData(event); } -void FlutterCompView::SendChar(char32_t code_point) { +void FlutterCompView::SendText(const std::u16string& code_point) { for (const auto& handler : keyboard_hook_handlers_) { - handler->CharHook(this, code_point); + handler->TextHook(this, code_point); } } @@ -287,14 +273,15 @@ void FlutterCompView::SendKey(int key, int scancode, int action, int mods) { } } -void FlutterCompView::SendScroll(double delta_x, double delta_y) { +void FlutterCompView::SendScroll(double x, double y, 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.x = x; + event.y = y; event.scroll_delta_x = delta_x * kScrollOffsetMultiplier; event.scroll_delta_y = delta_y * kScrollOffsetMultiplier; SendPointerEventWithData(event); @@ -380,6 +367,20 @@ void FlutterCompView::SizeHostVisual(size_t width, size_t height) { (SUCCEEDED(hr)); } +void FlutterCompView::CreateRenderSurface() { + if (compositor_ != nullptr) { + CreateRenderSurfaceUWP(); + } else { + CreateRenderSurfaceHWND(); + } +} + +void FlutterCompView::CreateRenderSurfaceHWND() { + //TODO: seems like we shouldn't get this from the window_wrapper as that is mainly used for plugins + render_surface = + surface_manager->CreateSurface(static_cast(window_rendertarget_)); +} + // TODO: move this into visual_flutter_host class when that exists // TODO: can we use c++/winrt in here (requires newer windows SDK and c++17 // support in compiler toolchain) @@ -403,9 +404,6 @@ void FlutterCompView::CreateRenderSurfaceUWP() { hr = visualPtr->put_Size({static_cast(width_), static_cast(height_)}); (SUCCEEDED(hr)); - hr = visualPtr->put_Offset({40, 20}); - (SUCCEEDED(hr)); - render_surface = surface_manager->CreateSurface(flutter_host_.Get()); } } diff --git a/shell/platform/windows/flutter_comp_view.h b/shell/platform/windows/flutter_comp_view.h index 03352d21ad6d5..fad886dd48b06 100644 --- a/shell/platform/windows/flutter_comp_view.h +++ b/shell/platform/windows/flutter_comp_view.h @@ -20,8 +20,6 @@ #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 "flutter/shell/platform/windows/window_state_comp.h" - #include #include #include @@ -29,9 +27,11 @@ #include #include +#include "flutter/shell/platform/windows/window_state_comp.h" + namespace flutter { - class RoHelper { +class RoHelper { public: RoHelper(); ~RoHelper(); @@ -110,18 +110,21 @@ struct MouseState { class FlutterCompView { public: // Create flutter Window for use as child window - FlutterCompView(int width, int height, void* compositor); + FlutterCompView(int width, int height); ~FlutterCompView(); - static FlutterDesktopViewControllerRef CreateFlutterCompView( - int width, - int height, - void* compositor); + static FlutterDesktopViewControllerRef + CreateFlutterCompView(int width, int height, void* compositor); + + static FlutterDesktopViewControllerRef CreateFlutterCompViewHwnd(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 SetState(FLUTTER_API_SYMBOL(FlutterEngine) state, void* externalwindow); // Returns the currently configured Plugin Registrar. FlutterDesktopPluginRegistrarRef GetRegistrar(); @@ -130,8 +133,7 @@ class FlutterCompView { // messages. void HandlePlatformMessage(const FlutterPlatformMessage*); - // Create a surface for Flutter engine to render into. - void CreateRenderSurfaceUWP(); + void CreateRenderSurface(); // Destroy current rendering surface if one has been allocated. void DestroyRenderSurface(); @@ -144,7 +146,7 @@ class FlutterCompView { // Sends a window metrics update to the Flutter engine using current window // dimensions in physical - void SendWindowMetrics(size_t width, size_t height); + void SendWindowMetrics(size_t width, size_t height, double dpiscale); Microsoft::WRL::ComPtr GetFlutterHost(); @@ -161,24 +163,28 @@ class FlutterCompView { // TODO void OnPointerLeave(); - // TODO - void OnChar(char32_t code_point); + // TODO + void OnText(const std::u16string&); // TODO void OnKey(int key, int scancode, int action, char32_t character); // TODO - void OnScroll(double delta_x, double delta_y); + 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(); -// Reports a mouse movement to Flutter engine. + void CreateRenderSurfaceHWND(); + + // Reports a mouse movement to Flutter engine. void SendPointerMove(double x, double y); - // Reports mouse press to Flutter engine. + // Reports mouse press to Flutter engine. void SendPointerDown(double x, double y); // Reports mouse release to Flutter engine. @@ -192,16 +198,13 @@ class FlutterCompView { void SendPointerLeave(); // Reports a keyboard character to Flutter engine. - void SendChar(char32_t code_point); + 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 delta_x, double delta_y); - - // Updates |event_data| with the current location of the mouse cursor. - void SetEventLocationFromCursorPosition(FlutterPointerEvent* event_data); + 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 @@ -234,7 +237,6 @@ class FlutterCompView { // 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); @@ -254,7 +256,7 @@ class FlutterCompView { // been added since it was last removed). bool pointer_currently_added_ = false; - // Set to true to be notified when the mouse leaves the window. + // 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. @@ -285,12 +287,14 @@ class FlutterCompView { // flag indicating if the message loop should be running bool messageloop_running_ = false; - Microsoft::WRL::ComPtr compositor_ {nullptr}; + Microsoft::WRL::ComPtr + compositor_{nullptr}; + + HWND window_rendertarget_; Microsoft::WRL::ComPtr flutter_host_{nullptr}; - int width_ = 0, height_ = 0; }; diff --git a/shell/platform/windows/flutter_compview_unittests.cc b/shell/platform/windows/flutter_compview_unittests.cc index 671a4adb9ea8a..0fcdddf3153ca 100644 --- a/shell/platform/windows/flutter_compview_unittests.cc +++ b/shell/platform/windows/flutter_compview_unittests.cc @@ -4,18 +4,19 @@ namespace flutter { namespace testing { -TEST(Win32FlutterWindowTest, CreateDestroy) { - Win32FlutterWindowTest window(800, 600); +TEST(FlutterCompViewTest, CreateDestroy) { + FlutterCompViewTest 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()); -} +//TODO MOVE to wrapper +//TEST(FlutterCompViewTest, CanFontChange) { +// FlutterCompViewTest 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 cb49ce2f84b8a..daa3794ceaf79 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -131,7 +131,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; @@ -148,62 +148,101 @@ static std::unique_ptr RunFlutterEngine( return state; } -FlutterDesktopViewControllerRef FlutterDesktopCreateViewController( +V2FlutterDesktopViewControllerRef +V2FlutterDesktopCreateViewControllerComposition( int width, int height, - const FlutterDesktopEngineProperties& engine_properties) { - FlutterDesktopViewControllerRef state = - flutter::Win32FlutterWindow::CreateWin32FlutterWindow(width, height); + const FlutterDesktopEngineProperties& engine_properties, + void* compositor, + void* externalWindow) { + V2FlutterDesktopViewControllerRef state = + flutter::FlutterCompView::CreateFlutterCompView(width, height, + compositor); 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; } -V2FlutterDesktopViewControllerRef V2FlutterDesktopCreateViewController( +V2FlutterDesktopViewControllerRef V2CreateViewControllerWindow( int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* compositor) { + void* externalWindow, + HWND windowrendertarget) { V2FlutterDesktopViewControllerRef state = - flutter::FlutterCompView::CreateFlutterCompView(width, height, - compositor); + flutter::FlutterCompView::CreateFlutterCompViewHwnd(width, height, externalWindow, static_cast(windowrendertarget)); 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); +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(); +} + +//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); +//} + uint64_t FlutterDesktopProcessMessages( FlutterDesktopViewControllerRef controller) { return controller->engine_state->task_runner->ProcessTasks().count(); @@ -230,16 +269,46 @@ FlutterDesktopViewRef FlutterDesktopGetView( return controller->view_wrapper.get(); } -HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view) { - return view->window->GetWindowHandle(); +// TODO return something more strongly typed +void* V2FlutterDesktopViewGetVisual(FlutterDesktopViewRef view) { + return (void*)view->window->GetFlutterHost().Get(); +} + +// TODO return something more strongly typed +void* V2FlutterDesktopGetExternalWindow(FlutterDesktopViewRef view) { + return (void*)view->externalwindow; +} + +// TODO +void V2FlutterDesktopSendScroll(FlutterDesktopViewRef view, + double x, + double y, + double delta_x, + double delta_y) { + view->window->OnScroll(x, y, delta_x, delta_y); +} + +// TODO +void V2FlutterDesktopSendFontChange(FlutterDesktopViewRef view) { + view->window->OnFontChange(); } -UINT FlutterDesktopGetDpiForHWND(HWND hwnd) { - return flutter::GetDpiForHWND(hwnd); +// 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); } -UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor) { - return flutter::GetDpiForMonitor(monitor); +// TODO +void V2FlutterDesktopSendKey(FlutterDesktopViewRef view, + int key, + int scancode, + int action, + char32_t character) { + view->window->OnKey(key, scancode, action, character); } void FlutterDesktopResyncOutputStreams() { diff --git a/shell/platform/windows/platform_handler.cc b/shell/platform/windows/platform_handler.cc index fff03fdab14ac..898424b2c101f 100644 --- a/shell/platform/windows/platform_handler.cc +++ b/shell/platform/windows/platform_handler.cc @@ -198,7 +198,7 @@ bool ScopedClipboard::SetString(const std::wstring string) { } // namespace PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger, - Win32FlutterWindow* window) + FlutterCompView* window) : channel_(std::make_unique>( messenger, kChannelName, @@ -215,71 +215,75 @@ 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(); - } + 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/public/flutter_windows.h b/shell/platform/windows/public/flutter_windows.h index ec6910d5a1bbf..f24a7efde7e1a 100644 --- a/shell/platform/windows/public/flutter_windows.h +++ b/shell/platform/windows/public/flutter_windows.h @@ -61,11 +61,12 @@ typedef struct { // // Returns a null pointer in the event of an error. FLUTTER_EXPORT FlutterDesktopViewControllerRef -V2FlutterDesktopCreateViewController( +V2FlutterDesktopCreateViewControllerComposition( int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* compositor); + void* compositor, //TODO: typedef + void* hostwindow); //TODO: typedef // Creates a View with the given dimensions running a Flutter Application. // @@ -74,19 +75,87 @@ V2FlutterDesktopCreateViewController( // // Returns a null pointer in the event of an error. FLUTTER_EXPORT FlutterDesktopViewControllerRef -FlutterDesktopCreateViewController( +V2CreateViewControllerWindow( int width, int height, - const FlutterDesktopEngineProperties& engine_properties); + const FlutterDesktopEngineProperties& engine_properties, + void* hostwindow, + HWND windowrendertarget); //TODO: typedef -// DEPRECATED. Will be removed soon; switch to the version above. -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); +// Return backing HWND for manipulation in host application. +FLUTTER_EXPORT +void* V2FlutterDesktopViewGetVisual(FlutterDesktopViewRef view); + +// Return backing HWND for manipulation in host application. +FLUTTER_EXPORT +void* V2FlutterDesktopGetExternalWindow(FlutterDesktopViewRef view); + +//TODO +FLUTTER_EXPORT void V2FlutterDesktopSendWindowMetrics(FlutterDesktopViewRef view, + size_t width, + size_t height, + double dpiScale); + +FLUTTER_EXPORT void V2FlutterDesktopSendPointerMove(FlutterDesktopViewRef view, + double x, + double y); + +FLUTTER_EXPORT void V2FlutterDesktopSendPointerDown( + FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn); // TODO: can / should this be a FlutterPointerMouseButtons + +FLUTTER_EXPORT void V2FlutterDesktopSendPointerUp(FlutterDesktopViewRef view, + double x, + double y, + uint64_t btn); //TODO typedef per above + +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); + + +// Creates a View with the given dimensions running a Flutter Application. +// +// This will set up and run an associated Flutter engine using the settings in +// |engine_properties|. +// +// Returns a null pointer in the event of an error. +//FLUTTER_EXPORT FlutterDesktopViewControllerRef +//FlutterDesktopCreateViewController( +// int width, +// int height, +// const FlutterDesktopEngineProperties& engine_properties); + +//// DEPRECATED. Will be removed soon; switch to the version above. +//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); // Shuts down the engine instance associated with |controller|, and cleans up // associated state. @@ -115,18 +184,6 @@ 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). diff --git a/shell/platform/windows/testing/flutter_compview_test.cc b/shell/platform/windows/testing/flutter_compview_test.cc index 95fc58b64eb36..d80418c3c12c8 100644 --- a/shell/platform/windows/testing/flutter_compview_test.cc +++ b/shell/platform/windows/testing/flutter_compview_test.cc @@ -4,7 +4,7 @@ namespace flutter { namespace testing { FlutterCompViewTest::FlutterCompViewTest(int width, int height) - : FlutterCompView(width, height, nullptr){}; + : FlutterCompView(width, height){}; FlutterCompViewTest::~FlutterCompViewTest() = default; diff --git a/shell/platform/windows/window_state_comp.h b/shell/platform/windows/window_state_comp.h index d1ef8d14780df..4007ed96de904 100644 --- a/shell/platform/windows/window_state_comp.h +++ b/shell/platform/windows/window_state_comp.h @@ -37,6 +37,8 @@ struct FlutterDesktopViewControllerState { struct FlutterDesktopView { // The window that (indirectly) owns this state object. flutter::FlutterCompView* window; + + void* externalwindow; }; // Struct for storing state of a Flutter engine instance. From b5488ef65c58a65fd7353bb3a80b2cb412540fd6 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 May 2020 04:39:37 -0700 Subject: [PATCH 05/13] Partially reinstigate compositor integration in win32_flutter_window_pub --- .../flutter/win32_flutter_window_pub.h | 79 +------------------ .../win32_flutter_window_pub.cc | 17 ++-- 2 files changed, 11 insertions(+), 85 deletions(-) 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 index dbdc7d36811b0..109e64bb819b6 100644 --- 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 @@ -12,8 +12,9 @@ #include #include -#include +//#include #include +#include #include #include @@ -92,30 +93,10 @@ class Win32FlutterWindowPub : public Win32WindowPub { // |Win32WindowPub| void OnFontChange() override; - winrt::Windows::UI::Composition::Compositor const& compositor_; + winrt::Windows::UI::Composition::Compositor compositor_; winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget target_{nullptr}; - //// 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(); @@ -141,62 +122,8 @@ class Win32FlutterWindowPub : public Win32WindowPub { // // 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); - // // Updates |event_data| with the current location of the mouse cursor. void GetEventLocationFromCursorPosition(POINT& location); - - // // 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 diff --git a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc index f603c1656cfc0..c5d83c6863a6c 100644 --- a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc +++ b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc @@ -1,12 +1,5 @@ #include "include/flutter/win32_flutter_window_pub.h" -// TODO move these to headers -#include -#include -#include -#include -#include - #include #include "include/flutter/flutter_view.h" @@ -19,12 +12,18 @@ CreateDesktopWindowTarget( HWND window) { namespace abi = ABI::Windows::UI::Composition::Desktop; - auto interop = compositor.as(); + // 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 target;*/ + return nullptr; } // The Windows DPI system is based on this From 7f969900bdd9bd1a8daf8f4bcd11421edeec6d27 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 May 2020 06:25:55 -0700 Subject: [PATCH 06/13] Switch compositor API to being push based. --- .../client_wrapper/flutter_view_controller.cc | 18 ++---- .../include/flutter/flutter_view.h | 4 -- .../flutter/win32_flutter_window_pub.h | 8 +-- .../win32_flutter_window_pub.cc | 28 +++------ shell/platform/windows/flutter_comp_view.cc | 59 +++++++------------ shell/platform/windows/flutter_comp_view.h | 30 ++++++---- shell/platform/windows/flutter_windows.cc | 18 +++--- .../platform/windows/public/flutter_windows.h | 18 ++++-- 8 files changed, 78 insertions(+), 105 deletions(-) diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller.cc b/shell/platform/windows/client_wrapper/flutter_view_controller.cc index ba1cf1f99066a..b5b1a7014be3a 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_controller.cc +++ b/shell/platform/windows/client_wrapper/flutter_view_controller.cc @@ -11,11 +11,6 @@ #include -using namespace winrt; -using namespace Windows::UI; -using namespace Windows::UI::Composition; -using namespace Windows::UI::Composition::Desktop; - #include #include @@ -27,10 +22,10 @@ auto CreateDispatcherQueueController() { DispatcherQueueOptions options{sizeof(DispatcherQueueOptions), DQTYPE_THREAD_CURRENT, DQTAT_COM_STA}; - Windows::System::DispatcherQueueController controller{nullptr}; - check_hresult(CreateDispatcherQueueController( + winrt::Windows::System::DispatcherQueueController controller{nullptr}; + winrt::check_hresult(CreateDispatcherQueueController( options, reinterpret_cast( - put_abi(controller)))); + winrt::put_abi(controller)))); return controller; } @@ -60,16 +55,15 @@ FlutterViewController::FlutterViewController(int width, child_window_ = std::make_unique(width, height, compositor_); - controller_ = V2FlutterDesktopCreateViewControllerComposition( + controller_ = V2CreateViewControllerVisual( width, height, properties, - static_cast(winrt::get_abi(compositor_)),child_window_.get()); + static_cast(winrt::get_abi(compositor_)),child_window_.get()); if (!controller_) { std::cerr << "Failed to create view controller." << std::endl; return; } view_ = std::make_unique(FlutterDesktopGetView(controller_)); - - child_window_->SetViewComposition(view_.get()); + child_window_->SetView(view_.get()); } // Window overload diff --git a/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h b/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h index e332cbd8b6360..4f6280380818e 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h +++ b/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h @@ -34,10 +34,6 @@ class FlutterView { return ptr->GetWindowHandle(); } - void* GetVisual() { - return V2FlutterDesktopViewGetVisual(view_); - } - void SendWindowMetrics(size_t width, size_t height, double dpiScale) { V2FlutterDesktopSendWindowMetrics(view_, width, height, dpiScale); } 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 index 109e64bb819b6..8fc10a1eb97ca 100644 --- 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 @@ -56,13 +56,9 @@ class Win32FlutterWindowPub : public Win32WindowPub { virtual ~Win32FlutterWindowPub(); - /*static FlutterDesktopViewControllerRef CreateWin32FlutterWindow(int width, - int height);*/ - + //TODO void SetView(FlutterView* view); - void SetViewComposition(FlutterView* view); - // |Win32WindowPub| void OnDpiScale(unsigned int dpi) override; @@ -97,6 +93,8 @@ class Win32FlutterWindowPub : public Win32WindowPub { 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(); diff --git a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc index c5d83c6863a6c..9e41dfa66eb3a 100644 --- a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc +++ b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc @@ -36,6 +36,13 @@ Win32FlutterWindowPub::Win32FlutterWindowPub( winrt::Windows::UI::Composition::Compositor const& compositor) : compositor_(compositor), flutter_view_(nullptr) { Win32WindowPub::InitializeChild("FLUTTERVIEW", 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) @@ -47,27 +54,6 @@ void Win32FlutterWindowPub::SetView(FlutterView* view) { flutter_view_ = view; } -// Called after view has been created. Binds the child HWND represented by this -// class to a composition visual that is passed to Flutter Engine -void Win32FlutterWindowPub::SetViewComposition(FlutterView* view) { - // Create Window target, set visual returned from the engine as the root - target_ = - CreateDesktopWindowTarget(compositor_, Win32WindowPub::GetWindowHandle()); - - void* pointer = view->GetVisual(); //TODO: change this to push - - winrt::com_ptr rawAbi = nullptr; - - winrt::Windows::UI::Composition::ISpriteVisual abiFlutterVisual = nullptr; - - winrt::copy_from_abi(abiFlutterVisual, pointer); - - winrt::Windows::UI::Composition::Visual flutterVisual = nullptr; - abiFlutterVisual.as(flutterVisual); - - target_.Root(flutterVisual); -} - Win32FlutterWindowPub::~Win32FlutterWindowPub() {} // Translates button codes from Win32 API to FlutterPointerMouseButtons. diff --git a/shell/platform/windows/flutter_comp_view.cc b/shell/platform/windows/flutter_comp_view.cc index 33c8493aacb6e..02d87b9273ecb 100644 --- a/shell/platform/windows/flutter_comp_view.cc +++ b/shell/platform/windows/flutter_comp_view.cc @@ -45,22 +45,28 @@ FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompViewHwnd( FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompView( const int width, const int height, - void* compositor) { + ABI::Windows::UI::Composition::IVisual* visual) { auto state = std::make_unique(); state->view = std::make_unique(width, height); - - if (compositor != nullptr) { - state->view->compositor_.Attach( - static_cast(compositor)); - } - - // TODO: use C++/Winrt copy_from_abi once C++.Winrt is supportrf - // winrt::copy_from_abi(compositor_, compositor); // 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(); } @@ -353,18 +359,8 @@ bool FlutterCompView::SwapBuffers() { return surface_manager->SwapBuffers(render_surface); } -Microsoft::WRL::ComPtr -FlutterCompView::GetFlutterHost() { - return flutter_host_; -} - void FlutterCompView::SizeHostVisual(size_t width, size_t height) { - Microsoft::WRL::ComPtr visualPtr; - - auto hr = flutter_host_.As(&visualPtr); - (SUCCEEDED(hr)); - hr = visualPtr->put_Size({static_cast(width), static_cast(height)}); - (SUCCEEDED(hr)); + flutter_host_.Size({static_cast(width), static_cast(height)}); } void FlutterCompView::CreateRenderSurface() { @@ -376,35 +372,24 @@ void FlutterCompView::CreateRenderSurface() { } void FlutterCompView::CreateRenderSurfaceHWND() { - //TODO: seems like we shouldn't get this from the window_wrapper as that is mainly used for plugins render_surface = surface_manager->CreateSurface(static_cast(window_rendertarget_)); } -// TODO: move this into visual_flutter_host class when that exists -// TODO: can we use c++/winrt in here (requires newer windows SDK and c++17 -// support in compiler toolchain) -// TODO: do we still need RoHelper with the above? void FlutterCompView::CreateRenderSurfaceUWP() { if (surface_manager && render_surface == EGL_NO_SURFACE) { - // render_surface = surface_manager->CreateSurface(GetWindowHandle()); - + + //TODO: replace ROHelper with regen'd c++/WinRT with downlevel RoHelper helper; HSTRING act; HSTRING_HEADER header; - auto hr = compositor_->CreateSpriteVisual(flutter_host_.GetAddressOf()); - (SUCCEEDED(hr)); - - Microsoft::WRL::ComPtr visualPtr; - - hr = flutter_host_.As(&visualPtr); - (SUCCEEDED(hr)); - hr = visualPtr->put_Size({static_cast(width_), static_cast(height_)}); - (SUCCEEDED(hr)); + flutter_host_.Size( + {static_cast(width_), static_cast(height_)}); - render_surface = surface_manager->CreateSurface(flutter_host_.Get()); + render_surface = surface_manager->CreateSurface( + static_cast(winrt::get_abi(flutter_host_))); } } diff --git a/shell/platform/windows/flutter_comp_view.h b/shell/platform/windows/flutter_comp_view.h index fad886dd48b06..d775771c643db 100644 --- a/shell/platform/windows/flutter_comp_view.h +++ b/shell/platform/windows/flutter_comp_view.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "flutter/shell/platform/windows/window_state_comp.h" @@ -114,13 +115,16 @@ class FlutterCompView { ~FlutterCompView(); - static FlutterDesktopViewControllerRef - CreateFlutterCompView(int width, int height, void* compositor); + static FlutterDesktopViewControllerRef CreateFlutterCompView( + int width, + int height, + ABI::Windows::UI::Composition::IVisual* visual); - static FlutterDesktopViewControllerRef CreateFlutterCompViewHwnd(int width, - int height, - void* externalwindow, - HWND windowrendertarget); + static FlutterDesktopViewControllerRef CreateFlutterCompViewHwnd( + int width, + int height, + void* externalwindow, + HWND windowrendertarget); // Configures the window instance with an instance of a running Flutter engine // returning a configured FlutterDesktopWindowControllerRef. @@ -287,13 +291,19 @@ class FlutterCompView { // flag indicating if the message loop should be running bool messageloop_running_ = false; - Microsoft::WRL::ComPtr - compositor_{nullptr}; + winrt::Windows::UI::Composition::Compositor compositor_ {nullptr}; + + winrt::Windows::UI::Composition::Visual flutter_host_{nullptr}; + + /*Microsoft::WRL::ComPtr + flutter_host_{nullptr};*/ + + //Microsoft::WRL::ComPtr + // compositor_{nullptr}; HWND window_rendertarget_; - Microsoft::WRL::ComPtr - flutter_host_{nullptr}; + int width_ = 0, height_ = 0; }; diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index daa3794ceaf79..ee8b2ff8c10f4 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -14,6 +14,8 @@ #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" @@ -148,16 +150,17 @@ static std::unique_ptr RunFlutterEngine( return state; } -V2FlutterDesktopViewControllerRef -V2FlutterDesktopCreateViewControllerComposition( +//TODO search for V2FlutterDesktopCreateViewControllerComposition + +V2FlutterDesktopViewControllerRef V2CreateViewControllerVisual( int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* compositor, - void* externalWindow) { + ABI::Windows::UI::Composition::IVisual* visual, + HostEnvironmentState externalWindow) { V2FlutterDesktopViewControllerRef state = flutter::FlutterCompView::CreateFlutterCompView(width, height, - compositor); + visual); auto engine_state = RunFlutterEngine(state->view.get(), engine_properties); @@ -269,11 +272,6 @@ FlutterDesktopViewRef FlutterDesktopGetView( return controller->view_wrapper.get(); } -// TODO return something more strongly typed -void* V2FlutterDesktopViewGetVisual(FlutterDesktopViewRef view) { - return (void*)view->window->GetFlutterHost().Get(); -} - // TODO return something more strongly typed void* V2FlutterDesktopGetExternalWindow(FlutterDesktopViewRef view) { return (void*)view->externalwindow; diff --git a/shell/platform/windows/public/flutter_windows.h b/shell/platform/windows/public/flutter_windows.h index f24a7efde7e1a..aabfa9567e012 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" { @@ -32,6 +33,9 @@ typedef struct FlutterDesktopView* FlutterDesktopViewRef; // Opaque reference to a Flutter engine instance. typedef struct FlutterDesktopEngineState* FlutterDesktopEngineRef; +// Opaque reference to 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. @@ -59,14 +63,16 @@ typedef struct { // This will set up and run an associated Flutter engine using the settings in // |engine_properties|. // +// View supplied must be integrated into host visual tree +// // Returns a null pointer in the event of an error. FLUTTER_EXPORT FlutterDesktopViewControllerRef -V2FlutterDesktopCreateViewControllerComposition( +V2CreateViewControllerVisual( int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* compositor, //TODO: typedef - void* hostwindow); //TODO: typedef + ABI::Windows::UI::Composition::IVisual* visual, + HostEnvironmentState hoststate); // Creates a View with the given dimensions running a Flutter Application. // @@ -82,9 +88,9 @@ V2CreateViewControllerWindow( void* hostwindow, HWND windowrendertarget); //TODO: typedef -// Return backing HWND for manipulation in host application. -FLUTTER_EXPORT -void* V2FlutterDesktopViewGetVisual(FlutterDesktopViewRef view); +//// Return backing HWND for manipulation in host application. +//FLUTTER_EXPORT +//void* V2FlutterDesktopViewGetVisual(FlutterDesktopViewRef view); // Return backing HWND for manipulation in host application. FLUTTER_EXPORT From 657c3b2b4d375494d736812dcddba62af331e1f1 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 May 2020 07:11:18 -0700 Subject: [PATCH 07/13] API cleanup --- .../client_wrapper/flutter_view_controller.cc | 6 +++- .../include/flutter/flutter_view.h | 3 +- .../include/flutter/flutter_view_controller.h | 2 ++ .../testing/stub_flutter_windows_api.cc | 12 +++---- .../testing/stub_flutter_windows_api.h | 5 ++- shell/platform/windows/flutter_comp_view.cc | 9 +----- shell/platform/windows/flutter_comp_view.h | 14 ++------ shell/platform/windows/flutter_windows.cc | 32 ++++--------------- .../platform/windows/public/flutter_windows.h | 11 +++---- 9 files changed, 30 insertions(+), 64 deletions(-) diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller.cc b/shell/platform/windows/client_wrapper/flutter_view_controller.cc index b5b1a7014be3a..8e4765a97c7e3 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_controller.cc +++ b/shell/platform/windows/client_wrapper/flutter_view_controller.cc @@ -87,9 +87,13 @@ FlutterViewController::FlutterViewController(int width, child_window_ = std::make_unique(width, height); + HostEnvironmentState host_state = + static_cast(child_window_.get()); + controller_ = V2CreateViewControllerWindow( width, height, properties, - child_window_.get(),child_window_->GetWindowHandle()); + child_window_->GetWindowHandle(), + host_state); if (!controller_) { std::cerr << "Failed to create view controller." << std::endl; return; diff --git a/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h b/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h index 4f6280380818e..8f5a788910ee4 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h +++ b/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h @@ -29,7 +29,8 @@ class FlutterView { // Returns the backing HWND for the view. HWND GetNativeWindow() { - void* windowptr = V2FlutterDesktopGetExternalWindow(view_); + // Retreive our hosting state from the backing view + HostEnvironmentState windowptr = V2FlutterDesktopGetHostState(view_); Win32FlutterWindowPub* ptr = static_cast(windowptr); return ptr->GetWindowHandle(); } diff --git a/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h b/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h index 952dddd08fbcb..a69aa7652c9ac 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h +++ b/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h @@ -73,8 +73,10 @@ class FlutterViewController : public PluginRegistry { // 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}; }; 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 81d8fbe026c70..21e08b415e0a0 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 @@ -48,15 +48,15 @@ FlutterDesktopViewControllerRef V2CreateViewControllerWindow( return nullptr; } -FlutterDesktopViewControllerRef V2FlutterDesktopCreateViewControllerComposition( +FlutterDesktopViewControllerRef V2CreateViewControllerVisual( int width, int height, const FlutterDesktopEngineProperties& engine_properties, void* compositor, void* hostwindow) { if (s_stub_implementation) { - return s_stub_implementation - ->V2FlutterDesktopCreateViewControllerComposition(width, height, + return s_stub_implementation->V2CreateViewControllerVisual( + width, height, engine_properties, compositor, hostwindow); } return nullptr; @@ -182,11 +182,11 @@ HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef controller) { return reinterpret_cast(-1); } -void* V2FlutterDesktopGetExternalWindow(FlutterDesktopViewRef view) { +void* V2FlutterDesktopGetHostState(FlutterDesktopViewRef view) { if (s_stub_implementation) { - return s_stub_implementation->V2FlutterDesktopGetExternalWindow(view); + return s_stub_implementation->V2FlutterDesktopGetHostState(view); } - return static_cast(nullptr); + return static_cast(nullptr); } FlutterDesktopEngineRef FlutterDesktopRunEngine( 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 5aeddb5585807..8ff2f5e15c965 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 @@ -39,8 +39,7 @@ class StubFlutterWindowsApi { return nullptr; } - virtual FlutterDesktopViewControllerRef - V2FlutterDesktopCreateViewControllerComposition( + virtual FlutterDesktopViewControllerRef V2CreateViewControllerVisual( int width, int height, const FlutterDesktopEngineProperties& engine_properties, @@ -112,7 +111,7 @@ class StubFlutterWindowsApi { return nullptr; } - virtual void* V2FlutterDesktopGetExternalWindow(FlutterDesktopViewRef view) { + virtual HostEnvironmentState V2FlutterDesktopGetHostState(FlutterDesktopViewRef view) { return nullptr; } diff --git a/shell/platform/windows/flutter_comp_view.cc b/shell/platform/windows/flutter_comp_view.cc index 02d87b9273ecb..a5256a7f48ad8 100644 --- a/shell/platform/windows/flutter_comp_view.cc +++ b/shell/platform/windows/flutter_comp_view.cc @@ -326,13 +326,6 @@ void FlutterCompView::SendPointerEventWithData( std::chrono::high_resolution_clock::now().time_since_epoch()) .count(); - //// Windows passes all input in either physical pixels (Per-monitor, System - //// DPI) or pre-scaled to match bitmap scaling of output where process is - //// running in DPI unaware more. In either case, no need to manually scale - //// input here. For more information see DPIHelper. - //event.scroll_delta_x; - //event.scroll_delta_y; - FlutterEngineSendPointerEvent(engine_, &event, 1); if (event_data.phase == FlutterPointerPhase::kAdd) { @@ -400,7 +393,7 @@ void FlutterCompView::DestroyRenderSurface() { render_surface = EGL_NO_SURFACE; } -// RoHelperImpl +// RoHelperImpl. This is temporary and will go away. template bool AssignProcAddress(HMODULE comBaseModule, const char* name, T*& outProc) { diff --git a/shell/platform/windows/flutter_comp_view.h b/shell/platform/windows/flutter_comp_view.h index d775771c643db..9aefde118b87d 100644 --- a/shell/platform/windows/flutter_comp_view.h +++ b/shell/platform/windows/flutter_comp_view.h @@ -104,10 +104,8 @@ struct MouseState { uint64_t buttons = 0; }; -// 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. +// A windowing neutral flutter child video used as implementation for flutter view that works +// with win32 hwnds and Windows::UI::Composition visuals class FlutterCompView { public: // Create flutter Window for use as child window @@ -295,16 +293,8 @@ class FlutterCompView { winrt::Windows::UI::Composition::Visual flutter_host_{nullptr}; - /*Microsoft::WRL::ComPtr - flutter_host_{nullptr};*/ - - //Microsoft::WRL::ComPtr - // compositor_{nullptr}; - HWND window_rendertarget_; - - int width_ = 0, height_ = 0; }; diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index ee8b2ff8c10f4..c3d1e28c36e59 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -150,8 +150,6 @@ static std::unique_ptr RunFlutterEngine( return state; } -//TODO search for V2FlutterDesktopCreateViewControllerComposition - V2FlutterDesktopViewControllerRef V2CreateViewControllerVisual( int width, int height, @@ -177,8 +175,9 @@ V2FlutterDesktopViewControllerRef V2CreateViewControllerWindow( int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* externalWindow, - HWND windowrendertarget) { + HWND windowrendertarget, + HostEnvironmentState externalWindow + ) { V2FlutterDesktopViewControllerRef state = flutter::FlutterCompView::CreateFlutterCompViewHwnd(width, height, externalWindow, static_cast(windowrendertarget)); @@ -226,26 +225,6 @@ void V2FlutterDesktopSendPointerLeave(FlutterDesktopViewRef view) { view->window->OnPointerLeave(); } -//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); -//} - uint64_t FlutterDesktopProcessMessages( FlutterDesktopViewControllerRef controller) { return controller->engine_state->task_runner->ProcessTasks().count(); @@ -273,8 +252,9 @@ FlutterDesktopViewRef FlutterDesktopGetView( } // TODO return something more strongly typed -void* V2FlutterDesktopGetExternalWindow(FlutterDesktopViewRef view) { - return (void*)view->externalwindow; +HostEnvironmentState V2FlutterDesktopGetHostState( + FlutterDesktopViewRef view) { + return (HostEnvironmentState)view->externalwindow; } // TODO diff --git a/shell/platform/windows/public/flutter_windows.h b/shell/platform/windows/public/flutter_windows.h index aabfa9567e012..661b4a5a66c97 100644 --- a/shell/platform/windows/public/flutter_windows.h +++ b/shell/platform/windows/public/flutter_windows.h @@ -85,16 +85,13 @@ V2CreateViewControllerWindow( int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* hostwindow, - HWND windowrendertarget); //TODO: typedef - -//// Return backing HWND for manipulation in host application. -//FLUTTER_EXPORT -//void* V2FlutterDesktopViewGetVisual(FlutterDesktopViewRef view); + HWND windowrendertarget, + HostEnvironmentState hostwindow + ); // Return backing HWND for manipulation in host application. FLUTTER_EXPORT -void* V2FlutterDesktopGetExternalWindow(FlutterDesktopViewRef view); +HostEnvironmentState V2FlutterDesktopGetHostState(FlutterDesktopViewRef view); //TODO FLUTTER_EXPORT void V2FlutterDesktopSendWindowMetrics(FlutterDesktopViewRef view, From f1c38e4d6d0b07137235ab8671a6f76d2553251e Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 May 2020 08:14:40 -0700 Subject: [PATCH 08/13] Rename FlutterCompView->FlutterWindowsView --- shell/platform/windows/BUILD.gn | 4 +- .../client_wrapper/flutter_view_controller.cc | 7 +- .../flutter_view_controller_unittests.cc | 5 +- .../testing/stub_flutter_windows_api.cc | 12 +- .../testing/stub_flutter_windows_api.h | 12 +- shell/platform/windows/flutter_comp_view.cc | 85 +-- shell/platform/windows/flutter_comp_view.h | 10 +- .../windows/flutter_compview_unittests.cc | 8 +- shell/platform/windows/flutter_windows.cc | 18 +- .../platform/windows/flutter_windows_view.cc | 595 ++++++++++++++++++ shell/platform/windows/flutter_windows_view.h | 303 +++++++++ shell/platform/windows/key_event_handler.cc | 4 +- shell/platform/windows/key_event_handler.h | 6 +- .../platform/windows/keyboard_hook_handler.h | 6 +- shell/platform/windows/platform_handler.cc | 4 +- shell/platform/windows/platform_handler.h | 6 +- .../windows/testing/flutter_compview_test.cc | 10 +- .../windows/testing/flutter_compview_test.h | 12 +- shell/platform/windows/text_input_plugin.cc | 4 +- shell/platform/windows/text_input_plugin.h | 6 +- shell/platform/windows/window_state_comp.h | 6 +- 21 files changed, 1021 insertions(+), 102 deletions(-) create mode 100644 shell/platform/windows/flutter_windows_view.cc create mode 100644 shell/platform/windows/flutter_windows_view.h diff --git a/shell/platform/windows/BUILD.gn b/shell/platform/windows/BUILD.gn index a33cc8b7e630d..b8114978f9ad8 100644 --- a/shell/platform/windows/BUILD.gn +++ b/shell/platform/windows/BUILD.gn @@ -51,8 +51,8 @@ source_set("flutter_windows_source") { "string_conversion.h", "text_input_plugin.cc", "text_input_plugin.h", - "flutter_comp_view.cc", - "flutter_comp_view.h", + "flutter_windows_view.cc", + "flutter_windows_view.h", "window_state_comp.h", "task_runner.cc", "task_runner.h", diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller.cc b/shell/platform/windows/client_wrapper/flutter_view_controller.cc index 8e4765a97c7e3..daa2791faeb81 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_controller.cc +++ b/shell/platform/windows/client_wrapper/flutter_view_controller.cc @@ -55,9 +55,14 @@ FlutterViewController::FlutterViewController(int width, 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_)),child_window_.get()); + static_cast( + winrt::get_abi(compositor_)), + host_state); if (!controller_) { std::cerr << "Failed to create view controller." << std::endl; return; diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc b/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc index f19eca5b20e0a..b8e67d0da88ec 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc +++ b/shell/platform/windows/client_wrapper/flutter_view_controller_unittests.cc @@ -19,8 +19,9 @@ class TestWindowsApi : public testing::StubFlutterWindowsApi { int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* hostwindow, - HWND windowrendertarget) override { + HWND windowrendertarget, + HostEnvironmentState hostwindow + ) override { return reinterpret_cast(1); } }; 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 21e08b415e0a0..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 @@ -39,11 +39,11 @@ FlutterDesktopViewControllerRef V2CreateViewControllerWindow( int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* hostwindow, - HWND windowrendertarget) { + HWND windowrendertarget, + HostEnvironmentState state) { if (s_stub_implementation) { return s_stub_implementation->V2CreateViewControllerWindow(width, height, - engine_properties, hostwindow, windowrendertarget); + engine_properties, windowrendertarget, state); } return nullptr; } @@ -52,12 +52,12 @@ FlutterDesktopViewControllerRef V2CreateViewControllerVisual( int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* compositor, - void* hostwindow) { + ABI::Windows::UI::Composition::IVisual* visual, + HostEnvironmentState state) { if (s_stub_implementation) { return s_stub_implementation->V2CreateViewControllerVisual( width, height, - engine_properties, compositor, hostwindow); + engine_properties, visual, state); } return nullptr; } 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 8ff2f5e15c965..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 { @@ -34,8 +36,9 @@ class StubFlutterWindowsApi { int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* hostwindow, - HWND windowrendertarget) { + HWND windowrendertarget, + HostEnvironmentState state + ) { return nullptr; } @@ -43,8 +46,9 @@ class StubFlutterWindowsApi { int width, int height, const FlutterDesktopEngineProperties& engine_properties, - void* compositor, - void* hostwindow) { + ABI::Windows::UI::Composition::IVisual* visual, + HostEnvironmentState state +) { return nullptr; } diff --git a/shell/platform/windows/flutter_comp_view.cc b/shell/platform/windows/flutter_comp_view.cc index a5256a7f48ad8..e640e81d1cd60 100644 --- a/shell/platform/windows/flutter_comp_view.cc +++ b/shell/platform/windows/flutter_comp_view.cc @@ -1,4 +1,4 @@ -#include "flutter/shell/platform/windows/flutter_comp_view.h" +#include "flutter/shell/platform/windows/flutter_windows_view.h" #include @@ -8,21 +8,21 @@ namespace flutter { // constant for machines running at 100% scaling. constexpr int base_dpi = 96; -FlutterCompView::FlutterCompView(int width, int height) { +FlutterWindowsView::FlutterWindowsView(int width, int height) { surface_manager = std::make_unique(); width_ = width; height_ = height; } -FlutterCompView::~FlutterCompView() { +FlutterWindowsView::~FlutterWindowsView() { DestroyRenderSurface(); if (plugin_registrar_ && plugin_registrar_->destruction_handler) { plugin_registrar_->destruction_handler(plugin_registrar_.get()); } } -FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompViewHwnd( +FlutterDesktopViewControllerRef FlutterWindowsView::CreateFlutterWindowsViewHwnd( const int width, const int height, void* externalWindow, @@ -30,7 +30,7 @@ FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompViewHwnd( auto state = std::make_unique(); state->view = - std::make_unique(width, height); + std::make_unique(width, height); state->view->window_rendertarget_ = windowrendertarget; @@ -42,12 +42,12 @@ FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompViewHwnd( return state.release(); } -FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompView( +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); + state->view = std::make_unique(width, height); // a window wrapper for the state block, distinct from the // window_wrapper handed to plugin_registrar. @@ -70,7 +70,8 @@ FlutterDesktopViewControllerRef FlutterCompView::CreateFlutterCompView( return state.release(); } -void FlutterCompView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng, void* externalwindow) { +void FlutterWindowsView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng, + void* externalwindow) { engine_ = eng; auto messenger = std::make_unique(); @@ -102,7 +103,7 @@ void FlutterCompView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng, void* exte process_events_ = true; } -FlutterDesktopPluginRegistrarRef FlutterCompView::GetRegistrar() { +FlutterDesktopPluginRegistrarRef FlutterWindowsView::GetRegistrar() { return plugin_registrar_.get(); } @@ -120,7 +121,7 @@ static FlutterDesktopMessage ConvertToDesktopMessage( // The Flutter Engine calls out to this function when new platform messages // are available. -void FlutterCompView::HandlePlatformMessage( +void FlutterWindowsView::HandlePlatformMessage( const FlutterPlatformMessage* engine_message) { if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) { std::cerr << "Invalid message size received. Expected: " @@ -136,13 +137,14 @@ void FlutterCompView::HandlePlatformMessage( [this] { this->process_events_ = true; }); } -void FlutterCompView::OnPointerMove(double x, double y) { +void FlutterWindowsView::OnPointerMove(double x, double y) { if (process_events_) { SendPointerMove(x, y); } } -void FlutterCompView::OnPointerDown(double x, +void FlutterWindowsView::OnPointerDown( + double x, double y, FlutterPointerMouseButtons flutter_button) { if (process_events_) { @@ -154,7 +156,8 @@ void FlutterCompView::OnPointerDown(double x, } } -void FlutterCompView::OnPointerUp(double x, +void FlutterWindowsView::OnPointerUp( + double x, double y, FlutterPointerMouseButtons flutter_button) { if (process_events_) { @@ -166,19 +169,19 @@ void FlutterCompView::OnPointerUp(double x, } } -void FlutterCompView::OnPointerLeave() { +void FlutterWindowsView::OnPointerLeave() { if (process_events_) { SendPointerLeave(); } } -void FlutterCompView::OnText(const std::u16string& text) { +void FlutterWindowsView::OnText(const std::u16string& text) { if (process_events_) { SendText(text); } } -void FlutterCompView::OnKey(int key, +void FlutterWindowsView::OnKey(int key, int scancode, int action, char32_t character) { @@ -187,13 +190,16 @@ void FlutterCompView::OnKey(int key, } } -void FlutterCompView::OnScroll(double x, double y, double delta_x, double delta_y) { +void FlutterWindowsView::OnScroll(double x, + double y, + double delta_x, + double delta_y) { if (process_events_) { SendScroll(x, y, delta_x, delta_y); } } -void FlutterCompView::OnFontChange() { +void FlutterWindowsView::OnFontChange() { if (engine_ == nullptr) { return; } @@ -201,7 +207,9 @@ void FlutterCompView::OnFontChange() { } // Sends new size information to FlutterEngine. -void FlutterCompView::SendWindowMetrics(size_t width, size_t height, double dpiScale) { +void FlutterWindowsView::SendWindowMetrics(size_t width, + size_t height, + double dpiScale) { if (engine_ == nullptr) { return; } @@ -220,7 +228,7 @@ void FlutterCompView::SendWindowMetrics(size_t width, size_t height, double dpiS // Set's |event_data|'s phase to either kMove or kHover depending on the current // primary mouse button state. -void FlutterCompView::SetEventPhaseFromCursorButtonState( +void FlutterWindowsView::SetEventPhaseFromCursorButtonState( FlutterPointerEvent* event_data) { MouseState state = GetMouseState(); // For details about this logic, see FlutterPointerPhase in the embedder.h @@ -233,7 +241,7 @@ void FlutterCompView::SetEventPhaseFromCursorButtonState( : FlutterPointerPhase::kDown; } -void FlutterCompView::SendPointerMove(double x, double y) { +void FlutterWindowsView::SendPointerMove(double x, double y) { FlutterPointerEvent event = {}; event.x = x; event.y = y; @@ -241,7 +249,7 @@ void FlutterCompView::SendPointerMove(double x, double y) { SendPointerEventWithData(event); } -void FlutterCompView::SendPointerDown(double x, double y) { +void FlutterWindowsView::SendPointerDown(double x, double y) { FlutterPointerEvent event = {}; SetEventPhaseFromCursorButtonState(&event); event.x = x; @@ -250,7 +258,7 @@ void FlutterCompView::SendPointerDown(double x, double y) { SetMouseFlutterStateDown(true); } -void FlutterCompView::SendPointerUp(double x, double y) { +void FlutterWindowsView::SendPointerUp(double x, double y) { FlutterPointerEvent event = {}; SetEventPhaseFromCursorButtonState(&event); event.x = x; @@ -261,25 +269,28 @@ void FlutterCompView::SendPointerUp(double x, double y) { } } -void FlutterCompView::SendPointerLeave() { +void FlutterWindowsView::SendPointerLeave() { FlutterPointerEvent event = {}; event.phase = FlutterPointerPhase::kRemove; SendPointerEventWithData(event); } -void FlutterCompView::SendText(const std::u16string& code_point) { +void FlutterWindowsView::SendText(const std::u16string& code_point) { for (const auto& handler : keyboard_hook_handlers_) { handler->TextHook(this, code_point); } } -void FlutterCompView::SendKey(int key, int scancode, int action, int mods) { +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 FlutterCompView::SendScroll(double x, double y, double delta_x, double delta_y) { +void FlutterWindowsView::SendScroll(double x, + double y, + double delta_x, + double delta_y) { FlutterPointerEvent event = {}; SetEventPhaseFromCursorButtonState(&event); event.signal_kind = FlutterPointerSignalKind::kFlutterPointerSignalKindScroll; @@ -293,7 +304,7 @@ void FlutterCompView::SendScroll(double x, double y, double delta_x, double delt SendPointerEventWithData(event); } -void FlutterCompView::SendPointerEventWithData( +void FlutterWindowsView::SendPointerEventWithData( const FlutterPointerEvent& event_data) { //TODO MouseState mouse_state = GetMouseState(); @@ -336,27 +347,27 @@ void FlutterCompView::SendPointerEventWithData( } } -bool FlutterCompView::MakeCurrent() { +bool FlutterWindowsView::MakeCurrent() { return surface_manager->MakeCurrent(render_surface); } -bool FlutterCompView::MakeResourceCurrent() { +bool FlutterWindowsView::MakeResourceCurrent() { return surface_manager->MakeResourceCurrent(); } -bool FlutterCompView::ClearContext() { +bool FlutterWindowsView::ClearContext() { return surface_manager->MakeCurrent(nullptr); } -bool FlutterCompView::SwapBuffers() { +bool FlutterWindowsView::SwapBuffers() { return surface_manager->SwapBuffers(render_surface); } -void FlutterCompView::SizeHostVisual(size_t width, size_t height) { +void FlutterWindowsView::SizeHostVisual(size_t width, size_t height) { flutter_host_.Size({static_cast(width), static_cast(height)}); } -void FlutterCompView::CreateRenderSurface() { +void FlutterWindowsView::CreateRenderSurface() { if (compositor_ != nullptr) { CreateRenderSurfaceUWP(); } else { @@ -364,12 +375,12 @@ void FlutterCompView::CreateRenderSurface() { } } -void FlutterCompView::CreateRenderSurfaceHWND() { +void FlutterWindowsView::CreateRenderSurfaceHWND() { render_surface = surface_manager->CreateSurface(static_cast(window_rendertarget_)); } -void FlutterCompView::CreateRenderSurfaceUWP() { +void FlutterWindowsView::CreateRenderSurfaceUWP() { if (surface_manager && render_surface == EGL_NO_SURFACE) { @@ -386,7 +397,7 @@ void FlutterCompView::CreateRenderSurfaceUWP() { } } -void FlutterCompView::DestroyRenderSurface() { +void FlutterWindowsView::DestroyRenderSurface() { if (surface_manager) { surface_manager->DestroySurface(render_surface); } diff --git a/shell/platform/windows/flutter_comp_view.h b/shell/platform/windows/flutter_comp_view.h index 9aefde118b87d..3a6c7b726e648 100644 --- a/shell/platform/windows/flutter_comp_view.h +++ b/shell/platform/windows/flutter_comp_view.h @@ -106,19 +106,19 @@ struct MouseState { // A windowing neutral flutter child video used as implementation for flutter view that works // with win32 hwnds and Windows::UI::Composition visuals -class FlutterCompView { +class FlutterWindowsView { public: // Create flutter Window for use as child window - FlutterCompView(int width, int height); + FlutterWindowsView(int width, int height); - ~FlutterCompView(); + ~FlutterWindowsView(); - static FlutterDesktopViewControllerRef CreateFlutterCompView( + static FlutterDesktopViewControllerRef CreateFlutterWindowsView( int width, int height, ABI::Windows::UI::Composition::IVisual* visual); - static FlutterDesktopViewControllerRef CreateFlutterCompViewHwnd( + static FlutterDesktopViewControllerRef CreateFlutterWindowsViewHwnd( int width, int height, void* externalwindow, diff --git a/shell/platform/windows/flutter_compview_unittests.cc b/shell/platform/windows/flutter_compview_unittests.cc index 0fcdddf3153ca..818135ded173a 100644 --- a/shell/platform/windows/flutter_compview_unittests.cc +++ b/shell/platform/windows/flutter_compview_unittests.cc @@ -4,14 +4,14 @@ namespace flutter { namespace testing { -TEST(FlutterCompViewTest, CreateDestroy) { - FlutterCompViewTest window(800, 600); +TEST(FlutterWindowsViewTest, CreateDestroy) { + FlutterWindowsViewTest window(800, 600); ASSERT_TRUE(TRUE); } //TODO MOVE to wrapper -//TEST(FlutterCompViewTest, CanFontChange) { -// FlutterCompViewTest window(800, 600); +//TEST(FlutterWindowsViewTest, CanFontChange) { +// FlutterWindowsViewTest window(800, 600); // HWND hwnd = window.GetWindowHandle(); // LRESULT result = SendMessage(hwnd, WM_FONTCHANGE, NULL, NULL); // ASSERT_EQ(result, 0); diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index c3d1e28c36e59..fd46e56e55f3a 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -25,7 +25,7 @@ #include "flutter/shell/platform/windows/platform_handler.h" #include "flutter/shell/platform/windows/text_input_plugin.h" #include "flutter/shell/platform/windows/task_runner.h" -#include "flutter/shell/platform/windows/flutter_comp_view.h" +#include "flutter/shell/platform/windows/flutter_windows_view.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::FlutterCompView* 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,7 +75,7 @@ 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(); }; @@ -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; @@ -157,7 +157,7 @@ V2FlutterDesktopViewControllerRef V2CreateViewControllerVisual( ABI::Windows::UI::Composition::IVisual* visual, HostEnvironmentState externalWindow) { V2FlutterDesktopViewControllerRef state = - flutter::FlutterCompView::CreateFlutterCompView(width, height, + flutter::FlutterWindowsView::CreateFlutterWindowsView(width, height, visual); auto engine_state = RunFlutterEngine(state->view.get(), engine_properties); @@ -179,7 +179,7 @@ V2FlutterDesktopViewControllerRef V2CreateViewControllerWindow( HostEnvironmentState externalWindow ) { V2FlutterDesktopViewControllerRef state = - flutter::FlutterCompView::CreateFlutterCompViewHwnd(width, height, externalWindow, static_cast(windowrendertarget)); + flutter::FlutterWindowsView::CreateFlutterWindowsViewHwnd(width, height, externalWindow, static_cast(windowrendertarget)); auto engine_state = RunFlutterEngine(state->view.get(), engine_properties); diff --git a/shell/platform/windows/flutter_windows_view.cc b/shell/platform/windows/flutter_windows_view.cc new file mode 100644 index 0000000000000..51c93894dcec2 --- /dev/null +++ b/shell/platform/windows/flutter_windows_view.cc @@ -0,0 +1,595 @@ +#include "flutter/shell/platform/windows/flutter_comp_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..3a6c7b726e648 --- /dev/null +++ b/shell/platform/windows/flutter_windows_view.h @@ -0,0 +1,303 @@ +// 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); + + Microsoft::WRL::ComPtr + GetFlutterHost(); + + // 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 671c3e0c69859..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(FlutterCompView* window, +void KeyEventHandler::TextHook(FlutterWindowsView* window, const std::u16string& code_point) {} -void KeyEventHandler::KeyboardHook(FlutterCompView* 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 33d19f1ff85b1..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 FlutterCompView; +class FlutterWindowsView; // Implements a KeyboardHookHandler // @@ -28,14 +28,14 @@ class KeyEventHandler : public KeyboardHookHandler { virtual ~KeyEventHandler(); // |KeyboardHookHandler| - void KeyboardHook(FlutterCompView* window, + void KeyboardHook(FlutterWindowsView* window, int key, int scancode, int action, char32_t character) override; // |KeyboardHookHandler| - void TextHook(FlutterCompView* 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 23cf92d638af6..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 FlutterCompView; +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(FlutterCompView* 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(FlutterCompView* 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 898424b2c101f..a858d4dfb7c7f 100644 --- a/shell/platform/windows/platform_handler.cc +++ b/shell/platform/windows/platform_handler.cc @@ -11,7 +11,7 @@ #include "flutter/shell/platform/common/cpp/json_method_codec.h" #include "flutter/shell/platform/windows/string_conversion.h" -#include "flutter/shell/platform/windows/flutter_comp_view.h" +#include "flutter/shell/platform/windows/flutter_windows_view.h" static constexpr char kChannelName[] = "flutter/platform"; @@ -198,7 +198,7 @@ bool ScopedClipboard::SetString(const std::wstring string) { } // namespace PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger, - FlutterCompView* window) + FlutterWindowsView* window) : channel_(std::make_unique>( messenger, kChannelName, diff --git a/shell/platform/windows/platform_handler.h b/shell/platform/windows/platform_handler.h index 3238b91a9c830..eed2b2f169ef8 100644 --- a/shell/platform/windows/platform_handler.h +++ b/shell/platform/windows/platform_handler.h @@ -12,13 +12,13 @@ namespace flutter { -class FlutterCompView; +class FlutterWindowsView; // Handler for internal system channels. class PlatformHandler { public: explicit PlatformHandler(flutter::BinaryMessenger* messenger, - FlutterCompView* 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. - FlutterCompView* window_; + FlutterWindowsView* window_; }; } // namespace flutter diff --git a/shell/platform/windows/testing/flutter_compview_test.cc b/shell/platform/windows/testing/flutter_compview_test.cc index d80418c3c12c8..20795f21fbb44 100644 --- a/shell/platform/windows/testing/flutter_compview_test.cc +++ b/shell/platform/windows/testing/flutter_compview_test.cc @@ -3,16 +3,16 @@ namespace flutter { namespace testing { -FlutterCompViewTest::FlutterCompViewTest(int width, int height) - : FlutterCompView(width, height){}; +FlutterWindowsViewTest::FlutterWindowsViewTest(int width, int height) + : FlutterWindowsView(width, height){}; -FlutterCompViewTest::~FlutterCompViewTest() = default; +FlutterWindowsViewTest::~FlutterWindowsViewTest() = default; -//void FlutterCompViewTest::OnFontChange() { +//void FlutterWindowsViewTest::OnFontChange() { // on_font_change_called_ = true; //} -bool FlutterCompViewTest::OnFontChangeWasCalled() { +bool FlutterWindowsViewTest::OnFontChangeWasCalled() { return true; //TODO create an actual test //return on_font_change_called_; } diff --git a/shell/platform/windows/testing/flutter_compview_test.h b/shell/platform/windows/testing/flutter_compview_test.h index 42c18dd9da1dd..a446b6f43ce61 100644 --- a/shell/platform/windows/testing/flutter_compview_test.h +++ b/shell/platform/windows/testing/flutter_compview_test.h @@ -4,20 +4,20 @@ #include -#include "flutter/shell/platform/windows/flutter_comp_view.h" +#include "flutter/shell/platform/windows/flutter_windows_view.h" namespace flutter { namespace testing { /// Test class for Win32FlutterWindow. -class FlutterCompViewTest : public FlutterCompView { +class FlutterWindowsViewTest : public FlutterWindowsView { public: - FlutterCompViewTest(int width, int height); - virtual ~FlutterCompViewTest(); + FlutterWindowsViewTest(int width, int height); + virtual ~FlutterWindowsViewTest(); // Prevent copying. - FlutterCompViewTest(FlutterCompViewTest const&) = delete; - FlutterCompViewTest& operator=(FlutterCompViewTest const&) = delete; + FlutterWindowsViewTest(FlutterWindowsViewTest const&) = delete; + FlutterWindowsViewTest& operator=(FlutterWindowsViewTest const&) = delete; //// |Win32Window| //void OnFontChange() override; diff --git a/shell/platform/windows/text_input_plugin.cc b/shell/platform/windows/text_input_plugin.cc index 20789067e9bc9..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(FlutterCompView* window, +void TextInputPlugin::TextHook(FlutterWindowsView* window, const std::u16string& text) { if (active_model_ == nullptr) { return; @@ -45,7 +45,7 @@ void TextInputPlugin::TextHook(FlutterCompView* window, SendStateUpdate(*active_model_); } -void TextInputPlugin::KeyboardHook(FlutterCompView* 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 3ae3c1882ad15..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 FlutterCompView; +class FlutterWindowsView; // Implements a text input plugin. // @@ -28,14 +28,14 @@ class TextInputPlugin : public KeyboardHookHandler { virtual ~TextInputPlugin(); // |KeyboardHookHandler| - void KeyboardHook(FlutterCompView* window, + void KeyboardHook(FlutterWindowsView* window, int key, int scancode, int action, char32_t character) override; // |KeyboardHookHandler| - void TextHook(FlutterCompView* window, + void TextHook(FlutterWindowsView* window, const std::u16string& text) override; private: diff --git a/shell/platform/windows/window_state_comp.h b/shell/platform/windows/window_state_comp.h index 4007ed96de904..c91d3126de9b8 100644 --- a/shell/platform/windows/window_state_comp.h +++ b/shell/platform/windows/window_state_comp.h @@ -15,14 +15,14 @@ #include "flutter/shell/platform/windows/task_runner.h" namespace flutter { - struct FlutterCompView; + 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; + std::unique_ptr view; // The state associate with the engine backing the view. std::unique_ptr engine_state; @@ -36,7 +36,7 @@ struct FlutterDesktopViewControllerState { // to all of the controller-based functionality. struct FlutterDesktopView { // The window that (indirectly) owns this state object. - flutter::FlutterCompView* window; + flutter::FlutterWindowsView* window; void* externalwindow; }; From 7a8d8ada4a7dc142d29f94ba9eeaa67044fd5710 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 May 2020 09:36:21 -0700 Subject: [PATCH 09/13] Rename flutter_view and flutter_view_controller --- shell/platform/windows/client_wrapper/BUILD.gn | 10 +++++----- .../include/flutter/dart_project.h | 2 +- .../include/flutter/plugin_registrar_windows.h | 8 ++++---- .../{flutter_view.h => win32_flutter_view.h} | 10 +++++----- ...oller.h => win32_flutter_view_controller.h} | 18 +++++++++--------- .../include/flutter/win32_flutter_window_pub.h | 6 +++--- ...ler.cc => win32_flutter_view_controller.cc} | 16 ++++++++-------- ...win32_flutter_view_controller_unittests.cc} | 10 +++++----- ...ests.cc => win32_flutter_view_unittests.cc} | 6 +++--- .../client_wrapper/win32_flutter_window_pub.cc | 8 ++++---- 10 files changed, 47 insertions(+), 47 deletions(-) rename shell/platform/windows/client_wrapper/include/flutter/{flutter_view.h => win32_flutter_view.h} (91%) rename shell/platform/windows/client_wrapper/include/flutter/{flutter_view_controller.h => win32_flutter_view_controller.h} (84%) rename shell/platform/windows/client_wrapper/{flutter_view_controller.cc => win32_flutter_view_controller.cc} (87%) rename shell/platform/windows/client_wrapper/{flutter_view_controller_unittests.cc => win32_flutter_view_controller_unittests.cc} (80%) rename shell/platform/windows/client_wrapper/{flutter_view_unittests.cc => win32_flutter_view_unittests.cc} (85%) diff --git a/shell/platform/windows/client_wrapper/BUILD.gn b/shell/platform/windows/client_wrapper/BUILD.gn index 00b83f85e8033..1a6258870d3a6 100644 --- a/shell/platform/windows/client_wrapper/BUILD.gn +++ b/shell/platform/windows/client_wrapper/BUILD.gn @@ -7,15 +7,15 @@ 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", @@ -84,8 +84,8 @@ executable("client_wrapper_windows_unittests") { 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/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/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/flutter_view.h b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view.h similarity index 91% rename from shell/platform/windows/client_wrapper/include/flutter/flutter_view.h rename to shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view.h index 8f5a788910ee4..01169e591df6e 100644 --- a/shell/platform/windows/client_wrapper/include/flutter/flutter_view.h +++ b/shell/platform/windows/client_wrapper/include/flutter/win32_flutter_view.h @@ -13,19 +13,19 @@ namespace flutter { // A view displaying Flutter content. -class FlutterView { +class Win32FlutterView { public: - explicit FlutterView( + explicit Win32FlutterView( FlutterDesktopViewRef view ) : view_(view) { } - virtual ~FlutterView() = default; + virtual ~Win32FlutterView() = default; // Prevent copying. - FlutterView(FlutterView const&) = delete; - FlutterView& operator=(FlutterView const&) = delete; + Win32FlutterView(Win32FlutterView const&) = delete; + Win32FlutterView& operator=(Win32FlutterView const&) = delete; // Returns the backing HWND for the view. HWND GetNativeWindow() { 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 84% 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 a69aa7652c9ac..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 @@ -14,7 +14,7 @@ #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" @@ -26,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, void* compositor); //TODO - explicit FlutterViewController(int width, + explicit Win32FlutterViewController(int width, int height, 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). @@ -68,7 +68,7 @@ class FlutterViewController : public PluginRegistry { FlutterDesktopViewControllerRef controller_ = nullptr; //// The owned FlutterView. - std::unique_ptr view_; + std::unique_ptr view_; // The owned Flutter child window std::unique_ptr child_window_; 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 index 8fc10a1eb97ca..531336bd1395f 100644 --- 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 @@ -35,7 +35,7 @@ namespace flutter { } FlutterPointerMouseButtons; //Forward declare to avoid circular references -class FlutterView; +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 @@ -57,7 +57,7 @@ class Win32FlutterWindowPub : public Win32WindowPub { virtual ~Win32FlutterWindowPub(); //TODO - void SetView(FlutterView* view); + void SetView(Win32FlutterView* view); // |Win32WindowPub| void OnDpiScale(unsigned int dpi) override; @@ -100,7 +100,7 @@ class Win32FlutterWindowPub : public Win32WindowPub { void SendWindowMetrics(); private: - FlutterView* flutter_view_; + Win32FlutterView* flutter_view_; // // Destroy current rendering surface if one has been allocated. // void DestroyRenderSurface(); diff --git a/shell/platform/windows/client_wrapper/flutter_view_controller.cc b/shell/platform/windows/client_wrapper/win32_flutter_view_controller.cc similarity index 87% rename from shell/platform/windows/client_wrapper/flutter_view_controller.cc rename to shell/platform/windows/client_wrapper/win32_flutter_view_controller.cc index daa2791faeb81..905e9180b9035 100644 --- a/shell/platform/windows/client_wrapper/flutter_view_controller.cc +++ b/shell/platform/windows/client_wrapper/win32_flutter_view_controller.cc @@ -4,7 +4,7 @@ #include -#include "include/flutter/flutter_view_controller.h" +#include "include/flutter/win32_flutter_view_controller.h" #include #include #include @@ -30,7 +30,7 @@ auto CreateDispatcherQueueController() { } // Compositor overload -FlutterViewController::FlutterViewController(int width, +Win32FlutterViewController::Win32FlutterViewController(int width, int height, const DartProject& project, void* compositor) { @@ -67,12 +67,12 @@ FlutterViewController::FlutterViewController(int width, std::cerr << "Failed to create view controller." << std::endl; return; } - view_ = std::make_unique(FlutterDesktopGetView(controller_)); + view_ = std::make_unique(FlutterDesktopGetView(controller_)); child_window_->SetView(view_.get()); } // Window overload -FlutterViewController::FlutterViewController(int width, +Win32FlutterViewController::Win32FlutterViewController(int width, int height, const DartProject& project, HWND parentwindow) { @@ -103,21 +103,21 @@ FlutterViewController::FlutterViewController(int width, std::cerr << "Failed to create view controller." << std::endl; return; } - view_ = std::make_unique(FlutterDesktopGetView(controller_)); + view_ = std::make_unique(FlutterDesktopGetView(controller_)); child_window_->SetView(view_.get()); } -FlutterViewController::~FlutterViewController() { +Win32FlutterViewController::~Win32FlutterViewController() { if (controller_) { FlutterDesktopDestroyViewController(controller_); } } -std::chrono::nanoseconds FlutterViewController::ProcessMessages() { +std::chrono::nanoseconds Win32FlutterViewController::ProcessMessages() { return std::chrono::nanoseconds(FlutterDesktopProcessMessages(controller_)); } -FlutterDesktopPluginRegistrarRef FlutterViewController::GetRegistrarForPlugin( +FlutterDesktopPluginRegistrarRef Win32FlutterViewController::GetRegistrarForPlugin( const std::string& plugin_name) { if (!controller_) { std::cerr << "Cannot get plugin registrar without a window; call " 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 80% 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 b8e67d0da88ec..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" @@ -28,20 +28,20 @@ class TestWindowsApi : public testing::StubFlutterWindowsApi { } // namespace -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, static_cast(nullptr)); } + { 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, static_cast(nullptr)); + 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 index 9e41dfa66eb3a..e79f24df58a23 100644 --- a/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc +++ b/shell/platform/windows/client_wrapper/win32_flutter_window_pub.cc @@ -2,7 +2,7 @@ #include -#include "include/flutter/flutter_view.h" +#include "include/flutter/win32_flutter_view.h" namespace flutter { @@ -35,7 +35,7 @@ Win32FlutterWindowPub::Win32FlutterWindowPub( int height, winrt::Windows::UI::Composition::Compositor const& compositor) : compositor_(compositor), flutter_view_(nullptr) { - Win32WindowPub::InitializeChild("FLUTTERVIEW", width, height); + Win32WindowPub::InitializeChild("Win32FlutterView", width, height); // Create Window target, set visual returned from the engine as the root target_ = @@ -47,10 +47,10 @@ Win32FlutterWindowPub::Win32FlutterWindowPub( Win32FlutterWindowPub::Win32FlutterWindowPub(int width, int height) : compositor_(nullptr), flutter_view_(nullptr) { - Win32WindowPub::InitializeChild("FLUTTERVIEW", width, height); + Win32WindowPub::InitializeChild("Win32FlutterView", width, height); } -void Win32FlutterWindowPub::SetView(FlutterView* view) { +void Win32FlutterWindowPub::SetView(Win32FlutterView* view) { flutter_view_ = view; } From d9536e2aa114987016e51f167c562dccc71b9aa4 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 May 2020 10:45:45 -0700 Subject: [PATCH 10/13] cleanup and some comments --- .../flutter_window_controller_unittests.cc | 2 +- shell/platform/windows/flutter_windows.cc | 26 ++++---- .../platform/windows/public/flutter_windows.h | 62 +++++++++---------- 3 files changed, 43 insertions(+), 47 deletions(-) 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/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index fd46e56e55f3a..8bf65f907302a 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -300,18 +300,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/public/flutter_windows.h b/shell/platform/windows/public/flutter_windows.h index 661b4a5a66c97..1757fe62a4fba 100644 --- a/shell/platform/windows/public/flutter_windows.h +++ b/shell/platform/windows/public/flutter_windows.h @@ -33,7 +33,7 @@ typedef struct FlutterDesktopView* FlutterDesktopViewRef; // Opaque reference to a Flutter engine instance. typedef struct FlutterDesktopEngineState* FlutterDesktopEngineRef; -// Opaque reference to host specific state +// Opaque reference to runner / host specific state typedef void* HostEnvironmentState; // Properties for configuring a Flutter engine instance. @@ -59,11 +59,14 @@ 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|. // -// View supplied must be integrated into host visual tree +// |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 @@ -75,10 +78,16 @@ V2CreateViewControllerVisual( HostEnvironmentState hoststate); // 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 V2CreateViewControllerWindow( @@ -89,7 +98,8 @@ V2CreateViewControllerWindow( HostEnvironmentState hostwindow ); -// Return backing HWND for manipulation in host application. +// Returns runner / host-specific state supplied when creating a viewcontroller. +// Typically used by plugins FLUTTER_EXPORT HostEnvironmentState V2FlutterDesktopGetHostState(FlutterDesktopViewRef view); @@ -99,21 +109,25 @@ FLUTTER_EXPORT void V2FlutterDesktopSendWindowMetrics(FlutterDesktopViewRef view 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 @@ -138,28 +152,6 @@ FLUTTER_EXPORT void V2FlutterDesktopSendKey(FlutterDesktopViewRef view, int action, char32_t character); - -// Creates a View with the given dimensions running a Flutter Application. -// -// This will set up and run an associated Flutter engine using the settings in -// |engine_properties|. -// -// Returns a null pointer in the event of an error. -//FLUTTER_EXPORT FlutterDesktopViewControllerRef -//FlutterDesktopCreateViewController( -// int width, -// int height, -// const FlutterDesktopEngineProperties& engine_properties); - -//// DEPRECATED. Will be removed soon; switch to the version above. -//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); - // Shuts down the engine instance associated with |controller|, and cleans up // associated state. // @@ -192,16 +184,18 @@ FlutterDesktopProcessMessages(FlutterDesktopViewControllerRef controller); // (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); +// 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); -// 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. 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. From 2f8004960dee740799b3600cc3e35eef7bb5d818 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 May 2020 11:50:30 -0700 Subject: [PATCH 11/13] cleanup --- shell/platform/windows/flutter_comp_view.cc | 606 ------------------ shell/platform/windows/flutter_comp_view.h | 303 --------- .../platform/windows/flutter_windows_view.cc | 2 +- .../platform/windows/win32_flutter_window.cc | 365 ----------- shell/platform/windows/win32_flutter_window.h | 178 ----- shell/platform/windows/win32_window.cc | 312 --------- shell/platform/windows/win32_window.h | 183 ------ 7 files changed, 1 insertion(+), 1948 deletions(-) delete mode 100644 shell/platform/windows/flutter_comp_view.cc delete mode 100644 shell/platform/windows/flutter_comp_view.h delete mode 100644 shell/platform/windows/win32_flutter_window.cc delete mode 100644 shell/platform/windows/win32_flutter_window.h delete mode 100644 shell/platform/windows/win32_window.cc delete mode 100644 shell/platform/windows/win32_window.h diff --git a/shell/platform/windows/flutter_comp_view.cc b/shell/platform/windows/flutter_comp_view.cc deleted file mode 100644 index e640e81d1cd60..0000000000000 --- a/shell/platform/windows/flutter_comp_view.cc +++ /dev/null @@ -1,606 +0,0 @@ -#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_comp_view.h b/shell/platform/windows/flutter_comp_view.h deleted file mode 100644 index 3a6c7b726e648..0000000000000 --- a/shell/platform/windows/flutter_comp_view.h +++ /dev/null @@ -1,303 +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/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); - - Microsoft::WRL::ComPtr - GetFlutterHost(); - - // 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/flutter_windows_view.cc b/shell/platform/windows/flutter_windows_view.cc index 51c93894dcec2..707dff0cfb780 100644 --- a/shell/platform/windows/flutter_windows_view.cc +++ b/shell/platform/windows/flutter_windows_view.cc @@ -1,4 +1,4 @@ -#include "flutter/shell/platform/windows/flutter_comp_view.h" +#include "flutter/shell/platform/windows/flutter_windows_view.h" #include 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_window.cc b/shell/platform/windows/win32_window.cc deleted file mode 100644 index e4cf979167b73..0000000000000 --- a/shell/platform/windows/win32_window.cc +++ /dev/null @@ -1,312 +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 "flutter/shell/platform/windows/win32_window.h" - -#include "dpi_utils.h" - -namespace flutter { - -namespace { -char32_t CodePointFromSurrogatePair(wchar_t high, wchar_t low) { - return 0x10000 + ((static_cast(high) & 0x000003FF) << 10) + - (low & 0x3FF); -} -} // namespace - -Win32Window::Win32Window() { - // 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); -} - -Win32Window::~Win32Window() { - Destroy(); -} - -void Win32Window::InitializeChild(const char* title, - unsigned int width, - unsigned int height) { - Destroy(); - std::wstring converted_title = NarrowToWide(title); - - WNDCLASS window_class = RegisterWindowClass(converted_title); - - auto* result = CreateWindowEx( - 0, window_class.lpszClassName, converted_title.c_str(), - WS_CHILD | WS_VISIBLE, CW_DEFAULT, CW_DEFAULT, width, height, - HWND_MESSAGE, nullptr, window_class.hInstance, this); - - if (result == nullptr) { - auto error = GetLastError(); - LPWSTR message = nullptr; - size_t size = FormatMessageW( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast(&message), 0, NULL); - OutputDebugString(message); - LocalFree(message); - } -} - -std::wstring Win32Window::NarrowToWide(const char* source) { - size_t length = strlen(source); - size_t outlen = 0; - std::wstring wideTitle(length, L'#'); - mbstowcs_s(&outlen, &wideTitle[0], length + 1, source, length); - return wideTitle; -} - -WNDCLASS Win32Window::RegisterWindowClass(std::wstring& title) { - window_class_name_ = title; - - WNDCLASS window_class{}; - window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); - window_class.lpszClassName = title.c_str(); - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = GetModuleHandle(nullptr); - window_class.hIcon = nullptr; - window_class.hbrBackground = 0; - window_class.lpszMenuName = nullptr; - window_class.lpfnWndProc = WndProc; - RegisterClass(&window_class); - return window_class; -} - -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept { - if (message == WM_NCCREATE) { - auto cs = reinterpret_cast(lparam); - SetWindowLongPtr(window, GWLP_USERDATA, - reinterpret_cast(cs->lpCreateParams)); - - auto that = static_cast(cs->lpCreateParams); - that->window_handle_ = window; - } else if (Win32Window* that = GetThisFromHandle(window)) { - return that->MessageHandler(window, message, wparam, lparam); - } - - return DefWindowProc(window, message, wparam, lparam); -} - -void Win32Window::TrackMouseLeaveEvent(HWND hwnd) { - if (!tracking_mouse_leave_) { - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof(tme); - tme.hwndTrack = hwnd; - tme.dwFlags = TME_LEAVE; - TrackMouseEvent(&tme); - tracking_mouse_leave_ = true; - } -} - -LRESULT -Win32Window::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)); - UINT button_pressed = 0; - - if (window != nullptr) { - switch (message) { - case kWmDpiChangedBeforeParent: - current_dpi_ = GetDpiForHWND(window_handle_); - window->OnDpiScale(current_dpi_); - return 0; - case WM_SIZE: - width = LOWORD(lparam); - height = HIWORD(lparam); - - current_width_ = width; - current_height_ = height; - window->HandleResize(width, height); - break; - case WM_FONTCHANGE: - window->OnFontChange(); - break; - case WM_MOUSEMOVE: - window->TrackMouseLeaveEvent(hwnd); - - xPos = GET_X_LPARAM(lparam); - yPos = GET_Y_LPARAM(lparam); - window->OnPointerMove(static_cast(xPos), - static_cast(yPos)); - break; - case WM_MOUSELEAVE:; - window->OnPointerLeave(); - // Once the tracked event is received, the TrackMouseEvent function - // resets. Set to false to make sure it's called once mouse movement is - // detected again. - tracking_mouse_leave_ = false; - break; - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_XBUTTONDOWN: - if (message == WM_LBUTTONDOWN) { - // Capture the pointer in case the user drags outside the client area. - // In this case, the "mouse leave" event is delayed until the user - // releases the button. It's only activated on left click given that - // it's more common for apps to handle dragging with only the left - // button. - SetCapture(hwnd); - } - button_pressed = message; - if (message == WM_XBUTTONDOWN) { - button_pressed = GET_XBUTTON_WPARAM(wparam); - } - xPos = GET_X_LPARAM(lparam); - yPos = GET_Y_LPARAM(lparam); - window->OnPointerDown(static_cast(xPos), - static_cast(yPos), button_pressed); - break; - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - case WM_XBUTTONUP: - if (message == WM_LBUTTONUP) { - ReleaseCapture(); - } - button_pressed = message; - if (message == WM_XBUTTONUP) { - button_pressed = GET_XBUTTON_WPARAM(wparam); - } - xPos = GET_X_LPARAM(lparam); - yPos = GET_Y_LPARAM(lparam); - window->OnPointerUp(static_cast(xPos), - static_cast(yPos), button_pressed); - break; - case WM_MOUSEWHEEL: - window->OnScroll( - 0.0, -(static_cast(HIWORD(wparam)) / (double)WHEEL_DELTA)); - break; - case WM_UNICHAR: { - // Tell third-pary app, we can support Unicode. - if (wparam == UNICODE_NOCHAR) - return TRUE; - // DefWindowProc will send WM_CHAR for this WM_UNICHAR. - break; - } - case WM_DEADCHAR: - case WM_SYSDEADCHAR: - case WM_CHAR: - case WM_SYSCHAR: { - static wchar_t s_pending_high_surrogate = 0; - - wchar_t character = static_cast(wparam); - std::u16string text({character}); - char32_t code_point = character; - if (IS_HIGH_SURROGATE(character)) { - // Save to send later with the trailing surrogate. - s_pending_high_surrogate = character; - } else if (IS_LOW_SURROGATE(character) && - s_pending_high_surrogate != 0) { - text.insert(text.begin(), s_pending_high_surrogate); - // Merge the surrogate pairs for the key event. - code_point = - CodePointFromSurrogatePair(s_pending_high_surrogate, character); - s_pending_high_surrogate = 0; - } - - // Of the messages handled here, only WM_CHAR should be treated as - // characters. WM_SYS*CHAR are not part of text input, and WM_DEADCHAR - // will be incorporated into a later WM_CHAR with the full character. - // Also filter out: - // - Lead surrogates, which like dead keys will be send once combined. - // - ASCII control characters, which are sent as WM_CHAR events for all - // control key shortcuts. - if (message == WM_CHAR && s_pending_high_surrogate == 0 && - character >= u' ') { - window->OnText(text); - } - - // All key presses that generate a character should be sent from - // WM_CHAR. In order to send the full key press information, the keycode - // is persisted in keycode_for_char_message_ obtained from WM_KEYDOWN. - if (keycode_for_char_message_ != 0) { - const unsigned int scancode = (lparam >> 16) & 0xff; - window->OnKey(keycode_for_char_message_, scancode, WM_KEYDOWN, - code_point); - keycode_for_char_message_ = 0; - } - break; - } - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - case WM_KEYUP: - case WM_SYSKEYUP: - const bool is_keydown_message = - (message == WM_KEYDOWN || message == WM_SYSKEYDOWN); - // 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); - if (character > 0 && is_keydown_message) { - keycode_for_char_message_ = wparam; - break; - } - unsigned int keyCode(wparam); - const unsigned int scancode = (lparam >> 16) & 0xff; - // If the key is a modifier, get its side. - if (keyCode == VK_SHIFT || keyCode == VK_MENU || - keyCode == VK_CONTROL) { - keyCode = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); - } - const int action = is_keydown_message ? WM_KEYDOWN : WM_KEYUP; - window->OnKey(keyCode, scancode, action, 0); - break; - } - return DefWindowProc(hwnd, message, wparam, lparam); - } - - return DefWindowProc(window_handle_, message, wparam, lparam); -} - -UINT Win32Window::GetCurrentDPI() { - return current_dpi_; -} - -UINT Win32Window::GetCurrentWidth() { - return current_width_; -} - -UINT Win32Window::GetCurrentHeight() { - return current_height_; -} - -HWND Win32Window::GetWindowHandle() { - return window_handle_; -} - -void Win32Window::Destroy() { - if (window_handle_) { - DestroyWindow(window_handle_); - window_handle_ = nullptr; - } - - UnregisterClass(window_class_name_.c_str(), nullptr); -} - -void Win32Window::HandleResize(UINT width, UINT height) { - current_width_ = width; - current_height_ = height; - OnResize(width, height); -} - -Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { - return reinterpret_cast( - GetWindowLongPtr(window, GWLP_USERDATA)); -} - -} // namespace flutter diff --git a/shell/platform/windows/win32_window.h b/shell/platform/windows/win32_window.h deleted file mode 100644 index d4481d89e2a68..0000000000000 --- a/shell/platform/windows/win32_window.h +++ /dev/null @@ -1,183 +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_WIN32_WINDOW_H_ -#define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WIN32_WINDOW_H_ - -#include -#include - -#include -#include - -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 { - // 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 class abstraction for a high DPI aware Win32 Window. Intended to be -// inherited from by classes that wish to specialize with custom -// rendering and input handling. -class Win32Window { - public: - Win32Window(); - virtual ~Win32Window(); - - // Initializes as a child window with size using |width| and |height| and - // |title| to identify the windowclass. Does not show window, window must be - // parented into window hierarchy by caller. - void InitializeChild(const char* title, - unsigned int width, - unsigned int height); - - HWND GetWindowHandle(); - - protected: - // Converts a c string to a wide unicode string. - std::wstring NarrowToWide(const char* source); - - // Registers a window class with default style attributes, cursor and - // icon. - WNDCLASS RegisterWindowClass(std::wstring& title); - - // OS callback called by message pump. Handles the WM_NCCREATE message which - // is passed when the non-client area is being created and enables automatic - // non-client DPI scaling so that the non-client area automatically - // responsponds to changes in DPI. All other messages are handled by - // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // Processes and route salient window messages for mouse handling, - // size change and DPI. Delegates handling of these to member overloads that - // inheriting classes can handle. - LRESULT - MessageHandler(HWND window, - UINT const message, - WPARAM const wparam, - LPARAM const lparam) noexcept; - - // When WM_DPICHANGE process it using |hWnd|, |wParam|. If - // |top_level| is set, extract the suggested new size from |lParam| and resize - // the window to the new suggested size. If |top_level| is not set, the - // |lParam| will not contain a suggested size hence ignore it. - LRESULT - HandleDpiChange(HWND hWnd, WPARAM wParam, LPARAM lParam, bool top_level); - - // Called when the DPI changes either when a - // user drags the window between monitors of differing DPI or when the user - // manually changes the scale factor. - virtual void OnDpiScale(UINT dpi) = 0; - - // Called when a resize occurs. - virtual void OnResize(UINT width, UINT height) = 0; - - // Called when the pointer moves within the - // window bounds. - virtual void OnPointerMove(double x, double y) = 0; - - // Called when the a mouse button, determined by |button|, goes down. - virtual void OnPointerDown(double x, double y, UINT button) = 0; - - // Called when the a mouse button, determined by |button|, goes from - // down to up - virtual void OnPointerUp(double x, double y, UINT button) = 0; - - // Called when the mouse leaves the window. - virtual void OnPointerLeave() = 0; - - // Called when text input occurs. - virtual void OnText(const std::u16string& text) = 0; - - // Called when raw keyboard input occurs. - virtual void OnKey(int key, int scancode, int action, char32_t character) = 0; - - // Called when mouse scrollwheel input occurs. - virtual void OnScroll(double delta_x, double delta_y) = 0; - - // Called when the system font change. - virtual void OnFontChange() = 0; - - UINT GetCurrentDPI(); - - UINT GetCurrentWidth(); - - UINT GetCurrentHeight(); - - // 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; } - - private: - // Release OS resources asociated with window. - void Destroy(); - - // Activates tracking for a "mouse leave" event. - void TrackMouseLeaveEvent(HWND hwnd); - - // Stores new width and height and calls |OnResize| to notify inheritors - void HandleResize(UINT width, UINT height); - - // Retrieves a class instance pointer for |window| - static Win32Window* GetThisFromHandle(HWND const window) noexcept; - int current_dpi_ = 0; - int current_width_ = 0; - int current_height_ = 0; - - // WM_DPICHANGED_BEFOREPARENT defined in more recent Windows - // SDK - const static long kWmDpiChangedBeforeParent = 0x02E2; - - // Member variable to hold window handle. - HWND window_handle_ = nullptr; - - // Member variable to hold the window title. - std::wstring window_class_name_; - - // 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_; - - // Keeps track of the last key code produced by a WM_KEYDOWN or WM_SYSKEYDOWN - // message. - int keycode_for_char_message_ = 0; -}; - -} // namespace flutter - -#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WIN32_WINDOW_H_ From 8b79aa8fa8977a9f6cc4e3d933c2e3ed5f61a923 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 May 2020 13:40:21 -0700 Subject: [PATCH 12/13] moahr cleanup --- shell/platform/windows/dpi_utils.cc | 129 ------------------ shell/platform/windows/dpi_utils.h | 24 ---- shell/platform/windows/flutter_windows_view.h | 3 - 3 files changed, 156 deletions(-) delete mode 100644 shell/platform/windows/dpi_utils.cc delete mode 100644 shell/platform/windows/dpi_utils.h diff --git a/shell/platform/windows/dpi_utils.cc b/shell/platform/windows/dpi_utils.cc deleted file mode 100644 index 20b706ef2fa95..0000000000000 --- a/shell/platform/windows/dpi_utils.cc +++ /dev/null @@ -1,129 +0,0 @@ -#include "dpi_utils.h" - -namespace flutter { - -namespace { - -constexpr UINT kDefaultDpi = 96; - -// This is the MDT_EFFECTIVE_DPI value from MONITOR_DPI_TYPE, an enum declared -// in ShellScalingApi.h. Replicating here to avoid importing the library -// directly. -constexpr UINT kEffectiveDpiMonitorType = 0; - -template - -/// Retrieves a function |name| from a given |comBaseModule| into |outProc|. -/// Returns a bool indicating whether the function was found. -bool AssignProcAddress(HMODULE comBaseModule, const char* name, T*& outProc) { - outProc = reinterpret_cast(GetProcAddress(comBaseModule, name)); - return *outProc != nullptr; -} - -/// A helper class for abstracting various Windows DPI related functions across -/// Windows OS versions. -class Win32DpiHelper { - public: - Win32DpiHelper(); - - ~Win32DpiHelper(); - - /// Returns the DPI for |hwnd|. Supports all DPI awareness modes, and is - /// backward compatible down to Windows Vista. If |hwnd| is nullptr, returns - /// the DPI for the primary monitor. If Per-Monitor DPI awareness is not - /// available, returns the system's DPI. - UINT GetDpiForWindow(HWND); - - /// Returns the DPI of a given monitor. Defaults to 96 if the API is not - /// available. - UINT GetDpiForMonitor(HMONITOR); - - private: - using GetDpiForWindow_ = UINT __stdcall(HWND); - using GetDpiForMonitor_ = HRESULT __stdcall(HMONITOR hmonitor, - UINT dpiType, - UINT* dpiX, - UINT* dpiY); - using EnableNonClientDpiScaling_ = BOOL __stdcall(HWND hwnd); - - GetDpiForWindow_* get_dpi_for_window_ = nullptr; - GetDpiForMonitor_* get_dpi_for_monitor_ = nullptr; - EnableNonClientDpiScaling_* enable_non_client_dpi_scaling_ = nullptr; - - HMODULE user32_module_ = nullptr; - HMODULE shlib_module_ = nullptr; - bool dpi_for_window_supported_ = false; - bool dpi_for_monitor_supported_ = false; -}; - -Win32DpiHelper::Win32DpiHelper() { - if ((user32_module_ = LoadLibraryA("User32.dll")) != nullptr) { - dpi_for_window_supported_ = (AssignProcAddress( - user32_module_, "GetDpiForWindow", get_dpi_for_window_)); - } - if ((shlib_module_ = LoadLibraryA("Shcore.dll")) != nullptr) { - dpi_for_monitor_supported_ = AssignProcAddress( - shlib_module_, "GetDpiForMonitor", get_dpi_for_monitor_); - } -} - -Win32DpiHelper::~Win32DpiHelper() { - if (user32_module_ != nullptr) { - FreeLibrary(user32_module_); - } - if (shlib_module_ != nullptr) { - FreeLibrary(shlib_module_); - } -} - -UINT Win32DpiHelper::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. - if (dpi_for_window_supported_ && hwnd != nullptr) { - return get_dpi_for_window_(hwnd); - } - - if (dpi_for_monitor_supported_) { - HMONITOR monitor = nullptr; - if (hwnd != nullptr) { - monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); - } - return GetDpiForMonitor(monitor); - } - HDC hdc = GetDC(hwnd); - UINT dpi = GetDeviceCaps(hdc, LOGPIXELSX); - ReleaseDC(hwnd, hdc); - return dpi; -} - -UINT Win32DpiHelper::GetDpiForMonitor(HMONITOR monitor) { - if (dpi_for_monitor_supported_) { - if (monitor == nullptr) { - const POINT target_point = {0, 0}; - monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTOPRIMARY); - } - UINT dpi_x = 0, dpi_y = 0; - HRESULT result = - get_dpi_for_monitor_(monitor, kEffectiveDpiMonitorType, &dpi_x, &dpi_y); - if (SUCCEEDED(result)) { - return dpi_x; - } - } - return kDefaultDpi; -} // namespace - -Win32DpiHelper* GetHelper() { - static Win32DpiHelper* dpi_helper = new Win32DpiHelper(); - return dpi_helper; -} -} // namespace - -UINT GetDpiForHWND(HWND hwnd) { - return GetHelper()->GetDpiForWindow(hwnd); -} - -UINT GetDpiForMonitor(HMONITOR monitor) { - return GetHelper()->GetDpiForMonitor(monitor); -} -} // namespace flutter diff --git a/shell/platform/windows/dpi_utils.h b/shell/platform/windows/dpi_utils.h deleted file mode 100644 index 1c14994b61235..0000000000000 --- a/shell/platform/windows/dpi_utils.h +++ /dev/null @@ -1,24 +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 "Windows.h" - -#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_DPI_UTILS_H_ -#define FLUTTER_SHELL_PLATFORM_WINDOWS_DPI_UTILS_H_ - -namespace flutter { - -/// Returns the DPI for |hwnd|. Supports all DPI awareness modes, and is -/// backward compatible down to Windows Vista. If |hwnd| is nullptr, returns the -/// DPI for the primary monitor. If Per-Monitor DPI awareness is not available, -/// returns the system's DPI. -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 flutter - -#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_DPI_UTILS_H_ diff --git a/shell/platform/windows/flutter_windows_view.h b/shell/platform/windows/flutter_windows_view.h index 3a6c7b726e648..fd975586d3b3a 100644 --- a/shell/platform/windows/flutter_windows_view.h +++ b/shell/platform/windows/flutter_windows_view.h @@ -150,9 +150,6 @@ class FlutterWindowsView { // dimensions in physical void SendWindowMetrics(size_t width, size_t height, double dpiscale); - Microsoft::WRL::ComPtr - GetFlutterHost(); - // TODO void OnPointerMove(double x, double y); From cd36a5150f92d7251e4066a4e9c1fb20c4913532 Mon Sep 17 00:00:00 2001 From: James Clarke Date: Sun, 3 May 2020 14:53:33 -0700 Subject: [PATCH 13/13] Clang-format --- .../platform/windows/angle_surface_manager.h | 1 - .../windows/flutter_compview_unittests.cc | 4 +- shell/platform/windows/flutter_windows.cc | 61 ++++++++------- .../platform/windows/flutter_windows_view.cc | 77 +++++++++++-------- shell/platform/windows/flutter_windows_view.h | 6 +- shell/platform/windows/platform_handler.cc | 11 ++- shell/platform/windows/task_runner.cc | 4 +- shell/platform/windows/task_runner.h | 3 +- shell/platform/windows/window_state_comp.h | 4 +- 9 files changed, 88 insertions(+), 83 deletions(-) diff --git a/shell/platform/windows/angle_surface_manager.h b/shell/platform/windows/angle_surface_manager.h index bc6ad742db4cd..1c65d53032e22 100644 --- a/shell/platform/windows/angle_surface_manager.h +++ b/shell/platform/windows/angle_surface_manager.h @@ -39,7 +39,6 @@ class AngleSurfaceManager { 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/flutter_compview_unittests.cc b/shell/platform/windows/flutter_compview_unittests.cc index 818135ded173a..dd33d993bf5b5 100644 --- a/shell/platform/windows/flutter_compview_unittests.cc +++ b/shell/platform/windows/flutter_compview_unittests.cc @@ -9,8 +9,8 @@ TEST(FlutterWindowsViewTest, CreateDestroy) { ASSERT_TRUE(TRUE); } -//TODO MOVE to wrapper -//TEST(FlutterWindowsViewTest, CanFontChange) { +// TODO MOVE to wrapper +// TEST(FlutterWindowsViewTest, CanFontChange) { // FlutterWindowsViewTest window(800, 600); // HWND hwnd = window.GetWindowHandle(); // LRESULT result = SendMessage(hwnd, WM_FONTCHANGE, NULL, NULL); diff --git a/shell/platform/windows/flutter_windows.cc b/shell/platform/windows/flutter_windows.cc index 8bf65f907302a..3f42bae0e7f95 100644 --- a/shell/platform/windows/flutter_windows.cc +++ b/shell/platform/windows/flutter_windows.cc @@ -20,12 +20,12 @@ #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/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/text_input_plugin.h" #include "flutter/shell/platform/windows/task_runner.h" -#include "flutter/shell/platform/windows/flutter_windows_view.h" +#include "flutter/shell/platform/windows/text_input_plugin.h" static_assert(FLUTTER_ENGINE_VERSION == 1, ""); @@ -158,7 +158,7 @@ V2FlutterDesktopViewControllerRef V2CreateViewControllerVisual( HostEnvironmentState externalWindow) { V2FlutterDesktopViewControllerRef state = flutter::FlutterWindowsView::CreateFlutterWindowsView(width, height, - visual); + visual); auto engine_state = RunFlutterEngine(state->view.get(), engine_properties); @@ -176,10 +176,10 @@ V2FlutterDesktopViewControllerRef V2CreateViewControllerWindow( int height, const FlutterDesktopEngineProperties& engine_properties, HWND windowrendertarget, - HostEnvironmentState externalWindow - ) { + HostEnvironmentState externalWindow) { V2FlutterDesktopViewControllerRef state = - flutter::FlutterWindowsView::CreateFlutterWindowsViewHwnd(width, height, externalWindow, static_cast(windowrendertarget)); + flutter::FlutterWindowsView::CreateFlutterWindowsViewHwnd( + width, height, externalWindow, static_cast(windowrendertarget)); auto engine_state = RunFlutterEngine(state->view.get(), engine_properties); @@ -193,30 +193,30 @@ V2FlutterDesktopViewControllerRef V2CreateViewControllerWindow( } void V2FlutterDesktopSendWindowMetrics(FlutterDesktopViewRef view, - size_t width, - size_t height, - double dpiScale) { + size_t width, + size_t height, + double dpiScale) { view->window->SendWindowMetrics(width, height, dpiScale); } void V2FlutterDesktopSendPointerMove(FlutterDesktopViewRef view, - double x, - double y) { + double x, + double y) { view->window->OnPointerMove(x, y); } void V2FlutterDesktopSendPointerDown(FlutterDesktopViewRef view, - double x, - double y, - uint64_t btn) { + 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) { + double x, + double y, + uint64_t btn) { view->window->OnPointerUp(x, y, static_cast(btn)); } @@ -252,17 +252,16 @@ FlutterDesktopViewRef FlutterDesktopGetView( } // TODO return something more strongly typed -HostEnvironmentState V2FlutterDesktopGetHostState( - FlutterDesktopViewRef view) { +HostEnvironmentState V2FlutterDesktopGetHostState(FlutterDesktopViewRef view) { return (HostEnvironmentState)view->externalwindow; } // TODO void V2FlutterDesktopSendScroll(FlutterDesktopViewRef view, - double x, - double y, - double delta_x, - double delta_y) { + double x, + double y, + double delta_x, + double delta_y) { view->window->OnScroll(x, y, delta_x, delta_y); } @@ -273,8 +272,8 @@ void V2FlutterDesktopSendFontChange(FlutterDesktopViewRef view) { // TODO void V2FlutterDesktopSendText(FlutterDesktopViewRef view, - const char16_t* code_point, - size_t size) { + const char16_t* code_point, + size_t size) { std::u16string str; str.append(code_point, size); view->window->OnText(str); @@ -282,10 +281,10 @@ void V2FlutterDesktopSendText(FlutterDesktopViewRef view, // TODO void V2FlutterDesktopSendKey(FlutterDesktopViewRef view, - int key, - int scancode, - int action, - char32_t character) { + int key, + int scancode, + int action, + char32_t character) { view->window->OnKey(key, scancode, action, character); } @@ -301,14 +300,14 @@ void FlutterDesktopResyncOutputStreams() { } ////TODO: do we still need this? Appears to be dead code -//FlutterDesktopEngineRef FlutterDesktopRunEngine( +// 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) { +// bool FlutterDesktopShutDownEngine(FlutterDesktopEngineRef engine_ref) { // std::cout << "Shutting down flutter engine process." << std::endl; // auto result = FlutterEngineShutdown(engine_ref->engine); // delete engine_ref; diff --git a/shell/platform/windows/flutter_windows_view.cc b/shell/platform/windows/flutter_windows_view.cc index 707dff0cfb780..3b69e8214c5dd 100644 --- a/shell/platform/windows/flutter_windows_view.cc +++ b/shell/platform/windows/flutter_windows_view.cc @@ -17,20 +17,18 @@ FlutterWindowsView::FlutterWindowsView(int width, int height) { FlutterWindowsView::~FlutterWindowsView() { DestroyRenderSurface(); - if (plugin_registrar_ && plugin_registrar_->destruction_handler) { + 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) { - +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 = std::make_unique(width, height); state->view->window_rendertarget_ = windowrendertarget; @@ -54,14 +52,15 @@ FlutterDesktopViewControllerRef FlutterWindowsView::CreateFlutterWindowsView( 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 + // 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); @@ -70,7 +69,8 @@ FlutterDesktopViewControllerRef FlutterWindowsView::CreateFlutterWindowsView( return state.release(); } -void FlutterWindowsView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng, void* externalwindow) { +void FlutterWindowsView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng, + void* externalwindow) { engine_ = eng; auto messenger = std::make_unique(); @@ -131,9 +131,9 @@ void FlutterWindowsView::HandlePlatformMessage( auto message = ConvertToDesktopMessage(*engine_message); - message_dispatcher_->HandleMessage(message, - [this] { this->process_events_ = false; }, - [this] { this->process_events_ = true; }); + message_dispatcher_->HandleMessage( + message, [this] { this->process_events_ = false; }, + [this] { this->process_events_ = true; }); } void FlutterWindowsView::OnPointerMove(double x, double y) { @@ -142,22 +142,24 @@ void FlutterWindowsView::OnPointerMove(double x, double y) { } } -void FlutterWindowsView::OnPointerDown(double x, - double y, - FlutterPointerMouseButtons flutter_button) { +void FlutterWindowsView::OnPointerDown( + double x, + double y, + FlutterPointerMouseButtons flutter_button) { if (process_events_) { - if (flutter_button != 0) { + 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_) { +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); @@ -187,7 +189,10 @@ void FlutterWindowsView::OnKey(int key, } } -void FlutterWindowsView::OnScroll(double x, double y, double delta_x, double delta_y) { +void FlutterWindowsView::OnScroll(double x, + double y, + double delta_x, + double delta_y) { if (process_events_) { SendScroll(x, y, delta_x, delta_y); } @@ -201,7 +206,9 @@ void FlutterWindowsView::OnFontChange() { } // Sends new size information to FlutterEngine. -void FlutterWindowsView::SendWindowMetrics(size_t width, size_t height, double dpiScale) { +void FlutterWindowsView::SendWindowMetrics(size_t width, + size_t height, + double dpiScale) { if (engine_ == nullptr) { return; } @@ -210,7 +217,7 @@ void FlutterWindowsView::SendWindowMetrics(size_t width, size_t height, double d event.struct_size = sizeof(event); event.width = width; event.height = height; - event.pixel_ratio = dpiScale; + event.pixel_ratio = dpiScale; auto result = FlutterEngineSendWindowMetricsEvent(engine_, &event); if (flutter_host_ != nullptr) { @@ -257,7 +264,7 @@ void FlutterWindowsView::SendPointerUp(double x, double y) { event.y = y; SendPointerEventWithData(event); if (event.phase == FlutterPointerPhase::kUp) { - SetMouseFlutterStateDown(false); + SetMouseFlutterStateDown(false); } } @@ -279,7 +286,10 @@ void FlutterWindowsView::SendKey(int key, int scancode, int action, int mods) { } } -void FlutterWindowsView::SendScroll(double x, double y, double delta_x, double delta_y) { +void FlutterWindowsView::SendScroll(double x, + double y, + double delta_x, + double delta_y) { FlutterPointerEvent event = {}; SetEventPhaseFromCursorButtonState(&event); event.signal_kind = FlutterPointerSignalKind::kFlutterPointerSignalKindScroll; @@ -295,7 +305,7 @@ void FlutterWindowsView::SendScroll(double x, double y, double delta_x, double d void FlutterWindowsView::SendPointerEventWithData( const FlutterPointerEvent& event_data) { - //TODO + // 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. @@ -370,10 +380,8 @@ void FlutterWindowsView::CreateRenderSurfaceHWND() { } void FlutterWindowsView::CreateRenderSurfaceUWP() { - if (surface_manager && render_surface == EGL_NO_SURFACE) { - - //TODO: replace ROHelper with regen'd c++/WinRT with downlevel + // TODO: replace ROHelper with regen'd c++/WinRT with downlevel RoHelper helper; HSTRING act; HSTRING_HEADER header; @@ -382,7 +390,8 @@ void FlutterWindowsView::CreateRenderSurfaceUWP() { {static_cast(width_), static_cast(height_)}); render_surface = surface_manager->CreateSurface( - static_cast(winrt::get_abi(flutter_host_))); + static_cast( + winrt::get_abi(flutter_host_))); } } diff --git a/shell/platform/windows/flutter_windows_view.h b/shell/platform/windows/flutter_windows_view.h index fd975586d3b3a..12f195c044b3c 100644 --- a/shell/platform/windows/flutter_windows_view.h +++ b/shell/platform/windows/flutter_windows_view.h @@ -104,8 +104,8 @@ struct MouseState { 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 +// 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 @@ -286,7 +286,7 @@ class FlutterWindowsView { // flag indicating if the message loop should be running bool messageloop_running_ = false; - winrt::Windows::UI::Composition::Compositor compositor_ {nullptr}; + winrt::Windows::UI::Composition::Compositor compositor_{nullptr}; winrt::Windows::UI::Composition::Visual flutter_host_{nullptr}; diff --git a/shell/platform/windows/platform_handler.cc b/shell/platform/windows/platform_handler.cc index a858d4dfb7c7f..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/string_conversion.h" #include "flutter/shell/platform/windows/flutter_windows_view.h" +#include "flutter/shell/platform/windows/string_conversion.h" static constexpr char kChannelName[] = "flutter/platform"; @@ -215,12 +215,11 @@ PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger, void PlatformHandler::HandleMethodCall( const flutter::MethodCall& method_call, std::unique_ptr> result) { + result->NotImplemented(); + return; - result->NotImplemented(); - return; - - //const std::string& method = method_call.method_name(); - //if (method.compare(kGetClipboardDataMethod) == 0) { + // 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]; diff --git a/shell/platform/windows/task_runner.cc b/shell/platform/windows/task_runner.cc index a89470474f490..377f890869cce 100644 --- a/shell/platform/windows/task_runner.cc +++ b/shell/platform/windows/task_runner.cc @@ -10,7 +10,7 @@ namespace flutter { TaskRunner::TaskRunner(DWORD main_thread_id, - const TaskExpiredCallback& on_task_expired) + const TaskExpiredCallback& on_task_expired) : main_thread_id_(main_thread_id), on_task_expired_(std::move(on_task_expired)) {} @@ -74,7 +74,7 @@ TaskRunner::TaskTimePoint TaskRunner::TimePointFromFlutterTime( } void TaskRunner::PostTask(FlutterTask flutter_task, - uint64_t flutter_target_time_nanos) { + uint64_t flutter_target_time_nanos) { static std::atomic_uint64_t sGlobalTaskOrder(0); Task task; diff --git a/shell/platform/windows/task_runner.h b/shell/platform/windows/task_runner.h index b361204324088..e24afaff87369 100644 --- a/shell/platform/windows/task_runner.h +++ b/shell/platform/windows/task_runner.h @@ -24,8 +24,7 @@ namespace flutter { class TaskRunner { public: using TaskExpiredCallback = std::function; - TaskRunner(DWORD main_thread_id, - const TaskExpiredCallback& on_task_expired); + TaskRunner(DWORD main_thread_id, const TaskExpiredCallback& on_task_expired); ~TaskRunner(); diff --git a/shell/platform/windows/window_state_comp.h b/shell/platform/windows/window_state_comp.h index c91d3126de9b8..908dad30895d8 100644 --- a/shell/platform/windows/window_state_comp.h +++ b/shell/platform/windows/window_state_comp.h @@ -11,11 +11,11 @@ #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/text_input_plugin.h" #include "flutter/shell/platform/windows/task_runner.h" +#include "flutter/shell/platform/windows/text_input_plugin.h" namespace flutter { - struct FlutterWindowsView; +struct FlutterWindowsView; } // Struct for storing state within an instance of the windows native (HWND or