// 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 namespace flutter { FlutterWindowsView::FlutterWindowsView( std::unique_ptr window_binding) { surface_manager_ = std::make_unique(); // 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( binding_handler_->GetRenderTarget()); } FlutterWindowsView::~FlutterWindowsView() { DestroyRenderSurface(); } void FlutterWindowsView::SetEngine( std::unique_ptr engine) { engine_ = std::move(engine); engine_->SetView(this); internal_plugin_registrar_ = std::make_unique(engine_->GetRegistrar()); // Set up the system channel 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_ = PlatformHandler::Create(internal_plugin_messenger, this); cursor_handler_ = std::make_unique( 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::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