| Index: ash/system/tray/system_tray.cc
|
| diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc
|
| index fdc9e0a327df500d2eba3268dba975c3e4171185..9b0af532d17615c66d5a431f2eb91695f6b2330c 100644
|
| --- a/ash/system/tray/system_tray.cc
|
| +++ b/ash/system/tray/system_tray.cc
|
| @@ -243,6 +243,7 @@ void SystemTray::AddTrayItem(SystemTrayItem* item) {
|
| if (tray_item) {
|
| tray_container_->AddChildViewAt(tray_item, 0);
|
| PreferredSizeChanged();
|
| + tray_item_map_[item] = tray_item;
|
| }
|
| }
|
|
|
| @@ -251,7 +252,7 @@ void SystemTray::RemoveTrayItem(SystemTrayItem* item) {
|
| }
|
|
|
| void SystemTray::ShowDefaultView(BubbleCreationType creation_type) {
|
| - ShowItems(items_.get(), false, true, creation_type);
|
| + ShowDefaultViewWithOffset(creation_type, -1);
|
| }
|
|
|
| void SystemTray::ShowDetailedView(SystemTrayItem* item,
|
| @@ -260,7 +261,7 @@ void SystemTray::ShowDetailedView(SystemTrayItem* item,
|
| BubbleCreationType creation_type) {
|
| std::vector<SystemTrayItem*> items;
|
| items.push_back(item);
|
| - ShowItems(items, true, activate, creation_type);
|
| + ShowItems(items, true, activate, creation_type, GetTrayXOffset(item));
|
| bubble_->StartAutoCloseTimer(close_delay);
|
| }
|
|
|
| @@ -335,10 +336,48 @@ void SystemTray::SetPaintsBackground(
|
| hide_background_animator_.SetPaintsBackground(value, change_type);
|
| }
|
|
|
| +int SystemTray::GetTrayXOffset(SystemTrayItem* item) const {
|
| + std::map<SystemTrayItem*, views::View*>::const_iterator it =
|
| + tray_item_map_.find(item);
|
| + if (it == tray_item_map_.end())
|
| + return -1;
|
| +
|
| + const views::View* item_view = it->second;
|
| + gfx::Rect item_bounds = item_view->bounds();
|
| + if (!item_bounds.IsEmpty()) {
|
| + int x_offset = item_bounds.x() + item_bounds.width() / 2;
|
| + return base::i18n::IsRTL() ? x_offset : tray_container_->width() - x_offset;
|
| + }
|
| +
|
| + // The bounds of item could be still empty. It could happen in the case that
|
| + // the view appears for the first time in the current session, because the
|
| + // bounds is not calculated yet. In that case, we want to guess the offset
|
| + // from the position of its parent.
|
| + int x_offset = 0;
|
| + for (int i = 0; i < tray_container_->child_count(); ++i) {
|
| + const views::View* child = tray_container_->child_at(i);
|
| + if (child == item_view)
|
| + return base::i18n::IsRTL() ?
|
| + x_offset : tray_container_->width() - x_offset;
|
| +
|
| + if (!child->visible())
|
| + continue;
|
| + x_offset = child->bounds().right();
|
| + }
|
| +
|
| + return -1;
|
| +}
|
| +
|
| +void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type,
|
| + int arrow_offset) {
|
| + ShowItems(items_.get(), false, true, creation_type, arrow_offset);
|
| +}
|
| +
|
| void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items,
|
| bool detailed,
|
| bool can_activate,
|
| - BubbleCreationType creation_type) {
|
| + BubbleCreationType creation_type,
|
| + int arrow_offset) {
|
| // Destroy any existing bubble and create a new one.
|
| SystemTrayBubble::BubbleType bubble_type = detailed ?
|
| SystemTrayBubble::BUBBLE_TYPE_DETAILED :
|
| @@ -349,8 +388,15 @@ void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items,
|
| bubble_.reset(new SystemTrayBubble(this, items, bubble_type));
|
| ash::SystemTrayDelegate* delegate =
|
| ash::Shell::GetInstance()->tray_delegate();
|
| - bubble_->InitView(tray_container_, SystemTrayBubble::ANCHOR_TYPE_TRAY,
|
| - can_activate, delegate->GetUserLoginStatus());
|
| + views::View* anchor = tray_container_;
|
| + SystemTrayBubble::InitParams init_params(
|
| + SystemTrayBubble::ANCHOR_TYPE_TRAY);
|
| + init_params.anchor = anchor;
|
| + init_params.can_activate = can_activate;
|
| + init_params.login_status = delegate->GetUserLoginStatus();
|
| + if (arrow_offset >= 0)
|
| + init_params.arrow_offset = arrow_offset;
|
| + bubble_->InitView(init_params);
|
| }
|
| // If we have focus the shelf should be visible and we need to continue
|
| // showing the shelf when the popup is shown.
|
| @@ -380,10 +426,14 @@ void SystemTray::UpdateNotificationBubble() {
|
| anchor = tray_container_;
|
| anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY;
|
| }
|
| - notification_bubble_->InitView(
|
| - anchor, anchor_type,
|
| - false /* can_activate */,
|
| - ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus());
|
| + SystemTrayBubble::InitParams init_params(anchor_type);
|
| + init_params.anchor = anchor;
|
| + init_params.login_status =
|
| + ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus();
|
| + int arrow_offset = GetTrayXOffset(notification_items_[0]);
|
| + if (arrow_offset >= 0)
|
| + init_params.arrow_offset = arrow_offset;
|
| + notification_bubble_->InitView(init_params);
|
| }
|
|
|
| void SystemTray::UpdateNotificationAnchor() {
|
| @@ -401,7 +451,14 @@ bool SystemTray::PerformAction(const views::Event& event) {
|
| bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) {
|
| bubble_->Close();
|
| } else {
|
| - ShowDefaultView(BUBBLE_CREATE_NEW);
|
| + int arrow_offset = -1;
|
| + if (event.IsMouseEvent() || event.IsTouchEvent()) {
|
| + const views::LocatedEvent& located_event =
|
| + static_cast<const views::LocatedEvent&>(event);
|
| + arrow_offset = base::i18n::IsRTL() ?
|
| + located_event.x() : tray_container_->width() - located_event.x();
|
| + }
|
| + ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset);
|
| }
|
| return true;
|
| }
|
|
|