Commit 84bfcb31 authored by Dana Fried's avatar Dana Fried Committed by Commit Bot

Hover cards: do not show placeholder image if image data is available.

Previously, the placeholder image could be shown for a frame or two
while the hover card is sliding between tabs, while we're waiting for
the uncompressed version of a cached thumbnail image. This change keeps
the old image around instead (leading to a more smooth hover card
transition as a side effect).


Change-Id: Iecc3f7f31616906c7c9a9d9b62cea31b67cf5f50
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1896240Reviewed-by: default avatarCaroline Rising <corising@chromium.org>
Commit-Queue: Caroline Rising <corising@chromium.org>
Auto-Submit: Dana Fried <dfried@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712292}
parent 6cc1da8e
...@@ -71,6 +71,8 @@ class ThumbnailImage : public base::RefCounted<ThumbnailImage> { ...@@ -71,6 +71,8 @@ class ThumbnailImage : public base::RefCounted<ThumbnailImage> {
explicit ThumbnailImage(Delegate* delegate); explicit ThumbnailImage(Delegate* delegate);
bool has_data() const { return data_.get(); }
void AddObserver(Observer* observer); void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer); void RemoveObserver(Observer* observer);
bool HasObserver(const Observer* observer) const; bool HasObserver(const Observer* observer) const;
......
...@@ -255,6 +255,7 @@ class TabHoverCardBubbleView::WidgetSlideAnimationDelegate ...@@ -255,6 +255,7 @@ class TabHoverCardBubbleView::WidgetSlideAnimationDelegate
void AnimationEnded(const gfx::Animation* animation) override { void AnimationEnded(const gfx::Animation* animation) override {
desired_anchor_view_ = nullptr; desired_anchor_view_ = nullptr;
bubble_delegate_->OnHoverCardLanded();
} }
void AnimationCanceled(const gfx::Animation* animation) override { void AnimationCanceled(const gfx::Animation* animation) override {
...@@ -411,6 +412,7 @@ void TabHoverCardBubbleView::UpdateAndShow(Tab* tab) { ...@@ -411,6 +412,7 @@ void TabHoverCardBubbleView::UpdateAndShow(Tab* tab) {
!slide_animation_delegate_->is_animating()) { !slide_animation_delegate_->is_animating()) {
widget_->SetBounds(slide_animation_delegate_->CalculateTargetBounds(tab)); widget_->SetBounds(slide_animation_delegate_->CalculateTargetBounds(tab));
slide_animation_delegate_->SetCurrentBounds(); slide_animation_delegate_->SetCurrentBounds();
OnHoverCardLanded();
return; return;
} }
...@@ -424,6 +426,7 @@ void TabHoverCardBubbleView::UpdateAndShow(Tab* tab) { ...@@ -424,6 +426,7 @@ void TabHoverCardBubbleView::UpdateAndShow(Tab* tab) {
SetAnchorView(tab); SetAnchorView(tab);
widget_->SetBounds(slide_animation_delegate_->CalculateTargetBounds(tab)); widget_->SetBounds(slide_animation_delegate_->CalculateTargetBounds(tab));
slide_animation_delegate_->SetCurrentBounds(); slide_animation_delegate_->SetCurrentBounds();
OnHoverCardLanded();
} }
if (!widget_->IsVisible()) { if (!widget_->IsVisible()) {
...@@ -599,8 +602,6 @@ void TabHoverCardBubbleView::UpdateCardContent(const Tab* tab) { ...@@ -599,8 +602,6 @@ void TabHoverCardBubbleView::UpdateCardContent(const Tab* tab) {
// If the preview image feature is not enabled, |preview_image_| will be null. // If the preview image feature is not enabled, |preview_image_| will be null.
if (preview_image_ && preview_image_->GetVisible()) { if (preview_image_ && preview_image_->GetVisible()) {
if (tab->data().thumbnail != thumbnail_image_)
ClearPreviewImage();
RegisterToThumbnailImageUpdates(tab->data().thumbnail); RegisterToThumbnailImageUpdates(tab->data().thumbnail);
} }
} }
...@@ -609,11 +610,18 @@ void TabHoverCardBubbleView::RegisterToThumbnailImageUpdates( ...@@ -609,11 +610,18 @@ void TabHoverCardBubbleView::RegisterToThumbnailImageUpdates(
scoped_refptr<ThumbnailImage> thumbnail_image) { scoped_refptr<ThumbnailImage> thumbnail_image) {
if (thumbnail_image_ == thumbnail_image) if (thumbnail_image_ == thumbnail_image)
return; return;
if (thumbnail_image_) { if (thumbnail_image_) {
thumbnail_observer_.Remove(thumbnail_image_.get()); thumbnail_observer_.Remove(thumbnail_image_.get());
thumbnail_image_.reset(); thumbnail_image_.reset();
} }
if (thumbnail_image) { if (thumbnail_image) {
if (!thumbnail_image->has_data())
ClearPreviewImage();
else
waiting_for_decompress_ = true;
thumbnail_image_ = thumbnail_image; thumbnail_image_ = thumbnail_image;
thumbnail_observer_.Add(thumbnail_image_.get()); thumbnail_observer_.Add(thumbnail_image_.get());
thumbnail_image->RequestThumbnailImage(); thumbnail_image->RequestThumbnailImage();
...@@ -645,6 +653,17 @@ void TabHoverCardBubbleView::ClearPreviewImage() { ...@@ -645,6 +653,17 @@ void TabHoverCardBubbleView::ClearPreviewImage() {
preview_image_->SetBackground( preview_image_->SetBackground(
views::CreateSolidBackground(background_color)); views::CreateSolidBackground(background_color));
} }
waiting_for_decompress_ = false;
}
void TabHoverCardBubbleView::OnHoverCardLanded() {
// If we were waiting for a preview image with data to load, we don't want to
// keep showing the old image while hovering on the new tab, so clear it. This
// shouldn't happen very often for slide animations, but could on slower
// computers.
if (waiting_for_decompress_)
ClearPreviewImage();
} }
void TabHoverCardBubbleView::OnThumbnailImageAvailable( void TabHoverCardBubbleView::OnThumbnailImageAvailable(
...@@ -654,6 +673,7 @@ void TabHoverCardBubbleView::OnThumbnailImageAvailable( ...@@ -654,6 +673,7 @@ void TabHoverCardBubbleView::OnThumbnailImageAvailable(
preview_image_->SetImageSize(preview_size); preview_image_->SetImageSize(preview_size);
preview_image_->SetPreferredSize(preview_size); preview_image_->SetPreferredSize(preview_size);
preview_image_->SetBackground(nullptr); preview_image_->SetBackground(nullptr);
waiting_for_decompress_ = false;
} }
base::Optional<gfx::Size> TabHoverCardBubbleView::GetThumbnailSizeHint() const { base::Optional<gfx::Size> TabHoverCardBubbleView::GetThumbnailSizeHint() const {
......
...@@ -83,6 +83,11 @@ class TabHoverCardBubbleView : public views::BubbleDialogDelegateView, ...@@ -83,6 +83,11 @@ class TabHoverCardBubbleView : public views::BubbleDialogDelegateView,
void ClearPreviewImage(); void ClearPreviewImage();
// Called when a hover card lands on the tab it's supposed to be a preview
// for; happens immediately if there is no slide animation, otherwise when the
// animation completes.
void OnHoverCardLanded();
// ThumbnailImage::Observer: // ThumbnailImage::Observer:
void OnThumbnailImageAvailable(gfx::ImageSkia thumbnail_image) override; void OnThumbnailImageAvailable(gfx::ImageSkia thumbnail_image) override;
base::Optional<gfx::Size> GetThumbnailSizeHint() const override; base::Optional<gfx::Size> GetThumbnailSizeHint() const override;
...@@ -115,12 +120,13 @@ class TabHoverCardBubbleView : public views::BubbleDialogDelegateView, ...@@ -115,12 +120,13 @@ class TabHoverCardBubbleView : public views::BubbleDialogDelegateView,
views::Label* domain_label_ = nullptr; views::Label* domain_label_ = nullptr;
views::ImageView* preview_image_ = nullptr; views::ImageView* preview_image_ = nullptr;
// Counter used to keey track of the number of tab hover cards seen before a // Counter used to keep track of the number of tab hover cards seen before a
// tab is selected by mouse press. // tab is selected by mouse press.
size_t hover_cards_seen_count_ = 0; size_t hover_cards_seen_count_ = 0;
scoped_refptr<ThumbnailImage> thumbnail_image_; scoped_refptr<ThumbnailImage> thumbnail_image_;
ScopedObserver<ThumbnailImage, ThumbnailImage::Observer> thumbnail_observer_{ ScopedObserver<ThumbnailImage, ThumbnailImage::Observer> thumbnail_observer_{
this}; this};
bool waiting_for_decompress_ = false;
base::WeakPtrFactory<TabHoverCardBubbleView> weak_factory_{this}; base::WeakPtrFactory<TabHoverCardBubbleView> weak_factory_{this};
......
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