1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "testing/gtest/include/gtest/gtest.h" 6 #include "ui/events/event.h" 7 #include "ui/events/event_targeter.h" 8 #include "ui/events/test/test_event_processor.h" 9 #include "ui/events/test/test_event_target.h" 10 11 namespace ui { 12 namespace test { 13 14 class EventProcessorTest : public testing::Test { 15 public: 16 EventProcessorTest() {} 17 virtual ~EventProcessorTest() {} 18 19 // testing::Test: 20 virtual void SetUp() OVERRIDE { 21 processor_.SetRoot(scoped_ptr<EventTarget>(new TestEventTarget())); 22 root()->SetEventTargeter(make_scoped_ptr(new EventTargeter())); 23 } 24 25 TestEventTarget* root() { 26 return static_cast<TestEventTarget*>(processor_.GetRootTarget()); 27 } 28 29 void DispatchEvent(Event* event) { 30 processor_.OnEventFromSource(event); 31 } 32 33 protected: 34 TestEventProcessor processor_; 35 36 DISALLOW_COPY_AND_ASSIGN(EventProcessorTest); 37 }; 38 39 TEST_F(EventProcessorTest, Basic) { 40 scoped_ptr<TestEventTarget> child(new TestEventTarget()); 41 root()->AddChild(child.Pass()); 42 43 MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10), 44 EF_NONE); 45 DispatchEvent(&mouse); 46 EXPECT_TRUE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED)); 47 EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 48 49 root()->RemoveChild(root()->child_at(0)); 50 DispatchEvent(&mouse); 51 EXPECT_TRUE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 52 } 53 54 template<typename T> 55 class BoundsEventTargeter : public EventTargeter { 56 public: 57 virtual ~BoundsEventTargeter() {} 58 59 protected: 60 virtual bool SubtreeShouldBeExploredForEvent( 61 EventTarget* target, const LocatedEvent& event) OVERRIDE { 62 T* t = static_cast<T*>(target); 63 return (t->bounds().Contains(event.location())); 64 } 65 }; 66 67 class BoundsTestTarget : public TestEventTarget { 68 public: 69 BoundsTestTarget() {} 70 virtual ~BoundsTestTarget() {} 71 72 void set_bounds(gfx::Rect rect) { bounds_ = rect; } 73 gfx::Rect bounds() const { return bounds_; } 74 75 static void ConvertPointToTarget(BoundsTestTarget* source, 76 BoundsTestTarget* target, 77 gfx::Point* location) { 78 gfx::Vector2d vector; 79 if (source->Contains(target)) { 80 for (; target && target != source; 81 target = static_cast<BoundsTestTarget*>(target->parent())) { 82 vector += target->bounds().OffsetFromOrigin(); 83 } 84 *location -= vector; 85 } else if (target->Contains(source)) { 86 for (; source && source != target; 87 source = static_cast<BoundsTestTarget*>(source->parent())) { 88 vector += source->bounds().OffsetFromOrigin(); 89 } 90 *location += vector; 91 } else { 92 NOTREACHED(); 93 } 94 } 95 96 private: 97 // EventTarget: 98 virtual void ConvertEventToTarget(EventTarget* target, 99 LocatedEvent* event) OVERRIDE { 100 event->ConvertLocationToTarget(this, 101 static_cast<BoundsTestTarget*>(target)); 102 } 103 104 gfx::Rect bounds_; 105 106 DISALLOW_COPY_AND_ASSIGN(BoundsTestTarget); 107 }; 108 109 TEST_F(EventProcessorTest, Bounds) { 110 scoped_ptr<BoundsTestTarget> parent(new BoundsTestTarget()); 111 scoped_ptr<BoundsTestTarget> child(new BoundsTestTarget()); 112 scoped_ptr<BoundsTestTarget> grandchild(new BoundsTestTarget()); 113 114 parent->set_bounds(gfx::Rect(0, 0, 30, 30)); 115 child->set_bounds(gfx::Rect(5, 5, 20, 20)); 116 grandchild->set_bounds(gfx::Rect(5, 5, 5, 5)); 117 118 child->AddChild(scoped_ptr<TestEventTarget>(grandchild.Pass())); 119 parent->AddChild(scoped_ptr<TestEventTarget>(child.Pass())); 120 root()->AddChild(scoped_ptr<TestEventTarget>(parent.Pass())); 121 122 ASSERT_EQ(1u, root()->child_count()); 123 ASSERT_EQ(1u, root()->child_at(0)->child_count()); 124 ASSERT_EQ(1u, root()->child_at(0)->child_at(0)->child_count()); 125 126 TestEventTarget* parent_r = root()->child_at(0); 127 TestEventTarget* child_r = parent_r->child_at(0); 128 TestEventTarget* grandchild_r = child_r->child_at(0); 129 130 // Dispatch a mouse event that falls on the parent, but not on the child. When 131 // the default event-targeter used, the event will still reach |grandchild|, 132 // because the default targeter does not look at the bounds. 133 MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(1, 1), gfx::Point(1, 1), EF_NONE); 134 DispatchEvent(&mouse); 135 EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 136 EXPECT_FALSE(parent_r->DidReceiveEvent(ET_MOUSE_MOVED)); 137 EXPECT_FALSE(child_r->DidReceiveEvent(ET_MOUSE_MOVED)); 138 EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_MOUSE_MOVED)); 139 grandchild_r->ResetReceivedEvents(); 140 141 // Now install a targeter on the parent that looks at the bounds and makes 142 // sure the event reaches the target only if the location of the event within 143 // the bounds of the target. 144 parent_r->SetEventTargeter(scoped_ptr<EventTargeter>( 145 new BoundsEventTargeter<BoundsTestTarget>())); 146 DispatchEvent(&mouse); 147 EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 148 EXPECT_TRUE(parent_r->DidReceiveEvent(ET_MOUSE_MOVED)); 149 EXPECT_FALSE(child_r->DidReceiveEvent(ET_MOUSE_MOVED)); 150 EXPECT_FALSE(grandchild_r->DidReceiveEvent(ET_MOUSE_MOVED)); 151 parent_r->ResetReceivedEvents(); 152 153 MouseEvent second(ET_MOUSE_MOVED, gfx::Point(12, 12), gfx::Point(12, 12), 154 EF_NONE); 155 DispatchEvent(&second); 156 EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 157 EXPECT_FALSE(parent_r->DidReceiveEvent(ET_MOUSE_MOVED)); 158 EXPECT_FALSE(child_r->DidReceiveEvent(ET_MOUSE_MOVED)); 159 EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_MOUSE_MOVED)); 160 } 161 162 } // namespace test 163 } // namespace ui 164