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() {
animation_settings_->TrilinearFiltering();
}
ui::LayerAnimator* ScopedOverviewAnimationSettings::GetAnimator() {
return animation_settings_->GetAnimator();
}
} // namespace ash
......@@ -36,6 +36,7 @@ class ScopedOverviewAnimationSettings {
void CacheRenderSurface();
void DeferPaint();
void TrilinearFiltering();
ui::LayerAnimator* GetAnimator();
private:
// The managed animation settings.
......
......@@ -18,6 +18,7 @@
#include "ash/wm/overview/overview_utils.h"
#include "ash/wm/overview/scoped_overview_animation_settings.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/window_preview_view.h"
#include "ash/wm/window_state.h"
......@@ -202,6 +203,8 @@ void ScopedOverviewTransformWindow::RestoreWindow(bool reset_transform) {
for (auto& settings : animation_settings_list) {
auto exit_observer = std::make_unique<ExitAnimationObserver>();
settings->AddObserver(exit_observer.get());
if (window_->layer()->GetAnimator() == settings->GetAnimator())
settings->AddObserver(new WindowTransformAnimationObserver(window_));
Shell::Get()->overview_controller()->AddExitAnimationObserver(
std::move(exit_observer));
}
......
......@@ -1703,9 +1703,12 @@ void SplitViewController::SetTransformWithAnimation(
if (new_start_transform != window_iter->layer()->GetTargetTransform())
window_iter->SetTransform(new_start_transform);
DoSplitviewTransformAnimation(window_iter->layer(),
SPLITVIEW_ANIMATION_SET_WINDOW_TRANSFORM,
new_target_transform);
DoSplitviewTransformAnimation(
window_iter->layer(), SPLITVIEW_ANIMATION_SET_WINDOW_TRANSFORM,
new_target_transform,
window_iter == window
? std::make_unique<WindowTransformAnimationObserver>(window)
: nullptr);
}
}
......@@ -1791,7 +1794,7 @@ void SplitViewController::EndWindowDragImpl(
if (desired_snap_position == SplitViewController::NONE) {
if (was_splitview_active) {
// 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
// location. Note if there is already a window at |desired_snap_postion|,
// SnapWindow() will put the previous snapped window in overview.
......
......@@ -567,11 +567,11 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView
DoSplitviewTransformAnimation(
preview_label_layer,
SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_OUT,
preview_label_transform);
preview_label_transform, /*animation_observer=*/nullptr);
DoSplitviewTransformAnimation(
other_highlight_label_layer,
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_OUT,
other_highlight_label_transform);
other_highlight_label_transform, /*animation_observer=*/nullptr);
} else {
// Put the labels where they belong.
preview_label_layer->SetTransform(preview_label_transform);
......@@ -590,11 +590,11 @@ class SplitViewDragIndicators::SplitViewDragIndicatorsView
// Animate the labels sliding in.
DoSplitviewTransformAnimation(
preview_label_layer, SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_IN,
gfx::Transform());
gfx::Transform(), /*animation_observer=*/nullptr);
DoSplitviewTransformAnimation(
other_highlight_label_layer,
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_IN,
gfx::Transform());
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_IN, gfx::Transform(),
/*animation_observer=*/nullptr);
} else {
// Put the labels where they belong.
preview_label_layer->SetTransform(gfx::Transform());
......
......@@ -149,15 +149,18 @@ void SplitViewHighlightView::SetBounds(
DoSplitviewTransformAnimation(
middle_->layer(), *animation_type,
CalculateTransformFromRects(middle_->bounds(), middle_bounds,
landscape));
landscape),
/*animation_observer=*/nullptr);
DoSplitviewTransformAnimation(
left_top_->layer(), *animation_type,
CalculateTransformFromRects(left_top_->bounds(), left_top_bounds,
landscape));
landscape),
/*animation_observer=*/nullptr);
DoSplitviewTransformAnimation(
right_bottom_->layer(), *animation_type,
CalculateTransformFromRects(right_bottom_->bounds(),
right_bottom_bounds, landscape));
right_bottom_bounds, landscape),
/*animation_observer=*/nullptr);
} else {
left_top_->layer()->SetTransform(gfx::Transform());
right_bottom_->layer()->SetTransform(gfx::Transform());
......
......@@ -24,6 +24,10 @@
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animator.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 {
......@@ -133,8 +137,56 @@ void ApplyAnimationSettings(
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
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,
SplitviewAnimationType type) {
float target_opacity = 0.f;
......@@ -182,9 +234,11 @@ void DoSplitviewOpacityAnimation(ui::Layer* layer,
layer->SetOpacity(target_opacity);
}
void DoSplitviewTransformAnimation(ui::Layer* layer,
SplitviewAnimationType type,
const gfx::Transform& target_transform) {
void DoSplitviewTransformAnimation(
ui::Layer* layer,
SplitviewAnimationType type,
const gfx::Transform& target_transform,
std::unique_ptr<ui::ImplicitAnimationObserver> animation_observer) {
if (layer->GetTargetTransform() == target_transform)
return;
......@@ -214,6 +268,8 @@ void DoSplitviewTransformAnimation(ui::Layer* layer,
ui::LayerAnimator* animator = layer->GetAnimator();
ui::ScopedLayerAnimationSettings settings(animator);
if (animation_observer.get())
settings.AddObserver(animation_observer.release());
ApplyAnimationSettings(&settings, animator,
ui::LayerAnimationElement::TRANSFORM, duration, tween,
preemption_strategy, delay);
......
......@@ -7,6 +7,8 @@
#include "ash/ash_export.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"
namespace aura {
......@@ -70,13 +72,45 @@ enum SplitviewAnimationType {
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|.
void DoSplitviewOpacityAnimation(ui::Layer* layer, SplitviewAnimationType type);
// Animates |layer|'s transform based on |type|.
void DoSplitviewTransformAnimation(ui::Layer* layer,
SplitviewAnimationType type,
const gfx::Transform& target_transform);
void DoSplitviewTransformAnimation(
ui::Layer* layer,
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.
// 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