blob: 6e9651057771a47fb102ad47088b5e030def2325 [file] [log] [blame]
// Copyright 2018 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_POINTER_EVENT_BUFFER_H_
#define SRC_UI_SCENIC_LIB_INPUT_POINTER_EVENT_BUFFER_H_
#include <fuchsia/ui/input/accessibility/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <deque>
#include <unordered_map>
#include <vector>
#include "src/ui/scenic/lib/input/view_stack.h"
namespace scenic_impl {
namespace input {
// A buffer to store pointer events.
//
// This buffer is used when an accessibility listener is intercepting pointer events.
// It sends each event to the accessibility listener, buffering streams of them until
// accessibility decides to either reject or consume a stream.
// If rejected, the events of the stream (past and future) are sent directly to the views that would
// normally receive them. If consumed, all events for the stream are sent only to accessibility.
class PointerEventBuffer {
public:
// Captures the deferred parallel dispatch of a pointer event.
struct DeferredPointerEvent {
fuchsia::ui::input::PointerEvent event;
// Position 0 of the vector holds the top-most view. The vector may be empty.
std::vector<ViewStack::Entry> parallel_event_receivers;
};
// Represents a stream of pointer events. A stream is a sequence of pointer events with phase
// ADD -> * -> REMOVE.
struct PointerIdStream {
// The temporally-ordered pointer events of this stream. Each element of this vector (indexed
// by time) contains another vector (indexed by view); one touch event may be dispatched
// multiple times, to multiple views, in parallel (simultaneously).
std::vector<DeferredPointerEvent> serial_events;
};
// Possible states of a stream.
enum PointerIdStreamStatus {
WAITING_RESPONSE = 0, // accessibility listener hasn't responded yet.
CONSUMED = 1,
REJECTED = 2,
};
using ReportAccessibilityEventFunction =
std::function<void(fuchsia::ui::input::accessibility::PointerEvent)>;
using DispatchEventFunction = fit::function<void(PointerEventBuffer::DeferredPointerEvent)>;
PointerEventBuffer(DispatchEventFunction dispatch_events,
ReportAccessibilityEventFunction report_to_accessibility);
~PointerEventBuffer();
// Adds a parallel dispatch event list |views_and_event| to the latest
// stream associated with |pointer_id|. It also takes
// |accessibility_pointer_event|, which is sent to the listener depending on
// the current stream status.
void AddEvent(uint32_t pointer_id, DeferredPointerEvent views_and_event,
fuchsia::ui::input::accessibility::PointerEvent accessibility_pointer_event);
// Adds a new stream associated with |pointer_id|.
void AddStream(uint32_t pointer_id);
// Updates the oldest stream associated with |pointer_id|, triggering an
// appropriate action depending on |handled|.
// If |handled| == CONSUMED, continues sending events to the listener.
// If |handled| == REJECTED, dispatches buffered pointer events to views.
void UpdateStream(uint32_t pointer_id, fuchsia::ui::input::accessibility::EventHandling handled);
// Sets the status of view of the active stream for a pointer ID.
void SetActiveStreamInfo(uint32_t pointer_id, PointerIdStreamStatus status) {
active_stream_info_[pointer_id] = {status};
}
private:
// NOTE: We assume there is one touch screen, and hence unique pointer IDs.
// key = pointer ID, value = a list of pointer streams. Every new stream is
// added to the end of the list, where a consume / reject response from the
// listener always removes the first element.
std::unordered_map<uint32_t, std::deque<PointerIdStream>> buffer_;
// Key = pointer ID, value = the status of the current active stream.
//
// This is kept separate from the map above because this must outlive
// the stream itself. When the accessibility listener responds, the first
// non-processed stream is consumed / rejected and gets removed from the
// buffer. It may not be finished (we haven't seen a pointer event with
// phase == REMOVE), so it is necessary to still keep track of where the
// incoming pointer events should go, although they don't need to be
// buffered anymore.
//
// Whenever a pointer ID is added, its default value is WAITING_RESPONSE.
std::unordered_map</*pointer ID*/ uint32_t, PointerIdStreamStatus> active_stream_info_;
DispatchEventFunction dispatch_events_;
ReportAccessibilityEventFunction report_to_accessibility_;
};
} // namespace input
} // namespace scenic_impl
#endif // SRC_UI_SCENIC_LIB_INPUT_POINTER_EVENT_BUFFER_H_