Home | History | Annotate | Download | only in dock
      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 "base/basictypes.h"
     15 #include "base/compiler_specific.h"
     16 #include "base/gtest_prod_util.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/observer_list.h"
     19 #include "base/time/time.h"
     20 #include "ui/aura/layout_manager.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 {
     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_;
     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 aura::LayoutManager,
     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 
    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 
    123   aura::Window* dock_container() const { return dock_container_; }
    124 
    125   // Returns current bounding rectangle of docked windows area.
    126   const gfx::Rect& docked_bounds() const { return docked_bounds_; }
    127 
    128   // Returns last known coordinates of |dragged_window_| after Relayout.
    129   const gfx::Rect dragged_bounds() const { return dragged_bounds_;}
    130 
    131   // Returns true if currently dragged window is docked at the screen edge.
    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   // aura::LayoutManager:
    138   virtual void OnWindowResized() OVERRIDE;
    139   virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
    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