event_processor_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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
11namespace ui {
12namespace test {
13
14class 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
39TEST_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, 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
54template<typename T>
55class 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
67class 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
109TEST_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                   EF_NONE);
135  DispatchEvent(&mouse);
136  EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
137  EXPECT_FALSE(parent_r->DidReceiveEvent(ET_MOUSE_MOVED));
138  EXPECT_FALSE(child_r->DidReceiveEvent(ET_MOUSE_MOVED));
139  EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_MOUSE_MOVED));
140  grandchild_r->ResetReceivedEvents();
141
142  // Now install a targeter on the parent that looks at the bounds and makes
143  // sure the event reaches the target only if the location of the event within
144  // the bounds of the target.
145  MouseEvent mouse2(ET_MOUSE_MOVED, gfx::Point(1, 1), gfx::Point(1, 1), EF_NONE,
146                    EF_NONE);
147  parent_r->SetEventTargeter(scoped_ptr<EventTargeter>(
148      new BoundsEventTargeter<BoundsTestTarget>()));
149  DispatchEvent(&mouse2);
150  EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
151  EXPECT_TRUE(parent_r->DidReceiveEvent(ET_MOUSE_MOVED));
152  EXPECT_FALSE(child_r->DidReceiveEvent(ET_MOUSE_MOVED));
153  EXPECT_FALSE(grandchild_r->DidReceiveEvent(ET_MOUSE_MOVED));
154  parent_r->ResetReceivedEvents();
155
156  MouseEvent second(ET_MOUSE_MOVED, gfx::Point(12, 12), gfx::Point(12, 12),
157                    EF_NONE, EF_NONE);
158  DispatchEvent(&second);
159  EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
160  EXPECT_FALSE(parent_r->DidReceiveEvent(ET_MOUSE_MOVED));
161  EXPECT_FALSE(child_r->DidReceiveEvent(ET_MOUSE_MOVED));
162  EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_MOUSE_MOVED));
163}
164
165class IgnoreEventTargeter : public EventTargeter {
166 public:
167  IgnoreEventTargeter() {}
168  virtual ~IgnoreEventTargeter() {}
169
170 private:
171  // EventTargeter:
172  virtual bool SubtreeShouldBeExploredForEvent(
173      EventTarget* target, const LocatedEvent& event) OVERRIDE {
174    return false;
175  }
176};
177
178// Verifies that the EventTargeter installed on an EventTarget can dictate
179// whether the target itself can process an event.
180TEST_F(EventProcessorTest, TargeterChecksOwningEventTarget) {
181  scoped_ptr<TestEventTarget> child(new TestEventTarget());
182  root()->AddChild(child.Pass());
183
184  MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
185                   EF_NONE, EF_NONE);
186  DispatchEvent(&mouse);
187  EXPECT_TRUE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED));
188  EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
189  root()->child_at(0)->ResetReceivedEvents();
190
191  // Install an even handler on |child| which always prevents the target from
192  // receiving event.
193  root()->child_at(0)->SetEventTargeter(
194      scoped_ptr<EventTargeter>(new IgnoreEventTargeter()));
195  MouseEvent mouse2(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
196                    EF_NONE, EF_NONE);
197  DispatchEvent(&mouse2);
198  EXPECT_FALSE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED));
199  EXPECT_TRUE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
200}
201
202}  // namespace test
203}  // namespace ui
204