From 3589654bc176bb4a5dfc48d59041c09adf7112f9 Mon Sep 17 00:00:00 2001 From: varkha Date: Wed, 2 Dec 2015 19:06:17 -0800 Subject: Removes unnecessary code path in ScopedTargetHandler With the separation of EventHandler and EventTarget (CL in https://codereview.chromium.org/1484513002/) the code path that explicitly invokes View::OnEvent is no longer needed. OnXxxxEvent overrides are also unnecessary. This CL will need to be rebased to https://codereview.chromium.org/1482293004/ and then it will be possible to move ScopedTargetHandler to ui/events/. BUG=537202 Review URL: https://codereview.chromium.org/1483283002 Cr-Commit-Position: refs/heads/master@{#362880} --- ui/events/scoped_target_handler_unittest.cc | 206 ++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 ui/events/scoped_target_handler_unittest.cc (limited to 'ui/events/scoped_target_handler_unittest.cc') diff --git a/ui/events/scoped_target_handler_unittest.cc b/ui/events/scoped_target_handler_unittest.cc new file mode 100644 index 0000000..b8c8d78 --- /dev/null +++ b/ui/events/scoped_target_handler_unittest.cc @@ -0,0 +1,206 @@ +// Copyright 2015 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 "ui/events/scoped_target_handler.h" + +#include "base/memory/scoped_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/event_handler.h" +#include "ui/events/event_target.h" +#include "ui/events/event_target_iterator.h" +#include "ui/events/event_utils.h" + +namespace ui { + +namespace { + +class TestEventTargetIterator : public EventTargetIterator { + public: + TestEventTargetIterator() {} + + // EventTargetIterator: + EventTarget* GetNextTarget() override { return nullptr; } + +private: + DISALLOW_COPY_AND_ASSIGN(TestEventTargetIterator); +}; + +// An EventTarget that holds ownership of its target and delegate EventHandlers. +class TestEventTarget : public EventTarget { + public: + TestEventTarget() {} + ~TestEventTarget() override {} + + void SetHandler(scoped_ptr target_handler, + scoped_ptr delegate) { + target_handler_ = target_handler.Pass(); + delegate_ = delegate.Pass(); + } + + // EventTarget: + void DispatchEvent(Event* event) { target_handler()->OnEvent(event); } + bool CanAcceptEvent(const Event& event) override { return true; } + EventTarget* GetParentTarget() override { return nullptr; } + scoped_ptr GetChildIterator() const override { + return make_scoped_ptr(new TestEventTargetIterator); + } + EventTargeter* GetEventTargeter() override { return nullptr; } + + private: + scoped_ptr target_handler_; + scoped_ptr delegate_; + + DISALLOW_COPY_AND_ASSIGN(TestEventTarget); +}; + +// An EventHandler that sets itself as a target handler for an EventTarget and +// can recursively dispatch an Event. +class NestedEventHandler : public EventHandler { + public: + NestedEventHandler(TestEventTarget* target, int nesting) + : target_(target), nesting_(nesting) { + original_handler_ = target_->SetTargetHandler(this); + } + ~NestedEventHandler() override { + EventHandler* handler = target_->SetTargetHandler(original_handler_); + DCHECK_EQ(this, handler); + } + + protected: + void OnEvent(Event* event) override { + if (--nesting_ == 0) + return; + target_->DispatchEvent(event); + } + + private: + TestEventTarget* target_; + int nesting_; + EventHandler* original_handler_; + + DISALLOW_COPY_AND_ASSIGN(NestedEventHandler); +}; + +// An EventHandler that sets itself as a target handler for an EventTarget and +// destroys that EventTarget when handling an Event, possibly after recursively +// handling the Event. +class TargetDestroyingEventHandler : public EventHandler { + public: + TargetDestroyingEventHandler(TestEventTarget* target, int nesting) + : target_(target), nesting_(nesting) { + original_handler_ = target_->SetTargetHandler(this); + } + ~TargetDestroyingEventHandler() override { + EventHandler* handler = target_->SetTargetHandler(original_handler_); + DCHECK_EQ(this, handler); + } + + protected: + void OnEvent(Event* event) override { + if (--nesting_ == 0) { + delete target_; + return; + } + target_->DispatchEvent(event); + } + + private: + TestEventTarget* target_; + int nesting_; + EventHandler* original_handler_; + + DISALLOW_COPY_AND_ASSIGN(TargetDestroyingEventHandler); +}; + +// An EventHandler that can be set to receive events in addition to the target +// handler and counts the Events that it receives. +class EventCountingEventHandler : public EventHandler { + public: + EventCountingEventHandler(EventTarget* target, int* count) + : scoped_target_handler_(new ScopedTargetHandler(target, this)), + count_(count) {} + ~EventCountingEventHandler() override {} + + protected: + void OnEvent(Event* event) override { (*count_)++; } + + private: + scoped_ptr scoped_target_handler_; + int* count_; + + DISALLOW_COPY_AND_ASSIGN(EventCountingEventHandler); +}; + +} // namespace + +// Tests that a ScopedTargetHandler invokes both the target and a delegate. +TEST(ScopedTargetHandlerTest, HandlerInvoked) { + int count = 0; + TestEventTarget* target = new TestEventTarget; + scoped_ptr target_handler( + new NestedEventHandler(target, 1)); + scoped_ptr delegate( + new EventCountingEventHandler(target, &count)); + target->SetHandler(target_handler.Pass(), delegate.Pass()); + MouseEvent event(ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + EventTimeForNow(), EF_LEFT_MOUSE_BUTTON, + EF_LEFT_MOUSE_BUTTON); + target->DispatchEvent(&event); + EXPECT_EQ(1, count); + delete target; +} + +// Tests that a ScopedTargetHandler invokes both the target and a delegate when +// an Event is dispatched recursively such as with synthetic events. +TEST(ScopedTargetHandlerTest, HandlerInvokedNested) { + int count = 0; + TestEventTarget* target = new TestEventTarget; + scoped_ptr target_handler( + new NestedEventHandler(target, 2)); + scoped_ptr delegate( + new EventCountingEventHandler(target, &count)); + target->SetHandler(target_handler.Pass(), delegate.Pass()); + MouseEvent event(ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + EventTimeForNow(), EF_LEFT_MOUSE_BUTTON, + EF_LEFT_MOUSE_BUTTON); + target->DispatchEvent(&event); + EXPECT_EQ(2, count); + delete target; +} + +// Tests that a it is safe to delete a ScopedTargetHandler while handling an +// event. +TEST(ScopedTargetHandlerTest, SafeToDestroy) { + int count = 0; + TestEventTarget* target = new TestEventTarget; + scoped_ptr target_handler( + new TargetDestroyingEventHandler(target, 1)); + scoped_ptr delegate( + new EventCountingEventHandler(target, &count)); + target->SetHandler(target_handler.Pass(), delegate.Pass()); + MouseEvent event(ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + EventTimeForNow(), EF_LEFT_MOUSE_BUTTON, + EF_LEFT_MOUSE_BUTTON); + target->DispatchEvent(&event); + EXPECT_EQ(0, count); +} + +// Tests that a it is safe to delete a ScopedTargetHandler while handling an +// event recursively. +TEST(ScopedTargetHandlerTest, SafeToDestroyNested) { + int count = 0; + TestEventTarget* target = new TestEventTarget; + scoped_ptr target_handler( + new TargetDestroyingEventHandler(target, 2)); + scoped_ptr delegate( + new EventCountingEventHandler(target, &count)); + target->SetHandler(target_handler.Pass(), delegate.Pass()); + MouseEvent event(ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + EventTimeForNow(), EF_LEFT_MOUSE_BUTTON, + EF_LEFT_MOUSE_BUTTON); + target->DispatchEvent(&event); + EXPECT_EQ(0, count); +} + +} // namespace ui -- cgit v1.1