Change behaviour of the Alt-] and Alt-[ keys so that it cycles through SnapLeft/SnapR...
[chromium-blink-merge.git] / ash / wm / dock / docked_window_layout_manager.h
bloba7b59d4eeff70e9f48f56a32a1b0b6e0ebead850
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.
5 #ifndef ASH_WM_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_
6 #define ASH_WM_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_
8 #include "ash/ash_export.h"
9 #include "ash/shelf/shelf_layout_manager_observer.h"
10 #include "ash/shell_observer.h"
11 #include "ash/snap_to_pixel_layout_manager.h"
12 #include "ash/wm/dock/dock_types.h"
13 #include "ash/wm/dock/docked_window_layout_manager_observer.h"
14 #include "ash/wm/window_state_observer.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/window.h"
22 #include "ui/aura/window_observer.h"
23 #include "ui/gfx/rect.h"
24 #include "ui/keyboard/keyboard_controller_observer.h"
25 #include "ui/wm/public/activation_change_observer.h"
27 namespace aura {
28 class Window;
31 namespace gfx {
32 class Point;
35 namespace views {
36 class Widget;
39 namespace ash {
40 class DockedBackgroundWidget;
41 class DockedWindowLayoutManagerObserver;
42 class DockedWindowResizerTest;
43 class Shelf;
44 class ShelfLayoutManager;
45 class WorkspaceController;
47 struct WindowWithHeight {
48 explicit WindowWithHeight(aura::Window* window) :
49 window_(window),
50 height_(window->bounds().height()) { }
51 aura::Window* window() { return window_; }
52 const aura::Window* window() const { return window_; }
53 aura::Window* window_;
54 int height_;
57 // DockedWindowLayoutManager is responsible for organizing windows when they are
58 // docked to the side of a screen. It is associated with a specific container
59 // window (i.e. kShellWindowId_DockContainer) and controls the layout of any
60 // windows added to that container.
62 // The constructor takes a |dock_container| argument which is expected to set
63 // its layout manager to this instance, e.g.:
64 // dock_container->SetLayoutManager(
65 // new DockedWindowLayoutManager(dock_container));
67 // TODO(varkha): extend BaseLayoutManager instead of LayoutManager to inherit
68 // common functionality.
69 class ASH_EXPORT DockedWindowLayoutManager
70 : public SnapToPixelLayoutManager,
71 public ash::ShellObserver,
72 public aura::WindowObserver,
73 public aura::client::ActivationChangeObserver,
74 public keyboard::KeyboardControllerObserver,
75 public ShelfLayoutManagerObserver,
76 public wm::WindowStateObserver {
77 public:
78 // Maximum width of the docked windows area.
79 static const int kMaxDockWidth;
81 // Minimum width of the docked windows area.
82 static const int kMinDockWidth;
84 DockedWindowLayoutManager(aura::Window* dock_container,
85 WorkspaceController* workspace_controller);
86 virtual ~DockedWindowLayoutManager();
88 // Disconnects observers before container windows get destroyed.
89 void Shutdown();
91 // Management of the observer list.
92 virtual void AddObserver(DockedWindowLayoutManagerObserver* observer);
93 virtual void RemoveObserver(DockedWindowLayoutManagerObserver* observer);
95 // Called by a DockedWindowResizer to update which window is being dragged.
96 // Starts observing the window unless it is a child.
97 void StartDragging(aura::Window* window);
99 // Called by a DockedWindowResizer when a dragged window is docked.
100 void DockDraggedWindow(aura::Window* window);
102 // Called by a DockedWindowResizer when a dragged window is no longer docked.
103 void UndockDraggedWindow();
105 // Called by a DockedWindowResizer when a window is no longer being dragged.
106 // Stops observing the window unless it is a child.
107 // Records |action| by |source| in UMA.
108 void FinishDragging(DockedAction action, DockedActionSource source);
110 // Checks the rules and possibly updates the docked layout to match
111 // the |alignment|. May not apply the |alignment| when
112 // the current shelf alignment conflicts. Never clears the |alignment_|.
113 void MaybeSetDesiredDockedAlignment(DockedAlignment alignment);
115 Shelf* shelf() { return shelf_; }
116 void SetShelf(Shelf* shelf);
118 // Calculates if a window is touching the screen edges and returns edge.
119 DockedAlignment GetAlignmentOfWindow(const aura::Window* window) const;
121 // Used to snap docked windows to the side of screen during drag.
122 DockedAlignment CalculateAlignment() const;
124 void set_preferred_alignment(DockedAlignment preferred_alignment) {
125 preferred_alignment_ = preferred_alignment;
128 void set_event_source(DockedActionSource event_source) {
129 event_source_ = event_source;
132 // Returns true when a window can be docked. Windows cannot be docked at the
133 // edge used by the shelf or the edge opposite from existing dock.
134 bool CanDockWindow(aura::Window* window, DockedAlignment desired_alignment);
136 aura::Window* dock_container() const { return dock_container_; }
138 // Returns current bounding rectangle of docked windows area.
139 const gfx::Rect& docked_bounds() const { return docked_bounds_; }
141 // Returns last known coordinates of |dragged_window_| after Relayout.
142 const gfx::Rect dragged_bounds() const { return dragged_bounds_;}
144 // Returns true if currently dragged window is docked at the screen edge.
145 bool is_dragged_window_docked() const { return is_dragged_window_docked_; }
147 // Updates docked layout when shelf bounds change.
148 void OnShelfBoundsChanged();
150 // SnapLayoutManager:
151 virtual void OnWindowResized() override;
152 virtual void OnWindowAddedToLayout(aura::Window* child) override;
153 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) override {}
154 virtual void OnWindowRemovedFromLayout(aura::Window* child) override;
155 virtual void OnChildWindowVisibilityChanged(aura::Window* child,
156 bool visibile) override;
157 virtual void SetChildBounds(aura::Window* child,
158 const gfx::Rect& requested_bounds) override;
160 // ash::ShellObserver:
161 virtual void OnDisplayWorkAreaInsetsChanged() override;
162 virtual void OnFullscreenStateChanged(bool is_fullscreen,
163 aura::Window* root_window) override;
164 virtual void OnShelfAlignmentChanged(aura::Window* root_window) override;
166 // ShelfLayoutManagerObserver:
167 virtual void OnBackgroundUpdated(
168 ShelfBackgroundType background_type,
169 BackgroundAnimatorChangeType change_type) override;
171 // wm::WindowStateObserver:
172 virtual void OnPreWindowStateTypeChange(
173 wm::WindowState* window_state,
174 wm::WindowStateType old_type) override;
176 // aura::WindowObserver:
177 virtual void OnWindowBoundsChanged(aura::Window* window,
178 const gfx::Rect& old_bounds,
179 const gfx::Rect& new_bounds) override;
180 virtual void OnWindowVisibilityChanging(aura::Window* window,
181 bool visible) override;
182 virtual void OnWindowDestroying(aura::Window* window) override;
184 // aura::client::ActivationChangeObserver:
185 virtual void OnWindowActivated(aura::Window* gained_active,
186 aura::Window* lost_active) override;
188 private:
189 class ShelfWindowObserver;
190 friend class DockedWindowLayoutManagerTest;
191 friend class DockedWindowResizerTest;
193 // Width of the gap between the docked windows and a workspace.
194 static const int kMinDockGap;
196 // Ideal (starting) width of the dock.
197 static const int kIdealWidth;
199 // Returns the alignment of the docked windows other than the |child|.
200 DockedAlignment CalculateAlignmentExcept(const aura::Window* child) const;
202 // Determines if the |alignment| is applicable taking into account
203 // the shelf alignment.
204 bool IsDockedAlignmentValid(DockedAlignment alignment) const;
206 // Keep at most kMaxVisibleWindows visible in the dock and minimize the rest
207 // (except for |child|).
208 void MaybeMinimizeChildrenExcept(aura::Window* child);
210 // Minimize / restore window and relayout.
211 void MinimizeDockedWindow(wm::WindowState* window_state);
212 void RestoreDockedWindow(wm::WindowState* window_state);
214 // Record user-initiated |action| by |source| in UMA metrics.
215 void RecordUmaAction(DockedAction action, DockedActionSource source);
217 // Updates |docked_width_| and UMA histograms.
218 void UpdateDockedWidth(int width);
220 // Updates docked layout state when a window gets inside the dock.
221 void OnDraggedWindowDocked(aura::Window* window);
223 // Updates docked layout state when a window gets outside the dock.
224 void OnDraggedWindowUndocked();
226 // Returns true if there are any windows currently docked.
227 bool IsAnyWindowDocked();
229 // Returns DOCKED_ALIGNMENT_LEFT if the |window|'s left edge is closer to
230 // the |dock_container_|'s left edge than the |window|'s right edge to
231 // the |dock_container_|'s right edge. Returns DOCKED_ALIGNMENT_RIGHT
232 // otherwise.
233 DockedAlignment GetEdgeNearestWindow(const aura::Window* window) const;
235 // Called whenever the window layout might change.
236 void Relayout();
238 // Calculates target heights (and fills it in |visible_windows| array) such
239 // that the vertical space is fairly distributed among the windows taking
240 // into account their minimum and maximum size. Returns free vertical space
241 // (positive value) that remains after resizing all windows or deficit
242 // (negative value) if not all the windows fit.
243 int CalculateWindowHeightsAndRemainingRoom(
244 const gfx::Rect work_area,
245 std::vector<WindowWithHeight>* visible_windows);
247 // Calculate ideal width for the docked area. It will get used to adjust the
248 // dragged window or other windows as necessary.
249 int CalculateIdealWidth(const std::vector<WindowWithHeight>& visible_windows);
251 // Fan out windows evenly distributing the overlap or remaining free space.
252 // Adjust the widths of the windows trying to make them all same. If this
253 // is not possible, center the windows in the docked area.
254 void FanOutChildren(const gfx::Rect& work_area,
255 int ideal_docked_width,
256 int available_room,
257 std::vector<WindowWithHeight>* visible_windows);
259 // Updates |docked_bounds_| and workspace insets when bounds of docked windows
260 // area change. Passing |reason| to observers allows selectively skipping
261 // notifications.
262 void UpdateDockBounds(DockedWindowLayoutManagerObserver::Reason reason);
264 // Called whenever the window stacking order needs to be updated (e.g. focus
265 // changes or a window is moved).
266 void UpdateStacking(aura::Window* active_window);
268 // keyboard::KeyboardControllerObserver:
269 virtual void OnKeyboardBoundsChanging(
270 const gfx::Rect& keyboard_bounds) override;
272 // Parent window associated with this layout manager.
273 aura::Window* dock_container_;
274 // Protect against recursive calls to Relayout().
275 bool in_layout_;
277 // A window that is being dragged (whether docked or not).
278 // Windows are tracked by docked layout manager only if they are docked;
279 // however we need to know if a window is being dragged in order to avoid
280 // positioning it or even considering it for layout.
281 aura::Window* dragged_window_;
283 // True if the window being dragged is currently docked.
284 bool is_dragged_window_docked_;
286 // Previously docked windows use a more relaxed dragging sorting algorithm
287 // that uses assumption that a window starts being dragged out of position
288 // that was previously established in Relayout. This allows easier reordering.
289 bool is_dragged_from_dock_;
291 // The shelf to respond to alignment changes.
292 Shelf* shelf_;
294 // Workspace controller that can be checked for fullscreen mode.
295 WorkspaceController* workspace_controller_;
296 // Tracks if any window in the same root window is in fullscreen mode.
297 bool in_fullscreen_;
298 // Current width of the dock.
299 int docked_width_;
301 // Last bounds that were sent to observers.
302 gfx::Rect docked_bounds_;
304 // Target bounds of a docked window being dragged.
305 gfx::Rect dragged_bounds_;
307 // Side of the screen that the dock is positioned at.
308 DockedAlignment alignment_;
310 // The preferred alignment of the next window to be added to docked layout.
311 DockedAlignment preferred_alignment_;
313 // The current event source
314 DockedActionSource event_source_;
316 // The last active window. Used to maintain stacking order even if no windows
317 // are currently focused.
318 aura::Window* last_active_window_;
320 // Timestamp of the last user-initiated action that changed docked state.
321 // Used in UMA metrics.
322 base::Time last_action_time_;
324 // Observes shelf for bounds changes.
325 scoped_ptr<ShelfWindowObserver> shelf_observer_;
327 // Widget used to paint a background for the docked area.
328 scoped_ptr<DockedBackgroundWidget> background_widget_;
330 // Observers of dock bounds changes.
331 ObserverList<DockedWindowLayoutManagerObserver> observer_list_;
333 DISALLOW_COPY_AND_ASSIGN(DockedWindowLayoutManager);
336 } // namespace ash
338 #endif // ASH_WM_DOCK_DOCKED_WINDOW_LAYOUT_MANAGER_H_