blob: 1030a569f4a6c5bec26da652f3d5c96965354864 [file] [log] [blame]
// Copyright 2018 The Chromium 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 "services/ws/event_injector.h"
#include <memory>
#include <utility>
#include "base/bind_helpers.h"
#include "services/ws/event_injector.h"
#include "services/ws/injected_event_handler.h"
#include "services/ws/window_delegate_impl.h"
#include "services/ws/window_service.h"
#include "services/ws/window_service_test_helper.h"
#include "services/ws/window_service_test_setup.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/test/aura_test_helper.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event_source.h"
#include "ui/events/test/test_event_rewriter.h"
namespace ws {
namespace {
std::unique_ptr<ui::Event> CreateMouseTestEvent() {
return std::make_unique<ui::MouseEvent>(
ui::ET_MOUSE_PRESSED, gfx::Point(100, 100), gfx::Point(100, 100),
base::TimeTicks::Now(), ui::EF_NONE, ui::EF_NONE);
}
std::unique_ptr<ui::Event> CreateTouchTestEvent() {
return std::make_unique<ui::TouchEvent>(
ui::ET_TOUCH_PRESSED, gfx::Point(100, 100), base::TimeTicks::Now(),
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
}
gfx::Transform GetPrimaryDisplayRotationTransform(
const display::Display::Rotation& rotation) {
gfx::Transform rotate_transform;
display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
switch (rotation) {
case display::Display::ROTATE_0:
break;
case display::Display::ROTATE_90:
rotate_transform.Translate(display.bounds().height(), 0);
rotate_transform.Rotate(90);
break;
case display::Display::ROTATE_180:
rotate_transform.Translate(display.bounds().width(),
display.bounds().height());
rotate_transform.Rotate(180);
break;
case display::Display::ROTATE_270:
rotate_transform.Translate(0, display.bounds().width());
rotate_transform.Rotate(270);
break;
}
return rotate_transform;
}
} // namespace
TEST(EventInjectorTest, NoAck) {
WindowServiceTestSetup test_setup;
test_setup.service()->OnStart();
auto* event_source = test_setup.root()->GetHost()->GetEventSource();
ui::test::TestEventRewriter test_event_rewriter;
event_source->AddEventRewriter(&test_event_rewriter);
EventInjector* event_injector =
WindowServiceTestHelper(test_setup.service()).event_injector();
mojom::EventInjector* mojom_event_injector =
static_cast<mojom::EventInjector*>(event_injector);
auto display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
mojom_event_injector->InjectEventNoAck(display_id, CreateMouseTestEvent());
EXPECT_EQ(1, test_event_rewriter.events_seen());
EXPECT_FALSE(event_injector->HasQueuedEvents());
test_event_rewriter.clear_events_seen();
// Repeat, using the API that circumvents rewriters.
mojom_event_injector->InjectEventNoAckNoRewriters(display_id,
CreateMouseTestEvent());
EXPECT_EQ(0, test_event_rewriter.events_seen());
EXPECT_FALSE(event_injector->HasQueuedEvents());
event_source->RemoveEventRewriter(&test_event_rewriter);
}
// Test that the event's coordinates are set correctly when the screen is
// rotated at a degree of 90. 180 and 270.
TEST(EventInjectorTest, EventLocationRootTransformRotation) {
WindowServiceTestSetup test_setup;
test_setup.service()->OnStart();
auto* event_source = test_setup.root()->GetHost()->GetEventSource();
ui::test::TestEventRewriter test_event_rewriter;
event_source->AddEventRewriter(&test_event_rewriter);
EventInjector* event_injector =
WindowServiceTestHelper(test_setup.service()).event_injector();
mojom::EventInjector* mojom_event_injector =
static_cast<mojom::EventInjector*>(event_injector);
auto display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
// Inject a touch press event without rotating the screen.
mojom_event_injector->InjectEventNoAck(display_id, CreateTouchTestEvent());
EXPECT_EQ(1, test_event_rewriter.events_seen());
const ui::Event* last_event = test_event_rewriter.last_event();
ASSERT_TRUE(last_event);
gfx::Point location(100, 100);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
test_event_rewriter.ResetLastEvent();
// Set the screen rotation degreen to 90 and inject a touch press event.
test_setup.root()->GetHost()->SetRootTransform(
GetPrimaryDisplayRotationTransform(display::Display::ROTATE_90));
mojom_event_injector->InjectEventNoAck(display_id, CreateTouchTestEvent());
EXPECT_EQ(2, test_event_rewriter.events_seen());
last_event = test_event_rewriter.last_event();
ASSERT_TRUE(last_event);
location = gfx::Point(500, 100);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
test_event_rewriter.ResetLastEvent();
// Set the screen rotation degreen to 180 and inject a touch press event.
test_setup.root()->GetHost()->SetRootTransform(
GetPrimaryDisplayRotationTransform(display::Display::ROTATE_180));
mojom_event_injector->InjectEventNoAck(display_id, CreateTouchTestEvent());
EXPECT_EQ(3, test_event_rewriter.events_seen());
last_event = test_event_rewriter.last_event();
ASSERT_TRUE(last_event);
location = gfx::Point(500, 700);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
test_event_rewriter.ResetLastEvent();
// Set the screen rotation degreen to 270 and inject a mouse press event.
test_setup.root()->GetHost()->SetRootTransform(
GetPrimaryDisplayRotationTransform(display::Display::ROTATE_270));
mojom_event_injector->InjectEventNoAck(display_id, CreateMouseTestEvent());
EXPECT_EQ(4, test_event_rewriter.events_seen());
last_event = test_event_rewriter.last_event();
ASSERT_TRUE(last_event);
location = gfx::Point(100, 700);
EXPECT_EQ(ui::ET_MOUSE_PRESSED, last_event->type());
EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
test_event_rewriter.ResetLastEvent();
event_source->RemoveEventRewriter(&test_event_rewriter);
}
// Test that the event's coordinates are set correctly when the screen is
// rotated at a degree of 90 and applied a scale factor of 2.
TEST(EventInjectorTest, EventLocationRootTransformRotationScale) {
WindowServiceTestSetup test_setup;
test_setup.service()->OnStart();
auto* event_source = test_setup.root()->GetHost()->GetEventSource();
ui::test::TestEventRewriter test_event_rewriter;
event_source->AddEventRewriter(&test_event_rewriter);
EventInjector* event_injector =
WindowServiceTestHelper(test_setup.service()).event_injector();
mojom::EventInjector* mojom_event_injector =
static_cast<mojom::EventInjector*>(event_injector);
display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
// Inject a touch press event without rotating the screen and scaling.
mojom_event_injector->InjectEventNoAck(display.id(), CreateTouchTestEvent());
EXPECT_EQ(1, test_event_rewriter.events_seen());
const ui::Event* last_event = test_event_rewriter.last_event();
ASSERT_TRUE(last_event);
gfx::Point location(100, 100);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
test_event_rewriter.ResetLastEvent();
// Inject a touch press event when the screen rotation degreen is 90 and the
// scale factor is 2.
gfx::Transform transform;
transform.Scale(2, 2);
transform.Translate(display.bounds().height(), 0);
transform.Rotate(90);
test_setup.root()->GetHost()->SetRootTransform(transform);
mojom_event_injector->InjectEventNoAck(display.id(), CreateTouchTestEvent());
EXPECT_EQ(2, test_event_rewriter.events_seen());
last_event = test_event_rewriter.last_event();
ASSERT_TRUE(last_event);
location = gfx::Point(1000, 200);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, last_event->type());
EXPECT_EQ(location, last_event->AsLocatedEvent()->location());
EXPECT_EQ(location, last_event->AsLocatedEvent()->root_location());
test_event_rewriter.ResetLastEvent();
event_source->RemoveEventRewriter(&test_event_rewriter);
}
} // namespace ws