blob: a0ff07c4a65e21597e8af94f1f61f0b2130ea26b [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.
#include <fuchsia/ui/input/cpp/fidl.h>
#include <lib/zx/eventpair.h>
#include <memory>
#include <string>
#include "garnet/lib/ui/gfx/displays/display.h"
#include "garnet/lib/ui/gfx/id.h"
#include "garnet/lib/ui/gfx/tests/mocks.h"
#include "garnet/lib/ui/input/input_system.h"
#include "garnet/lib/ui/scenic/scenic.h"
#include "src/ui/lib/escher/impl/command_buffer_sequencer.h"
#include "lib/ui/gfx/tests/gfx_test.h"
#include "lib/ui/scenic/cpp/resources.h"
#include "lib/ui/scenic/cpp/session.h"
namespace lib_ui_input_tests {
// Convenience function to reduce clutter.
void CreateTokenPair(zx::eventpair* t1, zx::eventpair* t2);
// Device-independent "display"; for testing only. Needed to ensure GfxSystem
// doesn't wait for a device-driven "display ready" signal.
class TestDisplay : public scenic_impl::gfx::Display {
TestDisplay(uint64_t id, uint32_t width_px, uint32_t height_px)
: Display(id, width_px, height_px) {}
~TestDisplay() = default;
bool is_test_display() const override { return true; }
// Test fixture for exercising the input subsystem.
class InputSystemTest : public scenic_impl::test::ScenicTest {
// For creation of a client-side session.
scenic_impl::Scenic* scenic() { return scenic_.get(); }
// Convenience function; triggers scene operations by scheduling the next
// render task in the event loop.
void RequestToPresent(scenic::Session* session);
// Debugging function.
std::string DumpScenes() { return gfx_->engine()->DumpScenes(); }
// Each test fixture defines its own test display parameters. It's needed
// both here (to define the display), and in the client (to define the size of
// a layer (TODO(SCN-248)).
virtual uint32_t test_display_width_px() const = 0;
virtual uint32_t test_display_height_px() const = 0;
// InputSystemTest needs its own teardown sequence, for session management.
void TearDown() override;
// Create a dummy GFX system, as well as a live input system to test.
void InitializeScenic(scenic_impl::Scenic* scenic) override;
scenic_impl::gfx::test::GfxSystemForTest* gfx_ = nullptr;
scenic_impl::input::InputSystem* input_ = nullptr;
// Convenience wrapper to write Scenic clients with less boilerplate.
class SessionWrapper {
SessionWrapper(scenic_impl::Scenic* scenic);
// Allow caller to run some code in the context of this particular session.
void RunNow(fit::function<void(scenic::Session* session,
scenic::EntityNode* root_node)>
// Allow caller to examine the events received by this particular session.
void ExamineEvents(
void(const std::vector<fuchsia::ui::input::InputEvent>& events)>
// Collects input events conveyed to this session.
std::vector<fuchsia::ui::input::InputEvent> events_;
// Client-side session object.
std::unique_ptr<scenic::Session> session_;
// Clients attach their nodes here to participate in the global scene graph.
std::unique_ptr<scenic::EntityNode> root_node_;
// Creates pointer event commands for one finger, where the pointer "device" is
// tied to one compositor. Helps remove boilerplate clutter.
// NOTE: It's easy to create an event stream with inconsistent state, e.g.,
// sending ADD ADD. Client is responsible for ensuring desired usage.
class PointerCommandGenerator {
PointerCommandGenerator(scenic_impl::ResourceId compositor_id,
uint32_t device_id, uint32_t pointer_id,
fuchsia::ui::input::PointerEventType type);
~PointerCommandGenerator() = default;
fuchsia::ui::input::Command Add(float x, float y);
fuchsia::ui::input::Command Down(float x, float y);
fuchsia::ui::input::Command Move(float x, float y);
fuchsia::ui::input::Command Up(float x, float y);
fuchsia::ui::input::Command Remove(float x, float y);
fuchsia::ui::input::Command MakeInputCommand(
fuchsia::ui::input::PointerEvent event);
scenic_impl::ResourceId compositor_id_;
fuchsia::ui::input::PointerEvent blank_;
// Creates keyboard event commands. Helps remove boilerplate clutter.
// NOTE: Just like PointerCommandGenerator, it's easy to create an event with
// inconsistent state. Client is responsible for ensuring desired usage.
class KeyboardCommandGenerator {
KeyboardCommandGenerator(scenic_impl::ResourceId compositor_id,
uint32_t device_id);
~KeyboardCommandGenerator() = default;
fuchsia::ui::input::Command Pressed(uint32_t hid_usage, uint32_t modifiers);
fuchsia::ui::input::Command Released(uint32_t hid_usage, uint32_t modifiers);
fuchsia::ui::input::Command Cancelled(uint32_t hid_usage, uint32_t modifiers);
fuchsia::ui::input::Command Repeat(uint32_t hid_usage, uint32_t modifiers);
fuchsia::ui::input::Command MakeInputCommand(
fuchsia::ui::input::KeyboardEvent event);
scenic_impl::ResourceId compositor_id_;
fuchsia::ui::input::KeyboardEvent blank_;
bool PointerMatches(const fuchsia::ui::input::PointerEvent& event,
uint32_t pointer_id,
fuchsia::ui::input::PointerEventPhase phase, float x,
float y);
} // namespace lib_ui_input_tests