Skip to content

Commit

Permalink
NotifierCollision: Move notifier collision code to a different class
Browse files Browse the repository at this point in the history
Move all the notifier collision code to a separate class. This makes the
code in AshMessagePopupCollection more organized and easier to read.
This CL just moves code without adding any new logic.

Change-Id: Iaa028dcb22ea79e9790980558faa1bdaebf171ee
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4807769
Commit-Queue: Andre Le <leandre@chromium.org>
Reviewed-by: Alex Newcomer <newcomer@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1188110}
  • Loading branch information
Andre Le authored and Chromium LUCI CQ committed Aug 25, 2023
1 parent 8482725 commit 8b20be1
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 139 deletions.
250 changes: 137 additions & 113 deletions ash/system/message_center/ash_message_popup_collection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "ash/system/message_center/ash_message_popup_collection.h"

#include <cstdint>
#include <memory>

#include "ash/constants/ash_constants.h"
#include "ash/constants/ash_features.h"
Expand Down Expand Up @@ -57,15 +58,147 @@ void ReportPopupAnimationSmoothness(int smoothness) {
const char AshMessagePopupCollection::kMessagePopupWidgetName[] =
"ash/message_center/MessagePopup";

///////////////////////////////////////////////////////////////////////////////
// NotifierCollisionHandler:

AshMessagePopupCollection::NotifierCollisionHandler::NotifierCollisionHandler(
AshMessagePopupCollection* popup_collection)
: popup_collection_(popup_collection) {
Shell::Get()->system_tray_notifier()->AddSystemTrayObserver(this);
}

AshMessagePopupCollection::NotifierCollisionHandler::
~NotifierCollisionHandler() {
Shell::Get()->system_tray_notifier()->RemoveSystemTrayObserver(this);
}

void AshMessagePopupCollection::NotifierCollisionHandler::
OnStatusAreaAnchoredBubbleVisibilityChanged(TrayBubbleView* tray_bubble,
bool visible) {
AdjustBaselineBasedOnBubbleChange(tray_bubble, /*bubble_visible=*/visible);
}

void AshMessagePopupCollection::NotifierCollisionHandler::
OnTrayBubbleBoundsChanged(TrayBubbleView* tray_bubble) {
AdjustBaselineBasedOnBubbleChange(tray_bubble, /*bubble_visible=*/true);
}

void AshMessagePopupCollection::NotifierCollisionHandler::
AdjustBaselineBasedOnBubbleChange(TrayBubbleView* tray_bubble,
bool bubble_visible) {
if (!features::IsNotifierCollisionEnabled()) {
return;
}

if (tray_bubble && tray_bubble->GetBubbleType() ==
TrayBubbleView::TrayBubbleType::kSecondaryBubble) {
AdjustBaselineBasedOnSecondaryBubble(tray_bubble, bubble_visible);
return;
}

AdjustBaselineBasedOnShelfPodBubble(/*triggered_by_bubble_change=*/true);
}

void AshMessagePopupCollection::NotifierCollisionHandler::
AdjustBaselineBasedOnShelfPodBubble(bool triggered_by_bubble_change) {
CHECK(features::IsNotifierCollisionEnabled());

auto* status_area =
StatusAreaWidget::ForWindow(popup_collection_->shelf_->GetWindow());
auto* shelf_pod_anchored_bubble =
status_area ? status_area->open_shelf_pod_bubble() : nullptr;

// The tray bubble might already be closed/deleted. We also only put the popup
// on top of tray bubble that is anchored to the shelf corner.
if (!shelf_pod_anchored_bubble ||
!shelf_pod_anchored_bubble->IsAnchoredToShelfCorner()) {
popup_collection_->SetBaselineOffset(0);
return;
}

// If there's not enough space above the tray bubble to display the entire
// popup collection, we will close the popups or the bubble since we want to
// avoid showing tray bubble and popups overlapping with each other.
if (shelf_pod_anchored_bubble->GetBoundsInScreen().y() -
message_center::kMarginBetweenPopups <
popup_collection_->popup_collection_bounds().height()) {
// When this function is triggered by a change that happens in the bubble
// (bubble size or visibility changed), we will close the popup. Otherwise,
// we will close the bubble.
if (triggered_by_bubble_change) {
popup_collection_->CloseAllPopupsNow();
popup_collection_->ResetBounds();
} else {
shelf_pod_anchored_bubble->CloseBubbleView();

// Reset and move down popups if tray bubble is closed.
popup_collection_->SetBaselineOffset(0);
popup_collection_->MoveDownPopups();
}
return;
}

popup_collection_->SetBaselineOffset(shelf_pod_anchored_bubble->height());
RecordPopupOnTopOfBubbleCount();
}

void AshMessagePopupCollection::NotifierCollisionHandler::
AdjustBaselineBasedOnSecondaryBubble(TrayBubbleView* tray_bubble,
bool visible) {
CHECK(features::IsNotifierCollisionEnabled());

CHECK(tray_bubble);
CHECK_EQ(tray_bubble->GetBubbleType(),
TrayBubbleView::TrayBubbleType::kSecondaryBubble);

auto* status_area =
StatusAreaWidget::ForWindow(popup_collection_->shelf_->GetWindow());
auto* current_open_shelf_pod_bubble =
status_area ? status_area->open_shelf_pod_bubble() : nullptr;

// If there's a current open shelf pod bubble, the popup should be on top of
// that bubble, not on top of the secondary bubble, so do nothing here.
if (current_open_shelf_pod_bubble &&
current_open_shelf_pod_bubble != tray_bubble) {
return;
}

// Only adjust the baseline if the secondary bubble is in the same display.
if (display::Screen::GetScreen()->GetDisplayNearestWindow(
tray_bubble->parent_window()) !=
popup_collection_->GetCurrentDisplay()) {
return;
}

popup_collection_->SetBaselineOffset(visible ? tray_bubble->height() : 0);
RecordPopupOnTopOfBubbleCount();
}

void AshMessagePopupCollection::NotifierCollisionHandler::
RecordPopupOnTopOfBubbleCount() {
int popup_items_count = popup_collection_->popup_items().size();
if (!features::IsNotifierCollisionEnabled() || popup_items_count == 0) {
return;
}

// Record the number of popups that are moved up.
base::UmaHistogramCounts100("Ash.NotificationPopup.OnTopOfBubbleCount",
popup_items_count);
}

///////////////////////////////////////////////////////////////////////////////
// AshMessagePopupCollection:

AshMessagePopupCollection::AshMessagePopupCollection(Shelf* shelf)
: screen_(nullptr), shelf_(shelf) {
notifier_collision_handler_ =
std::make_unique<NotifierCollisionHandler>(this);

shelf_->AddObserver(this);
Shell::Get()->tablet_mode_controller()->AddObserver(this);
Shell::Get()->system_tray_notifier()->AddSystemTrayObserver(this);
}

AshMessagePopupCollection::~AshMessagePopupCollection() {
Shell::Get()->system_tray_notifier()->RemoveSystemTrayObserver(this);
Shell::Get()->tablet_mode_controller()->RemoveObserver(this);
shelf_->RemoveObserver(this);
for (views::Widget* widget : tracked_widgets_)
Expand All @@ -92,8 +225,6 @@ void AshMessagePopupCollection::SetBaselineOffset(int baseline_offset) {
DCHECK_GE(baseline_offset_, 0);
if (baseline_offset_ != 0) {
baseline_offset_ += message_center::kMarginBetweenPopups;

RecordPopupOnTopOfBubbleCount();
}

if (old_baseline_offset != baseline_offset_) {
Expand Down Expand Up @@ -203,7 +334,8 @@ void AshMessagePopupCollection::NotifyPopupCollectionHeightChanged() {
return;
}

AdjustBaselineBasedOnShelfPodBubble(/*triggered_by_bubble_change=*/false);
notifier_collision_handler_->AdjustBaselineBasedOnShelfPodBubble(
/*triggered_by_bubble_change=*/false);
}

void AshMessagePopupCollection::AnimationStarted() {
Expand Down Expand Up @@ -263,17 +395,6 @@ void AshMessagePopupCollection::OnTabletModeEnded() {
ResetBounds();
}

void AshMessagePopupCollection::OnStatusAreaAnchoredBubbleVisibilityChanged(
TrayBubbleView* tray_bubble,
bool visible) {
AdjustBaselineBasedOnBubbleChange(tray_bubble, /*bubble_visible=*/visible);
}

void AshMessagePopupCollection::OnTrayBubbleBoundsChanged(
TrayBubbleView* tray_bubble) {
AdjustBaselineBasedOnBubbleChange(tray_bubble, /*bubble_visible=*/true);
}

bool AshMessagePopupCollection::IsWidgetAPopupNotification(
views::Widget* widget) {
for (auto* popup_widget : tracked_widgets_) {
Expand Down Expand Up @@ -334,92 +455,6 @@ void AshMessagePopupCollection::UpdateWorkArea() {
ResetBounds();
}

void AshMessagePopupCollection::AdjustBaselineBasedOnBubbleChange(
TrayBubbleView* tray_bubble,
bool bubble_visible) {
if (!features::IsNotifierCollisionEnabled()) {
return;
}

if (tray_bubble && tray_bubble->GetBubbleType() ==
TrayBubbleView::TrayBubbleType::kSecondaryBubble) {
AdjustBaselineBasedOnSecondaryBubble(tray_bubble, bubble_visible);
return;
}

AdjustBaselineBasedOnShelfPodBubble(/*triggered_by_bubble_change=*/true);
}

void AshMessagePopupCollection::AdjustBaselineBasedOnShelfPodBubble(
bool triggered_by_bubble_change) {
CHECK(features::IsNotifierCollisionEnabled());

auto* status_area = StatusAreaWidget::ForWindow(shelf_->GetWindow());
auto* shelf_pod_anchored_bubble =
status_area ? status_area->open_shelf_pod_bubble() : nullptr;

// The tray bubble might already be closed/deleted. We also only put the popup
// on top of tray bubble that is anchored to the shelf corner.
if (!shelf_pod_anchored_bubble ||
!shelf_pod_anchored_bubble->IsAnchoredToShelfCorner()) {
SetBaselineOffset(0);
return;
}

// If there's not enough space above the tray bubble to display the entire
// popup collection, we will close the popups or the bubble since we want to
// avoid showing tray bubble and popups overlapping with each other.
if (shelf_pod_anchored_bubble->GetBoundsInScreen().y() -
message_center::kMarginBetweenPopups <
popup_collection_bounds().height()) {
// When this function is triggered by a change that happens in the bubble
// (bubble size or visibility changed), we will close the popup. Otherwise,
// we will close the bubble.
if (triggered_by_bubble_change) {
CloseAllPopupsNow();
ResetBounds();
} else {
shelf_pod_anchored_bubble->CloseBubbleView();

// Reset and move down popups if tray bubble is closed.
SetBaselineOffset(0);
MoveDownPopups();
}
return;
}

SetBaselineOffset(shelf_pod_anchored_bubble->height());
}

void AshMessagePopupCollection::AdjustBaselineBasedOnSecondaryBubble(
TrayBubbleView* tray_bubble,
bool visible) {
CHECK(features::IsNotifierCollisionEnabled());

CHECK(tray_bubble);
CHECK_EQ(tray_bubble->GetBubbleType(),
TrayBubbleView::TrayBubbleType::kSecondaryBubble);

auto* status_area = StatusAreaWidget::ForWindow(shelf_->GetWindow());
auto* current_open_shelf_pod_bubble =
status_area ? status_area->open_shelf_pod_bubble() : nullptr;

// If there's a current open shelf pod bubble, the popup should be on top of
// that bubble, not on top of the secondary bubble, so do nothing here.
if (current_open_shelf_pod_bubble &&
current_open_shelf_pod_bubble != tray_bubble) {
return;
}

// Only adjust the baseline if the secondary bubble is in the same display.
if (display::Screen::GetScreen()->GetDisplayNearestWindow(
tray_bubble->parent_window()) != GetCurrentDisplay()) {
return;
}

SetBaselineOffset(visible ? tray_bubble->height() : 0);
}

///////////////////////////////////////////////////////////////////////////////
// ShelfObserver:

Expand Down Expand Up @@ -460,15 +495,4 @@ void AshMessagePopupCollection::OnWidgetActivationChanged(views::Widget* widget,
widget->GetFocusManager()->SetFocusedView(widget->GetContentsView());
}

void AshMessagePopupCollection::RecordPopupOnTopOfBubbleCount() {
int popup_items_count = popup_items().size();
if (!features::IsNotifierCollisionEnabled() || popup_items_count == 0) {
return;
}

// Record the number of popups that are moved up.
base::UmaHistogramCounts100("Ash.NotificationPopup.OnTopOfBubbleCount",
popup_items_count);
}

} // namespace ash

0 comments on commit 8b20be1

Please sign in to comment.