• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/dock/docked_window_layout_manager_observer.h"
13 #include "ash/wm/window_state_observer.h"
14 #include "ash/wm/workspace/snap_types.h"
15 #include "base/basictypes.h"
16 #include "base/compiler_specific.h"
17 #include "base/gtest_prod_util.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/observer_list.h"
20 #include "base/time/time.h"
21 #include "ui/aura/client/activation_change_observer.h"
22 #include "ui/aura/layout_manager.h"
23 #include "ui/aura/window.h"
24 #include "ui/aura/window_observer.h"
25 #include "ui/gfx/rect.h"
26 #include "ui/keyboard/keyboard_controller_observer.h"
27 
28 namespace aura {
29 class Window;
30 }
31 
32 namespace gfx {
33 class Point;
34 }
35 
36 namespace views {
37 class Widget;
38 }
39 
40 namespace ash {
41 class Launcher;
42 
43 namespace internal {
44 class DockedBackgroundWidget;
45 class DockedWindowLayoutManagerObserver;
46 class DockedWindowResizerTest;
47 class ShelfLayoutManager;
48 class WorkspaceController;
49 
50 struct WindowWithHeight {
WindowWithHeightWindowWithHeight51   explicit WindowWithHeight(aura::Window* window) :
52     window_(window),
53     height_(window->bounds().height()) { }
windowWindowWithHeight54   aura::Window* window() { return window_; }
windowWindowWithHeight55   const aura::Window* window() const { return window_; }
56   aura::Window* window_;
57   int height_;
58 };
59 
60 // DockedWindowLayoutManager is responsible for organizing windows when they are
61 // docked to the side of a screen. It is associated with a specific container
62 // window (i.e. kShellWindowId_DockContainer) and controls the layout of any
63 // windows added to that container.
64 //
65 // The constructor takes a |dock_container| argument which is expected to set
66 // its layout manager to this instance, e.g.:
67 // dock_container->SetLayoutManager(
68 //     new DockedWindowLayoutManager(dock_container));
69 //
70 // TODO(varkha): extend BaseLayoutManager instead of LayoutManager to inherit
71 // common functionality.
72 class ASH_EXPORT DockedWindowLayoutManager
73     : public aura::LayoutManager,
74       public ash::ShellObserver,
75       public aura::WindowObserver,
76       public aura::client::ActivationChangeObserver,
77       public keyboard::KeyboardControllerObserver,
78       public ShelfLayoutManagerObserver,
79       public wm::WindowStateObserver {
80  public:
81   // Maximum width of the docked windows area.
82   static const int kMaxDockWidth;
83 
84   // Minimum width of the docked windows area.
85   static const int kMinDockWidth;
86 
87   DockedWindowLayoutManager(aura::Window* dock_container,
88                             WorkspaceController* workspace_controller);
89   virtual ~DockedWindowLayoutManager();
90 
91   // Disconnects observers before container windows get destroyed.
92   void Shutdown();
93 
94   // Management of the observer list.
95   virtual void AddObserver(DockedWindowLayoutManagerObserver* observer);
96   virtual void RemoveObserver(DockedWindowLayoutManagerObserver* observer);
97 
98   // Called by a DockedWindowResizer to update which window is being dragged.
99   // Starts observing the window unless it is a child.
100   void StartDragging(aura::Window* window);
101 
102   // Called by a DockedWindowResizer when a dragged window is docked.
103   void DockDraggedWindow(aura::Window* window);
104 
105   // Called by a DockedWindowResizer when a dragged window is no longer docked.
106   void UndockDraggedWindow();
107 
108   // Called by a DockedWindowResizer when a window is no longer being dragged.
109   // Stops observing the window unless it is a child.
110   // Records |action| by |source| in UMA.
111   void FinishDragging(DockedAction action, DockedActionSource source);
112 
launcher()113   ash::Launcher* launcher() { return launcher_; }
114   void SetLauncher(ash::Launcher* launcher);
115 
116   // Calculates if a window is touching the screen edges and returns edge.
117   DockedAlignment GetAlignmentOfWindow(const aura::Window* window) const;
118 
119   // Used to snap docked windows to the side of screen during drag.
120   DockedAlignment CalculateAlignment() const;
121 
122   // Returns true when a window can be docked. Windows cannot be docked at the
123   // edge used by the launcher shelf or the edge opposite from existing dock.
124   bool CanDockWindow(aura::Window* window, SnapType edge);
125 
dock_container()126   aura::Window* dock_container() const { return dock_container_; }
127 
128   // Returns current bounding rectangle of docked windows area.
docked_bounds()129   const gfx::Rect& docked_bounds() const { return docked_bounds_; }
130 
131   // Returns last known coordinates of |dragged_window_| after Relayout.
dragged_bounds()132   const gfx::Rect dragged_bounds() const { return dragged_bounds_;}
133 
134   // Returns true if currently dragged window is docked at the screen edge.
is_dragged_window_docked()135   bool is_dragged_window_docked() const { return is_dragged_window_docked_; }
136 
137   // Updates docked layout when launcher shelf bounds change.
138   void OnShelfBoundsChanged();
139 
140   // aura::LayoutManager:
141   virtual void OnWindowResized() OVERRIDE;
142   virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
OnWillRemoveWindowFromLayout(aura::Window * child)143   virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
144   virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE;
145   virtual void OnChildWindowVisibilityChanged(aura::Window* child,
146                                               bool visibile) OVERRIDE;
147   virtual void SetChildBounds(aura::Window* child,
148                               const gfx::Rect& requested_bounds) OVERRIDE;
149 
150   // ash::ShellObserver:
151   virtual void OnDisplayWorkAreaInsetsChanged() OVERRIDE;
152   virtual void OnFullscreenStateChanged(bool is_fullscreen,
153                                         aura::Window* root_window) OVERRIDE;
154   virtual void OnShelfAlignmentChanged(aura::Window* root_window) OVERRIDE;
155 
156   // ShelfLayoutManagerObserver:
157   virtual void OnBackgroundUpdated(
158       ShelfBackgroundType background_type,
159       BackgroundAnimatorChangeType change_type) OVERRIDE;
160 
161   // wm::WindowStateObserver:
162   virtual void OnWindowShowTypeChanged(wm::WindowState* window_state,
163                                        wm::WindowShowType old_type) OVERRIDE;
164 
165   // aura::WindowObserver:
166   virtual void OnWindowBoundsChanged(aura::Window* window,
167                                      const gfx::Rect& old_bounds,
168                                      const gfx::Rect& new_bounds) OVERRIDE;
169   virtual void OnWindowVisibilityChanging(aura::Window* window,
170                                           bool visible) OVERRIDE;
171   virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
172 
173   // aura::client::ActivationChangeObserver:
174   virtual void OnWindowActivated(aura::Window* gained_active,
175                                  aura::Window* lost_active) OVERRIDE;
176 
177  private:
178   class ShelfWindowObserver;
179   friend class DockedWindowLayoutManagerTest;
180   friend class DockedWindowResizerTest;
181 
182   // Width of the gap between the docked windows and a workspace.
183   static const int kMinDockGap;
184 
185   // Ideal (starting) width of the dock.
186   static const int kIdealWidth;
187 
188   // Keep at most kMaxVisibleWindows visible in the dock and minimize the rest
189   // (except for |child|).
190   void MaybeMinimizeChildrenExcept(aura::Window* child);
191 
192   // Minimize / restore window and relayout.
193   void MinimizeDockedWindow(wm::WindowState* window_state);
194   void RestoreDockedWindow(wm::WindowState* window_state);
195 
196   // Record user-initiated |action| by |source| in UMA metrics.
197   void RecordUmaAction(DockedAction action, DockedActionSource source);
198 
199   // Updates |docked_width_| and UMA histograms.
200   void UpdateDockedWidth(int width);
201 
202   // Updates docked layout state when a window gets inside the dock.
203   void OnDraggedWindowDocked(aura::Window* window);
204 
205   // Updates docked layout state when a window gets outside the dock.
206   void OnDraggedWindowUndocked();
207 
208   // Returns true if there are any windows currently docked.
209   bool IsAnyWindowDocked();
210 
211   // Called whenever the window layout might change.
212   void Relayout();
213 
214   // Calculates target heights (and fills it in |visible_windows| array) such
215   // that the vertical space is fairly distributed among the windows taking
216   // into account their minimum and maximum size. Returns free vertical space
217   // (positive value) that remains after resizing all windows or deficit
218   // (negative value) if not all the windows fit.
219   int CalculateWindowHeightsAndRemainingRoom(
220       const gfx::Rect work_area,
221       std::vector<WindowWithHeight>* visible_windows);
222 
223   // Calculate ideal width for the docked area. It will get used to adjust the
224   // dragged window or other windows as necessary.
225   int CalculateIdealWidth(const std::vector<WindowWithHeight>& visible_windows);
226 
227   // Fan out windows evenly distributing the overlap or remaining free space.
228   // Adjust the widths of the windows trying to make them all same. If this
229   // is not possible, center the windows in the docked area.
230   void FanOutChildren(const gfx::Rect& work_area,
231                       int ideal_docked_width,
232                       int available_room,
233                       std::vector<WindowWithHeight>* visible_windows);
234 
235   // Updates |docked_bounds_| and workspace insets when bounds of docked windows
236   // area change. Passing |reason| to observers allows selectively skipping
237   // notifications.
238   void UpdateDockBounds(DockedWindowLayoutManagerObserver::Reason reason);
239 
240   // Called whenever the window stacking order needs to be updated (e.g. focus
241   // changes or a window is moved).
242   void UpdateStacking(aura::Window* active_window);
243 
244   // keyboard::KeyboardControllerObserver:
245   virtual void OnKeyboardBoundsChanging(
246       const gfx::Rect& keyboard_bounds) OVERRIDE;
247 
248   // Parent window associated with this layout manager.
249   aura::Window* dock_container_;
250   // Protect against recursive calls to Relayout().
251   bool in_layout_;
252 
253   // A window that is being dragged (whether docked or not).
254   // Windows are tracked by docked layout manager only if they are docked;
255   // however we need to know if a window is being dragged in order to avoid
256   // positioning it or even considering it for layout.
257   aura::Window* dragged_window_;
258 
259   // True if the window being dragged is currently docked.
260   bool is_dragged_window_docked_;
261 
262   // Previously docked windows use a more relaxed dragging sorting algorithm
263   // that uses assumption that a window starts being dragged out of position
264   // that was previously established in Relayout. This allows easier reordering.
265   bool is_dragged_from_dock_;
266 
267   // The launcher to respond to launcher alignment changes.
268   Launcher* launcher_;
269 
270   // Workspace controller that can be checked for fullscreen mode.
271   WorkspaceController* workspace_controller_;
272   // Tracks if any window in the same root window is in fullscreen mode.
273   bool in_fullscreen_;
274   // Current width of the dock.
275   int docked_width_;
276 
277   // Last bounds that were sent to observers.
278   gfx::Rect docked_bounds_;
279 
280   // Target bounds of a docked window being dragged.
281   gfx::Rect dragged_bounds_;
282 
283   // Side of the screen that the dock is positioned at.
284   DockedAlignment alignment_;
285 
286   // The last active window. Used to maintain stacking order even if no windows
287   // are currently focused.
288   aura::Window* last_active_window_;
289 
290   // Timestamp of the last user-initiated action that changed docked state.
291   // Used in UMA metrics.
292   base::Time last_action_time_;
293 
294   // Observes launcher shelf for bounds changes.
295   scoped_ptr<ShelfWindowObserver> shelf_observer_;
296 
297   // Widget used to paint a background for the docked area.
298   scoped_ptr<DockedBackgroundWidget> background_widget_;
299 
300   // Observers of dock bounds changes.
301   ObserverList<DockedWindowLayoutManagerObserver> observer_list_;
302 
303   DISALLOW_COPY_AND_ASSIGN(DockedWindowLayoutManager);
304 };
305 
306 }  // namespace internal
307 }  // namespace ash
308 
309 #endif  // ASH_WM_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_
310