blob: b8e6ea6d5eef47e2d4516a266a0e5f73d3f955fd [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_WINDOW_RESIZER_H_
#define ASH_WM_WORKSPACE_WINDOW_RESIZER_H_
#include <vector>
#include "ash/wm/window_resizer.h"
#include "ash/wm/workspace/magnetism_matcher.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "ui/aura/window_tracker.h"
namespace aura {
class RootWindow;
} // namespace aura
namespace ui {
class Layer;
} // namespace ui
namespace ash {
namespace internal {
class PhantomWindowController;
class SnapSizer;
// WindowResizer implementation for workspaces. This enforces that windows are
// not allowed to vertically move or resize outside of the work area. As windows
// are moved outside the work area they are shrunk. We remember the height of
// the window before it was moved so that if the window is again moved up we
// attempt to restore the old height.
class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
public:
// When dragging an attached window this is the min size we'll make sure is
// visible. In the vertical direction we take the max of this and that from
// the delegate.
static const int kMinOnscreenSize;
// Min height we'll force on screen when dragging the caption.
// TODO: this should come from a property on the window.
static const int kMinOnscreenHeight;
// Snap region when dragging close to the edges. That is, as the window gets
// this close to an edge of the screen it snaps to the edge.
static const int kScreenEdgeInset;
virtual ~WorkspaceWindowResizer();
static WorkspaceWindowResizer* Create(
aura::Window* window,
const gfx::Point& location_in_parent,
int window_component,
const std::vector<aura::Window*>& attached_windows);
// Returns true if the drag will result in changing the window in anyway.
bool is_resizable() const { return details_.is_resizable; }
const gfx::Point& initial_location_in_parent() const {
return details_.initial_location_in_parent;
}
// Overridden from WindowResizer:
virtual void Drag(const gfx::Point& location_in_parent,
int event_flags) OVERRIDE;
virtual void CompleteDrag(int event_flags) OVERRIDE;
virtual void RevertDrag() OVERRIDE;
virtual aura::Window* GetTarget() OVERRIDE;
private:
WorkspaceWindowResizer(const Details& details,
const std::vector<aura::Window*>& attached_windows);
private:
FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomStyle);
FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, CancelSnapPhantom);
// Type of snapping.
enum SnapType {
// Snap to the left/right edge of the screen.
SNAP_LEFT_EDGE,
SNAP_RIGHT_EDGE,
// No snap position.
SNAP_NONE
};
// Returns the final bounds to place the window at. This differs from
// the current when snapping.
gfx::Rect GetFinalBounds(const gfx::Rect& bounds) const;
// Lays out the attached windows. |bounds| is the bounds of the main window.
void LayoutAttachedWindows(const gfx::Rect& bounds);
// Calculates the size (along the primary axis) of the attached windows.
// |initial_size| is the initial size of the main window, |current_size| the
// new size of the main window, |start| the position to layout the attached
// windows from and |end| the coordinate to position to.
void CalculateAttachedSizes(int initial_size,
int current_size,
int start,
int end,
std::vector<int>* sizes) const;
// Attempts to snap the window to any other nearly windows, update |bounds| if
// there was a close enough window.
void MagneticallySnapToOtherWindows(gfx::Rect* bounds);
// Adjusts the bounds to enforce that windows are vertically contained in the
// work area.
void AdjustBoundsForMainWindow(gfx::Rect* bounds, int grid_size);
// Snaps the window bounds to the work area edges if necessary.
void SnapToWorkAreaEdges(
const gfx::Rect& work_area,
gfx::Rect* bounds,
int grid_size) const;
// Returns true if the window touches the bottom edge of the work area.
bool TouchesBottomOfScreen() const;
// Returns a coordinate along the primary axis. Used to share code for
// left/right multi window resize and top/bottom resize.
int PrimaryAxisSize(const gfx::Size& size) const;
int PrimaryAxisCoordinate(int x, int y) const;
// Updates the bounds of the phantom window for window snapping.
void UpdateSnapPhantomWindow(const gfx::Point& location,
const gfx::Rect& bounds);
// Updates the bounds of the phantom window for window dragging. Set true on
// |in_original_root| if the pointer is still in |window()->GetRootWindow()|.
void UpdateDragPhantomWindow(const gfx::Rect& bounds, bool in_original_root);
// Restacks the windows z-order position so that one of the windows is at the
// top of the z-order, and the rest directly underneath it.
void RestackWindows();
// Returns the SnapType for the specified point. SNAP_NONE is used if no
// snapping should be used.
SnapType GetSnapType(const gfx::Point& location) const;
// Returns true if we should allow the mouse pointer to warp.
bool ShouldAllowMouseWarp() const;
// Recreates a fresh layer for window() and all its child windows.
void RecreateWindowLayers();
aura::Window* window() const { return details_.window; }
const Details details_;
const std::vector<aura::Window*> attached_windows_;
// Set to true once Drag() is invoked and the bounds of the window change.
bool did_move_or_resize_;
// The initial size of each of the windows in |attached_windows_| along the
// primary axis.
std::vector<int> initial_size_;
// The min size of each of the windows in |attached_windows_| along the
// primary axis.
std::vector<int> min_size_;
// The amount each of the windows in |attached_windows_| can be compressed.
// This is a fraction of the amount a window can be compressed over the total
// space the windows can be compressed.
std::vector<float> compress_fraction_;
// The amount each of the windows in |attached_windows_| should be expanded
// by. This is used when the user drags to the left/up. In this case the main
// window shrinks and the attached windows expand.
std::vector<float> expand_fraction_;
// Sum of sizes in |min_size_|.
int total_min_;
// Sum of the sizes in |initial_size_|.
int total_initial_size_;
// Gives a previews of where the the window will end up. Only used if there
// is a grid and the caption is being dragged.
scoped_ptr<PhantomWindowController> snap_phantom_window_controller_;
// Shows a semi-transparent image of the window being dragged.
scoped_ptr<PhantomWindowController> drag_phantom_window_controller_;
// Used to determine the target position of a snap.
scoped_ptr<SnapSizer> snap_sizer_;
// Last SnapType.
SnapType snap_type_;
// Number of mouse moves since the last bounds change. Only used for phantom
// placement to track when the mouse is moved while pushed against the edge of
// the screen.
int num_mouse_moves_since_bounds_change_;
// The mouse location passed to Drag().
gfx::Point last_mouse_location_;
// The copy of window()->layer() and its children. This object is the owner of
// the layer.
ui::Layer* layer_;
// If non-NULL the destructor sets this to true. Used to determine if this has
// been deleted.
bool* destroyed_;
aura::Window* magnetism_window_;
// Used to verify |magnetism_window_| is still valid.
aura::WindowTracker window_tracker_;
MagnetismEdge magnetism_edge_;
DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizer);
};
} // namespace internal
} // namespace ash
#endif // ASH_WM_WORKSPACE_WINDOW_RESIZER_H_