summaryrefslogtreecommitdiffstats
path: root/ui/aura_shell
diff options
context:
space:
mode:
authorjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-22 23:04:38 +0000
committerjamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-22 23:04:38 +0000
commit17a6cb95e99a66058f8767a8e026148e7130119d (patch)
treee4ef0d098c3de3c5c93b66c816712f210b4d85f4 /ui/aura_shell
parentf552df55f9bac09d13c0d8d9566d9c1d3e73e4cc (diff)
downloadchromium_src-17a6cb95e99a66058f8767a8e026148e7130119d.zip
chromium_src-17a6cb95e99a66058f8767a8e026148e7130119d.tar.gz
chromium_src-17a6cb95e99a66058f8767a8e026148e7130119d.tar.bz2
Aura: Fix window resizing for large drags.
* Fix a DCHECK due to a negative width when resizing the right edge past the left one, and vice versa. * Fix the window moving when resizing its left edge past the minimum size, ditto for top edge. * Add unit tests for above. * Add GetMinimizeSize() method to aura::WindowDelegate interface. BUG=104245 TEST=aura_shell_unittests, manual Review URL: http://codereview.chromium.org/8618009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111244 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/aura_shell')
-rw-r--r--ui/aura_shell/toplevel_window_event_filter.cc131
-rw-r--r--ui/aura_shell/toplevel_window_event_filter.h28
-rw-r--r--ui/aura_shell/toplevel_window_event_filter_unittest.cc95
3 files changed, 187 insertions, 67 deletions
diff --git a/ui/aura_shell/toplevel_window_event_filter.cc b/ui/aura_shell/toplevel_window_event_filter.cc
index d6e996c..c29da93 100644
--- a/ui/aura_shell/toplevel_window_event_filter.cc
+++ b/ui/aura_shell/toplevel_window_event_filter.cc
@@ -106,15 +106,25 @@ int GetSizeChangeDirectionForWindowComponent(int window_component) {
return size_change_direction;
}
-int GetXMultiplierForWindowComponent(int window_component) {
- return window_component == HTTOPRIGHT ? -1 : 1;
+// Returns true for resize components along the right edge, where a drag in
+// positive x will make the window larger.
+bool IsRightEdge(int window_component) {
+ return window_component == HTTOPRIGHT ||
+ window_component == HTRIGHT ||
+ window_component == HTBOTTOMRIGHT ||
+ window_component == HTGROWBOX;
}
-int GetYMultiplierForWindowComponent(int window_component) {
- return window_component == HTBOTTOMLEFT ? -1 : 1;
+// Returns true for resize components in along the bottom edge, where a drag
+// in positive y will make the window larger.
+bool IsBottomEdge(int window_component) {
+ return window_component == HTBOTTOMLEFT ||
+ window_component == HTBOTTOM ||
+ window_component == HTBOTTOMRIGHT ||
+ window_component == HTGROWBOX;
}
-}
+} // namespace
ToplevelWindowEventFilter::ToplevelWindowEventFilter(aura::Window* owner)
: EventFilter(owner),
@@ -143,8 +153,7 @@ bool ToplevelWindowEventFilter::PreHandleMouseEvent(aura::Window* target,
// pressed without mouse move event.
UpdateWindowComponentForEvent(target, event);
mouse_down_bounds_ = target->bounds();
- mouse_down_offset_in_target_ = event->location();
- mouse_down_offset_in_parent_ = mouse_down_offset_in_target_;
+ mouse_down_offset_in_parent_ = event->location();
aura::Window::ConvertPointToWindow(target, target->parent(),
&mouse_down_offset_in_parent_);
return GetBoundsChangeForWindowComponent(window_component_) !=
@@ -192,8 +201,21 @@ bool ToplevelWindowEventFilter::HandleDrag(aura::Window* target,
target->GetIntProperty(aura::kShowStateKey) != ui::SHOW_STATE_DEFAULT)
return false;
- target->SetBounds(gfx::Rect(GetOriginForDrag(bounds_change, target, event),
- GetSizeForDrag(bounds_change, target, event)));
+ // Dragging a window moves the local coordinate frame, so do arithmetic
+ // in the parent coordinate frame.
+ gfx::Point event_location_in_parent(event->location());
+ aura::Window::ConvertPointToWindow(target, target->parent(),
+ &event_location_in_parent);
+ int delta_x = event_location_in_parent.x() - mouse_down_offset_in_parent_.x();
+ int delta_y = event_location_in_parent.y() - mouse_down_offset_in_parent_.y();
+
+ // The minimize size constraint may limit how much we change the window
+ // position. For example, dragging the left edge to the right should stop
+ // repositioning the window when the minimize size is reached.
+ gfx::Size size = GetSizeForDrag(bounds_change, target, &delta_x, &delta_y);
+ gfx::Point origin = GetOriginForDrag(bounds_change, delta_x, delta_y);
+
+ target->SetBounds(gfx::Rect(origin, size));
return true;
}
@@ -206,23 +228,16 @@ void ToplevelWindowEventFilter::UpdateWindowComponentForEvent(
gfx::Point ToplevelWindowEventFilter::GetOriginForDrag(
int bounds_change,
- aura::Window* target,
- aura::MouseEvent* event) const {
+ int delta_x,
+ int delta_y) const {
gfx::Point origin = mouse_down_bounds_.origin();
if (bounds_change & kBoundsChange_Repositions) {
int pos_change_direction =
GetPositionChangeDirectionForWindowComponent(window_component_);
-
- if (pos_change_direction & kBoundsChangeDirection_Horizontal) {
- origin.set_x(event->location().x());
- origin.Offset(-mouse_down_offset_in_target_.x(), 0);
- origin.Offset(target->bounds().x(), 0);
- }
- if (pos_change_direction & kBoundsChangeDirection_Vertical) {
- origin.set_y(event->location().y());
- origin.Offset(0, -mouse_down_offset_in_target_.y());
- origin.Offset(0, target->bounds().y());
- }
+ if (pos_change_direction & kBoundsChangeDirection_Horizontal)
+ origin.Offset(delta_x, 0);
+ if (pos_change_direction & kBoundsChangeDirection_Vertical)
+ origin.Offset(0, delta_y);
}
return origin;
}
@@ -230,40 +245,56 @@ gfx::Point ToplevelWindowEventFilter::GetOriginForDrag(
gfx::Size ToplevelWindowEventFilter::GetSizeForDrag(
int bounds_change,
aura::Window* target,
- aura::MouseEvent* event) const {
+ int* delta_x,
+ int* delta_y) const {
gfx::Size size = mouse_down_bounds_.size();
if (bounds_change & kBoundsChange_Resizes) {
+ gfx::Size min_size = target->delegate()->GetMinimumSize();
int size_change_direction =
GetSizeChangeDirectionForWindowComponent(window_component_);
-
- gfx::Point event_location_in_parent(event->location());
- aura::Window::ConvertPointToWindow(target, target->parent(),
- &event_location_in_parent);
-
- // The math changes depending on whether the window is being resized, or
- // repositioned in addition to being resized.
- int first_x = bounds_change & kBoundsChange_Repositions ?
- mouse_down_offset_in_parent_.x() : event_location_in_parent.x();
- int first_y = bounds_change & kBoundsChange_Repositions ?
- mouse_down_offset_in_parent_.y() : event_location_in_parent.y();
- int second_x = bounds_change & kBoundsChange_Repositions ?
- event_location_in_parent.x() : mouse_down_offset_in_parent_.x();
- int second_y = bounds_change & kBoundsChange_Repositions ?
- event_location_in_parent.y() : mouse_down_offset_in_parent_.y();
-
- int x_multiplier = GetXMultiplierForWindowComponent(window_component_);
- int y_multiplier = GetYMultiplierForWindowComponent(window_component_);
-
- int width = size.width() +
- (size_change_direction & kBoundsChangeDirection_Horizontal ?
- x_multiplier * (first_x - second_x) : 0);
- int height = size.height() +
- (size_change_direction & kBoundsChangeDirection_Vertical ?
- y_multiplier * (first_y - second_y) : 0);
-
- size.SetSize(width, height);
+ size.SetSize(
+ GetWidthForDrag(size_change_direction, min_size.width(), delta_x),
+ GetHeightForDrag(size_change_direction, min_size.height(), delta_y));
}
return size;
}
+int ToplevelWindowEventFilter::GetWidthForDrag(int size_change_direction,
+ int min_width,
+ int* delta_x) const {
+ int width = mouse_down_bounds_.width();
+ if (size_change_direction & kBoundsChangeDirection_Horizontal) {
+ // Along the right edge, positive delta_x increases the window size.
+ int x_multiplier = IsRightEdge(window_component_) ? 1 : -1;
+ width += x_multiplier * (*delta_x);
+
+ // Ensure we don't shrink past the minimum width and clamp delta_x
+ // for the window origin computation.
+ if (width < min_width) {
+ width = min_width;
+ *delta_x = -x_multiplier * (mouse_down_bounds_.width() - min_width);
+ }
+ }
+ return width;
+}
+
+int ToplevelWindowEventFilter::GetHeightForDrag(int size_change_direction,
+ int min_height,
+ int* delta_y) const {
+ int height = mouse_down_bounds_.height();
+ if (size_change_direction & kBoundsChangeDirection_Vertical) {
+ // Along the bottom edge, positive delta_y increases the window size.
+ int y_multiplier = IsBottomEdge(window_component_) ? 1 : -1;
+ height += y_multiplier * (*delta_y);
+
+ // Ensure we don't shrink past the minimum height and clamp delta_y
+ // for the window origin computation.
+ if (height < min_height) {
+ height = min_height;
+ *delta_y = -y_multiplier * (mouse_down_bounds_.height() - min_height);
+ }
+ }
+ return height;
+}
+
} // namespace aura
diff --git a/ui/aura_shell/toplevel_window_event_filter.h b/ui/aura_shell/toplevel_window_event_filter.h
index e114586..6491c0a 100644
--- a/ui/aura_shell/toplevel_window_event_filter.h
+++ b/ui/aura_shell/toplevel_window_event_filter.h
@@ -53,17 +53,29 @@ class AURA_SHELL_EXPORT ToplevelWindowEventFilter : public aura::EventFilter {
// Calculates the new origin of the window during a drag.
gfx::Point GetOriginForDrag(int bounds_change,
- aura::Window* target,
- aura::MouseEvent* event) const;
+ int delta_x,
+ int delta_y) const;
- // Calculates the new size of the window during a drag.
+ // Calculates the new size of the |target| window during a drag.
+ // If the size is constrained, |delta_x| and |delta_y| may be clamped.
gfx::Size GetSizeForDrag(int bounds_change,
aura::Window* target,
- aura::MouseEvent* event) const;
-
- // The mouse position in the target window when the mouse was pressed, in
- // target window coordinates.
- gfx::Point mouse_down_offset_in_target_;
+ int* delta_x,
+ int* delta_y) const;
+
+ // Calculates new width of a window during a drag where the mouse
+ // position changed by |delta_x|. |delta_x| may be clamped if the window
+ // size is constrained by |min_width|.
+ int GetWidthForDrag(int size_change_direction,
+ int min_width,
+ int* delta_x) const;
+
+ // Calculates new height of a window during a drag where the mouse
+ // position changed by |delta_y|. |delta_y| may be clamped if the window
+ // size is constrained by |min_height|.
+ int GetHeightForDrag(int size_change_direction,
+ int min_height,
+ int* delta_y) const;
// The mouse position in the target window when the mouse was pressed, in
// the target window's parent's coordinates.
diff --git a/ui/aura_shell/toplevel_window_event_filter_unittest.cc b/ui/aura_shell/toplevel_window_event_filter_unittest.cc
index e2c0094..a2c0eed 100644
--- a/ui/aura_shell/toplevel_window_event_filter_unittest.cc
+++ b/ui/aura_shell/toplevel_window_event_filter_unittest.cc
@@ -43,13 +43,8 @@ class TestWindowDelegate : public aura::test::TestWindowDelegate {
private:
// Overridden from aura::Test::TestWindowDelegate:
- virtual void OnBoundsChanging(gfx::Rect* new_bounds) OVERRIDE {
- if (!min_size_.IsEmpty()) {
- new_bounds->set_width(std::max(min_size_.width(),
- new_bounds->width()));
- new_bounds->set_height(std::max(min_size_.height(),
- new_bounds->height()));
- }
+ virtual gfx::Size GetMinimumSize() const OVERRIDE {
+ return min_size_;
}
virtual int GetNonClientComponent(const gfx::Point& point) const OVERRIDE {
return hittest_code_;
@@ -126,7 +121,7 @@ TEST_F(ToplevelWindowEventFilterTest, GrowBox) {
scoped_ptr<aura::Window> w1(CreateWindow(HTGROWBOX));
TestWindowDelegate* window_delegate =
static_cast<TestWindowDelegate*>(w1->delegate());
- window_delegate->set_min_size(gfx::Size(50, 50));
+ window_delegate->set_min_size(gfx::Size(40, 40));
gfx::Point position = w1->bounds().origin();
aura::test::EventGenerator generator;
@@ -147,7 +142,7 @@ TEST_F(ToplevelWindowEventFilterTest, GrowBox) {
// Enforce minimum size.
generator.DragMouseBy(-60, -60);
EXPECT_EQ(position, w1->bounds().origin());
- EXPECT_EQ(gfx::Size(50, 50), w1->bounds().size());
+ EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size());
}
TEST_F(ToplevelWindowEventFilterTest, Right) {
@@ -223,5 +218,87 @@ TEST_F(ToplevelWindowEventFilterTest, Client) {
EXPECT_EQ(bounds, w1->bounds());
}
+TEST_F(ToplevelWindowEventFilterTest, LeftPastMinimum) {
+ scoped_ptr<aura::Window> w1(CreateWindow(HTLEFT));
+ TestWindowDelegate* window_delegate =
+ static_cast<TestWindowDelegate*>(w1->delegate());
+ window_delegate->set_min_size(gfx::Size(40, 40));
+
+ // Simulate a large left-to-right drag. Window width should be clamped to
+ // minimum and position change should be limited as well.
+ DragFromCenterBy(w1.get(), 333, 0);
+ EXPECT_EQ(gfx::Point(60, 0), w1->bounds().origin());
+ EXPECT_EQ(gfx::Size(40, 100), w1->bounds().size());
+}
+
+TEST_F(ToplevelWindowEventFilterTest, RightPastMinimum) {
+ scoped_ptr<aura::Window> w1(CreateWindow(HTRIGHT));
+ TestWindowDelegate* window_delegate =
+ static_cast<TestWindowDelegate*>(w1->delegate());
+ window_delegate->set_min_size(gfx::Size(40, 40));
+ gfx::Point position = w1->bounds().origin();
+
+ // Simulate a large right-to-left drag. Window width should be clamped to
+ // minimum and position should not change.
+ DragFromCenterBy(w1.get(), -333, 0);
+ EXPECT_EQ(position, w1->bounds().origin());
+ EXPECT_EQ(gfx::Size(40, 100), w1->bounds().size());
+}
+
+TEST_F(ToplevelWindowEventFilterTest, TopLeftPastMinimum) {
+ scoped_ptr<aura::Window> w1(CreateWindow(HTTOPLEFT));
+ TestWindowDelegate* window_delegate =
+ static_cast<TestWindowDelegate*>(w1->delegate());
+ window_delegate->set_min_size(gfx::Size(40, 40));
+
+ // Simulate a large top-left to bottom-right drag. Window width should be
+ // clamped to minimum and position should be limited.
+ DragFromCenterBy(w1.get(), 333, 444);
+ EXPECT_EQ(gfx::Point(60, 60), w1->bounds().origin());
+ EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size());
+}
+
+TEST_F(ToplevelWindowEventFilterTest, TopRightPastMinimum) {
+ scoped_ptr<aura::Window> w1(CreateWindow(HTTOPRIGHT));
+ TestWindowDelegate* window_delegate =
+ static_cast<TestWindowDelegate*>(w1->delegate());
+ window_delegate->set_min_size(gfx::Size(40, 40));
+
+ // Simulate a large top-right to bottom-left drag. Window size should be
+ // clamped to minimum, x position should not change, and y position should
+ // be clamped.
+ DragFromCenterBy(w1.get(), -333, 444);
+ EXPECT_EQ(gfx::Point(0, 60), w1->bounds().origin());
+ EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size());
+}
+
+TEST_F(ToplevelWindowEventFilterTest, BottomLeftPastMinimum) {
+ scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMLEFT));
+ TestWindowDelegate* window_delegate =
+ static_cast<TestWindowDelegate*>(w1->delegate());
+ window_delegate->set_min_size(gfx::Size(40, 40));
+
+ // Simulate a large bottom-left to top-right drag. Window size should be
+ // clamped to minimum, x position should be clamped, and y position should
+ // not change.
+ DragFromCenterBy(w1.get(), 333, -444);
+ EXPECT_EQ(gfx::Point(60, 0), w1->bounds().origin());
+ EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size());
+}
+
+TEST_F(ToplevelWindowEventFilterTest, BottomRightPastMinimum) {
+ scoped_ptr<aura::Window> w1(CreateWindow(HTBOTTOMRIGHT));
+ TestWindowDelegate* window_delegate =
+ static_cast<TestWindowDelegate*>(w1->delegate());
+ window_delegate->set_min_size(gfx::Size(40, 40));
+ gfx::Point position = w1->bounds().origin();
+
+ // Simulate a large bottom-right to top-left drag. Window size should be
+ // clamped to minimum and position should not change.
+ DragFromCenterBy(w1.get(), -333, -444);
+ EXPECT_EQ(position, w1->bounds().origin());
+ EXPECT_EQ(gfx::Size(40, 40), w1->bounds().size());
+}
+
} // namespace test
} // namespace aura