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