1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file. 4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/views/view_targeter.h" 6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/events/event_targeter.h" 8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/events/event_utils.h" 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/path.h" 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/views/masked_targeter_delegate.h" 11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/views/test/views_test_base.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/views/view_targeter.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/views/view_targeter_delegate.h" 14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "ui/views/widget/root_view.h" 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace views { 17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// A derived class of View used for testing purposes. 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass TestingView : public View, public ViewTargeterDelegate { 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public: 2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) TestingView() : can_process_events_within_subtree_(true) {} 2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual ~TestingView() {} 2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Reset all test state. 2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void Reset() { can_process_events_within_subtree_ = true; } 2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void set_can_process_events_within_subtree(bool can_process) { 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) can_process_events_within_subtree_ = can_process; 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // A call-through function to ViewTargeterDelegate::DoesIntersectRect(). 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool TestDoesIntersectRect(const View* target, const gfx::Rect& rect) const { 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return DoesIntersectRect(target, rect); 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // View: 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual bool CanProcessEventsWithinSubtree() const OVERRIDE { 3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return can_process_events_within_subtree_; 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private: 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Value to return from CanProcessEventsWithinSubtree(). 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool can_process_events_within_subtree_; 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(TestingView); 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// A derived class of View having a triangular-shaped hit test mask. 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass TestMaskedView : public View, public MaskedTargeterDelegate { 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public: 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TestMaskedView() {} 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual ~TestMaskedView() {} 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // A call-through function to MaskedTargeterDelegate::DoesIntersectRect(). 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool TestDoesIntersectRect(const View* target, const gfx::Rect& rect) const { 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return DoesIntersectRect(target, rect); 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private: 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // MaskedTargeterDelegate: 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual bool GetHitTestMask(gfx::Path* mask) const OVERRIDE { 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(mask); 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SkScalar w = SkIntToScalar(width()); 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SkScalar h = SkIntToScalar(height()); 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Create a triangular mask within the bounds of this View. 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mask->moveTo(w / 2, 0); 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mask->lineTo(w, h); 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mask->lineTo(0, h); 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch mask->close(); 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DISALLOW_COPY_AND_ASSIGN(TestMaskedView); 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace test { 78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// TODO(tdanderson): Clean up this test suite by moving common code/state into 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// ViewTargeterTest and overriding SetUp(), TearDown(), etc. 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// See crbug.com/355680. 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ViewTargeterTest : public ViewsTestBase { 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ViewTargeterTest() {} 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual ~ViewTargeterTest() {} 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void SetGestureHandler(internal::RootView* root_view, View* handler) { 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci root_view->gesture_handler_ = handler; 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void SetGestureHandlerSetBeforeProcessing(internal::RootView* root_view, 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool set) { 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci root_view->gesture_handler_set_before_processing_ = set; 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DISALLOW_COPY_AND_ASSIGN(ViewTargeterTest); 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 99010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Point ConvertPointFromWidgetToView(View* view, const gfx::Point& p) { 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Point tmp(p); 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch View::ConvertPointToTarget(view->GetWidget()->GetRootView(), view, &tmp); 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return tmp; 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccigfx::Rect ConvertRectFromWidgetToView(View* view, const gfx::Rect& r) { 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect tmp(r); 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tmp.set_origin(ConvertPointFromWidgetToView(view, r.origin())); 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return tmp; 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Verifies that the the functions ViewTargeter::FindTargetForEvent() 117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// and ViewTargeter::FindNextBestTarget() are implemented correctly 118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// for key events. 119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(ViewTargeterTest, ViewTargeterForKeyEvents) { 120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Widget widget; 121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Widget::InitParams init_params = 122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateParams(Widget::InitParams::TYPE_POPUP); 123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) widget.Init(init_params); 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) View* content = new View; 127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) View* child = new View; 128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) View* grandchild = new View; 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) widget.SetContentsView(content); 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) content->AddChildView(child); 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) child->AddChildView(grandchild); 133010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) grandchild->SetFocusable(true); 135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) grandchild->RequestFocus(); 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) internal::RootView* root_view = 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static_cast<internal::RootView*>(widget.GetRootView()); 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::EventTargeter* targeter = root_view->targeter(); 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ui::KeyEvent key_event('a', ui::VKEY_A, ui::EF_NONE); 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The focused view should be the initial target of the event. 144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui::EventTarget* current_target = targeter->FindTargetForEvent(root_view, 145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) &key_event); 146010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(grandchild, static_cast<View*>(current_target)); 147010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Verify that FindNextBestTarget() will return the parent view of the 149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // argument (and NULL if the argument has no parent view). 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_target = targeter->FindNextBestTarget(grandchild, &key_event); 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(child, static_cast<View*>(current_target)); 152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_target = targeter->FindNextBestTarget(child, &key_event); 153010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(content, static_cast<View*>(current_target)); 154010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_target = targeter->FindNextBestTarget(content, &key_event); 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(widget.GetRootView(), static_cast<View*>(current_target)); 156010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_target = targeter->FindNextBestTarget(widget.GetRootView(), 157010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) &key_event); 158010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(NULL, static_cast<View*>(current_target)); 159010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Verifies that the the functions ViewTargeter::FindTargetForEvent() 162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// and ViewTargeter::FindNextBestTarget() are implemented correctly 163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// for scroll events. 164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)TEST_F(ViewTargeterTest, ViewTargeterForScrollEvents) { 165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Widget widget; 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Widget::InitParams init_params = 167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CreateParams(Widget::InitParams::TYPE_POPUP); 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) init_params.bounds = gfx::Rect(0, 0, 200, 200); 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) widget.Init(init_params); 171010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The coordinates used for SetBounds() are in the parent coordinate space. 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) View* content = new View; 174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) content->SetBounds(0, 0, 100, 100); 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) View* child = new View; 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) child->SetBounds(50, 50, 20, 20); 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) View* grandchild = new View; 178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) grandchild->SetBounds(0, 0, 5, 5); 179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) widget.SetContentsView(content); 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) content->AddChildView(child); 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) child->AddChildView(grandchild); 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) internal::RootView* root_view = 185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static_cast<internal::RootView*>(widget.GetRootView()); 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::EventTargeter* targeter = root_view->targeter(); 187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The event falls within the bounds of |child| and |content| but not 189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // |grandchild|, so |child| should be the initial target for the event. 190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui::ScrollEvent scroll(ui::ET_SCROLL, 191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) gfx::Point(60, 60), 192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui::EventTimeForNow(), 193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, 194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, 3, 195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, 3, 196010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2); 197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui::EventTarget* current_target = targeter->FindTargetForEvent(root_view, 198010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) &scroll); 199010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(child, static_cast<View*>(current_target)); 200010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 201010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Verify that FindNextBestTarget() will return the parent view of the 202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // argument (and NULL if the argument has no parent view). 203010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_target = targeter->FindNextBestTarget(child, &scroll); 204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(content, static_cast<View*>(current_target)); 205010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_target = targeter->FindNextBestTarget(content, &scroll); 206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(widget.GetRootView(), static_cast<View*>(current_target)); 207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_target = targeter->FindNextBestTarget(widget.GetRootView(), 208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) &scroll); 209010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(NULL, static_cast<View*>(current_target)); 210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // The event falls outside of the original specified bounds of |content|, 212010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // |child|, and |grandchild|. But since |content| is the contents view, 213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // and contents views are resized to fill the entire area of the root 214010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // view, the event's initial target should still be |content|. 215010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scroll = ui::ScrollEvent(ui::ET_SCROLL, 216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) gfx::Point(150, 150), 217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ui::EventTimeForNow(), 218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, 219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, 3, 220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 0, 3, 221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2); 222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) current_target = targeter->FindTargetForEvent(root_view, &scroll); 223010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) EXPECT_EQ(content, static_cast<View*>(current_target)); 224010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 225010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Convenience to make constructing a GestureEvent simpler. 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass GestureEventForTest : public ui::GestureEvent { 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GestureEventForTest(ui::EventType type, int x, int y) 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : GestureEvent(x, 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci y, 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::TimeDelta(), 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::GestureEventDetails(type)) {} 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GestureEventForTest(ui::GestureEventDetails details, int x, int y) 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : GestureEvent(x, y, 0, base::TimeDelta(), details) {} 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Verifies that the the functions ViewTargeter::FindTargetForEvent() 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// and ViewTargeter::FindNextBestTarget() are implemented correctly 2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// for gesture events. 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(ViewTargeterTest, ViewTargeterForGestureEvents) { 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Widget widget; 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Widget::InitParams init_params = CreateParams(Widget::InitParams::TYPE_POPUP); 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci init_params.bounds = gfx::Rect(0, 0, 200, 200); 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci widget.Init(init_params); 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The coordinates used for SetBounds() are in the parent coordinate space. 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci View* content = new View; 2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content->SetBounds(0, 0, 100, 100); 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci View* child = new View; 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci child->SetBounds(50, 50, 20, 20); 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci View* grandchild = new View; 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci grandchild->SetBounds(0, 0, 5, 5); 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci widget.SetContentsView(content); 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content->AddChildView(child); 2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci child->AddChildView(grandchild); 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci internal::RootView* root_view = 2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<internal::RootView*>(widget.GetRootView()); 2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::EventTargeter* targeter = root_view->targeter(); 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Define some gesture events for testing. 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect bounding_box(gfx::Point(46, 46), gfx::Size(8, 8)); 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Point center_point(bounding_box.CenterPoint()); 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::GestureEventDetails details(ui::ET_GESTURE_TAP); 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details.set_bounding_box(bounding_box); 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GestureEventForTest tap(details, center_point.x(), center_point.y()); 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details = ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN); 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details.set_bounding_box(bounding_box); 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GestureEventForTest scroll_begin(details, center_point.x(), center_point.y()); 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details = ui::GestureEventDetails(ui::ET_GESTURE_END); 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details.set_bounding_box(bounding_box); 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GestureEventForTest end(details, center_point.x(), center_point.y()); 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Assume that the view currently handling gestures has been set as 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |grandchild| by a previous gesture event. Thus subsequent TAP and 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // SCROLL_BEGIN events should be initially targeted to |grandchild|, and 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // re-targeting should be prohibited for TAP but permitted for 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // GESTURE_SCROLL_BEGIN (which should be re-targeted to the parent of 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |grandchild|). 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandlerSetBeforeProcessing(root_view, true); 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandler(root_view, grandchild); 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(grandchild, targeter->FindTargetForEvent(root_view, &tap)); 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(grandchild, &tap)); 2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(grandchild, targeter->FindTargetForEvent(root_view, &scroll_begin)); 2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(child, targeter->FindNextBestTarget(grandchild, &scroll_begin)); 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // GESTURE_END events should be targeted to the existing gesture handler, 2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // but re-targeting should be prohibited. 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(grandchild, targeter->FindTargetForEvent(root_view, &end)); 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(grandchild, &end)); 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Assume that the view currently handling gestures is still set as 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |grandchild|, but this was not done by a previous gesture. Thus we are 2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // in the process of finding the View to which subsequent gestures will be 3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // dispatched, so TAP and SCROLL_BEGIN events should be re-targeted up 3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the ancestor chain. 3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandlerSetBeforeProcessing(root_view, false); 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(child, targeter->FindNextBestTarget(grandchild, &tap)); 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(child, targeter->FindNextBestTarget(grandchild, &scroll_begin)); 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // GESTURE_END events are not permitted to be re-targeted up the ancestor 3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // chain; they are only ever targeted in the case where the gesture handler 3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // was established by a previous gesture. 3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(grandchild, &end)); 3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Assume that the default gesture handler was set by the previous gesture, 3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // but that this handler is currently NULL. No gesture events should be 3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // re-targeted in this case (regardless of the view that is passed in to 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // FindNextBestTarget() as the previous target). 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandler(root_view, NULL); 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandlerSetBeforeProcessing(root_view, true); 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(child, &tap)); 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(NULL, &tap)); 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(content, &scroll_begin)); 3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(content, &end)); 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Reset the locations of the gesture events to be in the root view 3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // coordinate space since we are about to call FindTargetForEvent() 3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // again (calls to FindTargetForEvent() and FindNextBestTarget() 3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // mutate the location of the gesture events to be in the coordinate 3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // space of the returned view). 3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details = ui::GestureEventDetails(ui::ET_GESTURE_TAP); 3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details.set_bounding_box(bounding_box); 3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tap = GestureEventForTest(details, center_point.x(), center_point.y()); 3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details = ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN); 3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details.set_bounding_box(bounding_box); 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scroll_begin = 3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GestureEventForTest(details, center_point.x(), center_point.y()); 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details = ui::GestureEventDetails(ui::ET_GESTURE_END); 3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details.set_bounding_box(bounding_box); 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci end = GestureEventForTest(details, center_point.x(), center_point.y()); 3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If no default gesture handler is currently set, targeting should be 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // performed using the location of the gesture event for a TAP and a 3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // SCROLL_BEGIN. 3411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandlerSetBeforeProcessing(root_view, false); 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(grandchild, targeter->FindTargetForEvent(root_view, &tap)); 3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(grandchild, targeter->FindTargetForEvent(root_view, &scroll_begin)); 3441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If no default gesture handler is currently set, GESTURE_END events 3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // should never be targeted or re-targeted to any View. 3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindTargetForEvent(root_view, &end)); 3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(NULL, &end)); 3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(child, &end)); 3501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Tests that calls to FindTargetForEvent() and FindNextBestTarget() change 3531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// the location of a gesture event to be in the correct coordinate space. 3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(ViewTargeterTest, GestureEventCoordinateConversion) { 3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Widget widget; 3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Widget::InitParams init_params = CreateParams(Widget::InitParams::TYPE_POPUP); 3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 3581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci init_params.bounds = gfx::Rect(0, 0, 200, 200); 3591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci widget.Init(init_params); 3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The coordinates used for SetBounds() are in the parent coordinate space. 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci View* content = new View; 3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content->SetBounds(0, 0, 100, 100); 3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci View* child = new View; 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci child->SetBounds(50, 50, 20, 20); 3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci View* grandchild = new View; 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci grandchild->SetBounds(5, 5, 10, 10); 3681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci View* great_grandchild = new View; 3691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci great_grandchild->SetBounds(3, 3, 4, 4); 3701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci widget.SetContentsView(content); 3721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci content->AddChildView(child); 3731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci child->AddChildView(grandchild); 3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci grandchild->AddChildView(great_grandchild); 3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci internal::RootView* root_view = 3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<internal::RootView*>(widget.GetRootView()); 3781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::EventTargeter* targeter = root_view->targeter(); 3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Define a GESTURE_TAP event with a bounding box centered at (60, 60) 3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // in root view coordinates with width and height of 4. 3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Rect bounding_box(gfx::Point(58, 58), gfx::Size(4, 4)); 3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Point center_point(bounding_box.CenterPoint()); 3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::GestureEventDetails details(ui::ET_GESTURE_TAP); 3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci details.set_bounding_box(bounding_box); 3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GestureEventForTest tap(details, center_point.x(), center_point.y()); 3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Calculate the location of the gesture in each of the different 3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // coordinate spaces. 3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Point location_in_root(center_point); 3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(gfx::Point(60, 60), location_in_root); 3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Point location_in_great_grandchild( 3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ConvertPointFromWidgetToView(great_grandchild, location_in_root)); 3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(gfx::Point(2, 2), location_in_great_grandchild); 3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Point location_in_grandchild( 3961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ConvertPointFromWidgetToView(grandchild, location_in_root)); 3971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(gfx::Point(5, 5), location_in_grandchild); 3981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Point location_in_child( 3991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ConvertPointFromWidgetToView(child, location_in_root)); 4001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(gfx::Point(10, 10), location_in_child); 4011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci gfx::Point location_in_content( 4021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ConvertPointFromWidgetToView(content, location_in_root)); 4031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(gfx::Point(60, 60), location_in_content); 4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Verify the location of |tap| is in screen coordinates. 4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(gfx::Point(60, 60), tap.location()); 4071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The initial target should be |great_grandchild| and the location of 4091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the event should be changed into the coordinate space of the target. 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(great_grandchild, targeter->FindTargetForEvent(root_view, &tap)); 4111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(location_in_great_grandchild, tap.location()); 4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandler(root_view, great_grandchild); 4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The next target should be |grandchild| and the location of 4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the event should be changed into the coordinate space of the target. 4161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(grandchild, targeter->FindNextBestTarget(great_grandchild, &tap)); 4171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(location_in_grandchild, tap.location()); 4181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandler(root_view, grandchild); 4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The next target should be |child| and the location of 4211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the event should be changed into the coordinate space of the target. 4221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(child, targeter->FindNextBestTarget(grandchild, &tap)); 4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(location_in_child, tap.location()); 4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandler(root_view, child); 4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The next target should be |content| and the location of 4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the event should be changed into the coordinate space of the target. 4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(content, targeter->FindNextBestTarget(child, &tap)); 4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(location_in_content, tap.location()); 4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandler(root_view, content); 4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The next target should be |root_view| and the location of 4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the event should be changed into the coordinate space of the target. 4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(widget.GetRootView(), targeter->FindNextBestTarget(content, &tap)); 4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(location_in_root, tap.location()); 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetGestureHandler(root_view, widget.GetRootView()); 4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The next target should be NULL and the location of the event should 4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // remain unchanged. 4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(NULL, targeter->FindNextBestTarget(widget.GetRootView(), &tap)); 4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_EQ(location_in_root, tap.location()); 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 444116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Tests that the functions ViewTargeterDelegate::DoesIntersectRect() 445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// and MaskedTargeterDelegate::DoesIntersectRect() work as intended when 446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// called on views which are derived from ViewTargeterDelegate. 447116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Also verifies that ViewTargeterDelegate::DoesIntersectRect() can 448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// be called from the ViewTargeter installed on RootView. 449116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(ViewTargeterTest, DoesIntersectRect) { 450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Widget widget; 451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) params.bounds = gfx::Rect(0, 0, 650, 650); 454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) widget.Init(params); 455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) internal::RootView* root_view = 457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static_cast<internal::RootView*>(widget.GetRootView()); 4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ViewTargeter* view_targeter = root_view->targeter(); 459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The coordinates used for SetBounds() are in the parent coordinate space. 461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TestingView v2; 462116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TestMaskedView v1, v3; 463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch v1.SetBounds(0, 0, 200, 200); 464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch v2.SetBounds(300, 0, 300, 300); 465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch v3.SetBounds(0, 0, 100, 100); 466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch root_view->AddChildView(&v1); 467116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch root_view->AddChildView(&v2); 468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch v2.AddChildView(&v3); 469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 470116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The coordinates used below are in the local coordinate space of the 471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // view that is passed in as an argument. 472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Hit tests against |v1|, which has a hit test mask. 474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(v1.TestDoesIntersectRect(&v1, gfx::Rect(0, 0, 200, 200))); 475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(v1.TestDoesIntersectRect(&v1, gfx::Rect(-10, -10, 110, 12))); 476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(v1.TestDoesIntersectRect(&v1, gfx::Rect(112, 142, 1, 1))); 477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(v1.TestDoesIntersectRect(&v1, gfx::Rect(0, 0, 20, 20))); 478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(v1.TestDoesIntersectRect(&v1, gfx::Rect(-10, -10, 90, 12))); 479116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(v1.TestDoesIntersectRect(&v1, gfx::Rect(150, 49, 1, 1))); 480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Hit tests against |v2|, which does not have a hit test mask. 482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(v2.TestDoesIntersectRect(&v2, gfx::Rect(0, 0, 200, 200))); 483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(v2.TestDoesIntersectRect(&v2, gfx::Rect(-10, 250, 60, 60))); 484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(v2.TestDoesIntersectRect(&v2, gfx::Rect(250, 250, 1, 1))); 485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(v2.TestDoesIntersectRect(&v2, gfx::Rect(-10, 250, 7, 7))); 486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(v2.TestDoesIntersectRect(&v2, gfx::Rect(-1, -1, 1, 1))); 487116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 488116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Hit tests against |v3|, which has a hit test mask and is a child of |v2|. 489116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(v3.TestDoesIntersectRect(&v3, gfx::Rect(0, 0, 50, 50))); 490116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(v3.TestDoesIntersectRect(&v3, gfx::Rect(90, 90, 1, 1))); 491116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(v3.TestDoesIntersectRect(&v3, gfx::Rect(10, 125, 50, 50))); 492116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(v3.TestDoesIntersectRect(&v3, gfx::Rect(110, 110, 1, 1))); 493116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 494116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Verify that hit-testing is performed correctly when using the 495116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // call-through function ViewTargeter::DoesIntersectRect(). 496116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(view_targeter->DoesIntersectRect(root_view, 497116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect(0, 0, 50, 50))); 498116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(view_targeter->DoesIntersectRect(root_view, 499116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect(-20, -20, 10, 10))); 500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 502116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Tests that calls made directly on the hit-testing methods in View 503116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// (HitTestPoint(), HitTestRect(), etc.) return the correct values. 504116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(ViewTargeterTest, HitTestCallsOnView) { 505116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The coordinates in this test are in the coordinate space of the root view. 506116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Widget* widget = new Widget; 507116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 508116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch widget->Init(params); 509116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch View* root_view = widget->GetRootView(); 510116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500)); 511116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 512116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // |v1| has no hit test mask. No ViewTargeter is installed on |v1|, which 513116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // means that View::HitTestRect() will call into the targeter installed on 514116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the root view instead when we hit test against |v1|. 515116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect v1_bounds = gfx::Rect(0, 0, 100, 100); 516116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TestingView* v1 = new TestingView(); 517116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch v1->SetBoundsRect(v1_bounds); 518116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch root_view->AddChildView(v1); 519116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 520116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // |v2| has a triangular hit test mask. Install a ViewTargeter on |v2| which 521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // will be called into by View::HitTestRect(). 522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect v2_bounds = gfx::Rect(105, 0, 100, 100); 523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch TestMaskedView* v2 = new TestMaskedView(); 524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch v2->SetBoundsRect(v2_bounds); 525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch root_view->AddChildView(v2); 526116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ViewTargeter* view_targeter = new ViewTargeter(v2); 527116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch v2->SetEventTargeter(make_scoped_ptr(view_targeter)); 528116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 529116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Point v1_centerpoint = v1_bounds.CenterPoint(); 530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Point v2_centerpoint = v2_bounds.CenterPoint(); 531116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Point v1_origin = v1_bounds.origin(); 532116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Point v2_origin = v2_bounds.origin(); 533116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect r1(10, 10, 110, 15); 534116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect r2(106, 1, 98, 98); 535116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect r3(0, 0, 300, 300); 536116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect r4(115, 342, 200, 10); 537116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 538116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Test calls into View::HitTestPoint(). 5391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE( 5401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v1->HitTestPoint(ConvertPointFromWidgetToView(v1, v1_centerpoint))); 5411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE( 5421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci v2->HitTestPoint(ConvertPointFromWidgetToView(v2, v2_centerpoint))); 543116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(v1->HitTestPoint(ConvertPointFromWidgetToView(v1, v1_origin))); 5451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(v2->HitTestPoint(ConvertPointFromWidgetToView(v2, v2_origin))); 546116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 547116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Test calls into View::HitTestRect(). 5481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(v1->HitTestRect(ConvertRectFromWidgetToView(v1, r1))); 5491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(v2->HitTestRect(ConvertRectFromWidgetToView(v2, r1))); 550116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(v1->HitTestRect(ConvertRectFromWidgetToView(v1, r2))); 5521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(v2->HitTestRect(ConvertRectFromWidgetToView(v2, r2))); 553116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(v1->HitTestRect(ConvertRectFromWidgetToView(v1, r3))); 5551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(v2->HitTestRect(ConvertRectFromWidgetToView(v2, r3))); 556116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(v1->HitTestRect(ConvertRectFromWidgetToView(v1, r4))); 5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(v2->HitTestRect(ConvertRectFromWidgetToView(v2, r4))); 559116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 560116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Test calls into View::GetEventHandlerForPoint(). 561116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(v1, root_view->GetEventHandlerForPoint(v1_centerpoint)); 562116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(v2, root_view->GetEventHandlerForPoint(v2_centerpoint)); 563116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 564116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(v1, root_view->GetEventHandlerForPoint(v1_origin)); 565116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(root_view, root_view->GetEventHandlerForPoint(v2_origin)); 566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Test calls into View::GetTooltipHandlerForPoint(). 568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(v1, root_view->GetTooltipHandlerForPoint(v1_centerpoint)); 569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(v2, root_view->GetTooltipHandlerForPoint(v2_centerpoint)); 570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(v1, root_view->GetTooltipHandlerForPoint(v1_origin)); 572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(root_view, root_view->GetTooltipHandlerForPoint(v2_origin)); 573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 574116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(v1->GetTooltipHandlerForPoint(v2_origin)); 575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 576116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch widget->CloseNow(); 577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 578cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 579010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace test 580010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace views 581