Commit 888ca287 authored by pkotwicz@chromium.org's avatar pkotwicz@chromium.org

Fix crash when dragging a half width window to split view from overview mode

BUG=405957
TEST=SplitViewControllerTest.SplitModeActivation

Review URL: https://codereview.chromium.org/488153003

Cr-Commit-Position: refs/heads/master@{#291400}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@291400 0039d316-1c4b-4281-b951-d872f2087c98
parent a55581ad
...@@ -164,6 +164,8 @@ ...@@ -164,6 +164,8 @@
'test/test_app_model_builder.h', 'test/test_app_model_builder.h',
'test/test_screen_manager_delegate.cc', 'test/test_screen_manager_delegate.cc',
'test/test_screen_manager_delegate.h', 'test/test_screen_manager_delegate.h',
'wm/test/window_manager_impl_test_api.cc',
'wm/test/window_manager_impl_test_api.h',
], ],
}, },
{ {
......
...@@ -20,6 +20,21 @@ ...@@ -20,6 +20,21 @@
namespace athena { namespace athena {
namespace {
// Returns a target transform which is suitable for animating a windows's
// bounds.
gfx::Transform GetTargetTransformForBoundsAnimation(const gfx::Rect& from,
const gfx::Rect& to) {
gfx::Transform transform;
transform.Translate(to.x() - from.x(), to.y() - from.y());
transform.Scale(to.width() / static_cast<float>(from.width()),
to.height() / static_cast<float>(from.height()));
return transform;
}
} // namespace
SplitViewController::SplitViewController( SplitViewController::SplitViewController(
aura::Window* container, aura::Window* container,
WindowListProvider* window_list_provider) WindowListProvider* window_list_provider)
...@@ -113,6 +128,20 @@ void SplitViewController::DeactivateSplitMode() { ...@@ -113,6 +128,20 @@ void SplitViewController::DeactivateSplitMode() {
left_window_ = right_window_ = NULL; left_window_ = right_window_ = NULL;
} }
gfx::Rect SplitViewController::GetLeftTargetBounds() {
gfx::Rect work_area =
gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area();
return gfx::Rect(0, 0, container_->bounds().width() / 2, work_area.height());
}
gfx::Rect SplitViewController::GetRightTargetBounds() {
gfx::Rect work_area =
gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area();
int container_width = container_->bounds().width();
return gfx::Rect(
container_width / 2, 0, container_width / 2, work_area.height());
}
void SplitViewController::UpdateLayout(bool animate) { void SplitViewController::UpdateLayout(bool animate) {
if (!left_window_) if (!left_window_)
return; return;
...@@ -121,19 +150,16 @@ void SplitViewController::UpdateLayout(bool animate) { ...@@ -121,19 +150,16 @@ void SplitViewController::UpdateLayout(bool animate) {
gfx::Transform right_transform; gfx::Transform right_transform;
int container_width = container_->GetBoundsInScreen().width(); int container_width = container_->GetBoundsInScreen().width();
if (state_ == ACTIVE) { if (state_ == ACTIVE) {
// This method should only be called once in ACTIVE state when
// the left and rightwindows are still full screen and need to be resized.
CHECK_EQ(left_window_->bounds().width(), container_width);
CHECK_EQ(right_window_->bounds().width(), container_width);
// Windows should be resized via an animation when entering the ACTIVE // Windows should be resized via an animation when entering the ACTIVE
// state. // state.
CHECK(animate); CHECK(animate);
// We scale the windows here, but when the animation finishes, we reset // We scale the windows here, but when the animation finishes, we reset
// the scaling and update the window bounds to the proper size - see // the scaling and update the window bounds to the proper size - see
// OnAnimationCompleted(). // OnAnimationCompleted().
left_transform.Scale(.5, 1); left_transform = GetTargetTransformForBoundsAnimation(
right_transform.Scale(.5, 1); left_window_->bounds(), GetLeftTargetBounds());
right_transform.Translate(container_width, 0); right_transform = GetTargetTransformForBoundsAnimation(
right_window_->bounds(), GetRightTargetBounds());
} else { } else {
left_transform.Translate(separator_position_ - container_width, 0); left_transform.Translate(separator_position_ - container_width, 0);
right_transform.Translate(separator_position_, 0); right_transform.Translate(separator_position_, 0);
...@@ -168,16 +194,11 @@ void SplitViewController::OnAnimationCompleted(aura::Window* window) { ...@@ -168,16 +194,11 @@ void SplitViewController::OnAnimationCompleted(aura::Window* window) {
return; return;
DCHECK(window == left_window_ || window == right_window_); DCHECK(window == left_window_ || window == right_window_);
if (state_ == ACTIVE) { if (state_ == ACTIVE) {
int container_width = container_->bounds().width();
gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
gfx::Rect window_bounds(container_width / 2, display.work_area().height());
window->SetTransform(gfx::Transform()); window->SetTransform(gfx::Transform());
if (window == left_window_) { if (window == left_window_)
left_window_->SetBounds(window_bounds); left_window_->SetBounds(GetLeftTargetBounds());
} else { else
window_bounds.set_x(container_width / 2); right_window_->SetBounds(GetRightTargetBounds());
right_window_->SetBounds(window_bounds);
}
} else { } else {
int container_width = container_->bounds().width(); int container_width = container_->bounds().width();
window->SetTransform(gfx::Transform()); window->SetTransform(gfx::Transform());
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
namespace gfx { namespace gfx {
class Rect;
class Transform; class Transform;
} }
...@@ -42,6 +43,13 @@ class ATHENA_EXPORT SplitViewController ...@@ -42,6 +43,13 @@ class ATHENA_EXPORT SplitViewController
void ReplaceWindow(aura::Window* window, void ReplaceWindow(aura::Window* window,
aura::Window* replace_with); aura::Window* replace_with);
// Returns the bounds that the left and right windows will have once split
// view is active and they are done animating. If |left_window_| and
// |right_window_| are still animating this may be different than their
// current bounds.
gfx::Rect GetLeftTargetBounds();
gfx::Rect GetRightTargetBounds();
aura::Window* left_window() { return left_window_; } aura::Window* left_window() { return left_window_; }
aura::Window* right_window() { return right_window_; } aura::Window* right_window() { return right_window_; }
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
#include "athena/wm/split_view_controller.h" #include "athena/wm/split_view_controller.h"
#include "athena/common/fill_layout_manager.h"
#include "athena/test/athena_test_base.h" #include "athena/test/athena_test_base.h"
#include "athena/wm/window_list_provider_impl.h" #include "athena/wm/public/window_list_provider.h"
#include "athena/wm/test/window_manager_impl_test_api.h"
#include "base/memory/scoped_vector.h" #include "base/memory/scoped_vector.h"
#include "ui/aura/test/test_window_delegate.h" #include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
...@@ -22,49 +22,46 @@ TEST_F(SplitViewControllerTest, SplitModeActivation) { ...@@ -22,49 +22,46 @@ TEST_F(SplitViewControllerTest, SplitModeActivation) {
ScopedVector<aura::Window> windows; ScopedVector<aura::Window> windows;
const int kNumWindows = 6; const int kNumWindows = 6;
for (size_t i = 0; i < kNumWindows; ++i) { for (size_t i = 0; i < kNumWindows; ++i) {
aura::Window* window = new aura::Window(&delegate); scoped_ptr<aura::Window> window = CreateTestWindow(NULL, gfx::Rect());
window->SetType(ui::wm::WINDOW_TYPE_NORMAL); windows.push_back(window.release());
window->Init(aura::WINDOW_LAYER_SOLID_COLOR);
root_window()->AddChild(window);
windows.push_back(window);
} }
scoped_ptr<WindowListProvider> list_provider( test::WindowManagerImplTestApi api;
new WindowListProviderImpl(root_window())); SplitViewController* controller = api.GetSplitViewController();
SplitViewController controller(root_window(), list_provider.get()); WindowListProvider* list_provider = api.GetWindowListProvider();
ASSERT_FALSE(controller.IsSplitViewModeActive()); ASSERT_FALSE(controller->IsSplitViewModeActive());
controller.ActivateSplitMode(NULL, NULL); controller->ActivateSplitMode(NULL, NULL);
ASSERT_TRUE(controller.IsSplitViewModeActive()); ASSERT_TRUE(controller->IsSplitViewModeActive());
// The last two windows should be on the left and right, respectively. // The last two windows should be on the left and right, respectively.
EXPECT_EQ(windows[kNumWindows - 1], controller.left_window()); EXPECT_EQ(windows[kNumWindows - 1], controller->left_window());
EXPECT_EQ(windows[kNumWindows - 2], controller.right_window()); EXPECT_EQ(windows[kNumWindows - 2], controller->right_window());
// Select the window that is currently on the left for the right panel. The // Select the window that is currently on the left for the right panel. The
// windows should switch. // windows should switch.
controller.ActivateSplitMode(NULL, windows[kNumWindows - 1]); controller->ActivateSplitMode(NULL, windows[kNumWindows - 1]);
EXPECT_EQ(windows[kNumWindows - 2], controller.left_window()); EXPECT_EQ(windows[kNumWindows - 2], controller->left_window());
EXPECT_EQ(windows[kNumWindows - 1], controller.right_window()); EXPECT_EQ(windows[kNumWindows - 1], controller->right_window());
controller.ActivateSplitMode(windows[kNumWindows - 1], NULL); controller->ActivateSplitMode(windows[kNumWindows - 1], NULL);
EXPECT_EQ(windows[kNumWindows - 1], controller.left_window()); EXPECT_EQ(windows[kNumWindows - 1], controller->left_window());
EXPECT_EQ(windows[kNumWindows - 2], controller.right_window()); EXPECT_EQ(windows[kNumWindows - 2], controller->right_window());
// Select one of the windows behind the stacks for the right panel. The window // Select one of the windows behind the stacks for the right panel. The window
// on the left should remain unchanged. // on the left should remain unchanged.
controller.ActivateSplitMode(NULL, windows[0]); controller->ActivateSplitMode(NULL, windows[0]);
EXPECT_EQ(windows[kNumWindows - 1], controller.left_window()); EXPECT_EQ(windows[kNumWindows - 1], controller->left_window());
EXPECT_EQ(windows[0], controller.right_window()); EXPECT_EQ(windows[0], controller->right_window());
EXPECT_EQ(windows[0], *list_provider->GetWindowList().rbegin()); EXPECT_EQ(windows[0], *list_provider->GetWindowList().rbegin());
controller.ActivateSplitMode(windows[1], NULL); controller->ActivateSplitMode(windows[1], NULL);
EXPECT_EQ(windows[1], controller.left_window()); EXPECT_EQ(windows[1], controller->left_window());
EXPECT_EQ(windows[0], controller.right_window()); EXPECT_EQ(windows[0], controller->right_window());
EXPECT_EQ(windows[1], *list_provider->GetWindowList().rbegin()); EXPECT_EQ(windows[1], *list_provider->GetWindowList().rbegin());
controller.ActivateSplitMode(windows[4], windows[5]); controller->ActivateSplitMode(windows[4], windows[5]);
EXPECT_EQ(windows[4], controller.left_window()); EXPECT_EQ(windows[4], controller->left_window());
EXPECT_EQ(windows[5], controller.right_window()); EXPECT_EQ(windows[5], controller->right_window());
EXPECT_EQ(windows[4], *list_provider->GetWindowList().rbegin()); EXPECT_EQ(windows[4], *list_provider->GetWindowList().rbegin());
EXPECT_EQ(windows[5], *(list_provider->GetWindowList().rbegin() + 1)); EXPECT_EQ(windows[5], *(list_provider->GetWindowList().rbegin() + 1));
} }
......
// Copyright 2014 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 "athena/wm/test/window_manager_impl_test_api.h"
#include "athena/wm/window_manager_impl.h"
namespace athena {
namespace test {
WindowManagerImplTestApi::WindowManagerImplTestApi()
: wm_(static_cast<WindowManagerImpl*>(WindowManager::GetInstance())) {
}
WindowManagerImplTestApi::~WindowManagerImplTestApi() {
}
athena::WindowListProvider* WindowManagerImplTestApi::GetWindowListProvider() {
return wm_->window_list_provider_.get();
}
athena::SplitViewController*
WindowManagerImplTestApi::GetSplitViewController() {
return wm_->split_view_controller_.get();
}
} // namespace test
} // namespace athena
// Copyright 2014 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 ATHENA_WM_TEST_WINDOW_MANAGER_IMPL_TEST_API_H_
#define ATHENA_WM_TEST_WINDOW_MANAGER_IMPL_TEST_API_H_
#include "base/macros.h"
namespace athena {
class SplitViewController;
class WindowListProvider;
class WindowManagerImpl;
namespace test {
class WindowManagerImplTestApi {
public:
WindowManagerImplTestApi();
~WindowManagerImplTestApi();
athena::WindowListProvider* GetWindowListProvider();
athena::SplitViewController* GetSplitViewController();
private:
athena::WindowManagerImpl* wm_;
DISALLOW_COPY_AND_ASSIGN(WindowManagerImplTestApi);
};
} // namespace test
} // namespace athena
#endif // ATHENA_WM_TEST_WINDOW_MANAGER_IMPL_TEST_API_H_
...@@ -20,6 +20,10 @@ class WMState; ...@@ -20,6 +20,10 @@ class WMState;
namespace athena { namespace athena {
namespace test {
class WindowManagerImplTestApi;
}
class BezelController; class BezelController;
class SplitViewController; class SplitViewController;
class WindowListProvider; class WindowListProvider;
...@@ -39,7 +43,7 @@ class WindowManagerImpl : public WindowManager, ...@@ -39,7 +43,7 @@ class WindowManagerImpl : public WindowManager,
virtual bool IsOverviewModeActive() OVERRIDE; virtual bool IsOverviewModeActive() OVERRIDE;
private: private:
friend class WindowManagerImplTestApi; friend class test::WindowManagerImplTestApi;
friend class AthenaContainerLayoutManager; friend class AthenaContainerLayoutManager;
enum Command { enum Command {
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment