123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- // Copyright (c) 2013 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 <tuple>
- #include <utility>
- #include <vector>
- #include "base/memory/ptr_util.h"
- #include "base/memory/raw_ptr.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/events/event.h"
- #include "ui/events/event_target_iterator.h"
- #include "ui/events/event_targeter.h"
- #include "ui/events/event_utils.h"
- #include "ui/events/test/events_test_utils.h"
- #include "ui/events/test/test_event_handler.h"
- #include "ui/events/test/test_event_processor.h"
- #include "ui/events/test/test_event_target.h"
- #include "ui/events/test/test_event_targeter.h"
- typedef std::vector<std::string> HandlerSequenceRecorder;
- namespace ui {
- namespace test {
- class EventProcessorTest : public testing::Test {
- public:
- EventProcessorTest() {}
- EventProcessorTest(const EventProcessorTest&) = delete;
- EventProcessorTest& operator=(const EventProcessorTest&) = delete;
- ~EventProcessorTest() override {}
- protected:
- // testing::Test:
- void SetUp() override {
- processor_.SetRoot(std::make_unique<TestEventTarget>());
- processor_.Reset();
- root()->SetEventTargeter(
- std::make_unique<TestEventTargeter>(root(), false));
- }
- TestEventTarget* root() {
- return static_cast<TestEventTarget*>(processor_.GetRoot());
- }
- TestEventProcessor* processor() {
- return &processor_;
- }
- void DispatchEvent(Event* event) {
- processor_.OnEventFromSource(event);
- }
- void SetTarget(TestEventTarget* target) {
- static_cast<TestEventTargeter*>(root()->GetEventTargeter())
- ->set_target(target);
- }
- private:
- TestEventProcessor processor_;
- };
- TEST_F(EventProcessorTest, Basic) {
- std::unique_ptr<TestEventTarget> child(new TestEventTarget());
- child->SetEventTargeter(
- std::make_unique<TestEventTargeter>(child.get(), false));
- SetTarget(child.get());
- root()->AddChild(std::move(child));
- MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
- EventTimeForNow(), EF_NONE, EF_NONE);
- DispatchEvent(&mouse);
- EXPECT_TRUE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED));
- EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
- SetTarget(root());
- root()->RemoveChild(root()->child_at(0));
- DispatchEvent(&mouse);
- EXPECT_TRUE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
- }
- // ReDispatchEventHandler is used to receive mouse events and forward them
- // to a specified EventProcessor. Verifies that the event has the correct
- // target and phase both before and after the nested event processing. Also
- // verifies that the location of the event remains the same after it has
- // been processed by the second EventProcessor.
- class ReDispatchEventHandler : public TestEventHandler {
- public:
- ReDispatchEventHandler(EventProcessor* processor, EventTarget* target)
- : processor_(processor), expected_target_(target) {}
- ReDispatchEventHandler(const ReDispatchEventHandler&) = delete;
- ReDispatchEventHandler& operator=(const ReDispatchEventHandler&) = delete;
- ~ReDispatchEventHandler() override {}
- // TestEventHandler:
- void OnMouseEvent(MouseEvent* event) override {
- TestEventHandler::OnMouseEvent(event);
- EXPECT_EQ(expected_target_, event->target());
- EXPECT_EQ(EP_TARGET, event->phase());
- gfx::Point location(event->location());
- EventDispatchDetails details = processor_->OnEventFromSource(event);
- EXPECT_FALSE(details.dispatcher_destroyed);
- EXPECT_FALSE(details.target_destroyed);
- // The nested event-processing should not have mutated the target,
- // phase, or location of |event|.
- EXPECT_EQ(expected_target_, event->target());
- EXPECT_EQ(EP_TARGET, event->phase());
- EXPECT_EQ(location, event->location());
- }
- private:
- raw_ptr<EventProcessor> processor_;
- raw_ptr<EventTarget> expected_target_;
- };
- // Verifies that the phase and target information of an event is not mutated
- // as a result of sending the event to an event processor while it is still
- // being processed by another event processor.
- TEST_F(EventProcessorTest, NestedEventProcessing) {
- // Add one child to the default event processor used in this test suite.
- std::unique_ptr<TestEventTarget> child(new TestEventTarget());
- SetTarget(child.get());
- root()->AddChild(std::move(child));
- // Define a second root target and child.
- std::unique_ptr<EventTarget> second_root_scoped(new TestEventTarget());
- TestEventTarget* second_root =
- static_cast<TestEventTarget*>(second_root_scoped.get());
- std::unique_ptr<TestEventTarget> second_child(new TestEventTarget());
- second_root->SetEventTargeter(
- base::WrapUnique(new TestEventTargeter(second_child.get(), false)));
- second_root->AddChild(std::move(second_child));
- // Define a second event processor which owns the second root.
- std::unique_ptr<TestEventProcessor> second_processor(
- new TestEventProcessor());
- second_processor->SetRoot(std::move(second_root_scoped));
- // Indicate that an event which is dispatched to the child target owned by the
- // first event processor should be handled by |target_handler| instead.
- std::unique_ptr<TestEventHandler> target_handler(
- new ReDispatchEventHandler(second_processor.get(), root()->child_at(0)));
- std::ignore = root()->child_at(0)->SetTargetHandler(target_handler.get());
- // Dispatch a mouse event to the tree of event targets owned by the first
- // event processor, checking in ReDispatchEventHandler that the phase and
- // target information of the event is correct.
- MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
- EventTimeForNow(), EF_NONE, EF_NONE);
- DispatchEvent(&mouse);
- // Verify also that |mouse| was seen by the child nodes contained in both
- // event processors and that the event was not handled.
- EXPECT_EQ(1, target_handler->num_mouse_events());
- EXPECT_TRUE(second_root->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED));
- EXPECT_FALSE(mouse.handled());
- second_root->child_at(0)->ResetReceivedEvents();
- root()->child_at(0)->ResetReceivedEvents();
- target_handler->Reset();
- // Indicate that the child of the second root should handle events, and
- // dispatch another mouse event to verify that it is marked as handled.
- second_root->child_at(0)->set_mark_events_as_handled(true);
- MouseEvent mouse2(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
- EventTimeForNow(), EF_NONE, EF_NONE);
- DispatchEvent(&mouse2);
- EXPECT_EQ(1, target_handler->num_mouse_events());
- EXPECT_TRUE(second_root->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED));
- EXPECT_TRUE(mouse2.handled());
- }
- // Verifies that OnEventProcessingFinished() is called when an event
- // has been handled.
- TEST_F(EventProcessorTest, OnEventProcessingFinished) {
- std::unique_ptr<TestEventTarget> child(new TestEventTarget());
- child->set_mark_events_as_handled(true);
- SetTarget(child.get());
- root()->AddChild(std::move(child));
- // Dispatch a mouse event. We expect the event to be seen by the target,
- // handled, and we expect OnEventProcessingFinished() to be invoked once.
- MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
- EventTimeForNow(), EF_NONE, EF_NONE);
- DispatchEvent(&mouse);
- EXPECT_TRUE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED));
- EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
- EXPECT_TRUE(mouse.handled());
- EXPECT_EQ(1, processor()->num_times_processing_finished());
- }
- // Verifies that OnEventProcessingStarted() has been called when starting to
- // process an event, and that processing does not take place if
- // OnEventProcessingStarted() marks the event as handled. Also verifies that
- // OnEventProcessingFinished() is also called in either case.
- TEST_F(EventProcessorTest, OnEventProcessingStarted) {
- std::unique_ptr<TestEventTarget> child(new TestEventTarget());
- SetTarget(child.get());
- root()->AddChild(std::move(child));
- // Dispatch a mouse event. We expect the event to be seen by the target,
- // OnEventProcessingStarted() should be called once, and
- // OnEventProcessingFinished() should be called once. The event should
- // remain unhandled.
- MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
- EventTimeForNow(), EF_NONE, EF_NONE);
- DispatchEvent(&mouse);
- EXPECT_TRUE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED));
- EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
- EXPECT_FALSE(mouse.handled());
- EXPECT_EQ(1, processor()->num_times_processing_started());
- EXPECT_EQ(1, processor()->num_times_processing_finished());
- processor()->Reset();
- root()->ResetReceivedEvents();
- root()->child_at(0)->ResetReceivedEvents();
- // Dispatch another mouse event, but with OnEventProcessingStarted() marking
- // the event as handled to prevent processing. We expect the event to not be
- // seen by the target this time, but OnEventProcessingStarted() and
- // OnEventProcessingFinished() should both still be called once.
- processor()->set_should_processing_occur(false);
- MouseEvent mouse2(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
- EventTimeForNow(), EF_NONE, EF_NONE);
- DispatchEvent(&mouse2);
- EXPECT_FALSE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED));
- EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
- EXPECT_TRUE(mouse2.handled());
- EXPECT_EQ(1, processor()->num_times_processing_started());
- EXPECT_EQ(1, processor()->num_times_processing_finished());
- }
- // Tests that unhandled events are correctly dispatched to the next-best
- // target as decided by the TestEventTargeter.
- TEST_F(EventProcessorTest, DispatchToNextBestTarget) {
- std::unique_ptr<TestEventTarget> child(new TestEventTarget());
- std::unique_ptr<TestEventTarget> grandchild(new TestEventTarget());
- // Install a TestEventTargeter which permits bubbling.
- root()->SetEventTargeter(
- base::WrapUnique(new TestEventTargeter(grandchild.get(), true)));
- child->AddChild(std::move(grandchild));
- root()->AddChild(std::move(child));
- ASSERT_EQ(1u, root()->child_count());
- ASSERT_EQ(1u, root()->child_at(0)->child_count());
- ASSERT_EQ(0u, root()->child_at(0)->child_at(0)->child_count());
- TestEventTarget* child_r = root()->child_at(0);
- TestEventTarget* grandchild_r = child_r->child_at(0);
- // When the root has a TestEventTargeter installed which permits bubbling,
- // events targeted at the grandchild target should be dispatched to all three
- // targets.
- KeyEvent key_event(ET_KEY_PRESSED, VKEY_ESCAPE, EF_NONE);
- DispatchEvent(&key_event);
- EXPECT_TRUE(root()->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_TRUE(child_r->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED));
- root()->ResetReceivedEvents();
- child_r->ResetReceivedEvents();
- grandchild_r->ResetReceivedEvents();
- // Add a pre-target handler on the child of the root that will mark the event
- // as handled. No targets in the hierarchy should receive the event.
- TestEventHandler handler;
- child_r->AddPreTargetHandler(&handler);
- key_event = KeyEvent(ET_KEY_PRESSED, VKEY_ESCAPE, EF_NONE);
- DispatchEvent(&key_event);
- EXPECT_FALSE(root()->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_FALSE(child_r->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_FALSE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_EQ(1, handler.num_key_events());
- handler.Reset();
- // Add a post-target handler on the child of the root that will mark the event
- // as handled. Only the grandchild (the initial target) should receive the
- // event.
- child_r->RemovePreTargetHandler(&handler);
- child_r->AddPostTargetHandler(&handler);
- key_event = KeyEvent(ET_KEY_PRESSED, VKEY_ESCAPE, EF_NONE);
- DispatchEvent(&key_event);
- EXPECT_FALSE(root()->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_FALSE(child_r->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_EQ(1, handler.num_key_events());
- handler.Reset();
- grandchild_r->ResetReceivedEvents();
- child_r->RemovePostTargetHandler(&handler);
- // Mark the event as handled when it reaches the EP_TARGET phase of
- // dispatch at the child of the root. The child and grandchild
- // targets should both receive the event, but the root should not.
- child_r->set_mark_events_as_handled(true);
- key_event = KeyEvent(ET_KEY_PRESSED, VKEY_ESCAPE, EF_NONE);
- DispatchEvent(&key_event);
- EXPECT_FALSE(root()->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_TRUE(child_r->DidReceiveEvent(ET_KEY_PRESSED));
- EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED));
- root()->ResetReceivedEvents();
- child_r->ResetReceivedEvents();
- grandchild_r->ResetReceivedEvents();
- child_r->set_mark_events_as_handled(false);
- }
- // Tests that unhandled events are seen by the correct sequence of
- // targets, pre-target handlers, and post-target handlers when
- // a TestEventTargeter is installed on the root target which permits bubbling.
- TEST_F(EventProcessorTest, HandlerSequence) {
- std::unique_ptr<TestEventTarget> child(new TestEventTarget());
- std::unique_ptr<TestEventTarget> grandchild(new TestEventTarget());
- // Install a TestEventTargeter which permits bubbling.
- root()->SetEventTargeter(
- base::WrapUnique(new TestEventTargeter(grandchild.get(), true)));
- child->AddChild(std::move(grandchild));
- root()->AddChild(std::move(child));
- ASSERT_EQ(1u, root()->child_count());
- ASSERT_EQ(1u, root()->child_at(0)->child_count());
- ASSERT_EQ(0u, root()->child_at(0)->child_at(0)->child_count());
- TestEventTarget* child_r = root()->child_at(0);
- TestEventTarget* grandchild_r = child_r->child_at(0);
- HandlerSequenceRecorder recorder;
- root()->set_target_name("R");
- root()->set_recorder(&recorder);
- child_r->set_target_name("C");
- child_r->set_recorder(&recorder);
- grandchild_r->set_target_name("G");
- grandchild_r->set_recorder(&recorder);
- TestEventHandler pre_root;
- pre_root.set_handler_name("PreR");
- pre_root.set_recorder(&recorder);
- root()->AddPreTargetHandler(&pre_root);
- TestEventHandler pre_child;
- pre_child.set_handler_name("PreC");
- pre_child.set_recorder(&recorder);
- child_r->AddPreTargetHandler(&pre_child);
- TestEventHandler pre_grandchild;
- pre_grandchild.set_handler_name("PreG");
- pre_grandchild.set_recorder(&recorder);
- grandchild_r->AddPreTargetHandler(&pre_grandchild);
- TestEventHandler post_root;
- post_root.set_handler_name("PostR");
- post_root.set_recorder(&recorder);
- root()->AddPostTargetHandler(&post_root);
- TestEventHandler post_child;
- post_child.set_handler_name("PostC");
- post_child.set_recorder(&recorder);
- child_r->AddPostTargetHandler(&post_child);
- TestEventHandler post_grandchild;
- post_grandchild.set_handler_name("PostG");
- post_grandchild.set_recorder(&recorder);
- grandchild_r->AddPostTargetHandler(&post_grandchild);
- MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
- EventTimeForNow(), EF_NONE, EF_NONE);
- DispatchEvent(&mouse);
- std::string expected[] = { "PreR", "PreC", "PreG", "G", "PostG", "PostC",
- "PostR", "PreR", "PreC", "C", "PostC", "PostR", "PreR", "R", "PostR" };
- EXPECT_EQ(std::vector<std::string>(expected, expected + std::size(expected)),
- recorder);
- root()->RemovePreTargetHandler(&pre_root);
- child_r->RemovePreTargetHandler(&pre_child);
- grandchild_r->RemovePreTargetHandler(&pre_grandchild);
- }
- namespace {
- class SelfDestroyingEventProcessor : public TestEventProcessor {
- public:
- SelfDestroyingEventProcessor() = default;
- SelfDestroyingEventProcessor(const SelfDestroyingEventProcessor&) = delete;
- SelfDestroyingEventProcessor& operator=(const SelfDestroyingEventProcessor&) =
- delete;
- ~SelfDestroyingEventProcessor() override = default;
- protected:
- EventDispatchDetails PostDispatchEvent(EventTarget* target,
- const Event& event) override;
- };
- class SelfDestroyingTestEventTarget : public TestEventTarget {
- public:
- SelfDestroyingTestEventTarget()
- : processor_(new SelfDestroyingEventProcessor()) {}
- SelfDestroyingTestEventTarget(const SelfDestroyingTestEventTarget&) = delete;
- SelfDestroyingTestEventTarget& operator=(
- const SelfDestroyingTestEventTarget&) = delete;
- TestEventProcessor* processor() { return processor_.get(); }
- void DestroyProcessor() { processor_.reset(); }
- private:
- std::unique_ptr<SelfDestroyingEventProcessor> processor_;
- };
- EventDispatchDetails SelfDestroyingEventProcessor::PostDispatchEvent(
- EventTarget* target,
- const Event& event) {
- static_cast<SelfDestroyingTestEventTarget*>(target)->DestroyProcessor();
- return EventDispatchDetails();
- }
- } // namespace
- TEST(EventProcessorCrashTest, Basic) {
- std::unique_ptr<TestEventTarget> root(new TestEventTarget());
- std::unique_ptr<SelfDestroyingTestEventTarget> target(
- new SelfDestroyingTestEventTarget());
- root->SetEventTargeter(
- std::make_unique<TestEventTargeter>(target.get(), false));
- TestEventProcessor* processor = target->processor();
- processor->SetRoot(std::move(root));
- MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
- EventTimeForNow(), EF_NONE, EF_NONE);
- EXPECT_TRUE(processor->OnEventFromSource(&mouse).dispatcher_destroyed);
- }
- namespace {
- class SelfDestroyingTestEventTargeter : public TestEventTargeter {
- public:
- explicit SelfDestroyingTestEventTargeter(std::unique_ptr<EventTarget> root)
- : TestEventTargeter(nullptr, false),
- processor_(new TestEventProcessor()) {
- processor_->SetRoot(std::move(root));
- }
- SelfDestroyingTestEventTargeter(const SelfDestroyingTestEventTarget&) =
- delete;
- SelfDestroyingTestEventTargeter& operator=(
- const SelfDestroyingTestEventTargeter&) = delete;
- ~SelfDestroyingTestEventTargeter() override = default;
- // EventTargeter:
- EventTarget* FindTargetForEvent(EventTarget* root, Event* event) override {
- processor_.reset();
- return nullptr;
- }
- EventProcessor* processor() { return processor_.get(); }
- private:
- std::unique_ptr<TestEventProcessor> processor_;
- };
- } // namespace
- TEST(EventProcessorCrashTest, DestroyDuringFindTarget) {
- std::unique_ptr<TestEventTarget> root(new TestEventTarget());
- auto* root_ptr = root.get();
- auto event_targeter =
- std::make_unique<SelfDestroyingTestEventTargeter>(std::move(root));
- auto* processor = event_targeter->processor();
- root_ptr->SetEventTargeter(std::move(event_targeter));
- MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
- EventTimeForNow(), EF_NONE, EF_NONE);
- EXPECT_TRUE(processor->OnEventFromSource(&mouse).dispatcher_destroyed);
- }
- } // namespace test
- } // namespace ui
|