| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/ui/views/apps/shaped_app_window_targeter.h" | |
| 6 | |
| 7 #include "chrome/browser/ui/views/apps/native_app_window_views.h" | |
| 8 #include "ui/aura/root_window.h" | |
| 9 #include "ui/aura/test/aura_test_base.h" | |
| 10 #include "ui/aura/window.h" | |
| 11 #include "ui/views/controls/webview/webview.h" | |
| 12 #include "ui/wm/public/easy_resize_window_targeter.h" | |
| 13 | |
| 14 class ShapedAppWindowTargeterTest : public aura::test::AuraTestBase { | |
| 15 public: | |
| 16 ShapedAppWindowTargeterTest() | |
| 17 : web_view_(NULL) { | |
| 18 } | |
| 19 | |
| 20 virtual ~ShapedAppWindowTargeterTest() {} | |
| 21 | |
| 22 views::Widget* widget() { return widget_.get(); } | |
| 23 | |
| 24 apps::NativeAppWindow* app_window() { return &app_window_; } | |
| 25 NativeAppWindowViews* app_window_views() { return &app_window_; } | |
| 26 | |
| 27 protected: | |
| 28 virtual void SetUp() OVERRIDE { | |
| 29 aura::test::AuraTestBase::SetUp(); | |
| 30 widget_.reset(new views::Widget); | |
| 31 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); | |
| 32 params.remove_standard_frame = true; | |
| 33 params.bounds = gfx::Rect(30, 30, 100, 100); | |
| 34 params.context = root_window(); | |
| 35 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 36 widget_->Init(params); | |
| 37 | |
| 38 app_window_.web_view_ = &web_view_; | |
| 39 app_window_.window_ = widget_.get(); | |
| 40 | |
| 41 widget_->Show(); | |
| 42 } | |
| 43 | |
| 44 virtual void TearDown() OVERRIDE { | |
| 45 widget_.reset(); | |
| 46 aura::test::AuraTestBase::TearDown(); | |
| 47 } | |
| 48 | |
| 49 private: | |
| 50 views::WebView web_view_; | |
| 51 scoped_ptr<views::Widget> widget_; | |
| 52 NativeAppWindowViews app_window_; | |
| 53 | |
| 54 DISALLOW_COPY_AND_ASSIGN(ShapedAppWindowTargeterTest); | |
| 55 }; | |
| 56 | |
| 57 TEST_F(ShapedAppWindowTargeterTest, HitTestBasic) { | |
| 58 aura::Window* window = widget()->GetNativeWindow(); | |
| 59 { | |
| 60 // Without any custom shapes, the event should be targeted correctly to the | |
| 61 // window. | |
| 62 ui::MouseEvent move(ui::ET_MOUSE_MOVED, | |
| 63 gfx::Point(40, 40), gfx::Point(40, 40), | |
| 64 ui::EF_NONE, ui::EF_NONE); | |
| 65 ui::EventDispatchDetails details = dispatcher()->OnEventFromSource(&move); | |
| 66 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 67 EXPECT_EQ(window, move.target()); | |
| 68 } | |
| 69 | |
| 70 scoped_ptr<SkRegion> region(new SkRegion); | |
| 71 region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op); | |
| 72 region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op); | |
| 73 app_window()->UpdateShape(region.Pass()); | |
| 74 { | |
| 75 // With the custom shape, the events that don't fall within the custom shape | |
| 76 // will go through to the root window. | |
| 77 ui::MouseEvent move(ui::ET_MOUSE_MOVED, | |
| 78 gfx::Point(40, 40), gfx::Point(40, 40), | |
| 79 ui::EF_NONE, ui::EF_NONE); | |
| 80 ui::EventDispatchDetails details = dispatcher()->OnEventFromSource(&move); | |
| 81 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 82 EXPECT_EQ(root_window(), move.target()); | |
| 83 | |
| 84 // But events within the shape will still reach the window. | |
| 85 ui::MouseEvent move2(ui::ET_MOUSE_MOVED, | |
| 86 gfx::Point(80, 80), gfx::Point(80, 80), | |
| 87 ui::EF_NONE, ui::EF_NONE); | |
| 88 details = dispatcher()->OnEventFromSource(&move2); | |
| 89 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 90 EXPECT_EQ(window, move2.target()); | |
| 91 } | |
| 92 } | |
| 93 | |
| 94 TEST_F(ShapedAppWindowTargeterTest, HitTestOnlyForShapedWindow) { | |
| 95 // Install a window-targeter on the root window that allows a window to | |
| 96 // receive events outside of its bounds. Verify that this window-targeter is | |
| 97 // active unless the window has a custom shape. | |
| 98 gfx::Insets inset(-30, -30, -30, -30); | |
| 99 root_window()->SetEventTargeter(scoped_ptr<ui::EventTargeter>( | |
| 100 new wm::EasyResizeWindowTargeter(root_window(), inset, inset))); | |
| 101 | |
| 102 aura::Window* window = widget()->GetNativeWindow(); | |
| 103 { | |
| 104 // Without any custom shapes, an event within the window bounds should be | |
| 105 // targeted correctly to the window. | |
| 106 ui::MouseEvent move(ui::ET_MOUSE_MOVED, | |
| 107 gfx::Point(40, 40), gfx::Point(40, 40), | |
| 108 ui::EF_NONE, ui::EF_NONE); | |
| 109 ui::EventDispatchDetails details = dispatcher()->OnEventFromSource(&move); | |
| 110 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 111 EXPECT_EQ(window, move.target()); | |
| 112 } | |
| 113 { | |
| 114 // Without any custom shapes, an event that falls just outside the window | |
| 115 // bounds should also be targeted correctly to the window, because of the | |
| 116 // targeter installed on the root-window. | |
| 117 ui::MouseEvent move(ui::ET_MOUSE_MOVED, | |
| 118 gfx::Point(10, 10), gfx::Point(10, 10), | |
| 119 ui::EF_NONE, ui::EF_NONE); | |
| 120 ui::EventDispatchDetails details = dispatcher()->OnEventFromSource(&move); | |
| 121 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 122 EXPECT_EQ(window, move.target()); | |
| 123 } | |
| 124 | |
| 125 scoped_ptr<SkRegion> region(new SkRegion); | |
| 126 region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op); | |
| 127 region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op); | |
| 128 app_window()->UpdateShape(region.Pass()); | |
| 129 { | |
| 130 // With the custom shape, the events that don't fall within the custom shape | |
| 131 // will go through to the root window. | |
| 132 ui::MouseEvent move(ui::ET_MOUSE_MOVED, | |
| 133 gfx::Point(10, 10), gfx::Point(10, 10), | |
| 134 ui::EF_NONE, ui::EF_NONE); | |
| 135 ui::EventDispatchDetails details = dispatcher()->OnEventFromSource(&move); | |
| 136 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 137 EXPECT_EQ(root_window(), move.target()); | |
| 138 } | |
| 139 | |
| 140 // Remove the custom shape. This should restore the behaviour of targeting the | |
| 141 // app window for events just outside its bounds. | |
| 142 app_window()->UpdateShape(scoped_ptr<SkRegion>()); | |
| 143 { | |
| 144 ui::MouseEvent move(ui::ET_MOUSE_MOVED, | |
| 145 gfx::Point(10, 10), gfx::Point(10, 10), | |
| 146 ui::EF_NONE, ui::EF_NONE); | |
| 147 ui::EventDispatchDetails details = dispatcher()->OnEventFromSource(&move); | |
| 148 ASSERT_FALSE(details.dispatcher_destroyed); | |
| 149 EXPECT_EQ(window, move.target()); | |
| 150 } | |
| 151 } | |
| OLD | NEW |