| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/view_targeter.h" | 5 #include "ui/views/view_targeter.h" |
| 6 | 6 |
| 7 #include "ui/events/event_targeter.h" | 7 #include "ui/events/event_targeter.h" |
| 8 #include "ui/events/event_utils.h" | 8 #include "ui/events/event_utils.h" |
| 9 #include "ui/gfx/path.h" | |
| 10 #include "ui/views/masked_view_targeter.h" | |
| 11 #include "ui/views/test/views_test_base.h" | 9 #include "ui/views/test/views_test_base.h" |
| 12 #include "ui/views/widget/root_view.h" | 10 #include "ui/views/widget/root_view.h" |
| 13 | 11 |
| 14 namespace views { | 12 namespace views { |
| 15 | 13 |
| 16 // A class used to define a triangular-shaped hit test mask on a View. | |
| 17 class TestMaskedViewTargeter : public MaskedViewTargeter { | |
| 18 public: | |
| 19 explicit TestMaskedViewTargeter(View* masked_view) | |
| 20 : MaskedViewTargeter(masked_view) {} | |
| 21 virtual ~TestMaskedViewTargeter() {} | |
| 22 | |
| 23 private: | |
| 24 virtual bool GetHitTestMask(const View* view, | |
| 25 gfx::Path* mask) const OVERRIDE { | |
| 26 SkScalar w = SkIntToScalar(view->width()); | |
| 27 SkScalar h = SkIntToScalar(view->height()); | |
| 28 | |
| 29 // Create a triangular mask within the bounds of |view|. | |
| 30 mask->moveTo(w / 2, 0); | |
| 31 mask->lineTo(w, h); | |
| 32 mask->lineTo(0, h); | |
| 33 mask->close(); | |
| 34 | |
| 35 return true; | |
| 36 } | |
| 37 | |
| 38 DISALLOW_COPY_AND_ASSIGN(TestMaskedViewTargeter); | |
| 39 }; | |
| 40 | |
| 41 // A derived class of View used for testing purposes. | 14 // A derived class of View used for testing purposes. |
| 42 class TestingView : public View { | 15 class TestingView : public View { |
| 43 public: | 16 public: |
| 44 TestingView() : can_process_events_within_subtree_(true) {} | 17 TestingView() : can_process_events_within_subtree_(true) {} |
| 45 virtual ~TestingView() {} | 18 virtual ~TestingView() {} |
| 46 | 19 |
| 47 // Reset all test state. | 20 // Reset all test state. |
| 48 void Reset() { can_process_events_within_subtree_ = true; } | 21 void Reset() { can_process_events_within_subtree_ = true; } |
| 49 | 22 |
| 50 void set_can_process_events_within_subtree(bool can_process) { | 23 void set_can_process_events_within_subtree(bool can_process) { |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 scroll.set_location(scroll_point); | 281 scroll.set_location(scroll_point); |
| 309 v2.Reset(); | 282 v2.Reset(); |
| 310 v1.set_can_process_events_within_subtree(false); | 283 v1.set_can_process_events_within_subtree(false); |
| 311 current_target = targeter->FindTargetForEvent(root_view, &scroll); | 284 current_target = targeter->FindTargetForEvent(root_view, &scroll); |
| 312 EXPECT_EQ(root_view, current_target); | 285 EXPECT_EQ(root_view, current_target); |
| 313 | 286 |
| 314 // TODO(tdanderson): We should also test that targeting works correctly | 287 // TODO(tdanderson): We should also test that targeting works correctly |
| 315 // with gestures. See crbug.com/375822. | 288 // with gestures. See crbug.com/375822. |
| 316 } | 289 } |
| 317 | 290 |
| 318 // Tests that FindTargetForEvent() returns the correct target when some | |
| 319 // views in the view tree have a MaskedViewTargeter installed, i.e., | |
| 320 // they have a custom-shaped hit test mask. | |
| 321 TEST_F(ViewTargeterTest, MaskedViewTargeter) { | |
| 322 Widget widget; | |
| 323 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | |
| 324 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 325 params.bounds = gfx::Rect(0, 0, 650, 650); | |
| 326 widget.Init(params); | |
| 327 | |
| 328 ui::EventTargeter* targeter = new ViewTargeter(); | |
| 329 internal::RootView* root_view = | |
| 330 static_cast<internal::RootView*>(widget.GetRootView()); | |
| 331 root_view->SetEventTargeter(make_scoped_ptr(targeter)); | |
| 332 | |
| 333 // The coordinates used for SetBounds() are in the parent coordinate space. | |
| 334 View masked_view, unmasked_view, masked_child; | |
| 335 masked_view.SetBounds(0, 0, 200, 200); | |
| 336 unmasked_view.SetBounds(300, 0, 300, 300); | |
| 337 masked_child.SetBounds(0, 0, 100, 100); | |
| 338 root_view->AddChildView(&masked_view); | |
| 339 root_view->AddChildView(&unmasked_view); | |
| 340 unmasked_view.AddChildView(&masked_child); | |
| 341 | |
| 342 // Install event targeters of type TestMaskedViewTargeter on the two masked | |
| 343 // views to define their hit test masks. | |
| 344 ui::EventTargeter* masked_targeter = new TestMaskedViewTargeter(&masked_view); | |
| 345 masked_view.SetEventTargeter(make_scoped_ptr(masked_targeter)); | |
| 346 masked_targeter = new TestMaskedViewTargeter(&masked_child); | |
| 347 masked_child.SetEventTargeter(make_scoped_ptr(masked_targeter)); | |
| 348 | |
| 349 // Note that the coordinates used below are in the coordinate space of | |
| 350 // the root view. | |
| 351 | |
| 352 // Event located within the hit test mask of |masked_view|. | |
| 353 ui::ScrollEvent scroll(ui::ET_SCROLL, | |
| 354 gfx::Point(100, 190), | |
| 355 ui::EventTimeForNow(), | |
| 356 0, | |
| 357 0, | |
| 358 3, | |
| 359 0, | |
| 360 3, | |
| 361 2); | |
| 362 ui::EventTarget* current_target = | |
| 363 targeter->FindTargetForEvent(root_view, &scroll); | |
| 364 EXPECT_EQ(&masked_view, static_cast<View*>(current_target)); | |
| 365 | |
| 366 // Event located outside the hit test mask of |masked_view|. | |
| 367 scroll.set_location(gfx::Point(10, 10)); | |
| 368 current_target = targeter->FindTargetForEvent(root_view, &scroll); | |
| 369 EXPECT_EQ(root_view, static_cast<View*>(current_target)); | |
| 370 | |
| 371 // Event located within the hit test mask of |masked_child|. | |
| 372 scroll.set_location(gfx::Point(350, 3)); | |
| 373 current_target = targeter->FindTargetForEvent(root_view, &scroll); | |
| 374 EXPECT_EQ(&masked_child, static_cast<View*>(current_target)); | |
| 375 | |
| 376 // Event located within the hit test mask of |masked_child|. | |
| 377 scroll.set_location(gfx::Point(300, 12)); | |
| 378 current_target = targeter->FindTargetForEvent(root_view, &scroll); | |
| 379 EXPECT_EQ(&unmasked_view, static_cast<View*>(current_target)); | |
| 380 | |
| 381 // TODO(tdanderson): We should also test that targeting of masked views | |
| 382 // works correctly with gestures. See crbug.com/375822. | |
| 383 } | |
| 384 | |
| 385 } // namespace test | 291 } // namespace test |
| 386 } // namespace views | 292 } // namespace views |
| OLD | NEW |