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" |
9 #include "ui/views/test/views_test_base.h" | 11 #include "ui/views/test/views_test_base.h" |
10 #include "ui/views/widget/root_view.h" | 12 #include "ui/views/widget/root_view.h" |
11 | 13 |
12 namespace views { | 14 namespace views { |
| 15 |
| 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(View* view, gfx::Path* mask) const OVERRIDE { |
| 25 SkScalar w = SkIntToScalar(view->width()); |
| 26 SkScalar h = SkIntToScalar(view->height()); |
| 27 |
| 28 // Create a triangular mask within the bounds of |view|. |
| 29 mask->moveTo(w / 2, 0); |
| 30 mask->lineTo(w, h); |
| 31 mask->lineTo(0, h); |
| 32 mask->close(); |
| 33 |
| 34 return true; |
| 35 } |
| 36 |
| 37 DISALLOW_COPY_AND_ASSIGN(TestMaskedViewTargeter); |
| 38 }; |
| 39 |
13 namespace test { | 40 namespace test { |
14 | 41 |
15 typedef ViewsTestBase ViewTargeterTest; | 42 typedef ViewsTestBase ViewTargeterTest; |
16 | 43 |
17 // Verifies that the the functions ViewTargeter::FindTargetForEvent() | 44 // Verifies that the the functions ViewTargeter::FindTargetForEvent() |
18 // and ViewTargeter::FindNextBestTarget() are implemented correctly | 45 // and ViewTargeter::FindNextBestTarget() are implemented correctly |
19 // for key events. | 46 // for key events. |
20 TEST_F(ViewTargeterTest, ViewTargeterForKeyEvents) { | 47 TEST_F(ViewTargeterTest, ViewTargeterForKeyEvents) { |
21 Widget widget; | 48 Widget widget; |
22 Widget::InitParams init_params = | 49 Widget::InitParams init_params = |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 event.set_location(gfx::Point(400, 400)); | 210 event.set_location(gfx::Point(400, 400)); |
184 EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v1, event)); | 211 EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v1, event)); |
185 EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v2, event)); | 212 EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v2, event)); |
186 v1.ConvertEventToTarget(&v2, &event); | 213 v1.ConvertEventToTarget(&v2, &event); |
187 EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v3, event)); | 214 EXPECT_FALSE(targeter->SubtreeShouldBeExploredForEvent(&v3, event)); |
188 | 215 |
189 // TODO(tdanderson): Move the hit-testing unit tests out of view_unittest | 216 // TODO(tdanderson): Move the hit-testing unit tests out of view_unittest |
190 // and into here. See crbug.com/355425. | 217 // and into here. See crbug.com/355425. |
191 } | 218 } |
192 | 219 |
| 220 // Tests that FindTargetForEvent() returns the correct target when some |
| 221 // views in the view tree have a MaskedViewTargeter installed, i.e., |
| 222 // they have a custom-shaped hit test mask. |
| 223 TEST_F(ViewTargeterTest, MaskedViewTargeter) { |
| 224 Widget widget; |
| 225 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
| 226 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 227 params.bounds = gfx::Rect(0, 0, 650, 650); |
| 228 widget.Init(params); |
| 229 |
| 230 ui::EventTargeter* targeter = new ViewTargeter(); |
| 231 internal::RootView* root_view = |
| 232 static_cast<internal::RootView*>(widget.GetRootView()); |
| 233 root_view->SetEventTargeter(make_scoped_ptr(targeter)); |
| 234 |
| 235 // The coordinates used for SetBounds() are in the parent coordinate space. |
| 236 View masked_view, unmasked_view, masked_child; |
| 237 masked_view.SetBounds(0, 0, 200, 200); |
| 238 unmasked_view.SetBounds(300, 0, 300, 300); |
| 239 masked_child.SetBounds(0, 0, 100, 100); |
| 240 root_view->AddChildView(&masked_view); |
| 241 root_view->AddChildView(&unmasked_view); |
| 242 unmasked_view.AddChildView(&masked_child); |
| 243 |
| 244 // Install event targeters of type TestMaskedViewTargeter on the two masked |
| 245 // views to define their hit test masks. |
| 246 ui::EventTargeter* masked_targeter = new TestMaskedViewTargeter(&masked_view); |
| 247 masked_view.SetEventTargeter(make_scoped_ptr(masked_targeter)); |
| 248 masked_targeter = new TestMaskedViewTargeter(&masked_child); |
| 249 masked_child.SetEventTargeter(make_scoped_ptr(masked_targeter)); |
| 250 |
| 251 // Note that the coordinates used below are in the coordinate space of |
| 252 // the root view. |
| 253 |
| 254 // Event located within the hit test mask of |masked_view|. |
| 255 ui::ScrollEvent scroll(ui::ET_SCROLL, |
| 256 gfx::Point(100, 190), |
| 257 ui::EventTimeForNow(), |
| 258 0, |
| 259 0, |
| 260 3, |
| 261 0, |
| 262 3, |
| 263 2); |
| 264 ui::EventTarget* current_target = |
| 265 targeter->FindTargetForEvent(root_view, &scroll); |
| 266 EXPECT_EQ(&masked_view, static_cast<View*>(current_target)); |
| 267 |
| 268 // Event located outside the hit test mask of |masked_view|. |
| 269 scroll.set_location(gfx::Point(10, 10)); |
| 270 current_target = targeter->FindTargetForEvent(root_view, &scroll); |
| 271 EXPECT_EQ(root_view, static_cast<View*>(current_target)); |
| 272 |
| 273 // Event located within the hit test mask of |masked_child|. |
| 274 scroll.set_location(gfx::Point(350, 3)); |
| 275 current_target = targeter->FindTargetForEvent(root_view, &scroll); |
| 276 EXPECT_EQ(&masked_child, static_cast<View*>(current_target)); |
| 277 |
| 278 // Event located within the hit test mask of |masked_child|. |
| 279 scroll.set_location(gfx::Point(300, 12)); |
| 280 current_target = targeter->FindTargetForEvent(root_view, &scroll); |
| 281 EXPECT_EQ(&unmasked_view, static_cast<View*>(current_target)); |
| 282 |
| 283 // TODO(tdanderson): We should also test that targeting of masked views |
| 284 // works correctly with gestures. See crbug.com/375822. |
| 285 } |
| 286 |
193 } // namespace test | 287 } // namespace test |
194 } // namespace views | 288 } // namespace views |
OLD | NEW |