1// Copyright (c) 2013 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 "ui/wm/core/capture_controller.h"
6
7#include "base/logging.h"
8#include "base/path_service.h"
9#include "ui/aura/env.h"
10#include "ui/aura/test/test_window_delegate.h"
11#include "ui/aura/window_event_dispatcher.h"
12#include "ui/aura/window_tree_host.h"
13#include "ui/base/resource/resource_bundle.h"
14#include "ui/base/ui_base_paths.h"
15#include "ui/events/event.h"
16#include "ui/events/test/event_generator.h"
17#include "ui/gl/gl_surface.h"
18#include "ui/views/test/views_test_base.h"
19#include "ui/views/view.h"
20#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
21#include "ui/views/widget/desktop_aura/desktop_screen_position_client.h"
22#include "ui/views/widget/root_view.h"
23#include "ui/views/widget/widget.h"
24
25// NOTE: these tests do native capture, so they have to be in
26// interactive_ui_tests.
27
28namespace views {
29
30class DesktopCaptureControllerTest : public ViewsTestBase {
31 public:
32  DesktopCaptureControllerTest() {}
33  virtual ~DesktopCaptureControllerTest() {}
34
35  virtual void SetUp() OVERRIDE {
36    gfx::GLSurface::InitializeOneOffForTests();
37    ui::RegisterPathProvider();
38    base::FilePath ui_test_pak_path;
39    ASSERT_TRUE(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
40    ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
41
42    ViewsTestBase::SetUp();
43  }
44};
45
46// This class provides functionality to verify whether the View instance
47// received the gesture event.
48class DesktopViewInputTest : public View {
49 public:
50  DesktopViewInputTest()
51      : received_gesture_event_(false) {}
52
53  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
54    received_gesture_event_ = true;
55    return View::OnGestureEvent(event);
56  }
57
58  // Resets state maintained by this class.
59  void Reset() {
60    received_gesture_event_ = false;
61  }
62
63  bool received_gesture_event() const { return received_gesture_event_; }
64
65 private:
66  bool received_gesture_event_;
67
68  DISALLOW_COPY_AND_ASSIGN(DesktopViewInputTest);
69};
70
71views::Widget* CreateWidget() {
72  views::Widget* widget = new views::Widget;
73  views::Widget::InitParams params;
74  params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
75  params.accept_events = true;
76  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
77  params.native_widget = new DesktopNativeWidgetAura(widget);
78  params.bounds = gfx::Rect(0, 0, 200, 100);
79  widget->Init(params);
80  widget->Show();
81  return widget;
82}
83
84// Verifies mouse handlers are reset when a window gains capture. Specifically
85// creates two widgets, does a mouse press in one, sets capture in the other and
86// verifies state is reset in the first.
87TEST_F(DesktopCaptureControllerTest, ResetMouseHandlers) {
88  scoped_ptr<Widget> w1(CreateWidget());
89  scoped_ptr<Widget> w2(CreateWidget());
90  ui::test::EventGenerator generator1(w1->GetNativeView()->GetRootWindow());
91  generator1.MoveMouseToCenterOf(w1->GetNativeView());
92  generator1.PressLeftButton();
93  EXPECT_FALSE(w1->HasCapture());
94  aura::WindowEventDispatcher* w1_dispatcher =
95      w1->GetNativeView()->GetHost()->dispatcher();
96  EXPECT_TRUE(w1_dispatcher->mouse_pressed_handler() != NULL);
97  EXPECT_TRUE(w1_dispatcher->mouse_moved_handler() != NULL);
98  w2->SetCapture(w2->GetRootView());
99  EXPECT_TRUE(w2->HasCapture());
100  EXPECT_TRUE(w1_dispatcher->mouse_pressed_handler() == NULL);
101  EXPECT_TRUE(w1_dispatcher->mouse_moved_handler() == NULL);
102  w2->ReleaseCapture();
103  RunPendingMessages();
104}
105
106// Tests aura::Window capture and whether gesture events are sent to the window
107// which has capture.
108// The test case creates two visible widgets and sets capture to the underlying
109// aura::Windows one by one. It then sends a gesture event and validates whether
110// the window which had capture receives the gesture.
111// TODO(sky): move this test, it should be part of ScopedCaptureClient tests.
112TEST_F(DesktopCaptureControllerTest, CaptureWindowInputEventTest) {
113  scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client1;
114  scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client2;
115
116  scoped_ptr<Widget> widget1(new Widget());
117  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
118  scoped_ptr<wm::ScopedCaptureClient> scoped_capture_client(
119      new wm::ScopedCaptureClient(params.context->GetRootWindow()));
120  aura::client::CaptureClient* capture_client =
121      scoped_capture_client->capture_client();
122  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
123  params.bounds = gfx::Rect(50, 50, 650, 650);
124  widget1->Init(params);
125  internal::RootView* root1 =
126      static_cast<internal::RootView*>(widget1->GetRootView());
127
128  desktop_position_client1.reset(
129      new DesktopScreenPositionClient(params.context->GetRootWindow()));
130  aura::client::SetScreenPositionClient(
131      widget1->GetNativeView()->GetRootWindow(),
132      desktop_position_client1.get());
133
134  DesktopViewInputTest* v1 = new DesktopViewInputTest();
135  v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
136  root1->AddChildView(v1);
137  widget1->Show();
138
139  scoped_ptr<Widget> widget2(new Widget());
140
141  params = CreateParams(Widget::InitParams::TYPE_POPUP);
142  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
143  params.bounds = gfx::Rect(50, 50, 650, 650);
144  widget2->Init(params);
145
146  internal::RootView* root2 =
147      static_cast<internal::RootView*>(widget2->GetRootView());
148  desktop_position_client2.reset(
149      new DesktopScreenPositionClient(params.context->GetRootWindow()));
150  aura::client::SetScreenPositionClient(
151      widget2->GetNativeView()->GetRootWindow(),
152      desktop_position_client2.get());
153  ui::EventDispatchDetails details;
154
155  DesktopViewInputTest* v2 = new DesktopViewInputTest();
156  v2->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
157  root2->AddChildView(v2);
158  widget2->Show();
159
160  EXPECT_FALSE(widget1->GetNativeView()->HasCapture());
161  EXPECT_FALSE(widget2->GetNativeView()->HasCapture());
162  EXPECT_EQ(reinterpret_cast<aura::Window*>(0),
163            capture_client->GetCaptureWindow());
164
165  widget1->GetNativeView()->SetCapture();
166  EXPECT_TRUE(widget1->GetNativeView()->HasCapture());
167  EXPECT_FALSE(widget2->GetNativeView()->HasCapture());
168  EXPECT_EQ(capture_client->GetCaptureWindow(), widget1->GetNativeView());
169
170  ui::GestureEvent g1(80,
171                      80,
172                      0,
173                      base::TimeDelta(),
174                      ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
175  details = root1->OnEventFromSource(&g1);
176  EXPECT_FALSE(details.dispatcher_destroyed);
177  EXPECT_FALSE(details.target_destroyed);
178
179  EXPECT_TRUE(v1->received_gesture_event());
180  EXPECT_FALSE(v2->received_gesture_event());
181  v1->Reset();
182  v2->Reset();
183
184  widget2->GetNativeView()->SetCapture();
185
186  EXPECT_FALSE(widget1->GetNativeView()->HasCapture());
187  EXPECT_TRUE(widget2->GetNativeView()->HasCapture());
188  EXPECT_EQ(capture_client->GetCaptureWindow(), widget2->GetNativeView());
189
190  details = root2->OnEventFromSource(&g1);
191  EXPECT_FALSE(details.dispatcher_destroyed);
192  EXPECT_FALSE(details.target_destroyed);
193
194  EXPECT_TRUE(v2->received_gesture_event());
195  EXPECT_FALSE(v1->received_gesture_event());
196
197  widget1->CloseNow();
198  widget2->CloseNow();
199  RunPendingMessages();
200}
201
202}  // namespace views
203