From a4d8d9c79709ed6588641a91cd603ea174acfdee Mon Sep 17 00:00:00 2001 From: Aleksey Seren Date: Thu, 9 Sep 2021 18:34:03 +0700 Subject: [PATCH] Snap custom ad notification to the screen edge. fix https://github.com/brave/brave-browser/issues/17527 --- .../views/brave_ads/ad_notification_popup.cc | 25 +++---- .../views/brave_ads/ad_notification_popup.h | 1 - .../views/brave_ads/ad_notification_view.cc | 2 +- browser/ui/views/brave_ads/bounds_util.cc | 72 ++++++++++++++++++- browser/ui/views/brave_ads/bounds_util.h | 4 +- 5 files changed, 84 insertions(+), 20 deletions(-) diff --git a/browser/ui/views/brave_ads/ad_notification_popup.cc b/browser/ui/views/brave_ads/ad_notification_popup.cc index b9d8f9c635a8..c4e5a66ccd25 100644 --- a/browser/ui/views/brave_ads/ad_notification_popup.cc +++ b/browser/ui/views/brave_ads/ad_notification_popup.cc @@ -82,6 +82,15 @@ class DefaultPopupInstanceFactory } }; +void AdjustBoundsAndSnapToFitWorkAreaForWidget(views::Widget* widget) { + DCHECK(widget); + + gfx::Rect bounds = widget->GetWindowBoundsInScreen(); + const gfx::NativeView native_view = widget->GetNativeView(); + AdjustBoundsAndSnapToFitWorkAreaForNativeView(native_view, &bounds); + widget->SetBounds(bounds); +} + } // namespace AdNotificationPopup::PopupInstanceFactory::~PopupInstanceFactory() = default; @@ -268,16 +277,6 @@ void AdNotificationPopup::OnThemeChanged() { SchedulePaint(); } -void AdNotificationPopup::OnWidgetCreated(views::Widget* widget) { - DCHECK(widget); - - gfx::Rect bounds = widget->GetWindowBoundsInScreen(); - const gfx::NativeView native_view = widget->GetNativeView(); - AdjustBoundsToFitWorkAreaForNativeView(&bounds, native_view); - - widget->SetBounds(bounds); -} - void AdNotificationPopup::OnWidgetDestroyed(views::Widget* widget) { DCHECK(widget); @@ -432,10 +431,7 @@ void AdNotificationPopup::RecomputeAlignment() { return; } - gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen(); - const gfx::NativeView native_view = GetWidget()->GetNativeView(); - AdjustBoundsToFitWorkAreaForNativeView(&bounds, native_view); - GetWidget()->SetBounds(bounds); + AdjustBoundsAndSnapToFitWorkAreaForWidget(GetWidget()); } const gfx::ShadowDetails& AdNotificationPopup::GetShadowDetails() const { @@ -459,6 +455,7 @@ void AdNotificationPopup::CreateWidgetView() { if (!g_disable_fade_in_animation_for_testing) { widget->SetOpacity(0.0); } + AdjustBoundsAndSnapToFitWorkAreaForWidget(widget); widget->ShowInactive(); } diff --git a/browser/ui/views/brave_ads/ad_notification_popup.h b/browser/ui/views/brave_ads/ad_notification_popup.h index ca5d9944f2f8..4ca129c60334 100644 --- a/browser/ui/views/brave_ads/ad_notification_popup.h +++ b/browser/ui/views/brave_ads/ad_notification_popup.h @@ -102,7 +102,6 @@ class AdNotificationPopup : public views::WidgetDelegateView, void OnThemeChanged() override; // views::WidgetObserver: - void OnWidgetCreated(views::Widget* widget) override; void OnWidgetDestroyed(views::Widget* widget) override; void OnWidgetBoundsChanged(views::Widget* widget, const gfx::Rect& new_bounds) override; diff --git a/browser/ui/views/brave_ads/ad_notification_view.cc b/browser/ui/views/brave_ads/ad_notification_view.cc index 2dede9865aae..fd7266e49a4d 100644 --- a/browser/ui/views/brave_ads/ad_notification_view.cc +++ b/browser/ui/views/brave_ads/ad_notification_view.cc @@ -81,7 +81,7 @@ bool AdNotificationView::OnMouseDragged(const ui::MouseEvent& event) { const std::string id = ad_notification_.id(); gfx::Rect bounds = AdNotificationPopup::GetBounds(id) + movement; const gfx::NativeView native_view = GetWidget()->GetNativeView(); - AdjustBoundsToFitWorkAreaForNativeView(&bounds, native_view); + AdjustBoundsAndSnapToFitWorkAreaForNativeView(native_view, &bounds); GetWidget()->SetBounds(bounds); return true; diff --git a/browser/ui/views/brave_ads/bounds_util.cc b/browser/ui/views/brave_ads/bounds_util.cc index ae61fb275d40..f6dab34891b1 100644 --- a/browser/ui/views/brave_ads/bounds_util.cc +++ b/browser/ui/views/brave_ads/bounds_util.cc @@ -6,12 +6,17 @@ #include "brave/browser/ui/views/brave_ads/bounds_util.h" #include "ui/display/screen.h" +#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" namespace brave_ads { -void AdjustBoundsToFitWorkAreaForNativeView(gfx::Rect* bounds, - gfx::NativeView native_view) { +namespace { + +enum class EdgeGravity { kTop, kBottom, kLeft, kRight }; + +gfx::Rect GetDisplayScreenWorkArea(gfx::Rect* bounds, + gfx::NativeView native_view) { DCHECK(bounds); gfx::Rect work_area = @@ -25,7 +30,70 @@ void AdjustBoundsToFitWorkAreaForNativeView(gfx::Rect* bounds, .work_area(); } + return work_area; +} + +void AdjustBoundsToFitWorkAreaForNativeView(const gfx::Rect& work_area, + gfx::Rect* bounds) { + DCHECK(bounds); + bounds->AdjustToFit(work_area); } +void SnapBoundsToEdgeOfWorkAreaForNativeView(const gfx::Rect& work_area, + gfx::Rect* bounds) { + DCHECK(bounds); + + // Find the nearest screen edge to bounds center point. + const gfx::Point center(bounds->x() + bounds->width() / 2, + bounds->y() + bounds->height() / 2); + EdgeGravity gravity = EdgeGravity::kTop; + int min_dist = bounds->y() - work_area.y(); + + int dist = + work_area.y() + work_area.height() - bounds->y() - bounds->height(); + if (min_dist > dist) { + min_dist = dist; + gravity = EdgeGravity::kBottom; + } + + dist = bounds->x() - work_area.x(); + if (min_dist > dist) { + min_dist = dist; + gravity = EdgeGravity::kLeft; + } + + dist = work_area.x() + work_area.width() - bounds->x() - bounds->width(); + if (min_dist > dist) { + min_dist = dist; + gravity = EdgeGravity::kRight; + } + + switch (gravity) { + case EdgeGravity::kTop: + bounds->set_y(work_area.y()); + break; + case EdgeGravity::kBottom: + bounds->set_y(work_area.y() + work_area.height() - bounds->height()); + break; + case EdgeGravity::kLeft: + bounds->set_x(work_area.x()); + break; + case EdgeGravity::kRight: + bounds->set_x(work_area.x() + work_area.width() - bounds->width()); + break; + } +} + +} // namespace + +void AdjustBoundsAndSnapToFitWorkAreaForNativeView(gfx::NativeView native_view, + gfx::Rect* bounds) { + DCHECK(bounds); + + const gfx::Rect work_area = GetDisplayScreenWorkArea(bounds, native_view); + AdjustBoundsToFitWorkAreaForNativeView(work_area, bounds); + SnapBoundsToEdgeOfWorkAreaForNativeView(work_area, bounds); +} + } // namespace brave_ads diff --git a/browser/ui/views/brave_ads/bounds_util.h b/browser/ui/views/brave_ads/bounds_util.h index c0c762d6dbaa..3ec2a4259984 100644 --- a/browser/ui/views/brave_ads/bounds_util.h +++ b/browser/ui/views/brave_ads/bounds_util.h @@ -14,8 +14,8 @@ class Rect; namespace brave_ads { -void AdjustBoundsToFitWorkAreaForNativeView(gfx::Rect* bounds, - gfx::NativeView native_view); +void AdjustBoundsAndSnapToFitWorkAreaForNativeView(gfx::NativeView native_view, + gfx::Rect* bounds); } // namespace brave_ads