blob: 5736ce988f53e11b75db105261b7adf4bcc9efab [file] [log] [blame]
// 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);
}
void FlutterWindowsView::OnFontChange() {
if (engine_->engine() == nullptr) {
return;
}
FlutterEngineReloadSystemFonts(engine_->engine());
}
// Sends new size information to FlutterEngine.
void FlutterWindowsView::SendWindowMetrics(size_t width,
size_t height,
double dpiScale) const {
if (engine_->engine() == nullptr) {
return;
}
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(event);
event.width = width;
event.height = height;
event.pixel_ratio = dpiScale;
auto result = FlutterEngineSendWindowMetricsEvent(engine_->engine(), &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();
FlutterEngineSendPointerEvent(engine_->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() {
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