mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Switches the Windows embedding from the standard C API to the new proctable version, to allow for unit testing of the embedding layer separately from the embedder APIs implementation. This includes moving some engine messaging that was still in flutter_windows to the C++ engine class to better encapsulate the proc table.
283 lines
8.9 KiB
C++
283 lines
8.9 KiB
C++
// 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/flutter_windows_view.h"
|
|
|
|
#include <chrono>
|
|
|
|
namespace flutter {
|
|
|
|
FlutterWindowsView::FlutterWindowsView(
|
|
std::unique_ptr<WindowBindingHandler> window_binding) {
|
|
surface_manager_ = std::make_unique<AngleSurfaceManager>();
|
|
|
|
// Take the binding handler, and give it a pointer back to self.
|
|
binding_handler_ = std::move(window_binding);
|
|
binding_handler_->SetView(this);
|
|
|
|
render_target_ = std::make_unique<WindowsRenderTarget>(
|
|
binding_handler_->GetRenderTarget());
|
|
}
|
|
|
|
FlutterWindowsView::~FlutterWindowsView() {
|
|
DestroyRenderSurface();
|
|
}
|
|
|
|
void FlutterWindowsView::SetEngine(
|
|
std::unique_ptr<FlutterWindowsEngine> engine) {
|
|
engine_ = std::move(engine);
|
|
|
|
engine_->SetView(this);
|
|
|
|
internal_plugin_registrar_ =
|
|
std::make_unique<flutter::PluginRegistrar>(engine_->GetRegistrar());
|
|
|
|
// Set up the system channel 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);
|
|
cursor_handler_ = std::make_unique<flutter::CursorHandler>(
|
|
internal_plugin_messenger, binding_handler_.get());
|
|
|
|
PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
|
|
|
|
SendWindowMetrics(bounds.width, bounds.height,
|
|
binding_handler_->GetDpiScale());
|
|
}
|
|
|
|
void FlutterWindowsView::OnWindowSizeChanged(size_t width,
|
|
size_t height) const {
|
|
surface_manager_->ResizeSurface(GetRenderTarget(), width, height);
|
|
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);
|
|
}
|
|
|
|
// Sends new size information to FlutterEngine.
|
|
void FlutterWindowsView::SendWindowMetrics(size_t width,
|
|
size_t height,
|
|
double dpiScale) const {
|
|
FlutterWindowMetricsEvent event = {};
|
|
event.struct_size = sizeof(event);
|
|
event.width = width;
|
|
event.height = height;
|
|
event.pixel_ratio = dpiScale;
|
|
engine_->SendWindowMetricsEvent(event);
|
|
}
|
|
|
|
void FlutterWindowsView::SendInitialBounds() {
|
|
PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
|
|
|
|
SendWindowMetrics(bounds.width, bounds.height,
|
|
binding_handler_->GetDpiScale());
|
|
}
|
|
|
|
// 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();
|
|
|
|
engine_->SendPointerEvent(event);
|
|
|
|
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() {
|
|
PhysicalWindowBounds bounds = binding_handler_->GetPhysicalWindowBounds();
|
|
surface_manager_->CreateSurface(GetRenderTarget(), bounds.width,
|
|
bounds.height);
|
|
}
|
|
|
|
void FlutterWindowsView::DestroyRenderSurface() {
|
|
if (surface_manager_) {
|
|
surface_manager_->DestroySurface();
|
|
}
|
|
}
|
|
|
|
WindowsRenderTarget* FlutterWindowsView::GetRenderTarget() const {
|
|
return render_target_.get();
|
|
}
|
|
|
|
FlutterWindowsEngine* FlutterWindowsView::GetEngine() {
|
|
return engine_.get();
|
|
}
|
|
|
|
} // namespace flutter
|