Index: ui/views/view_unittest.cc |
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc |
index dcc7dbf0f09aa9779737e3c2649e21da7a38e0ec..188ce4c37ba51064c9cb00bcbc584c934002da92 100644 |
--- a/ui/views/view_unittest.cc |
+++ b/ui/views/view_unittest.cc |
@@ -203,7 +203,11 @@ typedef ViewsTestBase ViewTest; |
// A derived class for testing purpose. |
class TestView : public View { |
public: |
- TestView() : View(), delete_on_pressed_(false), native_theme_(NULL) {} |
+ TestView() |
+ : View(), |
+ delete_on_pressed_(false), |
+ native_theme_(NULL), |
+ can_process_events_within_subtree_(true) {} |
virtual ~TestView() {} |
// Reset all test state |
@@ -217,6 +221,7 @@ class TestView : public View { |
last_gesture_event_was_handled_ = false; |
last_clip_.setEmpty(); |
accelerator_count_map_.clear(); |
+ can_process_events_within_subtree_ = true; |
} |
// Exposed as public for testing. |
@@ -230,6 +235,14 @@ class TestView : public View { |
bool focusable() const { return View::focusable(); } |
+ void set_can_process_events_within_subtree(bool can_process) { |
+ can_process_events_within_subtree_ = can_process; |
+ } |
+ |
+ virtual bool CanProcessEventsWithinSubtree() const OVERRIDE { |
+ return can_process_events_within_subtree_; |
+ } |
+ |
virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; |
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; |
virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; |
@@ -273,6 +286,9 @@ class TestView : public View { |
// Native theme. |
const ui::NativeTheme* native_theme_; |
+ |
+ // Value to return from CanProcessEventsWithinSubtree(). |
+ bool can_process_events_within_subtree_; |
}; |
// A view subclass that consumes all Gesture events for testing purposes. |
@@ -1212,6 +1228,153 @@ TEST_F(ViewTest, GetEventHandlerForRect) { |
widget->CloseNow(); |
} |
+// Tests that GetEventHandlerForRect() and GetTooltipHandlerForPoint() behave |
+// as expected when different views in the view hierarchy return false |
+// when CanProcessEventsWithinSubtree() is called. |
+TEST_F(ViewTest, CanProcessEventsWithinSubtree) { |
+ Widget* widget = new Widget; |
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
+ widget->Init(params); |
+ View* root_view = widget->GetRootView(); |
+ root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500)); |
+ |
+ // Have this hierarchy of views (the coords here are in the coordinate |
+ // space of the root view): |
+ // v (0, 0, 100, 100) |
+ // - v_child (0, 0, 20, 30) |
+ // - v_grandchild (5, 5, 5, 15) |
+ |
+ TestView* v = new TestView; |
+ v->SetBounds(0, 0, 100, 100); |
+ root_view->AddChildView(v); |
+ v->set_notify_enter_exit_on_child(true); |
+ |
+ TestView* v_child = new TestView; |
+ v_child->SetBounds(0, 0, 20, 30); |
+ v->AddChildView(v_child); |
+ |
+ TestView* v_grandchild = new TestView; |
+ v_grandchild->SetBounds(5, 5, 5, 15); |
+ v_child->AddChildView(v_grandchild); |
+ |
+ v->Reset(); |
+ v_child->Reset(); |
+ v_grandchild->Reset(); |
+ |
+ // Define rects and points within the views in the hierarchy. |
+ gfx::Rect rect_in_v_grandchild(7, 7, 3, 3); |
+ gfx::Point point_in_v_grandchild(rect_in_v_grandchild.origin()); |
+ gfx::Rect rect_in_v_child(12, 3, 5, 5); |
+ gfx::Point point_in_v_child(rect_in_v_child.origin()); |
+ gfx::Rect rect_in_v(50, 50, 25, 30); |
+ gfx::Point point_in_v(rect_in_v.origin()); |
+ |
+ // When all three views return true when CanProcessEventsWithinSubtree() |
+ // is called, targeting should behave as expected. |
+ |
+ View* result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild); |
+ EXPECT_EQ(v_grandchild, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild); |
+ EXPECT_EQ(v_grandchild, result_view); |
+ result_view = NULL; |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_child); |
+ EXPECT_EQ(v_child, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child); |
+ EXPECT_EQ(v_child, result_view); |
+ result_view = NULL; |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ |
+ // When |v_grandchild| returns false when CanProcessEventsWithinSubtree() |
+ // is called, then |v_grandchild| cannot be returned as a target. |
+ |
+ v_grandchild->set_can_process_events_within_subtree(false); |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild); |
+ EXPECT_EQ(v_child, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild); |
+ EXPECT_EQ(v_child, result_view); |
+ result_view = NULL; |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_child); |
+ EXPECT_EQ(v_child, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child); |
+ EXPECT_EQ(v_child, result_view); |
+ result_view = NULL; |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ |
+ // When |v_child| returns false when CanProcessEventsWithinSubtree() |
+ // is called, then neither |v_child| nor |v_grandchild| can be returned |
+ // as a target (|v| should be returned as the target for each case). |
+ |
+ v_grandchild->Reset(); |
+ v_child->set_can_process_events_within_subtree(false); |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_child); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v); |
+ EXPECT_EQ(v, result_view); |
+ result_view = NULL; |
+ |
+ // When |v| returns false when CanProcessEventsWithinSubtree() |
+ // is called, then none of |v|, |v_child|, and |v_grandchild| can be returned |
+ // as a target (|root_view| should be returned as the target for each case). |
+ |
+ v_child->Reset(); |
+ v->set_can_process_events_within_subtree(false); |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild); |
+ EXPECT_EQ(root_view, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild); |
+ EXPECT_EQ(root_view, result_view); |
+ result_view = NULL; |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v_child); |
+ EXPECT_EQ(root_view, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child); |
+ EXPECT_EQ(root_view, result_view); |
+ result_view = NULL; |
+ |
+ result_view = root_view->GetEventHandlerForRect(rect_in_v); |
+ EXPECT_EQ(root_view, result_view); |
+ result_view = NULL; |
+ result_view = root_view->GetTooltipHandlerForPoint(point_in_v); |
+ EXPECT_EQ(root_view, result_view); |
+} |
+ |
TEST_F(ViewTest, NotifyEnterExitOnChild) { |
Widget* widget = new Widget; |
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |