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