Improve audio/video sync during underflow, reduce underflow frequency.
[chromium-blink-merge.git] / ash / wm / workspace / multi_window_resize_controller_unittest.cc
blobea7e608ff150486fd79afdce0dda8fdad6d82dcb
1 // Copyright (c) 2012 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.
5 #include "ash/wm/workspace/multi_window_resize_controller.h"
7 #include "ash/ash_constants.h"
8 #include "ash/frame/custom_frame_view_ash.h"
9 #include "ash/shell.h"
10 #include "ash/test/ash_test_base.h"
11 #include "ash/test/shell_test_api.h"
12 #include "ash/wm/window_util.h"
13 #include "ash/wm/workspace/workspace_event_handler_test_helper.h"
14 #include "ash/wm/workspace_controller.h"
15 #include "ash/wm/workspace_controller_test_helper.h"
16 #include "ui/aura/test/test_window_delegate.h"
17 #include "ui/aura/window.h"
18 #include "ui/base/hit_test.h"
19 #include "ui/events/test/event_generator.h"
20 #include "ui/gfx/screen.h"
21 #include "ui/views/widget/widget.h"
22 #include "ui/views/widget/widget_delegate.h"
24 namespace ash {
26 namespace {
28 // WidgetDelegate for a resizable widget which creates a NonClientFrameView
29 // which is actually used in Ash.
30 class TestWidgetDelegate : public views::WidgetDelegateView {
31 public:
32 TestWidgetDelegate() {}
33 ~TestWidgetDelegate() override {}
35 // views::WidgetDelegateView:
36 bool CanResize() const override {
37 return true;
40 views::NonClientFrameView* CreateNonClientFrameView(
41 views::Widget* widget) override {
42 return new CustomFrameViewAsh(widget);
45 private:
46 DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate);
49 } // namespace
51 class MultiWindowResizeControllerTest : public test::AshTestBase {
52 public:
53 MultiWindowResizeControllerTest() : resize_controller_(NULL) {}
54 ~MultiWindowResizeControllerTest() override {}
56 void SetUp() override {
57 test::AshTestBase::SetUp();
58 WorkspaceController* wc =
59 test::ShellTestApi(Shell::GetInstance()).workspace_controller();
60 WorkspaceEventHandler* event_handler =
61 WorkspaceControllerTestHelper(wc).GetEventHandler();
62 resize_controller_ = WorkspaceEventHandlerTestHelper(event_handler).
63 resize_controller();
66 protected:
67 aura::Window* CreateTestWindow(aura::WindowDelegate* delegate,
68 const gfx::Rect& bounds) {
69 aura::Window* window = new aura::Window(delegate);
70 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
71 window->Init(ui::LAYER_TEXTURED);
72 ParentWindowInPrimaryRootWindow(window);
73 window->SetBounds(bounds);
74 window->Show();
75 return window;
78 void ShowNow() {
79 resize_controller_->ShowNow();
82 bool IsShowing() {
83 return resize_controller_->IsShowing();
86 bool HasPendingShow() {
87 return resize_controller_->show_timer_.IsRunning();
90 void Hide() {
91 resize_controller_->Hide();
94 bool HasTarget(aura::Window* window) {
95 if (!resize_controller_->windows_.is_valid())
96 return false;
97 if ((resize_controller_->windows_.window1 == window ||
98 resize_controller_->windows_.window2 == window))
99 return true;
100 for (size_t i = 0;
101 i < resize_controller_->windows_.other_windows.size(); ++i) {
102 if (resize_controller_->windows_.other_windows[i] == window)
103 return true;
105 return false;
108 bool IsOverWindows(const gfx::Point& loc) {
109 return resize_controller_->IsOverWindows(loc);
112 views::Widget* resize_widget() {
113 return resize_controller_->resize_widget_.get();
116 MultiWindowResizeController* resize_controller_;
118 private:
119 DISALLOW_COPY_AND_ASSIGN(MultiWindowResizeControllerTest);
122 // Assertions around moving mouse over 2 windows.
123 TEST_F(MultiWindowResizeControllerTest, BasicTests) {
124 aura::test::TestWindowDelegate delegate1;
125 scoped_ptr<aura::Window> w1(
126 CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100)));
127 delegate1.set_window_component(HTRIGHT);
128 aura::test::TestWindowDelegate delegate2;
129 scoped_ptr<aura::Window> w2(
130 CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100)));
131 delegate2.set_window_component(HTRIGHT);
132 ui::test::EventGenerator generator(w1->GetRootWindow());
133 generator.MoveMouseTo(w1->bounds().CenterPoint());
134 EXPECT_TRUE(HasPendingShow());
135 EXPECT_TRUE(IsShowing());
137 // Force a show now.
138 ShowNow();
139 EXPECT_FALSE(HasPendingShow());
140 EXPECT_TRUE(IsShowing());
142 EXPECT_FALSE(IsOverWindows(gfx::Point(200, 200)));
144 // Have to explicitly invoke this as MouseWatcher listens for native events.
145 resize_controller_->MouseMovedOutOfHost();
146 EXPECT_FALSE(HasPendingShow());
147 EXPECT_FALSE(IsShowing());
150 // Test the behavior of IsOverWindows().
151 TEST_F(MultiWindowResizeControllerTest, IsOverWindows) {
152 // Create the following layout:
153 // __________________
154 // | w1 | w2 |
155 // | |________|
156 // | | w3 |
157 // |________|________|
158 scoped_ptr<views::Widget> w1(new views::Widget);
159 views::Widget::InitParams params1;
160 params1.delegate = new TestWidgetDelegate;
161 params1.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
162 params1.bounds = gfx::Rect(100, 200);
163 params1.context = CurrentContext();
164 w1->Init(params1);
165 w1->Show();
167 scoped_ptr<views::Widget> w2(new views::Widget);
168 views::Widget::InitParams params2;
169 params2.delegate = new TestWidgetDelegate;
170 params2.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
171 params2.bounds = gfx::Rect(100, 0, 100, 100);
172 params2.context = CurrentContext();
173 w2->Init(params2);
174 w2->Show();
176 scoped_ptr<views::Widget> w3(new views::Widget);
177 views::Widget::InitParams params3;
178 params3.delegate = new TestWidgetDelegate;
179 params3.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
180 params3.bounds = gfx::Rect(100, 100, 100, 100);
181 params3.context = CurrentContext();
182 w3->Init(params3);
183 w3->Show();
185 ui::test::EventGenerator& generator = GetEventGenerator();
186 generator.MoveMouseTo(gfx::Point(100, 150));
187 EXPECT_TRUE(HasPendingShow());
188 EXPECT_TRUE(IsShowing());
189 ShowNow();
190 EXPECT_TRUE(IsShowing());
192 // Check that the multi-window resize handle does not hide while the mouse is
193 // over a window's resize area. A window's resize area extends outside the
194 // window's bounds.
195 EXPECT_TRUE(w3->IsActive());
196 ASSERT_LT(kResizeInsideBoundsSize, kResizeOutsideBoundsSize);
198 EXPECT_TRUE(IsOverWindows(gfx::Point(100, 150)));
199 EXPECT_TRUE(IsOverWindows(gfx::Point(100 - kResizeOutsideBoundsSize, 150)));
200 EXPECT_FALSE(
201 IsOverWindows(gfx::Point(100 - kResizeOutsideBoundsSize - 1, 150)));
202 EXPECT_TRUE(
203 IsOverWindows(gfx::Point(100 + kResizeInsideBoundsSize - 1, 150)));
204 EXPECT_FALSE(IsOverWindows(gfx::Point(100 + kResizeInsideBoundsSize, 150)));
205 EXPECT_FALSE(
206 IsOverWindows(gfx::Point(100 + kResizeOutsideBoundsSize - 1, 150)));
208 w1->Activate();
209 EXPECT_TRUE(IsOverWindows(gfx::Point(100, 150)));
210 EXPECT_TRUE(IsOverWindows(gfx::Point(100 - kResizeInsideBoundsSize, 150)));
211 EXPECT_FALSE(
212 IsOverWindows(gfx::Point(100 - kResizeInsideBoundsSize - 1, 150)));
213 EXPECT_FALSE(IsOverWindows(gfx::Point(100 - kResizeOutsideBoundsSize, 150)));
214 EXPECT_TRUE(
215 IsOverWindows(gfx::Point(100 + kResizeOutsideBoundsSize - 1, 150)));
216 EXPECT_FALSE(IsOverWindows(gfx::Point(100 + kResizeOutsideBoundsSize, 150)));
218 // Check that the multi-window resize handles eventually hide if the mouse
219 // moves between |w1| and |w2|.
220 EXPECT_FALSE(IsOverWindows(gfx::Point(100, 50)));
223 // Makes sure deleting a window hides.
224 TEST_F(MultiWindowResizeControllerTest, DeleteWindow) {
225 aura::test::TestWindowDelegate delegate1;
226 scoped_ptr<aura::Window> w1(
227 CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100)));
228 delegate1.set_window_component(HTRIGHT);
229 aura::test::TestWindowDelegate delegate2;
230 scoped_ptr<aura::Window> w2(
231 CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100)));
232 delegate2.set_window_component(HTRIGHT);
233 ui::test::EventGenerator generator(w1->GetRootWindow());
234 generator.MoveMouseTo(w1->bounds().CenterPoint());
235 EXPECT_TRUE(HasPendingShow());
236 EXPECT_TRUE(IsShowing());
238 // Force a show now.
239 ShowNow();
240 EXPECT_FALSE(HasPendingShow());
241 EXPECT_TRUE(IsShowing());
243 // Move the mouse over the resize widget.
244 ASSERT_TRUE(resize_widget());
245 gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen());
246 generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1);
247 EXPECT_FALSE(HasPendingShow());
248 EXPECT_TRUE(IsShowing());
250 // Move the resize widget
251 generator.PressLeftButton();
252 generator.MoveMouseTo(bounds.x() + 10, bounds.y() + 10);
254 // Delete w2.
255 w2.reset();
256 EXPECT_TRUE(resize_widget() == NULL);
257 EXPECT_FALSE(HasPendingShow());
258 EXPECT_FALSE(IsShowing());
259 EXPECT_FALSE(HasTarget(w1.get()));
262 // Tests resizing.
263 TEST_F(MultiWindowResizeControllerTest, Drag) {
264 aura::test::TestWindowDelegate delegate1;
265 scoped_ptr<aura::Window> w1(
266 CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100)));
267 delegate1.set_window_component(HTRIGHT);
268 aura::test::TestWindowDelegate delegate2;
269 scoped_ptr<aura::Window> w2(
270 CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100)));
271 delegate2.set_window_component(HTRIGHT);
272 ui::test::EventGenerator generator(w1->GetRootWindow());
273 generator.MoveMouseTo(w1->bounds().CenterPoint());
274 EXPECT_TRUE(HasPendingShow());
275 EXPECT_TRUE(IsShowing());
277 // Force a show now.
278 ShowNow();
279 EXPECT_FALSE(HasPendingShow());
280 EXPECT_TRUE(IsShowing());
282 // Move the mouse over the resize widget.
283 ASSERT_TRUE(resize_widget());
284 gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen());
285 generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1);
286 EXPECT_FALSE(HasPendingShow());
287 EXPECT_TRUE(IsShowing());
289 // Move the resize widget
290 generator.PressLeftButton();
291 generator.MoveMouseTo(bounds.x() + 11, bounds.y() + 10);
292 generator.ReleaseLeftButton();
294 EXPECT_TRUE(resize_widget());
295 EXPECT_FALSE(HasPendingShow());
296 EXPECT_TRUE(IsShowing());
297 EXPECT_EQ("0,0 110x100", w1->bounds().ToString());
298 EXPECT_EQ("110,0 100x100", w2->bounds().ToString());
301 // Makes sure three windows are picked up.
302 TEST_F(MultiWindowResizeControllerTest, Three) {
303 aura::test::TestWindowDelegate delegate1;
304 scoped_ptr<aura::Window> w1(
305 CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100)));
306 delegate1.set_window_component(HTRIGHT);
307 aura::test::TestWindowDelegate delegate2;
308 scoped_ptr<aura::Window> w2(
309 CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100)));
310 delegate2.set_window_component(HTRIGHT);
311 aura::test::TestWindowDelegate delegate3;
312 scoped_ptr<aura::Window> w3(
313 CreateTestWindow(&delegate3, gfx::Rect(200, 0, 100, 100)));
314 delegate3.set_window_component(HTRIGHT);
316 ui::test::EventGenerator generator(w1->GetRootWindow());
317 generator.MoveMouseTo(w1->bounds().CenterPoint());
318 EXPECT_TRUE(HasPendingShow());
319 EXPECT_TRUE(IsShowing());
320 EXPECT_FALSE(HasTarget(w3.get()));
322 ShowNow();
323 EXPECT_FALSE(HasPendingShow());
324 EXPECT_TRUE(IsShowing());
326 // w3 should be picked up when resize is started.
327 gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen());
328 generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1);
329 generator.PressLeftButton();
330 generator.MoveMouseTo(bounds.x() + 11, bounds.y() + 10);
332 EXPECT_TRUE(HasTarget(w3.get()));
334 // Release the mouse. The resizer should still be visible and a subsequent
335 // press should not trigger a DCHECK.
336 generator.ReleaseLeftButton();
337 EXPECT_TRUE(IsShowing());
338 generator.PressLeftButton();
341 // Tests that clicking outside of the resize handle dismisses it.
342 TEST_F(MultiWindowResizeControllerTest, ClickOutside) {
343 aura::test::TestWindowDelegate delegate1;
344 scoped_ptr<aura::Window> w1(
345 CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100)));
346 delegate1.set_window_component(HTRIGHT);
347 aura::test::TestWindowDelegate delegate2;
348 scoped_ptr<aura::Window> w2(
349 CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100)));
350 delegate2.set_window_component(HTLEFT);
352 ui::test::EventGenerator& generator(GetEventGenerator());
353 gfx::Point w1_center_in_screen = w1->GetBoundsInScreen().CenterPoint();
354 generator.MoveMouseTo(w1_center_in_screen);
355 EXPECT_TRUE(HasPendingShow());
356 EXPECT_TRUE(IsShowing());
357 ShowNow();
358 EXPECT_TRUE(IsShowing());
360 gfx::Rect resize_widget_bounds_in_screen =
361 resize_widget()->GetWindowBoundsInScreen();
363 // Clicking on the resize handle should not do anything.
364 generator.MoveMouseTo(resize_widget_bounds_in_screen.CenterPoint());
365 generator.ClickLeftButton();
366 EXPECT_TRUE(IsShowing());
368 // Clicking outside the resize handle should immediately hide the resize
369 // handle.
370 EXPECT_FALSE(resize_widget_bounds_in_screen.Contains(w1_center_in_screen));
371 generator.MoveMouseTo(w1_center_in_screen);
372 generator.ClickLeftButton();
373 EXPECT_FALSE(IsShowing());
376 } // namespace ash