Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ash / wm / panels / panel_window_resizer_unittest.cc
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 "ash/wm/panels/panel_window_resizer.h"
6
7 #include "ash/root_window_controller.h"
8 #include "ash/shelf/shelf.h"
9 #include "ash/shelf/shelf_layout_manager.h"
10 #include "ash/shelf/shelf_model.h"
11 #include "ash/shelf/shelf_types.h"
12 #include "ash/shelf/shelf_util.h"
13 #include "ash/shelf/shelf_widget.h"
14 #include "ash/shell.h"
15 #include "ash/shell_window_ids.h"
16 #include "ash/test/ash_test_base.h"
17 #include "ash/test/cursor_manager_test_api.h"
18 #include "ash/test/shell_test_api.h"
19 #include "ash/test/test_shelf_delegate.h"
20 #include "ash/wm/drag_window_resizer.h"
21 #include "ash/wm/panels/panel_layout_manager.h"
22 #include "ash/wm/window_state.h"
23 #include "base/win/windows_version.h"
24 #include "ui/aura/client/aura_constants.h"
25 #include "ui/aura/root_window.h"
26 #include "ui/base/hit_test.h"
27 #include "ui/base/l10n/l10n_util.h"
28 #include "ui/base/ui_base_types.h"
29 #include "ui/views/corewm/window_util.h"
30 #include "ui/views/widget/widget.h"
31
32 namespace ash {
33 namespace internal {
34
35 class PanelWindowResizerTest : public test::AshTestBase {
36  public:
37   PanelWindowResizerTest() {}
38   virtual ~PanelWindowResizerTest() {}
39
40   virtual void SetUp() OVERRIDE {
41     AshTestBase::SetUp();
42     UpdateDisplay("600x400");
43     test::ShellTestApi test_api(Shell::GetInstance());
44     model_ = test_api.shelf_model();
45     shelf_delegate_ = test::TestShelfDelegate::instance();
46   }
47
48   virtual void TearDown() OVERRIDE {
49     AshTestBase::TearDown();
50   }
51
52  protected:
53   gfx::Point CalculateDragPoint(const WindowResizer& resizer,
54                                 int delta_x,
55                                 int delta_y) const {
56     gfx::Point location = resizer.GetInitialLocation();
57     location.set_x(location.x() + delta_x);
58     location.set_y(location.y() + delta_y);
59     return location;
60   }
61
62   aura::Window* CreatePanelWindow(const gfx::Point& origin) {
63     gfx::Rect bounds(origin, gfx::Size(101, 101));
64     aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
65         NULL, ui::wm::WINDOW_TYPE_PANEL, 0, bounds);
66     shelf_delegate_->AddShelfItem(window);
67     PanelLayoutManager* manager =
68         static_cast<PanelLayoutManager*>(
69             Shell::GetContainer(window->GetRootWindow(),
70                                 internal::kShellWindowId_PanelContainer)->
71                 layout_manager());
72     manager->Relayout();
73     return window;
74   }
75
76   void DragStart(aura::Window* window) {
77     resizer_.reset(CreateWindowResizer(
78         window,
79         window->bounds().origin(),
80         HTCAPTION,
81         aura::client::WINDOW_MOVE_SOURCE_MOUSE).release());
82     ASSERT_TRUE(resizer_.get());
83   }
84
85   void DragMove(int dx, int dy) {
86     resizer_->Drag(CalculateDragPoint(*resizer_, dx, dy), 0);
87   }
88
89   void DragEnd() {
90     resizer_->CompleteDrag();
91     resizer_.reset();
92   }
93
94   void DragRevert() {
95     resizer_->RevertDrag();
96     resizer_.reset();
97   }
98
99   // Test dragging the panel slightly, then detaching, and then reattaching
100   // dragging out by the vector (dx, dy).
101   void DetachReattachTest(aura::Window* window, int dx, int dy) {
102     wm::WindowState* window_state = wm::GetWindowState(window);
103     EXPECT_TRUE(window_state->panel_attached());
104     aura::Window* root_window = window->GetRootWindow();
105     EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
106     DragStart(window);
107     gfx::Rect initial_bounds = window->GetBoundsInScreen();
108
109     // Drag the panel slightly. The window should still be snapped to the
110     // launcher.
111     DragMove(dx * 5, dy * 5);
112     EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
113     EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y());
114
115     // Drag further out and the window should now move to the cursor.
116     DragMove(dx * 100, dy * 100);
117     EXPECT_EQ(initial_bounds.x() + dx * 100, window->GetBoundsInScreen().x());
118     EXPECT_EQ(initial_bounds.y() + dy * 100, window->GetBoundsInScreen().y());
119
120     // The panel should be detached when the drag completes.
121     DragEnd();
122
123     EXPECT_FALSE(window_state->panel_attached());
124     EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
125               window->parent()->id());
126     EXPECT_EQ(root_window, window->GetRootWindow());
127
128     DragStart(window);
129     // Drag the panel down.
130     DragMove(dx * -95, dy * -95);
131     // Release the mouse and the panel should be reattached.
132     DragEnd();
133
134     // The panel should be reattached and have snapped to the launcher.
135     EXPECT_TRUE(window_state->panel_attached());
136     EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
137     EXPECT_EQ(initial_bounds.y(), window->GetBoundsInScreen().y());
138     EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
139   }
140
141   void TestWindowOrder(const std::vector<aura::Window*>& window_order) {
142     int panel_index = model_->FirstPanelIndex();
143     EXPECT_EQ((int)(panel_index + window_order.size()), model_->item_count());
144     for (std::vector<aura::Window*>::const_iterator iter =
145          window_order.begin(); iter != window_order.end();
146          ++iter, ++panel_index) {
147       ShelfID id = GetShelfIDForWindow(*iter);
148       EXPECT_EQ(id, model_->items()[panel_index].id);
149     }
150   }
151
152   // Test dragging panel window along the shelf and verify that panel icons
153   // are reordered appropriately.
154   void DragAlongShelfReorder(int dx, int dy) {
155     gfx::Point origin(0, 0);
156     scoped_ptr<aura::Window> w1(CreatePanelWindow(origin));
157     scoped_ptr<aura::Window> w2(CreatePanelWindow(origin));
158     std::vector<aura::Window*> window_order_original;
159     std::vector<aura::Window*> window_order_swapped;
160     window_order_original.push_back(w1.get());
161     window_order_original.push_back(w2.get());
162     window_order_swapped.push_back(w2.get());
163     window_order_swapped.push_back(w1.get());
164     TestWindowOrder(window_order_original);
165
166     // Drag window #2 to the beginning of the shelf.
167     DragStart(w2.get());
168     DragMove(400 * dx, 400 * dy);
169     TestWindowOrder(window_order_swapped);
170     DragEnd();
171
172     // Expect swapped window order.
173     TestWindowOrder(window_order_swapped);
174
175     // Drag window #2 back to the end.
176     DragStart(w2.get());
177     DragMove(-400 * dx, -400 * dy);
178     TestWindowOrder(window_order_original);
179     DragEnd();
180
181     // Expect original order.
182     TestWindowOrder(window_order_original);
183   }
184
185  private:
186   scoped_ptr<WindowResizer> resizer_;
187   internal::PanelLayoutManager* panel_layout_manager_;
188   ShelfModel* model_;
189   test::TestShelfDelegate* shelf_delegate_;
190
191   DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTest);
192 };
193
194 class PanelWindowResizerTextDirectionTest
195     : public PanelWindowResizerTest,
196       public testing::WithParamInterface<bool> {
197  public:
198   PanelWindowResizerTextDirectionTest() : is_rtl_(GetParam()) {}
199   virtual ~PanelWindowResizerTextDirectionTest() {}
200
201   virtual void SetUp() OVERRIDE {
202     original_locale = l10n_util::GetApplicationLocale(std::string());
203     if (is_rtl_)
204       base::i18n::SetICUDefaultLocale("he");
205     PanelWindowResizerTest::SetUp();
206     ASSERT_EQ(is_rtl_, base::i18n::IsRTL());
207   }
208
209   virtual void TearDown() OVERRIDE {
210     if (is_rtl_)
211       base::i18n::SetICUDefaultLocale(original_locale);
212     PanelWindowResizerTest::TearDown();
213   }
214
215  private:
216   bool is_rtl_;
217   std::string original_locale;
218
219   DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTextDirectionTest);
220 };
221
222 // PanelLayoutManager and PanelWindowResizer should work if panels have
223 // transient children of supported types.
224 class PanelWindowResizerTransientTest
225     : public PanelWindowResizerTest,
226       public testing::WithParamInterface<ui::wm::WindowType> {
227  public:
228   PanelWindowResizerTransientTest() : transient_window_type_(GetParam()) {}
229   virtual ~PanelWindowResizerTransientTest() {}
230
231  protected:
232   ui::wm::WindowType transient_window_type_;
233
234  private:
235   DISALLOW_COPY_AND_ASSIGN(PanelWindowResizerTransientTest);
236 };
237
238 // Verifies a window can be dragged from the panel and detached and then
239 // reattached.
240 TEST_F(PanelWindowResizerTest, PanelDetachReattachBottom) {
241  if (!SupportsHostWindowResize())
242     return;
243
244   scoped_ptr<aura::Window> window(
245       CreatePanelWindow(gfx::Point(0, 0)));
246   DetachReattachTest(window.get(), 0, -1);
247 }
248
249 TEST_F(PanelWindowResizerTest, PanelDetachReattachLeft) {
250  if (!SupportsHostWindowResize())
251     return;
252
253   ash::Shell* shell = ash::Shell::GetInstance();
254   shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow());
255   scoped_ptr<aura::Window> window(
256       CreatePanelWindow(gfx::Point(0, 0)));
257   DetachReattachTest(window.get(), 1, 0);
258 }
259
260 TEST_F(PanelWindowResizerTest, PanelDetachReattachRight) {
261   if (!SupportsHostWindowResize())
262     return;
263
264   ash::Shell* shell = ash::Shell::GetInstance();
265   shell->SetShelfAlignment(SHELF_ALIGNMENT_RIGHT,
266                            shell->GetPrimaryRootWindow());
267   scoped_ptr<aura::Window> window(
268       CreatePanelWindow(gfx::Point(0, 0)));
269   DetachReattachTest(window.get(), -1, 0);
270 }
271
272 TEST_F(PanelWindowResizerTest, PanelDetachReattachTop) {
273  if (!SupportsHostWindowResize())
274     return;
275
276   ash::Shell* shell = ash::Shell::GetInstance();
277   shell->SetShelfAlignment(SHELF_ALIGNMENT_TOP, shell->GetPrimaryRootWindow());
278   scoped_ptr<aura::Window> window(
279       CreatePanelWindow(gfx::Point(0, 0)));
280   DetachReattachTest(window.get(), 0, 1);
281 }
282
283 TEST_F(PanelWindowResizerTest, PanelDetachReattachMultipleDisplays) {
284   if (!SupportsMultipleDisplays())
285     return;
286
287   UpdateDisplay("600x400,600x400");
288   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
289   scoped_ptr<aura::Window> window(
290       CreatePanelWindow(gfx::Point(600, 0)));
291   EXPECT_EQ(root_windows[1], window->GetRootWindow());
292   DetachReattachTest(window.get(), 0, -1);
293 }
294
295 TEST_F(PanelWindowResizerTest, DetachThenDragAcrossDisplays) {
296   if (!SupportsMultipleDisplays())
297     return;
298
299   UpdateDisplay("600x400,600x400");
300   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
301   scoped_ptr<aura::Window> window(
302       CreatePanelWindow(gfx::Point(0, 0)));
303   gfx::Rect initial_bounds = window->GetBoundsInScreen();
304   EXPECT_EQ(root_windows[0], window->GetRootWindow());
305   DragStart(window.get());
306   DragMove(0, -100);
307   DragEnd();
308   EXPECT_EQ(root_windows[0], window->GetRootWindow());
309   EXPECT_EQ(initial_bounds.x(), window->GetBoundsInScreen().x());
310   EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y());
311   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
312   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
313
314   DragStart(window.get());
315   DragMove(500, 0);
316   DragEnd();
317   EXPECT_EQ(root_windows[1], window->GetRootWindow());
318   EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
319   EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y());
320   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
321   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
322 }
323
324 TEST_F(PanelWindowResizerTest, DetachAcrossDisplays) {
325   if (!SupportsMultipleDisplays())
326     return;
327
328   UpdateDisplay("600x400,600x400");
329   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
330   scoped_ptr<aura::Window> window(
331       CreatePanelWindow(gfx::Point(0, 0)));
332   gfx::Rect initial_bounds = window->GetBoundsInScreen();
333   EXPECT_EQ(root_windows[0], window->GetRootWindow());
334   DragStart(window.get());
335   DragMove(500, -100);
336   DragEnd();
337   EXPECT_EQ(root_windows[1], window->GetRootWindow());
338   EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
339   EXPECT_EQ(initial_bounds.y() - 100, window->GetBoundsInScreen().y());
340   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
341   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
342 }
343
344 TEST_F(PanelWindowResizerTest, DetachThenAttachToSecondDisplay) {
345   if (!SupportsMultipleDisplays())
346     return;
347
348   UpdateDisplay("600x400,600x600");
349   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
350   scoped_ptr<aura::Window> window(
351       CreatePanelWindow(gfx::Point(0, 0)));
352   gfx::Rect initial_bounds = window->GetBoundsInScreen();
353   EXPECT_EQ(root_windows[0], window->GetRootWindow());
354
355   // Detach the window.
356   DragStart(window.get());
357   DragMove(0, -100);
358   DragEnd();
359   EXPECT_EQ(root_windows[0], window->GetRootWindow());
360   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
361
362   // Drag the window just above the other display's launcher.
363   DragStart(window.get());
364   DragMove(500, 295);
365   EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
366
367   // Should stick to other launcher.
368   EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y());
369   DragEnd();
370
371   // When dropped should move to second display's panel container.
372   EXPECT_EQ(root_windows[1], window->GetRootWindow());
373   EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
374   EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
375 }
376
377 TEST_F(PanelWindowResizerTest, AttachToSecondDisplay) {
378   if (!SupportsMultipleDisplays())
379     return;
380
381   UpdateDisplay("600x400,600x600");
382   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
383   scoped_ptr<aura::Window> window(
384       CreatePanelWindow(gfx::Point(0, 0)));
385   gfx::Rect initial_bounds = window->GetBoundsInScreen();
386   EXPECT_EQ(root_windows[0], window->GetRootWindow());
387
388   // Drag the window just above the other display's launcher.
389   DragStart(window.get());
390   DragMove(500, 195);
391   EXPECT_EQ(initial_bounds.x() + 500, window->GetBoundsInScreen().x());
392
393   // Should stick to other launcher.
394   EXPECT_EQ(initial_bounds.y() + 200, window->GetBoundsInScreen().y());
395   DragEnd();
396
397   // When dropped should move to second display's panel container.
398   EXPECT_EQ(root_windows[1], window->GetRootWindow());
399   EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
400   EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
401 }
402
403 TEST_F(PanelWindowResizerTest, RevertDragRestoresAttachment) {
404   scoped_ptr<aura::Window> window(
405       CreatePanelWindow(gfx::Point(0, 0)));
406   EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
407   EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
408   DragStart(window.get());
409   DragMove(0, -100);
410   DragRevert();
411   EXPECT_TRUE(wm::GetWindowState(window.get())->panel_attached());
412   EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
413
414   // Detach panel.
415   DragStart(window.get());
416   DragMove(0, -100);
417   DragEnd();
418   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
419   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
420
421   // Drag back to launcher.
422   DragStart(window.get());
423   DragMove(0, 100);
424
425   // When the drag is reverted it should remain detached.
426   DragRevert();
427   EXPECT_FALSE(wm::GetWindowState(window.get())->panel_attached());
428   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
429 }
430
431 TEST_F(PanelWindowResizerTest, DragMovesToPanelLayer) {
432   scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Point(0, 0)));
433   DragStart(window.get());
434   DragMove(0, -100);
435   DragEnd();
436   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
437
438   // While moving the panel window should be moved to the panel container.
439   DragStart(window.get());
440   DragMove(20, 0);
441   EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
442   DragEnd();
443
444   // When dropped it should return to the default container.
445   EXPECT_EQ(internal::kShellWindowId_DefaultContainer,
446             window->parent()->id());
447 }
448
449 TEST_P(PanelWindowResizerTextDirectionTest, DragReordersPanelsHorizontal) {
450   if (!SupportsHostWindowResize())
451     return;
452
453   DragAlongShelfReorder(base::i18n::IsRTL() ? 1 : -1, 0);
454 }
455
456 TEST_F(PanelWindowResizerTest, DragReordersPanelsVertical) {
457   if (!SupportsHostWindowResize())
458     return;
459
460   ash::Shell* shell = ash::Shell::GetInstance();
461   shell->SetShelfAlignment(SHELF_ALIGNMENT_LEFT, shell->GetPrimaryRootWindow());
462   DragAlongShelfReorder(0, -1);
463 }
464
465 // Tests that panels can have transient children of different types.
466 // The transient children should be reparented in sync with the panel.
467 TEST_P(PanelWindowResizerTransientTest, PanelWithTransientChild) {
468   if (!SupportsHostWindowResize())
469     return;
470
471   scoped_ptr<aura::Window> window(CreatePanelWindow(gfx::Point(0, 0)));
472   scoped_ptr<aura::Window> child(CreateTestWindowInShellWithDelegateAndType(
473       NULL, transient_window_type_, 0, gfx::Rect(20, 20, 150, 40)));
474   views::corewm::AddTransientChild(window.get(), child.get());
475   if (window->parent() != child->parent())
476     window->parent()->AddChild(child.get());
477   EXPECT_EQ(window.get(), views::corewm::GetTransientParent(child.get()));
478
479   // Drag the child to the shelf. Its new position should not be overridden.
480   const gfx::Rect attached_bounds(window->GetBoundsInScreen());
481   const int dy = window->GetBoundsInScreen().bottom() -
482       child->GetBoundsInScreen().bottom();
483   DragStart(child.get());
484   DragMove(50, dy);
485   // While moving the transient child window should be in the panel container.
486   EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id());
487   DragEnd();
488   // Child should move, |window| should not.
489   EXPECT_EQ(gfx::Point(20 + 50, 20 + dy).ToString(),
490             child->GetBoundsInScreen().origin().ToString());
491   EXPECT_EQ(attached_bounds.ToString(), window->GetBoundsInScreen().ToString());
492
493   // Drag the child along the the shelf past the |window|.
494   // Its new position should not be overridden.
495   DragStart(child.get());
496   DragMove(350, 0);
497   // While moving the transient child window should be in the panel container.
498   EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id());
499   DragEnd();
500   // |child| should move, |window| should not.
501   EXPECT_EQ(gfx::Point(20 + 50 + 350, 20 + dy).ToString(),
502             child->GetBoundsInScreen().origin().ToString());
503   EXPECT_EQ(attached_bounds.ToString(), window->GetBoundsInScreen().ToString());
504
505   DragStart(window.get());
506   DragMove(0, -100);
507   // While moving the windows should be in the panel container.
508   EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
509   EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id());
510   DragEnd();
511   // When dropped they should return to the default container.
512   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
513   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, child->parent()->id());
514
515   // While moving the window and child should be moved to the panel container.
516   DragStart(window.get());
517   DragMove(20, 0);
518   EXPECT_EQ(internal::kShellWindowId_PanelContainer, window->parent()->id());
519   EXPECT_EQ(internal::kShellWindowId_PanelContainer, child->parent()->id());
520   DragEnd();
521
522   // When dropped they should return to the default container.
523   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, window->parent()->id());
524   EXPECT_EQ(internal::kShellWindowId_DefaultContainer, child->parent()->id());
525 }
526
527 INSTANTIATE_TEST_CASE_P(LtrRtl, PanelWindowResizerTextDirectionTest,
528                         testing::Bool());
529 INSTANTIATE_TEST_CASE_P(NormalPanelPopup,
530                         PanelWindowResizerTransientTest,
531                         testing::Values(ui::wm::WINDOW_TYPE_NORMAL,
532                                         ui::wm::WINDOW_TYPE_PANEL,
533                                         ui::wm::WINDOW_TYPE_POPUP));
534
535 }  // namespace internal
536 }  // namespace ash