diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/ash/wm/workspace | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/ash/wm/workspace')
24 files changed, 0 insertions, 7712 deletions
diff --git a/chromium/ash/wm/workspace/magnetism_matcher.cc b/chromium/ash/wm/workspace/magnetism_matcher.cc deleted file mode 100644 index e7d674b850c..00000000000 --- a/chromium/ash/wm/workspace/magnetism_matcher.cc +++ /dev/null @@ -1,194 +0,0 @@ -// 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. - -#include "ash/wm/workspace/magnetism_matcher.h" - -#include <algorithm> -#include <cmath> - -namespace ash { -namespace internal { - -namespace { - -// Returns true if |a| is close enough to |b| that the two edges snap. -bool IsCloseEnough(int a, int b) { - return abs(a - b) <= MagnetismMatcher::kMagneticDistance; -} - -// Returns true if the specified SecondaryMagnetismEdge can be matched with a -// primary edge of |primary|. |edges| is a bitmask of the allowed -// MagnetismEdges. -bool CanMatchSecondaryEdge(MagnetismEdge primary, - SecondaryMagnetismEdge secondary, - uint32 edges) { - // Convert |secondary| to a MagnetismEdge so we can compare it to |edges|. - MagnetismEdge secondary_as_magnetism_edge = MAGNETISM_EDGE_TOP; - switch (primary) { - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - if (secondary == SECONDARY_MAGNETISM_EDGE_LEADING) - secondary_as_magnetism_edge = MAGNETISM_EDGE_LEFT; - else if (secondary == SECONDARY_MAGNETISM_EDGE_TRAILING) - secondary_as_magnetism_edge = MAGNETISM_EDGE_RIGHT; - else - NOTREACHED(); - break; - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - if (secondary == SECONDARY_MAGNETISM_EDGE_LEADING) - secondary_as_magnetism_edge = MAGNETISM_EDGE_TOP; - else if (secondary == SECONDARY_MAGNETISM_EDGE_TRAILING) - secondary_as_magnetism_edge = MAGNETISM_EDGE_BOTTOM; - else - NOTREACHED(); - break; - } - return (edges & secondary_as_magnetism_edge) != 0; -} - -} // namespace - -// MagnetismEdgeMatcher -------------------------------------------------------- - -MagnetismEdgeMatcher::MagnetismEdgeMatcher(const gfx::Rect& bounds, - MagnetismEdge edge) - : bounds_(bounds), - edge_(edge) { - ranges_.push_back(GetSecondaryRange(bounds_)); -} - -MagnetismEdgeMatcher::~MagnetismEdgeMatcher() { -} - -bool MagnetismEdgeMatcher::ShouldAttach(const gfx::Rect& bounds) { - if (is_edge_obscured()) - return false; - - if (IsCloseEnough(GetPrimaryCoordinate(bounds_, edge_), - GetPrimaryCoordinate(bounds, FlipEdge(edge_)))) { - const Range range(GetSecondaryRange(bounds)); - Ranges::const_iterator i = - std::lower_bound(ranges_.begin(), ranges_.end(), range); - // Close enough, but only attach if some portion of the edge is visible. - if ((i != ranges_.begin() && RangesIntersect(*(i - 1), range)) || - (i != ranges_.end() && RangesIntersect(*i, range))) { - return true; - } - } - // NOTE: this checks against the current bounds, we may want to allow some - // flexibility here. - const Range primary_range(GetPrimaryRange(bounds)); - if (primary_range.first <= GetPrimaryCoordinate(bounds_, edge_) && - primary_range.second >= GetPrimaryCoordinate(bounds_, edge_)) { - UpdateRanges(GetSecondaryRange(bounds)); - } - return false; -} - -void MagnetismEdgeMatcher::UpdateRanges(const Range& range) { - Ranges::const_iterator it = - std::lower_bound(ranges_.begin(), ranges_.end(), range); - if (it != ranges_.begin() && RangesIntersect(*(it - 1), range)) - --it; - if (it == ranges_.end()) - return; - - for (size_t i = it - ranges_.begin(); - i < ranges_.size() && RangesIntersect(ranges_[i], range); ) { - if (range.first <= ranges_[i].first && - range.second >= ranges_[i].second) { - ranges_.erase(ranges_.begin() + i); - } else if (range.first < ranges_[i].first) { - DCHECK_GT(range.second, ranges_[i].first); - ranges_[i] = Range(range.second, ranges_[i].second); - ++i; - } else { - Range existing(ranges_[i]); - ranges_[i].second = range.first; - ++i; - if (existing.second > range.second) { - ranges_.insert(ranges_.begin() + i, - Range(range.second, existing.second)); - ++i; - } - } - } -} - -// MagnetismMatcher ------------------------------------------------------------ - -// static -const int MagnetismMatcher::kMagneticDistance = 8; - -MagnetismMatcher::MagnetismMatcher(const gfx::Rect& bounds, uint32 edges) - : edges_(edges) { - if (edges & MAGNETISM_EDGE_TOP) - matchers_.push_back(new MagnetismEdgeMatcher(bounds, MAGNETISM_EDGE_TOP)); - if (edges & MAGNETISM_EDGE_LEFT) - matchers_.push_back(new MagnetismEdgeMatcher(bounds, MAGNETISM_EDGE_LEFT)); - if (edges & MAGNETISM_EDGE_BOTTOM) { - matchers_.push_back(new MagnetismEdgeMatcher(bounds, - MAGNETISM_EDGE_BOTTOM)); - } - if (edges & MAGNETISM_EDGE_RIGHT) - matchers_.push_back(new MagnetismEdgeMatcher(bounds, MAGNETISM_EDGE_RIGHT)); -} - -MagnetismMatcher::~MagnetismMatcher() { -} - -bool MagnetismMatcher::ShouldAttach(const gfx::Rect& bounds, - MatchedEdge* edge) { - for (size_t i = 0; i < matchers_.size(); ++i) { - if (matchers_[i]->ShouldAttach(bounds)) { - edge->primary_edge = matchers_[i]->edge(); - AttachToSecondaryEdge(bounds, edge->primary_edge, - &(edge->secondary_edge)); - return true; - } - } - return false; -} - -bool MagnetismMatcher::AreEdgesObscured() const { - for (size_t i = 0; i < matchers_.size(); ++i) { - if (!matchers_[i]->is_edge_obscured()) - return false; - } - return true; -} - -void MagnetismMatcher::AttachToSecondaryEdge( - const gfx::Rect& bounds, - MagnetismEdge edge, - SecondaryMagnetismEdge* secondary_edge) const { - const gfx::Rect& src_bounds(matchers_[0]->bounds()); - if (edge == MAGNETISM_EDGE_LEFT || edge == MAGNETISM_EDGE_RIGHT) { - if (CanMatchSecondaryEdge(edge, SECONDARY_MAGNETISM_EDGE_LEADING, edges_) && - IsCloseEnough(bounds.y(), src_bounds.y())) { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_LEADING; - } else if (CanMatchSecondaryEdge(edge, SECONDARY_MAGNETISM_EDGE_TRAILING, - edges_) && - IsCloseEnough(bounds.bottom(), src_bounds.bottom())) { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_TRAILING; - } else { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_NONE; - } - } else { - if (CanMatchSecondaryEdge(edge, SECONDARY_MAGNETISM_EDGE_LEADING, edges_) && - IsCloseEnough(bounds.x(), src_bounds.x())) { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_LEADING; - } else if (CanMatchSecondaryEdge(edge, SECONDARY_MAGNETISM_EDGE_TRAILING, - edges_) && - IsCloseEnough(bounds.right(), src_bounds.right())) { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_TRAILING; - } else { - *secondary_edge = SECONDARY_MAGNETISM_EDGE_NONE; - } - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/magnetism_matcher.h b/chromium/ash/wm/workspace/magnetism_matcher.h deleted file mode 100644 index ff1f52810e9..00000000000 --- a/chromium/ash/wm/workspace/magnetism_matcher.h +++ /dev/null @@ -1,191 +0,0 @@ -// 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_MAGNETISM_MATCHER_H_ -#define ASH_WM_WORKSPACE_MAGNETISM_MATCHER_H_ - -#include <utility> -#include <vector> - -#include "ash/ash_export.h" -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/memory/scoped_vector.h" -#include "ui/gfx/rect.h" - -namespace ash { -namespace internal { - -enum MagnetismEdge { - MAGNETISM_EDGE_TOP = 1 << 0, - MAGNETISM_EDGE_LEFT = 1 << 1, - MAGNETISM_EDGE_BOTTOM = 1 << 2, - MAGNETISM_EDGE_RIGHT = 1 << 3, -}; - -const uint32 kAllMagnetismEdges = - MAGNETISM_EDGE_TOP | MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_BOTTOM | - MAGNETISM_EDGE_RIGHT; - -// MagnetismEdgeMatcher is used for matching a particular edge of a window. You -// shouldn't need to use this directly, instead use MagnetismMatcher which takes -// care of all edges. -// MagnetismEdgeMatcher maintains a range of the visible portions of the -// edge. As ShouldAttach() is invoked the visible range is updated. -class MagnetismEdgeMatcher { - public: - MagnetismEdgeMatcher(const gfx::Rect& bounds, MagnetismEdge edge); - ~MagnetismEdgeMatcher(); - - MagnetismEdge edge() const { return edge_; } - const gfx::Rect& bounds() const { return bounds_; } - - // Returns true if the edge is completely obscured. If true ShouldAttach() - // will return false. - bool is_edge_obscured() const { return ranges_.empty(); } - - // Returns true if should attach to the specified bounds. - bool ShouldAttach(const gfx::Rect& bounds); - - private: - typedef std::pair<int,int> Range; - typedef std::vector<Range> Ranges; - - // Removes |range| from |ranges_|. - void UpdateRanges(const Range& range); - - static int GetPrimaryCoordinate(const gfx::Rect& bounds, MagnetismEdge edge) { - switch (edge) { - case MAGNETISM_EDGE_TOP: - return bounds.y(); - case MAGNETISM_EDGE_LEFT: - return bounds.x(); - case MAGNETISM_EDGE_BOTTOM: - return bounds.bottom(); - case MAGNETISM_EDGE_RIGHT: - return bounds.right(); - } - NOTREACHED(); - return 0; - } - - static MagnetismEdge FlipEdge(MagnetismEdge edge) { - switch (edge) { - case MAGNETISM_EDGE_TOP: - return MAGNETISM_EDGE_BOTTOM; - case MAGNETISM_EDGE_BOTTOM: - return MAGNETISM_EDGE_TOP; - case MAGNETISM_EDGE_LEFT: - return MAGNETISM_EDGE_RIGHT; - case MAGNETISM_EDGE_RIGHT: - return MAGNETISM_EDGE_LEFT; - } - NOTREACHED(); - return MAGNETISM_EDGE_LEFT; - } - - Range GetPrimaryRange(const gfx::Rect& bounds) const { - switch (edge_) { - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - return Range(bounds.y(), bounds.bottom()); - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - return Range(bounds.x(), bounds.right()); - } - NOTREACHED(); - return Range(); - } - - Range GetSecondaryRange(const gfx::Rect& bounds) const { - switch (edge_) { - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - return Range(bounds.x(), bounds.right()); - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - return Range(bounds.y(), bounds.bottom()); - } - NOTREACHED(); - return Range(); - } - - static bool RangesIntersect(const Range& r1, const Range& r2) { - return r2.first < r1.second && r2.second > r1.first; - } - - // The bounds of window. - const gfx::Rect bounds_; - - // The edge this matcher checks. - const MagnetismEdge edge_; - - // Visible ranges of the edge. Initialized with GetSecondaryRange() and - // updated as ShouldAttach() is invoked. When empty the edge is completely - // obscured by other bounds. - Ranges ranges_; - - DISALLOW_COPY_AND_ASSIGN(MagnetismEdgeMatcher); -}; - -enum SecondaryMagnetismEdge { - SECONDARY_MAGNETISM_EDGE_LEADING, - SECONDARY_MAGNETISM_EDGE_TRAILING, - SECONDARY_MAGNETISM_EDGE_NONE, -}; - -// Used to identify a matched edge. |primary_edge| is relative to the source and -// indicates the edge the two are to share. For example, if |primary_edge| is -// MAGNETISM_EDGE_RIGHT then the right edge of the source should snap to to the -// left edge of the target. |secondary_edge| indicates one of the edges along -// the opposite axis should should also be aligned. For example, if -// |primary_edge| is MAGNETISM_EDGE_RIGHT and |secondary_edge| is -// SECONDARY_MAGNETISM_EDGE_LEADING then the source should snap to the left top -// corner of the target. -struct MatchedEdge { - MagnetismEdge primary_edge; - SecondaryMagnetismEdge secondary_edge; -}; - -// MagnetismMatcher is used to test if a window should snap to another window. -// To use MagnetismMatcher do the following: -// . Create it with the bounds of the window being dragged. -// . Iterate over the child windows checking if the window being dragged should -// attach to it using ShouldAttach(). -// . Use AreEdgesObscured() to test if no other windows can match (because all -// edges are completely obscured). -class ASH_EXPORT MagnetismMatcher { - public: - static const int kMagneticDistance; - - // |edges| is a bitmask of MagnetismEdges to match against. - MagnetismMatcher(const gfx::Rect& bounds, uint32 edges); - ~MagnetismMatcher(); - - // Returns true if |bounds| is close enough to the initial bounds that the two - // should be attached. If true is returned |edge| is set to indicates how the - // two should snap together. See description of MatchedEdge for details. - bool ShouldAttach(const gfx::Rect& bounds, MatchedEdge* edge); - - // Returns true if no other matches are possible. - bool AreEdgesObscured() const; - - private: - // Sets |secondary_edge| based on whether the secondary edges should snap. - void AttachToSecondaryEdge(const gfx::Rect& bounds, - MagnetismEdge edge, - SecondaryMagnetismEdge* secondary_edge) const; - - // The edges to match against. - const int32 edges_; - - ScopedVector<MagnetismEdgeMatcher> matchers_; - - DISALLOW_COPY_AND_ASSIGN(MagnetismMatcher); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_MAGNETISM_MATCHER_H_ diff --git a/chromium/ash/wm/workspace/magnetism_matcher_unittest.cc b/chromium/ash/wm/workspace/magnetism_matcher_unittest.cc deleted file mode 100644 index 054622ff572..00000000000 --- a/chromium/ash/wm/workspace/magnetism_matcher_unittest.cc +++ /dev/null @@ -1,171 +0,0 @@ -// 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. - -#include "ash/wm/workspace/magnetism_matcher.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash { -namespace internal { - -// Trivial test case verifying assertions on left edge. -TEST(MagnetismMatcherTest, TrivialLeft) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 50, 60); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - EXPECT_FALSE(matcher.AreEdgesObscured()); - MatchedEdge edge; - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - distance - 10, - initial_bounds.y() - distance - 10, 2, 3), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 2, initial_bounds.y(), 1, 1), - &edge)); - EXPECT_EQ(MAGNETISM_EDGE_LEFT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_LEADING, edge.secondary_edge); - - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 2, - initial_bounds.y() + distance + 1 , 1, 1), - &edge)); - EXPECT_EQ(MAGNETISM_EDGE_LEFT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -// Trivial test case verifying assertions on bottom edge. -TEST(MagnetismMatcherTest, TrivialBottom) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 50, 60); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - EXPECT_FALSE(matcher.AreEdgesObscured()); - MatchedEdge edge; - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - distance - 10, - initial_bounds.y() - distance - 10, 2, 3), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 2, - initial_bounds.bottom() + 4, 10, 1), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_BOTTOM, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_LEADING, edge.secondary_edge); - - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() + distance + 1, - initial_bounds.bottom() + 4, 10, 1), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_BOTTOM, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); - - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() - 10 - 1, - initial_bounds.bottom() + 4, 10, 1), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_BOTTOM, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_TRAILING, edge.secondary_edge); -} - -// Verifies we don't match an obscured corner. -TEST(MagnetismMatcherTest, ObscureLeading) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 150, 160); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - MatchedEdge edge; - // Overlap with the upper right corner. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() - distance * 2, - initial_bounds.y() - distance - 2, - distance * 3, - (distance + 2) * 2), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - // Verify doesn't match the following which is obscured by first. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() + 1, - initial_bounds.y(), - distance, - 5), &edge)); - // Should match the following which extends into non-overlapping region. - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() + 1, - initial_bounds.y() + distance + 1, - distance, - 15), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_RIGHT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -// Verifies obscuring one side doesn't obscure the other. -TEST(MagnetismMatcherTest, DontObscureOtherSide) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 150, 160); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - MatchedEdge edge; - // Overlap with the left side. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - distance + 1, - initial_bounds.y() + 2, - distance * 2 + 2, - initial_bounds.height() + distance * 4), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - // Should match the right side since it isn't obscured. - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.right() - 1, - initial_bounds.y() + distance + 1, - distance, - 5), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_RIGHT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -// Verifies we don't match an obscured center. -TEST(MagnetismMatcherTest, ObscureCenter) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 150, 160); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - MatchedEdge edge; - // Overlap with the center bottom edge. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(100, initial_bounds.bottom() - distance - 2, - 20, - (distance + 2) * 2), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - // Verify doesn't match the following which is obscured by first. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(110, initial_bounds.bottom() + 1, - 10, 5), &edge)); - // Should match the following which extends into non-overlapping region. - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(90, - initial_bounds.bottom() + 1, - 10, 5), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_BOTTOM, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -// Verifies we don't match an obscured trailing edge. -TEST(MagnetismMatcherTest, ObscureTrailing) { - const int distance = MagnetismMatcher::kMagneticDistance; - const gfx::Rect initial_bounds(20, 10, 150, 160); - MagnetismMatcher matcher(initial_bounds, kAllMagnetismEdges); - MatchedEdge edge; - // Overlap with the trailing left edge. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - distance - 2, - 150, - (distance + 2) * 2, - 50), &edge)); - EXPECT_FALSE(matcher.AreEdgesObscured()); - // Verify doesn't match the following which is obscured by first. - EXPECT_FALSE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 4, - 160, 3, 20), &edge)); - // Should match the following which extends into non-overlapping region. - EXPECT_TRUE(matcher.ShouldAttach( - gfx::Rect(initial_bounds.x() - 4, - 140, 3, 20), &edge)); - EXPECT_EQ(MAGNETISM_EDGE_LEFT, edge.primary_edge); - EXPECT_EQ(SECONDARY_MAGNETISM_EDGE_NONE, edge.secondary_edge); -} - -} // namespace internal -} // namespace ash - diff --git a/chromium/ash/wm/workspace/multi_window_resize_controller.cc b/chromium/ash/wm/workspace/multi_window_resize_controller.cc deleted file mode 100644 index 597acbf88ec..00000000000 --- a/chromium/ash/wm/workspace/multi_window_resize_controller.cc +++ /dev/null @@ -1,545 +0,0 @@ -// 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. - -#include "ash/wm/workspace/multi_window_resize_controller.h" - -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/workspace/workspace_event_handler.h" -#include "ash/wm/workspace/workspace_window_resizer.h" -#include "grit/ash_resources.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/image/image.h" -#include "ui/gfx/screen.h" -#include "ui/views/corewm/compound_event_filter.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -using aura::Window; - -namespace ash { -namespace internal { - -namespace { - -// Delay before showing. -const int kShowDelayMS = 400; - -// Delay before hiding. -const int kHideDelayMS = 500; - -// Padding from the bottom/right edge the resize widget is shown at. -const int kResizeWidgetPadding = 15; - -bool ContainsX(Window* window, int x) { - return window->bounds().x() <= x && window->bounds().right() >= x; -} - -bool ContainsY(Window* window, int y) { - return window->bounds().y() <= y && window->bounds().bottom() >= y; -} - -bool Intersects(int x1, int max_1, int x2, int max_2) { - return x2 <= max_1 && max_2 > x1; -} - -} // namespace - -// View contained in the widget. Passes along mouse events to the -// MultiWindowResizeController so that it can start/stop the resize loop. -class MultiWindowResizeController::ResizeView : public views::View { - public: - explicit ResizeView(MultiWindowResizeController* controller, - Direction direction) - : controller_(controller), - direction_(direction), - image_(NULL) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - int image_id = - direction == TOP_BOTTOM ? IDR_AURA_MULTI_WINDOW_RESIZE_H : - IDR_AURA_MULTI_WINDOW_RESIZE_V; - image_ = rb.GetImageNamed(image_id).ToImageSkia(); - } - - // views::View overrides: - virtual gfx::Size GetPreferredSize() OVERRIDE { - return gfx::Size(image_->width(), image_->height()); - } - virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { - canvas->DrawImageInt(*image_, 0, 0); - } - virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE { - gfx::Point location(event.location()); - views::View::ConvertPointToScreen(this, &location); - controller_->StartResize(location); - return true; - } - virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE { - gfx::Point location(event.location()); - views::View::ConvertPointToScreen(this, &location); - controller_->Resize(location, event.flags()); - return true; - } - virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE { - controller_->CompleteResize(event.flags()); - } - virtual void OnMouseCaptureLost() OVERRIDE { - controller_->CancelResize(); - } - virtual gfx::NativeCursor GetCursor( - const ui::MouseEvent& event) OVERRIDE { - int component = (direction_ == LEFT_RIGHT) ? HTRIGHT : HTBOTTOM; - return views::corewm::CompoundEventFilter::CursorForWindowComponent( - component); - } - - private: - MultiWindowResizeController* controller_; - const Direction direction_; - const gfx::ImageSkia* image_; - - DISALLOW_COPY_AND_ASSIGN(ResizeView); -}; - -// MouseWatcherHost implementation for MultiWindowResizeController. Forwards -// Contains() to MultiWindowResizeController. -class MultiWindowResizeController::ResizeMouseWatcherHost : - public views::MouseWatcherHost { - public: - ResizeMouseWatcherHost(MultiWindowResizeController* host) : host_(host) {} - - // MouseWatcherHost overrides: - virtual bool Contains(const gfx::Point& point_in_screen, - MouseEventType type) OVERRIDE { - return host_->IsOverWindows(point_in_screen); - } - - private: - MultiWindowResizeController* host_; - - DISALLOW_COPY_AND_ASSIGN(ResizeMouseWatcherHost); -}; - -MultiWindowResizeController::ResizeWindows::ResizeWindows() - : window1(NULL), - window2(NULL), - direction(TOP_BOTTOM){ -} - -MultiWindowResizeController::ResizeWindows::~ResizeWindows() { -} - -bool MultiWindowResizeController::ResizeWindows::Equals( - const ResizeWindows& other) const { - return window1 == other.window1 && - window2 == other.window2 && - direction == other.direction; -} - -MultiWindowResizeController::MultiWindowResizeController() { -} - -MultiWindowResizeController::~MultiWindowResizeController() { - window_resizer_.reset(); - Hide(); -} - -void MultiWindowResizeController::Show(Window* window, - int component, - const gfx::Point& point_in_window) { - // When the resize widget is showing we ignore Show() requests. Instead we - // only care about mouse movements from MouseWatcher. This is necessary as - // WorkspaceEventHandler only sees mouse movements over the windows, not all - // windows or over the desktop. - if (resize_widget_) - return; - - ResizeWindows windows(DetermineWindows(window, component, point_in_window)); - if (IsShowing()) { - if (windows_.Equals(windows)) - return; // Over the same windows. - DelayedHide(); - } - - if (!windows.is_valid()) - return; - Hide(); - windows_ = windows; - windows_.window1->AddObserver(this); - windows_.window2->AddObserver(this); - show_location_in_parent_ = point_in_window; - Window::ConvertPointToTarget( - window, window->parent(), &show_location_in_parent_); - if (show_timer_.IsRunning()) - return; - show_timer_.Start( - FROM_HERE, base::TimeDelta::FromMilliseconds(kShowDelayMS), - this, &MultiWindowResizeController::ShowIfValidMouseLocation); -} - -void MultiWindowResizeController::Hide() { - hide_timer_.Stop(); - if (window_resizer_) - return; // Ignore hides while actively resizing. - - if (windows_.window1) { - windows_.window1->RemoveObserver(this); - windows_.window1 = NULL; - } - if (windows_.window2) { - windows_.window2->RemoveObserver(this); - windows_.window2 = NULL; - } - - show_timer_.Stop(); - - if (!resize_widget_) - return; - - for (size_t i = 0; i < windows_.other_windows.size(); ++i) - windows_.other_windows[i]->RemoveObserver(this); - mouse_watcher_.reset(); - resize_widget_.reset(); - windows_ = ResizeWindows(); -} - -void MultiWindowResizeController::MouseMovedOutOfHost() { - Hide(); -} - -void MultiWindowResizeController::OnWindowDestroying( - aura::Window* window) { - // Have to explicitly reset the WindowResizer, otherwise Hide() does nothing. - window_resizer_.reset(); - Hide(); -} - -MultiWindowResizeController::ResizeWindows -MultiWindowResizeController::DetermineWindowsFromScreenPoint( - aura::Window* window) const { - gfx::Point mouse_location( - gfx::Screen::GetScreenFor(window)->GetCursorScreenPoint()); - wm::ConvertPointFromScreen(window, &mouse_location); - const int component = - window->delegate()->GetNonClientComponent(mouse_location); - return DetermineWindows(window, component, mouse_location); -} - -MultiWindowResizeController::ResizeWindows -MultiWindowResizeController::DetermineWindows( - Window* window, - int window_component, - const gfx::Point& point) const { - ResizeWindows result; - gfx::Point point_in_parent(point); - Window::ConvertPointToTarget(window, window->parent(), &point_in_parent); - switch (window_component) { - case HTRIGHT: - result.direction = LEFT_RIGHT; - result.window1 = window; - result.window2 = FindWindowByEdge( - window, HTLEFT, window->bounds().right(), point_in_parent.y()); - break; - case HTLEFT: - result.direction = LEFT_RIGHT; - result.window1 = FindWindowByEdge( - window, HTRIGHT, window->bounds().x(), point_in_parent.y()); - result.window2 = window; - break; - case HTTOP: - result.direction = TOP_BOTTOM; - result.window1 = FindWindowByEdge( - window, HTBOTTOM, point_in_parent.x(), window->bounds().y()); - result.window2 = window; - break; - case HTBOTTOM: - result.direction = TOP_BOTTOM; - result.window1 = window; - result.window2 = FindWindowByEdge( - window, HTTOP, point_in_parent.x(), window->bounds().bottom()); - break; - default: - break; - } - return result; -} - -Window* MultiWindowResizeController::FindWindowByEdge( - Window* window_to_ignore, - int edge_want, - int x, - int y) const { - Window* parent = window_to_ignore->parent(); - const Window::Windows& windows(parent->children()); - for (Window::Windows::const_reverse_iterator i = windows.rbegin(); - i != windows.rend(); ++i) { - Window* window = *i; - if (window == window_to_ignore || !window->IsVisible()) - continue; - switch (edge_want) { - case HTLEFT: - if (ContainsY(window, y) && window->bounds().x() == x) - return window; - break; - case HTRIGHT: - if (ContainsY(window, y) && window->bounds().right() == x) - return window; - break; - case HTTOP: - if (ContainsX(window, x) && window->bounds().y() == y) - return window; - break; - case HTBOTTOM: - if (ContainsX(window, x) && window->bounds().bottom() == y) - return window; - break; - default: - NOTREACHED(); - } - // Window doesn't contain the edge, but if window contains |point| - // it's obscuring any other window that could be at the location. - if (window->bounds().Contains(x, y)) - return NULL; - } - return NULL; -} - -aura::Window* MultiWindowResizeController::FindWindowTouching( - aura::Window* window, - Direction direction) const { - int right = window->bounds().right(); - int bottom = window->bounds().bottom(); - Window* parent = window->parent(); - const Window::Windows& windows(parent->children()); - for (Window::Windows::const_reverse_iterator i = windows.rbegin(); - i != windows.rend(); ++i) { - Window* other = *i; - if (other == window || !other->IsVisible()) - continue; - switch (direction) { - case TOP_BOTTOM: - if (other->bounds().y() == bottom && - Intersects(other->bounds().x(), other->bounds().right(), - window->bounds().x(), window->bounds().right())) { - return other; - } - break; - case LEFT_RIGHT: - if (other->bounds().x() == right && - Intersects(other->bounds().y(), other->bounds().bottom(), - window->bounds().y(), window->bounds().bottom())) { - return other; - } - break; - default: - NOTREACHED(); - } - } - return NULL; -} - -void MultiWindowResizeController::FindWindowsTouching( - aura::Window* start, - Direction direction, - std::vector<aura::Window*>* others) const { - while (start) { - start = FindWindowTouching(start, direction); - if (start) - others->push_back(start); - } -} - -void MultiWindowResizeController::DelayedHide() { - if (hide_timer_.IsRunning()) - return; - - hide_timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(kHideDelayMS), - this, &MultiWindowResizeController::Hide); -} - -void MultiWindowResizeController::ShowIfValidMouseLocation() { - if (DetermineWindowsFromScreenPoint(windows_.window1).Equals(windows_) || - DetermineWindowsFromScreenPoint(windows_.window2).Equals(windows_)) { - ShowNow(); - } else { - Hide(); - } -} - -void MultiWindowResizeController::ShowNow() { - DCHECK(!resize_widget_.get()); - DCHECK(windows_.is_valid()); - show_timer_.Stop(); - resize_widget_.reset(new views::Widget); - views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.parent = Shell::GetContainer( - Shell::GetTargetRootWindow(), - internal::kShellWindowId_AlwaysOnTopContainer); - params.can_activate = false; - ResizeView* view = new ResizeView(this, windows_.direction); - resize_widget_->set_focus_on_creation(false); - resize_widget_->Init(params); - views::corewm::SetWindowVisibilityAnimationType( - resize_widget_->GetNativeWindow(), - views::corewm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); - resize_widget_->GetNativeWindow()->SetName("MultiWindowResizeController"); - resize_widget_->SetContentsView(view); - show_bounds_in_screen_ = ScreenAsh::ConvertRectToScreen( - windows_.window1->parent(), - CalculateResizeWidgetBounds(show_location_in_parent_)); - resize_widget_->SetBounds(show_bounds_in_screen_); - resize_widget_->Show(); - mouse_watcher_.reset(new views::MouseWatcher( - new ResizeMouseWatcherHost(this), - this)); - mouse_watcher_->set_notify_on_exit_time( - base::TimeDelta::FromMilliseconds(kHideDelayMS)); - mouse_watcher_->Start(); -} - -bool MultiWindowResizeController::IsShowing() const { - return resize_widget_.get() || show_timer_.IsRunning(); -} - -void MultiWindowResizeController::StartResize( - const gfx::Point& location_in_screen) { - DCHECK(!window_resizer_.get()); - DCHECK(windows_.is_valid()); - hide_timer_.Stop(); - gfx::Point location_in_parent(location_in_screen); - aura::client::GetScreenPositionClient(windows_.window2->GetRootWindow())-> - ConvertPointFromScreen(windows_.window2->parent(), &location_in_parent); - std::vector<aura::Window*> windows; - windows.push_back(windows_.window2); - DCHECK(windows_.other_windows.empty()); - FindWindowsTouching(windows_.window2, windows_.direction, - &windows_.other_windows); - for (size_t i = 0; i < windows_.other_windows.size(); ++i) { - windows_.other_windows[i]->AddObserver(this); - windows.push_back(windows_.other_windows[i]); - } - int component = windows_.direction == LEFT_RIGHT ? HTRIGHT : HTBOTTOM; - window_resizer_.reset(WorkspaceWindowResizer::Create( - windows_.window1, - location_in_parent, - component, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, - windows)); -} - -void MultiWindowResizeController::Resize(const gfx::Point& location_in_screen, - int event_flags) { - gfx::Point location_in_parent(location_in_screen); - aura::client::GetScreenPositionClient(windows_.window1->GetRootWindow())-> - ConvertPointFromScreen(windows_.window1->parent(), &location_in_parent); - window_resizer_->Drag(location_in_parent, event_flags); - gfx::Rect bounds = ScreenAsh::ConvertRectToScreen( - windows_.window1->parent(), - CalculateResizeWidgetBounds(location_in_parent)); - - if (windows_.direction == LEFT_RIGHT) - bounds.set_y(show_bounds_in_screen_.y()); - else - bounds.set_x(show_bounds_in_screen_.x()); - resize_widget_->SetBounds(bounds); -} - -void MultiWindowResizeController::CompleteResize(int event_flags) { - window_resizer_->CompleteDrag(event_flags); - window_resizer_.reset(); - - // Mouse may still be over resizer, if not hide. - gfx::Point screen_loc = Shell::GetScreen()->GetCursorScreenPoint(); - if (!resize_widget_->GetWindowBoundsInScreen().Contains(screen_loc)) { - Hide(); - } else { - // If the mouse is over the resizer we need to remove observers on any of - // the |other_windows|. If we start another resize we'll recalculate the - // |other_windows| and invoke AddObserver() as necessary. - for (size_t i = 0; i < windows_.other_windows.size(); ++i) - windows_.other_windows[i]->RemoveObserver(this); - windows_.other_windows.clear(); - } -} - -void MultiWindowResizeController::CancelResize() { - if (!window_resizer_) - return; // Happens if window was destroyed and we nuked the WindowResizer. - window_resizer_->RevertDrag(); - window_resizer_.reset(); - Hide(); -} - -gfx::Rect MultiWindowResizeController::CalculateResizeWidgetBounds( - const gfx::Point& location_in_parent) const { - gfx::Size pref = resize_widget_->GetContentsView()->GetPreferredSize(); - int x = 0, y = 0; - if (windows_.direction == LEFT_RIGHT) { - x = windows_.window1->bounds().right() - pref.width() / 2; - y = location_in_parent.y() + kResizeWidgetPadding; - if (y + pref.height() / 2 > windows_.window1->bounds().bottom() && - y + pref.height() / 2 > windows_.window2->bounds().bottom()) { - y = location_in_parent.y() - kResizeWidgetPadding - pref.height(); - } - } else { - x = location_in_parent.x() + kResizeWidgetPadding; - if (x + pref.height() / 2 > windows_.window1->bounds().right() && - x + pref.height() / 2 > windows_.window2->bounds().right()) { - x = location_in_parent.x() - kResizeWidgetPadding - pref.width(); - } - y = windows_.window1->bounds().bottom() - pref.height() / 2; - } - return gfx::Rect(x, y, pref.width(), pref.height()); -} - -bool MultiWindowResizeController::IsOverWindows( - const gfx::Point& location_in_screen) const { - if (window_resizer_) - return true; // Ignore hides while actively resizing. - - if (resize_widget_->GetWindowBoundsInScreen().Contains(location_in_screen)) - return true; - - int hit1, hit2; - if (windows_.direction == TOP_BOTTOM) { - hit1 = HTBOTTOM; - hit2 = HTTOP; - } else { - hit1 = HTRIGHT; - hit2 = HTLEFT; - } - - return IsOverWindow(windows_.window1, location_in_screen, hit1) || - IsOverWindow(windows_.window2, location_in_screen, hit2); -} - -bool MultiWindowResizeController::IsOverWindow( - aura::Window* window, - const gfx::Point& location_in_screen, - int component) const { - if (!window->delegate()) - return false; - - gfx::Point window_loc(location_in_screen); - aura::Window::ConvertPointToTarget( - window->GetRootWindow(), window, &window_loc); - return window->HitTest(window_loc) && - window->delegate()->GetNonClientComponent(window_loc) == component; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/multi_window_resize_controller.h b/chromium/ash/wm/workspace/multi_window_resize_controller.h deleted file mode 100644 index 02eeb2511a4..00000000000 --- a/chromium/ash/wm/workspace/multi_window_resize_controller.h +++ /dev/null @@ -1,186 +0,0 @@ -// 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_MULTI_WINDOW_RESIZE_CONTROLLER_H_ -#define ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_ - -#include <vector> - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/timer/timer.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/rect.h" -#include "ui/views/mouse_watcher.h" - -namespace aura { -class Window; -} - -namespace views { -class Widget; -} - -namespace ash { -namespace internal { - -class MultiWindowResizeControllerTest; -class WorkspaceWindowResizer; - -// Two directions resizes happen in. -enum Direction { - TOP_BOTTOM, - LEFT_RIGHT, -}; - -// MultiWindowResizeController is responsible for determining and showing a -// widget that allows resizing multiple windows at the same time. -// MultiWindowResizeController is driven by WorkspaceEventFilter. -class ASH_EXPORT MultiWindowResizeController : - public views::MouseWatcherListener, public aura::WindowObserver { - public: - MultiWindowResizeController(); - virtual ~MultiWindowResizeController(); - - // If necessary, shows the resize widget. |window| is the window the mouse - // is over, |component| the edge and |point| the location of the mouse. - void Show(aura::Window* window, int component, const gfx::Point& point); - - // Hides the resize widget. - void Hide(); - - // MouseWatcherListenre overrides: - virtual void MouseMovedOutOfHost() OVERRIDE; - - // WindowObserver overrides: - virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; - - private: - friend class MultiWindowResizeControllerTest; - - // Used to track the two resizable windows and direction. - struct ResizeWindows { - ResizeWindows(); - ~ResizeWindows(); - - // Returns true if |other| equals this ResizeWindows. This does *not* - // consider the windows in |other_windows|. - bool Equals(const ResizeWindows& other) const; - - // Returns true if this ResizeWindows is valid. - bool is_valid() const { return window1 && window2; } - - // The left/top window to resize. - aura::Window* window1; - - // Other window to resize. - aura::Window* window2; - - // Direction - Direction direction; - - // Windows after |window2| that are to be resized. Determined at the time - // the resize starts. - std::vector<aura::Window*> other_windows; - }; - - class ResizeMouseWatcherHost; - class ResizeView; - - // Returns a ResizeWindows based on the specified arguments. Use is_valid() - // to test if the return value is a valid multi window resize location. - ResizeWindows DetermineWindows(aura::Window* window, - int window_component, - const gfx::Point& point) const; - - // Variant of DetermineWindows() that uses the current location of the mouse - // to determine the resize windows. - ResizeWindows DetermineWindowsFromScreenPoint(aura::Window* window) const; - - // Finds a window by edge (one of the constants HitTestCompat. - aura::Window* FindWindowByEdge(aura::Window* window_to_ignore, - int edge_want, - int x, - int y) const; - - // Returns the first window touching |window|. - aura::Window* FindWindowTouching(aura::Window* window, - Direction direction) const; - - // Places any windows touching |start| into |others|. - void FindWindowsTouching(aura::Window* start, - Direction direction, - std::vector<aura::Window*>* others) const; - - // Hides the window after a delay. - void DelayedHide(); - - // Shows the resizer if the mouse is still at a valid location. This is called - // from the |show_timer_|. - void ShowIfValidMouseLocation(); - - // Shows the widget immediately. - void ShowNow(); - - // Returns true if the widget is showing. - bool IsShowing() const; - - // Initiates a resize. - void StartResize(const gfx::Point& location_in_screen); - - // Resizes to the new location. - void Resize(const gfx::Point& location_in_screen, int event_flags); - - // Completes the resize. - void CompleteResize(int event_flags); - - // Cancels the resize. - void CancelResize(); - - // Returns the bounds for the resize widget. - gfx::Rect CalculateResizeWidgetBounds( - const gfx::Point& location_in_parent) const; - - // Returns true if |location_in_screen| is over the resize windows - // (or the resize widget itself). - bool IsOverWindows(const gfx::Point& location_in_screen) const; - - // Returns true if |location_in_screen| is over |window|. - bool IsOverWindow(aura::Window* window, - const gfx::Point& location_in_screen, - int component) const; - - // Windows and direction to resize. - ResizeWindows windows_; - - // Timer before hiding. - base::OneShotTimer<MultiWindowResizeController> hide_timer_; - - // Timer used before showing. - base::OneShotTimer<MultiWindowResizeController> show_timer_; - - scoped_ptr<views::Widget> resize_widget_; - - // If non-null we're in a resize loop. - scoped_ptr<WorkspaceWindowResizer> window_resizer_; - - // Mouse coordinate passed to Show() in container's coodinates. - gfx::Point show_location_in_parent_; - - // Bounds the widget was last shown at in screen coordinates. - gfx::Rect show_bounds_in_screen_; - - // Used to detect whether the mouse is over the windows. While - // |resize_widget_| is non-NULL (ie the widget is showing) we ignore calls - // to Show(). - scoped_ptr<views::MouseWatcher> mouse_watcher_; - - DISALLOW_COPY_AND_ASSIGN(MultiWindowResizeController); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_MULTI_WINDOW_RESIZE_CONTROLLER_H_ diff --git a/chromium/ash/wm/workspace/multi_window_resize_controller_unittest.cc b/chromium/ash/wm/workspace/multi_window_resize_controller_unittest.cc deleted file mode 100644 index a4756aa729d..00000000000 --- a/chromium/ash/wm/workspace/multi_window_resize_controller_unittest.cc +++ /dev/null @@ -1,258 +0,0 @@ -// 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. - -#include "ash/wm/workspace/multi_window_resize_controller.h" - -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/shell_test_api.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace_controller.h" -#include "ash/wm/workspace_controller_test_helper.h" -#include "ash/wm/workspace/workspace_event_handler_test_helper.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/window.h" -#include "ui/base/hit_test.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -class MultiWindowResizeControllerTest : public test::AshTestBase { - public: - MultiWindowResizeControllerTest() : resize_controller_(NULL) {} - virtual ~MultiWindowResizeControllerTest() {} - - virtual void SetUp() OVERRIDE { - test::AshTestBase::SetUp(); - WorkspaceController* wc = - test::ShellTestApi(Shell::GetInstance()).workspace_controller(); - WorkspaceEventHandler* event_handler = - WorkspaceControllerTestHelper(wc).GetEventHandler(); - resize_controller_ = WorkspaceEventHandlerTestHelper(event_handler). - resize_controller(); - } - - protected: - aura::Window* CreateTestWindow(aura::WindowDelegate* delegate, - const gfx::Rect& bounds) { - aura::Window* window = new aura::Window(delegate); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - ParentWindowInPrimaryRootWindow(window); - window->SetBounds(bounds); - window->Show(); - return window; - } - - void ShowNow() { - resize_controller_->ShowNow(); - } - - bool IsShowing() { - return resize_controller_->IsShowing(); - } - - bool HasPendingShow() { - return resize_controller_->show_timer_.IsRunning(); - } - - bool HasPendingHide() { - return resize_controller_->hide_timer_.IsRunning(); - } - - void Hide() { - resize_controller_->Hide(); - } - - bool HasTarget(aura::Window* window) { - if (!resize_controller_->windows_.is_valid()) - return false; - if ((resize_controller_->windows_.window1 == window || - resize_controller_->windows_.window2 == window)) - return true; - for (size_t i = 0; - i < resize_controller_->windows_.other_windows.size(); ++i) { - if (resize_controller_->windows_.other_windows[i] == window) - return true; - } - return false; - } - - bool IsOverWindows(const gfx::Point& loc) { - return resize_controller_->IsOverWindows(loc); - } - - views::Widget* resize_widget() { - return resize_controller_->resize_widget_.get(); - } - - MultiWindowResizeController* resize_controller_; - - private: - DISALLOW_COPY_AND_ASSIGN(MultiWindowResizeControllerTest); -}; - -// Assertions around moving mouse over 2 windows. -TEST_F(MultiWindowResizeControllerTest, BasicTests) { - aura::test::TestWindowDelegate delegate1; - scoped_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); - delegate1.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate2; - scoped_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); - delegate2.set_window_component(HTRIGHT); - aura::test::EventGenerator generator(w1->GetRootWindow()); - generator.MoveMouseTo(99, 50); - EXPECT_TRUE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Force a show now. - ShowNow(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - EXPECT_FALSE(IsOverWindows(gfx::Point(200, 200))); - - // Have to explicitly invoke this as MouseWatcher listens for native events. - resize_controller_->MouseMovedOutOfHost(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_FALSE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); -} - -// Makes sure deleting a window hides. -TEST_F(MultiWindowResizeControllerTest, DeleteWindow) { - aura::test::TestWindowDelegate delegate1; - scoped_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); - delegate1.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate2; - scoped_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); - delegate2.set_window_component(HTRIGHT); - aura::test::EventGenerator generator(w1->GetRootWindow()); - generator.MoveMouseTo(99, 50); - EXPECT_TRUE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Force a show now. - ShowNow(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Move the mouse over the resize widget. - ASSERT_TRUE(resize_widget()); - gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen()); - generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Move the resize widget - generator.PressLeftButton(); - generator.MoveMouseTo(bounds.x() + 10, bounds.y() + 10); - - // Delete w2. - w2.reset(); - EXPECT_TRUE(resize_widget() == NULL); - EXPECT_FALSE(HasPendingShow()); - EXPECT_FALSE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - EXPECT_FALSE(HasTarget(w1.get())); -} - -// Tests resizing. -TEST_F(MultiWindowResizeControllerTest, Drag) { - aura::test::TestWindowDelegate delegate1; - scoped_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); - delegate1.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate2; - scoped_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); - delegate2.set_window_component(HTRIGHT); - aura::test::EventGenerator generator(w1->GetRootWindow()); - generator.MoveMouseTo(99, 50); - EXPECT_TRUE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Force a show now. - ShowNow(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Move the mouse over the resize widget. - ASSERT_TRUE(resize_widget()); - gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen()); - generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // Move the resize widget - generator.PressLeftButton(); - generator.MoveMouseTo(bounds.x() + 11, bounds.y() + 10); - generator.ReleaseLeftButton(); - - EXPECT_TRUE(resize_widget()); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - EXPECT_EQ("0,0 110x100", w1->bounds().ToString()); - EXPECT_EQ("110,0 100x100", w2->bounds().ToString()); -} - -// Makes sure three windows are picked up. -TEST_F(MultiWindowResizeControllerTest, Three) { - aura::test::TestWindowDelegate delegate1; - scoped_ptr<aura::Window> w1( - CreateTestWindow(&delegate1, gfx::Rect(0, 0, 100, 100))); - delegate1.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate2; - scoped_ptr<aura::Window> w2( - CreateTestWindow(&delegate2, gfx::Rect(100, 0, 100, 100))); - delegate2.set_window_component(HTRIGHT); - aura::test::TestWindowDelegate delegate3; - scoped_ptr<aura::Window> w3( - CreateTestWindow(&delegate2, gfx::Rect(200, 0, 100, 100))); - delegate3.set_window_component(HTRIGHT); - - aura::test::EventGenerator generator(w1->GetRootWindow()); - generator.MoveMouseTo(99, 50); - EXPECT_TRUE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - EXPECT_FALSE(HasTarget(w3.get())); - - ShowNow(); - EXPECT_FALSE(HasPendingShow()); - EXPECT_TRUE(IsShowing()); - EXPECT_FALSE(HasPendingHide()); - - // w3 should be picked up when resize is started. - gfx::Rect bounds(resize_widget()->GetWindowBoundsInScreen()); - generator.MoveMouseTo(bounds.x() + 1, bounds.y() + 1); - generator.PressLeftButton(); - generator.MoveMouseTo(bounds.x() + 11, bounds.y() + 10); - - EXPECT_TRUE(HasTarget(w3.get())); - - // Release the mouse. The resizer should still be visible and a subsequent - // press should not trigger a DCHECK. - generator.ReleaseLeftButton(); - EXPECT_TRUE(IsShowing()); - generator.PressLeftButton(); -} -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/phantom_window_controller.cc b/chromium/ash/wm/workspace/phantom_window_controller.cc deleted file mode 100644 index 83a0e3fdcb0..00000000000 --- a/chromium/ash/wm/workspace/phantom_window_controller.cc +++ /dev/null @@ -1,214 +0,0 @@ -// 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. - -#include "ash/wm/workspace/phantom_window_controller.h" - -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/coordinate_conversion.h" -#include "third_party/skia/include/core/SkCanvas.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/compositor/layer.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/gfx/animation/slide_animation.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/skia_util.h" -#include "ui/views/background.h" -#include "ui/views/painter.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" - -namespace ash { -namespace internal { - -// EdgePainter ---------------------------------------------------------------- - -namespace { - -// Paints the background of the phantom window for window snapping. -class EdgePainter : public views::Painter { - public: - EdgePainter(); - virtual ~EdgePainter(); - - // views::Painter: - virtual gfx::Size GetMinimumSize() const OVERRIDE; - virtual void Paint(gfx::Canvas* canvas, const gfx::Size& size) OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(EdgePainter); -}; - -} // namespace - - -EdgePainter::EdgePainter() { -} - -EdgePainter::~EdgePainter() { -} - -gfx::Size EdgePainter::GetMinimumSize() const { - return gfx::Size(); -} - -void EdgePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) { - const int kInsetSize = 4; - int x = kInsetSize; - int y = kInsetSize; - int w = size.width() - kInsetSize * 2; - int h = size.height() - kInsetSize * 2; - bool inset = (w > 0 && h > 0); - if (!inset) { - x = 0; - y = 0; - w = size.width(); - h = size.height(); - } - SkPaint paint; - paint.setColor(SkColorSetARGB(100, 0, 0, 0)); - paint.setStyle(SkPaint::kFill_Style); - paint.setAntiAlias(true); - const int kRoundRectSize = 4; - canvas->sk_canvas()->drawRoundRect( - gfx::RectToSkRect(gfx::Rect(x, y, w, h)), - SkIntToScalar(kRoundRectSize), SkIntToScalar(kRoundRectSize), paint); - if (!inset) - return; - - paint.setColor(SkColorSetARGB(200, 255, 255, 255)); - paint.setStyle(SkPaint::kStroke_Style); - paint.setStrokeWidth(SkIntToScalar(2)); - canvas->sk_canvas()->drawRoundRect( - gfx::RectToSkRect(gfx::Rect(x, y, w, h)), SkIntToScalar(kRoundRectSize), - SkIntToScalar(kRoundRectSize), paint); -} - - -// PhantomWindowController ---------------------------------------------------- - -PhantomWindowController::PhantomWindowController(aura::Window* window) - : window_(window), - phantom_below_window_(NULL), - phantom_widget_(NULL), - phantom_widget_start_(NULL) { -} - -PhantomWindowController::~PhantomWindowController() { - Hide(); -} - -void PhantomWindowController::Show(const gfx::Rect& bounds_in_screen) { - if (bounds_in_screen == bounds_in_screen_) - return; - bounds_in_screen_ = bounds_in_screen; - aura::Window* target_root = wm::GetRootWindowMatching(bounds_in_screen); - // Show the phantom at the current bounds of the window. We'll animate to the - // target bounds. If phantom exists, update the start bounds. - if (!phantom_widget_) - start_bounds_ = window_->GetBoundsInScreen(); - else - start_bounds_ = phantom_widget_->GetWindowBoundsInScreen(); - if (phantom_widget_ && - phantom_widget_->GetNativeWindow()->GetRootWindow() != target_root) { - phantom_widget_->Close(); - phantom_widget_ = NULL; - } - if (!phantom_widget_) - phantom_widget_ = CreatePhantomWidget(target_root, start_bounds_); - - // Create a secondary widget in a second screen if start_bounds_ lie at least - // partially in that other screen. This allows animations to start or restart - // in one root window and progress into another root. - aura::Window* start_root = wm::GetRootWindowMatching(start_bounds_); - if (start_root == target_root) { - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - for (size_t i = 0; i < root_windows.size(); ++i) { - if (root_windows[i] != target_root && - root_windows[i]->GetBoundsInScreen().Intersects(start_bounds_)) { - start_root = root_windows[i]; - break; - } - } - } - if (phantom_widget_start_ && - (phantom_widget_start_->GetNativeWindow()->GetRootWindow() != start_root - || start_root == target_root)) { - phantom_widget_start_->Close(); - phantom_widget_start_ = NULL; - } - if (!phantom_widget_start_ && start_root != target_root) - phantom_widget_start_ = CreatePhantomWidget(start_root, start_bounds_); - - animation_.reset(new gfx::SlideAnimation(this)); - animation_->SetTweenType(gfx::Tween::EASE_IN); - const int kAnimationDurationMS = 200; - animation_->SetSlideDuration(kAnimationDurationMS); - animation_->Show(); -} - -void PhantomWindowController::Hide() { - if (phantom_widget_) - phantom_widget_->Close(); - phantom_widget_ = NULL; - if (phantom_widget_start_) - phantom_widget_start_->Close(); - phantom_widget_start_ = NULL; -} - -bool PhantomWindowController::IsShowing() const { - return phantom_widget_ != NULL; -} - -void PhantomWindowController::AnimationProgressed( - const gfx::Animation* animation) { - const gfx::Rect current_bounds = - animation->CurrentValueBetween(start_bounds_, bounds_in_screen_); - if (phantom_widget_start_) - phantom_widget_start_->SetBounds(current_bounds); - phantom_widget_->SetBounds(current_bounds); -} - -views::Widget* PhantomWindowController::CreatePhantomWidget( - aura::Window* root_window, - const gfx::Rect& bounds_in_screen) { - views::Widget* phantom_widget = new views::Widget; - views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - // PhantomWindowController is used by FrameMaximizeButton to highlight the - // launcher button. Put the phantom in the same window as the launcher so that - // the phantom is visible. - params.parent = Shell::GetContainer(root_window, - kShellWindowId_ShelfContainer); - params.can_activate = false; - params.keep_on_top = true; - phantom_widget->set_focus_on_creation(false); - phantom_widget->Init(params); - phantom_widget->SetVisibilityChangedAnimationsEnabled(false); - phantom_widget->GetNativeWindow()->SetName("PhantomWindow"); - phantom_widget->GetNativeWindow()->set_id(kShellWindowId_PhantomWindow); - views::View* content_view = new views::View; - content_view->set_background( - views::Background::CreateBackgroundPainter(true, new EdgePainter)); - phantom_widget->SetContentsView(content_view); - phantom_widget->SetBounds(bounds_in_screen); - if (phantom_below_window_) - phantom_widget->StackBelow(phantom_below_window_); - else - phantom_widget->StackAbove(window_); - - // Show the widget after all the setups. - phantom_widget->Show(); - - // Fade the window in. - ui::Layer* widget_layer = phantom_widget->GetNativeWindow()->layer(); - widget_layer->SetOpacity(0); - ui::ScopedLayerAnimationSettings scoped_setter(widget_layer->GetAnimator()); - widget_layer->SetOpacity(1); - return phantom_widget; -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/phantom_window_controller.h b/chromium/ash/wm/workspace/phantom_window_controller.h deleted file mode 100644 index 77d4a286035..00000000000 --- a/chromium/ash/wm/workspace/phantom_window_controller.h +++ /dev/null @@ -1,103 +0,0 @@ -// 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_PHANTOM_WINDOW_CONTROLLER_H_ -#define ASH_WM_WORKSPACE_PHANTOM_WINDOW_CONTROLLER_H_ - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "ui/gfx/animation/animation_delegate.h" -#include "ui/gfx/rect.h" - -namespace aura { -class Window; -} - -namespace gfx { -class SlideAnimation; -} - -namespace views { -class Widget; -} - -namespace ash { -namespace internal { - -// PhantomWindowController is responsible for showing a phantom representation -// of a window. It's used used during dragging a window to show a snap location. -class ASH_EXPORT PhantomWindowController : public gfx::AnimationDelegate { - public: - explicit PhantomWindowController(aura::Window* window); - virtual ~PhantomWindowController(); - - // Bounds last passed to Show(). - const gfx::Rect& bounds_in_screen() const { return bounds_in_screen_; } - - // Animates the phantom window towards |bounds_in_screen|. - // Creates two (if start bounds intersect any root window other than the - // root window that matches the target bounds) or one (otherwise) phantom - // widgets to display animated rectangle in each root. - // This does not immediately show the window. - void Show(const gfx::Rect& bounds_in_screen); - - // Hides the phantom. - void Hide(); - - // Returns true if the phantom is showing. - bool IsShowing() const; - - // If set, the phantom window is stacked below this window, otherwise it - // is stacked above the window passed to the constructor. - void set_phantom_below_window(aura::Window* phantom_below_window) { - phantom_below_window_ = phantom_below_window; - } - - // gfx::AnimationDelegate overrides: - virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE; - - private: - FRIEND_TEST_ALL_PREFIXES(WorkspaceWindowResizerTest, PhantomWindowShow); - - // Creates, shows and returns a phantom widget at |bounds| - // with kShellWindowId_ShelfContainer in |root_window| as a parent. - views::Widget* CreatePhantomWidget(aura::Window* root_window, - const gfx::Rect& bounds_in_screen); - - // Window the phantom is placed beneath. - aura::Window* window_; - - // If set, the phantom window should get stacked below this window. - aura::Window* phantom_below_window_; - - // Initially the bounds of |window_| (in screen coordinates). - // Each time Show() is invoked |start_bounds_| is then reset to the bounds of - // |phantom_widget_| and |bounds_| is set to the value passed into Show(). - // The animation animates between these two values. - gfx::Rect start_bounds_; - - // Target bounds of the animation in screen coordinates. - gfx::Rect bounds_in_screen_; - - // The primary phantom representation of the window. It is parented by the - // root window matching the target bounds. - views::Widget* phantom_widget_; - - // If the animation starts on another display, this is the secondary phantom - // representation of the window used on the initial display, otherwise this is - // NULL. This allows animation to progress from one display into the other. - views::Widget* phantom_widget_start_; - - // Used to transition the bounds. - scoped_ptr<gfx::SlideAnimation> animation_; - - DISALLOW_COPY_AND_ASSIGN(PhantomWindowController); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_PHANTOM_WINDOW_CONTROLLER_H_ diff --git a/chromium/ash/wm/workspace/snap_sizer.cc b/chromium/ash/wm/workspace/snap_sizer.cc deleted file mode 100644 index ba35f6ac3cc..00000000000 --- a/chromium/ash/wm/workspace/snap_sizer.cc +++ /dev/null @@ -1,292 +0,0 @@ -// 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. - -#include "ash/wm/workspace/snap_sizer.h" - -#include <cmath> - -#include "ash/ash_switches.h" -#include "ash/screen_ash.h" -#include "ash/wm/window_resizer.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/command_line.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/gfx/screen.h" - -namespace ash { -namespace internal { - -namespace { - -// A list of ideal window widths in DIP which will be used to populate the -// |usable_width_| list. -const int kIdealWidth[] = { 1280, 1024, 768, 640 }; - -// Windows are initially snapped to the size in |usable_width_| at index 0. -// The index into |usable_width_| is changed if any of the following happen: -// . The user stops moving the mouse for |kDelayBeforeIncreaseMS| and then -// moves the mouse again. -// . The mouse moves |kPixelsBeforeAdjust| horizontal pixels. -// . The mouse is against the edge of the screen and the mouse is moved -// |kMovesBeforeAdjust| times. -const int kDelayBeforeIncreaseMS = 500; -const int kMovesBeforeAdjust = 25; -const int kPixelsBeforeAdjust = 100; - -// The maximum fraction of the screen width that a snapped window is allowed -// to take up. -const int kMaximumScreenPercent = 90; - -// The width that a window should be snapped to if resizing is disabled in the -// SnapSizer for devices with small screen resolutions. -const int kDefaultWidthSmallScreen = 1024; - -// Returns the minimum width that |window| can be snapped to. The returned width -// may not be in the width list generated by BuildIdealWidthList(). -int GetMinWidth(aura::Window* window) { - return window->delegate() ? window->delegate()->GetMinimumSize().width() : 0; -} - -// Returns the maximum width that |window| can be snapped to. The returned width -// may not be in the width list generated by BuildIdealWidthList(). -// The aura::WindowDelegate's max size is ignored because -// ash::wm::CanSnapWindow() returns false when a max size is specified. -int GetMaxWidth(aura::Window* window) { - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); - return std::max(work_area.width() * kMaximumScreenPercent / 100, - GetMinWidth(window)); -} - -// Returns the width that |window| should be snapped to if resizing is disabled -// in the SnapSizer. -int GetDefaultWidth(aura::Window* window) { - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); - - int width = 0; - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshMultipleSnapWindowWidths)) { - width = work_area.width() / 2; - } else { - width = std::max(kDefaultWidthSmallScreen, work_area.width() / 2); - } - - width = std::min(width, GetMaxWidth(window)); - return std::max(width, GetMinWidth(window)); -} - -// Creates the list of possible width for the current screen configuration: -// Returns a list with items from |kIdealWidth| which fit on the screen and -// supplement it with the 'half of screen' size. Furthermore, add an entry for -// 90% of the screen size if it is smaller than the biggest value in the -// |kIdealWidth| list (to get a step between the values). -std::vector<int> BuildIdealWidthList(aura::Window* window) { - if (!CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshMultipleSnapWindowWidths)) { - return std::vector<int>(1u, GetDefaultWidth(window)); - } - - int minimum_width = GetMinWidth(window); - int maximum_width = GetMaxWidth(window); - - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); - int half_width = work_area.width() / 2; - if (half_width < minimum_width || half_width > maximum_width) - half_width = 0; - - std::vector<int> ideal_width_list; - for (size_t i = 0; i < arraysize(kIdealWidth); i++) { - if (kIdealWidth[i] >= minimum_width && kIdealWidth[i] <= maximum_width) { - if (i && !ideal_width_list.size() && maximum_width != kIdealWidth[i]) - ideal_width_list.push_back(maximum_width); - if (half_width > kIdealWidth[i]) - ideal_width_list.push_back(half_width); - if (half_width >= kIdealWidth[i]) - half_width = 0; - ideal_width_list.push_back(kIdealWidth[i]); - } - } - if (half_width) - ideal_width_list.push_back(half_width); - if (ideal_width_list.empty()) { - if (minimum_width > 0) - ideal_width_list.push_back(minimum_width); - else - ideal_width_list.push_back(maximum_width); - } - - return ideal_width_list; -} - -// Changes |window|'s bounds to |snap_bounds| while preserving the restore -// bounds. -void SnapWindowToBounds(wm::WindowState* window_state, - SnapSizer::Edge edge, - const gfx::Rect& snap_bounds) { - if (edge == SnapSizer::LEFT_EDGE) { - window_state->SnapLeft(snap_bounds); - } else { - window_state->SnapRight(snap_bounds); - } -} - -} // namespace - -SnapSizer::SnapSizer(wm::WindowState* window_state, - const gfx::Point& start, - Edge edge, - InputType input_type) - : window_state_(window_state), - edge_(edge), - time_last_update_(base::TimeTicks::Now()), - size_index_(0), - end_of_sequence_(false), - resize_disabled_(false), - num_moves_since_adjust_(0), - last_adjust_x_(start.x()), - last_update_x_(start.x()), - start_x_(start.x()), - input_type_(input_type), - usable_width_(BuildIdealWidthList(window_state->window())) { - DCHECK(!usable_width_.empty()); - target_bounds_ = GetTargetBounds(); -} - -SnapSizer::~SnapSizer() { -} - -void SnapSizer::SnapWindow(wm::WindowState* window_state, - SnapSizer::Edge edge) { - if (!window_state->CanSnap()) - return; - internal::SnapSizer sizer(window_state, gfx::Point(), edge, - internal::SnapSizer::OTHER_INPUT); - SnapWindowToBounds(window_state, edge, - sizer.GetSnapBounds(window_state->window()->bounds())); -} - -void SnapSizer::SnapWindowToTargetBounds() { - SnapWindowToBounds(window_state_, edge_, target_bounds()); -} - -void SnapSizer::Update(const gfx::Point& location) { - // See description above for details on this behavior. - num_moves_since_adjust_++; - if ((base::TimeTicks::Now() - time_last_update_).InMilliseconds() > - kDelayBeforeIncreaseMS) { - ChangeBounds(location.x(), - CalculateIncrement(location.x(), last_update_x_)); - } else { - bool along_edge = AlongEdge(location.x()); - int pixels_before_adjust = kPixelsBeforeAdjust; - if (input_type_ == TOUCH_MAXIMIZE_BUTTON_INPUT) { - const gfx::Rect& workspace_bounds = - window_state_->window()->parent()->bounds(); - if (start_x_ > location.x()) { - pixels_before_adjust = - std::min(pixels_before_adjust, start_x_ / 10); - } else { - pixels_before_adjust = - std::min(pixels_before_adjust, - (workspace_bounds.width() - start_x_) / 10); - } - } - if (std::abs(location.x() - last_adjust_x_) >= pixels_before_adjust || - (along_edge && num_moves_since_adjust_ >= kMovesBeforeAdjust)) { - ChangeBounds(location.x(), - CalculateIncrement(location.x(), last_adjust_x_)); - } - } - last_update_x_ = location.x(); - time_last_update_ = base::TimeTicks::Now(); -} - -gfx::Rect SnapSizer::GetSnapBounds(const gfx::Rect& bounds) { - int current = 0; - if (!resize_disabled_) { - for (current = usable_width_.size() - 1; current >= 0; current--) { - gfx::Rect target = GetTargetBoundsForSize(current); - if (target == bounds) { - ++current; - break; - } - } - } - if (current < 0) - current = 0; - return GetTargetBoundsForSize(current % usable_width_.size()); -} - -void SnapSizer::SelectDefaultSizeAndDisableResize() { - resize_disabled_ = true; - size_index_ = 0; - end_of_sequence_ = false; - target_bounds_ = GetTargetBounds(); -} - -gfx::Rect SnapSizer::GetTargetBoundsForSize(size_t size_index) const { - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_state_->window())); - int y = work_area.y(); - int max_y = work_area.bottom(); - int width = 0; - if (resize_disabled_) { - width = GetDefaultWidth(window_state_->window()); - } else { - DCHECK(size_index < usable_width_.size()); - width = usable_width_[size_index]; - } - - if (edge_ == LEFT_EDGE) { - int x = work_area.x(); - int mid_x = x + width; - return gfx::Rect(x, y, mid_x - x, max_y - y); - } - int max_x = work_area.right(); - int x = max_x - width; - return gfx::Rect(x , y, max_x - x, max_y - y); -} - -int SnapSizer::CalculateIncrement(int x, int reference_x) const { - if (AlongEdge(x)) - return 1; - if (x == reference_x) - return 0; - if (edge_ == LEFT_EDGE) { - if (x < reference_x) - return 1; - return -1; - } - // edge_ == RIGHT_EDGE. - if (x > reference_x) - return 1; - return -1; -} - -void SnapSizer::ChangeBounds(int x, int delta) { - end_of_sequence_ = - delta > 0 && size_index_ == static_cast<int>(usable_width_.size()) - 1; - int index = std::min(static_cast<int>(usable_width_.size()) - 1, - std::max(size_index_ + delta, 0)); - if (index != size_index_) { - size_index_ = index; - target_bounds_ = GetTargetBounds(); - } - num_moves_since_adjust_ = 0; - last_adjust_x_ = x; -} - -gfx::Rect SnapSizer::GetTargetBounds() const { - return GetTargetBoundsForSize(size_index_); -} - -bool SnapSizer::AlongEdge(int x) const { - gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_state_->window())); - return (x <= area.x()) || (x >= area.right() - 1); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/snap_sizer.h b/chromium/ash/wm/workspace/snap_sizer.h deleted file mode 100644 index b32c3c8c310..00000000000 --- a/chromium/ash/wm/workspace/snap_sizer.h +++ /dev/null @@ -1,140 +0,0 @@ -// 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_SNAP_SIZER_H_ -#define ASH_WM_WORKSPACE_SNAP_SIZER_H_ - -#include <vector> - -#include "ash/ash_export.h" -#include "base/basictypes.h" -#include "base/time/time.h" -#include "ui/gfx/rect.h" - -namespace ash { -namespace wm { -class WindowState; -} - -namespace internal { - -// SnapSizer is responsible for determining the resulting bounds of a window -// that is being snapped to the left or right side of the screen. -// The bounds used in this class are in the container's coordinates. -class ASH_EXPORT SnapSizer { - public: - enum Edge { - LEFT_EDGE, - RIGHT_EDGE - }; - - enum InputType { - TOUCH_MAXIMIZE_BUTTON_INPUT, - OTHER_INPUT - }; - - // Set |input_type| to |TOUCH_MAXIMIZE_BUTTON_INPUT| when called by a touch - // operation by the maximize button. This will allow the user to snap resize - // the window beginning close to the border. - SnapSizer(wm::WindowState* window_state, - const gfx::Point& start, - Edge edge, - InputType input_type); - virtual ~SnapSizer(); - - // Snaps a window left or right. - static void SnapWindow(wm::WindowState* window_state, Edge edge); - - // Snaps |window_| to the target bounds. - void SnapWindowToTargetBounds(); - - // Updates the target bounds based on a mouse move. - void Update(const gfx::Point& location); - - // Bounds to position the window at. - const gfx::Rect& target_bounds() const { return target_bounds_; } - - // Returns the appropriate snap bounds (e.g. if a window is already snapped, - // then it returns the next snap-bounds). - gfx::Rect GetSnapBounds(const gfx::Rect& bounds); - - // Set the snap sizer to the button press default size and prevent resizing. - void SelectDefaultSizeAndDisableResize(); - - // Returns the target bounds based on the edge and the provided |size_index|. - // For unit test purposes this function is not private. - gfx::Rect GetTargetBoundsForSize(size_t size_index) const; - - // Returns true when snapping sequence is at its last (docking) step. - bool end_of_sequence() const { return end_of_sequence_; } - - private: - // Calculates the amount to increment by. This returns one of -1, 0 or 1 and - // is intended to by applied to |size_index_|. |x| is the current - // x-coordinate, and |reference_x| is used to determine whether to increase - // or decrease the position. It's one of |last_adjust_x_| or |last_update_x_|. - int CalculateIncrement(int x, int reference_x) const; - - // Changes the bounds. |x| is the current x-coordinate and |delta| the amount - // to increase by. |delta| comes from CalculateIncrement() and is applied - // to |size_index_|. - void ChangeBounds(int x, int delta); - - // Returns the target bounds based on the edge and |size_index_|. - gfx::Rect GetTargetBounds() const; - - // Returns true if the specified point is along the edge of the screen. - bool AlongEdge(int x) const; - - // WindowState of the window being snapped. - wm::WindowState* window_state_; - - const Edge edge_; - - // Current target bounds for the snap. - gfx::Rect target_bounds_; - - // Time Update() was last invoked. - base::TimeTicks time_last_update_; - - // Index into |kSizes| that dictates the width of the screen the target - // bounds should get. - int size_index_; - - // Set to true when an attempt is made to increment |size_index_| past - // the size of |usable_width_|. - bool end_of_sequence_; - - // If set, |size_index_| will get ignored and the single button default - // setting will be used instead. - bool resize_disabled_; - - // Number of times Update() has been invoked since last ChangeBounds(). - int num_moves_since_adjust_; - - // X-coordinate the last time ChangeBounds() was invoked. - int last_adjust_x_; - - // X-coordinate last supplied to Update(). - int last_update_x_; - - // Initial x-coordinate. - const int start_x_; - - // |TOUCH_MAXIMIZE_BUTTON_INPUT| if the snap sizer was created through a - // touch & drag operation of the maximizer button. It changes the behavior of - // the drag / resize behavior when the dragging starts close to the border. - const InputType input_type_; - - // A list of usable window widths for size. This gets created when the - // sizer gets created. - const std::vector<int> usable_width_; - - DISALLOW_COPY_AND_ASSIGN(SnapSizer); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_SNAP_SIZER_H_ diff --git a/chromium/ash/wm/workspace/snap_sizer_unittest.cc b/chromium/ash/wm/workspace/snap_sizer_unittest.cc deleted file mode 100644 index 81a09f93940..00000000000 --- a/chromium/ash/wm/workspace/snap_sizer_unittest.cc +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright 2013 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. - -#include "ash/wm/workspace/snap_sizer.h" - -#include "ash/ash_switches.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "base/command_line.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/window.h" -#include "ui/gfx/screen.h" - -namespace ash { - -typedef test::AshTestBase SnapSizerTest; - -using internal::SnapSizer; - -// Test that a window gets properly snapped to the display's edges in a -// multi monitor environment. -TEST_F(SnapSizerTest, MultipleDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("0+0-500x400, 0+500-600x400"); - const gfx::Rect kPrimaryDisplayWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - const gfx::Rect kSecondaryDisplayWorkAreaBounds = - ScreenAsh::GetSecondaryDisplay().work_area(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - gfx::Rect expected = gfx::Rect( - kPrimaryDisplayWorkAreaBounds.x(), - kPrimaryDisplayWorkAreaBounds.y(), - window->bounds().width(), // No expectation for the width. - kPrimaryDisplayWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - // The width should not change when a window switches from being snapped to - // the left edge to being snapped to the right edge. - expected.set_x(kPrimaryDisplayWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Move the window to the secondary display. - window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100), - ScreenAsh::GetSecondaryDisplay()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected = gfx::Rect( - kSecondaryDisplayWorkAreaBounds.right() - window->bounds().width(), - kSecondaryDisplayWorkAreaBounds.y(), - window->bounds().width(), // No expectation for the width. - kSecondaryDisplayWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - // The width should not change when a window switches from being snapped to - // the right edge to being snapped to the left edge. - expected.set_x(kSecondaryDisplayWorkAreaBounds.x()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Test how the minimum and maximum size specified by the aura::WindowDelegate -// affect snapping. -TEST_F(SnapSizerTest, MinimumSize) { - if (!SupportsHostWindowResize()) - return; - - UpdateDisplay("0+0-600x800"); - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - - aura::test::TestWindowDelegate delegate; - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate( - &delegate, -1, gfx::Rect(0, 100, kWorkAreaBounds.width() - 1, 100))); - - // It should be possible to snap a window with a minimum size. - delegate.set_minimum_size(gfx::Size(kWorkAreaBounds.width() - 1, 0)); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - EXPECT_TRUE(window_state->CanSnap()); - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x() + 1, - kWorkAreaBounds.y(), - kWorkAreaBounds.width() - 1, - kWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // It should not be possible to snap a window with a maximum size. - delegate.set_minimum_size(gfx::Size()); - delegate.set_maximum_size(gfx::Size(kWorkAreaBounds.width() - 1, INT_MAX)); - EXPECT_FALSE(window_state->CanSnap()); -} - -// Test that repeatedly calling SnapSizer::SnapWindow() when the -// --ash-multiple-snap-window-widths flag is set steps through the ideal widths -// in descending order as well as 90% and 50% of the work area's width. -TEST_F(SnapSizerTest, StepThroughSizes) { - if (!SupportsHostWindowResize()) - return; - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshMultipleSnapWindowWidths); - - UpdateDisplay("1024x800"); - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - // Make sure that the work area is the size we expect it to be. - EXPECT_GT(kWorkAreaBounds.width() * 0.9, 768); - - // The first width should be 1024 * 0.9 because the larger ideal widths - // (1280, 1024) > 1024 * 0.9. - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(), - kWorkAreaBounds.y(), - kWorkAreaBounds.width() * 0.9, - kWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - expected.set_width(768); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - expected.set_width(640); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.5); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Wrap around. - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.9); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Repeat the test snapping right. - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.9); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(768); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(640); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.5); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Wrap around. - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_width(kWorkAreaBounds.width() * 0.9); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Test that a SnapSizer's target bounds always start from the widest possible -// bounds and that calling Update() steps through the ideal widths in descending -// order as well as 90% and 50% of the work area's width. -TEST_F(SnapSizerTest, Update) { - if (!SupportsHostWindowResize()) - return; - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshMultipleSnapWindowWidths); - UpdateDisplay("1024x800"); - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - - // Make sure that the work area is the size we expect it to be. - EXPECT_GT(kWorkAreaBounds.width() * 0.9, 768); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(), - kWorkAreaBounds.y(), - 768, - kWorkAreaBounds.height()); - - // The SnapSizer's target bounds should always start from the widest bounds - // (instead of the bounds with the next ideal width). - SnapSizer sizer(window_state, gfx::Point(800, 0), SnapSizer::LEFT_EDGE, - SnapSizer::OTHER_INPUT); - sizer.SnapWindowToTargetBounds(); - expected.set_width(kWorkAreaBounds.width() * .9); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - sizer.Update(gfx::Point(600, 0)); - sizer.SnapWindowToTargetBounds(); - expected.set_width(768); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - sizer.Update(gfx::Point(400, 0)); - sizer.SnapWindowToTargetBounds(); - expected.set_width(640); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - sizer.Update(gfx::Point(200, 0)); - sizer.SnapWindowToTargetBounds(); - expected.set_width(kWorkAreaBounds.width() * 0.5); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Do not wrap around. - sizer.Update(gfx::Point(0, 0)); - sizer.SnapWindowToTargetBounds(); - expected.set_width(kWorkAreaBounds.width() * 0.5); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Tests the SnapSizer's target bounds when resizing is disabled and the -// --ash-multiple-snap-window-widths flag is set. -TEST_F(SnapSizerTest, Default) { - if (!SupportsHostWindowResize()) - return; - CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAshMultipleSnapWindowWidths); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - SnapSizer sizer(wm::GetWindowState(window.get()), gfx::Point(), - SnapSizer::LEFT_EDGE, SnapSizer::OTHER_INPUT); - - // For small workspace widths, we should snap to 90% of the workspace width - // because it is the largest width the window can snap to. - UpdateDisplay("0+0-800x600"); - sizer.SelectDefaultSizeAndDisableResize(); - - gfx::Rect work_area = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - gfx::Rect expected(work_area); - expected.set_width(work_area.width() * 0.9); - EXPECT_EQ(expected.ToString(), - ScreenAsh::ConvertRectToScreen(window->parent(), - sizer.target_bounds()).ToString()); - - // If the largest width the window can snap to is between 1024 and 1280, we - // should snap to 1024. - UpdateDisplay("0+0-1280x800"); - sizer.SelectDefaultSizeAndDisableResize(); - sizer.SnapWindowToTargetBounds(); - EXPECT_EQ(1024, window->bounds().width()); - - // We should snap to a width of 50% of the work area if it is the largest - // width the window can snap to. - UpdateDisplay("0+0-2560x1080"); - work_area = ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - sizer.SelectDefaultSizeAndDisableResize(); - sizer.SnapWindowToTargetBounds(); - EXPECT_EQ(work_area.width() / 2, window->bounds().width()); -} - -// Test that the window only snaps to 50% of the work area width when the -// --ash-multiple-snap-window-widths flag is not set. -TEST_F(SnapSizerTest, SingleSnapWindowWidth) { - if (!SupportsHostWindowResize()) - return; - - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshMultipleSnapWindowWidths)) { - return; - } - - UpdateDisplay("0+0-800x600"); - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(), - kWorkAreaBounds.y(), - kWorkAreaBounds.width() / 2, - kWorkAreaBounds.height()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Because a window can only be snapped to one size when using the alternate - // caption button style, a second call to SnapSizer::SnapWindow() should have - // no effect. - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // It should still be possible to switch a window from being snapped to the - // left edge to being snapped to the right edge. - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - expected.set_x(kWorkAreaBounds.right() - expected.width()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // If resizing is disabled, the window should be snapped to 50% too. - SnapSizer sizer1(window_state, gfx::Point(), SnapSizer::RIGHT_EDGE, - SnapSizer::OTHER_INPUT); - sizer1.SelectDefaultSizeAndDisableResize(); - sizer1.SnapWindowToTargetBounds(); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); - - // Snapping to a SnapSizer's initial bounds snaps to 50% too. - SnapSizer sizer2(window_state, gfx::Point(), SnapSizer::LEFT_EDGE, - SnapSizer::OTHER_INPUT); - sizer2.SnapWindowToTargetBounds(); - expected.set_x(kWorkAreaBounds.x()); - EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Test that snapping left/right preserves the restore bounds. -TEST_F(SnapSizerTest, RestoreBounds) { - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - EXPECT_TRUE(window_state->IsNormalShowState()); - - // 1) Start with restored window with restore bounds set. - gfx::Rect restore_bounds = window->GetBoundsInScreen(); - restore_bounds.set_width(restore_bounds.width() + 1); - window_state->SetRestoreBoundsInScreen(restore_bounds); - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString()); - EXPECT_EQ(restore_bounds.ToString(), - window_state->GetRestoreBoundsInScreen().ToString()); - window_state->Restore(); - EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString()); - - // 2) Start with restored bounds set as a result of maximizing the window. - window_state->Maximize(); - gfx::Rect maximized_bounds = window->GetBoundsInScreen(); - EXPECT_NE(maximized_bounds.ToString(), restore_bounds.ToString()); - EXPECT_EQ(restore_bounds.ToString(), - window_state->GetRestoreBoundsInScreen().ToString()); - - SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE); - EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString()); - EXPECT_NE(maximized_bounds.ToString(), - window->GetBoundsInScreen().ToString()); - EXPECT_EQ(restore_bounds.ToString(), - window_state->GetRestoreBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString()); -} - -// Test that maximizing an auto managed window, then snapping it puts the window -// at the snapped bounds and not at the auto-managed (centered) bounds. -TEST_F(SnapSizerTest, AutoManaged) { - scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->set_window_position_managed(true); - window->Hide(); - window->SetBounds(gfx::Rect(100, 100, 100, 100)); - window->Show(); - - window_state->Maximize(); - SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE); - - const gfx::Rect kWorkAreaBounds = - ash::Shell::GetScreen()->GetPrimaryDisplay().work_area(); - gfx::Rect expected_snapped_bounds( - kWorkAreaBounds.right() - window->bounds().width(), - kWorkAreaBounds.y(), - window->bounds().width(), // No expectation for the width. - kWorkAreaBounds.height()); - EXPECT_EQ(expected_snapped_bounds.ToString(), - window->GetBoundsInScreen().ToString()); - - // The window should still be auto managed despite being right maximized. - EXPECT_TRUE(window_state->window_position_managed()); -} - -} // namespace ash diff --git a/chromium/ash/wm/workspace/snap_types.h b/chromium/ash/wm/workspace/snap_types.h deleted file mode 100644 index 482a7dd583b..00000000000 --- a/chromium/ash/wm/workspace/snap_types.h +++ /dev/null @@ -1,23 +0,0 @@ -// 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_SNAP_TYPES_H_ -#define ASH_WM_WORKSPACE_SNAP_TYPES_H_ - -namespace ash { - -// These are the window snap types which can be used for window resizing. -// Their main use case is the class FrameMaximizeButton. -enum SnapType { - SNAP_LEFT, - SNAP_RIGHT, - SNAP_MAXIMIZE, - SNAP_MINIMIZE, - SNAP_RESTORE, - SNAP_NONE -}; - -} // namespace ash - -#endif // ASH_WM_WORKSPACE_SNAP_TYPES_H_ diff --git a/chromium/ash/wm/workspace/workspace_event_handler.cc b/chromium/ash/wm/workspace/workspace_event_handler.cc deleted file mode 100644 index bcd7e9e1d64..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler.cc +++ /dev/null @@ -1,180 +0,0 @@ -// 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. - -#include "ash/wm/workspace/workspace_event_handler.h" - -#include "ash/metrics/user_metrics_recorder.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/touch/touch_uma.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/workspace_window_resizer.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/gfx/screen.h" - -namespace ash { -namespace { - -void SingleAxisMaximize(wm::WindowState* window_state, - const gfx::Rect& maximize_rect_in_screen) { - window_state->SaveCurrentBoundsForRestore(); - window_state->SetBoundsInScreen(maximize_rect_in_screen); -} - -void SingleAxisUnmaximize(wm::WindowState* window_state, - const gfx::Rect& restore_bounds_in_screen) { - window_state->SetBoundsInScreen(restore_bounds_in_screen); - window_state->ClearRestoreBounds(); -} - -void ToggleMaximizedState(wm::WindowState* window_state) { - if (window_state->HasRestoreBounds()) { - if (window_state->GetShowState() == ui::SHOW_STATE_NORMAL) { - window_state->window()->SetBounds( - window_state->GetRestoreBoundsInParent()); - window_state->ClearRestoreBounds(); - } else { - window_state->Restore(); - } - } else if (window_state->CanMaximize()) { - window_state->Maximize(); - } -} - -} // namespace - -namespace internal { - -WorkspaceEventHandler::WorkspaceEventHandler(aura::Window* owner) - : ToplevelWindowEventHandler(owner) { -} - -WorkspaceEventHandler::~WorkspaceEventHandler() { -} - -void WorkspaceEventHandler::OnMouseEvent(ui::MouseEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - switch (event->type()) { - case ui::ET_MOUSE_MOVED: { - int component = - target->delegate()->GetNonClientComponent(event->location()); - multi_window_resize_controller_.Show(target, component, - event->location()); - break; - } - case ui::ET_MOUSE_ENTERED: - break; - case ui::ET_MOUSE_CAPTURE_CHANGED: - case ui::ET_MOUSE_EXITED: - break; - case ui::ET_MOUSE_PRESSED: { - // Maximize behavior is implemented as post-target handling so the target - // can cancel it. - if (ui::EventCanceledDefaultHandling(*event)) { - ToplevelWindowEventHandler::OnMouseEvent(event); - return; - } - wm::WindowState* target_state = wm::GetWindowState(target); - if (event->flags() & ui::EF_IS_DOUBLE_CLICK && - event->IsOnlyLeftMouseButton() && - target->delegate()->GetNonClientComponent(event->location()) == - HTCAPTION) { - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( - ash::UMA_TOGGLE_MAXIMIZE_CAPTION_CLICK); - ToggleMaximizedState(target_state); - } - multi_window_resize_controller_.Hide(); - HandleVerticalResizeDoubleClick(target_state, event); - break; - } - default: - break; - } - ToplevelWindowEventHandler::OnMouseEvent(event); -} - -void WorkspaceEventHandler::OnGestureEvent(ui::GestureEvent* event) { - aura::Window* target = static_cast<aura::Window*>(event->target()); - if (event->type() == ui::ET_GESTURE_TAP && - target->delegate()->GetNonClientComponent(event->location()) == - HTCAPTION) { - if (event->details().tap_count() == 2) { - ash::Shell::GetInstance()->metrics()->RecordUserMetricsAction( - ash::UMA_TOGGLE_MAXIMIZE_CAPTION_GESTURE); - // Note: TouchUMA::GESTURE_FRAMEVIEW_TAP is counted twice each time - // TouchUMA::GESTURE_MAXIMIZE_DOUBLETAP is counted once. - TouchUMA::GetInstance()->RecordGestureAction( - TouchUMA::GESTURE_MAXIMIZE_DOUBLETAP); - ToggleMaximizedState(wm::GetWindowState(target)); - event->StopPropagation(); - return; - } else { - // Note: TouchUMA::GESTURE_FRAMEVIEW_TAP is counted twice for each tap. - TouchUMA::GetInstance()->RecordGestureAction( - TouchUMA::GESTURE_FRAMEVIEW_TAP); - } - } - ToplevelWindowEventHandler::OnGestureEvent(event); -} - -void WorkspaceEventHandler::HandleVerticalResizeDoubleClick( - wm::WindowState* target_state, - ui::MouseEvent* event) { - aura::Window* target = target_state->window(); - gfx::Rect max_size(target->delegate()->GetMaximumSize()); - if (event->flags() & ui::EF_IS_DOUBLE_CLICK && !target_state->IsMaximized()) { - int component = - target->delegate()->GetNonClientComponent(event->location()); - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - target).work_area(); - if (component == HTBOTTOM || component == HTTOP) { - // Don't maximize vertically if the window has a max height defined. - if (max_size.height() != 0) - return; - if (target_state->HasRestoreBounds() && - (target->bounds().height() == work_area.height() && - target->bounds().y() == work_area.y())) { - SingleAxisUnmaximize(target_state, - target_state->GetRestoreBoundsInScreen()); - } else { - gfx::Point origin = target->bounds().origin(); - wm::ConvertPointToScreen(target->parent(), &origin); - SingleAxisMaximize(target_state, - gfx::Rect(origin.x(), - work_area.y(), - target->bounds().width(), - work_area.height())); - } - } else if (component == HTLEFT || component == HTRIGHT) { - // Don't maximize horizontally if the window has a max width defined. - if (max_size.width() != 0) - return; - if (target_state->HasRestoreBounds() && - (target->bounds().width() == work_area.width() && - target->bounds().x() == work_area.x())) { - SingleAxisUnmaximize(target_state, - target_state->GetRestoreBoundsInScreen()); - } else { - gfx::Point origin = target->bounds().origin(); - wm::ConvertPointToScreen(target->parent(), &origin); - SingleAxisMaximize(target_state, - gfx::Rect(work_area.x(), - origin.y(), - work_area.width(), - target->bounds().height())); - } - } - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_event_handler.h b/chromium/ash/wm/workspace/workspace_event_handler.h deleted file mode 100644 index e8507e167bf..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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_WORKSPACE_EVENT_HANDLER_H_ -#define ASH_WM_WORKSPACE_WORKSPACE_EVENT_HANDLER_H_ - -#include "ash/wm/toplevel_window_event_handler.h" -#include "ash/wm/workspace/multi_window_resize_controller.h" - -namespace aura { -class Window; -} - -namespace ash { -namespace wm { -class WindowState; -} - -namespace internal { - -class WorkspaceEventHandlerTestHelper; - -class WorkspaceEventHandler : public ToplevelWindowEventHandler { - public: - explicit WorkspaceEventHandler(aura::Window* owner); - virtual ~WorkspaceEventHandler(); - - // Overridden from ToplevelWindowEventHandler: - virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; - virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; - - private: - friend class WorkspaceEventHandlerTestHelper; - - // Determines if |event| corresponds to a double click on either the top or - // bottom vertical resize edge, and if so toggles the vertical height of the - // window between its restored state and the full available height of the - // workspace. - void HandleVerticalResizeDoubleClick(wm::WindowState* window_state, - ui::MouseEvent* event); - - MultiWindowResizeController multi_window_resize_controller_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceEventHandler); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WORKSPACE_EVENT_HANDLER_H_ diff --git a/chromium/ash/wm/workspace/workspace_event_handler_test_helper.cc b/chromium/ash/wm/workspace/workspace_event_handler_test_helper.cc deleted file mode 100644 index 55b707b4402..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler_test_helper.cc +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -#include "ash/wm/workspace/workspace_event_handler_test_helper.h" - -namespace ash { -namespace internal { - -WorkspaceEventHandlerTestHelper::WorkspaceEventHandlerTestHelper( - WorkspaceEventHandler* handler) - : handler_(handler) { -} - -WorkspaceEventHandlerTestHelper::~WorkspaceEventHandlerTestHelper() { -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_event_handler_test_helper.h b/chromium/ash/wm/workspace/workspace_event_handler_test_helper.h deleted file mode 100644 index 21e1adb981b..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler_test_helper.h +++ /dev/null @@ -1,31 +0,0 @@ -// 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_WORKSPACE_EVENT_HANDLER_TEST_HELPER_H_ -#define ASH_WM_WORKSPACE_WORKSPACE_EVENT_HANDLER_TEST_HELPER_H_ - -#include "ash/wm/workspace/workspace_event_handler.h" - -namespace ash { -namespace internal { - -class WorkspaceEventHandlerTestHelper { - public: - explicit WorkspaceEventHandlerTestHelper(WorkspaceEventHandler* handler); - ~WorkspaceEventHandlerTestHelper(); - - MultiWindowResizeController* resize_controller() { - return &(handler_->multi_window_resize_controller_); - } - - private: - WorkspaceEventHandler* handler_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceEventHandlerTestHelper); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WORKSPACE_EVENT_HANDLER_TEST_HELPER_H_ diff --git a/chromium/ash/wm/workspace/workspace_event_handler_unittest.cc b/chromium/ash/wm/workspace/workspace_event_handler_unittest.cc deleted file mode 100644 index feec4bdbc6b..00000000000 --- a/chromium/ash/wm/workspace/workspace_event_handler_unittest.cc +++ /dev/null @@ -1,348 +0,0 @@ -// 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. - -#include "ash/wm/workspace/workspace_event_handler.h" - -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace_controller.h" -#include "ash/wm/workspace_controller_test_helper.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/window.h" -#include "ui/base/hit_test.h" -#include "ui/gfx/screen.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -namespace ash { -namespace internal { - -class WorkspaceEventHandlerTest : public test::AshTestBase { - public: - WorkspaceEventHandlerTest() {} - virtual ~WorkspaceEventHandlerTest() {} - - protected: - aura::Window* CreateTestWindow(aura::WindowDelegate* delegate, - const gfx::Rect& bounds) { - aura::Window* window = new aura::Window(delegate); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - ParentWindowInPrimaryRootWindow(window); - window->SetBounds(bounds); - window->Show(); - return window; - } - - private: - DISALLOW_COPY_AND_ASSIGN(WorkspaceEventHandlerTest); -}; - -// Keeps track of the properties changed of a particular window. -class WindowPropertyObserver : public aura::WindowObserver { - public: - explicit WindowPropertyObserver(aura::Window* window) - : window_(window) { - window->AddObserver(this); - } - - virtual ~WindowPropertyObserver() { - window_->RemoveObserver(this); - } - - bool DidPropertyChange(const void* property) const { - return std::find(properties_changed_.begin(), - properties_changed_.end(), - property) != properties_changed_.end(); - } - - private: - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE { - properties_changed_.push_back(key); - } - - aura::Window* window_; - std::vector<const void*> properties_changed_; - - DISALLOW_COPY_AND_ASSIGN(WindowPropertyObserver); -}; - -TEST_F(WorkspaceEventHandlerTest, DoubleClickSingleAxisResizeEdge) { - // Double clicking the vertical resize edge of a window should maximize it - // vertically. - gfx::Rect restored_bounds(10, 10, 50, 50); - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, restored_bounds)); - - wm::ActivateWindow(window.get()); - - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window.get()); - - // Double-click the top resize edge. - wd.set_window_component(HTTOP); - // On X a double click actually generates a drag between each press/release. - // Explicitly trigger this path since we had bugs in dealing with it - // correctly. - generator.PressLeftButton(); - generator.ReleaseLeftButton(); - generator.set_flags(ui::EF_IS_DOUBLE_CLICK); - generator.PressLeftButton(); - generator.MoveMouseTo(generator.current_location(), 1); - generator.ReleaseLeftButton(); - gfx::Rect bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.x(), bounds_in_screen.x()); - EXPECT_EQ(restored_bounds.width(), bounds_in_screen.width()); - EXPECT_EQ(work_area.y(), bounds_in_screen.y()); - EXPECT_EQ(work_area.height(), bounds_in_screen.height()); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - // Single-axis maximization is not considered real maximization. - EXPECT_FALSE(window_state->IsMaximized()); - - // Restore. - generator.DoubleClickLeftButton(); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.ToString(), bounds_in_screen.ToString()); - // Note that it should not even be restored at this point, it should have - // also cleared the restore rectangle. - EXPECT_FALSE(window_state->HasRestoreBounds()); - - // Double-click the top resize edge again to maximize vertically, then double - // click again to restore. - generator.DoubleClickLeftButton(); - wd.set_window_component(HTCAPTION); - generator.DoubleClickLeftButton(); - EXPECT_FALSE(window_state->IsMaximized()); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.ToString(), bounds_in_screen.ToString()); - - // Double clicking the left resize edge should maximize horizontally. - wd.set_window_component(HTLEFT); - generator.DoubleClickLeftButton(); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.y(), bounds_in_screen.y()); - EXPECT_EQ(restored_bounds.height(), bounds_in_screen.height()); - EXPECT_EQ(work_area.x(), bounds_in_screen.x()); - EXPECT_EQ(work_area.width(), bounds_in_screen.width()); - // Single-axis maximization is not considered real maximization. - EXPECT_FALSE(window_state->IsMaximized()); - - // Restore. - wd.set_window_component(HTCAPTION); - generator.DoubleClickLeftButton(); - EXPECT_EQ(restored_bounds.ToString(), window->GetBoundsInScreen().ToString()); - -#if defined(OS_WIN) - // Multi display test does not run on Win8 bot. crbug.com/247427. - if (base::win::GetVersion() >= base::win::VERSION_WIN8) - return; -#endif - - // Verify the double clicking the resize edge works on 2nd display too. - UpdateDisplay("200x200,400x300"); - gfx::Rect work_area2 = ScreenAsh::GetSecondaryDisplay().work_area(); - restored_bounds.SetRect(220,20, 50, 50); - window->SetBoundsInScreen(restored_bounds, ScreenAsh::GetSecondaryDisplay()); - aura::Window* second_root = Shell::GetAllRootWindows()[1]; - EXPECT_EQ(second_root, window->GetRootWindow()); - aura::test::EventGenerator generator2(second_root, window.get()); - - // Y-axis maximization. - wd.set_window_component(HTTOP); - generator2.PressLeftButton(); - generator2.ReleaseLeftButton(); - generator2.set_flags(ui::EF_IS_DOUBLE_CLICK); - generator2.PressLeftButton(); - generator2.MoveMouseTo(generator.current_location(), 1); - generator2.ReleaseLeftButton(); - generator.DoubleClickLeftButton(); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.x(), bounds_in_screen.x()); - EXPECT_EQ(restored_bounds.width(), bounds_in_screen.width()); - EXPECT_EQ(work_area2.y(), bounds_in_screen.y()); - EXPECT_EQ(work_area2.height(), bounds_in_screen.height()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Restore. - wd.set_window_component(HTCAPTION); - generator2.DoubleClickLeftButton(); - EXPECT_EQ(restored_bounds.ToString(), window->GetBoundsInScreen().ToString()); - - // X-axis maximization. - wd.set_window_component(HTLEFT); - generator2.DoubleClickLeftButton(); - bounds_in_screen = window->GetBoundsInScreen(); - EXPECT_EQ(restored_bounds.y(), bounds_in_screen.y()); - EXPECT_EQ(restored_bounds.height(), bounds_in_screen.height()); - EXPECT_EQ(work_area2.x(), bounds_in_screen.x()); - EXPECT_EQ(work_area2.width(), bounds_in_screen.width()); - EXPECT_FALSE(window_state->IsMaximized()); - - // Restore. - wd.set_window_component(HTCAPTION); - generator2.DoubleClickLeftButton(); - EXPECT_EQ(restored_bounds.ToString(), window->GetBoundsInScreen().ToString()); -} - -TEST_F(WorkspaceEventHandlerTest, - DoubleClickSingleAxisDoesntResizeVerticalEdgeIfConstrained) { - gfx::Rect restored_bounds(10, 10, 50, 50); - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, restored_bounds)); - - wm::ActivateWindow(window.get()); - - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - - wd.set_maximum_size(gfx::Size(0, 100)); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window.get()); - // Double-click the top resize edge. - wd.set_window_component(HTTOP); - generator.DoubleClickLeftButton(); - - // The size of the window should be unchanged. - EXPECT_EQ(restored_bounds.y(), window->bounds().y()); - EXPECT_EQ(restored_bounds.height(), window->bounds().height()); -} - -TEST_F(WorkspaceEventHandlerTest, - DoubleClickSingleAxisDoesntResizeHorizontalEdgeIfConstrained) { - gfx::Rect restored_bounds(10, 10, 50, 50); - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, restored_bounds)); - - wm::ActivateWindow(window.get()); - - gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( - window.get()).work_area(); - - wd.set_maximum_size(gfx::Size(100, 0)); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window.get()); - // Double-click the top resize edge. - wd.set_window_component(HTRIGHT); - generator.DoubleClickLeftButton(); - - // The size of the window should be unchanged. - EXPECT_EQ(restored_bounds.x(), window->bounds().x()); - EXPECT_EQ(restored_bounds.width(), window->bounds().width()); -} - -TEST_F(WorkspaceEventHandlerTest, DoubleClickCaptionTogglesMaximize) { - aura::test::TestWindowDelegate wd; - scoped_ptr<aura::Window> window( - CreateTestWindow(&wd, gfx::Rect(1, 2, 30, 40))); - window->SetProperty(aura::client::kCanMaximizeKey, true); - wd.set_window_component(HTCAPTION); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - EXPECT_FALSE(window_state->IsMaximized()); - aura::Window* root = Shell::GetPrimaryRootWindow(); - aura::test::EventGenerator generator(root, window.get()); - generator.DoubleClickLeftButton(); - EXPECT_NE("1,2 30x40", window->bounds().ToString()); - - EXPECT_TRUE(window_state->IsMaximized()); - generator.DoubleClickLeftButton(); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_EQ("1,2 30x40", window->bounds().ToString()); - - // Double-clicking the middle button shouldn't toggle the maximized state. - WindowPropertyObserver observer(window.get()); - ui::MouseEvent press(ui::ET_MOUSE_PRESSED, generator.current_location(), - generator.current_location(), - ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_IS_DOUBLE_CLICK); - aura::WindowEventDispatcher* dispatcher = root->GetDispatcher(); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&press); - ui::MouseEvent release(ui::ET_MOUSE_RELEASED, generator.current_location(), - generator.current_location(), - ui::EF_IS_DOUBLE_CLICK); - dispatcher->AsRootWindowHostDelegate()->OnHostMouseEvent(&release); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_EQ("1,2 30x40", window->bounds().ToString()); - EXPECT_FALSE(observer.DidPropertyChange(aura::client::kShowStateKey)); -} - -TEST_F(WorkspaceEventHandlerTest, DoubleTapCaptionTogglesMaximize) { - aura::test::TestWindowDelegate wd; - gfx::Rect bounds(10, 20, 30, 40); - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, bounds)); - window->SetProperty(aura::client::kCanMaximizeKey, true); - wd.set_window_component(HTCAPTION); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - EXPECT_FALSE(window_state->IsMaximized()); - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - window.get()); - generator.GestureTapAt(gfx::Point(25, 25)); - generator.GestureTapAt(gfx::Point(25, 25)); - RunAllPendingInMessageLoop(); - EXPECT_NE(bounds.ToString(), window->bounds().ToString()); - EXPECT_TRUE(window_state->IsMaximized()); - - generator.GestureTapAt(gfx::Point(5, 5)); - generator.GestureTapAt(gfx::Point(10, 10)); - - EXPECT_FALSE(window_state->IsMaximized()); - EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); -} - -// Verifies deleting the window while dragging doesn't crash. -TEST_F(WorkspaceEventHandlerTest, DeleteWhenDragging) { - // Create a large window in the background. This is necessary so that when we - // delete |window| WorkspaceEventHandler is still the active event handler. - aura::test::TestWindowDelegate wd2; - scoped_ptr<aura::Window> window2( - CreateTestWindow(&wd2, gfx::Rect(0, 0, 500, 500))); - - aura::test::TestWindowDelegate wd; - const gfx::Rect bounds(10, 20, 30, 40); - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, bounds)); - wd.set_window_component(HTCAPTION); - aura::test::EventGenerator generator(window->GetRootWindow()); - generator.MoveMouseToCenterOf(window.get()); - generator.PressLeftButton(); - generator.MoveMouseTo(generator.current_location() + gfx::Vector2d(50, 50)); - DCHECK_NE(bounds.origin().ToString(), window->bounds().origin().ToString()); - window.reset(); - generator.MoveMouseTo(generator.current_location() + gfx::Vector2d(50, 50)); -} - -// Verifies deleting the window while in a run loop doesn't crash. -TEST_F(WorkspaceEventHandlerTest, DeleteWhileInRunLoop) { - aura::test::TestWindowDelegate wd; - const gfx::Rect bounds(10, 20, 30, 40); - scoped_ptr<aura::Window> window(CreateTestWindow(&wd, bounds)); - wd.set_window_component(HTCAPTION); - - ASSERT_TRUE(aura::client::GetWindowMoveClient(window->parent())); - base::MessageLoop::current()->DeleteSoon(FROM_HERE, window.get()); - aura::client::GetWindowMoveClient(window->parent()) - ->RunMoveLoop(window.release(), - gfx::Vector2d(), - aura::client::WINDOW_MOVE_SOURCE_MOUSE); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_layout_manager.cc b/chromium/ash/wm/workspace/workspace_layout_manager.cc deleted file mode 100644 index fe7d748d19b..00000000000 --- a/chromium/ash/wm/workspace/workspace_layout_manager.cc +++ /dev/null @@ -1,436 +0,0 @@ -// 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. - -#include "ash/wm/workspace/workspace_layout_manager.h" - -#include "ash/display/display_controller.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/wm/always_on_top_controller.h" -#include "ash/wm/base_layout_manager.h" -#include "ash/wm/window_animations.h" -#include "ash/wm/window_positioner.h" -#include "ash/wm/window_properties.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" -#include "ui/base/ui_base_types.h" -#include "ui/compositor/scoped_layer_animation_settings.h" -#include "ui/events/event.h" -#include "ui/views/corewm/window_util.h" - -using aura::Window; - -namespace ash { - -namespace internal { - -namespace { - -// This specifies how much percent 30% of a window rect (width / height) -// must be visible when the window is added to the workspace. -const float kMinimumPercentOnScreenArea = 0.3f; - -void MoveToDisplayForRestore(wm::WindowState* window_state) { - if (!window_state->HasRestoreBounds()) - return; - const gfx::Rect& restore_bounds = window_state->GetRestoreBoundsInScreen(); - - // Move only if the restore bounds is outside of - // the display. There is no information about in which - // display it should be restored, so this is best guess. - // TODO(oshima): Restore information should contain the - // work area information like WindowResizer does for the - // last window location. - gfx::Rect display_area = Shell::GetScreen()->GetDisplayNearestWindow( - window_state->window()).bounds(); - - if (!display_area.Intersects(restore_bounds)) { - DisplayController* display_controller = - Shell::GetInstance()->display_controller(); - const gfx::Display& display = - display_controller->GetDisplayMatching(restore_bounds); - aura::Window* new_root = - display_controller->GetRootWindowForDisplayId(display.id()); - if (new_root != window_state->window()->GetRootWindow()) { - aura::Window* new_container = - Shell::GetContainer(new_root, window_state->window()->parent()->id()); - new_container->AddChild(window_state->window()); - } - } -} - -} // namespace - -WorkspaceLayoutManager::WorkspaceLayoutManager(aura::Window* window) - : BaseLayoutManager(window->GetRootWindow()), - shelf_(NULL), - window_(window), - work_area_in_parent_(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window->parent())), - is_fullscreen_(GetRootWindowController( - window->GetRootWindow())->GetWindowForFullscreenMode() != NULL) { -} - -WorkspaceLayoutManager::~WorkspaceLayoutManager() { -} - -void WorkspaceLayoutManager::SetShelf(internal::ShelfLayoutManager* shelf) { - shelf_ = shelf; -} - -void WorkspaceLayoutManager::OnWindowAddedToLayout(Window* child) { - AdjustWindowBoundsWhenAdded(wm::GetWindowState(child)); - BaseLayoutManager::OnWindowAddedToLayout(child); - UpdateShelfVisibility(); - UpdateFullscreenState(); - WindowPositioner::RearrangeVisibleWindowOnShow(child); -} - -void WorkspaceLayoutManager::OnWillRemoveWindowFromLayout(Window* child) { - BaseLayoutManager::OnWillRemoveWindowFromLayout(child); - if (child->TargetVisibility()) - WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child); -} - -void WorkspaceLayoutManager::OnWindowRemovedFromLayout(Window* child) { - BaseLayoutManager::OnWindowRemovedFromLayout(child); - UpdateShelfVisibility(); - UpdateFullscreenState(); -} - -void WorkspaceLayoutManager::OnChildWindowVisibilityChanged(Window* child, - bool visible) { - BaseLayoutManager::OnChildWindowVisibilityChanged(child, visible); - if (child->TargetVisibility()) { - WindowPositioner::RearrangeVisibleWindowOnShow(child); - } else { - if (wm::GetWindowState(child)->IsFullscreen()) - UpdateFullscreenState(); - WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child); - } - UpdateShelfVisibility(); -} - -void WorkspaceLayoutManager::SetChildBounds( - Window* child, - const gfx::Rect& requested_bounds) { - wm::WindowState* window_state = wm::GetWindowState(child); - if (window_state->is_dragged()) { - SetChildBoundsDirect(child, requested_bounds); - } else if (!SetMaximizedOrFullscreenBounds(window_state)) { - // Some windows rely on this to set their initial bounds. - // Non-maximized/full-screen windows have their size constrained to the - // work-area. - gfx::Rect child_bounds(requested_bounds); - child_bounds.set_width(std::min(work_area_in_parent_.width(), - child_bounds.width())); - child_bounds.set_height(std::min(work_area_in_parent_.height(), - child_bounds.height())); - AdjustSnappedBounds(window_state, &child_bounds); - SetChildBoundsDirect(child, child_bounds); - } - UpdateShelfVisibility(); -} - -void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() { - const gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_->parent())); - if (work_area != work_area_in_parent_) { - AdjustAllWindowsBoundsForWorkAreaChange( - ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED); - } -} - -void WorkspaceLayoutManager::OnWindowPropertyChanged(Window* window, - const void* key, - intptr_t old) { - if (key == aura::client::kAlwaysOnTopKey && - window->GetProperty(aura::client::kAlwaysOnTopKey)) { - GetRootWindowController(window->GetRootWindow())-> - always_on_top_controller()->GetContainer(window)->AddChild(window); - } -} - -void WorkspaceLayoutManager::OnWindowStackingChanged(aura::Window* window) { - BaseLayoutManager::OnWindowStackingChanged(window); - UpdateShelfVisibility(); - UpdateFullscreenState(); -} - -void WorkspaceLayoutManager::OnWindowShowTypeChanged( - wm::WindowState* window_state, - wm::WindowShowType old_type) { - ui::WindowShowState old_state = ToWindowShowState(old_type); - ui::WindowShowState new_state = window_state->GetShowState(); - if (old_state != ui::SHOW_STATE_MINIMIZED && - !window_state->HasRestoreBounds() && - window_state->IsMaximizedOrFullscreen() && - !wm::WindowState::IsMaximizedOrFullscreenState(old_state)) { - window_state->SaveCurrentBoundsForRestore(); - } - // When restoring from a minimized state, we want to restore to the - // previous (maybe L/R maximized) state. Since we do also want to keep the - // restore rectangle, we set the restore rectangle to the rectangle we want - // to restore to and restore it after we switched so that it is preserved. - gfx::Rect restore; - if (old_state == ui::SHOW_STATE_MINIMIZED && - (new_state == ui::SHOW_STATE_NORMAL || - new_state == ui::SHOW_STATE_DEFAULT) && - window_state->HasRestoreBounds() && - !window_state->always_restores_to_restore_bounds()) { - restore = window_state->GetRestoreBoundsInScreen(); - window_state->SaveCurrentBoundsForRestore(); - } - // Notify observers that fullscreen state may be changing. - if (old_state != new_state && - (new_state == ui::SHOW_STATE_FULLSCREEN || - old_state == ui::SHOW_STATE_FULLSCREEN)) { - UpdateFullscreenState(); - } - - UpdateBoundsFromShowState(window_state, old_state); - ShowStateChanged(window_state, old_state); - - // Set the restore rectangle to the previously set restore rectangle. - if (!restore.IsEmpty()) - window_state->SetRestoreBoundsInScreen(restore); -} - -void WorkspaceLayoutManager::ShowStateChanged( - wm::WindowState* state, - ui::WindowShowState last_show_state) { - BaseLayoutManager::ShowStateChanged(state, last_show_state); - UpdateShelfVisibility(); -} - -void WorkspaceLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange( - AdjustWindowReason reason) { - work_area_in_parent_ = - ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_->parent()); - BaseLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange(reason); -} - -void WorkspaceLayoutManager::AdjustWindowBoundsForWorkAreaChange( - wm::WindowState* window_state, - AdjustWindowReason reason) { - if (window_state->is_dragged()) - return; - - // Do not cross fade here: the window's layer hierarchy may be messed up for - // the transition between mirroring and extended. See also: crbug.com/267698 - // TODO(oshima): Differentiate display change and shelf visibility change, and - // bring back CrossFade animation. - if (window_state->IsMaximized() && - reason == ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED) { - SetChildBoundsDirect(window_state->window(), - ScreenAsh::GetMaximizedWindowBoundsInParent( - window_state->window()->parent()->parent())); - return; - } - - if (SetMaximizedOrFullscreenBounds(window_state)) - return; - - gfx::Rect bounds = window_state->window()->bounds(); - switch (reason) { - case ADJUST_WINDOW_DISPLAY_SIZE_CHANGED: - // The work area may be smaller than the full screen. Put as much of the - // window as possible within the display area. - bounds.AdjustToFit(work_area_in_parent_); - break; - case ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED: - ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( - work_area_in_parent_, &bounds); - break; - } - AdjustSnappedBounds(window_state, &bounds); - if (window_state->window()->bounds() != bounds) - SetChildBoundsAnimated(window_state->window(), bounds); -} - -void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded( - wm::WindowState* window_state) { - // Don't adjust window bounds if the bounds are empty as this - // happens when a new views::Widget is created. - // When a window is dragged and dropped onto a different - // root window, the bounds will be updated after they are added - // to the root window. - if (window_state->window()->bounds().IsEmpty()) - return; - - if (window_state->is_dragged()) - return; - - if (SetMaximizedOrFullscreenBounds(window_state)) - return; - - Window* window = window_state->window(); - gfx::Rect bounds = window->bounds(); - int min_width = bounds.width() * kMinimumPercentOnScreenArea; - int min_height = bounds.height() * kMinimumPercentOnScreenArea; - // Use entire display instead of workarea because the workarea can - // be further shrunk by the docked area. The logic ensures 30% - // visibility which should be enough to see where the window gets - // moved. - gfx::Rect display_area = ScreenAsh::GetDisplayBoundsInParent(window); - - ash::wm::AdjustBoundsToEnsureWindowVisibility( - display_area, min_width, min_height, &bounds); - AdjustSnappedBounds(window_state, &bounds); - if (window->bounds() != bounds) - window->SetBounds(bounds); -} - -void WorkspaceLayoutManager::UpdateShelfVisibility() { - if (shelf_) - shelf_->UpdateVisibilityState(); -} - -void WorkspaceLayoutManager::UpdateFullscreenState() { - bool is_fullscreen = GetRootWindowController( - window_->GetRootWindow())->GetWindowForFullscreenMode() != NULL; - if (is_fullscreen != is_fullscreen_) { - ash::Shell::GetInstance()->NotifyFullscreenStateChange( - is_fullscreen, window_->GetRootWindow()); - is_fullscreen_ = is_fullscreen; - } -} - -void WorkspaceLayoutManager::UpdateBoundsFromShowState( - wm::WindowState* window_state, - ui::WindowShowState last_show_state) { - aura::Window* window = window_state->window(); - // See comment in SetMaximizedOrFullscreenBounds() as to why we use parent in - // these calculation. - // TODO(varkha): Change the switch statement below to use wm::WindowShowType. - switch (window_state->GetShowState()) { - case ui::SHOW_STATE_DEFAULT: - case ui::SHOW_STATE_NORMAL: { - // Make sure that the part of the window is always visible - // when restored. - gfx::Rect bounds_in_parent; - if (window_state->HasRestoreBounds()) { - bounds_in_parent = window_state->GetRestoreBoundsInParent(); - ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( - work_area_in_parent_, &bounds_in_parent); - } else { - // Minimized windows have no restore bounds. - // Use the current bounds instead. - bounds_in_parent = window->bounds(); - ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( - work_area_in_parent_, &bounds_in_parent); - // Don't start animation if the bounds didn't change. - if (bounds_in_parent == window->bounds()) - bounds_in_parent.SetRect(0, 0, 0, 0); - } - if (!bounds_in_parent.IsEmpty()) { - if ((last_show_state == ui::SHOW_STATE_DEFAULT || - last_show_state == ui::SHOW_STATE_NORMAL) && - window_state->IsSnapped()) { - AdjustSnappedBounds(window_state, &bounds_in_parent); - SetChildBoundsAnimated(window, bounds_in_parent); - } else { - gfx::Rect new_bounds = BaseLayoutManager::BoundsWithScreenEdgeVisible( - window->parent()->parent(), - bounds_in_parent); - if (last_show_state == ui::SHOW_STATE_MINIMIZED) - SetChildBoundsDirect(window, new_bounds); - else - CrossFadeToBounds(window, new_bounds); - } - } - window_state->ClearRestoreBounds(); - break; - } - - case ui::SHOW_STATE_MAXIMIZED: { - MoveToDisplayForRestore(window_state); - gfx::Rect new_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent( - window->parent()->parent()); - // If the window is restored from minimized state, do not make the cross - // fade animation and set the child bounds directly. The restoring - // animation will be done by ash/wm/window_animations.cc. - if (last_show_state == ui::SHOW_STATE_MINIMIZED) - SetChildBoundsDirect(window, new_bounds); - else - CrossFadeToBounds(window, new_bounds); - break; - } - - case ui::SHOW_STATE_FULLSCREEN: { - MoveToDisplayForRestore(window_state); - gfx::Rect new_bounds = ScreenAsh::GetDisplayBoundsInParent( - window->parent()->parent()); - if (window_state->animate_to_fullscreen() && - last_show_state != ui::SHOW_STATE_MINIMIZED) { - CrossFadeToBounds(window, new_bounds); - } else { - SetChildBoundsDirect(window, new_bounds); - } - break; - } - - default: - break; - } -} - -bool WorkspaceLayoutManager::SetMaximizedOrFullscreenBounds( - wm::WindowState* window_state) { - DCHECK(!window_state->is_dragged()); - - // During animations there is a transform installed on the workspace - // windows. For this reason this code uses the parent so that the transform is - // ignored. - if (window_state->IsMaximized()) { - SetChildBoundsDirect( - window_state->window(), ScreenAsh::GetMaximizedWindowBoundsInParent( - window_state->window()->parent()->parent())); - return true; - } - if (window_state->IsFullscreen()) { - SetChildBoundsDirect( - window_state->window(), - ScreenAsh::GetDisplayBoundsInParent( - window_state->window()->parent()->parent())); - return true; - } - return false; -} - -void WorkspaceLayoutManager::AdjustSnappedBounds(wm::WindowState* window_state, - gfx::Rect* bounds) { - if (window_state->is_dragged() || !window_state->IsSnapped()) - return; - gfx::Rect maximized_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent( - window_state->window()->parent()->parent()); - if (window_state->window_show_type() == wm::SHOW_TYPE_LEFT_SNAPPED) - bounds->set_x(maximized_bounds.x()); - else if (window_state->window_show_type() == wm::SHOW_TYPE_RIGHT_SNAPPED) - bounds->set_x(maximized_bounds.right() - bounds->width()); - bounds->set_y(maximized_bounds.y()); - // TODO(varkha): Set width to 50% here for snapped windows. - bounds->set_height(maximized_bounds.height()); -} - -void WorkspaceLayoutManager::SetChildBoundsAnimated(Window* child, - const gfx::Rect& bounds) { - const int kBoundsChangeSlideDurationMs = 120; - - ui::Layer* layer = child->layer(); - ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator()); - slide_settings.SetPreemptionStrategy( - ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); - slide_settings.SetTransitionDuration( - base::TimeDelta::FromMilliseconds(kBoundsChangeSlideDurationMs)); - SetChildBoundsDirect(child, bounds); -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_layout_manager.h b/chromium/ash/wm/workspace/workspace_layout_manager.h deleted file mode 100644 index ab4876c5b2e..00000000000 --- a/chromium/ash/wm/workspace/workspace_layout_manager.h +++ /dev/null @@ -1,115 +0,0 @@ -// 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_WORKSPACE_LAYOUT_MANAGER_H_ -#define ASH_WM_WORKSPACE_WORKSPACE_LAYOUT_MANAGER_H_ - -#include <set> - -#include "ash/shell_observer.h" -#include "ash/wm/base_layout_manager.h" -#include "base/basictypes.h" -#include "base/compiler_specific.h" -#include "ui/base/ui_base_types.h" -#include "ui/aura/window_observer.h" -#include "ui/gfx/rect.h" - -namespace aura { -class RootWindow; -class Window; -} - -namespace ui { -class Layer; -} - -namespace ash { - -namespace internal { - -class ShelfLayoutManager; - -// LayoutManager used on the window created for a workspace. -class ASH_EXPORT WorkspaceLayoutManager : public BaseLayoutManager { - public: - explicit WorkspaceLayoutManager(aura::Window* window); - virtual ~WorkspaceLayoutManager(); - - void SetShelf(internal::ShelfLayoutManager* shelf); - - // Overridden from aura::LayoutManager: - virtual void OnWindowResized() OVERRIDE {} - virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; - virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; - virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; - virtual void OnChildWindowVisibilityChanged(aura::Window* child, - bool visibile) OVERRIDE; - virtual void SetChildBounds(aura::Window* child, - const gfx::Rect& requested_bounds) OVERRIDE; - - // ash::ShellObserver overrides: - virtual void OnDisplayWorkAreaInsetsChanged() OVERRIDE; - - // Overriden from WindowObserver: - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE; - virtual void OnWindowStackingChanged(aura::Window* window) OVERRIDE; - - // WindowStateObserver overrides: - virtual void OnWindowShowTypeChanged(wm::WindowState* window_state, - wm::WindowShowType old_type) OVERRIDE; - - private: - // Overridden from BaseLayoutManager: - virtual void ShowStateChanged(wm::WindowState* window_state, - ui::WindowShowState last_show_state) OVERRIDE; - virtual void AdjustAllWindowsBoundsForWorkAreaChange( - AdjustWindowReason reason) OVERRIDE; - virtual void AdjustWindowBoundsForWorkAreaChange( - wm::WindowState* window_state, - AdjustWindowReason reason) OVERRIDE; - - void AdjustWindowBoundsWhenAdded(wm::WindowState* window_state); - - // Updates the visibility state of the shelf. - void UpdateShelfVisibility(); - - // Updates the fullscreen state of the workspace and notifies Shell if it - // has changed. - void UpdateFullscreenState(); - - // Updates the bounds of the window for a show state change from - // |last_show_state|. - void UpdateBoundsFromShowState(wm::WindowState* window_state, - ui::WindowShowState last_show_state); - - // If |window_state| is maximized or fullscreen the bounds of the - // window are set and true is returned. Does nothing otherwise. - bool SetMaximizedOrFullscreenBounds(wm::WindowState* window_state); - - // Adjusts the |bounds| so that they are flush with the edge of the - // workspace if the window represented by |window_state| is side snapped. - void AdjustSnappedBounds(wm::WindowState* window_state, gfx::Rect* bounds); - - // Animates the window bounds to |bounds|. - void SetChildBoundsAnimated(aura::Window* child, const gfx::Rect& bounds); - - internal::ShelfLayoutManager* shelf_; - aura::Window* window_; - - // The work area. Cached to avoid unnecessarily moving windows during a - // workspace switch. - gfx::Rect work_area_in_parent_; - - // True if this workspace is currently in fullscreen mode. - bool is_fullscreen_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManager); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WORKSPACE_LAYOUT_MANAGER_H_ diff --git a/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc b/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc deleted file mode 100644 index d12fb15bb79..00000000000 --- a/chromium/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ /dev/null @@ -1,481 +0,0 @@ -// 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. - -#include "ash/wm/workspace/workspace_layout_manager.h" - -#include "ash/display/display_layout.h" -#include "ash/display/display_manager.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shelf/shelf_widget.h" -#include "ash/shell.h" -#include "ash/shell_observer.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/test_windows.h" -#include "ui/aura/window.h" -#include "ui/gfx/insets.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { -namespace { - -class MaximizeDelegateView : public views::WidgetDelegateView { - public: - MaximizeDelegateView(const gfx::Rect& initial_bounds) - : initial_bounds_(initial_bounds) { - } - virtual ~MaximizeDelegateView() {} - - virtual bool GetSavedWindowPlacement( - const views::Widget* widget, - gfx::Rect* bounds, - ui::WindowShowState* show_state) const OVERRIDE { - *bounds = initial_bounds_; - *show_state = ui::SHOW_STATE_MAXIMIZED; - return true; - } - - private: - const gfx::Rect initial_bounds_; - - DISALLOW_COPY_AND_ASSIGN(MaximizeDelegateView); -}; - -class TestShellObserver : public ShellObserver { - public: - TestShellObserver() : call_count_(0), - is_fullscreen_(false) { - Shell::GetInstance()->AddShellObserver(this); - } - - virtual ~TestShellObserver() { - Shell::GetInstance()->RemoveShellObserver(this); - } - - virtual void OnFullscreenStateChanged(bool is_fullscreen, - aura::Window* root_window) OVERRIDE { - call_count_++; - is_fullscreen_ = is_fullscreen; - } - - int call_count() const { - return call_count_; - } - - bool is_fullscreen() const { - return is_fullscreen_; - } - - private: - int call_count_; - bool is_fullscreen_; - - DISALLOW_COPY_AND_ASSIGN(TestShellObserver); -}; - -} // namespace - -typedef test::AshTestBase WorkspaceLayoutManagerTest; - -// Verifies that a window containing a restore coordinate will be restored to -// to the size prior to minimize, keeping the restore rectangle in tact (if -// there is one). -TEST_F(WorkspaceLayoutManagerTest, RestoreFromMinimizeKeepsRestore) { - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 3, 4))); - gfx::Rect bounds(10, 15, 25, 35); - window->SetBounds(bounds); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - // This will not be used for un-minimizing window. - window_state->SetRestoreBoundsInScreen(gfx::Rect(0, 0, 100, 100)); - window_state->Minimize(); - window_state->Restore(); - EXPECT_EQ("0,0 100x100", window_state->GetRestoreBoundsInScreen().ToString()); - EXPECT_EQ("10,15 25x35", window.get()->bounds().ToString()); - - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("400x300,500x400"); - window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100), - ScreenAsh::GetSecondaryDisplay()); - EXPECT_EQ(Shell::GetAllRootWindows()[1], window->GetRootWindow()); - window_state->Minimize(); - // This will not be used for un-minimizing window. - window_state->SetRestoreBoundsInScreen(gfx::Rect(0, 0, 100, 100)); - window_state->Restore(); - EXPECT_EQ("600,0 100x100", window->GetBoundsInScreen().ToString()); - - // Make sure the unminimized window moves inside the display when - // 2nd display is disconnected. - window_state->Minimize(); - UpdateDisplay("400x300"); - window_state->Restore(); - EXPECT_EQ(Shell::GetPrimaryRootWindow(), window->GetRootWindow()); - EXPECT_TRUE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); -} - -TEST_F(WorkspaceLayoutManagerTest, KeepMinimumVisibilityInDisplays) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("300x400,400x500"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - DisplayLayout layout(DisplayLayout::TOP, 0); - Shell::GetInstance()->display_manager()-> - SetLayoutForCurrentDisplays(layout); - EXPECT_EQ("0,-500 400x500", root_windows[1]->GetBoundsInScreen().ToString()); - - scoped_ptr<aura::Window> window1( - CreateTestWindowInShellWithBounds(gfx::Rect(10, -400, 200, 200))); - EXPECT_EQ("10,-400 200x200", window1->GetBoundsInScreen().ToString()); - - // Make sure the caption is visible. - scoped_ptr<aura::Window> window2( - CreateTestWindowInShellWithBounds(gfx::Rect(10, -600, 200, 200))); - EXPECT_EQ("10,-500 200x200", window2->GetBoundsInScreen().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, KeepRestoredWindowInDisplay) { - if (!SupportsHostWindowResize()) - return; - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - - // Maximized -> Normal transition. - window_state->Maximize(); - window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40)); - window_state->Restore(); - EXPECT_TRUE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); - // Y bounds should not be negative. - EXPECT_EQ("-20,0 30x40", window->bounds().ToString()); - - // Minimized -> Normal transition. - window->SetBounds(gfx::Rect(-100, -100, 30, 40)); - window_state->Minimize(); - EXPECT_FALSE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); - EXPECT_EQ("-100,-100 30x40", window->bounds().ToString()); - window->Show(); - EXPECT_TRUE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); - // Y bounds should not be negative. - EXPECT_EQ("-20,0 30x40", window->bounds().ToString()); - - // Fullscreen -> Normal transition. - window->SetBounds(gfx::Rect(0, 0, 30, 40)); // reset bounds. - ASSERT_EQ("0,0 30x40", window->bounds().ToString()); - window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(window->bounds(), window->GetRootWindow()->bounds()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40)); - window_state->Restore(); - EXPECT_TRUE( - Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds())); - // Y bounds should not be negative. - EXPECT_EQ("-20,0 30x40", window->bounds().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, MaximizeInDisplayToBeRestored) { - if (!SupportsMultipleDisplays()) - return; - UpdateDisplay("300x400,400x500"); - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40)); - // Maximize the window in 2nd display as the restore bounds - // is inside 2nd display. - window_state->Maximize(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("300,0 400x453", window->GetBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString()); - - // If the restore bounds intersects with the current display, - // don't move. - window_state->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40)); - window_state->Maximize(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("300,0 400x453", window->GetBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString()); - - // Restoring widget state. - scoped_ptr<views::Widget> w1(new views::Widget); - views::Widget::InitParams params; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.delegate = new MaximizeDelegateView(gfx::Rect(400, 0, 30, 40)); - params.context = root_windows[0]; - w1->Init(params); - w1->Show(); - EXPECT_TRUE(w1->IsMaximized()); - EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow()); - EXPECT_EQ("300,0 400x453", w1->GetWindowBoundsInScreen().ToString()); - w1->Restore(); - EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow()); - EXPECT_EQ("400,0 30x40", w1->GetWindowBoundsInScreen().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, FullscreenInDisplayToBeRestored) { - if (!SupportsMultipleDisplays()) - return; - UpdateDisplay("300x400,400x500"); - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - EXPECT_EQ(root_windows[0], window->GetRootWindow()); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40)); - // Maximize the window in 2nd display as the restore bounds - // is inside 2nd display. - window->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString()); - - // If the restore bounds intersects with the current display, - // don't move. - window_state->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40)); - window->SetProperty(aura::client::kShowStateKey, - ui::SHOW_STATE_FULLSCREEN); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString()); - - window_state->Restore(); - EXPECT_EQ(root_windows[1], window->GetRootWindow()); - EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString()); -} - -// WindowObserver implementation used by DontClobberRestoreBoundsWindowObserver. -// This code mirrors what BrowserFrameAsh does. In particular when this code -// sees the window was maximized it changes the bounds of a secondary -// window. The secondary window mirrors the status window. -class DontClobberRestoreBoundsWindowObserver : public aura::WindowObserver { - public: - DontClobberRestoreBoundsWindowObserver() : window_(NULL) {} - - void set_window(aura::Window* window) { window_ = window; } - - virtual void OnWindowPropertyChanged(aura::Window* window, - const void* key, - intptr_t old) OVERRIDE { - if (!window_) - return; - - if (wm::GetWindowState(window)->IsMaximized()) { - aura::Window* w = window_; - window_ = NULL; - - gfx::Rect shelf_bounds(Shell::GetPrimaryRootWindowController()-> - GetShelfLayoutManager()->GetIdealBounds()); - const gfx::Rect& window_bounds(w->bounds()); - w->SetBounds(gfx::Rect(window_bounds.x(), shelf_bounds.y() - 1, - window_bounds.width(), window_bounds.height())); - } - } - - private: - aura::Window* window_; - - DISALLOW_COPY_AND_ASSIGN(DontClobberRestoreBoundsWindowObserver); -}; - -// Creates a window, maximized the window and from within the maximized -// notification sets the bounds of a window to overlap the shelf. Verifies this -// doesn't effect the restore bounds. -TEST_F(WorkspaceLayoutManagerTest, DontClobberRestoreBounds) { - DontClobberRestoreBoundsWindowObserver window_observer; - scoped_ptr<aura::Window> window(new aura::Window(NULL)); - window->SetType(aura::client::WINDOW_TYPE_NORMAL); - window->Init(ui::LAYER_TEXTURED); - window->SetBounds(gfx::Rect(10, 20, 30, 40)); - // NOTE: for this test to exercise the failure the observer needs to be added - // before the parent set. This mimics what BrowserFrameAsh does. - window->AddObserver(&window_observer); - ParentWindowInPrimaryRootWindow(window.get()); - window->Show(); - - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->Activate(); - - scoped_ptr<aura::Window> window2( - CreateTestWindowInShellWithBounds(gfx::Rect(12, 20, 30, 40))); - window->AddTransientChild(window2.get()); - window2->Show(); - - window_observer.set_window(window2.get()); - window_state->Maximize(); - EXPECT_EQ("10,20 30x40", - window_state->GetRestoreBoundsInScreen().ToString()); - window->RemoveObserver(&window_observer); -} - -// Verifies when a window is maximized all descendant windows have a size. -TEST_F(WorkspaceLayoutManagerTest, ChildBoundsResetOnMaximize) { - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(gfx::Rect(10, 20, 30, 40))); - window->Show(); - wm::WindowState* window_state = wm::GetWindowState(window.get()); - window_state->Activate(); - scoped_ptr<aura::Window> child_window( - aura::test::CreateTestWindowWithBounds(gfx::Rect(5, 6, 7, 8), - window.get())); - child_window->Show(); - window_state->Maximize(); - EXPECT_EQ("5,6 7x8", child_window->bounds().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, WindowShouldBeOnScreenWhenAdded) { - // Normal window bounds shouldn't be changed. - gfx::Rect window_bounds(100, 100, 200, 200); - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_EQ(window_bounds, window->bounds()); - - // If the window is out of the workspace, it would be moved on screen. - gfx::Rect root_window_bounds = - Shell::GetInstance()->GetPrimaryRootWindow()->bounds(); - window_bounds.Offset(root_window_bounds.width(), root_window_bounds.height()); - ASSERT_FALSE(window_bounds.Intersects(root_window_bounds)); - scoped_ptr<aura::Window> out_window( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_EQ(window_bounds.size(), out_window->bounds().size()); - gfx::Rect bounds = out_window->bounds(); - bounds.Intersect(root_window_bounds); - - // 30% of the window edge must be visible. - EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29); - EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29); - - aura::Window* parent = out_window->parent(); - parent->RemoveChild(out_window.get()); - out_window->SetBounds(gfx::Rect(-200, -200, 200, 200)); - // UserHasChangedWindowPositionOrSize flag shouldn't turn off this behavior. - wm::GetWindowState(window.get())->set_bounds_changed_by_user(true); - parent->AddChild(out_window.get()); - EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29); - EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29); - - // Make sure we always make more than 1/3 of the window edge visible even - // if the initial bounds intersects with display. - window_bounds.SetRect(-150, -150, 200, 200); - bounds = window_bounds; - bounds.Intersect(root_window_bounds); - - // Make sure that the initial bounds' visible area is less than 26% - // so that the auto adjustment logic kicks in. - ASSERT_LT(bounds.width(), out_window->bounds().width() * 0.26); - ASSERT_LT(bounds.height(), out_window->bounds().height() * 0.26); - ASSERT_TRUE(window_bounds.Intersects(root_window_bounds)); - - scoped_ptr<aura::Window> partially_out_window( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_EQ(window_bounds.size(), partially_out_window->bounds().size()); - bounds = partially_out_window->bounds(); - bounds.Intersect(root_window_bounds); - EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29); - EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29); - - // Make sure the window whose 30% width/height is bigger than display - // will be placed correctly. - window_bounds.SetRect(-1900, -1900, 3000, 3000); - scoped_ptr<aura::Window> window_bigger_than_display( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_GE(root_window_bounds.width(), - window_bigger_than_display->bounds().width()); - EXPECT_GE(root_window_bounds.height(), - window_bigger_than_display->bounds().height()); - - bounds = window_bigger_than_display->bounds(); - bounds.Intersect(root_window_bounds); - EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29); - EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29); -} - -// Verifies the size of a window is enforced to be smaller than the work area. -TEST_F(WorkspaceLayoutManagerTest, SizeToWorkArea) { - // Normal window bounds shouldn't be changed. - gfx::Size work_area( - Shell::GetScreen()->GetPrimaryDisplay().work_area().size()); - const gfx::Rect window_bounds( - 100, 101, work_area.width() + 1, work_area.height() + 2); - scoped_ptr<aura::Window> window( - CreateTestWindowInShellWithBounds(window_bounds)); - EXPECT_EQ(gfx::Rect(gfx::Point(100, 101), work_area).ToString(), - window->bounds().ToString()); - - // Directly setting the bounds triggers a slightly different code path. Verify - // that too. - window->SetBounds(window_bounds); - EXPECT_EQ(gfx::Rect(gfx::Point(100, 101), work_area).ToString(), - window->bounds().ToString()); -} - -TEST_F(WorkspaceLayoutManagerTest, NotifyFullscreenChanges) { - TestShellObserver observer; - scoped_ptr<aura::Window> window1( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - scoped_ptr<aura::Window> window2( - CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40))); - wm::WindowState* window_state1 = wm::GetWindowState(window1.get()); - wm::WindowState* window_state2 = wm::GetWindowState(window2.get()); - window_state2->Activate(); - - window_state2->ToggleFullscreen(); - EXPECT_EQ(1, observer.call_count()); - EXPECT_TRUE(observer.is_fullscreen()); - - // When window1 moves to the front the fullscreen state should change. - window_state1->Activate(); - EXPECT_EQ(2, observer.call_count()); - EXPECT_FALSE(observer.is_fullscreen()); - - // It should change back if window2 becomes active again. - window_state2->Activate(); - EXPECT_EQ(3, observer.call_count()); - EXPECT_TRUE(observer.is_fullscreen()); - - window_state2->ToggleFullscreen(); - EXPECT_EQ(4, observer.call_count()); - EXPECT_FALSE(observer.is_fullscreen()); - - window_state2->ToggleFullscreen(); - EXPECT_EQ(5, observer.call_count()); - EXPECT_TRUE(observer.is_fullscreen()); - - // Closing the window should change the fullscreen state. - window2.reset(); - EXPECT_EQ(6, observer.call_count()); - EXPECT_FALSE(observer.is_fullscreen()); -} - -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_types.h b/chromium/ash/wm/workspace/workspace_types.h deleted file mode 100644 index 9572a328d8b..00000000000 --- a/chromium/ash/wm/workspace/workspace_types.h +++ /dev/null @@ -1,27 +0,0 @@ -// 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_WORKSPACE_TYPES_H_ -#define ASH_WM_WORKSPACE_WORKSPACE_TYPES_H_ - -namespace ash { - -// Enumeration of the possible window states. -enum WorkspaceWindowState { - // There's a full screen window. - WORKSPACE_WINDOW_STATE_FULL_SCREEN, - - // There's a maximized window. - WORKSPACE_WINDOW_STATE_MAXIMIZED, - - // At least one window overlaps the shelf. - WORKSPACE_WINDOW_STATE_WINDOW_OVERLAPS_SHELF, - - // None of the windows are fullscreen, maximized or touch the shelf. - WORKSPACE_WINDOW_STATE_DEFAULT, -}; - -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WORKSPACE_TYPES_H_ diff --git a/chromium/ash/wm/workspace/workspace_window_resizer.cc b/chromium/ash/wm/workspace/workspace_window_resizer.cc deleted file mode 100644 index b8cd5049448..00000000000 --- a/chromium/ash/wm/workspace/workspace_window_resizer.cc +++ /dev/null @@ -1,1051 +0,0 @@ -// 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. - -#include "ash/wm/workspace/workspace_window_resizer.h" - -#include <algorithm> -#include <cmath> -#include <utility> -#include <vector> - -#include "ash/ash_switches.h" -#include "ash/display/display_controller.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/wm/coordinate_conversion.h" -#include "ash/wm/default_window_resizer.h" -#include "ash/wm/dock/docked_window_layout_manager.h" -#include "ash/wm/dock/docked_window_resizer.h" -#include "ash/wm/drag_window_resizer.h" -#include "ash/wm/panels/panel_window_resizer.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/phantom_window_controller.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "base/command_line.h" -#include "base/memory/weak_ptr.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/client/screen_position_client.h" -#include "ui/aura/client/window_types.h" -#include "ui/aura/root_window.h" -#include "ui/aura/window.h" -#include "ui/aura/window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/compositor/layer.h" -#include "ui/gfx/screen.h" -#include "ui/gfx/transform.h" - -namespace ash { - -scoped_ptr<WindowResizer> CreateWindowResizer( - aura::Window* window, - const gfx::Point& point_in_parent, - int window_component, - aura::client::WindowMoveSource source) { - DCHECK(window); - wm::WindowState* window_state = wm::GetWindowState(window); - // No need to return a resizer when the window cannot get resized or when a - // resizer already exists for this window. - if ((!window_state->CanResize() && window_component != HTCAPTION) || - window_state->window_resizer()) { - return scoped_ptr<WindowResizer>(); - } - - // TODO(varkha): The chaining of window resizers causes some of the logic - // to be repeated and the logic flow difficult to control. With some windows - // classes using reparenting during drag operations it becomes challenging to - // implement proper transition from one resizer to another during or at the - // end of the drag. This also causes http://crbug.com/247085. - // It seems the only thing the panel or dock resizer needs to do is notify the - // layout manager when a docked window is being dragged. We should have a - // better way of doing this, perhaps by having a way of observing drags or - // having a generic drag window wrapper which informs a layout manager that a - // drag has started or stopped. - // It may be possible to refactor and eliminate chaining. - WindowResizer* window_resizer = NULL; - if (window->parent() && - (window->parent()->id() == internal::kShellWindowId_DefaultContainer || - window->parent()->id() == internal::kShellWindowId_DockedContainer || - window->parent()->id() == internal::kShellWindowId_PanelContainer)) { - // Allow dragging maximized windows if it's not tracked by workspace. This - // is set by tab dragging code. - if (!window_state->IsNormalShowState() && - (window_component != HTCAPTION || - !window_state->is_dragged())) { - return scoped_ptr<WindowResizer>(); - } - window_resizer = internal::WorkspaceWindowResizer::Create( - window, - point_in_parent, - window_component, - source, - std::vector<aura::Window*>()); - } else if (window_state->IsNormalShowState()) { - window_resizer = DefaultWindowResizer::Create( - window, point_in_parent, window_component, source); - } - if (window_resizer) { - window_resizer = internal::DragWindowResizer::Create( - window_resizer, window, point_in_parent, window_component, source); - } - if (window_resizer && window->type() == aura::client::WINDOW_TYPE_PANEL) { - window_resizer = PanelWindowResizer::Create( - window_resizer, window, point_in_parent, window_component, source); - } - if (switches::UseDockedWindows() && - window_resizer && window->parent() && - !window->transient_parent() && - (window->parent()->id() == internal::kShellWindowId_DefaultContainer || - window->parent()->id() == internal::kShellWindowId_DockedContainer || - window->parent()->id() == internal::kShellWindowId_PanelContainer)) { - window_resizer = internal::DockedWindowResizer::Create( - window_resizer, window, point_in_parent, window_component, source); - } - window_state->set_window_resizer_(window_resizer); - return make_scoped_ptr<WindowResizer>(window_resizer); -} - -namespace internal { - -namespace { - -// Snapping distance used instead of WorkspaceWindowResizer::kScreenEdgeInset -// when resizing a window using touchscreen. -const int kScreenEdgeInsetForTouchResize = 32; - -// Returns true if the window should stick to the edge. -bool ShouldStickToEdge(int distance_from_edge, int sticky_size) { - if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshEnableStickyEdges)) { - // TODO(varkha): Consider keeping snapping behavior for touch drag. - return distance_from_edge < 0 && - distance_from_edge > -sticky_size; - } - return distance_from_edge < sticky_size && - distance_from_edge > -sticky_size * 2; -} - -// Returns the coordinate along the secondary axis to snap to. -int CoordinateAlongSecondaryAxis(SecondaryMagnetismEdge edge, - int leading, - int trailing, - int none) { - switch (edge) { - case SECONDARY_MAGNETISM_EDGE_LEADING: - return leading; - case SECONDARY_MAGNETISM_EDGE_TRAILING: - return trailing; - case SECONDARY_MAGNETISM_EDGE_NONE: - return none; - } - NOTREACHED(); - return none; -} - -// Returns the origin for |src| when magnetically attaching to |attach_to| along -// the edges |edges|. |edges| is a bitmask of the MagnetismEdges. -gfx::Point OriginForMagneticAttach(const gfx::Rect& src, - const gfx::Rect& attach_to, - const MatchedEdge& edge) { - int x = 0, y = 0; - switch (edge.primary_edge) { - case MAGNETISM_EDGE_TOP: - y = attach_to.bottom(); - break; - case MAGNETISM_EDGE_LEFT: - x = attach_to.right(); - break; - case MAGNETISM_EDGE_BOTTOM: - y = attach_to.y() - src.height(); - break; - case MAGNETISM_EDGE_RIGHT: - x = attach_to.x() - src.width(); - break; - } - switch (edge.primary_edge) { - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - x = CoordinateAlongSecondaryAxis( - edge.secondary_edge, attach_to.x(), attach_to.right() - src.width(), - src.x()); - break; - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - y = CoordinateAlongSecondaryAxis( - edge.secondary_edge, attach_to.y(), attach_to.bottom() - src.height(), - src.y()); - break; - } - return gfx::Point(x, y); -} - -// Returns the bounds for a magnetic attach when resizing. |src| is the bounds -// of window being resized, |attach_to| the bounds of the window to attach to -// and |edge| identifies the edge to attach to. -gfx::Rect BoundsForMagneticResizeAttach(const gfx::Rect& src, - const gfx::Rect& attach_to, - const MatchedEdge& edge) { - int x = src.x(); - int y = src.y(); - int w = src.width(); - int h = src.height(); - gfx::Point attach_origin(OriginForMagneticAttach(src, attach_to, edge)); - switch (edge.primary_edge) { - case MAGNETISM_EDGE_LEFT: - x = attach_origin.x(); - w = src.right() - x; - break; - case MAGNETISM_EDGE_RIGHT: - w += attach_origin.x() - src.x(); - break; - case MAGNETISM_EDGE_TOP: - y = attach_origin.y(); - h = src.bottom() - y; - break; - case MAGNETISM_EDGE_BOTTOM: - h += attach_origin.y() - src.y(); - break; - } - switch (edge.primary_edge) { - case MAGNETISM_EDGE_LEFT: - case MAGNETISM_EDGE_RIGHT: - if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_LEADING) { - y = attach_origin.y(); - h = src.bottom() - y; - } else if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_TRAILING) { - h += attach_origin.y() - src.y(); - } - break; - case MAGNETISM_EDGE_TOP: - case MAGNETISM_EDGE_BOTTOM: - if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_LEADING) { - x = attach_origin.x(); - w = src.right() - x; - } else if (edge.secondary_edge == SECONDARY_MAGNETISM_EDGE_TRAILING) { - w += attach_origin.x() - src.x(); - } - break; - } - return gfx::Rect(x, y, w, h); -} - -// Converts a window component edge to the magnetic edge to snap to. -uint32 WindowComponentToMagneticEdge(int window_component) { - switch (window_component) { - case HTTOPLEFT: - return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_TOP; - case HTTOPRIGHT: - return MAGNETISM_EDGE_TOP | MAGNETISM_EDGE_RIGHT; - case HTBOTTOMLEFT: - return MAGNETISM_EDGE_LEFT | MAGNETISM_EDGE_BOTTOM; - case HTBOTTOMRIGHT: - return MAGNETISM_EDGE_RIGHT | MAGNETISM_EDGE_BOTTOM; - case HTTOP: - return MAGNETISM_EDGE_TOP; - case HTBOTTOM: - return MAGNETISM_EDGE_BOTTOM; - case HTRIGHT: - return MAGNETISM_EDGE_RIGHT; - case HTLEFT: - return MAGNETISM_EDGE_LEFT; - default: - break; - } - return 0; -} - -} // namespace - -// static -const int WorkspaceWindowResizer::kMinOnscreenSize = 20; - -// static -const int WorkspaceWindowResizer::kMinOnscreenHeight = 32; - -// static -const int WorkspaceWindowResizer::kScreenEdgeInset = 8; - -// static -const int WorkspaceWindowResizer::kStickyDistancePixels = 64; - -// static -WorkspaceWindowResizer* WorkspaceWindowResizer::instance_ = NULL; - -// Represents the width or height of a window with constraints on its minimum -// and maximum size. 0 represents a lack of a constraint. -class WindowSize { - public: - WindowSize(int size, int min, int max) - : size_(size), - min_(min), - max_(max) { - // Grow the min/max bounds to include the starting size. - if (is_underflowing()) - min_ = size_; - if (is_overflowing()) - max_ = size_; - } - - bool is_at_capacity(bool shrinking) { - return size_ == (shrinking ? min_ : max_); - } - - int size() const { - return size_; - } - - bool has_min() const { - return min_ != 0; - } - - bool has_max() const { - return max_ != 0; - } - - bool is_valid() const { - return !is_overflowing() && !is_underflowing(); - } - - bool is_overflowing() const { - return has_max() && size_ > max_; - } - - bool is_underflowing() const { - return has_min() && size_ < min_; - } - - // Add |amount| to this WindowSize not exceeding min or max size constraints. - // Returns by how much |size_| + |amount| exceeds the min/max constraints. - int Add(int amount) { - DCHECK(is_valid()); - int new_value = size_ + amount; - - if (has_min() && new_value < min_) { - size_ = min_; - return new_value - min_; - } - - if (has_max() && new_value > max_) { - size_ = max_; - return new_value - max_; - } - - size_ = new_value; - return 0; - } - - private: - int size_; - int min_; - int max_; -}; - -WorkspaceWindowResizer::~WorkspaceWindowResizer() { - if (did_lock_cursor_) { - Shell* shell = Shell::GetInstance(); - shell->cursor_manager()->UnlockCursor(); - } - if (instance_ == this) - instance_ = NULL; -} - -// static -WorkspaceWindowResizer* WorkspaceWindowResizer::Create( - aura::Window* window, - const gfx::Point& location_in_parent, - int window_component, - aura::client::WindowMoveSource source, - const std::vector<aura::Window*>& attached_windows) { - Details details(window, location_in_parent, window_component, source); - return details.is_resizable ? - new WorkspaceWindowResizer(details, attached_windows) : NULL; -} - -void WorkspaceWindowResizer::Drag(const gfx::Point& location_in_parent, - int event_flags) { - last_mouse_location_ = location_in_parent; - - int sticky_size; - if (event_flags & ui::EF_CONTROL_DOWN) { - sticky_size = 0; - } else if (CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshEnableStickyEdges)) { - sticky_size = kStickyDistancePixels; - } else if ((details_.bounds_change & kBoundsChange_Resizes) && - details_.source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { - sticky_size = kScreenEdgeInsetForTouchResize; - } else { - sticky_size = kScreenEdgeInset; - } - // |bounds| is in |window()->parent()|'s coordinates. - gfx::Rect bounds = CalculateBoundsForDrag(details_, location_in_parent); - if (window_state()->IsNormalShowState()) - AdjustBoundsForMainWindow(sticky_size, &bounds); - - if (bounds != window()->bounds()) { - if (!did_move_or_resize_) { - if (!details_.restore_bounds.IsEmpty()) - window_state()->ClearRestoreBounds(); - RestackWindows(); - } - did_move_or_resize_ = true; - } - - gfx::Point location_in_screen = location_in_parent; - wm::ConvertPointToScreen(window()->parent(), &location_in_screen); - - aura::Window* root = NULL; - gfx::Display display = - ScreenAsh::FindDisplayContainingPoint(location_in_screen); - // Track the last screen that the pointer was on to keep the snap phantom - // window there. - if (display.is_valid()) { - root = Shell::GetInstance()->display_controller()-> - GetRootWindowForDisplayId(display.id()); - } - if (!attached_windows_.empty()) - LayoutAttachedWindows(&bounds); - if (bounds != window()->bounds()) { - // SetBounds needs to be called to update the layout which affects where the - // phantom window is drawn. Keep track if the window was destroyed during - // the drag and quit early if so. - base::WeakPtr<WorkspaceWindowResizer> resizer( - weak_ptr_factory_.GetWeakPtr()); - window()->SetBounds(bounds); - if (!resizer) - return; - } - const bool in_original_root = !root || root == window()->GetRootWindow(); - // Hide a phantom window for snapping if the cursor is in another root window. - if (in_original_root) { - UpdateSnapPhantomWindow(location_in_parent, bounds); - } else { - snap_type_ = SNAP_NONE; - snap_phantom_window_controller_.reset(); - snap_sizer_.reset(); - SetDraggedWindowDocked(false); - } -} - -void WorkspaceWindowResizer::CompleteDrag(int event_flags) { - window_state()->set_bounds_changed_by_user(true); - snap_phantom_window_controller_.reset(); - if (!did_move_or_resize_ || details_.window_component != HTCAPTION) - return; - - bool snapped = false; - // When the window is not in the normal show state, we do not snap the window. - // This happens when the user minimizes or maximizes the window by keyboard - // shortcut while dragging it. If the window is the result of dragging a tab - // out of a maximized window, it's already in the normal show state when this - // is called, so it does not matter. - if (window_state()->IsNormalShowState() && - (window()->type() != aura::client::WINDOW_TYPE_PANEL || - !window_state()->panel_attached() || - dock_layout_->is_dragged_window_docked()) && - (snap_type_ == SNAP_LEFT || snap_type_ == SNAP_RIGHT)) { - if (!window_state()->HasRestoreBounds()) { - gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen( - window()->parent(), details_.initial_bounds_in_parent); - window_state()->SetRestoreBoundsInScreen( - details_.restore_bounds.IsEmpty() ? - initial_bounds : - details_.restore_bounds); - } - DCHECK(snap_sizer_); - if (window_state()->CanResize() && - !dock_layout_->is_dragged_window_docked()) { - snap_sizer_->SnapWindowToTargetBounds(); - snapped = true; - } - } - if (window_state()->IsSnapped() && !snapped) - window_state()->Restore(); -} - -void WorkspaceWindowResizer::RevertDrag() { - window_state()->set_bounds_changed_by_user(initial_bounds_changed_by_user_); - snap_phantom_window_controller_.reset(); - - if (!did_move_or_resize_) - return; - - window()->SetBounds(details_.initial_bounds_in_parent); - if (!details_.restore_bounds.IsEmpty()) { - window_state()->SetRestoreBoundsInScreen(details_.restore_bounds); - } - - if (details_.window_component == HTRIGHT) { - int last_x = details_.initial_bounds_in_parent.right(); - for (size_t i = 0; i < attached_windows_.size(); ++i) { - gfx::Rect bounds(attached_windows_[i]->bounds()); - bounds.set_x(last_x); - bounds.set_width(initial_size_[i]); - attached_windows_[i]->SetBounds(bounds); - last_x = attached_windows_[i]->bounds().right(); - } - } else { - int last_y = details_.initial_bounds_in_parent.bottom(); - for (size_t i = 0; i < attached_windows_.size(); ++i) { - gfx::Rect bounds(attached_windows_[i]->bounds()); - bounds.set_y(last_y); - bounds.set_height(initial_size_[i]); - attached_windows_[i]->SetBounds(bounds); - last_y = attached_windows_[i]->bounds().bottom(); - } - } -} - -aura::Window* WorkspaceWindowResizer::GetTarget() { - return details_.window; -} - -const gfx::Point& WorkspaceWindowResizer::GetInitialLocation() const { - return details_.initial_location_in_parent; -} - -WorkspaceWindowResizer::WorkspaceWindowResizer( - const Details& details, - const std::vector<aura::Window*>& attached_windows) - : details_(details), - attached_windows_(attached_windows), - did_lock_cursor_(false), - did_move_or_resize_(false), - initial_bounds_changed_by_user_( - details.window_state->bounds_changed_by_user()), - total_min_(0), - total_initial_size_(0), - snap_type_(SNAP_NONE), - num_mouse_moves_since_bounds_change_(0), - magnetism_window_(NULL), - weak_ptr_factory_(this) { - DCHECK(details_.is_resizable); - - // A mousemove should still show the cursor even if the window is - // being moved or resized with touch, so do not lock the cursor. - if (details.source != aura::client::WINDOW_MOVE_SOURCE_TOUCH) { - Shell* shell = Shell::GetInstance(); - shell->cursor_manager()->LockCursor(); - did_lock_cursor_ = true; - } - - aura::Window* dock_container = Shell::GetContainer( - window()->GetRootWindow(), kShellWindowId_DockedContainer); - dock_layout_ = static_cast<DockedWindowLayoutManager*>( - dock_container->layout_manager()); - - // Only support attaching to the right/bottom. - DCHECK(attached_windows_.empty() || - (details.window_component == HTRIGHT || - details.window_component == HTBOTTOM)); - - // TODO: figure out how to deal with window going off the edge. - - // Calculate sizes so that we can maintain the ratios if we need to resize. - int total_available = 0; - for (size_t i = 0; i < attached_windows_.size(); ++i) { - gfx::Size min(attached_windows_[i]->delegate()->GetMinimumSize()); - int initial_size = PrimaryAxisSize(attached_windows_[i]->bounds().size()); - initial_size_.push_back(initial_size); - // If current size is smaller than the min, use the current size as the min. - // This way we don't snap on resize. - int min_size = std::min(initial_size, - std::max(PrimaryAxisSize(min), kMinOnscreenSize)); - total_min_ += min_size; - total_initial_size_ += initial_size; - total_available += std::max(min_size, initial_size) - min_size; - } - instance_ = this; -} - -gfx::Rect WorkspaceWindowResizer::GetFinalBounds( - const gfx::Rect& bounds) const { - if (snap_phantom_window_controller_.get() && - snap_phantom_window_controller_->IsShowing()) { - return snap_phantom_window_controller_->bounds_in_screen(); - } - return bounds; -} - -void WorkspaceWindowResizer::LayoutAttachedWindows( - gfx::Rect* bounds) { - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); - int initial_size = PrimaryAxisSize(details_.initial_bounds_in_parent.size()); - int current_size = PrimaryAxisSize(bounds->size()); - int start = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); - int end = PrimaryAxisCoordinate(work_area.right(), work_area.bottom()); - - int delta = current_size - initial_size; - int available_size = end - start; - std::vector<int> sizes; - int leftovers = CalculateAttachedSizes(delta, available_size, &sizes); - - // leftovers > 0 means that the attached windows can't grow to compensate for - // the shrinkage of the main window. This line causes the attached windows to - // be moved so they are still flush against the main window, rather than the - // main window being prevented from shrinking. - leftovers = std::min(0, leftovers); - // Reallocate any leftover pixels back into the main window. This is - // necessary when, for example, the main window shrinks, but none of the - // attached windows can grow without exceeding their max size constraints. - // Adding the pixels back to the main window effectively prevents the main - // window from resizing too far. - if (details_.window_component == HTRIGHT) - bounds->set_width(bounds->width() + leftovers); - else - bounds->set_height(bounds->height() + leftovers); - - DCHECK_EQ(attached_windows_.size(), sizes.size()); - int last = PrimaryAxisCoordinate(bounds->right(), bounds->bottom()); - for (size_t i = 0; i < attached_windows_.size(); ++i) { - gfx::Rect attached_bounds(attached_windows_[i]->bounds()); - if (details_.window_component == HTRIGHT) { - attached_bounds.set_x(last); - attached_bounds.set_width(sizes[i]); - } else { - attached_bounds.set_y(last); - attached_bounds.set_height(sizes[i]); - } - attached_windows_[i]->SetBounds(attached_bounds); - last += sizes[i]; - } -} - -int WorkspaceWindowResizer::CalculateAttachedSizes( - int delta, - int available_size, - std::vector<int>* sizes) const { - std::vector<WindowSize> window_sizes; - CreateBucketsForAttached(&window_sizes); - - // How much we need to grow the attached by (collectively). - int grow_attached_by = 0; - if (delta > 0) { - // If the attached windows don't fit when at their initial size, we will - // have to shrink them by how much they overflow. - if (total_initial_size_ >= available_size) - grow_attached_by = available_size - total_initial_size_; - } else { - // If we're shrinking, we grow the attached so the total size remains - // constant. - grow_attached_by = -delta; - } - - int leftover_pixels = 0; - while (grow_attached_by != 0) { - int leftovers = GrowFairly(grow_attached_by, window_sizes); - if (leftovers == grow_attached_by) { - leftover_pixels = leftovers; - break; - } - grow_attached_by = leftovers; - } - - for (size_t i = 0; i < window_sizes.size(); ++i) - sizes->push_back(window_sizes[i].size()); - - return leftover_pixels; -} - -int WorkspaceWindowResizer::GrowFairly( - int pixels, - std::vector<WindowSize>& sizes) const { - bool shrinking = pixels < 0; - std::vector<WindowSize*> nonfull_windows; - for (size_t i = 0; i < sizes.size(); ++i) { - if (!sizes[i].is_at_capacity(shrinking)) - nonfull_windows.push_back(&sizes[i]); - } - std::vector<float> ratios; - CalculateGrowthRatios(nonfull_windows, &ratios); - - int remaining_pixels = pixels; - bool add_leftover_pixels_to_last = true; - for (size_t i = 0; i < nonfull_windows.size(); ++i) { - int grow_by = pixels * ratios[i]; - // Put any leftover pixels into the last window. - if (i == nonfull_windows.size() - 1 && add_leftover_pixels_to_last) - grow_by = remaining_pixels; - int remainder = nonfull_windows[i]->Add(grow_by); - int consumed = grow_by - remainder; - remaining_pixels -= consumed; - if (nonfull_windows[i]->is_at_capacity(shrinking) && remainder > 0) { - // Because this window overflowed, some of the pixels in - // |remaining_pixels| aren't there due to rounding errors. Rather than - // unfairly giving all those pixels to the last window, we refrain from - // allocating them so that this function can be called again to distribute - // the pixels fairly. - add_leftover_pixels_to_last = false; - } - } - return remaining_pixels; -} - -void WorkspaceWindowResizer::CalculateGrowthRatios( - const std::vector<WindowSize*>& sizes, - std::vector<float>* out_ratios) const { - DCHECK(out_ratios->empty()); - int total_value = 0; - for (size_t i = 0; i < sizes.size(); ++i) - total_value += sizes[i]->size(); - - for (size_t i = 0; i < sizes.size(); ++i) - out_ratios->push_back( - (static_cast<float>(sizes[i]->size())) / total_value); -} - -void WorkspaceWindowResizer::CreateBucketsForAttached( - std::vector<WindowSize>* sizes) const { - for (size_t i = 0; i < attached_windows_.size(); i++) { - int initial_size = initial_size_[i]; - aura::WindowDelegate* delegate = attached_windows_[i]->delegate(); - int min = PrimaryAxisSize(delegate->GetMinimumSize()); - int max = PrimaryAxisSize(delegate->GetMaximumSize()); - - sizes->push_back(WindowSize(initial_size, min, max)); - } -} - -void WorkspaceWindowResizer::MagneticallySnapToOtherWindows(gfx::Rect* bounds) { - if (UpdateMagnetismWindow(*bounds, kAllMagnetismEdges)) { - gfx::Point point = OriginForMagneticAttach( - ScreenAsh::ConvertRectToScreen(window()->parent(), *bounds), - magnetism_window_->GetBoundsInScreen(), - magnetism_edge_); - aura::client::GetScreenPositionClient(window()->GetRootWindow())-> - ConvertPointFromScreen(window()->parent(), &point); - bounds->set_origin(point); - } -} - -void WorkspaceWindowResizer::MagneticallySnapResizeToOtherWindows( - gfx::Rect* bounds) { - const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); - if (UpdateMagnetismWindow(*bounds, edges)) { - *bounds = ScreenAsh::ConvertRectFromScreen( - window()->parent(), - BoundsForMagneticResizeAttach( - ScreenAsh::ConvertRectToScreen(window()->parent(), *bounds), - magnetism_window_->GetBoundsInScreen(), - magnetism_edge_)); - } -} - -bool WorkspaceWindowResizer::UpdateMagnetismWindow(const gfx::Rect& bounds, - uint32 edges) { - // |bounds| are in coordinates of original window's parent. - gfx::Rect bounds_in_screen = - ScreenAsh::ConvertRectToScreen(window()->parent(), bounds); - MagnetismMatcher matcher(bounds_in_screen, edges); - - // If we snapped to a window then check it first. That way we don't bounce - // around when close to multiple edges. - if (magnetism_window_) { - if (window_tracker_.Contains(magnetism_window_) && - matcher.ShouldAttach(magnetism_window_->GetBoundsInScreen(), - &magnetism_edge_)) { - return true; - } - window_tracker_.Remove(magnetism_window_); - magnetism_window_ = NULL; - } - - // Avoid magnetically snapping windows that are not resizable. - // TODO(oshima): change this to window.type() == TYPE_NORMAL. - if (!window_state()->CanResize()) - return false; - - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - for (aura::Window::Windows::iterator iter = root_windows.begin(); - iter != root_windows.end(); ++iter) { - const aura::Window* root_window = *iter; - // Test all children from the desktop in each root window. - const aura::Window::Windows& children = Shell::GetContainer( - root_window, kShellWindowId_DefaultContainer)->children(); - for (aura::Window::Windows::const_reverse_iterator i = children.rbegin(); - i != children.rend() && !matcher.AreEdgesObscured(); ++i) { - wm::WindowState* other_state = wm::GetWindowState(*i); - if (other_state->window() == window() || - !other_state->window()->IsVisible() || - !other_state->IsNormalShowState() || - !other_state->CanResize()) { - continue; - } - if (matcher.ShouldAttach( - other_state->window()->GetBoundsInScreen(), &magnetism_edge_)) { - magnetism_window_ = other_state->window(); - window_tracker_.Add(magnetism_window_); - return true; - } - } - } - return false; -} - -void WorkspaceWindowResizer::AdjustBoundsForMainWindow( - int sticky_size, - gfx::Rect* bounds) { - gfx::Point last_mouse_location_in_screen = last_mouse_location_; - wm::ConvertPointToScreen(window()->parent(), &last_mouse_location_in_screen); - gfx::Display display = Shell::GetScreen()->GetDisplayNearestPoint( - last_mouse_location_in_screen); - gfx::Rect work_area = - ScreenAsh::ConvertRectFromScreen(window()->parent(), display.work_area()); - if (details_.window_component == HTCAPTION) { - // Adjust the bounds to the work area where the mouse cursor is located. - // Always keep kMinOnscreenHeight or the window height (whichever is less) - // on the bottom. - int max_y = work_area.bottom() - std::min(kMinOnscreenHeight, - bounds->height()); - if (bounds->y() > max_y) { - bounds->set_y(max_y); - } else if (bounds->y() <= work_area.y()) { - // Don't allow dragging above the top of the display until the mouse - // cursor reaches the work area above if any. - bounds->set_y(work_area.y()); - } - - if (sticky_size > 0) { - // Possibly stick to edge except when a mouse pointer is outside the - // work area. - if (!(display.work_area().Contains(last_mouse_location_in_screen) && - StickToWorkAreaOnMove(work_area, sticky_size, bounds))) { - MagneticallySnapToOtherWindows(bounds); - } - } - } else if (sticky_size > 0) { - MagneticallySnapResizeToOtherWindows(bounds); - if (!magnetism_window_ && sticky_size > 0) - StickToWorkAreaOnResize(work_area, sticky_size, bounds); - } - - if (attached_windows_.empty()) - return; - - if (details_.window_component == HTRIGHT) { - bounds->set_width(std::min(bounds->width(), - work_area.right() - total_min_ - bounds->x())); - } else { - DCHECK_EQ(HTBOTTOM, details_.window_component); - bounds->set_height(std::min(bounds->height(), - work_area.bottom() - total_min_ - bounds->y())); - } -} - -bool WorkspaceWindowResizer::StickToWorkAreaOnMove( - const gfx::Rect& work_area, - int sticky_size, - gfx::Rect* bounds) const { - const int left_edge = work_area.x(); - const int right_edge = work_area.right(); - const int top_edge = work_area.y(); - const int bottom_edge = work_area.bottom(); - bool updated = false; - if (ShouldStickToEdge(bounds->x() - left_edge, sticky_size)) { - bounds->set_x(left_edge); - updated = true; - } else if (ShouldStickToEdge(right_edge - bounds->right(), sticky_size)) { - bounds->set_x(right_edge - bounds->width()); - updated = true; - } - if (ShouldStickToEdge(bounds->y() - top_edge, sticky_size)) { - bounds->set_y(top_edge); - updated = true; - } else if (ShouldStickToEdge(bottom_edge - bounds->bottom(), sticky_size) && - bounds->height() < (bottom_edge - top_edge)) { - // 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 - // between snapping to top then bottom. - bounds->set_y(bottom_edge - bounds->height()); - updated = true; - } - return updated; -} - -void WorkspaceWindowResizer::StickToWorkAreaOnResize( - const gfx::Rect& work_area, - int sticky_size, - gfx::Rect* bounds) const { - const uint32 edges = WindowComponentToMagneticEdge(details_.window_component); - const int left_edge = work_area.x(); - const int right_edge = work_area.right(); - const int top_edge = work_area.y(); - const int bottom_edge = work_area.bottom(); - if (edges & MAGNETISM_EDGE_TOP && - ShouldStickToEdge(bounds->y() - top_edge, sticky_size)) { - bounds->set_height(bounds->bottom() - top_edge); - bounds->set_y(top_edge); - } - if (edges & MAGNETISM_EDGE_LEFT && - ShouldStickToEdge(bounds->x() - left_edge, sticky_size)) { - bounds->set_width(bounds->right() - left_edge); - bounds->set_x(left_edge); - } - if (edges & MAGNETISM_EDGE_BOTTOM && - ShouldStickToEdge(bottom_edge - bounds->bottom(), sticky_size)) { - bounds->set_height(bottom_edge - bounds->y()); - } - if (edges & MAGNETISM_EDGE_RIGHT && - ShouldStickToEdge(right_edge - bounds->right(), sticky_size)) { - bounds->set_width(right_edge - bounds->x()); - } -} - -int WorkspaceWindowResizer::PrimaryAxisSize(const gfx::Size& size) const { - return PrimaryAxisCoordinate(size.width(), size.height()); -} - -int WorkspaceWindowResizer::PrimaryAxisCoordinate(int x, int y) const { - switch (details_.window_component) { - case HTRIGHT: - return x; - case HTBOTTOM: - return y; - default: - NOTREACHED(); - } - return 0; -} - -void WorkspaceWindowResizer::UpdateSnapPhantomWindow(const gfx::Point& location, - const gfx::Rect& bounds) { - if (!did_move_or_resize_ || details_.window_component != HTCAPTION) - return; - - SnapType last_type = snap_type_; - snap_type_ = GetSnapType(location); - if (snap_type_ == SNAP_NONE || snap_type_ != last_type) { - snap_phantom_window_controller_.reset(); - snap_sizer_.reset(); - if (snap_type_ == SNAP_NONE) { - SetDraggedWindowDocked(false); - return; - } - } - const bool can_dock = dock_layout_->CanDockWindow(window(), snap_type_); - const bool can_snap = window_state()->CanSnap(); - if (!can_snap && !can_dock) { - snap_type_ = SNAP_NONE; - snap_phantom_window_controller_.reset(); - snap_sizer_.reset(); - SetDraggedWindowDocked(false); - return; - } - SnapSizer::Edge edge = (snap_type_ == SNAP_LEFT) ? - SnapSizer::LEFT_EDGE : SnapSizer::RIGHT_EDGE; - if (!snap_sizer_) { - snap_sizer_.reset(new SnapSizer(window_state(), - location, - edge, - internal::SnapSizer::OTHER_INPUT)); - } else { - snap_sizer_->Update(location); - } - - // Update phantom window with snapped or docked guide bounds. - // Windows that cannot be snapped or are less wide than kMaxDockWidth can get - // docked without going through a snapping sequence. - gfx::Rect phantom_bounds; - if (can_snap && - (!can_dock || - window()->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth)) - phantom_bounds = snap_sizer_->target_bounds(); - const bool should_dock = can_dock && - (phantom_bounds.IsEmpty() || - snap_sizer_->end_of_sequence() || - dock_layout_->is_dragged_window_docked()); - SetDraggedWindowDocked(should_dock); - snap_type_ = GetSnapType(location); - if (dock_layout_->is_dragged_window_docked()) { - phantom_bounds = ScreenAsh::ConvertRectFromScreen( - window()->parent(), dock_layout_->dragged_bounds()); - } - - if (phantom_bounds.IsEmpty()) { - snap_phantom_window_controller_.reset(); - return; - } - - if (!snap_phantom_window_controller_) { - snap_phantom_window_controller_.reset( - new PhantomWindowController(window())); - } - snap_phantom_window_controller_->Show(ScreenAsh::ConvertRectToScreen( - window()->parent(), phantom_bounds)); -} - -void WorkspaceWindowResizer::RestackWindows() { - if (attached_windows_.empty()) - return; - // Build a map from index in children to window, returning if there is a - // window with a different parent. - typedef std::map<size_t, aura::Window*> IndexToWindowMap; - IndexToWindowMap map; - aura::Window* parent = window()->parent(); - const aura::Window::Windows& windows(parent->children()); - map[std::find(windows.begin(), windows.end(), window()) - - windows.begin()] = window(); - for (std::vector<aura::Window*>::const_iterator i = - attached_windows_.begin(); i != attached_windows_.end(); ++i) { - if ((*i)->parent() != parent) - return; - size_t index = - std::find(windows.begin(), windows.end(), *i) - windows.begin(); - map[index] = *i; - } - - // Reorder the windows starting at the topmost. - parent->StackChildAtTop(map.rbegin()->second); - for (IndexToWindowMap::const_reverse_iterator i = map.rbegin(); - i != map.rend(); ) { - aura::Window* window = i->second; - ++i; - if (i != map.rend()) - parent->StackChildBelow(i->second, window); - } -} - -SnapType WorkspaceWindowResizer::GetSnapType( - const gfx::Point& location) const { - // TODO: this likely only wants total display area, not the area of a single - // display. - gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window())); - if (details_.source == aura::client::WINDOW_MOVE_SOURCE_TOUCH) { - // Increase tolerance for touch-snapping near the screen edges. This is only - // necessary when the work area left or right edge is same as screen edge. - gfx::Rect display_bounds(ScreenAsh::GetDisplayBoundsInParent(window())); - int inset_left = 0; - if (area.x() == display_bounds.x()) - inset_left = kScreenEdgeInsetForTouchResize; - int inset_right = 0; - if (area.right() == display_bounds.right()) - inset_right = kScreenEdgeInsetForTouchResize; - area.Inset(inset_left, 0, inset_right, 0); - } - if (location.x() <= area.x()) - return SNAP_LEFT; - if (location.x() >= area.right() - 1) - return SNAP_RIGHT; - return SNAP_NONE; -} - -void WorkspaceWindowResizer::SetDraggedWindowDocked(bool should_dock) { - if (should_dock && - dock_layout_->GetAlignmentOfWindow(window()) != DOCKED_ALIGNMENT_NONE) { - if (!dock_layout_->is_dragged_window_docked()) { - window_state()->set_bounds_changed_by_user(false); - dock_layout_->DockDraggedWindow(window()); - } - } else { - if (dock_layout_->is_dragged_window_docked()) { - dock_layout_->UndockDraggedWindow(); - window_state()->set_bounds_changed_by_user(true); - } - } -} - -} // namespace internal -} // namespace ash diff --git a/chromium/ash/wm/workspace/workspace_window_resizer.h b/chromium/ash/wm/workspace/workspace_window_resizer.h deleted file mode 100644 index 015e96ddb36..00000000000 --- a/chromium/ash/wm/workspace/workspace_window_resizer.h +++ /dev/null @@ -1,236 +0,0 @@ -// 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 "ash/wm/workspace/snap_types.h" -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" -#include "ui/aura/window_tracker.h" - -namespace ash { -namespace wm { -class WindowState; -} - -namespace internal { - -class DockedWindowLayoutManager; -class PhantomWindowController; -class SnapSizer; -class WindowSize; - -// 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; - - // Distance in pixels that the cursor must move past an edge for a window - // to move or resize beyond that edge. - static const int kStickyDistancePixels; - - virtual ~WorkspaceWindowResizer(); - - static WorkspaceWindowResizer* Create( - aura::Window* window, - const gfx::Point& location_in_parent, - int window_component, - aura::client::WindowMoveSource source, - const std::vector<aura::Window*>& attached_windows); - - // 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; - virtual const gfx::Point& GetInitialLocation() const OVERRIDE; - - private: - WorkspaceWindowResizer(const Details& details, - const std::vector<aura::Window*>& attached_windows); - - private: - friend class WorkspaceWindowResizerTest; - - // 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(gfx::Rect* bounds); - - // Calculates the new sizes of the attached windows, given that the main - // window has been resized (along the primary axis) by |delta|. - // |available_size| is the maximum length of the space that the attached - // windows are allowed to occupy (ie: the distance between the right/bottom - // edge of the primary window and the right/bottom of the desktop area). - // Populates |sizes| with the desired sizes of the attached windows, and - // returns the number of pixels that couldn't be allocated to the attached - // windows (due to min/max size constraints). - // Note the return value can be positive or negative, a negative value - // indicating that that many pixels couldn't be removed from the attached - // windows. - int CalculateAttachedSizes( - int delta, - int available_size, - std::vector<int>* sizes) const; - - // Divides |amount| evenly between |sizes|. If |amount| is negative it - // indicates how many pixels |sizes| should be shrunk by. - // Returns how many pixels failed to be allocated/removed from |sizes|. - int GrowFairly(int amount, std::vector<WindowSize>& sizes) const; - - // Calculate the ratio of pixels that each WindowSize in |sizes| should - // receive when growing or shrinking. - void CalculateGrowthRatios(const std::vector<WindowSize*>& sizes, - std::vector<float>* out_ratios) const; - - // Adds a WindowSize to |sizes| for each attached window. - void CreateBucketsForAttached(std::vector<WindowSize>* sizes) const; - - // If possible snaps the window to a neary window. Updates |bounds| if there - // was a close enough window. - void MagneticallySnapToOtherWindows(gfx::Rect* bounds); - - // If possible snaps the resize to a neary window. Updates |bounds| if there - // was a close enough window. - void MagneticallySnapResizeToOtherWindows(gfx::Rect* bounds); - - // Finds the neareset window to magentically snap to. Updates - // |magnetism_window_| and |magnetism_edge_| appropriately. |edges| is a - // bitmask of the MagnetismEdges to match again. Returns true if a match is - // found. - bool UpdateMagnetismWindow(const gfx::Rect& bounds, uint32 edges); - - // Adjusts the bounds of the window: magnetically snapping, ensuring the - // window has enough on screen... |snap_size| is the distance from an edge of - // the work area before the window is snapped. A value of 0 results in no - // snapping. - void AdjustBoundsForMainWindow(int snap_size, gfx::Rect* bounds); - - // Stick the window bounds to the work area during a move. - bool StickToWorkAreaOnMove(const gfx::Rect& work_area, - int sticky_size, - gfx::Rect* bounds) const; - - // Stick the window bounds to the work area during a resize. - void StickToWorkAreaOnResize(const gfx::Rect& work_area, - int sticky_size, - gfx::Rect* bounds) 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); - - // 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; - - // Docks the dragged window if |should_dock| and the window can be docked. - // Undocks the window if |should_dock| is false. - void SetDraggedWindowDocked(bool should_dock); - - aura::Window* window() const { return details_.window; } - - wm::WindowState* window_state() { return details_.window_state; } - - const Details details_; - - const std::vector<aura::Window*> attached_windows_; - - bool did_lock_cursor_; - - // Set to true once Drag() is invoked and the bounds of the window change. - bool did_move_or_resize_; - - // True if the window initially had |bounds_changed_by_user_| set in state. - bool initial_bounds_changed_by_user_; - - // The initial size of each of the windows in |attached_windows_| along the - // primary axis. - std::vector<int> initial_size_; - - // Sum of the minimum sizes of the attached windows. - 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_; - - // 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_; - - // Window the drag has magnetically attached to. - aura::Window* magnetism_window_; - - // Used to verify |magnetism_window_| is still valid. - aura::WindowTracker window_tracker_; - - // If |magnetism_window_| is non-NULL this indicates how the two windows - // should attach. - MatchedEdge magnetism_edge_; - - // Dock container window layout manager. - DockedWindowLayoutManager* dock_layout_; - - // Used to determine if this has been deleted during a drag such as when a tab - // gets dragged into another browser window. - base::WeakPtrFactory<WorkspaceWindowResizer> weak_ptr_factory_; - - // Current instance for use by the WorkspaceWindowResizerTest. - static WorkspaceWindowResizer* instance_; - - DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizer); -}; - -} // namespace internal -} // namespace ash - -#endif // ASH_WM_WORKSPACE_WINDOW_RESIZER_H_ diff --git a/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc b/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc deleted file mode 100644 index 599c4ea98e8..00000000000 --- a/chromium/ash/wm/workspace/workspace_window_resizer_unittest.cc +++ /dev/null @@ -1,2027 +0,0 @@ -// 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. - -#include "ash/wm/workspace/workspace_window_resizer.h" - -#include "ash/ash_constants.h" -#include "ash/ash_switches.h" -#include "ash/display/display_manager.h" -#include "ash/root_window_controller.h" -#include "ash/screen_ash.h" -#include "ash/shelf/shelf_layout_manager.h" -#include "ash/shell.h" -#include "ash/shell_window_ids.h" -#include "ash/test/ash_test_base.h" -#include "ash/wm/window_state.h" -#include "ash/wm/window_util.h" -#include "ash/wm/workspace/phantom_window_controller.h" -#include "ash/wm/workspace/snap_sizer.h" -#include "ash/wm/workspace_controller.h" -#include "base/command_line.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/stringprintf.h" -#include "ui/aura/client/aura_constants.h" -#include "ui/aura/root_window.h" -#include "ui/aura/test/event_generator.h" -#include "ui/aura/test/test_window_delegate.h" -#include "ui/base/hit_test.h" -#include "ui/gfx/insets.h" -#include "ui/gfx/screen.h" -#include "ui/views/widget/widget.h" - -namespace gfx { - -// Class to provide access to SlideAnimation internals for testing. -// TODO: this should be next to SlideAnimation, not here. -class SlideAnimation::TestApi { - public: - explicit TestApi(SlideAnimation* animation) : animation_(animation) {} - - void SetStartTime(base::TimeTicks ticks) { - animation_->SetStartTime(ticks); - } - - void Step(base::TimeTicks ticks) { - animation_->Step(ticks); - } - - void RunTillComplete() { - SetStartTime(base::TimeTicks()); - Step(base::TimeTicks() + - base::TimeDelta::FromMilliseconds(animation_->GetSlideDuration())); - EXPECT_EQ(1.0, animation_->GetCurrentValue()); - } - - private: - SlideAnimation* animation_; - - DISALLOW_COPY_AND_ASSIGN(TestApi); -}; - -} - -namespace ash { -namespace internal { -namespace { - -const int kRootHeight = 600; - -// A simple window delegate that returns the specified min size. -class TestWindowDelegate : public aura::test::TestWindowDelegate { - public: - TestWindowDelegate() { - } - virtual ~TestWindowDelegate() {} - - void set_min_size(const gfx::Size& size) { - min_size_ = size; - } - - void set_max_size(const gfx::Size& size) { - max_size_ = size; - } - - private: - // Overridden from aura::Test::TestWindowDelegate: - virtual gfx::Size GetMinimumSize() const OVERRIDE { - return min_size_; - } - - virtual gfx::Size GetMaximumSize() const OVERRIDE { - return max_size_; - } - - gfx::Size min_size_; - gfx::Size max_size_; - - DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate); -}; - -} // namespace - -class WorkspaceWindowResizerTest : public test::AshTestBase { - public: - WorkspaceWindowResizerTest() : workspace_resizer_(NULL) {} - virtual ~WorkspaceWindowResizerTest() {} - - virtual void SetUp() OVERRIDE { - AshTestBase::SetUp(); - UpdateDisplay(base::StringPrintf("800x%d", kRootHeight)); - - aura::Window* root = Shell::GetPrimaryRootWindow(); - gfx::Rect root_bounds(root->bounds()); -#if defined(OS_WIN) - // RootWindow and Display can't resize on Windows Ash. - // http://crbug.com/165962 - EXPECT_EQ(kRootHeight, root_bounds.height()); -#endif - EXPECT_EQ(800, root_bounds.width()); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - window_.reset(new aura::Window(&delegate_)); - window_->SetType(aura::client::WINDOW_TYPE_NORMAL); - window_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(window_.get()); - window_->set_id(1); - - window2_.reset(new aura::Window(&delegate2_)); - window2_->SetType(aura::client::WINDOW_TYPE_NORMAL); - window2_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(window2_.get()); - window2_->set_id(2); - - window3_.reset(new aura::Window(&delegate3_)); - window3_->SetType(aura::client::WINDOW_TYPE_NORMAL); - window3_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(window3_.get()); - window3_->set_id(3); - - window4_.reset(new aura::Window(&delegate4_)); - window4_->SetType(aura::client::WINDOW_TYPE_NORMAL); - window4_->Init(ui::LAYER_NOT_DRAWN); - ParentWindowInPrimaryRootWindow(window4_.get()); - window4_->set_id(4); - } - - virtual void TearDown() OVERRIDE { - window_.reset(); - window2_.reset(); - window3_.reset(); - window4_.reset(); - touch_resize_window_.reset(); - AshTestBase::TearDown(); - } - - // Returns a string identifying the z-order of each of the known child windows - // of |parent|. The returned string constains the id of the known windows and - // is ordered from topmost to bottomost windows. - std::string WindowOrderAsString(aura::Window* parent) const { - std::string result; - const aura::Window::Windows& windows = parent->children(); - for (aura::Window::Windows::const_reverse_iterator i = windows.rbegin(); - i != windows.rend(); ++i) { - if (*i == window_ || *i == window2_ || *i == window3_) { - if (!result.empty()) - result += " "; - result += base::IntToString((*i)->id()); - } - } - return result; - } - - protected: - WindowResizer* CreateResizerForTest( - aura::Window* window, - const gfx::Point& point_in_parent, - int window_component) { - WindowResizer* resizer = CreateWindowResizer( - window, - point_in_parent, - window_component, - aura::client::WINDOW_MOVE_SOURCE_MOUSE).release(); - workspace_resizer_ = WorkspaceWindowResizer::instance_; - return resizer; - } - - PhantomWindowController* snap_phantom_window_controller() const { - return workspace_resizer_->snap_phantom_window_controller_.get(); - } - - gfx::Point CalculateDragPoint(const WindowResizer& resizer, - int delta_x, - int delta_y) const { - gfx::Point location = resizer.GetInitialLocation(); - location.set_x(location.x() + delta_x); - location.set_y(location.y() + delta_y); - return location; - } - - std::vector<aura::Window*> empty_windows() const { - return std::vector<aura::Window*>(); - } - - internal::ShelfLayoutManager* shelf_layout_manager() { - return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager(); - } - - void InitTouchResizeWindow(const gfx::Rect& bounds, int window_component) { - touch_resize_delegate_.set_window_component(window_component); - touch_resize_window_.reset( - CreateTestWindowInShellWithDelegate(&touch_resize_delegate_, 0, - bounds)); - gfx::Insets mouse_outer_insets(-ash::kResizeOutsideBoundsSize, - -ash::kResizeOutsideBoundsSize, - -ash::kResizeOutsideBoundsSize, - -ash::kResizeOutsideBoundsSize); - gfx::Insets touch_outer_insets = mouse_outer_insets.Scale( - ash::kResizeOutsideBoundsScaleForTouch); - touch_resize_window_->SetHitTestBoundsOverrideOuter(mouse_outer_insets, - touch_outer_insets); - } - - // Simulate running the animation. - void RunAnimationTillComplete(gfx::SlideAnimation* animation) { - gfx::SlideAnimation::TestApi test_api(animation); - test_api.RunTillComplete(); - } - - TestWindowDelegate delegate_; - TestWindowDelegate delegate2_; - TestWindowDelegate delegate3_; - TestWindowDelegate delegate4_; - scoped_ptr<aura::Window> window_; - scoped_ptr<aura::Window> window2_; - scoped_ptr<aura::Window> window3_; - scoped_ptr<aura::Window> window4_; - - TestWindowDelegate touch_resize_delegate_; - scoped_ptr<aura::Window> touch_resize_window_; - WorkspaceWindowResizer* workspace_resizer_; - - private: - DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTest); -}; - -class WorkspaceWindowResizerTestSticky : public WorkspaceWindowResizerTest { - public: - WorkspaceWindowResizerTestSticky() {} - virtual ~WorkspaceWindowResizerTestSticky() {} - - virtual void SetUp() OVERRIDE { - CommandLine::ForCurrentProcess()->AppendSwitch( - ash::switches::kAshEnableStickyEdges); - WorkspaceWindowResizerTest::SetUp(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTestSticky); -}; - -// Assertions around attached window resize dragging from the right with 2 -// windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_2) { - window_->SetBounds(gfx::Rect(0, 300, 400, 300)); - window2_->SetBounds(gfx::Rect(400, 200, 100, 200)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the right, which should expand w1 and push w2. - resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0); - EXPECT_EQ("0,300 500x300", window_->bounds().ToString()); - EXPECT_EQ("500,200 100x200", window2_->bounds().ToString()); - - // Push off the screen, w2 should be resized to its min. - delegate2_.set_min_size(gfx::Size(20, 20)); - resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0); - EXPECT_EQ("0,300 780x300", window_->bounds().ToString()); - EXPECT_EQ("780,200 20x200", window2_->bounds().ToString()); - - // Move back to 100 and verify w2 gets its original size. - resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0); - EXPECT_EQ("0,300 500x300", window_->bounds().ToString()); - EXPECT_EQ("500,200 100x200", window2_->bounds().ToString()); - - // Revert and make sure everything moves back. - resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0); - resizer->RevertDrag(); - EXPECT_EQ("0,300 400x300", window_->bounds().ToString()); - EXPECT_EQ("400,200 100x200", window2_->bounds().ToString()); -} - -// Assertions around collapsing and expanding. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_Compress) { - window_->SetBounds(gfx::Rect( 0, 300, 400, 300)); - window2_->SetBounds(gfx::Rect(400, 200, 100, 200)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the left, which should expand w2 and collapse w1. - resizer->Drag(CalculateDragPoint(*resizer, -100, 10), 0); - EXPECT_EQ("0,300 300x300", window_->bounds().ToString()); - EXPECT_EQ("300,200 200x200", window2_->bounds().ToString()); - - // Collapse all the way to w1's min. - delegate_.set_min_size(gfx::Size(20, 20)); - resizer->Drag(CalculateDragPoint(*resizer, -800, 20), 0); - EXPECT_EQ("0,300 20x300", window_->bounds().ToString()); - EXPECT_EQ("20,200 480x200", window2_->bounds().ToString()); - - // Move 100 to the left. - resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0); - EXPECT_EQ("0,300 500x300", window_->bounds().ToString()); - EXPECT_EQ("500,200 100x200", window2_->bounds().ToString()); - - // Back to -100. - resizer->Drag(CalculateDragPoint(*resizer, -100, 20), 0); - EXPECT_EQ("0,300 300x300", window_->bounds().ToString()); - EXPECT_EQ("300,200 200x200", window2_->bounds().ToString()); -} - -// Assertions around attached window resize dragging from the right with 3 -// windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3) { - window_->SetBounds(gfx::Rect( 100, 300, 200, 300)); - window2_->SetBounds(gfx::Rect(300, 300, 150, 200)); - window3_->SetBounds(gfx::Rect(450, 300, 100, 200)); - delegate2_.set_min_size(gfx::Size(52, 50)); - delegate3_.set_min_size(gfx::Size(38, 50)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the right, which should expand w1 and push w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0); - EXPECT_EQ("100,300 300x300", window_->bounds().ToString()); - EXPECT_EQ("400,300 150x200", window2_->bounds().ToString()); - EXPECT_EQ("550,300 100x200", window3_->bounds().ToString()); - - // Move it 300, things should compress. - resizer->Drag(CalculateDragPoint(*resizer, 300, -10), 0); - EXPECT_EQ("100,300 500x300", window_->bounds().ToString()); - EXPECT_EQ("600,300 120x200", window2_->bounds().ToString()); - EXPECT_EQ("720,300 80x200", window3_->bounds().ToString()); - - // Move it so much the last two end up at their min. - resizer->Drag(CalculateDragPoint(*resizer, 800, 50), 0); - EXPECT_EQ("100,300 610x300", window_->bounds().ToString()); - EXPECT_EQ("710,300 52x200", window2_->bounds().ToString()); - EXPECT_EQ("762,300 38x200", window3_->bounds().ToString()); - - // Revert and make sure everything moves back. - resizer->RevertDrag(); - EXPECT_EQ("100,300 200x300", window_->bounds().ToString()); - EXPECT_EQ("300,300 150x200", window2_->bounds().ToString()); - EXPECT_EQ("450,300 100x200", window3_->bounds().ToString()); -} - -// Assertions around attached window resizing (collapsing and expanding) with -// 3 windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3_Compress) { - window_->SetBounds(gfx::Rect( 100, 300, 200, 300)); - window2_->SetBounds(gfx::Rect(300, 300, 200, 200)); - window3_->SetBounds(gfx::Rect(450, 300, 100, 200)); - delegate2_.set_min_size(gfx::Size(52, 50)); - delegate3_.set_min_size(gfx::Size(38, 50)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it -100 to the right, which should collapse w1 and expand w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0); - EXPECT_EQ("100,300 100x300", window_->bounds().ToString()); - EXPECT_EQ("200,300 266x200", window2_->bounds().ToString()); - EXPECT_EQ("466,300 134x200", window3_->bounds().ToString()); - - // Move it 100 to the right. - resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0); - EXPECT_EQ("100,300 300x300", window_->bounds().ToString()); - EXPECT_EQ("400,300 200x200", window2_->bounds().ToString()); - EXPECT_EQ("600,300 100x200", window3_->bounds().ToString()); - - // 100 to the left again. - resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0); - EXPECT_EQ("100,300 100x300", window_->bounds().ToString()); - EXPECT_EQ("200,300 266x200", window2_->bounds().ToString()); - EXPECT_EQ("466,300 134x200", window3_->bounds().ToString()); -} - -// Assertions around collapsing and expanding from the bottom. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_Compress) { - window_->SetBounds(gfx::Rect( 0, 100, 400, 300)); - window2_->SetBounds(gfx::Rect(400, 400, 100, 200)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it up 100, which should expand w2 and collapse w1. - resizer->Drag(CalculateDragPoint(*resizer, 10, -100), 0); - EXPECT_EQ("0,100 400x200", window_->bounds().ToString()); - EXPECT_EQ("400,300 100x300", window2_->bounds().ToString()); - - // Collapse all the way to w1's min. - delegate_.set_min_size(gfx::Size(20, 20)); - resizer->Drag(CalculateDragPoint(*resizer, 20, -800), 0); - EXPECT_EQ("0,100 400x20", window_->bounds().ToString()); - EXPECT_EQ("400,120 100x480", window2_->bounds().ToString()); - - // Move 100 down. - resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0); - EXPECT_EQ("0,100 400x400", window_->bounds().ToString()); - EXPECT_EQ("400,500 100x100", window2_->bounds().ToString()); - - // Back to -100. - resizer->Drag(CalculateDragPoint(*resizer, 20, -100), 0); - EXPECT_EQ("0,100 400x200", window_->bounds().ToString()); - EXPECT_EQ("400,300 100x300", window2_->bounds().ToString()); -} - -// Assertions around attached window resize dragging from the bottom with 2 -// windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_2) { - window_->SetBounds(gfx::Rect( 0, 50, 400, 200)); - window2_->SetBounds(gfx::Rect(0, 250, 200, 100)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the bottom, which should expand w1 and push w2. - resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0); - EXPECT_EQ("0,50 400x300", window_->bounds().ToString()); - EXPECT_EQ("0,350 200x100", window2_->bounds().ToString()); - - // Push off the screen, w2 should be resized to its min. - delegate2_.set_min_size(gfx::Size(20, 20)); - resizer->Drag(CalculateDragPoint(*resizer, 50, 820), 0); - EXPECT_EQ("0,50 400x530", window_->bounds().ToString()); - EXPECT_EQ("0,580 200x20", window2_->bounds().ToString()); - - // Move back to 100 and verify w2 gets its original size. - resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0); - EXPECT_EQ("0,50 400x300", window_->bounds().ToString()); - EXPECT_EQ("0,350 200x100", window2_->bounds().ToString()); - - // Revert and make sure everything moves back. - resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0); - resizer->RevertDrag(); - EXPECT_EQ("0,50 400x200", window_->bounds().ToString()); - EXPECT_EQ("0,250 200x100", window2_->bounds().ToString()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_AttachedResize_BOTTOM_3 DISABLED_AttachedResize_BOTTOM_3 -#else -#define MAYBE_AttachedResize_BOTTOM_3 AttachedResize_BOTTOM_3 -#endif - -// Assertions around attached window resize dragging from the bottom with 3 -// windows. -TEST_F(WorkspaceWindowResizerTest, MAYBE_AttachedResize_BOTTOM_3) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - window_->SetBounds(gfx::Rect( 300, 100, 300, 200)); - window2_->SetBounds(gfx::Rect(300, 300, 200, 150)); - window3_->SetBounds(gfx::Rect(300, 450, 200, 100)); - delegate2_.set_min_size(gfx::Size(50, 52)); - delegate3_.set_min_size(gfx::Size(50, 38)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 down, which should expand w1 and push w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, -10, 100), 0); - EXPECT_EQ("300,100 300x300", window_->bounds().ToString()); - EXPECT_EQ("300,400 200x150", window2_->bounds().ToString()); - EXPECT_EQ("300,550 200x100", window3_->bounds().ToString()); - - // Move it 296 things should compress. - resizer->Drag(CalculateDragPoint(*resizer, -10, 296), 0); - EXPECT_EQ("300,100 300x496", window_->bounds().ToString()); - EXPECT_EQ("300,596 200x123", window2_->bounds().ToString()); - EXPECT_EQ("300,719 200x81", window3_->bounds().ToString()); - - // Move it so much everything ends up at its min. - resizer->Drag(CalculateDragPoint(*resizer, 50, 798), 0); - EXPECT_EQ("300,100 300x610", window_->bounds().ToString()); - EXPECT_EQ("300,710 200x52", window2_->bounds().ToString()); - EXPECT_EQ("300,762 200x38", window3_->bounds().ToString()); - - // Revert and make sure everything moves back. - resizer->RevertDrag(); - EXPECT_EQ("300,100 300x200", window_->bounds().ToString()); - EXPECT_EQ("300,300 200x150", window2_->bounds().ToString()); - EXPECT_EQ("300,450 200x100", window3_->bounds().ToString()); -} - -// Assertions around attached window resizing (collapsing and expanding) with -// 3 windows. -TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_3_Compress) { - window_->SetBounds(gfx::Rect( 0, 0, 200, 200)); - window2_->SetBounds(gfx::Rect(10, 200, 200, 200)); - window3_->SetBounds(gfx::Rect(20, 400, 100, 100)); - delegate2_.set_min_size(gfx::Size(52, 50)); - delegate3_.set_min_size(gfx::Size(38, 50)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 up, which should collapse w1 and expand w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0); - EXPECT_EQ("0,0 200x100", window_->bounds().ToString()); - EXPECT_EQ("10,100 200x266", window2_->bounds().ToString()); - EXPECT_EQ("20,366 100x134", window3_->bounds().ToString()); - - // Move it 100 down. - resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0); - EXPECT_EQ("0,0 200x300", window_->bounds().ToString()); - EXPECT_EQ("10,300 200x200", window2_->bounds().ToString()); - EXPECT_EQ("20,500 100x100", window3_->bounds().ToString()); - - // 100 up again. - resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0); - EXPECT_EQ("0,0 200x100", window_->bounds().ToString()); - EXPECT_EQ("10,100 200x266", window2_->bounds().ToString()); - EXPECT_EQ("20,366 100x134", window3_->bounds().ToString()); -} - -// Tests that touch-dragging a window does not lock the mouse cursor -// and therefore shows the cursor on a mousemove. -TEST_F(WorkspaceWindowResizerTest, MouseMoveWithTouchDrag) { - window_->SetBounds(gfx::Rect(0, 300, 400, 300)); - window2_->SetBounds(gfx::Rect(400, 200, 100, 200)); - - Shell* shell = Shell::GetInstance(); - aura::test::EventGenerator generator(window_->GetRootWindow()); - - // The cursor should not be locked initially. - EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked()); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_TOUCH, windows)); - ASSERT_TRUE(resizer.get()); - - // Creating a WorkspaceWindowResizer should not lock the cursor. - EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked()); - - // The cursor should be hidden after touching the screen and - // starting a drag. - EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible()); - generator.PressTouch(); - resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0); - EXPECT_FALSE(shell->cursor_manager()->IsCursorVisible()); - EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked()); - - // Moving the mouse should show the cursor. - generator.MoveMouseBy(1, 1); - EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible()); - EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked()); - - resizer->RevertDrag(); -} - -// Assertions around dragging to the left/right edge of the screen. -TEST_F(WorkspaceWindowResizerTest, Edge) { - if (!SupportsHostWindowResize()) - return; - - // Resize host window to force insets update. - UpdateDisplay("800x700"); - // TODO(varkha): Insets are reset after every drag because of - // http://crbug.com/292238. - // Window is wide enough not to get docked right away. - window_->SetBounds(gfx::Rect(20, 30, 400, 60)); - wm::WindowState* window_state = wm::GetWindowState(window_.get()); - - { - internal::SnapSizer snap_sizer(window_state, gfx::Point(), - internal::SnapSizer::LEFT_EDGE, internal::SnapSizer::OTHER_INPUT); - gfx::Rect expected_bounds(snap_sizer.target_bounds()); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 10), 0); - resizer->CompleteDrag(0); - - EXPECT_EQ(expected_bounds.ToString(), window_->bounds().ToString()); - ASSERT_TRUE(window_state->HasRestoreBounds()); - EXPECT_EQ("20,30 400x60", - window_state->GetRestoreBoundsInScreen().ToString()); - } - // Try the same with the right side. - { - internal::SnapSizer snap_sizer(window_state, gfx::Point(), - internal::SnapSizer::RIGHT_EDGE, internal::SnapSizer::OTHER_INPUT); - gfx::Rect expected_bounds(snap_sizer.target_bounds()); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0); - resizer->CompleteDrag(0); - EXPECT_EQ(expected_bounds.ToString(), window_->bounds().ToString()); - ASSERT_TRUE(window_state->HasRestoreBounds()); - EXPECT_EQ("20,30 400x60", - window_state->GetRestoreBoundsInScreen().ToString()); - } - - // Test if the restore bounds is correct in multiple displays. - if (!SupportsMultipleDisplays()) - return; - - // Restore the window to clear snapped state. - window_state->Restore(); - - UpdateDisplay("800x600,500x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - // Window is wide enough not to get docked right away. - window_->SetBoundsInScreen(gfx::Rect(800, 10, 400, 60), - ScreenAsh::GetSecondaryDisplay()); - EXPECT_EQ(root_windows[1], window_->GetRootWindow()); - { - EXPECT_EQ("800,10 400x60", window_->GetBoundsInScreen().ToString()); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 499, 0), 0); - int bottom = - ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_.get()).bottom(); - resizer->CompleteDrag(0); - // With the resolution of 500x600 we will hit in this case the 50% screen - // size setting. - // TODO(varkha): Insets are updated because of http://crbug.com/292238 - EXPECT_EQ("250,0 250x" + base::IntToString(bottom), - window_->bounds().ToString()); - EXPECT_EQ("800,10 400x60", - window_state->GetRestoreBoundsInScreen().ToString()); - } -} - -// Check that non resizable windows will not get resized. -TEST_F(WorkspaceWindowResizerTest, NonResizableWindows) { - window_->SetBounds(gfx::Rect(20, 30, 50, 60)); - window_->SetProperty(aura::client::kCanResizeKey, false); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -20, 0), 0); - resizer->CompleteDrag(0); - EXPECT_EQ("0,30 50x60", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, CancelSnapPhantom) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("800x600,800x600"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); - - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity()); - { - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - EXPECT_FALSE(snap_phantom_window_controller()); - - // The pointer is on the edge but not shared. The snap phantom window - // controller should be non-NULL. - resizer->Drag(CalculateDragPoint(*resizer, 799, 0), 0); - EXPECT_TRUE(snap_phantom_window_controller()); - - // Move the cursor across the edge. Now the snap phantom window controller - // should be canceled. - resizer->Drag(CalculateDragPoint(*resizer, 800, 0), 0); - EXPECT_FALSE(snap_phantom_window_controller()); - } -} - -// Verifies windows are correctly restacked when reordering multiple windows. -TEST_F(WorkspaceWindowResizerTest, RestackAttached) { - window_->SetBounds(gfx::Rect( 0, 0, 200, 300)); - window2_->SetBounds(gfx::Rect(200, 0, 100, 200)); - window3_->SetBounds(gfx::Rect(300, 0, 100, 100)); - - { - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the right, which should expand w1 and push w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0); - - // 2 should be topmost since it's initially the highest in the stack. - EXPECT_EQ("2 1 3", WindowOrderAsString(window_->parent())); - } - - { - std::vector<aura::Window*> windows; - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window2_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the right, which should expand w1 and push w2 and w3. - resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0); - - // 2 should be topmost since it's initially the highest in the stack. - EXPECT_EQ("2 3 1", WindowOrderAsString(window_->parent())); - } -} - -// Makes sure we don't allow dragging below the work area. -TEST_F(WorkspaceWindowResizerTest, DontDragOffBottom) { - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0)); - - ASSERT_EQ(1, Shell::GetScreen()->GetNumDisplays()); - - window_->SetBounds(gfx::Rect(100, 200, 300, 400)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600), 0); - int expected_y = - kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10; - EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400", - window_->bounds().ToString()); -} - -// Makes sure we don't allow dragging on the work area with multidisplay. -TEST_F(WorkspaceWindowResizerTest, DontDragOffBottomWithMultiDisplay) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("800x600,800x600"); - ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays()); - - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0)); - - // Positions the secondary display at the bottom the primary display. - Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays( - ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 0)); - - { - window_->SetBounds(gfx::Rect(100, 200, 300, 20)); - DCHECK_LT(window_->bounds().height(), - WorkspaceWindowResizer::kMinOnscreenHeight); - // Drag down avoiding dragging along the edge as that would side-snap. - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(10, 0), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0); - int expected_y = kRootHeight - window_->bounds().height() - 10; - // When the mouse cursor is in the primary display, the window cannot move - // on non-work area but can get all the way towards the bottom, - // restricted only by the window height. - EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x20", - window_->bounds().ToString()); - // Revert the drag in order to not remember the restore bounds. - resizer->RevertDrag(); - } - - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0)); - { - window_->SetBounds(gfx::Rect(100, 200, 300, 400)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(10, 0), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag down avoiding dragging along the edge as that would side-snap. - resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0); - int expected_y = - kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10; - // When the mouse cursor is in the primary display, the window cannot move - // on non-work area with kMinOnscreenHeight margin. - EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400", - window_->bounds().ToString()); - resizer->CompleteDrag(0); - } - - { - window_->SetBounds(gfx::Rect(100, 200, 300, 400)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), window_->bounds().origin(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag down avoiding getting stuck against the shelf on the bottom screen. - resizer->Drag(CalculateDragPoint(*resizer, 0, 500), 0); - // The window can move to the secondary display beyond non-work area of - // the primary display. - EXPECT_EQ("100,700 300x400", window_->bounds().ToString()); - resizer->CompleteDrag(0); - } -} - -// Makes sure we don't allow dragging off the top of the work area. -TEST_F(WorkspaceWindowResizerTest, DontDragOffTop) { - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(10, 0, 0, 0)); - - window_->SetBounds(gfx::Rect(100, 200, 300, 400)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, -600), 0); - EXPECT_EQ("100,10 300x400", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, ResizeBottomOutsideWorkArea) { - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); - - window_->SetBounds(gfx::Rect(100, 200, 300, 380)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOP)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 8, 0), 0); - 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<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(pixels_to_left_border, 0), HTRIGHT)); - 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<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(window_x, 0), HTLEFT)); - 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<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(0, bottom - delta_to_bottom), HTTOP)); - 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 that 'outside' check of the resizer take into account the extended -// desktop in case of repositions. -TEST_F(WorkspaceWindowResizerTest, DragWindowOutsideRightToSecondaryDisplay) { - // Only primary display. Changes the window position to fit within the - // display. - 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<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(window_x, 0), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0); - EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) + - ",100 " + - base::IntToString(window_width) + - "x380", window_->bounds().ToString()); - - if (!SupportsMultipleDisplays()) - return; - - // With secondary display. Operation itself is same but doesn't change - // the position because the window is still within the secondary display. - UpdateDisplay("1000x600,600x400"); - Shell::GetInstance()->SetDisplayWorkAreaInsets( - Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0)); - window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380)); - resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0); - EXPECT_EQ(base::IntToString(window_x + window_width) + - ",100 " + - base::IntToString(window_width) + - "x380", window_->bounds().ToString()); -} - -// Verifies snapping to edges works. -TEST_F(WorkspaceWindowResizerTest, SnapToEdge) { - Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> - SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - // Click 50px to the right so that the mouse pointer does not leave the - // workspace ensuring sticky behavior. - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), - window_->bounds().origin() + gfx::Vector2d(50, 0), - HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move to an x-coordinate of 15, which should not snap. - resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0); - // An x-coordinate of 7 should snap. - resizer->Drag(CalculateDragPoint(*resizer, 7 - 96, 0), 0); - EXPECT_EQ("0,112 320x160", window_->bounds().ToString()); - // Move to -15, should still snap to 0. - resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0); - EXPECT_EQ("0,112 320x160", window_->bounds().ToString()); - // At -32 should move past snap points. - resizer->Drag(CalculateDragPoint(*resizer, -32 - 96, 0), 0); - EXPECT_EQ("-32,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, -33 - 96, 0), 0); - EXPECT_EQ("-33,112 320x160", window_->bounds().ToString()); - - // Right side should similarly snap. - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0); - EXPECT_EQ("465,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 7, 0), 0); - EXPECT_EQ("480,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0); - EXPECT_EQ("480,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 32, 0), 0); - EXPECT_EQ("512,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 33, 0), 0); - EXPECT_EQ("513,112 320x160", window_->bounds().ToString()); - - // And the bottom should snap too. - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 - 7), 0); - EXPECT_EQ("96,437 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0); - EXPECT_EQ("96,437 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 32), 0); - EXPECT_EQ("96,470 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 33), 0); - EXPECT_EQ("96,471 320x160", window_->bounds().ToString()); - - // And the top should snap too. - resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 20), 0); - EXPECT_EQ("96,20 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 7), 0); - EXPECT_EQ("96,0 320x160", window_->bounds().ToString()); - - // And bottom/left should snap too. - resizer->Drag( - CalculateDragPoint(*resizer, 7 - 96, 600 - 160 - 112 - 3 - 7), 0); - EXPECT_EQ("0,437 320x160", window_->bounds().ToString()); - resizer->Drag( - CalculateDragPoint(*resizer, -15 - 96, 600 - 160 - 112 - 3 + 15), 0); - EXPECT_EQ("0,437 320x160", window_->bounds().ToString()); - // should move past snap points. - resizer->Drag( - CalculateDragPoint(*resizer, -32 - 96, 600 - 160 - 112 - 2 + 32), 0); - EXPECT_EQ("-32,470 320x160", window_->bounds().ToString()); - resizer->Drag( - CalculateDragPoint(*resizer, -33 - 96, 600 - 160 - 112 - 2 + 33), 0); - EXPECT_EQ("-33,471 320x160", window_->bounds().ToString()); - - // No need to test dragging < 0 as we force that to 0. -} - -// Verifies a resize snap when dragging TOPLEFT. -TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -98, -199), 0); - EXPECT_EQ("0,0 120x230", window_->bounds().ToString()); -} - -// Verifies a resize snap when dragging TOPRIGHT. -TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag( - CalculateDragPoint(*resizer, work_area.right() - 120 - 1, -199), 0); - EXPECT_EQ(100, window_->bounds().x()); - EXPECT_EQ(work_area.y(), window_->bounds().y()); - EXPECT_EQ(work_area.right() - 100, window_->bounds().width()); - EXPECT_EQ(230, window_->bounds().height()); -} - -// Verifies a resize snap when dragging BOTTOMRIGHT. -TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag( - CalculateDragPoint(*resizer, work_area.right() - 120 - 1, - work_area.bottom() - 220 - 2), 0); - EXPECT_EQ(100, window_->bounds().x()); - EXPECT_EQ(200, window_->bounds().y()); - EXPECT_EQ(work_area.right() - 100, window_->bounds().width()); - EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height()); -} - -// Verifies a resize snap when dragging BOTTOMLEFT. -TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag( - CalculateDragPoint(*resizer, -98, work_area.bottom() - 220 - 2), 0); - EXPECT_EQ(0, window_->bounds().x()); - EXPECT_EQ(200, window_->bounds().y()); - EXPECT_EQ(120, window_->bounds().width()); - EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height()); -} - -// Verifies sticking to edges works. -TEST_F(WorkspaceWindowResizerTestSticky, StickToEdge) { - Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> - SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - // Click 50px to the right so that the mouse pointer does not leave the - // workspace ensuring sticky behavior. - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), - window_->bounds().origin() + gfx::Vector2d(50, 0), - HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move to an x-coordinate of 15, which should not stick. - resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0); - // Move to -15, should still stick to 0. - resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0); - EXPECT_EQ("0,112 320x160", window_->bounds().ToString()); - // At -100 should move past edge. - resizer->Drag(CalculateDragPoint(*resizer, -100 - 96, 0), 0); - EXPECT_EQ("-100,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, -101 - 96, 0), 0); - EXPECT_EQ("-101,112 320x160", window_->bounds().ToString()); - - // Right side should similarly stick. - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0); - EXPECT_EQ("465,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0); - EXPECT_EQ("480,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 100, 0), 0); - EXPECT_EQ("580,112 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 101, 0), 0); - EXPECT_EQ("581,112 320x160", window_->bounds().ToString()); - - // And the bottom should stick too. - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0); - EXPECT_EQ("96,437 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 100), 0); - EXPECT_EQ("96,538 320x160", window_->bounds().ToString()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 101), 0); - EXPECT_EQ("96,539 320x160", window_->bounds().ToString()); - - // No need to test dragging < 0 as we force that to 0. -} - -// Verifies not sticking to edges when a mouse pointer is outside of work area. -TEST_F(WorkspaceWindowResizerTestSticky, NoStickToEdgeWhenOutside) { - Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()-> - SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); - window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move to an x-coordinate of 15, which should not stick. - resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0); - // Move to -15, should still stick to 0. - resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0); - EXPECT_EQ("-15,112 320x160", window_->bounds().ToString()); -} - -// Verifies a resize sticks when dragging TOPLEFT. -TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_TOPLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -15 - 100, -15 -200), 0); - EXPECT_EQ("0,0 120x230", window_->bounds().ToString()); -} - -// Verifies a resize sticks when dragging TOPRIGHT. -TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_TOPRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, work_area.right() - 100 + 20, - -200 - 15), 0); - EXPECT_EQ(100, window_->bounds().x()); - EXPECT_EQ(work_area.y(), window_->bounds().y()); - EXPECT_EQ(work_area.right() - 100, window_->bounds().width()); - EXPECT_EQ(230, window_->bounds().height()); -} - -// Verifies a resize snap when dragging BOTTOMRIGHT. -TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_BOTTOMRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, work_area.right() - 100 - 20 + 15, - work_area.bottom() - 200 - 30 + 15), 0); - EXPECT_EQ(100, window_->bounds().x()); - EXPECT_EQ(200, window_->bounds().y()); - EXPECT_EQ(work_area.right() - 100, window_->bounds().width()); - EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height()); -} - -// Verifies a resize snap when dragging BOTTOMLEFT. -TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_BOTTOMLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( - window_.get())); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, -15 - 100, - work_area.bottom() - 200 - 30 + 15), 0); - EXPECT_EQ(0, window_->bounds().x()); - EXPECT_EQ(200, window_->bounds().y()); - EXPECT_EQ(120, window_->bounds().width()); - EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height()); -} - -TEST_F(WorkspaceWindowResizerTest, CtrlDragResizeToExactPosition) { - window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - // Resize the right bottom to add 10 in width, 12 in height. - resizer->Drag(CalculateDragPoint(*resizer, 10, 12), ui::EF_CONTROL_DOWN); - // Both bottom and right sides to resize to exact size requested. - EXPECT_EQ("96,112 330x172", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, CtrlCompleteDragMoveToExactPosition) { - window_->SetBounds(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Ctrl + drag the window to new poistion by adding (10, 12) to its origin, - // the window should move to the exact position. - resizer->Drag(CalculateDragPoint(*resizer, 10, 12), 0); - resizer->CompleteDrag(ui::EF_CONTROL_DOWN); - EXPECT_EQ("106,124 320x160", window_->bounds().ToString()); -} - -// Verifies that a dragged window will restore to its pre-maximized size. -TEST_F(WorkspaceWindowResizerTest, RestoreToPreMaximizeCoordinates) { - window_->SetBounds(gfx::Rect(0, 0, 1000, 1000)); - wm::WindowState* window_state = wm::GetWindowState(window_.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag the window to new position by adding (10, 10) to original point, - // the window should get restored. - resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0); - resizer->CompleteDrag(0); - EXPECT_EQ("10,10 320x160", window_->bounds().ToString()); - // The restore rectangle should get cleared as well. - EXPECT_FALSE(window_state->HasRestoreBounds()); -} - -// Verifies that a dragged window will restore to its pre-maximized size. -TEST_F(WorkspaceWindowResizerTest, RevertResizeOperation) { - const gfx::Rect initial_bounds(0, 0, 200, 400); - window_->SetBounds(initial_bounds); - - wm::WindowState* window_state = wm::GetWindowState(window_.get()); - window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Drag the window to new poistion by adding (180, 16) to original point, - // the window should get restored. - resizer->Drag(CalculateDragPoint(*resizer, 180, 16), 0); - resizer->RevertDrag(); - EXPECT_EQ(initial_bounds.ToString(), window_->bounds().ToString()); - EXPECT_EQ("96,112 320x160", - window_state->GetRestoreBoundsInScreen().ToString()); -} - -// Check that only usable sizes get returned by the resizer. -TEST_F(WorkspaceWindowResizerTest, MagneticallyAttach) { - window_->SetBounds(gfx::Rect(10, 10, 20, 30)); - window2_->SetBounds(gfx::Rect(150, 160, 25, 20)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move |window| one pixel to the left of |window2|. Should snap to right and - // top. - resizer->Drag(CalculateDragPoint(*resizer, 119, 145), 0); - EXPECT_EQ("130,160 20x30", window_->bounds().ToString()); - - // Move |window| one pixel to the right of |window2|. Should snap to left and - // top. - resizer->Drag(CalculateDragPoint(*resizer, 164, 145), 0); - EXPECT_EQ("175,160 20x30", window_->bounds().ToString()); - - // Move |window| one pixel above |window2|. Should snap to top and left. - resizer->Drag(CalculateDragPoint(*resizer, 142, 119), 0); - EXPECT_EQ("150,130 20x30", window_->bounds().ToString()); - - // Move |window| one pixel above the bottom of |window2|. Should snap to - // bottom and left. - resizer->Drag(CalculateDragPoint(*resizer, 142, 169), 0); - EXPECT_EQ("150,180 20x30", window_->bounds().ToString()); -} - -// The following variants verify magnetic snapping during resize when dragging a -// particular edge. -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOP) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->SetBounds(gfx::Rect(99, 179, 10, 20)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOP)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,199 20x31", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->SetBounds(gfx::Rect(99, 179, 10, 20)); - window2_->Show(); - - { - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("99,199 21x31", window_->bounds().ToString()); - resizer->RevertDrag(); - } - - { - window2_->SetBounds(gfx::Rect(88, 201, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("98,201 22x29", window_->bounds().ToString()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->Show(); - - { - window2_->SetBounds(gfx::Rect(111, 179, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,199 21x31", window_->bounds().ToString()); - resizer->RevertDrag(); - } - - { - window2_->SetBounds(gfx::Rect(121, 199, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTTOPRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,199 21x31", window_->bounds().ToString()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_RIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->SetBounds(gfx::Rect(121, 199, 10, 20)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,200 21x30", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMRIGHT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->Show(); - - { - window2_->SetBounds(gfx::Rect(122, 212, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,200 22x32", window_->bounds().ToString()); - resizer->RevertDrag(); - } - - { - window2_->SetBounds(gfx::Rect(111, 233, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,200 21x33", window_->bounds().ToString()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOM) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->SetBounds(gfx::Rect(111, 233, 10, 20)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOM)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("100,200 20x33", window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMLEFT) { - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->Show(); - - { - window2_->SetBounds(gfx::Rect(99, 231, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("99,200 21x31", window_->bounds().ToString()); - resizer->RevertDrag(); - } - - { - window2_->SetBounds(gfx::Rect(89, 209, 10, 20)); - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("99,200 21x29", window_->bounds().ToString()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_LEFT) { - window2_->SetBounds(gfx::Rect(89, 209, 10, 20)); - window_->SetBounds(gfx::Rect(100, 200, 20, 30)); - window2_->Show(); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTLEFT)); - ASSERT_TRUE(resizer.get()); - resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0); - EXPECT_EQ("99,200 21x30", window_->bounds().ToString()); -} - -// Test that the user user moved window flag is getting properly set. -TEST_F(WorkspaceWindowResizerTest, CheckUserWindowManagedFlags) { - window_->SetBounds(gfx::Rect( 0, 50, 400, 200)); - - std::vector<aura::Window*> no_attached_windows; - // Check that an abort doesn't change anything. - { - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the bottom. - resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0); - EXPECT_EQ("0,150 400x200", window_->bounds().ToString()); - resizer->RevertDrag(); - - EXPECT_FALSE(wm::GetWindowState(window_.get())->bounds_changed_by_user()); - } - - // Check that a completed move / size does change the user coordinates. - { - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - // Move it 100 to the bottom. - resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0); - EXPECT_EQ("0,150 400x200", window_->bounds().ToString()); - resizer->CompleteDrag(0); - EXPECT_TRUE(wm::GetWindowState(window_.get())->bounds_changed_by_user()); - } -} - -// Test that a window with a specified max size doesn't exceed it when dragged. -TEST_F(WorkspaceWindowResizerTest, TestMaxSizeEnforced) { - window_->SetBounds(gfx::Rect(0, 0, 400, 300)); - delegate_.set_max_size(gfx::Size(401, 301)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0); - EXPECT_EQ(401, window_->bounds().width()); - EXPECT_EQ(301, window_->bounds().height()); -} - -// Test that a window with a specified max width doesn't restrict its height. -TEST_F(WorkspaceWindowResizerTest, TestPartialMaxSizeEnforced) { - window_->SetBounds(gfx::Rect(0, 0, 400, 300)); - delegate_.set_max_size(gfx::Size(401, 0)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTBOTTOMRIGHT)); - resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0); - EXPECT_EQ(401, window_->bounds().width()); - EXPECT_EQ(302, window_->bounds().height()); -} - -// Test that a window with a specified max size can't be snapped. -TEST_F(WorkspaceWindowResizerTest, PhantomSnapMaxSize) { - { - // With max size not set we get a phantom window controller for dragging off - // the right hand side. - // Make the window wider than maximum docked width. - window_->SetBounds(gfx::Rect(0, 0, 400, 200)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - EXPECT_FALSE(snap_phantom_window_controller()); - resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0); - EXPECT_TRUE(snap_phantom_window_controller()); - resizer->RevertDrag(); - } - { - // With max size defined, we get no phantom window for snapping but we still - // get a phantom window (docking guide). - window_->SetBounds(gfx::Rect(0, 0, 400, 200)); - delegate_.set_max_size(gfx::Size(400, 200)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0); - if (switches::UseDockedWindows()) - EXPECT_TRUE(snap_phantom_window_controller()); - else - EXPECT_FALSE(snap_phantom_window_controller()); - resizer->RevertDrag(); - } - { - // With max size defined, we get no phantom window for snapping. - window_->SetBounds(gfx::Rect(0, 0, 400, 200)); - delegate_.set_max_size(gfx::Size(400, 200)); - // With min size defined, we get no phantom window for docking. - delegate_.set_min_size(gfx::Size(400, 200)); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0); - EXPECT_FALSE(snap_phantom_window_controller()); - resizer->RevertDrag(); - } -} - -TEST_F(WorkspaceWindowResizerTest, DontRewardRightmostWindowForOverflows) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Four 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - window4_->SetBounds(gfx::Rect(400, 100, 100, 100)); - delegate2_.set_max_size(gfx::Size(101, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 51 to the left, which should contract w1 and expand w2-4. - // w2 will hit its max size straight away, and in doing so will leave extra - // pixels that a naive implementation may award to the rightmost window. A - // fair implementation will give 25 pixels to each of the other windows. - resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0); - EXPECT_EQ("100,100 49x100", window_->bounds().ToString()); - EXPECT_EQ("149,100 101x100", window2_->bounds().ToString()); - EXPECT_EQ("250,100 125x100", window3_->bounds().ToString()); - EXPECT_EQ("375,100 125x100", window4_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, DontExceedMaxWidth) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Four 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - window4_->SetBounds(gfx::Rect(400, 100, 100, 100)); - delegate2_.set_max_size(gfx::Size(101, 0)); - delegate3_.set_max_size(gfx::Size(101, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 52 to the left, which should contract w1 and expand w2-4. - resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0); - EXPECT_EQ("100,100 48x100", window_->bounds().ToString()); - EXPECT_EQ("148,100 101x100", window2_->bounds().ToString()); - EXPECT_EQ("249,100 101x100", window3_->bounds().ToString()); - EXPECT_EQ("350,100 150x100", window4_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, DontExceedMaxHeight) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Four 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(100, 200, 100, 100)); - window3_->SetBounds(gfx::Rect(100, 300, 100, 100)); - window4_->SetBounds(gfx::Rect(100, 400, 100, 100)); - delegate2_.set_max_size(gfx::Size(0, 101)); - delegate3_.set_max_size(gfx::Size(0, 101)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 52 up, which should contract w1 and expand w2-4. - resizer->Drag(CalculateDragPoint(*resizer, 0, -52), 0); - EXPECT_EQ("100,100 100x48", window_->bounds().ToString()); - EXPECT_EQ("100,148 100x101", window2_->bounds().ToString()); - EXPECT_EQ("100,249 100x101", window3_->bounds().ToString()); - EXPECT_EQ("100,350 100x150", window4_->bounds().ToString()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_DontExceedMinHeight DISABLED_DontExceedMinHeight -#else -#define MAYBE_DontExceedMinHeight DontExceedMinHeight -#endif - -TEST_F(WorkspaceWindowResizerTest, MAYBE_DontExceedMinHeight) { - UpdateDisplay("600x500"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Four 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(100, 200, 100, 100)); - window3_->SetBounds(gfx::Rect(100, 300, 100, 100)); - window4_->SetBounds(gfx::Rect(100, 400, 100, 100)); - delegate2_.set_min_size(gfx::Size(0, 99)); - delegate3_.set_min_size(gfx::Size(0, 99)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTBOTTOM, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 52 down, which should expand w1 and contract w2-4. - resizer->Drag(CalculateDragPoint(*resizer, 0, 52), 0); - EXPECT_EQ("100,100 100x152", window_->bounds().ToString()); - EXPECT_EQ("100,252 100x99", window2_->bounds().ToString()); - EXPECT_EQ("100,351 100x99", window3_->bounds().ToString()); - EXPECT_EQ("100,450 100x50", window4_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, DontExpandRightmostPastMaxWidth) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Three 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - delegate3_.set_max_size(gfx::Size(101, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 51 to the left, which should contract w1 and expand w2-3. - resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0); - EXPECT_EQ("100,100 49x100", window_->bounds().ToString()); - EXPECT_EQ("149,100 150x100", window2_->bounds().ToString()); - EXPECT_EQ("299,100 101x100", window3_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MoveAttachedWhenGrownToMaxSize) { - UpdateDisplay("600x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Three 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - delegate2_.set_max_size(gfx::Size(101, 0)); - delegate3_.set_max_size(gfx::Size(101, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 52 to the left, which should contract w1 and expand and move w2-3. - resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0); - EXPECT_EQ("100,100 48x100", window_->bounds().ToString()); - EXPECT_EQ("148,100 101x100", window2_->bounds().ToString()); - EXPECT_EQ("249,100 101x100", window3_->bounds().ToString()); -} - -#if defined(OS_WIN) -// RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962 -#define MAYBE_MainWindowHonoursMaxWidth DISABLED_MainWindowHonoursMaxWidth -#else -#define MAYBE_MainWindowHonoursMaxWidth MainWindowHonoursMaxWidth -#endif - -TEST_F(WorkspaceWindowResizerTest, MAYBE_MainWindowHonoursMaxWidth) { - UpdateDisplay("400x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Three 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - delegate_.set_max_size(gfx::Size(102, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - windows.push_back(window4_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 50 to the right, which should expand w1 and contract w2-3, as they - // won't fit in the root window in their original sizes. - resizer->Drag(CalculateDragPoint(*resizer, 50, 0), 0); - EXPECT_EQ("100,100 102x100", window_->bounds().ToString()); - EXPECT_EQ("202,100 99x100", window2_->bounds().ToString()); - EXPECT_EQ("301,100 99x100", window3_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, MainWindowHonoursMinWidth) { - UpdateDisplay("400x800"); - aura::Window* root = Shell::GetPrimaryRootWindow(); - Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets()); - - // Three 100x100 windows flush against eachother, starting at 100,100. - window_->SetBounds(gfx::Rect( 100, 100, 100, 100)); - window2_->SetBounds(gfx::Rect(200, 100, 100, 100)); - window3_->SetBounds(gfx::Rect(300, 100, 100, 100)); - delegate_.set_min_size(gfx::Size(98, 0)); - - std::vector<aura::Window*> windows; - windows.push_back(window2_.get()); - windows.push_back(window3_.get()); - scoped_ptr<WorkspaceWindowResizer> resizer(WorkspaceWindowResizer::Create( - window_.get(), gfx::Point(), HTRIGHT, - aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows)); - ASSERT_TRUE(resizer.get()); - // Move it 50 to the left, which should contract w1 and expand w2-3. - resizer->Drag(CalculateDragPoint(*resizer, -50, 0), 0); - EXPECT_EQ("100,100 98x100", window_->bounds().ToString()); - EXPECT_EQ("198,100 101x100", window2_->bounds().ToString()); - EXPECT_EQ("299,100 101x100", window3_->bounds().ToString()); -} - -// The following variants test that windows are resized correctly to the edges -// of the screen using touch, when touch point is off of the window border. -TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_RIGHT) { - shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); - - InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTRIGHT); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - touch_resize_window_.get()); - - // Drag out of the right border a bit and check if the border is aligned with - // the touch point. - generator.GestureScrollSequence(gfx::Point(715, kRootHeight / 2), - gfx::Point(725, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 625, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag more, but stop before being snapped to the edge. - generator.GestureScrollSequence(gfx::Point(725, kRootHeight / 2), - gfx::Point(760, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 660, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag even more to snap to the edge. - generator.GestureScrollSequence(gfx::Point(760, kRootHeight / 2), - gfx::Point(775, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 700, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_LEFT) { - shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); - - InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTLEFT); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - touch_resize_window_.get()); - - // Drag out of the left border a bit and check if the border is aligned with - // the touch point. - generator.GestureScrollSequence(gfx::Point(85, kRootHeight / 2), - gfx::Point(75, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(75, 100, 625, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag more, but stop before being snapped to the edge. - generator.GestureScrollSequence(gfx::Point(75, kRootHeight / 2), - gfx::Point(40, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(40, 100, 660, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag even more to snap to the edge. - generator.GestureScrollSequence(gfx::Point(40, kRootHeight / 2), - gfx::Point(25, kRootHeight / 2), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(0, 100, 700, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_TOP) { - shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); - - InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTTOP); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - touch_resize_window_.get()); - - // Drag out of the top border a bit and check if the border is aligned with - // the touch point. - generator.GestureScrollSequence(gfx::Point(400, 85), - gfx::Point(400, 75), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 75, 600, kRootHeight - 175).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag more, but stop before being snapped to the edge. - generator.GestureScrollSequence(gfx::Point(400, 75), - gfx::Point(400, 40), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 40, 600, kRootHeight - 140).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag even more to snap to the edge. - generator.GestureScrollSequence(gfx::Point(400, 40), - gfx::Point(400, 25), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 0, 600, kRootHeight - 100).ToString(), - touch_resize_window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_BOTTOM) { - shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); - - InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTBOTTOM); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(), - touch_resize_window_->bounds().ToString()); - - aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - touch_resize_window_.get()); - - // Drag out of the bottom border a bit and check if the border is aligned with - // the touch point. - generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 85), - gfx::Point(400, kRootHeight - 75), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 175).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag more, but stop before being snapped to the edge. - generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 75), - gfx::Point(400, kRootHeight - 40), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 140).ToString(), - touch_resize_window_->bounds().ToString()); - // Drag even more to snap to the edge. - generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 40), - gfx::Point(400, kRootHeight - 25), - base::TimeDelta::FromMilliseconds(10), - 5); - EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 100).ToString(), - touch_resize_window_->bounds().ToString()); -} - -TEST_F(WorkspaceWindowResizerTest, PhantomWindowShow) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("500x400,500x400"); - window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), - Shell::GetScreen()->GetPrimaryDisplay()); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_EQ(root_windows[0], window_->GetRootWindow()); - - scoped_ptr<WindowResizer> resizer(CreateResizerForTest( - window_.get(), gfx::Point(), HTCAPTION)); - ASSERT_TRUE(resizer.get()); - EXPECT_FALSE(snap_phantom_window_controller()); - - // The pointer is on the edge but not shared. The snap phantom window - // controller should be non-NULL. - resizer->Drag(CalculateDragPoint(*resizer, -1, 0), 0); - EXPECT_TRUE(snap_phantom_window_controller()); - PhantomWindowController* phantom_controller(snap_phantom_window_controller()); - - // phantom widget only in the left screen. - phantom_controller->Show(gfx::Rect(100, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_FALSE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - - // Move phantom widget into the right screen. Test that 2 widgets got created. - phantom_controller->Show(gfx::Rect(600, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_TRUE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_start_->GetNativeWindow()-> - GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget only in the right screen. Start widget should close. - phantom_controller->Show(gfx::Rect(700, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_FALSE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget into the left screen. Start widget should open. - phantom_controller->Show(gfx::Rect(100, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_TRUE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_start_->GetNativeWindow()-> - GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget while in the left screen. Start widget should close. - phantom_controller->Show(gfx::Rect(200, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_FALSE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget spanning both screens with most of the window in the - // right screen. Two widgets are created. - phantom_controller->Show(gfx::Rect(495, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_TRUE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_start_->GetNativeWindow()-> - GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Move phantom widget back into the left screen. Phantom widgets should swap. - phantom_controller->Show(gfx::Rect(200, 100, 50, 60)); - EXPECT_TRUE(phantom_controller->phantom_widget_); - EXPECT_TRUE(phantom_controller->phantom_widget_start_); - EXPECT_EQ( - root_windows[0], - phantom_controller->phantom_widget_->GetNativeWindow()->GetRootWindow()); - EXPECT_EQ( - root_windows[1], - phantom_controller->phantom_widget_start_->GetNativeWindow()-> - GetRootWindow()); - RunAnimationTillComplete(phantom_controller->animation_.get()); - - // Hide phantom controller. Both widgets should close. - phantom_controller->Hide(); - EXPECT_FALSE(phantom_controller->phantom_widget_); - EXPECT_FALSE(phantom_controller->phantom_widget_start_); -} - -} // namespace internal -} // namespace ash |