Commit 1d286087 authored by Mohamed Amir Yosef's avatar Mohamed Amir Yosef Committed by Commit Bot

[Passwords] Use AnimatingLayoutManager instead of LayerAnimation ...

... to animate password save/update bubble.

The reason for that is GetWidget()->GetLayer() only works for animating
entire windows if the underlying widget is a `NativeWidgetAura`.
DesktopNativeWidgetAura and NativeWidgetMac have an OS-provided "frame"
that we can not animate in the same way.

Implementing the animation on MacOS and Windows is more complex
After CL the animation works on MacOS and Windows in the same way
as on Linux.

Here is a screencast on MacOS
https://drive.google.com/file/d/133bqSrjVA9PIuSDjQNKmfsCHBMXOAo5w/view?usp=sharing

Follow up CLs will fix the flickering of the dropdown menu.

Bug: 1044038
Change-Id: Id7a24bfb3049e3577c4ea7e2089b6679c41269d5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2195967
Commit-Queue: Mohamed Amir Yosef <mamir@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#771757}
parent b8096ae4
......@@ -30,8 +30,6 @@
#include "ui/base/models/combobox_model_observer.h"
#include "ui/base/models/simple_combobox_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/bubble/bubble_frame_view.h"
......@@ -40,6 +38,7 @@
#include "ui/views/controls/combobox/combobox.h"
#include "ui/views/controls/editable_combobox/editable_combobox.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/animating_layout_manager.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/layout_provider.h"
......@@ -268,20 +267,24 @@ std::string GetSignedInEmail(Profile* profile) {
} // namespace
// // The class notifies the bubble when it is expanded completely.
class PasswordSaveUpdateWithAccountStoreView::BubbleExpansionObserver
: public ui::ImplicitAnimationObserver {
// TODO(crbug.com/1077706): come up with a more general solution for this.
// This layout auto-resizes the host view to always adapt to changes in the size
// of the child views.
class PasswordSaveUpdateWithAccountStoreView::AutoResizingLayout
: public views::FillLayout {
public:
explicit BubbleExpansionObserver(
PasswordSaveUpdateWithAccountStoreView* bubble)
: bubble_(bubble) {}
AutoResizingLayout() = default;
void OnImplicitAnimationsCompleted() override {
bubble_->OnBubbleExpansionFinished();
private:
PasswordSaveUpdateWithAccountStoreView* bubble_view() {
return static_cast<PasswordSaveUpdateWithAccountStoreView*>(host_view());
}
private:
PasswordSaveUpdateWithAccountStoreView* bubble_;
void OnLayoutChanged() override {
FillLayout::OnLayoutChanged();
if (bubble_view()->GetWidget())
bubble_view()->SizeToContents();
}
};
PasswordSaveUpdateWithAccountStoreView::PasswordSaveUpdateWithAccountStoreView(
......@@ -338,11 +341,19 @@ PasswordSaveUpdateWithAccountStoreView::PasswordSaveUpdateWithAccountStoreView(
password_dropdown->set_listener(this);
std::unique_ptr<views::ToggleImageButton> password_view_button =
CreatePasswordViewButton(this, are_passwords_revealed_);
views::FlexLayout* layout =
SetLayoutManager(std::make_unique<views::FlexLayout>());
layout->SetOrientation(views::LayoutOrientation::kVertical)
.SetMainAxisAlignment(views::LayoutAlignment::kEnd)
// Set up layout:
SetLayoutManager(std::make_unique<AutoResizingLayout>());
views::View* root_view = AddChildView(std::make_unique<views::View>());
views::AnimatingLayoutManager* animating_layout =
root_view->SetLayoutManager(
std::make_unique<views::AnimatingLayoutManager>());
animating_layout
->SetBoundsAnimationMode(views::AnimatingLayoutManager::
BoundsAnimationMode::kAnimateMainAxis)
.SetOrientation(views::LayoutOrientation::kVertical);
views::FlexLayout* flex_layout = animating_layout->SetTargetLayoutManager(
std::make_unique<views::FlexLayout>());
flex_layout->SetOrientation(views::LayoutOrientation::kVertical)
.SetCrossAxisAlignment(views::LayoutAlignment::kStretch)
.SetIgnoreDefaultMainAxisMargins(true)
.SetCollapseMargins(true)
......@@ -357,11 +368,10 @@ PasswordSaveUpdateWithAccountStoreView::PasswordSaveUpdateWithAccountStoreView(
password_dropdown_ = password_dropdown.get();
destination_dropdown_ = destination_dropdown.get();
password_view_button_ = password_view_button.get();
BuildCredentialRows(
/*parent_view=*/this, std::move(destination_dropdown),
std::move(username_dropdown), std::move(password_dropdown),
std::move(password_view_button));
BuildCredentialRows(root_view, std::move(destination_dropdown),
std::move(username_dropdown),
std::move(password_dropdown),
std::move(password_view_button));
// The account picker is only visible in Save bubbble, not Update bubble.
if (destination_dropdown_)
......@@ -530,21 +540,7 @@ void PasswordSaveUpdateWithAccountStoreView::
if (!destination_dropdown_)
return;
// If the expanded bubble layer height isn't yet computed, do it.
if (expanded_bubble_height_ == -1) {
// We need to compute the layer height before any animation takes place.
ui::Layer* layer = GetWidget()->GetLayer();
expanded_bubble_height_ = layer->bounds().height();
// If the account picker is current invisible, account for the extra space
// added when it will become visible.
if (!destination_dropdown_->GetVisible()) {
expanded_bubble_height_ +=
destination_dropdown_->GetPreferredSize().height() +
ChromeLayoutProvider::Get()->GetDistanceMetric(
DISTANCE_CONTROL_LIST_VERTICAL);
}
}
StartResizing();
destination_dropdown_->SetVisible(!controller_.IsCurrentStateUpdate());
}
std::unique_ptr<views::View>
......@@ -559,30 +555,3 @@ PasswordSaveUpdateWithAccountStoreView::CreateFooterView() {
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
return label;
}
void PasswordSaveUpdateWithAccountStoreView::StartResizing() {
DCHECK(GetWidget());
DCHECK(destination_dropdown_);
expansion_observer_.reset();
ui::Layer* layer = GetWidget()->GetLayer();
ui::ScopedLayerAnimationSettings animator(layer->GetAnimator());
if (controller_.IsCurrentStateUpdate()) {
// We need to hide the account picker, do it immediately.
destination_dropdown_->SetVisible(false);
SizeToContents();
} else {
// We need to show the account picker: Expand the bubble first and then show
// the account picker.
expansion_observer_ = std::make_unique<BubbleExpansionObserver>(this);
animator.AddObserver(expansion_observer_.get());
gfx::Rect bounds = layer->bounds();
bounds.set_height(expanded_bubble_height_);
layer->SetBounds(bounds);
}
}
void PasswordSaveUpdateWithAccountStoreView::OnBubbleExpansionFinished() {
DCHECK(destination_dropdown_);
DCHECK(!controller_.IsCurrentStateUpdate());
destination_dropdown_->SetVisible(true);
}
......@@ -10,6 +10,7 @@
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/combobox/combobox_listener.h"
#include "ui/views/controls/editable_combobox/editable_combobox_listener.h"
#include "ui/views/layout/animating_layout_manager.h"
#include "ui/views/view.h"
namespace views {
......@@ -38,8 +39,7 @@ class PasswordSaveUpdateWithAccountStoreView
}
private:
class BubbleExpansionObserver;
class AutoResizingLayout;
~PasswordSaveUpdateWithAccountStoreView() override;
// PasswordBubbleViewBase
......@@ -74,12 +74,6 @@ class PasswordSaveUpdateWithAccountStoreView
void UpdateDialogButtonsAndAccountPickerVisiblity();
std::unique_ptr<views::View> CreateFooterView();
// Starts animating the bubble to expand or contract it.
void StartResizing();
// Called when the expansion animation is finished. When the bubble it fully
// expanded, the account picker is shown.
void OnBubbleExpansionFinished();
SaveUpdateWithAccountStoreBubbleController controller_;
// True iff it is an update password bubble on creation. False iff it is a
......@@ -93,14 +87,6 @@ class PasswordSaveUpdateWithAccountStoreView
// The view for the password value.
views::EditableCombobox* password_dropdown_;
// The height of widget layer when the account picker is visible.
int expanded_bubble_height_ = -1;
// Observers the animation of the bubbling during expansion and makes sure the
// OnBubbleExpansionFinished() is called when the bubble is fully expanded.
std::unique_ptr<BubbleExpansionObserver> expansion_observer_;
bool are_passwords_revealed_;
};
......
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