Commit a92de8fe authored by jennyz@chromium.org's avatar jennyz@chromium.org

Add ctrl+drag feature for allowing resizing window with exact positioning.


BUG=116077
TEST=ctrl+drag will allow resizing window with exact positioning, drag resizing will still snap to grid.


Review URL: http://codereview.chromium.org/10008084

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132497 0039d316-1c4b-4281-b951-d872f2087c98
parent e4f6eb02
...@@ -27,25 +27,28 @@ DefaultWindowResizer::~DefaultWindowResizer() { ...@@ -27,25 +27,28 @@ DefaultWindowResizer::~DefaultWindowResizer() {
DefaultWindowResizer* DefaultWindowResizer*
DefaultWindowResizer::Create(aura::Window* window, DefaultWindowResizer::Create(aura::Window* window,
const gfx::Point& location, const gfx::Point& location,
int window_component, int window_component) {
int grid_size) { Details details(window, location, window_component);
Details details(window, location, window_component, grid_size);
return details.is_resizable ? new DefaultWindowResizer(details) : NULL; return details.is_resizable ? new DefaultWindowResizer(details) : NULL;
} }
void DefaultWindowResizer::Drag(const gfx::Point& location) { void DefaultWindowResizer::Drag(const gfx::Point& location, int event_flags) {
gfx::Rect bounds(CalculateBoundsForDrag(details_, location)); int grid_size = event_flags & ui::EF_CONTROL_DOWN ?
0 : ash::Shell::GetInstance()->GetGridSize();
gfx::Rect bounds(CalculateBoundsForDrag(details_, location, grid_size));
if (bounds != details_.window->bounds()) { if (bounds != details_.window->bounds()) {
did_move_or_resize_ = true; did_move_or_resize_ = true;
details_.window->SetBounds(bounds); details_.window->SetBounds(bounds);
} }
} }
void DefaultWindowResizer::CompleteDrag() { void DefaultWindowResizer::CompleteDrag(int event_flags) {
if (details_.grid_size <= 1 || !did_move_or_resize_) int grid_size = event_flags & ui::EF_CONTROL_DOWN ?
0 : ash::Shell::GetInstance()->GetGridSize();
if (grid_size <= 1 || !did_move_or_resize_)
return; return;
gfx::Rect new_bounds( gfx::Rect new_bounds(
AdjustBoundsToGrid(details_.window->bounds(), details_.grid_size)); AdjustBoundsToGrid(details_.window->bounds(), grid_size));
if (new_bounds == details_.window->bounds()) if (new_bounds == details_.window->bounds())
return; return;
......
...@@ -26,8 +26,7 @@ class ASH_EXPORT DefaultWindowResizer : public WindowResizer { ...@@ -26,8 +26,7 @@ class ASH_EXPORT DefaultWindowResizer : public WindowResizer {
// returned object. Returns NULL if not resizable. // returned object. Returns NULL if not resizable.
static DefaultWindowResizer* Create(aura::Window* window, static DefaultWindowResizer* Create(aura::Window* window,
const gfx::Point& location, const gfx::Point& location,
int window_component, int window_component);
int grid_size);
// Returns true if the drag will result in changing the window in anyway. // Returns true if the drag will result in changing the window in anyway.
bool is_resizable() const { return details_.is_resizable; } bool is_resizable() const { return details_.is_resizable; }
...@@ -38,8 +37,8 @@ class ASH_EXPORT DefaultWindowResizer : public WindowResizer { ...@@ -38,8 +37,8 @@ class ASH_EXPORT DefaultWindowResizer : public WindowResizer {
aura::Window* target_window() const { return details_.window; } aura::Window* target_window() const { return details_.window; }
// WindowResizer overides: // WindowResizer overides:
virtual void Drag(const gfx::Point& location) OVERRIDE; virtual void Drag(const gfx::Point& location, int event_flags) OVERRIDE;
virtual void CompleteDrag() OVERRIDE; virtual void CompleteDrag(int event_flags) OVERRIDE;
virtual void RevertDrag() OVERRIDE; virtual void RevertDrag() OVERRIDE;
private: private:
......
...@@ -57,7 +57,7 @@ bool ToplevelWindowEventFilter::PreHandleKeyEvent(aura::Window* target, ...@@ -57,7 +57,7 @@ bool ToplevelWindowEventFilter::PreHandleKeyEvent(aura::Window* target,
aura::KeyEvent* event) { aura::KeyEvent* event) {
if (window_resizer_.get() && event->type() == ui::ET_KEY_PRESSED && if (window_resizer_.get() && event->type() == ui::ET_KEY_PRESSED &&
event->key_code() == ui::VKEY_ESCAPE) { event->key_code() == ui::VKEY_ESCAPE) {
CompleteDrag(DRAG_REVERT); CompleteDrag(DRAG_REVERT, event->flags());
} }
return false; return false;
} }
...@@ -94,7 +94,8 @@ bool ToplevelWindowEventFilter::PreHandleMouseEvent(aura::Window* target, ...@@ -94,7 +94,8 @@ bool ToplevelWindowEventFilter::PreHandleMouseEvent(aura::Window* target,
case ui::ET_MOUSE_CAPTURE_CHANGED: case ui::ET_MOUSE_CAPTURE_CHANGED:
case ui::ET_MOUSE_RELEASED: case ui::ET_MOUSE_RELEASED:
CompleteDrag(event->type() == ui::ET_MOUSE_RELEASED ? CompleteDrag(event->type() == ui::ET_MOUSE_RELEASED ?
DRAG_COMPLETE : DRAG_REVERT); DRAG_COMPLETE : DRAG_REVERT,
event->flags());
if (in_move_loop_) { if (in_move_loop_) {
MessageLoop::current()->Quit(); MessageLoop::current()->Quit();
in_move_loop_ = false; in_move_loop_ = false;
...@@ -183,7 +184,7 @@ ui::GestureStatus ToplevelWindowEventFilter::PreHandleGestureEvent( ...@@ -183,7 +184,7 @@ ui::GestureStatus ToplevelWindowEventFilter::PreHandleGestureEvent(
} }
if (!drag_done) if (!drag_done)
CompleteDrag(DRAG_COMPLETE); CompleteDrag(DRAG_COMPLETE, event->flags());
in_gesture_resize_ = false; in_gesture_resize_ = false;
break; break;
} }
...@@ -232,15 +233,15 @@ WindowResizer* ToplevelWindowEventFilter::CreateWindowResizer( ...@@ -232,15 +233,15 @@ WindowResizer* ToplevelWindowEventFilter::CreateWindowResizer(
int window_component) { int window_component) {
if (!wm::IsWindowNormal(window)) if (!wm::IsWindowNormal(window))
return NULL; // Don't allow resizing/dragging maximized/fullscreen windows. return NULL; // Don't allow resizing/dragging maximized/fullscreen windows.
return DefaultWindowResizer::Create( return DefaultWindowResizer::Create(window, point, window_component);
window, point, window_component, grid_size_);
} }
void ToplevelWindowEventFilter::CompleteDrag(DragCompletionStatus status) { void ToplevelWindowEventFilter::CompleteDrag(DragCompletionStatus status,
int event_flags) {
scoped_ptr<WindowResizer> resizer(window_resizer_.release()); scoped_ptr<WindowResizer> resizer(window_resizer_.release());
if (resizer.get()) { if (resizer.get()) {
if (status == DRAG_COMPLETE) if (status == DRAG_COMPLETE)
resizer->CompleteDrag(); resizer->CompleteDrag(event_flags);
else else
resizer->RevertDrag(); resizer->RevertDrag();
} }
...@@ -256,7 +257,8 @@ bool ToplevelWindowEventFilter::HandleDrag(aura::Window* target, ...@@ -256,7 +257,8 @@ bool ToplevelWindowEventFilter::HandleDrag(aura::Window* target,
if (!window_resizer_.get()) if (!window_resizer_.get())
return false; return false;
window_resizer_->Drag(ConvertPointToParent(target, event->location())); window_resizer_->Drag(ConvertPointToParent(target, event->location()),
event->flags());
return true; return true;
} }
......
...@@ -67,7 +67,7 @@ class ASH_EXPORT ToplevelWindowEventFilter : ...@@ -67,7 +67,7 @@ class ASH_EXPORT ToplevelWindowEventFilter :
}; };
// Finishes the drag. // Finishes the drag.
void CompleteDrag(DragCompletionStatus status); void CompleteDrag(DragCompletionStatus status, int event_flags);
// Called during a drag to resize/position the window. // Called during a drag to resize/position the window.
// The return value is returned by OnMouseEvent() above. // The return value is returned by OnMouseEvent() above.
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/test/ash_test_base.h" #include "ash/test/ash_test_base.h"
#include "ash/wm/window_util.h" #include "ash/wm/window_util.h"
#include "ash/wm/workspace_controller.h"
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -76,6 +77,7 @@ class ToplevelWindowEventFilterTest : public AshTestBase { ...@@ -76,6 +77,7 @@ class ToplevelWindowEventFilterTest : public AshTestBase {
parent_->SetBounds(Shell::GetRootWindow()->bounds()); parent_->SetBounds(Shell::GetRootWindow()->bounds());
filter_ = new ToplevelWindowEventFilter(parent_); filter_ = new ToplevelWindowEventFilter(parent_);
parent_->SetEventFilter(filter_); parent_->SetEventFilter(filter_);
SetGridSize(0);
} }
virtual void TearDown() OVERRIDE { virtual void TearDown() OVERRIDE {
...@@ -106,6 +108,11 @@ class ToplevelWindowEventFilterTest : public AshTestBase { ...@@ -106,6 +108,11 @@ class ToplevelWindowEventFilterTest : public AshTestBase {
generator.PressMoveAndReleaseTouchBy(dx, dy); generator.PressMoveAndReleaseTouchBy(dx, dy);
} }
void SetGridSize(int grid_size) {
Shell::TestApi shell_test(Shell::GetInstance());
shell_test.workspace_controller()->SetGridSize(grid_size);
}
ToplevelWindowEventFilter* filter_; ToplevelWindowEventFilter* filter_;
private: private:
...@@ -404,7 +411,7 @@ TEST_F(ToplevelWindowEventFilterTest, DontGotWiderThanScreen) { ...@@ -404,7 +411,7 @@ TEST_F(ToplevelWindowEventFilterTest, DontGotWiderThanScreen) {
// Verifies that when a grid size is set resizes snap to the grid. // Verifies that when a grid size is set resizes snap to the grid.
TEST_F(ToplevelWindowEventFilterTest, ResizeSnaps) { TEST_F(ToplevelWindowEventFilterTest, ResizeSnaps) {
filter_->set_grid_size(8); SetGridSize(8);
scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT)); scoped_ptr<aura::Window> target(CreateWindow(HTBOTTOMRIGHT));
DragFromCenterBy(target.get(), 11, 21); DragFromCenterBy(target.get(), 11, 21);
EXPECT_EQ(112, target->bounds().width()); EXPECT_EQ(112, target->bounds().width());
...@@ -420,7 +427,7 @@ TEST_F(ToplevelWindowEventFilterTest, ResizeSnaps) { ...@@ -420,7 +427,7 @@ TEST_F(ToplevelWindowEventFilterTest, ResizeSnaps) {
// Verifies that when a grid size is set dragging snaps to the grid. // Verifies that when a grid size is set dragging snaps to the grid.
TEST_F(ToplevelWindowEventFilterTest, DragSnaps) { TEST_F(ToplevelWindowEventFilterTest, DragSnaps) {
filter_->set_grid_size(8); SetGridSize(8);
scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION)); scoped_ptr<aura::Window> target(CreateWindow(HTCAPTION));
aura::test::EventGenerator generator(Shell::GetRootWindow(), target.get()); aura::test::EventGenerator generator(Shell::GetRootWindow(), target.get());
generator.PressLeftButton(); generator.PressLeftButton();
......
...@@ -104,14 +104,12 @@ WindowResizer::Details::Details() ...@@ -104,14 +104,12 @@ WindowResizer::Details::Details()
bounds_change(0), bounds_change(0),
position_change_direction(0), position_change_direction(0),
size_change_direction(0), size_change_direction(0),
is_resizable(false), is_resizable(false) {
grid_size(0) {
} }
WindowResizer::Details::Details(aura::Window* window, WindowResizer::Details::Details(aura::Window* window,
const gfx::Point& location, const gfx::Point& location,
int window_component, int window_component)
int grid_size)
: window(window), : window(window),
initial_bounds(window->bounds()), initial_bounds(window->bounds()),
initial_location_in_parent(location), initial_location_in_parent(location),
...@@ -121,8 +119,7 @@ WindowResizer::Details::Details(aura::Window* window, ...@@ -121,8 +119,7 @@ WindowResizer::Details::Details(aura::Window* window,
GetPositionChangeDirectionForWindowComponent(window_component)), GetPositionChangeDirectionForWindowComponent(window_component)),
size_change_direction( size_change_direction(
GetSizeChangeDirectionForWindowComponent(window_component)), GetSizeChangeDirectionForWindowComponent(window_component)),
is_resizable(bounds_change != kBoundsChangeDirection_None), is_resizable(bounds_change != kBoundsChangeDirection_None) {
grid_size(grid_size) {
} }
WindowResizer::Details::~Details() { WindowResizer::Details::~Details() {
...@@ -186,7 +183,8 @@ int WindowResizer::AlignToGridRoundDown(int location, int grid_size) { ...@@ -186,7 +183,8 @@ int WindowResizer::AlignToGridRoundDown(int location, int grid_size) {
// static // static
gfx::Rect WindowResizer::CalculateBoundsForDrag( gfx::Rect WindowResizer::CalculateBoundsForDrag(
const Details& details, const Details& details,
const gfx::Point& location) { const gfx::Point& location,
int grid_size) {
if (!details.is_resizable) if (!details.is_resizable)
return details.initial_bounds; return details.initial_bounds;
...@@ -196,7 +194,7 @@ gfx::Rect WindowResizer::CalculateBoundsForDrag( ...@@ -196,7 +194,7 @@ gfx::Rect WindowResizer::CalculateBoundsForDrag(
// The minimize size constraint may limit how much we change the window // The minimize size constraint may limit how much we change the window
// position. For example, dragging the left edge to the right should stop // position. For example, dragging the left edge to the right should stop
// repositioning the window when the minimize size is reached. // repositioning the window when the minimize size is reached.
gfx::Size size = GetSizeForDrag(details, &delta_x, &delta_y); gfx::Size size = GetSizeForDrag(details, &delta_x, &delta_y, grid_size);
gfx::Point origin = GetOriginForDrag(details, delta_x, delta_y); gfx::Point origin = GetOriginForDrag(details, delta_x, delta_y);
gfx::Rect new_bounds(origin, size); gfx::Rect new_bounds(origin, size);
...@@ -257,15 +255,17 @@ gfx::Point WindowResizer::GetOriginForDrag(const Details& details, ...@@ -257,15 +255,17 @@ gfx::Point WindowResizer::GetOriginForDrag(const Details& details,
// static // static
gfx::Size WindowResizer::GetSizeForDrag(const Details& details, gfx::Size WindowResizer::GetSizeForDrag(const Details& details,
int* delta_x, int* delta_x,
int* delta_y) { int* delta_y,
int grid_size) {
gfx::Size size = details.initial_bounds.size(); gfx::Size size = details.initial_bounds.size();
if (details.bounds_change & kBoundsChange_Resizes) { if (details.bounds_change & kBoundsChange_Resizes) {
gfx::Size min_size = details.window->delegate()->GetMinimumSize(); gfx::Size min_size = details.window->delegate()->GetMinimumSize();
min_size.set_width(AlignToGridRoundUp(min_size.width(), details.grid_size)); min_size.set_width(AlignToGridRoundUp(min_size.width(), grid_size));
min_size.set_height(AlignToGridRoundUp(min_size.height(), min_size.set_height(AlignToGridRoundUp(min_size.height(), grid_size));
details.grid_size)); size.SetSize(GetWidthForDrag(details, min_size.width(), delta_x,
size.SetSize(GetWidthForDrag(details, min_size.width(), delta_x), grid_size),
GetHeightForDrag(details, min_size.height(), delta_y)); GetHeightForDrag(details, min_size.height(), delta_y,
grid_size));
} }
return size; return size;
} }
...@@ -273,13 +273,14 @@ gfx::Size WindowResizer::GetSizeForDrag(const Details& details, ...@@ -273,13 +273,14 @@ gfx::Size WindowResizer::GetSizeForDrag(const Details& details,
// static // static
int WindowResizer::GetWidthForDrag(const Details& details, int WindowResizer::GetWidthForDrag(const Details& details,
int min_width, int min_width,
int* delta_x) { int* delta_x,
int grid_size) {
int width = details.initial_bounds.width(); int width = details.initial_bounds.width();
if (details.size_change_direction & kBoundsChangeDirection_Horizontal) { if (details.size_change_direction & kBoundsChangeDirection_Horizontal) {
// Along the right edge, positive delta_x increases the window size. // Along the right edge, positive delta_x increases the window size.
int x_multiplier = IsRightEdge(details.window_component) ? 1 : -1; int x_multiplier = IsRightEdge(details.window_component) ? 1 : -1;
width += x_multiplier * (*delta_x); width += x_multiplier * (*delta_x);
int adjusted_width = AlignToGrid(width, details.grid_size); int adjusted_width = AlignToGrid(width, grid_size);
if (adjusted_width != width) { if (adjusted_width != width) {
*delta_x += -x_multiplier * (width - adjusted_width); *delta_x += -x_multiplier * (width - adjusted_width);
width = adjusted_width; width = adjusted_width;
...@@ -306,13 +307,14 @@ int WindowResizer::GetWidthForDrag(const Details& details, ...@@ -306,13 +307,14 @@ int WindowResizer::GetWidthForDrag(const Details& details,
// static // static
int WindowResizer::GetHeightForDrag(const Details& details, int WindowResizer::GetHeightForDrag(const Details& details,
int min_height, int min_height,
int* delta_y) { int* delta_y,
int grid_size) {
int height = details.initial_bounds.height(); int height = details.initial_bounds.height();
if (details.size_change_direction & kBoundsChangeDirection_Vertical) { if (details.size_change_direction & kBoundsChangeDirection_Vertical) {
// Along the bottom edge, positive delta_y increases the window size. // Along the bottom edge, positive delta_y increases the window size.
int y_multiplier = IsBottomEdge(details.window_component) ? 1 : -1; int y_multiplier = IsBottomEdge(details.window_component) ? 1 : -1;
height += y_multiplier * (*delta_y); height += y_multiplier * (*delta_y);
int adjusted_height = AlignToGrid(height, details.grid_size); int adjusted_height = AlignToGrid(height, grid_size);
if (height != adjusted_height) { if (height != adjusted_height) {
*delta_y += -y_multiplier * (height - adjusted_height); *delta_y += -y_multiplier * (height - adjusted_height);
height = adjusted_height; height = adjusted_height;
......
...@@ -48,11 +48,12 @@ class ASH_EXPORT WindowResizer { ...@@ -48,11 +48,12 @@ class ASH_EXPORT WindowResizer {
static int AlignToGridRoundDown(int location, int grid_size); static int AlignToGridRoundDown(int location, int grid_size);
// Invoked to drag/move/resize the window. |location| is in the coordinates // Invoked to drag/move/resize the window. |location| is in the coordinates
// of the window supplied to the constructor. // of the window supplied to the constructor. |event_flags| is the event
virtual void Drag(const gfx::Point& location) = 0; // flags from the event.
virtual void Drag(const gfx::Point& location, int event_flags) = 0;
// Invoked to complete the drag. // Invoked to complete the drag.
virtual void CompleteDrag() = 0; virtual void CompleteDrag(int event_flags) = 0;
// Reverts the drag. // Reverts the drag.
virtual void RevertDrag() = 0; virtual void RevertDrag() = 0;
...@@ -62,8 +63,7 @@ class ASH_EXPORT WindowResizer { ...@@ -62,8 +63,7 @@ class ASH_EXPORT WindowResizer {
Details(); Details();
Details(aura::Window* window, Details(aura::Window* window,
const gfx::Point& location, const gfx::Point& location,
int window_component, int window_component);
int grid_size);
~Details(); ~Details();
// The window we're resizing. // The window we're resizing.
...@@ -89,14 +89,12 @@ class ASH_EXPORT WindowResizer { ...@@ -89,14 +89,12 @@ class ASH_EXPORT WindowResizer {
// Will the drag actually modify the window? // Will the drag actually modify the window?
bool is_resizable; bool is_resizable;
// Size of the grid.
int grid_size;
}; };
static gfx::Rect CalculateBoundsForDrag( static gfx::Rect CalculateBoundsForDrag(
const Details& details, const Details& details,
const gfx::Point& location); const gfx::Point& location,
int grid_size);
static gfx::Rect AdjustBoundsToGrid(const gfx::Rect& bounds, static gfx::Rect AdjustBoundsToGrid(const gfx::Rect& bounds,
int grid_size); int grid_size);
...@@ -113,17 +111,20 @@ class ASH_EXPORT WindowResizer { ...@@ -113,17 +111,20 @@ class ASH_EXPORT WindowResizer {
// Returns the size of the window for the drag. // Returns the size of the window for the drag.
static gfx::Size GetSizeForDrag(const Details& details, static gfx::Size GetSizeForDrag(const Details& details,
int* delta_x, int* delta_x,
int* delta_y); int* delta_y,
int grid_size);
// Returns the width of the window. // Returns the width of the window.
static int GetWidthForDrag(const Details& details, static int GetWidthForDrag(const Details& details,
int min_width, int min_width,
int* delta_x); int* delta_x,
int grid_size);
// Returns the height of the drag. // Returns the height of the drag.
static int GetHeightForDrag(const Details& details, static int GetHeightForDrag(const Details& details,
int min_height, int min_height,
int* delta_y); int* delta_y,
int grid_size);
}; };
} // namespace aura } // namespace aura
......
...@@ -86,11 +86,11 @@ class MultiWindowResizeController::ResizeView : public views::View { ...@@ -86,11 +86,11 @@ class MultiWindowResizeController::ResizeView : public views::View {
virtual bool OnMouseDragged(const views::MouseEvent& event) OVERRIDE { virtual bool OnMouseDragged(const views::MouseEvent& event) OVERRIDE {
gfx::Point location(event.location()); gfx::Point location(event.location());
views::View::ConvertPointToScreen(this, &location); views::View::ConvertPointToScreen(this, &location);
controller_->Resize(location); controller_->Resize(location, event.flags());
return true; return true;
} }
virtual void OnMouseReleased(const views::MouseEvent& event) OVERRIDE { virtual void OnMouseReleased(const views::MouseEvent& event) OVERRIDE {
controller_->CompleteResize(); controller_->CompleteResize(event.flags());
} }
virtual void OnMouseCaptureLost() OVERRIDE { virtual void OnMouseCaptureLost() OVERRIDE {
controller_->CancelResize(); controller_->CancelResize();
...@@ -400,15 +400,16 @@ void MultiWindowResizeController::StartResize( ...@@ -400,15 +400,16 @@ void MultiWindowResizeController::StartResize(
} }
int component = windows_.direction == LEFT_RIGHT ? HTRIGHT : HTBOTTOM; int component = windows_.direction == LEFT_RIGHT ? HTRIGHT : HTBOTTOM;
window_resizer_.reset(WorkspaceWindowResizer::Create( window_resizer_.reset(WorkspaceWindowResizer::Create(
windows_.window1, parent_location, component, grid_size_, windows)); windows_.window1, parent_location, component, windows));
} }
void MultiWindowResizeController::Resize(const gfx::Point& screen_location) { void MultiWindowResizeController::Resize(const gfx::Point& screen_location,
int event_flags) {
gfx::Point parent_location(screen_location); gfx::Point parent_location(screen_location);
aura::Window::ConvertPointToWindow(windows_.window1->GetRootWindow(), aura::Window::ConvertPointToWindow(windows_.window1->GetRootWindow(),
windows_.window1->parent(), windows_.window1->parent(),
&parent_location); &parent_location);
window_resizer_->Drag(parent_location); window_resizer_->Drag(parent_location, event_flags);
gfx::Rect bounds = CalculateResizeWidgetBounds(parent_location); gfx::Rect bounds = CalculateResizeWidgetBounds(parent_location);
if (windows_.direction == LEFT_RIGHT) if (windows_.direction == LEFT_RIGHT)
bounds.set_y(show_bounds_.y()); bounds.set_y(show_bounds_.y());
...@@ -417,8 +418,8 @@ void MultiWindowResizeController::Resize(const gfx::Point& screen_location) { ...@@ -417,8 +418,8 @@ void MultiWindowResizeController::Resize(const gfx::Point& screen_location) {
resize_widget_->SetBounds(bounds); resize_widget_->SetBounds(bounds);
} }
void MultiWindowResizeController::CompleteResize() { void MultiWindowResizeController::CompleteResize(int event_flags) {
window_resizer_->CompleteDrag(); window_resizer_->CompleteDrag(event_flags);
window_resizer_.reset(); window_resizer_.reset();
// Mouse may still be over resizer, if not hide. // Mouse may still be over resizer, if not hide.
......
...@@ -126,10 +126,10 @@ class ASH_EXPORT MultiWindowResizeController : ...@@ -126,10 +126,10 @@ class ASH_EXPORT MultiWindowResizeController :
void StartResize(const gfx::Point& screen_location); void StartResize(const gfx::Point& screen_location);
// Resizes to the new location. // Resizes to the new location.
void Resize(const gfx::Point& screen_location); void Resize(const gfx::Point& screen_location, int event_flags);
// Completes the resize. // Completes the resize.
void CompleteResize(); void CompleteResize(int event_flags);
// Cancels the resize. // Cancels the resize.
void CancelResize(); void CancelResize();
......
...@@ -103,7 +103,7 @@ WindowResizer* WorkspaceEventFilter::CreateWindowResizer( ...@@ -103,7 +103,7 @@ WindowResizer* WorkspaceEventFilter::CreateWindowResizer(
return NULL; return NULL;
} }
return WorkspaceWindowResizer::Create( return WorkspaceWindowResizer::Create(
window, point, window_component, grid_size(), window, point, window_component,
std::vector<aura::Window*>()); std::vector<aura::Window*>());
} }
......
...@@ -53,31 +53,33 @@ WorkspaceWindowResizer* WorkspaceWindowResizer::Create( ...@@ -53,31 +53,33 @@ WorkspaceWindowResizer* WorkspaceWindowResizer::Create(
aura::Window* window, aura::Window* window,
const gfx::Point& location, const gfx::Point& location,
int window_component, int window_component,
int grid_size,
const std::vector<aura::Window*>& attached_windows) { const std::vector<aura::Window*>& attached_windows) {
Details details(window, location, window_component, grid_size); Details details(window, location, window_component);
return details.is_resizable ? return details.is_resizable ?
new WorkspaceWindowResizer(details, attached_windows) : NULL; new WorkspaceWindowResizer(details, attached_windows) : NULL;
} }
void WorkspaceWindowResizer::Drag(const gfx::Point& location) { void WorkspaceWindowResizer::Drag(const gfx::Point& location, int event_flags) {
gfx::Rect bounds = CalculateBoundsForDrag(details_, location); int grid_size = event_flags & ui::EF_CONTROL_DOWN ?
0 : ash::Shell::GetInstance()->GetGridSize();
gfx::Rect bounds = CalculateBoundsForDrag(details_, location, grid_size);
if (wm::IsWindowNormal(details_.window)) if (wm::IsWindowNormal(details_.window))
AdjustBoundsForMainWindow(&bounds); AdjustBoundsForMainWindow(&bounds, grid_size);
if (bounds != details_.window->bounds()) { if (bounds != details_.window->bounds()) {
if (!did_move_or_resize_) if (!did_move_or_resize_)
RestackWindows(); RestackWindows();
did_move_or_resize_ = true; did_move_or_resize_ = true;
} }
UpdatePhantomWindow(location, bounds); UpdatePhantomWindow(location, bounds, grid_size);
if (!attached_windows_.empty()) if (!attached_windows_.empty())
LayoutAttachedWindows(bounds); LayoutAttachedWindows(bounds, grid_size);
if (bounds != details_.window->bounds()) if (bounds != details_.window->bounds())
details_.window->SetBounds(bounds); details_.window->SetBounds(bounds);
// WARNING: we may have been deleted. // WARNING: we may have been deleted.
} }
void WorkspaceWindowResizer::CompleteDrag() { void WorkspaceWindowResizer::CompleteDrag(int event_flags) {
phantom_window_controller_.reset(); phantom_window_controller_.reset();
if (!did_move_or_resize_ || details_.window_component != HTCAPTION) if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
return; return;
...@@ -89,10 +91,12 @@ void WorkspaceWindowResizer::CompleteDrag() { ...@@ -89,10 +91,12 @@ void WorkspaceWindowResizer::CompleteDrag() {
return; return;
} }
if (details_.grid_size <= 1) int grid_size = event_flags & ui::EF_CONTROL_DOWN ?
0 : ash::Shell::GetInstance()->GetGridSize();
if (grid_size <= 1)
return; return;
gfx::Rect bounds(GetFinalBounds(details_.window->bounds())); gfx::Rect bounds(GetFinalBounds(details_.window->bounds(), grid_size));
if (bounds == details_.window->bounds()) if (bounds == details_.window->bounds())
return; return;
...@@ -163,6 +167,7 @@ WorkspaceWindowResizer::WorkspaceWindowResizer( ...@@ -163,6 +167,7 @@ WorkspaceWindowResizer::WorkspaceWindowResizer(
// Calculate sizes so that we can maintain the ratios if we need to resize. // Calculate sizes so that we can maintain the ratios if we need to resize.
int total_available = 0; int total_available = 0;
int grid_size = ash::Shell::GetInstance()->GetGridSize();
for (size_t i = 0; i < attached_windows_.size(); ++i) { for (size_t i = 0; i < attached_windows_.size(); ++i) {
gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize());
int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size());
...@@ -172,8 +177,8 @@ WorkspaceWindowResizer::WorkspaceWindowResizer( ...@@ -172,8 +177,8 @@ WorkspaceWindowResizer::WorkspaceWindowResizer(
int min_size = std::min(initial_size, int min_size = std::min(initial_size,
std::max(PrimaryAxisSize(min), kMinOnscreenSize)); std::max(PrimaryAxisSize(min), kMinOnscreenSize));
// Make sure the min size falls on the grid. // Make sure the min size falls on the grid.
if (details_.grid_size > 1 && min_size % details_.grid_size != 0) if (grid_size > 1 && min_size % grid_size != 0)
min_size = (min_size / details_.grid_size + 1) * details_.grid_size; min_size = (min_size / grid_size + 1) * grid_size;
min_size_.push_back(min_size); min_size_.push_back(min_size);
total_min_ += min_size; total_min_ += min_size;
total_initial_size_ += initial_size; total_initial_size_ += initial_size;
...@@ -195,16 +200,18 @@ WorkspaceWindowResizer::WorkspaceWindowResizer( ...@@ -195,16 +200,18 @@ WorkspaceWindowResizer::WorkspaceWindowResizer(
} }
gfx::Rect WorkspaceWindowResizer::GetFinalBounds( gfx::Rect WorkspaceWindowResizer::GetFinalBounds(
const gfx::Rect& bounds) const { const gfx::Rect& bounds,
int grid_size) const {
if (phantom_window_controller_.get() && if (phantom_window_controller_.get() &&
phantom_window_controller_->IsShowing()) { phantom_window_controller_->IsShowing()) {
return phantom_window_controller_->bounds(); return phantom_window_controller_->bounds();
} }
return AdjustBoundsToGrid(bounds, details_.grid_size); return AdjustBoundsToGrid(bounds, grid_size);
} }
void WorkspaceWindowResizer::LayoutAttachedWindows( void WorkspaceWindowResizer::LayoutAttachedWindows(
const gfx::Rect& bounds) { const gfx::Rect& bounds,
int grid_size) {
gfx::Rect work_area(gfx::Screen::GetMonitorWorkAreaNearestWindow(window())); gfx::Rect work_area(gfx::Screen::GetMonitorWorkAreaNearestWindow(window()));
std::vector<int> sizes; std::vector<int> sizes;
CalculateAttachedSizes( CalculateAttachedSizes(
...@@ -212,6 +219,7 @@ void WorkspaceWindowResizer::LayoutAttachedWindows( ...@@ -212,6 +219,7 @@ void WorkspaceWindowResizer::LayoutAttachedWindows(
PrimaryAxisSize(bounds.size()), PrimaryAxisSize(bounds.size()),
PrimaryAxisCoordinate(bounds.right(), bounds.bottom()), PrimaryAxisCoordinate(bounds.right(), bounds.bottom()),
PrimaryAxisCoordinate(work_area.right(), work_area.bottom()), PrimaryAxisCoordinate(work_area.right(), work_area.bottom()),
grid_size,
&sizes); &sizes);
DCHECK_EQ(attached_windows_.size(), sizes.size()); DCHECK_EQ(attached_windows_.size(), sizes.size());
int last = PrimaryAxisCoordinate(bounds.right(), bounds.bottom()); int last = PrimaryAxisCoordinate(bounds.right(), bounds.bottom());
...@@ -234,6 +242,7 @@ void WorkspaceWindowResizer::CalculateAttachedSizes( ...@@ -234,6 +242,7 @@ void WorkspaceWindowResizer::CalculateAttachedSizes(
int current_size, int current_size,
int start, int start,
int end, int end,
int grid_size,
std::vector<int>* sizes) const { std::vector<int>* sizes) const {
sizes->clear(); sizes->clear();
if (current_size < initial_size) { if (current_size < initial_size) {
...@@ -243,7 +252,7 @@ void WorkspaceWindowResizer::CalculateAttachedSizes( ...@@ -243,7 +252,7 @@ void WorkspaceWindowResizer::CalculateAttachedSizes(
for (size_t i = 0; i < attached_windows_.size(); ++i) { for (size_t i = 0; i < attached_windows_.size(); ++i) {
int next = AlignToGrid( int next = AlignToGrid(
current + initial_size_[i] + expand_fraction_[i] * delta, current + initial_size_[i] + expand_fraction_[i] * delta,
details_.grid_size); grid_size);
if (i == attached_windows_.size()) if (i == attached_windows_.size())
next = end; next = end;
sizes->push_back(next - current); sizes->push_back(next - current);
...@@ -260,7 +269,7 @@ void WorkspaceWindowResizer::CalculateAttachedSizes( ...@@ -260,7 +269,7 @@ void WorkspaceWindowResizer::CalculateAttachedSizes(
for (size_t i = 0; i < attached_windows_.size(); ++i) { for (size_t i = 0; i < attached_windows_.size(); ++i) {
int size = initial_size_[i] - int size = initial_size_[i] -
static_cast<int>(compress_fraction_[i] * delta); static_cast<int>(compress_fraction_[i] * delta);
size = AlignToGrid(size, details_.grid_size); size = AlignToGrid(size, grid_size);
if (i == attached_windows_.size()) if (i == attached_windows_.size())
size = end - current; size = end - current;
current += size; current += size;
...@@ -270,11 +279,11 @@ void WorkspaceWindowResizer::CalculateAttachedSizes( ...@@ -270,11 +279,11 @@ void WorkspaceWindowResizer::CalculateAttachedSizes(
} }
void WorkspaceWindowResizer::AdjustBoundsForMainWindow( void WorkspaceWindowResizer::AdjustBoundsForMainWindow(
gfx::Rect* bounds) const { gfx::Rect* bounds, int grid_size) const {
// Always keep kMinOnscreenHeight on the bottom. // Always keep kMinOnscreenHeight on the bottom.
gfx::Rect work_area(gfx::Screen::GetMonitorWorkAreaNearestWindow(window())); gfx::Rect work_area(gfx::Screen::GetMonitorWorkAreaNearestWindow(window()));
int max_y = AlignToGridRoundUp(work_area.bottom() - kMinOnscreenHeight, int max_y = AlignToGridRoundUp(work_area.bottom() - kMinOnscreenHeight,
details_.grid_size); grid_size);
if (bounds->y() > max_y) if (bounds->y() > max_y)
bounds->set_y(max_y); bounds->set_y(max_y);
...@@ -282,8 +291,8 @@ void WorkspaceWindowResizer::AdjustBoundsForMainWindow( ...@@ -282,8 +291,8 @@ void WorkspaceWindowResizer::AdjustBoundsForMainWindow(
if (bounds->y() <= work_area.y()) if (bounds->y() <= work_area.y())
bounds->set_y(work_area.y()); bounds->set_y(work_area.y());
if (details_.grid_size >= 0 && details_.window_component == HTCAPTION) if (grid_size >= 0 && details_.window_component == HTCAPTION)
SnapToWorkAreaEdges(work_area, bounds); SnapToWorkAreaEdges(work_area, bounds, grid_size);
if (attached_windows_.empty()) if (attached_windows_.empty())
return; return;
...@@ -300,22 +309,22 @@ void WorkspaceWindowResizer::AdjustBoundsForMainWindow( ...@@ -300,22 +309,22 @@ void WorkspaceWindowResizer::AdjustBoundsForMainWindow(
void WorkspaceWindowResizer::SnapToWorkAreaEdges( void WorkspaceWindowResizer::SnapToWorkAreaEdges(
const gfx::Rect& work_area, const gfx::Rect& work_area,
gfx::Rect* bounds) const { gfx::Rect* bounds,
int left_edge = AlignToGridRoundUp(work_area.x(), details_.grid_size); int grid_size) const {
int right_edge = AlignToGridRoundDown(work_area.right(), details_.grid_size); int left_edge = AlignToGridRoundUp(work_area.x(), grid_size);
int top_edge = AlignToGridRoundUp(work_area.y(), details_.grid_size); int right_edge = AlignToGridRoundDown(work_area.right(), grid_size);
int top_edge = AlignToGridRoundUp(work_area.y(), grid_size);
int bottom_edge = AlignToGridRoundDown(work_area.bottom(), int bottom_edge = AlignToGridRoundDown(work_area.bottom(),
details_.grid_size); grid_size);
if (ShouldSnapToEdge(bounds->x() - left_edge, details_.grid_size)) { if (ShouldSnapToEdge(bounds->x() - left_edge, grid_size)) {
bounds->set_x(left_edge); bounds->set_x(left_edge);
} else if (ShouldSnapToEdge(right_edge - bounds->right(), } else if (ShouldSnapToEdge(right_edge - bounds->right(),
details_.grid_size)) { grid_size)) {
bounds->set_x(right_edge - bounds->width()); bounds->set_x(right_edge - bounds->width());
} }
if (ShouldSnapToEdge(bounds->y() - top_edge, details_.grid_size)) { if (ShouldSnapToEdge(bounds->y() - top_edge, grid_size)) {
bounds->set_y(top_edge); bounds->set_y(top_edge);
} else if (ShouldSnapToEdge(bottom_edge - bounds->bottom(), } else if (ShouldSnapToEdge(bottom_edge - bounds->bottom(), grid_size) &&
details_.grid_size) &&
bounds->height() < (bottom_edge - top_edge)) { bounds->height() < (bottom_edge - top_edge)) {
// Only snap to the bottom if the window is smaller than the work area. // Only snap to the bottom if the window is smaller than the work area.
// Doing otherwise can lead to window snapping in weird ways as it bounces // Doing otherwise can lead to window snapping in weird ways as it bounces
...@@ -350,7 +359,8 @@ int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { ...@@ -350,7 +359,8 @@ int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const {
} }
void WorkspaceWindowResizer::UpdatePhantomWindow(const gfx::Point& location, void WorkspaceWindowResizer::UpdatePhantomWindow(const gfx::Point& location,
const gfx::Rect& bounds) { const gfx::Rect& bounds,
int grid_size) {
if (!did_move_or_resize_ || details_.window_component != HTCAPTION) if (!did_move_or_resize_ || details_.window_component != HTCAPTION)
return; return;
...@@ -366,7 +376,7 @@ void WorkspaceWindowResizer::UpdatePhantomWindow(const gfx::Point& location, ...@@ -366,7 +376,7 @@ void WorkspaceWindowResizer::UpdatePhantomWindow(const gfx::Point& location,
SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ? SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT_EDGE) ?
SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE;
snap_sizer_.reset( snap_sizer_.reset(
new SnapSizer(details_.window, location, edge, details_.grid_size)); new SnapSizer(details_.window, location, edge, grid_size));
} else { } else {
snap_sizer_->Update(location); snap_sizer_->Update(location);
} }
......
...@@ -41,7 +41,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { ...@@ -41,7 +41,6 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
aura::Window* window, aura::Window* window,
const gfx::Point& location, const gfx::Point& location,
int window_component, int window_component,
int grid_size,
const std::vector<aura::Window*>& attached_windows); const std::vector<aura::Window*>& attached_windows);
// Returns true if the drag will result in changing the window in anyway. // Returns true if the drag will result in changing the window in anyway.
...@@ -52,8 +51,8 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { ...@@ -52,8 +51,8 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
} }
// Overridden from WindowResizer: // Overridden from WindowResizer:
virtual void Drag(const gfx::Point& location) OVERRIDE; virtual void Drag(const gfx::Point& location, int event_flags) OVERRIDE;
virtual void CompleteDrag() OVERRIDE; virtual void CompleteDrag(int event_flags) OVERRIDE;
virtual void RevertDrag() OVERRIDE; virtual void RevertDrag() OVERRIDE;
private: private:
...@@ -73,10 +72,10 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { ...@@ -73,10 +72,10 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
// Returns the final bounds to place the window at. This differs from // Returns the final bounds to place the window at. This differs from
// the current if there is a grid. // the current if there is a grid.
gfx::Rect GetFinalBounds(const gfx::Rect& bounds) const; gfx::Rect GetFinalBounds(const gfx::Rect& bounds, int grid_size) const;
// Lays out the attached windows. |bounds| is the bounds of the main window. // Lays out the attached windows. |bounds| is the bounds of the main window.
void LayoutAttachedWindows(const gfx::Rect& bounds); void LayoutAttachedWindows(const gfx::Rect& bounds, int grid_size);
// Calculates the size (along the primary axis) of the attached windows. // Calculates the size (along the primary axis) of the attached windows.
// |initial_size| is the initial size of the main window, |current_size| the // |initial_size| is the initial size of the main window, |current_size| the
...@@ -87,14 +86,18 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { ...@@ -87,14 +86,18 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
int current_size, int current_size,
int start, int start,
int end, int end,
int grid_size,
std::vector<int>* sizes) const; std::vector<int>* sizes) const;
// Adjusts the bounds to enforce that windows are vertically contained in the // Adjusts the bounds to enforce that windows are vertically contained in the
// work area. // work area.
void AdjustBoundsForMainWindow(gfx::Rect* bounds) const; void AdjustBoundsForMainWindow(gfx::Rect* bounds, int grid_size) const;
// Snaps the window bounds to the work area edges if necessary. // Snaps the window bounds to the work area edges if necessary.
void SnapToWorkAreaEdges(const gfx::Rect& work_area, gfx::Rect* bounds) const; 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. // Returns true if the window touches the bottom edge of the work area.
bool TouchesBottomOfScreen() const; bool TouchesBottomOfScreen() const;
...@@ -105,7 +108,10 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer { ...@@ -105,7 +108,10 @@ class ASH_EXPORT WorkspaceWindowResizer : public WindowResizer {
int PrimaryAxisCoordinate(int x, int y) const; int PrimaryAxisCoordinate(int x, int y) const;
// Updates the bounds of the phantom window. // Updates the bounds of the phantom window.
void UpdatePhantomWindow(const gfx::Point& location, const gfx::Rect& bounds); void UpdatePhantomWindow(
const gfx::Point& location,
const gfx::Rect& bounds,
int grid_size);
// Restacks the windows z-order position so that one of the windows is at the // 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. // top of the z-order, and the rest directly underneath it.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment