• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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