1// Copyright (c) 2012 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_WORKSPACE_WINDOW_RESIZER_H_ 6#define ASH_WM_WORKSPACE_WINDOW_RESIZER_H_ 7 8#include <vector> 9 10#include "ash/wm/window_resizer.h" 11#include "ash/wm/workspace/magnetism_matcher.h" 12#include "base/compiler_specific.h" 13#include "base/gtest_prod_util.h" 14#include "base/memory/scoped_ptr.h" 15#include "base/memory/weak_ptr.h" 16#include "ui/aura/window_tracker.h" 17 18namespace ash { 19class DockedWindowLayoutManager; 20class PhantomWindowController; 21class TwoStepEdgeCycler; 22class WindowSize; 23 24namespace wm { 25class WindowState; 26} 27 28// WindowResizer implementation for workspaces. This enforces that windows are 29// not allowed to vertically move or resize outside of the work area. As windows 30// are moved outside the work area they are shrunk. We remember the height of 31// the window before it was moved so that if the window is again moved up we 32// attempt to restore the old height. 33class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { 34 public: 35 // When dragging an attached window this is the min size we'll make sure is 36 // visible. In the vertical direction we take the max of this and that from 37 // the delegate. 38 static const int kMinOnscreenSize; 39 40 // Min height we'll force on screen when dragging the caption. 41 // TODO: this should come from a property on the window. 42 static const int kMinOnscreenHeight; 43 44 // Snap region when dragging close to the edges. That is, as the window gets 45 // this close to an edge of the screen it snaps to the edge. 46 static const int kScreenEdgeInset; 47 48 // Distance in pixels that the cursor must move past an edge for a window 49 // to move or resize beyond that edge. 50 static const int kStickyDistancePixels; 51 52 virtual ~WorkspaceWindowResizer(); 53 54 static WorkspaceWindowResizer* Create( 55 wm::WindowState* window_state, 56 const std::vector<aura::Window*>& attached_windows); 57 58 // WindowResizer: 59 virtual void Drag(const gfx::Point& location_in_parent, 60 int event_flags) OVERRIDE; 61 virtual void CompleteDrag() OVERRIDE; 62 virtual void RevertDrag() OVERRIDE; 63 64 private: 65 WorkspaceWindowResizer(wm::WindowState* window_state, 66 const std::vector<aura::Window*>& attached_windows); 67 68 private: 69 friend class WorkspaceWindowResizerTest; 70 71 // The edge to which the window should be snapped at the end of the drag. 72 enum SnapType { 73 SNAP_LEFT, 74 SNAP_RIGHT, 75 SNAP_NONE 76 }; 77 78 // Lays out the attached windows. |bounds| is the bounds of the main window. 79 void LayoutAttachedWindows(gfx::Rect* bounds); 80 81 // Calculates the new sizes of the attached windows, given that the main 82 // window has been resized (along the primary axis) by |delta|. 83 // |available_size| is the maximum length of the space that the attached 84 // windows are allowed to occupy (ie: the distance between the right/bottom 85 // edge of the primary window and the right/bottom of the desktop area). 86 // Populates |sizes| with the desired sizes of the attached windows, and 87 // returns the number of pixels that couldn't be allocated to the attached 88 // windows (due to min/max size constraints). 89 // Note the return value can be positive or negative, a negative value 90 // indicating that that many pixels couldn't be removed from the attached 91 // windows. 92 int CalculateAttachedSizes( 93 int delta, 94 int available_size, 95 std::vector<int>* sizes) const; 96 97 // Divides |amount| evenly between |sizes|. If |amount| is negative it 98 // indicates how many pixels |sizes| should be shrunk by. 99 // Returns how many pixels failed to be allocated/removed from |sizes|. 100 int GrowFairly(int amount, std::vector<WindowSize>& sizes) const; 101 102 // Calculate the ratio of pixels that each WindowSize in |sizes| should 103 // receive when growing or shrinking. 104 void CalculateGrowthRatios(const std::vector<WindowSize*>& sizes, 105 std::vector<float>* out_ratios) const; 106 107 // Adds a WindowSize to |sizes| for each attached window. 108 void CreateBucketsForAttached(std::vector<WindowSize>* sizes) const; 109 110 // If possible snaps the window to a neary window. Updates |bounds| if there 111 // was a close enough window. 112 void MagneticallySnapToOtherWindows(gfx::Rect* bounds); 113 114 // If possible snaps the resize to a neary window. Updates |bounds| if there 115 // was a close enough window. 116 void MagneticallySnapResizeToOtherWindows(gfx::Rect* bounds); 117 118 // Finds the neareset window to magentically snap to. Updates 119 // |magnetism_window_| and |magnetism_edge_| appropriately. |edges| is a 120 // bitmask of the MagnetismEdges to match again. Returns true if a match is 121 // found. 122 bool UpdateMagnetismWindow(const gfx::Rect& bounds, uint32 edges); 123 124 // Adjusts the bounds of the window: magnetically snapping, ensuring the 125 // window has enough on screen... |snap_size| is the distance from an edge of 126 // the work area before the window is snapped. A value of 0 results in no 127 // snapping. 128 void AdjustBoundsForMainWindow(int snap_size, gfx::Rect* bounds); 129 130 // Stick the window bounds to the work area during a move. 131 bool StickToWorkAreaOnMove(const gfx::Rect& work_area, 132 int sticky_size, 133 gfx::Rect* bounds) const; 134 135 // Stick the window bounds to the work area during a resize. 136 void StickToWorkAreaOnResize(const gfx::Rect& work_area, 137 int sticky_size, 138 gfx::Rect* bounds) const; 139 140 // Returns a coordinate along the primary axis. Used to share code for 141 // left/right multi window resize and top/bottom resize. 142 int PrimaryAxisSize(const gfx::Size& size) const; 143 int PrimaryAxisCoordinate(int x, int y) const; 144 145 // Updates the bounds of the phantom window for window snapping. 146 void UpdateSnapPhantomWindow(const gfx::Point& location, 147 const gfx::Rect& bounds); 148 149 // Restacks the windows z-order position so that one of the windows is at the 150 // top of the z-order, and the rest directly underneath it. 151 void RestackWindows(); 152 153 // Returns the edge to which the window should be snapped to if the user does 154 // no more dragging. SNAP_NONE is returned if the window should not be 155 // snapped. 156 SnapType GetSnapType(const gfx::Point& location) const; 157 158 // Returns true if |bounds_in_parent| are valid bounds for snapped state type 159 // |snapped_type|. 160 bool AreBoundsValidSnappedBounds(wm::WindowStateType snapped_type, 161 const gfx::Rect& bounds_in_parent) const; 162 163 // Docks or undocks the dragged window. 164 void SetDraggedWindowDocked(bool should_dock); 165 166 wm::WindowState* window_state() { return window_state_; } 167 168 const std::vector<aura::Window*> attached_windows_; 169 170 // Returns the currently used instance for test. 171 static WorkspaceWindowResizer* GetInstanceForTest(); 172 173 bool did_lock_cursor_; 174 175 // Set to true once Drag() is invoked and the bounds of the window change. 176 bool did_move_or_resize_; 177 178 // True if the window initially had |bounds_changed_by_user_| set in state. 179 bool initial_bounds_changed_by_user_; 180 181 // The initial size of each of the windows in |attached_windows_| along the 182 // primary axis. 183 std::vector<int> initial_size_; 184 185 // Sum of the minimum sizes of the attached windows. 186 int total_min_; 187 188 // Sum of the sizes in |initial_size_|. 189 int total_initial_size_; 190 191 // Gives a previews of where the the window will end up. Only used if there 192 // is a grid and the caption is being dragged. 193 scoped_ptr<PhantomWindowController> snap_phantom_window_controller_; 194 195 // Used to determine whether the window should be snapped or docked when 196 // the user drags a window to the edge of the screen. 197 scoped_ptr<TwoStepEdgeCycler> edge_cycler_; 198 199 // The edge to which the window should be snapped to at the end of the drag. 200 SnapType snap_type_; 201 202 // Number of mouse moves since the last bounds change. Only used for phantom 203 // placement to track when the mouse is moved while pushed against the edge of 204 // the screen. 205 int num_mouse_moves_since_bounds_change_; 206 207 // The mouse location passed to Drag(). 208 gfx::Point last_mouse_location_; 209 210 // Window the drag has magnetically attached to. 211 aura::Window* magnetism_window_; 212 213 // Used to verify |magnetism_window_| is still valid. 214 aura::WindowTracker window_tracker_; 215 216 // If |magnetism_window_| is non-NULL this indicates how the two windows 217 // should attach. 218 MatchedEdge magnetism_edge_; 219 220 // Dock container window layout manager. 221 DockedWindowLayoutManager* dock_layout_; 222 223 // Used to determine if this has been deleted during a drag such as when a tab 224 // gets dragged into another browser window. 225 base::WeakPtrFactory<WorkspaceWindowResizer> weak_ptr_factory_; 226 227 DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizer); 228}; 229 230} // namespace ash 231 232#endif // ASH_WM_WORKSPACE_WINDOW_RESIZER_H_ 233