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#ifndef ASH_WM_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_
6#define ASH_WM_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_
7
8#include "ash/ash_export.h"
9#include "ash/shelf/shelf_layout_manager_observer.h"
10#include "ash/shell_observer.h"
11#include "ash/wm/dock/dock_types.h"
12#include "ash/wm/property_util.h"
13#include "base/basictypes.h"
14#include "base/compiler_specific.h"
15#include "base/gtest_prod_util.h"
16#include "base/memory/scoped_ptr.h"
17#include "base/observer_list.h"
18#include "ui/aura/client/activation_change_observer.h"
19#include "ui/aura/layout_manager.h"
20#include "ui/aura/window_observer.h"
21#include "ui/gfx/rect.h"
22#include "ui/keyboard/keyboard_controller_observer.h"
23
24namespace aura {
25class Window;
26}
27
28namespace gfx {
29class Point;
30}
31
32namespace views {
33class Widget;
34}
35
36namespace ash {
37class Launcher;
38
39namespace internal {
40class DockedWindowLayoutManagerObserver;
41class DockedWindowResizerTest;
42class ShelfLayoutManager;
43
44// DockedWindowLayoutManager is responsible for organizing windows when they are
45// docked to the side of a screen. It is associated with a specific container
46// window (i.e. kShellWindowId_DockContainer) and controls the layout of any
47// windows added to that container.
48//
49// The constructor takes a |dock_container| argument which is expected to set
50// its layout manager to this instance, e.g.:
51// dock_container->SetLayoutManager(
52//     new DockedWindowLayoutManager(dock_container));
53
54class ASH_EXPORT DockedWindowLayoutManager
55    : public aura::LayoutManager,
56      public ash::ShellObserver,
57      public aura::WindowObserver,
58      public aura::client::ActivationChangeObserver,
59      public keyboard::KeyboardControllerObserver,
60      public ash::ShelfLayoutManagerObserver {
61 public:
62  explicit DockedWindowLayoutManager(aura::Window* dock_container);
63  virtual ~DockedWindowLayoutManager();
64
65  // Disconnects observers before container windows get destroyed.
66  void Shutdown();
67
68  // Management of the observer list.
69  virtual void AddObserver(DockedWindowLayoutManagerObserver* observer);
70  virtual void RemoveObserver(DockedWindowLayoutManagerObserver* observer);
71
72  // Called by a DockedWindowResizer to update which window is being dragged.
73  void StartDragging(aura::Window* window);
74  void FinishDragging();
75
76  // Returns true if a window is touching the side of the screen except 2 cases:
77  // when some other windows are already docked on the other side or
78  // when launcher (shelf) is aligned on the same side.
79  static bool ShouldWindowDock(aura::Window* window,
80                               const gfx::Point& location);
81
82  ash::Launcher* launcher() { return launcher_; }
83  void SetLauncher(ash::Launcher* launcher);
84
85  // Used to snap docked windows to the side of screen during drag.
86  DockedAlignment CalculateAlignment() const;
87
88  // Returns current bounding rectangle of docked windows area.
89  const gfx::Rect& docked_bounds() const { return docked_bounds_; }
90
91  // Currently dragged window should be able to dock on another screen
92  aura::Window* dragged_window() const { return dragged_window_;}
93
94  // aura::LayoutManager:
95  virtual void OnWindowResized() OVERRIDE;
96  virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
97  virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
98  virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE;
99  virtual void OnChildWindowVisibilityChanged(aura::Window* child,
100                                              bool visibile) OVERRIDE;
101  virtual void SetChildBounds(aura::Window* child,
102                              const gfx::Rect& requested_bounds) OVERRIDE;
103
104  // ash::ShellObserver:
105  virtual void OnShelfAlignmentChanged(aura::RootWindow* root_window) OVERRIDE;
106
107  // aura::WindowObserver:
108  virtual void OnWindowPropertyChanged(aura::Window* window,
109                                       const void* key,
110                                       intptr_t old) OVERRIDE;
111  virtual void OnWindowBoundsChanged(aura::Window* window,
112                                     const gfx::Rect& old_bounds,
113                                     const gfx::Rect& new_bounds) OVERRIDE;
114  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
115
116  // aura::client::ActivationChangeObserver:
117  virtual void OnWindowActivated(aura::Window* gained_active,
118                                 aura::Window* lost_active) OVERRIDE;
119
120  // ShelfLayoutManagerObserver:
121  virtual void WillChangeVisibilityState(
122      ShelfVisibilityState new_state) OVERRIDE;
123
124 private:
125  FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, AttachTwoWindowsDetachOne);
126  FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, AttachWindowMaximizeOther);
127  FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, AttachOneTestSticky);
128  FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, ResizeTwoWindows);
129  FRIEND_TEST_ALL_PREFIXES(DockedWindowResizerTest, DragToShelf);
130  friend class DockedWindowLayoutManagerTest;
131  friend class DockedWindowResizerTest;
132
133  // Minimum width of the docked windows area.
134  static const int kMinDockWidth;
135
136  // Maximum width of the docked windows area.
137  static const int kMaxDockWidth;
138
139  // Width of the gap between the docked windows and a workspace.
140  static const int kMinDockGap;
141
142  // Minimize / restore window and relayout.
143  void MinimizeWindow(aura::Window* window);
144  void RestoreWindow(aura::Window* window);
145
146  // Calculates if a window is touching the screen edges and returns edge.
147  DockedAlignment AlignmentOfWindow(const aura::Window* window) const;
148
149  // Called whenever the window layout might change.
150  void Relayout();
151
152  // Updates |docked_bounds_| and workspace insets when bounds of docked windows
153  // area change.
154  void UpdateDockBounds();
155
156  // Called whenever the window stacking order needs to be updated (e.g. focus
157  // changes or a window is moved).
158  void UpdateStacking(aura::Window* active_window);
159
160  // keyboard::KeyboardControllerObserver:
161  virtual void OnKeyboardBoundsChanging(
162      const gfx::Rect& keyboard_bounds) OVERRIDE;
163
164  // Parent window associated with this layout manager.
165  aura::Window* dock_container_;
166  // Protect against recursive calls to Relayout().
167  bool in_layout_;
168  // The docked window being dragged.
169  aura::Window* dragged_window_;
170  // The launcher we are observing for launcher icon changes.
171  Launcher* launcher_;
172  // The shelf layout manager being observed for visibility changes.
173  ShelfLayoutManager* shelf_layout_manager_;
174  // Tracks the visibility of the shelf. Defaults to false when there is no
175  // shelf.
176  bool shelf_hidden_;
177  // Current width of the dock.
178  int docked_width_;
179
180  // Last bounds that were sent to observers.
181  gfx::Rect docked_bounds_;
182
183  // Side of the screen that the dock is positioned at.
184  DockedAlignment alignment_;
185
186  // The last active window. Used to maintain stacking order even if no windows
187  // are currently focused.
188  aura::Window* last_active_window_;
189
190  // Widget used to paint a background for the docked area.
191  scoped_ptr<views::Widget> background_widget_;
192
193  // Observers of dock bounds changes.
194  ObserverList<DockedWindowLayoutManagerObserver> observer_list_;
195
196  DISALLOW_COPY_AND_ASSIGN(DockedWindowLayoutManager);
197};
198
199}  // namespace internal
200}  // namespace ash
201
202#endif  // ASH_WM_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_
203