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