Commit 17c45e51 authored by Xiaoqian Dai's avatar Xiaoqian Dai Committed by Commit Bot

Fix the bubble dialogs layout issue in splitview and overview.

The reason for this issue is a bubble dialog does not get the correct
bounds if the anchor window changes bounds when the anchor window has an
un-identity transform in place. This CL forces the bubble dialog
relayout itself when the anchor window's transform reset to the identity
transform.

Bug: 1035512
Change-Id: I3e73400320ecb5df99016ff1f53e6325dca2a1ad
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1974594Reviewed-by: default avatarSammie Quon <sammiequon@chromium.org>
Commit-Queue: Xiaoqian Dai <xdai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726162}
parent a239f265
...@@ -233,4 +233,8 @@ void ScopedOverviewAnimationSettings::TrilinearFiltering() { ...@@ -233,4 +233,8 @@ void ScopedOverviewAnimationSettings::TrilinearFiltering() {
animation_settings_->TrilinearFiltering(); animation_settings_->TrilinearFiltering();
} }
ui::LayerAnimator* ScopedOverviewAnimationSettings::GetAnimator() {
return animation_settings_->GetAnimator();
}
} // namespace ash } // namespace ash
...@@ -36,6 +36,7 @@ class ScopedOverviewAnimationSettings { ...@@ -36,6 +36,7 @@ class ScopedOverviewAnimationSettings {
void CacheRenderSurface(); void CacheRenderSurface();
void DeferPaint(); void DeferPaint();
void TrilinearFiltering(); void TrilinearFiltering();
ui::LayerAnimator* GetAnimator();
private: private:
// The managed animation settings. // The managed animation settings.
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/scoped_overview_animation_settings.h" #include "ash/wm/overview/scoped_overview_animation_settings.h"
#include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/splitview/split_view_utils.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_preview_view.h" #include "ash/wm/window_preview_view.h"
#include "ash/wm/window_state.h" #include "ash/wm/window_state.h"
...@@ -202,6 +203,8 @@ void ScopedOverviewTransformWindow::RestoreWindow(bool reset_transform) { ...@@ -202,6 +203,8 @@ void ScopedOverviewTransformWindow::RestoreWindow(bool reset_transform) {
for (auto& settings : animation_settings_list) { for (auto& settings : animation_settings_list) {
auto exit_observer = std::make_unique<ExitAnimationObserver>(); auto exit_observer = std::make_unique<ExitAnimationObserver>();
settings->AddObserver(exit_observer.get()); settings->AddObserver(exit_observer.get());
if (window_->layer()->GetAnimator() == settings->GetAnimator())
settings->AddObserver(new WindowTransformAnimationObserver(window_));
Shell::Get()->overview_controller()->AddExitAnimationObserver( Shell::Get()->overview_controller()->AddExitAnimationObserver(
std::move(exit_observer)); std::move(exit_observer));
} }
......
...@@ -1703,9 +1703,12 @@ void SplitViewController::SetTransformWithAnimation( ...@@ -1703,9 +1703,12 @@ void SplitViewController::SetTransformWithAnimation(
if (new_start_transform != window_iter->layer()->GetTargetTransform()) if (new_start_transform != window_iter->layer()->GetTargetTransform())
window_iter->SetTransform(new_start_transform); window_iter->SetTransform(new_start_transform);
DoSplitviewTransformAnimation(window_iter->layer(), DoSplitviewTransformAnimation(
SPLITVIEW_ANIMATION_SET_WINDOW_TRANSFORM, window_iter->layer(), SPLITVIEW_ANIMATION_SET_WINDOW_TRANSFORM,
new_target_transform); new_target_transform,
window_iter == window
? std::make_unique<WindowTransformAnimationObserver>(window)
: nullptr);
} }
} }
...@@ -1791,7 +1794,7 @@ void SplitViewController::EndWindowDragImpl( ...@@ -1791,7 +1794,7 @@ void SplitViewController::EndWindowDragImpl(
if (desired_snap_position == SplitViewController::NONE) { if (desired_snap_position == SplitViewController::NONE) {
if (was_splitview_active) { if (was_splitview_active) {
// Even though |snap_position| equals |NONE|, the dragged window still // Even though |snap_position| equals |NONE|, the dragged window still
// needs to be snapped if splitview mode is active at the momemnt. // needs to be snapped if splitview mode is active at the moment.
// Calculate the expected snap position based on the last event // Calculate the expected snap position based on the last event
// location. Note if there is already a window at |desired_snap_postion|, // location. Note if there is already a window at |desired_snap_postion|,
// SnapWindow() will put the previous snapped window in overview. // SnapWindow() will put the previous snapped window in overview.
......
...@@ -567,11 +567,11 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView ...@@ -567,11 +567,11 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView
DoSplitviewTransformAnimation( DoSplitviewTransformAnimation(
preview_label_layer, preview_label_layer,
SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_OUT, SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_OUT,
preview_label_transform); preview_label_transform, /*animation_observer=*/nullptr);
DoSplitviewTransformAnimation( DoSplitviewTransformAnimation(
other_highlight_label_layer, other_highlight_label_layer,
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_OUT, SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_OUT,
other_highlight_label_transform); other_highlight_label_transform, /*animation_observer=*/nullptr);
} else { } else {
// Put the labels where they belong. // Put the labels where they belong.
preview_label_layer->SetTransform(preview_label_transform); preview_label_layer->SetTransform(preview_label_transform);
...@@ -590,11 +590,11 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView ...@@ -590,11 +590,11 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView
// Animate the labels sliding in. // Animate the labels sliding in.
DoSplitviewTransformAnimation( DoSplitviewTransformAnimation(
preview_label_layer, SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_IN, preview_label_layer, SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_IN,
gfx::Transform()); gfx::Transform(), /*animation_observer=*/nullptr);
DoSplitviewTransformAnimation( DoSplitviewTransformAnimation(
other_highlight_label_layer, other_highlight_label_layer,
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_IN, SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_IN, gfx::Transform(),
gfx::Transform()); /*animation_observer=*/nullptr);
} else { } else {
// Put the labels where they belong. // Put the labels where they belong.
preview_label_layer->SetTransform(gfx::Transform()); preview_label_layer->SetTransform(gfx::Transform());
......
...@@ -149,15 +149,18 @@ void SplitViewHighlightView::SetBounds( ...@@ -149,15 +149,18 @@ void SplitViewHighlightView::SetBounds(
DoSplitviewTransformAnimation( DoSplitviewTransformAnimation(
middle_->layer(), *animation_type, middle_->layer(), *animation_type,
CalculateTransformFromRects(middle_->bounds(), middle_bounds, CalculateTransformFromRects(middle_->bounds(), middle_bounds,
landscape)); landscape),
/*animation_observer=*/nullptr);
DoSplitviewTransformAnimation( DoSplitviewTransformAnimation(
left_top_->layer(), *animation_type, left_top_->layer(), *animation_type,
CalculateTransformFromRects(left_top_->bounds(), left_top_bounds, CalculateTransformFromRects(left_top_->bounds(), left_top_bounds,
landscape)); landscape),
/*animation_observer=*/nullptr);
DoSplitviewTransformAnimation( DoSplitviewTransformAnimation(
right_bottom_->layer(), *animation_type, right_bottom_->layer(), *animation_type,
CalculateTransformFromRects(right_bottom_->bounds(), CalculateTransformFromRects(right_bottom_->bounds(),
right_bottom_bounds, landscape)); right_bottom_bounds, landscape),
/*animation_observer=*/nullptr);
} else { } else {
left_top_->layer()->SetTransform(gfx::Transform()); left_top_->layer()->SetTransform(gfx::Transform());
right_bottom_->layer()->SetTransform(gfx::Transform()); right_bottom_->layer()->SetTransform(gfx::Transform());
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
#include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animator.h" #include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/transient_window_manager.h"
namespace ash { namespace ash {
...@@ -133,8 +137,56 @@ void ApplyAnimationSettings( ...@@ -133,8 +137,56 @@ void ApplyAnimationSettings(
animator->SchedulePauseForProperties(delay, animated_property); animator->SchedulePauseForProperties(delay, animated_property);
} }
// Returns BubbleDialogDelegateView if |transient_window| is a bubble dialog.
views::BubbleDialogDelegateView* AsBubbleDialogDelegate(
aura::Window* transient_window) {
views::Widget* widget =
views::Widget::GetWidgetForNativeWindow(transient_window);
if (!widget || !widget->widget_delegate())
return nullptr;
return widget->widget_delegate()->AsBubbleDialogDelegate();
}
} // namespace } // namespace
WindowTransformAnimationObserver::WindowTransformAnimationObserver(
aura::Window* window)
: window_(window) {
window_->AddObserver(this);
}
WindowTransformAnimationObserver::~WindowTransformAnimationObserver() {
if (window_)
window_->RemoveObserver(this);
}
void WindowTransformAnimationObserver::OnImplicitAnimationsCompleted() {
// After window transform animation is done and if the window's transform is
// set to identity transform, force to relayout all its transient bubble
// dialogs.
if (!window_->layer()->GetTargetTransform().IsIdentity()) {
delete this;
return;
}
for (auto* transient_window :
::wm::TransientWindowManager::GetOrCreate(window_)
->transient_children()) {
// For now we only care about bubble dialog type transient children.
views::BubbleDialogDelegateView* bubble_delegate_view =
AsBubbleDialogDelegate(transient_window);
if (bubble_delegate_view)
bubble_delegate_view->OnAnchorBoundsChanged();
}
delete this;
}
void WindowTransformAnimationObserver::OnWindowDestroying(
aura::Window* window) {
delete this;
}
void DoSplitviewOpacityAnimation(ui::Layer* layer, void DoSplitviewOpacityAnimation(ui::Layer* layer,
SplitviewAnimationType type) { SplitviewAnimationType type) {
float target_opacity = 0.f; float target_opacity = 0.f;
...@@ -182,9 +234,11 @@ void DoSplitviewOpacityAnimation(ui::Layer* layer, ...@@ -182,9 +234,11 @@ void DoSplitviewOpacityAnimation(ui::Layer* layer,
layer->SetOpacity(target_opacity); layer->SetOpacity(target_opacity);
} }
void DoSplitviewTransformAnimation(ui::Layer* layer, void DoSplitviewTransformAnimation(
SplitviewAnimationType type, ui::Layer* layer,
const gfx::Transform& target_transform) { SplitviewAnimationType type,
const gfx::Transform& target_transform,
std::unique_ptr<ui::ImplicitAnimationObserver> animation_observer) {
if (layer->GetTargetTransform() == target_transform) if (layer->GetTargetTransform() == target_transform)
return; return;
...@@ -214,6 +268,8 @@ void DoSplitviewTransformAnimation(ui::Layer* layer, ...@@ -214,6 +268,8 @@ void DoSplitviewTransformAnimation(ui::Layer* layer,
ui::LayerAnimator* animator = layer->GetAnimator(); ui::LayerAnimator* animator = layer->GetAnimator();
ui::ScopedLayerAnimationSettings settings(animator); ui::ScopedLayerAnimationSettings settings(animator);
if (animation_observer.get())
settings.AddObserver(animation_observer.release());
ApplyAnimationSettings(&settings, animator, ApplyAnimationSettings(&settings, animator,
ui::LayerAnimationElement::TRANSFORM, duration, tween, ui::LayerAnimationElement::TRANSFORM, duration, tween,
preemption_strategy, delay); preemption_strategy, delay);
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/wm/splitview/split_view_controller.h" #include "ash/wm/splitview/split_view_controller.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/gfx/transform.h" #include "ui/gfx/transform.h"
namespace aura { namespace aura {
...@@ -70,13 +72,45 @@ enum SplitviewAnimationType { ...@@ -70,13 +72,45 @@ enum SplitviewAnimationType {
SPLITVIEW_ANIMATION_SET_WINDOW_TRANSFORM, SPLITVIEW_ANIMATION_SET_WINDOW_TRANSFORM,
}; };
// This class observes the window transform animation and relayout the window's
// transient bubble dialogs when animation is completed. This is needed in some
// splitview and overview cases as in splitview or overview, the window can have
// an un-identity transform in place when its bounds changed. And when this
// happens, its transient bubble dialogs won't have the correct bounds as the
// bounds are calculated based on the transformed window bounds. We'll need to
// manually relayout the bubble dialogs after the window's transform reset to
// the identity transform so that the bubble dialogs can have correct bounds.
class ASH_EXPORT WindowTransformAnimationObserver
: public ui::ImplicitAnimationObserver,
public aura::WindowObserver {
public:
explicit WindowTransformAnimationObserver(aura::Window* window);
~WindowTransformAnimationObserver() override;
// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsCompleted() override;
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
private:
aura::Window* const window_;
WindowTransformAnimationObserver(const WindowTransformAnimationObserver&) =
delete;
WindowTransformAnimationObserver& operator=(
const WindowTransformAnimationObserver&) = delete;
};
// Animates |layer|'s opacity based on |type|. // Animates |layer|'s opacity based on |type|.
void DoSplitviewOpacityAnimation(ui::Layer* layer, SplitviewAnimationType type); void DoSplitviewOpacityAnimation(ui::Layer* layer, SplitviewAnimationType type);
// Animates |layer|'s transform based on |type|. // Animates |layer|'s transform based on |type|.
void DoSplitviewTransformAnimation(ui::Layer* layer, void DoSplitviewTransformAnimation(
SplitviewAnimationType type, ui::Layer* layer,
const gfx::Transform& target_transform); SplitviewAnimationType type,
const gfx::Transform& target_transform,
std::unique_ptr<ui::ImplicitAnimationObserver> animation_observer);
// Restores split view and overview based on the current split view's state. // Restores split view and overview based on the current split view's state.
// If |refresh_snapped_windows| is true, it will update the left and right // If |refresh_snapped_windows| is true, it will update the left and right
......
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