13using fup_Data = fuchsia::ui::pointerinjector::Data;
16using fup_Event = fuchsia::ui::pointerinjector::Event;
27 static constexpr std::array<float, 9> kIdentityMatrix = {
37 const rapidjson::Document& request,
39 if (!registry_->is_bound()) {
41 <<
"Lost connection to fuchsia.ui.pointerinjector.Registry";
45 auto method = request.FindMember(
"method");
46 if (method == request.MemberEnd() || !method->value.IsString()) {
47 FML_LOG(ERROR) <<
"No method found in platform message.";
52 FML_LOG(ERROR) <<
"Unexpected platform message method, expected "
53 "View.pointerinjector.inject.";
57 auto args_it = request.FindMember(
"args");
58 if (args_it == request.MemberEnd() || !args_it->value.IsObject()) {
59 FML_LOG(ERROR) <<
"No arguments found in platform message's method";
63 const auto&
args = args_it->value;
66 if (!
view_id->value.IsUint64()) {
67 FML_LOG(ERROR) <<
"Argument 'viewId' is not a uint64";
71 auto id =
view_id->value.GetUint64();
72 if (valid_views_.count(
id) == 0) {
77 Complete(std::move(response),
"[0]");
81 auto phase =
args.FindMember(
"phase");
82 if (!phase->value.IsInt()) {
83 FML_LOG(ERROR) <<
"Argument 'phase' is not a int";
87 auto pointer_x =
args.FindMember(
"x");
88 if (!pointer_x->value.IsFloat() && !pointer_x->value.IsInt()) {
89 FML_LOG(ERROR) <<
"Argument 'Pointer.X' is not a float";
93 auto pointer_y =
args.FindMember(
"y");
94 if (!pointer_y->value.IsFloat() && !pointer_y->value.IsInt()) {
95 FML_LOG(ERROR) <<
"Argument 'Pointer.Y' is not a float";
99 auto pointer_id =
args.FindMember(
"pointerId");
100 if (!pointer_id->value.IsUint()) {
101 FML_LOG(ERROR) <<
"Argument 'pointerId' is not a uint32";
105 auto trace_flow_id =
args.FindMember(
"traceFlowId");
106 if (!trace_flow_id->value.IsInt()) {
107 FML_LOG(ERROR) <<
"Argument 'traceFlowId' is not a int";
111 auto width =
args.FindMember(
"logicalWidth");
112 if (!
width->value.IsFloat() && !
width->value.IsInt()) {
113 FML_LOG(ERROR) <<
"Argument 'logicalWidth' is not a float";
117 auto height =
args.FindMember(
"logicalHeight");
118 if (!
height->value.IsFloat() && !
height->value.IsInt()) {
119 FML_LOG(ERROR) <<
"Argument 'logicalHeight' is not a float";
123 auto timestamp =
args.FindMember(
"timestamp");
124 if (!timestamp->value.IsInt() && !timestamp->value.IsUint64()) {
125 FML_LOG(ERROR) <<
"Argument 'timestamp' is not a int";
129 PointerInjectorRequest
event = {
130 .x = pointer_x->value.GetFloat(),
131 .y = pointer_y->value.GetFloat(),
132 .pointer_id = pointer_id->value.GetUint(),
134 .trace_flow_id = trace_flow_id->value.GetUint64(),
135 .logical_size = {
width->value.GetFloat(),
height->value.GetFloat()},
136 .timestamp = timestamp->value.GetInt()};
139 valid_views_.at(
id).InjectEvent(std::move(event));
140 Complete(std::move(response),
"[0]");
146 std::optional<fuv_ViewRef> view_ref) {
149 auto [_, success] = valid_views_.try_emplace(
150 view_id, registry_, host_view_ref_, std::move(view_ref));
155fup_Event PointerInjectorDelegate::ExtractPointerEvent(
156 PointerInjectorRequest request) {
158 event.set_timestamp(request.timestamp);
159 event.set_trace_flow_id(request.trace_flow_id);
162 pointer_sample.set_pointer_id(request.pointer_id);
163 pointer_sample.set_phase(request.phase);
164 pointer_sample.set_position_in_viewport({request.x, request.y});
167 data.set_pointer_sample(std::move(pointer_sample));
169 event.set_data(std::move(data));
173void PointerInjectorDelegate::Complete(
177 response->Complete(std::make_unique<fml::DataMapping>(
178 std::vector<uint8_t>(
value.begin(),
value.end())));
182void PointerInjectorDelegate::PointerInjectorEndpoint::InjectEvent(
183 PointerInjectorRequest request) {
185 RegisterInjector(request);
188 auto event = ExtractPointerEvent(std::move(request));
191 EnqueueEvent(std::move(event));
193 DispatchPendingEvents();
196void PointerInjectorDelegate::PointerInjectorEndpoint::DispatchPendingEvents() {
200 if (injection_in_flight_) {
210 if (!injector_events_.empty()) {
211 auto events = std::move(injector_events_.front());
212 injector_events_.pop();
213 injection_in_flight_ =
true;
218 device_->Inject(std::move(events), [weak = weak_factory_.GetWeakPtr()] {
220 FML_LOG(WARNING) <<
"Use after free attempted.";
223 weak->injection_in_flight_ =
false;
224 weak->DispatchPendingEvents();
229void PointerInjectorDelegate::PointerInjectorEndpoint::EnqueueEvent(
233 if (!injector_events_.empty() &&
234 injector_events_.back().size() < fup_MAX_INJECT) {
235 injector_events_.back().push_back(std::move(event));
237 std::vector<fup_Event> vec;
238 vec.reserve(fup_MAX_INJECT);
239 vec.push_back(std::move(event));
240 injector_events_.push(std::move(vec));
244void PointerInjectorDelegate::PointerInjectorEndpoint::RegisterInjector(
245 const PointerInjectorRequest& request) {
251 config.set_device_id(1);
252 config.set_device_type(fup_DeviceType::TOUCH);
253 config.set_dispatch_policy(fup_DispatchPolicy::EXCLUSIVE_TARGET);
257 fidl::Clone(*host_view_ref_, &context_clone);
258 context.set_view(std::move(context_clone));
259 config.set_context(std::move(context));
265 fidl::Clone(*view_ref_, &target_clone);
266 target.set_view(std::move(target_clone));
267 config.set_target(std::move(
target));
270 viewport.set_viewport_to_context_transform(kIdentityMatrix);
271 std::array<std::array<float, 2>, 2> extents{
273 {request.logical_size[0], request.logical_size[1]}}};
274 viewport.set_extents(std::move(extents));
275 config.set_viewport(std::move(viewport));
279 (*registry_)->Register(std::move(config), device_.NewRequest(), [] {});
284void PointerInjectorDelegate::PointerInjectorEndpoint::Reset() {
285 injection_in_flight_ =
false;
287 injector_events_ = {};
static constexpr auto kPointerInjectorMethodPrefix
bool HandlePlatformMessage(const rapidjson::Document &request, fml::RefPtr< flutter::PlatformMessageResponse > response)
void OnCreateView(uint64_t view_id, std::optional< fuchsia::ui::views::ViewRef > view_ref=std::nullopt)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS FlutterViewId view_id
#define FML_LOG(severity)
#define FML_CHECK(condition)
fuchsia::ui::pointerinjector::Event fup_Event
const auto fup_MAX_INJECT
fuchsia::ui::pointerinjector::Target fup_Target
fuchsia::ui::views::ViewRef fuv_ViewRef
fuchsia::ui::pointerinjector::DeviceType fup_DeviceType
fuchsia::ui::pointerinjector::Context fup_Context
fuchsia::ui::pointerinjector::DispatchPolicy fup_DispatchPolicy
fuchsia::ui::pointerinjector::Viewport fup_Viewport
fuchsia::ui::pointerinjector::Config fup_Config
fuchsia::ui::pointerinjector::PointerSample fup_PointerSample
fuchsia::ui::pointerinjector::Data fup_Data
fuchsia::ui::pointer::EventPhase fup_EventPhase