blob: 336bf75bc7a7d19dd2021de958ebbc0aaeb656ef [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_INPUT_COMMAND_DISPATCHER_H_
#define SRC_UI_SCENIC_LIB_INPUT_INPUT_COMMAND_DISPATCHER_H_
#include <fuchsia/ui/input/accessibility/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/policy/accessibility/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <functional>
#include <memory>
#include <unordered_map>
#include "src/ui/scenic/lib/gfx/gfx_system.h"
#include "src/ui/scenic/lib/input/pointer_event_buffer.h"
namespace scenic_impl {
namespace input {
class InputSystem;
// Per-session treatment of input commands.
// Routes input events from a root presenter to Scenic clients.
// Manages input-related state, such as focus.
//
// The general flow of events is:
// If accessibility is off:
// DispatchCommand --[decide what/where]--> EnqueueEvent
// If accessibility is on:
// DispatchCommand --> accessibility --[does accessibility want to block it? then stop]--[otherwise
// decide where else to send]--> EnqueueEvent
class InputCommandDispatcher : public CommandDispatcher {
public:
InputCommandDispatcher(scheduling::SessionId session_id,
std::shared_ptr<EventReporter> event_reporter, gfx::Engine* engine,
InputSystem* input_system);
~InputCommandDispatcher() override = default;
// |CommandDispatcher|
void SetDebugName(const std::string& debug_name) override {}
// |CommandDispatcher|
void DispatchCommand(const fuchsia::ui::scenic::Command command) override;
private:
// Per-command dispatch logic.
void DispatchCommand(const fuchsia::ui::input::SendPointerInputCmd& command);
void DispatchCommand(const fuchsia::ui::input::SendKeyboardInputCmd& command);
void DispatchCommand(const fuchsia::ui::input::SetHardKeyboardDeliveryCmd& command);
void DispatchCommand(const fuchsia::ui::input::SetParallelDispatchCmd& command);
// Per-pointer-type dispatch logic.
void DispatchTouchCommand(const fuchsia::ui::input::SendPointerInputCmd& command);
void DispatchMouseCommand(const fuchsia::ui::input::SendPointerInputCmd& command);
// Dispatches an event to a parallel set of views; set may be empty.
// Conditionally trigger focus change request, based on |views_and_event.event.phase|.
// Called by PointerEventBuffer.
void DispatchDeferredPointerEvent(PointerEventBuffer::DeferredPointerEvent views_and_event);
// Enqueue the pointer event into the entry in a ViewStack.
static void ReportPointerEvent(const ViewStack::Entry& view_info,
const fuchsia::ui::input::PointerEvent& pointer);
// Enqueue the keyboard event into an EventReporter.
static void ReportKeyboardEvent(EventReporter* reporter,
fuchsia::ui::input::KeyboardEvent keyboard);
// Enqueue the keyboard event to the IME Service.
static void ReportToImeService(const fuchsia::ui::input::ImeServicePtr& ime_service,
fuchsia::ui::input::KeyboardEvent keyboard);
// Retrieve focused ViewRef's KOID from the scene graph.
// Return ZX_KOID_INVALID if scene does not exist, or if the focus chain is empty.
zx_koid_t focus() const;
// Retrieve KOID of focus chain's root view.
// Return ZX_KOID_INVALID if scene does not exist, or if the focus chain is empty.
zx_koid_t focus_chain_root() const;
// Request a focus change in the SceneGraph's ViewTree.
//
// The request is performed with the authority of the focus chain's root view (typically the
// Scene). However, a request may be denied if the requested view may not receive focus (a
// property set by the view holder).
void RequestFocusChange(zx_koid_t view_ref_koid);
// Checks if an accessibility listener is intercepting pointer events. If the
// listener is on, initializes the buffer if it hasn't been created.
// Important:
// When the buffer is initialized, it can be the case that there are active
// pointer event streams that haven't finished yet. They are sent to clients,
// and *not* to the a11y listener. When the stream is done and a new stream
// arrives, these will be sent to the a11y listener who will just continue its
// normal flow. In a disconnection, if there are active pointer event streams,
// its assume that the listener rejected them so they are sent to clients.
bool ShouldForwardAccessibilityPointerEvents();
// FIELDS
const scheduling::SessionId session_id_;
std::shared_ptr<EventReporter> event_reporter_;
gfx::Engine* const engine_ = nullptr;
InputSystem* const input_system_ = nullptr;
// Tracks the set of Views each touch event is delivered to; basically, a map from pointer ID to a
// stack of ViewRef KOIDs. This is used to ensure consistent delivery of pointer events for a
// given finger to its original destination targets on their respective DOWN event. In
// particular, a focus change triggered by a new finger should *not* affect delivery of events to
// existing fingers.
//
// NOTE: We assume there is one touch screen, and hence unique pointer IDs.
std::unordered_map<uint32_t, ViewStack> touch_targets_;
// Tracks the View each mouse pointer is delivered to; a map from device ID to a ViewRef KOID.
// This is used to ensure consistent delivery of mouse events for a given device. A focus change
// triggered by other pointer events should *not* affect delivery of events to existing mice.
//
// NOTE: We reuse the ViewStack here just for convenience.
std::unordered_map<uint32_t, ViewStack> mouse_targets_;
// TODO(SCN-1047): Remove when gesture disambiguation is the default.
bool parallel_dispatch_ = true;
// When accessibility pointer event forwarding is enabled, this buffer stores
// pointer events until an accessibility listener decides how to handle them.
// It is always null otherwise.
std::unique_ptr<PointerEventBuffer> pointer_event_buffer_;
};
} // namespace input
} // namespace scenic_impl
#endif // SRC_UI_SCENIC_LIB_INPUT_INPUT_COMMAND_DISPATCHER_H_