mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
fuchsia: Don't send ViewportMetrics w/ 0 DPR (#21392)
This commit is contained in:
parent
9a7b556f91
commit
d5dddf32e7
@ -10,6 +10,13 @@ namespace flutter {
|
||||
|
||||
ViewportMetrics::ViewportMetrics() = default;
|
||||
|
||||
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height)
|
||||
: device_pixel_ratio(p_device_pixel_ratio),
|
||||
physical_width(p_physical_width),
|
||||
physical_height(p_physical_height) {}
|
||||
|
||||
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height,
|
||||
@ -44,11 +51,42 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
physical_system_gesture_inset_left(p_physical_system_gesture_inset_left) {
|
||||
}
|
||||
|
||||
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height)
|
||||
: device_pixel_ratio(p_device_pixel_ratio),
|
||||
physical_width(p_physical_width),
|
||||
physical_height(p_physical_height) {}
|
||||
bool operator==(const ViewportMetrics& a, const ViewportMetrics& b) {
|
||||
return a.device_pixel_ratio == b.device_pixel_ratio &&
|
||||
a.physical_width == b.physical_width &&
|
||||
a.physical_height == b.physical_height &&
|
||||
a.physical_padding_top == b.physical_padding_top &&
|
||||
a.physical_padding_right == b.physical_padding_right &&
|
||||
a.physical_padding_bottom == b.physical_padding_bottom &&
|
||||
a.physical_padding_left == b.physical_padding_left &&
|
||||
a.physical_view_inset_top == b.physical_view_inset_top &&
|
||||
a.physical_view_inset_right == b.physical_view_inset_right &&
|
||||
a.physical_view_inset_bottom == b.physical_view_inset_bottom &&
|
||||
a.physical_view_inset_left == b.physical_view_inset_left &&
|
||||
a.physical_system_gesture_inset_top ==
|
||||
b.physical_system_gesture_inset_top &&
|
||||
a.physical_system_gesture_inset_right ==
|
||||
b.physical_system_gesture_inset_right &&
|
||||
a.physical_system_gesture_inset_bottom ==
|
||||
b.physical_system_gesture_inset_bottom &&
|
||||
a.physical_system_gesture_inset_left ==
|
||||
b.physical_system_gesture_inset_left;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const ViewportMetrics& a) {
|
||||
os << "DPR: " << a.device_pixel_ratio << " "
|
||||
<< "Size: [" << a.physical_width << "W " << a.physical_height << "H] "
|
||||
<< "Padding: [" << a.physical_padding_top << "T "
|
||||
<< a.physical_padding_right << "R " << a.physical_padding_bottom << "B "
|
||||
<< a.physical_padding_left << "L] "
|
||||
<< "Insets: [" << a.physical_view_inset_top << "T "
|
||||
<< a.physical_view_inset_right << "R " << a.physical_view_inset_bottom
|
||||
<< "B " << a.physical_view_inset_left << "L] "
|
||||
<< "Gesture Insets: [" << a.physical_system_gesture_inset_top << "T "
|
||||
<< a.physical_system_gesture_inset_right << "R "
|
||||
<< a.physical_system_gesture_inset_bottom << "B "
|
||||
<< a.physical_system_gesture_inset_left << "L]";
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -5,10 +5,15 @@
|
||||
#ifndef FLUTTER_LIB_UI_WINDOW_VIEWPORT_METRICS_H_
|
||||
#define FLUTTER_LIB_UI_WINDOW_VIEWPORT_METRICS_H_
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
struct ViewportMetrics {
|
||||
ViewportMetrics();
|
||||
ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height);
|
||||
ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height,
|
||||
@ -25,12 +30,6 @@ struct ViewportMetrics {
|
||||
double p_physical_system_gesture_inset_bottom,
|
||||
double p_physical_system_gesture_inset_left);
|
||||
|
||||
// Create a ViewportMetrics instance that doesn't include depth, padding, or
|
||||
// insets.
|
||||
ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height);
|
||||
|
||||
double device_pixel_ratio = 1.0;
|
||||
double physical_width = 0;
|
||||
double physical_height = 0;
|
||||
@ -48,24 +47,8 @@ struct ViewportMetrics {
|
||||
double physical_system_gesture_inset_left = 0;
|
||||
};
|
||||
|
||||
struct LogicalSize {
|
||||
double width = 0.0;
|
||||
double height = 0.0;
|
||||
};
|
||||
|
||||
struct LogicalInset {
|
||||
double left = 0.0;
|
||||
double top = 0.0;
|
||||
double right = 0.0;
|
||||
double bottom = 0.0;
|
||||
};
|
||||
|
||||
struct LogicalMetrics {
|
||||
LogicalSize size;
|
||||
double scale = 1.0;
|
||||
LogicalInset padding;
|
||||
LogicalInset view_inset;
|
||||
};
|
||||
bool operator==(const ViewportMetrics& a, const ViewportMetrics& b);
|
||||
std::ostream& operator<<(std::ostream& os, const ViewportMetrics& a);
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
|
||||
@ -14,10 +14,11 @@
|
||||
#include "flutter/fml/logging.h"
|
||||
#include "flutter/lib/ui/window/pointer_data.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "third_party/rapidjson/include/rapidjson/document.h"
|
||||
#include "third_party/rapidjson/include/rapidjson/stringbuffer.h"
|
||||
#include "third_party/rapidjson/include/rapidjson/writer.h"
|
||||
|
||||
#include "logging.h"
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/stringbuffer.h"
|
||||
#include "rapidjson/writer.h"
|
||||
#include "runtime/dart/utils/inlines.h"
|
||||
#include "vsync_waiter.h"
|
||||
|
||||
@ -214,7 +215,8 @@ void PlatformView::OnScenicError(std::string error) {
|
||||
void PlatformView::OnScenicEvent(
|
||||
std::vector<fuchsia::ui::scenic::Event> events) {
|
||||
TRACE_EVENT0("flutter", "PlatformView::OnScenicEvent");
|
||||
bool should_update_metrics = false;
|
||||
|
||||
bool metrics_changed = false;
|
||||
for (const auto& event : events) {
|
||||
switch (event.Which()) {
|
||||
case fuchsia::ui::scenic::Event::Tag::kGfx:
|
||||
@ -223,31 +225,52 @@ void PlatformView::OnScenicEvent(
|
||||
const fuchsia::ui::gfx::Metrics& metrics =
|
||||
event.gfx().metrics().metrics;
|
||||
const float new_view_pixel_ratio = metrics.scale_x;
|
||||
if (new_view_pixel_ratio <= 0.f) {
|
||||
FML_DLOG(ERROR)
|
||||
<< "Got an invalid pixel ratio from Scenic; ignoring: "
|
||||
<< new_view_pixel_ratio;
|
||||
break;
|
||||
}
|
||||
|
||||
// Avoid metrics update when possible -- it is computationally
|
||||
// expensive.
|
||||
if (view_pixel_ratio_ != new_view_pixel_ratio) {
|
||||
view_pixel_ratio_ = new_view_pixel_ratio;
|
||||
should_update_metrics = true;
|
||||
if (view_pixel_ratio_.has_value() &&
|
||||
*view_pixel_ratio_ == new_view_pixel_ratio) {
|
||||
FML_DLOG(ERROR)
|
||||
<< "Got an identical pixel ratio from Scenic; ignoring: "
|
||||
<< new_view_pixel_ratio;
|
||||
break;
|
||||
}
|
||||
|
||||
view_pixel_ratio_ = new_view_pixel_ratio;
|
||||
metrics_changed = true;
|
||||
break;
|
||||
}
|
||||
case fuchsia::ui::gfx::Event::Tag::kViewPropertiesChanged: {
|
||||
const fuchsia::ui::gfx::BoundingBox& bounding_box =
|
||||
event.gfx().view_properties_changed().properties.bounding_box;
|
||||
const float new_view_width =
|
||||
std::max(bounding_box.max.x - bounding_box.min.x, 0.0f);
|
||||
const float new_view_height =
|
||||
std::max(bounding_box.max.y - bounding_box.min.y, 0.0f);
|
||||
const std::pair<float, float> new_view_size = {
|
||||
std::max(bounding_box.max.x - bounding_box.min.x, 0.0f),
|
||||
std::max(bounding_box.max.y - bounding_box.min.y, 0.0f)};
|
||||
if (new_view_size.first <= 0.f || new_view_size.second <= 0.f) {
|
||||
FML_DLOG(ERROR)
|
||||
<< "Got an invalid view size from Scenic; ignoring: "
|
||||
<< new_view_size.first << " " << new_view_size.second;
|
||||
break;
|
||||
}
|
||||
|
||||
// Avoid metrics update when possible -- it is computationally
|
||||
// expensive.
|
||||
if (view_width_ != new_view_width ||
|
||||
view_height_ != new_view_width) {
|
||||
view_width_ = new_view_width;
|
||||
view_height_ = new_view_height;
|
||||
should_update_metrics = true;
|
||||
if (view_logical_size_.has_value() &&
|
||||
*view_logical_size_ == new_view_size) {
|
||||
FML_DLOG(ERROR)
|
||||
<< "Got an identical view size from Scenic; ignoring: "
|
||||
<< new_view_size.first << " " << new_view_size.second;
|
||||
break;
|
||||
}
|
||||
|
||||
view_logical_size_ = new_view_size;
|
||||
metrics_changed = true;
|
||||
break;
|
||||
}
|
||||
case fuchsia::ui::gfx::Event::Tag::kViewConnected:
|
||||
@ -298,19 +321,22 @@ void PlatformView::OnScenicEvent(
|
||||
}
|
||||
}
|
||||
|
||||
if (should_update_metrics) {
|
||||
if (view_pixel_ratio_.has_value() && view_logical_size_.has_value() &&
|
||||
metrics_changed) {
|
||||
const float pixel_ratio = *view_pixel_ratio_;
|
||||
const std::pair<float, float> logical_size = *view_logical_size_;
|
||||
SetViewportMetrics({
|
||||
view_pixel_ratio_, // device_pixel_ratio
|
||||
view_width_ * view_pixel_ratio_, // physical_width
|
||||
view_height_ * view_pixel_ratio_, // physical_height
|
||||
0.0f, // physical_padding_top
|
||||
0.0f, // physical_padding_right
|
||||
0.0f, // physical_padding_bottom
|
||||
0.0f, // physical_padding_left
|
||||
0.0f, // physical_view_inset_top
|
||||
0.0f, // physical_view_inset_right
|
||||
0.0f, // physical_view_inset_bottom
|
||||
0.0f, // physical_view_inset_left
|
||||
pixel_ratio, // device_pixel_ratio
|
||||
logical_size.first * pixel_ratio, // physical_width
|
||||
logical_size.second * pixel_ratio, // physical_height
|
||||
0.0f, // physical_padding_top
|
||||
0.0f, // physical_padding_right
|
||||
0.0f, // physical_padding_bottom
|
||||
0.0f, // physical_padding_left
|
||||
0.0f, // physical_view_inset_top
|
||||
0.0f, // physical_view_inset_right
|
||||
0.0f, // physical_view_inset_bottom
|
||||
0.0f, // physical_view_inset_left
|
||||
0.0f, // p_physical_system_gesture_inset_top
|
||||
0.0f, // p_physical_system_gesture_inset_right
|
||||
0.0f, // p_physical_system_gesture_inset_bottom
|
||||
@ -421,6 +447,9 @@ bool PlatformView::OnHandlePointerEvent(
|
||||
PointerTraceHACK(pointer.radius_major, pointer.radius_minor);
|
||||
TRACE_FLOW_END("input", "dispatch_event_to_client", trace_id);
|
||||
|
||||
const float pixel_ratio =
|
||||
view_pixel_ratio_.has_value() ? *view_pixel_ratio_ : 0.f;
|
||||
|
||||
flutter::PointerData pointer_data;
|
||||
pointer_data.Clear();
|
||||
pointer_data.time_stamp = pointer.event_time / 1000;
|
||||
@ -428,8 +457,8 @@ bool PlatformView::OnHandlePointerEvent(
|
||||
pointer_data.kind = GetKindFromPointerType(pointer.type);
|
||||
pointer_data.device = pointer.pointer_id;
|
||||
// Pointer events are in logical pixels, so scale to physical.
|
||||
pointer_data.physical_x = pointer.x * view_pixel_ratio_;
|
||||
pointer_data.physical_y = pointer.y * view_pixel_ratio_;
|
||||
pointer_data.physical_x = pointer.x * pixel_ratio;
|
||||
pointer_data.physical_y = pointer.y * pixel_ratio;
|
||||
// Buttons are single bit values starting with kMousePrimaryButton = 1.
|
||||
pointer_data.buttons = static_cast<uint64_t>(pointer.buttons);
|
||||
|
||||
@ -601,7 +630,10 @@ void PlatformView::DispatchSemanticsAction(int32_t node_id,
|
||||
void PlatformView::UpdateSemantics(
|
||||
flutter::SemanticsNodeUpdates update,
|
||||
flutter::CustomAccessibilityActionUpdates actions) {
|
||||
accessibility_bridge_->AddSemanticsNodeUpdate(update, view_pixel_ratio_);
|
||||
const float pixel_ratio =
|
||||
view_pixel_ratio_.has_value() ? *view_pixel_ratio_ : 0.f;
|
||||
|
||||
accessibility_bridge_->AddSemanticsNodeUpdate(update, pixel_ratio);
|
||||
}
|
||||
|
||||
// Channel handler for kAccessibilityChannel
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include <fuchsia/ui/scenic/cpp/fidl.h>
|
||||
#include <lib/fidl/cpp/binding.h>
|
||||
#include <lib/fit/function.h>
|
||||
#include <lib/ui/scenic/cpp/id.h>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
@ -19,8 +20,6 @@
|
||||
|
||||
#include "accessibility_bridge.h"
|
||||
|
||||
#include <lib/ui/scenic/cpp/id.h> // nogncheck
|
||||
|
||||
namespace flutter_runner {
|
||||
|
||||
using OnEnableWireframe = fit::function<void(bool)>;
|
||||
@ -29,16 +28,22 @@ using OnUpdateView = fit::function<void(int64_t, bool, bool)>;
|
||||
using OnDestroyView = fit::function<void(int64_t)>;
|
||||
using OnCreateSurface = fit::function<std::unique_ptr<flutter::Surface>()>;
|
||||
|
||||
// The per engine component residing on the platform thread is responsible for
|
||||
// all platform specific integrations.
|
||||
// PlatformView is the per-engine component residing on the platform thread that
|
||||
// is responsible for all platform specific integrations -- particularly
|
||||
// integration with the platform's accessibility, input, and windowing features.
|
||||
//
|
||||
// PlatformView communicates with the Dart code via "platform messages" handled
|
||||
// in HandlePlatformMessage. This communication is bidirectional. Platform
|
||||
// messages are notably responsible for communication related to input and
|
||||
// external views / windowing.
|
||||
//
|
||||
// The PlatformView implements SessionListener and gets Session events but it
|
||||
// does *not* actually own the Session itself; that is owned by the Compositor
|
||||
// thread.
|
||||
// does *not* actually own the Session itself; that is owned by the
|
||||
// FuchsiaExternalViewEmbedder on the raster thread.
|
||||
class PlatformView final : public flutter::PlatformView,
|
||||
public AccessibilityBridge::Delegate,
|
||||
private fuchsia::ui::scenic::SessionListener,
|
||||
public fuchsia::ui::input::InputMethodEditorClient,
|
||||
public AccessibilityBridge::Delegate {
|
||||
private fuchsia::ui::input::InputMethodEditorClient {
|
||||
public:
|
||||
PlatformView(flutter::PlatformView::Delegate& delegate,
|
||||
std::string debug_label,
|
||||
@ -73,51 +78,6 @@ class PlatformView final : public flutter::PlatformView,
|
||||
flutter::PointerDataDispatcherMaker GetDispatcherMaker() override;
|
||||
|
||||
private:
|
||||
const std::string debug_label_;
|
||||
// TODO(MI4-2490): remove once ViewRefControl is passed to Scenic and kept
|
||||
// alive there
|
||||
const fuchsia::ui::views::ViewRef view_ref_;
|
||||
fuchsia::ui::views::FocuserPtr focuser_;
|
||||
std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
|
||||
|
||||
fidl::Binding<fuchsia::ui::scenic::SessionListener> session_listener_binding_;
|
||||
fit::closure session_listener_error_callback_;
|
||||
OnEnableWireframe wireframe_enabled_callback_;
|
||||
OnCreateView on_create_view_callback_;
|
||||
OnUpdateView on_update_view_callback_;
|
||||
OnDestroyView on_destroy_view_callback_;
|
||||
OnCreateSurface on_create_surface_callback_;
|
||||
|
||||
int current_text_input_client_ = 0;
|
||||
fidl::Binding<fuchsia::ui::input::InputMethodEditorClient> ime_client_;
|
||||
fuchsia::ui::input::InputMethodEditorPtr ime_;
|
||||
fuchsia::ui::input::ImeServicePtr text_sync_service_;
|
||||
|
||||
fuchsia::sys::ServiceProviderPtr parent_environment_service_provider_;
|
||||
|
||||
// last_text_state_ is the last state of the text input as reported by the IME
|
||||
// or initialized by Flutter. We set it to null if Flutter doesn't want any
|
||||
// input, since then there is no text input state at all.
|
||||
std::unique_ptr<fuchsia::ui::input::TextInputState> last_text_state_;
|
||||
|
||||
std::set<int> down_pointers_;
|
||||
std::map<
|
||||
std::string /* channel */,
|
||||
fit::function<void(
|
||||
fml::RefPtr<flutter::PlatformMessage> /* message */)> /* handler */>
|
||||
platform_message_handlers_;
|
||||
// These are the channels that aren't registered and have been notified as
|
||||
// such. Notifying via logs multiple times results in log-spam. See:
|
||||
// https://github.com/flutter/flutter/issues/55966
|
||||
std::set<std::string /* channel */> unregistered_channels_;
|
||||
|
||||
fml::TimeDelta vsync_offset_;
|
||||
zx_handle_t vsync_event_handle_ = 0;
|
||||
|
||||
float view_width_ = 0.0f; // Width in logical pixels.
|
||||
float view_height_ = 0.0f; // Height in logical pixels.
|
||||
float view_pixel_ratio_ = 0.0f; // Logical / physical pixel ratio.
|
||||
|
||||
void RegisterPlatformMessageHandlers();
|
||||
|
||||
// |fuchsia::ui::input::InputMethodEditorClient|
|
||||
@ -185,6 +145,57 @@ class PlatformView final : public flutter::PlatformView,
|
||||
void HandleFlutterPlatformViewsChannelPlatformMessage(
|
||||
fml::RefPtr<flutter::PlatformMessage> message);
|
||||
|
||||
const std::string debug_label_;
|
||||
// TODO(MI4-2490): remove once ViewRefControl is passed to Scenic and kept
|
||||
// alive there
|
||||
const fuchsia::ui::views::ViewRef view_ref_;
|
||||
fuchsia::ui::views::FocuserPtr focuser_;
|
||||
std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
|
||||
|
||||
// Logical size and logical->physical ratio. These are optional to provide
|
||||
// an "unset" state during program startup, before Scenic has sent any
|
||||
// metrics-related events to provide initial values for these.
|
||||
//
|
||||
// The engine internally uses a default size of (0.f 0.f) with a default 1.f
|
||||
// ratio, so there is no need to emit events until Scenic has actually sent a
|
||||
// valid size and ratio.
|
||||
std::optional<std::pair<float, float>> view_logical_size_;
|
||||
std::optional<float> view_pixel_ratio_;
|
||||
|
||||
fidl::Binding<fuchsia::ui::scenic::SessionListener> session_listener_binding_;
|
||||
fit::closure session_listener_error_callback_;
|
||||
OnEnableWireframe wireframe_enabled_callback_;
|
||||
OnCreateView on_create_view_callback_;
|
||||
OnUpdateView on_update_view_callback_;
|
||||
OnDestroyView on_destroy_view_callback_;
|
||||
OnCreateSurface on_create_surface_callback_;
|
||||
|
||||
int current_text_input_client_ = 0;
|
||||
fidl::Binding<fuchsia::ui::input::InputMethodEditorClient> ime_client_;
|
||||
fuchsia::ui::input::InputMethodEditorPtr ime_;
|
||||
fuchsia::ui::input::ImeServicePtr text_sync_service_;
|
||||
|
||||
fuchsia::sys::ServiceProviderPtr parent_environment_service_provider_;
|
||||
|
||||
// last_text_state_ is the last state of the text input as reported by the IME
|
||||
// or initialized by Flutter. We set it to null if Flutter doesn't want any
|
||||
// input, since then there is no text input state at all.
|
||||
std::unique_ptr<fuchsia::ui::input::TextInputState> last_text_state_;
|
||||
|
||||
std::set<int> down_pointers_;
|
||||
std::map<
|
||||
std::string /* channel */,
|
||||
fit::function<void(
|
||||
fml::RefPtr<flutter::PlatformMessage> /* message */)> /* handler */>
|
||||
platform_message_handlers_;
|
||||
// These are the channels that aren't registered and have been notified as
|
||||
// such. Notifying via logs multiple times results in log-spam. See:
|
||||
// https://github.com/flutter/flutter/issues/55966
|
||||
std::set<std::string /* channel */> unregistered_channels_;
|
||||
|
||||
fml::TimeDelta vsync_offset_;
|
||||
zx_handle_t vsync_event_handle_ = 0;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(PlatformView);
|
||||
};
|
||||
|
||||
|
||||
@ -4,50 +4,35 @@
|
||||
|
||||
#include "flutter/shell/platform/fuchsia/flutter/platform_view.h"
|
||||
|
||||
#include <fuchsia/ui/gfx/cpp/fidl.h>
|
||||
#include <fuchsia/ui/scenic/cpp/fidl.h>
|
||||
#include <fuchsia/ui/views/cpp/fidl.h>
|
||||
#include <lib/async-loop/cpp/loop.h>
|
||||
#include <lib/async-loop/default.h>
|
||||
#include <lib/async/default.h>
|
||||
#include <lib/fidl/cpp/binding_set.h>
|
||||
#include <lib/fidl/cpp/interface_request.h>
|
||||
#include <lib/sys/cpp/testing/service_directory_provider.h>
|
||||
#include <lib/ui/scenic/cpp/view_ref_pair.h>
|
||||
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/flow/embedded_views.h"
|
||||
#include "flutter/lib/ui/window/platform_message.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "flutter/lib/ui/window/viewport_metrics.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "surface.h"
|
||||
#include "task_runner_adapter.h"
|
||||
|
||||
namespace flutter_runner_test::flutter_runner_a11y_test {
|
||||
|
||||
class PlatformViewTests : public testing::Test {
|
||||
protected:
|
||||
PlatformViewTests() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {}
|
||||
|
||||
async_dispatcher_t* dispatcher() { return loop_.dispatcher(); }
|
||||
|
||||
void RunLoopUntilIdle() {
|
||||
loop_.RunUntilIdle();
|
||||
loop_.ResetQuit();
|
||||
}
|
||||
|
||||
private:
|
||||
async::Loop loop_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewTests);
|
||||
};
|
||||
namespace flutter_runner::testing {
|
||||
namespace {
|
||||
|
||||
class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder {
|
||||
public:
|
||||
MockExternalViewEmbedder() = default;
|
||||
~MockExternalViewEmbedder() override = default;
|
||||
|
||||
SkCanvas* GetRootCanvas() override { return nullptr; }
|
||||
std::vector<SkCanvas*> GetCurrentCanvases() override {
|
||||
return std::vector<SkCanvas*>();
|
||||
@ -82,7 +67,9 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate {
|
||||
void OnPlatformViewSetNextFrameCallback(const fml::closure& closure) {}
|
||||
// |flutter::PlatformView::Delegate|
|
||||
void OnPlatformViewSetViewportMetrics(
|
||||
const flutter::ViewportMetrics& metrics) {}
|
||||
const flutter::ViewportMetrics& metrics) {
|
||||
metrics_ = metrics;
|
||||
}
|
||||
// |flutter::PlatformView::Delegate|
|
||||
void OnPlatformViewDispatchPlatformMessage(
|
||||
fml::RefPtr<flutter::PlatformMessage> message) {
|
||||
@ -113,43 +100,45 @@ class MockPlatformViewDelegate : public flutter::PlatformView::Delegate {
|
||||
// |flutter::PlatformView::Delegate|
|
||||
std::unique_ptr<std::vector<std::string>> ComputePlatformViewResolvedLocale(
|
||||
const std::vector<std::string>& supported_locale_data) {
|
||||
std::unique_ptr<std::vector<std::string>> out =
|
||||
std::make_unique<std::vector<std::string>>();
|
||||
return out;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool SemanticsEnabled() const { return semantics_enabled_; }
|
||||
int32_t SemanticsFeatures() const { return semantics_features_; }
|
||||
flutter::Surface* surface() const { return surface_.get(); }
|
||||
fml::RefPtr<flutter::PlatformMessage>& message() { return message_; }
|
||||
flutter::PlatformMessage* message() const { return message_.get(); }
|
||||
const flutter::ViewportMetrics& metrics() const { return metrics_; }
|
||||
int32_t semantics_features() const { return semantics_features_; }
|
||||
bool semantics_enabled() const { return semantics_enabled_; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<flutter::Surface> surface_;
|
||||
bool semantics_enabled_ = false;
|
||||
int32_t semantics_features_ = 0;
|
||||
fml::RefPtr<flutter::PlatformMessage> message_;
|
||||
flutter::ViewportMetrics metrics_;
|
||||
int32_t semantics_features_ = 0;
|
||||
bool semantics_enabled_ = false;
|
||||
};
|
||||
|
||||
class MockFocuser : public fuchsia::ui::views::Focuser {
|
||||
public:
|
||||
MockFocuser() = default;
|
||||
~MockFocuser() override = default;
|
||||
MockFocuser(bool fail_request_focus = false)
|
||||
: fail_request_focus_(fail_request_focus) {}
|
||||
|
||||
bool request_focus_called = false;
|
||||
bool fail_request_focus = false;
|
||||
bool request_focus_called() const { return request_focus_called_; }
|
||||
|
||||
private:
|
||||
void RequestFocus(fuchsia::ui::views::ViewRef view_ref,
|
||||
RequestFocusCallback callback) override {
|
||||
request_focus_called = true;
|
||||
request_focus_called_ = true;
|
||||
auto result =
|
||||
fail_request_focus
|
||||
fail_request_focus_
|
||||
? fuchsia::ui::views::Focuser_RequestFocus_Result::WithErr(
|
||||
fuchsia::ui::views::Error::DENIED)
|
||||
: fuchsia::ui::views::Focuser_RequestFocus_Result::WithResponse(
|
||||
fuchsia::ui::views::Focuser_RequestFocus_Response());
|
||||
callback(std::move(result));
|
||||
}
|
||||
|
||||
bool request_focus_called_ = false;
|
||||
bool fail_request_focus_ = false;
|
||||
};
|
||||
|
||||
class MockResponse : public flutter::PlatformMessageResponse {
|
||||
@ -158,25 +147,228 @@ class MockResponse : public flutter::PlatformMessageResponse {
|
||||
MOCK_METHOD0(CompleteEmpty, void());
|
||||
};
|
||||
|
||||
TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
|
||||
} // namespace
|
||||
|
||||
class PlatformViewTests : public ::testing::Test {
|
||||
protected:
|
||||
PlatformViewTests() : loop_(&kAsyncLoopConfigAttachToCurrentThread) {}
|
||||
|
||||
async_dispatcher_t* dispatcher() { return loop_.dispatcher(); }
|
||||
|
||||
void RunLoopUntilIdle() {
|
||||
loop_.RunUntilIdle();
|
||||
loop_.ResetQuit();
|
||||
}
|
||||
|
||||
private:
|
||||
async::Loop loop_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewTests);
|
||||
};
|
||||
|
||||
// This test makes sure that the PlatformView correctly returns a Surface
|
||||
// instance that can surface the provided gr_context and view_embedder.
|
||||
TEST_F(PlatformViewTests, CreateSurfaceTest) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
|
||||
MockPlatformViewDelegate delegate;
|
||||
zx::eventpair a, b;
|
||||
zx::eventpair::create(/* flags */ 0u, &a, &b);
|
||||
auto view_ref = fuchsia::ui::views::ViewRef({
|
||||
.reference = std::move(a),
|
||||
});
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
EXPECT_FALSE(delegate.SemanticsEnabled());
|
||||
EXPECT_EQ(delegate.SemanticsFeatures(), 0);
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", // label
|
||||
nullptr, // platform
|
||||
flutter_runner::CreateFMLTaskRunner(
|
||||
async_get_default_dispatcher()), // raster
|
||||
nullptr, // ui
|
||||
nullptr // io
|
||||
);
|
||||
|
||||
// Test create surface callback function.
|
||||
sk_sp<GrDirectContext> gr_context =
|
||||
GrDirectContext::MakeMock(nullptr, GrContextOptions());
|
||||
MockExternalViewEmbedder view_embedder;
|
||||
auto CreateSurfaceCallback = [&view_embedder, gr_context]() {
|
||||
return std::make_unique<flutter_runner::Surface>(
|
||||
"PlatformViewTest", &view_embedder, gr_context.get());
|
||||
};
|
||||
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
std::move(view_ref), // view_ref
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
nullptr, // session_listener_request
|
||||
nullptr, // focuser,
|
||||
nullptr, // on_session_listener_error_callback
|
||||
nullptr, // on_enable_wireframe_callback,
|
||||
nullptr, // on_create_view_callback,
|
||||
nullptr, // on_update_view_callback,
|
||||
nullptr, // on_destroy_view_callback,
|
||||
CreateSurfaceCallback, // on_create_surface_callback,
|
||||
fml::TimeDelta::Zero(), // vsync_offset
|
||||
ZX_HANDLE_INVALID // vsync_event_handle
|
||||
);
|
||||
platform_view.NotifyCreated();
|
||||
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_EQ(gr_context.get(), delegate.surface()->GetContext());
|
||||
EXPECT_EQ(&view_embedder, delegate.surface()->GetExternalViewEmbedder());
|
||||
}
|
||||
|
||||
// This test makes sure that the PlatformView correctly registers Scenic
|
||||
// MetricsEvents sent to it via FIDL, correctly parses the metrics it receives,
|
||||
// and calls the SetViewportMetrics callback with the appropriate parameters.
|
||||
TEST_F(PlatformViewTests, SetViewportMetrics) {
|
||||
constexpr float invalid_pixel_ratio = -0.75f;
|
||||
constexpr float valid_pixel_ratio = 0.75f;
|
||||
constexpr float invalid_max_bound = -0.75f;
|
||||
constexpr float valid_max_bound = 0.75f;
|
||||
|
||||
MockPlatformViewDelegate delegate;
|
||||
EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());
|
||||
|
||||
fuchsia::ui::scenic::SessionListenerPtr session_listener;
|
||||
std::vector<fuchsia::ui::scenic::Event> events;
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
flutter::TaskRunners task_runners("test_runners", nullptr, nullptr, nullptr,
|
||||
nullptr);
|
||||
flutter_runner::PlatformView platform_view(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
session_listener.NewRequest(), // session_listener_request
|
||||
nullptr, // focuser,
|
||||
nullptr, // on_session_listener_error_callback
|
||||
nullptr, // on_enable_wireframe_callback,
|
||||
nullptr, // on_create_view_callback,
|
||||
nullptr, // on_update_view_callback,
|
||||
nullptr, // on_destroy_view_callback,
|
||||
nullptr, // on_create_surface_callback,
|
||||
fml::TimeDelta::Zero(), // vsync_offset
|
||||
ZX_HANDLE_INVALID // vsync_event_handle
|
||||
);
|
||||
RunLoopUntilIdle();
|
||||
EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());
|
||||
|
||||
// Test updating with an invalid pixel ratio. The final metrics should be
|
||||
// unchanged.
|
||||
events.clear();
|
||||
events.emplace_back(fuchsia::ui::scenic::Event::WithGfx(
|
||||
fuchsia::ui::gfx::Event::WithMetrics(fuchsia::ui::gfx::MetricsEvent{
|
||||
.node_id = 0,
|
||||
.metrics =
|
||||
fuchsia::ui::gfx::Metrics{
|
||||
.scale_x = invalid_pixel_ratio,
|
||||
.scale_y = 1.f,
|
||||
.scale_z = 1.f,
|
||||
},
|
||||
})));
|
||||
session_listener->OnScenicEvent(std::move(events));
|
||||
RunLoopUntilIdle();
|
||||
EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());
|
||||
|
||||
// Test updating with an invalid size. The final metrics should be unchanged.
|
||||
events.clear();
|
||||
events.emplace_back(
|
||||
fuchsia::ui::scenic::Event::WithGfx(
|
||||
fuchsia::ui::gfx::Event::WithViewPropertiesChanged(
|
||||
fuchsia::ui::gfx::ViewPropertiesChangedEvent{
|
||||
.view_id = 0,
|
||||
.properties =
|
||||
fuchsia::ui::gfx::ViewProperties{
|
||||
.bounding_box =
|
||||
fuchsia::ui::gfx::BoundingBox{
|
||||
.min =
|
||||
fuchsia::ui::gfx::vec3{
|
||||
.x = 0.f,
|
||||
.y = 0.f,
|
||||
.z = 0.f,
|
||||
},
|
||||
.max =
|
||||
fuchsia::ui::gfx::vec3{
|
||||
.x = invalid_max_bound,
|
||||
.y = invalid_max_bound,
|
||||
.z = invalid_max_bound,
|
||||
},
|
||||
},
|
||||
},
|
||||
})));
|
||||
session_listener->OnScenicEvent(std::move(events));
|
||||
RunLoopUntilIdle();
|
||||
EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());
|
||||
|
||||
// Test updating the size only. The final metrics should be unchanged until
|
||||
// both pixel ratio and size are updated.
|
||||
events.clear();
|
||||
events.emplace_back(
|
||||
fuchsia::ui::scenic::Event::WithGfx(
|
||||
fuchsia::ui::gfx::Event::WithViewPropertiesChanged(
|
||||
fuchsia::ui::gfx::ViewPropertiesChangedEvent{
|
||||
.view_id = 0,
|
||||
.properties =
|
||||
fuchsia::ui::gfx::ViewProperties{
|
||||
.bounding_box =
|
||||
fuchsia::ui::gfx::BoundingBox{
|
||||
.min =
|
||||
fuchsia::ui::gfx::vec3{
|
||||
.x = 0.f,
|
||||
.y = 0.f,
|
||||
.z = 0.f,
|
||||
},
|
||||
.max =
|
||||
fuchsia::ui::gfx::vec3{
|
||||
.x = valid_max_bound,
|
||||
.y = valid_max_bound,
|
||||
.z = valid_max_bound,
|
||||
},
|
||||
},
|
||||
},
|
||||
})));
|
||||
session_listener->OnScenicEvent(std::move(events));
|
||||
RunLoopUntilIdle();
|
||||
EXPECT_EQ(delegate.metrics(), flutter::ViewportMetrics());
|
||||
|
||||
// Test updating the pixel ratio only. The final metrics should change now.
|
||||
events.clear();
|
||||
events.emplace_back(fuchsia::ui::scenic::Event::WithGfx(
|
||||
fuchsia::ui::gfx::Event::WithMetrics(fuchsia::ui::gfx::MetricsEvent{
|
||||
.node_id = 0,
|
||||
.metrics =
|
||||
fuchsia::ui::gfx::Metrics{
|
||||
.scale_x = valid_pixel_ratio,
|
||||
.scale_y = 1.f,
|
||||
.scale_z = 1.f,
|
||||
},
|
||||
})));
|
||||
session_listener->OnScenicEvent(std::move(events));
|
||||
RunLoopUntilIdle();
|
||||
EXPECT_EQ(delegate.metrics(),
|
||||
flutter::ViewportMetrics(valid_pixel_ratio,
|
||||
valid_pixel_ratio * valid_max_bound,
|
||||
valid_pixel_ratio * valid_max_bound));
|
||||
}
|
||||
|
||||
// This test makes sure that the PlatformView correctly registers semantics
|
||||
// settings changes applied to it and calls the SetSemanticsEnabled /
|
||||
// SetAccessibilityFeatures callbacks with the appropriate parameters.
|
||||
TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
|
||||
MockPlatformViewDelegate delegate;
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
EXPECT_FALSE(delegate.semantics_enabled());
|
||||
EXPECT_EQ(delegate.semantics_features(), 0);
|
||||
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
@ -196,28 +388,22 @@ TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
|
||||
|
||||
platform_view.SetSemanticsEnabled(true);
|
||||
|
||||
EXPECT_TRUE(delegate.SemanticsEnabled());
|
||||
EXPECT_EQ(delegate.SemanticsFeatures(),
|
||||
EXPECT_TRUE(delegate.semantics_enabled());
|
||||
EXPECT_EQ(delegate.semantics_features(),
|
||||
static_cast<int32_t>(
|
||||
flutter::AccessibilityFeatureFlag::kAccessibleNavigation));
|
||||
|
||||
platform_view.SetSemanticsEnabled(false);
|
||||
|
||||
EXPECT_FALSE(delegate.SemanticsEnabled());
|
||||
EXPECT_EQ(delegate.SemanticsFeatures(), 0);
|
||||
EXPECT_FALSE(delegate.semantics_enabled());
|
||||
EXPECT_EQ(delegate.semantics_features(), 0);
|
||||
}
|
||||
|
||||
// Test to make sure that PlatformView correctly registers messages sent on
|
||||
// the "flutter/platform_views" channel, correctly parses the JSON it receives
|
||||
// and calls the EnableWireframeCallback with the appropriate args.
|
||||
// This test makes sure that the PlatformView forwards messages on the
|
||||
// "flutter/platform_views" channel for EnableWireframe.
|
||||
TEST_F(PlatformViewTests, EnableWireframeTest) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
MockPlatformViewDelegate delegate;
|
||||
zx::eventpair a, b;
|
||||
zx::eventpair::create(/* flags */ 0u, &a, &b);
|
||||
auto view_ref = fuchsia::ui::views::ViewRef({
|
||||
.reference = std::move(a),
|
||||
});
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
@ -232,7 +418,7 @@ TEST_F(PlatformViewTests, EnableWireframeTest) {
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
std::move(view_ref), // view_refs
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
@ -274,17 +460,11 @@ TEST_F(PlatformViewTests, EnableWireframeTest) {
|
||||
EXPECT_TRUE(wireframe_enabled);
|
||||
}
|
||||
|
||||
// Test to make sure that PlatformView correctly registers messages sent on
|
||||
// the "flutter/platform_views" channel, correctly parses the JSON it receives
|
||||
// and calls the CreateViewCallback with the appropriate args.
|
||||
// This test makes sure that the PlatformView forwards messages on the
|
||||
// "flutter/platform_views" channel for Createview.
|
||||
TEST_F(PlatformViewTests, CreateViewTest) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
MockPlatformViewDelegate delegate;
|
||||
zx::eventpair a, b;
|
||||
zx::eventpair::create(/* flags */ 0u, &a, &b);
|
||||
auto view_ref = fuchsia::ui::views::ViewRef({
|
||||
.reference = std::move(a),
|
||||
});
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
@ -299,7 +479,7 @@ TEST_F(PlatformViewTests, CreateViewTest) {
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
std::move(view_ref), // view_refs
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
@ -343,17 +523,11 @@ TEST_F(PlatformViewTests, CreateViewTest) {
|
||||
EXPECT_TRUE(create_view_called);
|
||||
}
|
||||
|
||||
// Test to make sure that PlatformView correctly registers messages sent on
|
||||
// the "flutter/platform_views" channel, correctly parses the JSON it receives
|
||||
// and calls the UdpateViewCallback with the appropriate args.
|
||||
// This test makes sure that the PlatformView forwards messages on the
|
||||
// "flutter/platform_views" channel for UpdateView.
|
||||
TEST_F(PlatformViewTests, UpdateViewTest) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
MockPlatformViewDelegate delegate;
|
||||
zx::eventpair a, b;
|
||||
zx::eventpair::create(/* flags */ 0u, &a, &b);
|
||||
auto view_ref = fuchsia::ui::views::ViewRef({
|
||||
.reference = std::move(a),
|
||||
});
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
@ -368,7 +542,7 @@ TEST_F(PlatformViewTests, UpdateViewTest) {
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
std::move(view_ref), // view_refs
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
@ -412,17 +586,11 @@ TEST_F(PlatformViewTests, UpdateViewTest) {
|
||||
EXPECT_TRUE(update_view_called);
|
||||
}
|
||||
|
||||
// Test to make sure that PlatformView correctly registers messages sent on
|
||||
// the "flutter/platform_views" channel, correctly parses the JSON it receives
|
||||
// and calls the DestroyViewCallback with the appropriate args.
|
||||
// This test makes sure that the PlatformView forwards messages on the
|
||||
// "flutter/platform_views" channel for DestroyView.
|
||||
TEST_F(PlatformViewTests, DestroyViewTest) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
MockPlatformViewDelegate delegate;
|
||||
zx::eventpair a, b;
|
||||
zx::eventpair::create(/* flags */ 0u, &a, &b);
|
||||
auto view_ref = fuchsia::ui::views::ViewRef({
|
||||
.reference = std::move(a),
|
||||
});
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
@ -437,7 +605,7 @@ TEST_F(PlatformViewTests, DestroyViewTest) {
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
std::move(view_ref), // view_refs
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
@ -479,173 +647,9 @@ TEST_F(PlatformViewTests, DestroyViewTest) {
|
||||
EXPECT_TRUE(destroy_view_called);
|
||||
}
|
||||
|
||||
// Test to make sure that PlatformView correctly registers messages sent on
|
||||
// the "flutter/platform_views" channel, correctly parses the JSON it receives
|
||||
// and calls the focuser's RequestFocus with the appropriate args.
|
||||
TEST_F(PlatformViewTests, RequestFocusTest) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
MockPlatformViewDelegate delegate;
|
||||
zx::eventpair a, b;
|
||||
zx::eventpair::create(/* flags */ 0u, &a, &b);
|
||||
auto view_ref = fuchsia::ui::views::ViewRef({
|
||||
.reference = std::move(a),
|
||||
});
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
MockFocuser mock_focuser;
|
||||
fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
|
||||
auto focuser_handle = focuser_bindings.AddBinding(&mock_focuser);
|
||||
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
std::move(view_ref), // view_refs
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
nullptr, // session_listener_request
|
||||
std::move(focuser_handle), // focuser,
|
||||
nullptr, // on_session_listener_error_callback
|
||||
nullptr, // on_enable_wireframe_callback,
|
||||
nullptr, // on_create_view_callback,
|
||||
nullptr, // on_update_view_callback,
|
||||
nullptr, // on_destroy_view_callback,
|
||||
nullptr, // on_create_surface_callback,
|
||||
fml::TimeDelta::Zero(), // vsync_offset
|
||||
ZX_HANDLE_INVALID // vsync_event_handle
|
||||
);
|
||||
|
||||
// Cast platform_view to its base view so we can have access to the public
|
||||
// "HandlePlatformMessage" function.
|
||||
auto base_view = dynamic_cast<flutter::PlatformView*>(&platform_view);
|
||||
EXPECT_TRUE(base_view);
|
||||
|
||||
// JSON for the message to be passed into the PlatformView.
|
||||
char buff[254];
|
||||
snprintf(buff, sizeof(buff),
|
||||
"{"
|
||||
" \"method\":\"View.requestFocus\","
|
||||
" \"args\": {"
|
||||
" \"viewRef\":%u"
|
||||
" }"
|
||||
"}",
|
||||
b.get());
|
||||
|
||||
// Define a custom gmock matcher to capture the response to platform message.
|
||||
struct DataArg {
|
||||
void Complete(std::unique_ptr<fml::Mapping> data) {
|
||||
this->data = std::move(data);
|
||||
}
|
||||
std::unique_ptr<fml::Mapping> data;
|
||||
};
|
||||
DataArg data_arg;
|
||||
fml::RefPtr<MockResponse> response = fml::MakeRefCounted<MockResponse>();
|
||||
EXPECT_CALL(*response, Complete(testing::_))
|
||||
.WillOnce(testing::Invoke(&data_arg, &DataArg::Complete));
|
||||
|
||||
fml::RefPtr<flutter::PlatformMessage> message =
|
||||
fml::MakeRefCounted<flutter::PlatformMessage>(
|
||||
"flutter/platform_views",
|
||||
std::vector<uint8_t>(buff, buff + sizeof(buff)), response);
|
||||
base_view->HandlePlatformMessage(message);
|
||||
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_TRUE(mock_focuser.request_focus_called);
|
||||
auto result = std::string((const char*)data_arg.data->GetMapping(),
|
||||
data_arg.data->GetSize());
|
||||
EXPECT_EQ(std::string("[0]"), result);
|
||||
}
|
||||
|
||||
// Test to make sure that PlatformView correctly registers messages sent on
|
||||
// the "flutter/platform_views" channel, correctly parses the JSON it receives
|
||||
// and calls the focuser's RequestFocus with the appropriate args.
|
||||
TEST_F(PlatformViewTests, RequestFocusFailTest) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
MockPlatformViewDelegate delegate;
|
||||
zx::eventpair a, b;
|
||||
zx::eventpair::create(/* flags */ 0u, &a, &b);
|
||||
auto view_ref = fuchsia::ui::views::ViewRef({
|
||||
.reference = std::move(a),
|
||||
});
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
MockFocuser mock_focuser;
|
||||
mock_focuser.fail_request_focus = true;
|
||||
fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
|
||||
auto focuser_handle = focuser_bindings.AddBinding(&mock_focuser);
|
||||
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
std::move(view_ref), // view_refs
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
nullptr, // session_listener_request
|
||||
std::move(focuser_handle), // focuser,
|
||||
nullptr, // on_session_listener_error_callback
|
||||
nullptr, // on_enable_wireframe_callback,
|
||||
nullptr, // on_create_view_callback,
|
||||
nullptr, // on_update_view_callback,
|
||||
nullptr, // on_destroy_view_callback,
|
||||
nullptr, // on_create_surface_callback,
|
||||
fml::TimeDelta::Zero(), // vsync_offset
|
||||
ZX_HANDLE_INVALID // vsync_event_handle
|
||||
);
|
||||
|
||||
// Cast platform_view to its base view so we can have access to the public
|
||||
// "HandlePlatformMessage" function.
|
||||
auto base_view = dynamic_cast<flutter::PlatformView*>(&platform_view);
|
||||
EXPECT_TRUE(base_view);
|
||||
|
||||
// JSON for the message to be passed into the PlatformView.
|
||||
char buff[254];
|
||||
snprintf(buff, sizeof(buff),
|
||||
"{"
|
||||
" \"method\":\"View.requestFocus\","
|
||||
" \"args\": {"
|
||||
" \"viewRef\":%u"
|
||||
" }"
|
||||
"}",
|
||||
b.get());
|
||||
|
||||
// Define a custom gmock matcher to capture the response to platform message.
|
||||
struct DataArg {
|
||||
void Complete(std::unique_ptr<fml::Mapping> data) {
|
||||
this->data = std::move(data);
|
||||
}
|
||||
std::unique_ptr<fml::Mapping> data;
|
||||
};
|
||||
DataArg data_arg;
|
||||
fml::RefPtr<MockResponse> response = fml::MakeRefCounted<MockResponse>();
|
||||
EXPECT_CALL(*response, Complete(testing::_))
|
||||
.WillOnce(testing::Invoke(&data_arg, &DataArg::Complete));
|
||||
|
||||
fml::RefPtr<flutter::PlatformMessage> message =
|
||||
fml::MakeRefCounted<flutter::PlatformMessage>(
|
||||
"flutter/platform_views",
|
||||
std::vector<uint8_t>(buff, buff + sizeof(buff)), response);
|
||||
base_view->HandlePlatformMessage(message);
|
||||
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_TRUE(mock_focuser.request_focus_called);
|
||||
auto result = std::string((const char*)data_arg.data->GetMapping(),
|
||||
data_arg.data->GetSize());
|
||||
std::ostringstream out;
|
||||
out << "["
|
||||
<< static_cast<std::underlying_type_t<fuchsia::ui::views::Error>>(
|
||||
fuchsia::ui::views::Error::DENIED)
|
||||
<< "]";
|
||||
EXPECT_EQ(out.str(), result);
|
||||
}
|
||||
|
||||
// Test to make sure that PlatformView forward messages on the
|
||||
// "flutter/platform_views" channel, for viewConnected/viewDisconnected and
|
||||
// viewStateChanged events.
|
||||
// This test makes sure that the PlatformView forwards messages on the
|
||||
// "flutter/platform_views" channel for ViewConnected, ViewDisconnected, and
|
||||
// ViewStateChanged events.
|
||||
TEST_F(PlatformViewTests, ViewEventsTest) {
|
||||
MockPlatformViewDelegate delegate;
|
||||
|
||||
@ -661,7 +665,7 @@ TEST_F(PlatformViewTests, ViewEventsTest) {
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
fuchsia::ui::views::ViewRef{}, // view_ref
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
@ -728,58 +732,161 @@ TEST_F(PlatformViewTests, ViewEventsTest) {
|
||||
EXPECT_EQ(expected, call);
|
||||
}
|
||||
|
||||
// Test to make sure that PlatformView correctly returns a Surface instance
|
||||
// that can surface the provided gr_context and view_embedder.
|
||||
TEST_F(PlatformViewTests, CreateSurfaceTest) {
|
||||
// This test makes sure that the PlatformView forwards messages on the
|
||||
// "flutter/platform_views" channel for RequestFocus.
|
||||
TEST_F(PlatformViewTests, RequestFocusTest) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
MockPlatformViewDelegate delegate;
|
||||
zx::eventpair a, b;
|
||||
zx::eventpair::create(/* flags */ 0u, &a, &b);
|
||||
auto view_ref = fuchsia::ui::views::ViewRef({
|
||||
.reference = std::move(a),
|
||||
});
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", // label
|
||||
nullptr, // platform
|
||||
flutter_runner::CreateFMLTaskRunner(
|
||||
async_get_default_dispatcher()), // raster
|
||||
nullptr, // ui
|
||||
nullptr // io
|
||||
);
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
// Test create surface callback function.
|
||||
sk_sp<GrDirectContext> gr_context =
|
||||
GrDirectContext::MakeMock(nullptr, GrContextOptions());
|
||||
MockExternalViewEmbedder view_embedder;
|
||||
auto CreateSurfaceCallback = [&view_embedder, gr_context]() {
|
||||
return std::make_unique<flutter_runner::Surface>(
|
||||
"PlatformViewTest", &view_embedder, gr_context.get());
|
||||
};
|
||||
MockFocuser mock_focuser;
|
||||
fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
|
||||
auto focuser_handle = focuser_bindings.AddBinding(&mock_focuser);
|
||||
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
std::move(view_ref), // view_refs
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
nullptr, // session_listener_request
|
||||
nullptr, // focuser,
|
||||
nullptr, // on_session_listener_error_callback
|
||||
nullptr, // on_enable_wireframe_callback,
|
||||
nullptr, // on_create_view_callback,
|
||||
nullptr, // on_update_view_callback,
|
||||
nullptr, // on_destroy_view_callback,
|
||||
CreateSurfaceCallback, // on_create_surface_callback,
|
||||
fml::TimeDelta::Zero(), // vsync_offset
|
||||
ZX_HANDLE_INVALID // vsync_event_handle
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
nullptr, // session_listener_request
|
||||
std::move(focuser_handle), // focuser,
|
||||
nullptr, // on_session_listener_error_callback
|
||||
nullptr, // on_enable_wireframe_callback,
|
||||
nullptr, // on_create_view_callback,
|
||||
nullptr, // on_update_view_callback,
|
||||
nullptr, // on_destroy_view_callback,
|
||||
nullptr, // on_create_surface_callback,
|
||||
fml::TimeDelta::Zero(), // vsync_offset
|
||||
ZX_HANDLE_INVALID // vsync_event_handle
|
||||
);
|
||||
platform_view.NotifyCreated();
|
||||
|
||||
// Cast platform_view to its base view so we can have access to the public
|
||||
// "HandlePlatformMessage" function.
|
||||
auto base_view = dynamic_cast<flutter::PlatformView*>(&platform_view);
|
||||
EXPECT_TRUE(base_view);
|
||||
|
||||
// This "Mock" ViewRef serves as the target for the RequestFocus operation.
|
||||
auto mock_view_ref_pair = scenic::ViewRefPair::New();
|
||||
|
||||
// JSON for the message to be passed into the PlatformView.
|
||||
char buff[254];
|
||||
snprintf(buff, sizeof(buff),
|
||||
"{"
|
||||
" \"method\":\"View.requestFocus\","
|
||||
" \"args\": {"
|
||||
" \"viewRef\":%u"
|
||||
" }"
|
||||
"}",
|
||||
mock_view_ref_pair.view_ref.reference.get());
|
||||
|
||||
// Define a custom gmock matcher to capture the response to platform message.
|
||||
struct DataArg {
|
||||
void Complete(std::unique_ptr<fml::Mapping> data) {
|
||||
this->data = std::move(data);
|
||||
}
|
||||
std::unique_ptr<fml::Mapping> data;
|
||||
};
|
||||
DataArg data_arg;
|
||||
fml::RefPtr<MockResponse> response = fml::MakeRefCounted<MockResponse>();
|
||||
EXPECT_CALL(*response, Complete(::testing::_))
|
||||
.WillOnce(::testing::Invoke(&data_arg, &DataArg::Complete));
|
||||
|
||||
fml::RefPtr<flutter::PlatformMessage> message =
|
||||
fml::MakeRefCounted<flutter::PlatformMessage>(
|
||||
"flutter/platform_views",
|
||||
std::vector<uint8_t>(buff, buff + sizeof(buff)), response);
|
||||
base_view->HandlePlatformMessage(message);
|
||||
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_EQ(gr_context.get(), delegate.surface()->GetContext());
|
||||
EXPECT_EQ(&view_embedder, delegate.surface()->GetExternalViewEmbedder());
|
||||
EXPECT_TRUE(mock_focuser.request_focus_called());
|
||||
auto result = std::string((const char*)data_arg.data->GetMapping(),
|
||||
data_arg.data->GetSize());
|
||||
EXPECT_EQ(std::string("[0]"), result);
|
||||
}
|
||||
|
||||
} // namespace flutter_runner_test::flutter_runner_a11y_test
|
||||
// This test makes sure that the PlatformView correctly replies with an error
|
||||
// response when a RequestFocus call fails.
|
||||
TEST_F(PlatformViewTests, RequestFocusFailTest) {
|
||||
sys::testing::ServiceDirectoryProvider services_provider(dispatcher());
|
||||
MockPlatformViewDelegate delegate;
|
||||
flutter::TaskRunners task_runners =
|
||||
flutter::TaskRunners("test_runners", nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
MockFocuser mock_focuser(true /*fail_request_focus*/);
|
||||
fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
|
||||
auto focuser_handle = focuser_bindings.AddBinding(&mock_focuser);
|
||||
|
||||
auto platform_view = flutter_runner::PlatformView(
|
||||
delegate, // delegate
|
||||
"test_platform_view", // label
|
||||
fuchsia::ui::views::ViewRef(), // view_ref
|
||||
std::move(task_runners), // task_runners
|
||||
services_provider.service_directory(), // runner_services
|
||||
nullptr, // parent_environment_service_provider_handle
|
||||
nullptr, // session_listener_request
|
||||
std::move(focuser_handle), // focuser,
|
||||
nullptr, // on_session_listener_error_callback
|
||||
nullptr, // on_enable_wireframe_callback,
|
||||
nullptr, // on_create_view_callback,
|
||||
nullptr, // on_update_view_callback,
|
||||
nullptr, // on_destroy_view_callback,
|
||||
nullptr, // on_create_surface_callback,
|
||||
fml::TimeDelta::Zero(), // vsync_offset
|
||||
ZX_HANDLE_INVALID // vsync_event_handle
|
||||
);
|
||||
|
||||
// Cast platform_view to its base view so we can have access to the public
|
||||
// "HandlePlatformMessage" function.
|
||||
auto base_view = dynamic_cast<flutter::PlatformView*>(&platform_view);
|
||||
EXPECT_TRUE(base_view);
|
||||
|
||||
// This "Mock" ViewRef serves as the target for the RequestFocus operation.
|
||||
auto mock_view_ref_pair = scenic::ViewRefPair::New();
|
||||
|
||||
// JSON for the message to be passed into the PlatformView.
|
||||
char buff[254];
|
||||
snprintf(buff, sizeof(buff),
|
||||
"{"
|
||||
" \"method\":\"View.requestFocus\","
|
||||
" \"args\": {"
|
||||
" \"viewRef\":%u"
|
||||
" }"
|
||||
"}",
|
||||
mock_view_ref_pair.view_ref.reference.get());
|
||||
|
||||
// Define a custom gmock matcher to capture the response to platform message.
|
||||
struct DataArg {
|
||||
void Complete(std::unique_ptr<fml::Mapping> data) {
|
||||
this->data = std::move(data);
|
||||
}
|
||||
std::unique_ptr<fml::Mapping> data;
|
||||
};
|
||||
DataArg data_arg;
|
||||
fml::RefPtr<MockResponse> response = fml::MakeRefCounted<MockResponse>();
|
||||
EXPECT_CALL(*response, Complete(::testing::_))
|
||||
.WillOnce(::testing::Invoke(&data_arg, &DataArg::Complete));
|
||||
|
||||
fml::RefPtr<flutter::PlatformMessage> message =
|
||||
fml::MakeRefCounted<flutter::PlatformMessage>(
|
||||
"flutter/platform_views",
|
||||
std::vector<uint8_t>(buff, buff + sizeof(buff)), response);
|
||||
base_view->HandlePlatformMessage(message);
|
||||
|
||||
RunLoopUntilIdle();
|
||||
|
||||
EXPECT_TRUE(mock_focuser.request_focus_called());
|
||||
auto result = std::string((const char*)data_arg.data->GetMapping(),
|
||||
data_arg.data->GetSize());
|
||||
std::ostringstream out;
|
||||
out << "["
|
||||
<< static_cast<std::underlying_type_t<fuchsia::ui::views::Error>>(
|
||||
fuchsia::ui::views::Error::DENIED)
|
||||
<< "]";
|
||||
EXPECT_EQ(out.str(), result);
|
||||
}
|
||||
|
||||
} // namespace flutter_runner::testing
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user