// 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.

#include "garnet/lib/ui/input/input_system.h"

#include <memory>

#include <fuchsia/math/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>

#include "garnet/lib/ui/gfx/engine/hit.h"
#include "garnet/lib/ui/gfx/engine/hit_tester.h"
#include "garnet/lib/ui/gfx/engine/session.h"
#include "garnet/lib/ui/gfx/resources/compositor/compositor.h"
#include "garnet/lib/ui/gfx/resources/compositor/layer_stack.h"
#include "garnet/lib/ui/gfx/resources/nodes/entity_node.h"
#include "garnet/lib/ui/gfx/resources/nodes/node.h"
#include "garnet/lib/ui/gfx/resources/view.h"
#include "garnet/lib/ui/gfx/resources/view_holder.h"
#include "garnet/lib/ui/gfx/util/unwrap.h"
#include "garnet/lib/ui/scenic/event_reporter.h"
#include "lib/component/cpp/startup_context.h"
#include "lib/escher/geometry/types.h"
#include "lib/escher/util/type_utils.h"
#include "lib/fidl/cpp/clone.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/time/time_point.h"
#include "lib/ui/geometry/cpp/formatting.h"
#include "lib/ui/input/cpp/formatting.h"

namespace scenic_impl {
namespace input {

using InputCommand = fuchsia::ui::input::Command;
using Phase = fuchsia::ui::input::PointerEventPhase;
using ScenicCommand = fuchsia::ui::scenic::Command;
using fuchsia::ui::input::FocusEvent;
using fuchsia::ui::input::ImeService;
using fuchsia::ui::input::ImeServicePtr;
using fuchsia::ui::input::InputEvent;
using fuchsia::ui::input::KeyboardEvent;
using fuchsia::ui::input::PointerEvent;
using fuchsia::ui::input::PointerEventType;
using fuchsia::ui::input::SendKeyboardInputCmd;
using fuchsia::ui::input::SendPointerInputCmd;
using fuchsia::ui::input::SetHardKeyboardDeliveryCmd;
using fuchsia::ui::input::SetParallelDispatchCmd;

namespace {
// Helper for Dispatch[Touch|Mouse]Command.
int64_t NowInNs() {
  return fxl::TimePoint::Now().ToEpochDelta().ToNanoseconds();
}

// Helper for Dispatch[Touch|Mouse]Command and PerformGlobalHitTest.
escher::ray4 CreateScreenPerpendicularRay(float x, float y) {
  // We set the elevation for the origin point, and Z value for the direction,
  // such that we start above the scene and point into the scene.
  //
  // Scenic flips around Vulkan's camera to the more intuitive "look
  // forward" orientation. The ray must now be stated in terms of the camera's
  // model space, so "taking a step back" translates to "negative Z origin".
  // Similarly, "look at the scene" translates to "positive Z direction".
  //
  // For hit testing, these values work in conjunction with
  // Camera::ProjectRayIntoScene to create an appropriate ray4 that works
  // correctly with the hit tester.
  //
  // During dispatch, we translate an arbitrary pointer's (x,y) device-space
  // coordinates to a View's (x', y') model-space coordinates.
  return {{x, y, -1.f, 1.f},  // Origin as homogeneous point.
          {0.f, 0.f, 1.f, 0.f}};
}

// Helper for Dispatch[Touch|Mouse]Command.
escher::vec2 TransformPointerEvent(const escher::ray4& ray,
                                   const escher::mat4& transform) {
  escher::ray4 local_ray = glm::inverse(transform) * ray;

  // We treat distance as 0 to simplify; otherwise the formula is:
  // hit = homogenize(local_ray.origin + distance * local_ray.direction);
  escher::vec2 hit(escher::homogenize(local_ray.origin));

  FXL_VLOG(2) << "Coordinate transform (device->view): (" << ray.origin.x
              << ", " << ray.origin.x << ")->(" << hit.x << ", " << hit.y
              << ")";
  return hit;
}

// Helper for Dispatch[Touch|Mouse]Command.
glm::mat4 FindGlobalTransform(gfx::ResourcePtr view) {
  glm::mat4 global_transform(1.f);  // Default is identity transform.
  if (!view) {
    return global_transform;
  }

  if (view->IsKindOf<gfx::View>()) {
    gfx::ViewPtr v2view = view->As<gfx::View>();
    if (v2view->view_holder() && v2view->view_holder()->parent()) {
      global_transform = v2view->view_holder()->parent()->GetGlobalTransform();
    }
  } else {
    // TODO(SCN-1006): After v2 transition, remove this clause.
    FXL_DCHECK(view->IsKindOf<gfx::Import>());
    if (gfx::ImportPtr import = view->As<gfx::Import>()) {
      if (gfx::Resource* delegate = import->delegate()) {
        FXL_DCHECK(delegate->IsKindOf<gfx::Node>());
        if (gfx::NodePtr node = delegate->As<gfx::Node>()) {
          global_transform = node->GetGlobalTransform();
        }
      }
    }
  }
  return global_transform;
}

// The x and y values are in device (screen) coordinates.
// The initial dispatch logic guarantees a valid compositor and layer stack.
// NOTE: The returned gfx::Hit struct contains a raw Node*, so callers:
//   - must not retain it, or extends its lifetime via Refptr,
//   - must not write into it,
//   - may call const functions against it.
std::vector<gfx::Hit> PerformGlobalHitTest(gfx::GfxSystem* gfx_system,
                                           uint32_t compositor_id, float x,
                                           float y) {
  FXL_DCHECK(gfx_system);

  escher::ray4 ray = CreateScreenPerpendicularRay(x, y);
  FXL_VLOG(1) << "HitTest: device point (" << ray.origin.x << ", "
              << ray.origin.y << ")";

  gfx::Compositor* compositor = gfx_system->GetCompositor(compositor_id);
  FXL_DCHECK(compositor) << "No compositor, violated invariant.";

  gfx::LayerStackPtr layer_stack = compositor->layer_stack();
  FXL_DCHECK(layer_stack.get()) << "No layer stack, violated invariant.";

  auto hit_tester = std::make_unique<gfx::GlobalHitTester>();
  std::vector<gfx::Hit> hits = layer_stack->HitTest(ray, hit_tester.get());

  FXL_VLOG(1) << "Hits acquired, count: " << hits.size();

  if (FXL_VLOG_IS_ON(2)) {
    for (size_t i = 0; i < hits.size(); ++i) {
      FXL_VLOG(2) << "\tHit[" << i << "]: " << hits[i].node->global_id();
    }
  }

  return hits;
}

// Helper for DispatchCommand.
PointerEvent ClonePointerWithCoords(const PointerEvent& event, float x,
                                    float y) {
  PointerEvent clone;
  fidl::Clone(event, &clone);
  clone.x = x;
  clone.y = y;
  return clone;
}

// Helper for DispatchTouchCommand.
// Ensure sessions get each event just once: stamp out duplicate
// sessions in the rest of the hits. This assumes:
// - there may be a ViewManager that interposes many Import nodes
// - each client has at most one "view" (whether View or Import)
// - each client receives at most one hit per view
// which reflects the pre-v2 migration scene graph.
// TODO(SCN-1006): Enable multiple Views per client.
// TODO(SCN-935): Return full set of hits to each client.
void RemoveHitsFromSameSession(SessionId session_id, size_t start_idx,
                               std::vector<gfx::ResourcePtr>* views) {
  FXL_DCHECK(views);
  for (size_t k = start_idx; k < views->size(); ++k) {
    if ((*views)[k] && ((*views)[k]->session()->id() == session_id)) {
      (*views)[k] = nullptr;
    }
  }
}

// Helper for Dispatch[Touch|Mouse]Command.
bool IsFocusChange(gfx::ResourcePtr view) {
  FXL_DCHECK(view);
  if (view->IsKindOf<gfx::View>()) {
    gfx::ViewPtr view_ptr = view->As<gfx::View>();
    if (view_ptr->connected()) {
      return view_ptr->view_holder()->view_properties().focus_change;
    }
  } else {
    // TODO(SCN-1026): Convert to query v2 view properties.
    // TODO(SCN-1006): After v2 transition, remove this clause.
    // We traverse up the scene graph to find the closest "ancestor" Import
    // starting from a given Import. We assume the scene graph is set up by
    // ViewManager in a very particular configuration for this traversal.
    FXL_DCHECK(view->IsKindOf<gfx::Import>());
    if (gfx::ImportPtr import = view->As<gfx::Import>()) {
      if (gfx::Resource* imported = import->imported_resource()) {
        if (imported->IsKindOf<gfx::EntityNode>()) {
          gfx::NodePtr attach_point = imported->As<gfx::EntityNode>();
          if (gfx::Node* delegate = attach_point->parent()) {
            if (gfx::Node* parent_node = delegate->parent()) {
              if (parent_node->imports().size() > 0) {
                return parent_node->imports()[0]->focusable();
              }
            }
          }
        }
      }
    }
  }
  return true;  // Implicitly, all Views can receive focus.
}
}  // namespace

InputSystem::InputSystem(SystemContext context, gfx::GfxSystem* gfx_system)
    : System(std::move(context), /*initialized_after_construction*/ false),
      gfx_system_(gfx_system) {
  FXL_CHECK(gfx_system_);
  gfx_system_->AddInitClosure([this]() {
    SetToInitialized();

    text_sync_service_ = this->context()
                             ->app_context()
                             ->ConnectToEnvironmentService<ImeService>();
    text_sync_service_.set_error_handler([](zx_status_t status) {
      FXL_LOG(ERROR) << "Scenic lost connection to TextSync";
    });

    FXL_LOG(INFO) << "Scenic input system initialized.";
  });
}

std::unique_ptr<CommandDispatcher> InputSystem::CreateCommandDispatcher(
    CommandDispatcherContext context) {
  return std::make_unique<InputCommandDispatcher>(std::move(context),
                                                  gfx_system_, this);
}

InputCommandDispatcher::InputCommandDispatcher(CommandDispatcherContext context,
                                               gfx::GfxSystem* gfx_system,
                                               InputSystem* input_system)
    : CommandDispatcher(std::move(context)),
      gfx_system_(gfx_system),
      input_system_(input_system) {
  FXL_CHECK(gfx_system_);
  FXL_CHECK(input_system_);
}

void InputCommandDispatcher::DispatchCommand(ScenicCommand command) {
  FXL_DCHECK(command.Which() == ScenicCommand::Tag::kInput);

  InputCommand& input = command.input();
  if (input.is_send_keyboard_input()) {
    DispatchCommand(std::move(input.send_keyboard_input()));
  } else if (input.is_send_pointer_input()) {
    // Compositor and layer stack required for dispatch.
    gfx::Compositor* compositor =
        gfx_system_->GetCompositor(input.send_pointer_input().compositor_id);
    if (!compositor)
      return;  // It's legal to race against GFX's compositor setup.

    gfx::LayerStackPtr layer_stack = compositor->layer_stack();
    if (!layer_stack)
      return;  // It's legal to race against GFX's layer stack setup.

    DispatchCommand(std::move(input.send_pointer_input()));
  } else if (input.is_set_hard_keyboard_delivery()) {
    DispatchCommand(std::move(input.set_hard_keyboard_delivery()));
  } else if (input.is_set_parallel_dispatch()) {
    DispatchCommand(std::move(input.set_parallel_dispatch()));
  }
}

void InputCommandDispatcher::DispatchCommand(
    const SendPointerInputCmd command) {
  const PointerEventType& event_type = command.pointer_event.type;
  if (event_type == PointerEventType::TOUCH) {
    DispatchTouchCommand(std::move(command));
  } else if (event_type == PointerEventType::MOUSE) {
    DispatchMouseCommand(std::move(command));
  } else {
    // TODO(SCN-940), TODO(SCN-164): Stylus support needs to account for HOVER
    // events, which need to trigger an additional hit test on the DOWN event
    // and send CANCEL events to disassociated clients.
    FXL_LOG(INFO) << "Add stylus support.";
  }
}

// The touch state machine comprises ADD/DOWN/MOVE*/UP/REMOVE. Some notes:
//  - We assume one touchscreen device, and use the device-assigned finger ID.
//  - Touch ADD associates the following ADD/DOWN/MOVE*/UP/REMOVE event sequence
//    with the set of clients available at that time. To enable gesture
//    disambiguation, we perform parallel dispatch to all clients.
//  - Touch DOWN triggers a focus change, but honors the no-focus property.
//  - Touch REMOVE drops the association between event stream and client.
void InputCommandDispatcher::DispatchTouchCommand(
    const SendPointerInputCmd command) {
  const uint32_t pointer_id = command.pointer_event.pointer_id;
  const Phase pointer_phase = command.pointer_event.phase;
  const float pointer_x = command.pointer_event.x;
  const float pointer_y = command.pointer_event.y;

  FXL_DCHECK(command.pointer_event.type == PointerEventType::TOUCH);
  FXL_DCHECK(pointer_phase != Phase::HOVER)
      << "Oops, touch device had unexpected HOVER event.";

  if (pointer_phase == Phase::ADD) {
    const std::vector<gfx::Hit> hits = PerformGlobalHitTest(
        gfx_system_, command.compositor_id, pointer_x, pointer_y);

    // Find input targets.  Honor the "input masking" view property.
    ViewStack hit_views;
    {
      // Find the View for each hit. Don't hold on to these RefPtrs!
      std::vector<gfx::ResourcePtr> views;
      views.reserve(hits.size());
      for (const gfx::Hit& hit : hits) {
        FXL_DCHECK(hit.node);  // Raw ptr, use it and let go.
        views.push_back(hit.node->FindOwningView());
      }
      FXL_DCHECK(hits.size() == views.size());

      // Find the global transform for each hit, fill out hit_views.
      for (size_t i = 0; i < hits.size(); ++i) {
        if (gfx::ResourcePtr view = views[i]) {
          hit_views.stack.push_back(
              {view->global_id(), FindGlobalTransform(view)});
          if (/*TODO(SCN-919): view_id may mask input */ false) {
            break;
          }
          // Don't do this. Refer to comment on RemoveHitsFromSameSession.
          RemoveHitsFromSameSession(view->session()->id(), i + 1, &views);
        }
      }

      // Determine focusability of top-level view.
      if (views.size() > 0 && views[0]) {
        hit_views.focus_change = IsFocusChange(views[0]);
      }
    }
    FXL_VLOG(1) << "View stack of hits: " << hit_views;

    // Save targets for consistent delivery of touch events.
    touch_targets_[pointer_id] = hit_views;

  } else if (pointer_phase == Phase::DOWN) {
    // New focus can be: (1) empty (if no views), or (2) the old focus (either
    // deliberately, or by the no-focus property), or (3) another view.
    GlobalId new_focus;
    if (!touch_targets_[pointer_id].stack.empty()) {
      if (touch_targets_[pointer_id].focus_change) {
        new_focus = touch_targets_[pointer_id].stack[0].view_id;
      } else {
        new_focus = focus_;  // No focus change.
      }
    }
    FXL_VLOG(1) << "Focus, old and new: " << focus_ << " vs " << new_focus;

    // Deliver focus events.
    if (focus_ != new_focus) {
      const int64_t focus_time = NowInNs();
      if (focus_) {
        FocusEvent event;
        event.event_time = focus_time;
        event.focused = false;
        EnqueueEventToView(focus_, event);
        FXL_VLOG(1) << "Input focus lost by " << focus_;
      }
      if (new_focus) {
        FocusEvent event;
        event.event_time = focus_time;
        event.focused = true;
        EnqueueEventToView(new_focus, event);
        FXL_VLOG(1) << "Input focus gained by " << new_focus;
      }
      focus_ = new_focus;
    }
  }

  // Input delivery must be parallel; needed for gesture disambiguation.
  for (const auto& entry : touch_targets_[pointer_id].stack) {
    escher::ray4 screen_ray =
        CreateScreenPerpendicularRay(pointer_x, pointer_y);
    escher::vec2 hit =
        TransformPointerEvent(screen_ray, entry.global_transform);

    auto clone = ClonePointerWithCoords(command.pointer_event, hit.x, hit.y);
    EnqueueEventToView(entry.view_id, std::move(clone));

    if (!parallel_dispatch_) {
      break;  // TODO(SCN-1047): Remove when gesture disambiguation is ready.
    }
  }

  if (pointer_phase == Phase::REMOVE || pointer_phase == Phase::CANCEL) {
    touch_targets_.erase(pointer_id);
  }
}

// The mouse state machine is simpler, comprising MOVE*-DOWN/MOVE*/UP-MOVE*. Its
// behavior is similar to touch events, but with some differences.
//  - There can be multiple mouse devices, so we track each device individually.
//  - Mouse DOWN associates the following DOWN/MOVE*/UP event sequence with one
//    particular client: the top-hit View. Mouse events aren't associated with
//    gestures, so there is no parallel dispatch.
//  - Mouse DOWN triggers a focus change, but honors the no-focus property.
//  - Mouse UP drops the association between event stream and client.
//  - For an unassociated MOVE event, we perform a hit test, and send the top-most
//    client this MOVE event. Focus does not change for unassociated MOVEs.
//  - The hit test must account for the mouse cursor itself, which today is
//    owned by the root presenter. The nodes associated with visible mouse
//    cursors(!) do not roll up to any View (as expected), but may appear in the
//    hit test; our dispatch needs to account for such behavior.
// TODO(SCN-1078): Enhance trackpad support.
void InputCommandDispatcher::DispatchMouseCommand(
    const SendPointerInputCmd command) {
  const uint32_t device_id = command.pointer_event.device_id;
  const Phase pointer_phase = command.pointer_event.phase;
  const float pointer_x = command.pointer_event.x;
  const float pointer_y = command.pointer_event.y;

  FXL_DCHECK(command.pointer_event.type == PointerEventType::MOUSE);
  FXL_DCHECK(pointer_phase != Phase::ADD && pointer_phase != Phase::REMOVE &&
             pointer_phase != Phase::HOVER)
      << "Oops, mouse device (id=" << device_id
      << ") had an unexpected event: " << pointer_phase;

  if (pointer_phase == Phase::DOWN) {
    const std::vector<gfx::Hit> hits = PerformGlobalHitTest(
        gfx_system_, command.compositor_id, pointer_x, pointer_y);

    // Find top-hit target and associated properties.
    // NOTE: We may hit various mouse cursors (owned by root presenter), so keep
    // going until we find a hit with a valid owning View.
    ViewStack hit_view;
    for (gfx::Hit hit : hits) {
      FXL_DCHECK(hit.node);  // Raw ptr, use it and let go.
      if (gfx::ResourcePtr view = hit.node->FindOwningView()) {
        hit_view.stack.push_back(
            {view->global_id(), FindGlobalTransform(view)});
        hit_view.focus_change = IsFocusChange(view);
        break;  // Just need the first one.
      }
    }
    FXL_VLOG(1) << "View hit: " << hit_view;

    // New focus can be: (1) empty (if no views), or (2) the old focus (either
    // deliberately, or by the no-focus property), or (3) another view.
    GlobalId new_focus;
    if (!hit_view.stack.empty()) {
      if (hit_view.focus_change) {
        new_focus = hit_view.stack[0].view_id;
      } else {
        new_focus = focus_;  // No focus change.
      }
    }
    FXL_VLOG(1) << "Focus, old and new: " << focus_ << " vs " << new_focus;

    // Deliver focus events.
    if (focus_ != new_focus) {
      const int64_t focus_time = NowInNs();
      if (focus_) {
        FocusEvent event;
        event.event_time = focus_time;
        event.focused = false;
        EnqueueEventToView(focus_, event);
        FXL_VLOG(1) << "Input focus lost by " << focus_;
      }
      if (new_focus) {
        FocusEvent event;
        event.event_time = focus_time;
        event.focused = true;
        EnqueueEventToView(new_focus, event);
        FXL_VLOG(1) << "Input focus gained by " << new_focus;
      }
      focus_ = new_focus;
    }

    // Save target for consistent delivery of mouse events.
    mouse_targets_[device_id] = hit_view;
  }

  if (mouse_targets_.count(device_id) > 0 &&  // Tracking this device, and
      mouse_targets_[device_id].stack.size() > 0) {  // target view exists.
    const auto& entry = mouse_targets_[device_id].stack[0];

    escher::ray4 screen_ray =
        CreateScreenPerpendicularRay(pointer_x, pointer_y);
    escher::vec2 hit =
        TransformPointerEvent(screen_ray, entry.global_transform);

    auto clone = ClonePointerWithCoords(command.pointer_event, hit.x, hit.y);
    EnqueueEventToView(entry.view_id, std::move(clone));
  }

  if (pointer_phase == Phase::UP || pointer_phase == Phase::CANCEL) {
    mouse_targets_.erase(device_id);
  }

  // Deal with unassociated MOVE events.
  if (pointer_phase == Phase::MOVE && mouse_targets_.count(device_id) == 0) {
    const std::vector<gfx::Hit> hits = PerformGlobalHitTest(
        gfx_system_, command.compositor_id, pointer_x, pointer_y);
    // Find top-hit target and send it this move event.
    // NOTE: We may hit various mouse cursors (owned by root presenter), so keep
    // going until we find a hit with a valid owning View.
    GlobalId view_id;
    for (gfx::Hit hit : hits) {
      FXL_DCHECK(hit.node);  // Raw ptr, use it and let go.
      if (gfx::ResourcePtr view = hit.node->FindOwningView()) {
        view_id = view->global_id();

        escher::ray4 screen_ray =
            CreateScreenPerpendicularRay(pointer_x, pointer_y);
        glm::mat4 global_transform = FindGlobalTransform(view);
        escher::vec2 hit = TransformPointerEvent(screen_ray, global_transform);

        auto clone =
            ClonePointerWithCoords(command.pointer_event, hit.x, hit.y);
        EnqueueEventToView(view_id, std::move(clone));
        break;  // Just need the first one.
      }
    }

    FXL_VLOG(2) << "View hit: " << view_id;
  }
}

void InputCommandDispatcher::DispatchCommand(
    const SendKeyboardInputCmd command) {
  // Send keyboard events to the active focus via Text Sync.
  EnqueueEventToTextSync(focus_, command.keyboard_event);

  // Clients may request direct delivery.
  if (focus_.session_id > 0 &&
      input_system_->hard_keyboard_requested().count(focus_.session_id) > 0) {
    EnqueueEventToView(focus_, command.keyboard_event);
  }
}

void InputCommandDispatcher::DispatchCommand(
    const SetHardKeyboardDeliveryCmd command) {
  const SessionId session_id = context()->session_id();
  FXL_VLOG(2) << "Hard keyboard events, session_id=" << session_id
              << ", delivery_request="
              << (command.delivery_request ? "on" : "off");

  if (command.delivery_request) {
    // Take this opportunity to remove dead sessions.
    for (SessionId id : input_system_->hard_keyboard_requested()) {
      if (gfx_system_->GetSession(id) == nullptr) {
        input_system_->hard_keyboard_requested().erase(id);
      }
    }

    input_system_->hard_keyboard_requested().insert(session_id);
  } else {
    input_system_->hard_keyboard_requested().erase(session_id);
  }
}

void InputCommandDispatcher::DispatchCommand(
    const SetParallelDispatchCmd command) {
  FXL_LOG(INFO) << "Scenic: Parallel dispatch is turned "
                << (command.parallel_dispatch ? "ON" : "OFF");
  parallel_dispatch_ = command.parallel_dispatch;
}

void InputCommandDispatcher::EnqueueEventToView(GlobalId view_id,
                                                FocusEvent focus) {
  if (gfx::Session* session = gfx_system_->GetSession(view_id.session_id)) {
    InputEvent event;
    event.set_focus(std::move(focus));

    session->EnqueueEvent(std::move(event));
  }
}

void InputCommandDispatcher::EnqueueEventToView(GlobalId view_id,
                                                PointerEvent pointer) {
  if (gfx::Session* session = gfx_system_->GetSession(view_id.session_id)) {
    InputEvent event;
    event.set_pointer(std::move(pointer));

    session->EnqueueEvent(std::move(event));
  }
}

void InputCommandDispatcher::EnqueueEventToView(GlobalId view_id,
                                                KeyboardEvent keyboard) {
  if (gfx::Session* session = gfx_system_->GetSession(view_id.session_id)) {
    InputEvent event;
    event.set_keyboard(std::move(keyboard));

    session->EnqueueEvent(std::move(event));
  }
}

void InputCommandDispatcher::EnqueueEventToTextSync(GlobalId view_id,
                                                    KeyboardEvent keyboard) {
  ImeServicePtr& text_sync = input_system_->text_sync_service();
  if (text_sync && text_sync.is_bound()) {
    InputEvent event;
    event.set_keyboard(std::move(keyboard));

    text_sync->InjectInput(std::move(event));
  }
}

}  // namespace input
}  // namespace scenic_impl
