Commit 165e7384 authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

views: Account for transforms on a bubble's anchor widget.

In cros, normally overview related, we apply transforms on an anchor
widget (normal the browser). The browser may have a number of transient
bubbles associated with it. The transient bubbles get transformed to
the correct locations on entry, but when the anchor widget's bounds
update, we query the new transient bubbles bounds (and will transform).
The transient bubbles bounds include the transform of their anchor,
(GetAnchorBoundsInScreen()) applies transforms from descendants, so
their offset by the anchor widget's translation.

To counter this, undo the translation of the anchor widget when
fetching the anchor rectangle.

Easiest way to repro is by forcing the crash bubble to always show,
then entering overview and rotating the chromebook. For a browser
sized 1600x800 with anchor rect say 1500,0, after entering overview,
the browser has a translation of 100,100. After rotating, the
browser is sized 800x1600 and the anchor rect will be 800,100. On
exiting the bubble correctly relocates and the anchor rect is
seen to be 700,0.

Test: manual
Change-Id: Ie732e95e9b353cccfb7ae7158b6842596467d284
Fixed: 1004238, 1001039, 920134
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2305067
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Reviewed-by: default avatarAllen Bauer <kylixrd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790055}
parent 3030e0e7
...@@ -15,8 +15,10 @@ ...@@ -15,8 +15,10 @@
#include "ui/accessibility/ax_role_properties.h" #include "ui/accessibility/ax_role_properties.h"
#include "ui/base/default_style.h" #include "ui/base/default_style.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/layer_animation_element.h"
#include "ui/gfx/color_utils.h" #include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d_conversions.h"
#include "ui/native_theme/native_theme.h" #include "ui/native_theme/native_theme.h"
#include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/layout/layout_manager.h" #include "ui/views/layout/layout_manager.h"
...@@ -32,6 +34,9 @@ ...@@ -32,6 +34,9 @@
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
#include "ui/views/widget/widget_utils_mac.h" #include "ui/views/widget/widget_utils_mac.h"
#else
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#endif #endif
namespace views { namespace views {
...@@ -174,16 +179,29 @@ class BubbleDialogDelegate::AnchorViewObserver : public ViewObserver { ...@@ -174,16 +179,29 @@ class BubbleDialogDelegate::AnchorViewObserver : public ViewObserver {
// This class is responsible for observing events on a BubbleDialogDelegate's // This class is responsible for observing events on a BubbleDialogDelegate's
// anchor widget and notifying the BubbleDialogDelegate of them. // anchor widget and notifying the BubbleDialogDelegate of them.
#if defined(OS_MACOSX)
class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver { class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver {
#else
class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver,
public aura::WindowObserver {
#endif
public: public:
AnchorWidgetObserver(BubbleDialogDelegate* owner, Widget* widget) AnchorWidgetObserver(BubbleDialogDelegate* owner, Widget* widget)
: owner_(owner) { : owner_(owner) {
observer_.Add(widget); widget_observer_.Add(widget);
#if !defined(OS_MACOSX)
window_observer_.Add(widget->GetNativeWindow());
#endif
} }
~AnchorWidgetObserver() override = default; ~AnchorWidgetObserver() override = default;
// WidgetObserver:
void OnWidgetDestroying(Widget* widget) override { void OnWidgetDestroying(Widget* widget) override {
observer_.Remove(widget); #if !defined(OS_MACOSX)
window_observer_.Remove(widget->GetNativeWindow());
#endif
widget_observer_.Remove(widget);
owner_->OnAnchorWidgetDestroying(); owner_->OnAnchorWidgetDestroying();
// |this| may be destroyed here! // |this| may be destroyed here!
} }
...@@ -196,9 +214,28 @@ class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver { ...@@ -196,9 +214,28 @@ class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver {
owner_->OnAnchorBoundsChanged(); owner_->OnAnchorBoundsChanged();
} }
#if !defined(OS_MACOSX)
// aura::WindowObserver:
void OnWindowTransformed(aura::Window* window,
ui::PropertyChangeReason reason) override {
if (window->is_destroying())
return;
// Update the anchor bounds when the transform animation is complete, or
// when the transform is set without animation.
if (!window->layer()->GetAnimator()->IsAnimatingOnePropertyOf(
ui::LayerAnimationElement::TRANSFORM)) {
owner_->OnAnchorBoundsChanged();
}
}
#endif
private: private:
BubbleDialogDelegate* owner_; BubbleDialogDelegate* owner_;
ScopedObserver<views::Widget, views::WidgetObserver> observer_{this}; ScopedObserver<views::Widget, views::WidgetObserver> widget_observer_{this};
#if !defined(OS_MACOSX)
ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this};
#endif
}; };
// This class is responsible for observing events on a BubbleDialogDelegate's // This class is responsible for observing events on a BubbleDialogDelegate's
...@@ -511,6 +548,21 @@ gfx::Rect BubbleDialogDelegate::GetAnchorRect() const { ...@@ -511,6 +548,21 @@ gfx::Rect BubbleDialogDelegate::GetAnchorRect() const {
anchor_rect_ = GetAnchorView()->GetAnchorBoundsInScreen(); anchor_rect_ = GetAnchorView()->GetAnchorBoundsInScreen();
anchor_rect_->Inset(anchor_view_insets_); anchor_rect_->Inset(anchor_view_insets_);
#if !defined(OS_MACOSX)
// GetAnchorBoundsInScreen returns values that take anchor widget's
// translation into account, so undo that here. Without this, features which
// apply transforms on windows such as ChromeOS overview mode will see bubbles
// offset.
// TODO(sammiequon): Investigate if we can remove |anchor_widget_| and just
// replace its calls with GetAnchorView()->GetWidget().
DCHECK_EQ(anchor_widget_, GetAnchorView()->GetWidget());
gfx::Transform transform =
anchor_widget_->GetNativeWindow()->layer()->GetTargetTransform();
if (!transform.IsIdentity())
anchor_rect_->Offset(-gfx::ToRoundedVector2d(transform.To2dTranslation()));
#endif
return anchor_rect_.value(); return anchor_rect_.value();
} }
......
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