Chromium Code Reviews| Index: ash/system/tray/system_tray.cc |
| diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc |
| index e0362d57e60cfc0db3328e544eb3cb1a1a91bbc0..24098b4b6dc5238341832c3ae0aa041c9660ccd1 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,11 @@ void SystemTray::RemoveTrayItem(SystemTrayItem* item) { |
| } |
| void SystemTray::ShowDefaultView() { |
| - ShowItems(items_.get(), false, true); |
| + ShowDefaultViewWithOffset(-1); |
| +} |
| + |
| +void SystemTray::ShowDefaultViewWithOffset(int arrow_offset) { |
|
sadrul
2012/05/15 02:18:15
The order of the functions in the .cc file should
Jun Mukai
2012/05/15 02:43:05
Done.
|
| + ShowItems(items_.get(), false, true, arrow_offset); |
| } |
| void SystemTray::ShowDetailedView(SystemTrayItem* item, |
| @@ -259,7 +264,7 @@ void SystemTray::ShowDetailedView(SystemTrayItem* item, |
| bool activate) { |
| std::vector<SystemTrayItem*> items; |
| items.push_back(item); |
| - ShowItems(items, true, activate); |
| + ShowItems(items, true, activate, GetTrayXOffset(item)); |
| bubble_->StartAutoCloseTimer(close_delay); |
| } |
| @@ -334,9 +339,40 @@ 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; |
| + } |
| + |
| + // Sometimes the bounds of item is still empty. In that case, we |
| + // want to guess the offset from the position of its parent. |
|
sadrul
2012/05/15 02:18:15
I guess this happens when the tray-view for an ite
Jun Mukai
2012/05/15 02:43:05
No... It happens first time the user presses caps
sadrul
2012/05/15 02:58:16
Ah, cool. Thanks for explaining.
|
| + 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::ShowItems(const std::vector<SystemTrayItem*>& items, |
| bool detailed, |
| - bool can_activate) { |
| + bool can_activate, |
| + int arrow_offset) { |
| // Destroy any existing bubble and create a new one. |
| SystemTrayBubble::BubbleType bubble_type = detailed ? |
| SystemTrayBubble::BUBBLE_TYPE_DETAILED : |
| @@ -345,8 +381,12 @@ void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, |
| ash::SystemTrayDelegate* delegate = |
| ash::Shell::GetInstance()->tray_delegate(); |
| views::View* anchor = tray_container_; |
| - bubble_->InitView(anchor, SystemTrayBubble::ANCHOR_TYPE_TRAY, |
| - can_activate, delegate->GetUserLoginStatus()); |
| + SystemTrayBubble::InitParams init_params(SystemTrayBubble::ANCHOR_TYPE_TRAY); |
| + init_params.anchor = anchor; |
| + init_params.can_activate = can_activate; |
| + init_params.login_status = delegate->GetUserLoginStatus(); |
| + 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. |
| if (GetWidget()->IsActive()) |
| @@ -375,10 +415,12 @@ 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(); |
| + init_params.arrow_offset = GetTrayXOffset(notification_items_[0]); |
| + notification_bubble_->InitView(init_params); |
| } |
| void SystemTray::UpdateNotificationAnchor() { |
| @@ -396,7 +438,14 @@ bool SystemTray::PerformAction(const views::Event& event) { |
| bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { |
| bubble_->Close(); |
| } else { |
| - ShowDefaultView(); |
| + 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(arrow_offset); |
| } |
| return true; |
| } |