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; |
} |