summaryrefslogtreecommitdiffstats
path: root/chromium/ash/wm/workspace/multi_window_resize_controller.h
blob: 02eeb2511a4bdcedc3f67fe1c78ff3221f2cc307 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_
#define ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_

#include <vector>

#include "ash/ash_export.h"
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
#include "ui/aura/window_observer.h"
#include "ui/gfx/rect.h"
#include "ui/views/mouse_watcher.h"

namespace aura {
class Window;
}

namespace views {
class Widget;
}

namespace ash {
namespace internal {

class MultiWindowResizeControllerTest;
class WorkspaceWindowResizer;

// Two directions resizes happen in.
enum Direction {
  TOP_BOTTOM,
  LEFT_RIGHT,
};

// MultiWindowResizeController is responsible for determining and showing a
// widget that allows resizing multiple windows at the same time.
// MultiWindowResizeController is driven by WorkspaceEventFilter.
class ASH_EXPORT MultiWindowResizeController :
    public views::MouseWatcherListener, public aura::WindowObserver {
 public:
  MultiWindowResizeController();
  virtual ~MultiWindowResizeController();

  // If necessary, shows the resize widget. |window| is the window the mouse
  // is over, |component| the edge and |point| the location of the mouse.
  void Show(aura::Window* window, int component, const gfx::Point& point);

  // Hides the resize widget.
  void Hide();

  // MouseWatcherListenre overrides:
  virtual void MouseMovedOutOfHost() OVERRIDE;

  // WindowObserver overrides:
  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;

 private:
  friend class MultiWindowResizeControllerTest;

  // Used to track the two resizable windows and direction.
  struct ResizeWindows {
    ResizeWindows();
    ~ResizeWindows();

    // Returns true if |other| equals this ResizeWindows. This does *not*
    // consider the windows in |other_windows|.
    bool Equals(const ResizeWindows& other) const;

    // Returns true if this ResizeWindows is valid.
    bool is_valid() const { return window1 && window2; }

    // The left/top window to resize.
    aura::Window* window1;

    // Other window to resize.
    aura::Window* window2;

    // Direction
    Direction direction;

    // Windows after |window2| that are to be resized. Determined at the time
    // the resize starts.
    std::vector<aura::Window*> other_windows;
  };

  class ResizeMouseWatcherHost;
  class ResizeView;

  // Returns a ResizeWindows based on the specified arguments. Use is_valid()
  // to test if the return value is a valid multi window resize location.
  ResizeWindows DetermineWindows(aura::Window* window,
                                 int window_component,
                                 const gfx::Point& point) const;

  // Variant of DetermineWindows() that uses the current location of the mouse
  // to determine the resize windows.
  ResizeWindows DetermineWindowsFromScreenPoint(aura::Window* window) const;

  // Finds a window by edge (one of the constants HitTestCompat.
  aura::Window* FindWindowByEdge(aura::Window* window_to_ignore,
                                 int edge_want,
                                 int x,
                                 int y) const;

  // Returns the first window touching |window|.
  aura::Window* FindWindowTouching(aura::Window* window,
                                   Direction direction) const;

  // Places any windows touching |start| into |others|.
  void FindWindowsTouching(aura::Window* start,
                           Direction direction,
                           std::vector<aura::Window*>* others) const;

  // Hides the window after a delay.
  void DelayedHide();

  // Shows the resizer if the mouse is still at a valid location. This is called
  // from the |show_timer_|.
  void ShowIfValidMouseLocation();

  // Shows the widget immediately.
  void ShowNow();

  // Returns true if the widget is showing.
  bool IsShowing() const;

  // Initiates a resize.
  void StartResize(const gfx::Point& location_in_screen);

  // Resizes to the new location.
  void Resize(const gfx::Point& location_in_screen, int event_flags);

  // Completes the resize.
  void CompleteResize(int event_flags);

  // Cancels the resize.
  void CancelResize();

  // Returns the bounds for the resize widget.
  gfx::Rect CalculateResizeWidgetBounds(
      const gfx::Point& location_in_parent) const;

  // Returns true if |location_in_screen| is over the resize windows
  // (or the resize widget itself).
  bool IsOverWindows(const gfx::Point& location_in_screen) const;

  // Returns true if |location_in_screen| is over |window|.
  bool IsOverWindow(aura::Window* window,
                    const gfx::Point& location_in_screen,
                    int component) const;

  // Windows and direction to resize.
  ResizeWindows windows_;

  // Timer before hiding.
  base::OneShotTimer<MultiWindowResizeController> hide_timer_;

  // Timer used before showing.
  base::OneShotTimer<MultiWindowResizeController> show_timer_;

  scoped_ptr<views::Widget> resize_widget_;

  // If non-null we're in a resize loop.
  scoped_ptr<WorkspaceWindowResizer> window_resizer_;

  // Mouse coordinate passed to Show() in container's coodinates.
  gfx::Point show_location_in_parent_;

  // Bounds the widget was last shown at in screen coordinates.
  gfx::Rect show_bounds_in_screen_;

  // Used to detect whether the mouse is over the windows. While
  // |resize_widget_| is non-NULL (ie the widget is showing) we ignore calls
  // to Show().
  scoped_ptr<views::MouseWatcher> mouse_watcher_;

  DISALLOW_COPY_AND_ASSIGN(MultiWindowResizeController);
};

}  // namespace internal
}  // namespace ash

#endif  // ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_