OLD | NEW |
| (Empty) |
1 // Copyright 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 "ash/frame/caption_buttons/frame_maximize_button.h" | |
6 | |
7 #include "ash/ash_switches.h" | |
8 #include "ash/frame/caption_buttons/frame_caption_button_container_view.h" | |
9 #include "ash/frame/caption_buttons/maximize_bubble_controller.h" | |
10 #include "ash/shell.h" | |
11 #include "ash/test/ash_test_base.h" | |
12 #include "ash/wm/window_state.h" | |
13 #include "ash/wm/window_util.h" | |
14 #include "base/command_line.h" | |
15 #include "grit/ash_resources.h" | |
16 #include "ui/aura/client/focus_client.h" | |
17 #include "ui/aura/test/event_generator.h" | |
18 #include "ui/aura/window.h" | |
19 #include "ui/aura/window_tree_host.h" | |
20 #include "ui/events/event_processor.h" | |
21 #include "ui/events/event_utils.h" | |
22 #include "ui/events/gestures/gesture_configuration.h" | |
23 #include "ui/views/widget/widget.h" | |
24 #include "ui/views/widget/widget_delegate.h" | |
25 | |
26 namespace ash { | |
27 namespace test { | |
28 | |
29 namespace { | |
30 | |
31 class CancelCallbackHandler { | |
32 public: | |
33 CancelCallbackHandler(int update_events_before_cancel, | |
34 FrameMaximizeButton* maximize_button) : | |
35 update_events_before_cancel_(update_events_before_cancel), | |
36 maximize_button_(maximize_button) {} | |
37 virtual ~CancelCallbackHandler() {} | |
38 | |
39 void CountedCancelCallback(ui::EventType event_type, | |
40 const gfx::Vector2dF& pos) { | |
41 if (event_type == ui::ET_GESTURE_SCROLL_UPDATE && | |
42 !(--update_events_before_cancel_)) { | |
43 // Make sure that we are in the middle of a resizing operation, cancel it | |
44 // and then test that it is exited. | |
45 EXPECT_TRUE(maximize_button_->is_snap_enabled()); | |
46 maximize_button_->DestroyMaximizeMenu(); | |
47 EXPECT_FALSE(maximize_button_->is_snap_enabled()); | |
48 } | |
49 } | |
50 | |
51 private: | |
52 // When this counter reaches 0, the gesture maximize action gets cancelled. | |
53 int update_events_before_cancel_; | |
54 | |
55 // The maximize button which needs to get informed of the gesture termination. | |
56 FrameMaximizeButton* maximize_button_; | |
57 | |
58 DISALLOW_COPY_AND_ASSIGN(CancelCallbackHandler); | |
59 }; | |
60 | |
61 class TestWidgetDelegate : public views::WidgetDelegateView { | |
62 public: | |
63 TestWidgetDelegate() {} | |
64 virtual ~TestWidgetDelegate() {} | |
65 | |
66 // views::WidgetDelegate overrides: | |
67 virtual views::View* GetContentsView() OVERRIDE { | |
68 return this; | |
69 } | |
70 virtual bool CanResize() const OVERRIDE { | |
71 return true; | |
72 } | |
73 virtual bool CanMaximize() const OVERRIDE { | |
74 return true; | |
75 } | |
76 | |
77 ash::FrameCaptionButtonContainerView* caption_button_container() { | |
78 return caption_button_container_; | |
79 } | |
80 | |
81 private: | |
82 // Overridden from views::View: | |
83 virtual void Layout() OVERRIDE { | |
84 caption_button_container_->Layout(); | |
85 | |
86 // Right align the caption button container. | |
87 gfx::Size preferred_size = caption_button_container_->GetPreferredSize(); | |
88 caption_button_container_->SetBounds(width() - preferred_size.width(), 0, | |
89 preferred_size.width(), preferred_size.height()); | |
90 } | |
91 | |
92 virtual void ViewHierarchyChanged( | |
93 const ViewHierarchyChangedDetails& details) OVERRIDE { | |
94 if (details.is_add && details.child == this) { | |
95 caption_button_container_ = new FrameCaptionButtonContainerView( | |
96 GetWidget(), FrameCaptionButtonContainerView::MINIMIZE_ALLOWED); | |
97 | |
98 // Set arbitrary images for the container's buttons so that the buttons | |
99 // have non-empty sizes. | |
100 for (int icon = 0; icon < CAPTION_BUTTON_ICON_COUNT; ++icon) { | |
101 caption_button_container_->SetButtonImages( | |
102 static_cast<CaptionButtonIcon>(icon), | |
103 IDR_AURA_WINDOW_CONTROL_ICON_CLOSE, | |
104 IDR_AURA_WINDOW_CONTROL_ICON_CLOSE_I, | |
105 IDR_AURA_WINDOW_CONTROL_BACKGROUND_H, | |
106 IDR_AURA_WINDOW_CONTROL_BACKGROUND_P); | |
107 } | |
108 | |
109 AddChildView(caption_button_container_); | |
110 } | |
111 } | |
112 | |
113 // Not owned. | |
114 ash::FrameCaptionButtonContainerView* caption_button_container_; | |
115 | |
116 DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate); | |
117 }; | |
118 | |
119 } // namespace | |
120 | |
121 class FrameMaximizeButtonTest : public ash::test::AshTestBase { | |
122 public: | |
123 FrameMaximizeButtonTest() {} | |
124 virtual ~FrameMaximizeButtonTest() {} | |
125 | |
126 // The returned widget takes ownership of |delegate|. | |
127 views::Widget* CreateWidget(views::WidgetDelegate* delegate) { | |
128 views::Widget::InitParams params( | |
129 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); | |
130 views::Widget* widget = new views::Widget; | |
131 params.context = CurrentContext(); | |
132 params.delegate = delegate; | |
133 params.bounds = gfx::Rect(10, 10, 100, 100); | |
134 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; | |
135 widget->Init(params); | |
136 widget->Show(); | |
137 return widget; | |
138 } | |
139 | |
140 void CloseWidget() { | |
141 if (widget_) | |
142 widget_->CloseNow(); | |
143 widget_ = NULL; | |
144 } | |
145 | |
146 virtual void SetUp() OVERRIDE { | |
147 AshTestBase::SetUp(); | |
148 | |
149 CommandLine::ForCurrentProcess()->AppendSwitch( | |
150 switches::kAshDisableAlternateFrameCaptionButtonStyle); | |
151 | |
152 TestWidgetDelegate* delegate = new TestWidgetDelegate(); | |
153 widget_ = CreateWidget(delegate); | |
154 FrameCaptionButtonContainerView* caption_button_container = | |
155 delegate->caption_button_container(); | |
156 | |
157 FrameCaptionButtonContainerView::TestApi test(caption_button_container); | |
158 maximize_button_ = static_cast<FrameMaximizeButton*>( | |
159 test.size_button()); | |
160 } | |
161 | |
162 virtual void TearDown() OVERRIDE { | |
163 CloseWidget(); | |
164 AshTestBase::TearDown(); | |
165 } | |
166 | |
167 views::Widget* widget() { return widget_; } | |
168 | |
169 FrameMaximizeButton* maximize_button() { return maximize_button_; } | |
170 | |
171 private: | |
172 views::Widget* widget_; | |
173 FrameMaximizeButton* maximize_button_; | |
174 | |
175 DISALLOW_COPY_AND_ASSIGN(FrameMaximizeButtonTest); | |
176 }; | |
177 | |
178 // Tests that clicking on the resize-button toggles between maximize and normal | |
179 // state. | |
180 TEST_F(FrameMaximizeButtonTest, ResizeButtonToggleMaximize) { | |
181 wm::WindowState* window_state = | |
182 wm::GetWindowState(widget()->GetNativeWindow()); | |
183 views::View* view = maximize_button(); | |
184 gfx::Point center = view->GetBoundsInScreen().CenterPoint(); | |
185 | |
186 aura::test::EventGenerator generator( | |
187 window_state->window()->GetRootWindow(), center); | |
188 | |
189 EXPECT_FALSE(window_state->IsMaximized()); | |
190 | |
191 generator.ClickLeftButton(); | |
192 RunAllPendingInMessageLoop(); | |
193 EXPECT_TRUE(window_state->IsMaximized()); | |
194 | |
195 center = view->GetBoundsInScreen().CenterPoint(); | |
196 generator.MoveMouseTo(center); | |
197 generator.ClickLeftButton(); | |
198 RunAllPendingInMessageLoop(); | |
199 EXPECT_FALSE(window_state->IsMaximized()); | |
200 | |
201 generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint()); | |
202 EXPECT_TRUE(window_state->IsMaximized()); | |
203 | |
204 generator.GestureTapAt(view->GetBoundsInScreen().CenterPoint()); | |
205 EXPECT_FALSE(window_state->IsMaximized()); | |
206 | |
207 generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint()); | |
208 EXPECT_TRUE(window_state->IsMaximized()); | |
209 | |
210 generator.GestureTapDownAndUp(view->GetBoundsInScreen().CenterPoint()); | |
211 EXPECT_FALSE(window_state->IsMaximized()); | |
212 } | |
213 | |
214 #if defined(OS_WIN) | |
215 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 | |
216 #define MAYBE_ResizeButtonDrag DISABLED_ResizeButtonDrag | |
217 #else | |
218 #define MAYBE_ResizeButtonDrag ResizeButtonDrag | |
219 #endif | |
220 | |
221 // Tests that click+dragging on the resize-button tiles or minimizes the window. | |
222 TEST_F(FrameMaximizeButtonTest, MAYBE_ResizeButtonDrag) { | |
223 aura::Window* window = widget()->GetNativeWindow(); | |
224 views::View* view = maximize_button(); | |
225 gfx::Point center = view->GetBoundsInScreen().CenterPoint(); | |
226 | |
227 aura::test::EventGenerator generator(window->GetRootWindow(), center); | |
228 | |
229 wm::WindowState* window_state = wm::GetWindowState(window); | |
230 EXPECT_TRUE(window_state->IsNormalStateType()); | |
231 | |
232 // Snap right. | |
233 { | |
234 generator.PressLeftButton(); | |
235 generator.MoveMouseBy(10, 0); | |
236 generator.ReleaseLeftButton(); | |
237 RunAllPendingInMessageLoop(); | |
238 | |
239 EXPECT_FALSE(window_state->IsMaximized()); | |
240 EXPECT_FALSE(window_state->IsMinimized()); | |
241 EXPECT_EQ(wm::GetDefaultRightSnappedWindowBoundsInParent(window).ToString(), | |
242 window->bounds().ToString()); | |
243 } | |
244 | |
245 // Snap left. | |
246 { | |
247 center = view->GetBoundsInScreen().CenterPoint(); | |
248 generator.MoveMouseTo(center); | |
249 generator.PressLeftButton(); | |
250 generator.MoveMouseBy(-10, 0); | |
251 generator.ReleaseLeftButton(); | |
252 RunAllPendingInMessageLoop(); | |
253 | |
254 EXPECT_FALSE(window_state->IsMaximized()); | |
255 EXPECT_FALSE(window_state->IsMinimized()); | |
256 EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(), | |
257 window->bounds().ToString()); | |
258 } | |
259 | |
260 // Minimize. | |
261 { | |
262 center = view->GetBoundsInScreen().CenterPoint(); | |
263 generator.MoveMouseTo(center); | |
264 generator.PressLeftButton(); | |
265 generator.MoveMouseBy(0, 10); | |
266 generator.ReleaseLeftButton(); | |
267 RunAllPendingInMessageLoop(); | |
268 | |
269 EXPECT_TRUE(window_state->IsMinimized()); | |
270 } | |
271 | |
272 window_state->Restore(); | |
273 | |
274 // Now test the same behaviour for gesture events. | |
275 | |
276 // Snap right. | |
277 { | |
278 center = view->GetBoundsInScreen().CenterPoint(); | |
279 gfx::Point end = center; | |
280 end.Offset(80, 0); | |
281 generator.GestureScrollSequence(center, end, | |
282 base::TimeDelta::FromMilliseconds(100), | |
283 3); | |
284 RunAllPendingInMessageLoop(); | |
285 | |
286 EXPECT_FALSE(window_state->IsMaximized()); | |
287 EXPECT_FALSE(window_state->IsMinimized()); | |
288 // This is a short resizing distance and different touch behavior | |
289 // applies which leads in half of the screen being used. | |
290 EXPECT_EQ("400,0 400x553", window->bounds().ToString()); | |
291 } | |
292 | |
293 // Snap left. | |
294 { | |
295 center = view->GetBoundsInScreen().CenterPoint(); | |
296 gfx::Point end = center; | |
297 end.Offset(-80, 0); | |
298 generator.GestureScrollSequence(center, end, | |
299 base::TimeDelta::FromMilliseconds(100), | |
300 3); | |
301 RunAllPendingInMessageLoop(); | |
302 | |
303 EXPECT_FALSE(window_state->IsMaximized()); | |
304 EXPECT_FALSE(window_state->IsMinimized()); | |
305 EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(), | |
306 window->bounds().ToString()); | |
307 } | |
308 | |
309 // Minimize. | |
310 { | |
311 center = view->GetBoundsInScreen().CenterPoint(); | |
312 gfx::Point end = center; | |
313 end.Offset(0, 40); | |
314 generator.GestureScrollSequence(center, end, | |
315 base::TimeDelta::FromMilliseconds(100), | |
316 3); | |
317 RunAllPendingInMessageLoop(); | |
318 | |
319 EXPECT_TRUE(window_state->IsMinimized()); | |
320 } | |
321 | |
322 // Test with gesture events. | |
323 } | |
324 | |
325 // Test that closing the (browser) window with an opened balloon does not | |
326 // crash the system. In other words: Make sure that shutting down the frame | |
327 // destroys the opened balloon in an orderly fashion. | |
328 TEST_F(FrameMaximizeButtonTest, MaximizeButtonExternalShutDown) { | |
329 aura::Window* window = widget()->GetNativeWindow(); | |
330 ash::FrameMaximizeButton* maximize_button = | |
331 FrameMaximizeButtonTest::maximize_button(); | |
332 maximize_button->set_bubble_appearance_delay_ms(0); | |
333 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
334 gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); | |
335 | |
336 aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); | |
337 EXPECT_FALSE(maximize_button->maximizer()); | |
338 EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); | |
339 | |
340 // Move the mouse cursor over the button to bring up the maximizer bubble. | |
341 generator.MoveMouseTo(button_pos); | |
342 EXPECT_TRUE(maximize_button->maximizer()); | |
343 | |
344 // Even though the widget is closing the bubble menu should not crash upon | |
345 // its delayed destruction. | |
346 CloseWidget(); | |
347 } | |
348 | |
349 // Test that maximizing the browser after hovering in does not crash the system | |
350 // when the observer gets removed in the bubble destruction process. | |
351 TEST_F(FrameMaximizeButtonTest, MaximizeOnHoverThenClick) { | |
352 aura::Window* window = widget()->GetNativeWindow(); | |
353 ash::FrameMaximizeButton* maximize_button = | |
354 FrameMaximizeButtonTest::maximize_button(); | |
355 maximize_button->set_bubble_appearance_delay_ms(0); | |
356 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
357 gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); | |
358 | |
359 aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); | |
360 EXPECT_FALSE(maximize_button->maximizer()); | |
361 EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); | |
362 | |
363 // Move the mouse cursor over the button to bring up the maximizer bubble. | |
364 generator.MoveMouseTo(button_pos); | |
365 EXPECT_TRUE(maximize_button->maximizer()); | |
366 generator.ClickLeftButton(); | |
367 EXPECT_TRUE(wm::GetWindowState(window)->IsMaximized()); | |
368 } | |
369 | |
370 // Test that hovering over a button in the balloon dialog will show the phantom | |
371 // window. Moving then away from the button will hide it again. Then check that | |
372 // pressing and dragging the button itself off the button will also release the | |
373 // phantom window. | |
374 TEST_F(FrameMaximizeButtonTest, MaximizeLeftButtonDragOut) { | |
375 aura::Window* window = widget()->GetNativeWindow(); | |
376 ash::FrameMaximizeButton* maximize_button = | |
377 FrameMaximizeButtonTest::maximize_button(); | |
378 maximize_button->set_bubble_appearance_delay_ms(0); | |
379 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
380 gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); | |
381 | |
382 aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); | |
383 EXPECT_FALSE(maximize_button->maximizer()); | |
384 EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); | |
385 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
386 | |
387 // Move the mouse cursor over the button to bring up the maximizer bubble. | |
388 generator.MoveMouseTo(button_pos); | |
389 EXPECT_TRUE(maximize_button->maximizer()); | |
390 | |
391 // Move the mouse over the left maximize button. | |
392 gfx::Point left_max_pos = maximize_button->maximizer()-> | |
393 GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); | |
394 | |
395 generator.MoveMouseTo(left_max_pos); | |
396 // Expect the phantom window to be open. | |
397 EXPECT_TRUE(maximize_button->phantom_window_open()); | |
398 | |
399 // Move away to see the window being destroyed. | |
400 generator.MoveMouseTo(off_pos); | |
401 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
402 | |
403 // Move back over the button. | |
404 generator.MoveMouseTo(button_pos); | |
405 generator.MoveMouseTo(left_max_pos); | |
406 EXPECT_TRUE(maximize_button->phantom_window_open()); | |
407 | |
408 // Press button and drag out of dialog. | |
409 generator.PressLeftButton(); | |
410 generator.MoveMouseTo(off_pos); | |
411 generator.ReleaseLeftButton(); | |
412 | |
413 // Check that the phantom window is also gone. | |
414 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
415 } | |
416 | |
417 // Test that clicking a button in the maximizer bubble (in this case the | |
418 // maximize left button) will do the requested action. | |
419 TEST_F(FrameMaximizeButtonTest, MaximizeLeftByButton) { | |
420 aura::Window* window = widget()->GetNativeWindow(); | |
421 | |
422 ash::FrameMaximizeButton* maximize_button = | |
423 FrameMaximizeButtonTest::maximize_button(); | |
424 maximize_button->set_bubble_appearance_delay_ms(0); | |
425 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
426 gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); | |
427 | |
428 aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); | |
429 EXPECT_FALSE(maximize_button->maximizer()); | |
430 EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); | |
431 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
432 | |
433 // Move the mouse cursor over the button to bring up the maximizer bubble. | |
434 generator.MoveMouseTo(button_pos); | |
435 EXPECT_TRUE(maximize_button->maximizer()); | |
436 | |
437 // Move the mouse over the left maximize button. | |
438 gfx::Point left_max_pos = maximize_button->maximizer()-> | |
439 GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); | |
440 generator.MoveMouseTo(left_max_pos); | |
441 EXPECT_TRUE(maximize_button->phantom_window_open()); | |
442 generator.ClickLeftButton(); | |
443 | |
444 EXPECT_FALSE(maximize_button->maximizer()); | |
445 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
446 | |
447 wm::WindowState* window_state = wm::GetWindowState(window); | |
448 EXPECT_FALSE(window_state->IsMaximized()); | |
449 EXPECT_FALSE(window_state->IsMinimized()); | |
450 EXPECT_EQ(wm::GetDefaultLeftSnappedWindowBoundsInParent(window).ToString(), | |
451 window->bounds().ToString()); | |
452 } | |
453 | |
454 // Test that the activation focus does not change when the bubble gets shown. | |
455 TEST_F(FrameMaximizeButtonTest, MaximizeKeepFocus) { | |
456 aura::Window* window = widget()->GetNativeWindow(); | |
457 ash::FrameMaximizeButton* maximize_button = | |
458 FrameMaximizeButtonTest::maximize_button(); | |
459 maximize_button->set_bubble_appearance_delay_ms(0); | |
460 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
461 gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); | |
462 | |
463 aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); | |
464 EXPECT_FALSE(maximize_button->maximizer()); | |
465 EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); | |
466 | |
467 aura::Window* active = | |
468 aura::client::GetFocusClient(window)->GetFocusedWindow(); | |
469 | |
470 // Move the mouse cursor over the button to bring up the maximizer bubble. | |
471 generator.MoveMouseTo(button_pos); | |
472 EXPECT_TRUE(maximize_button->maximizer()); | |
473 | |
474 // Check that the focused window is still the same. | |
475 EXPECT_EQ(active, aura::client::GetFocusClient(window)->GetFocusedWindow()); | |
476 } | |
477 | |
478 TEST_F(FrameMaximizeButtonTest, MaximizeTap) { | |
479 aura::Window* window = widget()->GetNativeWindow(); | |
480 aura::Window* root_window = window->GetRootWindow(); | |
481 ash::FrameMaximizeButton* maximize_button = | |
482 FrameMaximizeButtonTest::maximize_button(); | |
483 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
484 | |
485 const int touch_default_radius = | |
486 ui::GestureConfiguration::default_radius(); | |
487 ui::GestureConfiguration::set_default_radius(0); | |
488 | |
489 ui::EventProcessor* dispatcher = root_window->GetHost()->event_processor(); | |
490 const int kTouchId = 2; | |
491 ui::TouchEvent press(ui::ET_TOUCH_PRESSED, | |
492 button_pos, | |
493 kTouchId, | |
494 ui::EventTimeForNow()); | |
495 ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&press); | |
496 ASSERT_FALSE(details.dispatcher_destroyed); | |
497 | |
498 button_pos.Offset(9, 8); | |
499 ui::TouchEvent release( | |
500 ui::ET_TOUCH_RELEASED, | |
501 button_pos, | |
502 kTouchId, | |
503 press.time_stamp() + base::TimeDelta::FromMilliseconds(50)); | |
504 details = dispatcher->OnEventFromSource(&release); | |
505 ASSERT_FALSE(details.dispatcher_destroyed); | |
506 | |
507 ui::GestureConfiguration::set_default_radius(touch_default_radius); | |
508 } | |
509 | |
510 // Test that only the left button will activate the maximize button. | |
511 TEST_F(FrameMaximizeButtonTest, OnlyLeftButtonMaximizes) { | |
512 aura::Window* window = widget()->GetNativeWindow(); | |
513 ash::FrameMaximizeButton* maximize_button = | |
514 FrameMaximizeButtonTest::maximize_button(); | |
515 maximize_button->set_bubble_appearance_delay_ms(0); | |
516 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
517 gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); | |
518 | |
519 aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); | |
520 EXPECT_FALSE(maximize_button->maximizer()); | |
521 wm::WindowState* window_state = wm::GetWindowState(window); | |
522 EXPECT_TRUE(window_state->IsNormalStateType()); | |
523 EXPECT_FALSE(window_state->IsMaximized()); | |
524 | |
525 // Move the mouse cursor over the button. | |
526 generator.MoveMouseTo(button_pos); | |
527 EXPECT_TRUE(maximize_button->maximizer()); | |
528 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
529 | |
530 // After pressing the left button the button should get triggered. | |
531 generator.PressLeftButton(); | |
532 RunAllPendingInMessageLoop(); | |
533 EXPECT_TRUE(maximize_button->is_snap_enabled()); | |
534 EXPECT_FALSE(window_state->IsMaximized()); | |
535 | |
536 // Pressing the right button then should cancel the operation. | |
537 generator.PressRightButton(); | |
538 RunAllPendingInMessageLoop(); | |
539 EXPECT_FALSE(maximize_button->maximizer()); | |
540 | |
541 // After releasing the second button the window shouldn't be maximized. | |
542 generator.ReleaseRightButton(); | |
543 generator.ReleaseLeftButton(); | |
544 RunAllPendingInMessageLoop(); | |
545 EXPECT_FALSE(window_state->IsMaximized()); | |
546 | |
547 // Second experiment: Starting with right should also not trigger. | |
548 generator.MoveMouseTo(off_pos); | |
549 generator.MoveMouseTo(button_pos); | |
550 EXPECT_TRUE(maximize_button->maximizer()); | |
551 | |
552 // Pressing first the right button should not activate. | |
553 generator.PressRightButton(); | |
554 RunAllPendingInMessageLoop(); | |
555 EXPECT_FALSE(maximize_button->is_snap_enabled()); | |
556 | |
557 // Pressing then additionally the left button shouldn't activate either. | |
558 generator.PressLeftButton(); | |
559 RunAllPendingInMessageLoop(); | |
560 EXPECT_FALSE(maximize_button->is_snap_enabled()); | |
561 generator.ReleaseRightButton(); | |
562 generator.ReleaseLeftButton(); | |
563 EXPECT_FALSE(window_state->IsMaximized()); | |
564 } | |
565 | |
566 // Click a button of window maximize functionality. | |
567 // If |snap_type| is SNAP_NONE the FrameMaximizeButton gets clicked, otherwise | |
568 // the associated snap button. | |
569 // |Window| is the window which owns the maximize button. | |
570 // |maximize_button| is the FrameMaximizeButton which controls the window. | |
571 void ClickMaxButton( | |
572 ash::FrameMaximizeButton* maximize_button, | |
573 aura::Window* window, | |
574 SnapType snap_type) { | |
575 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
576 gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); | |
577 | |
578 aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); | |
579 generator.MoveMouseTo(off_pos); | |
580 EXPECT_FALSE(maximize_button->maximizer()); | |
581 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
582 | |
583 // Move the mouse cursor over the button. | |
584 generator.MoveMouseTo(button_pos); | |
585 EXPECT_TRUE(maximize_button->maximizer()); | |
586 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
587 | |
588 if (snap_type != SNAP_NONE) { | |
589 gfx::Point left_max_pos = maximize_button->maximizer()-> | |
590 GetButtonForUnitTest(snap_type)->GetBoundsInScreen().CenterPoint(); | |
591 generator.MoveMouseTo(left_max_pos); | |
592 EXPECT_TRUE(maximize_button->phantom_window_open()); | |
593 } | |
594 // After pressing the left button the button should get triggered. | |
595 generator.ClickLeftButton(); | |
596 EXPECT_FALSE(maximize_button->maximizer()); | |
597 } | |
598 | |
599 // Test that the restore from left/right maximize is properly done. | |
600 TEST_F(FrameMaximizeButtonTest, MaximizeLeftRestore) { | |
601 aura::Window* window = widget()->GetNativeWindow(); | |
602 gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); | |
603 ash::FrameMaximizeButton* maximize_button = | |
604 FrameMaximizeButtonTest::maximize_button(); | |
605 maximize_button->set_bubble_appearance_delay_ms(0); | |
606 | |
607 ClickMaxButton(maximize_button, window, SNAP_LEFT); | |
608 wm::WindowState* window_state = wm::GetWindowState(window); | |
609 // The window should not be maximized. | |
610 EXPECT_FALSE(window_state->IsMaximized()); | |
611 // But the bounds should be different. | |
612 gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); | |
613 EXPECT_EQ(0, new_bounds.x()); | |
614 EXPECT_EQ(0, new_bounds.y()); | |
615 | |
616 // Now click the same button again to see that it restores. | |
617 ClickMaxButton(maximize_button, window, SNAP_LEFT); | |
618 // But the bounds should be restored. | |
619 new_bounds = widget()->GetWindowBoundsInScreen(); | |
620 EXPECT_EQ(new_bounds.x(), initial_bounds.x()); | |
621 EXPECT_EQ(new_bounds.y(), initial_bounds.x()); | |
622 EXPECT_EQ(new_bounds.width(), initial_bounds.width()); | |
623 EXPECT_EQ(new_bounds.height(), initial_bounds.height()); | |
624 // Make sure that there is no restore rectangle left. | |
625 EXPECT_FALSE(window_state->HasRestoreBounds()); | |
626 } | |
627 | |
628 // Maximize, left/right maximize and then restore should works. | |
629 TEST_F(FrameMaximizeButtonTest, MaximizeMaximizeLeftRestore) { | |
630 aura::Window* window = widget()->GetNativeWindow(); | |
631 gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); | |
632 ash::FrameMaximizeButton* maximize_button = | |
633 FrameMaximizeButtonTest::maximize_button(); | |
634 maximize_button->set_bubble_appearance_delay_ms(0); | |
635 | |
636 ClickMaxButton(maximize_button, window, SNAP_NONE); | |
637 | |
638 wm::WindowState* window_state = wm::GetWindowState(window); | |
639 EXPECT_TRUE(window_state->IsMaximized()); | |
640 | |
641 ClickMaxButton(maximize_button, window, SNAP_LEFT); | |
642 EXPECT_FALSE(window_state->IsMaximized()); | |
643 gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); | |
644 EXPECT_EQ(0, new_bounds.x()); | |
645 EXPECT_EQ(0, new_bounds.y()); | |
646 | |
647 // Now click the same button again to see that it restores. | |
648 ClickMaxButton(maximize_button, window, SNAP_LEFT); | |
649 RunAllPendingInMessageLoop(); | |
650 // But the bounds should be restored. | |
651 new_bounds = widget()->GetWindowBoundsInScreen(); | |
652 EXPECT_EQ(new_bounds.x(), initial_bounds.x()); | |
653 EXPECT_EQ(new_bounds.y(), initial_bounds.x()); | |
654 EXPECT_EQ(new_bounds.width(), initial_bounds.width()); | |
655 EXPECT_EQ(new_bounds.height(), initial_bounds.height()); | |
656 // Make sure that there is no restore rectangle left. | |
657 EXPECT_FALSE(window_state->HasRestoreBounds()); | |
658 } | |
659 | |
660 // Left/right maximize, maximize and then restore should work. | |
661 TEST_F(FrameMaximizeButtonTest, MaximizeSnapLeftRestore) { | |
662 aura::Window* window = widget()->GetNativeWindow(); | |
663 gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); | |
664 ash::FrameMaximizeButton* maximize_button = | |
665 FrameMaximizeButtonTest::maximize_button(); | |
666 maximize_button->set_bubble_appearance_delay_ms(0); | |
667 | |
668 ClickMaxButton(maximize_button, window, SNAP_LEFT); | |
669 | |
670 wm::WindowState* window_state = wm::GetWindowState(window); | |
671 EXPECT_FALSE(window_state->IsMaximized()); | |
672 | |
673 ClickMaxButton(maximize_button, window, SNAP_NONE); | |
674 EXPECT_TRUE(window_state->IsMaximized()); | |
675 | |
676 ClickMaxButton(maximize_button, window, SNAP_NONE); | |
677 EXPECT_FALSE(window_state->IsMaximized()); | |
678 gfx::Rect new_bounds = widget()->GetWindowBoundsInScreen(); | |
679 EXPECT_EQ(new_bounds.x(), initial_bounds.x()); | |
680 EXPECT_EQ(new_bounds.y(), initial_bounds.x()); | |
681 EXPECT_EQ(new_bounds.width(), initial_bounds.width()); | |
682 EXPECT_EQ(new_bounds.height(), initial_bounds.height()); | |
683 // Make sure that there is no restore rectangle left. | |
684 EXPECT_FALSE(window_state->HasRestoreBounds()); | |
685 } | |
686 | |
687 // Test that minimizing the window per keyboard closes the maximize bubble. | |
688 TEST_F(FrameMaximizeButtonTest, MinimizePerKeyClosesBubble) { | |
689 aura::Window* window = widget()->GetNativeWindow(); | |
690 ash::FrameMaximizeButton* maximize_button = | |
691 FrameMaximizeButtonTest::maximize_button(); | |
692 | |
693 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
694 gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); | |
695 | |
696 aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); | |
697 generator.MoveMouseTo(off_pos); | |
698 EXPECT_FALSE(maximize_button->maximizer()); | |
699 | |
700 // Move the mouse cursor over the maximize button. | |
701 generator.MoveMouseTo(button_pos); | |
702 EXPECT_TRUE(maximize_button->maximizer()); | |
703 | |
704 // We simulate the keystroke by calling minimizeWindow directly. | |
705 wm::WindowState* window_state = wm::GetWindowState(window); | |
706 window_state->Minimize(); | |
707 | |
708 EXPECT_TRUE(window_state->IsMinimized()); | |
709 EXPECT_FALSE(maximize_button->maximizer()); | |
710 } | |
711 | |
712 // Tests that dragging down on the maximize button minimizes the window. | |
713 TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragDownMinimizes) { | |
714 aura::Window* window = widget()->GetNativeWindow(); | |
715 ash::FrameMaximizeButton* maximize_button = | |
716 FrameMaximizeButtonTest::maximize_button(); | |
717 | |
718 wm::WindowState* window_state = wm::GetWindowState(window); | |
719 // Drag down on a maximized window. | |
720 window_state->Maximize(); | |
721 EXPECT_TRUE(window_state->IsMaximized()); | |
722 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
723 gfx::Point off_pos(button_pos.x(), button_pos.y() + 100); | |
724 | |
725 aura::test::EventGenerator generator(window->GetRootWindow()); | |
726 generator.GestureScrollSequence(button_pos, off_pos, | |
727 base::TimeDelta::FromMilliseconds(0), 1); | |
728 | |
729 EXPECT_TRUE(window_state->IsMinimized()); | |
730 EXPECT_FALSE(maximize_button->maximizer()); | |
731 | |
732 // Drag down on a restored window. | |
733 window_state->Restore(); | |
734 | |
735 button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
736 off_pos = gfx::Point(button_pos.x(), button_pos.y() + 200); | |
737 generator.GestureScrollSequence(button_pos, off_pos, | |
738 base::TimeDelta::FromMilliseconds(10), 1); | |
739 EXPECT_TRUE(window_state->IsMinimized()); | |
740 EXPECT_FALSE(maximize_button->maximizer()); | |
741 } | |
742 | |
743 // Tests that dragging Left and pressing ESC does properly abort. | |
744 TEST_F(FrameMaximizeButtonTest, MaximizeButtonDragLeftEscapeExits) { | |
745 aura::Window* window = widget()->GetNativeWindow(); | |
746 gfx::Rect initial_bounds = widget()->GetWindowBoundsInScreen(); | |
747 ash::FrameMaximizeButton* maximize_button = | |
748 FrameMaximizeButtonTest::maximize_button(); | |
749 | |
750 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
751 gfx::Point off_pos(button_pos.x() - button_pos.x() / 2, button_pos.y()); | |
752 | |
753 const int kGestureSteps = 10; | |
754 CancelCallbackHandler cancel_handler(kGestureSteps / 2, maximize_button); | |
755 aura::test::EventGenerator generator(window->GetRootWindow()); | |
756 generator.GestureScrollSequenceWithCallback( | |
757 button_pos, | |
758 off_pos, | |
759 base::TimeDelta::FromMilliseconds(0), | |
760 kGestureSteps, | |
761 base::Bind(&CancelCallbackHandler::CountedCancelCallback, | |
762 base::Unretained(&cancel_handler))); | |
763 | |
764 // Check that there was no size change. | |
765 EXPECT_EQ(widget()->GetWindowBoundsInScreen().size().ToString(), | |
766 initial_bounds.size().ToString()); | |
767 // Check that there is no phantom window left open. | |
768 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
769 } | |
770 | |
771 // Test that hovering over a button in the maximizer bubble and switching | |
772 // activation without moving the mouse properly aborts. | |
773 TEST_F(FrameMaximizeButtonTest, LossOfActivationWhileMaximizeBubbleOpenAborts) { | |
774 aura::Window* window = widget()->GetNativeWindow(); | |
775 ash::FrameMaximizeButton* maximize_button = | |
776 FrameMaximizeButtonTest::maximize_button(); | |
777 maximize_button->set_bubble_appearance_delay_ms(0); | |
778 | |
779 gfx::Rect initial_bounds = window->GetBoundsInScreen(); | |
780 EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); | |
781 EXPECT_TRUE(widget()->IsActive()); | |
782 | |
783 // Move the mouse over the maximize button in order to bring up the maximizer | |
784 // bubble. | |
785 gfx::Point button_pos = maximize_button->GetBoundsInScreen().CenterPoint(); | |
786 gfx::Point off_pos(button_pos.x() + 100, button_pos.y() + 100); | |
787 aura::test::EventGenerator generator(window->GetRootWindow(), off_pos); | |
788 generator.MoveMouseTo(button_pos); | |
789 EXPECT_TRUE(maximize_button->maximizer()); | |
790 | |
791 // Hover the mouse over the left maximize button in the maximizer bubble to | |
792 // show the phantom window. | |
793 gfx::Point left_max_pos = maximize_button->maximizer()-> | |
794 GetButtonForUnitTest(SNAP_LEFT)->GetBoundsInScreen().CenterPoint(); | |
795 generator.MoveMouseTo(left_max_pos); | |
796 EXPECT_TRUE(maximize_button->phantom_window_open()); | |
797 | |
798 // Change activation by creating a new window. This could be done via an | |
799 // accelerator. The root window takes ownership of |just_created|. | |
800 views::Widget* just_created = views::Widget::CreateWindowWithContextAndBounds( | |
801 NULL, widget()->GetNativeWindow(), gfx::Rect(100, 100)); | |
802 just_created->Show(); | |
803 just_created->Activate(); | |
804 EXPECT_FALSE(widget()->IsActive()); | |
805 | |
806 // Test that we have properly reset the state of the now inactive window. | |
807 EXPECT_FALSE(maximize_button->maximizer()); | |
808 EXPECT_FALSE(maximize_button->phantom_window_open()); | |
809 EXPECT_TRUE(wm::GetWindowState(window)->IsNormalStateType()); | |
810 EXPECT_EQ(initial_bounds.ToString(), window->GetBoundsInScreen().ToString()); | |
811 } | |
812 | |
813 } // namespace test | |
814 } // namespace ash | |
OLD | NEW |