blob: a8bd92277a79b219d7846ec99d3493fc971b3e6f [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_window_winuwp.h"
namespace flutter {
// Multipler used to map controller velocity to an appropriate scroll input.
static constexpr double kControllerScrollMultiplier = 3;
FlutterWindowWinUWP::FlutterWindowWinUWP(
ABI::Windows::UI::Core::CoreWindow* window) {
winrt::Windows::UI::Core::CoreWindow cw{nullptr};
winrt::copy_from_abi(cw, window);
window_ = cw;
SetEventHandlers();
display_helper_ = std::make_unique<DisplayHelperWinUWP>();
}
WindowsRenderTarget FlutterWindowWinUWP::GetRenderTarget() {
#ifdef USECOREWINDOW
return WindowsRenderTarget(window_);
#else
compositor_ = winrt::Windows::UI::Composition::Compositor();
target_ = compositor_.CreateTargetForCurrentView();
visual_tree_root_ = compositor_.CreateContainerVisual();
target_.Root(visual_tree_root_);
render_target_ = compositor_.CreateSpriteVisual();
render_target_.Offset({display_helper_->GetRenderTargetXOffset(),
display_helper_->GetRenderTargetYOffset(), 1.0});
if (!display_helper_->IsRunningOnLargeScreenDevice()) {
ApplyInverseDpiScalingTransform();
}
visual_tree_root_.Children().InsertAtBottom(render_target_);
game_pad_cursor_ = std::make_unique<GamepadCursorWinUWP>(
binding_handler_delegate_, display_helper_.get(), window_, compositor_,
visual_tree_root_.Children());
WindowBoundsWinUWP bounds = display_helper_->GetPhysicalBounds();
render_target_.Size({bounds.width, bounds.height});
return WindowsRenderTarget(render_target_);
#endif
}
void FlutterWindowWinUWP::ApplyInverseDpiScalingTransform() {
// Apply inverse transform to negate built in DPI scaling in order to render
// at native scale.
auto dpiScale = GetDpiScale();
render_target_.Scale({1 / dpiScale, 1 / dpiScale, 1 / dpiScale});
}
PhysicalWindowBounds FlutterWindowWinUWP::GetPhysicalWindowBounds() {
WindowBoundsWinUWP bounds = display_helper_->GetPhysicalBounds();
return {static_cast<size_t>(bounds.width),
static_cast<size_t>(bounds.height)};
}
void FlutterWindowWinUWP::UpdateFlutterCursor(const std::string& cursor_name) {
// TODO(clarkezone): add support for Flutter cursors:
// https://github.com/flutter/flutter/issues/70199
}
void FlutterWindowWinUWP::OnCursorRectUpdated(const Rect& rect) {
// TODO(cbracken): Implement IMM candidate window positioning.
}
void FlutterWindowWinUWP::OnWindowResized() {}
FlutterWindowWinUWP::~FlutterWindowWinUWP() {}
void FlutterWindowWinUWP::SetView(WindowBindingHandlerDelegate* view) {
binding_handler_delegate_ = view;
}
void FlutterWindowWinUWP::SetEventHandlers() {
auto app_view =
winrt::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
app_view.SetDesiredBoundsMode(winrt::Windows::UI::ViewManagement::
ApplicationViewBoundsMode::UseCoreWindow);
app_view.VisibleBoundsChanged({this, &FlutterWindowWinUWP::OnBoundsChanged});
window_.PointerPressed({this, &FlutterWindowWinUWP::OnPointerPressed});
window_.PointerReleased({this, &FlutterWindowWinUWP::OnPointerReleased});
window_.PointerMoved({this, &FlutterWindowWinUWP::OnPointerMoved});
window_.PointerWheelChanged(
{this, &FlutterWindowWinUWP::OnPointerWheelChanged});
// TODO(clarkezone) support mouse leave handling
// https://github.com/flutter/flutter/issues/70199
// TODO(clarkezone) support system font changed
// https://github.com/flutter/flutter/issues/70198
window_.KeyUp({this, &FlutterWindowWinUWP::OnKeyUp});
window_.KeyDown({this, &FlutterWindowWinUWP::OnKeyDown});
window_.CharacterReceived({this, &FlutterWindowWinUWP::OnCharacterReceived});
auto display = winrt::Windows::Graphics::Display::DisplayInformation::
GetForCurrentView();
display.DpiChanged({this, &FlutterWindowWinUWP::OnDpiChanged});
}
float FlutterWindowWinUWP::GetDpiScale() {
return display_helper_->GetDpiScale();
}
void FlutterWindowWinUWP::OnDpiChanged(
winrt::Windows::Graphics::Display::DisplayInformation const& args,
winrt::Windows::Foundation::IInspectable const&) {
ApplyInverseDpiScalingTransform();
WindowBoundsWinUWP bounds = display_helper_->GetPhysicalBounds();
binding_handler_delegate_->OnWindowSizeChanged(
static_cast<size_t>(bounds.width), static_cast<size_t>(bounds.height));
}
void FlutterWindowWinUWP::OnPointerPressed(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::PointerEventArgs const& args) {
double x = GetPosX(args);
double y = GetPosY(args);
binding_handler_delegate_->OnPointerDown(
x, y, FlutterPointerMouseButtons::kFlutterPointerButtonMousePrimary);
}
void FlutterWindowWinUWP::OnPointerReleased(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::PointerEventArgs const& args) {
double x = GetPosX(args);
double y = GetPosY(args);
binding_handler_delegate_->OnPointerUp(
x, y, FlutterPointerMouseButtons::kFlutterPointerButtonMousePrimary);
}
void FlutterWindowWinUWP::OnPointerMoved(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::PointerEventArgs const& args) {
double x = GetPosX(args);
double y = GetPosY(args);
binding_handler_delegate_->OnPointerMove(x, y);
}
void FlutterWindowWinUWP::OnPointerWheelChanged(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::PointerEventArgs const& args) {
double x = GetPosX(args);
double y = GetPosY(args);
int delta = args.CurrentPoint().Properties().MouseWheelDelta();
binding_handler_delegate_->OnScroll(x, y, 0, -delta, 1);
}
double FlutterWindowWinUWP::GetPosX(
winrt::Windows::UI::Core::PointerEventArgs const& args) {
const double inverse_dpi_scale = GetDpiScale();
return (args.CurrentPoint().Position().X -
display_helper_->GetRenderTargetXOffset()) *
inverse_dpi_scale;
}
double FlutterWindowWinUWP::GetPosY(
winrt::Windows::UI::Core::PointerEventArgs const& args) {
const double inverse_dpi_scale = GetDpiScale();
return static_cast<double>((args.CurrentPoint().Position().Y -
display_helper_->GetRenderTargetYOffset()) *
inverse_dpi_scale);
}
void FlutterWindowWinUWP::OnBoundsChanged(
winrt::Windows::UI::ViewManagement::ApplicationView const& app_view,
winrt::Windows::Foundation::IInspectable const&) {
if (binding_handler_delegate_) {
auto bounds = display_helper_->GetPhysicalBounds();
binding_handler_delegate_->OnWindowSizeChanged(
static_cast<size_t>(bounds.width), static_cast<size_t>(bounds.height));
#ifndef USECOREWINDOW
render_target_.Size({bounds.width, bounds.height});
#endif
}
}
void FlutterWindowWinUWP::OnKeyUp(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::KeyEventArgs const& args) {
// TODO(clarkezone) complete keyboard handling including
// system key (back), unicode handling, shortcut support,
// handling defered delivery, remove the need for action value.
// https://github.com/flutter/flutter/issues/70202
auto status = args.KeyStatus();
unsigned int scancode = status.ScanCode;
int key = static_cast<int>(args.VirtualKey());
int action = 0x0101;
binding_handler_delegate_->OnKey(key, scancode, action, 0,
status.IsExtendedKey /* extended */,
status.WasKeyDown /* was_down */);
}
void FlutterWindowWinUWP::OnKeyDown(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::KeyEventArgs const& args) {
// TODO(clarkezone) complete keyboard handling including
// system key (back), unicode handling, shortcut support
// handling defered delivery, remove the need for action value.
// https://github.com/flutter/flutter/issues/70202
auto status = args.KeyStatus();
unsigned int scancode = status.ScanCode;
int key = static_cast<int>(args.VirtualKey());
int action = 0x0100;
binding_handler_delegate_->OnKey(key, scancode, action, 0,
status.IsExtendedKey /* extended */,
status.WasKeyDown /* was_down */);
}
void FlutterWindowWinUWP::OnCharacterReceived(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::CharacterReceivedEventArgs const& args) {
auto key = args.KeyCode();
wchar_t keycode = static_cast<wchar_t>(key);
if (keycode >= u' ') {
std::u16string text({keycode});
binding_handler_delegate_->OnText(text);
}
}
bool FlutterWindowWinUWP::OnBitmapSurfaceUpdated(const void* allocation,
size_t row_bytes,
size_t height) {
// TODO(gw280): Support software rendering fallback on UWP
return false;
}
} // namespace flutter