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_MULTI_WINDOW_RESIZE_CONTROLLER_H_ 6 #define ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_ 7 8 #include <vector> 9 10 #include "ash/ash_export.h" 11 #include "base/basictypes.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/timer/timer.h" 14 #include "ui/aura/window_observer.h" 15 #include "ui/gfx/rect.h" 16 #include "ui/views/mouse_watcher.h" 17 18 namespace aura { 19 class Window; 20 } 21 22 namespace views { 23 class Widget; 24 } 25 26 namespace ash { 27 namespace internal { 28 29 class MultiWindowResizeControllerTest; 30 class WorkspaceWindowResizer; 31 32 // Two directions resizes happen in. 33 enum Direction { 34 TOP_BOTTOM, 35 LEFT_RIGHT, 36 }; 37 38 // MultiWindowResizeController is responsible for determining and showing a 39 // widget that allows resizing multiple windows at the same time. 40 // MultiWindowResizeController is driven by WorkspaceEventFilter. 41 class ASH_EXPORT MultiWindowResizeController : 42 public views::MouseWatcherListener, public aura::WindowObserver { 43 public: 44 MultiWindowResizeController(); 45 virtual ~MultiWindowResizeController(); 46 47 // If necessary, shows the resize widget. |window| is the window the mouse 48 // is over, |component| the edge and |point| the location of the mouse. 49 void Show(aura::Window* window, int component, const gfx::Point& point); 50 51 // Hides the resize widget. 52 void Hide(); 53 54 // MouseWatcherListenre overrides: 55 virtual void MouseMovedOutOfHost() OVERRIDE; 56 57 // WindowObserver overrides: 58 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; 59 60 private: 61 friend class MultiWindowResizeControllerTest; 62 63 // Used to track the two resizable windows and direction. 64 struct ResizeWindows { 65 ResizeWindows(); 66 ~ResizeWindows(); 67 68 // Returns true if |other| equals this ResizeWindows. This does *not* 69 // consider the windows in |other_windows|. 70 bool Equals(const ResizeWindows& other) const; 71 72 // Returns true if this ResizeWindows is valid. is_validResizeWindows73 bool is_valid() const { return window1 && window2; } 74 75 // The left/top window to resize. 76 aura::Window* window1; 77 78 // Other window to resize. 79 aura::Window* window2; 80 81 // Direction 82 Direction direction; 83 84 // Windows after |window2| that are to be resized. Determined at the time 85 // the resize starts. 86 std::vector<aura::Window*> other_windows; 87 }; 88 89 class ResizeMouseWatcherHost; 90 class ResizeView; 91 92 // Returns a ResizeWindows based on the specified arguments. Use is_valid() 93 // to test if the return value is a valid multi window resize location. 94 ResizeWindows DetermineWindows(aura::Window* window, 95 int window_component, 96 const gfx::Point& point) const; 97 98 // Variant of DetermineWindows() that uses the current location of the mouse 99 // to determine the resize windows. 100 ResizeWindows DetermineWindowsFromScreenPoint(aura::Window* window) const; 101 102 // Finds a window by edge (one of the constants HitTestCompat. 103 aura::Window* FindWindowByEdge(aura::Window* window_to_ignore, 104 int edge_want, 105 int x, 106 int y) const; 107 108 // Returns the first window touching |window|. 109 aura::Window* FindWindowTouching(aura::Window* window, 110 Direction direction) const; 111 112 // Places any windows touching |start| into |others|. 113 void FindWindowsTouching(aura::Window* start, 114 Direction direction, 115 std::vector<aura::Window*>* others) const; 116 117 // Hides the window after a delay. 118 void DelayedHide(); 119 120 // Shows the resizer if the mouse is still at a valid location. This is called 121 // from the |show_timer_|. 122 void ShowIfValidMouseLocation(); 123 124 // Shows the widget immediately. 125 void ShowNow(); 126 127 // Returns true if the widget is showing. 128 bool IsShowing() const; 129 130 // Initiates a resize. 131 void StartResize(const gfx::Point& location_in_screen); 132 133 // Resizes to the new location. 134 void Resize(const gfx::Point& location_in_screen, int event_flags); 135 136 // Completes the resize. 137 void CompleteResize(int event_flags); 138 139 // Cancels the resize. 140 void CancelResize(); 141 142 // Returns the bounds for the resize widget. 143 gfx::Rect CalculateResizeWidgetBounds( 144 const gfx::Point& location_in_parent) const; 145 146 // Returns true if |location_in_screen| is over the resize windows 147 // (or the resize widget itself). 148 bool IsOverWindows(const gfx::Point& location_in_screen) const; 149 150 // Returns true if |location_in_screen| is over |window|. 151 bool IsOverWindow(aura::Window* window, 152 const gfx::Point& location_in_screen, 153 int component) const; 154 155 // Windows and direction to resize. 156 ResizeWindows windows_; 157 158 // Timer before hiding. 159 base::OneShotTimer<MultiWindowResizeController> hide_timer_; 160 161 // Timer used before showing. 162 base::OneShotTimer<MultiWindowResizeController> show_timer_; 163 164 scoped_ptr<views::Widget> resize_widget_; 165 166 // If non-null we're in a resize loop. 167 scoped_ptr<WorkspaceWindowResizer> window_resizer_; 168 169 // Mouse coordinate passed to Show() in container's coodinates. 170 gfx::Point show_location_in_parent_; 171 172 // Bounds the widget was last shown at in screen coordinates. 173 gfx::Rect show_bounds_in_screen_; 174 175 // Used to detect whether the mouse is over the windows. While 176 // |resize_widget_| is non-NULL (ie the widget is showing) we ignore calls 177 // to Show(). 178 scoped_ptr<views::MouseWatcher> mouse_watcher_; 179 180 DISALLOW_COPY_AND_ASSIGN(MultiWindowResizeController); 181 }; 182 183 } // namespace internal 184 } // namespace ash 185 186 #endif // ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_ 187