Commit d4763e45 authored by skuhne@chromium.org's avatar skuhne@chromium.org

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
parent e5fcc944
......@@ -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;
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -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(
......
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