diff options
author | skuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-17 13:31:23 +0000 |
---|---|---|
committer | skuhne@chromium.org <skuhne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-17 13:31:23 +0000 |
commit | d4763e45453135e147aaef2f18756cc42a927d8f (patch) | |
tree | 7d8b42b30df06cdfcf0f09143a742c87ca00062d /ash/wm | |
parent | e5fcc944433a2dbb69b7948f8040dd58a57627ce (diff) | |
download | chromium_src-d4763e45453135e147aaef2f18756cc42a927d8f.zip chromium_src-d4763e45453135e147aaef2f18756cc42a927d8f.tar.gz chromium_src-d4763e45453135e147aaef2f18756cc42a927d8f.tar.bz2 |
Dont allow the user to 'resize a window out of the workarea'
BUG=151255
TEST=unit test & visual
Review URL: https://chromiumcodereview.appspot.com/11087037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162390 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/wm')
-rw-r--r-- | ash/wm/window_resizer.cc | 90 | ||||
-rw-r--r-- | ash/wm/workspace/workspace_layout_manager2.cc | 10 | ||||
-rw-r--r-- | ash/wm/workspace/workspace_layout_manager2.h | 4 | ||||
-rw-r--r-- | ash/wm/workspace/workspace_window_resizer_unittest.cc | 61 |
4 files changed, 133 insertions, 32 deletions
diff --git a/ash/wm/window_resizer.cc b/ash/wm/window_resizer.cc index 6ea7552..bcb59a7 100644 --- a/ash/wm/window_resizer.cc +++ b/ash/wm/window_resizer.cc @@ -8,6 +8,7 @@ #include "ash/shell.h" #include "ash/wm/property_util.h" #include "ash/wm/window_util.h" +#include "ash/wm/workspace/workspace_layout_manager2.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/root_window.h" #include "ui/aura/window.h" @@ -169,10 +170,14 @@ int WindowResizer::GetBoundsChangeForWindowComponent(int component) { // static gfx::Rect WindowResizer::CalculateBoundsForDrag( const Details& details, - const gfx::Point& location) { + const gfx::Point& passed_location) { if (!details.is_resizable) return details.initial_bounds; + gfx::Point location = passed_location; + gfx::Rect work_area = + ScreenAsh::GetDisplayWorkAreaBoundsInParent(details.window); + int delta_x = location.x() - details.initial_location_in_parent.x(); int delta_y = location.y() - details.initial_location_in_parent.y(); @@ -181,36 +186,67 @@ gfx::Rect WindowResizer::CalculateBoundsForDrag( // repositioning the window when the minimize size is reached. gfx::Size size = GetSizeForDrag(details, &delta_x, &delta_y); gfx::Point origin = GetOriginForDrag(details, delta_x, delta_y); + gfx::Rect new_bounds(origin, size); - // When we might want to reposition a window which is also restored to its - // previous size, to keep the cursor within the dragged window. - if (!details.restore_bounds.IsEmpty() && - details.bounds_change & kBoundsChange_Repositions) { - // However - it is not desirable to change the origin if the window would - // be still hit by the cursor. - if (details.initial_location_in_parent.x() > - details.initial_bounds.x() + details.restore_bounds.width()) - origin.set_x(location.x() - details.restore_bounds.width() / 2); + // Sizing has to keep the result on the screen. Note that this correction + // has to come first since it might have an impact on the origin as well as + // on the size. + if (details.bounds_change & kBoundsChange_Resizes) { + if (details.size_change_direction & kBoundsChangeDirection_Horizontal) { + if (IsRightEdge(details.window_component) && + new_bounds.right() < work_area.x() + kMinimumOnScreenArea) { + int delta = work_area.x() + kMinimumOnScreenArea - new_bounds.right(); + new_bounds.set_width(new_bounds.width() + delta); + } else if (new_bounds.x() > work_area.right() - kMinimumOnScreenArea) { + int width = new_bounds.right() - work_area.right() + + kMinimumOnScreenArea; + new_bounds.set_x(work_area.right() - kMinimumOnScreenArea); + new_bounds.set_width(width); + } + } + if (details.size_change_direction & kBoundsChangeDirection_Vertical) { + if (!IsBottomEdge(details.window_component) && + new_bounds.y() > work_area.bottom() - kMinimumOnScreenArea) { + int height = new_bounds.bottom() - work_area.bottom() + + kMinimumOnScreenArea; + new_bounds.set_y(work_area.bottom() - kMinimumOnScreenArea); + new_bounds.set_height(height); + } else if (details.window_component == HTBOTTOM || + details.window_component == HTBOTTOMRIGHT || + details.window_component == HTBOTTOMLEFT) { + // Update bottom edge to stay in the work area when we are resizing + // by dragging the bottom edge or corners. + if (new_bounds.bottom() > work_area.bottom()) + new_bounds.Inset(0, 0, 0, + new_bounds.bottom() - work_area.bottom()); + } + } + if (details.bounds_change & kBoundsChange_Repositions && + new_bounds.y() < 0) { + int delta = new_bounds.y(); + new_bounds.set_y(0); + new_bounds.set_height(new_bounds.height() + delta); + } } - gfx::Rect new_bounds(origin, size); - // Update bottom edge to stay in the work area when we are resizing - // by dragging the bottome edge or corners. - if (details.window_component == HTBOTTOM || - details.window_component == HTBOTTOMRIGHT || - details.window_component == HTBOTTOMLEFT) { - gfx::Rect work_area = - ScreenAsh::GetDisplayWorkAreaBoundsInParent(details.window); - if (new_bounds.bottom() > work_area.bottom()) - new_bounds.Inset(0, 0, 0, - new_bounds.bottom() - work_area.bottom()); - } - if (details.bounds_change & kBoundsChange_Resizes && - details.bounds_change & kBoundsChange_Repositions && new_bounds.y() < 0) { - int delta = new_bounds.y(); - new_bounds.set_y(0); - new_bounds.set_height(new_bounds.height() + delta); + if (details.bounds_change & kBoundsChange_Repositions) { + // When we might want to reposition a window which is also restored to its + // previous size, to keep the cursor within the dragged window. + if (!details.restore_bounds.IsEmpty()) { + // However - it is not desirable to change the origin if the window would + // be still hit by the cursor. + if (details.initial_location_in_parent.x() > + details.initial_bounds.x() + details.restore_bounds.width()) + new_bounds.set_x(location.x() - details.restore_bounds.width() / 2); + } + // Make sure that the x origin does not leave the screen. Note that y is + // taken care of next. + new_bounds.set_x( + std::max(work_area.x() - new_bounds.width() + kMinimumOnScreenArea, + std::min(work_area.right() - kMinimumOnScreenArea, + new_bounds.x()))); } + return new_bounds; } diff --git a/ash/wm/workspace/workspace_layout_manager2.cc b/ash/wm/workspace/workspace_layout_manager2.cc index 7f3be99..6731557 100644 --- a/ash/wm/workspace/workspace_layout_manager2.cc +++ b/ash/wm/workspace/workspace_layout_manager2.cc @@ -27,6 +27,7 @@ using aura::Window; namespace ash { + namespace internal { namespace { @@ -292,21 +293,20 @@ void WorkspaceLayoutManager2::AdjustWindowSizeForScreenChange( } else if (reason == ADJUST_WINDOW_DISPLAY_INSETS_CHANGED) { // If the window is completely outside the display work area, then move it // enough to be visible again. - const int kMinAreaVisible = 10; gfx::Rect bounds = window->bounds(); if (!work_area_.Intersects(bounds)) { int y_offset = 0; if (work_area_.bottom() < bounds.y()) { - y_offset = work_area_.bottom() - bounds.y() - kMinAreaVisible; + y_offset = work_area_.bottom() - bounds.y() - kMinimumOnScreenArea; } else if (bounds.bottom() < work_area_.y()) { - y_offset = work_area_.y() - bounds.bottom() + kMinAreaVisible; + y_offset = work_area_.y() - bounds.bottom() + kMinimumOnScreenArea; } int x_offset = 0; if (work_area_.right() < bounds.x()) { - x_offset = work_area_.right() - bounds.x() - kMinAreaVisible; + x_offset = work_area_.right() - bounds.x() - kMinimumOnScreenArea; } else if (bounds.right() < work_area_.x()) { - x_offset = work_area_.x() - bounds.right() + kMinAreaVisible; + x_offset = work_area_.x() - bounds.right() + kMinimumOnScreenArea; } bounds.Offset(x_offset, y_offset); diff --git a/ash/wm/workspace/workspace_layout_manager2.h b/ash/wm/workspace/workspace_layout_manager2.h index 636892d..771a56a 100644 --- a/ash/wm/workspace/workspace_layout_manager2.h +++ b/ash/wm/workspace/workspace_layout_manager2.h @@ -27,6 +27,10 @@ class Layer; } namespace ash { + +// We force at least this many DIPs for any window on the screen. +const int kMinimumOnScreenArea = 10; + namespace internal { class Workspace2; diff --git a/ash/wm/workspace/workspace_window_resizer_unittest.cc b/ash/wm/workspace/workspace_window_resizer_unittest.cc index 6457d16..8c80687 100644 --- a/ash/wm/workspace/workspace_window_resizer_unittest.cc +++ b/ash/wm/workspace/workspace_window_resizer_unittest.cc @@ -15,6 +15,7 @@ #include "ash/wm/workspace_controller.h" #include "ash/wm/workspace/snap_sizer.h" #include "ash/wm/workspace/phantom_window_controller.h" +#include "ash/wm/workspace/workspace_layout_manager2.h" #include "base/string_number_conversions.h" #include "base/stringprintf.h" #include "ui/aura/root_window.h" @@ -845,6 +846,66 @@ TEST_F(WorkspaceWindowResizerTest, ResizeBottomOutsideWorkArea) { EXPECT_EQ("100,200 300x380", window_->bounds().ToString()); } +TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideLeftWorkArea) { + Shell::GetInstance()->SetDisplayWorkAreaInsets( + Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); + int left = ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_.get()).x(); + int pixels_to_left_border = 50; + int window_width = 300; + int window_x = left - window_width + pixels_to_left_border; + window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380)); + scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( + window_.get(), gfx::Point(pixels_to_left_border, 0), HTRIGHT, + empty_windows())); + ASSERT_TRUE(resizer.get()); + resizer->Drag(CalculateDragPoint(*resizer, -window_width, 0), 0); + EXPECT_EQ(base::IntToString(window_x) + ",100 " + + base::IntToString(kMinimumOnScreenArea - window_x) + + "x380", window_->bounds().ToString()); +} + +TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideRightWorkArea) { + Shell::GetInstance()->SetDisplayWorkAreaInsets( + Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); + int right = ScreenAsh::GetDisplayWorkAreaBoundsInParent( + window_.get()).right(); + int pixels_to_right_border = 50; + int window_width = 300; + int window_x = right - pixels_to_right_border; + window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380)); + scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( + window_.get(), gfx::Point(window_x, 0), HTLEFT, + empty_windows())); + ASSERT_TRUE(resizer.get()); + resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0); + EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) + + ",100 " + + base::IntToString(window_width - pixels_to_right_border + + kMinimumOnScreenArea) + + "x380", window_->bounds().ToString()); +} + +TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideBottomWorkArea) { + Shell::GetInstance()->SetDisplayWorkAreaInsets( + Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); + int bottom = ScreenAsh::GetDisplayWorkAreaBoundsInParent( + window_.get()).bottom(); + int delta_to_bottom = 50; + int height = 380; + window_->SetBounds(gfx::Rect(100, bottom - delta_to_bottom, 300, height)); + scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( + window_.get(), gfx::Point(0, bottom - delta_to_bottom), HTTOP, + empty_windows())); + ASSERT_TRUE(resizer.get()); + resizer->Drag(CalculateDragPoint(*resizer, 0, bottom), 0); + EXPECT_EQ("100," + + base::IntToString(bottom - kMinimumOnScreenArea) + + " 300x" + + base::IntToString(height - (delta_to_bottom - + kMinimumOnScreenArea)), + window_->bounds().ToString()); +} + // Verifies snapping to edges works. TEST_F(WorkspaceWindowResizerTest, SnapToEdge) { Shell::GetInstance()->SetShelfAutoHideBehavior( |