| // Copyright 2020 The Fuchsia 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 SRC_UI_SCENIC_LIB_INPUT_INJECTOR_H_ |
| #define SRC_UI_SCENIC_LIB_INPUT_INJECTOR_H_ |
| |
| #include <fuchsia/ui/pointerinjector/cpp/fidl.h> |
| #include <lib/async/cpp/task.h> |
| #include <lib/fidl/cpp/binding.h> |
| |
| #include <unordered_map> |
| |
| #include "src/ui/scenic/lib/input/gesture_contender.h" |
| #include "src/ui/scenic/lib/input/helper.h" |
| #include "src/ui/scenic/lib/input/internal_pointer_event.h" |
| |
| namespace scenic_impl { |
| namespace input { |
| |
| // Non-FIDL-type struct for keeping client defined settings. |
| struct InjectorSettings { |
| fuchsia::ui::pointerinjector::DispatchPolicy dispatch_policy = |
| fuchsia::ui::pointerinjector::DispatchPolicy(0u); |
| uint32_t device_id = 0u; |
| fuchsia::ui::pointerinjector::DeviceType device_type = |
| fuchsia::ui::pointerinjector::DeviceType(0u); |
| zx_koid_t context_koid = ZX_KOID_INVALID; |
| zx_koid_t target_koid = ZX_KOID_INVALID; |
| }; |
| |
| // Utility that Injectors use to send diagnostics to Inspect. |
| class InjectorInspector { |
| public: |
| explicit InjectorInspector(inspect::Node inspect_node); |
| |
| void OnPointerInjectorEvent(const fuchsia::ui::pointerinjector::Event& event); |
| |
| private: |
| inspect::Node node_; |
| |
| inspect::ExponentialUintHistogram viewport_event_latency_; |
| inspect::ExponentialUintHistogram pointer_event_latency_; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(InjectorInspector); |
| }; |
| |
| // Implementation of the |fuchsia::ui::pointerinjector::Device| interface. One instance per channel. |
| class Injector : public fuchsia::ui::pointerinjector::Device { |
| public: |
| Injector(inspect::Node inspect_node, InjectorSettings settings, Viewport viewport, |
| fidl::InterfaceRequest<fuchsia::ui::pointerinjector::Device> device, |
| fit::function<bool(/*descendant*/ zx_koid_t, /*ancestor*/ zx_koid_t)> |
| is_descendant_and_connected, |
| fit::function<void(const InternalPointerEvent&, StreamId stream_id)> inject, |
| fit::function<void()> on_channel_closed); |
| |
| static bool IsValidConfig(const fuchsia::ui::pointerinjector::Config& config); |
| |
| // |fuchsia::ui::pointerinjector::Device| |
| void Inject(std::vector<fuchsia::ui::pointerinjector::Event> events, |
| InjectCallback callback) override; |
| |
| private: |
| // Return value is either both valid, {ZX_OK, valid stream id} or both |
| // invalid: {error, kInvalidStreamId} |
| std::pair<zx_status_t, StreamId> ValidatePointerSample( |
| const fuchsia::ui::pointerinjector::PointerSample& pointer_sample); |
| |
| // Tracks event streams. Returns the id of the event stream if the stream is valid |
| // and kInvalidStreamId otherwise. |
| // Event streams are expected to start with an ADD, followed by a number of CHANGE events, and |
| // ending in either a REMOVE or a CANCEL. Anything else is invalid. |
| StreamId ValidateEventStream(uint32_t pointer_id, fuchsia::ui::pointerinjector::EventPhase phase); |
| |
| // Injects a CANCEL event for each ongoing stream and stops tracking them. |
| void CancelOngoingStreams(); |
| |
| // Closes the fidl channel. This triggers the destruction of the Injector object through the |
| // error handler set in InputSystem. |
| // NOTE: No further method calls or member accesses should be made after CloseChannel(), since |
| // they might be made on a destroyed object. |
| void CloseChannel(zx_status_t epitaph); |
| |
| InjectorInspector inspector_; |
| |
| fidl::Binding<fuchsia::ui::pointerinjector::Device> binding_; |
| |
| // Client defined data. |
| const InjectorSettings settings_; |
| Viewport viewport_; |
| |
| // Tracks stream's status (per stream id) as it moves through its state machine. Used to |
| // validate each event's phase. |
| // - ADD: add stream to set |
| // - CHANGE: no-op |
| // - REMOVE/CANCEL: remove stream from set. |
| // Hence, each stream here matches ADD - CHANGE*. |
| std::unordered_map<uint32_t, StreamId> ongoing_streams_; |
| |
| fit::function<bool(/*descendant*/ zx_koid_t, /*ancestor*/ zx_koid_t)> |
| is_descendant_and_connected_; |
| |
| // Used to inject the event into InputSystem for dispatch to clients. |
| const fit::function<void(const InternalPointerEvent&, StreamId)> inject_; |
| |
| // Called both when an error is triggered by either the remote or the local side of the channel. |
| // Triggers destruction of this object. |
| const fit::function<void()> on_channel_closed_; |
| }; |
| |
| } // namespace input |
| } // namespace scenic_impl |
| |
| #endif // SRC_UI_SCENIC_LIB_INPUT_INJECTOR_H_ |