blob: 02eeb2511a4bdcedc3f67fe1c78ff3221f2cc307 [file] [log] [blame]
// 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_