blob: 9a2723ef2bfbd145361d3588cdb6e6e06ddb6511 [file] [log] [blame]
// Copyright 2021 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_TOUCH_SOURCE_H_
#define SRC_UI_SCENIC_LIB_INPUT_TOUCH_SOURCE_H_
#include <fuchsia/ui/pointer/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fit/function.h>
#include <queue>
#include <unordered_map>
#include "src/ui/scenic/lib/input/gesture_contender.h"
namespace scenic_impl::input {
// Implementation of the |fuchsia::ui::pointer::TouchSource| interface. One instance per
// channel.
class TouchSource : public GestureContender, public fuchsia::ui::pointer::TouchSource {
public:
// |respond_| must not destroy the TouchSource object.
TouchSource(fidl::InterfaceRequest<fuchsia::ui::pointer::TouchSource> event_provider,
fit::function<void(StreamId, const std::vector<GestureResponse>&)> respond,
fit::function<void()> error_handler);
~TouchSource() override;
// |GestureContender|
void UpdateStream(StreamId stream_id, const InternalPointerEvent& event,
bool is_end_of_stream) override;
// |GestureContender|
void EndContest(StreamId stream_id, bool awarded_win) override;
// |fuchsia::ui::pointer::TouchSource|
void Watch(std::vector<fuchsia::ui::pointer::TouchResponse> responses,
WatchCallback callback) override;
// |fuchsia::ui::pointer::TouchSource|
void UpdateResponse(fuchsia::ui::pointer::TouchInteractionId stream,
fuchsia::ui::pointer::TouchResponse response,
UpdateResponseCallback callback) override;
// TODO(fxbug.dev/64379): Implement ANR.
private:
struct StreamData {
uint32_t device_id = 0;
uint32_t pointer_id = 0;
bool stream_has_ended = false;
bool was_won = false;
GestureResponse last_response = GestureResponse::kUndefined;
// TODO(fxbug.dev/53316): Remove when we no longer need to filter events. Keeps indexes into
// duplicate events for legacy injectors.
uint64_t num_pointer_events = 0;
uint64_t num_responses = 0;
std::queue<uint64_t> filtered_events;
};
// Used to track expected responses from the client for each sent event.
struct ReturnTicket {
StreamId stream_id = kInvalidStreamId;
bool expects_response = false;
};
// Used to track events awaiting Watch() calls.
struct PendingEvent {
StreamId stream_id = kInvalidStreamId;
fuchsia::ui::pointer::TouchEvent event;
};
void SendPendingIfWaiting();
// Checks that the input is valid for the current state. If not valid it returns the error string
// to print and the epitaph to send on the channel when closing.
static zx_status_t ValidateResponses(
const std::vector<fuchsia::ui::pointer::TouchResponse>& responses,
const std::vector<ReturnTicket>& last_messages, bool have_pending_callback);
static zx_status_t ValidateUpdateResponse(
const fuchsia::ui::pointer::TouchInteractionId& stream_identifier,
const fuchsia::ui::pointer::TouchResponse& response,
const std::unordered_map<StreamId, StreamData>& ongoing_streams);
// Closes the fidl channel. This triggers the destruction of the TouchSource 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);
bool is_first_event_ = true;
Viewport current_viewport_;
// Events waiting to be sent to client. Sent in batches of up to
// fuchsia::ui::pointer::TOUCH_MAX_EVENT events on each call to Watch().
std::queue<PendingEvent> pending_events_;
// When a vector of events is sent out in response to a Watch() call, the next Watch() call must
// contain responses matching the previous set of events. |return_tickets_| tracks the expected
// responses for the previous set of events.
std::vector<ReturnTicket> return_tickets_;
fidl::Binding<fuchsia::ui::pointer::TouchSource> binding_;
const fit::function<void(StreamId, const std::vector<GestureResponse>&)> respond_;
const fit::function<void()> error_handler_;
std::unordered_map<StreamId, StreamData> ongoing_streams_;
WatchCallback pending_callback_ = nullptr;
};
} // namespace scenic_impl::input
#endif // SRC_UI_SCENIC_LIB_INPUT_TOUCH_SOURCE_H_