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

Windows: Add CoreWindow implementation of FlutterWindowsView (Flutter#70205) (#23573)

* Windows: Add CoreWindow implementation of FlutterWindowsView (Flutter#70205)
上级 e598d2f9
......@@ -164,8 +164,10 @@ group("flutter") {
if (is_win) {
if (target_os == "winuwp") {
# TODO: Add winnup variant of the unit tests here; see
# TODO: Add winnup variant of client_wrapper_windows_unittests here; see
# https://github.com/flutter/flutter/issues/70197
public_deps +=
[ "//flutter/shell/platform/windows:flutter_windows_unittests" ]
} else {
public_deps += [
"//flutter/shell/platform/windows:flutter_windows_unittests",
......
......@@ -1462,6 +1462,8 @@ FILE: ../../../flutter/shell/platform/windows/external_texture_gl.h
FILE: ../../../flutter/shell/platform/windows/flutter_project_bundle.cc
FILE: ../../../flutter/shell/platform/windows/flutter_project_bundle.h
FILE: ../../../flutter/shell/platform/windows/flutter_project_bundle_unittests.cc
FILE: ../../../flutter/shell/platform/windows/flutter_window_winuwp.cc
FILE: ../../../flutter/shell/platform/windows/flutter_window_winuwp.h
FILE: ../../../flutter/shell/platform/windows/flutter_windows.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine.h
......
......@@ -16,6 +16,9 @@ std::vector<std::string> GetSwitchesFromEnvironment() {
// Read engine switches from the environment in debug/profile. If release mode
// support is needed in the future, it should likely use a whitelist.
#ifndef FLUTTER_RELEASE
// TODO(clarkezone): figure out how to handle engine switches in UWP mode
// https://github.com/flutter/flutter/issues/74153
#ifndef WINUWP
const char* switch_count_key = "FLUTTER_ENGINE_SWITCHES";
const int kMaxSwitchCount = 50;
const char* switch_count_string = std::getenv(switch_count_key);
......@@ -36,6 +39,7 @@ std::vector<std::string> GetSwitchesFromEnvironment() {
<< ", but " << switch_key.str() << " is missing." << std::endl;
}
}
#endif // !WINUWP
#endif // !FLUTTER_RELEASE
return switches;
}
......
......@@ -78,6 +78,8 @@ source_set("flutter_windows_source") {
# Target-specific sources.
if (target_os == "winuwp") {
sources += [
"flutter_window_winuwp.cc",
"flutter_window_winuwp.h",
"flutter_windows_winuwp.cc",
"platform_handler_winuwp.cc",
"platform_handler_winuwp.h",
......@@ -118,7 +120,10 @@ source_set("flutter_windows_source") {
public_configs = [ ":relative_angle_headers" ]
defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES" ]
defines = [
"FLUTTER_ENGINE_NO_PROTOTYPES",
"USECOREWINDOW",
]
deps = [
":flutter_windows_headers",
......@@ -162,20 +167,33 @@ test_fixtures("flutter_windows_fixtures") {
fixtures = []
}
if (target_os == "winuwp") {
# disabled until the uwp implementation is present
} else {
executable("flutter_windows_unittests") {
testonly = true
executable("flutter_windows_unittests") {
testonly = true
if (target_os == "winuwp") {
libs = [ "windowsapp.lib" ]
}
sources = [
# Common Windows test sources.
sources = [
# "flutter_project_bundle_unittests.cc", //TODO failing due to switches test failing. Blocked on https://github.com/flutter/flutter/issues/74153
# "flutter_windows_engine_unittests.cc", //TODO failing to send / receive platform message get plugins working first. Blocked on https://github.com/flutter/flutter/issues/74155
"string_conversion_unittests.cc",
"system_utils_unittests.cc",
"testing/engine_embedder_api_modifier.h",
]
# Target-specific sources.
if (target_os == "winuwp") {
# TODO(clarkezone) add UWP tests
# https://github.com/flutter/flutter/issues/70197
} else {
sources += [
# TODO move first two tests to common once above TODO's unblocked.
"flutter_project_bundle_unittests.cc",
"flutter_windows_engine_unittests.cc",
"flutter_windows_texture_registrar_unittests.cc",
"key_event_handler_unittests.cc",
"string_conversion_unittests.cc",
"system_utils_unittests.cc",
"testing/engine_embedder_api_modifier.h",
"testing/mock_win32_window.cc",
"testing/mock_win32_window.h",
"testing/mock_window_binding_handler.cc",
......@@ -187,20 +205,20 @@ if (target_os == "winuwp") {
"win32_window_proc_delegate_manager_unittests.cc",
"win32_window_unittests.cc",
]
}
public_configs = [ "//flutter:config" ]
public_configs = [ "//flutter:config" ]
deps = [
":flutter_windows_fixtures",
":flutter_windows_headers",
":flutter_windows_source",
"//flutter/shell/platform/common/cpp:common_cpp",
"//flutter/shell/platform/embedder:embedder_as_internal_library",
"//flutter/shell/platform/embedder:embedder_test_utils",
"//flutter/testing",
"//third_party/rapidjson",
]
}
deps = [
":flutter_windows_fixtures",
":flutter_windows_headers",
":flutter_windows_source",
"//flutter/shell/platform/common/cpp:common_cpp",
"//flutter/shell/platform/embedder:embedder_as_internal_library",
"//flutter/shell/platform/embedder:embedder_test_utils",
"//flutter/testing",
"//third_party/rapidjson",
]
}
shared_library("flutter_windows_glfw") {
......
......@@ -7,6 +7,15 @@
#include <iostream>
#include <vector>
#ifdef WINUWP
#include <windows.ui.core.h>
#include <winrt/Windows.UI.Composition.h>
#endif
#if defined(WINUWP) && defined(USECOREWINDOW)
#include <winrt/Windows.UI.Core.h>
#endif
namespace flutter {
AngleSurfaceManager::AngleSurfaceManager()
......@@ -188,10 +197,23 @@ bool AngleSurfaceManager::CreateSurface(WindowsRenderTarget* render_target,
EGL_FIXED_SIZE_ANGLE, EGL_TRUE, EGL_WIDTH, width,
EGL_HEIGHT, height, EGL_NONE};
#ifdef WINUWP
#ifdef USECOREWINDOW
auto target = std::get<winrt::Windows::UI::Core::CoreWindow>(*render_target);
#else
auto target =
std::get<winrt::Windows::UI::Composition::SpriteVisual>(*render_target);
#endif
surface = eglCreateWindowSurface(
egl_display_, egl_config_,
static_cast<EGLNativeWindowType>(winrt::get_abi(target)),
surfaceAttributes);
#else
surface = eglCreateWindowSurface(
egl_display_, egl_config_,
static_cast<EGLNativeWindowType>(std::get<HWND>(*render_target)),
surfaceAttributes);
#endif
if (surface == EGL_NO_SURFACE) {
std::cerr << "Surface creation failed." << std::endl;
}
......@@ -212,6 +234,8 @@ void AngleSurfaceManager::ResizeSurface(WindowsRenderTarget* render_target,
// preserve the previous surface contents. This resize approach could be
// further optimized if Angle exposed a public entrypoint for
// SwapChain11::reset or SwapChain11::resize.
// a possible starting point for that could build on
// eglPostSubBufferNV(egl_display_, render_surface_, 1, 1, width, height);
DestroySurface();
if (!CreateSurface(render_target, width, height)) {
std::cerr << "AngleSurfaceManager::ResizeSurface failed to create surface"
......
......@@ -9,6 +9,21 @@
namespace flutter {
#ifdef WINUWP
FlutterViewController::FlutterViewController(
ABI::Windows::UI::Core::CoreWindow* window,
const DartProject& project) {
engine_ = std::make_unique<FlutterEngine>(project);
controller_ = FlutterDesktopViewControllerCreateFromCoreWindow(
window, engine_->RelinquishEngine());
if (!controller_) {
std::cerr << "Failed to create view controller." << std::endl;
return;
}
view_ = std::make_unique<FlutterView>(
FlutterDesktopViewControllerGetView(controller_));
}
#else
FlutterViewController::FlutterViewController(int width,
int height,
const DartProject& project) {
......@@ -22,6 +37,7 @@ FlutterViewController::FlutterViewController(int width,
view_ = std::make_unique<FlutterView>(
FlutterDesktopViewControllerGetView(controller_));
}
#endif
FlutterViewController::~FlutterViewController() {
if (controller_) {
......
......@@ -13,6 +13,22 @@ namespace flutter {
// A set of Flutter and Dart assets used to initialize a Flutter engine.
class DartProject {
public:
#ifdef WINUWP
// Creates a DartProject from a series of absolute paths.
// The directory should contain the following top-level items:
// - icudtl.dat (provided as a resource by the Flutter tool)
// - flutter_assets (as built by the Flutter tool)
// - app.so, for an AOT build (as built by the Flutter tool)
//
// The path must be absolute.
explicit DartProject(const std::wstring& assetspath,
const std::wstring& icupath,
const std::wstring& aotpath) {
assets_path_ = assetspath;
icu_data_path_ = icupath;
aot_library_path_ = aotpath;
}
#else
// Creates a DartProject from a directory path. The directory should contain
// the following top-level items:
// - icudtl.dat (provided as a resource by the Flutter tool)
......@@ -26,6 +42,7 @@ class DartProject {
icu_data_path_ = path + L"\\icudtl.dat";
aot_library_path_ = path + L"\\app.so";
}
#endif
~DartProject() = default;
......
......@@ -20,8 +20,10 @@ class FlutterView {
FlutterView(FlutterView const&) = delete;
FlutterView& operator=(FlutterView const&) = delete;
#ifndef WINUWP
// Returns the backing HWND for the view.
HWND GetNativeWindow() { return FlutterDesktopViewGetHWND(view_); }
#endif
private:
// Handle for interacting with the C API's view.
......
......@@ -17,6 +17,10 @@
#include "plugin_registrar.h"
#include "plugin_registry.h"
#ifdef WINUWP
#include <windows.ui.core.h>
#endif
namespace flutter {
// A controller for a view displaying Flutter content.
......@@ -26,13 +30,22 @@ namespace flutter {
// methods in the C API directly, as this class will do that internally.
class FlutterViewController {
public:
#ifndef WINUWP
// Creates a FlutterView that can be parented into a Windows View hierarchy
// either using HWNDs or in the future into a CoreWindow, or using compositor.
// either using HWNDs.
//
// |dart_project| will be used to configure the engine backing this view.
explicit FlutterViewController(int width,
int height,
const DartProject& project);
#else
// Creates a FlutterView that can be parented into a Windows View hierarchy
// either using CoreWindow.
//
// |dart_project| will be used to configure the engine backing this view.
explicit FlutterViewController(ABI::Windows::UI::Core::CoreWindow* window,
const DartProject& project);
#endif
virtual ~FlutterViewController();
......
// 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();
ConfigureXboxSpecific();
current_display_info_ = winrt::Windows::Graphics::Display::
DisplayInformation::GetForCurrentView();
}
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_);
cursor_visual_ = CreateCursorVisual();
render_target_ = compositor_.CreateSpriteVisual();
if (running_on_xbox_) {
render_target_.Offset(
{xbox_overscan_x_offset_, xbox_overscan_y_offset_, 1.0});
} else {
render_target_.Offset({1.0, 1.0, 1.0});
ApplyInverseDpiScalingTransform();
}
visual_tree_root_.Children().InsertAtBottom(render_target_);
WindowBoundsWinUWP bounds = GetBounds(current_display_info_, true);
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 = GetBounds(current_display_info_, true);
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::UpdateCursorRect(const Rect& rect) {
// TODO(cbracken): Implement IMM candidate window positioning.
}
void FlutterWindowWinUWP::OnWindowResized() {}
float FlutterWindowWinUWP::GetDpiScale() {
auto disp = winrt::Windows::Graphics::Display::DisplayInformation::
GetForCurrentView();
return GetDpiScale(disp);
}
WindowBoundsWinUWP FlutterWindowWinUWP::GetBounds(
winrt::Windows::Graphics::Display::DisplayInformation const& disp,
bool physical) {
winrt::Windows::UI::ViewManagement::ApplicationView app_view =
winrt::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
winrt::Windows::Foundation::Rect bounds = app_view.VisibleBounds();
if (running_on_xbox_) {
return {bounds.Width + (bounds.X), bounds.Height + (bounds.Y)};
}
if (physical) {
// Return the height in physical pixels
return {bounds.Width * static_cast<float>(disp.RawPixelsPerViewPixel()),
bounds.Height * static_cast<float>(disp.RawPixelsPerViewPixel())};
}
return {bounds.Width, bounds.Height};
}
float FlutterWindowWinUWP::GetDpiScale(
winrt::Windows::Graphics::Display::DisplayInformation const& disp) {
double raw_per_view = disp.RawPixelsPerViewPixel();
// TODO(clarkezone): ensure DPI handling is correct:
// because XBOX has display scaling off, logicalDpi retuns 96 which is
// incorrect check if raw_per_view is more acurate.
// Also confirm if it is necessary to use this workaround on 10X
// https://github.com/flutter/flutter/issues/70198
if (running_on_xbox_) {
return 1.5;
}
return static_cast<float>(raw_per_view);
}
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});
}
void FlutterWindowWinUWP::ConfigureXboxSpecific() {
running_on_xbox_ =
winrt::Windows::System::Profile::AnalyticsInfo::VersionInfo()
.DeviceFamily() == L"Windows.Xbox";
if (running_on_xbox_) {
bool result =
winrt::Windows::UI::ViewManagement::ApplicationView::GetForCurrentView()
.SetDesiredBoundsMode(winrt::Windows::UI::ViewManagement::
ApplicationViewBoundsMode::UseCoreWindow);
if (!result) {
OutputDebugString(L"Couldn't set bounds mode.");
}
winrt::Windows::UI::ViewManagement::ApplicationView app_view = winrt::
Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
winrt::Windows::Foundation::Rect bounds = app_view.VisibleBounds();
// the offset /2 represents how much off-screan the core window is
// positioned unclear why disabling overscan doesn't correct this
xbox_overscan_x_offset_ = bounds.X / 2;
xbox_overscan_y_offset_ = bounds.Y / 2;
}
}
void FlutterWindowWinUWP::OnDpiChanged(
winrt::Windows::Graphics::Display::DisplayInformation const& args,
winrt::Windows::Foundation::IInspectable const&) {
ApplyInverseDpiScalingTransform();
WindowBoundsWinUWP bounds = GetBounds(current_display_info_, true);
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 - xbox_overscan_x_offset_) *
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 - xbox_overscan_y_offset_) *
inverse_dpi_scale);
}
void FlutterWindowWinUWP::OnBoundsChanged(
winrt::Windows::UI::ViewManagement::ApplicationView const& app_view,
winrt::Windows::Foundation::IInspectable const&) {
#ifndef USECOREWINDOW
if (binding_handler_delegate_) {
auto bounds = GetBounds(current_display_info_, true);
binding_handler_delegate_->OnWindowSizeChanged(
static_cast<size_t>(bounds.width), static_cast<size_t>(bounds.height));
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());
char32_t chararacter = static_cast<char32_t>(key | 32);
int action = 0x0101;
binding_handler_delegate_->OnKey(key, scancode, action, chararacter, false);
}
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());
char32_t chararacter = static_cast<char32_t>(key | 32);
int action = 0x0100;
binding_handler_delegate_->OnKey(key, scancode, action, chararacter, false);
}
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);
}
}
winrt::Windows::UI::Composition::Visual
FlutterWindowWinUWP::CreateCursorVisual() {
auto container = compositor_.CreateContainerVisual();
container.Offset(
{window_.Bounds().Width / 2, window_.Bounds().Height / 2, 1.0});
// size of the simulated mouse cursor
const float size = 30;
auto cursor_visual = compositor_.CreateShapeVisual();
cursor_visual.Size({size, size});
// compensate for overscan in cursor visual
cursor_visual.Offset({xbox_overscan_x_offset_, xbox_overscan_y_offset_, 1.0});
winrt::Windows::UI::Composition::CompositionEllipseGeometry circle =
compositor_.CreateEllipseGeometry();
circle.Radius({size / 2, size / 2});
auto circleshape = compositor_.CreateSpriteShape(circle);
circleshape.FillBrush(
compositor_.CreateColorBrush(winrt::Windows::UI::Colors::Black()));
circleshape.Offset({size / 2, size / 2});
cursor_visual.Shapes().Append(circleshape);
winrt::Windows::UI::Composition::Visual visual =
cursor_visual.as<winrt::Windows::UI::Composition::Visual>();
visual.CompositeMode(winrt::Windows::UI::Composition::
CompositionCompositeMode::DestinationInvert);
visual.AnchorPoint({0.5, 0.5});
container.Children().InsertAtTop(visual);
return container;
}
} // 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_UWP_FLUTTER_WINDOW_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_UWP_FLUTTER_WINDOW_H_
#include <winrt/Windows.Graphics.Display.h>
#include <winrt/Windows.System.Profile.h>
#include <winrt/Windows.UI.Input.h>
#include <winrt/Windows.UI.ViewManagement.Core.h>
#include <windows.ui.core.h>
#include <winrt/Windows.UI.Composition.h>
#include <winrt/Windows.UI.Core.h>
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
namespace flutter {
struct WindowBoundsWinUWP {
float width;
float height;
};
// Implements a UWP CoreWindow. Underlying window has been created and provided
// by the runner.
//
// Specifically handles window events within windows.
class FlutterWindowWinUWP : public WindowBindingHandler {
public:
explicit FlutterWindowWinUWP(ABI::Windows::UI::Core::CoreWindow* window);
virtual ~FlutterWindowWinUWP();
// |WindowBindingHandler|
void SetView(WindowBindingHandlerDelegate* view) override;
// |WindowBindingHandler|
WindowsRenderTarget GetRenderTarget() override;
// |WindowBindingHandler|
float GetDpiScale() override;
// |WindowBindingHandler|
PhysicalWindowBounds GetPhysicalWindowBounds() override;
// |WindowBindingHandler|
void UpdateFlutterCursor(const std::string& cursor_name) override;
// |WindowBindingHandler|
void UpdateCursorRect(const Rect& rect) override;
// |WindowBindingHandler|
void OnWindowResized() override;
private:
// Returns a bounds structure containing width and height information
// for the backing CoreWindow in either view or physical pixels depending on
// |physical|.
WindowBoundsWinUWP GetBounds(
winrt::Windows::Graphics::Display::DisplayInformation const& disp,
bool physical);
// Returns a scaling factor representing the current DPI scale applied to the
// backing CoreWindow.
float GetDpiScale(
winrt::Windows::Graphics::Display::DisplayInformation const&);
// Undoes the scale transform applied by the Windows compositor in order to
// render at native scale and produce smooth results on high DPI screens.
void ApplyInverseDpiScalingTransform();
// Hooks up event handers for keyboard, mouse, size, DPI changed events on the
// underlying CoreWindow.
void SetEventHandlers();
// Notifies current |WindowBindingHandlerDelegate| of DPI Changed events.
void OnDpiChanged(
winrt::Windows::Graphics::Display::DisplayInformation const& args,
winrt::Windows::Foundation::IInspectable const&);
// Notifies current |WindowBindingHandlerDelegate| of pointer pressed events.
void OnPointerPressed(winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::PointerEventArgs const& args);
// Notifies current |WindowBindingHandlerDelegate| of pointer released events.
void OnPointerReleased(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::PointerEventArgs const& args);
// Notifies current |WindowBindingHandlerDelegate| of pointer pressed events.
void OnBoundsChanged(
winrt::Windows::UI::ViewManagement::ApplicationView const& appView,
winrt::Windows::Foundation::IInspectable const&);
// Notifies current |WindowBindingHandlerDelegate| of pointer moved events.
void OnPointerMoved(winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::PointerEventArgs const& args);
// Notifies current |WindowBindingHandlerDelegate| of mouse wheel events.
void OnPointerWheelChanged(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::PointerEventArgs const& args);
// Notifies current |WindowBindingHandlerDelegate| of key up events.
void OnKeyUp(winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::KeyEventArgs const& args);
// Notifies current |WindowBindingHandlerDelegate| of key down events.
void OnKeyDown(winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::KeyEventArgs const& args);
// Notifies current |WindowBindingHandlerDelegate| of character received
// events.
void OnCharacterReceived(
winrt::Windows::Foundation::IInspectable const&,
winrt::Windows::UI::Core::CharacterReceivedEventArgs const& args);
// Creates a visual representing the emulated cursor and add to the visual
// tree
winrt::Windows::UI::Composition::Visual CreateCursorVisual();
// Test is current context is running on an xbox device and perform device
// specific initialization.
void ConfigureXboxSpecific();
// Converts from logical point to physical X value.
double GetPosX(winrt::Windows::UI::Core::PointerEventArgs const& args);
// Converts from logical point to physical Y value.
double GetPosY(winrt::Windows::UI::Core::PointerEventArgs const& args);
// Token representing current worker thread.
winrt::Windows::Foundation::IAsyncAction worker_loop_{nullptr};
// Backing CoreWindow. nullptr if not set.
winrt::Windows::UI::Core::CoreWindow window_{nullptr};
// Pointer to a FlutterWindowsView that can be
// used to update engine windowing and input state.
WindowBindingHandlerDelegate* binding_handler_delegate_;
// Current active compositor. nullptr if not set.
winrt::Windows::UI::Composition::Compositor compositor_{nullptr};
// Current CompositionTarget for binding the
// rendering context to the CoreWindow. nullptr if not set.
winrt::Windows::UI::Composition::CompositionTarget target_{nullptr};
// Composition tree root object.
winrt::Windows::UI::Composition::ContainerVisual visual_tree_root_{nullptr};
// Composition visual representing the emulated
// cursor visual.
winrt::Windows::UI::Composition::Visual cursor_visual_{nullptr};
// Compositor object that represents the render target binding the backing
// SwapChain to the CoreWindow.
winrt::Windows::UI::Composition::SpriteVisual render_target_{nullptr};
// Is current context is executing on an XBOX
// device.
bool running_on_xbox_ = false;
// Current X overscan compensation factor.
float xbox_overscan_x_offset_ = 0.0f;
// Current Y overscan compensation factor.
float xbox_overscan_y_offset_ = 0.0f;
// Most recent display information.
winrt::Windows::Graphics::Display::DisplayInformation current_display_info_{
nullptr};
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_UWP_FLUTTER_WINDOW_H_
......@@ -17,29 +17,36 @@
#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/windows/flutter_window_winuwp.h" // nogncheck
FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(
int width,
int height,
FlutterDesktopEngineRef engine) {
// TODO add WINUWP implementation.
return nullptr;
}
uint64_t FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine) {
// TODO add WINUWP implementation.
return 0;
// Returns the engine corresponding to the given opaque API handle.
static flutter::FlutterWindowsEngine* EngineFromHandle(
FlutterDesktopEngineRef ref) {
return reinterpret_cast<flutter::FlutterWindowsEngine*>(ref);
}
void FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopWindowProcCallback delegate,
void* user_data) {
// TODO add WINUWP implementation.
}
void FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopWindowProcCallback delegate) {
// TODO add WINUWP implementation.
FlutterDesktopViewControllerRef
FlutterDesktopViewControllerCreateFromCoreWindow(
ABI::Windows::UI::Core::CoreWindow* window,
FlutterDesktopEngineRef engine) {
std::unique_ptr<flutter::WindowBindingHandler> window_wrapper =
std::make_unique<flutter::FlutterWindowWinUWP>(window);
auto state = std::make_unique<FlutterDesktopViewControllerState>();
state->view =
std::make_unique<flutter::FlutterWindowsView>(std::move(window_wrapper));
state->view->CreateRenderSurface();
// Take ownership of the engine, starting it if necessary.
state->view->SetEngine(
std::unique_ptr<flutter::FlutterWindowsEngine>(EngineFromHandle(engine)));
if (!state->view->GetEngine()->running()) {
if (!state->view->GetEngine()->RunWithEntrypoint(nullptr)) {
return nullptr;
}
}
// Must happen after engine is running.
state->view->SendInitialBounds();
return state.release();
}
......@@ -51,6 +51,9 @@ static constexpr int kCapsLock = 1 << 11;
static constexpr int kNumLock = 1 << 12;
static constexpr int kScrollLock = 1 << 13;
// TODO(clarkezone) need to add support for get keystate
// https://github.com/flutter/flutter/issues/70202
#ifndef WINUWP
/// Calls GetKeyState() an all modifier keys and packs the result in an int,
/// with the re-defined values declared above for compatibility with the Flutter
/// framework.
......@@ -87,6 +90,7 @@ int GetModsForKeyState() {
mods |= kScrollLock;
return mods;
}
#endif
// This uses event data instead of generating a serial number because
// information can't be attached to the redispatched events, so it has to be
......@@ -219,7 +223,9 @@ bool KeyEventHandler::KeyboardHook(FlutterWindowsView* view,
event.AddMember(kScanCodeKey, scancode, allocator);
event.AddMember(kCharacterCodePointKey, character, allocator);
event.AddMember(kKeyMapKey, kWindowsKeyMap, allocator);
#ifndef WINUWP
event.AddMember(kModifiersKey, GetModsForKeyState(), allocator);
#endif
switch (action) {
case WM_KEYDOWN:
......
......@@ -13,6 +13,10 @@
#include "flutter_messenger.h"
#include "flutter_plugin_registrar.h"
#ifdef WINUWP
#include <windows.ui.core.h>
#endif
#if defined(__cplusplus)
extern "C" {
#endif
......@@ -70,10 +74,21 @@ typedef struct {
// The caller owns the returned reference, and is responsible for calling
// FlutterDesktopViewControllerDestroy. Returns a null pointer in the event of
// an error.
#ifdef WINUWP
// The CoreWindow implementation accepts a pointer to the host CoreWindow
// and view hookup is performed in the construction path.
FLUTTER_EXPORT FlutterDesktopViewControllerRef
FlutterDesktopViewControllerCreateFromCoreWindow(
ABI::Windows::UI::Core::CoreWindow* window,
FlutterDesktopEngineRef engine);
#else //! WINUWP
// The Win32 implementation accepts width, height
// with view hookup explicitly performed using the caller using HWND parenting.
FLUTTER_EXPORT FlutterDesktopViewControllerRef
FlutterDesktopViewControllerCreate(int width,
int height,
FlutterDesktopEngineRef engine);
#endif
// Shuts down the engine instance associated with |controller|, and cleans up
// associated state.
......@@ -166,8 +181,10 @@ FlutterDesktopEngineGetTextureRegistrar(
// ========== View ==========
#ifndef WINUWP
// Return backing HWND for manipulation in host application.
FLUTTER_EXPORT HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view);
#endif
// ========== Plugin Registrar (extensions) ==========
// These are Windows-specific extensions to flutter_plugin_registrar.h
......@@ -191,6 +208,7 @@ typedef bool (*FlutterDesktopWindowProcCallback)(HWND /* hwnd */,
FLUTTER_EXPORT FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(
FlutterDesktopPluginRegistrarRef registrar);
#ifndef WINUWP
FLUTTER_EXPORT void
FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
......@@ -201,6 +219,7 @@ FLUTTER_EXPORT void
FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopWindowProcCallback delegate);
#endif
// ========== Freestanding Utilities ==========
......
......@@ -15,20 +15,50 @@ namespace flutter {
std::vector<LanguageInfo> GetPreferredLanguageInfo() {
std::vector<std::wstring> languages = GetPreferredLanguages();
std::vector<LanguageInfo> language_info;
// TODO populate via WinRT
for (auto language : languages) {
language_info.push_back(ParseLanguageName(language));
}
return language_info;
}
std::vector<std::wstring> GetPreferredLanguages() {
std::vector<std::wstring> languages;
// TODO populate via WinRT
// TODO(clarkezone) need to implement a complete version of this function in
// order to get full list of platform languages
// https://github.com/flutter/flutter/issues/74156
languages.push_back(L"en-US");
languages.push_back(L"en");
return languages;
}
LanguageInfo ParseLanguageName(std::wstring language_name) {
LanguageInfo info;
// TODO populate via WinRT
// Split by '-', discarding any suplemental language info (-x-foo).
std::vector<std::string> components;
std::istringstream stream(Utf8FromUtf16(language_name));
std::string component;
while (getline(stream, component, '-')) {
if (component == "x") {
break;
}
components.push_back(component);
}
// Determine which components are which.
info.language = components[0];
if (components.size() == 3) {
info.script = components[1];
info.region = components[2];
} else if (components.size() == 2) {
// A script code will always be four characters long.
if (components[1].size() == 4) {
info.script = components[1];
} else {
info.region = components[1];
}
}
return info;
}
......
......@@ -45,7 +45,7 @@ void TaskRunnerWinUwp::PostTask(TaskClosure task) {
// TODO: Handle the target time. See PostFlutterTask()
dispatcher_.RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal,
[task]() { task() });
[task]() { task(); });
}
} // namespace flutter
......@@ -71,7 +71,8 @@ class SpyKeyEventHandler : public KeyboardHookHandler {
void(FlutterWindowsView* window, const std::u16string& text));
MOCK_METHOD0(ComposeBeginHook, void());
MOCK_METHOD0(ComposeEndHook, void());
MOCK_METHOD2(ComposeChangeHook, void(const std::u16string& text, int cursor_pos));
MOCK_METHOD2(ComposeChangeHook,
void(const std::u16string& text, int cursor_pos));
private:
std::unique_ptr<KeyEventHandler> real_implementation_;
......@@ -103,7 +104,8 @@ class SpyTextInputPlugin : public KeyboardHookHandler,
void(FlutterWindowsView* window, const std::u16string& text));
MOCK_METHOD0(ComposeBeginHook, void());
MOCK_METHOD0(ComposeEndHook, void());
MOCK_METHOD2(ComposeChangeHook, void(const std::u16string& text, int cursor_pos));
MOCK_METHOD2(ComposeChangeHook,
void(const std::u16string& text, int cursor_pos));
virtual void OnCursorRectUpdated(const Rect& rect) {}
......
......@@ -14,6 +14,10 @@
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "flutter/shell/platform/windows/window_binding_handler_delegate.h"
#ifdef WINUWP
#include <winrt/Windows.UI.Composition.h>
#endif
namespace flutter {
class FlutterWindowsView;
......@@ -24,8 +28,14 @@ struct PhysicalWindowBounds {
size_t height;
};
using WindowsRenderTarget = std::variant<
/*winrt::Windows::UI::Composition::SpriteVisual, */ HWND>;
#ifdef WINUWP
using WindowsRenderTarget =
std::variant<winrt::Windows::UI::Composition::SpriteVisual,
winrt::Windows::UI::Core::CoreWindow,
HWND>;
#else
using WindowsRenderTarget = std::variant<HWND>;
#endif
// Abstract class for binding Windows platform windows to Flutter views.
class WindowBindingHandler {
......
......@@ -41,9 +41,11 @@ class WindowBindingHandlerDelegate {
// Typically called by currently configured WindowBindingHandler
virtual void OnText(const std::u16string&) = 0;
// Notifies delegate that backing window size has received key press. Should
// return true if the event was handled and should not be propagated.
// Typically called by currently configured WindowBindingHandler.
// TODO(clarkezone) refactor delegate to avoid needing win32 magic values in
// UWP implementation https://github.com/flutter/flutter/issues/70202 Notifies
// delegate that backing window size has received key press. Should return
// true if the event was handled and should not be propagated. Typically
// called by currently configured WindowBindingHandler.
virtual bool OnKey(int key,
int scancode,
int action,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册