| Index: ui/message_center/views/message_popup_collection.cc
|
| diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc
|
| index 76bd6ff8d934abc1cd07190afd6e1c0bac1ded87..3f0bc2ae7e3cc0bf26b27e2e31aa1ce948272f57 100644
|
| --- a/ui/message_center/views/message_popup_collection.cc
|
| +++ b/ui/message_center/views/message_popup_collection.cc
|
| @@ -24,6 +24,7 @@
|
| #include "ui/message_center/notification_list.h"
|
| #include "ui/message_center/views/message_view_context_menu_controller.h"
|
| #include "ui/message_center/views/notification_view.h"
|
| +#include "ui/message_center/views/popup_alignment_delegate.h"
|
| #include "ui/message_center/views/toast_contents_view.h"
|
| #include "ui/views/background.h"
|
| #include "ui/views/layout/fill_layout.h"
|
| @@ -43,45 +44,32 @@ const int kMouseExitedDeferTimeoutMs = 200;
|
| // The margin between messages (and between the anchor unless
|
| // first_item_has_no_margin was specified).
|
| const int kToastMarginY = kMarginBetweenItems;
|
| -#if defined(OS_CHROMEOS)
|
| -const int kToastMarginX = 3;
|
| -#else
|
| -const int kToastMarginX = kMarginBetweenItems;
|
| -#endif
|
| -
|
| -
|
| -// If there should be no margin for the first item, this value needs to be
|
| -// substracted to flush the message to the shelf (the width of the border +
|
| -// shadow).
|
| -const int kNoToastMarginBorderAndShadowOffset = 2;
|
|
|
| } // namespace.
|
|
|
| -MessagePopupCollection::MessagePopupCollection(gfx::NativeView parent,
|
| - MessageCenter* message_center,
|
| - MessageCenterTray* tray,
|
| - bool first_item_has_no_margin)
|
| +MessagePopupCollection::MessagePopupCollection(
|
| + gfx::NativeView parent,
|
| + MessageCenter* message_center,
|
| + MessageCenterTray* tray,
|
| + PopupAlignmentDelegate* alignment_delegate)
|
| : parent_(parent),
|
| message_center_(message_center),
|
| tray_(tray),
|
| - display_id_(gfx::Display::kInvalidDisplayID),
|
| - screen_(NULL),
|
| + alignment_delegate_(alignment_delegate),
|
| defer_counter_(0),
|
| latest_toast_entered_(NULL),
|
| user_is_closing_toasts_by_clicking_(false),
|
| - first_item_has_no_margin_(first_item_has_no_margin),
|
| context_menu_controller_(new MessageViewContextMenuController(this)),
|
| weak_factory_(this) {
|
| DCHECK(message_center_);
|
| defer_timer_.reset(new base::OneShotTimer<MessagePopupCollection>);
|
| message_center_->AddObserver(this);
|
| + alignment_delegate_->set_collection(this);
|
| }
|
|
|
| MessagePopupCollection::~MessagePopupCollection() {
|
| weak_factory_.InvalidateWeakPtrs();
|
|
|
| - if (screen_)
|
| - screen_->RemoveObserver(this);
|
| message_center_->RemoveObserver(this);
|
|
|
| CloseAllWidgets();
|
| @@ -132,7 +120,7 @@ void MessagePopupCollection::UpdateWidgets() {
|
| return;
|
| }
|
|
|
| - bool top_down = alignment_ & POPUP_ALIGNMENT_TOP;
|
| + bool top_down = alignment_delegate_->IsTopDown();
|
| int base = GetBaseLine(toasts_.empty() ? NULL : toasts_.back());
|
|
|
| // Iterate in the reverse order to keep the oldest toasts on screen. Newer
|
| @@ -148,7 +136,8 @@ void MessagePopupCollection::UpdateWidgets() {
|
| true); // Create top-level notification.
|
| view->set_context_menu_controller(context_menu_controller_.get());
|
| int view_height = ToastContentsView::GetToastSizeForView(view).height();
|
| - int height_available = top_down ? work_area_.bottom() - base : base;
|
| + int height_available =
|
| + top_down ? alignment_delegate_->GetWorkAreaBottom() - base : base;
|
|
|
| if (height_available - view_height - kToastMarginY < 0) {
|
| delete view;
|
| @@ -163,9 +152,10 @@ void MessagePopupCollection::UpdateWidgets() {
|
| view->set_controller(toast);
|
|
|
| gfx::Size preferred_size = toast->GetPreferredSize();
|
| - gfx::Point origin(GetToastOriginX(gfx::Rect(preferred_size)), base);
|
| + gfx::Point origin(
|
| + alignment_delegate_->GetToastOriginX(gfx::Rect(preferred_size)), base);
|
| // The toast slides in from the edge of the screen horizontally.
|
| - if (alignment_ & POPUP_ALIGNMENT_LEFT)
|
| + if (alignment_delegate_->IsFromLeft())
|
| origin.set_x(origin.x() - preferred_size.width());
|
| else
|
| origin.set_x(origin.x() + preferred_size.width());
|
| @@ -253,36 +243,23 @@ void MessagePopupCollection::RemoveToast(ToastContentsView* toast,
|
| message_center_->MarkSinglePopupAsShown(toast->id(), false);
|
| }
|
|
|
| -int MessagePopupCollection::GetToastOriginX(const gfx::Rect& toast_bounds)
|
| - const {
|
| -#if defined(OS_CHROMEOS)
|
| - // In ChromeOS, RTL UI language mirrors the whole desktop layout, so the toast
|
| - // widgets should be at the bottom-left instead of bottom right.
|
| - if (base::i18n::IsRTL())
|
| - return work_area_.x() + kToastMarginX;
|
| -#endif
|
| - if (alignment_ & POPUP_ALIGNMENT_LEFT)
|
| - return work_area_.x() + kToastMarginX;
|
| - return work_area_.right() - kToastMarginX - toast_bounds.width();
|
| -}
|
| -
|
| void MessagePopupCollection::RepositionWidgets() {
|
| - bool top_down = alignment_ & POPUP_ALIGNMENT_TOP;
|
| + bool top_down = alignment_delegate_->IsTopDown();
|
| int base = GetBaseLine(NULL); // We don't want to position relative to last
|
| // toast - we want re-position.
|
|
|
| for (Toasts::const_iterator iter = toasts_.begin(); iter != toasts_.end();) {
|
| Toasts::const_iterator curr = iter++;
|
| gfx::Rect bounds((*curr)->bounds());
|
| - bounds.set_x(GetToastOriginX(bounds));
|
| - bounds.set_y(alignment_ & POPUP_ALIGNMENT_TOP ? base
|
| - : base - bounds.height());
|
| + bounds.set_x(alignment_delegate_->GetToastOriginX(bounds));
|
| + bounds.set_y(top_down ? base : base - bounds.height());
|
|
|
| // The notification may scrolls the boundary of the screen due to image
|
| // load and such notifications should disappear. Do not call
|
| // CloseWithAnimation, we don't want to show the closing animation, and we
|
| // don't want to mark such notifications as shown. See crbug.com/233424
|
| - if ((top_down ? work_area_.bottom() - bounds.bottom() : bounds.y()) >= 0)
|
| + if ((top_down ? alignment_delegate_->GetWorkAreaBottom() - bounds.bottom()
|
| + : bounds.y()) >= 0)
|
| (*curr)->SetBoundsWithAnimation(bounds);
|
| else
|
| RemoveToast(*curr, /*mark_as_shown=*/false);
|
| @@ -300,7 +277,7 @@ void MessagePopupCollection::RepositionWidgetsWithTarget() {
|
| if (toasts_.empty())
|
| return;
|
|
|
| - bool top_down = alignment_ & POPUP_ALIGNMENT_TOP;
|
| + bool top_down = alignment_delegate_->IsTopDown();
|
|
|
| // Nothing to do if there are no widgets above target if bottom-aligned or no
|
| // widgets below target if top-aligned.
|
| @@ -337,53 +314,14 @@ void MessagePopupCollection::RepositionWidgetsWithTarget() {
|
| }
|
| }
|
|
|
| -void MessagePopupCollection::ComputePopupAlignment(gfx::Rect work_area,
|
| - gfx::Rect screen_bounds) {
|
| - // If the taskbar is at the top, render notifications top down. Some platforms
|
| - // like Gnome can have taskbars at top and bottom. In this case it's more
|
| - // likely that the systray is on the top one.
|
| - alignment_ = work_area.y() > screen_bounds.y() ? POPUP_ALIGNMENT_TOP
|
| - : POPUP_ALIGNMENT_BOTTOM;
|
| -
|
| - // If the taskbar is on the left show the notifications on the left. Otherwise
|
| - // show it on right since it's very likely that the systray is on the right if
|
| - // the taskbar is on the top or bottom.
|
| - // Since on some platforms like Ubuntu Unity there's also a launcher along
|
| - // with a taskbar (panel), we need to check that there is really nothing at
|
| - // the top before concluding that the taskbar is at the left.
|
| - alignment_ = static_cast<PopupAlignment>(
|
| - alignment_ |
|
| - ((work_area.x() > screen_bounds.x() && work_area.y() == screen_bounds.y())
|
| - ? POPUP_ALIGNMENT_LEFT
|
| - : POPUP_ALIGNMENT_RIGHT));
|
| -}
|
| -
|
| int MessagePopupCollection::GetBaseLine(ToastContentsView* last_toast) const {
|
| - bool top_down = alignment_ & POPUP_ALIGNMENT_TOP;
|
| - int base;
|
| -
|
| - if (top_down) {
|
| - if (!last_toast) {
|
| - base = work_area_.y();
|
| - if (!first_item_has_no_margin_)
|
| - base += kToastMarginY;
|
| - else
|
| - base -= kNoToastMarginBorderAndShadowOffset;
|
| - } else {
|
| - base = toasts_.back()->bounds().bottom() + kToastMarginY;
|
| - }
|
| + if (!last_toast) {
|
| + return alignment_delegate_->GetBaseLine();
|
| + } else if (alignment_delegate_->IsTopDown()) {
|
| + return toasts_.back()->bounds().bottom() + kToastMarginY;
|
| } else {
|
| - if (!last_toast) {
|
| - base = work_area_.bottom();
|
| - if (!first_item_has_no_margin_)
|
| - base -= kToastMarginY;
|
| - else
|
| - base += kNoToastMarginBorderAndShadowOffset;
|
| - } else {
|
| - base = toasts_.back()->origin().y() - kToastMarginY;
|
| - }
|
| + return toasts_.back()->origin().y() - kToastMarginY;
|
| }
|
| - return base;
|
| }
|
|
|
| void MessagePopupCollection::OnNotificationAdded(
|
| @@ -508,28 +446,6 @@ void MessagePopupCollection::DecrementDeferCounter() {
|
| // deferred tasks are even able to run)
|
| // Then, see if there is vacant space for new toasts.
|
| void MessagePopupCollection::DoUpdateIfPossible() {
|
| - if (!screen_) {
|
| - gfx::Display display;
|
| - if (!parent_) {
|
| - // On Win+Aura, we don't have a parent since the popups currently show up
|
| - // on the Windows desktop, not in the Aura/Ash desktop. This code will
|
| - // display the popups on the primary display.
|
| - screen_ = gfx::Screen::GetNativeScreen();
|
| - display = screen_->GetPrimaryDisplay();
|
| - } else {
|
| - screen_ = gfx::Screen::GetScreenFor(parent_);
|
| - display = screen_->GetDisplayNearestWindow(parent_);
|
| - }
|
| - screen_->AddObserver(this);
|
| -
|
| - display_id_ = display.id();
|
| - // |work_area_| can be set already and it should not be overwritten here.
|
| - if (work_area_.IsEmpty()) {
|
| - work_area_ = display.work_area();
|
| - ComputePopupAlignment(work_area_, display.bounds());
|
| - }
|
| - }
|
| -
|
| if (defer_counter_ > 0)
|
| return;
|
|
|
| @@ -551,33 +467,9 @@ void MessagePopupCollection::DoUpdateIfPossible() {
|
| run_loop_for_test_->Quit();
|
| }
|
|
|
| -void MessagePopupCollection::SetDisplayInfo(const gfx::Rect& work_area,
|
| - const gfx::Rect& screen_bounds) {
|
| - if (work_area_ == work_area)
|
| - return;
|
| -
|
| - work_area_ = work_area;
|
| - ComputePopupAlignment(work_area, screen_bounds);
|
| - RepositionWidgets();
|
| -}
|
| -
|
| -void MessagePopupCollection::OnDisplayAdded(const gfx::Display& new_display) {
|
| -}
|
| -
|
| -void MessagePopupCollection::OnDisplayRemoved(const gfx::Display& old_display) {
|
| - if (display_id_ == old_display.id() && !parent_) {
|
| - gfx::Display display = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
|
| - display_id_ = display.id();
|
| - SetDisplayInfo(display.work_area(), display.bounds());
|
| - }
|
| -}
|
| -
|
| void MessagePopupCollection::OnDisplayMetricsChanged(
|
| - const gfx::Display& display, uint32_t metrics) {
|
| - if (display.id() != display_id_)
|
| - return;
|
| -
|
| - SetDisplayInfo(display.work_area(), display.bounds());
|
| + const gfx::Display& display) {
|
| + alignment_delegate_->RecomputeAlignment(display);
|
| }
|
|
|
| views::Widget* MessagePopupCollection::GetWidgetForTest(const std::string& id)
|
|
|