Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / apps / shaped_app_window_targeter_unittest.cc
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 "apps/ui/views/app_window_frame_view.h"
8 #include "chrome/browser/ui/views/apps/chrome_native_app_window_views.h"
9 #include "ui/aura/test/aura_test_base.h"
10 #include "ui/aura/window.h"
11 #include "ui/aura/window_event_dispatcher.h"
12 #include "ui/views/controls/webview/webview.h"
13 #include "ui/wm/core/default_activation_client.h"
14 #include "ui/wm/core/easy_resize_window_targeter.h"
15
16 class ShapedAppWindowTargeterTest : public aura::test::AuraTestBase {
17  public:
18   ShapedAppWindowTargeterTest()
19       : web_view_(NULL) {
20   }
21
22   virtual ~ShapedAppWindowTargeterTest() {}
23
24   views::Widget* widget() { return widget_.get(); }
25
26   extensions::NativeAppWindow* app_window() { return &app_window_; }
27   ChromeNativeAppWindowViews* app_window_views() { return &app_window_; }
28
29  protected:
30   virtual void SetUp() OVERRIDE {
31     aura::test::AuraTestBase::SetUp();
32     new wm::DefaultActivationClient(root_window());
33     widget_.reset(new views::Widget);
34     views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
35     params.remove_standard_frame = true;
36     params.bounds = gfx::Rect(30, 30, 100, 100);
37     params.context = root_window();
38     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
39     widget_->Init(params);
40
41     app_window_.set_web_view_for_testing(&web_view_);
42     app_window_.set_window_for_testing(widget_.get());
43
44     widget_->Show();
45   }
46
47   virtual void TearDown() OVERRIDE {
48     widget_.reset();
49     aura::test::AuraTestBase::TearDown();
50   }
51
52  private:
53   views::WebView web_view_;
54   scoped_ptr<views::Widget> widget_;
55   ChromeNativeAppWindowViews app_window_;
56
57   DISALLOW_COPY_AND_ASSIGN(ShapedAppWindowTargeterTest);
58 };
59
60 TEST_F(ShapedAppWindowTargeterTest, HitTestBasic) {
61   aura::Window* window = widget()->GetNativeWindow();
62   {
63     // Without any custom shapes, the event should be targeted correctly to the
64     // window.
65     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
66                         gfx::Point(40, 40), gfx::Point(40, 40),
67                         ui::EF_NONE, ui::EF_NONE);
68     ui::EventDispatchDetails details =
69         event_processor()->OnEventFromSource(&move);
70     ASSERT_FALSE(details.dispatcher_destroyed);
71     EXPECT_EQ(window, move.target());
72   }
73
74   scoped_ptr<SkRegion> region(new SkRegion);
75   region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op);
76   region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op);
77   app_window()->UpdateShape(region.Pass());
78   {
79     // With the custom shape, the events that don't fall within the custom shape
80     // will go through to the root window.
81     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
82                         gfx::Point(40, 40), gfx::Point(40, 40),
83                         ui::EF_NONE, ui::EF_NONE);
84     ui::EventDispatchDetails details =
85         event_processor()->OnEventFromSource(&move);
86     ASSERT_FALSE(details.dispatcher_destroyed);
87     EXPECT_EQ(root_window(), move.target());
88
89     // But events within the shape will still reach the window.
90     ui::MouseEvent move2(ui::ET_MOUSE_MOVED,
91                          gfx::Point(80, 80), gfx::Point(80, 80),
92                          ui::EF_NONE, ui::EF_NONE);
93     details = event_processor()->OnEventFromSource(&move2);
94     ASSERT_FALSE(details.dispatcher_destroyed);
95     EXPECT_EQ(window, move2.target());
96   }
97 }
98
99 TEST_F(ShapedAppWindowTargeterTest, HitTestOnlyForShapedWindow) {
100   // Install a window-targeter on the root window that allows a window to
101   // receive events outside of its bounds. Verify that this window-targeter is
102   // active unless the window has a custom shape.
103   gfx::Insets inset(-30, -30, -30, -30);
104   root_window()->SetEventTargeter(scoped_ptr<ui::EventTargeter>(
105       new wm::EasyResizeWindowTargeter(root_window(), inset, inset)));
106
107   aura::Window* window = widget()->GetNativeWindow();
108   {
109     // Without any custom shapes, an event within the window bounds should be
110     // targeted correctly to the window.
111     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
112                         gfx::Point(40, 40), gfx::Point(40, 40),
113                         ui::EF_NONE, ui::EF_NONE);
114     ui::EventDispatchDetails details =
115         event_processor()->OnEventFromSource(&move);
116     ASSERT_FALSE(details.dispatcher_destroyed);
117     EXPECT_EQ(window, move.target());
118   }
119   {
120     // Without any custom shapes, an event that falls just outside the window
121     // bounds should also be targeted correctly to the window, because of the
122     // targeter installed on the root-window.
123     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
124                         gfx::Point(10, 10), gfx::Point(10, 10),
125                         ui::EF_NONE, ui::EF_NONE);
126     ui::EventDispatchDetails details =
127         event_processor()->OnEventFromSource(&move);
128     ASSERT_FALSE(details.dispatcher_destroyed);
129     EXPECT_EQ(window, move.target());
130   }
131
132   scoped_ptr<SkRegion> region(new SkRegion);
133   region->op(SkIRect::MakeXYWH(40, 0, 20, 100), SkRegion::kUnion_Op);
134   region->op(SkIRect::MakeXYWH(0, 40, 100, 20), SkRegion::kUnion_Op);
135   app_window()->UpdateShape(region.Pass());
136   {
137     // With the custom shape, the events that don't fall within the custom shape
138     // will go through to the root window.
139     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
140                         gfx::Point(10, 10), gfx::Point(10, 10),
141                         ui::EF_NONE, ui::EF_NONE);
142     ui::EventDispatchDetails details =
143         event_processor()->OnEventFromSource(&move);
144     ASSERT_FALSE(details.dispatcher_destroyed);
145     EXPECT_EQ(root_window(), move.target());
146   }
147
148   // Remove the custom shape. This should restore the behaviour of targeting the
149   // app window for events just outside its bounds.
150   app_window()->UpdateShape(scoped_ptr<SkRegion>());
151   {
152     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
153                         gfx::Point(10, 10), gfx::Point(10, 10),
154                         ui::EF_NONE, ui::EF_NONE);
155     ui::EventDispatchDetails details =
156         event_processor()->OnEventFromSource(&move);
157     ASSERT_FALSE(details.dispatcher_destroyed);
158     EXPECT_EQ(window, move.target());
159   }
160 }
161
162 // Tests targeting of events on a window with an EasyResizeWindowTargeter
163 // installed on its container.
164 TEST_F(ShapedAppWindowTargeterTest, ResizeInsetsWithinBounds) {
165   aura::Window* window = widget()->GetNativeWindow();
166   {
167     // An event in the center of the window should always have
168     // |window| as its target.
169     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
170                         gfx::Point(80, 80), gfx::Point(80, 80),
171                         ui::EF_NONE, ui::EF_NONE);
172     ui::EventDispatchDetails details =
173         event_processor()->OnEventFromSource(&move);
174     ASSERT_FALSE(details.dispatcher_destroyed);
175     EXPECT_EQ(window, move.target());
176   }
177   {
178     // Without an EasyResizeTargeter on the container, an event
179     // inside the window and within 5px of an edge should have
180     // |window| as its target.
181     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
182                         gfx::Point(32, 37), gfx::Point(32, 37),
183                         ui::EF_NONE, ui::EF_NONE);
184     ui::EventDispatchDetails details =
185         event_processor()->OnEventFromSource(&move);
186     ASSERT_FALSE(details.dispatcher_destroyed);
187     EXPECT_EQ(window, move.target());
188   }
189
190 #if !defined(OS_CHROMEOS)
191   // The non standard app frame has a easy resize targetter installed.
192   scoped_ptr<apps::AppWindowFrameView> frame(
193       app_window_views()->CreateNonStandardAppFrame());
194   {
195     // Ensure that the window has an event targeter (there should be an
196     // EasyResizeWindowTargeter installed).
197     EXPECT_TRUE(static_cast<ui::EventTarget*>(window)->GetEventTargeter());
198   }
199   {
200     // An event in the center of the window should always have
201     // |window| as its target.
202     // TODO(mgiuca): This isn't really testing anything (note that it has the
203     // same expectation as the border case below). In the real environment, the
204     // target will actually be the RenderWidgetHostViewAura's window that is the
205     // child of the child of |window|, whereas in the border case it *will* be
206     // |window|. However, since this test environment does not have a
207     // RenderWidgetHostViewAura, we cannot differentiate the two cases. Fix
208     // the test environment so that the test can assert that non-border events
209     // bubble down to a child of |window|.
210     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
211                         gfx::Point(80, 80), gfx::Point(80, 80),
212                         ui::EF_NONE, ui::EF_NONE);
213     ui::EventDispatchDetails details =
214         event_processor()->OnEventFromSource(&move);
215     ASSERT_FALSE(details.dispatcher_destroyed);
216     EXPECT_EQ(window, move.target());
217   }
218   {
219     // With an EasyResizeTargeter on the container, an event
220     // inside the window and within 5px of an edge should have
221     // |window| as its target.
222     ui::MouseEvent move(ui::ET_MOUSE_MOVED,
223                         gfx::Point(32, 37), gfx::Point(32, 37),
224                         ui::EF_NONE, ui::EF_NONE);
225     ui::EventDispatchDetails details =
226         event_processor()->OnEventFromSource(&move);
227     ASSERT_FALSE(details.dispatcher_destroyed);
228     EXPECT_EQ(window, move.target());
229   }
230 #endif  // defined (OS_CHROMEOS)
231 }