Commit be1f70ab authored by pkotwicz's avatar pkotwicz Committed by Commit bot

Fix crash when using title drag on a window opened while split view is active.

This CL also centralizes setting the activity's bounds and transform while in
split view to SplitViewController::UpdateLayout(). In particular, the bounds of
an activity are now correct even if it is opened while some other activity is
animating into split view

BUG=405964
TEST=WindowManagerTest.NewWindowBounds

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

Cr-Commit-Position: refs/heads/master@{#293019}
parent 43ae1fb3
...@@ -112,19 +112,20 @@ void SplitViewController::ReplaceWindow(aura::Window* window, ...@@ -112,19 +112,20 @@ void SplitViewController::ReplaceWindow(aura::Window* window,
windows.end()); windows.end());
#endif #endif
replace_with->SetBounds(window->bounds());
replace_with->SetTransform(gfx::Transform());
if (window == left_window_) if (window == left_window_)
left_window_ = replace_with; left_window_ = replace_with;
else else
right_window_ = replace_with; right_window_ = replace_with;
wm::ActivateWindow(replace_with); wm::ActivateWindow(replace_with);
UpdateLayout(false);
window->SetTransform(gfx::Transform()); window->SetTransform(gfx::Transform());
window->Hide();
} }
void SplitViewController::DeactivateSplitMode() { void SplitViewController::DeactivateSplitMode() {
CHECK_NE(SCROLLING, state_); CHECK_EQ(ACTIVE, state_);
state_ = INACTIVE; state_ = INACTIVE;
UpdateLayout(false);
left_window_ = right_window_ = NULL; left_window_ = right_window_ = NULL;
} }
...@@ -143,76 +144,80 @@ gfx::Rect SplitViewController::GetRightTargetBounds() { ...@@ -143,76 +144,80 @@ gfx::Rect SplitViewController::GetRightTargetBounds() {
} }
void SplitViewController::UpdateLayout(bool animate) { void SplitViewController::UpdateLayout(bool animate) {
if (!left_window_) CHECK(left_window_);
return;
CHECK(right_window_); CHECK(right_window_);
gfx::Transform left_transform;
gfx::Transform right_transform; if (state_ == INACTIVE && !animate) {
int container_width = container_->GetBoundsInScreen().width(); if (!wm::IsActiveWindow(left_window_))
left_window_->Hide();
if (!wm::IsActiveWindow(right_window_))
right_window_->Hide();
SetWindowTransforms(gfx::Transform(), gfx::Transform(), false);
return;
}
left_window_->Show();
right_window_->Show();
if (state_ == ACTIVE) { if (state_ == ACTIVE) {
// Windows should be resized via an animation when entering the ACTIVE if (animate) {
// state. gfx::Transform left_transform = GetTargetTransformForBoundsAnimation(
CHECK(animate); left_window_->bounds(), GetLeftTargetBounds());
// We scale the windows here, but when the animation finishes, we reset gfx::Transform right_transform = GetTargetTransformForBoundsAnimation(
// the scaling and update the window bounds to the proper size - see right_window_->bounds(), GetRightTargetBounds());
// OnAnimationCompleted(). SetWindowTransforms(left_transform, right_transform, true);
left_transform = GetTargetTransformForBoundsAnimation( } else {
left_window_->bounds(), GetLeftTargetBounds()); left_window_->SetBounds(GetLeftTargetBounds());
right_transform = GetTargetTransformForBoundsAnimation( right_window_->SetBounds(GetRightTargetBounds());
right_window_->bounds(), GetRightTargetBounds()); SetWindowTransforms(gfx::Transform(), gfx::Transform(), false);
}
} else { } else {
left_transform.Translate(separator_position_ - container_width, 0); gfx::Transform left_transform;
left_transform.Translate(separator_position_ - container_->bounds().width(),
0);
gfx::Transform right_transform;
right_transform.Translate(separator_position_, 0); right_transform.Translate(separator_position_, 0);
SetWindowTransforms(left_transform, right_transform, animate);
} }
left_window_->Show(); // Note: |left_window_| and |right_window_| may be NULL if calling
right_window_->Show(); // SetWindowTransforms():
SetWindowTransform(left_window_, left_transform, animate); // - caused the in-progress animation to abort.
SetWindowTransform(right_window_, right_transform, animate); // - started a zero duration animation.
} }
void SplitViewController::SetWindowTransform(aura::Window* window, void SplitViewController::SetWindowTransforms(
const gfx::Transform& transform, const gfx::Transform& left_transform,
bool animate) { const gfx::Transform& right_transform,
bool animate) {
if (animate) { if (animate) {
scoped_refptr<ui::LayerAnimator> animator = window->layer()->GetAnimator(); ui::ScopedLayerAnimationSettings left_settings(
ui::ScopedLayerAnimationSettings settings(animator); left_window_->layer()->GetAnimator());
settings.SetPreemptionStrategy( left_settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
settings.AddObserver(new ui::ClosureAnimationObserver( left_window_->SetTransform(left_transform);
ui::ScopedLayerAnimationSettings right_settings(
right_window_->layer()->GetAnimator());
right_settings.SetPreemptionStrategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
right_settings.AddObserver(new ui::ClosureAnimationObserver(
base::Bind(&SplitViewController::OnAnimationCompleted, base::Bind(&SplitViewController::OnAnimationCompleted,
weak_factory_.GetWeakPtr(), weak_factory_.GetWeakPtr())));
window))); right_window_->SetTransform(right_transform);
window->SetTransform(transform);
} else { } else {
window->SetTransform(transform); left_window_->SetTransform(left_transform);
right_window_->SetTransform(right_transform);
} }
} }
void SplitViewController::OnAnimationCompleted(aura::Window* window) { void SplitViewController::OnAnimationCompleted() {
// Animation can be cancelled when deactivated. // Animation can be cancelled when deactivated.
if (left_window_ == NULL) if (left_window_ == NULL)
return; return;
DCHECK(window == left_window_ || window == right_window_); UpdateLayout(false);
if (state_ == ACTIVE) {
window->SetTransform(gfx::Transform()); if (state_ == INACTIVE) {
if (window == left_window_) left_window_ = NULL;
left_window_->SetBounds(GetLeftTargetBounds()); right_window_ = NULL;
else
right_window_->SetBounds(GetRightTargetBounds());
} else {
int container_width = container_->bounds().width();
window->SetTransform(gfx::Transform());
if (window == left_window_) {
if (separator_position_ == 0)
left_window_->Hide();
if (state_ == INACTIVE)
left_window_ = NULL;
} else {
if (separator_position_ == container_width)
right_window_->Hide();
if (state_ == INACTIVE)
right_window_ = NULL;
}
} }
} }
......
...@@ -35,11 +35,12 @@ class ATHENA_EXPORT SplitViewController ...@@ -35,11 +35,12 @@ class ATHENA_EXPORT SplitViewController
// |left| nor |right|) is selected instead. // |left| nor |right|) is selected instead.
void ActivateSplitMode(aura::Window* left, aura::Window* right); void ActivateSplitMode(aura::Window* left, aura::Window* right);
// Resets the internal state to an inactive state. Calling this does not // Resets the internal state to an inactive state.
// change the window bounds/transforms etc. The caller must take care of
// making any necessary changes.
void DeactivateSplitMode(); void DeactivateSplitMode();
// Replaces |window| in split-view mode with |replace_with|. Adjusts
// |replace_with|'s visibility, transform and bounds. Resets |window|'s
// visibility and transform but does not change its bounds.
void ReplaceWindow(aura::Window* window, void ReplaceWindow(aura::Window* window,
aura::Window* replace_with); aura::Window* replace_with);
...@@ -69,11 +70,12 @@ class ATHENA_EXPORT SplitViewController ...@@ -69,11 +70,12 @@ class ATHENA_EXPORT SplitViewController
void UpdateLayout(bool animate); void UpdateLayout(bool animate);
void SetWindowTransform(aura::Window* left_window, void SetWindowTransforms(const gfx::Transform& left_transform,
const gfx::Transform& transform, const gfx::Transform& right_transform,
bool animate); bool animate);
void OnAnimationCompleted(aura::Window* window); // Called when the animation initiated by SetWindowTransforms() completes.
void OnAnimationCompleted();
void UpdateSeparatorPositionFromScrollDelta(float delta); void UpdateSeparatorPositionFromScrollDelta(float delta);
......
...@@ -101,14 +101,14 @@ void AthenaContainerLayoutManager::OnWindowAddedToLayout(aura::Window* child) { ...@@ -101,14 +101,14 @@ void AthenaContainerLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
aura::Window::Windows list = instance->window_list_provider_->GetWindowList(); aura::Window::Windows list = instance->window_list_provider_->GetWindowList();
if (std::find(list.begin(), list.end(), child) == list.end()) if (std::find(list.begin(), list.end(), child) == list.end())
return; return;
gfx::Size size;
if (instance->split_view_controller_->IsSplitViewModeActive()) { if (instance->split_view_controller_->IsSplitViewModeActive()) {
size = instance->split_view_controller_->left_window()->bounds().size(); instance->split_view_controller_->ReplaceWindow(
instance->split_view_controller_->left_window(), child);
} else { } else {
size = gfx::Size size =
gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area().size(); gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area().size();
child->SetBounds(gfx::Rect(size));
} }
child->SetBounds(gfx::Rect(size));
} }
void AthenaContainerLayoutManager::OnWillRemoveWindowFromLayout( void AthenaContainerLayoutManager::OnWillRemoveWindowFromLayout(
......
...@@ -139,6 +139,8 @@ TEST_F(WindowManagerTest, BezelGestureToSwitchBetweenWindows) { ...@@ -139,6 +139,8 @@ TEST_F(WindowManagerTest, BezelGestureToSwitchBetweenWindows) {
scoped_ptr<aura::Window> first(CreateWindow(&delegate)); scoped_ptr<aura::Window> first(CreateWindow(&delegate));
scoped_ptr<aura::Window> second(CreateWindow(&delegate)); scoped_ptr<aura::Window> second(CreateWindow(&delegate));
scoped_ptr<aura::Window> third(CreateWindow(&delegate)); scoped_ptr<aura::Window> third(CreateWindow(&delegate));
first->Hide();
second->Hide();
test::WindowManagerImplTestApi wm_api; test::WindowManagerImplTestApi wm_api;
aura::client::ParentWindowWithContext( aura::client::ParentWindowWithContext(
...@@ -163,6 +165,9 @@ TEST_F(WindowManagerTest, BezelGestureToSwitchBetweenWindows) { ...@@ -163,6 +165,9 @@ TEST_F(WindowManagerTest, BezelGestureToSwitchBetweenWindows) {
EXPECT_TRUE(wm::IsActiveWindow(second.get())); EXPECT_TRUE(wm::IsActiveWindow(second.get()));
EXPECT_EQ(second.get(), EXPECT_EQ(second.get(),
wm_api.GetWindowListProvider()->GetWindowList().back()); wm_api.GetWindowListProvider()->GetWindowList().back());
EXPECT_FALSE(first->IsVisible());
EXPECT_TRUE(second->IsVisible());
EXPECT_FALSE(third->IsVisible());
} }
TEST_F(WindowManagerTest, TitleDragSwitchBetweenWindows) { TEST_F(WindowManagerTest, TitleDragSwitchBetweenWindows) {
...@@ -300,16 +305,12 @@ TEST_F(WindowManagerTest, NewWindowBounds) { ...@@ -300,16 +305,12 @@ TEST_F(WindowManagerTest, NewWindowBounds) {
EXPECT_NE(work_area.ToString(), EXPECT_NE(work_area.ToString(),
left_bounds.size().ToString()); left_bounds.size().ToString());
// A new window should replace the left window when in split view.
scoped_ptr<aura::Window> third(CreateWindow(&delegate)); scoped_ptr<aura::Window> third(CreateWindow(&delegate));
aura::client::ParentWindowWithContext( aura::client::ParentWindowWithContext(
third.get(), ScreenManager::Get()->GetContext(), gfx::Rect()); third.get(), ScreenManager::Get()->GetContext(), gfx::Rect());
EXPECT_NE(wm_api.GetSplitViewController()->left_window(), third.get()); EXPECT_EQ(wm_api.GetSplitViewController()->left_window(), third.get());
EXPECT_EQ(left_bounds.ToString(), third->bounds().ToString()); EXPECT_EQ(left_bounds.ToString(), third->bounds().ToString());
third->Hide();
EXPECT_EQ(
left_bounds.ToString(),
wm_api.GetSplitViewController()->left_window()->bounds().ToString());
} }
TEST_F(WindowManagerTest, SplitModeActivationByShortcut) { TEST_F(WindowManagerTest, SplitModeActivationByShortcut) {
......
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