未验证 提交 d0d6a4c2 编写于 作者: J James Clarke 提交者: GitHub

Refactor Win32FlutterWindow in preparation for UWP windowing implementation (#18878)

* Add flutter_windows_view and window_binding_handler

Switch input handling infra to FlutterWindowsView

win32_flutter_window implement WindowBindingHandler

Strip unneeded functionality from win32flutterwindow

Fulfill WindowBindingHandler interface in Win32FlutterWindow

Add implementations for missing input handling in Win32FlutterWindow

Cleanup dead code

Correctly hook up rendering again

Fix resizing

clang-format

Fix clipboard

Cleanup

Rename

Add comments

cleanup

* clang-format

* CR Feedback

* clang-format; gn format

* Fix licensing

* CR feedback

* CR feedback

* CR feedback

* Git rid of unnecessar :: prefixes

* Extract WindowBindingHandlerDelegate as an interface

* Missing file

* Extract physical window bounds as a struct

* CR Feedback

* CR feedback

* clang-format
Co-authored-by: NStuart Morgan <stuartmorgan@google.com>
上级 110a5798
......@@ -1306,29 +1306,33 @@ FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flu
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_view_controller.h
FILE: ../../../flutter/shell/platform/windows/client_wrapper/include/flutter/plugin_registrar_windows.h
FILE: ../../../flutter/shell/platform/windows/client_wrapper/plugin_registrar_windows_unittests.cc
FILE: ../../../flutter/shell/platform/windows/dpi_utils.cc
FILE: ../../../flutter/shell/platform/windows/dpi_utils.h
FILE: ../../../flutter/shell/platform/windows/dpi_utils_unittests.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.h
FILE: ../../../flutter/shell/platform/windows/key_event_handler.cc
FILE: ../../../flutter/shell/platform/windows/key_event_handler.h
FILE: ../../../flutter/shell/platform/windows/keyboard_hook_handler.h
FILE: ../../../flutter/shell/platform/windows/platform_handler.cc
FILE: ../../../flutter/shell/platform/windows/platform_handler.h
FILE: ../../../flutter/shell/platform/windows/public/flutter_windows.h
FILE: ../../../flutter/shell/platform/windows/string_conversion.cc
FILE: ../../../flutter/shell/platform/windows/string_conversion.h
FILE: ../../../flutter/shell/platform/windows/string_conversion_unittests.cc
FILE: ../../../flutter/shell/platform/windows/text_input_plugin.cc
FILE: ../../../flutter/shell/platform/windows/text_input_plugin.h
FILE: ../../../flutter/shell/platform/windows/win32_dpi_utils.cc
FILE: ../../../flutter/shell/platform/windows/win32_dpi_utils.h
FILE: ../../../flutter/shell/platform/windows/win32_dpi_utils_unittests.cc
FILE: ../../../flutter/shell/platform/windows/win32_flutter_window.cc
FILE: ../../../flutter/shell/platform/windows/win32_flutter_window.h
FILE: ../../../flutter/shell/platform/windows/win32_flutter_window_unittests.cc
FILE: ../../../flutter/shell/platform/windows/win32_platform_handler.cc
FILE: ../../../flutter/shell/platform/windows/win32_platform_handler.h
FILE: ../../../flutter/shell/platform/windows/win32_task_runner.cc
FILE: ../../../flutter/shell/platform/windows/win32_task_runner.h
FILE: ../../../flutter/shell/platform/windows/win32_window.cc
FILE: ../../../flutter/shell/platform/windows/win32_window.h
FILE: ../../../flutter/shell/platform/windows/win32_window_unittests.cc
FILE: ../../../flutter/shell/platform/windows/window_binding_handler.h
FILE: ../../../flutter/shell/platform/windows/window_binding_handler_delegate.h
FILE: ../../../flutter/shell/platform/windows/window_state.h
FILE: ../../../flutter/shell/profiling/sampling_profiler.cc
FILE: ../../../flutter/shell/profiling/sampling_profiler.h
......
......@@ -41,24 +41,28 @@ source_set("flutter_windows_source") {
sources = [
"angle_surface_manager.cc",
"angle_surface_manager.h",
"dpi_utils.cc",
"dpi_utils.h",
"flutter_windows.cc",
"flutter_windows_view.cc",
"flutter_windows_view.h",
"key_event_handler.cc",
"key_event_handler.h",
"keyboard_hook_handler.h",
"platform_handler.cc",
"platform_handler.h",
"string_conversion.cc",
"string_conversion.h",
"text_input_plugin.cc",
"text_input_plugin.h",
"win32_dpi_utils.cc",
"win32_dpi_utils.h",
"win32_flutter_window.cc",
"win32_flutter_window.h",
"win32_platform_handler.cc",
"win32_platform_handler.h",
"win32_task_runner.cc",
"win32_task_runner.h",
"win32_window.cc",
"win32_window.h",
"window_binding_handler.h",
"window_binding_handler_delegate.h",
"window_state.h",
]
......@@ -110,12 +114,12 @@ 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_dpi_utils_unittests.cc",
"win32_flutter_window_unittests.cc",
"win32_window_unittests.cc",
]
......
......@@ -169,46 +169,52 @@ void AngleSurfaceManager::CleanUp() {
}
}
EGLSurface AngleSurfaceManager::CreateSurface(HWND window) {
if (!window || !initialize_succeeded_) {
return EGL_NO_SURFACE;
bool AngleSurfaceManager::CreateSurface(WindowsRenderTarget* render_target) {
if (!render_target || !initialize_succeeded_) {
return false;
}
EGLSurface surface = EGL_NO_SURFACE;
const EGLint surfaceAttributes[] = {EGL_NONE};
surface = eglCreateWindowSurface(egl_display_, egl_config_,
static_cast<EGLNativeWindowType>(window),
surfaceAttributes);
surface = eglCreateWindowSurface(
egl_display_, egl_config_,
static_cast<EGLNativeWindowType>(std::get<HWND>(*render_target)),
surfaceAttributes);
if (surface == EGL_NO_SURFACE) {
std::cerr << "Surface creation failed." << std::endl;
}
return surface;
render_surface_ = surface;
return true;
}
void AngleSurfaceManager::GetSurfaceDimensions(const EGLSurface surface,
EGLint* width,
EGLint* height) {
if (surface == EGL_NO_SURFACE || !initialize_succeeded_) {
void AngleSurfaceManager::GetSurfaceDimensions(EGLint* width, EGLint* height) {
if (render_surface_ == EGL_NO_SURFACE || !initialize_succeeded_) {
width = 0;
height = 0;
return;
}
eglQuerySurface(egl_display_, surface, EGL_WIDTH, width);
eglQuerySurface(egl_display_, surface, EGL_HEIGHT, height);
eglQuerySurface(egl_display_, render_surface_, EGL_WIDTH, width);
eglQuerySurface(egl_display_, render_surface_, EGL_HEIGHT, height);
}
void AngleSurfaceManager::DestroySurface(const EGLSurface surface) {
if (egl_display_ != EGL_NO_DISPLAY && surface != EGL_NO_SURFACE) {
eglDestroySurface(egl_display_, surface);
void AngleSurfaceManager::DestroySurface() {
if (egl_display_ != EGL_NO_DISPLAY && render_surface_ != EGL_NO_SURFACE) {
eglDestroySurface(egl_display_, render_surface_);
}
render_surface_ = EGL_NO_SURFACE;
}
bool AngleSurfaceManager::MakeCurrent() {
return (eglMakeCurrent(egl_display_, render_surface_, render_surface_,
egl_context_) == EGL_TRUE);
}
bool AngleSurfaceManager::MakeCurrent(const EGLSurface surface) {
return (eglMakeCurrent(egl_display_, surface, surface, egl_context_) ==
bool AngleSurfaceManager::ClearContext() {
return (eglMakeCurrent(egl_display_, nullptr, nullptr, egl_context_) ==
EGL_TRUE);
}
......@@ -217,8 +223,8 @@ bool AngleSurfaceManager::MakeResourceCurrent() {
egl_resource_context_) == EGL_TRUE);
}
EGLBoolean AngleSurfaceManager::SwapBuffers(const EGLSurface surface) {
return (eglSwapBuffers(egl_display_, surface));
EGLBoolean AngleSurfaceManager::SwapBuffers() {
return (eglSwapBuffers(egl_display_, render_surface_));
}
} // namespace flutter
......@@ -15,9 +15,11 @@
// Windows platform specific includes
#include <windows.h>
#include "window_binding_handler.h"
namespace flutter {
// An manager for inializing ANGLE correctly and using it to create and
// A manager for inializing ANGLE correctly and using it to create and
// destroy surfaces
class AngleSurfaceManager {
public:
......@@ -28,23 +30,24 @@ class AngleSurfaceManager {
AngleSurfaceManager(const AngleSurfaceManager&) = delete;
AngleSurfaceManager& operator=(const AngleSurfaceManager&) = delete;
// Creates and returns an EGLSurface wrapper and backing DirectX 11 SwapChain
// asociated with window, in the appropriate format for display in a
// HWND-backed window.
EGLSurface CreateSurface(HWND window);
// Creates an EGLSurface wrapper and backing DirectX 11 SwapChain
// asociated with window, in the appropriate format for display.
// Target represents the visual entity to bind to.
bool CreateSurface(WindowsRenderTarget* render_target);
// queries EGL for the dimensions of surface in physical
// pixels returning width and height as out params.
void GetSurfaceDimensions(const EGLSurface surface,
EGLint* width,
EGLint* height);
void GetSurfaceDimensions(EGLint* width, EGLint* height);
// Releases the pass-in EGLSurface wrapping and backing resources if not null.
void DestroySurface(const EGLSurface surface);
void DestroySurface();
// Binds egl_context_ to the current rendering thread and to the draw and read
// surfaces returning a boolean result reflecting success.
bool MakeCurrent(const EGLSurface surface);
bool MakeCurrent();
// Clears current egl_context_
bool ClearContext();
// Binds egl_resource_context_ to the current rendering thread and to the draw
// and read surfaces returning a boolean result reflecting success.
......@@ -52,7 +55,7 @@ class AngleSurfaceManager {
// Swaps the front and back buffers of the DX11 swapchain backing surface if
// not null.
EGLBoolean SwapBuffers(const EGLSurface surface);
EGLBoolean SwapBuffers();
private:
bool Initialize();
......@@ -75,6 +78,9 @@ class AngleSurfaceManager {
// State representing success or failure of display initialization used when
// creating surfaces.
bool initialize_succeeded_;
// Current render_surface that engine will draw into.
EGLSurface render_surface_ = EGL_NO_SURFACE;
};
} // namespace flutter
......
......@@ -19,13 +19,15 @@
#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h"
#include "flutter/shell/platform/common/cpp/path_utils.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/dpi_utils.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/key_event_handler.h"
#include "flutter/shell/platform/windows/keyboard_hook_handler.h"
#include "flutter/shell/platform/windows/platform_handler.h"
#include "flutter/shell/platform/windows/text_input_plugin.h"
#include "flutter/shell/platform/windows/win32_dpi_utils.h"
#include "flutter/shell/platform/windows/win32_flutter_window.h"
#include "flutter/shell/platform/windows/win32_platform_handler.h"
#include "flutter/shell/platform/windows/win32_task_runner.h"
#include "flutter/shell/platform/windows/window_binding_handler.h"
#include "flutter/shell/platform/windows/window_state.h"
static_assert(FLUTTER_ENGINE_VERSION == 1, "");
......@@ -66,7 +68,7 @@ UniqueAotDataPtr LoadAotData(std::filesystem::path aot_data_path) {
// Returns the state object for the engine, or null on failure to start the
// engine.
static std::unique_ptr<FlutterDesktopEngineState> RunFlutterEngine(
flutter::Win32FlutterWindow* window,
flutter::FlutterWindowsView* view,
const FlutterDesktopEngineProperties& engine_properties) {
auto state = std::make_unique<FlutterDesktopEngineState>();
......@@ -79,22 +81,22 @@ static std::unique_ptr<FlutterDesktopEngineState> RunFlutterEngine(
&engine_properties.switches[engine_properties.switches_count]);
}
window->CreateRenderSurface();
view->CreateRenderSurface();
// Provide the necessary callbacks for rendering within a win32 child window.
FlutterRendererConfig config = {};
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<flutter::Win32FlutterWindow*>(user_data);
auto host = static_cast<flutter::FlutterWindowsView*>(user_data);
return host->MakeCurrent();
};
config.open_gl.clear_current = [](void* user_data) -> bool {
auto host = static_cast<flutter::Win32FlutterWindow*>(user_data);
auto host = static_cast<flutter::FlutterWindowsView*>(user_data);
return host->ClearContext();
};
config.open_gl.present = [](void* user_data) -> bool {
auto host = static_cast<flutter::Win32FlutterWindow*>(user_data);
auto host = static_cast<flutter::FlutterWindowsView*>(user_data);
return host->SwapBuffers();
};
config.open_gl.fbo_callback = [](void* user_data) -> uint32_t { return 0; };
......@@ -103,7 +105,7 @@ static std::unique_ptr<FlutterDesktopEngineState> RunFlutterEngine(
return reinterpret_cast<void*>(eglGetProcAddress(what));
};
config.open_gl.make_resource_current = [](void* user_data) -> bool {
auto host = static_cast<flutter::Win32FlutterWindow*>(user_data);
auto host = static_cast<flutter::FlutterWindowsView*>(user_data);
return host->MakeResourceCurrent();
};
......@@ -178,7 +180,7 @@ static std::unique_ptr<FlutterDesktopEngineState> RunFlutterEngine(
args.platform_message_callback =
[](const FlutterPlatformMessage* engine_message,
void* user_data) -> void {
auto window = reinterpret_cast<flutter::Win32FlutterWindow*>(user_data);
auto window = reinterpret_cast<flutter::FlutterWindowsView*>(user_data);
return window->HandlePlatformMessage(engine_message);
};
args.custom_task_runners = &custom_task_runners;
......@@ -188,7 +190,7 @@ static std::unique_ptr<FlutterDesktopEngineState> RunFlutterEngine(
FLUTTER_API_SYMBOL(FlutterEngine) engine = nullptr;
auto result =
FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, &args, window, &engine);
FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, &args, view, &engine);
if (result != kSuccess || engine == nullptr) {
std::cerr << "Failed to start Flutter engine: error " << result
<< std::endl;
......@@ -202,8 +204,12 @@ FlutterDesktopViewControllerRef FlutterDesktopCreateViewController(
int width,
int height,
const FlutterDesktopEngineProperties& engine_properties) {
std::unique_ptr<flutter::WindowBindingHandler> window_wrapper =
std::make_unique<flutter::Win32FlutterWindow>(width, height);
FlutterDesktopViewControllerRef state =
flutter::Win32FlutterWindow::CreateWin32FlutterWindow(width, height);
flutter::FlutterWindowsView::CreateFlutterWindowsView(
std::move(window_wrapper));
auto engine_state = RunFlutterEngine(state->view.get(), engine_properties);
......@@ -261,8 +267,8 @@ FlutterDesktopViewRef FlutterDesktopGetView(
return controller->view_wrapper.get();
}
HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view) {
return view->window->GetWindowHandle();
HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view_ref) {
return std::get<HWND>(*view_ref->view->GetRenderTarget());
}
UINT FlutterDesktopGetDpiForHWND(HWND hwnd) {
......@@ -316,7 +322,7 @@ void FlutterDesktopRegistrarSetDestructionHandler(
FlutterDesktopViewRef FlutterDesktopRegistrarGetView(
FlutterDesktopPluginRegistrarRef registrar) {
return registrar->window;
return registrar->view;
}
bool FlutterDesktopMessengerSendWithReply(FlutterDesktopMessengerRef messenger,
......
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include <chrono>
namespace flutter {
FlutterWindowsView::FlutterWindowsView() {
surface_manager_ = std::make_unique<AngleSurfaceManager>();
}
FlutterWindowsView::~FlutterWindowsView() {
DestroyRenderSurface();
if (plugin_registrar_ && plugin_registrar_->destruction_handler) {
plugin_registrar_->destruction_handler(plugin_registrar_.get());
}
}
FlutterDesktopViewControllerRef FlutterWindowsView::CreateFlutterWindowsView(
std::unique_ptr<WindowBindingHandler> windowbinding) {
auto state = std::make_unique<FlutterDesktopViewControllerState>();
state->view = std::make_unique<flutter::FlutterWindowsView>();
// FlutterWindowsView instance owns windowbinding
state->view->binding_handler_ = std::move(windowbinding);
// a window wrapper for the state block, distinct from the
// window_wrapper handed to plugin_registrar.
state->view_wrapper = std::make_unique<FlutterDesktopView>();
// Give the binding handler a pointer back to this | FlutterWindowsView |
state->view->binding_handler_->SetView(state->view.get());
// opaque pointer to FlutterWindowsView
state->view_wrapper->view = state->view.get();
state->view->render_target_ = std::make_unique<WindowsRenderTarget>(
state->view->binding_handler_->GetRenderTarget());
return state.release();
}
void FlutterWindowsView::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng) {
engine_ = eng;
auto messenger = std::make_unique<FlutterDesktopMessenger>();
message_dispatcher_ =
std::make_unique<flutter::IncomingMessageDispatcher>(messenger.get());
messenger->engine = engine_;
messenger->dispatcher = message_dispatcher_.get();
window_wrapper_ = std::make_unique<FlutterDesktopView>();
window_wrapper_->view = this;
plugin_registrar_ = std::make_unique<FlutterDesktopPluginRegistrar>();
plugin_registrar_->messenger = std::move(messenger);
plugin_registrar_->view = window_wrapper_.get();
internal_plugin_registrar_ =
std::make_unique<flutter::PluginRegistrar>(plugin_registrar_.get());
// Set up the keyboard handlers.
auto internal_plugin_messenger = internal_plugin_registrar_->messenger();
keyboard_hook_handlers_.push_back(
std::make_unique<flutter::KeyEventHandler>(internal_plugin_messenger));
keyboard_hook_handlers_.push_back(
std::make_unique<flutter::TextInputPlugin>(internal_plugin_messenger));
platform_handler_ = std::make_unique<flutter::PlatformHandler>(
internal_plugin_messenger, this);
PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
SendWindowMetrics(bounds.width, bounds.height,
binding_handler_->GetDpiScale());
}
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] {});
}
void FlutterWindowsView::OnWindowSizeChanged(size_t width,
size_t height) const {
SendWindowMetrics(width, height, binding_handler_->GetDpiScale());
}
void FlutterWindowsView::OnPointerMove(double x, double y) {
SendPointerMove(x, y);
}
void FlutterWindowsView::OnPointerDown(
double x,
double y,
FlutterPointerMouseButtons flutter_button) {
if (flutter_button != 0) {
uint64_t mouse_buttons = mouse_state_.buttons | flutter_button;
SetMouseButtons(mouse_buttons);
SendPointerDown(x, y);
}
}
void FlutterWindowsView::OnPointerUp(
double x,
double y,
FlutterPointerMouseButtons flutter_button) {
if (flutter_button != 0) {
uint64_t mouse_buttons = mouse_state_.buttons & ~flutter_button;
SetMouseButtons(mouse_buttons);
SendPointerUp(x, y);
}
}
void FlutterWindowsView::OnPointerLeave() {
SendPointerLeave();
}
void FlutterWindowsView::OnText(const std::u16string& text) {
SendText(text);
}
void FlutterWindowsView::OnKey(int key,
int scancode,
int action,
char32_t character) {
SendKey(key, scancode, action, character);
}
void FlutterWindowsView::OnScroll(double x,
double y,
double delta_x,
double delta_y,
int scroll_offset_multiplier) {
SendScroll(x, y, delta_x, delta_y, scroll_offset_multiplier);
}
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) const {
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);
}
// 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) const {
// For details about this logic, see FlutterPointerPhase in the embedder.h
// file.
event_data->phase =
mouse_state_.buttons == 0
? mouse_state_.flutter_state_is_down ? FlutterPointerPhase::kUp
: FlutterPointerPhase::kHover
: mouse_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& text) {
for (const auto& handler : keyboard_hook_handlers_) {
handler->TextHook(this, text);
}
}
void FlutterWindowsView::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 FlutterWindowsView::SendScroll(double x,
double y,
double delta_x,
double delta_y,
int scroll_offset_multiplier) {
FlutterPointerEvent event = {};
SetEventPhaseFromCursorButtonState(&event);
event.signal_kind = FlutterPointerSignalKind::kFlutterPointerSignalKindScroll;
event.x = x;
event.y = y;
event.scroll_delta_x = delta_x * scroll_offset_multiplier;
event.scroll_delta_y = delta_y * scroll_offset_multiplier;
SendPointerEventWithData(event);
}
void FlutterWindowsView::SendPointerEventWithData(
const FlutterPointerEvent& event_data) {
// 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::microseconds>(
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();
}
bool FlutterWindowsView::MakeResourceCurrent() {
return surface_manager_->MakeResourceCurrent();
}
bool FlutterWindowsView::ClearContext() {
return surface_manager_->ClearContext();
}
bool FlutterWindowsView::SwapBuffers() {
return surface_manager_->SwapBuffers();
}
void FlutterWindowsView::CreateRenderSurface() {
surface_manager_->CreateSurface(render_target_.get());
}
void FlutterWindowsView::DestroyRenderSurface() {
if (surface_manager_) {
surface_manager_->DestroySurface();
}
}
WindowsRenderTarget* FlutterWindowsView::GetRenderTarget() {
return render_target_.get();
}
} // namespace flutter
// 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_WINDOWS_VIEW_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_VIEW_H_
#include <windowsx.h>
#include <string>
#include <vector>
#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/public/flutter_windows.h"
#include "flutter/shell/platform/windows/text_input_plugin.h"
#include "flutter/shell/platform/windows/win32_platform_handler.h"
#include "flutter/shell/platform/windows/window_binding_handler.h"
#include "flutter/shell/platform/windows/window_binding_handler_delegate.h"
#include "flutter/shell/platform/windows/window_state.h"
namespace flutter {
// An OS-windowing neutral abstration for flutter
// view that works with win32 hwnds and Windows::UI::Composition visuals.
class FlutterWindowsView : public WindowBindingHandlerDelegate {
public:
FlutterWindowsView();
~FlutterWindowsView();
// Factory for creating FlutterWindowsView requiring an implementator of
// WindowBindingHandler. In order for object to render Flutter content
// the SetState method must be called with a valid FlutterEngine instance.
static FlutterDesktopViewControllerRef CreateFlutterWindowsView(
std::unique_ptr<WindowBindingHandler> window_binding);
// Configures the window instance with an instance of a running Flutter
// engine.
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*);
// Creates rendering surface for Flutter engine to draw into.
// Should be called before calling FlutterEngineRun using this view.
void CreateRenderSurface();
// Destroys current rendering surface if one has been allocated.
void DestroyRenderSurface();
// Return the currently configured WindowsRenderTarget.
WindowsRenderTarget* GetRenderTarget();
// Callbacks for clearing context, settings context and swapping buffers.
bool ClearContext();
bool MakeCurrent();
bool MakeResourceCurrent();
bool SwapBuffers();
// |WindowBindingHandlerDelegate|
void OnWindowSizeChanged(size_t width, size_t height) const override;
// |WindowBindingHandlerDelegate|
void OnPointerMove(double x, double y) override;
// |WindowBindingHandlerDelegate|
void OnPointerDown(double x,
double y,
FlutterPointerMouseButtons button) override;
// |WindowBindingHandlerDelegate|
void OnPointerUp(double x,
double y,
FlutterPointerMouseButtons button) override;
// |WindowBindingHandlerDelegate|
void OnPointerLeave() override;
// |WindowBindingHandlerDelegate|
void OnText(const std::u16string&) override;
// |WindowBindingHandlerDelegate|
void OnKey(int key, int scancode, int action, char32_t character) override;
// |WindowBindingHandlerDelegate|
void OnScroll(double x,
double y,
double delta_x,
double delta_y,
int scroll_offset_multiplier) override;
// |WindowBindingHandlerDelegate|
void OnFontChange() override;
private:
// 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;
};
// 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) const;
// 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, char32_t character);
// Reports scroll wheel events to Flutter engine.
void SendScroll(double x,
double y,
double delta_x,
double delta_y,
int scroll_offset_multiplier);
// Sets |event_data|'s phase to either kMove or kHover depending on the
// current primary mouse button state.
void SetEventPhaseFromCursorButtonState(
FlutterPointerEvent* event_data) const;
// Sends a pointer event to the Flutter engine based on given 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);
// 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; }
// Currently configured WindowsRenderTarget for this view used by
// surface_manager for creation of render surfaces and bound to the physical
// os window.
std::unique_ptr<WindowsRenderTarget> render_target_;
// An object used for intializing Angle and creating / destroying render
// surfaces. Surface creation functionality requires a valid render_target.
std::unique_ptr<AngleSurfaceManager> surface_manager_;
// The handle to the Flutter engine instance.
FLUTTER_API_SYMBOL(FlutterEngine) engine_ = nullptr;
// Keeps track of mouse state in relation to the window.
MouseState mouse_state_;
// The window handle given to API clients.
std::unique_ptr<FlutterDesktopView> window_wrapper_;
// The plugin registrar handle given to API clients.
std::unique_ptr<FlutterDesktopPluginRegistrar> plugin_registrar_;
// Message dispatch manager for messages from the Flutter engine.
std::unique_ptr<flutter::IncomingMessageDispatcher> message_dispatcher_;
// The plugin registrar managing internal plugins.
std::unique_ptr<flutter::PluginRegistrar> internal_plugin_registrar_;
// Handlers for keyboard events from Windows.
std::vector<std::unique_ptr<flutter::KeyboardHookHandler>>
keyboard_hook_handlers_;
// Handler for the flutter/platform channel.
std::unique_ptr<flutter::PlatformHandler> platform_handler_;
// Currently configured WindowBindingHandler for view.
std::unique_ptr<flutter::WindowBindingHandler> binding_handler_;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_VIEW_H_
......@@ -92,10 +92,10 @@ KeyEventHandler::KeyEventHandler(flutter::BinaryMessenger* messenger)
KeyEventHandler::~KeyEventHandler() = default;
void KeyEventHandler::TextHook(Win32FlutterWindow* window,
void KeyEventHandler::TextHook(FlutterWindowsView* view,
const std::u16string& code_point) {}
void KeyEventHandler::KeyboardHook(Win32FlutterWindow* window,
void KeyEventHandler::KeyboardHook(FlutterWindowsView* view,
int key,
int scancode,
int action,
......
......@@ -16,7 +16,7 @@
namespace flutter {
class Win32FlutterWindow;
class FlutterWindowsView;
// Implements a KeyboardHookHandler
//
......@@ -28,14 +28,14 @@ class KeyEventHandler : public KeyboardHookHandler {
virtual ~KeyEventHandler();
// |KeyboardHookHandler|
void KeyboardHook(Win32FlutterWindow* window,
void KeyboardHook(FlutterWindowsView* window,
int key,
int scancode,
int action,
char32_t character) override;
// |KeyboardHookHandler|
void TextHook(Win32FlutterWindow* window,
void TextHook(FlutterWindowsView* window,
const std::u16string& text) override;
private:
......
......@@ -11,7 +11,7 @@
namespace flutter {
class Win32FlutterWindow;
class FlutterWindowsView;
// Abstract class for handling keyboard input events.
class KeyboardHookHandler {
......@@ -19,14 +19,14 @@ class KeyboardHookHandler {
virtual ~KeyboardHookHandler() = default;
// A function for hooking into keyboard input.
virtual void KeyboardHook(Win32FlutterWindow* window,
virtual void KeyboardHook(FlutterWindowsView* view,
int key,
int scancode,
int action,
char32_t character) = 0;
// A function for hooking into Unicode text input.
virtual void TextHook(Win32FlutterWindow* window,
virtual void TextHook(FlutterWindowsView* view,
const std::u16string& text) = 0;
};
......
......@@ -43,7 +43,7 @@ static constexpr char kInternalConsistencyError[] =
namespace flutter {
void TextInputPlugin::TextHook(Win32FlutterWindow* window,
void TextInputPlugin::TextHook(FlutterWindowsView* view,
const std::u16string& text) {
if (active_model_ == nullptr) {
return;
......@@ -52,7 +52,7 @@ void TextInputPlugin::TextHook(Win32FlutterWindow* window,
SendStateUpdate(*active_model_);
}
void TextInputPlugin::KeyboardHook(Win32FlutterWindow* window,
void TextInputPlugin::KeyboardHook(FlutterWindowsView* view,
int key,
int scancode,
int action,
......
......@@ -17,7 +17,7 @@
namespace flutter {
class Win32FlutterWindow;
class FlutterWindowsView;
// Implements a text input plugin.
//
......@@ -29,15 +29,14 @@ class TextInputPlugin : public KeyboardHookHandler {
virtual ~TextInputPlugin();
// |KeyboardHookHandler|
void KeyboardHook(Win32FlutterWindow* window,
void KeyboardHook(FlutterWindowsView* view,
int key,
int scancode,
int action,
char32_t character) override;
// |KeyboardHookHandler|
void TextHook(Win32FlutterWindow* window,
const std::u16string& text) override;
void TextHook(FlutterWindowsView* view, const std::u16string& text) override;
private:
// Sends the current state of the given model to the Flutter engine.
......
#include "dpi_utils.h"
#include "win32_dpi_utils.h"
namespace flutter {
......
#include <windows.h>
#include "flutter/shell/platform/windows/dpi_utils.h"
#include "flutter/shell/platform/windows/win32_dpi_utils.h"
#include "gtest/gtest.h"
namespace flutter {
......
......@@ -8,76 +8,31 @@ namespace flutter {
// constant for machines running at 100% scaling.
constexpr int base_dpi = 96;
Win32FlutterWindow::Win32FlutterWindow(int width, int height) {
surface_manager = std::make_unique<AngleSurfaceManager>();
Win32Window::InitializeChild("FLUTTERVIEW", width, height);
}
// TODO: See if this can be queried from the OS; this value is chosen
// arbitrarily to get something that feels reasonable.
constexpr int kScrollOffsetMultiplier = 20;
Win32FlutterWindow::~Win32FlutterWindow() {
DestroyRenderSurface();
if (plugin_registrar_ && plugin_registrar_->destruction_handler) {
plugin_registrar_->destruction_handler(plugin_registrar_.get());
}
Win32FlutterWindow::Win32FlutterWindow(int width, int height)
: binding_handler_delegate_(nullptr) {
Win32Window::InitializeChild("FLUTTERVIEW", width, height);
}
FlutterDesktopViewControllerRef Win32FlutterWindow::CreateWin32FlutterWindow(
const int width,
const int height) {
auto state = std::make_unique<FlutterDesktopViewControllerState>();
state->view = std::make_unique<flutter::Win32FlutterWindow>(width, height);
Win32FlutterWindow::~Win32FlutterWindow() {}
// a window wrapper for the state block, distinct from the
// window_wrapper handed to plugin_registrar.
state->view_wrapper = std::make_unique<FlutterDesktopView>();
state->view_wrapper->window = state->view.get();
return state.release();
void Win32FlutterWindow::SetView(WindowBindingHandlerDelegate* window) {
binding_handler_delegate_ = window;
}
void Win32FlutterWindow::SetState(FLUTTER_API_SYMBOL(FlutterEngine) eng) {
engine_ = eng;
auto messenger = std::make_unique<FlutterDesktopMessenger>();
message_dispatcher_ =
std::make_unique<flutter::IncomingMessageDispatcher>(messenger.get());
messenger->engine = engine_;
messenger->dispatcher = message_dispatcher_.get();
window_wrapper_ = std::make_unique<FlutterDesktopView>();
window_wrapper_->window = this;
plugin_registrar_ = std::make_unique<FlutterDesktopPluginRegistrar>();
plugin_registrar_->messenger = std::move(messenger);
plugin_registrar_->window = window_wrapper_.get();
internal_plugin_registrar_ =
std::make_unique<flutter::PluginRegistrar>(plugin_registrar_.get());
// Set up the keyboard handlers.
auto internal_plugin_messenger = internal_plugin_registrar_->messenger();
keyboard_hook_handlers_.push_back(
std::make_unique<flutter::KeyEventHandler>(internal_plugin_messenger));
keyboard_hook_handlers_.push_back(
std::make_unique<flutter::TextInputPlugin>(internal_plugin_messenger));
platform_handler_ = std::make_unique<flutter::PlatformHandler>(
internal_plugin_messenger, this);
process_events_ = true;
WindowsRenderTarget Win32FlutterWindow::GetRenderTarget() {
return WindowsRenderTarget(GetWindowHandle());
}
FlutterDesktopPluginRegistrarRef Win32FlutterWindow::GetRegistrar() {
return plugin_registrar_.get();
float Win32FlutterWindow::GetDpiScale() {
return static_cast<float>(GetCurrentDPI()) / static_cast<float>(base_dpi);
}
// 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;
PhysicalWindowBounds Win32FlutterWindow::GetPhysicalWindowBounds() {
return {GetCurrentWidth(), GetCurrentHeight()};
}
// Translates button codes from Win32 API to FlutterPointerMouseButtons.
......@@ -101,265 +56,62 @@ static uint64_t ConvertWinButtonToFlutterButton(UINT button) {
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();
if (binding_handler_delegate_ != nullptr) {
binding_handler_delegate_->OnWindowSizeChanged(width, height);
}
}
void Win32FlutterWindow::OnPointerMove(double x, double y) {
if (process_events_) {
SendPointerMove(x, y);
}
binding_handler_delegate_->OnPointerMove(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);
}
uint64_t flutter_button = ConvertWinButtonToFlutterButton(button);
if (flutter_button != 0) {
binding_handler_delegate_->OnPointerDown(
x, y, static_cast<FlutterPointerMouseButtons>(flutter_button));
}
}
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);
}
uint64_t flutter_button = ConvertWinButtonToFlutterButton(button);
if (flutter_button != 0) {
binding_handler_delegate_->OnPointerUp(
x, y, static_cast<FlutterPointerMouseButtons>(flutter_button));
}
}
void Win32FlutterWindow::OnPointerLeave() {
if (process_events_) {
SendPointerLeave();
}
binding_handler_delegate_->OnPointerLeave();
}
void Win32FlutterWindow::OnText(const std::u16string& text) {
if (process_events_) {
SendText(text);
}
binding_handler_delegate_->OnText(text);
}
void Win32FlutterWindow::OnKey(int key,
int scancode,
int action,
char32_t character) {
if (process_events_) {
SendKey(key, scancode, action, character);
}
binding_handler_delegate_->OnKey(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<double>(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);
binding_handler_delegate_->OnScroll(point.x, point.y, delta_x, delta_y,
kScrollOffsetMultiplier);
}
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::microseconds>(
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::OnFontChange() {
binding_handler_delegate_->OnFontChange();
}
void Win32FlutterWindow::DestroyRenderSurface() {
if (surface_manager) {
surface_manager->DestroySurface(render_surface);
}
render_surface = EGL_NO_SURFACE;
}
} // namespace flutter
......@@ -7,20 +7,15 @@
#include <windowsx.h>
#include <iostream>
#include <string>
#include <vector>
#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/flutter_windows_view.h"
#include "flutter/shell/platform/windows/win32_window.h"
#include "flutter/shell/platform/windows/window_state.h"
#include "flutter/shell/platform/windows/window_binding_handler.h"
namespace flutter {
......@@ -28,16 +23,13 @@ namespace flutter {
// 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 {
class Win32FlutterWindow : public Win32Window, public WindowBindingHandler {
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;
......@@ -68,109 +60,21 @@ class Win32FlutterWindow : public Win32Window {
// |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<AngleSurfaceManager> 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<FlutterDesktopView> window_wrapper_;
// The plugin registrar handle given to API clients.
std::unique_ptr<FlutterDesktopPluginRegistrar> plugin_registrar_;
// Message dispatch manager for messages from the Flutter engine.
std::unique_ptr<flutter::IncomingMessageDispatcher> message_dispatcher_;
// |FlutterWindowBindingHandler|
void SetView(WindowBindingHandlerDelegate* view) override;
// The plugin registrar managing internal plugins.
std::unique_ptr<flutter::PluginRegistrar> internal_plugin_registrar_;
// |FlutterWindowBindingHandler|
WindowsRenderTarget GetRenderTarget() override;
// Handlers for keyboard events from Windows.
std::vector<std::unique_ptr<flutter::KeyboardHookHandler>>
keyboard_hook_handlers_;
// |FlutterWindowBindingHandler|
float GetDpiScale() override;
// Handler for the flutter/platform channel.
std::unique_ptr<flutter::PlatformHandler> platform_handler_;
// |FlutterWindowBindingHandler|
PhysicalWindowBounds GetPhysicalWindowBounds() override;
// should we forword input messages or not
bool process_events_ = false;
// A pointer to a FlutterWindowsView that can be used to update engine
// windowing and input state.
WindowBindingHandlerDelegate* binding_handler_delegate_;
};
} // namespace flutter
......
......@@ -2,7 +2,7 @@
// 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/platform_handler.h"
#include "flutter/shell/platform/windows/win32_platform_handler.h"
#include <windows.h>
......@@ -10,8 +10,8 @@
#include <optional>
#include "flutter/shell/platform/common/cpp/json_method_codec.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/string_conversion.h"
#include "flutter/shell/platform/windows/win32_flutter_window.h"
static constexpr char kChannelName[] = "flutter/platform";
......@@ -198,12 +198,12 @@ bool ScopedClipboard::SetString(const std::wstring string) {
} // namespace
PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger,
Win32FlutterWindow* window)
FlutterWindowsView* view)
: channel_(std::make_unique<flutter::MethodChannel<rapidjson::Document>>(
messenger,
kChannelName,
&flutter::JsonMethodCodec::GetInstance())),
window_(window) {
view_(view) {
channel_->SetMethodCallHandler(
[this](
const flutter::MethodCall<rapidjson::Document>& call,
......@@ -224,9 +224,8 @@ void PlatformHandler::HandleMethodCall(
result->Error(kClipboardError, kUnknownClipboardFormatMessage);
return;
}
ScopedClipboard clipboard;
if (!clipboard.Open(window_->GetWindowHandle())) {
if (!clipboard.Open(std::get<HWND>(*view_->GetRenderTarget()))) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to open clipboard", &error_code);
......@@ -263,7 +262,8 @@ void PlatformHandler::HandleMethodCall(
}
ScopedClipboard clipboard;
if (!clipboard.Open(window_->GetWindowHandle())) {
if (!clipboard.Open(std::get<HWND>(*view_->GetRenderTarget()))) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to open clipboard", &error_code);
......
......@@ -12,13 +12,13 @@
namespace flutter {
class Win32FlutterWindow;
class FlutterWindowsView;
// Handler for internal system channels.
class PlatformHandler {
public:
explicit PlatformHandler(flutter::BinaryMessenger* messenger,
Win32FlutterWindow* window);
FlutterWindowsView* view);
private:
// Called when a method is called on |channel_|;
......@@ -30,7 +30,7 @@ class PlatformHandler {
std::unique_ptr<flutter::MethodChannel<rapidjson::Document>> channel_;
// A reference to the win32 window.
Win32FlutterWindow* window_;
FlutterWindowsView* view_;
};
} // namespace flutter
......
......@@ -4,7 +4,7 @@
#include "flutter/shell/platform/windows/win32_window.h"
#include "dpi_utils.h"
#include "win32_dpi_utils.h"
namespace flutter {
......
......@@ -13,22 +13,6 @@
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.
......@@ -120,27 +104,6 @@ class Win32Window {
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();
......@@ -170,9 +133,6 @@ class Win32Window {
// 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;
......
// 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_WINDOW_BINDING_HANDLER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_WINDOW_BINDING_HANDLER_H_
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include <string>
#include <variant>
#include <windows.h>
#include "flutter/shell/platform/windows/window_binding_handler_delegate.h"
namespace flutter {
class FlutterWindowsView;
// Structure containing physical bounds of a Window
struct PhysicalWindowBounds {
size_t width;
size_t height;
};
using WindowsRenderTarget = std::variant<
/*winrt::Windows::UI::Composition::SpriteVisual, */ HWND>;
// Abstract class for binding Windows platform windows to Flutter views.
class WindowBindingHandler {
public:
virtual ~WindowBindingHandler() = default;
// Sets the delegate used to communicate state changes from window to view
// such as key presses, mouse position updates etc.
virtual void SetView(WindowBindingHandlerDelegate* view) = 0;
// Returns a valid WindowsRenderTarget representing the backing
// window.
virtual WindowsRenderTarget GetRenderTarget() = 0;
// Returns the scale factor for the backing window.
virtual float GetDpiScale() = 0;
// Returns the bounds of the backing window in physical pixels.
virtual PhysicalWindowBounds GetPhysicalWindowBounds() = 0;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_WINDOW_BINDING_HANDLER_H_
// 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_WINDOW_BINDING_HANDLER_DELEGATE_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_WINDOW_BINDING_HANDLER_DELEGATE_H_
#include "flutter/shell/platform/embedder/embedder.h"
namespace flutter {
class WindowBindingHandlerDelegate {
public:
// Notifies delegate that backing window size has changed.
// Typically called by currently configured WindowBindingHandler
virtual void OnWindowSizeChanged(size_t width, size_t height) const = 0;
// Notifies delegate that backing window mouse has moved.
// Typically called by currently configured WindowBindingHandler
virtual void OnPointerMove(double x, double y) = 0;
// Notifies delegate that backing window mouse pointer button has been
// pressed. Typically called by currently configured WindowBindingHandler
virtual void OnPointerDown(double x,
double y,
FlutterPointerMouseButtons button) = 0;
// Notifies delegate that backing window mouse pointer button has been
// released. Typically called by currently configured WindowBindingHandler
virtual void OnPointerUp(double x,
double y,
FlutterPointerMouseButtons button) = 0;
// Notifies delegate that backing window mouse pointer has left the window.
// Typically called by currently configured WindowBindingHandler
virtual void OnPointerLeave() = 0;
// Notifies delegate that backing window has received text.
// Typically called by currently configured WindowBindingHandler
virtual void OnText(const std::u16string&) = 0;
// Notifies delegate that backing window size has received key press.
// Typically called by currently configured WindowBindingHandler
virtual void OnKey(int key, int scancode, int action, char32_t character) = 0;
// Notifies delegate that backing window size has recevied scroll.
// Typically called by currently configured WindowBindingHandler
virtual void OnScroll(double x,
double y,
double delta_x,
double delta_y,
int scroll_offset_multiplier) = 0;
// Notifies delegate that backing window size has had system font change.
// Typically called by currently configured WindowBindingHandler
virtual void OnFontChange() = 0;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_WINDOW_BINDING_HANDLER_DELEGATE_H_
......@@ -10,19 +10,19 @@
#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/win32_platform_handler.h"
#include "flutter/shell/platform/windows/win32_task_runner.h"
namespace flutter {
struct Win32FlutterWindow;
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<flutter::Win32FlutterWindow> view;
// The view that owns this state object.
std::unique_ptr<flutter::FlutterWindowsView> view;
// The state associate with the engine backing the view.
std::unique_ptr<FlutterDesktopEngineState> engine_state;
......@@ -35,8 +35,8 @@ struct FlutterDesktopViewControllerState {
// 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::Win32FlutterWindow* window;
// The view that (indirectly) owns this state object.
flutter::FlutterWindowsView* view;
};
struct AotDataDeleter {
......@@ -64,8 +64,8 @@ struct FlutterDesktopPluginRegistrar {
// The plugin messenger handle given to API clients.
std::unique_ptr<FlutterDesktopMessenger> messenger;
// The handle for the window associated with this registrar.
FlutterDesktopView* window;
// The handle for the view associated with this registrar.
FlutterDesktopView* view;
// Callback to be called on registrar destruction.
FlutterDesktopOnRegistrarDestroyed destruction_handler;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册