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