event_processor_unittest.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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 <vector> 6 7#include "testing/gtest/include/gtest/gtest.h" 8#include "ui/events/event.h" 9#include "ui/events/event_targeter.h" 10#include "ui/events/test/events_test_utils.h" 11#include "ui/events/test/test_event_handler.h" 12#include "ui/events/test/test_event_processor.h" 13#include "ui/events/test/test_event_target.h" 14 15typedef std::vector<std::string> HandlerSequenceRecorder; 16 17namespace ui { 18namespace test { 19 20class EventProcessorTest : public testing::Test { 21 public: 22 EventProcessorTest() {} 23 virtual ~EventProcessorTest() {} 24 25 // testing::Test: 26 virtual void SetUp() OVERRIDE { 27 processor_.SetRoot(scoped_ptr<EventTarget>(new TestEventTarget())); 28 root()->SetEventTargeter(make_scoped_ptr(new EventTargeter())); 29 } 30 31 TestEventTarget* root() { 32 return static_cast<TestEventTarget*>(processor_.GetRootTarget()); 33 } 34 35 void DispatchEvent(Event* event) { 36 processor_.OnEventFromSource(event); 37 } 38 39 protected: 40 TestEventProcessor processor_; 41 42 DISALLOW_COPY_AND_ASSIGN(EventProcessorTest); 43}; 44 45TEST_F(EventProcessorTest, Basic) { 46 scoped_ptr<TestEventTarget> child(new TestEventTarget()); 47 root()->AddChild(child.Pass()); 48 49 MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10), 50 EF_NONE, EF_NONE); 51 DispatchEvent(&mouse); 52 EXPECT_TRUE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED)); 53 EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 54 55 root()->RemoveChild(root()->child_at(0)); 56 DispatchEvent(&mouse); 57 EXPECT_TRUE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 58} 59 60template<typename T> 61class BoundsEventTargeter : public EventTargeter { 62 public: 63 virtual ~BoundsEventTargeter() {} 64 65 protected: 66 virtual bool SubtreeShouldBeExploredForEvent( 67 EventTarget* target, const LocatedEvent& event) OVERRIDE { 68 T* t = static_cast<T*>(target); 69 return (t->bounds().Contains(event.location())); 70 } 71}; 72 73class BoundsTestTarget : public TestEventTarget { 74 public: 75 BoundsTestTarget() {} 76 virtual ~BoundsTestTarget() {} 77 78 void set_bounds(gfx::Rect rect) { bounds_ = rect; } 79 gfx::Rect bounds() const { return bounds_; } 80 81 static void ConvertPointToTarget(BoundsTestTarget* source, 82 BoundsTestTarget* target, 83 gfx::Point* location) { 84 gfx::Vector2d vector; 85 if (source->Contains(target)) { 86 for (; target && target != source; 87 target = static_cast<BoundsTestTarget*>(target->parent())) { 88 vector += target->bounds().OffsetFromOrigin(); 89 } 90 *location -= vector; 91 } else if (target->Contains(source)) { 92 for (; source && source != target; 93 source = static_cast<BoundsTestTarget*>(source->parent())) { 94 vector += source->bounds().OffsetFromOrigin(); 95 } 96 *location += vector; 97 } else { 98 NOTREACHED(); 99 } 100 } 101 102 private: 103 // EventTarget: 104 virtual void ConvertEventToTarget(EventTarget* target, 105 LocatedEvent* event) OVERRIDE { 106 event->ConvertLocationToTarget(this, 107 static_cast<BoundsTestTarget*>(target)); 108 } 109 110 gfx::Rect bounds_; 111 112 DISALLOW_COPY_AND_ASSIGN(BoundsTestTarget); 113}; 114 115TEST_F(EventProcessorTest, Bounds) { 116 scoped_ptr<BoundsTestTarget> parent(new BoundsTestTarget()); 117 scoped_ptr<BoundsTestTarget> child(new BoundsTestTarget()); 118 scoped_ptr<BoundsTestTarget> grandchild(new BoundsTestTarget()); 119 120 parent->set_bounds(gfx::Rect(0, 0, 30, 30)); 121 child->set_bounds(gfx::Rect(5, 5, 20, 20)); 122 grandchild->set_bounds(gfx::Rect(5, 5, 5, 5)); 123 124 child->AddChild(scoped_ptr<TestEventTarget>(grandchild.Pass())); 125 parent->AddChild(scoped_ptr<TestEventTarget>(child.Pass())); 126 root()->AddChild(scoped_ptr<TestEventTarget>(parent.Pass())); 127 128 ASSERT_EQ(1u, root()->child_count()); 129 ASSERT_EQ(1u, root()->child_at(0)->child_count()); 130 ASSERT_EQ(1u, root()->child_at(0)->child_at(0)->child_count()); 131 132 TestEventTarget* parent_r = root()->child_at(0); 133 TestEventTarget* child_r = parent_r->child_at(0); 134 TestEventTarget* grandchild_r = child_r->child_at(0); 135 136 // Dispatch a mouse event that falls on the parent, but not on the child. When 137 // the default event-targeter used, the event will still reach |grandchild|, 138 // because the default targeter does not look at the bounds. 139 MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(1, 1), gfx::Point(1, 1), EF_NONE, 140 EF_NONE); 141 DispatchEvent(&mouse); 142 EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 143 EXPECT_FALSE(parent_r->DidReceiveEvent(ET_MOUSE_MOVED)); 144 EXPECT_FALSE(child_r->DidReceiveEvent(ET_MOUSE_MOVED)); 145 EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_MOUSE_MOVED)); 146 grandchild_r->ResetReceivedEvents(); 147 148 // Now install a targeter on the parent that looks at the bounds and makes 149 // sure the event reaches the target only if the location of the event within 150 // the bounds of the target. 151 MouseEvent mouse2(ET_MOUSE_MOVED, gfx::Point(1, 1), gfx::Point(1, 1), EF_NONE, 152 EF_NONE); 153 parent_r->SetEventTargeter(scoped_ptr<EventTargeter>( 154 new BoundsEventTargeter<BoundsTestTarget>())); 155 DispatchEvent(&mouse2); 156 EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 157 EXPECT_TRUE(parent_r->DidReceiveEvent(ET_MOUSE_MOVED)); 158 EXPECT_FALSE(child_r->DidReceiveEvent(ET_MOUSE_MOVED)); 159 EXPECT_FALSE(grandchild_r->DidReceiveEvent(ET_MOUSE_MOVED)); 160 parent_r->ResetReceivedEvents(); 161 162 MouseEvent second(ET_MOUSE_MOVED, gfx::Point(12, 12), gfx::Point(12, 12), 163 EF_NONE, EF_NONE); 164 DispatchEvent(&second); 165 EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 166 EXPECT_FALSE(parent_r->DidReceiveEvent(ET_MOUSE_MOVED)); 167 EXPECT_FALSE(child_r->DidReceiveEvent(ET_MOUSE_MOVED)); 168 EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_MOUSE_MOVED)); 169} 170 171class IgnoreEventTargeter : public EventTargeter { 172 public: 173 IgnoreEventTargeter() {} 174 virtual ~IgnoreEventTargeter() {} 175 176 private: 177 // EventTargeter: 178 virtual bool SubtreeShouldBeExploredForEvent( 179 EventTarget* target, const LocatedEvent& event) OVERRIDE { 180 return false; 181 } 182}; 183 184// Verifies that the EventTargeter installed on an EventTarget can dictate 185// whether the target itself can process an event. 186TEST_F(EventProcessorTest, TargeterChecksOwningEventTarget) { 187 scoped_ptr<TestEventTarget> child(new TestEventTarget()); 188 root()->AddChild(child.Pass()); 189 190 MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10), 191 EF_NONE, EF_NONE); 192 DispatchEvent(&mouse); 193 EXPECT_TRUE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED)); 194 EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 195 root()->child_at(0)->ResetReceivedEvents(); 196 197 // Install an event handler on |child| which always prevents the target from 198 // receiving event. 199 root()->child_at(0)->SetEventTargeter( 200 scoped_ptr<EventTargeter>(new IgnoreEventTargeter())); 201 MouseEvent mouse2(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10), 202 EF_NONE, EF_NONE); 203 DispatchEvent(&mouse2); 204 EXPECT_FALSE(root()->child_at(0)->DidReceiveEvent(ET_MOUSE_MOVED)); 205 EXPECT_TRUE(root()->DidReceiveEvent(ET_MOUSE_MOVED)); 206} 207 208// An EventTargeter which is used to allow a bubbling behaviour in event 209// dispatch: if an event is not handled after being dispatched to its 210// initial target, the event is dispatched to the next-best target as 211// specified by FindNextBestTarget(). 212class BubblingEventTargeter : public EventTargeter { 213 public: 214 explicit BubblingEventTargeter(TestEventTarget* initial_target) 215 : initial_target_(initial_target) {} 216 virtual ~BubblingEventTargeter() {} 217 218 private: 219 // EventTargeter: 220 virtual EventTarget* FindTargetForEvent(EventTarget* root, 221 Event* event) OVERRIDE { 222 return initial_target_; 223 } 224 225 virtual EventTarget* FindNextBestTarget(EventTarget* previous_target, 226 Event* event) OVERRIDE { 227 return previous_target->GetParentTarget(); 228 } 229 230 TestEventTarget* initial_target_; 231 232 DISALLOW_COPY_AND_ASSIGN(BubblingEventTargeter); 233}; 234 235// Tests that unhandled events are correctly dispatched to the next-best 236// target as decided by the BubblingEventTargeter. 237TEST_F(EventProcessorTest, DispatchToNextBestTarget) { 238 scoped_ptr<TestEventTarget> child(new TestEventTarget()); 239 scoped_ptr<TestEventTarget> grandchild(new TestEventTarget()); 240 241 root()->SetEventTargeter( 242 scoped_ptr<EventTargeter>(new BubblingEventTargeter(grandchild.get()))); 243 child->AddChild(grandchild.Pass()); 244 root()->AddChild(child.Pass()); 245 246 ASSERT_EQ(1u, root()->child_count()); 247 ASSERT_EQ(1u, root()->child_at(0)->child_count()); 248 ASSERT_EQ(0u, root()->child_at(0)->child_at(0)->child_count()); 249 250 TestEventTarget* child_r = root()->child_at(0); 251 TestEventTarget* grandchild_r = child_r->child_at(0); 252 253 // When the root has a BubblingEventTargeter installed, events targeted 254 // at the grandchild target should be dispatched to all three targets. 255 KeyEvent key_event(ET_KEY_PRESSED, VKEY_ESCAPE, 0, false); 256 DispatchEvent(&key_event); 257 EXPECT_TRUE(root()->DidReceiveEvent(ET_KEY_PRESSED)); 258 EXPECT_TRUE(child_r->DidReceiveEvent(ET_KEY_PRESSED)); 259 EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED)); 260 root()->ResetReceivedEvents(); 261 child_r->ResetReceivedEvents(); 262 grandchild_r->ResetReceivedEvents(); 263 264 // Add a pre-target handler on the child of the root that will mark the event 265 // as handled. No targets in the hierarchy should receive the event. 266 TestEventHandler handler; 267 child_r->AddPreTargetHandler(&handler); 268 key_event = KeyEvent(ET_KEY_PRESSED, VKEY_ESCAPE, 0, false); 269 DispatchEvent(&key_event); 270 EXPECT_FALSE(root()->DidReceiveEvent(ET_KEY_PRESSED)); 271 EXPECT_FALSE(child_r->DidReceiveEvent(ET_KEY_PRESSED)); 272 EXPECT_FALSE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED)); 273 EXPECT_EQ(1, handler.num_key_events()); 274 handler.Reset(); 275 276 // Add a post-target handler on the child of the root that will mark the event 277 // as handled. Only the grandchild (the initial target) should receive the 278 // event. 279 child_r->RemovePreTargetHandler(&handler); 280 child_r->AddPostTargetHandler(&handler); 281 key_event = KeyEvent(ET_KEY_PRESSED, VKEY_ESCAPE, 0, false); 282 DispatchEvent(&key_event); 283 EXPECT_FALSE(root()->DidReceiveEvent(ET_KEY_PRESSED)); 284 EXPECT_FALSE(child_r->DidReceiveEvent(ET_KEY_PRESSED)); 285 EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED)); 286 EXPECT_EQ(1, handler.num_key_events()); 287 handler.Reset(); 288 grandchild_r->ResetReceivedEvents(); 289 child_r->RemovePostTargetHandler(&handler); 290 291 // Mark the event as handled when it reaches the EP_TARGET phase of 292 // dispatch at the child of the root. The child and grandchild 293 // targets should both receive the event, but the root should not. 294 child_r->set_mark_events_as_handled(true); 295 key_event = KeyEvent(ET_KEY_PRESSED, VKEY_ESCAPE, 0, false); 296 DispatchEvent(&key_event); 297 EXPECT_FALSE(root()->DidReceiveEvent(ET_KEY_PRESSED)); 298 EXPECT_TRUE(child_r->DidReceiveEvent(ET_KEY_PRESSED)); 299 EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED)); 300 root()->ResetReceivedEvents(); 301 child_r->ResetReceivedEvents(); 302 grandchild_r->ResetReceivedEvents(); 303 child_r->set_mark_events_as_handled(false); 304} 305 306// Tests that unhandled events are seen by the correct sequence of 307// targets, pre-target handlers, and post-target handlers when 308// a BubblingEventTargeter is installed on the root target. 309TEST_F(EventProcessorTest, HandlerSequence) { 310 scoped_ptr<TestEventTarget> child(new TestEventTarget()); 311 scoped_ptr<TestEventTarget> grandchild(new TestEventTarget()); 312 313 root()->SetEventTargeter( 314 scoped_ptr<EventTargeter>(new BubblingEventTargeter(grandchild.get()))); 315 child->AddChild(grandchild.Pass()); 316 root()->AddChild(child.Pass()); 317 318 ASSERT_EQ(1u, root()->child_count()); 319 ASSERT_EQ(1u, root()->child_at(0)->child_count()); 320 ASSERT_EQ(0u, root()->child_at(0)->child_at(0)->child_count()); 321 322 TestEventTarget* child_r = root()->child_at(0); 323 TestEventTarget* grandchild_r = child_r->child_at(0); 324 325 HandlerSequenceRecorder recorder; 326 root()->set_target_name("R"); 327 root()->set_recorder(&recorder); 328 child_r->set_target_name("C"); 329 child_r->set_recorder(&recorder); 330 grandchild_r->set_target_name("G"); 331 grandchild_r->set_recorder(&recorder); 332 333 TestEventHandler pre_root; 334 pre_root.set_handler_name("PreR"); 335 pre_root.set_recorder(&recorder); 336 root()->AddPreTargetHandler(&pre_root); 337 338 TestEventHandler pre_child; 339 pre_child.set_handler_name("PreC"); 340 pre_child.set_recorder(&recorder); 341 child_r->AddPreTargetHandler(&pre_child); 342 343 TestEventHandler pre_grandchild; 344 pre_grandchild.set_handler_name("PreG"); 345 pre_grandchild.set_recorder(&recorder); 346 grandchild_r->AddPreTargetHandler(&pre_grandchild); 347 348 TestEventHandler post_root; 349 post_root.set_handler_name("PostR"); 350 post_root.set_recorder(&recorder); 351 root()->AddPostTargetHandler(&post_root); 352 353 TestEventHandler post_child; 354 post_child.set_handler_name("PostC"); 355 post_child.set_recorder(&recorder); 356 child_r->AddPostTargetHandler(&post_child); 357 358 TestEventHandler post_grandchild; 359 post_grandchild.set_handler_name("PostG"); 360 post_grandchild.set_recorder(&recorder); 361 grandchild_r->AddPostTargetHandler(&post_grandchild); 362 363 MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10), 364 EF_NONE, EF_NONE); 365 DispatchEvent(&mouse); 366 367 std::string expected[] = { "PreR", "PreC", "PreG", "G", "PostG", "PostC", 368 "PostR", "PreR", "PreC", "C", "PostC", "PostR", "PreR", "R", "PostR" }; 369 EXPECT_EQ(std::vector<std::string>( 370 expected, expected + arraysize(expected)), recorder); 371} 372 373} // namespace test 374} // namespace ui 375